material-plus-ui 1.3.1 → 1.5.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 (261) hide show
  1. package/.fix.py +92 -0
  2. package/README.md +2 -2
  3. package/dist/components/alert/MPAlert.d.ts +26 -0
  4. package/dist/components/alert/MPAlert.js +1 -1
  5. package/dist/components/alert/index.d.ts +1 -1
  6. package/dist/components/animate-marquee/MPAnimateMarquee.js +1 -1
  7. package/dist/components/avatar/MPAvatar.js +1 -1
  8. package/dist/components/avatar-group/MPAvatarGroup.d.ts +74 -0
  9. package/dist/components/avatar-group/MPAvatarGroup.js +2 -0
  10. package/dist/components/avatar-group/index.d.ts +2 -0
  11. package/dist/components/avatar-group/index.js +1 -0
  12. package/dist/components/breadcrumb/MPBreadcrumb.d.ts +10 -4
  13. package/dist/components/breadcrumb/MPBreadcrumb.js +1 -1
  14. package/dist/components/button/MPButton.js +1 -1
  15. package/dist/components/button-group/MPButtonGroup.d.ts +9 -0
  16. package/dist/components/button-group/MPButtonGroup.js +1 -1
  17. package/dist/components/carousel/MPCarousel.d.ts +12 -7
  18. package/dist/components/carousel/MPCarousel.js +1 -1
  19. package/dist/components/chat-bubble/MPChatBubble.d.ts +15 -2
  20. package/dist/components/chat-bubble/MPChatBubble.js +1 -1
  21. package/dist/components/checkbox/MPCheckbox.d.ts +6 -0
  22. package/dist/components/checkbox/MPCheckbox.js +1 -1
  23. package/dist/components/color-picker/MPColorPicker.d.ts +20 -17
  24. package/dist/components/color-picker/MPColorPicker.js +1 -1
  25. package/dist/components/combobox/MPCombobox.d.ts +22 -4
  26. package/dist/components/combobox/MPCombobox.js +1 -1
  27. package/dist/components/command-palette/MPCommandPalette.d.ts +132 -0
  28. package/dist/components/command-palette/MPCommandPalette.js +2 -0
  29. package/dist/components/command-palette/index.d.ts +2 -0
  30. package/dist/components/command-palette/index.js +1 -0
  31. package/dist/components/container/MPContainer.js +1 -1
  32. package/dist/components/date-time-picker/MPDateTimePicker.d.ts +5 -0
  33. package/dist/components/dialog/MPDialog.js +1 -1
  34. package/dist/components/divider/MPDivider.js +1 -1
  35. package/dist/components/drawer/MPDrawer.js +1 -1
  36. package/dist/components/fieldset/MPFieldset.d.ts +52 -0
  37. package/dist/components/fieldset/MPFieldset.js +2 -0
  38. package/dist/components/fieldset/index.d.ts +2 -0
  39. package/dist/components/fieldset/index.js +1 -0
  40. package/dist/components/file-picker/MPFilePicker.d.ts +10 -3
  41. package/dist/components/file-picker/MPFilePicker.js +1 -1
  42. package/dist/components/floating-action-button/MPFloatingActionButton.js +1 -1
  43. package/dist/components/footer/MPFooter.d.ts +94 -0
  44. package/dist/components/footer/MPFooter.js +2 -0
  45. package/dist/components/footer/index.d.ts +2 -0
  46. package/dist/components/footer/index.js +1 -0
  47. package/dist/components/form/MPForm.d.ts +73 -0
  48. package/dist/components/form/MPForm.js +2 -0
  49. package/dist/components/form/index.d.ts +2 -0
  50. package/dist/components/form/index.js +1 -0
  51. package/dist/components/header/MPHeader.d.ts +122 -0
  52. package/dist/components/header/MPHeader.js +2 -0
  53. package/dist/components/header/index.d.ts +2 -0
  54. package/dist/components/header/index.js +1 -0
  55. package/dist/components/highlight/MPHighlight.d.ts +7 -0
  56. package/dist/components/menu/MPMenu.d.ts +4 -2
  57. package/dist/components/menu/MPMenu.js +1 -1
  58. package/dist/components/menubar/MPMenubar.d.ts +89 -0
  59. package/dist/components/menubar/MPMenubar.js +2 -0
  60. package/dist/components/menubar/index.d.ts +2 -0
  61. package/dist/components/menubar/index.js +1 -0
  62. package/dist/components/navigation-menu/MPNavigationMenu.d.ts +158 -0
  63. package/dist/components/navigation-menu/MPNavigationMenu.js +2 -0
  64. package/dist/components/navigation-menu/index.d.ts +2 -0
  65. package/dist/components/navigation-menu/index.js +1 -0
  66. package/dist/components/number-field/MPNumberField.d.ts +19 -4
  67. package/dist/components/number-field/MPNumberField.js +1 -1
  68. package/dist/components/overlay/MPOverlay.d.ts +8 -2
  69. package/dist/components/overlay/MPOverlay.js +1 -1
  70. package/dist/components/page-layout/MPPageLayout.d.ts +145 -0
  71. package/dist/components/page-layout/MPPageLayout.js +2 -0
  72. package/dist/components/page-layout/index.d.ts +2 -0
  73. package/dist/components/page-layout/index.js +1 -0
  74. package/dist/components/panes/MPPanes.js +1 -1
  75. package/dist/components/popover/MPPopover.js +1 -1
  76. package/dist/components/progress-box/MPProgressBox.js +1 -1
  77. package/dist/components/progress-circular/MPProgressCircular.js +1 -1
  78. package/dist/components/progress-linear/MPProgressLinear.js +1 -1
  79. package/dist/components/radio-group/MPRadioGroup.d.ts +12 -0
  80. package/dist/components/radio-group/MPRadioGroup.js +1 -1
  81. package/dist/components/segmented-button/MPSegmentedButton.d.ts +7 -0
  82. package/dist/components/segmented-button/MPSegmentedButton.js +1 -1
  83. package/dist/components/select/MPSelect.d.ts +19 -1
  84. package/dist/components/select/MPSelect.js +1 -1
  85. package/dist/components/shortcut/MPShortcut.js +1 -1
  86. package/dist/components/sidebar/MPSidebar.d.ts +160 -0
  87. package/dist/components/sidebar/MPSidebar.js +2 -0
  88. package/dist/components/sidebar/MPSidebarTrigger.d.ts +45 -0
  89. package/dist/components/sidebar/MPSidebarTrigger.js +2 -0
  90. package/dist/components/sidebar/index.d.ts +4 -0
  91. package/dist/components/sidebar/index.js +1 -0
  92. package/dist/components/skeleton/MPSkeleton.js +1 -1
  93. package/dist/components/slider/MPSlider.d.ts +6 -0
  94. package/dist/components/slider/MPSlider.js +1 -1
  95. package/dist/components/snackbar/MPSnackbar.js +1 -1
  96. package/dist/components/switch/MPSwitch.d.ts +6 -0
  97. package/dist/components/switch/MPSwitch.js +1 -1
  98. package/dist/components/table/MPTable.d.ts +27 -5
  99. package/dist/components/table/MPTable.js +1 -1
  100. package/dist/components/text-field/MPTextField.d.ts +21 -2
  101. package/dist/components/text-field/MPTextField.js +1 -1
  102. package/dist/components/text-link/MPTextLink.d.ts +7 -1
  103. package/dist/components/text-link/MPTextLink.js +1 -1
  104. package/dist/components/time-picker/MPTimePicker.d.ts +4 -0
  105. package/dist/components/toggle/MPToggle.d.ts +72 -0
  106. package/dist/components/toggle/MPToggle.js +2 -0
  107. package/dist/components/toggle/index.d.ts +2 -0
  108. package/dist/components/toggle/index.js +1 -0
  109. package/dist/components/toggle-group/MPToggleGroup.d.ts +74 -0
  110. package/dist/components/toggle-group/MPToggleGroup.js +2 -0
  111. package/dist/components/toggle-group/index.d.ts +2 -0
  112. package/dist/components/toggle-group/index.js +1 -0
  113. package/dist/components/tooltip/MPTooltip.js +1 -1
  114. package/dist/components/transfer/MPTransfer.d.ts +98 -0
  115. package/dist/components/transfer/MPTransfer.js +2 -0
  116. package/dist/components/transfer/index.d.ts +2 -0
  117. package/dist/components/transfer/index.js +1 -0
  118. package/dist/constants/glyphs.d.ts +10 -0
  119. package/dist/constants/glyphs.js +1 -1
  120. package/dist/constants/icons.d.ts +1 -0
  121. package/dist/constants/icons.js +1 -1
  122. package/dist/index.d.ts +13 -0
  123. package/dist/index.js +1 -1
  124. package/dist/internal/Calendar.js +1 -1
  125. package/dist/internal/FieldOutline.js +1 -1
  126. package/dist/internal/SupportingText.d.ts +1 -1
  127. package/dist/internal/SupportingText.js +1 -1
  128. package/dist/internal/animate.d.ts +0 -17
  129. package/dist/internal/animate.js +1 -1
  130. package/dist/internal/avatar-group.d.ts +22 -0
  131. package/dist/internal/avatar-group.js +2 -0
  132. package/dist/internal/button-group.d.ts +20 -1
  133. package/dist/internal/button-group.js +1 -1
  134. package/dist/internal/color.d.ts +0 -5
  135. package/dist/internal/color.js +1 -1
  136. package/dist/internal/date.js +1 -1
  137. package/dist/internal/i18n.d.ts +201 -4
  138. package/dist/internal/keys.d.ts +72 -0
  139. package/dist/internal/keys.js +2 -0
  140. package/dist/internal/length.d.ts +42 -0
  141. package/dist/internal/length.js +1 -0
  142. package/dist/internal/link.d.ts +44 -0
  143. package/dist/internal/link.js +1 -0
  144. package/dist/internal/locale.d.ts +20 -1
  145. package/dist/internal/locale.js +1 -1
  146. package/dist/internal/messages/breadcrumb.d.ts +3 -0
  147. package/dist/internal/messages/breadcrumb.js +1 -0
  148. package/dist/internal/messages/carousel.d.ts +3 -0
  149. package/dist/internal/messages/carousel.js +1 -0
  150. package/dist/internal/messages/color-picker.d.ts +3 -0
  151. package/dist/internal/messages/color-picker.js +1 -0
  152. package/dist/internal/messages/combobox.d.ts +3 -0
  153. package/dist/internal/messages/combobox.js +1 -0
  154. package/dist/internal/messages/command.d.ts +3 -0
  155. package/dist/internal/messages/command.js +1 -0
  156. package/dist/internal/messages/file-picker.d.ts +3 -0
  157. package/dist/internal/messages/file-picker.js +1 -0
  158. package/dist/internal/messages/layout.d.ts +3 -0
  159. package/dist/internal/messages/layout.js +1 -0
  160. package/dist/internal/messages/number-field.d.ts +3 -0
  161. package/dist/internal/messages/number-field.js +1 -0
  162. package/dist/internal/messages/overlay.d.ts +3 -0
  163. package/dist/internal/messages/overlay.js +1 -0
  164. package/dist/internal/messages/table.d.ts +3 -0
  165. package/dist/internal/messages/table.js +1 -0
  166. package/dist/internal/messages/text-link.d.ts +3 -0
  167. package/dist/internal/messages/text-link.js +1 -0
  168. package/dist/internal/messages/transfer.d.ts +3 -0
  169. package/dist/internal/messages/transfer.js +1 -0
  170. package/dist/internal/page-layout.d.ts +182 -0
  171. package/dist/internal/page-layout.js +2 -0
  172. package/dist/internal/scale.d.ts +17 -0
  173. package/dist/internal/scale.js +1 -1
  174. package/dist/locales/ar.js +1 -1
  175. package/dist/locales/de.js +1 -1
  176. package/dist/locales/es.js +1 -1
  177. package/dist/locales/fr.js +1 -1
  178. package/dist/locales/hi.js +1 -1
  179. package/dist/locales/id.js +1 -1
  180. package/dist/locales/it.js +1 -1
  181. package/dist/locales/ja.js +1 -1
  182. package/dist/locales/ko.js +1 -1
  183. package/dist/locales/nl.js +1 -1
  184. package/dist/locales/pl.js +1 -1
  185. package/dist/locales/pt.js +1 -1
  186. package/dist/locales/ru.js +1 -1
  187. package/dist/locales/th.js +1 -1
  188. package/dist/locales/tr.js +1 -1
  189. package/dist/locales/vi.js +1 -1
  190. package/dist/locales/zh-hans.js +1 -1
  191. package/dist/locales/zh-hant.js +1 -1
  192. package/dist/styles/accordion.css +1 -1
  193. package/dist/styles/alert.css +1 -1
  194. package/dist/styles/avatar-group.css +2 -0
  195. package/dist/styles/avatar.css +1 -1
  196. package/dist/styles/badge.css +1 -1
  197. package/dist/styles/blockquote.css +1 -1
  198. package/dist/styles/bottom-navigation.css +1 -1
  199. package/dist/styles/box.css +1 -1
  200. package/dist/styles/breadcrumb.css +1 -1
  201. package/dist/styles/button-group.css +1 -1
  202. package/dist/styles/button.css +1 -1
  203. package/dist/styles/card.css +1 -1
  204. package/dist/styles/carousel.css +1 -1
  205. package/dist/styles/chat-bubble.css +1 -1
  206. package/dist/styles/checkbox.css +1 -1
  207. package/dist/styles/chip.css +1 -1
  208. package/dist/styles/collapsible.css +1 -1
  209. package/dist/styles/color-picker.css +1 -1
  210. package/dist/styles/combobox.css +1 -1
  211. package/dist/styles/command-palette.css +2 -0
  212. package/dist/styles/date-picker.css +1 -1
  213. package/dist/styles/date-range-picker.css +1 -1
  214. package/dist/styles/date-time-picker.css +1 -1
  215. package/dist/styles/dialog.css +1 -1
  216. package/dist/styles/divider.css +1 -1
  217. package/dist/styles/drawer.css +1 -1
  218. package/dist/styles/empty.css +1 -1
  219. package/dist/styles/fieldset.css +2 -0
  220. package/dist/styles/file-picker.css +1 -1
  221. package/dist/styles/floating-action-button.css +1 -1
  222. package/dist/styles/footer.css +2 -0
  223. package/dist/styles/form.css +2 -0
  224. package/dist/styles/header.css +2 -0
  225. package/dist/styles/highlight.css +1 -1
  226. package/dist/styles/icon-button.css +1 -1
  227. package/dist/styles/list.css +1 -1
  228. package/dist/styles/locale.css +1 -1
  229. package/dist/styles/menu.css +1 -1
  230. package/dist/styles/menubar.css +2 -0
  231. package/dist/styles/navigation-menu.css +2 -0
  232. package/dist/styles/number-field.css +1 -1
  233. package/dist/styles/otp-field.css +1 -1
  234. package/dist/styles/overlay.css +1 -1
  235. package/dist/styles/page-layout.css +2 -0
  236. package/dist/styles/pagination.css +1 -1
  237. package/dist/styles/panes.css +1 -1
  238. package/dist/styles/pill.css +1 -1
  239. package/dist/styles/popover.css +1 -1
  240. package/dist/styles/progress-box.css +1 -1
  241. package/dist/styles/progress-circular.css +1 -1
  242. package/dist/styles/progress-linear.css +1 -1
  243. package/dist/styles/radio-group.css +1 -1
  244. package/dist/styles/segmented-button.css +1 -1
  245. package/dist/styles/select.css +1 -1
  246. package/dist/styles/sidebar.css +2 -0
  247. package/dist/styles/skeleton.css +1 -1
  248. package/dist/styles/slider.css +1 -1
  249. package/dist/styles/spoiler.css +1 -1
  250. package/dist/styles/switch.css +1 -1
  251. package/dist/styles/table.css +1 -1
  252. package/dist/styles/tabs.css +1 -1
  253. package/dist/styles/text-field.css +1 -1
  254. package/dist/styles/text-link.css +1 -1
  255. package/dist/styles/time-picker.css +1 -1
  256. package/dist/styles/timeline.css +1 -1
  257. package/dist/styles/toggle-group.css +2 -0
  258. package/dist/styles/toggle.css +2 -0
  259. package/dist/styles/transfer.css +2 -0
  260. package/dist/styles.css +1 -1
  261. package/package.json +2 -2
