@oxy.so/bloom 7.1.4 → 7.2.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 (442) hide show
  1. package/assets/character-runtime/README.md +19 -114
  2. package/assets/character-runtime/legacy-engine.mjs +54 -406
  3. package/assets/character-runtime/legacy-geometry.mjs +85 -242
  4. package/assets/character-runtime/legacy-worker.mjs +23 -82
  5. package/assets/character-runtime/managed-avatar.mjs +18 -12
  6. package/assets/character-runtime/render-budget.mjs +11 -6
  7. package/assets/character-runtime/runtime.mjs +295 -744
  8. package/docs/adoption-matrix.mdx +12 -11
  9. package/docs/agent-avatar.mdx +8 -45
  10. package/docs/agent-creator.mdx +3 -13
  11. package/docs/app-shell.mdx +26 -2
  12. package/docs/appearance.mdx +16 -1
  13. package/docs/content-panel.mdx +4 -0
  14. package/docs/mail-thread.mdx +8 -0
  15. package/docs/page-footer.mdx +60 -0
  16. package/docs/sidebar.mdx +1 -1
  17. package/lib/commonjs/agent-avatar/AgentAvatar.js +1 -1
  18. package/lib/commonjs/agent-avatar/AgentAvatar.js.map +1 -1
  19. package/lib/commonjs/agent-avatar/CharacterAvatar.js +1 -2
  20. package/lib/commonjs/agent-avatar/CharacterAvatar.js.map +1 -1
  21. package/lib/commonjs/agent-avatar/config-character.js +0 -4
  22. package/lib/commonjs/agent-avatar/config-character.js.map +1 -1
  23. package/lib/commonjs/agent-avatar/legacy-recipe.js +6 -19
  24. package/lib/commonjs/agent-avatar/legacy-recipe.js.map +1 -1
  25. package/lib/commonjs/agent-creator/AgentCreatorBase.js +107 -67
  26. package/lib/commonjs/agent-creator/AgentCreatorBase.js.map +1 -1
  27. package/lib/commonjs/agent-creator/CharacterControls.js +5 -23
  28. package/lib/commonjs/agent-creator/CharacterControls.js.map +1 -1
  29. package/lib/commonjs/agent-creator/EmotionPicker.js +1 -8
  30. package/lib/commonjs/agent-creator/EmotionPicker.js.map +1 -1
  31. package/lib/commonjs/agent-creator/ShapeSilhouette.js +1 -8
  32. package/lib/commonjs/agent-creator/ShapeSilhouette.js.map +1 -1
  33. package/lib/commonjs/agent-creator/constants.js +17 -16
  34. package/lib/commonjs/agent-creator/constants.js.map +1 -1
  35. package/lib/commonjs/agent-creator/messages.js +1 -1
  36. package/lib/commonjs/agent-creator/messages.js.map +1 -1
  37. package/lib/commonjs/app-shell/AppShell.js +3 -2
  38. package/lib/commonjs/app-shell/AppShell.js.map +1 -1
  39. package/lib/commonjs/app-shell/AppShellBars.js +8 -5
  40. package/lib/commonjs/app-shell/AppShellBars.js.map +1 -1
  41. package/lib/commonjs/app-shell/AppShellEngine.js +81 -36
  42. package/lib/commonjs/app-shell/AppShellEngine.js.map +1 -1
  43. package/lib/commonjs/appearance/BloomScope.js +8 -3
  44. package/lib/commonjs/appearance/BloomScope.js.map +1 -1
  45. package/lib/commonjs/appearance/context.js.map +1 -1
  46. package/lib/commonjs/content-panel/ContentPanel.js +34 -23
  47. package/lib/commonjs/content-panel/ContentPanel.js.map +1 -1
  48. package/lib/commonjs/content-panel/ContentPanel.web.js +39 -17
  49. package/lib/commonjs/content-panel/ContentPanel.web.js.map +1 -1
  50. package/lib/commonjs/design-tokens/shapes.js +2 -2
  51. package/lib/commonjs/design-tokens/shapes.js.map +1 -1
  52. package/lib/commonjs/design-tokens/tokens.json +2 -2
  53. package/lib/commonjs/index.js +939 -927
  54. package/lib/commonjs/index.js.map +1 -1
  55. package/lib/commonjs/index.web.js +939 -927
  56. package/lib/commonjs/index.web.js.map +1 -1
  57. package/lib/commonjs/locale/translations/ar.js +1 -1
  58. package/lib/commonjs/locale/translations/ar.js.map +1 -1
  59. package/lib/commonjs/locale/translations/bn.js +1 -1
  60. package/lib/commonjs/locale/translations/bn.js.map +1 -1
  61. package/lib/commonjs/locale/translations/ca.js +1 -1
  62. package/lib/commonjs/locale/translations/ca.js.map +1 -1
  63. package/lib/commonjs/locale/translations/de.js +1 -1
  64. package/lib/commonjs/locale/translations/de.js.map +1 -1
  65. package/lib/commonjs/locale/translations/es.js +1 -1
  66. package/lib/commonjs/locale/translations/es.js.map +1 -1
  67. package/lib/commonjs/locale/translations/fr.js +1 -1
  68. package/lib/commonjs/locale/translations/fr.js.map +1 -1
  69. package/lib/commonjs/locale/translations/hi.js +1 -1
  70. package/lib/commonjs/locale/translations/hi.js.map +1 -1
  71. package/lib/commonjs/locale/translations/id.js +1 -1
  72. package/lib/commonjs/locale/translations/id.js.map +1 -1
  73. package/lib/commonjs/locale/translations/it.js +1 -1
  74. package/lib/commonjs/locale/translations/it.js.map +1 -1
  75. package/lib/commonjs/locale/translations/ja.js +1 -1
  76. package/lib/commonjs/locale/translations/ja.js.map +1 -1
  77. package/lib/commonjs/locale/translations/pt.js +1 -1
  78. package/lib/commonjs/locale/translations/pt.js.map +1 -1
  79. package/lib/commonjs/locale/translations/ru.js +1 -1
  80. package/lib/commonjs/locale/translations/ru.js.map +1 -1
  81. package/lib/commonjs/locale/translations/tr.js +1 -1
  82. package/lib/commonjs/locale/translations/tr.js.map +1 -1
  83. package/lib/commonjs/locale/translations/zh.js +1 -1
  84. package/lib/commonjs/locale/translations/zh.js.map +1 -1
  85. package/lib/commonjs/mail-thread/MailMessage.js +8 -14
  86. package/lib/commonjs/mail-thread/MailMessage.js.map +1 -1
  87. package/lib/commonjs/mail-thread/MailThread.js +6 -2
  88. package/lib/commonjs/mail-thread/MailThread.js.map +1 -1
  89. package/lib/commonjs/mail-thread/shared.js +2 -1
  90. package/lib/commonjs/mail-thread/shared.js.map +1 -1
  91. package/lib/commonjs/page-footer/PageFooter.js +137 -0
  92. package/lib/commonjs/page-footer/PageFooter.js.map +1 -0
  93. package/lib/commonjs/page-footer/PageFooterProvider.js +22 -0
  94. package/lib/commonjs/page-footer/PageFooterProvider.js.map +1 -0
  95. package/lib/commonjs/page-footer/context.js +11 -0
  96. package/lib/commonjs/page-footer/context.js.map +1 -0
  97. package/lib/commonjs/page-footer/index.js +27 -0
  98. package/lib/commonjs/page-footer/index.js.map +1 -0
  99. package/lib/commonjs/page-footer/types.js +6 -0
  100. package/lib/commonjs/page-footer/types.js.map +1 -0
  101. package/lib/commonjs/page-footer/use-page-footer-inset.js +19 -0
  102. package/lib/commonjs/page-footer/use-page-footer-inset.js.map +1 -0
  103. package/lib/commonjs/sidebar/Sidebar.js +6 -5
  104. package/lib/commonjs/sidebar/Sidebar.js.map +1 -1
  105. package/lib/commonjs/styles/panel-chrome.js +15 -1
  106. package/lib/commonjs/styles/panel-chrome.js.map +1 -1
  107. package/lib/module/agent-avatar/AgentAvatar.js +1 -1
  108. package/lib/module/agent-avatar/AgentAvatar.js.map +1 -1
  109. package/lib/module/agent-avatar/CharacterAvatar.js +1 -2
  110. package/lib/module/agent-avatar/CharacterAvatar.js.map +1 -1
  111. package/lib/module/agent-avatar/config-character.js +0 -4
  112. package/lib/module/agent-avatar/config-character.js.map +1 -1
  113. package/lib/module/agent-avatar/legacy-recipe.js +6 -19
  114. package/lib/module/agent-avatar/legacy-recipe.js.map +1 -1
  115. package/lib/module/agent-creator/AgentCreatorBase.js +109 -69
  116. package/lib/module/agent-creator/AgentCreatorBase.js.map +1 -1
  117. package/lib/module/agent-creator/CharacterControls.js +6 -24
  118. package/lib/module/agent-creator/CharacterControls.js.map +1 -1
  119. package/lib/module/agent-creator/EmotionPicker.js +1 -8
  120. package/lib/module/agent-creator/EmotionPicker.js.map +1 -1
  121. package/lib/module/agent-creator/ShapeSilhouette.js +1 -8
  122. package/lib/module/agent-creator/ShapeSilhouette.js.map +1 -1
  123. package/lib/module/agent-creator/constants.js +16 -8
  124. package/lib/module/agent-creator/constants.js.map +1 -1
  125. package/lib/module/agent-creator/messages.js +1 -1
  126. package/lib/module/agent-creator/messages.js.map +1 -1
  127. package/lib/module/app-shell/AppShell.js +3 -2
  128. package/lib/module/app-shell/AppShell.js.map +1 -1
  129. package/lib/module/app-shell/AppShellBars.js +8 -5
  130. package/lib/module/app-shell/AppShellBars.js.map +1 -1
  131. package/lib/module/app-shell/AppShellEngine.js +81 -36
  132. package/lib/module/app-shell/AppShellEngine.js.map +1 -1
  133. package/lib/module/appearance/BloomScope.js +8 -3
  134. package/lib/module/appearance/BloomScope.js.map +1 -1
  135. package/lib/module/appearance/context.js.map +1 -1
  136. package/lib/module/content-panel/ContentPanel.js +35 -24
  137. package/lib/module/content-panel/ContentPanel.js.map +1 -1
  138. package/lib/module/content-panel/ContentPanel.web.js +41 -19
  139. package/lib/module/content-panel/ContentPanel.web.js.map +1 -1
  140. package/lib/module/design-tokens/shapes.js +2 -2
  141. package/lib/module/design-tokens/shapes.js.map +1 -1
  142. package/lib/module/design-tokens/tokens.json +2 -2
  143. package/lib/module/index.js +1 -0
  144. package/lib/module/index.js.map +1 -1
  145. package/lib/module/index.web.js +1 -0
  146. package/lib/module/index.web.js.map +1 -1
  147. package/lib/module/locale/translations/ar.js +1 -1
  148. package/lib/module/locale/translations/ar.js.map +1 -1
  149. package/lib/module/locale/translations/bn.js +1 -1
  150. package/lib/module/locale/translations/bn.js.map +1 -1
  151. package/lib/module/locale/translations/ca.js +1 -1
  152. package/lib/module/locale/translations/ca.js.map +1 -1
  153. package/lib/module/locale/translations/de.js +1 -1
  154. package/lib/module/locale/translations/de.js.map +1 -1
  155. package/lib/module/locale/translations/es.js +1 -1
  156. package/lib/module/locale/translations/es.js.map +1 -1
  157. package/lib/module/locale/translations/fr.js +1 -1
  158. package/lib/module/locale/translations/fr.js.map +1 -1
  159. package/lib/module/locale/translations/hi.js +1 -1
  160. package/lib/module/locale/translations/hi.js.map +1 -1
  161. package/lib/module/locale/translations/id.js +1 -1
  162. package/lib/module/locale/translations/id.js.map +1 -1
  163. package/lib/module/locale/translations/it.js +1 -1
  164. package/lib/module/locale/translations/it.js.map +1 -1
  165. package/lib/module/locale/translations/ja.js +1 -1
  166. package/lib/module/locale/translations/ja.js.map +1 -1
  167. package/lib/module/locale/translations/pt.js +1 -1
  168. package/lib/module/locale/translations/pt.js.map +1 -1
  169. package/lib/module/locale/translations/ru.js +1 -1
  170. package/lib/module/locale/translations/ru.js.map +1 -1
  171. package/lib/module/locale/translations/tr.js +1 -1
  172. package/lib/module/locale/translations/tr.js.map +1 -1
  173. package/lib/module/locale/translations/zh.js +1 -1
  174. package/lib/module/locale/translations/zh.js.map +1 -1
  175. package/lib/module/mail-thread/MailMessage.js +8 -14
  176. package/lib/module/mail-thread/MailMessage.js.map +1 -1
  177. package/lib/module/mail-thread/MailThread.js +6 -2
  178. package/lib/module/mail-thread/MailThread.js.map +1 -1
  179. package/lib/module/mail-thread/shared.js +2 -1
  180. package/lib/module/mail-thread/shared.js.map +1 -1
  181. package/lib/module/page-footer/PageFooter.js +132 -0
  182. package/lib/module/page-footer/PageFooter.js.map +1 -0
  183. package/lib/module/page-footer/PageFooterProvider.js +18 -0
  184. package/lib/module/page-footer/PageFooterProvider.js.map +1 -0
  185. package/lib/module/page-footer/context.js +7 -0
  186. package/lib/module/page-footer/context.js.map +1 -0
  187. package/lib/module/page-footer/index.js +6 -0
  188. package/lib/module/page-footer/index.js.map +1 -0
  189. package/lib/module/page-footer/types.js +4 -0
  190. package/lib/module/page-footer/types.js.map +1 -0
  191. package/lib/module/page-footer/use-page-footer-inset.js +16 -0
  192. package/lib/module/page-footer/use-page-footer-inset.js.map +1 -0
  193. package/lib/module/sidebar/Sidebar.js +6 -5
  194. package/lib/module/sidebar/Sidebar.js.map +1 -1
  195. package/lib/module/styles/panel-chrome.js +14 -1
  196. package/lib/module/styles/panel-chrome.js.map +1 -1
  197. package/lib/typescript/commonjs/agent-avatar/CharacterAvatar.d.ts.map +1 -1
  198. package/lib/typescript/commonjs/agent-avatar/config-character.d.ts +0 -4
  199. package/lib/typescript/commonjs/agent-avatar/config-character.d.ts.map +1 -1
  200. package/lib/typescript/commonjs/agent-avatar/legacy-recipe.d.ts +10 -2
  201. package/lib/typescript/commonjs/agent-avatar/legacy-recipe.d.ts.map +1 -1
  202. package/lib/typescript/commonjs/agent-creator/AgentCreatorBase.d.ts.map +1 -1
  203. package/lib/typescript/commonjs/agent-creator/CharacterControls.d.ts +1 -2
  204. package/lib/typescript/commonjs/agent-creator/CharacterControls.d.ts.map +1 -1
  205. package/lib/typescript/commonjs/agent-creator/EmotionPicker.d.ts +0 -1
  206. package/lib/typescript/commonjs/agent-creator/EmotionPicker.d.ts.map +1 -1
  207. package/lib/typescript/commonjs/agent-creator/ShapeSilhouette.d.ts.map +1 -1
  208. package/lib/typescript/commonjs/agent-creator/constants.d.ts +15 -7
  209. package/lib/typescript/commonjs/agent-creator/constants.d.ts.map +1 -1
  210. package/lib/typescript/commonjs/agent-creator/messages.d.ts.map +1 -1
  211. package/lib/typescript/commonjs/app-shell/AppShellBars.d.ts +4 -0
  212. package/lib/typescript/commonjs/app-shell/AppShellBars.d.ts.map +1 -1
  213. package/lib/typescript/commonjs/app-shell/AppShellEngine.d.ts.map +1 -1
  214. package/lib/typescript/commonjs/app-shell/types.d.ts +11 -3
  215. package/lib/typescript/commonjs/app-shell/types.d.ts.map +1 -1
  216. package/lib/typescript/commonjs/appearance/BloomScope.d.ts +1 -1
  217. package/lib/typescript/commonjs/appearance/BloomScope.d.ts.map +1 -1
  218. package/lib/typescript/commonjs/appearance/context.d.ts +2 -2
  219. package/lib/typescript/commonjs/appearance/context.d.ts.map +1 -1
  220. package/lib/typescript/commonjs/appearance/types.d.ts +4 -1
  221. package/lib/typescript/commonjs/appearance/types.d.ts.map +1 -1
  222. package/lib/typescript/commonjs/content-panel/ContentPanel.d.ts +3 -4
  223. package/lib/typescript/commonjs/content-panel/ContentPanel.d.ts.map +1 -1
  224. package/lib/typescript/commonjs/content-panel/ContentPanel.web.d.ts +1 -1
  225. package/lib/typescript/commonjs/content-panel/ContentPanel.web.d.ts.map +1 -1
  226. package/lib/typescript/commonjs/content-panel/types.d.ts +2 -2
  227. package/lib/typescript/commonjs/design-tokens/shapes.d.ts +2 -2
  228. package/lib/typescript/commonjs/index.d.ts +1 -0
  229. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  230. package/lib/typescript/commonjs/index.web.d.ts +1 -0
  231. package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
  232. package/lib/typescript/commonjs/mail-thread/MailMessage.d.ts.map +1 -1
  233. package/lib/typescript/commonjs/mail-thread/MailThread.d.ts +1 -1
  234. package/lib/typescript/commonjs/mail-thread/MailThread.d.ts.map +1 -1
  235. package/lib/typescript/commonjs/mail-thread/shared.d.ts +1 -1
  236. package/lib/typescript/commonjs/mail-thread/shared.d.ts.map +1 -1
  237. package/lib/typescript/commonjs/mail-thread/types.d.ts +2 -0
  238. package/lib/typescript/commonjs/mail-thread/types.d.ts.map +1 -1
  239. package/lib/typescript/commonjs/page-footer/PageFooter.d.ts +7 -0
  240. package/lib/typescript/commonjs/page-footer/PageFooter.d.ts.map +1 -0
  241. package/lib/typescript/commonjs/page-footer/PageFooterProvider.d.ts +4 -0
  242. package/lib/typescript/commonjs/page-footer/PageFooterProvider.d.ts.map +1 -0
  243. package/lib/typescript/commonjs/page-footer/context.d.ts +3 -0
  244. package/lib/typescript/commonjs/page-footer/context.d.ts.map +1 -0
  245. package/lib/typescript/commonjs/page-footer/index.d.ts +5 -0
  246. package/lib/typescript/commonjs/page-footer/index.d.ts.map +1 -0
  247. package/lib/typescript/commonjs/page-footer/types.d.ts +26 -0
  248. package/lib/typescript/commonjs/page-footer/types.d.ts.map +1 -0
  249. package/lib/typescript/commonjs/page-footer/use-page-footer-inset.d.ts +7 -0
  250. package/lib/typescript/commonjs/page-footer/use-page-footer-inset.d.ts.map +1 -0
  251. package/lib/typescript/commonjs/sidebar/Sidebar.d.ts.map +1 -1
  252. package/lib/typescript/commonjs/sidebar/types.d.ts +1 -1
  253. package/lib/typescript/commonjs/styles/panel-chrome.d.ts +5 -0
  254. package/lib/typescript/commonjs/styles/panel-chrome.d.ts.map +1 -1
  255. package/lib/typescript/module/agent-avatar/CharacterAvatar.d.ts.map +1 -1
  256. package/lib/typescript/module/agent-avatar/config-character.d.ts +0 -4
  257. package/lib/typescript/module/agent-avatar/config-character.d.ts.map +1 -1
  258. package/lib/typescript/module/agent-avatar/legacy-recipe.d.ts +10 -2
  259. package/lib/typescript/module/agent-avatar/legacy-recipe.d.ts.map +1 -1
  260. package/lib/typescript/module/agent-creator/AgentCreatorBase.d.ts.map +1 -1
  261. package/lib/typescript/module/agent-creator/CharacterControls.d.ts +1 -2
  262. package/lib/typescript/module/agent-creator/CharacterControls.d.ts.map +1 -1
  263. package/lib/typescript/module/agent-creator/EmotionPicker.d.ts +0 -1
  264. package/lib/typescript/module/agent-creator/EmotionPicker.d.ts.map +1 -1
  265. package/lib/typescript/module/agent-creator/ShapeSilhouette.d.ts.map +1 -1
  266. package/lib/typescript/module/agent-creator/constants.d.ts +15 -7
  267. package/lib/typescript/module/agent-creator/constants.d.ts.map +1 -1
  268. package/lib/typescript/module/agent-creator/messages.d.ts.map +1 -1
  269. package/lib/typescript/module/app-shell/AppShellBars.d.ts +4 -0
  270. package/lib/typescript/module/app-shell/AppShellBars.d.ts.map +1 -1
  271. package/lib/typescript/module/app-shell/AppShellEngine.d.ts.map +1 -1
  272. package/lib/typescript/module/app-shell/types.d.ts +11 -3
  273. package/lib/typescript/module/app-shell/types.d.ts.map +1 -1
  274. package/lib/typescript/module/appearance/BloomScope.d.ts +1 -1
  275. package/lib/typescript/module/appearance/BloomScope.d.ts.map +1 -1
  276. package/lib/typescript/module/appearance/context.d.ts +2 -2
  277. package/lib/typescript/module/appearance/context.d.ts.map +1 -1
  278. package/lib/typescript/module/appearance/types.d.ts +4 -1
  279. package/lib/typescript/module/appearance/types.d.ts.map +1 -1
  280. package/lib/typescript/module/content-panel/ContentPanel.d.ts +3 -4
  281. package/lib/typescript/module/content-panel/ContentPanel.d.ts.map +1 -1
  282. package/lib/typescript/module/content-panel/ContentPanel.web.d.ts +1 -1
  283. package/lib/typescript/module/content-panel/ContentPanel.web.d.ts.map +1 -1
  284. package/lib/typescript/module/content-panel/types.d.ts +2 -2
  285. package/lib/typescript/module/design-tokens/shapes.d.ts +2 -2
  286. package/lib/typescript/module/index.d.ts +1 -0
  287. package/lib/typescript/module/index.d.ts.map +1 -1
  288. package/lib/typescript/module/index.web.d.ts +1 -0
  289. package/lib/typescript/module/index.web.d.ts.map +1 -1
  290. package/lib/typescript/module/mail-thread/MailMessage.d.ts.map +1 -1
  291. package/lib/typescript/module/mail-thread/MailThread.d.ts +1 -1
  292. package/lib/typescript/module/mail-thread/MailThread.d.ts.map +1 -1
  293. package/lib/typescript/module/mail-thread/shared.d.ts +1 -1
  294. package/lib/typescript/module/mail-thread/shared.d.ts.map +1 -1
  295. package/lib/typescript/module/mail-thread/types.d.ts +2 -0
  296. package/lib/typescript/module/mail-thread/types.d.ts.map +1 -1
  297. package/lib/typescript/module/page-footer/PageFooter.d.ts +7 -0
  298. package/lib/typescript/module/page-footer/PageFooter.d.ts.map +1 -0
  299. package/lib/typescript/module/page-footer/PageFooterProvider.d.ts +4 -0
  300. package/lib/typescript/module/page-footer/PageFooterProvider.d.ts.map +1 -0
  301. package/lib/typescript/module/page-footer/context.d.ts +3 -0
  302. package/lib/typescript/module/page-footer/context.d.ts.map +1 -0
  303. package/lib/typescript/module/page-footer/index.d.ts +5 -0
  304. package/lib/typescript/module/page-footer/index.d.ts.map +1 -0
  305. package/lib/typescript/module/page-footer/types.d.ts +26 -0
  306. package/lib/typescript/module/page-footer/types.d.ts.map +1 -0
  307. package/lib/typescript/module/page-footer/use-page-footer-inset.d.ts +7 -0
  308. package/lib/typescript/module/page-footer/use-page-footer-inset.d.ts.map +1 -0
  309. package/lib/typescript/module/sidebar/Sidebar.d.ts.map +1 -1
  310. package/lib/typescript/module/sidebar/types.d.ts +1 -1
  311. package/lib/typescript/module/styles/panel-chrome.d.ts +5 -0
  312. package/lib/typescript/module/styles/panel-chrome.d.ts.map +1 -1
  313. package/package.json +18 -1
  314. package/src/__tests__/support/adoption-matrix.ts +683 -0
  315. package/src/__tests__/support/card-surface.ts +25 -0
  316. package/src/__tests__/support/collision-fixture-barrel.ts +20 -0
  317. package/src/__tests__/support/commerce-harness.tsx +97 -0
  318. package/src/__tests__/support/composite.ts +68 -0
  319. package/src/__tests__/support/constructed-style-sheets.ts +68 -0
  320. package/src/__tests__/support/messages-in.ts +10 -0
  321. package/src/__tests__/support/press-host.ts +30 -0
  322. package/src/__tests__/support/rendered-style.ts +99 -0
  323. package/src/__tests__/support/unread-hook-fixture.ts +33 -0
  324. package/src/__tests__/support/worklet-capture-fixture.tsx +28 -0
  325. package/src/agent-avatar/AgentAvatar.tsx +1 -1
  326. package/src/agent-avatar/CharacterAvatar.tsx +1 -4
  327. package/src/agent-avatar/__tests__/artwork-golden.json +774 -0
  328. package/src/agent-avatar/config-character.ts +6 -39
  329. package/src/agent-avatar/legacy-recipe.ts +6 -34
  330. package/src/agent-creator/AgentCreatorBase.tsx +152 -121
  331. package/src/agent-creator/CharacterControls.tsx +14 -39
  332. package/src/agent-creator/EmotionPicker.tsx +16 -55
  333. package/src/agent-creator/ShapeSilhouette.tsx +1 -16
  334. package/src/agent-creator/__tests__/support/character-runtime-fixture.tsx +26 -0
  335. package/src/agent-creator/constants.ts +14 -47
  336. package/src/agent-creator/messages.ts +1 -2
  337. package/src/app-shell/AppShell.tsx +2 -2
  338. package/src/app-shell/AppShellBars.tsx +6 -4
  339. package/src/app-shell/AppShellEngine.tsx +51 -18
  340. package/src/app-shell/types.ts +11 -3
  341. package/src/appearance/BloomScope.tsx +5 -2
  342. package/src/appearance/context.ts +2 -2
  343. package/src/appearance/types.ts +4 -1
  344. package/src/content-panel/ContentPanel.tsx +32 -25
  345. package/src/content-panel/ContentPanel.web.tsx +32 -23
  346. package/src/content-panel/types.ts +2 -2
  347. package/src/design-tokens/shapes.ts +1 -1
  348. package/src/design-tokens/tokens.json +2 -2
  349. package/src/index.ts +1 -0
  350. package/src/index.web.ts +1 -0
  351. package/src/locale/translations/ar.ts +1 -1
  352. package/src/locale/translations/bn.ts +1 -1
  353. package/src/locale/translations/ca.ts +1 -1
  354. package/src/locale/translations/de.ts +1 -1
  355. package/src/locale/translations/es.ts +1 -1
  356. package/src/locale/translations/fr.ts +1 -1
  357. package/src/locale/translations/hi.ts +1 -1
  358. package/src/locale/translations/id.ts +1 -1
  359. package/src/locale/translations/it.ts +1 -1
  360. package/src/locale/translations/ja.ts +1 -1
  361. package/src/locale/translations/pt.ts +1 -1
  362. package/src/locale/translations/ru.ts +1 -1
  363. package/src/locale/translations/tr.ts +1 -1
  364. package/src/locale/translations/zh.ts +1 -1
  365. package/src/mail-thread/MailMessage.tsx +9 -11
  366. package/src/mail-thread/MailThread.tsx +3 -1
  367. package/src/mail-thread/shared.ts +2 -1
  368. package/src/mail-thread/types.ts +2 -0
  369. package/src/page-footer/PageFooter.tsx +96 -0
  370. package/src/page-footer/PageFooterProvider.tsx +9 -0
  371. package/src/page-footer/context.ts +6 -0
  372. package/src/page-footer/index.ts +4 -0
  373. package/src/page-footer/types.ts +26 -0
  374. package/src/page-footer/use-page-footer-inset.ts +17 -0
  375. package/src/sidebar/Sidebar.tsx +5 -4
  376. package/src/sidebar/types.ts +1 -1
  377. package/src/styles/panel-chrome.ts +9 -1
  378. package/src/theme/__tests__/__fixtures__/golden-resolved-tokens.json +9346 -0
  379. package/src/theme/__tests__/__fixtures__/tonal-glass-primary-failures.json +69 -0
  380. package/src/theme/__tests__/fixtures/color-engine-golden.json +1 -0
  381. package/assets/character-runtime/authored-parts.mjs +0 -754
  382. package/assets/character-runtime/catalog-parts.mjs +0 -362
  383. package/assets/character-runtime/character-recipe.mjs +0 -247
  384. package/assets/character-runtime/clippo-geometry.mjs +0 -679
  385. package/assets/character-runtime/controller-mode.mjs +0 -208
  386. package/assets/character-runtime/cyclops-geometry.mjs +0 -180
  387. package/assets/character-runtime/migrated-contours.mjs +0 -2067
  388. package/assets/character-runtime/migrated-faces.mjs +0 -59
  389. package/assets/character-runtime/pose-transition.mjs +0 -523
  390. package/assets/character-runtime/preparation-cache.mjs +0 -60
  391. package/assets/character-runtime/render-errors.mjs +0 -180
  392. package/assets/character-runtime/resolution.mjs +0 -10
  393. package/assets/character-runtime/sha256.mjs +0 -44
  394. package/assets/character-runtime/shared-programs.mjs +0 -534
  395. package/assets/character-runtime/shared-surface.mjs +0 -490
  396. package/assets/character-runtime/shared-textures.mjs +0 -420
  397. package/assets/character-runtime/thumbnails/eyes/todd.png +0 -0
  398. package/lib/commonjs/agent-avatar/character-colors.js +0 -19
  399. package/lib/commonjs/agent-avatar/character-colors.js.map +0 -1
  400. package/lib/commonjs/agent-avatar/character-shapes.js +0 -106
  401. package/lib/commonjs/agent-avatar/character-shapes.js.map +0 -1
  402. package/lib/commonjs/agent-creator/ClippoArtwork.js +0 -63
  403. package/lib/commonjs/agent-creator/ClippoArtwork.js.map +0 -1
  404. package/lib/commonjs/agent-creator/CyclopsArtwork.js +0 -45
  405. package/lib/commonjs/agent-creator/CyclopsArtwork.js.map +0 -1
  406. package/lib/commonjs/agent-creator/ToddArtwork.js +0 -29
  407. package/lib/commonjs/agent-creator/ToddArtwork.js.map +0 -1
  408. package/lib/module/agent-avatar/character-colors.js +0 -15
  409. package/lib/module/agent-avatar/character-colors.js.map +0 -1
  410. package/lib/module/agent-avatar/character-shapes.js +0 -97
  411. package/lib/module/agent-avatar/character-shapes.js.map +0 -1
  412. package/lib/module/agent-creator/ClippoArtwork.js +0 -59
  413. package/lib/module/agent-creator/ClippoArtwork.js.map +0 -1
  414. package/lib/module/agent-creator/CyclopsArtwork.js +0 -41
  415. package/lib/module/agent-creator/CyclopsArtwork.js.map +0 -1
  416. package/lib/module/agent-creator/ToddArtwork.js +0 -25
  417. package/lib/module/agent-creator/ToddArtwork.js.map +0 -1
  418. package/lib/typescript/commonjs/agent-avatar/character-colors.d.ts +0 -13
  419. package/lib/typescript/commonjs/agent-avatar/character-colors.d.ts.map +0 -1
  420. package/lib/typescript/commonjs/agent-avatar/character-shapes.d.ts +0 -19
  421. package/lib/typescript/commonjs/agent-avatar/character-shapes.d.ts.map +0 -1
  422. package/lib/typescript/commonjs/agent-creator/ClippoArtwork.d.ts +0 -6
  423. package/lib/typescript/commonjs/agent-creator/ClippoArtwork.d.ts.map +0 -1
  424. package/lib/typescript/commonjs/agent-creator/CyclopsArtwork.d.ts +0 -5
  425. package/lib/typescript/commonjs/agent-creator/CyclopsArtwork.d.ts.map +0 -1
  426. package/lib/typescript/commonjs/agent-creator/ToddArtwork.d.ts +0 -6
  427. package/lib/typescript/commonjs/agent-creator/ToddArtwork.d.ts.map +0 -1
  428. package/lib/typescript/module/agent-avatar/character-colors.d.ts +0 -13
  429. package/lib/typescript/module/agent-avatar/character-colors.d.ts.map +0 -1
  430. package/lib/typescript/module/agent-avatar/character-shapes.d.ts +0 -19
  431. package/lib/typescript/module/agent-avatar/character-shapes.d.ts.map +0 -1
  432. package/lib/typescript/module/agent-creator/ClippoArtwork.d.ts +0 -6
  433. package/lib/typescript/module/agent-creator/ClippoArtwork.d.ts.map +0 -1
  434. package/lib/typescript/module/agent-creator/CyclopsArtwork.d.ts +0 -5
  435. package/lib/typescript/module/agent-creator/CyclopsArtwork.d.ts.map +0 -1
  436. package/lib/typescript/module/agent-creator/ToddArtwork.d.ts +0 -6
  437. package/lib/typescript/module/agent-creator/ToddArtwork.d.ts.map +0 -1
  438. package/src/agent-avatar/character-colors.ts +0 -12
  439. package/src/agent-avatar/character-shapes.ts +0 -122
  440. package/src/agent-creator/ClippoArtwork.tsx +0 -49
  441. package/src/agent-creator/CyclopsArtwork.tsx +0 -27
  442. package/src/agent-creator/ToddArtwork.tsx +0 -24
