@open-mercato/core 0.7.1-develop.7203.1.9396450b78 → 0.8.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 (416) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/build.mjs +11 -0
  3. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +23 -0
  4. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  5. package/dist/modules/customers/backend/customers/companies/[id]/page.js +2 -1
  6. package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
  7. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +2 -1
  8. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  9. package/dist/modules/customers/backend/customers/people/[id]/page.js +2 -2
  10. package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
  11. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +2 -1
  12. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  13. package/dist/modules/customers/lib/detailHelpers.js +4 -0
  14. package/dist/modules/customers/lib/detailHelpers.js.map +2 -2
  15. package/dist/modules/customers/lib/todoCompatibility.js +5 -0
  16. package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
  17. package/dist/modules/design_system/backend/design-system/page.meta.js +3 -2
  18. package/dist/modules/design_system/backend/design-system/page.meta.js.map +2 -2
  19. package/dist/modules/design_system/gallery/assets/ai-prompt-image.png +0 -0
  20. package/dist/modules/design_system/gallery/assets/avatar-illustration.png +0 -0
  21. package/dist/modules/design_system/gallery/assets/avatar-memoji.png +0 -0
  22. package/dist/modules/design_system/gallery/assets/avatar-photo.png +0 -0
  23. package/dist/modules/design_system/gallery/assets/blog-photo-0.png +0 -0
  24. package/dist/modules/design_system/gallery/assets/contact-support-portrait.png +0 -0
  25. package/dist/modules/design_system/gallery/assets/crypto-ada.png +0 -0
  26. package/dist/modules/design_system/gallery/assets/crypto-avax.png +0 -0
  27. package/dist/modules/design_system/gallery/assets/crypto-bnb.png +0 -0
  28. package/dist/modules/design_system/gallery/assets/crypto-brand.png +0 -0
  29. package/dist/modules/design_system/gallery/assets/crypto-btc.png +0 -0
  30. package/dist/modules/design_system/gallery/assets/crypto-clock.svg +3 -0
  31. package/dist/modules/design_system/gallery/assets/crypto-crown.svg +3 -0
  32. package/dist/modules/design_system/gallery/assets/crypto-dot.png +0 -0
  33. package/dist/modules/design_system/gallery/assets/crypto-eth.png +0 -0
  34. package/dist/modules/design_system/gallery/assets/crypto-hbar.png +0 -0
  35. package/dist/modules/design_system/gallery/assets/crypto-history.svg +3 -0
  36. package/dist/modules/design_system/gallery/assets/crypto-link.svg +3 -0
  37. package/dist/modules/design_system/gallery/assets/crypto-menu.svg +3 -0
  38. package/dist/modules/design_system/gallery/assets/crypto-metamask.png +0 -0
  39. package/dist/modules/design_system/gallery/assets/crypto-more.svg +3 -0
  40. package/dist/modules/design_system/gallery/assets/crypto-phantom.png +0 -0
  41. package/dist/modules/design_system/gallery/assets/crypto-rewards.svg +3 -0
  42. package/dist/modules/design_system/gallery/assets/crypto-sad-face.png +0 -0
  43. package/dist/modules/design_system/gallery/assets/crypto-sol.png +0 -0
  44. package/dist/modules/design_system/gallery/assets/crypto-star.svg +3 -0
  45. package/dist/modules/design_system/gallery/assets/crypto-status-cancelled.svg +3 -0
  46. package/dist/modules/design_system/gallery/assets/crypto-status-pending.svg +3 -0
  47. package/dist/modules/design_system/gallery/assets/crypto-status-success.svg +3 -0
  48. package/dist/modules/design_system/gallery/assets/crypto-status-warning.svg +3 -0
  49. package/dist/modules/design_system/gallery/assets/crypto-trx.png +0 -0
  50. package/dist/modules/design_system/gallery/assets/crypto-usdc.png +0 -0
  51. package/dist/modules/design_system/gallery/assets/crypto-usdt.png +0 -0
  52. package/dist/modules/design_system/gallery/assets/crypto-walletconnect.png +0 -0
  53. package/dist/modules/design_system/gallery/assets/crypto-wei.png +0 -0
  54. package/dist/modules/design_system/gallery/assets/crypto-xrp.png +0 -0
  55. package/dist/modules/design_system/gallery/assets/cryptocurrency-artwork.js +67 -0
  56. package/dist/modules/design_system/gallery/assets/cryptocurrency-artwork.js.map +7 -0
  57. package/dist/modules/design_system/gallery/assets/github-logo.png +0 -0
  58. package/dist/modules/design_system/gallery/assets/images.d.js +1 -0
  59. package/dist/modules/design_system/gallery/assets/images.d.js.map +7 -0
  60. package/dist/modules/design_system/gallery/assets/input-european-union.svg +18 -0
  61. package/dist/modules/design_system/gallery/assets/landing-teams-01.png +0 -0
  62. package/dist/modules/design_system/gallery/assets/marketing-artwork.js +83 -0
  63. package/dist/modules/design_system/gallery/assets/marketing-artwork.js.map +7 -0
  64. package/dist/modules/design_system/gallery/assets/menu-apex.svg +18 -0
  65. package/dist/modules/design_system/gallery/assets/menu-mastercard.svg +7 -0
  66. package/dist/modules/design_system/gallery/assets/menu-spotify.svg +4 -0
  67. package/dist/modules/design_system/gallery/assets/menu-united-states.svg +16 -0
  68. package/dist/modules/design_system/gallery/assets/select-google.png +0 -0
  69. package/dist/modules/design_system/gallery/assets/select-poland.png +0 -0
  70. package/dist/modules/design_system/gallery/assets/selection-artwork.js +5 -0
  71. package/dist/modules/design_system/gallery/assets/selection-artwork.js.map +7 -0
  72. package/dist/modules/design_system/gallery/assets/social-apple-filled.svg +4 -0
  73. package/dist/modules/design_system/gallery/assets/social-apple-stroke.svg +4 -0
  74. package/dist/modules/design_system/gallery/assets/social-dropbox-filled.svg +5 -0
  75. package/dist/modules/design_system/gallery/assets/social-dropbox-stroke.svg +5 -0
  76. package/dist/modules/design_system/gallery/assets/social-facebook-filled.svg +4 -0
  77. package/dist/modules/design_system/gallery/assets/social-facebook-stroke.svg +10 -0
  78. package/dist/modules/design_system/gallery/assets/social-github-filled.svg +4 -0
  79. package/dist/modules/design_system/gallery/assets/social-github-stroke.svg +4 -0
  80. package/dist/modules/design_system/gallery/assets/social-google-filled.svg +7 -0
  81. package/dist/modules/design_system/gallery/assets/social-google-stroke.svg +7 -0
  82. package/dist/modules/design_system/gallery/assets/social-linkedin-filled.svg +4 -0
  83. package/dist/modules/design_system/gallery/assets/social-linkedin-stroke.svg +4 -0
  84. package/dist/modules/design_system/gallery/assets/social-x-filled.svg +4 -0
  85. package/dist/modules/design_system/gallery/assets/social-x-stroke.svg +4 -0
  86. package/dist/modules/design_system/gallery/assets/style-studio-product.png +0 -0
  87. package/dist/modules/design_system/gallery/assets/upload-images.js +8 -0
  88. package/dist/modules/design_system/gallery/assets/upload-images.js.map +7 -0
  89. package/dist/modules/design_system/gallery/components/BrandStylePreview.js +74 -0
  90. package/dist/modules/design_system/gallery/components/BrandStylePreview.js.map +7 -0
  91. package/dist/modules/design_system/gallery/components/CodeSnippet.js +31 -31
  92. package/dist/modules/design_system/gallery/components/CodeSnippet.js.map +2 -2
  93. package/dist/modules/design_system/gallery/components/ColorPlayground.js +408 -0
  94. package/dist/modules/design_system/gallery/components/ColorPlayground.js.map +7 -0
  95. package/dist/modules/design_system/gallery/components/ColorStudioCompositions.js +166 -0
  96. package/dist/modules/design_system/gallery/components/ColorStudioCompositions.js.map +7 -0
  97. package/dist/modules/design_system/gallery/components/ColorStudioSpecimen.js +182 -0
  98. package/dist/modules/design_system/gallery/components/ColorStudioSpecimen.js.map +7 -0
  99. package/dist/modules/design_system/gallery/components/CompactEntrySpecimen.js +80 -0
  100. package/dist/modules/design_system/gallery/components/CompactEntrySpecimen.js.map +7 -0
  101. package/dist/modules/design_system/gallery/components/ComponentIndex.js +42 -0
  102. package/dist/modules/design_system/gallery/components/ComponentIndex.js.map +7 -0
  103. package/dist/modules/design_system/gallery/components/DesignSystemHome.js +69 -0
  104. package/dist/modules/design_system/gallery/components/DesignSystemHome.js.map +7 -0
  105. package/dist/modules/design_system/gallery/components/EntryCard.js +47 -41
  106. package/dist/modules/design_system/gallery/components/EntryCard.js.map +2 -2
  107. package/dist/modules/design_system/gallery/components/EntryHeader.js +68 -0
  108. package/dist/modules/design_system/gallery/components/EntryHeader.js.map +7 -0
  109. package/dist/modules/design_system/gallery/components/FamilyEntryPreview.js +19 -0
  110. package/dist/modules/design_system/gallery/components/FamilyEntryPreview.js.map +7 -0
  111. package/dist/modules/design_system/gallery/components/FoundationGuide.js +46 -0
  112. package/dist/modules/design_system/gallery/components/FoundationGuide.js.map +7 -0
  113. package/dist/modules/design_system/gallery/components/GalleryLink.js +21 -0
  114. package/dist/modules/design_system/gallery/components/GalleryLink.js.map +7 -0
  115. package/dist/modules/design_system/gallery/components/GalleryNavigation.js +82 -0
  116. package/dist/modules/design_system/gallery/components/GalleryNavigation.js.map +7 -0
  117. package/dist/modules/design_system/gallery/components/GalleryShell.js +147 -67
  118. package/dist/modules/design_system/gallery/components/GalleryShell.js.map +3 -3
  119. package/dist/modules/design_system/gallery/components/IconsBrowser.js +33 -0
  120. package/dist/modules/design_system/gallery/components/IconsBrowser.js.map +7 -0
  121. package/dist/modules/design_system/gallery/components/SourceLibrary.js +93 -0
  122. package/dist/modules/design_system/gallery/components/SourceLibrary.js.map +7 -0
  123. package/dist/modules/design_system/gallery/components/StyleAgents.js +139 -0
  124. package/dist/modules/design_system/gallery/components/StyleAgents.js.map +7 -0
  125. package/dist/modules/design_system/gallery/components/ThemeTokenReference.js +101 -0
  126. package/dist/modules/design_system/gallery/components/ThemeTokenReference.js.map +7 -0
  127. package/dist/modules/design_system/gallery/components/VariantPreview.js +2 -2
  128. package/dist/modules/design_system/gallery/components/VariantPreview.js.map +2 -2
  129. package/dist/modules/design_system/gallery/components/colorPreview.js +58 -0
  130. package/dist/modules/design_system/gallery/components/colorPreview.js.map +7 -0
  131. package/dist/modules/design_system/gallery/components/colorStudio.js +218 -0
  132. package/dist/modules/design_system/gallery/components/colorStudio.js.map +7 -0
  133. package/dist/modules/design_system/gallery/components/styleAgentBranding.js +46 -0
  134. package/dist/modules/design_system/gallery/components/styleAgentBranding.js.map +7 -0
  135. package/dist/modules/design_system/gallery/components/themeTokens.js +32 -0
  136. package/dist/modules/design_system/gallery/components/themeTokens.js.map +7 -0
  137. package/dist/modules/design_system/gallery/demos/ai-product-code.generated.js +194 -0
  138. package/dist/modules/design_system/gallery/demos/ai-product-code.generated.js.map +7 -0
  139. package/dist/modules/design_system/gallery/demos/ai-product.js +423 -0
  140. package/dist/modules/design_system/gallery/demos/ai-product.js.map +7 -0
  141. package/dist/modules/design_system/gallery/demos/buttons.js +289 -0
  142. package/dist/modules/design_system/gallery/demos/buttons.js.map +7 -0
  143. package/dist/modules/design_system/gallery/demos/cryptocurrency.js +1708 -0
  144. package/dist/modules/design_system/gallery/demos/cryptocurrency.js.map +7 -0
  145. package/dist/modules/design_system/gallery/demos/feeds-code.generated.js +92 -0
  146. package/dist/modules/design_system/gallery/demos/feeds-code.generated.js.map +7 -0
  147. package/dist/modules/design_system/gallery/demos/feeds.js +148 -0
  148. package/dist/modules/design_system/gallery/demos/feeds.js.map +7 -0
  149. package/dist/modules/design_system/gallery/demos/file-upload.js +72 -0
  150. package/dist/modules/design_system/gallery/demos/file-upload.js.map +7 -0
  151. package/dist/modules/design_system/gallery/demos/foundation-reference-data.js +4875 -0
  152. package/dist/modules/design_system/gallery/demos/foundation-reference-data.js.map +7 -0
  153. package/dist/modules/design_system/gallery/demos/foundation-references.js +188 -0
  154. package/dist/modules/design_system/gallery/demos/foundation-references.js.map +7 -0
  155. package/dist/modules/design_system/gallery/demos/key-components-code.generated.js +6 -0
  156. package/dist/modules/design_system/gallery/demos/key-components-code.generated.js.map +7 -0
  157. package/dist/modules/design_system/gallery/demos/key-components.js +127 -0
  158. package/dist/modules/design_system/gallery/demos/key-components.js.map +7 -0
  159. package/dist/modules/design_system/gallery/demos/marketing-controls-code.generated.js +98 -0
  160. package/dist/modules/design_system/gallery/demos/marketing-controls-code.generated.js.map +7 -0
  161. package/dist/modules/design_system/gallery/demos/marketing-controls.js +134 -0
  162. package/dist/modules/design_system/gallery/demos/marketing-controls.js.map +7 -0
  163. package/dist/modules/design_system/gallery/demos/marketing-widgets-code.generated.js +195 -0
  164. package/dist/modules/design_system/gallery/demos/marketing-widgets-code.generated.js.map +7 -0
  165. package/dist/modules/design_system/gallery/demos/marketing-widgets.js +586 -0
  166. package/dist/modules/design_system/gallery/demos/marketing-widgets.js.map +7 -0
  167. package/dist/modules/design_system/gallery/demos/menu-fixtures.js +40 -0
  168. package/dist/modules/design_system/gallery/demos/menu-fixtures.js.map +7 -0
  169. package/dist/modules/design_system/gallery/demos/menu-sources.js +295 -0
  170. package/dist/modules/design_system/gallery/demos/menu-sources.js.map +7 -0
  171. package/dist/modules/design_system/gallery/demos/menus.js +150 -0
  172. package/dist/modules/design_system/gallery/demos/menus.js.map +7 -0
  173. package/dist/modules/design_system/gallery/demos/rating-reviews.js +53 -0
  174. package/dist/modules/design_system/gallery/demos/rating-reviews.js.map +7 -0
  175. package/dist/modules/design_system/gallery/demos/registered-icons.js +104 -0
  176. package/dist/modules/design_system/gallery/demos/registered-icons.js.map +7 -0
  177. package/dist/modules/design_system/gallery/demos/selection-cards.js +99 -0
  178. package/dist/modules/design_system/gallery/demos/selection-cards.js.map +7 -0
  179. package/dist/modules/design_system/gallery/demos/shell-code.generated.js +189 -0
  180. package/dist/modules/design_system/gallery/demos/shell-code.generated.js.map +7 -0
  181. package/dist/modules/design_system/gallery/demos/shell.js +330 -0
  182. package/dist/modules/design_system/gallery/demos/shell.js.map +7 -0
  183. package/dist/modules/design_system/gallery/demos/source-artwork.js +120 -0
  184. package/dist/modules/design_system/gallery/demos/source-artwork.js.map +7 -0
  185. package/dist/modules/design_system/gallery/demos/source-filters-code.generated.js +125 -0
  186. package/dist/modules/design_system/gallery/demos/source-filters-code.generated.js.map +7 -0
  187. package/dist/modules/design_system/gallery/demos/source-filters.js +185 -0
  188. package/dist/modules/design_system/gallery/demos/source-filters.js.map +7 -0
  189. package/dist/modules/design_system/gallery/demos/source-icons.js +69 -0
  190. package/dist/modules/design_system/gallery/demos/source-icons.js.map +7 -0
  191. package/dist/modules/design_system/gallery/demos/table-cells-code.generated.js +150 -0
  192. package/dist/modules/design_system/gallery/demos/table-cells-code.generated.js.map +7 -0
  193. package/dist/modules/design_system/gallery/demos/table-cells.js +181 -0
  194. package/dist/modules/design_system/gallery/demos/table-cells.js.map +7 -0
  195. package/dist/modules/design_system/gallery/demos/text-inputs.js +113 -0
  196. package/dist/modules/design_system/gallery/demos/text-inputs.js.map +7 -0
  197. package/dist/modules/design_system/gallery/demos/time-picker-code.generated.js +41 -0
  198. package/dist/modules/design_system/gallery/demos/time-picker-code.generated.js.map +7 -0
  199. package/dist/modules/design_system/gallery/demos/time-picker.js +41 -0
  200. package/dist/modules/design_system/gallery/demos/time-picker.js.map +7 -0
  201. package/dist/modules/design_system/gallery/entries/banners.js +123 -60
  202. package/dist/modules/design_system/gallery/entries/banners.js.map +2 -2
  203. package/dist/modules/design_system/gallery/entries/buttons-snippets.js +433 -0
  204. package/dist/modules/design_system/gallery/entries/buttons-snippets.js.map +7 -0
  205. package/dist/modules/design_system/gallery/entries/buttons.js +127 -148
  206. package/dist/modules/design_system/gallery/entries/buttons.js.map +2 -2
  207. package/dist/modules/design_system/gallery/entries/charts.js +532 -186
  208. package/dist/modules/design_system/gallery/entries/charts.js.map +2 -2
  209. package/dist/modules/design_system/gallery/entries/dates.js +191 -3
  210. package/dist/modules/design_system/gallery/entries/dates.js.map +2 -2
  211. package/dist/modules/design_system/gallery/entries/detail.js +118 -77
  212. package/dist/modules/design_system/gallery/entries/detail.js.map +2 -2
  213. package/dist/modules/design_system/gallery/entries/display.js +1449 -240
  214. package/dist/modules/design_system/gallery/entries/display.js.map +2 -2
  215. package/dist/modules/design_system/gallery/entries/feedback.js +1058 -132
  216. package/dist/modules/design_system/gallery/entries/feedback.js.map +2 -2
  217. package/dist/modules/design_system/gallery/entries/filters.js +231 -103
  218. package/dist/modules/design_system/gallery/entries/filters.js.map +2 -2
  219. package/dist/modules/design_system/gallery/entries/foundations.js +368 -57
  220. package/dist/modules/design_system/gallery/entries/foundations.js.map +2 -2
  221. package/dist/modules/design_system/gallery/entries/icons.js +29 -91
  222. package/dist/modules/design_system/gallery/entries/icons.js.map +2 -2
  223. package/dist/modules/design_system/gallery/entries/inputs-snippets.js +154 -0
  224. package/dist/modules/design_system/gallery/entries/inputs-snippets.js.map +7 -0
  225. package/dist/modules/design_system/gallery/entries/inputs.js +2043 -306
  226. package/dist/modules/design_system/gallery/entries/inputs.js.map +2 -2
  227. package/dist/modules/design_system/gallery/entries/library.js +20 -0
  228. package/dist/modules/design_system/gallery/entries/library.js.map +7 -0
  229. package/dist/modules/design_system/gallery/entries/messages.js +121 -103
  230. package/dist/modules/design_system/gallery/entries/messages.js.map +2 -2
  231. package/dist/modules/design_system/gallery/entries/navigation.js +676 -103
  232. package/dist/modules/design_system/gallery/entries/navigation.js.map +2 -2
  233. package/dist/modules/design_system/gallery/entries/notifications.js +131 -78
  234. package/dist/modules/design_system/gallery/entries/notifications.js.map +2 -2
  235. package/dist/modules/design_system/gallery/entries/overlays.js +611 -203
  236. package/dist/modules/design_system/gallery/entries/overlays.js.map +2 -2
  237. package/dist/modules/design_system/gallery/entries/scaffolding.js +1175 -120
  238. package/dist/modules/design_system/gallery/entries/scaffolding.js.map +2 -2
  239. package/dist/modules/design_system/gallery/entries/schedule.js +79 -54
  240. package/dist/modules/design_system/gallery/entries/schedule.js.map +2 -2
  241. package/dist/modules/design_system/gallery/presentation.js +108 -0
  242. package/dist/modules/design_system/gallery/presentation.js.map +7 -0
  243. package/dist/modules/design_system/gallery/registry.js +8 -5
  244. package/dist/modules/design_system/gallery/registry.js.map +2 -2
  245. package/dist/modules/design_system/gallery/source-library.generated.js +5 -0
  246. package/dist/modules/design_system/gallery/source-library.generated.js.map +7 -0
  247. package/dist/modules/design_system/i18n/de.json +7167 -0
  248. package/dist/modules/design_system/i18n/en.json +7167 -0
  249. package/dist/modules/design_system/i18n/es.json +7167 -0
  250. package/dist/modules/design_system/i18n/ko.json +7167 -0
  251. package/dist/modules/design_system/i18n/pl.json +7167 -0
  252. package/dist/modules/push_notifications/lib/queue.js +1 -31
  253. package/dist/modules/push_notifications/lib/queue.js.map +2 -2
  254. package/jest.config.cjs +1 -0
  255. package/jest.mocks/image.js +1 -0
  256. package/package.json +8 -9
  257. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +50 -0
  258. package/src/modules/customers/backend/customers/companies/[id]/page.tsx +2 -1
  259. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +2 -1
  260. package/src/modules/customers/backend/customers/people/[id]/page.tsx +2 -2
  261. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +2 -1
  262. package/src/modules/customers/lib/detailHelpers.ts +4 -0
  263. package/src/modules/customers/lib/todoCompatibility.ts +10 -0
  264. package/src/modules/design_system/backend/design-system/page.meta.ts +3 -2
  265. package/src/modules/design_system/gallery/assets/README.md +30 -0
  266. package/src/modules/design_system/gallery/assets/ai-prompt-image.png +0 -0
  267. package/src/modules/design_system/gallery/assets/avatar-illustration.png +0 -0
  268. package/src/modules/design_system/gallery/assets/avatar-memoji.png +0 -0
  269. package/src/modules/design_system/gallery/assets/avatar-photo.png +0 -0
  270. package/src/modules/design_system/gallery/assets/blog-photo-0.png +0 -0
  271. package/src/modules/design_system/gallery/assets/contact-support-portrait.png +0 -0
  272. package/src/modules/design_system/gallery/assets/crypto-ada.png +0 -0
  273. package/src/modules/design_system/gallery/assets/crypto-avax.png +0 -0
  274. package/src/modules/design_system/gallery/assets/crypto-bnb.png +0 -0
  275. package/src/modules/design_system/gallery/assets/crypto-brand.png +0 -0
  276. package/src/modules/design_system/gallery/assets/crypto-btc.png +0 -0
  277. package/src/modules/design_system/gallery/assets/crypto-clock.svg +3 -0
  278. package/src/modules/design_system/gallery/assets/crypto-crown.svg +3 -0
  279. package/src/modules/design_system/gallery/assets/crypto-dot.png +0 -0
  280. package/src/modules/design_system/gallery/assets/crypto-eth.png +0 -0
  281. package/src/modules/design_system/gallery/assets/crypto-hbar.png +0 -0
  282. package/src/modules/design_system/gallery/assets/crypto-history.svg +3 -0
  283. package/src/modules/design_system/gallery/assets/crypto-link.svg +3 -0
  284. package/src/modules/design_system/gallery/assets/crypto-menu.svg +3 -0
  285. package/src/modules/design_system/gallery/assets/crypto-metamask.png +0 -0
  286. package/src/modules/design_system/gallery/assets/crypto-more.svg +3 -0
  287. package/src/modules/design_system/gallery/assets/crypto-phantom.png +0 -0
  288. package/src/modules/design_system/gallery/assets/crypto-rewards.svg +3 -0
  289. package/src/modules/design_system/gallery/assets/crypto-sad-face.png +0 -0
  290. package/src/modules/design_system/gallery/assets/crypto-sol.png +0 -0
  291. package/src/modules/design_system/gallery/assets/crypto-star.svg +3 -0
  292. package/src/modules/design_system/gallery/assets/crypto-status-cancelled.svg +3 -0
  293. package/src/modules/design_system/gallery/assets/crypto-status-pending.svg +3 -0
  294. package/src/modules/design_system/gallery/assets/crypto-status-success.svg +3 -0
  295. package/src/modules/design_system/gallery/assets/crypto-status-warning.svg +3 -0
  296. package/src/modules/design_system/gallery/assets/crypto-trx.png +0 -0
  297. package/src/modules/design_system/gallery/assets/crypto-usdc.png +0 -0
  298. package/src/modules/design_system/gallery/assets/crypto-usdt.png +0 -0
  299. package/src/modules/design_system/gallery/assets/crypto-walletconnect.png +0 -0
  300. package/src/modules/design_system/gallery/assets/crypto-wei.png +0 -0
  301. package/src/modules/design_system/gallery/assets/crypto-xrp.png +0 -0
  302. package/src/modules/design_system/gallery/assets/cryptocurrency-artwork.ts +63 -0
  303. package/src/modules/design_system/gallery/assets/github-logo.png +0 -0
  304. package/src/modules/design_system/gallery/assets/images.d.ts +9 -0
  305. package/src/modules/design_system/gallery/assets/input-european-union.svg +18 -0
  306. package/src/modules/design_system/gallery/assets/landing-teams-01.png +0 -0
  307. package/src/modules/design_system/gallery/assets/marketing-artwork.ts +79 -0
  308. package/src/modules/design_system/gallery/assets/menu-apex.svg +18 -0
  309. package/src/modules/design_system/gallery/assets/menu-mastercard.svg +7 -0
  310. package/src/modules/design_system/gallery/assets/menu-spotify.svg +4 -0
  311. package/src/modules/design_system/gallery/assets/menu-united-states.svg +16 -0
  312. package/src/modules/design_system/gallery/assets/select-google.png +0 -0
  313. package/src/modules/design_system/gallery/assets/select-poland.png +0 -0
  314. package/src/modules/design_system/gallery/assets/selection-artwork.ts +1 -0
  315. package/src/modules/design_system/gallery/assets/social-apple-filled.svg +4 -0
  316. package/src/modules/design_system/gallery/assets/social-apple-stroke.svg +4 -0
  317. package/src/modules/design_system/gallery/assets/social-dropbox-filled.svg +5 -0
  318. package/src/modules/design_system/gallery/assets/social-dropbox-stroke.svg +5 -0
  319. package/src/modules/design_system/gallery/assets/social-facebook-filled.svg +4 -0
  320. package/src/modules/design_system/gallery/assets/social-facebook-stroke.svg +10 -0
  321. package/src/modules/design_system/gallery/assets/social-github-filled.svg +4 -0
  322. package/src/modules/design_system/gallery/assets/social-github-stroke.svg +4 -0
  323. package/src/modules/design_system/gallery/assets/social-google-filled.svg +7 -0
  324. package/src/modules/design_system/gallery/assets/social-google-stroke.svg +7 -0
  325. package/src/modules/design_system/gallery/assets/social-linkedin-filled.svg +4 -0
  326. package/src/modules/design_system/gallery/assets/social-linkedin-stroke.svg +4 -0
  327. package/src/modules/design_system/gallery/assets/social-x-filled.svg +4 -0
  328. package/src/modules/design_system/gallery/assets/social-x-stroke.svg +4 -0
  329. package/src/modules/design_system/gallery/assets/style-studio-product.png +0 -0
  330. package/src/modules/design_system/gallery/assets/upload-images.ts +5 -0
  331. package/src/modules/design_system/gallery/components/BrandStylePreview.tsx +94 -0
  332. package/src/modules/design_system/gallery/components/CodeSnippet.tsx +34 -34
  333. package/src/modules/design_system/gallery/components/ColorPlayground.tsx +324 -0
  334. package/src/modules/design_system/gallery/components/ColorStudioCompositions.tsx +96 -0
  335. package/src/modules/design_system/gallery/components/ColorStudioSpecimen.tsx +164 -0
  336. package/src/modules/design_system/gallery/components/CompactEntrySpecimen.tsx +65 -0
  337. package/src/modules/design_system/gallery/components/ComponentIndex.tsx +47 -0
  338. package/src/modules/design_system/gallery/components/DesignSystemHome.tsx +66 -0
  339. package/src/modules/design_system/gallery/components/EntryCard.tsx +52 -37
  340. package/src/modules/design_system/gallery/components/EntryHeader.tsx +80 -0
  341. package/src/modules/design_system/gallery/components/FamilyEntryPreview.tsx +22 -0
  342. package/src/modules/design_system/gallery/components/FoundationGuide.tsx +43 -0
  343. package/src/modules/design_system/gallery/components/GalleryLink.tsx +19 -0
  344. package/src/modules/design_system/gallery/components/GalleryNavigation.tsx +86 -0
  345. package/src/modules/design_system/gallery/components/GalleryShell.tsx +149 -63
  346. package/src/modules/design_system/gallery/components/IconsBrowser.tsx +40 -0
  347. package/src/modules/design_system/gallery/components/SourceLibrary.tsx +90 -0
  348. package/src/modules/design_system/gallery/components/StyleAgents.tsx +115 -0
  349. package/src/modules/design_system/gallery/components/ThemeTokenReference.tsx +76 -0
  350. package/src/modules/design_system/gallery/components/VariantPreview.tsx +2 -2
  351. package/src/modules/design_system/gallery/components/colorPreview.ts +63 -0
  352. package/src/modules/design_system/gallery/components/colorStudio.ts +260 -0
  353. package/src/modules/design_system/gallery/components/styleAgentBranding.ts +42 -0
  354. package/src/modules/design_system/gallery/components/themeTokens.ts +26 -0
  355. package/src/modules/design_system/gallery/demos/ai-product-code.generated.ts +3 -0
  356. package/src/modules/design_system/gallery/demos/ai-product.tsx +188 -0
  357. package/src/modules/design_system/gallery/demos/buttons.tsx +331 -0
  358. package/src/modules/design_system/gallery/demos/cryptocurrency.tsx +1943 -0
  359. package/src/modules/design_system/gallery/demos/feeds-code.generated.ts +4 -0
  360. package/src/modules/design_system/gallery/demos/feeds.tsx +82 -0
  361. package/src/modules/design_system/gallery/demos/file-upload.tsx +61 -0
  362. package/src/modules/design_system/gallery/demos/foundation-reference-data.ts +4872 -0
  363. package/src/modules/design_system/gallery/demos/foundation-references.tsx +140 -0
  364. package/src/modules/design_system/gallery/demos/key-components-code.generated.ts +3 -0
  365. package/src/modules/design_system/gallery/demos/key-components.tsx +106 -0
  366. package/src/modules/design_system/gallery/demos/marketing-controls-code.generated.ts +3 -0
  367. package/src/modules/design_system/gallery/demos/marketing-controls.tsx +92 -0
  368. package/src/modules/design_system/gallery/demos/marketing-widgets-code.generated.ts +3 -0
  369. package/src/modules/design_system/gallery/demos/marketing-widgets.tsx +189 -0
  370. package/src/modules/design_system/gallery/demos/menu-fixtures.tsx +48 -0
  371. package/src/modules/design_system/gallery/demos/menu-sources.ts +5 -0
  372. package/src/modules/design_system/gallery/demos/menus.tsx +122 -0
  373. package/src/modules/design_system/gallery/demos/rating-reviews.tsx +44 -0
  374. package/src/modules/design_system/gallery/demos/registered-icons.tsx +117 -0
  375. package/src/modules/design_system/gallery/demos/selection-cards.tsx +97 -0
  376. package/src/modules/design_system/gallery/demos/shell-code.generated.ts +3 -0
  377. package/src/modules/design_system/gallery/demos/shell.tsx +183 -0
  378. package/src/modules/design_system/gallery/demos/source-artwork.tsx +88 -0
  379. package/src/modules/design_system/gallery/demos/source-filters-code.generated.ts +3 -0
  380. package/src/modules/design_system/gallery/demos/source-filters.tsx +119 -0
  381. package/src/modules/design_system/gallery/demos/source-icons.tsx +62 -0
  382. package/src/modules/design_system/gallery/demos/table-cells-code.generated.ts +3 -0
  383. package/src/modules/design_system/gallery/demos/table-cells.tsx +144 -0
  384. package/src/modules/design_system/gallery/demos/text-inputs.tsx +90 -0
  385. package/src/modules/design_system/gallery/demos/time-picker-code.generated.ts +5 -0
  386. package/src/modules/design_system/gallery/demos/time-picker.tsx +31 -0
  387. package/src/modules/design_system/gallery/entries/banners.tsx +143 -94
  388. package/src/modules/design_system/gallery/entries/buttons-snippets.ts +432 -0
  389. package/src/modules/design_system/gallery/entries/buttons.tsx +125 -196
  390. package/src/modules/design_system/gallery/entries/charts.tsx +545 -233
  391. package/src/modules/design_system/gallery/entries/dates.tsx +171 -3
  392. package/src/modules/design_system/gallery/entries/detail.tsx +142 -115
  393. package/src/modules/design_system/gallery/entries/display.tsx +1691 -319
  394. package/src/modules/design_system/gallery/entries/feedback.tsx +1082 -169
  395. package/src/modules/design_system/gallery/entries/filters.tsx +238 -143
  396. package/src/modules/design_system/gallery/entries/foundations.tsx +404 -61
  397. package/src/modules/design_system/gallery/entries/icons.tsx +31 -117
  398. package/src/modules/design_system/gallery/entries/inputs-snippets.ts +156 -0
  399. package/src/modules/design_system/gallery/entries/inputs.tsx +2146 -503
  400. package/src/modules/design_system/gallery/entries/library.tsx +16 -0
  401. package/src/modules/design_system/gallery/entries/messages.tsx +114 -106
  402. package/src/modules/design_system/gallery/entries/navigation.tsx +782 -192
  403. package/src/modules/design_system/gallery/entries/notifications.tsx +145 -120
  404. package/src/modules/design_system/gallery/entries/overlays.tsx +696 -280
  405. package/src/modules/design_system/gallery/entries/scaffolding.tsx +1192 -158
  406. package/src/modules/design_system/gallery/entries/schedule.tsx +72 -58
  407. package/src/modules/design_system/gallery/presentation.ts +106 -0
  408. package/src/modules/design_system/gallery/registry.ts +8 -6
  409. package/src/modules/design_system/gallery/source-library.generated.ts +2 -0
  410. package/src/modules/design_system/i18n/de.json +7112 -3
  411. package/src/modules/design_system/i18n/en.json +7112 -3
  412. package/src/modules/design_system/i18n/es.json +7112 -3
  413. package/src/modules/design_system/i18n/ko.json +7112 -3
  414. package/src/modules/design_system/i18n/pl.json +7112 -3
  415. package/src/modules/push_notifications/AGENTS.md +9 -5
  416. package/src/modules/push_notifications/lib/queue.ts +15 -44