package/.fix.py ADDED
@@ -0,0 +1,92 @@
1
+ import pathlib, sys
2
+ def rep(path, old, new):
3
+ p = pathlib.Path(path); s = p.read_text(encoding='utf-8')
4
+ if s.count(old) != 1: print(f'FAIL {path}: {s.count(old)}'); sys.exit(1)
5
+ p.write_text(s.replace(old, new, 1), encoding='utf-8'); print('ok ', path)
6
+
7
+ EN_OLD = """Yours is appended to the component's own, and nothing is removed to make room for it. So **two utilities setting the same property are resolved by the stylesheet rather than by which of them you wrote.**
8
+
9
+ Which one that is depends on how the styles were wired up. On the precompiled path it is whichever sheet the application imported second. On the Tailwind path both are generated in one pass, and Tailwind's own ordering decides — which is per property, and not something to work out at the call site:
10
+
11
+ | You pass | The component sets | Which one wins |
12
+ | ------------ | --------------------- | -------------- |
13
+ | `p-8` | `px-6` | the component |
14
+ | `rounded-lg` | `rounded-mp-full` | the component |
15
+ | `shadow-lg` | `shadow-mp-1` | the component |
16
+ | `text-lg` | `text-mp-label-large` | yours |
17
+ | `bg-red-500` | `bg-mp-primary` | yours |
18
+ | `h-20` | `h-14` | yours |
19
+
20
+ Read the column, not the rows: the answers are what one version of Tailwind happens to emit, and the point is that there is no rule connecting them. `className` is the right tool for what a component does **not** already set — margin, width, grid placement, position, an animation — and the wrong one for taking something over."""
21
+
22
+ EN_NEW = """Yours is appended to the component's own, and nothing is removed to make room for it. Two classes setting the same property both end up on the element, at equal specificity, and **the one that wins is the one the stylesheet happens to put last** — not the one you wrote.
23
+
24
+ A class for something the component does not already set always works. That is most of what a class is for, and there is nothing more to know about it:
25
+
26
+ ```tsx
27
+ <MPButton className="mt-4 w-full">Save</MPButton>
28
+ ```
29
+
30
+ Past that it depends on the pair. On the precompiled path it depends on which sheet the application imported second; on the Tailwind path both are generated in one pass and Tailwind's own ordering decides. Measured against this repository's own stylesheet, on an `MPButton` at the default size:
31
+
32
+ | You pass | It sets | Result |
33
+ | ---------------------------- | ------------------------ | ------- |
34
+ | `px-8` | `px-6` | applies |
35
+ | `px-2` | `px-6` | ignored |
36
+ | `h-20` | `h-14` | applies |
37
+ | `h-8` | `h-14` | ignored |
38
+ | `text-lg`, `text-xs` | `text-mp-title-medium` | applies |
39
+ | `bg-red-500` | `bg-(--_mp-accent)` | applies |
40
+ | `rounded-lg` | `rounded-mp-full` | ignored |
41
+ | `shadow-lg` | `shadow-mp-1` | ignored |
42
+ | `p-8` | `px-6` | ignored |
43
+ | any of the above with a `!` | — | applies |
44
+
45
+ The first four rows are the ones worth staring at. `px-8` works and `px-2` does not, on the same component and the same property, because Tailwind emits a scale in scale order and the larger step is therefore later — so *making a control bigger tends to work and making it smaller tends not to*. The rest is which of two theme keys Tailwind happened to sort first: the library's `--text-mp-*` land before Tailwind's own, so any `text-*` you pass wins, while `--radius-mp-*` and `--shadow-mp-*` land after, so `rounded-*` and `shadow-*` do not.
46
+
47
+ None of that is a promise. It is what one version of Tailwind emits, it is per pair rather than per property, and it can move under you when either side adds a token. Treat `className` as the tool for what the component leaves alone."""
48
+
49
+ KO_OLD = """넘긴 클래스는 컴포넌트 자신의 클래스 뒤에 붙고, 자리를 내주기 위해 지워지는 것은 없습니다. 그래서 **같은 속성을 지정하는 두 유틸리티는 어느 쪽을 썼는지가 아니라 스타일시트가 결정합니다.**
50
+
51
+ 어느 쪽이 되는지는 스타일을 어떻게 연결했는지에 달려 있습니다. 컴파일된 시트를 쓰는 경우에는 애플리케이션이 나중에 import한 시트가 이깁니다. Tailwind를 쓰는 경우에는 둘이 한 번의 패스에서 생성되고 Tailwind 자신의 정렬이 결정하는데, 그 정렬은 속성마다 다르고 호출부에서 따져볼 만한 것이 아닙니다.
52
+
53
+ | 넘긴 것 | 컴포넌트가 지정한 것 | 이기는 쪽 |
54
+ | --- | --- | --- |
55
+ | `p-8` | `px-6` | 컴포넌트 |
56
+ | `rounded-lg` | `rounded-mp-full` | 컴포넌트 |
57
+ | `shadow-lg` | `shadow-mp-1` | 컴포넌트 |
58
+ | `text-lg` | `text-mp-label-large` | 넘긴 쪽 |
59
+ | `bg-red-500` | `bg-mp-primary` | 넘긴 쪽 |
60
+ | `h-20` | `h-14` | 넘긴 쪽 |
61
+
62
+ 행이 아니라 열을 보세요. 이 답들은 어떤 한 버전의 Tailwind가 그렇게 내놓은 것일 뿐이고, 요점은 이들을 이어 주는 규칙이 없다는 것입니다. `className`은 컴포넌트가 **지정하지 않은** 것 — 마진, 너비, 그리드 배치, 위치, 애니메이션 — 에 쓰는 도구이고, 이미 지정된 것을 가져오는 데 쓰는 도구가 아닙니다."""
63
+
64
+ KO_NEW = """넘긴 클래스는 컴포넌트 자신의 클래스 뒤에 붙고, 자리를 내주기 위해 지워지는 것은 없습니다. 같은 속성을 지정하는 두 클래스가 같은 명시도로 엘리먼트에 함께 올라가고, **이기는 쪽은 스타일시트가 뒤에 놓은 쪽입니다.** 어느 쪽을 썼는지가 아닙니다.
65
+
66
+ 컴포넌트가 지정하지 않은 것에 대한 클래스는 언제나 적용됩니다. 클래스로 하려는 일의 대부분이 이것이고, 여기에 더 알아야 할 것은 없습니다.
67
+
68
+ ```tsx
69
+ <MPButton className="mt-4 w-full">저장</MPButton>
70
+ ```
71
+
72
+ 그 너머는 짝에 따라 다릅니다. 컴파일된 시트를 쓰는 경우에는 애플리케이션이 나중에 import한 시트가 이기고, Tailwind를 쓰는 경우에는 둘이 한 번의 패스에서 생성되어 Tailwind 자신의 정렬이 결정합니다. 이 저장소의 시트로, 기본 크기의 `MPButton`에 대고 실제로 측정한 결과입니다.
73
+
74
+ | 넘긴 것 | 컴포넌트가 지정한 것 | 결과 |
75
+ | --- | --- | --- |
76
+ | `px-8` | `px-6` | 적용됨 |
77
+ | `px-2` | `px-6` | 무시됨 |
78
+ | `h-20` | `h-14` | 적용됨 |
79
+ | `h-8` | `h-14` | 무시됨 |
80
+ | `text-lg`, `text-xs` | `text-mp-title-medium` | 적용됨 |
81
+ | `bg-red-500` | `bg-(--_mp-accent)` | 적용됨 |
82
+ | `rounded-lg` | `rounded-mp-full` | 무시됨 |
83
+ | `shadow-lg` | `shadow-mp-1` | 무시됨 |
84
+ | `p-8` | `px-6` | 무시됨 |
85
+ | 위의 어느 것이든 `!`를 붙이면 | — | 적용됨 |
86
+
87
+ 들여다볼 만한 것은 처음 네 줄입니다. 같은 컴포넌트, 같은 속성인데 `px-8`은 되고 `px-2`는 안 됩니다. Tailwind가 스케일을 스케일 순서로 내놓기 때문에 더 큰 단계가 더 뒤에 오고, 그래서 *컨트롤을 키우는 쪽은 대체로 되고 줄이는 쪽은 대체로 안 됩니다*. 나머지는 두 테마 키 중 어느 쪽을 Tailwind가 먼저 정렬했는가의 문제입니다. 이 라이브러리의 `--text-mp-*`는 Tailwind 자신의 것보다 앞에 놓이므로 넘긴 `text-*`가 이기고, `--radius-mp-*`와 `--shadow-mp-*`는 뒤에 놓이므로 `rounded-*`와 `shadow-*`는 지지 않고 집니다.
88
+
89
+ 이 중 무엇도 약속이 아닙니다. 어떤 한 버전의 Tailwind가 내놓은 결과이고, 속성 단위가 아니라 짝 단위이며, 양쪽 중 어느 한쪽이 토큰을 추가하면 발밑에서 움직일 수 있습니다. `className`은 컴포넌트가 건드리지 않는 것에 쓰는 도구로 두세요."""
90
+
91
+ rep('docs/en/guide/getting-started.md', EN_OLD, EN_NEW)
92
+ rep('docs/ko/guide/getting-started.md', KO_OLD, KO_NEW)
package/README.md CHANGED
@@ -23,7 +23,7 @@ It follows the specification directly rather than wrapping somebody's implementa
23
23
  - **IME-safe by construction.** Korean, Japanese and Chinese composition survives whatever your `onChange` does with the value.
24
24
  - **Bring your own icons.** `MPIcon` takes a component or an element from any set. `lucide-react` ships with the package, gathered in one readable constants file.
25
25
  - **Works in a Next.js server component**, and in any bundler: the components carry `"use client"`, the barrel and the data do not, and every specifier in `dist/` names a file — so webpack, Vite, esbuild, Rollup and plain Node all resolve it.
26
- - **ESM only**, TypeScript declarations included, and tree-shakeable for real: one component is 2.9 kB gzipped and five are 7.3 kB, against 64 kB for all ninety-four. `npm run measure` prints those numbers off a real bundler, so they cannot quietly stop being true. The stylesheet splits the same way.
26
+ - **ESM only**, TypeScript declarations included, and tree-shakeable for real: one component is 2.9 kB gzipped and five are 7.4 kB, against 74 kB for all hundred and eleven. `npm run measure` prints those numbers off a real bundler, so they cannot quietly stop being true. The stylesheet splits the same way.
27
27
  - **One runtime dependency.** React 18 or 19, Node.js 22 or later.
28
28
 
29
29
  ## Documentation
