@hjmds/react 1.41.2 → 1.42.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 (389) hide show
  1. package/README.md +2 -2
  2. package/dist/actions.d.ts +41 -0
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +40 -3
  5. package/dist/actions.js.map +1 -1
  6. package/dist/activity-chip.d.ts.map +1 -1
  7. package/dist/activity-chip.js +1 -0
  8. package/dist/activity-chip.js.map +1 -1
  9. package/dist/advanced-display.d.ts +47 -14
  10. package/dist/advanced-display.d.ts.map +1 -1
  11. package/dist/advanced-display.js +72 -17
  12. package/dist/advanced-display.js.map +1 -1
  13. package/dist/advanced-forms.d.ts.map +1 -1
  14. package/dist/advanced-forms.js +1 -0
  15. package/dist/advanced-forms.js.map +1 -1
  16. package/dist/affix.d.ts +6 -1
  17. package/dist/affix.d.ts.map +1 -1
  18. package/dist/affix.js +5 -3
  19. package/dist/affix.js.map +1 -1
  20. package/dist/agreement.d.ts.map +1 -1
  21. package/dist/agreement.js +1 -0
  22. package/dist/agreement.js.map +1 -1
  23. package/dist/alert-dialog-queue.d.ts +24 -0
  24. package/dist/alert-dialog-queue.d.ts.map +1 -0
  25. package/dist/alert-dialog-queue.js +44 -0
  26. package/dist/alert-dialog-queue.js.map +1 -0
  27. package/dist/anchor.d.ts.map +1 -1
  28. package/dist/anchor.js +1 -0
  29. package/dist/anchor.js.map +1 -1
  30. package/dist/asset.d.ts.map +1 -1
  31. package/dist/asset.js +1 -0
  32. package/dist/asset.js.map +1 -1
  33. package/dist/auth-screen.d.ts.map +1 -1
  34. package/dist/auth-screen.js +1 -0
  35. package/dist/auth-screen.js.map +1 -1
  36. package/dist/avatar-blobatar-motion.d.ts.map +1 -1
  37. package/dist/avatar-blobatar-motion.js +1 -0
  38. package/dist/avatar-blobatar-motion.js.map +1 -1
  39. package/dist/avatar-blobatar.d.ts.map +1 -1
  40. package/dist/avatar-blobatar.js +1 -0
  41. package/dist/avatar-blobatar.js.map +1 -1
  42. package/dist/bottom-cta.d.ts.map +1 -1
  43. package/dist/bottom-cta.js +1 -0
  44. package/dist/bottom-cta.js.map +1 -1
  45. package/dist/bottom-info.d.ts.map +1 -1
  46. package/dist/bottom-info.js +1 -0
  47. package/dist/bottom-info.js.map +1 -1
  48. package/dist/bottom-navigation.d.ts.map +1 -1
  49. package/dist/bottom-navigation.js +1 -0
  50. package/dist/bottom-navigation.js.map +1 -1
  51. package/dist/breadcrumb.d.ts.map +1 -1
  52. package/dist/breadcrumb.js +1 -0
  53. package/dist/breadcrumb.js.map +1 -1
  54. package/dist/calendar.d.ts.map +1 -1
  55. package/dist/calendar.js +1 -0
  56. package/dist/calendar.js.map +1 -1
  57. package/dist/carousel-motion.d.ts.map +1 -1
  58. package/dist/carousel-motion.js +1 -0
  59. package/dist/carousel-motion.js.map +1 -1
  60. package/dist/carousel.d.ts.map +1 -1
  61. package/dist/carousel.js +1 -0
  62. package/dist/carousel.js.map +1 -1
  63. package/dist/celebration.d.ts.map +1 -1
  64. package/dist/celebration.js +1 -0
  65. package/dist/celebration.js.map +1 -1
  66. package/dist/chart.d.ts +7 -2
  67. package/dist/chart.d.ts.map +1 -1
  68. package/dist/chart.js +6 -3
  69. package/dist/chart.js.map +1 -1
  70. package/dist/choice-row.d.ts +10 -2
  71. package/dist/choice-row.d.ts.map +1 -1
  72. package/dist/choice-row.js +7 -3
  73. package/dist/choice-row.js.map +1 -1
  74. package/dist/clipboard.d.ts.map +1 -1
  75. package/dist/clipboard.js +1 -0
  76. package/dist/clipboard.js.map +1 -1
  77. package/dist/collapsible.d.ts.map +1 -1
  78. package/dist/collapsible.js +1 -0
  79. package/dist/collapsible.js.map +1 -1
  80. package/dist/collection-rail.d.ts.map +1 -1
  81. package/dist/collection-rail.js +3 -1
  82. package/dist/collection-rail.js.map +1 -1
  83. package/dist/color-picker.d.ts.map +1 -1
  84. package/dist/color-picker.js +1 -0
  85. package/dist/color-picker.js.map +1 -1
  86. package/dist/command-palette.d.ts.map +1 -1
  87. package/dist/command-palette.js +1 -0
  88. package/dist/command-palette.js.map +1 -1
  89. package/dist/content-transition.d.ts.map +1 -1
  90. package/dist/content-transition.js +1 -0
  91. package/dist/content-transition.js.map +1 -1
  92. package/dist/context-menu.d.ts.map +1 -1
  93. package/dist/context-menu.js +1 -0
  94. package/dist/context-menu.js.map +1 -1
  95. package/dist/conversation-row.d.ts.map +1 -1
  96. package/dist/conversation-row.js +1 -0
  97. package/dist/conversation-row.js.map +1 -1
  98. package/dist/data-table.d.ts.map +1 -1
  99. package/dist/data-table.js +1 -0
  100. package/dist/data-table.js.map +1 -1
  101. package/dist/date-entry.d.ts.map +1 -1
  102. package/dist/date-entry.js +1 -0
  103. package/dist/date-entry.js.map +1 -1
  104. package/dist/date-picker.d.ts.map +1 -1
  105. package/dist/date-picker.js +1 -0
  106. package/dist/date-picker.js.map +1 -1
  107. package/dist/date-range.d.ts.map +1 -1
  108. package/dist/date-range.js +1 -0
  109. package/dist/date-range.js.map +1 -1
  110. package/dist/design-profile.d.ts.map +1 -1
  111. package/dist/design-profile.js +1 -0
  112. package/dist/design-profile.js.map +1 -1
  113. package/dist/display.d.ts +21 -1
  114. package/dist/display.d.ts.map +1 -1
  115. package/dist/display.js +34 -8
  116. package/dist/display.js.map +1 -1
  117. package/dist/duration-field.d.ts.map +1 -1
  118. package/dist/duration-field.js +1 -0
  119. package/dist/duration-field.js.map +1 -1
  120. package/dist/effect-surface.d.ts.map +1 -1
  121. package/dist/effect-surface.js +1 -0
  122. package/dist/effect-surface.js.map +1 -1
  123. package/dist/evidence.d.ts +1 -1
  124. package/dist/evidence.js +1 -1
  125. package/dist/evidence.js.map +1 -1
  126. package/dist/feedback.d.ts.map +1 -1
  127. package/dist/feedback.js +1 -0
  128. package/dist/feedback.js.map +1 -1
  129. package/dist/field-group.d.ts.map +1 -1
  130. package/dist/field-group.js +1 -0
  131. package/dist/field-group.js.map +1 -1
  132. package/dist/file-picker.d.ts.map +1 -1
  133. package/dist/file-picker.js +1 -0
  134. package/dist/file-picker.js.map +1 -1
  135. package/dist/floating-action-button.d.ts.map +1 -1
  136. package/dist/floating-action-button.js +1 -0
  137. package/dist/floating-action-button.js.map +1 -1
  138. package/dist/folder-preview.d.ts.map +1 -1
  139. package/dist/folder-preview.js +1 -0
  140. package/dist/folder-preview.js.map +1 -1
  141. package/dist/forms.d.ts +30 -6
  142. package/dist/forms.d.ts.map +1 -1
  143. package/dist/forms.js +56 -14
  144. package/dist/forms.js.map +1 -1
  145. package/dist/gravity-letters.d.ts.map +1 -1
  146. package/dist/gravity-letters.js +1 -0
  147. package/dist/gravity-letters.js.map +1 -1
  148. package/dist/grid-reveal.d.ts.map +1 -1
  149. package/dist/grid-reveal.js +1 -0
  150. package/dist/grid-reveal.js.map +1 -1
  151. package/dist/heading.d.ts.map +1 -1
  152. package/dist/heading.js +1 -0
  153. package/dist/heading.js.map +1 -1
  154. package/dist/image-choice.d.ts.map +1 -1
  155. package/dist/image-choice.js +1 -0
  156. package/dist/image-choice.js.map +1 -1
  157. package/dist/image-comparison.d.ts.map +1 -1
  158. package/dist/image-comparison.js +1 -0
  159. package/dist/image-comparison.js.map +1 -1
  160. package/dist/image-viewer.d.ts +22 -1
  161. package/dist/image-viewer.d.ts.map +1 -1
  162. package/dist/image-viewer.js +14 -1
  163. package/dist/image-viewer.js.map +1 -1
  164. package/dist/index.d.ts +3 -3
  165. package/dist/index.d.ts.map +1 -1
  166. package/dist/index.js +1 -1
  167. package/dist/index.js.map +1 -1
  168. package/dist/inline-confirm.d.ts.map +1 -1
  169. package/dist/inline-confirm.js +1 -0
  170. package/dist/inline-confirm.js.map +1 -1
  171. package/dist/internal/document-resource.d.ts.map +1 -1
  172. package/dist/internal/document-resource.js +1 -0
  173. package/dist/internal/document-resource.js.map +1 -1
  174. package/dist/internal/initial-focus.d.ts.map +1 -1
  175. package/dist/internal/initial-focus.js +1 -0
  176. package/dist/internal/initial-focus.js.map +1 -1
  177. package/dist/internal/media-album.d.ts.map +1 -1
  178. package/dist/internal/media-album.js +1 -0
  179. package/dist/internal/media-album.js.map +1 -1
  180. package/dist/internal/message-reactions.d.ts.map +1 -1
  181. package/dist/internal/message-reactions.js +1 -0
  182. package/dist/internal/message-reactions.js.map +1 -1
  183. package/dist/internal/overlay-origin-motion.d.ts.map +1 -1
  184. package/dist/internal/overlay-origin-motion.js +1 -0
  185. package/dist/internal/overlay-origin-motion.js.map +1 -1
  186. package/dist/internal/pending-content.d.ts.map +1 -1
  187. package/dist/internal/pending-content.js +1 -0
  188. package/dist/internal/pending-content.js.map +1 -1
  189. package/dist/internal/photo-source-icon.d.ts.map +1 -1
  190. package/dist/internal/photo-source-icon.js +1 -0
  191. package/dist/internal/photo-source-icon.js.map +1 -1
  192. package/dist/internal/screen-exit.d.ts.map +1 -1
  193. package/dist/internal/screen-exit.js +1 -0
  194. package/dist/internal/screen-exit.js.map +1 -1
  195. package/dist/internal/screen-footer.d.ts.map +1 -1
  196. package/dist/internal/screen-footer.js +1 -0
  197. package/dist/internal/screen-footer.js.map +1 -1
  198. package/dist/internal/spinner.d.ts.map +1 -1
  199. package/dist/internal/spinner.js +1 -0
  200. package/dist/internal/spinner.js.map +1 -1
  201. package/dist/internal/use-composition-action.d.ts.map +1 -1
  202. package/dist/internal/use-composition-action.js +1 -0
  203. package/dist/internal/use-composition-action.js.map +1 -1
  204. package/dist/internal.d.ts.map +1 -1
  205. package/dist/internal.js +1 -0
  206. package/dist/internal.js.map +1 -1
  207. package/dist/layout.d.ts +11 -1
  208. package/dist/layout.d.ts.map +1 -1
  209. package/dist/layout.js +8 -4
  210. package/dist/layout.js.map +1 -1
  211. package/dist/mentions.d.ts.map +1 -1
  212. package/dist/mentions.js +1 -0
  213. package/dist/mentions.js.map +1 -1
  214. package/dist/menu-morph.d.ts.map +1 -1
  215. package/dist/menu-morph.js +1 -0
  216. package/dist/menu-morph.js.map +1 -1
  217. package/dist/menubar.d.ts.map +1 -1
  218. package/dist/menubar.js +1 -0
  219. package/dist/menubar.js.map +1 -1
  220. package/dist/modal.d.ts.map +1 -1
  221. package/dist/modal.js +1 -0
  222. package/dist/modal.js.map +1 -1
  223. package/dist/navigation-bar.d.ts.map +1 -1
  224. package/dist/navigation-bar.js +1 -0
  225. package/dist/navigation-bar.js.map +1 -1
  226. package/dist/navigation.d.ts.map +1 -1
  227. package/dist/navigation.js +1 -0
  228. package/dist/navigation.js.map +1 -1
  229. package/dist/notification-bell.d.ts +1 -1
  230. package/dist/notification-bell.d.ts.map +1 -1
  231. package/dist/notification-bell.js +5 -1
  232. package/dist/notification-bell.js.map +1 -1
  233. package/dist/number-field.d.ts.map +1 -1
  234. package/dist/number-field.js +1 -0
  235. package/dist/number-field.js.map +1 -1
  236. package/dist/overlay-stack.d.ts.map +1 -1
  237. package/dist/overlay-stack.js +1 -0
  238. package/dist/overlay-stack.js.map +1 -1
  239. package/dist/overlays.d.ts.map +1 -1
  240. package/dist/overlays.js +11 -2
  241. package/dist/overlays.js.map +1 -1
  242. package/dist/pagination.d.ts.map +1 -1
  243. package/dist/pagination.js +1 -0
  244. package/dist/pagination.js.map +1 -1
  245. package/dist/popover.d.ts.map +1 -1
  246. package/dist/popover.js +1 -0
  247. package/dist/popover.js.map +1 -1
  248. package/dist/portal.d.ts.map +1 -1
  249. package/dist/portal.js +1 -0
  250. package/dist/portal.js.map +1 -1
  251. package/dist/progressive-blur.d.ts.map +1 -1
  252. package/dist/progressive-blur.js +1 -0
  253. package/dist/progressive-blur.js.map +1 -1
  254. package/dist/provider-button.d.ts.map +1 -1
  255. package/dist/provider-button.js +1 -0
  256. package/dist/provider-button.js.map +1 -1
  257. package/dist/provider.d.ts +9 -1
  258. package/dist/provider.d.ts.map +1 -1
  259. package/dist/provider.js +2 -2
  260. package/dist/provider.js.map +1 -1
  261. package/dist/public-exports.generated.d.ts +3 -0
  262. package/dist/public-exports.generated.d.ts.map +1 -1
  263. package/dist/public-exports.generated.js +9 -0
  264. package/dist/public-exports.generated.js.map +1 -1
  265. package/dist/rating.d.ts.map +1 -1
  266. package/dist/rating.js +1 -0
  267. package/dist/rating.js.map +1 -1
  268. package/dist/reaction-picker.d.ts.map +1 -1
  269. package/dist/reaction-picker.js +1 -0
  270. package/dist/reaction-picker.js.map +1 -1
  271. package/dist/saved-items.d.ts.map +1 -1
  272. package/dist/saved-items.js +1 -0
  273. package/dist/saved-items.js.map +1 -1
  274. package/dist/screen-flows.d.ts +5 -1
  275. package/dist/screen-flows.d.ts.map +1 -1
  276. package/dist/screen-flows.js +13 -4
  277. package/dist/screen-flows.js.map +1 -1
  278. package/dist/screens.d.ts +24 -4
  279. package/dist/screens.d.ts.map +1 -1
  280. package/dist/screens.js +38 -11
  281. package/dist/screens.js.map +1 -1
  282. package/dist/scroll-progress.d.ts.map +1 -1
  283. package/dist/scroll-progress.js +1 -0
  284. package/dist/scroll-progress.js.map +1 -1
  285. package/dist/select.d.ts.map +1 -1
  286. package/dist/select.js +1 -0
  287. package/dist/select.js.map +1 -1
  288. package/dist/selection.d.ts +7 -1
  289. package/dist/selection.d.ts.map +1 -1
  290. package/dist/selection.js +33 -10
  291. package/dist/selection.js.map +1 -1
  292. package/dist/side-panel.d.ts.map +1 -1
  293. package/dist/side-panel.js +1 -0
  294. package/dist/side-panel.js.map +1 -1
  295. package/dist/sidebar.d.ts +21 -2
  296. package/dist/sidebar.d.ts.map +1 -1
  297. package/dist/sidebar.js +40 -20
  298. package/dist/sidebar.js.map +1 -1
  299. package/dist/skip-nav.d.ts.map +1 -1
  300. package/dist/skip-nav.js +1 -0
  301. package/dist/skip-nav.js.map +1 -1
  302. package/dist/slider.d.ts.map +1 -1
  303. package/dist/slider.js +1 -0
  304. package/dist/slider.js.map +1 -1
  305. package/dist/sortable.d.ts.map +1 -1
  306. package/dist/sortable.js +1 -0
  307. package/dist/sortable.js.map +1 -1
  308. package/dist/splitter.d.ts.map +1 -1
  309. package/dist/splitter.js +1 -0
  310. package/dist/splitter.js.map +1 -1
  311. package/dist/statistic-motion.d.ts.map +1 -1
  312. package/dist/statistic-motion.js +1 -0
  313. package/dist/statistic-motion.js.map +1 -1
  314. package/dist/status-text.d.ts.map +1 -1
  315. package/dist/status-text.js +1 -0
  316. package/dist/status-text.js.map +1 -1
  317. package/dist/step-player.d.ts.map +1 -1
  318. package/dist/step-player.js +1 -0
  319. package/dist/step-player.js.map +1 -1
  320. package/dist/steps.d.ts +16 -14
  321. package/dist/steps.d.ts.map +1 -1
  322. package/dist/steps.js +26 -9
  323. package/dist/steps.js.map +1 -1
  324. package/dist/styles.css +140 -35
  325. package/dist/styles.layered.css +140 -35
  326. package/dist/supplemental-display.d.ts.map +1 -1
  327. package/dist/supplemental-display.js +1 -0
  328. package/dist/supplemental-display.js.map +1 -1
  329. package/dist/supplemental-navigation.d.ts.map +1 -1
  330. package/dist/supplemental-navigation.js +1 -0
  331. package/dist/supplemental-navigation.js.map +1 -1
  332. package/dist/swipe-actions.d.ts.map +1 -1
  333. package/dist/swipe-actions.js +1 -0
  334. package/dist/swipe-actions.js.map +1 -1
  335. package/dist/table-family.d.ts.map +1 -1
  336. package/dist/table-family.js +1 -0
  337. package/dist/table-family.js.map +1 -1
  338. package/dist/table-sort-button.d.ts.map +1 -1
  339. package/dist/table-sort-button.js +1 -0
  340. package/dist/table-sort-button.js.map +1 -1
  341. package/dist/tags-input.d.ts.map +1 -1
  342. package/dist/tags-input.js +1 -0
  343. package/dist/tags-input.js.map +1 -1
  344. package/dist/task-list.d.ts.map +1 -1
  345. package/dist/task-list.js +1 -0
  346. package/dist/task-list.js.map +1 -1
  347. package/dist/text-annotation.d.ts.map +1 -1
  348. package/dist/text-annotation.js +1 -0
  349. package/dist/text-annotation.js.map +1 -1
  350. package/dist/text-formats.d.ts.map +1 -1
  351. package/dist/text-formats.js +1 -0
  352. package/dist/text-formats.js.map +1 -1
  353. package/dist/theme.d.ts.map +1 -1
  354. package/dist/theme.js +12 -1
  355. package/dist/theme.js.map +1 -1
  356. package/dist/thinking-orb.d.ts.map +1 -1
  357. package/dist/thinking-orb.js +1 -0
  358. package/dist/thinking-orb.js.map +1 -1
  359. package/dist/toast.d.ts.map +1 -1
  360. package/dist/toast.js +1 -0
  361. package/dist/toast.js.map +1 -1
  362. package/dist/toggle-group.d.ts.map +1 -1
  363. package/dist/toggle-group.js +1 -0
  364. package/dist/toggle-group.js.map +1 -1
  365. package/dist/top-bar.d.ts.map +1 -1
  366. package/dist/top-bar.js +1 -0
  367. package/dist/top-bar.js.map +1 -1
  368. package/dist/top.d.ts.map +1 -1
  369. package/dist/top.js +4 -3
  370. package/dist/top.js.map +1 -1
  371. package/dist/tour.d.ts.map +1 -1
  372. package/dist/tour.js +1 -0
  373. package/dist/tour.js.map +1 -1
  374. package/dist/transfer-list.d.ts.map +1 -1
  375. package/dist/transfer-list.js +1 -0
  376. package/dist/transfer-list.js.map +1 -1
  377. package/dist/tree.d.ts.map +1 -1
  378. package/dist/tree.js +1 -0
  379. package/dist/tree.js.map +1 -1
  380. package/dist/upload-item.d.ts.map +1 -1
  381. package/dist/upload-item.js +1 -0
  382. package/dist/upload-item.js.map +1 -1
  383. package/dist/virtual-list.d.ts.map +1 -1
  384. package/dist/virtual-list.js +1 -0
  385. package/dist/virtual-list.js.map +1 -1
  386. package/dist/voice-note.d.ts.map +1 -1
  387. package/dist/voice-note.js +1 -0
  388. package/dist/voice-note.js.map +1 -1
  389. package/package.json +8 -3
