@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
@@ -1 +1 @@
1
- {"version":3,"file":"initial-focus.js","sourceRoot":"","sources":["../../src/internal/initial-focus.tsx"],"names":[],"mappings":"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","sourcesContent":["import { resolveEntryFocus, type EntryFocusEvent, type EntryFocusPhase, type InitialFocusCandidate, type InitialFocusMode } from \"@hjmds/design-contracts/screen-patterns\";\nimport { createContext, useContext, useEffect, useLayoutEffect, useMemo, useRef, type ReactNode, type RefObject } from \"react\";\nimport { getTopModal, subscribeModalClose, type ActiveModal } from \"../modal.js\";\n\ntype Entry = { order: number; preference: boolean | undefined; element(): HTMLElement | null; focusable(): boolean };\ntype Registry = { nextOrder(): number; register(entry: Entry, mounted: boolean): () => void };\n/** The overlay's own entry on the shared modal stack while it is active (set by `useModalFocus`). */\nexport type ModalLayerRef = { current: ActiveModal | null };\n\n/**\n * Nearest screen/overlay scope that chooses the field focused on entry (rules: screen-patterns `resolveEntryFocus`,\n * shared with Native). Fields register by context, the same model as Native, instead of the scope querying the DOM; a\n * scope with mode \"none\" still owns its fields so they never reach an outer scope.\n */\nconst InitialFocusContext = createContext<Registry | null>(null);\n// A bottom sheet owns this boundary, including ScreenLayout/marked fields nested inside its body.\nconst EntryFocusEnabledContext = createContext(true);\n/** Layer of the enclosing HJM overlay; null on the page itself. A ScreenLayout inside a sheet uses the sheet's. */\nconst ModalLayerContext = createContext<ModalLayerRef | null>(null);\n\ntype NestedScope = { enter(): HTMLElement | null; settle(): void };\n/**\n * Screen scopes rendered inside an HJM overlay, keyed by that overlay's layer. Their fields register with the screen,\n * not the overlay, so the overlay's activation asks them for the entry field instead of focusing its first control\n * over them (BurnTok search: a ScreenLayout in a Sheet left focus on the close button, 2026-10-18).\n */\nconst nestedScopes = new WeakMap<ModalLayerRef, Set<NestedScope>>();\n\n/**\n * Product modals (not on the HJM stack) layered above the scope. A product modal that contains the scope's own fields\n * wraps the screen rather than covering it, so it does not block (BurnTok search overlay, 2026-10-18).\n */\nfunction productModalAbove(fields: readonly HTMLElement[]): boolean {\n return [...document.querySelectorAll('[aria-modal=\"true\"], dialog[open]')]\n .some(modal => !fields.some(field => modal.contains(field)));\n}\n\nfunction isEditable(element: Element | null): boolean {\n return element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement\n || (element instanceof HTMLElement && element.isContentEditable);\n}\n\ntype Candidate = InitialFocusCandidate & { entry: Entry };\nexport type InitialFocusScopeHandle = Readonly<{\n registry: Registry;\n layer: ModalLayerRef | null;\n enabled: boolean;\n /**\n * Overlays only: runs entry when the modal activates and returns the field for `useModalFocus` to focus. `explicit`\n * means the overlay already has an `initialFocusRef`, so entry settles without choosing a field.\n */\n enter(explicit: boolean): HTMLElement | null;\n}>;\n\n/**\n * Screen scopes enter on mount (Web has no enter transition to wait for); overlays pass `layer` and enter through\n * `useModalFocus`. User pointer, key, wheel or touch input while no modal is above the scope ends the entry window.\n */\nexport function useInitialFocusScope({ mode, active = true, layer: ownLayer, enabled = true }: { mode: InitialFocusMode; active?: boolean; layer?: ModalLayerRef; enabled?: boolean }): InitialFocusScopeHandle {\n const inherited = useContext(ModalLayerContext);\n const inheritedEnabled = useContext(EntryFocusEnabledContext);\n // A separate overlay owns its policy; ordinary nested screens inherit their enclosing sheet's policy.\n const entryFocusEnabled = enabled && (ownLayer !== undefined || inheritedEnabled);\n const enabledRef = useRef(entryFocusEnabled); enabledRef.current = entryFocusEnabled;\n const layer = ownLayer ?? inherited;\n const overlay = ownLayer !== undefined;\n const modeRef = useRef(mode); modeRef.current = mode;\n const state = useRef({ phase: \"inactive\" as EntryFocusPhase, entries: new Set<Entry>(), fresh: new Set<Entry>(), counter: 0, flushQueued: false });\n\n const scope = useMemo(() => {\n const s = state.current;\n const blocked = () => {\n const own = layer?.current ?? null;\n // Inside an HJM overlay that is not on the stack yet: its activation runs this scope's entry (`nestedScopes`).\n if (layer !== null && own === null) return true;\n const top = getTopModal();\n if (top) return top !== own;\n // A product's own modal above the page still covers it; overlay content is portaled outside product markup.\n if (layer !== null) return false;\n const fields = [...s.entries].map(entry => entry.element()).filter((element): element is HTMLElement => element !== null);\n return productModalAbove(fields);\n };\n const dispatch = (event: EntryFocusEvent<Candidate> | { kind: \"register\"; entry: Entry }): HTMLElement | null => {\n if (!enabledRef.current) return null;\n const candidates: Candidate[] = [...s.entries].map(entry => ({ entry, order: entry.order, preference: entry.preference, focusable: entry.focusable() }));\n const resolved = event.kind === \"register\" && \"entry\" in event\n ? { kind: \"register\" as const, field: candidates.find(candidate => candidate.entry === event.entry)! }\n : event as EntryFocusEvent<Candidate>;\n const result = resolveEntryFocus(s.phase, resolved, { mode: modeRef.current, candidates, blocked: blocked(), textEntryFocused: isEditable(document.activeElement) });\n s.phase = result.phase;\n return result.target?.entry.element() ?? null;\n };\n const focus = (target: HTMLElement | null) => target?.focus({ preventScroll: true });\n // Fields mounting in one commit are judged together.\n const flush = () => {\n s.flushQueued = false;\n const fresh = [...s.fresh].filter(entry => s.entries.has(entry)).sort((a, b) => a.order - b.order);\n s.fresh.clear();\n const field = fresh.find(entry => entry.preference === true) ?? fresh[0];\n if (field) focus(dispatch({ kind: \"register\", entry: field }));\n };\n const registry: Registry = {\n nextOrder: () => s.counter++,\n register(entry, mounted) {\n s.entries.add(entry);\n if (mounted) { s.fresh.add(entry); if (!s.flushQueued) { s.flushQueued = true; queueMicrotask(flush); } }\n return () => { s.entries.delete(entry); s.fresh.delete(entry); };\n },\n };\n const settle = () => { s.phase = \"settled\"; };\n const enter = (explicit: boolean) => {\n s.fresh.clear();\n const nested = overlay && layer ? [...(nestedScopes.get(layer) ?? [])] : [];\n if (explicit) { settle(); for (const scope of nested) scope.settle(); return null; }\n // A user can open a menu before the deferred entry runs. Never reset their settled entry window.\n if (s.phase === \"settled\") return null;\n if (s.phase === \"inactive\") dispatch({ kind: \"activate\" });\n const own = dispatch({ kind: s.phase === \"open\" ? \"unblock\" : \"enter\" });\n if (own) return own;\n for (const scope of nested) { const target = scope.enter(); if (target) return target; }\n return null;\n };\n return { registry, layer, dispatch, focus, enter, settle };\n }, [layer, overlay]);\n\n useEffect(() => {\n if (!active) { scope.dispatch({ kind: \"deactivate\" }); return undefined; }\n // Observe interaction immediately; deferring activation too would lose a click before the entry microtask.\n scope.dispatch({ kind: \"activate\" });\n // After every effect of this commit, so a modal opening in the same commit (an app-root consent dialog) is\n // already on the stack and blocks entry instead of taking focus away and handing it back later.\n let cancelled = false;\n if (!overlay) queueMicrotask(() => { if (!cancelled) scope.focus(scope.enter(false)); });\n // A screen inside an overlay that activates later enters when the overlay does (see `enter`).\n let nested: Set<NestedScope> | undefined;\n const nestedEntry: NestedScope = { enter: () => scope.enter(false), settle: scope.settle };\n if (!overlay && scope.layer) {\n nested = nestedScopes.get(scope.layer) ?? new Set();\n nestedScopes.set(scope.layer, nested);\n nested.add(nestedEntry);\n }\n const interact = () => { scope.dispatch({ kind: \"interact\" }); };\n const events = [\"pointerdown\", \"click\", \"contextmenu\", \"keydown\", \"wheel\", \"touchstart\"] as const;\n for (const type of events) document.addEventListener(type, interact, true);\n // A modal above closed (after its return focus ran): retry a pending entry.\n const unsubscribe = subscribeModalClose(() => scope.focus(scope.dispatch({ kind: \"unblock\" })));\n return () => {\n cancelled = true;\n nested?.delete(nestedEntry);\n for (const type of events) document.removeEventListener(type, interact, true);\n unsubscribe();\n scope.dispatch({ kind: \"deactivate\" });\n };\n }, [active, overlay, scope, entryFocusEnabled]);\n\n return useMemo(() => ({ registry: scope.registry, layer: scope.layer, enter: scope.enter, enabled: entryFocusEnabled }), [scope, entryFocusEnabled]);\n}\n\nexport function InitialFocusProvider({ scope, children }: { scope: InitialFocusScopeHandle; children: ReactNode }) {\n return <EntryFocusEnabledContext.Provider value={scope.enabled}><ModalLayerContext.Provider value={scope.layer}><InitialFocusContext.Provider value={scope.registry}>{children}</InitialFocusContext.Provider></ModalLayerContext.Provider></EntryFocusEnabledContext.Provider>;\n}\n\n/** Screen scope: focuses the chosen field on mount, never over a field the user is in or under an open modal. */\nexport function InitialFocusScope({ mode, children }: { mode: InitialFocusMode; children: ReactNode }) {\n const scope = useInitialFocusScope({ mode });\n return <InitialFocusProvider scope={scope}>{children}</InitialFocusProvider>;\n}\n\n/** Registers a text field with the nearest scope. `preference` is the field's public `initialFocusTarget`. */\nexport function useInitialFocusTarget(element: RefObject<HTMLElement | null>, preference: boolean | undefined) {\n const registry = useContext(InitialFocusContext);\n // Tree order is fixed at first registration, so changing `preference` later does not move the field to the end.\n const order = useRef<number | null>(null);\n useLayoutEffect(() => {\n if (!registry) return undefined;\n // Only the first registration of this field instance counts as \"appeared\"; a later `preference` change does not.\n const mounted = order.current === null;\n order.current ??= registry.nextOrder();\n return registry.register({\n order: order.current, preference, element: () => element.current,\n // Disabled and read-only fields are never focused on entry.\n focusable: () => { const node = element.current as (HTMLInputElement | HTMLTextAreaElement | null); return !!node && !node.disabled && !node.readOnly; },\n }, mounted);\n }, [registry, preference, element]);\n}\n\n/** Page footer inputs are bottom-anchored, so entry must not open their keyboard (2026-10-18 user request).\n * Keep the boundary through nested screens; a separately opened overlay owns its own focus policy.\n */\nexport function BottomEntryFocusBoundary({ children }: { children: ReactNode }) {\n return <EntryFocusEnabledContext.Provider value={false}><InitialFocusContext.Provider value={null}>{children}</InitialFocusContext.Provider></EntryFocusEnabledContext.Provider>;\n}\n"]}
1
+ {"version":3,"file":"initial-focus.js","sourceRoot":"","sources":["../../src/internal/initial-focus.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport { resolveEntryFocus, type EntryFocusEvent, type EntryFocusPhase, type InitialFocusCandidate, type InitialFocusMode } from \"@hjmds/design-contracts/screen-patterns\";\nimport { createContext, useContext, useEffect, useLayoutEffect, useMemo, useRef, type ReactNode, type RefObject } from \"react\";\nimport { getTopModal, subscribeModalClose, type ActiveModal } from \"../modal.js\";\n\ntype Entry = { order: number; preference: boolean | undefined; element(): HTMLElement | null; focusable(): boolean };\ntype Registry = { nextOrder(): number; register(entry: Entry, mounted: boolean): () => void };\n/** The overlay's own entry on the shared modal stack while it is active (set by `useModalFocus`). */\nexport type ModalLayerRef = { current: ActiveModal | null };\n\n/**\n * Nearest screen/overlay scope that chooses the field focused on entry (rules: screen-patterns `resolveEntryFocus`,\n * shared with Native). Fields register by context, the same model as Native, instead of the scope querying the DOM; a\n * scope with mode \"none\" still owns its fields so they never reach an outer scope.\n */\nconst InitialFocusContext = createContext<Registry | null>(null);\n// A bottom sheet owns this boundary, including ScreenLayout/marked fields nested inside its body.\nconst EntryFocusEnabledContext = createContext(true);\n/** Layer of the enclosing HJM overlay; null on the page itself. A ScreenLayout inside a sheet uses the sheet's. */\nconst ModalLayerContext = createContext<ModalLayerRef | null>(null);\n\ntype NestedScope = { enter(): HTMLElement | null; settle(): void };\n/**\n * Screen scopes rendered inside an HJM overlay, keyed by that overlay's layer. Their fields register with the screen,\n * not the overlay, so the overlay's activation asks them for the entry field instead of focusing its first control\n * over them (BurnTok search: a ScreenLayout in a Sheet left focus on the close button, 2026-10-18).\n */\nconst nestedScopes = new WeakMap<ModalLayerRef, Set<NestedScope>>();\n\n/**\n * Product modals (not on the HJM stack) layered above the scope. A product modal that contains the scope's own fields\n * wraps the screen rather than covering it, so it does not block (BurnTok search overlay, 2026-10-18).\n */\nfunction productModalAbove(fields: readonly HTMLElement[]): boolean {\n return [...document.querySelectorAll('[aria-modal=\"true\"], dialog[open]')]\n .some(modal => !fields.some(field => modal.contains(field)));\n}\n\nfunction isEditable(element: Element | null): boolean {\n return element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement\n || (element instanceof HTMLElement && element.isContentEditable);\n}\n\ntype Candidate = InitialFocusCandidate & { entry: Entry };\nexport type InitialFocusScopeHandle = Readonly<{\n registry: Registry;\n layer: ModalLayerRef | null;\n enabled: boolean;\n /**\n * Overlays only: runs entry when the modal activates and returns the field for `useModalFocus` to focus. `explicit`\n * means the overlay already has an `initialFocusRef`, so entry settles without choosing a field.\n */\n enter(explicit: boolean): HTMLElement | null;\n}>;\n\n/**\n * Screen scopes enter on mount (Web has no enter transition to wait for); overlays pass `layer` and enter through\n * `useModalFocus`. User pointer, key, wheel or touch input while no modal is above the scope ends the entry window.\n */\nexport function useInitialFocusScope({ mode, active = true, layer: ownLayer, enabled = true }: { mode: InitialFocusMode; active?: boolean; layer?: ModalLayerRef; enabled?: boolean }): InitialFocusScopeHandle {\n const inherited = useContext(ModalLayerContext);\n const inheritedEnabled = useContext(EntryFocusEnabledContext);\n // A separate overlay owns its policy; ordinary nested screens inherit their enclosing sheet's policy.\n const entryFocusEnabled = enabled && (ownLayer !== undefined || inheritedEnabled);\n const enabledRef = useRef(entryFocusEnabled); enabledRef.current = entryFocusEnabled;\n const layer = ownLayer ?? inherited;\n const overlay = ownLayer !== undefined;\n const modeRef = useRef(mode); modeRef.current = mode;\n const state = useRef({ phase: \"inactive\" as EntryFocusPhase, entries: new Set<Entry>(), fresh: new Set<Entry>(), counter: 0, flushQueued: false });\n\n const scope = useMemo(() => {\n const s = state.current;\n const blocked = () => {\n const own = layer?.current ?? null;\n // Inside an HJM overlay that is not on the stack yet: its activation runs this scope's entry (`nestedScopes`).\n if (layer !== null && own === null) return true;\n const top = getTopModal();\n if (top) return top !== own;\n // A product's own modal above the page still covers it; overlay content is portaled outside product markup.\n if (layer !== null) return false;\n const fields = [...s.entries].map(entry => entry.element()).filter((element): element is HTMLElement => element !== null);\n return productModalAbove(fields);\n };\n const dispatch = (event: EntryFocusEvent<Candidate> | { kind: \"register\"; entry: Entry }): HTMLElement | null => {\n if (!enabledRef.current) return null;\n const candidates: Candidate[] = [...s.entries].map(entry => ({ entry, order: entry.order, preference: entry.preference, focusable: entry.focusable() }));\n const resolved = event.kind === \"register\" && \"entry\" in event\n ? { kind: \"register\" as const, field: candidates.find(candidate => candidate.entry === event.entry)! }\n : event as EntryFocusEvent<Candidate>;\n const result = resolveEntryFocus(s.phase, resolved, { mode: modeRef.current, candidates, blocked: blocked(), textEntryFocused: isEditable(document.activeElement) });\n s.phase = result.phase;\n return result.target?.entry.element() ?? null;\n };\n const focus = (target: HTMLElement | null) => target?.focus({ preventScroll: true });\n // Fields mounting in one commit are judged together.\n const flush = () => {\n s.flushQueued = false;\n const fresh = [...s.fresh].filter(entry => s.entries.has(entry)).sort((a, b) => a.order - b.order);\n s.fresh.clear();\n const field = fresh.find(entry => entry.preference === true) ?? fresh[0];\n if (field) focus(dispatch({ kind: \"register\", entry: field }));\n };\n const registry: Registry = {\n nextOrder: () => s.counter++,\n register(entry, mounted) {\n s.entries.add(entry);\n if (mounted) { s.fresh.add(entry); if (!s.flushQueued) { s.flushQueued = true; queueMicrotask(flush); } }\n return () => { s.entries.delete(entry); s.fresh.delete(entry); };\n },\n };\n const settle = () => { s.phase = \"settled\"; };\n const enter = (explicit: boolean) => {\n s.fresh.clear();\n const nested = overlay && layer ? [...(nestedScopes.get(layer) ?? [])] : [];\n if (explicit) { settle(); for (const scope of nested) scope.settle(); return null; }\n // A user can open a menu before the deferred entry runs. Never reset their settled entry window.\n if (s.phase === \"settled\") return null;\n if (s.phase === \"inactive\") dispatch({ kind: \"activate\" });\n const own = dispatch({ kind: s.phase === \"open\" ? \"unblock\" : \"enter\" });\n if (own) return own;\n for (const scope of nested) { const target = scope.enter(); if (target) return target; }\n return null;\n };\n return { registry, layer, dispatch, focus, enter, settle };\n }, [layer, overlay]);\n\n useEffect(() => {\n if (!active) { scope.dispatch({ kind: \"deactivate\" }); return undefined; }\n // Observe interaction immediately; deferring activation too would lose a click before the entry microtask.\n scope.dispatch({ kind: \"activate\" });\n // After every effect of this commit, so a modal opening in the same commit (an app-root consent dialog) is\n // already on the stack and blocks entry instead of taking focus away and handing it back later.\n let cancelled = false;\n if (!overlay) queueMicrotask(() => { if (!cancelled) scope.focus(scope.enter(false)); });\n // A screen inside an overlay that activates later enters when the overlay does (see `enter`).\n let nested: Set<NestedScope> | undefined;\n const nestedEntry: NestedScope = { enter: () => scope.enter(false), settle: scope.settle };\n if (!overlay && scope.layer) {\n nested = nestedScopes.get(scope.layer) ?? new Set();\n nestedScopes.set(scope.layer, nested);\n nested.add(nestedEntry);\n }\n const interact = () => { scope.dispatch({ kind: \"interact\" }); };\n const events = [\"pointerdown\", \"click\", \"contextmenu\", \"keydown\", \"wheel\", \"touchstart\"] as const;\n for (const type of events) document.addEventListener(type, interact, true);\n // A modal above closed (after its return focus ran): retry a pending entry.\n const unsubscribe = subscribeModalClose(() => scope.focus(scope.dispatch({ kind: \"unblock\" })));\n return () => {\n cancelled = true;\n nested?.delete(nestedEntry);\n for (const type of events) document.removeEventListener(type, interact, true);\n unsubscribe();\n scope.dispatch({ kind: \"deactivate\" });\n };\n }, [active, overlay, scope, entryFocusEnabled]);\n\n return useMemo(() => ({ registry: scope.registry, layer: scope.layer, enter: scope.enter, enabled: entryFocusEnabled }), [scope, entryFocusEnabled]);\n}\n\nexport function InitialFocusProvider({ scope, children }: { scope: InitialFocusScopeHandle; children: ReactNode }) {\n return <EntryFocusEnabledContext.Provider value={scope.enabled}><ModalLayerContext.Provider value={scope.layer}><InitialFocusContext.Provider value={scope.registry}>{children}</InitialFocusContext.Provider></ModalLayerContext.Provider></EntryFocusEnabledContext.Provider>;\n}\n\n/** Screen scope: focuses the chosen field on mount, never over a field the user is in or under an open modal. */\nexport function InitialFocusScope({ mode, children }: { mode: InitialFocusMode; children: ReactNode }) {\n const scope = useInitialFocusScope({ mode });\n return <InitialFocusProvider scope={scope}>{children}</InitialFocusProvider>;\n}\n\n/** Registers a text field with the nearest scope. `preference` is the field's public `initialFocusTarget`. */\nexport function useInitialFocusTarget(element: RefObject<HTMLElement | null>, preference: boolean | undefined) {\n const registry = useContext(InitialFocusContext);\n // Tree order is fixed at first registration, so changing `preference` later does not move the field to the end.\n const order = useRef<number | null>(null);\n useLayoutEffect(() => {\n if (!registry) return undefined;\n // Only the first registration of this field instance counts as \"appeared\"; a later `preference` change does not.\n const mounted = order.current === null;\n order.current ??= registry.nextOrder();\n return registry.register({\n order: order.current, preference, element: () => element.current,\n // Disabled and read-only fields are never focused on entry.\n focusable: () => { const node = element.current as (HTMLInputElement | HTMLTextAreaElement | null); return !!node && !node.disabled && !node.readOnly; },\n }, mounted);\n }, [registry, preference, element]);\n}\n\n/** Page footer inputs are bottom-anchored, so entry must not open their keyboard (2026-10-18 user request).\n * Keep the boundary through nested screens; a separately opened overlay owns its own focus policy.\n */\nexport function BottomEntryFocusBoundary({ children }: { children: ReactNode }) {\n return <EntryFocusEnabledContext.Provider value={false}><InitialFocusContext.Provider value={null}>{children}</InitialFocusContext.Provider></EntryFocusEnabledContext.Provider>;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"media-album.d.ts","sourceRoot":"","sources":["../../src/internal/media-album.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4E,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAOjH,KAAK,cAAc,GAAG,QAAQ,CAAC;IAC7B,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,gEAAgE;IAChE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAChD,oEAAoE;IACpE,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,6FAA6F;IAC7F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,OAAO,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,CACtC,QAAQ,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,YAAY,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,GACrF,QAAQ,CAAC;IAAE,KAAK,CAAC,EAAE,KAAK,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAC1F,CAAC;AAEF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,CAS5G;AAKD,MAAM,MAAM,yBAAyB,GACjC,QAAQ,CAAC;IAAE,IAAI,EAAE,SAAS,CAAC,CAAC,+DAA+D;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GAC5G,QAAQ,CAAC;IAAE,IAAI,EAAE,OAAO,CAAC,CAAC,mDAAmD;IAAC,KAAK,EAAE,MAAM,CAAC;IAC1F,4DAA4D,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,IAAI,IAAI,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAAC;AAE3H;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,+BAYpE;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,QAAQ,CAAC;IACjG,KAAK,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrE,+GAA+G;IAC/G,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CACnD,CAAC,+BAuBD"}
1
+ {"version":3,"file":"media-album.d.ts","sourceRoot":"","sources":["../../src/internal/media-album.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA4E,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAOjH,KAAK,cAAc,GAAG,QAAQ,CAAC;IAC7B,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,gEAAgE;IAChE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAChD,oEAAoE;IACpE,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,6FAA6F;IAC7F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,OAAO,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,CACtC,QAAQ,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,YAAY,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,GACrF,QAAQ,CAAC;IAAE,KAAK,CAAC,EAAE,KAAK,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAC1F,CAAC;AAEF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,CAS5G;AAKD,MAAM,MAAM,yBAAyB,GACjC,QAAQ,CAAC;IAAE,IAAI,EAAE,SAAS,CAAC,CAAC,+DAA+D;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GAC5G,QAAQ,CAAC;IAAE,IAAI,EAAE,OAAO,CAAC,CAAC,mDAAmD;IAAC,KAAK,EAAE,MAAM,CAAC;IAC1F,4DAA4D,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,IAAI,IAAI,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAAC;AAE3H;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,+BAYpE;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,QAAQ,CAAC;IACjG,KAAK,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrE,+GAA+G;IAC/G,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CACnD,CAAC,+BAuBD"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { createContext, useContext, useLayoutEffect, useState } from "react";
3
4
  import { mediaAlbumRecipe, resolveMediaAlbumIndex, validateMediaAlbum, validateMediaAlbumPageStatus } from "@hjmds/design-contracts/screen-patterns";
@@ -1 +1 @@
1
- {"version":3,"file":"media-album.js","sourceRoot":"","sources":["../../src/internal/media-album.tsx"],"names":[],"mappings":"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","sourcesContent":["import { createContext, useContext, useLayoutEffect, useState, type CSSProperties, type ReactNode } from \"react\";\nimport { mediaAlbumRecipe, resolveMediaAlbumIndex, validateMediaAlbum, validateMediaAlbumPageStatus } from \"@hjmds/design-contracts/screen-patterns\";\nimport { Button, IconButton } from \"../actions.js\";\nimport { Text } from \"../layout.js\";\nimport { Icon } from \"../supplemental-display.js\";\nimport { Spinner } from \"./spinner.js\";\n\ntype MediaAlbumBase = Readonly<{\n /** Number of photos in the set; at least one. */\n count: number;\n /**\n * Draws one page. HJM calls it only for the page on screen, so the product can fetch, authorize and decode that\n * photo alone instead of mounting every image in the set.\n */\n renderPage(index: number): ReactNode;\n /** Localized accessible name of a page, e.g. \"Photo 2 of 5\". */\n pageLabel(index: number, count: number): string;\n /** Localized accessible names of the previous/next icon buttons. */\n previousLabel: string;\n nextLabel: string;\n /** Page frame width / height. Defaults to `mediaAlbumRecipe.defaultAspectRatio` (square). */\n aspectRatio?: number;\n /**\n * Opens the shown page (viewer); without it the page is a static image. While the page renders a\n * `MediaAlbumPageStatus` it is not an image yet, so it does not open.\n */\n onPress?(index: number): void;\n}>;\n\n/**\n * Paged photo set (2026-10-18). Products own image sources, authorization and the viewer; HJM owns the frame,\n * the counter row and which page is mounted. Controlled with `index` + `onIndexChange`, or uncontrolled from\n * `defaultIndex`.\n */\nexport type MediaAlbum = MediaAlbumBase & (\n | Readonly<{ index: number; onIndexChange(index: number): void; defaultIndex?: never }>\n | Readonly<{ index?: never; defaultIndex?: number; onIndexChange?(index: number): void }>\n);\n\n/**\n * Hosts keep the page state so every copy of the album they render (the message and its hold-menu preview) shows\n * the same page. Called unconditionally; `album` may be absent.\n */\nexport function useMediaAlbumIndex(album: MediaAlbum | undefined): readonly [number, (index: number) => void] {\n const [own, setOwn] = useState(album?.defaultIndex ?? 0);\n if (!album) return [0, setOwn];\n if (album.index !== undefined) {\n validateMediaAlbum(album.count, album.index);\n return [album.index, album.onIndexChange];\n }\n const current = resolveMediaAlbumIndex(album.count, own);\n return [current, (next: number) => { setOwn(next); album.onIndexChange?.(next); }];\n}\n\n/** Lets a page's status tell its frame that the page is not an image yet. */\nconst MediaAlbumPageContext = createContext<((shown: boolean) => void) | null>(null);\n\nexport type MediaAlbumPageStatusProps =\n | Readonly<{ kind: \"loading\"; /** Localized name of what is loading, e.g. \"Loading photo\". */ label: string }>\n | Readonly<{ kind: \"error\"; /** Localized failure text, shown and announced. */ label: string;\n /** Retry button; label and action come from the product. */ retry?: Readonly<{ label: string; onPress(): void }> }>;\n\n/**\n * Loading or failed page of a `mediaAlbum` (2026-10-18 Utilverse). Return it from `renderPage` (or the component it\n * renders) while the photo is not available. While it is shown the frame drops its image name and open action, so\n * the spinner's name, the failure text and the retry button are reachable by screen readers and pointer instead of\n * being swallowed by one accessible image. Centered in the frame (VQ-09).\n */\nexport function MediaAlbumPageStatus(props: MediaAlbumPageStatusProps) {\n validateMediaAlbumPageStatus(props.kind, props.label);\n const report = useContext(MediaAlbumPageContext);\n // Layout effect: the frame switches its semantics before the browser paints, so the status never shows inside\n // an image or button for a frame.\n useLayoutEffect(() => { report?.(true); return () => report?.(false); }, [report]);\n const s = mediaAlbumRecipe.pageStatus;\n return <div className=\"hjm-media-album__status\" style={{ gap: s.gap, padding: s.padding }}>\n {props.kind === \"loading\" ? <Spinner label={props.label} />\n : <><Text as=\"p\" role=\"alert\" variant={s.textVariant} tone=\"muted\">{props.label}</Text>\n {props.retry ? <Button type=\"button\" tone={s.retryTone} size={s.retrySize} onClick={props.retry.onPress}>{props.retry.label}</Button> : null}</>}\n </div>;\n}\n\nexport function MediaAlbumView({ album, index, onIndexChange, width, radius, className }: Readonly<{\n album: MediaAlbum; index: number; onIndexChange(index: number): void;\n /** Host media width (chat `mediaWidth`, comment `mediaMaxWidth`); the album never grows past its container. */\n width: number; radius: number; className?: string;\n}>) {\n validateMediaAlbum(album.count, index);\n const [statusShown, setStatusShown] = useState(false);\n const label = album.pageLabel(index, album.count);\n const frame = { aspectRatio: album.aspectRatio ?? mediaAlbumRecipe.defaultAspectRatio, borderRadius: radius } as CSSProperties;\n const page = album.renderPage(index);\n const opens = album.onPress !== undefined && !statusShown;\n // The frame element and the page wrapper stay the same elements in every state, so the product's page (which owns\n // the fetch) is never remounted when its status comes and goes. Only roles and the open overlay change.\n return <div className={[\"hjm-media-album\", className].filter(Boolean).join(\" \")} style={{ inlineSize: width, gap: mediaAlbumRecipe.controlGap }}>\n <div className=\"hjm-media-album__page\" style={frame} role={statusShown || album.onPress ? undefined : \"img\"} aria-label={statusShown || album.onPress ? undefined : label}>\n <div className=\"hjm-media-album__content\" aria-hidden={opens || undefined}>\n <MediaAlbumPageContext.Provider value={setStatusShown}>{page}</MediaAlbumPageContext.Provider>\n </div>\n {opens ? <button type=\"button\" className=\"hjm-media-album__open\" aria-label={label} onClick={() => album.onPress?.(index)} /> : null}\n </div>\n {album.count > 1 ? <div className=\"hjm-media-album__controls\">\n {/* Same counter presentation as CarouselMotion navigation=\"counter\"; logical chevrons mirror in RTL. */}\n <IconButton label={album.previousLabel} tone=\"ghost\" size={mediaAlbumRecipe.controlSize} edge=\"start\" disabled={index === 0} onClick={() => onIndexChange(index - 1)}><Icon name=\"chevronStart\" /></IconButton>\n <Text variant=\"caption\" aria-live=\"polite\">{index + 1}/{album.count}</Text>\n <IconButton label={album.nextLabel} tone=\"ghost\" size={mediaAlbumRecipe.controlSize} edge=\"end\" disabled={index === album.count - 1} onClick={() => onIndexChange(index + 1)}><Icon name=\"chevronEnd\" /></IconButton>\n </div> : null}\n </div>;\n}\n"]}
1
+ {"version":3,"file":"media-album.js","sourceRoot":"","sources":["../../src/internal/media-album.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,QAAQ,EAAsC,MAAM,OAAO,CAAC;AACjH,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAC;AACrJ,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAkCvC;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAA6B;IAC9D,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,EAAE,YAAY,IAAI,CAAC,CAAC,CAAC;IACzD,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC9B,kBAAkB,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7C,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,OAAO,GAAG,sBAAsB,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACzD,OAAO,CAAC,OAAO,EAAE,CAAC,IAAY,EAAE,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrF,CAAC;AAED,6EAA6E;AAC7E,MAAM,qBAAqB,GAAG,aAAa,CAAoC,IAAI,CAAC,CAAC;AAOrF;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAgC;IACnE,4BAA4B,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,UAAU,CAAC,qBAAqB,CAAC,CAAC;IACjD,8GAA8G;IAC9G,kCAAkC;IAClC,eAAe,CAAC,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACnF,MAAM,CAAC,GAAG,gBAAgB,CAAC,UAAU,CAAC;IACtC,OAAO,cAAK,SAAS,EAAC,yBAAyB,EAAC,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,YACtF,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAC,OAAO,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAI;YACzD,CAAC,CAAC,8BAAE,KAAC,IAAI,IAAC,EAAE,EAAC,GAAG,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAE,CAAC,CAAC,WAAW,EAAE,IAAI,EAAC,OAAO,YAAE,KAAK,CAAC,KAAK,GAAQ,EACpF,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO,YAAG,KAAK,CAAC,KAAK,CAAC,KAAK,GAAU,CAAC,CAAC,CAAC,IAAI,IAAI,GAChJ,CAAC;AACT,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAIpF;IACA,kBAAkB,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACvC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,gBAAgB,CAAC,kBAAkB,EAAE,YAAY,EAAE,MAAM,EAAmB,CAAC;IAC/H,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,WAAW,CAAC;IAC1D,kHAAkH;IAClH,wGAAwG;IACxG,OAAO,eAAK,SAAS,EAAE,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,gBAAgB,CAAC,UAAU,EAAE,aAC7I,eAAK,SAAS,EAAC,uBAAuB,EAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,gBAAc,WAAW,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,aACvK,cAAK,SAAS,EAAC,0BAA0B,iBAAc,KAAK,IAAI,SAAS,YACvE,KAAC,qBAAqB,CAAC,QAAQ,IAAC,KAAK,EAAE,cAAc,YAAG,IAAI,GAAkC,GAC1F,EACL,KAAK,CAAC,CAAC,CAAC,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAC,uBAAuB,gBAAa,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAI,CAAC,CAAC,CAAC,IAAI,IAChI,EACL,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,eAAK,SAAS,EAAC,2BAA2B,aAE3D,KAAC,UAAU,IAAC,KAAK,EAAE,KAAK,CAAC,aAAa,EAAE,IAAI,EAAC,OAAO,EAAC,IAAI,EAAE,gBAAgB,CAAC,WAAW,EAAE,IAAI,EAAC,OAAO,EAAC,QAAQ,EAAE,KAAK,KAAK,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,GAAG,CAAC,CAAC,YAAE,KAAC,IAAI,IAAC,IAAI,EAAC,cAAc,GAAG,GAAa,EAC/M,MAAC,IAAI,IAAC,OAAO,EAAC,SAAS,eAAW,QAAQ,aAAE,KAAK,GAAG,CAAC,OAAG,KAAK,CAAC,KAAK,IAAQ,EAC3E,KAAC,UAAU,IAAC,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,EAAC,OAAO,EAAC,IAAI,EAAE,gBAAgB,CAAC,WAAW,EAAE,IAAI,EAAC,KAAK,EAAC,QAAQ,EAAE,KAAK,KAAK,KAAK,CAAC,KAAK,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,GAAG,CAAC,CAAC,YAAE,KAAC,IAAI,IAAC,IAAI,EAAC,YAAY,GAAG,GAAa,IACjN,CAAC,CAAC,CAAC,IAAI,IACT,CAAC;AACT,CAAC","sourcesContent":["\"use client\";\n\nimport { createContext, useContext, useLayoutEffect, useState, type CSSProperties, type ReactNode } from \"react\";\nimport { mediaAlbumRecipe, resolveMediaAlbumIndex, validateMediaAlbum, validateMediaAlbumPageStatus } from \"@hjmds/design-contracts/screen-patterns\";\nimport { Button, IconButton } from \"../actions.js\";\nimport { Text } from \"../layout.js\";\nimport { Icon } from \"../supplemental-display.js\";\nimport { Spinner } from \"./spinner.js\";\n\ntype MediaAlbumBase = Readonly<{\n /** Number of photos in the set; at least one. */\n count: number;\n /**\n * Draws one page. HJM calls it only for the page on screen, so the product can fetch, authorize and decode that\n * photo alone instead of mounting every image in the set.\n */\n renderPage(index: number): ReactNode;\n /** Localized accessible name of a page, e.g. \"Photo 2 of 5\". */\n pageLabel(index: number, count: number): string;\n /** Localized accessible names of the previous/next icon buttons. */\n previousLabel: string;\n nextLabel: string;\n /** Page frame width / height. Defaults to `mediaAlbumRecipe.defaultAspectRatio` (square). */\n aspectRatio?: number;\n /**\n * Opens the shown page (viewer); without it the page is a static image. While the page renders a\n * `MediaAlbumPageStatus` it is not an image yet, so it does not open.\n */\n onPress?(index: number): void;\n}>;\n\n/**\n * Paged photo set (2026-10-18). Products own image sources, authorization and the viewer; HJM owns the frame,\n * the counter row and which page is mounted. Controlled with `index` + `onIndexChange`, or uncontrolled from\n * `defaultIndex`.\n */\nexport type MediaAlbum = MediaAlbumBase & (\n | Readonly<{ index: number; onIndexChange(index: number): void; defaultIndex?: never }>\n | Readonly<{ index?: never; defaultIndex?: number; onIndexChange?(index: number): void }>\n);\n\n/**\n * Hosts keep the page state so every copy of the album they render (the message and its hold-menu preview) shows\n * the same page. Called unconditionally; `album` may be absent.\n */\nexport function useMediaAlbumIndex(album: MediaAlbum | undefined): readonly [number, (index: number) => void] {\n const [own, setOwn] = useState(album?.defaultIndex ?? 0);\n if (!album) return [0, setOwn];\n if (album.index !== undefined) {\n validateMediaAlbum(album.count, album.index);\n return [album.index, album.onIndexChange];\n }\n const current = resolveMediaAlbumIndex(album.count, own);\n return [current, (next: number) => { setOwn(next); album.onIndexChange?.(next); }];\n}\n\n/** Lets a page's status tell its frame that the page is not an image yet. */\nconst MediaAlbumPageContext = createContext<((shown: boolean) => void) | null>(null);\n\nexport type MediaAlbumPageStatusProps =\n | Readonly<{ kind: \"loading\"; /** Localized name of what is loading, e.g. \"Loading photo\". */ label: string }>\n | Readonly<{ kind: \"error\"; /** Localized failure text, shown and announced. */ label: string;\n /** Retry button; label and action come from the product. */ retry?: Readonly<{ label: string; onPress(): void }> }>;\n\n/**\n * Loading or failed page of a `mediaAlbum` (2026-10-18 Utilverse). Return it from `renderPage` (or the component it\n * renders) while the photo is not available. While it is shown the frame drops its image name and open action, so\n * the spinner's name, the failure text and the retry button are reachable by screen readers and pointer instead of\n * being swallowed by one accessible image. Centered in the frame (VQ-09).\n */\nexport function MediaAlbumPageStatus(props: MediaAlbumPageStatusProps) {\n validateMediaAlbumPageStatus(props.kind, props.label);\n const report = useContext(MediaAlbumPageContext);\n // Layout effect: the frame switches its semantics before the browser paints, so the status never shows inside\n // an image or button for a frame.\n useLayoutEffect(() => { report?.(true); return () => report?.(false); }, [report]);\n const s = mediaAlbumRecipe.pageStatus;\n return <div className=\"hjm-media-album__status\" style={{ gap: s.gap, padding: s.padding }}>\n {props.kind === \"loading\" ? <Spinner label={props.label} />\n : <><Text as=\"p\" role=\"alert\" variant={s.textVariant} tone=\"muted\">{props.label}</Text>\n {props.retry ? <Button type=\"button\" tone={s.retryTone} size={s.retrySize} onClick={props.retry.onPress}>{props.retry.label}</Button> : null}</>}\n </div>;\n}\n\nexport function MediaAlbumView({ album, index, onIndexChange, width, radius, className }: Readonly<{\n album: MediaAlbum; index: number; onIndexChange(index: number): void;\n /** Host media width (chat `mediaWidth`, comment `mediaMaxWidth`); the album never grows past its container. */\n width: number; radius: number; className?: string;\n}>) {\n validateMediaAlbum(album.count, index);\n const [statusShown, setStatusShown] = useState(false);\n const label = album.pageLabel(index, album.count);\n const frame = { aspectRatio: album.aspectRatio ?? mediaAlbumRecipe.defaultAspectRatio, borderRadius: radius } as CSSProperties;\n const page = album.renderPage(index);\n const opens = album.onPress !== undefined && !statusShown;\n // The frame element and the page wrapper stay the same elements in every state, so the product's page (which owns\n // the fetch) is never remounted when its status comes and goes. Only roles and the open overlay change.\n return <div className={[\"hjm-media-album\", className].filter(Boolean).join(\" \")} style={{ inlineSize: width, gap: mediaAlbumRecipe.controlGap }}>\n <div className=\"hjm-media-album__page\" style={frame} role={statusShown || album.onPress ? undefined : \"img\"} aria-label={statusShown || album.onPress ? undefined : label}>\n <div className=\"hjm-media-album__content\" aria-hidden={opens || undefined}>\n <MediaAlbumPageContext.Provider value={setStatusShown}>{page}</MediaAlbumPageContext.Provider>\n </div>\n {opens ? <button type=\"button\" className=\"hjm-media-album__open\" aria-label={label} onClick={() => album.onPress?.(index)} /> : null}\n </div>\n {album.count > 1 ? <div className=\"hjm-media-album__controls\">\n {/* Same counter presentation as CarouselMotion navigation=\"counter\"; logical chevrons mirror in RTL. */}\n <IconButton label={album.previousLabel} tone=\"ghost\" size={mediaAlbumRecipe.controlSize} edge=\"start\" disabled={index === 0} onClick={() => onIndexChange(index - 1)}><Icon name=\"chevronStart\" /></IconButton>\n <Text variant=\"caption\" aria-live=\"polite\">{index + 1}/{album.count}</Text>\n <IconButton label={album.nextLabel} tone=\"ghost\" size={mediaAlbumRecipe.controlSize} edge=\"end\" disabled={index === album.count - 1} onClick={() => onIndexChange(index + 1)}><Icon name=\"chevronEnd\" /></IconButton>\n </div> : null}\n </div>;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"message-reactions.d.ts","sourceRoot":"","sources":["../../src/internal/message-reactions.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoD,KAAK,SAAS,EAAE,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AACnG,OAAO,EAA0C,KAAK,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAC/H,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAGpE,OAAO,EAAkB,KAAK,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAEjF,+FAA+F;AAC/F,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAAC,OAAO,IAAI,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,iDAAiD;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC/L,uGAAuG,CAAC,IAAI,CAAC,EAAE,YAAY,CAAA;CAAE,CAAC,CAAC;AACjI,iFAAiF;AACjF,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAAE,IAAI,IAAI,IAAI,CAAA;CAAE,CAAC,CAAC;AAChE,KAAK,KAAK,GAAG,mBAAmB,GAAG,QAAQ,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAC,MAAM,CAAC;QAAA,OAAO,IAAG,IAAI,CAAC;QAAA,QAAQ,CAAC,EAAC,OAAO,CAAA;KAAC,CAAC,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAC;IAAC,kBAAkB,CAAC,EAAC,OAAO,CAAC,CAAC,gEAAgE;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACrR,WAAW,CAAC,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAC,MAAM,CAAC;QAAA,OAAO,IAAG,IAAI,CAAC;QAAA,QAAQ,CAAC,EAAC,OAAO,CAAC;QAAA,IAAI,CAAC,EAAC,SAAS,CAAA;KAAC,CAAC,CAAC;IACxF,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC3C,6FAA6F;IAC7F,YAAY,CAAC,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAC,MAAM,CAAC;QAAA,OAAO,IAAG,IAAI,CAAC;QAAA,QAAQ,CAAC,EAAC,OAAO,CAAC;QAAA,IAAI,CAAC,EAAC,SAAS,CAAA;KAAC,CAAC,CAAC;IACzF,OAAO,CAAC,EAAE,GAAG,CAAC,sBAAsB,CAAC,CAAA;CAAE,CAAC,CAAC;AAC3C,yGAAyG;AACzG,wBAAgB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,kBAAwB,EAAE,gBAA6C,EAAE,WAAW,EAAE,SAAS,EAAE,WAAgB,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,EAAE,KAAK,+BAwChO;AAED,mFAAmF;AACnF,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,QAAQ,CAAC;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,SAAS,CAAC,CAEpI;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,QAAQ,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC,uBAAuB,GAAG,QAAQ,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,OAAO,IAAI,IAAI,CAAA;CAAE,CAAC,+BAO5P;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,QAAQ,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC,uBAAuB,GAAG,QAAQ,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC,EAAE,CAAA;CAAE,CAAC,+BAMhK"}
1
+ {"version":3,"file":"message-reactions.d.ts","sourceRoot":"","sources":["../../src/internal/message-reactions.tsx"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { useEffect, useImperativeHandle, useRef, useState } from "react";
3
4
  import { chatMessageRecipe, screenPatternRecipe } from "@hjmds/design-contracts/screen-patterns";
@@ -1 +1 @@
1
- {"version":3,"file":"message-reactions.js","sourceRoot":"","sources":["../../src/internal/message-reactions.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useImperativeHandle, useRef, useState, type ReactNode, type Ref } from \"react\";\nimport { chatMessageRecipe, screenPatternRecipe, type ChatReactionSummaryItem } from \"@hjmds/design-contracts/screen-patterns\";\nimport type { MenuItemTone } from \"@hjmds/design-contracts/recipes\";\nimport { Text, VisuallyHidden } from \"../layout.js\";\nimport { Popover } from \"../popover.js\";\nimport { ReactionPicker, type ReactionPickerProps } from \"../reaction-picker.js\";\n\n/** One row of the hold menu. Products supply copy and icons; HJM owns order, size and tone. */\nexport type MessageMenuAction = Readonly<{ id: string; label: string; icon?: ReactNode; onPress(): void; disabled?: boolean; /** Shows › for rows that open a further list. */ submenu?: boolean;\n /** Same vocabulary as Menu items: `danger` for destructive rows such as delete (default `neutral`). */ tone?: MenuItemTone }>;\n/** Lets the owning message open the same hold menu from its reaction summary. */\nexport type MessageReactionsHandle = Readonly<{ open(): void }>;\ntype Props = ReactionPickerProps & Readonly<{ closeLabel: string; menuAction?: Readonly<{label:string;onPress():void;disabled?:boolean}>; children: ReactNode; interactiveContent?:boolean; /** Comments reuse the hold menu without chat bubble styling. */ triggerClassName?: string;\n replyAction?: Readonly<{label:string;onPress():void;disabled?:boolean;icon?:ReactNode}>;\n /** Shown above the actions, e.g. the exact send time that a run only shows once. */\n menuTitle?: string;\n menuActions?: readonly MessageMenuAction[];\n /** Always last and in the danger tone, matching the measured reference menu (2026-10-16). */\n reportAction?: Readonly<{label:string;onPress():void;disabled?:boolean;icon?:ReactNode}>;\n menuRef?: Ref<MessageReactionsHandle> }>;\n/** Chat-specific trigger translation; Popover retains collision, focus, Escape and outside dismissal. */\nexport function MessageReactions({ children, closeLabel, menuAction, interactiveContent=false, triggerClassName = \"hjm-chat-message__bubble\", replyAction, menuTitle, menuActions = [], reportAction, menuRef, ...picker }: Props) {\n // Reply leads and report trails; legacy single menuAction keeps its place before report.\n const rows: MessageMenuAction[] = [\n ...(replyAction ? [{ id: \"reply\", ...replyAction }] : []),\n ...menuActions,\n ...(menuAction ? [{ id: \"menu\", ...menuAction }] : []),\n ...(reportAction ? [{ id: \"report\", ...reportAction, tone: \"danger\" as const }] : []),\n ];\n const [open, setOpen] = useState(false);\n const press = useRef<{ timer: ReturnType<typeof setTimeout>; x: number; y: number } | null>(null);\n const held = useRef(false);\n const cancel = () => { if (press.current) clearTimeout(press.current.timer); press.current = null; };\n useEffect(() => () => { if (press.current) clearTimeout(press.current.timer); }, []);\n useEffect(() => { if (picker.disabled) { cancel(); setOpen(false); } }, [picker.disabled]);\n useImperativeHandle(menuRef, () => ({ open: () => { if (!picker.disabled) setOpen(true); } }), [picker.disabled]);\n return <Popover open={open && !picker.disabled} onOpenChange={(next) => { if (!next) setOpen(false); }} title={picker.label} closeLabel={closeLabel}\n descriptor={{ placement: \"top\", align: \"start\" }} className=\"hjm-message-reactions\" trigger={<div\n className={triggerClassName} tabIndex={picker.disabled ? -1 : 0} role={interactiveContent?\"group\":\"button\"} aria-label={picker.label} aria-disabled={picker.disabled}\n onContextMenu={event => { event.preventDefault(); cancel(); if (!picker.disabled) setOpen(true); }}\n // Only the bubble itself opens reactions: with interactiveContent, Enter/Space on a nested\n // link or button must keep its native activation instead of being swallowed here.\n onKeyDown={event => { if (event.target === event.currentTarget && (event.key === \"Enter\" || event.key === \" \") && !picker.disabled) { event.preventDefault(); setOpen(true); } }}\n onPointerDown={event => {\n if (picker.disabled || event.button !== 0 || (event.target as HTMLElement).closest(\"button,a,input,textarea\")) return;\n cancel(); held.current = false;\n const { clientX: x, clientY: y } = event;\n press.current = { x, y, timer: setTimeout(() => { held.current = true; press.current = null; setOpen(true); }, screenPatternRecipe.reactionHoldMs) };\n }}\n onPointerMove={event => { const start = press.current; if (start && Math.hypot(event.clientX - start.x, event.clientY - start.y) > screenPatternRecipe.reactionMoveTolerance) cancel(); }}\n onPointerCancel={cancel} onPointerLeave={cancel} onPointerUp={cancel}\n onClickCapture={event => { if (held.current) { event.preventDefault(); event.stopPropagation(); held.current = false; } }}\n >{children}</div>}>\n {/* Action-only menus (comments, 2026-10-16 reference) pass no options and show no strip. */}\n {picker.options.length ? <ReactionPicker {...picker} layout=\"strip\" onValueChange={value => { picker.onValueChange(value); setOpen(false); }} /> : null}\n {menuTitle || rows.length ? <div className=\"hjm-message-menu\">\n {menuTitle ? <Text variant=\"caption\" tone=\"muted\" className=\"hjm-message-menu__title\">{menuTitle}</Text> : null}\n {rows.map(row => <button key={row.id} type=\"button\" className=\"hjm-message-menu__item\" data-tone={row.tone === \"danger\" ? \"danger\" : undefined} disabled={row.disabled} onClick={() => { setOpen(false); row.onPress(); }}>\n {row.icon ? <span className=\"hjm-message-menu__icon\" aria-hidden=\"true\">{row.icon}</span> : null}<span className=\"hjm-message-menu__label\">{row.label}</span>{row.submenu ? <span className=\"hjm-message-menu__chevron\" aria-hidden=\"true\">›</span> : null}</button>)}\n </div> : null}\n </Popover>;\n}\n\n/** ChatMessage strips its summary before spreading the rest into the hold menu. */\nexport function omitReactionSummary<T extends Readonly<{ summary?: unknown }>>({ summary: _summary, ...rest }: T): Omit<T, \"summary\"> {\n return rest;\n}\n\n/**\n * Current reactions as one button beside the time; pressing it opens the hold menu (the press target and its name\n * are the whole pill, so per-emoji parts are hidden from assistive tech). The pill shows the brand border when the\n * reader's own reaction is among the items.\n */\nexport function ReactionSummaryButton({ label, items, selected, disabled, onPress }: Readonly<{ label: string; items: readonly (ChatReactionSummaryItem & Readonly<{ showCount: boolean }>)[]; selected: string | null; disabled: boolean; onPress(): void }>) {\n const r = chatMessageRecipe.reactionSummary;\n const mine = items.some(item => item.id === selected);\n return <button type=\"button\" className=\"hjm-chat-message__reaction-summary\" aria-label={label} disabled={disabled} data-selected={mine || undefined} onClick={onPress}\n style={{ minBlockSize: r.minHeight, paddingInline: r.paddingInline, gap: r.itemGap }}>\n {items.map(item => <span key={item.id} aria-hidden=\"true\" style={{ display: \"inline-flex\", alignItems: \"center\", gap: r.emojiGap }}><span>{item.emoji}</span>{item.showCount ? <Text as=\"span\" variant=\"caption\">{item.count}</Text> : null}</span>)}\n </button>;\n}\n\n/**\n * Read-only counts (`summary.readOnly`, 2026-10-18 Utilverse guests who cannot react): the same place and items as\n * the pill, as plain caption text without the pill surface, so it is neither drawn nor announced as a control. The\n * product label is the text screen readers read; the drawn emoji and numbers are hidden from them.\n */\nexport function ReactionSummaryText({ label, items }: Readonly<{ label: string; items: readonly (ChatReactionSummaryItem & Readonly<{ showCount: boolean }>)[] }>) {\n const r = chatMessageRecipe.reactionSummary;\n return <span className=\"hjm-chat-message__reaction-counts\" style={{ minBlockSize: r.minHeight, gap: r.itemGap }}>\n <VisuallyHidden>{label}</VisuallyHidden>\n {items.map(item => <span key={item.id} aria-hidden=\"true\" style={{ display: \"inline-flex\", alignItems: \"center\", gap: r.emojiGap }}><span>{item.emoji}</span>{item.showCount ? <Text as=\"span\" variant=\"caption\" tone=\"muted\">{item.count}</Text> : null}</span>)}\n </span>;\n}\n"]}
1
+ {"version":3,"file":"message-reactions.js","sourceRoot":"","sources":["../../src/internal/message-reactions.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport { useEffect, useImperativeHandle, useRef, useState, type ReactNode, type Ref } from \"react\";\nimport { chatMessageRecipe, screenPatternRecipe, type ChatReactionSummaryItem } from \"@hjmds/design-contracts/screen-patterns\";\nimport type { MenuItemTone } from \"@hjmds/design-contracts/recipes\";\nimport { Text, VisuallyHidden } from \"../layout.js\";\nimport { Popover } from \"../popover.js\";\nimport { ReactionPicker, type ReactionPickerProps } from \"../reaction-picker.js\";\n\n/** One row of the hold menu. Products supply copy and icons; HJM owns order, size and tone. */\nexport type MessageMenuAction = Readonly<{ id: string; label: string; icon?: ReactNode; onPress(): void; disabled?: boolean; /** Shows › for rows that open a further list. */ submenu?: boolean;\n /** Same vocabulary as Menu items: `danger` for destructive rows such as delete (default `neutral`). */ tone?: MenuItemTone }>;\n/** Lets the owning message open the same hold menu from its reaction summary. */\nexport type MessageReactionsHandle = Readonly<{ open(): void }>;\ntype Props = ReactionPickerProps & Readonly<{ closeLabel: string; menuAction?: Readonly<{label:string;onPress():void;disabled?:boolean}>; children: ReactNode; interactiveContent?:boolean; /** Comments reuse the hold menu without chat bubble styling. */ triggerClassName?: string;\n replyAction?: Readonly<{label:string;onPress():void;disabled?:boolean;icon?:ReactNode}>;\n /** Shown above the actions, e.g. the exact send time that a run only shows once. */\n menuTitle?: string;\n menuActions?: readonly MessageMenuAction[];\n /** Always last and in the danger tone, matching the measured reference menu (2026-10-16). */\n reportAction?: Readonly<{label:string;onPress():void;disabled?:boolean;icon?:ReactNode}>;\n menuRef?: Ref<MessageReactionsHandle> }>;\n/** Chat-specific trigger translation; Popover retains collision, focus, Escape and outside dismissal. */\nexport function MessageReactions({ children, closeLabel, menuAction, interactiveContent=false, triggerClassName = \"hjm-chat-message__bubble\", replyAction, menuTitle, menuActions = [], reportAction, menuRef, ...picker }: Props) {\n // Reply leads and report trails; legacy single menuAction keeps its place before report.\n const rows: MessageMenuAction[] = [\n ...(replyAction ? [{ id: \"reply\", ...replyAction }] : []),\n ...menuActions,\n ...(menuAction ? [{ id: \"menu\", ...menuAction }] : []),\n ...(reportAction ? [{ id: \"report\", ...reportAction, tone: \"danger\" as const }] : []),\n ];\n const [open, setOpen] = useState(false);\n const press = useRef<{ timer: ReturnType<typeof setTimeout>; x: number; y: number } | null>(null);\n const held = useRef(false);\n const cancel = () => { if (press.current) clearTimeout(press.current.timer); press.current = null; };\n useEffect(() => () => { if (press.current) clearTimeout(press.current.timer); }, []);\n useEffect(() => { if (picker.disabled) { cancel(); setOpen(false); } }, [picker.disabled]);\n useImperativeHandle(menuRef, () => ({ open: () => { if (!picker.disabled) setOpen(true); } }), [picker.disabled]);\n return <Popover open={open && !picker.disabled} onOpenChange={(next) => { if (!next) setOpen(false); }} title={picker.label} closeLabel={closeLabel}\n descriptor={{ placement: \"top\", align: \"start\" }} className=\"hjm-message-reactions\" trigger={<div\n className={triggerClassName} tabIndex={picker.disabled ? -1 : 0} role={interactiveContent?\"group\":\"button\"} aria-label={picker.label} aria-disabled={picker.disabled}\n onContextMenu={event => { event.preventDefault(); cancel(); if (!picker.disabled) setOpen(true); }}\n // Only the bubble itself opens reactions: with interactiveContent, Enter/Space on a nested\n // link or button must keep its native activation instead of being swallowed here.\n onKeyDown={event => { if (event.target === event.currentTarget && (event.key === \"Enter\" || event.key === \" \") && !picker.disabled) { event.preventDefault(); setOpen(true); } }}\n onPointerDown={event => {\n if (picker.disabled || event.button !== 0 || (event.target as HTMLElement).closest(\"button,a,input,textarea\")) return;\n cancel(); held.current = false;\n const { clientX: x, clientY: y } = event;\n press.current = { x, y, timer: setTimeout(() => { held.current = true; press.current = null; setOpen(true); }, screenPatternRecipe.reactionHoldMs) };\n }}\n onPointerMove={event => { const start = press.current; if (start && Math.hypot(event.clientX - start.x, event.clientY - start.y) > screenPatternRecipe.reactionMoveTolerance) cancel(); }}\n onPointerCancel={cancel} onPointerLeave={cancel} onPointerUp={cancel}\n onClickCapture={event => { if (held.current) { event.preventDefault(); event.stopPropagation(); held.current = false; } }}\n >{children}</div>}>\n {/* Action-only menus (comments, 2026-10-16 reference) pass no options and show no strip. */}\n {picker.options.length ? <ReactionPicker {...picker} layout=\"strip\" onValueChange={value => { picker.onValueChange(value); setOpen(false); }} /> : null}\n {menuTitle || rows.length ? <div className=\"hjm-message-menu\">\n {menuTitle ? <Text variant=\"caption\" tone=\"muted\" className=\"hjm-message-menu__title\">{menuTitle}</Text> : null}\n {rows.map(row => <button key={row.id} type=\"button\" className=\"hjm-message-menu__item\" data-tone={row.tone === \"danger\" ? \"danger\" : undefined} disabled={row.disabled} onClick={() => { setOpen(false); row.onPress(); }}>\n {row.icon ? <span className=\"hjm-message-menu__icon\" aria-hidden=\"true\">{row.icon}</span> : null}<span className=\"hjm-message-menu__label\">{row.label}</span>{row.submenu ? <span className=\"hjm-message-menu__chevron\" aria-hidden=\"true\">›</span> : null}</button>)}\n </div> : null}\n </Popover>;\n}\n\n/** ChatMessage strips its summary before spreading the rest into the hold menu. */\nexport function omitReactionSummary<T extends Readonly<{ summary?: unknown }>>({ summary: _summary, ...rest }: T): Omit<T, \"summary\"> {\n return rest;\n}\n\n/**\n * Current reactions as one button beside the time; pressing it opens the hold menu (the press target and its name\n * are the whole pill, so per-emoji parts are hidden from assistive tech). The pill shows the brand border when the\n * reader's own reaction is among the items.\n */\nexport function ReactionSummaryButton({ label, items, selected, disabled, onPress }: Readonly<{ label: string; items: readonly (ChatReactionSummaryItem & Readonly<{ showCount: boolean }>)[]; selected: string | null; disabled: boolean; onPress(): void }>) {\n const r = chatMessageRecipe.reactionSummary;\n const mine = items.some(item => item.id === selected);\n return <button type=\"button\" className=\"hjm-chat-message__reaction-summary\" aria-label={label} disabled={disabled} data-selected={mine || undefined} onClick={onPress}\n style={{ minBlockSize: r.minHeight, paddingInline: r.paddingInline, gap: r.itemGap }}>\n {items.map(item => <span key={item.id} aria-hidden=\"true\" style={{ display: \"inline-flex\", alignItems: \"center\", gap: r.emojiGap }}><span>{item.emoji}</span>{item.showCount ? <Text as=\"span\" variant=\"caption\">{item.count}</Text> : null}</span>)}\n </button>;\n}\n\n/**\n * Read-only counts (`summary.readOnly`, 2026-10-18 Utilverse guests who cannot react): the same place and items as\n * the pill, as plain caption text without the pill surface, so it is neither drawn nor announced as a control. The\n * product label is the text screen readers read; the drawn emoji and numbers are hidden from them.\n */\nexport function ReactionSummaryText({ label, items }: Readonly<{ label: string; items: readonly (ChatReactionSummaryItem & Readonly<{ showCount: boolean }>)[] }>) {\n const r = chatMessageRecipe.reactionSummary;\n return <span className=\"hjm-chat-message__reaction-counts\" style={{ minBlockSize: r.minHeight, gap: r.itemGap }}>\n <VisuallyHidden>{label}</VisuallyHidden>\n {items.map(item => <span key={item.id} aria-hidden=\"true\" style={{ display: \"inline-flex\", alignItems: \"center\", gap: r.emojiGap }}><span>{item.emoji}</span>{item.showCount ? <Text as=\"span\" variant=\"caption\" tone=\"muted\">{item.count}</Text> : null}</span>)}\n </span>;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"overlay-origin-motion.d.ts","sourceRoot":"","sources":["../../src/internal/overlay-origin-motion.ts"],"names":[],"mappings":"AACA,OAAO,EAA2B,KAAK,cAAc,EAAE,MAAM,4CAA4C,CAAC;AAC1G,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAG/D,KAAK,mBAAmB,GAAG,QAAQ,CAAC;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,YAAY,CAAC,UAAU,CAAC;CAC7C,CAAC,CAAC;AAEH,mGAAmG;AACnG,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,EAAE,EAAE,KAAY,EAAE,UAAoC,EAAE,GAAE,mBAAwB;;;EAwCvM"}
1
+ {"version":3,"file":"overlay-origin-motion.d.ts","sourceRoot":"","sources":["../../src/internal/overlay-origin-motion.ts"],"names":[],"mappings":"AAGA,OAAO,EAA2B,KAAK,cAAc,EAAE,MAAM,4CAA4C,CAAC;AAC1G,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAG/D,KAAK,mBAAmB,GAAG,QAAQ,CAAC;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,YAAY,CAAC,UAAU,CAAC;CAC7C,CAAC,CAAC;AAEH,mGAAmG;AACnG,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,EAAE,EAAE,KAAY,EAAE,UAAoC,EAAE,GAAE,mBAAwB;;;EAwCvM"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { useLayoutEffect, useRef, useState, useSyncExternalStore } from 'react';
2
3
  import { resolveOriginTransition } from '@hjmds/design-contracts/content-transition';
3
4
  import { dialogRecipe } from '@hjmds/design-contracts/recipes';
@@ -1 +1 @@
1
- {"version":3,"file":"overlay-origin-motion.js","sourceRoot":"","sources":["../../src/internal/overlay-origin-motion.ts"],"names":[],"mappings":"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","sourcesContent":["import { useLayoutEffect, useRef, useState, useSyncExternalStore } from 'react';\nimport { resolveOriginTransition, type TransitionRect } from '@hjmds/design-contracts/content-transition';\nimport { dialogRecipe } from '@hjmds/design-contracts/recipes';\nimport { easing } from '@hjmds/design-contracts/foundations';\n\ntype OriginMotionOptions = Readonly<{\n ready?: boolean;\n transition?: typeof dialogRecipe.transition;\n}>;\n\n/** Keep one real overlay subtree through exit; cancellation must never settle a reopened cycle. */\nexport function useOverlayOriginMotion(open: boolean, origin: TransitionRect | undefined, reduced: boolean | undefined, { ready = true, transition = dialogRecipe.transition }: OriginMotionOptions = {}) {\n const systemReduced = useSyncExternalStore(subscribeMotion, readMotion, () => false);\n const reduce = reduced ?? systemReduced;\n const interrupted = useRef<string | null>(null);\n const [node, setNode] = useState<HTMLDivElement | null>(null);\n const [present, setPresent] = useState(open);\n const visible = open || present;\n useLayoutEffect(() => {\n if (!node) { interrupted.current = null; if (!open) setPresent(false); return; }\n if (open) setPresent(true);\n // Anchored surfaces must finish placement before measuring their destination.\n // Measuring the hidden portal at (0, 0) makes its first frame jump across the viewport.\n if (!ready) { if (!open) setPresent(false); return; }\n const transform = resolveOriginTransition(origin, node.getBoundingClientRect(), reduce);\n if (!transform || typeof node.animate !== 'function') { interrupted.current = null; setPresent(open); return; }\n const from = `translate(${transform.translateX}px, ${transform.translateY}px) scale(${transform.scaleX}, ${transform.scaleY})`;\n const start = interrupted.current;\n interrupted.current = null;\n const phase = open ? transition.enter : transition.exit;\n let cancelled = false;\n let animation: Animation;\n try {\n // WAAPI only owns presentation. Overlay focus, state and completion remain canonical.\n animation = node.animate([{ transform: start ?? (open ? from : 'none') }, { transform: open ? 'none' : from }], {\n duration: phase.duration, easing: `cubic-bezier(${easing[phase.easing].join(',')})`, fill: 'both',\n });\n } catch { setPresent(open); return; }\n animation.finished.then(() => {\n if (cancelled) return;\n if (!open) setPresent(false);\n animation.cancel();\n }, () => { if (!cancelled) setPresent(open); });\n return () => {\n cancelled = true;\n // Sample before cancelling so a rapid close/reopen continues at its current visual position.\n interrupted.current = animation.playState === 'running' ? getComputedStyle(node).transform : null;\n animation.cancel();\n };\n }, [open, node, origin?.x, origin?.y, origin?.width, origin?.height, reduce, ready, transition]);\n return { visible, setNode };\n}\n\nfunction readMotion() { return typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches; }\nfunction subscribeMotion(listener: () => void) {\n if (typeof matchMedia === 'undefined') return () => {};\n const query = matchMedia('(prefers-reduced-motion: reduce)');\n query.addEventListener('change', listener);\n return () => query.removeEventListener('change', listener);\n}\n"]}
1
+ {"version":3,"file":"overlay-origin-motion.js","sourceRoot":"","sources":["../../src/internal/overlay-origin-motion.ts"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport { useLayoutEffect, useRef, useState, useSyncExternalStore } from 'react';\nimport { resolveOriginTransition, type TransitionRect } from '@hjmds/design-contracts/content-transition';\nimport { dialogRecipe } from '@hjmds/design-contracts/recipes';\nimport { easing } from '@hjmds/design-contracts/foundations';\n\ntype OriginMotionOptions = Readonly<{\n ready?: boolean;\n transition?: typeof dialogRecipe.transition;\n}>;\n\n/** Keep one real overlay subtree through exit; cancellation must never settle a reopened cycle. */\nexport function useOverlayOriginMotion(open: boolean, origin: TransitionRect | undefined, reduced: boolean | undefined, { ready = true, transition = dialogRecipe.transition }: OriginMotionOptions = {}) {\n const systemReduced = useSyncExternalStore(subscribeMotion, readMotion, () => false);\n const reduce = reduced ?? systemReduced;\n const interrupted = useRef<string | null>(null);\n const [node, setNode] = useState<HTMLDivElement | null>(null);\n const [present, setPresent] = useState(open);\n const visible = open || present;\n useLayoutEffect(() => {\n if (!node) { interrupted.current = null; if (!open) setPresent(false); return; }\n if (open) setPresent(true);\n // Anchored surfaces must finish placement before measuring their destination.\n // Measuring the hidden portal at (0, 0) makes its first frame jump across the viewport.\n if (!ready) { if (!open) setPresent(false); return; }\n const transform = resolveOriginTransition(origin, node.getBoundingClientRect(), reduce);\n if (!transform || typeof node.animate !== 'function') { interrupted.current = null; setPresent(open); return; }\n const from = `translate(${transform.translateX}px, ${transform.translateY}px) scale(${transform.scaleX}, ${transform.scaleY})`;\n const start = interrupted.current;\n interrupted.current = null;\n const phase = open ? transition.enter : transition.exit;\n let cancelled = false;\n let animation: Animation;\n try {\n // WAAPI only owns presentation. Overlay focus, state and completion remain canonical.\n animation = node.animate([{ transform: start ?? (open ? from : 'none') }, { transform: open ? 'none' : from }], {\n duration: phase.duration, easing: `cubic-bezier(${easing[phase.easing].join(',')})`, fill: 'both',\n });\n } catch { setPresent(open); return; }\n animation.finished.then(() => {\n if (cancelled) return;\n if (!open) setPresent(false);\n animation.cancel();\n }, () => { if (!cancelled) setPresent(open); });\n return () => {\n cancelled = true;\n // Sample before cancelling so a rapid close/reopen continues at its current visual position.\n interrupted.current = animation.playState === 'running' ? getComputedStyle(node).transform : null;\n animation.cancel();\n };\n }, [open, node, origin?.x, origin?.y, origin?.width, origin?.height, reduce, ready, transition]);\n return { visible, setNode };\n}\n\nfunction readMotion() { return typeof matchMedia !== 'undefined' && matchMedia('(prefers-reduced-motion: reduce)').matches; }\nfunction subscribeMotion(listener: () => void) {\n if (typeof matchMedia === 'undefined') return () => {};\n const query = matchMedia('(prefers-reduced-motion: reduce)');\n query.addEventListener('change', listener);\n return () => query.removeEventListener('change', listener);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"pending-content.d.ts","sourceRoot":"","sources":["../../src/internal/pending-content.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqC,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AACzG,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAGvE,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;IACpB,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC,CAAC,CAAC;AAEH,qFAAqF;AACrF,wBAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,kBAAkB,EAAE,EACvH,mBAAmB,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG;QAAE,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAA;KAAE,CAAC;IAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAAE,+BAwBzJ;AAED,gHAAgH;AAChH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,+BAA+C"}
1
+ {"version":3,"file":"pending-content.d.ts","sourceRoot":"","sources":["../../src/internal/pending-content.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAqC,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AACzG,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAGvE,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;IACpB,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC,CAAC,CAAC;AAEH,qFAAqF;AACrF,wBAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,kBAAkB,EAAE,EACvH,mBAAmB,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG;QAAE,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAA;KAAE,CAAC;IAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAAE,+BAwBzJ;AAED,gHAAgH;AAChH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,+BAA+C"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { useLayoutEffect, useRef, useState } from "react";
3
4
  import { Spinner } from "./spinner.js";
@@ -1 +1 @@
1
- {"version":3,"file":"pending-content.js","sourceRoot":"","sources":["../../src/internal/pending-content.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAiD,MAAM,OAAO,CAAC;AAEzG,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AASvC,qFAAqF;AACrF,MAAM,UAAU,kBAAkB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,kBAAkB,EACmC;IACxJ,MAAM,OAAO,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,EAAU,CAAC;IAC/C,eAAe,CAAC,GAAG,EAAE;QACnB,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE,OAAO;QACxC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;QAC7B,MAAM,OAAO,GAAG,GAAG,EAAE,GAAG,MAAM,IAAI,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC;YAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3G,OAAO,EAAE,CAAC;QACV,IAAI,OAAO,cAAc,KAAK,WAAW;YAAE,OAAO;QAClD,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;QAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACrE,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;IACrC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACd,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC,CAAC;IACvG,OAAO,eAAK,SAAS,EAAE,SAAS,eAAa,OAAO,IAAI,SAAS,EAC/D,KAAK,EAAE,EAAE,GAAG,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,aACxG,iBAAS,YAAY,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE;oBACjC,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;oBACvB,MAAM,GAAG,GAAG,YAAY,EAAE,GAAG,CAAC;oBAC9B,IAAI,OAAO,GAAG,KAAK,UAAU;wBAAE,GAAG,CAAC,IAAI,CAAC,CAAC;yBAAM,IAAI,GAAG;wBAAE,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC;gBAC7E,CAAC,EAAE,KAAK,EAAE,OAAO,iBAAe,OAAO,IAAI,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS,YAAG,QAAQ,GAAO,EAC5H,OAAO,CAAC,CAAC,CAAC,cAAK,SAAS,EAAE,kBAAkB,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,YACpJ,KAAC,OAAO,IAAC,KAAK,EAAE,KAAK,GAAI,GACrB,CAAC,CAAC,CAAC,IAAI,IACT,CAAC;AACT,CAAC;AAED,gHAAgH;AAChH,MAAM,UAAU,cAAc,CAAC,KAA0B,IAAI,OAAO,KAAC,kBAAkB,OAAK,KAAK,GAAI,CAAC,CAAC,CAAC","sourcesContent":["import { useLayoutEffect, useRef, useState, type HTMLAttributes, type ReactNode, type Ref } from \"react\";\nimport type { HjmCompositionStyleProp } from \"../composition-style.js\";\nimport { Spinner } from \"./spinner.js\";\n\nexport type PendingContentProps = Readonly<{\n pending: boolean;\n label: string;\n children: ReactNode;\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\n/** Shared host for the public region and AuthScreen's focus-managed action block. */\nexport function PendingContentHost({ pending, label, children, layoutStyle, className, contentProps, indicatorClassName }:\n PendingContentProps & { className?: string; contentProps?: HTMLAttributes<HTMLDivElement> & { ref?: Ref<HTMLDivElement> }; indicatorClassName?: string }) {\n const content = useRef<HTMLDivElement>(null);\n const [height, setHeight] = useState<number>();\n useLayoutEffect(() => {\n if (pending || !content.current) return;\n const node = content.current;\n const measure = () => { const next = node.getBoundingClientRect().height; if (next > 0) setHeight(next); };\n measure();\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(measure); observer.observe(node);\n return () => observer.disconnect();\n }, [pending]);\n if (pending && !label.trim()) throw new TypeError(\"PendingContent requires a non-empty pending label\");\n return <div className={className} aria-busy={pending || undefined}\n style={{ ...layoutStyle, position: \"relative\", width: \"100%\", ...(pending && height ? { height } : {}) }}>\n <div {...contentProps} ref={node => {\n content.current = node;\n const ref = contentProps?.ref;\n if (typeof ref === \"function\") ref(node); else if (ref) ref.current = node;\n }} inert={pending} aria-hidden={pending || undefined} style={pending ? { visibility: \"hidden\" } : undefined}>{children}</div>\n {pending ? <div className={indicatorClassName} style={{ position: \"absolute\", inset: 0, display: \"grid\", placeItems: \"center\", pointerEvents: \"none\" }}>\n <Spinner label={label} />\n </div> : null}\n </div>;\n}\n\n/** Keep controls mounted and preserve their last ready height while a single centered spinner replaces them. */\nexport function PendingContent(props: PendingContentProps) { return <PendingContentHost {...props} />; }\n"]}
1
+ {"version":3,"file":"pending-content.js","sourceRoot":"","sources":["../../src/internal/pending-content.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAiD,MAAM,OAAO,CAAC;AAEzG,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AASvC,qFAAqF;AACrF,MAAM,UAAU,kBAAkB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,kBAAkB,EACmC;IACxJ,MAAM,OAAO,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,EAAU,CAAC;IAC/C,eAAe,CAAC,GAAG,EAAE;QACnB,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE,OAAO;QACxC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;QAC7B,MAAM,OAAO,GAAG,GAAG,EAAE,GAAG,MAAM,IAAI,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC;YAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3G,OAAO,EAAE,CAAC;QACV,IAAI,OAAO,cAAc,KAAK,WAAW;YAAE,OAAO;QAClD,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;QAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACrE,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;IACrC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACd,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC,CAAC;IACvG,OAAO,eAAK,SAAS,EAAE,SAAS,eAAa,OAAO,IAAI,SAAS,EAC/D,KAAK,EAAE,EAAE,GAAG,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,aACxG,iBAAS,YAAY,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE;oBACjC,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;oBACvB,MAAM,GAAG,GAAG,YAAY,EAAE,GAAG,CAAC;oBAC9B,IAAI,OAAO,GAAG,KAAK,UAAU;wBAAE,GAAG,CAAC,IAAI,CAAC,CAAC;yBAAM,IAAI,GAAG;wBAAE,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC;gBAC7E,CAAC,EAAE,KAAK,EAAE,OAAO,iBAAe,OAAO,IAAI,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS,YAAG,QAAQ,GAAO,EAC5H,OAAO,CAAC,CAAC,CAAC,cAAK,SAAS,EAAE,kBAAkB,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,YACpJ,KAAC,OAAO,IAAC,KAAK,EAAE,KAAK,GAAI,GACrB,CAAC,CAAC,CAAC,IAAI,IACT,CAAC;AACT,CAAC;AAED,gHAAgH;AAChH,MAAM,UAAU,cAAc,CAAC,KAA0B,IAAI,OAAO,KAAC,kBAAkB,OAAK,KAAK,GAAI,CAAC,CAAC,CAAC","sourcesContent":["\"use client\";\n\nimport { useLayoutEffect, useRef, useState, type HTMLAttributes, type ReactNode, type Ref } from \"react\";\nimport type { HjmCompositionStyleProp } from \"../composition-style.js\";\nimport { Spinner } from \"./spinner.js\";\n\nexport type PendingContentProps = Readonly<{\n pending: boolean;\n label: string;\n children: ReactNode;\n layoutStyle?: HjmCompositionStyleProp;\n}>;\n\n/** Shared host for the public region and AuthScreen's focus-managed action block. */\nexport function PendingContentHost({ pending, label, children, layoutStyle, className, contentProps, indicatorClassName }:\n PendingContentProps & { className?: string; contentProps?: HTMLAttributes<HTMLDivElement> & { ref?: Ref<HTMLDivElement> }; indicatorClassName?: string }) {\n const content = useRef<HTMLDivElement>(null);\n const [height, setHeight] = useState<number>();\n useLayoutEffect(() => {\n if (pending || !content.current) return;\n const node = content.current;\n const measure = () => { const next = node.getBoundingClientRect().height; if (next > 0) setHeight(next); };\n measure();\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(measure); observer.observe(node);\n return () => observer.disconnect();\n }, [pending]);\n if (pending && !label.trim()) throw new TypeError(\"PendingContent requires a non-empty pending label\");\n return <div className={className} aria-busy={pending || undefined}\n style={{ ...layoutStyle, position: \"relative\", width: \"100%\", ...(pending && height ? { height } : {}) }}>\n <div {...contentProps} ref={node => {\n content.current = node;\n const ref = contentProps?.ref;\n if (typeof ref === \"function\") ref(node); else if (ref) ref.current = node;\n }} inert={pending} aria-hidden={pending || undefined} style={pending ? { visibility: \"hidden\" } : undefined}>{children}</div>\n {pending ? <div className={indicatorClassName} style={{ position: \"absolute\", inset: 0, display: \"grid\", placeItems: \"center\", pointerEvents: \"none\" }}>\n <Spinner label={label} />\n </div> : null}\n </div>;\n}\n\n/** Keep controls mounted and preserve their last ready height while a single centered spinner replaces them. */\nexport function PendingContent(props: PendingContentProps) { return <PendingContentHost {...props} />; }\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"photo-source-icon.d.ts","sourceRoot":"","sources":["../../src/internal/photo-source-icon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAI3E,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,+BAalE"}
1
+ {"version":3,"file":"photo-source-icon.d.ts","sourceRoot":"","sources":["../../src/internal/photo-source-icon.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAI3E,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,+BAalE"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx } from "react/jsx-runtime";
2
3
  import { useHjmTheme } from "../provider.js";
3
4
  export function PhotoSourceIcon({ source }) {
@@ -1 +1 @@
1
- {"version":3,"file":"photo-source-icon.js","sourceRoot":"","sources":["../../src/internal/photo-source-icon.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,UAAU,eAAe,CAAC,EAAE,MAAM,EAA2B;IACjE,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAAC;IACtC,+FAA+F;IAC/F,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,KAAK,MAAM;QACzC,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;QAC7C,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAChD,OAAO,eAAM,SAAS,EAAC,wBAAwB,EAAC,KAAK,EAAE,MAAM,iBAAc,MAAM,YAC/E,cAAK,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAC,GAAG,EAAC,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,EAAC,SAAS,EAAC,OAAO,YACtI,MAAM,KAAK,QAAQ;gBAClB,CAAC,CAAC,eAAM,CAAC,EAAC,wHAAwH,GAAG;gBACrI,CAAC,CAAC,eAAM,CAAC,EAAC,iKAAiK,GAAG,GAC5K,GACD,CAAC;AACV,CAAC","sourcesContent":["import type { PhotoSource } from \"@hjmds/design-contracts/screen-patterns\";\n\nimport { useHjmTheme } from \"../provider.js\";\n\nexport function PhotoSourceIcon({ source }: { source: PhotoSource }) {\n const { environment } = useHjmTheme();\n // Shared neutral colors use a stronger plate/line contrast after device feedback (2026-10-20).\n const colors = environment.theme === \"dark\"\n ? { background: \"#334155\", color: \"#F1F5F9\" }\n : { background: \"#E2E8F0\", color: \"#334155\" };\n return <span className=\"hjm-photo-source__icon\" style={colors} aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" focusable=\"false\">\n {source === \"camera\"\n ? <path d=\"M8 6 9.5 3h5L16 6h4a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4Zm8 7a4 4 0 1 0-8 0 4 4 0 0 0 8 0Z\" />\n : <path d=\"M5 17H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v1M9 7h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H9a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2Zm-2 12 5-5 4 4 2-2 4 4M17 11h.01\" />}\n </svg>\n </span>;\n}\n"]}
1
+ {"version":3,"file":"photo-source-icon.js","sourceRoot":"","sources":["../../src/internal/photo-source-icon.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAIb,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,UAAU,eAAe,CAAC,EAAE,MAAM,EAA2B;IACjE,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAAC;IACtC,+FAA+F;IAC/F,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,KAAK,MAAM;QACzC,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;QAC7C,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAChD,OAAO,eAAM,SAAS,EAAC,wBAAwB,EAAC,KAAK,EAAE,MAAM,iBAAc,MAAM,YAC/E,cAAK,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAC,GAAG,EAAC,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,EAAC,SAAS,EAAC,OAAO,YACtI,MAAM,KAAK,QAAQ;gBAClB,CAAC,CAAC,eAAM,CAAC,EAAC,wHAAwH,GAAG;gBACrI,CAAC,CAAC,eAAM,CAAC,EAAC,iKAAiK,GAAG,GAC5K,GACD,CAAC;AACV,CAAC","sourcesContent":["\"use client\";\n\nimport type { PhotoSource } from \"@hjmds/design-contracts/screen-patterns\";\n\nimport { useHjmTheme } from \"../provider.js\";\n\nexport function PhotoSourceIcon({ source }: { source: PhotoSource }) {\n const { environment } = useHjmTheme();\n // Shared neutral colors use a stronger plate/line contrast after device feedback (2026-10-20).\n const colors = environment.theme === \"dark\"\n ? { background: \"#334155\", color: \"#F1F5F9\" }\n : { background: \"#E2E8F0\", color: \"#334155\" };\n return <span className=\"hjm-photo-source__icon\" style={colors} aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" focusable=\"false\">\n {source === \"camera\"\n ? <path d=\"M8 6 9.5 3h5L16 6h4a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4Zm8 7a4 4 0 1 0-8 0 4 4 0 0 0 8 0Z\" />\n : <path d=\"M5 17H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v1M9 7h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H9a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2Zm-2 12 5-5 4 4 2-2 4 4M17 11h.01\" />}\n </svg>\n </span>;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"screen-exit.d.ts","sourceRoot":"","sources":["../../src/internal/screen-exit.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAGhG,wGAAwG;AACxG,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,IAAI,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAEhH,sGAAsG;AACtG,wBAAgB,gBAAgB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,QAAgB,EAAE,EAAE,UAAU,+BAStF"}
1
+ {"version":3,"file":"screen-exit.d.ts","sourceRoot":"","sources":["../../src/internal/screen-exit.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAGhG,wGAAwG;AACxG,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,IAAI,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAEhH,sGAAsG;AACtG,wBAAgB,gBAAgB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,QAAgB,EAAE,EAAE,UAAU,+BAStF"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx } from "react/jsx-runtime";
2
3
  import { screenExitRecipe } from "@hjmds/design-contracts/screen-patterns";
3
4
  import { IconButton } from "../actions.js";
@@ -1 +1 @@
1
- {"version":3,"file":"screen-exit.js","sourceRoot":"","sources":["../../src/internal/screen-exit.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,gBAAgB,EAAuB,MAAM,yCAAyC,CAAC;AAChG,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAK3C,sGAAsG;AACtG,MAAM,UAAU,gBAAgB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,GAAG,KAAK,EAAc;IACrF,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAAC;IAC5D,MAAM,IAAI,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3D,wFAAwF;IACxF,OAAO,KAAC,UAAU,IAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAC,OAAO,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,YACzG,cAAK,SAAS,EAAC,wBAAwB,eAAY,IAAI,iBAAc,MAAM,EAAC,SAAS,EAAC,OAAO,EAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,IAAI,IAAI,IAAI,EAAE,EAAE,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,YACzP,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,eAAM,CAAC,EAAE,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,KAAK,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,EAAE,GAAI,CAAC,CAAC,CAAC,eAAM,CAAC,EAAE,SAAS,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,EAAE,GAAI,GACnM,GACK,CAAC;AAChB,CAAC","sourcesContent":["import { screenExitRecipe, type ScreenExitKind } from \"@hjmds/design-contracts/screen-patterns\";\nimport { IconButton } from \"../actions.js\";\n\n/** Leaving a screen: icon-only, fixed at the header's leading edge (ScreenLayout and TopBar `exit`). */\nexport type ScreenExit = Readonly<{ kind: ScreenExitKind; label: string; onClick(): void; disabled?: boolean }>;\n\n/** Drawn chevron/cross (currentColor) so back and close match native; back mirrors in RTL via CSS. */\nexport function ScreenExitButton({ kind, label, onClick, disabled = false }: ScreenExit) {\n const { chevronSize, closeSize, stroke } = screenExitRecipe;\n const size = kind === \"back\" ? chevronSize * 2 : closeSize;\n // The compact target aligns to the header gutter without an edge overhang (2026-10-21).\n return <IconButton label={label} tone=\"ghost\" size=\"small\" hitSlop={0} disabled={disabled} onClick={onClick}>\n <svg className=\"hjm-screen__exit-glyph\" data-kind={kind} aria-hidden=\"true\" focusable=\"false\" width={size} height={size} viewBox={`0 0 ${size} ${size}`} fill=\"none\" stroke=\"currentColor\" strokeWidth={stroke} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n {kind === \"back\" ? <path d={`M${size * 0.65} ${size * 0.15} L${size * 0.3} ${size / 2} L${size * 0.65} ${size * 0.85}`} /> : <path d={`M1 1 L${size - 1} ${size - 1} M${size - 1} 1 L1 ${size - 1}`} />}\n </svg>\n </IconButton>;\n}\n"]}
1
+ {"version":3,"file":"screen-exit.js","sourceRoot":"","sources":["../../src/internal/screen-exit.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,gBAAgB,EAAuB,MAAM,yCAAyC,CAAC;AAChG,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAK3C,sGAAsG;AACtG,MAAM,UAAU,gBAAgB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,GAAG,KAAK,EAAc;IACrF,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAAC;IAC5D,MAAM,IAAI,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3D,wFAAwF;IACxF,OAAO,KAAC,UAAU,IAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAC,OAAO,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,YACzG,cAAK,SAAS,EAAC,wBAAwB,eAAY,IAAI,iBAAc,MAAM,EAAC,SAAS,EAAC,OAAO,EAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,IAAI,IAAI,IAAI,EAAE,EAAE,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,YACzP,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,eAAM,CAAC,EAAE,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,KAAK,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI,EAAE,GAAI,CAAC,CAAC,CAAC,eAAM,CAAC,EAAE,SAAS,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,EAAE,GAAI,GACnM,GACK,CAAC;AAChB,CAAC","sourcesContent":["\"use client\";\n\nimport { screenExitRecipe, type ScreenExitKind } from \"@hjmds/design-contracts/screen-patterns\";\nimport { IconButton } from \"../actions.js\";\n\n/** Leaving a screen: icon-only, fixed at the header's leading edge (ScreenLayout and TopBar `exit`). */\nexport type ScreenExit = Readonly<{ kind: ScreenExitKind; label: string; onClick(): void; disabled?: boolean }>;\n\n/** Drawn chevron/cross (currentColor) so back and close match native; back mirrors in RTL via CSS. */\nexport function ScreenExitButton({ kind, label, onClick, disabled = false }: ScreenExit) {\n const { chevronSize, closeSize, stroke } = screenExitRecipe;\n const size = kind === \"back\" ? chevronSize * 2 : closeSize;\n // The compact target aligns to the header gutter without an edge overhang (2026-10-21).\n return <IconButton label={label} tone=\"ghost\" size=\"small\" hitSlop={0} disabled={disabled} onClick={onClick}>\n <svg className=\"hjm-screen__exit-glyph\" data-kind={kind} aria-hidden=\"true\" focusable=\"false\" width={size} height={size} viewBox={`0 0 ${size} ${size}`} fill=\"none\" stroke=\"currentColor\" strokeWidth={stroke} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n {kind === \"back\" ? <path d={`M${size * 0.65} ${size * 0.15} L${size * 0.3} ${size / 2} L${size * 0.65} ${size * 0.85}`} /> : <path d={`M1 1 L${size - 1} ${size - 1} M${size - 1} 1 L1 ${size - 1}`} />}\n </svg>\n </IconButton>;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"screen-footer.d.ts","sourceRoot":"","sources":["../../src/internal/screen-footer.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;mBAA2C,MAAM;UAAiB,CAAC"}
1
+ {"version":3,"file":"screen-footer.d.ts","sourceRoot":"","sources":["../../src/internal/screen-footer.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;mBAA2C,MAAM;UAAiB,CAAC"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { createContext } from "react";
2
3
  /**
3
4
  * Set inside a padded ScreenLayout or Sheet footer. The parent owns the bar chrome and safe area, so
@@ -1 +1 @@
1
- {"version":3,"file":"screen-footer.js","sourceRoot":"","sources":["../../src/internal/screen-footer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,aAAa,CAA6C,IAAI,CAAC,CAAC","sourcesContent":["import { createContext } from \"react\";\n\n/**\n * Set inside a padded ScreenLayout or Sheet footer. The parent owns the bar chrome and safe area, so\n * BottomCTA placed there renders only its copy and actions; drawing its own bar too doubled the border, inset the\n * buttons twice and (Native) added a shadowed surface inside the footer (2026-10-17 screen review, common-screen-shell).\n */\nexport const ScreenFooterContext = createContext<Readonly<{ bottomPadding: string }> | null>(null);\n"]}
1
+ {"version":3,"file":"screen-footer.js","sourceRoot":"","sources":["../../src/internal/screen-footer.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,aAAa,CAA6C,IAAI,CAAC,CAAC","sourcesContent":["\"use client\";\n\nimport { createContext } from \"react\";\n\n/**\n * Set inside a padded ScreenLayout or Sheet footer. The parent owns the bar chrome and safe area, so\n * BottomCTA placed there renders only its copy and actions; drawing its own bar too doubled the border, inset the\n * buttons twice and (Native) added a shadowed surface inside the footer (2026-10-17 screen review, common-screen-shell).\n */\nexport const ScreenFooterContext = createContext<Readonly<{ bottomPadding: string }> | null>(null);\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/internal/spinner.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AACxD,OAAO,EAAiB,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACpG,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAGvE,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC,eAAe,CAAC,GACxD,QAAQ,CAAC;IACP,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,gGAAgG;IAChG,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC,CAAC,CAAC;AAEL,eAAO,MAAM,OAAO;WAPT,MAAM;WACN,WAAW;WACX,WAAW;IAClB,gGAAgG;kBAClF,uBAAuB;oDA8BvC,CAAC"}
1
+ {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/internal/spinner.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AACxD,OAAO,EAAiB,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACpG,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAGvE,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC,eAAe,CAAC,GACxD,QAAQ,CAAC;IACP,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,gGAAgG;IAChG,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC,CAAC,CAAC;AAEL,eAAO,MAAM,OAAO;WAPT,MAAM;WACN,WAAW;WACX,WAAW;IAClB,gGAAgG;kBAClF,uBAAuB;oDA8BvC,CAAC"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  // Shared by feedback and screen shells without pulling unrelated feedback UI
3
4
  // into the lightweight screens entry. The public import remains /feedback.
@@ -1 +1 @@
1
- {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/internal/spinner.tsx"],"names":[],"mappings":";AAAA,6EAA6E;AAC7E,2EAA2E;AAC3E,OAAO,EAAE,UAAU,EAAuB,MAAM,OAAO,CAAC;AACxD,OAAO,EAAE,aAAa,EAAsC,MAAM,iCAAiC,CAAC;AAEpG,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAW5C,MAAM,CAAC,MAAM,OAAO,GAAG,UAAU,CAAgC,SAAS,OAAO,CAC/E,EACE,KAAK,EACL,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,IAAI,EAClC,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,IAAI,EAClC,SAAS,EACT,WAAW,EACX,GAAG,KAAK,EACT,EACD,GAAG;IAEH,OAAO,CACL,mBACM,KAAK,EACT,KAAK,EAAE,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,GAAG,WAAW,EAAE,EACzC,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,UAAU,CAAC,aAAa,EAAE,SAAS,CAAC,eACpC,IAAI,eACJ,IAAI,EACf,IAAI,EAAC,QAAQ,gBACD,KAAK,eACP,QAAQ,aAElB,eAAM,SAAS,EAAC,oBAAoB,iBAAa,MAAM,GAAG,EAC1D,eAAM,SAAS,EAAC,qBAAqB,YAAE,KAAK,GAAQ,IAC/C,CACR,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["// Shared by feedback and screen shells without pulling unrelated feedback UI\n// into the lightweight screens entry. The public import remains /feedback.\nimport { forwardRef, type HTMLAttributes } from \"react\";\nimport { spinnerRecipe, type SpinnerSize, type SpinnerTone } from \"@hjmds/design-contracts/recipes\";\nimport type { HjmCompositionStyleProp } from \"../composition-style.js\";\nimport { classNames } from \"../internal.js\";\n\nexport type SpinnerProps = HTMLAttributes<HTMLSpanElement> &\n Readonly<{\n label: string;\n size?: SpinnerSize;\n tone?: SpinnerTone;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n }>;\n\nexport const Spinner = forwardRef<HTMLSpanElement, SpinnerProps>(function Spinner(\n {\n label,\n size = spinnerRecipe.defaults.size,\n tone = spinnerRecipe.defaults.tone,\n className,\n layoutStyle,\n ...props\n },\n ref,\n) {\n return (\n <span\n {...props}\n style={{ ...props.style, ...layoutStyle }}\n ref={ref}\n className={classNames(\"hjm-spinner\", className)}\n data-size={size}\n data-tone={tone}\n role=\"status\"\n aria-label={label}\n aria-live=\"polite\"\n >\n <span className=\"hjm-spinner__glyph\" aria-hidden=\"true\" />\n <span className=\"hjm-visually-hidden\">{label}</span>\n </span>\n );\n});\n\n"]}
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/internal/spinner.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,6EAA6E;AAC7E,2EAA2E;AAC3E,OAAO,EAAE,UAAU,EAAuB,MAAM,OAAO,CAAC;AACxD,OAAO,EAAE,aAAa,EAAsC,MAAM,iCAAiC,CAAC;AAEpG,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAW5C,MAAM,CAAC,MAAM,OAAO,GAAG,UAAU,CAAgC,SAAS,OAAO,CAC/E,EACE,KAAK,EACL,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,IAAI,EAClC,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,IAAI,EAClC,SAAS,EACT,WAAW,EACX,GAAG,KAAK,EACT,EACD,GAAG;IAEH,OAAO,CACL,mBACM,KAAK,EACT,KAAK,EAAE,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,GAAG,WAAW,EAAE,EACzC,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,UAAU,CAAC,aAAa,EAAE,SAAS,CAAC,eACpC,IAAI,eACJ,IAAI,EACf,IAAI,EAAC,QAAQ,gBACD,KAAK,eACP,QAAQ,aAElB,eAAM,SAAS,EAAC,oBAAoB,iBAAa,MAAM,GAAG,EAC1D,eAAM,SAAS,EAAC,qBAAqB,YAAE,KAAK,GAAQ,IAC/C,CACR,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["\"use client\";\n\n// Shared by feedback and screen shells without pulling unrelated feedback UI\n// into the lightweight screens entry. The public import remains /feedback.\nimport { forwardRef, type HTMLAttributes } from \"react\";\nimport { spinnerRecipe, type SpinnerSize, type SpinnerTone } from \"@hjmds/design-contracts/recipes\";\nimport type { HjmCompositionStyleProp } from \"../composition-style.js\";\nimport { classNames } from \"../internal.js\";\n\nexport type SpinnerProps = HTMLAttributes<HTMLSpanElement> &\n Readonly<{\n label: string;\n size?: SpinnerSize;\n tone?: SpinnerTone;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n }>;\n\nexport const Spinner = forwardRef<HTMLSpanElement, SpinnerProps>(function Spinner(\n {\n label,\n size = spinnerRecipe.defaults.size,\n tone = spinnerRecipe.defaults.tone,\n className,\n layoutStyle,\n ...props\n },\n ref,\n) {\n return (\n <span\n {...props}\n style={{ ...props.style, ...layoutStyle }}\n ref={ref}\n className={classNames(\"hjm-spinner\", className)}\n data-size={size}\n data-tone={tone}\n role=\"status\"\n aria-label={label}\n aria-live=\"polite\"\n >\n <span className=\"hjm-spinner__glyph\" aria-hidden=\"true\" />\n <span className=\"hjm-visually-hidden\">{label}</span>\n </span>\n );\n});\n\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"use-composition-action.d.ts","sourceRoot":"","sources":["../../src/internal/use-composition-action.ts"],"names":[],"mappings":"AAGA,wBAAgB,oBAAoB,CAAC,CAAC,GAAG,MAAM,EAAE,QAAQ,UAAQ;;;;;;;;;;;;;;eASlD,CAAC,QAAQ,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;EAIjD"}
1
+ {"version":3,"file":"use-composition-action.d.ts","sourceRoot":"","sources":["../../src/internal/use-composition-action.ts"],"names":[],"mappings":"AAKA,wBAAgB,oBAAoB,CAAC,CAAC,GAAG,MAAM,EAAE,QAAQ,UAAQ;;;;;;;;;;;;;;eASlD,CAAC,QAAQ,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;EAIjD"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { useEffect, useRef, useState, useSyncExternalStore } from "react";
2
3
  import { createActionSession } from "@hjmds/design-contracts/action-session";
3
4
  export function useCompositionAction(disabled = false) {
@@ -1 +1 @@
1
- {"version":3,"file":"use-composition-action.js","sourceRoot":"","sources":["../../src/internal/use-composition-action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAE7E,MAAM,UAAU,oBAAoB,CAAa,QAAQ,GAAG,KAAK;IAC/D,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/D,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAC;IAC/B,MAAM,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAW,IAAI,CAAC,CAAC,CAAC;IACtE,MAAM,KAAK,GAAG,oBAAoB,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAChG,sFAAsF;IACtF,SAAS,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,OAAO,GAAG,EAAE,GAAG,SAAS,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5H,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,KAAK,OAAO;QACrF,MAAM,EAAE,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;QACvD,GAAG,EAAE,CAAC,GAAM,EAAE,IAAgC,EAAE,EAAE;YAChD,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,WAAW,CAAC,OAAO;gBAAE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,SAAkB,EAAE,CAAC,CAAC;YACtG,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,CAAC;QAC3F,CAAC,EAAE,CAAC;AACR,CAAC","sourcesContent":["import { useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { createActionSession } from \"@hjmds/design-contracts/action-session\";\n\nexport function useCompositionAction<T = string>(disabled = false) {\n const available = useRef(true), disabledRef = useRef(disabled);\n disabledRef.current = disabled;\n const [session] = useState(() => createActionSession<T | null>(null));\n const state = useSyncExternalStore(session.subscribe, session.getSnapshot, session.getSnapshot);\n // Reset detaches responses after unmount, including a keyed change to another entity.\n useEffect(() => { available.current = true; return () => { available.current = false; session.reset(null); }; }, [session]);\n return { session, pending: state.status === \"pending\", failed: state.status === \"error\",\n active: state.status === \"pending\" ? state.value : null,\n run: (key: T, task: () => void | Promise<void>) => {\n if (!available.current || disabledRef.current) return Promise.resolve({ status: \"ignored\" as const });\n return session.run(async () => { await task(); return null; }, { optimisticValue: key });\n } };\n}\n"]}
1
+ {"version":3,"file":"use-composition-action.js","sourceRoot":"","sources":["../../src/internal/use-composition-action.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAE7E,MAAM,UAAU,oBAAoB,CAAa,QAAQ,GAAG,KAAK;IAC/D,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/D,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAC;IAC/B,MAAM,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAW,IAAI,CAAC,CAAC,CAAC;IACtE,MAAM,KAAK,GAAG,oBAAoB,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAChG,sFAAsF;IACtF,SAAS,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,OAAO,GAAG,EAAE,GAAG,SAAS,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5H,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,KAAK,OAAO;QACrF,MAAM,EAAE,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;QACvD,GAAG,EAAE,CAAC,GAAM,EAAE,IAAgC,EAAE,EAAE;YAChD,IAAI,CAAC,SAAS,CAAC,OAAO,IAAI,WAAW,CAAC,OAAO;gBAAE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,SAAkB,EAAE,CAAC,CAAC;YACtG,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,CAAC;QAC3F,CAAC,EAAE,CAAC;AACR,CAAC","sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { createActionSession } from \"@hjmds/design-contracts/action-session\";\n\nexport function useCompositionAction<T = string>(disabled = false) {\n const available = useRef(true), disabledRef = useRef(disabled);\n disabledRef.current = disabled;\n const [session] = useState(() => createActionSession<T | null>(null));\n const state = useSyncExternalStore(session.subscribe, session.getSnapshot, session.getSnapshot);\n // Reset detaches responses after unmount, including a keyed change to another entity.\n useEffect(() => { available.current = true; return () => { available.current = false; session.reset(null); }; }, [session]);\n return { session, pending: state.status === \"pending\", failed: state.status === \"error\",\n active: state.status === \"pending\" ? state.value : null,\n run: (key: T, task: () => void | Promise<void>) => {\n if (!available.current || disabledRef.current) return Promise.resolve({ status: \"ignored\" as const });\n return session.run(async () => { await task(); return null; }, { optimisticValue: key });\n } };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAOL,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,GAAG,EACR,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AAEf,6FAA6F;AAC7F,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,OAAO,CAE5E;AAED,wBAAgB,UAAU,CACxB,GAAG,MAAM,EAAE,SAAS,CAAC,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,GACxD,MAAM,GAAG,SAAS,CAGpB;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAG7F;AAED,wBAAgB,WAAW,CAAC,OAAO,EACjC,GAAG,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC,EAAE,GAC7C,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAIjC;AAED,KAAK,wBAAwB,CAAC,KAAK,IAAI,QAAQ,CAAC;IAC9C,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,YAAY,EAAE,KAAK,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACnC,CAAC,CAAC;AAEH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,EAC1C,KAAK,EACL,YAAY,EACZ,QAAQ,GACT,EAAE,wBAAwB,CAAC,KAAK,CAAC,GAAG,SAAS;IAC5C,KAAK;IACL,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;CAChC,CAiBA;AAeD,wBAAgB,cAAc,IAAI,MAAM,CAMvC;AAED,wBAAgB,eAAe,CAAC,OAAO,SAAS,WAAW,EACzD,WAAW,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,GACzB,SAAS,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC,CAyB/D;AAID,eAAO,MAAM,oBAAoB;;;cA1DR,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;eAoBf,CAAC;;;;;;;;;;;;;;;;;;;;;;;;eAsC8E,CAAC;AAC3F,wBAAgB,wBAAwB,IAAI,gBAAgB,GAAG,SAAS,CAEvE"}
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAOL,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,GAAG,EACR,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AAEf,6FAA6F;AAC7F,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,OAAO,CAE5E;AAED,wBAAgB,UAAU,CACxB,GAAG,MAAM,EAAE,SAAS,CAAC,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,GACxD,MAAM,GAAG,SAAS,CAGpB;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAG7F;AAED,wBAAgB,WAAW,CAAC,OAAO,EACjC,GAAG,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC,EAAE,GAC7C,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAIjC;AAED,KAAK,wBAAwB,CAAC,KAAK,IAAI,QAAQ,CAAC;IAC9C,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,YAAY,EAAE,KAAK,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACnC,CAAC,CAAC;AAEH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,EAC1C,KAAK,EACL,YAAY,EACZ,QAAQ,GACT,EAAE,wBAAwB,CAAC,KAAK,CAAC,GAAG,SAAS;IAC5C,KAAK;IACL,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;CAChC,CAiBA;AAeD,wBAAgB,cAAc,IAAI,MAAM,CAMvC;AAED,wBAAgB,eAAe,CAAC,OAAO,SAAS,WAAW,EACzD,WAAW,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,GACzB,SAAS,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC,CAyB/D;AAID,eAAO,MAAM,oBAAoB;;;cA1DvB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;eAmB4B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;eAuCkD,CAAC;AAC3F,wBAAgB,wBAAwB,IAAI,gBAAgB,GAAG,SAAS,CAEvE"}
package/dist/internal.js CHANGED
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { createContext, useContext, useCallback, useEffect, useState, useSyncExternalStore, } from "react";
2
3
  /** ARIA's string "false" is valid; grammar/spelling express invalid input just like true. */
3
4
  export function isAriaInvalid(value) {
@@ -1 +1 @@
1
- {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"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","sourcesContent":["import type { HjmDesignProfile } from \"@hjmds/design-contracts/design-profile\";\nimport {\n createContext,\n useContext,\n useCallback,\n useEffect,\n useState,\n useSyncExternalStore,\n type AriaAttributes,\n type Dispatch,\n type Ref,\n type SetStateAction,\n} from \"react\";\n\n/** ARIA's string \"false\" is valid; grammar/spelling express invalid input just like true. */\nexport function isAriaInvalid(value: AriaAttributes[\"aria-invalid\"]): boolean {\n return value === true || (typeof value === \"string\" && value !== \"false\");\n}\n\nexport function classNames(\n ...values: readonly (string | false | null | undefined)[]\n): string | undefined {\n const result = values.filter(Boolean).join(\" \");\n return result.length > 0 ? result : undefined;\n}\n\nexport function assignRef<Element>(ref: Ref<Element> | undefined, value: Element | null): void {\n if (typeof ref === \"function\") ref(value);\n else if (ref) ref.current = value;\n}\n\nexport function composeRefs<Element>(\n ...refs: readonly (Ref<Element> | undefined)[]\n): (value: Element | null) => void {\n return (value) => {\n for (const ref of refs) assignRef(ref, value);\n };\n}\n\ntype ControllableStateOptions<Value> = Readonly<{\n value?: Value;\n defaultValue: Value;\n onChange?: (value: Value) => void;\n}>;\n\nexport function useControllableState<Value>({\n value,\n defaultValue,\n onChange,\n}: ControllableStateOptions<Value>): readonly [\n Value,\n Dispatch<SetStateAction<Value>>,\n] {\n const [internalValue, setInternalValue] = useState(defaultValue);\n const controlled = value !== undefined;\n const currentValue = controlled ? value : internalValue;\n\n const setValue: Dispatch<SetStateAction<Value>> = useCallback(\n (next) => {\n const resolved = typeof next === \"function\"\n ? (next as (previous: Value) => Value)(currentValue)\n : next;\n if (!controlled) setInternalValue(resolved);\n if (!Object.is(resolved, currentValue)) onChange?.(resolved);\n },\n [controlled, currentValue, onChange],\n );\n\n return [currentValue, setValue] as const;\n}\n\nfunction subscribeWindowResize(callback: () => void): () => void {\n window.addEventListener(\"resize\", callback);\n return () => window.removeEventListener(\"resize\", callback);\n}\n\nfunction getWindowWidth(): number {\n return window.innerWidth;\n}\n\nfunction getServerWindowWidth(): number {\n return 0;\n}\n\nexport function useWindowWidth(): number {\n return useSyncExternalStore(\n subscribeWindowResize,\n getWindowWidth,\n getServerWindowWidth,\n );\n}\n\nexport function useElementWidth<Element extends HTMLElement>(\n externalRef?: Ref<Element>,\n): readonly [number | undefined, (node: Element | null) => void] {\n const [node, setNode] = useState<Element | null>(null);\n const [width, setWidth] = useState<number>();\n const ref = useCallback(\n (nextNode: Element | null) => {\n setNode(nextNode);\n assignRef(externalRef, nextNode);\n },\n [externalRef],\n );\n\n useEffect(() => {\n if (!node) return;\n const update = () => setWidth(node.getBoundingClientRect().width);\n update();\n if (typeof ResizeObserver === \"undefined\") {\n window.addEventListener(\"resize\", update);\n return () => window.removeEventListener(\"resize\", update);\n }\n const observer = new ResizeObserver(update);\n observer.observe(node);\n return () => observer.disconnect();\n }, [node]);\n\n return [width, ref] as const;\n}\n\n// This existing helper module is already used by provider and granular selection.\n// Keeping resolved data here avoids importing provider recipes or all preset packs.\nexport const DesignProfileContext = createContext<HjmDesignProfile | undefined>(undefined);\nexport function useDesignProfileDefaults(): HjmDesignProfile | undefined {\n return useContext(DesignProfileContext);\n}\n"]}
1
+ {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\nimport type { HjmDesignProfile } from \"@hjmds/design-contracts/design-profile\";\nimport {\n createContext,\n useContext,\n useCallback,\n useEffect,\n useState,\n useSyncExternalStore,\n type AriaAttributes,\n type Dispatch,\n type Ref,\n type SetStateAction,\n} from \"react\";\n\n/** ARIA's string \"false\" is valid; grammar/spelling express invalid input just like true. */\nexport function isAriaInvalid(value: AriaAttributes[\"aria-invalid\"]): boolean {\n return value === true || (typeof value === \"string\" && value !== \"false\");\n}\n\nexport function classNames(\n ...values: readonly (string | false | null | undefined)[]\n): string | undefined {\n const result = values.filter(Boolean).join(\" \");\n return result.length > 0 ? result : undefined;\n}\n\nexport function assignRef<Element>(ref: Ref<Element> | undefined, value: Element | null): void {\n if (typeof ref === \"function\") ref(value);\n else if (ref) ref.current = value;\n}\n\nexport function composeRefs<Element>(\n ...refs: readonly (Ref<Element> | undefined)[]\n): (value: Element | null) => void {\n return (value) => {\n for (const ref of refs) assignRef(ref, value);\n };\n}\n\ntype ControllableStateOptions<Value> = Readonly<{\n value?: Value;\n defaultValue: Value;\n onChange?: (value: Value) => void;\n}>;\n\nexport function useControllableState<Value>({\n value,\n defaultValue,\n onChange,\n}: ControllableStateOptions<Value>): readonly [\n Value,\n Dispatch<SetStateAction<Value>>,\n] {\n const [internalValue, setInternalValue] = useState(defaultValue);\n const controlled = value !== undefined;\n const currentValue = controlled ? value : internalValue;\n\n const setValue: Dispatch<SetStateAction<Value>> = useCallback(\n (next) => {\n const resolved = typeof next === \"function\"\n ? (next as (previous: Value) => Value)(currentValue)\n : next;\n if (!controlled) setInternalValue(resolved);\n if (!Object.is(resolved, currentValue)) onChange?.(resolved);\n },\n [controlled, currentValue, onChange],\n );\n\n return [currentValue, setValue] as const;\n}\n\nfunction subscribeWindowResize(callback: () => void): () => void {\n window.addEventListener(\"resize\", callback);\n return () => window.removeEventListener(\"resize\", callback);\n}\n\nfunction getWindowWidth(): number {\n return window.innerWidth;\n}\n\nfunction getServerWindowWidth(): number {\n return 0;\n}\n\nexport function useWindowWidth(): number {\n return useSyncExternalStore(\n subscribeWindowResize,\n getWindowWidth,\n getServerWindowWidth,\n );\n}\n\nexport function useElementWidth<Element extends HTMLElement>(\n externalRef?: Ref<Element>,\n): readonly [number | undefined, (node: Element | null) => void] {\n const [node, setNode] = useState<Element | null>(null);\n const [width, setWidth] = useState<number>();\n const ref = useCallback(\n (nextNode: Element | null) => {\n setNode(nextNode);\n assignRef(externalRef, nextNode);\n },\n [externalRef],\n );\n\n useEffect(() => {\n if (!node) return;\n const update = () => setWidth(node.getBoundingClientRect().width);\n update();\n if (typeof ResizeObserver === \"undefined\") {\n window.addEventListener(\"resize\", update);\n return () => window.removeEventListener(\"resize\", update);\n }\n const observer = new ResizeObserver(update);\n observer.observe(node);\n return () => observer.disconnect();\n }, [node]);\n\n return [width, ref] as const;\n}\n\n// This existing helper module is already used by provider and granular selection.\n// Keeping resolved data here avoids importing provider recipes or all preset packs.\nexport const DesignProfileContext = createContext<HjmDesignProfile | undefined>(undefined);\nexport function useDesignProfileDefaults(): HjmDesignProfile | undefined {\n return useContext(DesignProfileContext);\n}\n"]}