@@ -74,7 +74,7 @@ If Tailwind v4 is already in your project, import the token sheet instead:
74
74
  @import 'material-plus-ui/tailwind.css';
75
75
  ```
76
76
 
77
- A page that renders a handful of components can take the tokens and a sheet each instead of the whole 109 kB — 3.8 kB gzipped for one component against 15.6 kB for the lot. [The guide](https://material-plus.cdget.com/guide/getting-started#if-you-only-render-a-few-components) has the numbers and where the two paths cross.
77
+ A page that renders a handful of components can take the tokens and a sheet each instead of the whole 113 kB — 4.5 kB gzipped for one component against 16.1 kB for the lot. [The guide](https://material-plus.cdget.com/guide/getting-started#if-you-only-render-a-few-components) has the numbers and where the two paths cross.
78
78
 
79
79
  ```ts
80
80
  import 'material-plus-ui/styles/tokens.css';
@@ -1,5 +1,20 @@
1
1
  import * as React from 'react';
2
2
  import type { MPColor, MPSize, MPVariant } from '../../types.js';
3
+ /**
4
+ * How loudly an alert announces itself.
5
+ *
6
+ * - `assertive` — interrupts whatever a screen reader is in the middle of
7
+ * saying. `role="alert"`.
8
+ * - `polite` — waits for a pause. `role="status"`.
9
+ * - `off` — announces nothing, and is read only by somebody who walks into it.
10
+ *
11
+ * The third is the one worth knowing about. A live region is for content that
12
+ * *arrives*, and an alert that was on the page when it loaded did not arrive —
13
+ * it is part of the page, and interrupting to read it is interrupting to say
14
+ * something the reader was going to reach anyway. A form's list of errors on a
15
+ * server-rendered page is exactly that case.
16
+ */
17
+ export type MPAlertLive = 'assertive' | 'polite' | 'off';
3
18
  export interface MPAlertProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'title'> {
4
19
  /**
5
20
  * How much surface the alert paints.
@@ -50,6 +65,17 @@ export interface MPAlertProps extends Omit<React.ComponentPropsWithoutRef<'div'>
50
65
  * `children` so it stays on the first line while the message wraps.
51
66
  */
52
67
  action?: React.ReactNode;
68
+ /**
69
+ * How loudly it announces itself.
70
+ *
71
+ * Defaults to `assertive` for the `error` family and `polite` for the other
72
+ * three, which is the right split for a message that *appeared*. Reach for
73
+ * `off` when the alert was on the page before the reader was: an error summary
74
+ * rendered by the server is not news, and a screen reader interrupting itself
75
+ * to read it is interrupting to say something the reader was about to reach on
76
+ * their own.
77
+ */
78
+ live?: MPAlertLive;
53
79
  /** Passing it is what makes the dismiss button appear. */
54
80
  onClose?: (event: React.MouseEvent<HTMLButtonElement>) => void;
55
81
  /**
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as n from"react";import{MPIcon as r}from"../icon/MPIcon.js";import{CloseIcon as a,ErrorIcon as l,InfoIcon as o}from"../../constants/icons.js";import{accentSlots as i}from"../../internal/accent.js";import{useMPLocale as s,useMPMessages as c}from"../../internal/locale.js";import{ALERT as m}from"../../internal/messages/alert.js";import{MPStateLayer as d}from"../../internal/StateLayer.js";import{CONTROL_ICON as f,hasContent as p,PROSE_TEXT as u,SHEET_GAP as x,SHEET_PAD as h,SHEET_TITLE as v,STACK_GAP as b}from"../../internal/scale.js";const j={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"shadow-mp-1 bg-mp-surface-container-low text-mp-on-surface",outlined:"border-mp-outline border bg-transparent text-mp-on-surface",text:"bg-transparent text-mp-on-surface"},y={filled:"",tonal:"",elevated:"text-(--_mp-accent)",outlined:"text-(--_mp-accent)",text:"text-(--_mp-accent)"},N={filled:"",tonal:"",elevated:"text-mp-on-surface-variant",outlined:"text-mp-on-surface-variant",text:"text-mp-on-surface-variant"},g={primary:"status",secondary:"status",tertiary:"status",error:"alert"};export const MPAlert=/*@__PURE__*/n.forwardRef(function({variant:n="tonal",color:_="primary",size:w="md",title:z,icon:k,action:B,onClose:C,closeLabel:L,locale:M,className:P,style:A,children:I,...R},S){const $=s(M),q=c(m,$),D=y[n],E=p(z),F=void 0===k?e(r,{icon:"error"===_?l:o,size:f[w]}):k;return t("div",{ref:S,role:g[_],"data-mp-size":w,"data-mp-variant":n,className:["mp-alert rounded-mp-md flex w-full items-start","box-border",h[w],x[w],u[w],j[n],P??""].filter(Boolean).join(" "),style:{...i(_),...A},...R,children:[p(F)?e("span",{className:["flex h-[1lh] shrink-0 items-center",D].filter(Boolean).join(" "),children:F}):null,t("div",{className:`flex min-w-0 flex-1 flex-col ${b[w]}`,children:[E?e("div",{className:[v[w],D].filter(Boolean).join(" "),children:z}):null,p(I)?e("div",{className:E?N[n]:void 0,children:I}):null]}),p(B)?e("div",{className:"flex h-[1lh] shrink-0 items-center",children:B}):null,C?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:t("button",{type:"button","aria-label":L??q.dismiss,onClick:C,className:["group rounded-mp-full relative -m-1 flex size-8 cursor-pointer items-center","justify-center bg-transparent text-inherit","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid outline-none"].join(" "),children:[e(d,{}),e(r,{icon:a,size:f[w]})]})}):null]})});
2
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as n from"react";import{MPIcon as r}from"../icon/MPIcon.js";import{CloseIcon as l,ErrorIcon as i,InfoIcon as o}from"../../constants/icons.js";import{accentSlots as a}from"../../internal/accent.js";import{useMPLocale as s,useMPMessages as c}from"../../internal/locale.js";import{ALERT as m}from"../../internal/messages/alert.js";import{MPStateLayer as p}from"../../internal/StateLayer.js";import{CONTROL_ICON as f,hasContent as d,PROSE_TEXT as u,SHEET_GAP as x,SHEET_PAD as v,SHEET_TITLE as h,STACK_GAP as b}from"../../internal/scale.js";const j={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"shadow-mp-1 bg-mp-surface-container-low text-mp-on-surface",outlined:"border-mp-outline border bg-transparent text-mp-on-surface",text:"bg-transparent text-mp-on-surface"},y={filled:"",tonal:"",elevated:"text-(--_mp-accent)",outlined:"text-(--_mp-accent)",text:"text-(--_mp-accent)"},N={filled:"",tonal:"",elevated:"text-mp-on-surface-variant",outlined:"text-mp-on-surface-variant",text:"text-mp-on-surface-variant"},g={primary:"polite",secondary:"polite",tertiary:"polite",error:"assertive"},_={assertive:"alert",polite:"status",off:void 0};export const MPAlert=/*@__PURE__*/n.forwardRef(function({variant:n="tonal",color:w="primary",size:z="md",title:k,icon:B,action:C,live:L,onClose:M,closeLabel:P,locale:A,className:I,style:R,children:S,...$},q){const D=s(A),E=c(m,D),F=y[n],G=d(k),H=void 0===B?e(r,{icon:"error"===w?i:o,size:f[z]}):B;return t("div",{ref:q,role:_[L??g[w]],"data-mp-size":z,"data-mp-variant":n,className:["mp-alert rounded-mp-md flex w-full items-start","box-border",v[z],x[z],u[z],j[n],I??""].filter(Boolean).join(" "),style:{...a(w),...R},...$,children:[d(H)?e("span",{className:["flex h-[1lh] shrink-0 items-center",F].filter(Boolean).join(" "),children:H}):null,t("div",{className:`flex min-w-0 flex-1 flex-col ${b[z]}`,children:[G?e("div",{className:[h[z],F].filter(Boolean).join(" "),children:k}):null,d(S)?e("div",{className:G?N[n]:void 0,children:S}):null]}),d(C)?e("div",{className:"flex h-[1lh] shrink-0 items-center",children:C}):null,M?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:t("button",{type:"button","aria-label":P??E.dismiss,onClick:M,className:["group rounded-mp-full relative -m-1 flex size-8 cursor-pointer items-center","justify-center bg-transparent text-inherit","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid outline-none"].join(" "),children:[e(p,{}),e(r,{icon:l,size:f[z]})]})}):null]})});
@@ -1,2 +1,2 @@
1
1
  export { MPAlert } from './MPAlert.js';