@@ -89,6 +89,11 @@
89
89
  opts out because clipping cuts off its own shadow. */
90
90
  .hjm-surface[data-clips="true"] { overflow: hidden; }
91
91
  .hjm-surface[data-tone="raised"] { background: var(--hjm-color-bg); box-shadow: var(--hjm-surface-raised-shadow, var(--hjm-shadow-raised)); }
92
+ /* Surface `elevation` (shadow token steps, 2026-10-23) overrides the tone's shadow; declared after the tone rule. */
93
+ .hjm-surface[data-elevation="none"] { box-shadow: var(--hjm-surface-inset-shadow, none); }
94
+ .hjm-surface[data-elevation="raised"] { box-shadow: var(--hjm-surface-raised-shadow, var(--hjm-shadow-raised)); }
95
+ .hjm-surface[data-elevation="floating"] { box-shadow: var(--hjm-shadow-floating); }
96
+ .hjm-surface[data-elevation="overlay"] { box-shadow: var(--hjm-shadow-overlay); }
92
97
  .hjm-surface[data-tone="accent"] { background: var(--hjm-color-bg); }
93
98
  .hjm-surface[data-tone="sunken"] { background: var(--hjm-color-bg); }
94
99
  .hjm-surface[data-tone="subtle"] { background: var(--hjm-color-bg); }
@@ -269,7 +274,8 @@
269
274
  /* Toggle treatment: aria-pressed already carried the state, so without a paired
270
275
  visual every consumer painted the selected background in product styles.
271
276
  Selection uses content color without an added border (2026-10-10 user request); focus stays separate. */
272
- .hjm-button[data-selected="true"], .hjm-icon-button[data-selected="true"] { color: var(--hjm-color-text); background: var(--hjm-color-surface-selected); border-color: transparent; }
277
+ /* IconButtonLink `current` (aria-current="page") reuses the selected surface: iconButtonRecipe.states.selected. */
278
+ .hjm-button[data-selected="true"], .hjm-icon-button[data-selected="true"], .hjm-icon-button[aria-current="page"] { color: var(--hjm-color-text); background: var(--hjm-color-surface-selected); border-color: transparent; }
273
279
  .hjm-button:active:not(:disabled):not([aria-disabled="true"]), .hjm-icon-button:active:not(:disabled):not([aria-disabled="true"]) { opacity: var(--hjm-button-pressed-opacity); }
274
280
  /* data-state="disabled" also covers focusable boundaries (aria-disabled, e.g. Carousel previous on the first slide),
275
281
  which looked enabled while Native dimmed them (2026-10-17 review E9). */
@@ -307,6 +313,8 @@
307
313
  }
308
314
  .hjm-icon-button {
309
315
  position: relative;
316
+ /* IconButtonLink draws the same frame on an anchor. */
317
+ text-decoration: none;
310
318
  inline-size: var(--hjm-control-button-medium);
311
319
  block-size: var(--hjm-control-button-medium);
312
320
  min-inline-size: var(--hjm-control-min-touch-target);
@@ -315,6 +323,10 @@
315
323
  border-radius: var(--hjm-radius-md);
316
324
  }
317
325
  .hjm-icon-button[data-shape="circle"] { border-radius: var(--hjm-radius-full); }
326
+ /* IconButton `elevation` (iconButtonRecipe.elevation, 2026-10-23): a floating control's lift from the shadow tokens. */
327
+ .hjm-icon-button[data-elevation="raised"] { box-shadow: var(--hjm-shadow-raised); }
328
+ .hjm-icon-button[data-elevation="floating"] { box-shadow: var(--hjm-shadow-floating); }
329
+ .hjm-icon-button[data-elevation="overlay"] { box-shadow: var(--hjm-shadow-overlay); }
318
330
  .hjm-icon-button[data-size="small"] { inline-size: var(--hjm-control-button-small); block-size: var(--hjm-control-button-small); min-inline-size: 0; min-block-size: 0; }
319
331
  .hjm-icon-button[data-size="small"]::after { content: ""; position: absolute; inset: calc(-1 * var(--hjm-button-hit-slop, var(--hjm-space-xxs))); }
320
332
  .hjm-icon-button[data-size="large"] { inline-size: var(--hjm-control-button-large); block-size: var(--hjm-control-button-large); }
@@ -335,6 +347,9 @@
335
347
  takes the same overhang and the badge keeps the icon's corner (2026-10-17 1.27.2 adoption: Spint's top-bar bell). */
336
348
  .hjm-notification-bell:is([data-edge="start"], [data-edge="both"]) { margin-inline-start: calc(-1 * var(--hjm-icon-button-edge-small)); }
337
349
  .hjm-notification-bell:is([data-edge="end"], [data-edge="both"]) { margin-inline-end: calc(-1 * var(--hjm-icon-button-edge-small)); }
350
+ /* Count badge (iconButtonRecipe.badge / resolveIconButtonBadgeOffset, 2026-10-23 web check): on the button's end edge,
351
+ raised above the glyph slot so only the floating ring overlaps the glyph. The bell is always the small IconButton. */
352
+ .hjm-notification-bell__badge { position: absolute; inset-inline-end: var(--hjm-icon-button-badge-inline-end-small); inset-block-start: var(--hjm-icon-button-badge-block-start-small); display: flex; pointer-events: none; }
338
353
  .hjm-link { display: inline-flex; align-items: center; gap: var(--hjm-space-xxs); max-inline-size: 100%; min-inline-size: 0; overflow-wrap: anywhere; color: var(--hjm-color-content-brand); text-underline-offset: 0.18em; }
339
354
  .hjm-link[data-tone="neutral"] { color: var(--hjm-color-text-body); }
340
355
  .hjm-link[data-variant="standalone"] { min-block-size: var(--hjm-control-min-touch-target); min-inline-size: var(--hjm-control-min-touch-target); justify-content: center; text-decoration: none; }
@@ -390,7 +405,7 @@
390
405
  the support text fades, so a custom Field control dims without needing a class. A component
391
406
  recipe value (Select, NumberField, OtpField, SearchField, PasswordField) arrives as an
392
407
  inline --hjm-field-disabled-opacity on the root. */
393
- .hjm-field[data-state="disabled"] > :not(.hjm-field__description):not(.hjm-field__error):not([data-hjm-field-error]) { opacity: var(--hjm-field-disabled-opacity); }
408
+ .hjm-field[data-state="disabled"] > :not(.hjm-field__description):not(.hjm-field__count):not(.hjm-field__error):not([data-hjm-field-error]) { opacity: var(--hjm-field-disabled-opacity); }
394
409
  /* The editable minimum excludes both resolved borders, keeping the field footprint stable in invalid state. */
