@12-apps/ui 6.98.0 → 6.99.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 (210) hide show
  1. package/dist/_internal/components/data-display/Alert/Alert.content.js +4 -2
  2. package/dist/_internal/components/data-display/Alert/Alert.ink.js +27 -0
  3. package/dist/_internal/components/data-display/Alert/Alert.js +6 -5
  4. package/dist/_internal/components/data-display/Alert/Alert.metrics.js +5 -1
  5. package/dist/_internal/components/data-display/Alert/Alert.styles.js +2 -2
  6. package/dist/_internal/components/data-display/Banner/Banner.js +3 -3
  7. package/dist/_internal/components/data-display/Banner/Banner.styles.js +2 -2
  8. package/dist/_internal/components/data-display/CardKit/card-actions-context.js +8 -7
  9. package/dist/_internal/components/data-display/CardKit/use-remove-confirm.js +9 -8
  10. package/dist/_internal/components/data-display/Carousel/Carousel.js +2 -2
  11. package/dist/_internal/components/data-display/Chart/SpecChart.js +3 -3
  12. package/dist/_internal/components/data-display/DataGrid/DataGrid.js +1 -1
  13. package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +17 -17
  14. package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +26 -25
  15. package/dist/_internal/components/data-display/DataViews/base-list-card-geometry.js +1 -1
  16. package/dist/_internal/components/data-display/DataViews/base-list-card-layout.js +1 -1
  17. package/dist/_internal/components/data-display/DataViews/base-list-card-slots.js +1 -1
  18. package/dist/_internal/components/data-display/DataViews/base-list-card.js +4 -4
  19. package/dist/_internal/components/data-display/DataViews/data-views-grid-bodies.js +2 -2
  20. package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +14 -14
  21. package/dist/_internal/components/data-display/DataViews/data-views-inline-bar.js +6 -6
  22. package/dist/_internal/components/data-display/DataViews/data-views-more-fields.js +2 -2
  23. package/dist/_internal/components/data-display/DataViews/data-views-more-filters.js +3 -3
  24. package/dist/_internal/components/data-display/DataViews/data-views-table-parts.js +8 -7
  25. package/dist/_internal/components/data-display/DataViews/list-card-rails.js +1 -1
  26. package/dist/_internal/components/data-display/DataViews/use-data-views-state.js +2 -2
  27. package/dist/_internal/components/data-display/DayRuler/DayRuler.footer.js +2 -2
  28. package/dist/_internal/components/data-display/DayRuler/DayRuler.js +7 -7
  29. package/dist/_internal/components/data-display/DayRuler/DayRuler.keyboard.js +2 -2
  30. package/dist/_internal/components/data-display/DayRuler/DayRuler.parts.js +3 -3
  31. package/dist/_internal/components/data-display/DayRuler/useRulerDrag.js +2 -2
  32. package/dist/_internal/components/data-display/FleetMap/FleetBody.js +6 -6
  33. package/dist/_internal/components/data-display/FleetMap/FleetCanvas.js +5 -5
  34. package/dist/_internal/components/data-display/FleetMap/FleetMap.js +7 -7
  35. package/dist/_internal/components/data-display/HoverCard/HoverCard.js +2 -2
  36. package/dist/_internal/components/data-display/Lightbox/Lightbox.js +3 -3
  37. package/dist/_internal/components/data-display/MapPreview/MapLayers.js +2 -2
  38. package/dist/_internal/components/data-display/MapPreview/MapPreview.js +4 -4
  39. package/dist/_internal/components/data-display/Progress/Progress.js +2 -2
  40. package/dist/_internal/components/data-display/RegionMap/RegionMap.fixtures.js +1 -1
  41. package/dist/_internal/components/data-display/RegionMap/RegionMap.helpers.js +3 -1
  42. package/dist/_internal/components/data-display/RegionMap/RegionMap.hooks.js +3 -3
  43. package/dist/_internal/components/data-display/RegionMap/RegionMap.js +6 -5
  44. package/dist/_internal/components/data-display/RegionMap/RegionMap.view.js +2 -2
  45. package/dist/_internal/components/data-display/RegionMap/RegionMapDrawing.js +3 -2
  46. package/dist/_internal/components/data-display/RegionMap/RegionMapPin.js +26 -0
  47. package/dist/_internal/components/data-display/index.js +60 -50
  48. package/dist/_internal/components/feedback/NotificationStatusNotice/NotificationStatusNotice.js +7 -6
  49. package/dist/_internal/components/feedback/SequenceResolver/SequenceResolver.frame.js +4 -4
  50. package/dist/_internal/components/feedback/SequenceResolver/SequenceResolver.header.js +3 -3
  51. package/dist/_internal/components/feedback/SequenceResolver/SequenceResolver.js +14 -13
  52. package/dist/_internal/components/feedback/SequenceResolver/SequenceResolver.overview.js +9 -8
  53. package/dist/_internal/components/feedback/SequenceResolver/SequenceResolver.parts.js +8 -7
  54. package/dist/_internal/components/feedback/index.js +15 -14
  55. package/dist/_internal/components/index.js +66 -56
  56. package/dist/charts.js +11 -11
  57. package/dist/{chunk-WYNGH2WL.js → chunk-255WTBZ5.js} +8 -8
  58. package/dist/{chunk-QIP37Y2C.js → chunk-2RC6EAGD.js} +2 -2
  59. package/dist/{chunk-ZKVSFVIA.js → chunk-37MJZLQU.js} +2 -2
  60. package/dist/{chunk-BQBEN44R.js → chunk-3I7KE2N6.js} +2 -2
  61. package/dist/{chunk-L4FWEI2P.js → chunk-3V3Z4EML.js} +5 -5
  62. package/dist/{chunk-E4MJA52O.js → chunk-3V5V44UP.js} +16 -18
  63. package/dist/chunk-3V5V44UP.js.map +1 -0
  64. package/dist/{chunk-6RYSSNOO.js → chunk-54DOLCJ3.js} +2 -2
  65. package/dist/{chunk-74IH3ZGD.js → chunk-643YFWNK.js} +2 -2
  66. package/dist/{chunk-FRQGZIYU.js → chunk-6WAP7BJS.js} +2 -2
  67. package/dist/chunk-AG4F6NVT.js +1 -0
  68. package/dist/chunk-AG4F6NVT.js.map +1 -0
  69. package/dist/{chunk-3CXRHRGE.js → chunk-AYDVNXGR.js} +7 -3
  70. package/dist/chunk-AYDVNXGR.js.map +1 -0
  71. package/dist/{chunk-JO6D7YGN.js → chunk-CWRQGA2T.js} +2 -2
  72. package/dist/chunk-DRYBA76G.js +293 -0
  73. package/dist/chunk-DRYBA76G.js.map +1 -0
  74. package/dist/{chunk-ZW7Q3IRL.js → chunk-FYJL432J.js} +4 -4
  75. package/dist/{chunk-G6TKWNF2.js → chunk-GZITNT7O.js} +11 -11
  76. package/dist/{chunk-RFMQBIE6.js → chunk-HBHBRRSW.js} +4 -4
  77. package/dist/{chunk-U4Z6GZDW.js → chunk-HN36UVOE.js} +4 -4
  78. package/dist/{chunk-WK577LQL.js → chunk-J2IQ6FJ5.js} +4 -4
  79. package/dist/{chunk-HCTHY66U.js → chunk-KAGXV3ID.js} +4 -4
  80. package/dist/{chunk-FWAY2SAI.js → chunk-KAZWBDIH.js} +2 -2
  81. package/dist/{chunk-DKPELKGL.js → chunk-KV7LTOWC.js} +5 -5
  82. package/dist/{chunk-UC7DLGMP.js → chunk-KVP5A3YK.js} +2 -2
  83. package/dist/chunk-LNZJJFZQ.js +41 -0
  84. package/dist/chunk-LNZJJFZQ.js.map +1 -0
  85. package/dist/{chunk-EGBQR5GH.js → chunk-LOLYBFYY.js} +5 -5
  86. package/dist/{chunk-SOXO2VN3.js → chunk-MEMVZW64.js} +3 -3
  87. package/dist/{chunk-COOSJKZL.js → chunk-MNJZPJ5S.js} +2 -1
  88. package/dist/chunk-MNJZPJ5S.js.map +1 -0
  89. package/dist/{chunk-G2NVBCF7.js → chunk-NWUMGE6T.js} +3 -3
  90. package/dist/{chunk-NQCTANF3.js → chunk-Q5SCBQLY.js} +18 -11
  91. package/dist/chunk-Q5SCBQLY.js.map +1 -0
  92. package/dist/{chunk-64LNNC54.js → chunk-QLKUWDMQ.js} +4 -4
  93. package/dist/{chunk-MPVH2GM5.js → chunk-RAQD5QCM.js} +4 -4
  94. package/dist/{chunk-KXDLLS62.js → chunk-REHGWN5M.js} +4 -4
  95. package/dist/{chunk-Z4ZFJ565.js → chunk-SRAIV6U6.js} +3 -3
  96. package/dist/{chunk-5ZY3IIIG.js → chunk-TBQR5VCN.js} +11 -1
  97. package/dist/chunk-TBQR5VCN.js.map +1 -0
  98. package/dist/{chunk-3N2HWNKT.js → chunk-UIJLDAV7.js} +2 -2
  99. package/dist/{chunk-7HZ36QDH.js → chunk-UN5WU2OX.js} +9 -3
  100. package/dist/chunk-UN5WU2OX.js.map +1 -0
  101. package/dist/{chunk-A27J4CIZ.js → chunk-UTIYB6VE.js} +11 -11
  102. package/dist/{chunk-5V7IZBRY.js → chunk-VRSW7PIO.js} +5 -5
  103. package/dist/{chunk-U4PV2ZKK.js → chunk-WDEVKND3.js} +3 -3
  104. package/dist/chunk-WGKLBVDZ.js +1 -0
  105. package/dist/chunk-WGKLBVDZ.js.map +1 -0
  106. package/dist/{chunk-AP7GEUJS.js → chunk-XFOKLWJZ.js} +2 -2
  107. package/dist/{chunk-6D5AMANO.js → chunk-XQAFSC66.js} +2 -2
  108. package/dist/{chunk-YNZUYZ2O.js → chunk-XR474YYX.js} +2 -2
  109. package/dist/{chunk-L5RS6QAT.js → chunk-YBF2WUGQ.js} +2 -2
  110. package/dist/{chunk-RCTHCXS6.js → chunk-YQ5GQ32T.js} +2 -2
  111. package/dist/{chunk-YLZXIR6B.js → chunk-Z5V5E3JW.js} +4 -4
  112. package/dist/data-display/Alert.js +10 -6
  113. package/dist/data-display/Banner.js +3 -3
  114. package/dist/data-display/CardKit.js +9 -8
  115. package/dist/data-display/Carousel.js +2 -2
  116. package/dist/data-display/Chart.js +11 -11
  117. package/dist/data-display/DataGrid.js +1 -1
  118. package/dist/data-display/DataViews.js +33 -32
  119. package/dist/data-display/DayRuler.js +7 -7
  120. package/dist/data-display/FleetMap.js +7 -7
  121. package/dist/data-display/HoverCard.js +2 -2
  122. package/dist/data-display/Lightbox.js +3 -3
  123. package/dist/data-display/MapPreview.js +4 -4
  124. package/dist/data-display/Progress.js +2 -2
  125. package/dist/data-display/RegionMap.js +14 -8
  126. package/dist/feedback/NotificationStatusNotice.js +7 -6
  127. package/dist/feedback/SequenceResolver.js +14 -13
  128. package/dist/native/data-display/Alert.js +10 -0
  129. package/dist/native/data-display/Alert.js.map +1 -1
  130. package/dist/types/components/data-display/Alert/Alert.content.d.ts.map +1 -1
  131. package/dist/types/components/data-display/Alert/Alert.d.ts.map +1 -1
  132. package/dist/types/components/data-display/Alert/Alert.ink.d.ts +65 -0
  133. package/dist/types/components/data-display/Alert/Alert.ink.d.ts.map +1 -0
  134. package/dist/types/components/data-display/Alert/Alert.metrics.d.ts +73 -5
  135. package/dist/types/components/data-display/Alert/Alert.metrics.d.ts.map +1 -1
  136. package/dist/types/components/data-display/Alert/index.d.ts +1 -0
  137. package/dist/types/components/data-display/Alert/index.d.ts.map +1 -1
  138. package/dist/types/components/data-display/RegionMap/RegionMap.d.ts +1 -1
  139. package/dist/types/components/data-display/RegionMap/RegionMap.d.ts.map +1 -1
  140. package/dist/types/components/data-display/RegionMap/RegionMap.helpers.d.ts +9 -0
  141. package/dist/types/components/data-display/RegionMap/RegionMap.helpers.d.ts.map +1 -1
  142. package/dist/types/components/data-display/RegionMap/RegionMap.types.d.ts +45 -1
  143. package/dist/types/components/data-display/RegionMap/RegionMap.types.d.ts.map +1 -1
  144. package/dist/types/components/data-display/RegionMap/RegionMapDrawing.d.ts +4 -1
  145. package/dist/types/components/data-display/RegionMap/RegionMapDrawing.d.ts.map +1 -1
  146. package/dist/types/components/data-display/RegionMap/RegionMapPin.d.ts +102 -0
  147. package/dist/types/components/data-display/RegionMap/RegionMapPin.d.ts.map +1 -0
  148. package/dist/types/components/data-display/RegionMap/index.d.ts +2 -1
  149. package/dist/types/components/data-display/RegionMap/index.d.ts.map +1 -1
  150. package/dist/types-native/components/data-display/Alert/Alert.metrics.d.ts +73 -5
  151. package/dist/types-native/components/data-display/Alert/Alert.metrics.d.ts.map +1 -1
  152. package/package.json +1 -1
  153. package/src/components/data-display/Alert/Alert.content.tsx +16 -1
  154. package/src/components/data-display/Alert/Alert.ink.ts +106 -0
  155. package/src/components/data-display/Alert/Alert.md +40 -0
  156. package/src/components/data-display/Alert/Alert.metrics.ts +57 -5
  157. package/src/components/data-display/Alert/Alert.tsx +18 -7
  158. package/src/components/data-display/Alert/index.ts +1 -0
  159. package/src/components/data-display/RegionMap/RegionMap.helpers.ts +1 -1
  160. package/src/components/data-display/RegionMap/RegionMap.md +19 -2
  161. package/src/components/data-display/RegionMap/RegionMap.tsx +4 -0
  162. package/src/components/data-display/RegionMap/RegionMap.types.ts +49 -1
  163. package/src/components/data-display/RegionMap/RegionMapDrawing.tsx +11 -13
  164. package/src/components/data-display/RegionMap/RegionMapPin.tsx +388 -0
  165. package/src/components/data-display/RegionMap/index.ts +5 -0
  166. package/dist/chunk-3CXRHRGE.js.map +0 -1
  167. package/dist/chunk-5ZY3IIIG.js.map +0 -1
  168. package/dist/chunk-7HZ36QDH.js.map +0 -1
  169. package/dist/chunk-COOSJKZL.js.map +0 -1
  170. package/dist/chunk-DY2I6LMX.js +0 -1
  171. package/dist/chunk-E4MJA52O.js.map +0 -1
  172. package/dist/chunk-NQCTANF3.js.map +0 -1
  173. package/dist/chunk-NUGT7LMR.js +0 -1
  174. /package/dist/{chunk-DY2I6LMX.js.map → _internal/components/data-display/Alert/Alert.ink.js.map} +0 -0
  175. /package/dist/{chunk-NUGT7LMR.js.map → _internal/components/data-display/RegionMap/RegionMapPin.js.map} +0 -0
  176. /package/dist/{chunk-WYNGH2WL.js.map → chunk-255WTBZ5.js.map} +0 -0
  177. /package/dist/{chunk-QIP37Y2C.js.map → chunk-2RC6EAGD.js.map} +0 -0
  178. /package/dist/{chunk-ZKVSFVIA.js.map → chunk-37MJZLQU.js.map} +0 -0
  179. /package/dist/{chunk-BQBEN44R.js.map → chunk-3I7KE2N6.js.map} +0 -0
  180. /package/dist/{chunk-L4FWEI2P.js.map → chunk-3V3Z4EML.js.map} +0 -0
  181. /package/dist/{chunk-6RYSSNOO.js.map → chunk-54DOLCJ3.js.map} +0 -0
  182. /package/dist/{chunk-74IH3ZGD.js.map → chunk-643YFWNK.js.map} +0 -0
  183. /package/dist/{chunk-FRQGZIYU.js.map → chunk-6WAP7BJS.js.map} +0 -0
  184. /package/dist/{chunk-JO6D7YGN.js.map → chunk-CWRQGA2T.js.map} +0 -0
  185. /package/dist/{chunk-ZW7Q3IRL.js.map → chunk-FYJL432J.js.map} +0 -0
  186. /package/dist/{chunk-G6TKWNF2.js.map → chunk-GZITNT7O.js.map} +0 -0
  187. /package/dist/{chunk-RFMQBIE6.js.map → chunk-HBHBRRSW.js.map} +0 -0
  188. /package/dist/{chunk-U4Z6GZDW.js.map → chunk-HN36UVOE.js.map} +0 -0
  189. /package/dist/{chunk-WK577LQL.js.map → chunk-J2IQ6FJ5.js.map} +0 -0
  190. /package/dist/{chunk-HCTHY66U.js.map → chunk-KAGXV3ID.js.map} +0 -0
  191. /package/dist/{chunk-FWAY2SAI.js.map → chunk-KAZWBDIH.js.map} +0 -0
  192. /package/dist/{chunk-DKPELKGL.js.map → chunk-KV7LTOWC.js.map} +0 -0
  193. /package/dist/{chunk-UC7DLGMP.js.map → chunk-KVP5A3YK.js.map} +0 -0
  194. /package/dist/{chunk-EGBQR5GH.js.map → chunk-LOLYBFYY.js.map} +0 -0
  195. /package/dist/{chunk-SOXO2VN3.js.map → chunk-MEMVZW64.js.map} +0 -0
  196. /package/dist/{chunk-G2NVBCF7.js.map → chunk-NWUMGE6T.js.map} +0 -0
  197. /package/dist/{chunk-64LNNC54.js.map → chunk-QLKUWDMQ.js.map} +0 -0
  198. /package/dist/{chunk-MPVH2GM5.js.map → chunk-RAQD5QCM.js.map} +0 -0
  199. /package/dist/{chunk-KXDLLS62.js.map → chunk-REHGWN5M.js.map} +0 -0
  200. /package/dist/{chunk-Z4ZFJ565.js.map → chunk-SRAIV6U6.js.map} +0 -0
  201. /package/dist/{chunk-3N2HWNKT.js.map → chunk-UIJLDAV7.js.map} +0 -0
  202. /package/dist/{chunk-A27J4CIZ.js.map → chunk-UTIYB6VE.js.map} +0 -0
  203. /package/dist/{chunk-5V7IZBRY.js.map → chunk-VRSW7PIO.js.map} +0 -0
  204. /package/dist/{chunk-U4PV2ZKK.js.map → chunk-WDEVKND3.js.map} +0 -0
  205. /package/dist/{chunk-AP7GEUJS.js.map → chunk-XFOKLWJZ.js.map} +0 -0
  206. /package/dist/{chunk-6D5AMANO.js.map → chunk-XQAFSC66.js.map} +0 -0
  207. /package/dist/{chunk-YNZUYZ2O.js.map → chunk-XR474YYX.js.map} +0 -0
  208. /package/dist/{chunk-L5RS6QAT.js.map → chunk-YBF2WUGQ.js.map} +0 -0
  209. /package/dist/{chunk-RCTHCXS6.js.map → chunk-YQ5GQ32T.js.map} +0 -0
  210. /package/dist/{chunk-YLZXIR6B.js.map → chunk-Z5V5E3JW.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/RegionMap/RegionMap.helpers.ts"],"sourcesContent":["import type { RegionMapPoint, RegionMapRegion, RegionMapRing } from './RegionMap.types';\n\n/**\n * The geometry behind `RegionMap`, kept pure so it is tested without a DOM.\n *\n * Coordinates are projected to METRES on a plane around the centre\n * (equirectangular): within the tens of kilometres a map like this spans, its\n * error is far below any outline's own. `y` grows SOUTH, as SVG's does.\n */\n\n/** Metres per degree of latitude on the mean sphere. */\nconst METRES_PER_DEGREE = 111_195;\n\n/** A projected point, metres east (`x`) and south (`y`) of the centre. */\nexport interface PlanePoint {\n x: number;\n y: number;\n}\n\n/** An SVG viewBox in projected metres. */\nexport interface PlaneBox {\n /** West edge, metres east of the centre. */\n minX: number;\n /** North edge, metres south of the centre. */\n minY: number;\n /** East-west extent, metres. */\n spanX: number;\n /** North-south extent, metres. */\n spanY: number;\n}\n\nexport interface Projection {\n project: (point: RegionMapPoint) => PlanePoint;\n}\n\n/** The projection around a centre. */\nexport function projectionAt(center: { latitude: number; longitude: number }): Projection {\n const kx = METRES_PER_DEGREE * Math.cos((center.latitude * Math.PI) / 180);\n return {\n project: ([latitude, longitude]) => ({\n x: (longitude - center.longitude) * kx,\n y: -(latitude - center.latitude) * METRES_PER_DEGREE,\n }),\n };\n}\n\n/** A ring as an SVG path segment, closed. */\nfunction ringPath(ring: readonly PlanePoint[]): string {\n if (ring.length === 0) return '';\n const [first, ...rest] = ring;\n return `M${first!.x.toFixed(1)} ${first!.y.toFixed(1)}${rest.map((p) => `L${p.x.toFixed(1)} ${p.y.toFixed(1)}`).join('')}Z`;\n}\n\n/** Every ring of an area as one path, to be filled with `fill-rule=\"evenodd\"`. */\nexport function regionPath(rings: readonly (readonly PlanePoint[])[]): string {\n return rings.map(ringPath).join('');\n}\n\n/** The smallest and largest of some numbers, in one pass (no spread). */\nexport function extent(values: Iterable<number>): { min: number; max: number } | null {\n let min = Infinity;\n let max = -Infinity;\n for (const value of values) {\n if (value < min) min = value;\n if (value > max) max = value;\n }\n return min === Infinity ? null : { min, max };\n}\n\n/** The box around projected rings. */\nexport function planeBounds(rings: readonly (readonly PlanePoint[])[]): PlaneBox | null {\n const points = rings.flat();\n const xs = extent(points.map((p) => p.x));\n const ys = extent(points.map((p) => p.y));\n if (xs === null || ys === null) return null;\n return { minX: xs.min, minY: ys.min, spanX: xs.max - xs.min, spanY: ys.max - ys.min };\n}\n\n/**\n * The square the map shows: the largest circle with a margin, else every area,\n * else nothing. Square so the drawing keeps its proportions at every width.\n */\nexport function viewBoxFor(\n largestRadius: number | null,\n areaBounds: PlaneBox | null,\n margin = 0.12,\n): PlaneBox | null {\n if (largestRadius !== null && largestRadius > 0) {\n const half = largestRadius * (1 + margin);\n return { minX: -half, minY: -half, spanX: half * 2, spanY: half * 2 };\n }\n if (areaBounds === null) return null;\n const side = Math.max(areaBounds.spanX, areaBounds.spanY) * (1 + margin) || 1;\n const cx = areaBounds.minX + areaBounds.spanX / 2;\n const cy = areaBounds.minY + areaBounds.spanY / 2;\n return { minX: cx - side / 2, minY: cy - side / 2, spanX: side, spanY: side };\n}\n\n/** Do two boxes overlap? Used to skip areas wholly outside the view. */\nexport function boxesOverlap(a: PlaneBox, b: PlaneBox): boolean {\n return (\n a.minX <= b.minX + b.spanX &&\n b.minX <= a.minX + a.spanX &&\n a.minY <= b.minY + b.spanY &&\n b.minY <= a.minY + a.spanY\n );\n}\n\n/** How many of one ring's edges a ray from the point, eastward, crosses. */\nfunction ringCrossings(ring: readonly PlanePoint[], point: PlanePoint): number {\n let crossings = 0;\n for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {\n const a = ring[i]!;\n const b = ring[j]!;\n if (a.y > point.y !== b.y > point.y && point.x < ((b.x - a.x) * (point.y - a.y)) / (b.y - a.y) + a.x) {\n crossings += 1;\n }\n }\n return crossings;\n}\n\n/** Is the point inside the rings, by the even-odd rule? */\nexport function ringsContain(rings: readonly (readonly PlanePoint[])[], point: PlanePoint): boolean {\n return rings.reduce((sum, ring) => sum + ringCrossings(ring, point), 0) % 2 === 1;\n}\n\n/** The point's distance to one ring's nearest edge. */\nfunction ringDistance(ring: readonly PlanePoint[], point: PlanePoint): number {\n let best = Infinity;\n for (let i = 1; i <= ring.length; i++) {\n const a = ring[i - 1]!;\n const b = ring[i % ring.length]!;\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const lengthSquared = dx * dx + dy * dy;\n const t =\n lengthSquared === 0\n ? 0\n : Math.max(0, Math.min(1, ((point.x - a.x) * dx + (point.y - a.y) * dy) / lengthSquared));\n best = Math.min(best, Math.hypot(a.x + t * dx - point.x, a.y + t * dy - point.y));\n }\n return best;\n}\n\n/** The point's distance to the rings: 0 inside, else to the nearest edge. */\nexport function ringsDistance(rings: readonly (readonly PlanePoint[])[], point: PlanePoint): number {\n if (ringsContain(rings, point)) return 0;\n let best = Infinity;\n for (const ring of rings) best = Math.min(best, ringDistance(ring, point));\n return best;\n}\n\n/** An area projected once: what drawing it and hit-testing it read. */\nexport interface AreaGeometry {\n rings: readonly (readonly PlanePoint[])[];\n /** Null for an area with no points. */\n bounds: PlaneBox | null;\n /** Square metres of the largest ring — orders hits and draw order. */\n area: number;\n /** The SVG path, every ring, for `fill-rule=\"evenodd\"`. */\n path: string;\n}\n\n/** A projected area, as the hit test reads it. */\nexport interface PlaneRegion {\n id: string;\n geometry: AreaGeometry;\n}\n\n/** Is the point within `margin` of the box? */\nfunction nearBox(box: PlaneBox, point: PlanePoint, margin: number): boolean {\n return (\n point.x >= box.minX - margin &&\n point.x <= box.minX + box.spanX + margin &&\n point.y >= box.minY - margin &&\n point.y <= box.minY + box.spanY + margin\n );\n}\n\n/**\n * Which area a tap at this point means: the SMALLEST area within `tolerance`\n * of it, the ones holding it included (distance 0).\n *\n * Smallest, because a fingertip is wider than a sliver: a tap that lands on a\n * big area a few pixels from a 10 m strip almost always meant the strip, and\n * the big one stays easy to hit everywhere else. An area in another's hole is\n * smaller than the one around it, so it wins too. Nothing within the\n * tolerance — empty map — is nothing: a tap there is not a guess. Areas whose\n * box is not near the point are skipped before any ray is cast.\n */\nexport function hitRegion(\n regions: readonly PlaneRegion[],\n point: PlanePoint,\n tolerance: number,\n): string | null {\n let best: { id: string; area: number; distance: number } | null = null;\n for (const { id, geometry } of regions) {\n const distance = reach(geometry, point, tolerance);\n if (distance !== null && beats(geometry.area, distance, best)) {\n best = { id, area: geometry.area, distance };\n }\n }\n return best?.id ?? null;\n}\n\n/** The point's distance to the area, or null when it is beyond the tolerance. */\nfunction reach(geometry: AreaGeometry, point: PlanePoint, tolerance: number): number | null {\n if (geometry.bounds === null || !nearBox(geometry.bounds, point, tolerance)) return null;\n const distance = ringsDistance(geometry.rings, point);\n return distance <= tolerance ? distance : null;\n}\n\n/** Smaller wins; between two the same size, the nearer. */\nfunction beats(area: number, distance: number, best: { area: number; distance: number } | null): boolean {\n if (best === null || area < best.area) return true;\n return area === best.area && distance < best.distance;\n}\n\n/** Signed area and centroid of one ring (shoelace). */\nfunction ringCentroid(ring: readonly PlanePoint[]): { area: number; x: number; y: number } {\n let area = 0;\n let cx = 0;\n let cy = 0;\n for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {\n const a = ring[j]!;\n const b = ring[i]!;\n const cross = a.x * b.y - b.x * a.y;\n area += cross;\n cx += (a.x + b.x) * cross;\n cy += (a.y + b.y) * cross;\n }\n area /= 2;\n if (area === 0) return { area: 0, x: ring[0]?.x ?? 0, y: ring[0]?.y ?? 0 };\n return { area, x: cx / (6 * area), y: cy / (6 * area) };\n}\n\n/**\n * The area's size in square metres, read from its LARGEST ring. Rough on\n * purpose — holes and second parts are ignored — because it only orders\n * things: which of two areas holding a tap is the smaller, and which is drawn\n * first so a small one is never painted over by its neighbour.\n */\nexport function planeArea(rings: readonly (readonly PlanePoint[])[]): number {\n let largest = 0;\n for (const ring of rings) largest = Math.max(largest, Math.abs(ringCentroid(ring).area));\n return largest;\n}\n\n/**\n * Where an area's label goes: the centroid of its largest ring, pulled back\n * inside the view, as fractions of the view (0..1) — the label is HTML laid\n * over the drawing, so its type stays the theme's size at every width.\n */\nexport function labelPosition(\n rings: readonly (readonly PlanePoint[])[],\n view: PlaneBox,\n inset = 0.04,\n): { fractionX: number; fractionY: number } {\n const largest = rings\n .map(ringCentroid)\n .reduce((a, b) => (Math.abs(b.area) > Math.abs(a.area) ? b : a), { area: 0, x: 0, y: 0 });\n const clamp = (value: number): number => Math.min(1 - inset, Math.max(inset, value));\n return {\n fractionX: clamp((largest.x - view.minX) / view.spanX),\n fractionY: clamp((largest.y - view.minY) / view.spanY),\n };\n}\n\n/** Every ring of an area, projected. */\nexport function projectRings(rings: readonly RegionMapRing[], projection: Projection): PlanePoint[][] {\n return rings.map((ring) => ring.map(projection.project));\n}\n\n/** One area's geometry, projected and pathed. */\nexport function areaGeometry(rings: readonly RegionMapRing[], projection: Projection): AreaGeometry {\n const plane = projectRings(rings, projection);\n return { rings: plane, bounds: planeBounds(plane), area: planeArea(plane), path: regionPath(plane) };\n}\n\n/**\n * A cache of geometry per `rings` IDENTITY, for one projection. A host that\n * re-creates its region objects on every toggle (`{ ...area, excluded }`)\n * keeps the same `rings` arrays, so a tap re-projects nothing.\n */\nexport function geometryCache(projection: Projection): (rings: readonly RegionMapRing[]) => AreaGeometry {\n const cache = new WeakMap<readonly RegionMapRing[], AreaGeometry>();\n return (rings) => {\n let geometry = cache.get(rings);\n if (geometry === undefined) {\n geometry = areaGeometry(rings, projection);\n cache.set(rings, geometry);\n }\n return geometry;\n };\n}\n\n/** An area as the drawing reads it. */\nexport type DrawnRegion = RegionMapRegion & { geometry: AreaGeometry };\n\n/** The areas worth drawing — any part in the view — largest first. */\nexport function drawOrder(\n regions: readonly RegionMapRegion[],\n geometryOf: (rings: readonly RegionMapRing[]) => AreaGeometry,\n view: PlaneBox,\n): DrawnRegion[] {\n return regions\n .map((region) => ({ ...region, geometry: geometryOf(region.rings) }))\n .filter(({ geometry }) => geometry.bounds !== null && boxesOverlap(geometry.bounds, view))\n .sort((a, b) => b.geometry.area - a.geometry.area);\n}\n\n/**\n * A Google encoded polyline into `[latitude, longitude]` points, at 1e-5 — the\n * compact form an outline usually travels in. Product-free, so it lives here.\n */\nexport function decodePolyline(encoded: string, precision = 1e5): RegionMapPoint[] {\n const points: RegionMapPoint[] = [];\n let index = 0;\n let lat = 0;\n let lng = 0;\n const next = (): number => {\n let shift = 0;\n let result = 0;\n let byte: number;\n do {\n byte = encoded.charCodeAt(index++) - 63;\n result |= (byte & 0x1f) << shift;\n shift += 5;\n } while (byte >= 0x20);\n return result & 1 ? ~(result >> 1) : result >> 1;\n };\n while (index < encoded.length) {\n lat += next();\n lng += next();\n points.push([lat / precision, lng / precision]);\n }\n return points;\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- //# sourceMappingURL=chunk-DY2I6LMX.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/RegionMap/RegionMapDrawing.tsx"],"sourcesContent":["import Box from '@mui/material/Box/index.js';\nimport Typography from '@mui/material/Typography/index.js';\nimport { alpha, type Theme } from '@mui/material/styles/index.js';\nimport React from 'react';\n\nimport { rem, remPx } from '../../../tokens/relative';\n\nimport { labelPosition, type AreaGeometry, type DrawnRegion, type PlaneBox } from './RegionMap.helpers';\nimport type { RegionMapModel } from './RegionMap.hooks';\nimport { labelOrder, placeLabels } from './RegionMap.labels';\nimport type { RegionMapLayer } from './RegionMap.types';\n\nexport interface RegionMapDrawingProps {\n model: RegionMapModel & { view: PlaneBox };\n /** The host's layer, drawn inside the SVG under the circles (`RegionMapProps.overlay`). */\n overlay?: (layer: RegionMapLayer) => React.ReactNode;\n showCenter: boolean;\n highlightedIds: readonly string[];\n maxHeight: string | undefined;\n label: string;\n tappable: boolean;\n testId: string;\n theme: Theme;\n}\n\n/**\n * The drawing: one `role=\"img\"`, square, with HTML labels laid over it.\n *\n * Strokes are `non-scaling-stroke` and labels are HTML at theme sizes, so the\n * picture reads the same at 320 px and 1600 px; `maxHeight` caps it on a wide\n * screen. Where it sits in a wider box is the host's call.\n *\n * The base areas are a memoised layer: a toggle changes `excluded`, not the\n * geometry, so only the hatch, highlight and label layers re-render.\n */\nexport function RegionMapDrawing({\n model,\n overlay,\n showCenter,\n highlightedIds,\n maxHeight,\n label,\n tappable,\n testId,\n theme,\n}: RegionMapDrawingProps): React.JSX.Element {\n const hatchId = `${React.useId().replace(/:/g, '')}-hatch`;\n const { view, drawn } = model;\n const wanted = new Set(highlightedIds);\n const highlighted = drawn.filter((d) => wanted.has(d.id));\n // Highlighted, then excluded, then larger, then by name: the order labels\n // claim their place in, so a collision hides the less important one.\n const labelled = labelOrder(drawn.filter((d) => d.excluded || wanted.has(d.id)), wanted);\n const boxRef = React.useRef<HTMLDivElement>(null);\n useLabelPlacement(boxRef, labelled.map((d) => d.id).join('|'), remPx(theme, 4));\n const base = drawn.map((d) => ({ id: d.id, name: d.name, geometry: d.geometry, outside: d.outside === true }));\n return (\n <Box\n sx={{\n position: 'relative',\n width: '100%',\n maxWidth: maxHeight,\n maxHeight,\n aspectRatio: '1 / 1',\n border: 1,\n borderColor: 'divider',\n borderRadius: 1,\n overflow: 'hidden',\n bgcolor: 'background.paper',\n }}\n data-testid={`${testId}-canvas`}\n ref={boxRef}\n >\n <svg\n viewBox={`${view.minX} ${view.minY} ${view.spanX} ${view.spanY}`}\n role=\"img\"\n aria-label={label}\n onPointerDown={model.onPointerDown}\n onClick={model.onClick}\n style={{ display: 'block', width: '100%', height: '100%', cursor: tappable ? 'pointer' : 'default' }}\n >\n <Hatch id={hatchId} pitch={view.spanX / 70} theme={theme} />\n <BaseAreas areas={base} testId={testId} theme={theme} />\n <ExcludedAreas drawn={drawn} hatchId={hatchId} testId={testId} theme={theme} />\n {overlay && model.projection && (\n // `pointer-events` is inherited in SVG: nothing the host draws here\n // takes a tap from the areas beneath.\n <g pointerEvents=\"none\" data-testid={`${testId}-overlay`}>\n {overlay({ view, projection: model.projection })}\n </g>\n )}\n <Circles radii={model.radii} theme={theme} />\n <Highlights areas={highlighted} testId={testId} theme={theme} />\n {showCenter && (\n <circle\n cx={0}\n cy={0}\n r={view.spanX / 90}\n fill={theme.palette.primary.main}\n stroke={theme.palette.background.paper}\n strokeWidth={2}\n vectorEffect=\"non-scaling-stroke\"\n pointerEvents=\"none\"\n data-testid={`${testId}-center`}\n />\n )}\n </svg>\n {labelled.map((d) => (\n <AreaLabel key={`l-${d.id}`} area={d} view={view} testId={testId} theme={theme} />\n ))}\n </Box>\n );\n}\n\n/** The highlighted areas, drawn over everything but the centre. */\nfunction Highlights({\n areas,\n testId,\n theme,\n}: {\n areas: readonly DrawnRegion[];\n testId: string;\n theme: Theme;\n}): React.JSX.Element {\n return (\n <>\n {areas.map((d) => (\n <path\n key={`h-${d.id}`}\n d={d.geometry.path}\n fillRule=\"evenodd\"\n vectorEffect=\"non-scaling-stroke\"\n fill={alpha(theme.palette.primary.main, 0.3)}\n stroke={theme.palette.primary.main}\n strokeWidth={2.5}\n pointerEvents=\"none\"\n data-testid={`${testId}-highlight-${d.id}`}\n />\n ))}\n </>\n );\n}\n\n/** The hatch an excluded area is filled with: lines, not a colour. */\nfunction Hatch({ id, pitch, theme }: { id: string; pitch: number; theme: Theme }): React.JSX.Element {\n return (\n <defs>\n <pattern id={id} width={pitch} height={pitch} patternUnits=\"userSpaceOnUse\" patternTransform=\"rotate(45)\">\n <rect width={pitch} height={pitch} fill={alpha(theme.palette.text.primary, 0.1)} />\n <rect width={pitch / 3} height={pitch} fill={theme.palette.text.secondary} />\n </pattern>\n </defs>\n );\n}\n\ninterface BaseArea {\n id: string;\n name: string;\n geometry: AreaGeometry;\n outside: boolean;\n}\n\ninterface BaseAreasProps {\n areas: readonly BaseArea[];\n testId: string;\n theme: Theme;\n}\n\n/** Same areas, same geometry objects, same look: nothing to re-render. */\nfunction sameBase(a: BaseAreasProps, b: BaseAreasProps): boolean {\n if (a.theme !== b.theme || a.testId !== b.testId || a.areas.length !== b.areas.length) return false;\n return a.areas.every((area, i) => {\n const other = b.areas[i]!;\n return (\n area.id === other.id &&\n area.geometry === other.geometry &&\n area.outside === other.outside &&\n area.name === other.name\n );\n });\n}\n\n/** Every area's fill and border — the tap targets. Memoised: see `sameBase`. */\nconst BaseAreas = React.memo(function BaseAreas({ areas, testId, theme }: BaseAreasProps): React.JSX.Element {\n const { palette } = theme;\n return (\n <>\n {areas.map((d) => (\n <path\n key={d.id}\n d={d.geometry.path}\n fillRule=\"evenodd\"\n vectorEffect=\"non-scaling-stroke\"\n fill={d.outside ? palette.background.paper : palette.action.hover}\n stroke={palette.divider}\n strokeWidth={1}\n data-region-id={d.id}\n data-testid={`${testId}-area-${d.id}`}\n >\n <title>{d.name}</title>\n </path>\n ))}\n </>\n );\n}, sameBase);\n\n/** The hatch over every excluded area. */\nfunction ExcludedAreas({\n drawn,\n hatchId,\n testId,\n theme,\n}: {\n drawn: readonly DrawnRegion[];\n hatchId: string;\n testId: string;\n theme: Theme;\n}): React.JSX.Element {\n return (\n <>\n {drawn\n .filter((d) => d.excluded)\n .map((d) => (\n <path\n key={`x-${d.id}`}\n d={d.geometry.path}\n fillRule=\"evenodd\"\n vectorEffect=\"non-scaling-stroke\"\n fill={`url(#${hatchId})`}\n stroke={theme.palette.text.secondary}\n strokeWidth={1.5}\n pointerEvents=\"none\"\n data-testid={`${testId}-excluded-${d.id}`}\n />\n ))}\n </>\n );\n}\n\n/** The dashed circles around the centre. */\nfunction Circles({ radii, theme }: { radii: readonly number[]; theme: Theme }): React.JSX.Element {\n return (\n <>\n {radii.map((radius) => (\n <circle\n key={radius}\n cx={0}\n cy={0}\n r={radius}\n fill=\"none\"\n stroke={theme.palette.info.main}\n strokeWidth={1.75}\n strokeDasharray=\"7 5\"\n vectorEffect=\"non-scaling-stroke\"\n pointerEvents=\"none\"\n />\n ))}\n </>\n );\n}\n\n/**\n * Places every label the drawing carries, in their DOM order (the priority\n * order), and hides one that would overlap a label already drawn\n * (`placeLabels`). Measured by a ResizeObserver, never in a layout effect: its\n * first call comes after the browser's own layout, so mounting a label on a\n * tap forces no synchronous reflow of the drawing.\n */\nfunction useLabelPlacement(boxRef: React.RefObject<HTMLDivElement | null>, key: string, gap: number): void {\n React.useEffect(() => {\n const box = boxRef.current;\n if (!box || typeof ResizeObserver === 'undefined') return undefined;\n const labels = Array.from(box.querySelectorAll<HTMLElement>('[data-region-label]'));\n const place = (): void => {\n const spanX = box.clientWidth;\n const spanY = box.clientHeight;\n if (spanX === 0 || spanY === 0) return;\n const placed = placeLabels(\n labels.map((label) => ({\n fractionX: Number(label.dataset.fractionX),\n fractionY: Number(label.dataset.fractionY),\n spanX: label.offsetWidth,\n spanY: label.offsetHeight,\n })),\n { spanX, spanY },\n gap,\n );\n placed.forEach(({ x, y, visible }, index) => {\n const label = labels[index]!;\n label.style.left = `${(x / spanX) * 100}%`;\n label.style.top = `${(y / spanY) * 100}%`;\n label.style.visibility = visible ? 'visible' : 'hidden';\n label.dataset.hidden = visible ? 'false' : 'true';\n });\n };\n const observer = new ResizeObserver(place);\n observer.observe(box);\n for (const label of labels) observer.observe(label);\n return () => observer.disconnect();\n }, [boxRef, key, gap]);\n}\n\n/**\n * An area's name over the drawing, at the theme's type size whatever the\n * width. Placed — and hidden on a collision — by {@link useLabelPlacement}.\n * Decorative (`aria-hidden`): the area's name is its `<title>` and its row in\n * the list.\n */\nfunction AreaLabel({\n area,\n view,\n testId,\n theme,\n}: {\n area: DrawnRegion;\n view: PlaneBox;\n testId: string;\n theme: Theme;\n}): React.JSX.Element {\n const at = labelPosition(area.geometry.rings, view);\n const halo = `0 0 ${rem(theme, 3)} ${theme.palette.background.paper}`;\n return (\n <Typography\n component=\"span\"\n aria-hidden\n data-testid={`${testId}-label-${area.id}`}\n data-region-label=\"\"\n data-fraction-x={at.fractionX}\n data-fraction-y={at.fractionY}\n // Position as an inline style, not `sx`: a per-label class would insert\n // a new CSS rule (and a style recalculation) on every tap.\n style={{\n left: `${(at.fractionX * 100).toFixed(2)}%`,\n top: `${(at.fractionY * 100).toFixed(2)}%`,\n }}\n sx={{\n position: 'absolute',\n transform: 'translate(-50%, -50%)',\n fontSize: rem(theme, 12),\n fontWeight: 700,\n lineHeight: 1.1,\n textAlign: 'center',\n maxWidth: '45%',\n color: 'text.primary',\n pointerEvents: 'none',\n textShadow: `${halo}, ${halo}`,\n }}\n >\n {area.name}\n </Typography>\n );\n}\n"],"mappings":"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","names":["BaseAreas"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/Alert/Alert.tsx"],"sourcesContent":["import Close from '@mui/icons-material/Close';\nimport MuiAlert from '@mui/material/Alert/index.js';\nimport Box from '@mui/material/Box/index.js';\nimport Collapse from '@mui/material/Collapse/index.js';\nimport IconButton from '@mui/material/IconButton/index.js';\nimport { alpha, styled, useTheme } from '@mui/material/styles/index.js';\nimport type { Theme } from '@mui/material/styles/index.js';\nimport React from 'react';\n\nimport { absoluteInk, modeInk } from '../../../tokens/ink';\n\nimport { AlertContent } from './Alert.content';\nimport { resolveAlertProps, resolveAnnouncement, testIdFor } from './Alert.helpers';\nimport { resolveIconPlacement, type AlertIconPlacement } from './Alert.placement';\nimport type { AlertPalette } from './Alert.metrics';\nimport {\n ACTIVE,\n GLOW,\n ALERT_EASING,\n ALERT_RADIUS_UNITS,\n ALERT_TRANSITION_MS,\n CLOSE_BUTTON,\n CLOSE_DELAY_MS,\n COLLAPSE_MS,\n FADE_IN,\n FOCUS,\n HOVER,\n seconds,\n} from './Alert.metrics';\nimport {\n alertEmphasisStyles,\n alertLayoutStyles,\n alertVariantStyles,\n fadeInScale,\n getColorFromTheme,\n getVariantIcon,\n} from './Alert.styles';\nimport type { AlertColor } from '@mui/material/Alert/index.js';\nimport type { AlertProps } from './Alert.types';\nimport { resolveTestId, withoutTestIdProps } from '../../../platform/test-id';\nimport { rem, rems } from '../../../tokens/relative';\n\nconst transition = `all ${seconds(ALERT_TRANSITION_MS)} ${ALERT_EASING}`;\n\n// Define animations\n/**\n * The pointer states' shadow: a flat tint, plus the glow when the alert has one.\n *\n * The tint is an inset spread at 100vmax, which always exceeds the element, so\n * it covers the surface edge to edge. It paints ABOVE the background and BELOW\n * the content, which is what keeps the ink's own contrast out of these states\n * entirely — see `ACTIVE` in `Alert.metrics.ts` for why a layer replaced the\n * opacity dip and the brightness multiplier that each preceded it.\n *\n * The glow is COMPOSED rather than replaced, so hovering a glowing alert keeps\n * its glow; `glowStyles` gave up its `!important` for this.\n */\nfunction pointerShadow(\n theme: Theme,\n colorPalette: AlertPalette,\n glow: boolean,\n variant: string | undefined,\n): (alpha_: number) => string {\n // The tint moves the surface AWAY from its own ink, which is why this reads\n // the variant and not only the mode.\n //\n // `gradient` is the one variant where the two disagree: it paints a\n // mid-lightness sweep (L* 42–61) under WHITE ink in BOTH modes, so the\n // mode-keyed answer tinted it white in dark mode — toward the text. Measured:\n // white-on-gradient fell to 2.90:1 on hover and 2.41:1 pressed, under the 3:1\n // floor and below its own idle. Every other variant's surface tracks the mode,\n // so for them the two rules agree.\n const ink = variant === 'gradient' ? absoluteInk(theme).black : modeInk(theme);\n const glowShadow = glow\n ? `0 0 ${rems(theme, GLOW.blur, GLOW.spread)} ${alpha(colorPalette.main, GLOW.alpha)}`\n : null;\n return (alpha_) =>\n [`inset 0 0 0 100vmax ${alpha(ink, alpha_)}`, glowShadow].filter(Boolean).join(', ');\n}\n\nconst StyledAlert = styled(MuiAlert, {\n shouldForwardProp: (prop) =>\n !['customVariant', 'customColor', 'glow', 'pulse', 'animate'].includes(prop as string),\n})<{\n customVariant?: string;\n customColor?: string;\n glow?: boolean;\n pulse?: boolean;\n animate?: boolean;\n}>(({ theme, customVariant, customColor, glow, pulse, animate }) => {\n const colorPalette = getColorFromTheme(theme, customColor || customVariant || 'info');\n\n const withTint = pointerShadow(theme, colorPalette, Boolean(glow), customVariant);\n\n return {\n borderRadius: theme.spacing(ALERT_RADIUS_UNITS),\n transition: `${transition}, box-shadow ${seconds(ACTIVE.ms)} ${ALERT_EASING}`,\n position: 'relative',\n overflow: 'hidden',\n animation: animate ? `${fadeInScale(theme)} ${seconds(FADE_IN.ms)} ease-out` : 'none',\n willChange: 'transform, opacity',\n\n ...alertLayoutStyles(theme, colorPalette, animate),\n\n // Hover: one tint step, and nothing that moves. An alert is a surface\n // rather than a control, so the pointer only needs telling it is here. The\n // icon keeps its own place for the same reason — it is the variant's\n // meaning, not an affordance to animate.\n '&:hover': {\n boxShadow: withTint(HOVER.tintAlpha),\n\n '&::before': {\n opacity: 1,\n },\n },\n\n // Press: a 20% tint, landing at once and easing back. Still no geometry.\n //\n // `transition: none` here is what makes the dip INSTANT: a click's\n // `:active` lasts about as long as the finger is down, so easing into it\n // would be cut off in its first tenth and read as a flicker. The ease is on\n // the way back, governed by the root.\n //\n // Neither `:hover` nor `:focus-visible` may declare `transition`, and that\n // is not a style preference. `:active` under a mouse ALWAYS implies\n // `:hover`, so a bare shorthand in the hover block outranks the root's\n // (0,2,0 beats 0,1,0) and silently resets the timing this state rests on.\n //\n // The `:not(:has(…))` names CONTROLS, not any descendant. `:active`\n // matches an ancestor of whatever is pressed, so dismissing an alert\n // dimmed the alert being dismissed and pressing a call to action dimmed\n // the message explaining it. Excluding `:has(:active)` wholesale does not\n // work and was the first attempt: pressing the TEXT makes that text\n // `:active` too, so the guard matched on every press and the state never\n // fired at all.\n '&:active:not(:has(button:active, a:active, [role=\"button\"]:active))': {\n boxShadow: withTint(ACTIVE.tintAlpha),\n transition: 'none',\n },\n\n // Focus: `:focus-visible`, not `:focus-within`.\n //\n // The alert carries `tabIndex={0}`, so a MOUSE CLICK focused it and painted\n // the ring — a keyboard affordance answering a pointer, which is what made\n // clicking one look like an error state. `:focus-visible` is the browser's\n // own answer to \"did this focus come from the keyboard\": the ring stays for\n // whoever tabs here and never fires on a click.\n //\n // One ring, not three. It was a 3px outline at 3px offset UNDER a 6px halo,\n // and stacking two rings on one edge is what read as unfinished rather than\n // as emphasis.\n // It declares no `transition`: `outline-style` is discrete, so the ring\n // arrives at full width with only its COLOUR easing — from `currentcolor`,\n // the near-black alert ink, to the blue. That is a visible dark flash on\n // every keyboard focus, and it would also outrank the root's opacity\n // transition the way the hover block did.\n '&:focus-visible': {\n outline: `${rem(theme, FOCUS.ringWidth)} solid ${alpha(colorPalette.main, FOCUS.ringAlpha)}`,\n outlineOffset: rem(theme, FOCUS.offset),\n },\n\n ...alertVariantStyles(theme, customVariant, colorPalette),\n ...alertEmphasisStyles(theme, colorPalette, Boolean(glow), Boolean(pulse)),\n };\n});\n\n// glass and gradient are our own looks with no MUI severity of their own; both\n// borrow info's. danger is MUI's error.\nconst MUI_SEVERITY: Record<string, AlertColor> = {\n danger: 'error',\n glass: 'info',\n gradient: 'info',\n};\n\nconst toMuiSeverity = (variant: string): AlertColor =>\n MUI_SEVERITY[variant] ?? (variant as AlertColor);\n\nconst AlertCloseButton: React.FC<{ dataTestId?: string; label: string; onClose: () => void }> = ({\n dataTestId,\n label,\n onClose,\n}) => (\n <IconButton\n data-testid={testIdFor(dataTestId, 'close')}\n aria-label={label}\n color=\"inherit\"\n size=\"small\"\n onClick={onClose}\n sx={(theme) => ({\n transition,\n opacity: CLOSE_BUTTON.opacity,\n // Opacity and a wash only: the button used to spin 90deg and grow 1.1,\n // which drew the eye to the dismiss rather than to the message.\n '&:hover': {\n opacity: 1,\n backgroundColor: alpha(theme.palette.action.hover, CLOSE_BUTTON.washAlpha),\n },\n // A REAL ring, on the keyboard-only selector.\n //\n // This used to be `&:focus` setting `outline: 'none'` over a\n // `rgba(0,0,0,0.1)` wash — 1.25:1 against the info surface, and MUI's\n // ButtonBase already sets `outline: 0`, so there was no UA fallback\n // either. It went unnoticed while the ROOT still matched `:focus-within`\n // and drew a ring around the whole alert; moving the root to\n // `:focus-visible` took that away and left this button with no visible\n // focus at all. `Banner`'s dismiss already draws its own outline, so\n // this is also what keeps the two surfaces telling a keyboard user the\n // same thing.\n '&:focus-visible': {\n opacity: 1,\n // `currentColor` is the alert's own ink, inherited through\n // `color=\"inherit\"`, so the ring is drawn in whatever colour was\n // already chosen to be READ on this surface. Measured 11.2:1 on the\n // semantic variants and 5.7:1 on `gradient`.\n //\n // That is a reasoned choice, not a test-backed one, and the difference\n // matters: `alert-contrast.test.tsx` covers the ink of the four\n // semantic variants only — its `glass` case asserts the pane's alpha\n // rather than its ink, and `gradient` it does not render at all. A\n // translucent surface's contrast depends on what sits behind it, which\n // is why that test stops where it does and why this comment does not\n // borrow a guarantee it never made.\n outline: `${rem(theme, FOCUS.ringWidth)} solid currentColor`,\n outlineOffset: rem(theme, FOCUS.offset),\n backgroundColor: alpha(theme.palette.action.focus, CLOSE_BUTTON.washAlpha),\n },\n })}\n >\n <Close fontSize=\"inherit\" />\n </IconButton>\n);\n\n/**\n * The dismiss button, or nothing.\n *\n * Reads `closeLabel` straight off the props rather than through the\n * `definedProps` merge, which would widen it to `string | undefined` and hand\n * the button an empty name. The UNION in `AlertProps` guarantees the label\n * wherever `closable` is true — that narrowing is gone inside the component,\n * which is why the fallback below exists and why it is unreachable.\n */\nfunction dismissButton(\n props: AlertProps,\n dataTestId: string | undefined,\n onClose: () => void,\n): React.JSX.Element | null {\n if (!props.closable) return null;\n return <AlertCloseButton dataTestId={dataTestId} label={props.closeLabel} onClose={onClose} />;\n}\n\n/**\n * Where the icon goes: MUI's own slot (`slot`), or the title's row\n * (`titleIcon`) — never both. On the title's row only when there IS a title\n * and an icon to put on it (`Alert.placement.ts`).\n */\nfunction placeIcon({\n icon,\n dataTestId,\n hasTitle,\n placement,\n}: {\n icon: React.ReactNode;\n dataTestId: string | undefined;\n hasTitle: boolean;\n placement: AlertIconPlacement;\n}): { slot: React.ReactNode; titleIcon?: React.ReactNode } {\n if (icon === null) return { slot: false };\n const glyph = (\n <Box component=\"span\" data-testid={testIdFor(dataTestId, 'icon')}>\n {icon}\n </Box>\n );\n return placement === 'title' && hasTitle ? { slot: false, titleIcon: glyph } : { slot: glyph };\n}\n\nexport const Alert = React.forwardRef<HTMLDivElement, AlertProps>((alertProps, ref) => {\n const {\n variant,\n color,\n glow,\n pulse,\n icon,\n showIcon,\n onClose,\n title,\n description,\n children,\n animate,\n iconPlacement,\n role: _role, announce: _announce, // resolved from `alertProps` — see `resolveAnnouncement`\n 'aria-atomic': ariaAtomic,\n ...others\n } = resolveAlertProps(alertProps);\n\n // Every spelling of the test id the shared contract allows, mapped to the\n // one the DOM reads and defaulted to `alert`; the native Alert does the same.\n const dataTestId = resolveTestId(others, 'alert');\n // Then the dismiss union, which `dismissButton` reads off `alertProps` rather\n // than through this destructure — so without this strip it rides `...props`\n // onto the DOM. `ALERT_DEFAULTS` supplies `closable: false`, so that happened\n // on EVERY alert, not only the closable ones.\n const props = withoutAlertOnlyProps(withoutTestIdProps(others));\n\n // Depends on `variant`, so it cannot live in the static defaults above.\n const announcement = resolveAnnouncement(alertProps, variant);\n const theme = useTheme();\n const [open, setOpen] = React.useState(true);\n const [isClosing, setIsClosing] = React.useState(false);\n\n const handleClose = () => {\n setIsClosing(true);\n window.setTimeout(() => {\n setOpen(false);\n onClose?.();\n }, CLOSE_DELAY_MS);\n };\n\n const severity = toMuiSeverity(variant);\n\n const { slot, titleIcon } = placeIcon({\n icon: showIcon ? (icon ?? getVariantIcon(variant)) : null,\n dataTestId,\n hasTitle: Boolean(title),\n placement: resolveIconPlacement(theme, iconPlacement),\n });\n\n return (\n <Collapse in={open && !isClosing} timeout={COLLAPSE_MS}>\n <StyledAlert\n ref={ref}\n data-testid={dataTestId}\n severity={severity}\n customVariant={variant}\n customColor={color}\n glow={glow}\n pulse={pulse}\n animate={animate}\n icon={slot}\n role={announcement.role}\n aria-live={announcement['aria-live']}\n aria-atomic={ariaAtomic}\n tabIndex={0}\n action={dismissButton(alertProps, dataTestId, handleClose)}\n {...props}\n >\n <AlertContent title={title} description={description} titleIcon={titleIcon} dataTestId={dataTestId}>\n {children}\n </AlertContent>\n </StyledAlert>\n </Collapse>\n );\n});\n\n/**\n * The props `Alert` OWNS, which must never reach the DOM.\n *\n * `AlertProps` extends MUI's, whose rest-spread is how a host's real HTML\n * attributes get onto the root — so the same spread carries the alert's own\n * configuration unless it is named here. Everything else the component consumes\n * leaves through the destructure above; these two do not, because\n * `dismissButton` reads them off the original props to keep the dismiss union's\n * narrowing intact.\n *\n * Exported so a test can render an alert carrying every name on it and assert\n * none reaches the DOM — the check that would have caught `closable`.\n */\nexport const ALERT_ONLY_PROPS = ['closable', 'closeLabel'] as const;\n\nfunction withoutAlertOnlyProps<P extends object>(rest: P): P {\n const html = { ...rest } as Record<string, unknown>;\n for (const key of ALERT_ONLY_PROPS) delete html[key];\n return html as P;\n}\n\nAlert.displayName = 'Alert';\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- //# sourceMappingURL=chunk-NUGT7LMR.js.map