2
- export type { MPAlertProps } from './MPAlert.js';
2
+ export type { MPAlertLive, MPAlertProps } from './MPAlert.js';
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e}from"react/jsx-runtime";import*as r from"react";import{easingValue as t,isInfinite as a,lengthValue as n,repeatValue as i,useAnimationRun as o}from"../../internal/animate.js";export const MPAnimateMarquee=/*@__PURE__*/r.forwardRef(function({duration:s,delay:m=0,easing:p,repeat:u="infinite",alternate:l,paused:c,trigger:d="mount",play:f,once:h=!0,threshold:v=.2,orientation:g="horizontal",reverse:y=!1,speed:_=60,gap:q="2rem",copies:R=2,pauseOnHover:b=!0,className:j,style:x,children:M,...w},z){const N=o({trigger:d,play:f,once:h,threshold:v,paused:c,infinite:a(u)}),O=r.useRef(null),A=r.useRef(null),[G,H]=r.useState(0),S="vertical"===g;r.useEffect(()=>{const e=O.current,r=A.current;if(!e||!r)return;const t=()=>{const t=getComputedStyle(e),a=parseFloat(S?t.rowGap:t.columnGap)||0,n=S?r.offsetHeight:r.offsetWidth;H(n+a)};if(t(),"undefined"==typeof ResizeObserver)return;const a=new ResizeObserver(t);return a.observe(r),a.observe(e),()=>a.disconnect()},[S,M]);const $=s??(G>0?G/_*1e3:12e3);return e("div",{ref:e=>{O.current=e,N.ref(e),"function"==typeof z?z(e):z&&(z.current=e)},className:["mp-marquee",S?"mp-marquee-vertical":"",j??""].filter(Boolean).join(" "),style:{"--_mp-anim-gap":n(q),...p?{"--_mp-anim-ease":t(p)}:{},"--_mp-anim-duration":`${Math.round($)}ms`,"--_mp-anim-delay":`${m}ms`,"--_mp-anim-repeat":i(u),"--_mp-anim-direction":y?l?"alternate-reverse":"reverse":l?"alternate":"normal","--_mp-anim-state":N.state,...x},"data-mp-animation":"marquee","data-mp-state":N.state,"data-mp-pause-on-hover":b?"":void 0,...N.handlers,...w,children:Array.from({length:Math.max(1,R)},(r,t)=>(r=>e("div",{ref:0===r?A:void 0,className:"mp-marquee-track","aria-hidden":0===r?void 0:"true",children:M},r))(t))})});
2
+ import{jsx as e}from"react/jsx-runtime";import*as r from"react";import{easingValue as t,isInfinite as a,lengthValue as n,repeatValue as i,useAnimationRun as o}from"../../internal/animate.js";import{inertProps as s}from"../../internal/inert.js";export const MPAnimateMarquee=/*@__PURE__*/r.forwardRef(function({duration:m,delay:p=0,easing:l,repeat:u="infinite",alternate:c,paused:d,trigger:f="mount",play:h,once:v=!0,threshold:g=.2,orientation:y="horizontal",reverse:_=!1,speed:j=60,gap:q="2rem",copies:R=2,pauseOnHover:b=!0,className:x,style:M,children:w,...z},N){const O=o({trigger:f,play:h,once:v,threshold:g,paused:d,infinite:a(u)}),A=r.useRef(null),G=r.useRef(null),[H,S]=r.useState(0),$="vertical"===y;r.useEffect(()=>{const e=A.current,r=G.current;if(!e||!r)return;const t=()=>{const t=getComputedStyle(e),a=parseFloat($?t.rowGap:t.columnGap)||0,n=$?r.offsetHeight:r.offsetWidth;S(n+a)};if(t(),"undefined"==typeof ResizeObserver)return;const a=new ResizeObserver(t);return a.observe(r),a.observe(e),()=>a.disconnect()},[$,w]);const k=m??(H>0?H/j*1e3:12e3);return e("div",{ref:e=>{A.current=e,O.ref(e),"function"==typeof N?N(e):N&&(N.current=e)},className:["mp-marquee",$?"mp-marquee-vertical":"",x??""].filter(Boolean).join(" "),style:{"--_mp-anim-gap":n(q),...l?{"--_mp-anim-ease":t(l)}:{},"--_mp-anim-duration":`${Math.round(k)}ms`,"--_mp-anim-delay":`${p}ms`,"--_mp-anim-repeat":i(u),"--_mp-anim-direction":_?c?"alternate-reverse":"reverse":c?"alternate":"normal","--_mp-anim-state":O.state,...M},"data-mp-animation":"marquee","data-mp-state":O.state,"data-mp-pause-on-hover":b?"":void 0,...O.handlers,...z,children:Array.from({length:Math.max(1,R)},(r,t)=>(r=>e("div",{ref:0===r?G:void 0,className:"mp-marquee-track","aria-hidden":0===r?void 0:"true",...s(0!==r),children:w},r))(t))})});
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as t from"react";import{Avatar as n}from"@base-ui/react/avatar";import{accentSlots as r}from"../../internal/accent.js";import{CONTROL_SQUARE as l,hasContent as i}from"../../internal/scale.js";import{VISUALLY_HIDDEN as o}from"../../internal/visually-hidden.js";const s={xs:"text-mp-label-medium",sm:"text-mp-label-large",md:"text-mp-title-large",lg:"text-mp-headline-small",xl:"text-mp-headline-medium"},m={xs:"rounded-mp-xs",sm:"rounded-mp-sm",md:"rounded-mp-md",lg:"rounded-mp-md",xl:"rounded-mp-md"},c={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"shadow-mp-1 bg-mp-surface-container-low text-(--_mp-accent)",outlined:"border-mp-outline border bg-transparent text-(--_mp-accent)",text:"text-mp-on-surface-variant bg-transparent"};function d(){return a("svg",{viewBox:"0 0 24 24",fill:"currentColor","aria-hidden":"true",className:"size-[60%]",children:[e("path",{d:"M12 12a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9Z"}),e("path",{d:"M12 14.25c-4.28 0-7.75 2.42-7.75 5.4 0 .75.6 1.35 1.35 1.35h12.8c.75 0 1.35-.6 1.35-1.35 0-2.98-3.47-5.4-7.75-5.4Z"})]})}export const MPAvatar=/*@__PURE__*/t.forwardRef(function({src:t,srcSet:p,alt:u,name:f,initials:h,shape:x="circle",variant:g="tonal",size:v="md",color:b="primary",delay:j,imageProps:y,onLoadingStatusChange:N,className:w,style:z,children:_,...C},A){const B=f?function(e){const a=e.normalize("NFC").trim().split(/\s+/).filter(Boolean);return 0===a.length?"":((Array.from(a[0])[0]??"")+(a.length>1?Array.from(a[a.length-1])[0]??"":"")).toLocaleUpperCase()}(f):"",S=u??f,L=i(_)?_:(h??B)||e(d,{}),M=i(_)||Boolean(h??B),k=["mp-avatar relative inline-flex shrink-0 items-center justify-center overflow-hidden","align-middle leading-none font-medium whitespace-nowrap select-none",l[v],s[v],"circle"===x?"rounded-mp-full":m[v],c[g],w??""].filter(Boolean).join(" ");return a(n.Root,{ref:A,"data-mp-size":v,"data-mp-variant":g,className:k,style:{...r(b),...z},...C,children:[t?e(n.Image,{src:t,srcSet:p,alt:S??"",onLoadingStatusChange:N,...y,className:"size-full object-cover"}):null,a(n.Fallback,{delay:t?j:void 0,className:"flex size-full items-center justify-center",children:[S&&M?e("span",{className:o,children:S}):null,e("span",{"aria-hidden":!(!S||!M)||void 0,className:"contents",children:L})]})]})});
2
+ import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as t from"react";import{Avatar as n}from"@base-ui/react/avatar";import{accentSlots as r}from"../../internal/accent.js";import{MPAvatarGroupContext as l}from"../../internal/avatar-group.js";import{CONTROL_SQUARE as i,hasContent as o}from"../../internal/scale.js";import{VISUALLY_HIDDEN as s}from"../../internal/visually-hidden.js";const m={xs:"text-mp-label-medium",sm:"text-mp-label-large",md:"text-mp-title-large",lg:"text-mp-headline-small",xl:"text-mp-headline-medium"},c={xs:"rounded-mp-xs",sm:"rounded-mp-sm",md:"rounded-mp-md",lg:"rounded-mp-md",xl:"rounded-mp-md"},d={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"shadow-mp-1 bg-mp-surface-container-low text-(--_mp-accent)",outlined:"border-mp-outline border bg-transparent text-(--_mp-accent)",text:"text-mp-on-surface-variant bg-transparent"};function p(){return a("svg",{viewBox:"0 0 24 24",fill:"currentColor","aria-hidden":"true",className:"size-[60%]",children:[e("path",{d:"M12 12a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9Z"}),e("path",{d:"M12 14.25c-4.28 0-7.75 2.42-7.75 5.4 0 .75.6 1.35 1.35 1.35h12.8c.75 0 1.35-.6 1.35-1.35 0-2.98-3.47-5.4-7.75-5.4Z"})]})}export const MPAvatar=/*@__PURE__*/t.forwardRef(function({src:u,srcSet:f,alt:h,name:x,initials:g,shape:v,variant:b,size:j,color:y,delay:N,imageProps:w,onLoadingStatusChange:z,className:C,style:_,children:A,...B},S){const L=t.useContext(l),M=v??L?.shape??"circle",k=b??L?.variant??"tonal",F=j??L?.size??"md",P=y??L?.color??"primary",R=x?function(e){const a=e.normalize("NFC").trim().split(/\s+/).filter(Boolean);return 0===a.length?"":((Array.from(a[0])[0]??"")+(a.length>1?Array.from(a[a.length-1])[0]??"":"")).toLocaleUpperCase()}(x):"",Z=h??x,I=o(A)?A:(g??R)||e(p,{}),U=o(A)||Boolean(g??R),q=["mp-avatar relative inline-flex shrink-0 items-center justify-center overflow-hidden","align-middle leading-none font-medium whitespace-nowrap select-none",i[F],m[F],"circle"===M?"rounded-mp-full":c[F],d[k],C??""].filter(Boolean).join(" ");return a(n.Root,{ref:S,"data-mp-size":F,"data-mp-variant":k,className:q,style:{...r(P),..._},...B,children:[u?e(n.Image,{src:u,srcSet:f,alt:Z??"",onLoadingStatusChange:z,...w,className:"size-full object-cover"}):null,a(n.Fallback,{delay:u?N:void 0,className:"flex size-full items-center justify-center",children:[Z&&U?e("span",{className:s,children:Z}):null,e("span",{"aria-hidden":!(!Z||!U)||void 0,className:"contents",children:I})]})]})});
@@ -0,0 +1,74 @@
1
+ import * as React from 'react';
2
+ import { type MPAvatarShape } from '../avatar/MPAvatar.js';
3
+ import type { MPColor, MPSize, MPVariant } from '../../types.js';
4
+ export interface MPAvatarGroupProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color'> {
5
+ /**
6
+ * How many avatars are drawn before the rest become a count. Left out, every
7
+ * one of them is drawn.
8
+ */
9
+ max?: number;
10
+ /**
11
+ * How many there are altogether, when the group was handed only the first few.
12
+ *
13
+ * Without it the count is worked out from the children, which is right only
14
+ * when all of them were passed — and a list of forty faces that ships four
15
+ * `<img>`s and a number is exactly why this prop exists.
16
+ */
17
+ total?: number;
18
+ /**
19
+ * How far each avatar sits under the one before it — a number in pixels, or
20
+ * any CSS length. Left out it is a fraction of `size`, which keeps the overlap
21
+ * looking the same at every rung.
22
+ */
23
+ overlap?: number | string;
24
+ /**
25
+ * Passed to every avatar in the group.
26
+ * @default 'md'
27
+ */
28
+ size?: MPSize;
29
+ /**
30
+ * Passed to every avatar in the group.
31
+ * @default 'circle'
32
+ */
33
+ shape?: MPAvatarShape;
34
+ /**
35
+ * Passed to every avatar in the group.
36
+ * @default 'tonal'
37
+ */
38
+ variant?: MPVariant;
39
+ /**
40
+ * Passed to every avatar in the group.
41
+ * @default 'primary'
42
+ */
43
+ color?: MPColor;
44
+ /** The avatars. */
45
+ children?: React.ReactNode;
46
+ }
47
+ /**
48
+ * A stack of avatars, overlapping, with the ones that did not fit as a count.
49
+ *
50
+ * `size`, `shape`, `variant` and `color` are set once here rather than on every
51
+ * avatar — a stack whose fourth face is a rung out is not a stack — and an
52
+ * avatar's own prop still wins, which is what lets one of them be marked out
53
+ * from the rest.
54
+ *
55
+ * ## The ring is not decoration
56
+ *
57
+ * Two circles of similar tone laid over each other have no edge between them at
58
+ * all, and the stack reads as one smeared shape. The ring is drawn in the page's
59
+ * own `surface`, so it is the background showing through rather than a colour of
60
+ * its own — which is what puts the near avatar in front instead of putting a
61
+ * white line on it.
62
+ *
63
+ * `isolate` on the group is the other half: it makes the first avatar's ring
64
+ * paint against the page rather than against whatever the group happens to be
65
+ * stacked over.
66
+ *
67
+ * ## The first avatar is on top
68
+ *
69
+ * The order is the DOM order, and each avatar is drawn under the one before it.
70
+ * A stack read from the start is therefore read front to back, so the person the
71
+ * group is *about* comes first rather than last — and under RTL the whole thing
72
+ * flips on its own, because the overlap is a logical margin.
73
+ */
74
+ export declare const MPAvatarGroup: React.ForwardRefExoticComponent<MPAvatarGroupProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ import{jsx as r,jsxs as a}from"react/jsx-runtime";import*as e from"react";import{MPAvatar as t}from"../avatar/MPAvatar.js";import{MPAvatarGroupContext as i}from"../../internal/avatar-group.js";const o={xs:"0.625rem",sm:"0.75rem",md:"1.125rem",lg:"1.25rem",xl:"1.5rem"};export const MPAvatarGroup=/*@__PURE__*/e.forwardRef(function({max:l,total:m,overlap:n,size:s="md",shape:c="circle",variant:p="tonal",color:v="primary",className:d,style:f,children:h,...u},x){const g=e.useMemo(()=>({size:s,shape:c,variant:p,color:v}),[s,c,p,v]),j=e.Children.toArray(h),y=void 0===l?j:j.slice(0,Math.max(0,l)),M=m??j.length,z=Math.max(0,M-y.length);return r(i.Provider,{value:g,children:a("div",{ref:x,"data-mp-size":s,className:["mp-avatar-group isolate inline-flex items-center align-middle","[&>*:not(:first-child)]:[margin-inline-start:calc(var(--_mp-avatar-overlap)*-1)]","ring-mp-surface [&>*]:ring-2",d??""].filter(Boolean).join(" "),style:{"--_mp-avatar-overlap":void 0===n?o[s]:"number"==typeof n?`${n}px`:n,...f},...u,children:[y,z>0?r(t,{initials:`+${z}`}):null]})})});
@@ -0,0 +1,2 @@
1
+ export { MPAvatarGroup } from './MPAvatarGroup.js';
2
+ export type { MPAvatarGroupProps } from './MPAvatarGroup.js';
@@ -0,0 +1 @@
1
+ export{MPAvatarGroup}from"./MPAvatarGroup.js";
@@ -45,15 +45,21 @@ export interface MPBreadcrumbProps extends Omit<React.ComponentPropsWithoutRef<'
45
45
  */
46
46
  expandable?: boolean;
47
47
  /**
48
- * The name the trail is announced by.
49
- * @default 'Breadcrumb'
48
+ * The name the trail is announced by. Defaults to the word for it in `locale`.
50
49
  */
51
50
  label?: string;
52
51
  /**
53
- * What the `…` is announced as.
54
- * @default 'Show hidden steps'
52
+ * What the `…` is announced as. Defaults to the wording in `locale`.
55
53
  */
56
54
  expandLabel?: string;