395
410
  .hjm-field__input {
396
411
  inline-size: 100%;
@@ -423,6 +438,14 @@
423
438
  .hjm-field__affix { display: inline-flex; align-items: center; color: var(--hjm-color-text-muted); }
424
439
  .hjm-field__description, .hjm-choice__description { color: var(--hjm-color-text-muted); font-size: var(--hjm-type-label-size); line-height: var(--hjm-type-label-line-height); }
425
440
  .hjm-field__error { color: var(--hjm-color-danger); font-size: var(--hjm-type-label-size); line-height: var(--hjm-type-label-line-height); }
441
+ /* characterCountRecipe (2026-10-23): label type, sentence and counter on one row with spacing.sm between, the counter
442
+ at the end in tabular numbers. short/over switch the row to danger and the counter to semibold, so the error is
443
+ not carried by color alone. Support text, so it keeps full contrast in the disabled scope like the description. */
444
+ .hjm-field__count { display: flex; align-items: flex-start; gap: var(--hjm-space-sm); color: var(--hjm-color-text-muted); font-size: var(--hjm-type-label-size); line-height: var(--hjm-type-label-line-height); }
445
+ .hjm-field__count-message { flex: 1 1 auto; min-inline-size: 0; }
446
+ .hjm-field__counter { flex: 0 0 auto; margin-inline-start: auto; font-variant-numeric: tabular-nums; font-weight: var(--hjm-font-weight-regular); }
447
+ .hjm-field__count[data-invalid] { color: var(--hjm-color-danger); }
448
+ .hjm-field__count[data-invalid] .hjm-field__counter { font-weight: var(--hjm-font-weight-semibold); }
426
449
  /* searchFieldRecipe.sizes.* (emitted by theme.ts): medium padding 12 · gap 8 · clear 36 + slop 4, large 52 high ·
427
450
  padding 16 · gap 12 · clear 44. Size is applied to the input by TextField; size the control from that public attribute. */
428
451
  .hjm-search-field .hjm-field__control { padding-inline: var(--hjm-search-field-padding-medium, var(--hjm-space-sm)); gap: var(--hjm-search-field-gap-medium, var(--hjm-space-xs)); }
@@ -878,6 +901,14 @@
878
901
  .hjm-choice[data-presentation="chips"][data-size="small"] { min-block-size: 36px; padding-inline: var(--hjm-space-sm); }
879
902
  .hjm-choice[data-presentation="chips"][data-size="small"]::after { content: ""; position: absolute; inset: -4px 0; }
880
903
  .hjm-choice[data-presentation="chips"].hjm-choice--with-action { padding: 0; }
904
+ /* selectionGroupRecipe.overflow (2026-10-23): CheckboxGroup chips on one scrolling line, the same meaning as
905
+ SegmentedControl overflow="scroll". The scrollport keeps scrollInset (spacing.xxs 4) on every side so the focus ring
906
+ (2 + offset 2) and the small chip hit slop are not clipped and the last chip ends like the first starts; the
907
+ negative margin keeps the chips aligned with the column. The items row sits inside the scroller, so the chip row
908
+ rule above (a direct-child selector) is restated here. */
909
+ .hjm-checkbox-group__scroller { min-inline-size: 0; overflow-x: auto; padding: var(--hjm-space-xxs); margin: calc(-1 * var(--hjm-space-xxs)); }
910
+ .hjm-checkbox-group[data-presentation="chips"][data-overflow="scroll"] .hjm-checkbox-group__items { flex-direction: row; flex-wrap: nowrap; gap: var(--hjm-space-xs); inline-size: max-content; }
911
+ .hjm-checkbox-group[data-presentation="chips"][data-overflow="scroll"] .hjm-choice { flex-shrink: 0; }
881
912
  .hjm-choice[data-presentation="chips"] > .hjm-choice__target { padding-block: 0; }
882
913
  .hjm-choice[data-presentation="chips"] .hjm-choice__indicator { display: none; }
883
914
  .hjm-choice[data-presentation="chips"] .hjm-choice__leading { color: inherit; }
@@ -981,6 +1012,9 @@
981
1012
  .hjm-badge[data-variant="outline"][data-tone="warning"] { background: transparent; color: var(--hjm-accent-warning); border-color: color-mix(in srgb, var(--hjm-accent-warning) 30%, transparent); }
982
1013
  .hjm-badge[data-tone="attention"] { background: var(--hjm-accent-fill-attention); }
983
1014
  .hjm-badge[data-variant="outline"][data-tone="attention"] { background: transparent; color: var(--hjm-accent-attention); border-color: color-mix(in srgb, var(--hjm-accent-attention) 30%, transparent); }
1015
+ /* Product classification color (Badge categoryColor): the renderer resolves fill, ink and stroke per theme and checks AA. */
1016
+ .hjm-badge[data-tone="category"] { color: var(--hjm-badge-category-content); background: var(--hjm-badge-category-background); }
1017
+ .hjm-badge[data-variant="outline"][data-tone="category"] { background: transparent; border-color: var(--hjm-badge-category-border); }
984
1018
  .hjm-tag[data-tone="info"] { color: var(--hjm-accent-info); background: color-mix(in srgb, var(--hjm-accent-info) 14%, transparent); border-color: color-mix(in srgb, var(--hjm-accent-info) 30%, transparent); }
985
1019
  .hjm-tag[data-tone="success"] { color: var(--hjm-accent-success); background: color-mix(in srgb, var(--hjm-accent-success) 14%, transparent); border-color: color-mix(in srgb, var(--hjm-accent-success) 30%, transparent); }
986
1020
  .hjm-tag[data-tone="attention"] { color: var(--hjm-accent-attention); background: color-mix(in srgb, var(--hjm-accent-attention) 14%, transparent); border-color: color-mix(in srgb, var(--hjm-accent-attention) 30%, transparent); }
@@ -1058,10 +1092,17 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
1058
1092
  baseline 2–2.5px above the row center (2026-10-17 measured audit); a flex
1059
1093
  box centers any trailing node like Native's row-centered View. */
1060
1094
  .hjm-list-row__trailing { display: flex; align-items: center; }
1095
+ /* Disclosure mark (listRowRecipe.accessories): decorative content.decorative chevron after any trailing value, inside the
1096
+ row command. The row gap applies before it; a preceding trailing value pulls it to the tighter accessory gap. */
1097
+ .hjm-list-row__accessory { flex: 0 0 auto; display: flex; align-items: center; color: var(--hjm-color-text-weak); }
1098
+ .hjm-list-row__accessory .hjm-icon { color: inherit; }
1099
+ .hjm-list-row__trailing + .hjm-list-row__accessory { margin-inline-start: calc(var(--hjm-list-row-accessory-gap) - var(--hjm-list-row-gap)); }
1061
1100
  /* `leadingSize` was declared by the recipe but unbound, so consumers rebuilt
1062
1101
  the avatar box in product styles. */
1063
1102
  .hjm-list-row__leading { display: flex; align-items: center; justify-content: center; inline-size: var(--hjm-list-row-leading-size); block-size: var(--hjm-list-row-leading-size); overflow: hidden; }
1064
1103
  .hjm-list-row__leading[data-shape="circle"] { border-radius: var(--hjm-radius-full); }
1104
+ /* ChoiceRow sheet item picture: the row leading box (choiceRowRecipe.itemLeading), empty for items without one. */
1105
+ .hjm-choice-row__item-leading { display: flex; align-items: center; justify-content: center; inline-size: var(--hjm-choice-row-item-leading-size); block-size: var(--hjm-choice-row-item-leading-size); overflow: hidden; }
1065
1106
  /* Photo source peers share ListRow geometry; only their decorative brand plate is specialized. */
1066
1107
  .hjm-photo-source__icon { display: grid; place-items: center; inline-size: 100%; block-size: 100%; border-radius: var(--hjm-radius-md); }
1067
1108
  .hjm-photo-source__icon svg { inline-size: 24px; block-size: 24px; }
@@ -1509,7 +1550,8 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
1509
1550
  font-size: var(--hjm-type-label-size);
1510
1551
  line-height: var(--hjm-type-label-line-height);
1511
1552
  }
1512
- .hjm-chart-legend[data-interactive] { flex-direction: column; flex-wrap: nowrap; }
1553
+ /* chartRecipe.legend.layouts: stack = one row per series; inline = entries flow and wrap (base rule above). */
1554
+ .hjm-chart-legend[data-layout="stack"] { flex-direction: column; flex-wrap: nowrap; }
1513
1555
  .hjm-chart-legend__item, .hjm-chart-legend__button { display: flex; align-items: center; gap: var(--hjm-space-xs); }
1514
1556
  .hjm-chart-legend__item[data-dimmed] { opacity: 0.5; }
1515
1557
  .hjm-chart-legend__button {
@@ -1528,7 +1570,8 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
1528
1570
  .hjm-chart-legend__button[aria-pressed="true"] { background: var(--hjm-color-surface); }
1529
1571
  .hjm-chart-legend__button:focus-visible { outline: var(--hjm-focus-width) solid var(--hjm-color-focus); outline-offset: var(--hjm-focus-offset); }
1530
1572
  .hjm-chart-legend__swatch { flex: none; inline-size: 10px; block-size: 10px; border-radius: 3px; }
1531
- .hjm-chart-legend[data-interactive] .hjm-chart-legend__label { flex: 1; }
1573
+ .hjm-chart-legend[data-layout="stack"] .hjm-chart-legend__label { flex: 1; }
1574
+ .hjm-chart-legend[data-layout="inline"] .hjm-chart-legend__button { flex: none; }
1532
1575
  .hjm-chart-legend__value { font-weight: var(--hjm-text-emphasis-medium); font-variant-numeric: tabular-nums; }
1533
1576
 
1534
1577
  /* Mentions ---------------------------------------------------------------- */
@@ -2120,6 +2163,7 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2120
2163
  font-weight: var(--hjm-top-title-weight);
2121
2164
  overflow-wrap: anywhere;
2122
2165
  }
2166
+ .hjm-top__title[data-line-breaks="preserve"] { white-space: pre-line; }
2123
2167
  .hjm-top__trailing { display: flex; flex: 0 0 auto; align-items: center; gap: var(--hjm-space-xs); }