@@ -0,0 +1,218 @@
1
+ import { contrastRatio, normalizeHex } from "./colorPreview.js";
2
+ const STEPS = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
3
+ const LIGHTNESS = [0.98, 0.95, 0.9, 0.83, 0.74, 0.64, 0.54, 0.44, 0.35, 0.26, 0.18];
4
+ function linearChannel(channel) {
5
+ return channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4;
6
+ }
7
+ function toOklch(hex) {
8
+ const [red, green, blue] = [1, 3, 5].map((offset) => linearChannel(Number.parseInt(hex.slice(offset, offset + 2), 16) / 255));
9
+ const long = Math.cbrt(0.4122214708 * red + 0.5363325363 * green + 0.0514459929 * blue);
10
+ const medium = Math.cbrt(0.2119034982 * red + 0.6806995451 * green + 0.1073969566 * blue);
11
+ const short = Math.cbrt(0.0883024619 * red + 0.2817188376 * green + 0.6299787005 * blue);
12
+ const lightness = 0.2104542553 * long + 0.793617785 * medium - 0.0040720468 * short;
13
+ const axisA = 1.9779984951 * long - 2.428592205 * medium + 0.4505937099 * short;
14
+ const axisB = 0.0259040371 * long + 0.7827717662 * medium - 0.808675766 * short;
15
+ return { lightness, chroma: Math.hypot(axisA, axisB), hue: Math.atan2(axisB, axisA) };
16
+ }
17
+ function toLinearRgb({ lightness, chroma, hue }) {
18
+ const axisA = chroma * Math.cos(hue);
19
+ const axisB = chroma * Math.sin(hue);
20
+ const long = (lightness + 0.3963377774 * axisA + 0.2158037573 * axisB) ** 3;
21
+ const medium = (lightness - 0.1055613458 * axisA - 0.0638541728 * axisB) ** 3;
22
+ const short = (lightness - 0.0894841775 * axisA - 1.291485548 * axisB) ** 3;
23
+ return [
24
+ 4.0767416621 * long - 3.3077115913 * medium + 0.2309699292 * short,
25
+ -1.2684380046 * long + 2.6097574011 * medium - 0.3413193965 * short,
26
+ -0.0041960863 * long - 0.7034186147 * medium + 1.707614701 * short
27
+ ];
28
+ }
29
+ function inGamut(channels) {
30
+ return channels.every((channel) => channel >= -1e-7 && channel <= 1.0000001);
31
+ }
32
+ function toHex(color) {
33
+ let channels = toLinearRgb(color);
34
+ if (!inGamut(channels)) {
35
+ let low = 0;
36
+ let high = color.chroma;
37
+ for (let iteration = 0; iteration < 24; iteration += 1) {
38
+ const chroma = (low + high) / 2;
39
+ if (inGamut(toLinearRgb({ ...color, chroma }))) low = chroma;
40
+ else high = chroma;
41
+ }
42
+ channels = toLinearRgb({ ...color, chroma: low });
43
+ }
44
+ return `#${channels.map((channel) => {
45
+ const clamped = Math.max(0, Math.min(1, channel));
46
+ const encoded = clamped <= 31308e-7 ? clamped * 12.92 : 1.055 * clamped ** (1 / 2.4) - 0.055;
47
+ return Math.round(encoded * 255).toString(16).padStart(2, "0");
48
+ }).join("").toUpperCase()}`;
49
+ }
50
+ function subtleSurface(surface, accent) {
51
+ const base = toOklch(surface);
52
+ const tint = toOklch(accent);
53
+ const amount = 0.15;
54
+ const axisA = base.chroma * Math.cos(base.hue) * (1 - amount) + tint.chroma * Math.cos(tint.hue) * amount;
55
+ const axisB = base.chroma * Math.sin(base.hue) * (1 - amount) + tint.chroma * Math.sin(tint.hue) * amount;
56
+ return toHex({
57
+ lightness: base.lightness * (1 - amount) + tint.lightness * amount,
58
+ chroma: Math.hypot(axisA, axisB),
59
+ hue: Math.atan2(axisB, axisA)
60
+ });
61
+ }
62
+ function accentScale(hex) {
63
+ const seed = toOklch(hex);
64
+ const anchor = LIGHTNESS.reduce((closest, value, index) => Math.abs(value - seed.lightness) < Math.abs(LIGHTNESS[closest] - seed.lightness) ? index : closest, 0);
65
+ const seedEnvelope = Math.max(0.25, Math.sin(Math.PI * seed.lightness) ** 0.8);
66
+ return STEPS.map((step, index) => {
67
+ if (index === anchor) return { step, hex };
68
+ const lightness = LIGHTNESS[index];
69
+ const chroma = seed.chroma < 1e-5 ? 0 : Math.min(0.32, seed.chroma * Math.sin(Math.PI * lightness) ** 0.8 / seedEnvelope);
70
+ return { step, hex: toHex({ lightness, chroma, hue: seed.hue }) };
71
+ });
72
+ }
73
+ function neutralScale(tone) {
74
+ const hue = (tone === "warm" ? 75 : 255) * Math.PI / 180;
75
+ return STEPS.map((step, index) => ({
76
+ step,
77
+ hex: toHex({ lightness: LIGHTNESS[index], chroma: tone === "neutral" ? 0 : 0.014 * Math.sin(Math.PI * LIGHTNESS[index]), hue })
78
+ }));
79
+ }
80
+ function atShade(scale, shade) {
81
+ return scale.find((stop) => stop.step === shade).hex;
82
+ }
83
+ function foregroundFor(background) {
84
+ return contrastRatio("#000000", background) >= contrastRatio("#FFFFFF", background) ? "#000000" : "#FFFFFF";
85
+ }
86
+ function nearestReadable(scale, target, background, minimum) {
87
+ const targetIndex = STEPS.indexOf(target);
88
+ return scale.filter((stop) => contrastRatio(stop.hex, background) >= minimum).sort((first, second) => Math.abs(STEPS.indexOf(first.step) - targetIndex) - Math.abs(STEPS.indexOf(second.step) - targetIndex))[0]?.hex ?? foregroundFor(background);
89
+ }
90
+ function themeFor(scale, neutrals, dark, actionStep, secondary, tertiary) {
91
+ const background = atShade(neutrals, dark ? 950 : 50);
92
+ const card = dark ? atShade(neutrals, 900) : "#FFFFFF";
93
+ const foreground = atShade(neutrals, dark ? 50 : 950);
94
+ const muted = atShade(neutrals, dark ? 800 : 100);
95
+ const mutedForeground = nearestReadable(neutrals, dark ? 300 : 600, muted, 4.5);
96
+ const primary = atShade(scale, actionStep);
97
+ const primaryForeground = foregroundFor(primary);
98
+ const actionIndex = STEPS.indexOf(actionStep);
99
+ const hoverIndex = Math.max(0, Math.min(STEPS.length - 1, actionIndex + (primaryForeground === "#FFFFFF" ? 1 : -1)));
100
+ const hoverCandidate = scale[hoverIndex].hex;
101
+ const hover = contrastRatio(primaryForeground, hoverCandidate) >= 4.5 ? hoverCandidate : primary;
102
+ const accent = dark ? subtleSurface(card, primary) : atShade(scale, 100);
103
+ const accentForeground = nearestReadable(scale, dark ? 200 : 800, accent, 4.5);
104
+ const focus = nearestReadable(scale, actionStep, background, 3);
105
+ const input = atShade(neutrals, dark ? 600 : 300);
106
+ const selection = scale.filter((stop) => contrastRatio(stop.hex, input) >= 3 && contrastRatio(stop.hex, background) >= 3).sort((first, second) => Math.abs(STEPS.indexOf(first.step) - actionIndex) - Math.abs(STEPS.indexOf(second.step) - actionIndex))[0]?.hex ?? foregroundFor(background);
107
+ const selectionForeground = foregroundFor(selection);
108
+ const categoryTokens = (name, colors) => {
109
+ const strong = atShade(colors, dark ? 400 : 600);
110
+ const soft = dark ? subtleSurface(card, strong) : atShade(colors, 100);
111
+ return {
112
+ [`--studio-${name}`]: strong,
113
+ [`--studio-${name}-foreground`]: foregroundFor(strong),
114
+ [`--studio-${name}-soft`]: soft,
115
+ [`--studio-${name}-soft-foreground`]: nearestReadable(colors, dark ? 200 : 800, soft, 4.5)
116
+ };
117
+ };
118
+ const tokens = {
119
+ ...categoryTokens("secondary", secondary),
120
+ ...categoryTokens("tertiary", tertiary),
121
+ "--background": background,
122
+ "--foreground": foreground,
123
+ "--card": card,
124
+ "--card-foreground": foreground,
125
+ "--popover": card,
126
+ "--popover-foreground": foreground,
127
+ "--muted": muted,
128
+ "--muted-foreground": mutedForeground,
129
+ "--secondary": muted,
130
+ "--secondary-foreground": foreground,
131
+ "--border": atShade(neutrals, dark ? 700 : 200),
132
+ "--input": input,
133
+ "--bg-disabled": muted,
134
+ "--text-disabled": atShade(neutrals, dark ? 500 : 400),
135
+ "--border-disabled": atShade(neutrals, dark ? 700 : 200),
136
+ "--primary": primary,
137
+ "--primary-foreground": primaryForeground,
138
+ "--primary-hover": hover,
139
+ "--accent": accent,
140
+ "--accent-foreground": accentForeground,
141
+ "--accent-indigo": selection,
142
+ "--accent-indigo-foreground": selectionForeground,
143
+ "--ring": focus,
144
+ "--focus-ring-inner": background,
145
+ "--focus-ring-outer": focus
146
+ };
147
+ const pair = (id, text, surface, minimum = 4.5) => ({
148
+ id,
149
+ foreground: text,
150
+ background: surface,
151
+ ratio: contrastRatio(text, surface),
152
+ minimum
153
+ });
154
+ return {
155
+ tokens,
156
+ actionStep,
157
+ pairs: [
158
+ pair("action", primaryForeground, primary),
159
+ pair("hover", primaryForeground, hover),
160
+ pair("body", foreground, background),
161
+ pair("muted", mutedForeground, muted),
162
+ pair("selection", accentForeground, accent),
163
+ pair("focus", focus, background, 3)
164
+ ]
165
+ };
166
+ }
167
+ function createHarmonySeeds(seed, harmony) {
168
+ const color = toOklch(normalizeHex(seed) ?? "#F4700D");
169
+ const offset = { analogous: 30, triadic: 120, split: 150 }[harmony] * Math.PI / 180;
170
+ const lightness = Math.max(0.55, Math.min(0.72, color.lightness));
171
+ const chroma = Math.max(0.1, Math.min(0.18, color.chroma));
172
+ const hue = color.chroma < 1e-5 ? 0 : color.hue;
173
+ return {
174
+ secondary: toHex({ lightness, chroma, hue: hue + offset }),
175
+ tertiary: toHex({ lightness, chroma, hue: hue - offset })
176
+ };
177
+ }
178
+ function createColorStudio(seed, neutral, actionShades = {}, colors = {}) {
179
+ const primary = normalizeHex(seed) ?? "#F4700D";
180
+ const derived = createHarmonySeeds(primary, colors.harmony ?? "triadic");
181
+ const seeds = {
182
+ primary,
183
+ secondary: normalizeHex(colors.secondary ?? "") ?? derived.secondary,
184
+ tertiary: normalizeHex(colors.tertiary ?? "") ?? derived.tertiary
185
+ };
186
+ const scale = accentScale(primary);
187
+ const secondary = accentScale(seeds.secondary);
188
+ const tertiary = accentScale(seeds.tertiary);
189
+ const neutrals = neutralScale(neutral);
190
+ return {
191
+ seeds,
192
+ scale,
193
+ secondaryScale: secondary,
194
+ tertiaryScale: tertiary,
195
+ neutralScale: neutrals,
196
+ light: themeFor(scale, neutrals, false, actionShades.light ?? 600, secondary, tertiary),
197
+ dark: themeFor(scale, neutrals, true, actionShades.dark ?? 400, secondary, tertiary)
198
+ };
199
+ }
200
+ function exportColorStudio(studio, format) {
201
+ const scales = {
202
+ accent: Object.fromEntries(studio.scale.map((stop) => [stop.step, stop.hex])),
203
+ secondary: Object.fromEntries(studio.secondaryScale.map((stop) => [stop.step, stop.hex])),
204
+ tertiary: Object.fromEntries(studio.tertiaryScale.map((stop) => [stop.step, stop.hex])),
205
+ neutral: Object.fromEntries(studio.neutralScale.map((stop) => [stop.step, stop.hex]))
206
+ };
207
+ if (format === "json") return JSON.stringify({ seeds: studio.seeds, scales, themes: { light: studio.light.tokens, dark: studio.dark.tokens } }, null, 2);
208
+ const scaleTokens = Object.fromEntries(Object.entries(scales).flatMap(([name, stops]) => Object.entries(stops).map(([step, hex]) => [`--palette-${name}-${step}`, hex])));
209
+ return ["light", "dark"].map((theme) => `.ds-color-preview-${theme} {
210
+ ${Object.entries({ ...scaleTokens, ...studio[theme].tokens }).map(([token, value]) => ` ${token}: ${value};`).join("\n")}
211
+ }`).join("\n\n");
212
+ }
213
+ export {
214
+ createColorStudio,
215
+ createHarmonySeeds,
216
+ exportColorStudio
217
+ };
218
+ //# sourceMappingURL=colorStudio.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/design_system/gallery/components/colorStudio.ts"],
4
+ "sourcesContent": ["import { contrastRatio, normalizeHex } from './colorPreview'\n\nexport type Shade = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950\nexport type NeutralTone = 'neutral' | 'warm' | 'cool'\nexport type Harmony = 'analogous' | 'triadic' | 'split'\nexport type ColorStop = { step: Shade; hex: string }\nexport type StudioTheme = {\n tokens: Record<string, string>\n actionStep: Shade\n pairs: Array<{\n id: 'action' | 'hover' | 'body' | 'muted' | 'selection' | 'focus'\n foreground: string\n background: string\n ratio: number\n minimum: number\n }>\n}\nexport type ColorStudio = {\n seeds: { primary: string; secondary: string; tertiary: string }\n scale: ColorStop[]\n secondaryScale: ColorStop[]\n tertiaryScale: ColorStop[]\n neutralScale: ColorStop[]\n light: StudioTheme\n dark: StudioTheme\n}\n\ntype Rgb = [number, number, number]\ntype Oklch = { lightness: number; chroma: number; hue: number }\nconst STEPS: Shade[] = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950]\nconst LIGHTNESS = [0.98, 0.95, 0.9, 0.83, 0.74, 0.64, 0.54, 0.44, 0.35, 0.26, 0.18]\n\nfunction linearChannel(channel: number): number {\n return channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4\n}\n\nfunction toOklch(hex: string): Oklch {\n const [red, green, blue] = [1, 3, 5].map((offset) => linearChannel(Number.parseInt(hex.slice(offset, offset + 2), 16) / 255))\n const long = Math.cbrt(0.4122214708 * red + 0.5363325363 * green + 0.0514459929 * blue)\n const medium = Math.cbrt(0.2119034982 * red + 0.6806995451 * green + 0.1073969566 * blue)\n const short = Math.cbrt(0.0883024619 * red + 0.2817188376 * green + 0.6299787005 * blue)\n const lightness = 0.2104542553 * long + 0.793617785 * medium - 0.0040720468 * short\n const axisA = 1.9779984951 * long - 2.428592205 * medium + 0.4505937099 * short\n const axisB = 0.0259040371 * long + 0.7827717662 * medium - 0.808675766 * short\n return { lightness, chroma: Math.hypot(axisA, axisB), hue: Math.atan2(axisB, axisA) }\n}\n\nfunction toLinearRgb({ lightness, chroma, hue }: Oklch): Rgb {\n const axisA = chroma * Math.cos(hue)\n const axisB = chroma * Math.sin(hue)\n const long = (lightness + 0.3963377774 * axisA + 0.2158037573 * axisB) ** 3\n const medium = (lightness - 0.1055613458 * axisA - 0.0638541728 * axisB) ** 3\n const short = (lightness - 0.0894841775 * axisA - 1.291485548 * axisB) ** 3\n return [\n 4.0767416621 * long - 3.3077115913 * medium + 0.2309699292 * short,\n -1.2684380046 * long + 2.6097574011 * medium - 0.3413193965 * short,\n -0.0041960863 * long - 0.7034186147 * medium + 1.707614701 * short,\n ]\n}\n\nfunction inGamut(channels: Rgb): boolean {\n return channels.every((channel) => channel >= -0.0000001 && channel <= 1.0000001)\n}\n\nfunction toHex(color: Oklch): string {\n let channels = toLinearRgb(color)\n if (!inGamut(channels)) {\n let low = 0\n let high = color.chroma\n for (let iteration = 0; iteration < 24; iteration += 1) {\n const chroma = (low + high) / 2\n if (inGamut(toLinearRgb({ ...color, chroma }))) low = chroma\n else high = chroma\n }\n channels = toLinearRgb({ ...color, chroma: low })\n }\n return `#${channels.map((channel) => {\n const clamped = Math.max(0, Math.min(1, channel))\n const encoded = clamped <= 0.0031308 ? clamped * 12.92 : 1.055 * clamped ** (1 / 2.4) - 0.055\n return Math.round(encoded * 255).toString(16).padStart(2, '0')\n }).join('').toUpperCase()}`\n}\n\nfunction subtleSurface(surface: string, accent: string): string {\n const base = toOklch(surface)\n const tint = toOklch(accent)\n const amount = 0.15\n const axisA = base.chroma * Math.cos(base.hue) * (1 - amount) + tint.chroma * Math.cos(tint.hue) * amount\n const axisB = base.chroma * Math.sin(base.hue) * (1 - amount) + tint.chroma * Math.sin(tint.hue) * amount\n return toHex({\n lightness: base.lightness * (1 - amount) + tint.lightness * amount,\n chroma: Math.hypot(axisA, axisB),\n hue: Math.atan2(axisB, axisA),\n })\n}\n\nfunction accentScale(hex: string): ColorStop[] {\n const seed = toOklch(hex)\n const anchor = LIGHTNESS.reduce((closest, value, index) => (\n Math.abs(value - seed.lightness) < Math.abs(LIGHTNESS[closest] - seed.lightness) ? index : closest\n ), 0)\n const seedEnvelope = Math.max(0.25, Math.sin(Math.PI * seed.lightness) ** 0.8)\n return STEPS.map((step, index) => {\n if (index === anchor) return { step, hex }\n const lightness = LIGHTNESS[index]\n const chroma = seed.chroma < 0.00001 ? 0 : Math.min(0.32, seed.chroma * Math.sin(Math.PI * lightness) ** 0.8 / seedEnvelope)\n return { step, hex: toHex({ lightness, chroma, hue: seed.hue }) }\n })\n}\n\nfunction neutralScale(tone: NeutralTone): ColorStop[] {\n const hue = (tone === 'warm' ? 75 : 255) * Math.PI / 180\n return STEPS.map((step, index) => ({\n step,\n hex: toHex({ lightness: LIGHTNESS[index], chroma: tone === 'neutral' ? 0 : 0.014 * Math.sin(Math.PI * LIGHTNESS[index]), hue }),\n }))\n}\n\nfunction atShade(scale: ColorStop[], shade: Shade): string {\n return scale.find((stop) => stop.step === shade)!.hex\n}\n\nfunction foregroundFor(background: string): string {\n return contrastRatio('#000000', background) >= contrastRatio('#FFFFFF', background) ? '#000000' : '#FFFFFF'\n}\n\nfunction nearestReadable(scale: ColorStop[], target: Shade, background: string, minimum: number): string {\n const targetIndex = STEPS.indexOf(target)\n return scale.filter((stop) => contrastRatio(stop.hex, background) >= minimum)\n .sort((first, second) => Math.abs(STEPS.indexOf(first.step) - targetIndex) - Math.abs(STEPS.indexOf(second.step) - targetIndex))[0]?.hex ?? foregroundFor(background)\n}\n\nfunction themeFor(scale: ColorStop[], neutrals: ColorStop[], dark: boolean, actionStep: Shade, secondary: ColorStop[], tertiary: ColorStop[]): StudioTheme {\n const background = atShade(neutrals, dark ? 950 : 50)\n const card = dark ? atShade(neutrals, 900) : '#FFFFFF'\n const foreground = atShade(neutrals, dark ? 50 : 950)\n const muted = atShade(neutrals, dark ? 800 : 100)\n const mutedForeground = nearestReadable(neutrals, dark ? 300 : 600, muted, 4.5)\n const primary = atShade(scale, actionStep)\n const primaryForeground = foregroundFor(primary)\n const actionIndex = STEPS.indexOf(actionStep)\n const hoverIndex = Math.max(0, Math.min(STEPS.length - 1, actionIndex + (primaryForeground === '#FFFFFF' ? 1 : -1)))\n const hoverCandidate = scale[hoverIndex].hex\n const hover = contrastRatio(primaryForeground, hoverCandidate) >= 4.5 ? hoverCandidate : primary\n const accent = dark ? subtleSurface(card, primary) : atShade(scale, 100)\n const accentForeground = nearestReadable(scale, dark ? 200 : 800, accent, 4.5)\n const focus = nearestReadable(scale, actionStep, background, 3)\n const input = atShade(neutrals, dark ? 600 : 300)\n const selection = scale.filter((stop) => contrastRatio(stop.hex, input) >= 3 && contrastRatio(stop.hex, background) >= 3)\n .sort((first, second) => Math.abs(STEPS.indexOf(first.step) - actionIndex) - Math.abs(STEPS.indexOf(second.step) - actionIndex))[0]?.hex ?? foregroundFor(background)\n const selectionForeground = foregroundFor(selection)\n const categoryTokens = (name: string, colors: ColorStop[]) => {\n const strong = atShade(colors, dark ? 400 : 600)\n const soft = dark ? subtleSurface(card, strong) : atShade(colors, 100)\n return {\n [`--studio-${name}`]: strong,\n [`--studio-${name}-foreground`]: foregroundFor(strong),\n [`--studio-${name}-soft`]: soft,\n [`--studio-${name}-soft-foreground`]: nearestReadable(colors, dark ? 200 : 800, soft, 4.5),\n }\n }\n const tokens: Record<string, string> = {\n ...categoryTokens('secondary', secondary),\n ...categoryTokens('tertiary', tertiary),\n '--background': background,\n '--foreground': foreground,\n '--card': card,\n '--card-foreground': foreground,\n '--popover': card,\n '--popover-foreground': foreground,\n '--muted': muted,\n '--muted-foreground': mutedForeground,\n '--secondary': muted,\n '--secondary-foreground': foreground,\n '--border': atShade(neutrals, dark ? 700 : 200),\n '--input': input,\n '--bg-disabled': muted,\n '--text-disabled': atShade(neutrals, dark ? 500 : 400),\n '--border-disabled': atShade(neutrals, dark ? 700 : 200),\n '--primary': primary,\n '--primary-foreground': primaryForeground,\n '--primary-hover': hover,\n '--accent': accent,\n '--accent-foreground': accentForeground,\n '--accent-indigo': selection,\n '--accent-indigo-foreground': selectionForeground,\n '--ring': focus,\n '--focus-ring-inner': background,\n '--focus-ring-outer': focus,\n }\n const pair = (id: StudioTheme['pairs'][number]['id'], text: string, surface: string, minimum = 4.5) => ({\n id, foreground: text, background: surface, ratio: contrastRatio(text, surface), minimum,\n })\n return {\n tokens,\n actionStep,\n pairs: [\n pair('action', primaryForeground, primary),\n pair('hover', primaryForeground, hover),\n pair('body', foreground, background),\n pair('muted', mutedForeground, muted),\n pair('selection', accentForeground, accent),\n pair('focus', focus, background, 3),\n ],\n }\n}\n\nexport function createHarmonySeeds(seed: string, harmony: Harmony): { secondary: string; tertiary: string } {\n const color = toOklch(normalizeHex(seed) ?? '#F4700D')\n const offset = ({ analogous: 30, triadic: 120, split: 150 }[harmony]) * Math.PI / 180\n const lightness = Math.max(0.55, Math.min(0.72, color.lightness))\n const chroma = Math.max(0.1, Math.min(0.18, color.chroma))\n const hue = color.chroma < 0.00001 ? 0 : color.hue\n return {\n secondary: toHex({ lightness, chroma, hue: hue + offset }),\n tertiary: toHex({ lightness, chroma, hue: hue - offset }),\n }\n}\n\nexport function createColorStudio(\n seed: string,\n neutral: NeutralTone,\n actionShades: { light?: Shade; dark?: Shade } = {},\n colors: { secondary?: string; tertiary?: string; harmony?: Harmony } = {},\n): ColorStudio {\n const primary = normalizeHex(seed) ?? '#F4700D'\n const derived = createHarmonySeeds(primary, colors.harmony ?? 'triadic')\n const seeds = {\n primary,\n secondary: normalizeHex(colors.secondary ?? '') ?? derived.secondary,\n tertiary: normalizeHex(colors.tertiary ?? '') ?? derived.tertiary,\n }\n const scale = accentScale(primary)\n const secondary = accentScale(seeds.secondary)\n const tertiary = accentScale(seeds.tertiary)\n const neutrals = neutralScale(neutral)\n return {\n seeds,\n scale,\n secondaryScale: secondary,\n tertiaryScale: tertiary,\n neutralScale: neutrals,\n light: themeFor(scale, neutrals, false, actionShades.light ?? 600, secondary, tertiary),\n dark: themeFor(scale, neutrals, true, actionShades.dark ?? 400, secondary, tertiary),\n }\n}\n\nexport function exportColorStudio(studio: ColorStudio, format: 'css' | 'json'): string {\n const scales = {\n accent: Object.fromEntries(studio.scale.map((stop) => [stop.step, stop.hex])),\n secondary: Object.fromEntries(studio.secondaryScale.map((stop) => [stop.step, stop.hex])),\n tertiary: Object.fromEntries(studio.tertiaryScale.map((stop) => [stop.step, stop.hex])),\n neutral: Object.fromEntries(studio.neutralScale.map((stop) => [stop.step, stop.hex])),\n }\n if (format === 'json') return JSON.stringify({ seeds: studio.seeds, scales, themes: { light: studio.light.tokens, dark: studio.dark.tokens } }, null, 2)\n const scaleTokens = Object.fromEntries(Object.entries(scales).flatMap(([name, stops]) => Object.entries(stops).map(([step, hex]) => [`--palette-${name}-${step}`, hex])))\n return (['light', 'dark'] as const).map((theme) => (\n `.ds-color-preview-${theme} {\\n${Object.entries({ ...scaleTokens, ...studio[theme].tokens }).map(([token, value]) => ` ${token}: ${value};`).join('\\n')}\\n}`\n )).join('\\n\\n')\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,46 @@
1
+ function studioBrandStyle(studio, logo) {
2
+ const theme = (mode) => {
3
+ const tokens = studio[mode].tokens;
4
+ return {
5
+ "--primary": tokens["--primary"],
6
+ "--primary-hover": tokens["--primary-hover"],
7
+ "--primary-foreground": tokens["--primary-foreground"],
8
+ "--brand-lime": studio.secondaryScale.find((stop) => stop.step === 200).hex,
9
+ "--brand-yellow": studio.scale.find((stop) => stop.step === 200).hex,
10
+ "--brand-violet": studio.tertiaryScale.find((stop) => stop.step === 200).hex,
11
+ "--brand-violet-foreground": "#000000"
12
+ };
13
+ };
14
+ return { version: 1, logo, seeds: studio.seeds, actionShades: { light: studio.light.actionStep, dark: studio.dark.actionStep }, light: theme("light"), dark: theme("dark") };
15
+ }
16
+ function readBrandLogo(file) {
17
+ if (!["image/png", "image/jpeg", "image/webp"].includes(file.type)) return Promise.reject(new Error("fileType"));
18
+ if (file.size > 1024 * 1024) return Promise.reject(new Error("fileSize"));
19
+ return new Promise((resolve, reject) => {
20
+ const reader = new FileReader();
21
+ reader.onerror = () => reject(new Error("fileDecode"));
22
+ reader.onload = () => {
23
+ if (typeof reader.result !== "string") {
24
+ reject(new Error("fileDecode"));
25
+ return;
26
+ }
27
+ const data = reader.result;
28
+ const image = new Image();
29
+ image.onerror = () => reject(new Error("fileDecode"));
30
+ image.onload = () => {
31
+ if (!image.naturalWidth || !image.naturalHeight || image.naturalWidth > 4096 || image.naturalHeight > 4096) {
32
+ reject(new Error("fileDimensions"));
33
+ return;
34
+ }
35
+ resolve(data);
36
+ };
37
+ image.src = data;
38
+ };
39
+ reader.readAsDataURL(file);
40
+ });
41
+ }
42
+ export {
43
+ readBrandLogo,
44
+ studioBrandStyle
45
+ };
46
+ //# sourceMappingURL=styleAgentBranding.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/design_system/gallery/components/styleAgentBranding.ts"],
4
+ "sourcesContent": ["import type { BrandStyle } from '@open-mercato/ui/theme/brand-style'\nimport type { ColorStudio } from './colorStudio'\n\nexport function studioBrandStyle(studio: ColorStudio, logo: string | null): BrandStyle {\n const theme = (mode: 'light' | 'dark') => {\n const tokens = studio[mode].tokens\n return {\n '--primary': tokens['--primary'],\n '--primary-hover': tokens['--primary-hover'],\n '--primary-foreground': tokens['--primary-foreground'],\n '--brand-lime': studio.secondaryScale.find(stop => stop.step === 200)!.hex,\n '--brand-yellow': studio.scale.find(stop => stop.step === 200)!.hex,\n '--brand-violet': studio.tertiaryScale.find(stop => stop.step === 200)!.hex,\n '--brand-violet-foreground': '#000000',\n }\n }\n return { version: 1, logo, seeds: studio.seeds, actionShades: { light: studio.light.actionStep, dark: studio.dark.actionStep }, light: theme('light'), dark: theme('dark') }\n}\n\nexport function readBrandLogo(file: File): Promise<string> {\n if (!['image/png', 'image/jpeg', 'image/webp'].includes(file.type)) return Promise.reject(new Error('fileType'))\n if (file.size > 1024 * 1024) return Promise.reject(new Error('fileSize'))\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onerror = () => reject(new Error('fileDecode'))\n reader.onload = () => {\n if (typeof reader.result !== 'string') { reject(new Error('fileDecode')); return }\n const data = reader.result\n const image = new Image()\n image.onerror = () => reject(new Error('fileDecode'))\n image.onload = () => {\n if (!image.naturalWidth || !image.naturalHeight || image.naturalWidth > 4096 || image.naturalHeight > 4096) {\n reject(new Error('fileDimensions'))\n return\n }\n resolve(data)\n }\n image.src = data\n }\n reader.readAsDataURL(file)\n })\n}\n"],
5
+ "mappings": "AAGO,SAAS,iBAAiB,QAAqB,MAAiC;AACrF,QAAM,QAAQ,CAAC,SAA2B;AACxC,UAAM,SAAS,OAAO,IAAI,EAAE;AAC5B,WAAO;AAAA,MACL,aAAa,OAAO,WAAW;AAAA,MAC/B,mBAAmB,OAAO,iBAAiB;AAAA,MAC3C,wBAAwB,OAAO,sBAAsB;AAAA,MACrD,gBAAgB,OAAO,eAAe,KAAK,UAAQ,KAAK,SAAS,GAAG,EAAG;AAAA,MACvE,kBAAkB,OAAO,MAAM,KAAK,UAAQ,KAAK,SAAS,GAAG,EAAG;AAAA,MAChE,kBAAkB,OAAO,cAAc,KAAK,UAAQ,KAAK,SAAS,GAAG,EAAG;AAAA,MACxE,6BAA6B;AAAA,IAC/B;AAAA,EACF;AACA,SAAO,EAAE,SAAS,GAAG,MAAM,OAAO,OAAO,OAAO,cAAc,EAAE,OAAO,OAAO,MAAM,YAAY,MAAM,OAAO,KAAK,WAAW,GAAG,OAAO,MAAM,OAAO,GAAG,MAAM,MAAM,MAAM,EAAE;AAC7K;AAEO,SAAS,cAAc,MAA6B;AACzD,MAAI,CAAC,CAAC,aAAa,cAAc,YAAY,EAAE,SAAS,KAAK,IAAI,EAAG,QAAO,QAAQ,OAAO,IAAI,MAAM,UAAU,CAAC;AAC/G,MAAI,KAAK,OAAO,OAAO,KAAM,QAAO,QAAQ,OAAO,IAAI,MAAM,UAAU,CAAC;AACxE,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAS,IAAI,WAAW;AAC9B,WAAO,UAAU,MAAM,OAAO,IAAI,MAAM,YAAY,CAAC;AACrD,WAAO,SAAS,MAAM;AACpB,UAAI,OAAO,OAAO,WAAW,UAAU;AAAE,eAAO,IAAI,MAAM,YAAY,CAAC;AAAG;AAAA,MAAO;AACjF,YAAM,OAAO,OAAO;AACpB,YAAM,QAAQ,IAAI,MAAM;AACxB,YAAM,UAAU,MAAM,OAAO,IAAI,MAAM,YAAY,CAAC;AACpD,YAAM,SAAS,MAAM;AACnB,YAAI,CAAC,MAAM,gBAAgB,CAAC,MAAM,iBAAiB,MAAM,eAAe,QAAQ,MAAM,gBAAgB,MAAM;AAC1G,iBAAO,IAAI,MAAM,gBAAgB,CAAC;AAClC;AAAA,QACF;AACA,gBAAQ,IAAI;AAAA,MACd;AACA,YAAM,MAAM;AAAA,IACd;AACA,WAAO,cAAc,IAAI;AAAA,EAC3B,CAAC;AACH;",
6
+ "names": []
7
+ }
@@ -0,0 +1,32 @@
1
+ function readThemeTokens(sheets) {
2
+ const light = {};
3
+ const dark = {};
4
+ function readRules(rules) {
5
+ for (const rule of Array.from(rules)) {
6
+ if ("selectorText" in rule && "style" in rule) {
7
+ const styleRule = rule;
8
+ const selectors = styleRule.selectorText.split(",").map((selector) => selector.trim());
9
+ const target = selectors.includes(".dark") ? dark : selectors.includes(":root") ? light : null;
10
+ if (target) {
11
+ for (const property of Array.from(styleRule.style)) {
12
+ if (property.startsWith("--")) target[property] = styleRule.style.getPropertyValue(property).trim();
13
+ }
14
+ }
15
+ }
16
+ if ("cssRules" in rule) readRules(rule.cssRules);
17
+ }
18
+ }
19
+ for (const sheet of sheets) {
20
+ if (sheet.ownerNode instanceof Element && sheet.ownerNode.id === "om-brand-style") continue;
21
+ try {
22
+ readRules(sheet.cssRules);
23
+ } catch {
24
+ continue;
25
+ }
26
+ }
27
+ return { light, dark: { ...light, ...dark } };
28
+ }
29
+ export {
30
+ readThemeTokens
31
+ };
32
+ //# sourceMappingURL=themeTokens.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/design_system/gallery/components/themeTokens.ts"],
4
+ "sourcesContent": ["export type ThemeTokens = { light: Record<string, string>; dark: Record<string, string> }\n\nexport function readThemeTokens(sheets: Iterable<CSSStyleSheet>): ThemeTokens {\n const light: Record<string, string> = {}\n const dark: Record<string, string> = {}\n function readRules(rules: CSSRuleList) {\n for (const rule of Array.from(rules)) {\n if ('selectorText' in rule && 'style' in rule) {\n const styleRule = rule as CSSStyleRule\n const selectors = styleRule.selectorText.split(',').map(selector => selector.trim())\n const target = selectors.includes('.dark') ? dark : selectors.includes(':root') ? light : null\n if (target) {\n for (const property of Array.from(styleRule.style)) {\n if (property.startsWith('--')) target[property] = styleRule.style.getPropertyValue(property).trim()\n }\n }\n }\n if ('cssRules' in rule) readRules((rule as CSSGroupingRule).cssRules)\n }\n }\n for (const sheet of sheets) {\n if (sheet.ownerNode instanceof Element && sheet.ownerNode.id === 'om-brand-style') continue\n try { readRules(sheet.cssRules) } catch { continue }\n }\n return { light, dark: { ...light, ...dark } }\n}\n"],
5
+ "mappings": "AAEO,SAAS,gBAAgB,QAA8C;AAC5E,QAAM,QAAgC,CAAC;AACvC,QAAM,OAA+B,CAAC;AACtC,WAAS,UAAU,OAAoB;AACrC,eAAW,QAAQ,MAAM,KAAK,KAAK,GAAG;AACpC,UAAI,kBAAkB,QAAQ,WAAW,MAAM;AAC7C,cAAM,YAAY;AAClB,cAAM,YAAY,UAAU,aAAa,MAAM,GAAG,EAAE,IAAI,cAAY,SAAS,KAAK,CAAC;AACnF,cAAM,SAAS,UAAU,SAAS,OAAO,IAAI,OAAO,UAAU,SAAS,OAAO,IAAI,QAAQ;AAC1F,YAAI,QAAQ;AACV,qBAAW,YAAY,MAAM,KAAK,UAAU,KAAK,GAAG;AAClD,gBAAI,SAAS,WAAW,IAAI,EAAG,QAAO,QAAQ,IAAI,UAAU,MAAM,iBAAiB,QAAQ,EAAE,KAAK;AAAA,UACpG;AAAA,QACF;AAAA,MACF;AACA,UAAI,cAAc,KAAM,WAAW,KAAyB,QAAQ;AAAA,IACtE;AAAA,EACF;AACA,aAAW,SAAS,QAAQ;AAC1B,QAAI,MAAM,qBAAqB,WAAW,MAAM,UAAU,OAAO,iBAAkB;AACnF,QAAI;AAAE,gBAAU,MAAM,QAAQ;AAAA,IAAE,QAAQ;AAAE;AAAA,IAAS;AAAA,EACrD;AACA,SAAO,EAAE,OAAO,MAAM,EAAE,GAAG,OAAO,GAAG,KAAK,EAAE;AAC9C;",
6
+ "names": []
7
+ }
@@ -0,0 +1,194 @@
1
+ const source = `import * as React from 'react'
2
+ import { ArrowLeft, BookOpen, ChevronDown, ChevronRight, Folder, Mail, Menu, MoreHorizontal, MoreVertical, PanelLeft, Plus, Search, User, X, Zap } from 'lucide-react'
3
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
4
+ import { cn } from '@open-mercato/shared/lib/utils'
5
+ import { Button } from '@open-mercato/ui/primitives/button'
6
+ import { Input } from '@open-mercato/ui/primitives/input'
7
+ import { SearchInput } from '@open-mercato/ui/primitives/search-input'
8
+ import { FieldLabel } from '@open-mercato/ui/primitives/label'
9
+ import { HintText } from '@open-mercato/ui/primitives/hint-text'
10
+ import { KeyIconGlyph } from '@open-mercato/ui/primitives/key-icon'
11
+ import { DigitInput } from '@open-mercato/ui/primitives/digit-input'
12
+ import { CounterInput } from '@open-mercato/ui/primitives/counter-input'
13
+ import { Select, SelectTrigger, SelectContent, SelectItem, SelectValue } from '@open-mercato/ui/primitives/select'
14
+ import { Popover, PopoverTrigger, PopoverContent } from '@open-mercato/ui/primitives/popover'
15
+ import { CheckboxField } from '@open-mercato/ui/primitives/checkbox-field'
16
+ import { SocialButton } from '@open-mercato/ui/primitives/social-button'
17
+ import { Avatar } from '@open-mercato/ui/primitives/avatar'
18
+ import { Badge } from '@open-mercato/ui/primitives/badge'
19
+ import { Sidebar } from '@open-mercato/ui/primitives/sidebar'
20
+ import { PromptArea } from '@open-mercato/ui/primitives/prompt-area'
21
+ import { FileFormatIcon } from '@open-mercato/ui/primitives/file-format-icon'
22
+ import { aiProductArtwork } from '@open-mercato/ui/assets/ai-product-artwork'
23
+ import promptImage from '../assets/ai-prompt-image.png'
24
+ import avatarPhoto from '../assets/avatar-photo.png'
25
+ import googleIcon from '../assets/select-google.png'
26
+
27
+ type ButtonProps = React.ComponentProps<typeof Button>
28
+
29
+ const prefix = 'design_system.gallery.examples.aiProduct.'
30
+ const source = (asset: string | { readonly src: string }) => typeof asset === 'string' ? asset : asset.src
31
+
32
+ function AiIconButton({ size = 32, tone = 'default', appearance = 'plain', className, children, ...props }: Omit<ButtonProps, 'size'> & { size?: 20 | 24 | 28 | 32; tone?: 'default' | 'error'; appearance?: 'plain' | 'stroke' | 'lighter' }) {
33
+ const content = React.isValidElement<{ className?: string }>(children) && children.type !== 'img'
34
+ ? React.cloneElement(children, { className: cn(children.props.className, size === 24 ? 'size-4.5' : 'size-5') })
35
+ : children
36
+ return <Button type="button" variant="ghost" size="icon" data-slot="ai-icon-button" data-size={size} data-tone={tone} data-appearance={appearance} className={cn(
37
+ 'shrink-0 p-0',
38
+ size === 32 ? 'size-8 rounded-md' : size === 28 ? 'size-7 rounded-md' : size === 24 ? 'size-6 rounded-sm' : 'size-5 rounded-sm',
39
+ appearance !== 'plain' && 'rounded-ai-control',
40
+ appearance === 'stroke' ? 'bg-background shadow-xs ring-1 ring-inset ring-border' : appearance === 'lighter' ? 'bg-muted' : 'bg-background',
41
+ tone === 'error' ? 'text-status-error-text hover:bg-status-error-bg hover:text-status-error-text aria-pressed:bg-status-error-bg aria-pressed:text-status-error-text' : 'text-muted-foreground hover:bg-muted hover:text-foreground aria-pressed:bg-muted aria-pressed:text-foreground',
42
+ appearance !== 'plain' && 'aria-pressed:bg-primary aria-pressed:text-primary-foreground',
43
+ className,
44
+ )} {...props}>{content}</Button>
45
+ }
46
+
47
+ function AiModelSelect({ value, onChange, compact = false, className }: { value: string; onChange: (value: string) => void; compact?: boolean; className?: string }) {
48
+ const t = useT()
49
+ return <Select value={value} onValueChange={onChange}><SelectTrigger aria-label={t(\`\${prefix}model\`)} data-slot="ai-model-select" className={cn('h-7 w-auto min-w-19.75 gap-1 rounded-ai-control border-0 bg-muted py-1 pl-2 pr-1 text-sm leading-5 shadow-none hover:bg-accent [&>svg]:size-5', compact && 'h-5 bg-transparent p-0', className)}><SelectValue /></SelectTrigger><SelectContent>{['GPT-4', 'GPT-3.5'].map(model => <SelectItem key={model} value={model}>{model}</SelectItem>)}</SelectContent></Select>
50
+ }
51
+
52
+ type PromptAttachment = { id: string; name: string; image?: string; objectUrl?: boolean }
53
+
54
+ export function AiPromptExample({ compact = false, attachment = 'none' }: { compact?: boolean; attachment?: 'none' | 'file' | 'image' }) {
55
+ const t = useT()
56
+ const [value, setValue] = React.useState('')
57
+ const [model, setModel] = React.useState('GPT-4')
58
+ const [lastPrompt, setLastPrompt] = React.useState('')
59
+ const [files, setFiles] = React.useState<PromptAttachment[]>(attachment === 'none' ? [] : [{ id: 'source', name: t(\`\${prefix}\${attachment === 'image' ? 'imageName' : 'fileName'}\`), image: attachment === 'image' ? source(promptImage) : undefined }])
60
+ const upload = React.useRef<HTMLInputElement>(null)
61
+ const attachmentId = React.useRef(0)
62
+ const objectUrls = React.useRef(new Set<string>())
63
+ React.useEffect(() => () => { for (const url of objectUrls.current) URL.revokeObjectURL(url) }, [])
64
+ const remove = (id: string) => setFiles(current => current.filter(file => {
65
+ if (file.id !== id) return true
66
+ if (file.objectUrl && file.image) { URL.revokeObjectURL(file.image); objectUrls.current.delete(file.image) }
67
+ return false
68
+ }))
69
+ const submit = (message: string) => { setLastPrompt(\`\${model}: \${message}\`); setValue('') }
70
+ return <div className={cn('grid max-w-full gap-4', compact ? 'w-93.5' : 'w-175')}>
71
+ <PromptArea compact={compact} value={value} onValueChange={setValue} onSubmit={submit} inputLabel={t(\`\${prefix}prompt\`)} submitLabel={t(\`\${prefix}saveDraft\`)} placeholder={t(\`\${prefix}placeholder\`)} information={<><Zap aria-hidden="true" className="size-4 shrink-0" /><span>{t(\`\${prefix}premium\`)}</span><span aria-hidden="true">\xB7</span><Popover><PopoverTrigger asChild><Button type="button" variant="ghost" className="h-4 rounded-sm p-0 text-xs font-medium leading-4">{t(\`\${prefix}upgrade\`)}</Button></PopoverTrigger><PopoverContent className="text-sm">{t(\`\${prefix}localOnly\`)}</PopoverContent></Popover></>}
72
+ toolbar={<><AiIconButton size={28} appearance="lighter" aria-label={t(\`\${prefix}addFile\`)} onClick={() => upload.current?.click()}><Plus aria-hidden="true" /></AiIconButton><AiModelSelect value={model} onChange={setModel} /></>}
73
+ attachments={files.length ? files.map(file => file.image ? <div key={file.id} className="relative size-24 shrink-0"><img src={file.image} alt={file.name} className="size-24 rounded-xl object-cover" /><AiIconButton size={20} aria-label={\`\${t(\`\${prefix}remove\`)} \${file.name}\`} className="absolute right-1.5 top-1.5 rounded-full bg-primary text-primary-foreground hover:bg-primary-hover hover:text-primary-foreground" onClick={() => remove(file.id)}><X aria-hidden="true" /></AiIconButton></div> : <div key={file.id} className="flex h-15 max-w-full items-center gap-3 rounded-xl bg-muted py-2.5 pl-3 pr-4"><FileFormatIcon format={file.name.includes('.') ? file.name.split('.').pop()?.toUpperCase().slice(0, 5) ?? 'FILE' : 'FILE'} /><div className="grid min-w-0 gap-1"><span className="truncate text-sm font-medium">{file.name}</span><span className="text-xs text-muted-foreground">{t(\`\${prefix}localFile\`)}</span></div><AiIconButton size={20} aria-label={\`\${t(\`\${prefix}remove\`)} \${file.name}\`} onClick={() => remove(file.id)}><X aria-hidden="true" /></AiIconButton></div>) : undefined} />
74
+ <input ref={upload} type="file" className="sr-only" tabIndex={-1} aria-label={t(\`\${prefix}attachmentInput\`)} multiple onChange={event => { const selected = Array.from(event.target.files ?? []); setFiles(current => [...current, ...selected.map(file => { const image = file.type.startsWith('image/') ? URL.createObjectURL(file) : undefined; if (image) objectUrls.current.add(image); return { id: \`attachment-\${attachmentId.current++}\`, name: file.name, image, objectUrl: Boolean(image) } })]); event.target.value = '' }} />
75
+ <p className="text-xs leading-4 text-muted-foreground">{t(\`\${prefix}localOnly\`)}</p>
76
+ {lastPrompt ? <output className="rounded-md border border-border p-3 text-sm">{t(\`\${prefix}saved\`)} {lastPrompt}</output> : null}
77
+ </div>
78
+ }
79
+
80
+ export function AiIconButtonExamples({ chat = false }: { chat?: boolean }) {
81
+ const t = useT()
82
+ const [active, setActive] = React.useState<string[]>([])
83
+ const toggle = (key: string) => setActive(items => items.includes(key) ? items.filter(item => item !== key) : [...items, key])
84
+ return <div className="grid gap-5">{chat ? <div className="flex gap-5">{(['stroke', 'lighter'] as const).map(appearance => <AiIconButton key={appearance} size={28} appearance={appearance} aria-label={\`\${t(\`\${prefix}toggleControl\`)} \${appearance}\`} aria-pressed={active.includes(appearance)} onClick={() => toggle(appearance)}><Plus aria-hidden="true" /></AiIconButton>)}</div> : (['default', 'error'] as const).map(tone => <div key={tone} className="flex items-center gap-5">{([32, 28, 24, 20] as const).map(size => <AiIconButton key={size} size={size} tone={tone} aria-label={\`\${t(\`\${prefix}\${tone}\`)} \${size}\`} aria-pressed={active.includes(\`\${tone}-\${size}\`)} onClick={() => toggle(\`\${tone}-\${size}\`)}><ChevronDown aria-hidden="true" /></AiIconButton>)}</div>)}</div>
85
+ }
86
+
87
+ function AiNavItem({ children, icon = true, leading, mobile = false, active = false, className, ...props }: ButtonProps & { icon?: boolean; leading?: React.ReactNode; mobile?: boolean; active?: boolean }) {
88
+ return <Button type="button" variant="ghost" size="sm" data-slot="ai-nav-item" data-mobile={mobile} data-leading={icon} aria-current={active ? 'page' : undefined} className={cn('group h-8 w-61 max-w-full justify-start gap-2 rounded-md bg-background py-1.5 pl-1.5 pr-2 text-sm font-medium leading-5 text-muted-foreground hover:bg-muted hover:text-foreground', active && 'bg-muted text-foreground', !icon && 'hover:pl-2.5', !icon && active && 'pl-2.5', className)} {...props}>
89
+ {icon ? leading ?? <Folder aria-hidden="true" className="size-5" /> : null}<span className="min-w-0 flex-1 truncate text-left">{children}</span>{icon ? <ChevronRight aria-hidden="true" className={cn('size-4.5 shrink-0', !mobile && !active && 'hidden group-hover:block group-focus-visible:block')} /> : <MoreVertical aria-hidden="true" className={cn('size-4.5 shrink-0', !mobile && (active ? 'hidden' : 'hidden group-hover:block group-focus-visible:block'))} />}
90
+ </Button>
91
+ }
92
+
93
+ export function AiNavigationExamples() {
94
+ const t = useT()
95
+ const [active, setActive] = React.useState<string[]>([])
96
+ return <div className="grid gap-4">{[false, true].flatMap(mobile => [true, false].map(icon => { const key = \`\${mobile}-\${icon}\`; return <AiNavItem key={key} icon={icon} mobile={mobile} active={active.includes(key)} onClick={() => setActive(values => values.includes(key) ? values.filter(value => value !== key) : [...values, key])}>{t(\`\${prefix}projects\`)}</AiNavItem> }))}</div>
97
+ }
98
+
99
+ export function AiSearchExamples() {
100
+ const t = useT()
101
+ const [query, setQuery] = React.useState('')
102
+ return <div className="grid w-64 max-w-full gap-4">{(['default', 'sm'] as const).map(size => <SearchInput key={size} size={size} value={query} onChange={setQuery} clearable={false} aria-label={\`\${t(\`\${prefix}search\`)} \${size}\`} placeholder={t(\`\${prefix}searchPlaceholder\`)} className={cn('rounded-lg border-0 px-2 shadow-none focus-within:bg-background [&>svg]:size-5', size === 'sm' ? 'bg-background hover:bg-muted' : 'bg-muted')} />)}<output className="text-xs text-muted-foreground">{t(\`\${prefix}query\`)} {query}</output></div>
103
+ }
104
+
105
+ export function AiAuthExamples({ kind = 'icons' }: { kind?: 'icons' | 'social' | 'text' | 'digits' }) {
106
+ const t = useT()
107
+ const [value, setValue] = React.useState('')
108
+ const [clicked, setClicked] = React.useState(false)
109
+ const id = React.useId()
110
+ if (kind === 'icons') return <div className="grid w-full max-w-lg grid-cols-2 gap-6 sm:grid-cols-4">{(['signIn', 'signUp', 'reset', 'verification', 'signInGray', 'signUpGray', 'resetGray', 'verificationGray'] as const).map(key => <div key={key} className="grid justify-items-center gap-2"><span className="flex size-14 items-center justify-center rounded-full border border-status-neutral-bg bg-background"><img src={aiProductArtwork[key]} alt="" className="size-8" /></span><span className="text-xs text-muted-foreground">{t(\`\${prefix}\${key.replace('Gray', '')}\`)}{key.endsWith('Gray') ? \` \xB7 \${t(\`\${prefix}gray\`)}\` : ''}</span></div>)}</div>
111
+ if (kind === 'social') return <div className="grid gap-3"><SocialButton type="button" brand="google" appearance="stroke" className="h-auto min-h-10 w-fit max-w-full whitespace-normal py-2 text-left" onClick={() => setClicked(true)}><img src={source(googleIcon)} alt="" className="size-5 shrink-0" /><span className="min-w-0">{t(\`\${prefix}google\`)}</span></SocialButton>{clicked ? <output className="max-w-sm text-xs text-muted-foreground">{t(\`\${prefix}localOnly\`)}</output> : null}</div>
112
+ if (kind === 'digits') return <div className="grid gap-4">{[false, true].map(disabled => <DigitInput key={String(disabled)} length={4} value={disabled ? '1234' : value} onChange={setValue} disabled={disabled} aria-label={\`\${t(\`\${prefix}verification\`)} \${disabled ? t(\`\${prefix}disabled\`) : t(\`\${prefix}editable\`)}\`} cellClassName="size-12 sm:w-12 rounded-ai-input px-2 py-2.5 text-lg leading-6" />)}<output className="text-xs text-muted-foreground">{value}</output></div>
113
+ return <div className="grid w-83 max-w-full gap-5">{[false, true].map(disabled => <div key={String(disabled)} data-slot="ai-text-input" className="grid gap-1"><FieldLabel htmlFor={\`\${id}-\${disabled}\`} disabled={disabled} required>{t(\`\${prefix}email\`)}</FieldLabel><Input id={\`\${id}-\${disabled}\`} type="email" value={disabled ? 'james@example.com' : value} onChange={event => setValue(event.target.value)} disabled={disabled} aria-required aria-describedby={\`\${id}-\${disabled}-hint\`} placeholder="hello@alignui.com" leading={<Mail aria-hidden="true" className="size-5 text-muted-foreground" />} size="lg" className="rounded-ai-input" /><HintText id={\`\${id}-\${disabled}-hint\`} state={disabled ? 'disabled' : 'default'} leading={<KeyIconGlyph name="information" />} className="pt-1">{t(\`\${prefix}hint\`)}</HintText></div>)}</div>
114
+ }
115
+
116
+ export function AiSettingsExamples() {
117
+ const t = useT()
118
+ const [tab, setTab] = React.useState('people')
119
+ const [size, setSize] = React.useState('medium')
120
+ const [count, setCount] = React.useState<number | null>(30)
121
+ const [model, setModel] = React.useState('GPT-4')
122
+ return <div className="grid gap-6"><div className="grid gap-2">{(['people', 'profile'] as const).map(value => <Button key={value} type="button" variant="ghost" data-slot="ai-settings-item" aria-pressed={tab === value} className="h-auto min-h-10 w-56 max-w-full justify-start gap-2 rounded-lg bg-background px-3 py-2 text-sm text-muted-foreground hover:bg-muted aria-pressed:bg-muted aria-pressed:text-foreground" onClick={() => setTab(value)}>{value === 'profile' ? <span aria-hidden="true"><Avatar size={20} label="James Brown" src={source(avatarPhoto)} /></span> : <User aria-hidden="true" className="size-5" />}<span className="min-w-0 flex-1 whitespace-normal text-left">{value === 'profile' ? 'James Brown' : t(\`\${prefix}people\`)}</span>{tab === value ? <ChevronRight aria-hidden="true" className="size-4.5" /> : null}</Button>)}</div><output className="text-sm text-muted-foreground">{t(\`\${prefix}\${tab}\`)}</output>
123
+ <div className="flex flex-wrap items-center gap-5"><Select value={size} onValueChange={setSize}><SelectTrigger data-slot="ai-size-select" aria-label={t(\`\${prefix}responseLength\`)} className="w-auto min-w-28 gap-2 rounded-lg [&>svg]:size-5"><SelectValue /></SelectTrigger><SelectContent>{['small', 'medium', 'large'].map(value => <SelectItem key={value} value={value}>{t(\`\${prefix}\${value}\`)}</SelectItem>)}</SelectContent></Select><CounterInput data-slot="ai-counter" value={count} min={0} max={99} onChange={setCount} size="default" aria-label={t(\`\${prefix}historyLimit\`)} decrementAriaLabel={t(\`\${prefix}decrease\`)} incrementAriaLabel={t(\`\${prefix}increase\`)} className="w-28 rounded-lg" inputClassName="text-sm" /><AiModelSelect value={model} onChange={setModel} className="h-9 px-3 py-2" /></div>
124
+ </div>
125
+ }
126
+
127
+ function AiNewChatButton({ onClick }: { onClick: () => void }) {
128
+ const t = useT()
129
+ return <Button type="button" variant="ghost" data-slot="ai-new-chat" className="h-auto min-h-8 w-61 max-w-full justify-start gap-2 rounded-md p-1.5 text-sm text-status-success-text hover:bg-status-success-bg hover:text-status-success-text" onClick={onClick}><span aria-hidden="true" className="flex size-5 items-center justify-center rounded-full bg-status-success-solid text-status-success-solid-foreground"><Plus className="size-3.5" /></span><span className="min-w-0 whitespace-normal text-left">{t(\`\${prefix}newChat\`)}</span></Button>
130
+ }
131
+
132
+ export function AiNewChatExample() {
133
+ const t = useT()
134
+ const [draft, setDraft] = React.useState(0)
135
+ return <div className="grid gap-3"><AiNewChatButton onClick={() => setDraft(value => value + 1)} /><output className="text-xs text-muted-foreground">{t(\`\${prefix}draftNumber\`, { number: draft })}</output></div>
136
+ }
137
+
138
+ function AiDivider() {
139
+ return <div role="separator" className="flex h-1 shrink-0 items-center px-1.5"><span className="h-px w-full bg-border" /></div>
140
+ }
141
+
142
+ export function AiSidebarExample({ search = '01', initialCollapsed = false }: { search?: '01' | '02' | '03'; initialCollapsed?: boolean }) {
143
+ const t = useT()
144
+ const [collapsed, setCollapsed] = React.useState(initialCollapsed)
145
+ const [query, setQuery] = React.useState('')
146
+ const [active, setActive] = React.useState('projects')
147
+ const [draft, setDraft] = React.useState(0)
148
+ const newChat = () => { setDraft(value => value + 1); setActive('newChat') }
149
+ const searchControl = <SearchInput value={query} onChange={setQuery} clearable={false} aria-label={t(\`\${prefix}search\`)} placeholder={t(\`\${prefix}searchPlaceholder\`)} className="h-9 w-61 max-w-full rounded-lg border-0 bg-muted px-2 shadow-none [&>svg]:size-5" />
150
+ const searchPopover = <Popover><PopoverTrigger asChild><AiIconButton aria-label={t(\`\${prefix}search\`)}><Search aria-hidden="true" /></AiIconButton></PopoverTrigger><PopoverContent className="w-auto p-3">{searchControl}<p className="mt-2 text-xs text-muted-foreground">{t(\`\${prefix}query\`)} {query}</p></PopoverContent></Popover>
151
+ const groups = [
152
+ { label: 'pinned', items: ['launchPlan', 'researchNotes', 'contentIdeas'], icon: true },
153
+ { label: 'recent', items: ['quarterlyReport', 'emailDraft', 'meetingNotes'], icon: false },
154
+ { label: 'yesterday', items: ['campaignIdeas', 'productBrief', 'supportReply', 'weeklyPlan', 'projectSummary'], icon: false },
155
+ ]
156
+ return <div className="flex max-w-full flex-wrap items-start gap-5">
157
+ <Sidebar collapsed={collapsed} aria-label={t(\`\${prefix}sidebar\`)} className={cn('max-w-full rounded-lg border border-border', collapsed ? 'w-18 gap-5 border-0 p-5' : 'w-68 gap-4 border-0 px-3.5 pb-3.5 pt-5')}>
158
+ <div className="flex shrink-0 flex-col gap-5"><div className="flex h-8 items-center justify-between">
159
+ {collapsed ? <AiIconButton aria-label={t(\`\${prefix}expand\`)} onClick={() => setCollapsed(false)}><img src={aiProductArtwork.logo} alt="" className="size-8" /></AiIconButton> : <><img src={aiProductArtwork.logo} alt={t(\`\${prefix}brand\`)} className="size-8" /><div className="flex gap-1">{search === '02' ? searchPopover : null}<AiIconButton aria-label={t(\`\${prefix}collapse\`)} onClick={() => setCollapsed(true)}><PanelLeft aria-hidden="true" /></AiIconButton></div></>}
160
+ </div>{!collapsed && search === '01' ? searchControl : null}</div>
161
+ {collapsed ? <><AiDivider /><div className="flex flex-1 flex-col gap-3"><AiIconButton aria-label={t(\`\${prefix}newChat\`)} onClick={newChat}><Plus aria-hidden="true" /></AiIconButton><AiIconButton aria-label={t(\`\${prefix}projects\`)} aria-pressed={active === 'projects'} onClick={() => setActive('projects')}><Folder aria-hidden="true" /></AiIconButton><AiIconButton aria-label={t(\`\${prefix}library\`)} aria-pressed={active === 'library'} onClick={() => setActive('library')}><BookOpen aria-hidden="true" /></AiIconButton>{searchPopover}</div><AiDivider /></> : <>
162
+ <div className="grid shrink-0 gap-1"><AiNewChatButton onClick={newChat} /><AiNavItem active={active === 'projects'} onClick={() => setActive('projects')}>{t(\`\${prefix}projects\`)}</AiNavItem><AiNavItem leading={<BookOpen aria-hidden="true" className="size-5" />} active={active === 'library'} onClick={() => setActive('library')}>{t(\`\${prefix}library\`)}</AiNavItem>{search === '03' ? <Popover><PopoverTrigger asChild><Button type="button" variant="ghost" className="h-8 justify-start gap-2 rounded-md p-1.5 text-sm text-muted-foreground"><Search aria-hidden="true" className="size-5" />{t(\`\${prefix}search\`)}</Button></PopoverTrigger><PopoverContent className="w-auto p-3">{searchControl}</PopoverContent></Popover> : null}</div>
163
+ <AiDivider /><div className="flex min-h-0 flex-1 flex-col gap-4 overflow-auto">
164
+ {groups.map((group, groupIndex) => <React.Fragment key={group.label}>{groupIndex === 1 ? <AiDivider /> : null}<div className="grid shrink-0 gap-2"><h3 className="px-1.5 text-xs font-medium leading-4 text-muted-foreground">{t(\`\${prefix}\${group.label}\`)}</h3><div className="grid gap-1">{group.items.filter(item => t(\`\${prefix}\${item}\`).toLocaleLowerCase().includes(query.toLocaleLowerCase())).map(item => <AiNavItem key={item} icon={group.icon} active={active === item} onClick={() => setActive(item)}>{t(\`\${prefix}\${item}\`)}</AiNavItem>)}</div></div></React.Fragment>)}
165
+ </div><AiDivider />
166
+ </>}
167
+ <Popover><PopoverTrigger asChild><Button type="button" variant="ghost" aria-label={t(\`\${prefix}profile\`)} data-slot="ai-sidebar-profile" className={cn('shrink-0 justify-start rounded-md text-left', collapsed ? 'size-8 p-0' : 'h-13 gap-3 p-1.5')}><Avatar label="James Brown" size={collapsed ? 32 : 40} />{!collapsed ? <><span className="flex min-w-0 flex-1 flex-col gap-1"><span className="flex items-center gap-1 text-sm font-medium leading-5">James Brown <Badge size={16} appearance="light">Pro</Badge></span><span className="truncate text-xs font-normal leading-4 text-muted-foreground">james@example.com</span></span><MoreVertical aria-hidden="true" className="size-4.5" /></> : null}</Button></PopoverTrigger><PopoverContent className="w-64 text-sm"><p className="font-medium">James Brown</p><p className="mt-2 text-muted-foreground">{t(\`\${prefix}localOnly\`)}</p></PopoverContent></Popover>
168
+ </Sidebar><output aria-live="polite" className="grid max-w-xs gap-2 text-sm text-muted-foreground"><span>{t(\`\${prefix}selected\`)} {t(\`\${prefix}\${active}\`)}</span><span>{t(\`\${prefix}draftNumber\`, { number: draft })}</span>{query ? <span>{t(\`\${prefix}query\`)} {query}</span> : null}</output>
169
+ </div>
170
+ }
171
+
172
+ export function AiMobileNavigationExample({ kind = 'default' }: { kind?: 'default' | 'in-projects' | 'projects' | 'project-details' }) {
173
+ const t = useT()
174
+ const [model, setModel] = React.useState('GPT-4')
175
+ const [selected, setSelected] = React.useState('projects')
176
+ const [draft, setDraft] = React.useState(0)
177
+ const [project, setProject] = React.useState('')
178
+ const [name, setName] = React.useState('')
179
+ const [createOpen, setCreateOpen] = React.useState(false)
180
+ const [pinned, setPinned] = React.useState(false)
181
+ const id = React.useId()
182
+ const menu = <Popover><PopoverTrigger asChild><AiIconButton aria-label={t(\`\${prefix}menu\`)}><Menu aria-hidden="true" /></AiIconButton></PopoverTrigger><PopoverContent className="grid w-auto gap-1 p-2">{['projects', 'library'].map(item => <AiNavItem key={item} mobile active={selected === item} onClick={() => setSelected(item)}>{t(\`\${prefix}\${item}\`)}</AiNavItem>)}</PopoverContent></Popover>
183
+ const more = <Popover><PopoverTrigger asChild><AiIconButton size={kind === 'project-details' ? 24 : 32} aria-label={t(\`\${prefix}more\`)}><MoreHorizontal aria-hidden="true" /></AiIconButton></PopoverTrigger><PopoverContent className="w-64"><CheckboxField checked={pinned} onCheckedChange={value => setPinned(value === true)} label={t(\`\${prefix}pinProject\`)} /></PopoverContent></Popover>
184
+ const create = () => { if (!name.trim()) return; setProject(name.trim()); setName(''); setCreateOpen(false) }
185
+ return <div className="grid w-full min-w-0 max-w-sm grid-cols-1 gap-4"><header data-slot="ai-mobile-navigation" data-kind={kind} className={cn('flex h-16 w-full min-w-0 items-center gap-2 bg-background px-2 py-3 sm:px-4', kind === 'project-details' ? 'sm:gap-2.5' : 'sm:gap-3.5')}>
186
+ {kind === 'project-details' ? <><AiIconButton size={20} aria-label={t(\`\${prefix}allProjects\`)} onClick={() => setSelected('projects')}><ArrowLeft aria-hidden="true" /></AiIconButton><span className="flex-1 text-sm font-medium">{t(\`\${prefix}allProjects\`)}</span><div className="flex gap-2"><AiIconButton size={24} aria-label={t(\`\${prefix}newChat\`)} onClick={() => setDraft(value => value + 1)}><Plus aria-hidden="true" /></AiIconButton>{more}</div></> : <>{menu}{kind === 'projects' ? <div className="flex flex-1 justify-end"><Popover open={createOpen} onOpenChange={setCreateOpen}><PopoverTrigger asChild><Button type="button" size="sm" variant="outline" className="w-auto shrink-0 gap-2 rounded-lg"><Plus aria-hidden="true" className="size-5" />{t(\`\${prefix}addProject\`)}</Button></PopoverTrigger><PopoverContent className="w-72"><form className="grid gap-3" onSubmit={event => { event.preventDefault(); create() }} onKeyDown={event => { if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) { event.preventDefault(); create() } }}><FieldLabel htmlFor={id} required>{t(\`\${prefix}projectName\`)}</FieldLabel><Input id={id} value={name} onChange={event => setName(event.target.value)} autoFocus /><Button type="submit" size="sm" disabled={!name.trim()}>{t(\`\${prefix}addProject\`)}</Button></form></PopoverContent></Popover></div> : <><div className="flex min-w-0 flex-1 flex-col gap-1"><AiModelSelect value={model} onChange={setModel} compact />{kind === 'in-projects' ? <span className="truncate text-xs leading-4 text-muted-foreground">{t(\`\${prefix}launchPlan\`)}</span> : null}</div><AiIconButton aria-label={t(\`\${prefix}newChat\`)} onClick={() => setDraft(value => value + 1)}><Plus aria-hidden="true" /></AiIconButton>{more}</>}</>}
187
+ </header><output aria-live="polite" className="grid gap-1 text-xs text-muted-foreground"><span>{t(\`\${prefix}selected\`)} {t(\`\${prefix}\${selected}\`)}</span><span>{t(\`\${prefix}draftNumber\`, { number: draft })}</span>{project ? <span>{t(\`\${prefix}createdProject\`)} {project}</span> : null}{pinned ? <span>{t(\`\${prefix}pinProject\`)}</span> : null}</output></div>
188
+ }
189
+ `;
190
+ const aiProductExampleCode = (expression) => source + "\n" + expression + "\n";
191
+ export {
192
+ aiProductExampleCode
193
+ };
194
+ //# sourceMappingURL=ai-product-code.generated.js.map