55
+ /**
56
+ * Which language those two are written in. Falls back to the nearest
57
+ * `MPLocaleProvider`, then to English.
58
+ *
59
+ * Neither is ever drawn — the steps are the caller's own words — so without it
60
+ * a Korean page announces its trail in English.
61
+ */
62
+ locale?: string;
57
63
  /**
58
64
  * Publishes the trail as schema.org `BreadcrumbList` microdata, which is what
59
65
  * a search engine reads to draw the trail under a result instead of the bare
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e,jsxs as n,Fragment as t}from"react/jsx-runtime";import*as r from"react";import{MPIcon as o}from"../icon/MPIcon.js";import{ArrowRightIcon as i,ChevronRightIcon as a,MoreIcon as s}from"../../constants/icons.js";import{accentSlots as l}from"../../internal/accent.js";import{CONTROL_GAP as c,hasContent as m,PROSE_TEXT as d}from"../../internal/scale.js";const u=/*@__PURE__*/r.createContext({size:"md",last:!1,position:null}),p={xs:"gap-1",sm:"gap-1.5",md:"gap-2",lg:"gap-2.5",xl:"gap-3"},h={xs:"rounded-mp-xs",sm:"rounded-mp-xs",md:"rounded-mp-xs",lg:"rounded-mp-sm",xl:"rounded-mp-sm"};const f=["chevron","arrow","slash","dot"];export const MPBreadcrumb=/*@__PURE__*/r.forwardRef(function({size:t="md",color:c="primary",separator:m="chevron",maxItems:h,itemsBeforeCollapse:x=1,itemsAfterCollapse:b=1,expandable:v=!0,label:g="Breadcrumb",expandLabel:N="Show hidden steps",structuredData:y=!1,className:j,style:k,children:B,...w},z){const[C,P]=r.useState(!1),M=r.Children.toArray(B).filter(r.isValidElement),I=M.length,S=M.some(e=>!0===e.props.current),L=!C&&!y&&void 0!==h&&I>Math.max(h,1)&&I-x-b>1?[...M.slice(0,Math.max(0,x)),null,...M.slice(I-Math.max(0,b))]:M,_="string"==typeof(A=m)&&f.includes(A)?function(n){switch(n){case"chevron":return e(o,{icon:a,size:"1.1em",className:"rtl:rotate-180"});case"arrow":return e(o,{icon:i,size:"1em",className:"rtl:rotate-180"});case"slash":return e("span",{"aria-hidden":"true",children:"/"});case"dot":return e("span",{"aria-hidden":"true",children:"·"});default:return null}}(m):m;var A;const E=r.useMemo(()=>Array.from({length:L.length},(e,n)=>({size:t,last:!S&&n===L.length-1,position:y?n+1:null})),[t,S,L.length,y]),F=["rounded-mp-xs text-mp-on-surface-variant inline-flex items-center px-0.5","appearance-none border-0 bg-transparent font-[inherit]","transition-[background-color,color] duration-(--mp-sys-motion-duration-short4)",v?["cursor-pointer hover:bg-(--_mp-accent-container) hover:text-(--_mp-on-accent-container)","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-1","focus-visible:outline-solid outline-none"].join(" "):""].filter(Boolean).join(" ");return e("nav",{ref:z,"aria-label":g,"data-mp-size":t,className:["mp-breadcrumb flex",d[t],j??""].filter(Boolean).join(" "),style:{...l(c),...k},...w,children:e("ol",{role:"list",itemScope:y||void 0,itemType:y?"https://schema.org/BreadcrumbList":void 0,className:`flex list-none flex-wrap items-center p-0 ${p[t]}`,children:L.map((t,i)=>n(r.Fragment,{children:[i>0?e("li",{"aria-hidden":"true",className:"text-mp-on-surface-variant flex shrink-0 items-center select-none",children:_}):null,t?e(u.Provider,{value:E[i],children:t}):e("li",{className:"flex shrink-0 items-center",children:v?e("button",{type:"button",className:F,"aria-label":N,onClick:()=>P(!0),children:e(o,{icon:s,size:"1.1em"})}):e("span",{className:F,"aria-hidden":"true",children:e(o,{icon:s,size:"1.1em"})})})]},t?t.key??i:"fold"))})})});export const MPBreadcrumbItem=/*@__PURE__*/r.forwardRef(function({href:o,onClick:i,startIcon:a,endIcon:s,current:l,disabled:d=!1,className:p,children:f,...x},b){const{size:v,last:g,position:N}=r.useContext(u),y=l??g,j=Boolean(o||i)&&!y&&!d,k=null!==N,B=["inline-flex min-w-0 items-center px-1 no-underline","appearance-none border-0 bg-transparent font-[inherit] text-[inherit]",c[v],h[v],"transition-[background-color,color] duration-(--mp-sys-motion-duration-short4)",d?"text-mp-on-surface/38 cursor-default":y?"text-mp-on-surface font-medium":j?["text-mp-on-surface-variant cursor-pointer","hover:bg-(--_mp-accent-container) hover:text-(--_mp-on-accent-container)","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-1","focus-visible:outline-solid outline-none"].join(" "):"text-mp-on-surface-variant"].filter(Boolean).join(" "),w=n(t,{children:[m(a)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:a}):null,e("span",{className:"truncate",itemProp:k?"name":void 0,children:f}),m(s)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:s}):null]});return n("li",{ref:b,itemProp:k?"itemListElement":void 0,itemScope:k||void 0,itemType:k?"https://schema.org/ListItem":void 0,className:["flex min-w-0 items-center",p??""].filter(Boolean).join(" "),...x,children:[k?e("meta",{itemProp:"position",content:String(N)}):null,j&&o?e("a",{href:o,itemProp:k?"item":void 0,className:B,onClick:i,children:w}):j?e("button",{type:"button",className:B,onClick:i,children:w}):e("span",{className:B,"aria-current":y?"page":void 0,"aria-disabled":d||void 0,children:w})]})});
2
+ import{jsx as e,jsxs as n,Fragment as t}from"react/jsx-runtime";import*as r from"react";import{MPIcon as o}from"../icon/MPIcon.js";import{ArrowRightIcon as i,ChevronRightIcon as a,MoreIcon as s}from"../../constants/icons.js";import{accentSlots as l}from"../../internal/accent.js";import{useMPLocale as c,useMPMessages as m}from"../../internal/locale.js";import{BREADCRUMB as d}from"../../internal/messages/breadcrumb.js";import{CONTROL_GAP as u,hasContent as p,PROSE_TEXT as h}from"../../internal/scale.js";const f=/*@__PURE__*/r.createContext({size:"md",last:!1,position:null}),x={xs:"gap-1",sm:"gap-1.5",md:"gap-2",lg:"gap-2.5",xl:"gap-3"},b={xs:"rounded-mp-xs",sm:"rounded-mp-xs",md:"rounded-mp-xs",lg:"rounded-mp-sm",xl:"rounded-mp-sm"};const v=["chevron","arrow","slash","dot"];export const MPBreadcrumb=/*@__PURE__*/r.forwardRef(function({size:t="md",color:u="primary",separator:p="chevron",maxItems:b,itemsBeforeCollapse:g=1,itemsAfterCollapse:N=1,expandable:j=!0,label:y,expandLabel:k,locale:z,structuredData:B=!1,className:C,style:w,children:P,...M},I){const L=m(d,c(z)),[S,_]=r.useState(!1),A=r.Children.toArray(P).filter(r.isValidElement),E=A.length,F=A.some(e=>!0===e.props.current),R=!S&&!B&&void 0!==b&&E>Math.max(b,1)&&E-g-N>1?[...A.slice(0,Math.max(0,g)),null,...A.slice(E-Math.max(0,N))]:A,T="string"==typeof(D=p)&&v.includes(D)?function(n){switch(n){case"chevron":return e(o,{icon:a,size:"1.1em",className:"rtl:rotate-180"});case"arrow":return e(o,{icon:i,size:"1em",className:"rtl:rotate-180"});case"slash":return e("span",{"aria-hidden":"true",children:"/"});case"dot":return e("span",{"aria-hidden":"true",children:"·"});default:return null}}(p):p;var D;const V=r.useMemo(()=>Array.from({length:R.length},(e,n)=>({size:t,last:!F&&n===R.length-1,position:B?n+1:null})),[t,F,R.length,B]),$=["rounded-mp-xs text-mp-on-surface-variant inline-flex items-center px-0.5","appearance-none border-0 bg-transparent font-[inherit]","transition-[background-color,color] duration-(--mp-sys-motion-duration-short4)",j?["cursor-pointer hover:bg-(--_mp-accent-container) hover:text-(--_mp-on-accent-container)","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-1","focus-visible:outline-solid outline-none"].join(" "):""].filter(Boolean).join(" ");return e("nav",{ref:I,"aria-label":y??L.label,"data-mp-size":t,className:["mp-breadcrumb flex",h[t],C??""].filter(Boolean).join(" "),style:{...l(u),...w},...M,children:e("ol",{role:"list",itemScope:B||void 0,itemType:B?"https://schema.org/BreadcrumbList":void 0,className:`flex list-none flex-wrap items-center p-0 ${x[t]}`,children:R.map((t,i)=>n(r.Fragment,{children:[i>0?e("li",{"aria-hidden":"true",className:"text-mp-on-surface-variant flex shrink-0 items-center select-none",children:T}):null,t?e(f.Provider,{value:V[i],children:t}):e("li",{className:"flex shrink-0 items-center",children:j?e("button",{type:"button",className:$,"aria-label":k??L.expand,onClick:()=>_(!0),children:e(o,{icon:s,size:"1.1em"})}):e("span",{className:$,"aria-hidden":"true",children:e(o,{icon:s,size:"1.1em"})})})]},t?t.key??i:"fold"))})})});export const MPBreadcrumbItem=/*@__PURE__*/r.forwardRef(function({href:o,onClick:i,startIcon:a,endIcon:s,current:l,disabled:c=!1,className:m,children:d,...h},x){const{size:v,last:g,position:N}=r.useContext(f),j=l??g,y=Boolean(o||i)&&!j&&!c,k=null!==N,z=["inline-flex min-w-0 items-center px-1 no-underline","appearance-none border-0 bg-transparent font-[inherit] text-[inherit]",u[v],b[v],"transition-[background-color,color] duration-(--mp-sys-motion-duration-short4)",c?"text-mp-on-surface/38 cursor-default":j?"text-mp-on-surface font-medium":y?["text-mp-on-surface-variant cursor-pointer","hover:bg-(--_mp-accent-container) hover:text-(--_mp-on-accent-container)","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-1","focus-visible:outline-solid outline-none"].join(" "):"text-mp-on-surface-variant"].filter(Boolean).join(" "),B=n(t,{children:[p(a)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:a}):null,e("span",{className:"truncate",itemProp:k?"name":void 0,children:d}),p(s)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:s}):null]});return n("li",{ref:x,itemProp:k?"itemListElement":void 0,itemScope:k||void 0,itemType:k?"https://schema.org/ListItem":void 0,className:["flex min-w-0 items-center",m??""].filter(Boolean).join(" "),...h,children:[k?e("meta",{itemProp:"position",content:String(N)}):null,y&&o?e("a",{href:o,itemProp:k?"item":void 0,className:z,onClick:i,children:B}):y?e("button",{type:"button",className:z,onClick:i,children:B}):e("span",{className:z,"aria-current":j?"page":void 0,"aria-disabled":c||void 0,children:B})]})});
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e,jsxs as o}from"react/jsx-runtime";import*as t from"react";import{Button as n}from"@base-ui/react/button";import{MPIcon as r}from"../icon/MPIcon.js";import{SpinnerIcon as a}from"../../constants/icons.js";import{accentSlots as i}from"../../internal/accent.js";import{MPButtonGroupContext as s}from"../../internal/button-group.js";import{useMPLocale as l,useMPMessages as c}from"../../internal/locale.js";import{COMMON as m}from"../../internal/messages/common.js";import{MPStateLayer as p}from"../../internal/StateLayer.js";import{CONTROL_GAP as d,CONTROL_HEIGHT as u,CONTROL_ICON as f,CONTROL_PAD_X as b,CONTROL_SQUARE as g,CONTROL_TEXT as x,hasContent as v}from"../../internal/scale.js";const h={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"shadow-mp-1 hover:shadow-mp-2 bg-mp-surface-container-low text-(--_mp-accent)",outlined:"border-mp-outline border bg-transparent text-(--_mp-accent)",text:"bg-transparent text-(--_mp-accent)"},j={filled:"bg-mp-on-surface/12 text-mp-on-surface/38",tonal:"bg-mp-on-surface/12 text-mp-on-surface/38",elevated:"bg-mp-on-surface/12 text-mp-on-surface/38 shadow-none",outlined:"border-mp-on-surface/12 border bg-transparent text-mp-on-surface/38",text:"bg-transparent text-mp-on-surface/38"};export const MPButton=/*@__PURE__*/t.forwardRef(function({variant:w,size:y,color:_,disabled:k,startIcon:z,endIcon:B,loading:C=!1,loadingLabel:I,locale:N,fullWidth:P=!1,type:L="button",className:M,style:D,children:R,onClick:S,...W},$){const q=l(N),A=c(m,q),E=t.useContext(s),F=w??E?.variant??"filled",G=y??E?.size??"md",H=_??E?.color??"primary",J=k??E?.disabled??!1,K=!v(R);return o(n,{ref:$,type:L,disabled:J,"aria-busy":C||void 0,"aria-disabled":C||void 0,"data-mp-size":G,"data-mp-variant":F,"data-loading":C||void 0,className:["mp-button group relative inline-flex shrink-0 items-center justify-center","rounded-mp-full box-border overflow-hidden align-middle whitespace-nowrap select-none","cursor-pointer appearance-none font-[inherit]","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid outline-none","transition-[background-color,border-color,box-shadow,color]","duration-(--mp-sys-motion-duration-short4)",u[G],x[G],d[G],K?`${g[G]} px-0`:b[G],J?j[F]:h[F],J?"cursor-default":"",C?"cursor-progress":"",P?"w-full":"",M??""].filter(Boolean).join(" "),style:{...i(H),...D},onClick:e=>{if(C)return e.preventDefault(),void e.stopPropagation();S?.(e)},...W,children:[J?null:e(p,{}),C?e(r,{icon:a,size:f[G],label:I??A.loading,className:"animate-spin"}):z,R,B]})});
2
+ import{jsx as e,jsxs as o}from"react/jsx-runtime";import*as t from"react";import{Button as n}from"@base-ui/react/button";import{MPIcon as r}from"../icon/MPIcon.js";import{SpinnerIcon as a}from"../../constants/icons.js";import{accentSlots as i}from"../../internal/accent.js";import{MPButtonGroupContext as s}from"../../internal/button-group.js";import{useMPLocale as l,useMPMessages as c}from"../../internal/locale.js";import{COMMON as m}from"../../internal/messages/common.js";import{MPStateLayer as p}from"../../internal/StateLayer.js";import{CONTROL_GAP as d,CONTROL_HEIGHT as u,CONTROL_ICON as f,CONTROL_PAD_X as b,CONTROL_SQUARE as g,CONTROL_TEXT as x,hasContent as v}from"../../internal/scale.js";const h={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"shadow-mp-1 hover:shadow-mp-2 bg-mp-surface-container-low text-(--_mp-accent)",outlined:"border-mp-outline border bg-transparent text-(--_mp-accent)",text:"bg-transparent text-(--_mp-accent)"},j={filled:"bg-mp-on-surface/12 text-mp-on-surface/38",tonal:"bg-mp-on-surface/12 text-mp-on-surface/38",elevated:"bg-mp-on-surface/12 text-mp-on-surface/38 shadow-none",outlined:"border-mp-on-surface/12 border bg-transparent text-mp-on-surface/38",text:"bg-transparent text-mp-on-surface/38"};export const MPButton=/*@__PURE__*/t.forwardRef(function({variant:w,size:y,color:_,disabled:k,startIcon:z,endIcon:B,loading:C=!1,loadingLabel:I,locale:N,fullWidth:P=!1,type:L="button",className:M,style:D,children:R,onClick:S,...W},$){const q=l(N),A=c(m,q),E=t.useContext(s),F=w??E?.variant??"filled",G=y??E?.size??"md",H=_??E?.color??"primary",J=k??E?.disabled??!1,K=C||v(z),O=!(v(R)||K&&v(B));return o(n,{ref:$,type:L,disabled:J,"aria-busy":C||void 0,"aria-disabled":C||void 0,"data-mp-size":G,"data-mp-variant":F,"data-loading":C||void 0,className:["mp-button group relative inline-flex shrink-0 items-center justify-center","rounded-mp-full box-border overflow-hidden align-middle whitespace-nowrap select-none","cursor-pointer appearance-none font-[inherit]","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid outline-none","transition-[background-color,border-color,box-shadow,color]","duration-(--mp-sys-motion-duration-short4)",u[G],x[G],d[G],O?`${g[G]} px-0`:b[G],J?j[F]:h[F],J?"cursor-default":"",C?"cursor-progress":"",P?"w-full":"",M??""].filter(Boolean).join(" "),style:{...i(H),...D},onClick:e=>{if(C)return e.preventDefault(),void e.stopPropagation();S?.(e)},...W,children:[J?null:e(p,{}),C?e(r,{icon:a,size:f[G],label:I??A.loading,className:"animate-spin"}):z,R,B]})});
@@ -12,6 +12,15 @@ export interface MPButtonGroupProps extends MPStyleProps, Omit<React.ComponentPr
12
12
  color?: MPColor;