2124
2168
  .hjm-top__description {
2125
2169
  margin: var(--hjm-space-xs) 0 0;
@@ -2799,6 +2843,11 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2799
2843
  /* Baseline sharing put the smaller caption 1.5px under the label's center; center it on the label's first line instead. */
2800
2844
  .hjm-timeline__timestamp { color: var(--hjm-color-text-muted); font-size: var(--hjm-type-caption-size); line-height: var(--hjm-type-caption-line-height); }
2801
2845
  .hjm-timeline__description { color: var(--hjm-color-text-body); white-space: pre-wrap; overflow-wrap: anywhere; }
2846
+ /* Selectable record (timelineRecipe.item.selected): the neutral persistent-selection surface + ring shared with ListRow.
2847
+ Selection outranks passive emphasis; the focus ring stays the shared focus role. */
2848
+ .hjm-timeline[data-selectable] .hjm-timeline__item { cursor: pointer; }
2849
+ .hjm-timeline__item[aria-selected="true"] { background: var(--hjm-color-surface-selected); box-shadow: inset 0 0 0 1px var(--hjm-color-border-control); }
2850
+ .hjm-timeline__item[role="option"]:focus-visible { outline: var(--hjm-focus-width) solid var(--hjm-color-focus); outline-offset: var(--hjm-focus-offset); }
2802
2851
  .hjm-accordion { border-block-start: 1px solid var(--hjm-color-border); }
2803
2852
  .hjm-accordion__item { border-block-end: 1px solid var(--hjm-color-border); }
2804
2853
  .hjm-accordion__header { margin: 0; }
@@ -2825,28 +2874,44 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2825
2874
  .hjm-accordion__indicator { flex: 0 0 auto; color: var(--hjm-color-text-muted); }
2826
2875
  .hjm-accordion__panel { padding: 0 var(--hjm-space-xs) var(--hjm-space-md); color: var(--hjm-color-text-body); overflow-wrap: anywhere; }
2827
2876
  .hjm-avatar {
2877
+ /* Diameter from avatarRecipe.sizes via --hjm-avatar-size (set inline by Avatar). The frame no longer clips
2878
+ the root so a corner accessory can sit on the edge; the image and fallback clip to the shape themselves. */
2879
+ position: relative;
2880
+ box-sizing: border-box;
2828
2881
  display: inline-grid;
2882
+ flex: 0 0 auto;
2829
2883
  place-items: center;
2830
- inline-size: 2.5rem;
2831
- block-size: 2.5rem;
2832
- overflow: hidden;
2884
+ inline-size: var(--hjm-avatar-size, 2.5rem);
2885
+ block-size: var(--hjm-avatar-size, 2.5rem);
2833
2886
  border: 1px solid var(--hjm-color-border);
2834
2887
  border-radius: 50%;
2835
2888
  color: var(--hjm-color-text-muted);
2836
2889
  background: var(--hjm-color-bg);
2837
2890
  font-weight: var(--hjm-text-emphasis-strong);
2838
2891
  }
2839
- .hjm-avatar[data-size="small"] { inline-size: 2rem; block-size: 2rem; font-size: var(--hjm-type-label-size); }
2840
- .hjm-avatar[data-size="large"] { inline-size: 3rem; block-size: 3rem; }
2841
- .hjm-avatar[data-size="xlarge"] { inline-size: 4rem; block-size: 4rem; font-size: var(--hjm-type-title-size); }
2892
+ .hjm-avatar[data-size="xxsmall"], .hjm-avatar[data-size="xsmall"], .hjm-avatar[data-size="small"] { font-size: var(--hjm-type-label-size); }
2893
+ .hjm-avatar[data-size="xlarge"] { font-size: var(--hjm-type-title-size); }
2842
2894
  .hjm-avatar[data-shape="rounded"] { border-radius: var(--hjm-radius-md); }
2843
- .hjm-avatar__image { inline-size: 100%; block-size: 100%; object-fit: cover; }
2844
- .hjm-avatar__fallback { display: grid; place-items: center; inline-size: 100%; block-size: 100%; }
2895
+ /* avatarRecipe.frames: surface drops the border, none drops border and background. */
2896
+ .hjm-avatar[data-frame="surface"] { border-width: 0; }
2897
+ .hjm-avatar[data-frame="none"] { border-width: 0; background: transparent; }
2898
+ .hjm-avatar__image { display: block; inline-size: 100%; block-size: 100%; object-fit: cover; border-radius: inherit; }
2899
+ .hjm-avatar__fallback { display: grid; place-items: center; inline-size: 100%; block-size: 100%; overflow: hidden; border-radius: inherit; }
2900
+ /* avatarRecipe.accessory.offset (outward overhang, 0): the mark sits on the avatar's box corner so the row layout does not move. */
2901
+ .hjm-avatar__accessory { position: absolute; inset-inline-end: var(--hjm-avatar-accessory-inset, 0px); display: inline-flex; line-height: 0; }
2902
+ .hjm-avatar__accessory[data-placement="bottom-end"] { inset-block-end: var(--hjm-avatar-accessory-inset, 0px); }
2903
+ .hjm-avatar__accessory[data-placement="top-end"] { inset-block-start: var(--hjm-avatar-accessory-inset, 0px); }
2845
2904
  .hjm-divider { flex: 0 0 auto; margin: 0; border: 0; background: var(--hjm-color-border); }
2846
2905
  .hjm-divider[data-orientation="horizontal"] { inline-size: 100%; block-size: 1px; }
2847
2906
  .hjm-divider[data-orientation="vertical"] { align-self: stretch; inline-size: 1px; min-block-size: var(--hjm-control-min-touch-target); }
2848
2907
  .hjm-divider[data-orientation="horizontal"][data-inset="start"] { margin-inline-start: var(--hjm-space-md); inline-size: calc(100% - var(--hjm-space-md)); }
2849
2908
  .hjm-divider[data-orientation="horizontal"][data-inset="both"] { margin-inline: var(--hjm-space-md); inline-size: calc(100% - (2 * var(--hjm-space-md))); }
2909
+ /* lineStyle="dashed" (dividerRecipe.lineStyles.dashed): exact dash/gap from the recipe instead of the browser's own
2910
+ dashed border, so Web and Native draw the same 4/4 rhythm starting with a dash at the line's start edge. */
2911
+ .hjm-divider[data-line-style="dashed"] { --hjm-divider-pattern: var(--hjm-color-border) 0 var(--hjm-divider-dash), transparent var(--hjm-divider-dash) calc(var(--hjm-divider-dash) + var(--hjm-divider-gap)); }
2912
+ .hjm-divider[data-line-style="dashed"][data-orientation="horizontal"] { background: repeating-linear-gradient(to right, var(--hjm-divider-pattern)); }
2913
+ .hjm-divider[data-line-style="dashed"][data-orientation="horizontal"]:dir(rtl) { background: repeating-linear-gradient(to left, var(--hjm-divider-pattern)); }
2914
+ .hjm-divider[data-line-style="dashed"][data-orientation="vertical"] { background: repeating-linear-gradient(to bottom, var(--hjm-divider-pattern)); }
2850
2915
  .hjm-description-list { display: grid; grid-template-columns: repeat(var(--hjm-description-columns), minmax(0, 1fr)); gap: var(--hjm-space-sm); margin: 0; }
2851
2916
  .hjm-description-list__item { min-inline-size: 0; display: grid; gap: var(--hjm-space-xxs); }
2852
2917
  .hjm-description-list__label { color: var(--hjm-color-text-muted); font-size: var(--hjm-type-label-size); font-weight: var(--hjm-text-emphasis-medium); }
@@ -2900,28 +2965,48 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
2900
2965
  .hjm-load-more__spinner { inline-size: 1em; block-size: 1em; border: 2px solid var(--hjm-color-content-brand); border-inline-end-color: transparent; border-radius: 50%; animation: hjm-spin 800ms linear infinite; }
2901
2966
 
2902
2967
  /* Expansion renderers --------------------------------------------------- */
2903
- .hjm-steps { display: grid; grid-template-columns: repeat(var(--hjm-steps-connector-count), minmax(0, 1fr)) fit-content(calc(100% / var(--hjm-steps-count))); gap: 0; margin: 0; padding: 0 var(--hjm-steps-inset); list-style: none; }
2904
- .hjm-steps__step { min-inline-size: 0; display: grid; align-content: start; gap: var(--hjm-space-xs); }
2905
- .hjm-steps__rail { display: flex; align-items: center; min-inline-size: 0; }
2906
- .hjm-steps__indicator { flex: 0 0 auto; inline-size: var(--hjm-steps-indicator-size); block-size: var(--hjm-steps-indicator-size); display: grid; place-items: center; border: 1px solid var(--hjm-color-border); border-radius: 50%; color: var(--hjm-color-text-muted); background: var(--hjm-color-bg); font-size: var(--hjm-type-label-size); font-weight: var(--hjm-text-emphasis-medium); }
2907
- .hjm-steps__connector { flex: 1 1 auto; block-size: 1px; background: var(--hjm-color-border); }
2908
- .hjm-steps__step[data-status="current"] .hjm-steps__indicator { border: 2px solid var(--hjm-color-content-brand); color: var(--hjm-color-content-brand); }
2909
- .hjm-steps__step[data-status="complete"] .hjm-steps__indicator { border-color: var(--hjm-accent-success); color: var(--hjm-accent-success); background: var(--hjm-color-bg); }
2910
- .hjm-steps__step[data-status="complete"] .hjm-steps__connector { background: var(--hjm-color-content-brand); }
2911
- /* The terminal incoming segment continues the previous rail across its copy width. */
2912
- .hjm-steps__connector[data-reached="true"] { background: var(--hjm-color-content-brand); }
2913
- .hjm-steps__step[data-status="error"] .hjm-steps__indicator { border: 2px solid var(--hjm-color-danger); color: var(--hjm-color-danger); background: var(--hjm-color-danger-fill); }
2914
- .hjm-steps__copy { min-inline-size: 0; display: grid; gap: var(--hjm-space-xxs); padding-inline-end: var(--hjm-space-sm); }
2915
- .hjm-steps__label { color: var(--hjm-color-text); font-size: var(--hjm-type-label-size); line-height: var(--hjm-type-label-line-height); font-weight: var(--hjm-text-emphasis-medium); overflow-wrap: anywhere; }
2916
- .hjm-steps__step[data-status="pending"] .hjm-steps__label { color: var(--hjm-color-text-muted); }
2917
- .hjm-steps__step[data-status="error"] .hjm-steps__label { color: var(--hjm-color-danger); }
2918
- /* Keep the terminal marker at the inline edge instead of an empty trailing step cell. */
2919
- .hjm-steps__step:last-child .hjm-steps__rail { justify-content: flex-end; }
2920
- .hjm-steps__step:last-child .hjm-steps__copy { padding-inline-end: 0; text-align: end; }
2921
- .hjm-steps__description { color: var(--hjm-color-text-muted); font-size: var(--hjm-type-caption-size); overflow-wrap: anywhere; }
2922
- /* A step before the cursor is one button over marker and label (Steps onStepPress); the cell keeps its static layout. */
2923
- .hjm-steps__press { display: grid; align-content: start; gap: var(--hjm-space-xs); min-inline-size: 0; min-block-size: var(--hjm-steps-press-target); margin: 0; padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: start; cursor: pointer; }
2924
- .hjm-steps__press:focus-visible { outline: var(--hjm-focus-width) solid var(--hjm-color-focus); outline-offset: var(--hjm-focus-offset); }
2968
+ /* Focus rail is shared by ordinary Steps and the expandable presentations (2026-10-23 user proposal). */
2969
+ .hjm-steps { display:grid; grid-template-columns:repeat(var(--hjm-steps-connector-count),minmax(0,1fr)) fit-content(calc(100% / var(--hjm-steps-count))); gap:0; margin:0; padding:0 var(--hjm-steps-inset); list-style:none; }
2970
+ .hjm-steps__step { min-inline-size:0; position:relative; }
2971
+ .hjm-steps__item,.hjm-steps__press { display:grid; align-content:start; gap:var(--hjm-space-xs); min-inline-size:0; min-block-size:var(--hjm-steps-press-target); }
2972
+ .hjm-steps__rail { display:flex; align-items:center; min-inline-size:0; }
2973
+ .hjm-steps__indicator { flex:0 0 auto; inline-size:var(--hjm-steps-indicator-size); block-size:var(--hjm-steps-indicator-size); display:grid; place-items:center; border:1px solid var(--hjm-color-border); border-radius:50%; color:var(--hjm-color-text-muted); background:var(--hjm-color-bg); font-size:var(--hjm-type-label-size); font-weight:var(--hjm-text-emphasis-medium); transition:background-color var(--hjm-steps-duration),color var(--hjm-steps-duration),border-color var(--hjm-steps-duration),transform var(--hjm-motion-fast); }
2974
+ .hjm-steps__connector { flex:1 1 auto; block-size:1px; background:var(--hjm-color-border); transition:background-color var(--hjm-steps-duration); }
2975
+ .hjm-steps__step[data-status="current"] .hjm-steps__indicator { border-color:var(--hjm-color-text); background:var(--hjm-color-text); color:var(--hjm-color-bg); box-shadow:0 0 0 3px var(--hjm-color-bg),0 0 0 4px var(--hjm-color-border); }
2976
+ .hjm-steps__step[data-status="complete"] .hjm-steps__indicator { border-color:var(--hjm-color-border-control); color:var(--hjm-color-text); }
2977
+ .hjm-steps__step[data-status="complete"] .hjm-steps__connector,.hjm-steps__connector[data-reached="true"] { background:var(--hjm-color-text); }
2978
+ .hjm-steps__step[data-status="error"] .hjm-steps__indicator { border:2px solid var(--hjm-color-danger); color:var(--hjm-color-danger); background:color-mix(in srgb,var(--hjm-color-danger) 12%,var(--hjm-color-bg)); }
2979
+ .hjm-steps__copy { min-inline-size:0; display:grid; gap:var(--hjm-space-xxs); padding-inline-end:var(--hjm-space-sm); }
2980
+ .hjm-steps__label { color:var(--hjm-color-text); font-size:var(--hjm-type-label-size); line-height:var(--hjm-type-label-line-height); overflow-wrap:anywhere; }
2981
+ .hjm-steps__step[data-status="current"] .hjm-steps__label { font-weight:var(--hjm-text-emphasis-medium); }
2982
+ .hjm-steps__step[data-status="pending"] .hjm-steps__label { color:var(--hjm-color-text-muted); }
2983
+ .hjm-steps__step[data-status="error"] .hjm-steps__label { color:var(--hjm-color-danger); }
2984
+ .hjm-steps__step:last-child .hjm-steps__rail { justify-content:flex-end; }
2985
+ .hjm-steps__step:last-child .hjm-steps__copy { padding-inline-end:0; text-align:end; }
2986
+ .hjm-steps__description,.hjm-steps__status { color:var(--hjm-color-text-muted); font-size:var(--hjm-type-caption-size); overflow-wrap:anywhere; }
2987
+ .hjm-steps__press { width:100%; margin:0; padding:0; border:0; background:none; color:inherit; font:inherit; text-align:start; cursor:pointer; }
2988
+ .hjm-steps__press:focus-visible,.hjm-steps-compact__toggle:focus-visible { outline:var(--hjm-focus-width) solid var(--hjm-color-focus); outline-offset:var(--hjm-focus-offset); border-radius:var(--hjm-radius-sm); }
2989
+ @media(hover:hover) { .hjm-steps__press:hover .hjm-steps__indicator { transform:translateY(-2px); } }
2990
+ .hjm-steps__press:active .hjm-steps__indicator { transform:scale(.96); }
2991
+ /* A product illustration keeps its own colors and must not disappear into the current fill. */
2992
+ .hjm-steps[data-custom-mark] .hjm-steps__indicator { background:var(--hjm-color-bg); color:var(--hjm-color-text); }
2993
+ .hjm-steps[data-presentation="vertical"],.hjm-steps[data-presentation="compact"][data-expanded="true"] { display:flex; flex-direction:column; }
2994
+ .hjm-steps:is([data-presentation="vertical"],[data-presentation="compact"][data-expanded="true"]) .hjm-steps__step { padding-block-end:var(--hjm-space-md); }
2995
+ .hjm-steps:is([data-presentation="vertical"],[data-presentation="compact"][data-expanded="true"]) .hjm-steps__step:not(:last-child)::before { content:""; position:absolute; inset-inline-start:calc(var(--hjm-steps-indicator-size) / 2); inset-block-start:var(--hjm-steps-indicator-size); inset-block-end:0; inline-size:1px; background:var(--hjm-color-border); }
2996
+ .hjm-steps:is([data-presentation="vertical"],[data-presentation="compact"][data-expanded="true"]) :is(.hjm-steps__item,.hjm-steps__press) { grid-template-columns:var(--hjm-steps-indicator-size) minmax(0,1fr); align-items:center; column-gap:var(--hjm-space-md); }
2997
+ .hjm-steps:is([data-presentation="vertical"],[data-presentation="compact"][data-expanded="true"]) .hjm-steps__copy { text-align:start; }
2998
+ .hjm-steps__body { margin-inline-start:calc(var(--hjm-steps-indicator-size) + var(--hjm-space-md)); padding-block:var(--hjm-space-sm); }
2999
+ .hjm-steps-compact { min-inline-size:0; }
3000
+ .hjm-steps-compact__header { display:flex; align-items:center; justify-content:space-between; gap:var(--hjm-space-sm); margin-block-end:var(--hjm-space-xs); font-size:var(--hjm-type-label-size); }
3001
+ .hjm-steps-compact__toggle { display:flex; align-items:center; gap:var(--hjm-space-xs); flex-shrink:0; min-block-size:44px; padding:0; border:0; background:none; font:inherit; color:var(--hjm-color-text-muted); cursor:pointer; }
3002
+ .hjm-steps[data-presentation="compact"][data-expanded="false"] { display:flex; gap:var(--hjm-space-xxs); padding:0; }
3003
+ .hjm-steps[data-presentation="compact"][data-expanded="false"] .hjm-steps__step { flex:1; height:var(--hjm-steps-segment-height); background:var(--hjm-color-border); border-radius:var(--hjm-radius-full); }
3004
+ .hjm-steps[data-presentation="compact"][data-expanded="false"] .hjm-steps__step:is([data-status="complete"],[data-status="current"]) { background:var(--hjm-color-text); }
3005
+ .hjm-steps[data-presentation="compact"][data-expanded="false"] .hjm-steps__step[data-status="error"] { background:var(--hjm-color-danger); }
3006
+ .hjm-steps[data-presentation="compact"][data-expanded="false"] .hjm-steps__item { position:absolute; width:1px; height:1px; overflow:hidden; clip-path:inset(50%); min-block-size:0; }
3007
+ @media(prefers-reduced-motion:reduce) { .hjm-steps * { transition:none!important; transform:none!important; } }
3008
+ .hjm-root[data-motion="reduced"] .hjm-steps * { transition:none!important; transform:none!important; }
3009
+
2925
3010
 
2926
3011
  .hjm-file-picker { display: grid; gap: var(--hjm-space-xs); }
2927
3012
  .hjm-file-picker__label { color: var(--hjm-color-text); font-weight: var(--hjm-text-emphasis-medium); }
@@ -3278,7 +3363,11 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
3278
3363
  .hjm-watermark { position: relative; isolation: isolate; }
3279
3364
  .hjm-watermark__content { position: relative; z-index: 0; overflow-wrap: anywhere; }
3280
3365
  .hjm-watermark__overlay { position: absolute; inset: 0; z-index: 1; pointer-events: none; user-select: none; overflow: hidden; color: var(--hjm-color-text-sub); font: inherit; }
3281
- .hjm-affix { color: var(--hjm-color-text); background: var(--hjm-color-bg); overflow-wrap: anywhere; }
3366
+ /* Stacking and fill come from affixRecipe.defaults (layer sticky = --hjm-layer-sticky 100, fill canvas); the box is always
3367
+ positioned (sticky or relative), so z-index applies in both the pinned and the released state. */
3368
+ .hjm-affix { z-index: var(--hjm-layer-sticky); color: var(--hjm-color-text); background: var(--hjm-color-bg); overflow-wrap: anywhere; }
3369
+ .hjm-affix[data-layer="base"] { z-index: var(--hjm-layer-base); }
3370
+ .hjm-affix[data-fill="none"] { background: transparent; }
3282
3371
  .hjm-affix__marker { display: block; block-size: 0; pointer-events: none; }
3283
3372
 
3284
3373
  /* Sidebar presentation decorates fixed link boxes; no pointer/focus target is transformed. */
@@ -3388,6 +3477,12 @@ button.hjm-list-row, a.hjm-list-row { cursor: pointer; }
3388
3477
  /* contentInset="none" hands every inset to the host: no footer rule, as on Native (BottomCTA then draws its own bar). */
3389
3478
  .hjm-screen[data-content-inset="none"] > .hjm-screen__footer { border-block-start: 0; }
3390
3479
  .hjm-screen__body[data-scroll="screen"] { overflow-y: auto; }
3480
+ /* A screen-scrolled body is a Tab stop for keyboard scrolling, so reaching it by keyboard draws the HJM ring, inset
3481
+ because the body fills the screen and an outer ring would be clipped. Focus that ScreenLayout itself parks on the
3482
+ body after the focused node was removed (data-focus-landing) is a landing, not a control, and draws none, like
3483
+ the search results landing (2026-10-23 web check: the browser default ring outlined the whole body). */
3484
+ .hjm-screen__body:focus { outline: none; }
3485
+ .hjm-screen__body:focus-visible:not([data-focus-landing]) { outline: var(--hjm-focus-width) solid var(--hjm-color-focus); outline-offset: calc(-1 * var(--hjm-focus-width)); }
3391
3486
  .hjm-screen__body[data-scroll="content"] { display: flex; flex-direction: column; overflow: hidden; }
3392
3487
  .hjm-screen__body[data-content-alignment="center"] { display: flex; flex-direction: column; }
3393
3488
  .hjm-screen__centered-content { margin-block: auto; flex-shrink: 0; inline-size: 100%; }
@@ -3739,6 +3834,10 @@ button.hjm-chat-message__media-item:focus-visible { outline: 2px solid var(--hjm
3739
3834
  }
3740
3835
 
3741
3836
  .hjm-statistic__leading { display: inline-flex; align-items: center; color: var(--hjm-statistic-value-color, var(--hjm-color-text)); }
3837
+ /* A leading glyph labels its value: keep them on one line and let the value text wrap beside it.
3838
+ Wrapping the row dropped a long value (e.g. "10월 9일 09:40") under a lone icon (2026-10-23). */
3839
+ .hjm-statistic__value-row[data-leading] { flex-wrap: nowrap; }
3840
+ .hjm-statistic__value-row[data-leading] > .hjm-statistic__leading { flex-shrink: 0; }
3742
3841
  .hjm-statistic-group[data-arrangement="bar"] { grid-template-columns: repeat(var(--hjm-statistic-columns), minmax(0, 1fr)); gap: 0; }
3743
3842
  .hjm-statistic-group[data-arrangement="bar"] > * { min-inline-size: 0; padding-inline: var(--hjm-space-xs); }
3744
3843
  .hjm-statistic-group[data-arrangement="bar"] > * + * { border-inline-start: 1px solid var(--hjm-color-border); }
@@ -3844,6 +3943,12 @@ button.hjm-chat-message__media-item:focus-visible { outline: 2px solid var(--hjm
3844
3943
  .hjm-segmented[data-selection-tone="brand"][data-presentation="pills"] .hjm-segmented__items[data-highlight-ready="true"] > .hjm-segmented__item[data-state="checked"]::before { background: transparent; }
3845
3944
 
3846
3945
  /* Photo chrome is deliberately independent of the product theme: no card frame or crop. */
3946
+ /* ImageViewerTrigger: imageViewerTriggerRecipe (radius = imageRecipe.radius md so the ring follows the image frame). */
3947
+ .hjm-image-viewer-trigger { display: block; inline-size: 100%; margin: 0; padding: 0; border: 0; border-radius: var(--hjm-radius-md); background: none; color: inherit; font: inherit; text-align: inherit; cursor: var(--hjm-image-viewer-trigger-cursor, zoom-in); }
3948
+ .hjm-image-viewer-trigger > * { display: block; }
3949
+ .hjm-image-viewer-trigger:active:not(:disabled) { opacity: var(--hjm-image-viewer-trigger-pressed-opacity); }
3950
+ .hjm-image-viewer-trigger:disabled { cursor: default; opacity: var(--hjm-image-viewer-trigger-disabled-opacity); }
3951
+ .hjm-image-viewer-trigger:focus-visible { outline: var(--hjm-focus-width) solid var(--hjm-color-focus); outline-offset: var(--hjm-focus-offset); }
3847
3952
  .hjm-image-viewer { position: fixed; inset: 0; display: flex; flex-direction: column; min-inline-size: 0; background: #000; color: #fff; padding-block: env(safe-area-inset-top) env(safe-area-inset-bottom); }
3848
3953
  .hjm-image-viewer__header, .hjm-image-viewer__footer { display: flex; align-items: center; gap: var(--hjm-space-xs); padding: var(--hjm-space-xs) max(var(--hjm-space-md), env(safe-area-inset-left)) var(--hjm-space-xs) max(var(--hjm-space-md), env(safe-area-inset-right)); }
3849
3954
  .hjm-image-viewer__footer > span { flex: 1; text-align: center; }
@@ -1 +1 @@
1
- {"version":3,"file":"supplemental-display.d.ts","sourceRoot":"","sources":["../src/supplemental-display.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"supplemental-display.d.ts","sourceRoot":"","sources":["../src/supplemental-display.tsx"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx } from "react/jsx-runtime";
2
3
  import { getIconTransform, resolveIconDescriptor, semanticIconPaths, } from "@hjmds/design-contracts/components/icon";
3
4
  import { imageRecipe, resolveImageAspectRatio, resolveImageDescriptor, resolveImageFallbackAccessibilityLabel, } from "@hjmds/design-contracts/components/image";
@@ -1 +1 @@
1
- {"version":3,"file":"supplemental-display.js","sourceRoot":"","sources":["../src/supplemental-display.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n getIconTransform,\n resolveIconDescriptor,\n semanticIconPaths,\n type IconDescriptor,\n type SemanticIconName,\n} from \"@hjmds/design-contracts/components/icon\";\nimport {\n imageRecipe,\n resolveImageAspectRatio,\n resolveImageDescriptor,\n resolveImageFallbackAccessibilityLabel,\n type ImageDescriptor,\n type ImageLoadStatus,\n} from \"@hjmds/design-contracts/components/image\";\nimport {\n counterBadgeRecipe,\n formatCounterBadgeCount,\n iconRecipe,\n type CounterBadgeSize,\n type CounterBadgeTone,\n type CounterBadgeVariant,\n} from \"@hjmds/design-contracts/recipes\";\nimport {\n forwardRef,\n useState,\n useMemo,\n useRef,\n useLayoutEffect,\n type CSSProperties,\n type HTMLAttributes,\n type ImgHTMLAttributes,\n type ReactElement,\n type ReactEventHandler,\n type ReactNode,\n type Ref,\n type SVGAttributes,\n} from \"react\";\nimport { classNames } from \"./internal.js\";\nimport { useOptionalHjmTheme } from \"./provider.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\n\nexport type IconProps = Omit<\n SVGAttributes<SVGSVGElement>,\n \"children\" | \"color\"\n> & IconDescriptor & Readonly<{\n /** Optional glyph inside the existing 24-unit SVG frame; HJM owns semantics. */\n renderGlyph?: (props: Readonly<{ name: SemanticIconName; size: number; color: string; strokeWidth: number }>) => ReactNode;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\nexport const Icon = forwardRef<SVGSVGElement, IconProps>(function Icon(\n {\n name,\n size,\n tone,\n weight,\n directionality,\n decorative,\n accessibilityLabel,\n renderGlyph,\n className,\n style,\n layoutStyle,\n ...props\n },\n ref,\n) {\n const descriptor = resolveIconDescriptor({\n name,\n ...(size === undefined ? {} : { size }),\n ...(tone === undefined ? {} : { tone }),\n ...(weight === undefined ? {} : { weight }),\n ...(directionality === undefined ? {} : { directionality }),\n ...(decorative === undefined ? {} : { decorative }),\n ...(accessibilityLabel === undefined ? {} : { accessibilityLabel }),\n } as IconDescriptor);\n const theme = useOptionalHjmTheme();\n const transform = getIconTransform(\n descriptor.directionality,\n theme?.environment.direction ?? \"ltr\",\n );\n const dimension = iconRecipe.sizes[descriptor.size];\n return (\n <svg\n {...props}\n ref={ref}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={classNames(\"hjm-icon\", className)}\n data-name={descriptor.name}\n data-size={descriptor.size}\n data-tone={descriptor.tone}\n data-weight={descriptor.weight}\n data-transform={transform}\n width={dimension}\n height={dimension}\n stroke=\"currentColor\"\n strokeWidth={iconRecipe.weights[descriptor.weight]}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n role={descriptor.decorative ? undefined : \"img\"}\n aria-hidden={descriptor.decorative || undefined}\n aria-label={descriptor.decorative ? undefined : descriptor.accessibilityLabel}\n focusable=\"false\"\n style={{ ...style, ...layoutStyle }}\n >\n {renderGlyph?.({ name: descriptor.name, size: 24, color: \"currentColor\", strokeWidth: iconRecipe.weights[descriptor.weight] }) ?? <path d={semanticIconPaths[descriptor.name]} />}\n </svg>\n );\n});\n\ntype ImageElementProps = Omit<\n ImgHTMLAttributes<HTMLImageElement>,\n | \"alt\"\n | \"aria-hidden\"\n | \"aria-label\"\n | \"children\"\n | \"className\"\n | \"height\"\n | \"onError\"\n | \"onLoad\"\n | \"role\"\n | \"src\"\n | \"style\"\n | \"width\"\n>;\n\n/** Canonical props handed to a framework adapter such as `next/image`. */\nexport type ImageAdapterProps = ImageElementProps &\n Readonly<{\n src: string;\n alt: string;\n width: number;\n height: number;\n className?: string;\n style: CSSProperties;\n \"aria-hidden\"?: true;\n onLoad: ReactEventHandler<HTMLImageElement>;\n onError: ReactEventHandler<HTMLImageElement>;\n ref?: Ref<HTMLImageElement>;\n }>;\n\ntype ImageRootProps = Omit<\n HTMLAttributes<HTMLSpanElement>,\n | \"aria-hidden\"\n | \"aria-label\"\n | \"aria-labelledby\"\n | \"children\"\n | \"onError\"\n | \"onLoad\"\n | \"role\"\n>;\n\nexport type ImageProps = ImageRootProps &\n ImageDescriptor &\n Readonly<{\n /** Additional native `<img>` props shared with the framework adapter. */\n imageProps?: ImageElementProps &\n Readonly<{ className?: string; style?: CSSProperties }>;\n /**\n * Receives the complete accessible image contract. The adapter must pass\n * these props to its underlying image element so HJM can observe failure.\n */\n renderImage?: (props: ImageAdapterProps) => ReactElement;\n /** Visual content only; HJM keeps the fallback's accessible name. */\n fallback?: ReactNode;\n imageRef?: Ref<HTMLImageElement>;\n onLoad?: ReactEventHandler<HTMLImageElement>;\n onError?: ReactEventHandler<HTMLImageElement>;\n onLoadStatusChange?: (status: Extract<ImageLoadStatus, \"loaded\" | \"error\">) => void;\n /** Canonical layout-only placement on the root frame; the aspect ratio stays descriptor-owned. */\n layoutStyle?: HjmCompositionStyleProp;\n }>;\n\ntype ImageState = Readonly<{\n generation: object;\n status: Extract<ImageLoadStatus, \"loading\" | \"loaded\" | \"error\">;\n}>;\n\n/** Intrinsic-size image with canonical alt semantics and an accessible fallback. */\nexport const Image = forwardRef<HTMLSpanElement, ImageProps>(function Image(\n {\n src,\n width,\n height,\n fit,\n decorative,\n accessibilityLabel,\n imageProps,\n renderImage,\n fallback,\n imageRef,\n onLoad,\n onError,\n onLoadStatusChange,\n className,\n style,\n layoutStyle,\n ...props\n },\n ref,\n) {\n const descriptor = resolveImageDescriptor({\n src,\n width,\n height,\n ...(fit === undefined ? {} : { fit }),\n ...(decorative === undefined ? {} : { decorative }),\n ...(accessibilityLabel === undefined ? {} : { accessibilityLabel }),\n } as ImageDescriptor);\n // A→B→A is a new request even when the URL repeats. Retire adapter callbacks\n // at commit/unmount so old network events cannot update state or product observers.\n // Responsive source candidates and request policy are part of image identity;\n // a new srcSet must recover even when its fallback src is unchanged.\n const generation = useMemo(() => ({}), [descriptor.src, imageProps?.srcSet, imageProps?.sizes, imageProps?.crossOrigin, imageProps?.referrerPolicy]);\n const activeGeneration = useRef<object | null>(generation);\n useLayoutEffect(() => {\n activeGeneration.current = generation;\n return () => { activeGeneration.current = null; };\n }, [generation]);\n const [state, setState] = useState<ImageState>({ generation, status: \"loading\" });\n const status = state.generation === generation ? state.status : \"loading\";\n const {\n className: imageClassName,\n style: imageStyle,\n ...restImageProps\n } = imageProps ?? {};\n\n const handleLoad: ReactEventHandler<HTMLImageElement> = (event) => {\n if (activeGeneration.current !== generation) return;\n setState({ generation, status: \"loaded\" });\n onLoadStatusChange?.(\"loaded\");\n onLoad?.(event);\n };\n const handleError: ReactEventHandler<HTMLImageElement> = (event) => {\n if (activeGeneration.current !== generation) return;\n setState({ generation, status: \"error\" });\n onLoadStatusChange?.(\"error\");\n onError?.(event);\n };\n const adapterProps: ImageAdapterProps = {\n ...restImageProps,\n src: descriptor.src,\n alt: descriptor.decorative ? \"\" : descriptor.accessibilityLabel,\n width: descriptor.width,\n height: descriptor.height,\n className: classNames(\"hjm-image__asset\", imageClassName) ??\n \"hjm-image__asset\",\n style: { ...imageStyle, objectFit: descriptor.fit },\n ...(descriptor.decorative ? { \"aria-hidden\": true } : {}),\n onLoad: handleLoad,\n onError: handleError,\n ...(imageRef === undefined ? {} : { ref: imageRef }),\n };\n\n let visual: ReactNode;\n if (status === \"error\") {\n const fallbackLabel = resolveImageFallbackAccessibilityLabel(descriptor);\n visual = (\n <span\n className=\"hjm-image__fallback\"\n role={descriptor.decorative ? undefined : \"img\"}\n aria-label={fallbackLabel}\n aria-hidden={descriptor.decorative || undefined}\n >\n <span className=\"hjm-image__fallback-icon\" aria-hidden=\"true\">\n {fallback ?? (\n <Icon\n name={imageRecipe.fallback.icon.name}\n tone={imageRecipe.fallback.icon.tone}\n decorative\n />\n )}\n </span>\n </span>\n );\n } else if (renderImage === undefined) {\n const { ref: assetRef, ...nativeImageProps } = adapterProps;\n visual = <img {...nativeImageProps} ref={assetRef} />;\n } else {\n visual = renderImage(adapterProps);\n }\n\n return (\n <span\n {...props}\n ref={ref}\n className={classNames(\"hjm-image\", className)}\n data-fit={descriptor.fit}\n data-status={status}\n style={{\n inlineSize: descriptor.width,\n ...style,\n ...layoutStyle,\n aspectRatio: resolveImageAspectRatio(\n descriptor.width,\n descriptor.height,\n ),\n }}\n >\n {visual}\n </span>\n );\n});\n\nexport type CounterBadgeProps = Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> &\n Readonly<{\n count: number;\n max?: number;\n tone?: CounterBadgeTone;\n size?: CounterBadgeSize;\n variant?: CounterBadgeVariant;\n /**\n * Says \"there is something new\" without a number. Use it where the count is\n * unknown or not worth reading; inventing a number would be worse than\n * saying none. The accessible name then carries the whole meaning.\n */\n dot?: boolean;\n accessibilityLabel?: string;\n /** Canonical layout-only placement. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\nexport const CounterBadge = forwardRef<HTMLSpanElement, CounterBadgeProps>(\n function CounterBadge(\n {\n count,\n max = counterBadgeRecipe.defaults.max,\n tone = counterBadgeRecipe.defaults.tone,\n size = counterBadgeRecipe.defaults.size,\n variant = counterBadgeRecipe.defaults.variant,\n dot = false,\n accessibilityLabel,\n className,\n layoutStyle,\n style,\n ...props\n },\n ref,\n ) {\n const label = formatCounterBadgeCount(count, max);\n if (accessibilityLabel !== undefined && accessibilityLabel.trim().length === 0) {\n throw new TypeError(\"CounterBadge accessibilityLabel must not be empty\");\n }\n if (dot && accessibilityLabel === undefined) {\n // A dot with no name is a decoration that nobody can read.\n throw new TypeError(\"CounterBadge dot requires an accessibilityLabel\");\n }\n if (label === null) return null;\n return (\n <span\n {...props}\n ref={ref}\n className={classNames(\"hjm-counter-badge\", className)}\n data-tone={tone}\n data-size={size}\n data-variant={variant}\n data-dot={dot || undefined}\n style={dot ? { ...style, ...layoutStyle, \"--hjm-counter-dot-size\": `${counterBadgeRecipe.dotSize}px` } as typeof style : { ...style, ...layoutStyle }}\n aria-hidden={accessibilityLabel === undefined || undefined}\n // A named count needs a semantic role; generic spans cannot carry aria-label.\n role={accessibilityLabel === undefined ? undefined : \"img\"}\n aria-label={accessibilityLabel}\n >\n {dot ? null : label}\n </span>\n );\n },\n);\n"]}
1
+ {"version":3,"file":"supplemental-display.js","sourceRoot":"","sources":["../src/supplemental-display.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport {\n getIconTransform,\n resolveIconDescriptor,\n semanticIconPaths,\n type IconDescriptor,\n type SemanticIconName,\n} from \"@hjmds/design-contracts/components/icon\";\nimport {\n imageRecipe,\n resolveImageAspectRatio,\n resolveImageDescriptor,\n resolveImageFallbackAccessibilityLabel,\n type ImageDescriptor,\n type ImageLoadStatus,\n} from \"@hjmds/design-contracts/components/image\";\nimport {\n counterBadgeRecipe,\n formatCounterBadgeCount,\n iconRecipe,\n type CounterBadgeSize,\n type CounterBadgeTone,\n type CounterBadgeVariant,\n} from \"@hjmds/design-contracts/recipes\";\nimport {\n forwardRef,\n useState,\n useMemo,\n useRef,\n useLayoutEffect,\n type CSSProperties,\n type HTMLAttributes,\n type ImgHTMLAttributes,\n type ReactElement,\n type ReactEventHandler,\n type ReactNode,\n type Ref,\n type SVGAttributes,\n} from \"react\";\nimport { classNames } from \"./internal.js\";\nimport { useOptionalHjmTheme } from \"./provider.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\n\nexport type IconProps = Omit<\n SVGAttributes<SVGSVGElement>,\n \"children\" | \"color\"\n> & IconDescriptor & Readonly<{\n /** Optional glyph inside the existing 24-unit SVG frame; HJM owns semantics. */\n renderGlyph?: (props: Readonly<{ name: SemanticIconName; size: number; color: string; strokeWidth: number }>) => ReactNode;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\nexport const Icon = forwardRef<SVGSVGElement, IconProps>(function Icon(\n {\n name,\n size,\n tone,\n weight,\n directionality,\n decorative,\n accessibilityLabel,\n renderGlyph,\n className,\n style,\n layoutStyle,\n ...props\n },\n ref,\n) {\n const descriptor = resolveIconDescriptor({\n name,\n ...(size === undefined ? {} : { size }),\n ...(tone === undefined ? {} : { tone }),\n ...(weight === undefined ? {} : { weight }),\n ...(directionality === undefined ? {} : { directionality }),\n ...(decorative === undefined ? {} : { decorative }),\n ...(accessibilityLabel === undefined ? {} : { accessibilityLabel }),\n } as IconDescriptor);\n const theme = useOptionalHjmTheme();\n const transform = getIconTransform(\n descriptor.directionality,\n theme?.environment.direction ?? \"ltr\",\n );\n const dimension = iconRecipe.sizes[descriptor.size];\n return (\n <svg\n {...props}\n ref={ref}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={classNames(\"hjm-icon\", className)}\n data-name={descriptor.name}\n data-size={descriptor.size}\n data-tone={descriptor.tone}\n data-weight={descriptor.weight}\n data-transform={transform}\n width={dimension}\n height={dimension}\n stroke=\"currentColor\"\n strokeWidth={iconRecipe.weights[descriptor.weight]}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n role={descriptor.decorative ? undefined : \"img\"}\n aria-hidden={descriptor.decorative || undefined}\n aria-label={descriptor.decorative ? undefined : descriptor.accessibilityLabel}\n focusable=\"false\"\n style={{ ...style, ...layoutStyle }}\n >\n {renderGlyph?.({ name: descriptor.name, size: 24, color: \"currentColor\", strokeWidth: iconRecipe.weights[descriptor.weight] }) ?? <path d={semanticIconPaths[descriptor.name]} />}\n </svg>\n );\n});\n\ntype ImageElementProps = Omit<\n ImgHTMLAttributes<HTMLImageElement>,\n | \"alt\"\n | \"aria-hidden\"\n | \"aria-label\"\n | \"children\"\n | \"className\"\n | \"height\"\n | \"onError\"\n | \"onLoad\"\n | \"role\"\n | \"src\"\n | \"style\"\n | \"width\"\n>;\n\n/** Canonical props handed to a framework adapter such as `next/image`. */\nexport type ImageAdapterProps = ImageElementProps &\n Readonly<{\n src: string;\n alt: string;\n width: number;\n height: number;\n className?: string;\n style: CSSProperties;\n \"aria-hidden\"?: true;\n onLoad: ReactEventHandler<HTMLImageElement>;\n onError: ReactEventHandler<HTMLImageElement>;\n ref?: Ref<HTMLImageElement>;\n }>;\n\ntype ImageRootProps = Omit<\n HTMLAttributes<HTMLSpanElement>,\n | \"aria-hidden\"\n | \"aria-label\"\n | \"aria-labelledby\"\n | \"children\"\n | \"onError\"\n | \"onLoad\"\n | \"role\"\n>;\n\nexport type ImageProps = ImageRootProps &\n ImageDescriptor &\n Readonly<{\n /** Additional native `<img>` props shared with the framework adapter. */\n imageProps?: ImageElementProps &\n Readonly<{ className?: string; style?: CSSProperties }>;\n /**\n * Receives the complete accessible image contract. The adapter must pass\n * these props to its underlying image element so HJM can observe failure.\n */\n renderImage?: (props: ImageAdapterProps) => ReactElement;\n /** Visual content only; HJM keeps the fallback's accessible name. */\n fallback?: ReactNode;\n imageRef?: Ref<HTMLImageElement>;\n onLoad?: ReactEventHandler<HTMLImageElement>;\n onError?: ReactEventHandler<HTMLImageElement>;\n onLoadStatusChange?: (status: Extract<ImageLoadStatus, \"loaded\" | \"error\">) => void;\n /** Canonical layout-only placement on the root frame; the aspect ratio stays descriptor-owned. */\n layoutStyle?: HjmCompositionStyleProp;\n }>;\n\ntype ImageState = Readonly<{\n generation: object;\n status: Extract<ImageLoadStatus, \"loading\" | \"loaded\" | \"error\">;\n}>;\n\n/** Intrinsic-size image with canonical alt semantics and an accessible fallback. */\nexport const Image = forwardRef<HTMLSpanElement, ImageProps>(function Image(\n {\n src,\n width,\n height,\n fit,\n decorative,\n accessibilityLabel,\n imageProps,\n renderImage,\n fallback,\n imageRef,\n onLoad,\n onError,\n onLoadStatusChange,\n className,\n style,\n layoutStyle,\n ...props\n },\n ref,\n) {\n const descriptor = resolveImageDescriptor({\n src,\n width,\n height,\n ...(fit === undefined ? {} : { fit }),\n ...(decorative === undefined ? {} : { decorative }),\n ...(accessibilityLabel === undefined ? {} : { accessibilityLabel }),\n } as ImageDescriptor);\n // A→B→A is a new request even when the URL repeats. Retire adapter callbacks\n // at commit/unmount so old network events cannot update state or product observers.\n // Responsive source candidates and request policy are part of image identity;\n // a new srcSet must recover even when its fallback src is unchanged.\n const generation = useMemo(() => ({}), [descriptor.src, imageProps?.srcSet, imageProps?.sizes, imageProps?.crossOrigin, imageProps?.referrerPolicy]);\n const activeGeneration = useRef<object | null>(generation);\n useLayoutEffect(() => {\n activeGeneration.current = generation;\n return () => { activeGeneration.current = null; };\n }, [generation]);\n const [state, setState] = useState<ImageState>({ generation, status: \"loading\" });\n const status = state.generation === generation ? state.status : \"loading\";\n const {\n className: imageClassName,\n style: imageStyle,\n ...restImageProps\n } = imageProps ?? {};\n\n const handleLoad: ReactEventHandler<HTMLImageElement> = (event) => {\n if (activeGeneration.current !== generation) return;\n setState({ generation, status: \"loaded\" });\n onLoadStatusChange?.(\"loaded\");\n onLoad?.(event);\n };\n const handleError: ReactEventHandler<HTMLImageElement> = (event) => {\n if (activeGeneration.current !== generation) return;\n setState({ generation, status: \"error\" });\n onLoadStatusChange?.(\"error\");\n onError?.(event);\n };\n const adapterProps: ImageAdapterProps = {\n ...restImageProps,\n src: descriptor.src,\n alt: descriptor.decorative ? \"\" : descriptor.accessibilityLabel,\n width: descriptor.width,\n height: descriptor.height,\n className: classNames(\"hjm-image__asset\", imageClassName) ??\n \"hjm-image__asset\",\n style: { ...imageStyle, objectFit: descriptor.fit },\n ...(descriptor.decorative ? { \"aria-hidden\": true } : {}),\n onLoad: handleLoad,\n onError: handleError,\n ...(imageRef === undefined ? {} : { ref: imageRef }),\n };\n\n let visual: ReactNode;\n if (status === \"error\") {\n const fallbackLabel = resolveImageFallbackAccessibilityLabel(descriptor);\n visual = (\n <span\n className=\"hjm-image__fallback\"\n role={descriptor.decorative ? undefined : \"img\"}\n aria-label={fallbackLabel}\n aria-hidden={descriptor.decorative || undefined}\n >\n <span className=\"hjm-image__fallback-icon\" aria-hidden=\"true\">\n {fallback ?? (\n <Icon\n name={imageRecipe.fallback.icon.name}\n tone={imageRecipe.fallback.icon.tone}\n decorative\n />\n )}\n </span>\n </span>\n );\n } else if (renderImage === undefined) {\n const { ref: assetRef, ...nativeImageProps } = adapterProps;\n visual = <img {...nativeImageProps} ref={assetRef} />;\n } else {\n visual = renderImage(adapterProps);\n }\n\n return (\n <span\n {...props}\n ref={ref}\n className={classNames(\"hjm-image\", className)}\n data-fit={descriptor.fit}\n data-status={status}\n style={{\n inlineSize: descriptor.width,\n ...style,\n ...layoutStyle,\n aspectRatio: resolveImageAspectRatio(\n descriptor.width,\n descriptor.height,\n ),\n }}\n >\n {visual}\n </span>\n );\n});\n\nexport type CounterBadgeProps = Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> &\n Readonly<{\n count: number;\n max?: number;\n tone?: CounterBadgeTone;\n size?: CounterBadgeSize;\n variant?: CounterBadgeVariant;\n /**\n * Says \"there is something new\" without a number. Use it where the count is\n * unknown or not worth reading; inventing a number would be worse than\n * saying none. The accessible name then carries the whole meaning.\n */\n dot?: boolean;\n accessibilityLabel?: string;\n /** Canonical layout-only placement. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\nexport const CounterBadge = forwardRef<HTMLSpanElement, CounterBadgeProps>(\n function CounterBadge(\n {\n count,\n max = counterBadgeRecipe.defaults.max,\n tone = counterBadgeRecipe.defaults.tone,\n size = counterBadgeRecipe.defaults.size,\n variant = counterBadgeRecipe.defaults.variant,\n dot = false,\n accessibilityLabel,\n className,\n layoutStyle,\n style,\n ...props\n },\n ref,\n ) {\n const label = formatCounterBadgeCount(count, max);\n if (accessibilityLabel !== undefined && accessibilityLabel.trim().length === 0) {\n throw new TypeError(\"CounterBadge accessibilityLabel must not be empty\");\n }\n if (dot && accessibilityLabel === undefined) {\n // A dot with no name is a decoration that nobody can read.\n throw new TypeError(\"CounterBadge dot requires an accessibilityLabel\");\n }\n if (label === null) return null;\n return (\n <span\n {...props}\n ref={ref}\n className={classNames(\"hjm-counter-badge\", className)}\n data-tone={tone}\n data-size={size}\n data-variant={variant}\n data-dot={dot || undefined}\n style={dot ? { ...style, ...layoutStyle, \"--hjm-counter-dot-size\": `${counterBadgeRecipe.dotSize}px` } as typeof style : { ...style, ...layoutStyle }}\n aria-hidden={accessibilityLabel === undefined || undefined}\n // A named count needs a semantic role; generic spans cannot carry aria-label.\n role={accessibilityLabel === undefined ? undefined : \"img\"}\n aria-label={accessibilityLabel}\n >\n {dot ? null : label}\n </span>\n );\n },\n);\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"supplemental-navigation.d.ts","sourceRoot":"","sources":["../src/supplemental-navigation.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC3B,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAOL,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AA8BtE,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAC1E,QAAQ,CAAC;IACP,UAAU,EAAE,kBAAkB,CAAC;IAC/B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,UAAU,EAAE,sBAAsB,CAAC;IACnC,gBAAgB,CAAC,EAAE,CACjB,OAAO,EAAE,sBAAsB,EAC/B,MAAM,EAAE,qBAAqB,KAC1B,IAAI,CAAC;IACV,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACzE,gBAAgB,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gGAAgG;IAChG,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC,CAAC,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,QAAQ;gBArBL,kBAAkB;IAC9B,gFAAgF;eACrE,OAAO;WACX,YAAY;cACT,eAAe;gBACb,sBAAsB;uBACf,CACjB,OAAO,EAAE,sBAAsB,EAC/B,MAAM,EAAE,qBAAqB,KAC1B,IAAI;qBACQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,qBAAqB,KAAK,IAAI;uBACrD,OAAO,GAAG,QAAQ,GAAG,IAAI;iBAC/B,MAAM;IACnB,gGAAgG;kBAClF,uBAAuB;mDA+JxC,CAAC"}
1
+ {"version":3,"file":"supplemental-navigation.d.ts","sourceRoot":"","sources":["../src/supplemental-navigation.tsx"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC3B,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAOL,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AA8BtE,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAC1E,QAAQ,CAAC;IACP,UAAU,EAAE,kBAAkB,CAAC;IAC/B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,UAAU,EAAE,sBAAsB,CAAC;IACnC,gBAAgB,CAAC,EAAE,CACjB,OAAO,EAAE,sBAAsB,EAC/B,MAAM,EAAE,qBAAqB,KAC1B,IAAI,CAAC;IACV,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACzE,gBAAgB,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gGAAgG;IAChG,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC,CAAC,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,QAAQ;gBArBL,kBAAkB;IAC9B,gFAAgF;eACrE,OAAO;WACX,YAAY;cACT,eAAe;gBACb,sBAAsB;uBACf,CACjB,OAAO,EAAE,sBAAsB,EAC/B,MAAM,EAAE,qBAAqB,KAC1B,IAAI;qBACQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,qBAAqB,KAAK,IAAI;uBACrD,OAAO,GAAG,QAAQ,GAAG,IAAI;iBAC/B,MAAM;IACnB,gGAAgG;kBAClF,uBAAuB;mDA+JxC,CAAC"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { createLoadMoreController, validateLoadMoreDescriptor, } from "@hjmds/design-contracts/components/load-more";
3
4
  import { loadMoreRecipe, } from "@hjmds/design-contracts/recipes";
@@ -1 +1 @@
1
- {"version":3,"file":"supplemental-navigation.js","sourceRoot":"","sources":["../src/supplemental-navigation.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n createLoadMoreController,\n validateLoadMoreDescriptor,\n type LoadMoreController,\n type LoadMoreControllerSnapshot,\n type LoadMoreDescriptor,\n type LoadMoreMode,\n type LoadMoreRequestHandler,\n type LoadMoreRequestOutcome,\n type LoadMoreRequestReason,\n} from \"@hjmds/design-contracts/components/load-more\";\nimport {\n loadMoreRecipe,\n type LoadMoreDensity,\n} from \"@hjmds/design-contracts/recipes\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type HTMLAttributes,\n} from \"react\";\nimport { classNames } from \"./internal.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\nfunction createLoadMoreControllerFacade(): Readonly<{\n facade: LoadMoreController;\n attach(controller: LoadMoreController): () => void;\n}> {\n const detachedSnapshot: LoadMoreControllerSnapshot = {\n mode: \"automatic\",\n inFlightRequestKey: null,\n disposed: true,\n };\n let active: LoadMoreController | null = null;\n return {\n facade: {\n getSnapshot: () => active?.getSnapshot() ?? detachedSnapshot,\n request: (state, reason) => {\n if (!active) throw new Error(\"Cannot use a detached LoadMore controller\");\n return active.request(state, reason);\n },\n dispose: () => active?.dispose() ?? false,\n },\n attach(controller) {\n active = controller;\n return () => {\n if (active === controller) active = null;\n };\n },\n };\n}\n\nexport type LoadMoreProps = Omit<HTMLAttributes<HTMLDivElement>, \"children\"> &\n Readonly<{\n descriptor: LoadMoreDescriptor;\n /** Product mutation/refetch lock, separate from the next-page loading state. */\n disabled?: boolean;\n mode?: LoadMoreMode;\n density?: LoadMoreDensity;\n onLoadMore: LoadMoreRequestHandler;\n onRequestOutcome?: (\n outcome: LoadMoreRequestOutcome,\n reason: LoadMoreRequestReason,\n ) => void;\n onRequestError?: (error: unknown, reason: LoadMoreRequestReason) => void;\n intersectionRoot?: Element | Document | null;\n rootMargin?: string;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n }>;\n\n/**\n * A collection footer that keeps product data controlled while the shared\n * controller prevents overlapping cursor requests.\n */\nexport const LoadMore = forwardRef<HTMLDivElement, LoadMoreProps>(\n function LoadMore(\n {\n descriptor,\n disabled = false,\n mode = loadMoreRecipe.defaults.mode,\n density = loadMoreRecipe.defaults.density,\n onLoadMore,\n onRequestOutcome,\n onRequestError,\n intersectionRoot = null,\n rootMargin = \"200px 0px\",\n className,\n layoutStyle,\n style,\n ...props\n },\n ref,\n ) {\n validateLoadMoreDescriptor(descriptor);\n const disabledRef = useRef(disabled);\n disabledRef.current = disabled;\n const onLoadMoreRef = useRef(onLoadMore);\n onLoadMoreRef.current = onLoadMore;\n const [controllerFacade] = useState(createLoadMoreControllerFacade);\n const controller = controllerFacade.facade;\n const requestGeneration = useRef(0);\n const sentinelRef = useRef<HTMLSpanElement>(null);\n const currentRequestIdentityRef = useRef<string | null>(null);\n const completedRequestIdentityRef = useRef<string | null>(null);\n const currentRequestIdentity =\n descriptor.state.status === \"ready\" || descriptor.state.status === \"error\"\n ? `${descriptor.state.status}:${descriptor.state.requestKey}`\n : null;\n\n useLayoutEffect(() => {\n currentRequestIdentityRef.current = currentRequestIdentity;\n return () => { currentRequestIdentityRef.current = null; };\n }, [currentRequestIdentity]);\n\n const request = useCallback(\n async (\n state: LoadMoreDescriptor[\"state\"],\n reason: LoadMoreRequestReason,\n ) => {\n if (disabledRef.current || state.status === \"loading\" || state.status === \"complete\") return;\n const requestIdentity = `${state.status}:${state.requestKey}`;\n // IntersectionObserver may deliver an already queued callback after\n // disconnect. Only events for the currently committed descriptor may\n // enter the shared request controller.\n if (currentRequestIdentityRef.current !== requestIdentity) return;\n // Once a request settles successfully, retire that exact state/key\n // until the product commits a new cursor or a retryable error state.\n if (completedRequestIdentityRef.current === requestIdentity) return;\n const generation = requestGeneration.current;\n try {\n const outcome = await controller.request(state, reason);\n if (generation !== requestGeneration.current) return;\n if (outcome === \"started\") {\n completedRequestIdentityRef.current = requestIdentity;\n }\n onRequestOutcome?.(outcome, reason);\n } catch (error) {\n if (generation === requestGeneration.current) onRequestError?.(error, reason);\n }\n },\n [controller, onRequestError, onRequestOutcome],\n );\n\n useEffect(() => {\n const attached = createLoadMoreController({\n mode,\n onLoadMore: (nextRequest) => onLoadMoreRef.current(nextRequest),\n });\n const detach = controllerFacade.attach(attached);\n requestGeneration.current += 1;\n return () => {\n // The query remains product-owned; only this retired footer's callbacks stop.\n requestGeneration.current += 1;\n detach();\n attached.dispose();\n };\n }, [controllerFacade, mode]);\n\n useEffect(() => {\n if (\n disabled || mode !== \"automatic\" ||\n descriptor.state.status !== \"ready\" ||\n typeof IntersectionObserver === \"undefined\"\n ) {\n return;\n }\n const sentinel = sentinelRef.current;\n if (!sentinel) return;\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n void request(descriptor.state, \"viewport\");\n }\n },\n { root: intersectionRoot, rootMargin },\n );\n observer.observe(sentinel);\n return () => observer.disconnect();\n }, [descriptor.state, disabled, intersectionRoot, mode, request, rootMargin]);\n\n const { state, labels } = descriptor;\n return (\n <div\n {...props}\n style={{ ...style, ...layoutStyle }}\n ref={ref}\n className={classNames(\"hjm-load-more\", className)}\n data-mode={mode}\n data-density={density}\n data-state={state.status}\n aria-disabled={disabled || undefined}\n aria-busy={state.status === \"loading\" || undefined}\n >\n <span ref={sentinelRef} className=\"hjm-load-more__sentinel\" aria-hidden=\"true\" />\n {state.status === \"ready\" ? (\n <button\n type=\"button\"\n className=\"hjm-load-more__trigger\"\n disabled={disabled}\n onClick={() => void request(state, \"manual\")}\n >\n {labels.loadMore}\n </button>\n ) : state.status === \"loading\" ? (\n <div className=\"hjm-load-more__status\" role=\"status\">\n <span className=\"hjm-load-more__spinner\" aria-hidden=\"true\" />\n <span className=\"hjm-visually-hidden\">{labels.loading}</span>\n </div>\n ) : state.status === \"error\" ? (\n <div className=\"hjm-load-more__error\">\n <span role=\"alert\">{state.message}</span>\n <button\n type=\"button\"\n className=\"hjm-load-more__trigger\"\n disabled={disabled}\n onClick={() => void request(state, \"retry\")}\n >\n {labels.retry}\n </button>\n </div>\n ) : (\n <div className=\"hjm-load-more__end\">{labels.complete}</div>\n )}\n </div>\n );\n },\n);\n"]}
1
+ {"version":3,"file":"supplemental-navigation.js","sourceRoot":"","sources":["../src/supplemental-navigation.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport {\n createLoadMoreController,\n validateLoadMoreDescriptor,\n type LoadMoreController,\n type LoadMoreControllerSnapshot,\n type LoadMoreDescriptor,\n type LoadMoreMode,\n type LoadMoreRequestHandler,\n type LoadMoreRequestOutcome,\n type LoadMoreRequestReason,\n} from \"@hjmds/design-contracts/components/load-more\";\nimport {\n loadMoreRecipe,\n type LoadMoreDensity,\n} from \"@hjmds/design-contracts/recipes\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type HTMLAttributes,\n} from \"react\";\nimport { classNames } from \"./internal.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\nfunction createLoadMoreControllerFacade(): Readonly<{\n facade: LoadMoreController;\n attach(controller: LoadMoreController): () => void;\n}> {\n const detachedSnapshot: LoadMoreControllerSnapshot = {\n mode: \"automatic\",\n inFlightRequestKey: null,\n disposed: true,\n };\n let active: LoadMoreController | null = null;\n return {\n facade: {\n getSnapshot: () => active?.getSnapshot() ?? detachedSnapshot,\n request: (state, reason) => {\n if (!active) throw new Error(\"Cannot use a detached LoadMore controller\");\n return active.request(state, reason);\n },\n dispose: () => active?.dispose() ?? false,\n },\n attach(controller) {\n active = controller;\n return () => {\n if (active === controller) active = null;\n };\n },\n };\n}\n\nexport type LoadMoreProps = Omit<HTMLAttributes<HTMLDivElement>, \"children\"> &\n Readonly<{\n descriptor: LoadMoreDescriptor;\n /** Product mutation/refetch lock, separate from the next-page loading state. */\n disabled?: boolean;\n mode?: LoadMoreMode;\n density?: LoadMoreDensity;\n onLoadMore: LoadMoreRequestHandler;\n onRequestOutcome?: (\n outcome: LoadMoreRequestOutcome,\n reason: LoadMoreRequestReason,\n ) => void;\n onRequestError?: (error: unknown, reason: LoadMoreRequestReason) => void;\n intersectionRoot?: Element | Document | null;\n rootMargin?: string;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n }>;\n\n/**\n * A collection footer that keeps product data controlled while the shared\n * controller prevents overlapping cursor requests.\n */\nexport const LoadMore = forwardRef<HTMLDivElement, LoadMoreProps>(\n function LoadMore(\n {\n descriptor,\n disabled = false,\n mode = loadMoreRecipe.defaults.mode,\n density = loadMoreRecipe.defaults.density,\n onLoadMore,\n onRequestOutcome,\n onRequestError,\n intersectionRoot = null,\n rootMargin = \"200px 0px\",\n className,\n layoutStyle,\n style,\n ...props\n },\n ref,\n ) {\n validateLoadMoreDescriptor(descriptor);\n const disabledRef = useRef(disabled);\n disabledRef.current = disabled;\n const onLoadMoreRef = useRef(onLoadMore);\n onLoadMoreRef.current = onLoadMore;\n const [controllerFacade] = useState(createLoadMoreControllerFacade);\n const controller = controllerFacade.facade;\n const requestGeneration = useRef(0);\n const sentinelRef = useRef<HTMLSpanElement>(null);\n const currentRequestIdentityRef = useRef<string | null>(null);\n const completedRequestIdentityRef = useRef<string | null>(null);\n const currentRequestIdentity =\n descriptor.state.status === \"ready\" || descriptor.state.status === \"error\"\n ? `${descriptor.state.status}:${descriptor.state.requestKey}`\n : null;\n\n useLayoutEffect(() => {\n currentRequestIdentityRef.current = currentRequestIdentity;\n return () => { currentRequestIdentityRef.current = null; };\n }, [currentRequestIdentity]);\n\n const request = useCallback(\n async (\n state: LoadMoreDescriptor[\"state\"],\n reason: LoadMoreRequestReason,\n ) => {\n if (disabledRef.current || state.status === \"loading\" || state.status === \"complete\") return;\n const requestIdentity = `${state.status}:${state.requestKey}`;\n // IntersectionObserver may deliver an already queued callback after\n // disconnect. Only events for the currently committed descriptor may\n // enter the shared request controller.\n if (currentRequestIdentityRef.current !== requestIdentity) return;\n // Once a request settles successfully, retire that exact state/key\n // until the product commits a new cursor or a retryable error state.\n if (completedRequestIdentityRef.current === requestIdentity) return;\n const generation = requestGeneration.current;\n try {\n const outcome = await controller.request(state, reason);\n if (generation !== requestGeneration.current) return;\n if (outcome === \"started\") {\n completedRequestIdentityRef.current = requestIdentity;\n }\n onRequestOutcome?.(outcome, reason);\n } catch (error) {\n if (generation === requestGeneration.current) onRequestError?.(error, reason);\n }\n },\n [controller, onRequestError, onRequestOutcome],\n );\n\n useEffect(() => {\n const attached = createLoadMoreController({\n mode,\n onLoadMore: (nextRequest) => onLoadMoreRef.current(nextRequest),\n });\n const detach = controllerFacade.attach(attached);\n requestGeneration.current += 1;\n return () => {\n // The query remains product-owned; only this retired footer's callbacks stop.\n requestGeneration.current += 1;\n detach();\n attached.dispose();\n };\n }, [controllerFacade, mode]);\n\n useEffect(() => {\n if (\n disabled || mode !== \"automatic\" ||\n descriptor.state.status !== \"ready\" ||\n typeof IntersectionObserver === \"undefined\"\n ) {\n return;\n }\n const sentinel = sentinelRef.current;\n if (!sentinel) return;\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n void request(descriptor.state, \"viewport\");\n }\n },\n { root: intersectionRoot, rootMargin },\n );\n observer.observe(sentinel);\n return () => observer.disconnect();\n }, [descriptor.state, disabled, intersectionRoot, mode, request, rootMargin]);\n\n const { state, labels } = descriptor;\n return (\n <div\n {...props}\n style={{ ...style, ...layoutStyle }}\n ref={ref}\n className={classNames(\"hjm-load-more\", className)}\n data-mode={mode}\n data-density={density}\n data-state={state.status}\n aria-disabled={disabled || undefined}\n aria-busy={state.status === \"loading\" || undefined}\n >\n <span ref={sentinelRef} className=\"hjm-load-more__sentinel\" aria-hidden=\"true\" />\n {state.status === \"ready\" ? (\n <button\n type=\"button\"\n className=\"hjm-load-more__trigger\"\n disabled={disabled}\n onClick={() => void request(state, \"manual\")}\n >\n {labels.loadMore}\n </button>\n ) : state.status === \"loading\" ? (\n <div className=\"hjm-load-more__status\" role=\"status\">\n <span className=\"hjm-load-more__spinner\" aria-hidden=\"true\" />\n <span className=\"hjm-visually-hidden\">{labels.loading}</span>\n </div>\n ) : state.status === \"error\" ? (\n <div className=\"hjm-load-more__error\">\n <span role=\"alert\">{state.message}</span>\n <button\n type=\"button\"\n className=\"hjm-load-more__trigger\"\n disabled={disabled}\n onClick={() => void request(state, \"retry\")}\n >\n {labels.retry}\n </button>\n </div>\n ) : (\n <div className=\"hjm-load-more__end\">{labels.complete}</div>\n )}\n </div>\n );\n },\n);\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"swipe-actions.d.ts","sourceRoot":"","sources":["../src/swipe-actions.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,yDAAyD,CAAC;AAE1G,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEtE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAClF,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1E,gGAAgG;IAChG,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC,CAAC;AACF,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,iBAAiB,+BAcjH"}
1
+ {"version":3,"file":"swipe-actions.d.ts","sourceRoot":"","sources":["../src/swipe-actions.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,yDAAyD,CAAC;AAE1G,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEtE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAClF,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1E,gGAAgG;IAChG,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC,CAAC;AACF,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,iBAAiB,+BAcjH"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { useRef } from "react";
3
4
  import { validateActions } from "@hjmds/design-contracts/components/interaction-adapters";
@@ -1 +1 @@
1
- {"version":3,"file":"swipe-actions.js","sourceRoot":"","sources":["../src/swipe-actions.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAkB,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAkB,MAAM,yDAAyD,CAAC;AAC1G,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAStC,qFAAqF;AACrF,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAqB;IAChH,eAAe,CAAC,OAAO,CAAC,CAAC;IACzB,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9B,KAAK,UAAU,GAAG,CAAC,MAAiB;QAClC,IAAI,IAAI,IAAI,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC,QAAQ;YAAE,OAAO;QACvD,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC;YAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAAC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAAC,CAAC;gBAAS,CAAC;YAAC,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC;QAAC,CAAC;IAC3G,CAAC;IACD,OAAO,eAAK,IAAI,EAAC,OAAO,gBAAa,KAAK,eAAa,IAAI,EAAE,KAAK,EAAE,WAAW,aAC5E,QAAQ,EAAC,cAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,EAAE,YACpF,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,KAAC,MAAM,IAAiB,IAAI,EAAE,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAClG,QAAQ,EAAE,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,YAAG,MAAM,CAAC,KAAK,IADxD,MAAM,CAAC,EAAE,CACyD,CAAC,GACnG,IACF,CAAC;AACT,CAAC","sourcesContent":["import { useRef, type ReactNode } from \"react\";\nimport { validateActions, type RowAction } from \"@hjmds/design-contracts/components/interaction-adapters\";\nimport { Button } from \"./actions.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\nexport type SwipeActionsProps = {\n children: ReactNode; label: string; actions: readonly RowAction[]; busy?: boolean;\n onAction(id: string): void | Promise<void>; onError(error: unknown): void;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n};\n/** Desktop exposes the same actions directly; no hidden swipe-only functionality. */\nexport function SwipeActions({ children, label, actions, busy, onAction, onError, layoutStyle }: SwipeActionsProps) {\n validateActions(actions);\n const pending = useRef(false);\n async function run(action: RowAction) {\n if (busy || pending.current || action.disabled) return;\n pending.current = true;\n try { await onAction(action.id); } catch (error) { onError(error); } finally { pending.current = false; }\n }\n return <div role=\"group\" aria-label={label} aria-busy={busy} style={layoutStyle}>\n {children}<div style={{ display: \"flex\", gap: \"var(--hjm-space-xs)\", flexWrap: \"wrap\" }}>\n {actions.map(action => <Button key={action.id} tone={action.intent === \"danger\" ? \"danger\" : \"ghost\"}\n disabled={Boolean(busy || action.disabled)} onClick={() => void run(action)}>{action.label}</Button>)}\n </div>\n </div>;\n}\n"]}
1
+ {"version":3,"file":"swipe-actions.js","sourceRoot":"","sources":["../src/swipe-actions.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,MAAM,EAAkB,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAkB,MAAM,yDAAyD,CAAC;AAC1G,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAStC,qFAAqF;AACrF,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAqB;IAChH,eAAe,CAAC,OAAO,CAAC,CAAC;IACzB,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9B,KAAK,UAAU,GAAG,CAAC,MAAiB;QAClC,IAAI,IAAI,IAAI,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC,QAAQ;YAAE,OAAO;QACvD,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC;YAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAAC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAAC,CAAC;gBAAS,CAAC;YAAC,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC;QAAC,CAAC;IAC3G,CAAC;IACD,OAAO,eAAK,IAAI,EAAC,OAAO,gBAAa,KAAK,eAAa,IAAI,EAAE,KAAK,EAAE,WAAW,aAC5E,QAAQ,EAAC,cAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,EAAE,YACpF,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,KAAC,MAAM,IAAiB,IAAI,EAAE,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAClG,QAAQ,EAAE,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,YAAG,MAAM,CAAC,KAAK,IADxD,MAAM,CAAC,EAAE,CACyD,CAAC,GACnG,IACF,CAAC;AACT,CAAC","sourcesContent":["\"use client\";\n\nimport { useRef, type ReactNode } from \"react\";\nimport { validateActions, type RowAction } from \"@hjmds/design-contracts/components/interaction-adapters\";\nimport { Button } from \"./actions.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\nexport type SwipeActionsProps = {\n children: ReactNode; label: string; actions: readonly RowAction[]; busy?: boolean;\n onAction(id: string): void | Promise<void>; onError(error: unknown): void;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n};\n/** Desktop exposes the same actions directly; no hidden swipe-only functionality. */\nexport function SwipeActions({ children, label, actions, busy, onAction, onError, layoutStyle }: SwipeActionsProps) {\n validateActions(actions);\n const pending = useRef(false);\n async function run(action: RowAction) {\n if (busy || pending.current || action.disabled) return;\n pending.current = true;\n try { await onAction(action.id); } catch (error) { onError(error); } finally { pending.current = false; }\n }\n return <div role=\"group\" aria-label={label} aria-busy={busy} style={layoutStyle}>\n {children}<div style={{ display: \"flex\", gap: \"var(--hjm-space-xs)\", flexWrap: \"wrap\" }}>\n {actions.map(action => <Button key={action.id} tone={action.intent === \"danger\" ? \"danger\" : \"ghost\"}\n disabled={Boolean(busy || action.disabled)} onClick={() => void run(action)}>{action.label}</Button>)}\n </div>\n </div>;\n}\n"]}