@@ -1,362 +0,0 @@
1
- // Compatibility comes from original native donor meshes, never a fake enabled
2
- // catalog selection. Source assemblies and the target's activity payload stay
3
- // in the original renderer.
4
- import { decodeAppearance, encodeAppearance } from './appearance-codec.mjs';
5
- import {
6
- authoredAssemblyRecords,
7
- authoredEyeRecords,
8
- assembleAuthoredRecords,
9
- fitCatalogPartRecords,
10
- transformAuthoredRecord,
11
- } from './authored-parts.mjs';
12
- import { NATIVE_PARTS } from './character-recipe.mjs';
13
- import { sha256 } from './sha256.mjs';
14
- const encoder = new TextEncoder();
15
- const fail = (message) => {
16
- throw Error(`Catalog avatar parts: ${message}`);
17
- };
18
- const references = new Map();
19
- let retainedBytes = 0;
20
- const MAXIMUM_BYTES = 8 * 1024 * 1024;
21
- const originalPaint = new Map();
22
- /** Read an unnamed paint from the actual original body material, not a palette approximation. */
23
- export function originalBodyColor(module, preset) {
24
- if (originalPaint.has(preset)) return originalPaint.get(preset);
25
- const result = module.orbitPrepareAssembly(
26
- module.presetAppearance(preset),
27
- 0,
28
- `original-paint:${preset}`,
29
- false,
30
- );
31
- if (!result.bytes || result.error)
32
- fail(result.error || 'original body paint missing');
33
- const bytes = result.bytes,
34
- view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
35
- if (
36
- bytes.length < 48 ||
37
- view.getUint32(0, true) < 1 ||
38
- view.getUint32(28, true) !== 1
39
- )
40
- fail('unrecognized original body paint layout');
41
- const rgb = [0, 1, 2].map((k) => view.getFloat32(32 + k * 4, true));
42
- if (rgb.some((v) => !Number.isFinite(v) || v < 0 || v > 1))
43
- fail('invalid original body paint');
44
- const hex =
45
- '#' +
46
- rgb
47
- .map((v) =>
48
- Math.round(v * 255)
49
- .toString(16)
50
- .padStart(2, '0'),
51
- )
52
- .join('');
53
- originalPaint.set(preset, hex);
54
- return hex;
55
- }
56
- /** Editable backing paint, with the original RGB retained for unnamed colors. */
57
- export function originalPalettePaint(module, preset) {
58
- const color = decodeAppearance(module.presetAppearance(preset)).color;
59
- return module.catalog(1).some((item) => item.id === color)
60
- ? { color }
61
- : { color: 'yellow', bodyColor: originalBodyColor(module, preset) };
62
- }
63
- export function recordHasLabel(info, part, label) {
64
- const needle = encoder.encode(label),
65
- bytes = info.bytes;
66
- for (
67
- let at = part.start + 24;
68
- at + 4 + needle.length <= part.nameOffset - 4;
69
- at++
70
- )
71
- if (
72
- new DataView(bytes.buffer, bytes.byteOffset + at, 4).getUint32(
73
- 0,
74
- true,
75
- ) === needle.length &&
76
- needle.every((v, i) => bytes[at + 4 + i] === v)
77
- )
78
- return true;
79
- return false;
80
- }
81
- function isCategory(info, part, category) {
82
- const ids =
83
- category === 'eyes'
84
- ? [...NATIVE_PARTS.eyes, 'source_integrated_eye', 'brows']
85
- : NATIVE_PARTS[category].filter((id) => id !== 'none');
86
- return ids.some((id) => recordHasLabel(info, part, id));
87
- }
88
- function record(info, part) {
89
- return {
90
- bytes: info.bytes.slice(part.start, part.end),
91
- name: part.name,
92
- bounds: part.bounds,
93
- };
94
- }
95
- function mappedFaceReference(module, appearance, request) {
96
- const result = module.orbitPrepareAssembly(
97
- appearance,
98
- request.quality,
99
- `${request.key}:uncovered-donor`,
100
- false,
101
- );
102
- if (!result.bytes || result.error) return null;
103
- const info = authoredAssemblyRecords(result.bytes.slice());
104
- return info.records.slice(1).some((part) => isCategory(info, part, 'eyes'))
105
- ? info
106
- : null;
107
- }
108
- async function reference(module, category, id, request) {
109
- const key = JSON.stringify([category, id, request.quality]);
110
- if (references.has(key)) {
111
- const cached = references.get(key);
112
- references.delete(key);
113
- references.set(key, cached);
114
- return cached;
115
- }
116
- if (category === 'eyes' && id === 'todd') {
117
- const result = module.orbitPrepareAssembly(
118
- module.presetAppearance('lime_frog'),
119
- request.quality,
120
- `${request.key}:donor:eyes:todd`,
121
- false,
122
- );
123
- if (!result.bytes || result.error)
124
- fail(result.error || 'Todd eye donor missing');
125
- const info = authoredAssemblyRecords(result.bytes.slice());
126
- if (!authoredEyeRecords(info).length) fail('Todd eye meshes missing');
127
- return info;
128
- }
129
- if (category === 'accessory' && id === 'felipe_beret') {
130
- const result = module.orbitPrepareAssembly(
131
- module.presetAppearance('blue_beret'),
132
- request.quality,
133
- `${request.key}:donor:accessory:felipe_beret`,
134
- false,
135
- );
136
- if (!result.bytes || result.error)
137
- fail(result.error || 'Felipe beret donor missing');
138
- const info = authoredAssemblyRecords(result.bytes.slice());
139
- if (
140
- !info.records
141
- .slice(1)
142
- .some((part) => recordHasLabel(info, part, 'beret'))
143
- )
144
- fail('Felipe beret mesh missing');
145
- return info;
146
- }
147
- const shapes = module.catalog(0).map((item) => item.id),
148
- eyes =
149
- category === 'eyes'
150
- ? [id]
151
- : ['oval', ...NATIVE_PARTS.eyes.filter((id) => id !== 'oval')];
152
- let donor;
153
- for (const shape of ['circle', ...shapes.filter((id) => id !== 'circle')]) {
154
- for (const eye of eyes) {
155
- const appearance = encodeAppearance({
156
- version: 1,
157
- shape,
158
- color: 'blue',
159
- eyes: eye,
160
- eyewear: category === 'eyewear' ? id : 'none',
161
- accessories: category === 'accessory' ? [id] : [],
162
- accessoryColors: {},
163
- constrained: 0,
164
- depth: 0.5,
165
- model: null,
166
- rig: null,
167
- hereCharacter: null,
168
- });
169
- const result = module.orbitPrepareAssembly(
170
- appearance,
171
- request.quality,
172
- `${request.key}:donor:${category}:${id}:${shape}:${eye}`,
173
- false,
174
- );
175
- if (!result.bytes || result.error) continue;
176
- let info = authoredAssemblyRecords(result.bytes.slice());
177
- if (!info.records.slice(1).some((part) => recordHasLabel(info, part, id)))
178
- continue;
179
- if (
180
- !info.records.slice(1).some((part) => isCategory(info, part, 'eyes'))
181
- ) {
182
- const exposed = decodeAppearance(appearance);
183
- exposed.eyewear = 'none';
184
- const face = mappedFaceReference(
185
- module,
186
- encodeAppearance(exposed),
187
- request,
188
- );
189
- if (!face) continue;
190
- const records = info.records.map((part) => record(info, part));
191
- records.splice(
192
- 1,
193
- 0,
194
- ...face.records
195
- .slice(1)
196
- .filter((part) => isCategory(face, part, 'eyes'))
197
- .map((part) => record(face, part)),
198
- );
199
- info = authoredAssemblyRecords(
200
- await assembleAuthoredRecords(info, records),
201
- );
202
- }
203
- donor = info;
204
- break;
205
- }
206
- if (donor) break;
207
- }
208
- if (!donor) fail(`no original donor for ${category}:${id}`);
209
- if (donor.bytes.length <= MAXIMUM_BYTES) {
210
- references.set(key, donor);
211
- retainedBytes += donor.bytes.length;
212
- while (references.size > 24 || retainedBytes > MAXIMUM_BYTES) {
213
- const first = references.keys().next().value;
214
- retainedBytes -= references.get(first).bytes.length;
215
- references.delete(first);
216
- }
217
- }
218
- return donor;
219
- }
220
- /** Keep actual named-preset geometry/default pieces when only parts or paint
221
- * change. Original untouched presets never enter this adapter. */
222
- export async function composePresetBody(module, bytes, request) {
223
- const preset = request.authoredParts?.bodyPreset;
224
- if (!preset) return bytes;
225
- const prepared = module.orbitPrepareAssembly(
226
- module.presetAppearance(preset),
227
- request.quality,
228
- `${request.key}:body:${preset}`,
229
- request.activities,
230
- );
231
- if (!prepared.bytes || prepared.error)
232
- fail(prepared.error || 'original preset body missing');
233
- const source = authoredAssemblyRecords(prepared.bytes.slice()),
234
- target = authoredAssemblyRecords(bytes),
235
- records = source.records.map((part) => record(source, part));
236
- if (
237
- !source.records.slice(1).some((part) => isCategory(source, part, 'eyes'))
238
- ) {
239
- // Opaque sunglasses legitimately omit the original eye meshes. Recover the
240
- // engine's actual hidden-eye reference without changing the preserved body.
241
- const exposed = decodeAppearance(module.presetAppearance(preset));
242
- exposed.hereCharacter = null;
243
- exposed.eyewear = 'none';
244
- if (exposed.model) exposed.model.eyewear = null;
245
- const result = module.orbitPrepareAssembly(
246
- encodeAppearance(exposed),
247
- request.quality,
248
- `${request.key}:hidden-eyes:${preset}`,
249
- false,
250
- );
251
- if (!result.bytes || result.error)
252
- fail(result.error || 'hidden original eye reference missing');
253
- const face = authoredAssemblyRecords(result.bytes.slice()),
254
- eyes = face.records
255
- .slice(1)
256
- .filter((part) => isCategory(face, part, 'eyes'));
257
- if (!eyes.length) fail('hidden original eye classification missing');
258
- records.splice(1, 0, ...eyes.map((part) => record(face, part)));
259
- }
260
-
261
- if (request.authoredParts.paintBody) {
262
- const out = new DataView(records[0].bytes.buffer),
263
- sourceView = new DataView(source.bytes.buffer, source.bytes.byteOffset),
264
- targetView = new DataView(target.bytes.buffer, target.bytes.byteOffset);
265
- if (
266
- sourceView.getUint32(source.body.start + 24, true) !== 1 ||
267
- targetView.getUint32(target.body.start + 24, true) !== 1
268
- )
269
- fail('unrecognized body paint layout');
270
- for (const at of [28, 60])
271
- for (let k = 0; k < 3; k++)
272
- out.setFloat32(
273
- at + k * 4,
274
- targetView.getFloat32(target.body.start + at + k * 4, true),
275
- true,
276
- );
277
- const hash = await sha256(records[0].bytes);
278
- records[0].bytes.set(
279
- encoder.encode(hash),
280
- source.body.nameOffset - source.body.start,
281
- );
282
- records[0].name = hash + source.body.name.slice(64);
283
- }
284
- // Preserve the body's actual authored activity payload and fitted hands,
285
- // instead of borrowing the neutral backing circle's fit.
286
- const footer = source.footer.slice(),
287
- view = new DataView(footer.buffer);
288
- for (let k = 0; k < 3; k++) {
289
- view.setFloat32(28 + k * 4, source.body.bounds.min[k], true);
290
- view.setFloat32(40 + k * 4, source.body.bounds.max[k], true);
291
- }
292
- return assembleAuthoredRecords(
293
- { ...source, body: { ...source.body, name: records[0].name }, footer },
294
- records,
295
- );
296
- }
297
- /** Native catalog pieces can be transplanted onto any actual body. */
298
- export async function composeCatalogParts(
299
- module,
300
- bytes,
301
- request,
302
- categories = ['eyes', 'eyewear', 'accessory'],
303
- ) {
304
- let info = authoredAssemblyRecords(bytes);
305
- for (const category of categories) {
306
- const id = request.authoredParts?.[category];
307
- if (!id) continue;
308
- // An authored body's own eye style already has its exact sculpted layout.
309
- if (
310
- category === 'eyes' &&
311
- request.authoredParts.bodyPreset &&
312
- authoredEyeRecords(info).length &&
313
- authoredEyeRecords(info).every((p) => recordHasLabel(info, p, id))
314
- )
315
- continue;
316
- const virtual =
317
- (category === 'accessory' && id === 'felipe_beret') ||
318
- (category === 'eyes' && id === 'todd');
319
- if (!NATIVE_PARTS[category].includes(id) && !virtual) continue;
320
- const records = info.records.map((part) => record(info, part));
321
- const removed = new Set(
322
- info.records
323
- .slice(1)
324
- .filter((part) => isCategory(info, part, category))
325
- .map((part) => part.part),
326
- );
327
- if (category === 'eyes' && !removed.size)
328
- fail('target face classification missing');
329
- let fitted = [];
330
- if (id !== 'none') {
331
- const donor = await reference(module, category, id, request);
332
- const transforms = fitCatalogPartRecords(
333
- info,
334
- donor,
335
- category,
336
- id === 'felipe_beret' ? 'beret' : id,
337
- {
338
- singleEye: request.authoredParts?.eyes === 'cyclops',
339
- faceLayout: request.faceLayout,
340
- },
341
- );
342
- fitted = await Promise.all(
343
- transforms.map(({ part, ...transform }) =>
344
- transformAuthoredRecord(donor.bytes, part, transform),
345
- ),
346
- );
347
- }
348
- const kept = records.filter((_, index) => !removed.has(index));
349
- const at = category === 'eyes' ? 1 : kept.length;
350
- kept.splice(at, 0, ...fitted);
351
- bytes = await assembleAuthoredRecords(info, kept);
352
- info = authoredAssemblyRecords(bytes);
353
- }
354
- return bytes;
355
- }
356
- export function catalogPartCacheStats() {
357
- return {
358
- entries: references.size,
359
- bytes: retainedBytes,
360
- maximumBytes: MAXIMUM_BYTES,
361
- };
362
- }
@@ -1,247 +0,0 @@
1
- /** Resolve editable defaults without passing virtual catalog IDs to the engine. */
2
- import { MIGRATED_CONTOURS } from './migrated-contours.mjs';
3
- export function isLegacyRecipe(props) {
4
- return !props.config.character || props.config.character.preset === 'bloom';
5
- }
6
- export const MIGRATED_SHAPE_IDS = Object.freeze([
7
- 'slender',
8
- 'pocket',
9
- 'petal',
10
- 'star',
11
- 'cloud',
12
- 'shield',
13
- 'pebble',
14
- 'squircle',
15
- ]);
16
- export function withCharacterGeometry(props) {
17
- const shape = props.config.character?.selections?.shape;
18
- if (!Object.hasOwn(MIGRATED_CONTOURS, shape)) return props;
19
- return {
20
- ...props,
21
- legacy: props.legacy?.points
22
- ? props.legacy
23
- : { points: MIGRATED_CONTOURS[shape] },
24
- };
25
- }
26
- const PRESET_DEFAULTS = Object.freeze({
27
- blue_beret: {
28
- shape: 'six_lobed_flower',
29
- eyes: 'oval',
30
- eyewear: 'none',
31
- accessory: 'felipe_beret',
32
- },
33
- alfred: {
34
- shape: 'rounded_triangle',
35
- eyes: 'sleepy_lids',
36
- eyewear: 'tall_oval_frames',
37
- accessory: 'bow',
38
- },
39
- purple_heart: {
40
- shape: 'heart',
41
- eyes: 'oval',
42
- eyewear: 'round_sunglasses',
43
- accessory: 'none',
44
- },
45
- lime_frog: {
46
- shape: 'rounded_head_two_ears',
47
- eyes: 'todd',
48
- eyewear: 'none',
49
- accessory: 'bow',
50
- },
51
- coral_monocle: {
52
- shape: 'twelve_scalloped_rosette',
53
- eyes: 'double_highlights',
54
- eyewear: 'monocle',
55
- accessory: 'none',
56
- },
57
- gus: {
58
- shape: 'rounded_diamond',
59
- eyes: 'oval',
60
- eyewear: 'classic_sunglasses',
61
- accessory: 'orb',
62
- },
63
- blue_spectacles: {
64
- shape: 'rounded_cube',
65
- eyes: 'crescent_inset',
66
- eyewear: 'tall_oval_frames',
67
- accessory: 'three_lobe',
68
- },
69
- lime_headphones: {
70
- shape: 'circle_two_ears',
71
- eyes: 'swept_lids',
72
- eyewear: 'none',
73
- accessory: 'headphones',
74
- },
75
- });
76
- export function characterRecipe(props) {
77
- if (props.legacy && isLegacyRecipe(props))
78
- return {
79
- preset: 'legacy',
80
- selections: {
81
- shape: props.legacy.shape ?? 'circle',
82
- eyes: props.legacy.eyes ?? 'oval',
83
- ...props.legacy.selections,
84
- },
85
- ...props.legacy.patch,
86
- ...(props.legacy.eyeSpacing !== undefined
87
- ? { eyeSpacing: props.legacy.eyeSpacing }
88
- : {}),
89
- };
90
- const recipe = props.config.character;
91
- if (recipe?.preset !== 'clippo') return recipe;
92
- return {
93
- ...recipe,
94
- selections: { shape: 'clippo', eyes: 'clippo', ...recipe.selections },
95
- // A palette selection is an explicit replacement of the preset's grey.
96
- ...(!recipe.bodyColor && !recipe.selections?.color
97
- ? { bodyColor: '#999b9d' }
98
- : {}),
99
- };
100
- }
101
-
102
- export function authoredPartsFor(props) {
103
- const recipe = characterRecipe(props);
104
- const selections = recipe?.selections ?? {};
105
- const customized = Boolean(
106
- props.legacy || recipe?.bodyColor || Object.keys(selections).length,
107
- );
108
- const defaults = !isLegacyRecipe(props)
109
- ? PRESET_DEFAULTS[recipe.preset]
110
- : undefined;
111
- const selectedShape = selections.shape ?? defaults?.shape;
112
- const shape =
113
- selectedShape === 'todd' ? 'rounded_head_two_ears' : selectedShape;
114
- const eyes =
115
- selections.eyes ??
116
- defaults?.eyes ??
117
- (customized && recipe?.preset === 'lime_frog' ? 'todd' : undefined);
118
- const accessory =
119
- selections.accessory ??
120
- defaults?.accessory ??
121
- (customized && recipe?.preset === 'blue_beret'
122
- ? 'felipe_beret'
123
- : undefined);
124
- if (!customized) return {};
125
- const bodyPreset =
126
- !shape &&
127
- !isLegacyRecipe(props) &&
128
- ORIGINAL_PRESETS.includes(recipe?.preset)
129
- ? recipe.preset
130
- : undefined;
131
- return {
132
- ...(bodyPreset ? { bodyPreset } : {}),
133
- ...(bodyPreset &&
134
- (recipe.bodyColor || selections.color || bodyPreset !== recipe.preset)
135
- ? { paintBody: true }
136
- : {}),
137
- ...(selections.shape === 'clippo' ? { shape: 'clippo' } : {}),
138
- ...((!isLegacyRecipe(props) || !props.legacy?.points) &&
139
- (MIGRATED_SHAPE_IDS.includes(shape) || NATIVE_PARTS.shape.includes(shape))
140
- ? { faceShape: shape }
141
- : {}),
142
- ...(eyes ? { eyes } : {}),
143
- ...((selections.eyewear ?? defaults?.eyewear)
144
- ? { eyewear: selections.eyewear ?? defaults?.eyewear }
145
- : {}),
146
- ...(accessory ? { accessory } : {}),
147
- };
148
- }
149
- export const ORIGINAL_PRESETS = Object.freeze([
150
- 'blue_beret',
151
- 'alfred',
152
- 'purple_heart',
153
- 'lime_frog',
154
- 'coral_monocle',
155
- 'gus',
156
- 'blue_spectacles',
157
- 'lime_headphones',
158
- ]);
159
- // Exact shapes reported by the original engine's eight named appearances.
160
- const BODY_SIGNATURES = Object.freeze({
161
- six_lobed_flower: 'blue_beret',
162
- rounded_triangle: 'alfred',
163
- heart: 'purple_heart',
164
- rounded_head_two_ears: 'lime_frog',
165
- twelve_scalloped_rosette: 'coral_monocle',
166
- rounded_diamond: 'gus',
167
- rounded_cube: 'blue_spectacles',
168
- circle_two_ears: 'lime_headphones',
169
- todd: 'lime_frog',
170
- });
171
- /** The body's authored reaction follows its geometry, independently of its pieces. */
172
- export function bodySignatureFor(props) {
173
- const recipe = characterRecipe(props),
174
- parts = authoredPartsFor(props);
175
- if (parts.bodyPreset) return parts.bodyPreset;
176
- if (
177
- !isLegacyRecipe(props) &&
178
- !recipe.selections?.shape &&
179
- ORIGINAL_PRESETS.includes(recipe.preset)
180
- )
181
- return recipe.preset;
182
- // Distinct migrated contours and Clippo use Todd's original signature as the
183
- // shared standard; they never fall back to the original Wave/maracas.
184
- if (props.legacy?.points) return 'lime_frog';
185
- return (
186
- BODY_SIGNATURES[
187
- recipe.selections?.shape ?? PRESET_DEFAULTS[recipe.preset]?.shape
188
- ] ?? 'lime_frog'
189
- );
190
- }
191
- /** Prepared authored bodies retain their actual defaults, not the fitting scene's catalog selections. */
192
- export function bodySelectionDefaults(preset, appearance) {
193
- return {
194
- shape: appearance.shape,
195
- eyes: preset === 'lime_frog' ? 'todd' : appearance.eyes,
196
- eyewear: appearance.eyewear ?? 'none',
197
- accessory:
198
- preset === 'blue_beret'
199
- ? 'felipe_beret'
200
- : (appearance.accessories?.[0] ?? 'none'),
201
- };
202
- }
203
- export const NATIVE_PARTS = Object.freeze({
204
- shape: Object.freeze([
205
- 'circle',
206
- 'rounded_triangle',
207
- 'capsule',
208
- 'rounded_head_two_ears',
209
- 'six_lobed_flower',
210
- 'heart',
211
- 'four_lobed_butterfly',
212
- 'circle_two_ears',
213
- 'twelve_scalloped_rosette',
214
- 'rounded_cube',
215
- 'rounded_diamond',
216
- ]),
217
- eyes: Object.freeze([
218
- 'swept_lids',
219
- 'oval',
220
- 'sparkle_capsules',
221
- 'highlight_capsules',
222
- 'dots',
223
- 'double_highlights',
224
- 'round_inset',
225
- 'crescent_inset',
226
- 'sleepy_lids',
227
- ]),
228
- eyewear: Object.freeze([
229
- 'none',
230
- 'monocle',
231
- 'tall_oval_frames',
232
- 'separate_trapezoid_lenses',
233
- 'classic_sunglasses',
234
- 'round_sunglasses',
235
- ]),
236
- accessory: Object.freeze([
237
- 'none',
238
- 'headphones',
239
- 'bow',
240
- 'beanie',
241
- 'hat',
242
- 'beret',
243
- 'orb',
244
- 'three_lobe',
245
- 'crown',
246
- ]),
247
- });