13
13
  /** Disables every button in the group at once. */
14
14
  disabled?: boolean;
15
+ /**
16
+ * The group's name is `aria-label` through the rest props, and is worth
17
+ * setting whenever the run is a *set* rather than a row that happens to be
18
+ * adjacent — "Alignment", "Text style".
19
+ *
20
+ * A screen reader announces the boundaries of a `role="group"` either way; the
21
+ * name is what makes crossing that boundary mean something rather than being
22
+ * an interruption between two buttons.
23
+ */
15
24
  children?: React.ReactNode;
16
25
  }
17
26
  /**
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as o}from"react/jsx-runtime";import*as r from"react";import{MPButtonGroupContext as e}from"../../internal/button-group.js";const t={horizontal:"[&>*:not(:first-child)]:rounded-s-mp-sm [&>*:not(:last-child)]:rounded-e-mp-sm",vertical:"[&>*:not(:first-child)]:rounded-t-mp-sm [&>*:not(:last-child)]:rounded-b-mp-sm"};export const MPButtonGroup=/*@__PURE__*/r.forwardRef(function({variant:i,size:l,color:n,disabled:a,orientation:s="horizontal",fullWidth:d=!1,className:c,children:m,...u},f){const p=r.useMemo(()=>({variant:i,size:l,color:n,disabled:a}),[i,l,n,a]);return o(e.Provider,{value:p,children:o("div",{ref:f,role:"group","data-mp-orientation":s,className:["mp-button-group inline-flex gap-0.5 align-middle","vertical"===s?"flex-col":"flex-row",t[s],"[&>*]:relative [&>*:focus-visible]:z-10",d?"flex w-full [&>*]:flex-1":"",c??""].filter(Boolean).join(" "),...u,children:m})})});
2
+ import{jsx as e}from"react/jsx-runtime";import*as o from"react";import{GROUP_JOIN as r,MPButtonGroupContext as i}from"../../internal/button-group.js";export const MPButtonGroup=/*@__PURE__*/o.forwardRef(function({variant:l,size:t,color:a,disabled:n,orientation:s="horizontal",fullWidth:f=!1,className:c,children:u,...d},m){const p=o.useMemo(()=>({variant:l,size:t,color:a,disabled:n}),[l,t,a,n]);return e(i.Provider,{value:p,children:e("div",{ref:m,role:"group","data-mp-orientation":s,className:["mp-button-group inline-flex gap-0.5 align-middle","vertical"===s?"flex-col":"flex-row",r[s],"[&>*]:relative [&>*:focus-visible]:z-10",f?"flex w-full [&>*]:flex-1":"",c??""].filter(Boolean).join(" "),...d,children:u})})});
@@ -62,20 +62,25 @@ export interface MPCarouselProps extends Omit<React.ComponentPropsWithoutRef<'di
62
62
  * @default 'primary'
63
63
  */
64
64
  color?: MPColor;
65
- /**
66
- * The carousel's accessible name.
67
- * @default 'Carousel'
68
- */
65
+ /** The carousel's accessible name. Defaults to the word for it in `locale`. */
69
66
  label?: string;
70
- /** @default 'Previous slide' */
67
+ /** Defaults to the wording in `locale`. */
71
68
  previousLabel?: string;
72
- /** @default 'Next slide' */
69
+ /** The same. */
73
70
  nextLabel?: string;
74
71
  /**
75
72
  * How one slide is named to a screen reader, and how its mark is labelled.
76
- * @default (index, count) => `Slide ${index} of ${count}`
73
+ * Defaults to the wording in `locale` with the two numbers set into it.
77
74
  */
78
75
  slideLabel?: (index: number, count: number) => string;
76
+ /**
77
+ * Which language the carousel's own names are written in. Falls back to the
78
+ * nearest `MPLocaleProvider`, then to English.
79
+ *
80
+ * Nothing here is ever drawn — the strip is pictures and the arrows are
81
+ * chevrons — so without it a Korean page reads its slides out in English.
82
+ */
83
+ locale?: string;
79
84
  /** The slides. Every top-level child becomes one. */
80
85
  children?: React.ReactNode;
81
86
  }
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as t from"react";import{MPIconButton as n}from"../icon-button/MPIconButton.js";import{MPIcon as o}from"../icon/MPIcon.js";import{ChevronLeftIcon as a,ChevronRightIcon as i}from"../../constants/icons.js";import{accentSlots as s}from"../../internal/accent.js";import{CONTROL_ICON as l}from"../../internal/scale.js";import{CONTAINER_SURFACE as c}from"../../internal/surface.js";import{VISUALLY_HIDDEN as u}from"../../internal/visually-hidden.js";const d={xs:"start-1 end-1",sm:"start-1.5 end-1.5",md:"start-2 end-2",lg:"start-3 end-3",xl:"start-4 end-4"},m={xs:{rest:"h-1 w-1",current:"h-1 w-3",gap:"gap-1"},sm:{rest:"h-1 w-1",current:"h-1 w-3.5",gap:"gap-1"},md:{rest:"h-1.5 w-1.5",current:"h-1.5 w-4",gap:"gap-1.5"},lg:{rest:"h-1.5 w-1.5",current:"h-1.5 w-5",gap:"gap-2"},xl:{rest:"h-2 w-2",current:"h-2 w-6",gap:"gap-2"}},f=(e,r)=>`Slide ${e} of ${r}`;export const MPCarousel=/*@__PURE__*/t.forwardRef(function({value:p,defaultValue:h=0,onValueChange:b,loop:v=!0,autoPlay:w=!1,interval:g=5e3,arrows:x=!0,indicators:j=!0,variant:N="outlined",size:y="md",color:M="primary",label:k="Carousel",previousLabel:R="Previous slide",nextLabel:C="Next slide",slideLabel:P=f,className:z,style:I,children:$,...L},E){const S=t.Children.toArray($),T=S.length,[A,B]=t.useState(h),F=Math.min(Math.max(p??A,0),Math.max(T-1,0)),V=t.useRef(null),W=t.useRef([]),q=t.useRef(!1),_=t.useRef(!1),D=t.useRef(!1),[G,H]=t.useState(!1),J=t.useRef(F),K=t.useRef(b);J.current=F,K.current=b;const O=t.useCallback((e,r=!1)=>{if(0===T)return;const t=v?(e%T+T)%T:Math.min(Math.max(e,0),T-1);q.current=r,void 0===p&&B(t),t!==J.current&&K.current?.(t)},[T,v,p]);t.useEffect(()=>{if(q.current)return void(q.current=!1);if(!_.current)return void(_.current=!0);W.current[F]?.scrollIntoView({block:"nearest",inline:"start"}),D.current=!0;const e=window.setTimeout(()=>{D.current=!1},700);return()=>window.clearTimeout(e)},[F]),t.useEffect(()=>{if(!w||G||T<2)return;if(window.matchMedia?.("(prefers-reduced-motion: reduce)").matches)return;const e=window.setInterval(()=>{document.hidden||O(J.current+1)},g);return()=>window.clearInterval(e)},[w,G,T,g,O]);const Q=t.useRef(0);t.useEffect(()=>()=>cancelAnimationFrame(Q.current),[]);const U=F<=0,X=F>=T-1;return r("div",{ref:E,role:"region","aria-roledescription":"carousel","aria-label":k,"data-mp-size":y,"data-mp-variant":N,className:["mp-carousel flex w-full flex-col",z??""].filter(Boolean).join(" "),style:{...s(M),...I},onPointerEnter:()=>H(!0),onPointerLeave:()=>H(!1),onFocus:()=>H(!0),onBlur:e=>{e.currentTarget.contains(e.relatedTarget)||H(!1)},...L,children:[r("div",{className:["relative min-w-0 overflow-hidden","rounded-mp-md box-border",c[N],"text-mp-on-surface"].join(" "),children:[e("div",{ref:V,tabIndex:0,role:"group","aria-label":k,className:["flex min-w-0 snap-x snap-mandatory overflow-x-auto scroll-smooth","motion-reduce:scroll-auto","[scrollbar-width:none] [&::-webkit-scrollbar]:hidden","outline-mp-secondary focus-visible:outline-2 focus-visible:-outline-offset-2","focus-visible:outline-solid outline-none"].join(" "),onScroll:()=>{Q.current||(Q.current=requestAnimationFrame(()=>{Q.current=0;const e=V.current;if(!e||0===e.clientWidth||D.current)return;const r=Math.round(Math.abs(e.scrollLeft)/e.clientWidth);r!==J.current&&r>=0&&r<T&&O(r,!0)}))},children:S.map((r,t)=>e("div",{ref:e=>{W.current[t]=e,W.current.length=T},role:"group","aria-roledescription":"slide","aria-label":P(t+1,T),className:"w-full shrink-0 grow-0 basis-full snap-start",children:r},t))}),x&&T>1?r("div",{className:`pointer-events-none absolute inset-y-0 flex items-center ${d[y]}`,children:[e(n,{variant:"filled",size:y,color:M,label:R,disabled:!v&&U,className:"pointer-events-auto",icon:e(o,{icon:a,size:l[y],className:"rtl:rotate-180"}),onClick:()=>O(F-1)}),e("span",{className:"flex-1"}),e(n,{variant:"filled",size:y,color:M,label:C,disabled:!v&&X,className:"pointer-events-auto",icon:e(o,{icon:i,size:l[y],className:"rtl:rotate-180"}),onClick:()=>O(F+1)})]}):null]}),j&&T>1?e("div",{className:`flex shrink-0 items-center justify-center pt-2 ${m[y].gap}`,children:S.map((r,t)=>e("button",{type:"button","aria-label":P(t+1,T),"aria-current":t===F?"true":void 0,className:["rounded-mp-full cursor-pointer appearance-none border-0 p-0","transition-[width,background-color] duration-(--mp-sys-motion-duration-short4)","ease-mp-standard motion-reduce:transition-none","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid outline-none",t===F?`${m[y].current} bg-(--_mp-accent)`:`${m[y].rest} bg-mp-outline-variant hover:bg-mp-outline`].join(" "),onClick:()=>O(t)},t))}):null,e("span",{className:u,"aria-live":w?"off":"polite",children:T>0?P(F+1,T):""})]})});
2
+ import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as t from"react";import{MPIconButton as n}from"../icon-button/MPIconButton.js";import{MPIcon as o}from"../icon/MPIcon.js";import{ChevronLeftIcon as a,ChevronRightIcon as i}from"../../constants/icons.js";import{accentSlots as s}from"../../internal/accent.js";import{fillMessage as l}from"../../internal/i18n.js";import{useMPLocale as c,useMPMessages as u}from"../../internal/locale.js";import{CAROUSEL as d}from"../../internal/messages/carousel.js";import{CONTROL_ICON as m}from"../../internal/scale.js";import{CONTAINER_SURFACE as f}from"../../internal/surface.js";import{VISUALLY_HIDDEN as p}from"../../internal/visually-hidden.js";const h={xs:"start-1 end-1",sm:"start-1.5 end-1.5",md:"start-2 end-2",lg:"start-3 end-3",xl:"start-4 end-4"},b={xs:{rest:"h-1 w-1",current:"h-1 w-3",gap:"gap-1"},sm:{rest:"h-1 w-1",current:"h-1 w-3.5",gap:"gap-1"},md:{rest:"h-1.5 w-1.5",current:"h-1.5 w-4",gap:"gap-1.5"},lg:{rest:"h-1.5 w-1.5",current:"h-1.5 w-5",gap:"gap-2"},xl:{rest:"h-2 w-2",current:"h-2 w-6",gap:"gap-2"}};export const MPCarousel=/*@__PURE__*/t.forwardRef(function({value:v,defaultValue:w=0,onValueChange:g,loop:x=!0,autoPlay:j=!1,interval:N=5e3,arrows:y=!0,indicators:M=!0,variant:k="outlined",size:R="md",color:C="primary",label:z,previousLabel:I,nextLabel:P,slideLabel:S,locale:L,className:E,style:T,children:$,...A},B){const F=u(d,c(L)),V=z??F.label,W=S??((e,r)=>l(F.slide,{index:String(e),total:String(r)})),q=t.Children.toArray($),_=q.length,[D,G]=t.useState(w),H=Math.min(Math.max(v??D,0),Math.max(_-1,0)),J=t.useRef(null),K=t.useRef([]),O=t.useRef(!1),Q=t.useRef(!1),U=t.useRef(!1),[X,Y]=t.useState(!1),[Z,ee]=t.useState(!1),re=X||Z,te=t.useRef(H),ne=t.useRef(g);te.current=H,ne.current=g;const oe=t.useCallback((e,r=!1)=>{if(0===_)return;const t=x?(e%_+_)%_:Math.min(Math.max(e,0),_-1);O.current=r,void 0===v&&G(t),t!==te.current&&ne.current?.(t)},[_,x,v]);t.useEffect(()=>{if(O.current)return void(O.current=!1);if(!Q.current)return void(Q.current=!0);K.current[H]?.scrollIntoView({block:"nearest",inline:"start"}),U.current=!0;const e=window.setTimeout(()=>{U.current=!1},700);return()=>window.clearTimeout(e)},[H]),t.useEffect(()=>{if(!j||re||_<2)return;if(window.matchMedia?.("(prefers-reduced-motion: reduce)").matches)return;const e=window.setInterval(()=>{document.hidden||oe(te.current+1)},N);return()=>window.clearInterval(e)},[j,re,_,N,oe]);const ae=t.useRef(0);t.useEffect(()=>()=>cancelAnimationFrame(ae.current),[]);const ie=H<=0,se=H>=_-1;return r("div",{ref:B,role:"region","aria-roledescription":"carousel","aria-label":V,"data-mp-size":R,"data-mp-variant":k,className:["mp-carousel flex w-full flex-col",E??""].filter(Boolean).join(" "),style:{...s(C),...T},onPointerEnter:()=>Y(!0),onPointerLeave:()=>Y(!1),onFocus:()=>ee(!0),onBlur:e=>{e.currentTarget.contains(e.relatedTarget)||ee(!1)},...A,children:[r("div",{className:["relative min-w-0 overflow-hidden","rounded-mp-md box-border",f[k],"text-mp-on-surface"].join(" "),children:[e("div",{ref:J,tabIndex:0,role:"group","aria-label":V,className:["flex min-w-0 snap-x snap-mandatory overflow-x-auto scroll-smooth","motion-reduce:scroll-auto","[scrollbar-width:none] [&::-webkit-scrollbar]:hidden","outline-mp-secondary focus-visible:outline-2 focus-visible:-outline-offset-2","focus-visible:outline-solid outline-none"].join(" "),onScroll:()=>{ae.current||(ae.current=requestAnimationFrame(()=>{ae.current=0;const e=J.current;if(!e||0===e.clientWidth||U.current)return;const r=Math.round(Math.abs(e.scrollLeft)/e.clientWidth);r!==te.current&&r>=0&&r<_&&oe(r,!0)}))},children:q.map((r,t)=>e("div",{ref:e=>{K.current[t]=e,K.current.length=_},role:"group","aria-roledescription":"slide","aria-label":W(t+1,_),className:"w-full shrink-0 grow-0 basis-full snap-start",children:r},t))}),y&&_>1?r("div",{className:`pointer-events-none absolute inset-y-0 flex items-center ${h[R]}`,children:[e(n,{variant:"filled",size:R,color:C,label:I??F.previous,disabled:!x&&ie,className:"pointer-events-auto",icon:e(o,{icon:a,size:m[R],className:"rtl:rotate-180"}),onClick:()=>oe(H-1)}),e("span",{className:"flex-1"}),e(n,{variant:"filled",size:R,color:C,label:P??F.next,disabled:!x&&se,className:"pointer-events-auto",icon:e(o,{icon:i,size:m[R],className:"rtl:rotate-180"}),onClick:()=>oe(H+1)})]}):null]}),M&&_>1?e("div",{className:`flex shrink-0 items-center justify-center pt-2 ${b[R].gap}`,children:q.map((r,t)=>e("button",{type:"button","aria-label":W(t+1,_),"aria-current":t===H?"true":void 0,className:["rounded-mp-full cursor-pointer appearance-none border-0 p-0","transition-[width,background-color] duration-(--mp-sys-motion-duration-short4)","ease-mp-standard motion-reduce:transition-none","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid outline-none",t===H?`${b[R].current} bg-(--_mp-accent)`:`${b[R].rest} bg-mp-outline-variant hover:bg-mp-outline`].join(" "),onClick:()=>oe(t)},t))}):null,e("span",{className:p,"aria-live":j?"off":"polite",children:_>0?W(H+1,_):""})]})});
@@ -17,9 +17,22 @@ export type MPChatBubbleSide = 'start' | 'end';
17
17
  * colour family.
18
18
  */
19
19
  export type MPChatBubbleStatus = 'sending' | 'sent' | 'delivered' | 'read' | 'failed';
20
- /** What a link inside a message unfurls to. */
20
+ /**
21
+ * What a link inside a message unfurls to.
22
+ *
23
+ * This is the one shape in the library whose contents typically come from
24
+ * **somebody else** — a preview is attached to a message another person sent —
25
+ * so `url` is checked before it is rendered rather than trusted. See the note on
26
+ * `LinkPreview` below.
27
+ */
21
28
  export interface MPChatBubblePreview {
22
- /** Where the card goes. */
29
+ /**
30
+ * Where the card goes.
31
+ *
32
+ * Only `http:`, `https:`, `mailto:`, `tel:` and relative URLs are rendered.
33
+ * Anything else — `javascript:`, `data:` — draws the card without a link
34
+ * rather than handing the reader a one-click script execution.
35
+ */
23
36
  url: string;
24
37
  /** The page's title. */
25
38
  title?: React.ReactNode;
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e,jsxs as n}from"react/jsx-runtime";import*as r from"react";import{MPIcon as a}from"../icon/MPIcon.js";import{CheckIcon as l,ClockIcon as t,ErrorIcon as i,LinkIcon as s}from"../../constants/icons.js";import{accentSlots as o}from"../../internal/accent.js";import{useMPLocale as c,useMPMessages as m}from"../../internal/locale.js";import{CHAT as d}from"../../internal/messages/chat.js";import{hasContent as p,META_TEXT as u,PROSE_TEXT as f}from"../../internal/scale.js";import{VISUALLY_HIDDEN as h}from"../../internal/visually-hidden.js";const b={xs:"px-2 py-1",sm:"px-2.5 py-1.5",md:"px-3 py-2",lg:"px-3.5 py-2.5",xl:"px-4 py-3"},x={start:"[border-start-start-radius:var(--mp-sys-shape-corner-extra-small)]",end:"[border-start-end-radius:var(--mp-sys-shape-corner-extra-small)]"},v={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"shadow-mp-1 bg-mp-surface-container-low text-mp-on-surface",outlined:"border-mp-outline-variant border bg-transparent text-mp-on-surface",text:"bg-mp-surface-container-low text-mp-on-surface"};function g(){return n("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",className:"size-full",children:[e("path",{d:"m1.5 8.5 2.75 2.75L9.5 6",stroke:"currentColor",strokeWidth:"1.75",strokeLinecap:"round",strokeLinejoin:"round"}),e("path",{d:"M7 10.75 8.25 12l5.25-5.25",stroke:"currentColor",strokeWidth:"1.75",strokeLinecap:"round",strokeLinejoin:"round"})]})}const N={sending:e(a,{icon:t,size:"1.15em"}),sent:e(a,{icon:l,size:"1.15em"}),delivered:e("span",{className:"block size-[1.15em]",children:e(g,{})}),read:e("span",{className:"block size-[1.15em]",children:e(g,{})}),failed:e(a,{icon:i,size:"1.15em"})},w={sending:"text-mp-on-surface-variant",sent:"text-mp-on-surface-variant",delivered:"text-mp-on-surface-variant",read:"text-(--_mp-accent)",failed:"text-mp-error"},y=/*@__PURE__*/["rounded-mp-sm block overflow-hidden border no-underline","[border-color:color-mix(in_oklab,currentColor_18%,transparent)]","[background-color:color-mix(in_oklab,currentColor_7%,transparent)]","hover:[background-color:color-mix(in_oklab,currentColor_12%,transparent)]","transition-[background-color] duration-(--mp-sys-motion-duration-short4) ease-mp-standard","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid outline-none"].join(" "),k=/*@__PURE__*/["shrink-0 opacity-0","transition-opacity duration-(--mp-sys-motion-duration-short4) ease-mp-standard","group-hover/bubble:opacity-100 group-focus-within/bubble:opacity-100","[@media(hover:none)]:opacity-100"].join(" ");export const MPChatBubble=/*@__PURE__*/r.forwardRef(function({side:r="start",name:a,time:l,avatar:t,status:i,statusLabel:s,typing:g=!1,media:y,preview:z,actions:C,locale:L,variant:B="tonal",size:$="md",color:M="primary",className:P,style:W,children:I,...R},T){const q=c(L),A=m(d,q),D="end"===r,E=p(a)||p(l),F=g||p(I)||Boolean(z);return n("div",{ref:T,"data-mp-size":$,"data-mp-variant":B,"data-mp-side":r,className:["mp-chat-bubble group/bubble flex w-full items-start gap-2",D?"flex-row-reverse":"",P??""].filter(Boolean).join(" "),style:{...o(M),...W},...R,children:[p(t)?e("div",{className:"shrink-0",children:t}):null,n("div",{className:["flex min-w-0 max-w-[min(100%,32rem)] flex-col gap-1",D?"items-end":"items-start"].join(" "),children:[E?n("div",{className:`flex items-baseline gap-2 ${u}`,children:[p(a)?e("span",{className:"font-medium",children:a}):null,p(l)?e("span",{className:"text-mp-on-surface-variant",children:l}):null]}):null,n("div",{className:"flex min-w-0 items-center gap-1 "+(D?"flex-row-reverse":""),children:[n("div",{className:["mp-chat-bubble__sheet rounded-mp-xl flex min-w-0 flex-col overflow-hidden","box-border",x[r],v[B],f[$]].join(" "),children:[p(y)?e("div",{className:"[&_img]:block [&_img]:w-full [&_video]:block [&_video]:w-full",children:y}):null,F?n("div",{className:`flex min-w-0 flex-col gap-2 ${b[$]}`,children:[g?e(_,{label:A.typing}):p(I)?e("div",{className:"min-w-0 break-words whitespace-pre-line",children:I}):null,z?e(j,{preview:z}):null]}):null]}),p(C)?e("div",{className:k,children:C}):null]}),i?n("div",{className:`flex items-center gap-1 ${u} ${w[i]}`,children:[N[i],e("span",{className:h,children:s??A[i]})]}):null]})]})});function _({label:r}){return n("div",{className:"flex items-center gap-1 py-[0.35em]",role:"status",children:[[0,1,2].map(n=>e("span",{"aria-hidden":"true",className:"mp-chat-typing size-[0.45em] rounded-full bg-current",style:{"--_mp-index":n}},n)),e("span",{className:h,children:r})]})}function j({preview:r}){const{url:l,title:t,description:i,image:o,site:c,newTab:m=!1}=r;return n("a",{href:l,target:m?"_blank":void 0,rel:m?"noopener noreferrer":void 0,className:y,children:[o?e("img",{src:o,alt:"",className:"block h-28 w-full object-cover"}):null,n("div",{className:"flex flex-col gap-0.5 p-2",children:[p(c)?n("span",{className:"flex items-center gap-1 text-[0.85em] opacity-70",children:[e(a,{icon:s,size:"1em"}),e("span",{className:"truncate",children:c})]}):null,p(t)?e("span",{className:"font-medium",children:t}):null,p(i)?e("span",{className:"line-clamp-2 text-[0.9em] opacity-80",children:i}):null]})]})}
2
+ import{jsx as e,jsxs as n}from"react/jsx-runtime";import*as r from"react";import{MPIcon as a}from"../icon/MPIcon.js";import{CheckIcon as l,ClockIcon as i,ErrorIcon as t,LinkIcon as s}from"../../constants/icons.js";import{accentSlots as o}from"../../internal/accent.js";import{useMPLocale as c,useMPMessages as m}from"../../internal/locale.js";import{linkRel as d,safeHref as p}from"../../internal/link.js";import{CHAT as u}from"../../internal/messages/chat.js";import{hasContent as f,META_TEXT as h,PROSE_TEXT as b}from"../../internal/scale.js";import{VISUALLY_HIDDEN as x}from"../../internal/visually-hidden.js";const v={xs:"px-2 py-1",sm:"px-2.5 py-1.5",md:"px-3 py-2",lg:"px-3.5 py-2.5",xl:"px-4 py-3"},g={start:"[border-start-start-radius:var(--mp-sys-shape-corner-extra-small)]",end:"[border-start-end-radius:var(--mp-sys-shape-corner-extra-small)]"},y={filled:"bg-(--_mp-accent) text-(--_mp-on-accent)",tonal:"bg-(--_mp-accent-container) text-(--_mp-on-accent-container)",elevated:"shadow-mp-1 bg-mp-surface-container-low text-mp-on-surface",outlined:"border-mp-outline-variant border bg-transparent text-mp-on-surface",text:"bg-mp-surface-container-low text-mp-on-surface"};function N(){return n("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",className:"size-full",children:[e("path",{d:"m1.5 8.5 2.75 2.75L9.5 6",stroke:"currentColor",strokeWidth:"1.75",strokeLinecap:"round",strokeLinejoin:"round"}),e("path",{d:"M7 10.75 8.25 12l5.25-5.25",stroke:"currentColor",strokeWidth:"1.75",strokeLinecap:"round",strokeLinejoin:"round"})]})}const w={sending:e(a,{icon:i,size:"1.15em"}),sent:e(a,{icon:l,size:"1.15em"}),delivered:e("span",{className:"block size-[1.15em]",children:e(N,{})}),read:e("span",{className:"block size-[1.15em]",children:e(N,{})}),failed:e(a,{icon:t,size:"1.15em"})},k={sending:"text-mp-on-surface-variant",sent:"text-mp-on-surface-variant",delivered:"text-mp-on-surface-variant",read:"text-(--_mp-accent)",failed:"text-mp-error"},j=/*@__PURE__*/["rounded-mp-sm block overflow-hidden border no-underline","[border-color:color-mix(in_oklab,currentColor_18%,transparent)]","[background-color:color-mix(in_oklab,currentColor_7%,transparent)]","hover:[background-color:color-mix(in_oklab,currentColor_12%,transparent)]","transition-[background-color] duration-(--mp-sys-motion-duration-short4) ease-mp-standard","outline-mp-secondary focus-visible:outline-2 focus-visible:outline-offset-2","focus-visible:outline-solid outline-none"].join(" "),_=/*@__PURE__*/["shrink-0 opacity-0","transition-opacity duration-(--mp-sys-motion-duration-short4) ease-mp-standard","group-hover/bubble:opacity-100 group-focus-within/bubble:opacity-100","[@media(hover:none)]:opacity-100"].join(" ");export const MPChatBubble=/*@__PURE__*/r.forwardRef(function({side:r="start",name:a,time:l,avatar:i,status:t,statusLabel:s,typing:d=!1,media:p,preview:N,actions:j,locale:L,variant:B="tonal",size:$="md",color:M="primary",className:P,style:W,children:I,...R},T){const q=c(L),A=m(u,q),D="end"===r,E=f(a)||f(l),F=d||f(I)||Boolean(N);return n("div",{ref:T,"data-mp-size":$,"data-mp-variant":B,"data-mp-side":r,className:["mp-chat-bubble group/bubble flex w-full items-start gap-2",D?"flex-row-reverse":"",P??""].filter(Boolean).join(" "),style:{...o(M),...W},...R,children:[f(i)?e("div",{className:"shrink-0",children:i}):null,n("div",{className:["flex min-w-0 max-w-[min(100%,32rem)] flex-col gap-1",D?"items-end":"items-start"].join(" "),children:[E?n("div",{className:`flex items-baseline gap-2 ${h}`,children:[f(a)?e("span",{className:"font-medium",children:a}):null,f(l)?e("span",{className:"text-mp-on-surface-variant",children:l}):null]}):null,n("div",{className:"flex min-w-0 items-center gap-1 "+(D?"flex-row-reverse":""),children:[n("div",{className:["mp-chat-bubble__sheet rounded-mp-xl flex min-w-0 flex-col overflow-hidden","box-border",g[r],y[B],b[$]].join(" "),children:[f(p)?e("div",{className:"[&_img]:block [&_img]:w-full [&_video]:block [&_video]:w-full",children:p}):null,F?n("div",{className:`flex min-w-0 flex-col gap-2 ${v[$]}`,children:[d?e(z,{label:A.typing}):f(I)?e("div",{className:"min-w-0 break-words whitespace-pre-line",children:I}):null,N?e(C,{preview:N}):null]}):null]}),f(j)?e("div",{className:_,children:j}):null]}),t?n("div",{className:`flex items-center gap-1 ${h} ${k[t]}`,children:[w[t],e("span",{className:x,children:s??A[t]})]}):null]})]})});function z({label:r}){return n("div",{className:"flex items-center gap-1 py-[0.35em]",role:"status",children:[[0,1,2].map(n=>e("span",{"aria-hidden":"true",className:"mp-chat-typing size-[0.45em] rounded-full bg-current",style:{"--_mp-index":n}},n)),e("span",{className:x,children:r})]})}function C({preview:r}){const{url:l,title:i,description:t,image:o,site:c,newTab:m=!1}=r,u=m?"_blank":void 0;return n("a",{href:p(l),target:u,rel:d(u,void 0),className:j,children:[o?e("img",{src:o,alt:"",loading:"lazy",decoding:"async",referrerPolicy:"no-referrer",width:640,height:112,className:"block h-28 w-full object-cover"}):null,n("div",{className:"flex flex-col gap-0.5 p-2",children:[f(c)?n("span",{className:"flex items-center gap-1 text-[0.85em] opacity-70",children:[e(a,{icon:s,size:"1em"}),e("span",{className:"truncate",children:c})]}):null,f(i)?e("span",{className:"font-medium",children:i}):null,f(t)?e("span",{className:"line-clamp-2 text-[0.9em] opacity-80",children:t}):null]})]})}
@@ -56,6 +56,12 @@ export interface MPCheckboxProps {
56
56
  * left out.
57
57
  */
58
58
  id?: string;
59
+ /**
60
+ * Added to the outermost element — the box around the tick, its label and its
61
+ * supporting line, rather than to the tick itself.
62
+ */
63
+ className?: string;
64
+ style?: React.CSSProperties;
59
65
  }
60
66
  /**
61
67
  * A Material Design checkbox.
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as r from"react";import{Checkbox as t}from"@base-ui/react/checkbox";import{Field as n}from"@base-ui/react/field";import{MPIcon as o}from"../icon/MPIcon.js";import{CheckIcon as i,RemoveIcon as s}from"../../constants/icons.js";import{accentSlots as c}from"../../internal/accent.js";import{MPStateLayer as d}from"../../internal/StateLayer.js";import{MPSupportingText as l}from"../../internal/SupportingText.js";import{PROSE_TEXT as m,hasContent as p}from"../../internal/scale.js";const h={xs:{box:"size-3.5",halo:"size-8",glyph:12},sm:{box:"size-4",halo:"size-9",glyph:14},md:{box:"size-[18px]",halo:"size-10",glyph:16},lg:{box:"size-5",halo:"size-11",glyph:18},xl:{box:"size-[22px]",halo:"size-12",glyph:20}};export const MPCheckbox=/*@__PURE__*/r.forwardRef(function({checked:u,defaultChecked:f,onCheckedChange:b,indeterminate:x=!1,label:g,description:y,errorMessage:k,size:j="md",color:z="primary",required:_=!1,disabled:v=!1,readOnly:C=!1,name:N,value:M,id:I},R){const q=p(k),w=q?"error":z,L=h[j],O=r.useId(),P=I??O;return e(n.Root,{className:"mp-checkbox inline-block align-top",disabled:v,invalid:q,"data-mp-size":j,style:c(w),children:a("div",{className:["flex items-start gap-3",m[j]].join(" "),children:[e("span",{className:"flex h-[1lh] shrink-0 items-center",children:a(t.Root,{ref:R,id:P,name:N,value:M,checked:u,defaultChecked:f,indeterminate:x,required:_,disabled:v,readOnly:C,onCheckedChange:e=>b?.(e),className:["mp-checkbox__tick group relative inline-flex shrink-0 items-center","box-border justify-center border-2 p-0","rounded-[calc(var(--mp-sys-shape-corner-extra-small)/2)]","appearance-none bg-transparent font-[inherit] outline-none","transition-[background-color,border-color]","duration-(--mp-sys-motion-duration-short4)",L.box,v?["border-mp-on-surface/38 cursor-default","data-checked:bg-mp-on-surface/38 data-checked:border-transparent","data-indeterminate:bg-mp-on-surface/38 data-indeterminate:border-transparent"].join(" "):[C?"cursor-default":"cursor-pointer",q?"border-mp-error":"border-mp-on-surface-variant","data-checked:border-transparent data-checked:bg-(--_mp-accent)","data-checked:text-(--_mp-on-accent)","data-indeterminate:border-transparent data-indeterminate:bg-(--_mp-accent)","data-indeterminate:text-(--_mp-on-accent)"].join(" ")].join(" "),children:[v?null:e(d,{layer:["top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full",L.halo,"bg-mp-on-surface","group-data-checked:bg-(--_mp-accent)","group-data-indeterminate:bg-(--_mp-accent)"].join(" ")}),e(t.Indicator,{className:["flex items-center justify-center","transition-[opacity,scale] duration-(--mp-sys-motion-duration-short4)","ease-mp-standard","data-starting-style:scale-60 data-starting-style:opacity-0","data-ending-style:scale-60 data-ending-style:opacity-0"].join(" "),children:e(o,{icon:x?s:i,size:L.glyph,strokeWidth:3})})]})}),p(g)||p(y)||q?a("span",{className:"flex min-w-0 flex-col gap-0.5",children:[p(g)?a(n.Label,{htmlFor:P,className:["leading-[1.4]",v?"text-mp-on-surface/38 cursor-default":C?"text-mp-on-surface":"text-mp-on-surface cursor-pointer"].join(" "),children:[g,_?e("span",{"aria-hidden":"true",children:" *"}):null]}):null,e(l,{description:y,errorMessage:k})]}):null]})})});
2
+ import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as r from"react";import{Checkbox as t}from"@base-ui/react/checkbox";import{Field as n}from"@base-ui/react/field";import{MPIcon as o}from"../icon/MPIcon.js";import{CheckIcon as i,RemoveIcon as s}from"../../constants/icons.js";import{accentSlots as c}from"../../internal/accent.js";import{MPStateLayer as d}from"../../internal/StateLayer.js";import{MPSupportingText as l}from"../../internal/SupportingText.js";import{PROSE_TEXT as m,hasContent as p}from"../../internal/scale.js";const h={xs:{box:"size-3.5",halo:"size-8",glyph:12},sm:{box:"size-4",halo:"size-9",glyph:14},md:{box:"size-[18px]",halo:"size-10",glyph:16},lg:{box:"size-5",halo:"size-11",glyph:18},xl:{box:"size-[22px]",halo:"size-12",glyph:20}};export const MPCheckbox=/*@__PURE__*/r.forwardRef(function({checked:u,defaultChecked:f,onCheckedChange:b,indeterminate:x=!1,label:g,description:y,errorMessage:k,size:j="md",color:z="primary",required:N=!1,disabled:_=!1,readOnly:v=!1,name:C,value:M,id:I,className:R,style:q},w){const L=p(k),O=L?"error":z,P=h[j],S=r.useId(),B=I??S;return e(n.Root,{className:["mp-checkbox inline-block align-top",R??""].filter(Boolean).join(" "),disabled:_,invalid:L,"data-mp-size":j,style:{...c(O),...q},children:a("div",{className:["flex items-start gap-3",m[j]].join(" "),children:[e("span",{className:"flex h-[1lh] shrink-0 items-center",children:a(t.Root,{ref:w,id:B,name:C,value:M,checked:u,defaultChecked:f,indeterminate:x,required:N,disabled:_,readOnly:v,onCheckedChange:e=>b?.(e),className:["mp-checkbox__tick group relative inline-flex shrink-0 items-center","box-border justify-center border-2 p-0","rounded-[calc(var(--mp-sys-shape-corner-extra-small)/2)]","appearance-none bg-transparent font-[inherit] outline-none","transition-[background-color,border-color]","duration-(--mp-sys-motion-duration-short4)",P.box,_?["border-mp-on-surface/38 cursor-default","data-checked:bg-mp-on-surface/38 data-checked:border-transparent","data-indeterminate:bg-mp-on-surface/38 data-indeterminate:border-transparent"].join(" "):[v?"cursor-default":"cursor-pointer",L?"border-mp-error":"border-mp-on-surface-variant","data-checked:border-transparent data-checked:bg-(--_mp-accent)","data-checked:text-(--_mp-on-accent)","data-indeterminate:border-transparent data-indeterminate:bg-(--_mp-accent)","data-indeterminate:text-(--_mp-on-accent)"].join(" ")].join(" "),children:[_?null:e(d,{layer:["top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full",P.halo,"bg-mp-on-surface","group-data-checked:bg-(--_mp-accent)","group-data-indeterminate:bg-(--_mp-accent)"].join(" ")}),e(t.Indicator,{className:["flex items-center justify-center","transition-[opacity,scale] duration-(--mp-sys-motion-duration-short4)","ease-mp-standard","data-starting-style:scale-60 data-starting-style:opacity-0","data-ending-style:scale-60 data-ending-style:opacity-0"].join(" "),children:e(o,{icon:x?s:i,size:P.glyph,strokeWidth:3})})]})}),p(g)||p(y)||L?a("span",{className:"flex min-w-0 flex-col gap-0.5",children:[p(g)?a(n.Label,{htmlFor:B,className:["leading-[1.4]",_?"text-mp-on-surface/38 cursor-default":v?"text-mp-on-surface":"text-mp-on-surface cursor-pointer"].join(" "),children:[g,N?e("span",{"aria-hidden":"true",children:" *"}):null]}):null,e(l,{description:y,errorMessage:k})]}):null]})})});