@govbr-ds/webcomponents 2.1.2 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (960) hide show
  1. package/README.md +87 -46
  2. package/cem/custom-elements.json +6367 -1134
  3. package/cem/webcomponents.html-custom-data.json +399 -286
  4. package/dist/cjs/br-avatar.cjs.entry.js +21 -14
  5. package/dist/cjs/br-breadcrumb-item.cjs.entry.js +2 -2
  6. package/dist/cjs/br-breadcrumb.cjs.entry.js +49 -22
  7. package/dist/cjs/br-button_2.cjs.entry.js +72 -35
  8. package/dist/cjs/br-card.cjs.entry.js +6 -5
  9. package/dist/cjs/br-carousel-page.cjs.entry.js +3 -3
  10. package/dist/cjs/br-carousel.cjs.entry.js +77 -21
  11. package/dist/cjs/br-checkbox-group.cjs.entry.js +157 -27
  12. package/dist/cjs/br-checkbox.cjs.entry.js +85 -15
  13. package/dist/cjs/br-checkgroup.cjs.entry.js +5 -2
  14. package/dist/cjs/br-collapse_2.cjs.entry.js +85 -26
  15. package/dist/cjs/br-cookiebar-cookie.cjs.entry.js +4 -4
  16. package/dist/cjs/br-cookiebar-group.cjs.entry.js +4 -4
  17. package/dist/cjs/br-cookiebar-header.cjs.entry.js +4 -4
  18. package/dist/cjs/br-cookiebar-link.cjs.entry.js +14 -6
  19. package/dist/cjs/br-cookiebar-note-group.cjs.entry.js +3 -5
  20. package/dist/cjs/br-cookiebar-note.cjs.entry.js +4 -4
  21. package/dist/cjs/br-cookiebar.cjs.entry.js +38 -25
  22. package/dist/cjs/br-crumb.cjs.entry.js +2 -2
  23. package/dist/cjs/br-date-picker_3.cjs.entry.js +246 -88
  24. package/dist/cjs/br-datetime-picker.cjs.entry.js +115 -527
  25. package/dist/cjs/br-divider.cjs.entry.js +70 -17
  26. package/dist/cjs/br-dropdown_2.cjs.entry.js +304 -122
  27. package/dist/cjs/br-footer-category.cjs.entry.js +10 -6
  28. package/dist/cjs/br-footer-item.cjs.entry.js +9 -4
  29. package/dist/cjs/br-footer-legal.cjs.entry.js +4 -4
  30. package/dist/cjs/br-footer-logo.cjs.entry.js +22 -10
  31. package/dist/cjs/br-footer-social.cjs.entry.js +14 -6
  32. package/dist/cjs/br-footer.cjs.entry.js +16 -7
  33. package/dist/cjs/br-header-function.cjs.entry.js +28 -7
  34. package/dist/cjs/br-header-link.cjs.entry.js +25 -4
  35. package/dist/cjs/br-header-list.cjs.entry.js +6 -17
  36. package/dist/cjs/br-header-logo.cjs.entry.js +18 -7
  37. package/dist/cjs/br-header.cjs.entry.js +72 -17
  38. package/dist/cjs/br-icon.cjs.entry.js +160 -23
  39. package/dist/cjs/br-input.cjs.entry.js +130 -39
  40. package/dist/cjs/br-item.cjs.entry.js +96 -48
  41. package/dist/cjs/br-link.cjs.entry.js +20 -7
  42. package/dist/cjs/br-loading.cjs.entry.js +100 -38
  43. package/dist/cjs/br-magic-button.cjs.entry.js +26 -9
  44. package/dist/cjs/br-menu-group.cjs.entry.js +14 -3
  45. package/dist/cjs/br-menu-header.cjs.entry.js +4 -4
  46. package/dist/cjs/br-menu-info.cjs.entry.js +4 -4
  47. package/dist/cjs/br-menu-item.cjs.entry.js +27 -5
  48. package/dist/cjs/br-menu-link.cjs.entry.js +14 -6
  49. package/dist/cjs/br-menu-list.cjs.entry.js +23 -27
  50. package/dist/cjs/br-menu-logo.cjs.entry.js +4 -4
  51. package/dist/cjs/br-menu-social.cjs.entry.js +16 -6
  52. package/dist/cjs/br-menu.cjs.entry.js +41 -64
  53. package/dist/cjs/br-modal.cjs.entry.js +26 -40
  54. package/dist/cjs/br-notification-body.cjs.entry.js +4 -4
  55. package/dist/cjs/br-notification-header.cjs.entry.js +4 -4
  56. package/dist/cjs/br-notification-item.cjs.entry.js +14 -8
  57. package/dist/cjs/br-notification.cjs.entry.js +23 -8
  58. package/dist/cjs/br-pagination.cjs.entry.js +119 -87
  59. package/dist/cjs/br-radio-group.cjs.entry.js +106 -57
  60. package/dist/cjs/br-radio.cjs.entry.js +61 -11
  61. package/dist/cjs/br-scrim.cjs.entry.js +161 -67
  62. package/dist/cjs/br-select-input_3.cjs.entry.js +283 -90
  63. package/dist/cjs/br-sign-in.cjs.entry.js +34 -15
  64. package/dist/cjs/br-skip-link-item.cjs.entry.js +39 -2
  65. package/dist/cjs/br-skip-link.cjs.entry.js +50 -33
  66. package/dist/cjs/br-skiplink-item.cjs.entry.js +22 -6
  67. package/dist/cjs/br-slider.cjs.entry.js +521 -99
  68. package/dist/cjs/br-step_2.cjs.entry.js +98 -44
  69. package/dist/cjs/br-switch.cjs.entry.js +20 -11
  70. package/dist/cjs/br-tab-item.cjs.entry.js +38 -14
  71. package/dist/cjs/br-tab.cjs.entry.js +57 -44
  72. package/dist/cjs/br-table-body.cjs.entry.js +3 -3
  73. package/dist/cjs/br-table-cell.cjs.entry.js +30 -13
  74. package/dist/cjs/br-table-header-cell.cjs.entry.js +23 -7
  75. package/dist/cjs/br-table-header.cjs.entry.js +3 -3
  76. package/dist/cjs/br-table-row.cjs.entry.js +17 -3
  77. package/dist/cjs/br-table.cjs.entry.js +67 -21
  78. package/dist/cjs/br-tag.cjs.entry.js +48 -30
  79. package/dist/cjs/br-textarea.cjs.entry.js +117 -12
  80. package/dist/cjs/br-tooltip.cjs.entry.js +87 -41
  81. package/dist/cjs/br-upload.cjs.entry.js +83 -24
  82. package/dist/cjs/br-wizard-panel.cjs.entry.js +16 -3
  83. package/dist/cjs/br-wizard.cjs.entry.js +52 -28
  84. package/dist/cjs/{isValid-Fu3kaWNn.js → datetime-picker-props-validation-DmNKSXsy.js} +481 -4
  85. package/dist/cjs/{floating-ui-MBI1osio.js → floating-ui-B6nsdYUU.js} +24 -1
  86. package/dist/cjs/{floating-ui.dom-BUSTaaxR.js → floating-ui.dom-wzdGZjyG.js} +201 -113
  87. package/dist/cjs/{focus-DuywwJPR.js → focus-BhfJnFgJ.js} +21 -0
  88. package/dist/cjs/header-context-CdawuLsH.js +17 -0
  89. package/dist/cjs/id-DE4jSi-L.js +36 -0
  90. package/dist/cjs/{index-CRdcutym.js → index-CGgZBuyy.js} +68 -752
  91. package/dist/cjs/loader.cjs.js +2 -2
  92. package/dist/cjs/motion-CgIooxWS.js +29 -0
  93. package/dist/cjs/ownership-UnpufyCx.js +116 -0
  94. package/dist/cjs/prop-warning-xvEHQz8H.js +60 -0
  95. package/dist/cjs/props-D8dybmr0.js +124 -0
  96. package/dist/cjs/{swipe-BU8_XE9f.js → swipe-BGF-h9WY.js} +11 -1
  97. package/dist/cjs/webcomponents.cjs.js +3 -3
  98. package/dist/collection/collection-manifest.json +1 -1
  99. package/dist/collection/components/avatar/avatar.css +1 -1
  100. package/dist/collection/components/avatar/avatar.js +48 -16
  101. package/dist/collection/components/breadcrumb/breadcrumb-item/breadcrumb-item.js +15 -3
  102. package/dist/collection/components/breadcrumb/breadcrumb.css +1 -1
  103. package/dist/collection/components/breadcrumb/breadcrumb.js +107 -22
  104. package/dist/collection/components/breadcrumb/crumb/crumb.js +14 -2
  105. package/dist/collection/components/button/button.css +1 -1
  106. package/dist/collection/components/button/button.js +88 -24
  107. package/dist/collection/components/card/card.css +1 -1
  108. package/dist/collection/components/card/card.js +33 -5
  109. package/dist/collection/components/carousel/carousel-page/carousel-page.css +1 -1
  110. package/dist/collection/components/carousel/carousel-page/carousel-page.js +11 -4
  111. package/dist/collection/components/carousel/carousel.css +1 -1
  112. package/dist/collection/components/carousel/carousel.js +107 -21
  113. package/dist/collection/components/checkbox/checkbox.css +1 -1
  114. package/dist/collection/components/checkbox/checkbox.js +134 -20
  115. package/dist/collection/components/checkbox-group/checkbox-group.css +1 -1
  116. package/dist/collection/components/checkbox-group/checkbox-group.js +210 -30
  117. package/dist/collection/components/checkgroup/checkgroup.js +42 -4
  118. package/dist/collection/components/collapse/collapse.css +1 -1
  119. package/dist/collection/components/collapse/collapse.js +48 -8
  120. package/dist/collection/components/cookiebar/cookiebar-cookie/cookiebar-cookie.css +1 -1
  121. package/dist/collection/components/cookiebar/cookiebar-cookie/cookiebar-cookie.js +17 -4
  122. package/dist/collection/components/cookiebar/cookiebar-group/cookiebar-group.css +1 -1
  123. package/dist/collection/components/cookiebar/cookiebar-group/cookiebar-group.js +16 -7
  124. package/dist/collection/components/cookiebar/cookiebar-header/cookiebar-header.css +1 -1
  125. package/dist/collection/components/cookiebar/cookiebar-header/cookiebar-header.js +15 -9
  126. package/dist/collection/components/cookiebar/cookiebar-link/cookiebar-link.css +1 -1
  127. package/dist/collection/components/cookiebar/cookiebar-link/cookiebar-link.js +24 -8
  128. package/dist/collection/components/cookiebar/cookiebar-note/cookiebar-note.css +1 -1
  129. package/dist/collection/components/cookiebar/cookiebar-note/cookiebar-note.js +14 -4
  130. package/dist/collection/components/cookiebar/cookiebar-note-group/cookiebar-note-group.css +1 -1
  131. package/dist/collection/components/cookiebar/cookiebar-note-group/cookiebar-note-group.js +13 -5
  132. package/dist/collection/components/cookiebar/cookiebar.css +1 -1
  133. package/dist/collection/components/cookiebar/cookiebar.js +67 -32
  134. package/dist/collection/components/datetime-picker/date-picker/date-picker.css +1 -1
  135. package/dist/collection/components/datetime-picker/date-picker/date-picker.js +134 -35
  136. package/dist/collection/components/datetime-picker/datetime-input/datetime-input.css +1 -1
  137. package/dist/collection/components/datetime-picker/datetime-input/datetime-input.js +112 -22
  138. package/dist/collection/components/datetime-picker/datetime-picker-props-validation.js +13 -5
  139. package/dist/collection/components/datetime-picker/datetime-picker.css +1 -1
  140. package/dist/collection/components/datetime-picker/datetime-picker.js +158 -42
  141. package/dist/collection/components/datetime-picker/time-picker/time-picker.css +1 -1
  142. package/dist/collection/components/datetime-picker/time-picker/time-picker.js +78 -9
  143. package/dist/collection/components/divider/divider.css +1 -1
  144. package/dist/collection/components/divider/divider.js +101 -26
  145. package/dist/collection/components/dropdown/dropdown.css +1 -1
  146. package/dist/collection/components/dropdown/dropdown.js +166 -18
  147. package/dist/collection/components/footer/footer-category/footer-category.css +1 -1
  148. package/dist/collection/components/footer/footer-category/footer-category.js +23 -4
  149. package/dist/collection/components/footer/footer-item/footer-item.css +1 -1
  150. package/dist/collection/components/footer/footer-item/footer-item.js +21 -2
  151. package/dist/collection/components/footer/footer-legal/footer-legal.css +1 -1
  152. package/dist/collection/components/footer/footer-legal/footer-legal.js +16 -2
  153. package/dist/collection/components/footer/footer-logo/footer-logo.css +1 -1
  154. package/dist/collection/components/footer/footer-logo/footer-logo.js +35 -9
  155. package/dist/collection/components/footer/footer-social/footer-social.css +1 -1
  156. package/dist/collection/components/footer/footer-social/footer-social.js +26 -6
  157. package/dist/collection/components/footer/footer.css +1 -1
  158. package/dist/collection/components/footer/footer.js +48 -7
  159. package/dist/collection/components/header/header-context.js +13 -0
  160. package/dist/collection/components/header/header-function/header-function.css +1 -1
  161. package/dist/collection/components/header/header-function/header-function.js +51 -8
  162. package/dist/collection/components/header/header-link/header-link.css +1 -1
  163. package/dist/collection/components/header/header-link/header-link.js +52 -2
  164. package/dist/collection/components/header/header-list/header-list.css +1 -1
  165. package/dist/collection/components/header/header-list/header-list.js +20 -23
  166. package/dist/collection/components/header/header-logo/header-logo.css +1 -1
  167. package/dist/collection/components/header/header-logo/header-logo.js +33 -8
  168. package/dist/collection/components/header/header.css +1 -1
  169. package/dist/collection/components/header/header.js +110 -24
  170. package/dist/collection/components/icon/default-icons-cache.js +111 -3
  171. package/dist/collection/components/icon/icon.css +1 -1
  172. package/dist/collection/components/icon/icon.js +80 -33
  173. package/dist/collection/components/input/input.css +1 -1
  174. package/dist/collection/components/input/input.js +169 -54
  175. package/dist/collection/components/item/item.css +1 -1
  176. package/dist/collection/components/item/item.js +134 -51
  177. package/dist/collection/components/link/link.css +1 -1
  178. package/dist/collection/components/link/link.js +48 -15
  179. package/dist/collection/components/list/list.css +1 -1
  180. package/dist/collection/components/list/list.js +106 -25
  181. package/dist/collection/components/loading/loading.css +1 -1
  182. package/dist/collection/components/loading/loading.js +131 -43
  183. package/dist/collection/components/magic-button/magic-button.css +1 -1
  184. package/dist/collection/components/magic-button/magic-button.js +51 -9
  185. package/dist/collection/components/menu/menu-group/menu-group.css +1 -1
  186. package/dist/collection/components/menu/menu-group/menu-group.js +60 -2
  187. package/dist/collection/components/menu/menu-header/menu-header.css +1 -1
  188. package/dist/collection/components/menu/menu-header/menu-header.js +17 -2
  189. package/dist/collection/components/menu/menu-info/menu-info.css +1 -1
  190. package/dist/collection/components/menu/menu-info/menu-info.js +15 -2
  191. package/dist/collection/components/menu/menu-item/menu-item.css +1 -1
  192. package/dist/collection/components/menu/menu-item/menu-item.js +72 -8
  193. package/dist/collection/components/menu/menu-link/menu-link.css +1 -1
  194. package/dist/collection/components/menu/menu-link/menu-link.js +25 -4
  195. package/dist/collection/components/menu/menu-list/menu-list.css +1 -1
  196. package/dist/collection/components/menu/menu-list/menu-list.js +64 -29
  197. package/dist/collection/components/menu/menu-logo/menu-logo.css +1 -1
  198. package/dist/collection/components/menu/menu-logo/menu-logo.js +15 -2
  199. package/dist/collection/components/menu/menu-social/menu-social.css +1 -1
  200. package/dist/collection/components/menu/menu-social/menu-social.js +29 -7
  201. package/dist/collection/components/menu/menu.css +1 -1
  202. package/dist/collection/components/menu/menu.js +75 -68
  203. package/dist/collection/components/menu/menu.utils.js +8 -18
  204. package/dist/collection/components/message/message.css +1 -1
  205. package/dist/collection/components/message/message.js +50 -24
  206. package/dist/collection/components/modal/modal.css +1 -1
  207. package/dist/collection/components/modal/modal.js +54 -41
  208. package/dist/collection/components/notification/notification-body/notification-body.css +1 -1
  209. package/dist/collection/components/notification/notification-body/notification-body.js +13 -4
  210. package/dist/collection/components/notification/notification-header/notification-header.css +1 -1
  211. package/dist/collection/components/notification/notification-header/notification-header.js +13 -4
  212. package/dist/collection/components/notification/notification-item/notification-item.css +1 -1
  213. package/dist/collection/components/notification/notification-item/notification-item.js +23 -9
  214. package/dist/collection/components/notification/notification.css +1 -1
  215. package/dist/collection/components/notification/notification.js +54 -10
  216. package/dist/collection/components/pagination/pagination.css +1 -1
  217. package/dist/collection/components/pagination/pagination.js +161 -74
  218. package/dist/collection/components/radio/radio.css +1 -1
  219. package/dist/collection/components/radio/radio.js +109 -14
  220. package/dist/collection/components/radio-group/radio-group.css +1 -1
  221. package/dist/collection/components/radio-group/radio-group.js +153 -63
  222. package/dist/collection/components/scrim/scrim.css +1 -1
  223. package/dist/collection/components/scrim/scrim.js +215 -74
  224. package/dist/collection/components/scrim/scrim.utils.js +5 -51
  225. package/dist/collection/components/select/select-input/select-input.css +1 -1
  226. package/dist/collection/components/select/select-input/select-input.js +58 -5
  227. package/dist/collection/components/select/select-list/select-list.css +1 -1
  228. package/dist/collection/components/select/select-list/select-list.js +247 -52
  229. package/dist/collection/components/select/select-option/select-option.css +1 -1
  230. package/dist/collection/components/select/select-option/select-option.js +108 -46
  231. package/dist/collection/components/select/select.css +1 -1
  232. package/dist/collection/components/select/select.js +323 -118
  233. package/dist/collection/components/sign-in/sign-in.css +1 -1
  234. package/dist/collection/components/sign-in/sign-in.js +55 -16
  235. package/dist/collection/components/skip-link/skip-link-item/skip-link-item-alias.js +112 -3
  236. package/dist/collection/components/skip-link/skip-link-item/skip-link-item.css +1 -1
  237. package/dist/collection/components/skip-link/skip-link-item/skip-link-item.js +58 -5
  238. package/dist/collection/components/skip-link/skip-link.css +1 -1
  239. package/dist/collection/components/skip-link/skip-link.js +78 -39
  240. package/dist/collection/components/slider/slider.css +1 -1
  241. package/dist/collection/components/slider/slider.js +530 -132
  242. package/dist/collection/components/slider/slider.utils.js +178 -0
  243. package/dist/collection/components/step/step-item/step-item.css +1 -1
  244. package/dist/collection/components/step/step-item/step-item.js +29 -12
  245. package/dist/collection/components/step/step.css +1 -1
  246. package/dist/collection/components/step/step.js +119 -44
  247. package/dist/collection/components/switch/switch.css +1 -1
  248. package/dist/collection/components/switch/switch.js +48 -15
  249. package/dist/collection/components/tab/tab-item/tab-item.css +1 -1
  250. package/dist/collection/components/tab/tab-item/tab-item.js +49 -14
  251. package/dist/collection/components/tab/tab.css +1 -1
  252. package/dist/collection/components/tab/tab.js +89 -46
  253. package/dist/collection/components/table/table-body/table-body.css +1 -1
  254. package/dist/collection/components/table/table-body/table-body.js +11 -7
  255. package/dist/collection/components/table/table-cell/table-cell.css +1 -1
  256. package/dist/collection/components/table/table-cell/table-cell.js +36 -17
  257. package/dist/collection/components/table/table-header/table-header.css +1 -1
  258. package/dist/collection/components/table/table-header/table-header.js +11 -7
  259. package/dist/collection/components/table/table-header-cell/table-header-cell.css +1 -1
  260. package/dist/collection/components/table/table-header-cell/table-header-cell.js +35 -13
  261. package/dist/collection/components/table/table-row/table-row.css +1 -1
  262. package/dist/collection/components/table/table-row/table-row.js +24 -7
  263. package/dist/collection/components/table/table.css +1 -1
  264. package/dist/collection/components/table/table.js +107 -31
  265. package/dist/collection/components/tag/tag.css +1 -1
  266. package/dist/collection/components/tag/tag.js +86 -36
  267. package/dist/collection/components/textarea/textarea.css +1 -1
  268. package/dist/collection/components/textarea/textarea.js +222 -19
  269. package/dist/collection/components/tooltip/tooltip.css +1 -1
  270. package/dist/collection/components/tooltip/tooltip.js +134 -45
  271. package/dist/collection/components/upload/upload.css +1 -1
  272. package/dist/collection/components/upload/upload.js +135 -33
  273. package/dist/collection/components/wizard/wizard-panel/wizard-panel.css +1 -1
  274. package/dist/collection/components/wizard/wizard-panel/wizard-panel.js +54 -3
  275. package/dist/collection/components/wizard/wizard.css +1 -1
  276. package/dist/collection/components/wizard/wizard.js +82 -28
  277. package/dist/collection/pages/scripts/component-controls-core.js +95 -0
  278. package/dist/collection/pages/scripts/component-controls.js +238 -153
  279. package/dist/collection/pages/scripts/dev-event-console.js +5 -1
  280. package/dist/collection/pages/scripts/menu.js +90 -5
  281. package/dist/collection/pages/scripts/pageLoader.js +1486 -586
  282. package/dist/collection/pages/scripts/pageloader-preview.js +787 -0
  283. package/dist/collection/pages/scripts/playground-core.js +173 -0
  284. package/dist/collection/shared/utils/cssVariables.js +2 -0
  285. package/dist/collection/shared/utils/date.js +8 -4
  286. package/dist/collection/shared/utils/floating-ui.js +24 -1
  287. package/dist/collection/shared/utils/focus.js +31 -0
  288. package/dist/collection/shared/utils/getRandom.js +16 -1
  289. package/dist/collection/shared/utils/helpers.js +4 -11
  290. package/dist/collection/shared/utils/id.js +23 -7
  291. package/dist/collection/shared/utils/index.js +6 -1
  292. package/dist/collection/shared/utils/isEmpty.js +5 -3
  293. package/dist/collection/shared/utils/motion.js +25 -0
  294. package/dist/collection/shared/utils/ownership.js +113 -0
  295. package/dist/collection/shared/utils/prop-warning.js +47 -0
  296. package/dist/collection/shared/utils/props.js +79 -0
  297. package/dist/collection/shared/utils/swipe.js +11 -1
  298. package/dist/collection/shared/utils/transition.js +3 -0
  299. package/dist/collection/shared/utils/virtual-scroll.js +24 -0
  300. package/dist/components/br-avatar.d.ts +1 -1
  301. package/dist/components/br-avatar.js +1 -1
  302. package/dist/components/br-breadcrumb-item.d.ts +1 -1
  303. package/dist/components/br-breadcrumb-item.js +1 -1
  304. package/dist/components/br-breadcrumb.d.ts +1 -1
  305. package/dist/components/br-breadcrumb.js +1 -1
  306. package/dist/components/br-button.d.ts +1 -1
  307. package/dist/components/br-button.js +1 -1
  308. package/dist/components/br-card.d.ts +1 -1
  309. package/dist/components/br-card.js +1 -1
  310. package/dist/components/br-carousel-page.d.ts +1 -1
  311. package/dist/components/br-carousel-page.js +1 -1
  312. package/dist/components/br-carousel.d.ts +1 -1
  313. package/dist/components/br-carousel.js +1 -1
  314. package/dist/components/br-checkbox-group.d.ts +1 -1
  315. package/dist/components/br-checkbox-group.js +1 -1
  316. package/dist/components/br-checkbox.d.ts +1 -1
  317. package/dist/components/br-checkbox.js +1 -1
  318. package/dist/components/br-checkgroup.d.ts +1 -1
  319. package/dist/components/br-checkgroup.js +1 -1
  320. package/dist/components/br-collapse.d.ts +1 -1
  321. package/dist/components/br-collapse.js +1 -1
  322. package/dist/components/br-cookiebar-cookie.d.ts +1 -1
  323. package/dist/components/br-cookiebar-cookie.js +1 -1
  324. package/dist/components/br-cookiebar-group.d.ts +1 -1
  325. package/dist/components/br-cookiebar-group.js +1 -1
  326. package/dist/components/br-cookiebar-header.d.ts +1 -1
  327. package/dist/components/br-cookiebar-header.js +1 -1
  328. package/dist/components/br-cookiebar-link.d.ts +1 -1
  329. package/dist/components/br-cookiebar-link.js +1 -1
  330. package/dist/components/br-cookiebar-note-group.d.ts +1 -1
  331. package/dist/components/br-cookiebar-note-group.js +1 -1
  332. package/dist/components/br-cookiebar-note.d.ts +1 -1
  333. package/dist/components/br-cookiebar-note.js +1 -1
  334. package/dist/components/br-cookiebar.d.ts +1 -1
  335. package/dist/components/br-cookiebar.js +1 -1
  336. package/dist/components/br-crumb.d.ts +1 -1
  337. package/dist/components/br-crumb.js +1 -1
  338. package/dist/components/br-date-picker.d.ts +1 -1
  339. package/dist/components/br-date-picker.js +1 -1
  340. package/dist/components/br-datetime-input.d.ts +1 -1
  341. package/dist/components/br-datetime-input.js +1 -1
  342. package/dist/components/br-datetime-picker.d.ts +1 -1
  343. package/dist/components/br-datetime-picker.js +1 -1
  344. package/dist/components/br-divider.d.ts +1 -1
  345. package/dist/components/br-divider.js +1 -1
  346. package/dist/components/br-dropdown.d.ts +1 -1
  347. package/dist/components/br-dropdown.js +1 -1
  348. package/dist/components/br-footer-category.d.ts +1 -1
  349. package/dist/components/br-footer-category.js +1 -1
  350. package/dist/components/br-footer-item.d.ts +1 -1
  351. package/dist/components/br-footer-item.js +1 -1
  352. package/dist/components/br-footer-legal.d.ts +1 -1
  353. package/dist/components/br-footer-legal.js +1 -1
  354. package/dist/components/br-footer-logo.d.ts +1 -1
  355. package/dist/components/br-footer-logo.js +1 -1
  356. package/dist/components/br-footer-social.d.ts +1 -1
  357. package/dist/components/br-footer-social.js +1 -1
  358. package/dist/components/br-footer.d.ts +1 -1
  359. package/dist/components/br-footer.js +1 -1
  360. package/dist/components/br-header-function.d.ts +1 -1
  361. package/dist/components/br-header-function.js +1 -1
  362. package/dist/components/br-header-link.d.ts +1 -1
  363. package/dist/components/br-header-link.js +1 -1
  364. package/dist/components/br-header-list.d.ts +1 -1
  365. package/dist/components/br-header-list.js +1 -1
  366. package/dist/components/br-header-logo.d.ts +1 -1
  367. package/dist/components/br-header-logo.js +1 -1
  368. package/dist/components/br-header.d.ts +1 -1
  369. package/dist/components/br-header.js +1 -1
  370. package/dist/components/br-icon.d.ts +1 -1
  371. package/dist/components/br-icon.js +1 -1
  372. package/dist/components/br-input.d.ts +1 -1
  373. package/dist/components/br-input.js +1 -1
  374. package/dist/components/br-item.d.ts +1 -1
  375. package/dist/components/br-item.js +1 -1
  376. package/dist/components/br-link.d.ts +1 -1
  377. package/dist/components/br-link.js +1 -1
  378. package/dist/components/br-list.d.ts +1 -1
  379. package/dist/components/br-list.js +1 -1
  380. package/dist/components/br-loading.d.ts +1 -1
  381. package/dist/components/br-loading.js +1 -1
  382. package/dist/components/br-magic-button.d.ts +1 -1
  383. package/dist/components/br-magic-button.js +1 -1
  384. package/dist/components/br-menu-group.d.ts +1 -1
  385. package/dist/components/br-menu-group.js +1 -1
  386. package/dist/components/br-menu-header.d.ts +1 -1
  387. package/dist/components/br-menu-header.js +1 -1
  388. package/dist/components/br-menu-info.d.ts +1 -1
  389. package/dist/components/br-menu-info.js +1 -1
  390. package/dist/components/br-menu-item.d.ts +1 -1
  391. package/dist/components/br-menu-item.js +1 -1
  392. package/dist/components/br-menu-link.d.ts +1 -1
  393. package/dist/components/br-menu-link.js +1 -1
  394. package/dist/components/br-menu-list.d.ts +1 -1
  395. package/dist/components/br-menu-list.js +1 -1
  396. package/dist/components/br-menu-logo.d.ts +1 -1
  397. package/dist/components/br-menu-logo.js +1 -1
  398. package/dist/components/br-menu-social.d.ts +1 -1
  399. package/dist/components/br-menu-social.js +1 -1
  400. package/dist/components/br-menu.d.ts +1 -1
  401. package/dist/components/br-menu.js +1 -1
  402. package/dist/components/br-message.d.ts +1 -1
  403. package/dist/components/br-message.js +1 -1
  404. package/dist/components/br-modal.d.ts +1 -1
  405. package/dist/components/br-modal.js +1 -1
  406. package/dist/components/br-notification-body.d.ts +1 -1
  407. package/dist/components/br-notification-body.js +1 -1
  408. package/dist/components/br-notification-header.d.ts +1 -1
  409. package/dist/components/br-notification-header.js +1 -1
  410. package/dist/components/br-notification-item.d.ts +1 -1
  411. package/dist/components/br-notification-item.js +1 -1
  412. package/dist/components/br-notification.d.ts +1 -1
  413. package/dist/components/br-notification.js +1 -1
  414. package/dist/components/br-pagination.d.ts +1 -1
  415. package/dist/components/br-pagination.js +1 -1
  416. package/dist/components/br-radio-group.d.ts +1 -1
  417. package/dist/components/br-radio-group.js +1 -1
  418. package/dist/components/br-radio.d.ts +1 -1
  419. package/dist/components/br-radio.js +1 -1
  420. package/dist/components/br-scrim.d.ts +1 -1
  421. package/dist/components/br-scrim.js +1 -1
  422. package/dist/components/br-select-input.d.ts +1 -1
  423. package/dist/components/br-select-input.js +1 -1
  424. package/dist/components/br-select-list.d.ts +1 -1
  425. package/dist/components/br-select-list.js +1 -1
  426. package/dist/components/br-select-option.d.ts +1 -1
  427. package/dist/components/br-select-option.js +1 -1
  428. package/dist/components/br-select.d.ts +1 -1
  429. package/dist/components/br-select.js +1 -1
  430. package/dist/components/br-sign-in.d.ts +1 -1
  431. package/dist/components/br-sign-in.js +1 -1
  432. package/dist/components/br-skip-link-item.d.ts +1 -1
  433. package/dist/components/br-skip-link-item.js +1 -1
  434. package/dist/components/br-skip-link.d.ts +1 -1
  435. package/dist/components/br-skip-link.js +1 -1
  436. package/dist/components/br-skiplink-item.d.ts +1 -1
  437. package/dist/components/br-skiplink-item.js +1 -1
  438. package/dist/components/br-slider.d.ts +1 -1
  439. package/dist/components/br-slider.js +1 -1
  440. package/dist/components/br-step-item.d.ts +1 -1
  441. package/dist/components/br-step-item.js +1 -1
  442. package/dist/components/br-step.d.ts +1 -1
  443. package/dist/components/br-step.js +1 -1
  444. package/dist/components/br-switch.d.ts +1 -1
  445. package/dist/components/br-switch.js +1 -1
  446. package/dist/components/br-tab-item.d.ts +1 -1
  447. package/dist/components/br-tab-item.js +1 -1
  448. package/dist/components/br-tab.d.ts +1 -1
  449. package/dist/components/br-tab.js +1 -1
  450. package/dist/components/br-table-body.d.ts +1 -1
  451. package/dist/components/br-table-body.js +1 -1
  452. package/dist/components/br-table-cell.d.ts +1 -1
  453. package/dist/components/br-table-cell.js +1 -1
  454. package/dist/components/br-table-header-cell.d.ts +1 -1
  455. package/dist/components/br-table-header-cell.js +1 -1
  456. package/dist/components/br-table-header.d.ts +1 -1
  457. package/dist/components/br-table-header.js +1 -1
  458. package/dist/components/br-table-row.d.ts +1 -1
  459. package/dist/components/br-table-row.js +1 -1
  460. package/dist/components/br-table.d.ts +1 -1
  461. package/dist/components/br-table.js +1 -1
  462. package/dist/components/br-tag.d.ts +1 -1
  463. package/dist/components/br-tag.js +1 -1
  464. package/dist/components/br-textarea.d.ts +1 -1
  465. package/dist/components/br-textarea.js +1 -1
  466. package/dist/components/br-time-picker.d.ts +1 -1
  467. package/dist/components/br-time-picker.js +1 -1
  468. package/dist/components/br-tooltip.d.ts +1 -1
  469. package/dist/components/br-tooltip.js +1 -1
  470. package/dist/components/br-upload.d.ts +1 -1
  471. package/dist/components/br-upload.js +1 -1
  472. package/dist/components/br-wizard-panel.d.ts +1 -1
  473. package/dist/components/br-wizard-panel.js +1 -1
  474. package/dist/components/br-wizard.d.ts +1 -1
  475. package/dist/components/br-wizard.js +1 -1
  476. package/dist/components/index.d.ts +89 -89
  477. package/dist/components/index.js +1 -1
  478. package/dist/components/p-B0o70fWP.js +5 -0
  479. package/dist/components/p-B96LROz9.js +5 -0
  480. package/dist/components/p-BDqef5-y.js +5 -0
  481. package/dist/components/p-BEJGB0Nd.js +5 -0
  482. package/dist/{webcomponents/p-Dmfk7eEe.js → components/p-BJZC_NuV.js} +1 -1
  483. package/dist/components/p-BJtdabsr.js +5 -0
  484. package/dist/components/p-BP5zMCxG.js +5 -0
  485. package/dist/components/p-BRaphxoP.js +5 -0
  486. package/dist/components/p-BUzBa9L1.js +5 -0
  487. package/dist/components/{p-DA5GS53D.js → p-BblZlUp2.js} +1 -1
  488. package/dist/components/p-Bc4nAk5i.js +5 -0
  489. package/dist/components/{p-C1yRmdso.js → p-BcqVlof7.js} +1 -1
  490. package/dist/components/p-BeJxz5TQ.js +5 -0
  491. package/dist/components/p-Bezou5CQ.js +5 -0
  492. package/dist/components/p-BrNh9KdF.js +5 -0
  493. package/dist/components/p-C5th2dxu.js +5 -0
  494. package/dist/components/p-CDtFCbKp.js +5 -0
  495. package/dist/components/p-CEdUp183.js +5 -0
  496. package/dist/components/p-CF7t0uxQ.js +5 -0
  497. package/dist/components/p-CFzHx6zV.js +5 -0
  498. package/dist/components/p-CG4em0S6.js +5 -0
  499. package/dist/components/p-CI4D3-pf.js +5 -0
  500. package/dist/components/p-CIrVPkVg.js +5 -0
  501. package/dist/components/p-CNwZRgyL.js +5 -0
  502. package/dist/components/p-CppRJiyC.js +5 -0
  503. package/dist/components/p-Cvk1Ggs5.js +5 -0
  504. package/dist/components/p-D12US39c.js +5 -0
  505. package/dist/components/p-D9Zo6FlV.js +5 -0
  506. package/dist/components/p-DGPJkJsj.js +5 -0
  507. package/dist/components/p-DSHbttu9.js +5 -0
  508. package/dist/components/p-DTGNra9m.js +5 -0
  509. package/dist/components/p-DWhzxlCx.js +5 -0
  510. package/dist/components/p-DX1wAFn4.js +5 -0
  511. package/dist/components/p-DiLI514I.js +5 -0
  512. package/dist/components/p-Dma14GVa.js +5 -0
  513. package/dist/components/p-DpRZ4B0d.js +5 -0
  514. package/dist/components/p-G35qEQZd.js +5 -0
  515. package/dist/components/p-Ho_IybzR.js +5 -0
  516. package/dist/components/p-SvVnvJdC.js +5 -0
  517. package/dist/components/p-emAWunES.js +5 -0
  518. package/dist/components/p-fB79wKCm.js +5 -0
  519. package/dist/components/p-k7p4QJ8a.js +5 -0
  520. package/dist/esm/br-avatar.entry.js +21 -14
  521. package/dist/esm/br-breadcrumb-item.entry.js +2 -2
  522. package/dist/esm/br-breadcrumb.entry.js +49 -22
  523. package/dist/esm/br-button_2.entry.js +72 -35
  524. package/dist/esm/br-card.entry.js +6 -5
  525. package/dist/esm/br-carousel-page.entry.js +3 -3
  526. package/dist/esm/br-carousel.entry.js +78 -22
  527. package/dist/esm/br-checkbox-group.entry.js +157 -27
  528. package/dist/esm/br-checkbox.entry.js +86 -16
  529. package/dist/esm/br-checkgroup.entry.js +5 -2
  530. package/dist/esm/br-collapse_2.entry.js +86 -27
  531. package/dist/esm/br-cookiebar-cookie.entry.js +4 -4
  532. package/dist/esm/br-cookiebar-group.entry.js +4 -4
  533. package/dist/esm/br-cookiebar-header.entry.js +4 -4
  534. package/dist/esm/br-cookiebar-link.entry.js +14 -6
  535. package/dist/esm/br-cookiebar-note-group.entry.js +3 -5
  536. package/dist/esm/br-cookiebar-note.entry.js +4 -4
  537. package/dist/esm/br-cookiebar.entry.js +39 -26
  538. package/dist/esm/br-crumb.entry.js +2 -2
  539. package/dist/esm/br-date-picker_3.entry.js +207 -49
  540. package/dist/esm/br-datetime-picker.entry.js +82 -494
  541. package/dist/esm/br-divider.entry.js +70 -17
  542. package/dist/esm/br-dropdown_2.entry.js +305 -123
  543. package/dist/esm/br-footer-category.entry.js +10 -6
  544. package/dist/esm/br-footer-item.entry.js +9 -4
  545. package/dist/esm/br-footer-legal.entry.js +4 -4
  546. package/dist/esm/br-footer-logo.entry.js +22 -10
  547. package/dist/esm/br-footer-social.entry.js +14 -6
  548. package/dist/esm/br-footer.entry.js +16 -7
  549. package/dist/esm/br-header-function.entry.js +28 -7
  550. package/dist/esm/br-header-link.entry.js +25 -4
  551. package/dist/esm/br-header-list.entry.js +7 -18
  552. package/dist/esm/br-header-logo.entry.js +18 -7
  553. package/dist/esm/br-header.entry.js +72 -17
  554. package/dist/esm/br-icon.entry.js +160 -23
  555. package/dist/esm/br-input.entry.js +132 -41
  556. package/dist/esm/br-item.entry.js +96 -48
  557. package/dist/esm/br-link.entry.js +20 -7
  558. package/dist/esm/br-loading.entry.js +100 -38
  559. package/dist/esm/br-magic-button.entry.js +26 -9
  560. package/dist/esm/br-menu-group.entry.js +14 -3
  561. package/dist/esm/br-menu-header.entry.js +4 -4
  562. package/dist/esm/br-menu-info.entry.js +4 -4
  563. package/dist/esm/br-menu-item.entry.js +27 -5
  564. package/dist/esm/br-menu-link.entry.js +14 -6
  565. package/dist/esm/br-menu-list.entry.js +23 -27
  566. package/dist/esm/br-menu-logo.entry.js +4 -4
  567. package/dist/esm/br-menu-social.entry.js +16 -6
  568. package/dist/esm/br-menu.entry.js +42 -65
  569. package/dist/esm/br-modal.entry.js +26 -40
  570. package/dist/esm/br-notification-body.entry.js +4 -4
  571. package/dist/esm/br-notification-header.entry.js +4 -4
  572. package/dist/esm/br-notification-item.entry.js +14 -8
  573. package/dist/esm/br-notification.entry.js +24 -9
  574. package/dist/esm/br-pagination.entry.js +119 -87
  575. package/dist/esm/br-radio-group.entry.js +107 -58
  576. package/dist/esm/br-radio.entry.js +62 -12
  577. package/dist/esm/br-scrim.entry.js +161 -67
  578. package/dist/esm/br-select-input_3.entry.js +283 -90
  579. package/dist/esm/br-sign-in.entry.js +34 -15
  580. package/dist/esm/br-skip-link-item.entry.js +39 -2
  581. package/dist/esm/br-skip-link.entry.js +50 -33
  582. package/dist/esm/br-skiplink-item.entry.js +22 -6
  583. package/dist/esm/br-slider.entry.js +519 -97
  584. package/dist/esm/br-step_2.entry.js +98 -44
  585. package/dist/esm/br-switch.entry.js +21 -12
  586. package/dist/esm/br-tab-item.entry.js +38 -14
  587. package/dist/esm/br-tab.entry.js +57 -44
  588. package/dist/esm/br-table-body.entry.js +3 -3
  589. package/dist/esm/br-table-cell.entry.js +30 -13
  590. package/dist/esm/br-table-header-cell.entry.js +23 -7
  591. package/dist/esm/br-table-header.entry.js +3 -3
  592. package/dist/esm/br-table-row.entry.js +17 -3
  593. package/dist/esm/br-table.entry.js +68 -22
  594. package/dist/esm/br-tag.entry.js +49 -31
  595. package/dist/esm/br-textarea.entry.js +118 -13
  596. package/dist/esm/br-tooltip.entry.js +88 -42
  597. package/dist/esm/br-upload.entry.js +84 -25
  598. package/dist/esm/br-wizard-panel.entry.js +16 -3
  599. package/dist/esm/br-wizard.entry.js +52 -28
  600. package/dist/esm/{datetime-picker-constants-Bfm58jO6.js → datetime-picker-constants-BtRPYRvA.js} +1 -1
  601. package/dist/esm/{isValid-DIUZX1qS.js → datetime-picker-props-validation-BeTcUTnE.js} +476 -5
  602. package/dist/esm/{event-DFN_so7I.js → event-CfuJQ1DY.js} +1 -1
  603. package/dist/esm/{floating-ui-BavFwMnx.js → floating-ui-CskvaxD5.js} +24 -1
  604. package/dist/esm/{floating-ui.dom-DIK54tTj.js → floating-ui.dom-D9Zo6FlV.js} +201 -114
  605. package/dist/esm/{focus-DxZJrIyL.js → focus-CNwZRgyL.js} +20 -1
  606. package/dist/esm/header-context-BEJGB0Nd.js +15 -0
  607. package/dist/esm/id-BeJxz5TQ.js +34 -0
  608. package/dist/esm/{index-Bo-2igoO.js → index-BQPOWxe5.js} +1 -1
  609. package/dist/esm/{index-C2RBydfd.js → index-Dcn7tRST.js} +68 -752
  610. package/dist/esm/index.js +2 -2
  611. package/dist/esm/loader.js +3 -3
  612. package/dist/esm/motion-DWhzxlCx.js +27 -0
  613. package/dist/esm/ownership-CDtFCbKp.js +111 -0
  614. package/dist/esm/prop-warning-BlGV-x0w.js +56 -0
  615. package/dist/esm/props-D07GjR4_.js +116 -0
  616. package/dist/esm/{swipe-Dmfk7eEe.js → swipe-BJZC_NuV.js} +11 -1
  617. package/dist/esm/webcomponents.js +4 -4
  618. package/dist/hydrate/index.js +7370 -2603
  619. package/dist/hydrate/index.mjs +7370 -2603
  620. package/dist/loader/index.d.ts +1 -1
  621. package/dist/types/components/avatar/avatar.d.ts +34 -4
  622. package/dist/types/components/breadcrumb/breadcrumb-item/breadcrumb-item.d.ts +14 -2
  623. package/dist/types/components/breadcrumb/breadcrumb.d.ts +66 -5
  624. package/dist/types/components/breadcrumb/crumb/crumb.d.ts +13 -1
  625. package/dist/types/components/button/button.d.ts +45 -9
  626. package/dist/types/components/card/card.d.ts +31 -3
  627. package/dist/types/components/carousel/carousel-page/carousel-page.d.ts +10 -3
  628. package/dist/types/components/carousel/carousel.d.ts +46 -3
  629. package/dist/types/components/checkbox/checkbox.d.ts +59 -6
  630. package/dist/types/components/checkbox-group/checkbox-group.d.ts +47 -5
  631. package/dist/types/components/checkgroup/checkgroup.d.ts +27 -5
  632. package/dist/types/components/collapse/collapse.d.ts +33 -4
  633. package/dist/types/components/cookiebar/cookiebar-cookie/cookiebar-cookie.d.ts +16 -3
  634. package/dist/types/components/cookiebar/cookiebar-group/cookiebar-group.d.ts +15 -6
  635. package/dist/types/components/cookiebar/cookiebar-header/cookiebar-header.d.ts +14 -8
  636. package/dist/types/components/cookiebar/cookiebar-link/cookiebar-link.d.ts +16 -5
  637. package/dist/types/components/cookiebar/cookiebar-note/cookiebar-note.d.ts +13 -3
  638. package/dist/types/components/cookiebar/cookiebar-note-group/cookiebar-note-group.d.ts +13 -3
  639. package/dist/types/components/cookiebar/cookiebar.d.ts +35 -10
  640. package/dist/types/components/datetime-picker/date-picker/date-picker.d.ts +63 -7
  641. package/dist/types/components/datetime-picker/datetime-input/datetime-input.d.ts +51 -9
  642. package/dist/types/components/datetime-picker/datetime-picker-props-validation.d.ts +4 -2
  643. package/dist/types/components/datetime-picker/datetime-picker.d.ts +118 -12
  644. package/dist/types/components/datetime-picker/time-picker/time-picker.d.ts +38 -4
  645. package/dist/types/components/divider/divider.d.ts +45 -8
  646. package/dist/types/components/dropdown/dropdown.d.ts +41 -3
  647. package/dist/types/components/footer/footer-category/footer-category.d.ts +16 -1
  648. package/dist/types/components/footer/footer-item/footer-item.d.ts +17 -1
  649. package/dist/types/components/footer/footer-legal/footer-legal.d.ts +15 -1
  650. package/dist/types/components/footer/footer-logo/footer-logo.d.ts +21 -2
  651. package/dist/types/components/footer/footer-social/footer-social.d.ts +20 -3
  652. package/dist/types/components/footer/footer.d.ts +39 -3
  653. package/dist/types/components/header/header-context.d.ts +1 -0
  654. package/dist/types/components/header/header-function/header-function.d.ts +24 -2
  655. package/dist/types/components/header/header-link/header-link.d.ts +22 -1
  656. package/dist/types/components/header/header-list/header-list.d.ts +16 -8
  657. package/dist/types/components/header/header-logo/header-logo.d.ts +20 -1
  658. package/dist/types/components/header/header.d.ts +45 -7
  659. package/dist/types/components/icon/icon.d.ts +44 -13
  660. package/dist/types/components/input/input.d.ts +65 -15
  661. package/dist/types/components/item/item.d.ts +38 -5
  662. package/dist/types/components/link/link.d.ts +41 -9
  663. package/dist/types/components/list/list.d.ts +58 -8
  664. package/dist/types/components/loading/loading.d.ts +48 -8
  665. package/dist/types/components/magic-button/magic-button.d.ts +37 -3
  666. package/dist/types/components/menu/menu-group/menu-group.d.ts +19 -1
  667. package/dist/types/components/menu/menu-header/menu-header.d.ts +16 -1
  668. package/dist/types/components/menu/menu-info/menu-info.d.ts +14 -1
  669. package/dist/types/components/menu/menu-item/menu-item.d.ts +27 -3
  670. package/dist/types/components/menu/menu-link/menu-link.d.ts +17 -1
  671. package/dist/types/components/menu/menu-list/menu-list.d.ts +22 -4
  672. package/dist/types/components/menu/menu-logo/menu-logo.d.ts +14 -1
  673. package/dist/types/components/menu/menu-social/menu-social.d.ts +21 -2
  674. package/dist/types/components/menu/menu.d.ts +42 -9
  675. package/dist/types/components/menu/menu.utils.d.ts +2 -6
  676. package/dist/types/components/message/message.d.ts +38 -9
  677. package/dist/types/components/modal/modal.d.ts +34 -4
  678. package/dist/types/components/notification/notification-body/notification-body.d.ts +12 -3
  679. package/dist/types/components/notification/notification-header/notification-header.d.ts +12 -3
  680. package/dist/types/components/notification/notification-item/notification-item.d.ts +15 -3
  681. package/dist/types/components/notification/notification.d.ts +36 -5
  682. package/dist/types/components/pagination/pagination.d.ts +56 -20
  683. package/dist/types/components/radio/radio.d.ts +49 -4
  684. package/dist/types/components/radio-group/radio-group.d.ts +52 -10
  685. package/dist/types/components/scrim/scrim.d.ts +72 -11
  686. package/dist/types/components/scrim/scrim.utils.d.ts +2 -17
  687. package/dist/types/components/select/select-input/select-input.d.ts +22 -4
  688. package/dist/types/components/select/select-list/select-list.d.ts +51 -5
  689. package/dist/types/components/select/select-option/select-option.d.ts +31 -8
  690. package/dist/types/components/select/select.d.ts +152 -13
  691. package/dist/types/components/select/select.types.d.ts +5 -0
  692. package/dist/types/components/sign-in/sign-in.d.ts +30 -3
  693. package/dist/types/components/skip-link/skip-link-item/skip-link-item-alias.d.ts +15 -2
  694. package/dist/types/components/skip-link/skip-link-item/skip-link-item.d.ts +22 -1
  695. package/dist/types/components/skip-link/skip-link.d.ts +37 -3
  696. package/dist/types/components/slider/slider.d.ts +147 -21
  697. package/dist/types/components/slider/slider.types.d.ts +7 -2
  698. package/dist/types/components/slider/slider.utils.d.ts +27 -0
  699. package/dist/types/components/step/step-item/step-item.d.ts +15 -3
  700. package/dist/types/components/step/step.d.ts +47 -12
  701. package/dist/types/components/switch/switch.d.ts +39 -6
  702. package/dist/types/components/tab/tab-item/tab-item.d.ts +20 -4
  703. package/dist/types/components/tab/tab.d.ts +41 -11
  704. package/dist/types/components/table/table-body/table-body.d.ts +10 -6
  705. package/dist/types/components/table/table-cell/table-cell.d.ts +10 -6
  706. package/dist/types/components/table/table-header/table-header.d.ts +10 -6
  707. package/dist/types/components/table/table-header-cell/table-header-cell.d.ts +18 -6
  708. package/dist/types/components/table/table-row/table-row.d.ts +11 -6
  709. package/dist/types/components/table/table.d.ts +49 -11
  710. package/dist/types/components/tag/tag.d.ts +55 -7
  711. package/dist/types/components/textarea/textarea.d.ts +75 -5
  712. package/dist/types/components/textarea/textarea.types.d.ts +4 -0
  713. package/dist/types/components/tooltip/tooltip.d.ts +46 -8
  714. package/dist/types/components/upload/upload.d.ts +78 -10
  715. package/dist/types/components/wizard/wizard-panel/wizard-panel.d.ts +20 -2
  716. package/dist/types/components/wizard/wizard.d.ts +44 -7
  717. package/dist/types/components.d.ts +5825 -1352
  718. package/dist/types/shared/utils/floating-ui.d.ts +4 -0
  719. package/dist/types/shared/utils/focus.d.ts +14 -0
  720. package/dist/types/shared/utils/getRandom.d.ts +1 -0
  721. package/dist/types/shared/utils/id.d.ts +1 -1
  722. package/dist/types/shared/utils/index.d.ts +6 -1
  723. package/dist/types/shared/utils/motion.d.ts +14 -0
  724. package/dist/types/shared/utils/ownership.d.ts +33 -0
  725. package/dist/types/shared/utils/prop-warning.d.ts +7 -0
  726. package/dist/types/shared/utils/props.d.ts +38 -0
  727. package/dist/types/shared/utils/swipe.d.ts +5 -0
  728. package/dist/types/shared/utils/virtual-scroll.d.ts +25 -0
  729. package/dist/types/stencil-public-runtime.d.ts +12 -0
  730. package/dist/webcomponents/index.esm.js +1 -1
  731. package/dist/webcomponents/p-01baafce.entry.js +5 -0
  732. package/dist/webcomponents/p-01fb0754.entry.js +5 -0
  733. package/dist/webcomponents/p-030c02f8.entry.js +5 -0
  734. package/dist/webcomponents/p-03359c92.entry.js +5 -0
  735. package/dist/webcomponents/p-09770c98.entry.js +5 -0
  736. package/dist/webcomponents/p-0b9714f1.entry.js +5 -0
  737. package/dist/webcomponents/p-12aa36a8.entry.js +5 -0
  738. package/dist/webcomponents/p-130b6e06.entry.js +5 -0
  739. package/dist/webcomponents/p-144f8c8d.entry.js +5 -0
  740. package/dist/webcomponents/p-14fe22e2.entry.js +5 -0
  741. package/dist/webcomponents/p-1ff9210a.entry.js +5 -0
  742. package/dist/webcomponents/p-2605cdc3.entry.js +5 -0
  743. package/dist/webcomponents/p-27afaec9.entry.js +5 -0
  744. package/dist/webcomponents/p-2a50e42d.entry.js +5 -0
  745. package/dist/webcomponents/p-327f034f.entry.js +5 -0
  746. package/dist/webcomponents/p-342650b8.entry.js +5 -0
  747. package/dist/webcomponents/p-38f6a78b.entry.js +5 -0
  748. package/dist/webcomponents/p-3920fe3a.entry.js +5 -0
  749. package/dist/webcomponents/p-3ae97345.entry.js +5 -0
  750. package/dist/webcomponents/p-3cce767c.entry.js +5 -0
  751. package/dist/webcomponents/p-3df6c5d2.entry.js +5 -0
  752. package/dist/webcomponents/p-3e287899.entry.js +5 -0
  753. package/dist/webcomponents/p-3e5580ba.entry.js +5 -0
  754. package/dist/webcomponents/p-403637dd.entry.js +5 -0
  755. package/dist/webcomponents/p-435c8ef2.entry.js +5 -0
  756. package/dist/webcomponents/p-59da5b55.entry.js +5 -0
  757. package/dist/webcomponents/p-5dd4314c.entry.js +5 -0
  758. package/dist/webcomponents/p-646af6a5.entry.js +5 -0
  759. package/dist/webcomponents/p-670e8fec.entry.js +5 -0
  760. package/dist/webcomponents/p-68046544.entry.js +5 -0
  761. package/dist/webcomponents/p-68ec76b8.entry.js +5 -0
  762. package/dist/webcomponents/p-6c0ea20c.entry.js +5 -0
  763. package/dist/webcomponents/p-6c2fe5e4.entry.js +5 -0
  764. package/dist/webcomponents/p-707df9b9.entry.js +5 -0
  765. package/dist/webcomponents/p-72b839fe.entry.js +5 -0
  766. package/dist/webcomponents/p-73dcc05b.entry.js +5 -0
  767. package/dist/webcomponents/p-7acf20d3.entry.js +5 -0
  768. package/dist/webcomponents/p-7b01bddb.entry.js +5 -0
  769. package/dist/webcomponents/p-7cd38850.entry.js +5 -0
  770. package/dist/webcomponents/p-82454383.entry.js +5 -0
  771. package/dist/webcomponents/p-91e959a8.entry.js +5 -0
  772. package/dist/webcomponents/p-964c01e6.entry.js +5 -0
  773. package/dist/webcomponents/p-9858e42a.entry.js +5 -0
  774. package/dist/webcomponents/p-9c4200b0.entry.js +5 -0
  775. package/dist/webcomponents/p-9d9c87b1.entry.js +5 -0
  776. package/dist/webcomponents/p-B0PbhaxL.js +5 -0
  777. package/dist/webcomponents/p-BEJGB0Nd.js +5 -0
  778. package/dist/{components/p-Dmfk7eEe.js → webcomponents/p-BJZC_NuV.js} +1 -1
  779. package/dist/webcomponents/p-BJtdabsr.js +5 -0
  780. package/dist/webcomponents/p-BeJxz5TQ.js +5 -0
  781. package/dist/webcomponents/p-BlGV-x0w.js +5 -0
  782. package/dist/webcomponents/{p-Bfm58jO6.js → p-BtRPYRvA.js} +1 -1
  783. package/dist/webcomponents/p-CDtFCbKp.js +5 -0
  784. package/dist/webcomponents/p-CNwZRgyL.js +5 -0
  785. package/dist/webcomponents/{p-DFN_so7I.js → p-CfuJQ1DY.js} +1 -1
  786. package/dist/webcomponents/p-D9Zo6FlV.js +5 -0
  787. package/dist/webcomponents/{p-BhMVJQ4-.js → p-DV-iW9Aj.js} +1 -1
  788. package/dist/webcomponents/p-DWhzxlCx.js +5 -0
  789. package/dist/webcomponents/p-Dcn7tRST.js +7 -0
  790. package/dist/webcomponents/p-EbtQZm5s.js +5 -0
  791. package/dist/webcomponents/p-a0931550.entry.js +5 -0
  792. package/dist/webcomponents/p-a212fd85.entry.js +5 -0
  793. package/dist/webcomponents/p-a2e75143.entry.js +5 -0
  794. package/dist/webcomponents/p-a3bb98c9.entry.js +5 -0
  795. package/dist/webcomponents/p-a8b5dba0.entry.js +5 -0
  796. package/dist/webcomponents/p-aa909443.entry.js +5 -0
  797. package/dist/webcomponents/p-abaf2365.entry.js +5 -0
  798. package/dist/webcomponents/p-aeb16645.entry.js +5 -0
  799. package/dist/webcomponents/p-b287c384.entry.js +5 -0
  800. package/dist/webcomponents/p-b506b0a1.entry.js +5 -0
  801. package/dist/webcomponents/p-b520c08c.entry.js +5 -0
  802. package/dist/webcomponents/p-b94c3f84.entry.js +5 -0
  803. package/dist/webcomponents/p-bda62f90.entry.js +5 -0
  804. package/dist/webcomponents/p-c201ae16.entry.js +5 -0
  805. package/dist/webcomponents/p-c7e899a1.entry.js +5 -0
  806. package/dist/webcomponents/p-c8b7bbab.entry.js +5 -0
  807. package/dist/webcomponents/p-cbf3e251.entry.js +5 -0
  808. package/dist/webcomponents/{p-7f7506f0.entry.js → p-cff24492.entry.js} +1 -1
  809. package/dist/webcomponents/p-d35cf5b4.entry.js +5 -0
  810. package/dist/webcomponents/p-d45ffe9c.entry.js +5 -0
  811. package/dist/webcomponents/p-d719a4af.entry.js +5 -0
  812. package/dist/webcomponents/p-d826c052.entry.js +5 -0
  813. package/dist/webcomponents/p-da21a60d.entry.js +5 -0
  814. package/dist/webcomponents/p-de0c7f26.entry.js +5 -0
  815. package/dist/webcomponents/p-e20188c0.entry.js +5 -0
  816. package/dist/webcomponents/p-e27882e1.entry.js +5 -0
  817. package/dist/webcomponents/p-e3de5bb3.entry.js +5 -0
  818. package/dist/webcomponents/p-e624ff04.entry.js +5 -0
  819. package/dist/webcomponents/p-ed5af0e4.entry.js +5 -0
  820. package/dist/webcomponents/p-edc6da0e.entry.js +5 -0
  821. package/dist/webcomponents/p-f24fcf3d.entry.js +5 -0
  822. package/dist/webcomponents/p-f52ef0dc.entry.js +5 -0
  823. package/dist/webcomponents/{p-12286e73.entry.js → p-f558d7b9.entry.js} +1 -1
  824. package/dist/webcomponents/p-fcab1428.entry.js +5 -0
  825. package/dist/webcomponents/p-fe1729a7.entry.js +5 -0
  826. package/dist/webcomponents/webcomponents.esm.js +1 -1
  827. package/package.json +18 -3
  828. package/dist/cjs/clamp-Co_hWptd.js +0 -25
  829. package/dist/cjs/id-CjRFMzf6.js +0 -20
  830. package/dist/cjs/props-CScmBvKd.js +0 -24
  831. package/dist/collection/pages/components/cookiebar/index.js +0 -26
  832. package/dist/collection/pages/components/link/index.js +0 -29
  833. package/dist/collection/pages/components/pagination/index.js +0 -12
  834. package/dist/collection/pages/components/slider/index.js +0 -18
  835. package/dist/components/p-34Jfn-U-.js +0 -5
  836. package/dist/components/p-6OdfnwnK.js +0 -5
  837. package/dist/components/p-B7Amgxkp.js +0 -5
  838. package/dist/components/p-BKuMQJrQ.js +0 -5
  839. package/dist/components/p-BPJpHGOW.js +0 -5
  840. package/dist/components/p-Bb-nLtTG.js +0 -5
  841. package/dist/components/p-BeE7R9nu.js +0 -5
  842. package/dist/components/p-BkS6ujyf.js +0 -5
  843. package/dist/components/p-Bo0QYHJO.js +0 -5
  844. package/dist/components/p-C2i2c_io.js +0 -5
  845. package/dist/components/p-C7v0lVlX.js +0 -5
  846. package/dist/components/p-CMBsvswx.js +0 -5
  847. package/dist/components/p-CRrimdz6.js +0 -5
  848. package/dist/components/p-CWORw84-.js +0 -5
  849. package/dist/components/p-CvUMXJCl.js +0 -5
  850. package/dist/components/p-D6zroLx5.js +0 -5
  851. package/dist/components/p-DBP6K_aq.js +0 -5
  852. package/dist/components/p-DCrVo-8T.js +0 -5
  853. package/dist/components/p-DFUKDNck.js +0 -5
  854. package/dist/components/p-DHicj0By.js +0 -5
  855. package/dist/components/p-DIK54tTj.js +0 -5
  856. package/dist/components/p-DQRSHR-D.js +0 -5
  857. package/dist/components/p-DRVMm1Py.js +0 -5
  858. package/dist/components/p-DWPmUV72.js +0 -5
  859. package/dist/components/p-DXjQyH6s.js +0 -5
  860. package/dist/components/p-DmCxdB9P.js +0 -5
  861. package/dist/components/p-Dp0xy_3n.js +0 -5
  862. package/dist/components/p-DxZJrIyL.js +0 -5
  863. package/dist/components/p-JAkkThgf.js +0 -5
  864. package/dist/components/p-Ud-WB0hx.js +0 -5
  865. package/dist/components/p-fpMNttbg.js +0 -5
  866. package/dist/components/p-gvnfuTjd.js +0 -5
  867. package/dist/components/p-qYONSNcf.js +0 -5
  868. package/dist/components/p-qhhHGJY1.js +0 -5
  869. package/dist/components/p-ttI0nvv_.js +0 -5
  870. package/dist/components/p-ukNmfGNP.js +0 -5
  871. package/dist/components/p-xa8e1kSW.js +0 -5
  872. package/dist/esm/clamp-gvnfuTjd.js +0 -23
  873. package/dist/esm/id-BkS6ujyf.js +0 -18
  874. package/dist/esm/props-DRVMm1Py.js +0 -22
  875. package/dist/webcomponents/p-0196804a.entry.js +0 -5
  876. package/dist/webcomponents/p-0410186a.entry.js +0 -5
  877. package/dist/webcomponents/p-0415ef22.entry.js +0 -5
  878. package/dist/webcomponents/p-0777c7b1.entry.js +0 -5
  879. package/dist/webcomponents/p-0caa4d12.entry.js +0 -5
  880. package/dist/webcomponents/p-0d4f718d.entry.js +0 -5
  881. package/dist/webcomponents/p-0e84c9e8.entry.js +0 -5
  882. package/dist/webcomponents/p-147ac8d3.entry.js +0 -5
  883. package/dist/webcomponents/p-1580beee.entry.js +0 -5
  884. package/dist/webcomponents/p-18ee6175.entry.js +0 -5
  885. package/dist/webcomponents/p-1bca4499.entry.js +0 -5
  886. package/dist/webcomponents/p-1c303a4e.entry.js +0 -5
  887. package/dist/webcomponents/p-1d6b0b6f.entry.js +0 -5
  888. package/dist/webcomponents/p-1d8cb8fd.entry.js +0 -5
  889. package/dist/webcomponents/p-224daaac.entry.js +0 -5
  890. package/dist/webcomponents/p-28426d2a.entry.js +0 -5
  891. package/dist/webcomponents/p-2abd2da0.entry.js +0 -5
  892. package/dist/webcomponents/p-2fdc51ae.entry.js +0 -5
  893. package/dist/webcomponents/p-30c428b6.entry.js +0 -5
  894. package/dist/webcomponents/p-36bbea4e.entry.js +0 -5
  895. package/dist/webcomponents/p-3907ebfa.entry.js +0 -5
  896. package/dist/webcomponents/p-39a16f9d.entry.js +0 -5
  897. package/dist/webcomponents/p-3ebbd2f5.entry.js +0 -5
  898. package/dist/webcomponents/p-3ef7eac8.entry.js +0 -5
  899. package/dist/webcomponents/p-45356e9a.entry.js +0 -5
  900. package/dist/webcomponents/p-46513db4.entry.js +0 -5
  901. package/dist/webcomponents/p-4c13221a.entry.js +0 -5
  902. package/dist/webcomponents/p-51ce2c31.entry.js +0 -5
  903. package/dist/webcomponents/p-52df61cb.entry.js +0 -5
  904. package/dist/webcomponents/p-569134cf.entry.js +0 -5
  905. package/dist/webcomponents/p-5ce7db4a.entry.js +0 -5
  906. package/dist/webcomponents/p-5f373708.entry.js +0 -5
  907. package/dist/webcomponents/p-5f6afb79.entry.js +0 -5
  908. package/dist/webcomponents/p-5fc7ba4c.entry.js +0 -5
  909. package/dist/webcomponents/p-66006312.entry.js +0 -5
  910. package/dist/webcomponents/p-66b13fd9.entry.js +0 -5
  911. package/dist/webcomponents/p-6OdfnwnK.js +0 -5
  912. package/dist/webcomponents/p-750799b7.entry.js +0 -5
  913. package/dist/webcomponents/p-756ff2ad.entry.js +0 -5
  914. package/dist/webcomponents/p-765bfe27.entry.js +0 -5
  915. package/dist/webcomponents/p-7ab96c11.entry.js +0 -5
  916. package/dist/webcomponents/p-7c2ff8b4.entry.js +0 -5
  917. package/dist/webcomponents/p-7fb03a49.entry.js +0 -5
  918. package/dist/webcomponents/p-82200563.entry.js +0 -5
  919. package/dist/webcomponents/p-83ff4579.entry.js +0 -5
  920. package/dist/webcomponents/p-85f8063b.entry.js +0 -5
  921. package/dist/webcomponents/p-8b558233.entry.js +0 -5
  922. package/dist/webcomponents/p-8e6c2767.entry.js +0 -5
  923. package/dist/webcomponents/p-8e819355.entry.js +0 -5
  924. package/dist/webcomponents/p-92a9b9c4.entry.js +0 -5
  925. package/dist/webcomponents/p-966ad32f.entry.js +0 -5
  926. package/dist/webcomponents/p-9679d230.entry.js +0 -5
  927. package/dist/webcomponents/p-96dd663b.entry.js +0 -5
  928. package/dist/webcomponents/p-98843fa3.entry.js +0 -5
  929. package/dist/webcomponents/p-9a375eff.entry.js +0 -5
  930. package/dist/webcomponents/p-9b358cff.entry.js +0 -5
  931. package/dist/webcomponents/p-9f7558c7.entry.js +0 -5
  932. package/dist/webcomponents/p-BkS6ujyf.js +0 -5
  933. package/dist/webcomponents/p-C2RBydfd.js +0 -6
  934. package/dist/webcomponents/p-CO5cOQQU.js +0 -5
  935. package/dist/webcomponents/p-DIK54tTj.js +0 -5
  936. package/dist/webcomponents/p-DRVMm1Py.js +0 -5
  937. package/dist/webcomponents/p-DxZJrIyL.js +0 -5
  938. package/dist/webcomponents/p-a382e115.entry.js +0 -5
  939. package/dist/webcomponents/p-a4ae72e3.entry.js +0 -5
  940. package/dist/webcomponents/p-a994c190.entry.js +0 -5
  941. package/dist/webcomponents/p-a9ff7c25.entry.js +0 -5
  942. package/dist/webcomponents/p-c0b0f531.entry.js +0 -5
  943. package/dist/webcomponents/p-c211af17.entry.js +0 -5
  944. package/dist/webcomponents/p-c492d926.entry.js +0 -5
  945. package/dist/webcomponents/p-c4cfe599.entry.js +0 -5
  946. package/dist/webcomponents/p-c846e784.entry.js +0 -5
  947. package/dist/webcomponents/p-c949d993.entry.js +0 -5
  948. package/dist/webcomponents/p-d1e899cd.entry.js +0 -5
  949. package/dist/webcomponents/p-d38d82cc.entry.js +0 -5
  950. package/dist/webcomponents/p-e0ce536a.entry.js +0 -5
  951. package/dist/webcomponents/p-e1331288.entry.js +0 -5
  952. package/dist/webcomponents/p-e360a463.entry.js +0 -5
  953. package/dist/webcomponents/p-f078f972.entry.js +0 -5
  954. package/dist/webcomponents/p-f26038e2.entry.js +0 -5
  955. package/dist/webcomponents/p-f303f6b3.entry.js +0 -5
  956. package/dist/webcomponents/p-f6318e94.entry.js +0 -5
  957. package/dist/webcomponents/p-f85ee01c.entry.js +0 -5
  958. package/dist/webcomponents/p-fcd4ae48.entry.js +0 -5
  959. package/dist/webcomponents/p-ffe0241e.entry.js +0 -5
  960. package/dist/webcomponents/p-gvnfuTjd.js +0 -5
@@ -4,10 +4,77 @@ const CLEAR_COMPONENTS_FILTER = document.getElementById('clear-components-filter
4
4
 
5
5
  let renderedFilesContent = {};
6
6
  let currentLoadedPath = null;
7
+ let pageLoadGeneration = 0;
8
+ const activeExampleCleanups = new Set();
7
9
  const markdownParser = window.marked;
8
- const DEV_SERVER_CONNECTOR_IFRAME_RE =
9
- /<iframe\b[^>]*title=["']Stencil Dev Server Connector[^"']*["'][\s\S]*?<\/iframe>/gi;
10
10
  let lzStringPromise;
11
+ const MAX_PLAYGROUND_DRAFT_SIZE = 512 * 1024;
12
+ const DEV_VIEWPORTS = [
13
+ { id: 'desktop', label: 'Desktop (100%)', icon: 'fas fa-desktop', mode: 'web', width: null, height: null },
14
+ { id: 'tablet', label: 'Tablet - 768px', icon: 'fas fa-tablet-alt', mode: 'web', width: 768, height: 600 },
15
+ { id: 'ios', label: 'iPhone (iOS) - 390x844', icon: 'fab fa-apple', mode: 'ios', width: 390, height: 844 },
16
+ { id: 'android', label: 'Android - 360x800', icon: 'fab fa-android', mode: 'android', width: 360, height: 800 },
17
+ ];
18
+ const DEV_PREVIEW_MIN_WIDTH = 200;
19
+ const DEV_PREVIEW_MIN_HEIGHT = 180;
20
+ const DEV_PREVIEW_RESIZE_STEP = 16;
21
+
22
+ function createPreviewResizeHandle(axis) {
23
+ const isWidthHandle = axis === 'vertical';
24
+ const handle = document.createElement('div');
25
+ handle.className = `wbc-example-preview-resize-handle wbc-example-preview-resize-handle--${axis}`;
26
+ handle.setAttribute('role', 'separator');
27
+ handle.setAttribute('tabindex', '0');
28
+ handle.setAttribute(
29
+ 'aria-label',
30
+ isWidthHandle ? 'Redimensionar largura do preview' : 'Redimensionar altura do preview',
31
+ );
32
+ handle.setAttribute('aria-orientation', axis);
33
+ const line = document.createElement('span');
34
+ line.className = 'wbc-example-preview-resize-handle__line';
35
+ handle.appendChild(line);
36
+ return handle;
37
+ }
38
+
39
+ function getPreviewResizeDelta(key, decreaseKey, increaseKey) {
40
+ if (key === decreaseKey) return -DEV_PREVIEW_RESIZE_STEP;
41
+ if (key === increaseKey) return DEV_PREVIEW_RESIZE_STEP;
42
+ return 0;
43
+ }
44
+
45
+ function getPlaygroundDraftKey(path, file) {
46
+ return `wbc-playground-draft:${path}/${file}`;
47
+ }
48
+
49
+ function readPlaygroundDraft(path, file) {
50
+ try {
51
+ const raw = window.localStorage.getItem(getPlaygroundDraftKey(path, file));
52
+ if (!raw || raw.length > MAX_PLAYGROUND_DRAFT_SIZE) return null;
53
+ const draft = JSON.parse(raw);
54
+ if (typeof draft?.html !== 'string') return null;
55
+ return draft;
56
+ } catch {
57
+ return null;
58
+ }
59
+ }
60
+
61
+ function writePlaygroundDraft(path, file, draft) {
62
+ try {
63
+ const serialized = JSON.stringify({ ...draft, updatedAt: Date.now() });
64
+ if (serialized.length > MAX_PLAYGROUND_DRAFT_SIZE) return false;
65
+ window.localStorage.setItem(getPlaygroundDraftKey(path, file), serialized);
66
+ return true;
67
+ } catch {
68
+ return false;
69
+ }
70
+ }
71
+
72
+ function getScrollBehavior() {
73
+ const prefersReducedMotion =
74
+ (typeof document !== 'undefined' && document.documentElement.dataset.wbcReducedMotion === 'true') ||
75
+ (typeof window.matchMedia === 'function' && window.matchMedia('(prefers-reduced-motion: reduce)').matches);
76
+ return prefersReducedMotion ? 'auto' : 'smooth';
77
+ }
11
78
 
12
79
  function loadLzString() {
13
80
  if (window.LZString) return Promise.resolve(window.LZString);
@@ -23,6 +90,13 @@ function loadLzString() {
23
90
  return lzStringPromise;
24
91
  }
25
92
 
93
+ function cleanupExamples() {
94
+ activeExampleCleanups.forEach((cleanup) => {
95
+ cleanup();
96
+ });
97
+ activeExampleCleanups.clear();
98
+ }
99
+
26
100
  // Decode shared state from URL parameters on initialization
27
101
  (() => {
28
102
  const params = new URLSearchParams(window.location.search);
@@ -53,313 +127,25 @@ function getBaseUrl() {
53
127
  return baseUrl === '' ? '' : baseUrl;
54
128
  }
55
129
 
56
- function renderExamplePreview(previewElement, source, edgeToEdge = false) {
57
- const frame = previewElement.querySelector('iframe');
58
- if (!frame) return;
130
+ function getPresetScriptUrl(path, script) {
131
+ if (typeof script !== 'string' || !/\.js$/i.test(script)) return '';
59
132
 
60
- const baseUrl = getBaseUrl();
61
- const componentBundleUrl = new URL(`${baseUrl}/build/webcomponents.esm.js`, window.location.href);
62
- componentBundleUrl.searchParams.set('preview-version', String(Date.now()));
63
- const componentBundle = componentBundleUrl.href;
64
- const frameSource = stripDevServerConnector(source);
65
-
66
- frame.srcdoc = `<!doctype html>
67
- <html lang="pt-BR">
68
- <head>
69
- <meta charset="UTF-8">
70
- <meta name="viewport" content="width=device-width, initial-scale=1">
71
- <base href="${window.location.href}">
72
- <link rel="stylesheet" href="${new URL(`${baseUrl}/assets/core.min.css`, window.location.href).href}">
73
- <link rel="stylesheet" href="${new URL(`${baseUrl}/assets/fonts/rawline/400.css`, window.location.href).href}">
74
- <link rel="stylesheet" href="${new URL(`${baseUrl}/assets/fonts/raleway/wght.css`, window.location.href).href}">
75
- <link rel="stylesheet" href="${new URL(`${baseUrl}/assets/fonts/fontawesome/css/all.min.css`, window.location.href).href}">
76
- <style>
77
- * { font-family: Rawline, Raleway, sans-serif; }
78
- html, body { margin: 0; min-height: 1px; overflow: visible; }
79
- body { box-sizing: border-box; padding: 24px 16px; }
80
- body.wbc-preview-edge-to-edge { padding: 0; }
81
- br-cookiebar, br-scrim { inset: 0; position: absolute; pointer-events: none; z-index: 1000; }
82
- br-scrim { --scrim-display-mode: parent; }
83
- </style>
84
- </head>
85
- <body${edgeToEdge ? ' class="wbc-preview-edge-to-edge"' : ''}><main data-wbc-preview-content>${frameSource}</main>
86
- <script type="module" src="${componentBundle}"></script>
87
- <script>
88
- (() => {
89
- const overlayContentSelector =
90
- '[part="open-panel"], [part="default-panel"], [part="body"], .cookiebar-body, .content, .br-modal';
91
- const getOverlayHeight = (overlay) => {
92
- const measuredHeight = Array.from(overlay.shadowRoot?.querySelectorAll(overlayContentSelector) || []).reduce(
93
- (height, element) =>
94
- Math.max(height, element.scrollHeight, element.clientHeight, element.getBoundingClientRect().height),
95
- 0,
96
- );
97
- if (measuredHeight > 0) return measuredHeight;
98
-
99
- const modal = overlay.matches('br-scrim') ? overlay.querySelector('br-modal') : overlay;
100
- return modal?.shadowRoot?.querySelector('.br-modal')?.getBoundingClientRect().height || 0;
101
- };
102
- const getElementsIncludingShadowRoots = (root = document) => {
103
- const elements = [];
104
- const visit = (tree) => {
105
- tree.querySelectorAll('*').forEach((element) => {
106
- elements.push(element);
107
- if (element.shadowRoot) visit(element.shadowRoot);
108
- });
109
- };
110
- visit(root);
111
- return elements;
112
- };
113
- const getFloatingHeight = () => {
114
- const bodyStyle = getComputedStyle(document.body);
115
- const bottomPadding = parseFloat(bodyStyle.paddingBottom) || 0;
116
- return getElementsIncludingShadowRoots().reduce((height, element) => {
117
- if (element.matches('br-cookiebar, br-scrim, br-modal')) return height;
118
- const style = getComputedStyle(element);
119
- if (style.position !== 'absolute' && style.position !== 'fixed') return height;
120
- if (style.display === 'none' || style.visibility === 'hidden') return height;
121
- return Math.max(height, element.getBoundingClientRect().bottom + bottomPadding);
122
- }, 0);
123
- };
124
- const sendHeight = () => {
125
- const body = document.body;
126
- const bodyStyle = getComputedStyle(body);
127
- const overlayHeight = Array.from(document.querySelectorAll('br-cookiebar, br-scrim, br-modal')).reduce(
128
- (height, overlay) => Math.max(height, getOverlayHeight(overlay)),
129
- 0,
130
- );
131
- const verticalPadding = parseFloat(bodyStyle.paddingTop) + parseFloat(bodyStyle.paddingBottom);
132
- const height = Math.ceil(
133
- Math.max(
134
- body.scrollHeight,
135
- body.offsetHeight,
136
- body.getBoundingClientRect().height,
137
- overlayHeight + verticalPadding,
138
- getFloatingHeight(),
139
- ),
140
- );
141
- parent.postMessage({ type: 'wbc-preview-height', height }, '*');
142
- };
143
- document.querySelectorAll('br-cookiebar, br-scrim').forEach((overlay) => {
144
- overlay.setAttribute('data-wbc-preview-contained', '');
145
- if (overlay.matches('br-scrim')) overlay.setAttribute('display-mode', 'parent');
146
- });
147
- const serialize = (value, seen = new WeakSet()) => {
148
- if (value instanceof Element) return '<' + value.localName + '>';
149
- if (value instanceof Event) return { type: value.type };
150
- if (value && typeof value === 'object') {
151
- if (seen.has(value)) return '[Circular]';
152
- seen.add(value);
153
- if (Array.isArray(value)) return value.map((item) => serialize(item, seen));
154
- return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, serialize(item, seen)]));
155
- }
156
- return value;
157
- };
158
- const sendEvent = (event, dispatchedBy = event.target) => {
159
- const target = dispatchedBy instanceof Element ? dispatchedBy : dispatchedBy?.host instanceof Element ? dispatchedBy.host : null;
160
- parent.postMessage({
161
- type: 'wbc-preview-event',
162
- eventType: event.type,
163
- custom: event instanceof CustomEvent,
164
- detail: event instanceof CustomEvent ? serialize(event.detail) : undefined,
165
- target: target ? target.localName + (target.id ? '#' + target.id : '') : 'window',
166
- }, '*');
167
- };
168
- ['change', 'click', 'input', 'submit'].forEach((name) => document.addEventListener(name, sendEvent, true));
169
- document.addEventListener('brInternalEvent', sendEvent, true);
170
- const originalDispatchEvent = EventTarget.prototype.dispatchEvent;
171
- EventTarget.prototype.dispatchEvent = function dispatchEvent(event) {
172
- if (event instanceof CustomEvent) sendEvent(event, this);
173
- return originalDispatchEvent.call(this, event);
174
- };
175
- let heightFrame = 0;
176
- const scheduleHeight = () => {
177
- cancelAnimationFrame(heightFrame);
178
- heightFrame = requestAnimationFrame(sendHeight);
179
- };
180
- const resizeObserver = new ResizeObserver(scheduleHeight);
181
- const observeOverlayContent = () => {
182
- document.querySelectorAll('br-cookiebar, br-scrim, br-modal').forEach((overlay) => {
183
- overlay.shadowRoot?.querySelectorAll(overlayContentSelector).forEach((element) => {
184
- resizeObserver.observe(element);
185
- });
186
- });
187
- getElementsIncludingShadowRoots().forEach((element) => {
188
- const position = getComputedStyle(element).position;
189
- if (position === 'absolute' || position === 'fixed') resizeObserver.observe(element);
190
- });
191
- };
192
- resizeObserver.observe(document.documentElement);
193
- resizeObserver.observe(document.body);
194
- new MutationObserver(() =>
195
- requestAnimationFrame(() => {
196
- observeOverlayContent();
197
- scheduleHeight();
198
- }),
199
- ).observe(document.body, { attributes: true, childList: true, subtree: true });
200
- Promise.all(
201
- [...document.querySelectorAll('*')]
202
- .map((element) => element.localName)
203
- .filter((tag, index, tags) => tag.includes('-') && tags.indexOf(tag) === index)
204
- .map((tag) => customElements.whenDefined(tag)),
205
- ).then(() =>
206
- requestAnimationFrame(() =>
207
- requestAnimationFrame(() => {
208
- observeOverlayContent();
209
- scheduleHeight();
210
- }),
211
- ),
212
- );
213
- addEventListener('load', scheduleHeight);
214
- scheduleHeight();
215
- })();
216
- </script>
217
- </body>
218
- </html>`;
219
- }
220
-
221
- function stripDevServerConnector(source) {
222
- return String(source || '')
223
- .replace(DEV_SERVER_CONNECTOR_IFRAME_RE, '')
224
- .trim();
225
- }
226
-
227
- function getFrameworkCode(source, framework) {
228
- const html = String(source || '').trim();
229
- const components = Array.from(html.matchAll(/<\/?(br-[a-z0-9-]+)/gi), (match) => match[1]);
230
- const imports = [...new Set(components)].map((tag) =>
231
- tag
232
- .split('-')
233
- .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
234
- .join(''),
235
- );
236
- const importList = imports.length > 0 ? imports.join(', ') : 'BrButton';
237
- const pascalMarkup = html.replace(/(<\/?)(br-[a-z0-9-]+)/gi, (_match, prefix, tag) => {
238
- return `${prefix}${tag
239
- .split('-')
240
- .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
241
- .join('')}`;
242
- });
243
-
244
- if (framework === 'javascript') {
245
- return `import { ${importList} } from '@govbr-ds/webcomponents';\n\nconst example = document.querySelector('${components[0] || 'br-button'}');\n\n// Use o exemplo renderizado para adicionar comportamento com JavaScript.\nconsole.log(example);`;
246
- }
247
- if (framework === 'css') {
248
- return `/* Customize os componentes usando CSS Parts */
249
- /* Exemplo:
250
- br-${String(location.pathname).split('/').filter(Boolean).pop() || 'component'}::part(container) {
251
- background-color: #f8f9fa;
252
- }
253
- */`;
254
- }
255
- if (framework === 'angular') {
256
- return `import { Component } from '@angular/core';\nimport { ${importList} } from '@govbr-ds/webcomponents-angular/standalone';\n\n@Component({\n selector: 'app-root',\n standalone: true,\n imports: [${importList}],\n template: \`${html.replace(/`/g, '\\`')}\`,\n})\nexport class AppComponent {}`;
257
- }
258
- if (framework === 'react') {
259
- return `import { ${importList} } from '@govbr-ds/webcomponents-react';\n\nexport default function App() {\n return (\n <>\n ${pascalMarkup.replace(/\n/g, '\n ')}\n </>\n );\n}`;
133
+ const componentSegments = String(path).replaceAll('\\', '/').split('/').filter(Boolean);
134
+ const scriptSegments = script.replaceAll('\\', '/').split('/');
135
+ if (
136
+ componentSegments.length === 0 ||
137
+ scriptSegments.some((segment) => !segment || segment === '.' || segment === '..')
138
+ ) {
139
+ return '';
260
140
  }
261
- return `<script setup lang="ts">\nimport { ${importList} } from '@govbr-ds/webcomponents-vue';\n</script>\n\n<template>\n ${pascalMarkup.replace(/\n/g, '\n ')}\n</template>`;
262
- }
263
-
264
- function getFrameworkFiles(source, framework) {
265
- if (framework !== 'angular') return null;
266
-
267
- const html = String(source || '').trim();
268
- const components = Array.from(html.matchAll(/<\/?(br-[a-z0-9-]+)/gi), (match) => match[1]);
269
- const imports = [...new Set(components)].map((tag) =>
270
- tag
271
- .split('-')
272
- .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
273
- .join(''),
274
- );
275
- const importList = imports.length > 0 ? imports.join(', ') : 'BrButton';
276
141
 
277
- return [
278
- {
279
- filename: 'app.component.ts',
280
- language: 'typescript',
281
- code: `import { Component } from '@angular/core'\nimport { ${importList} } from '@govbr-ds/webcomponents-angular/standalone'\n\n@Component({\n selector: 'app-root',\n standalone: true,\n imports: [${importList}],\n templateUrl: './app.component.html',\n})\nexport class AppComponent {}`,
282
- },
283
- { filename: 'app.component.html', language: 'html', code: html },
284
- ];
142
+ const relativePath = [...componentSegments, ...scriptSegments].map(encodeURIComponent).join('/');
143
+ const scriptUrl = new URL(`${getBaseUrl()}/pages/components/${relativePath}`, window.location.href);
144
+ scriptUrl.searchParams.set('preview-version', String(Date.now()));
145
+ return scriptUrl.href;
285
146
  }
286
147
 
287
- function createReadOnlyFrameworkTab(label, icon, tabId, source, framework) {
288
- const tab = document.createElement('br-tab-item');
289
- tab.setAttribute('label', label);
290
- tab.setAttribute('icon', icon);
291
- tab.setAttribute('icon-only', 'true');
292
- tab.setAttribute('title', label);
293
- tab.setAttribute('tab-item-id', tabId);
294
- tab.dataset.framework = framework;
295
-
296
- const files = getFrameworkFiles(source, framework);
297
- tab._frameworkFiles = files;
298
-
299
- if (files?.length > 1) {
300
- const fileTabs = document.createElement('div');
301
- fileTabs.className = 'wbc-framework-file-tabs';
302
- fileTabs.setAttribute('role', 'tablist');
303
- files.forEach((file, index) => {
304
- const fileTab = document.createElement('button');
305
- fileTab.className = `wbc-framework-file-tab${index === 0 ? ' is-active' : ''}`;
306
- fileTab.type = 'button';
307
- fileTab.dataset.filename = file.filename;
308
- fileTab.setAttribute('aria-selected', String(index === 0));
309
- fileTab.setAttribute('role', 'tab');
310
- fileTab.textContent = file.filename;
311
- fileTabs.appendChild(fileTab);
312
- });
313
- tab.appendChild(fileTabs);
314
- }
315
-
316
- const code = document.createElement('pre');
317
- code.className = 'wbc-framework-code';
318
- code.dataset.framework = framework;
319
- code.dataset.filename = files?.[0]?.filename || '';
320
- code.textContent = files?.[0]?.code || getFrameworkCode(source, framework);
321
- tab.appendChild(code);
322
- return tab;
323
- }
324
-
325
- async function getPreviewAxeContext(previewFrame) {
326
- const previewDocument = previewFrame.contentDocument;
327
- const previewWindow = previewFrame.contentWindow;
328
- if (!previewDocument?.body || !previewWindow) {
329
- throw new Error('O conteúdo do preview ainda não está disponível.');
330
- }
331
-
332
- if (!previewWindow.axe) {
333
- const axeScriptUrl = new URL(`${getBaseUrl()}/assets/axe-core.min.js`, window.location.href).href;
334
-
335
- const response = await fetch(axeScriptUrl);
336
- if (!response.ok) throw new Error('Não foi possível carregar o Axe-Core no preview.');
337
-
338
- const axeScript = previewDocument.createElement('script');
339
- axeScript.textContent = await response.text();
340
- previewDocument.head.appendChild(axeScript);
341
- }
342
-
343
- const previewContent = previewDocument.querySelector('[data-wbc-preview-content]');
344
- if (!previewContent) throw new Error('Não foi possível localizar o conteúdo do exemplo.');
345
-
346
- return { axe: previewWindow.axe, previewContent };
347
- }
348
-
349
- function getExampleHash(file) {
350
- return `#${encodeURIComponent(file)}`;
351
- }
352
-
353
- function getRequestedExampleFile() {
354
- if (!window.location.hash) return null;
355
- try {
356
- return decodeURIComponent(window.location.hash.slice(1));
357
- } catch {
358
- return window.location.hash.slice(1);
359
- }
360
- }
361
-
362
- function createExampleElement(path, file, text, isExpanded = false, onOpen) {
148
+ function createExampleElement(path, file, text, presets = [], defaultPreset = '', exampleLabel = '', baseScript = '') {
363
149
  text = stripDevServerConnector(text);
364
150
  const contentDiv = document.createElement('br-item');
365
151
  contentDiv.classList.add('file', 'wbc-example');
@@ -367,16 +153,25 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
367
153
  contentDiv.dataset.exampleFile = file;
368
154
  const controlsScope = `wbc-example-${path}-${file}`.replace(/[^a-zA-Z0-9_-]/g, '-');
369
155
  contentDiv.dataset.controlsScope = controlsScope;
156
+ const previewChannelId = `${controlsScope}-preview`;
370
157
 
371
- const dropdown = document.createElement('br-dropdown');
372
- dropdown.className = 'wbc-example-dropdown';
373
- if (isExpanded) dropdown.setAttribute('is-open', '');
158
+ const exampleAbortController = new AbortController();
374
159
  let initializeExample;
375
160
  let isInitialized = false;
376
161
 
377
162
  const preview = document.createElement('div');
378
163
  preview.className = 'wbc-example-preview';
164
+ const previewViewport = document.createElement('div');
165
+ previewViewport.className = 'wbc-example-preview-viewport';
379
166
  let previewFrame;
167
+ const previewWidthResizeHandle = createPreviewResizeHandle('vertical');
168
+ const previewHeightResizeHandle = createPreviewResizeHandle('horizontal');
169
+ let previewResizeState = null;
170
+ let hasManualPreviewHeight = false;
171
+ let activeViewport = DEV_VIEWPORTS[0];
172
+ let darkThemeEnabled = false;
173
+ let reducedMotionEnabled =
174
+ typeof window.matchMedia === 'function' && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
380
175
 
381
176
  // --- EDITOR CONTAINER ---
382
177
  const editorContainer = document.createElement('div');
@@ -385,12 +180,13 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
385
180
  const tabComponent = document.createElement('br-tab');
386
181
  tabComponent.setAttribute('density', 'small');
387
182
  tabComponent.setAttribute('active-tab-id', 'code-tab');
183
+ tabComponent.setAttribute('data-playground-badges', '');
388
184
 
389
185
  const codeTabItem = document.createElement('br-tab-item');
390
186
  codeTabItem.setAttribute('label', 'HTML');
391
187
  codeTabItem.setAttribute('icon', 'fab fa-html5');
392
188
  codeTabItem.setAttribute('icon-only', 'true');
393
- codeTabItem.setAttribute('title', 'HTML');
189
+ codeTabItem.setAttribute('title', 'Editor HTML');
394
190
  codeTabItem.setAttribute('tab-item-id', 'code-tab');
395
191
  codeTabItem.setAttribute('active', 'true');
396
192
  codeTabItem.setAttribute('is-active', 'true');
@@ -399,21 +195,23 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
399
195
  eventsTabItem.setAttribute('label', 'Console');
400
196
  eventsTabItem.setAttribute('icon', 'fas fa-terminal');
401
197
  eventsTabItem.setAttribute('icon-only', 'true');
402
- eventsTabItem.setAttribute('title', 'Console');
198
+ eventsTabItem.setAttribute('title', 'Console: eventos e mensagens de runtime');
403
199
  eventsTabItem.setAttribute('tab-item-id', 'events-tab');
404
200
 
405
201
  const controlsTabItem = document.createElement('br-tab-item');
406
202
  controlsTabItem.setAttribute('label', 'Controles');
407
203
  controlsTabItem.setAttribute('icon', 'fas fa-sliders-h');
408
204
  controlsTabItem.setAttribute('icon-only', 'true');
409
- controlsTabItem.setAttribute('title', 'Controles');
205
+ controlsTabItem.setAttribute('title', 'Controles do componente');
410
206
  controlsTabItem.setAttribute('tab-item-id', 'controls-tab');
411
207
 
412
- const javascriptTabItem = createReadOnlyFrameworkTab('JS', 'fab fa-js', 'javascript-tab', text, 'javascript');
413
- const cssTabItem = createReadOnlyFrameworkTab('CSS', 'fab fa-css3-alt', 'css-tab', text, 'css');
414
- const angularTabItem = createReadOnlyFrameworkTab('Angular', 'fab fa-angular', 'angular-tab', text, 'angular');
415
- const reactTabItem = createReadOnlyFrameworkTab('React', 'fab fa-react', 'react-tab', text, 'react');
416
- const vueTabItem = createReadOnlyFrameworkTab('Vue', 'fab fa-vuejs', 'vue-tab', text, 'vue');
208
+ const javascriptTabItem = createFrameworkTab('JS', 'fab fa-js', 'javascript-tab', text, 'javascript', {
209
+ editable: true,
210
+ });
211
+ const cssTabItem = createFrameworkTab('CSS', 'fab fa-css3-alt', 'css-tab', text, 'css', { editable: true });
212
+ const angularTabItem = createFrameworkTab('Angular', 'fab fa-angular', 'angular-tab', text, 'angular');
213
+ const reactTabItem = createFrameworkTab('React', 'fab fa-react', 'react-tab', text, 'react');
214
+ const vueTabItem = createFrameworkTab('Vue', 'fab fa-vuejs', 'vue-tab', text, 'vue');
417
215
  const frameworkTabItems = [javascriptTabItem, cssTabItem, angularTabItem, reactTabItem, vueTabItem];
418
216
  const frameworkEditors = new Map();
419
217
  const refreshFrameworkEditors = () => {
@@ -424,6 +222,7 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
424
222
  });
425
223
  };
426
224
  const getFrameworkEditorLanguage = (framework) => {
225
+ if (framework === 'javascript') return 'javascript';
427
226
  if (framework === 'css') return 'css';
428
227
  if (framework === 'angular') return 'typescript';
429
228
  if (framework === 'react') return 'tsx';
@@ -478,6 +277,7 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
478
277
 
479
278
  const button = document.createElement('br-button');
480
279
  button.setAttribute('slot', 'trigger');
280
+ button.setAttribute('type', 'button');
481
281
  button.setAttribute('shape', 'circle');
482
282
  button.setAttribute('density', 'small');
483
283
  button.setAttribute('emphasis', 'secondary');
@@ -499,164 +299,781 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
499
299
  return { tooltip, button, icon, tooltipContent };
500
300
  };
501
301
 
502
- const editorState = { value: text };
302
+ const localDraft =
303
+ window.SHARED_STATE?.p === path && window.SHARED_STATE?.f === file ? null : readPlaygroundDraft(path, file);
304
+ const presetOptions = presets;
305
+ const draftPreset = presetOptions.find(({ id }) => id === localDraft?.presetId);
306
+ const draftBaseline = typeof localDraft?.baselineHtml === 'string' ? localDraft.baselineHtml : null;
307
+ const currentDraftBaseline = draftPreset ? getPresetSource(draftPreset) : text;
308
+ const activeDraft = draftBaseline === currentDraftBaseline ? localDraft : null;
309
+ const editorState = { value: activeDraft?.html || text };
310
+ const vanillaSources = {
311
+ html: editorState.value,
312
+ css: getFrameworkCode(editorState.value, 'css'),
313
+ javascript: getFrameworkCode(editorState.value, 'javascript'),
314
+ };
315
+ let activeVanillaFile = 'html';
316
+ let isSwitchingVanillaFile = false;
317
+ let comparisonBaseline = text;
318
+ const editorHistory = { entries: [editorState.value], index: 0 };
319
+ const editorHistoryLimit = 50;
320
+ let isApplyingEditorValue = false;
321
+ let controlsApi = null;
322
+ let isUpdatingFromControls = false;
323
+ let undoAction;
324
+ let redoAction;
325
+ let diffAction;
326
+ let overflowUndo;
327
+ let overflowRedo;
328
+ let overflowDiff;
503
329
  let editorApi = null;
504
330
  const getEditorValue = () => editorApi?.getValue() ?? editorState.value;
505
331
  const refreshEditor = () => {
506
332
  requestAnimationFrame(() => requestAnimationFrame(() => editorApi?.refresh?.()));
507
333
  };
334
+ const updateHistoryActions = () => {
335
+ if (undoAction) undoAction.button.disabled = editorHistory.index === 0;
336
+ if (redoAction) redoAction.button.disabled = editorHistory.index === editorHistory.entries.length - 1;
337
+ if (overflowUndo) overflowUndo.item.disabled = editorHistory.index === 0;
338
+ if (overflowRedo) overflowRedo.item.disabled = editorHistory.index === editorHistory.entries.length - 1;
339
+ };
340
+ const recordEditorHistory = (source) => {
341
+ if (editorHistory.entries[editorHistory.index] === source) return;
342
+ editorHistory.entries = editorHistory.entries.slice(0, editorHistory.index + 1);
343
+ editorHistory.entries.push(source);
344
+ if (editorHistory.entries.length > editorHistoryLimit) editorHistory.entries.shift();
345
+ editorHistory.index = editorHistory.entries.length - 1;
346
+ };
347
+ const moveEditorHistory = (offset) => {
348
+ const nextIndex = editorHistory.index + offset;
349
+ if (nextIndex < 0 || nextIndex >= editorHistory.entries.length) return;
350
+ editorHistory.index = nextIndex;
351
+ setEditorValue(editorHistory.entries[nextIndex], { recordHistory: false });
352
+ };
353
+ const handleEditorKeydown = (event) => {
354
+ if (!(event.ctrlKey || event.metaKey) || event.altKey) return;
355
+ const key = event.key.toLowerCase();
356
+ if (key === 'z') {
357
+ event.preventDefault();
358
+ event.stopPropagation();
359
+ moveEditorHistory(event.shiftKey ? 1 : -1);
360
+ } else if (key === 'y') {
361
+ event.preventDefault();
362
+ event.stopPropagation();
363
+ moveEditorHistory(1);
364
+ }
365
+ };
366
+
367
+ undoAction = createActionButton('fas fa-undo', 'Desfazer alteração', 'Desfazer alteração', () =>
368
+ moveEditorHistory(-1),
369
+ );
370
+ redoAction = createActionButton('fas fa-redo', 'Refazer alteração', 'Refazer alteração', () => moveEditorHistory(1));
371
+ diffAction = createActionButton('fas fa-columns', 'Comparar alterações', 'Comparar alterações', () => {
372
+ diffPanel.hidden = !diffPanel.hidden;
373
+ });
374
+ undoAction.button.setAttribute('aria-keyshortcuts', 'Control+Z Meta+Z');
375
+ redoAction.button.setAttribute('aria-keyshortcuts', 'Control+Y Meta+Y Control+Shift+Z Meta+Shift+Z');
376
+ updateHistoryActions();
377
+ diffAction.button.disabled = true;
378
+
379
+ const presetSelect = document.createElement('br-select');
380
+ presetSelect.className = 'wbc-example-preset';
381
+ presetSelect.id = `${controlsScope}-preset`;
382
+ presetSelect.setAttribute('density', 'small');
383
+ presetSelect.setAttribute('inline', '');
384
+ presetSelect.setAttribute('label', 'Preset');
385
+ const initialPreset =
386
+ presets.find(({ id, source }) => id === activeDraft?.presetId && Boolean(source)) ??
387
+ presets.find(({ id, source }) => id === defaultPreset && Boolean(source)) ??
388
+ presets.find(({ source }) => Boolean(source));
389
+ const initialPresetId = initialPreset?.id || '';
390
+ const baseScriptUrl = getPresetScriptUrl(path, baseScript);
391
+ let activePresetScriptUrl = getPresetScriptUrl(path, initialPreset?.script);
392
+ presetOptions.forEach(({ id, label, source }) => {
393
+ const option = document.createElement('br-select-option');
394
+ option.value = id;
395
+ option.setAttribute('label', label);
396
+ option.textContent = label;
397
+ if (id === initialPresetId) option.setAttribute('selected', '');
398
+ if (id && !source) option.setAttribute('disabled', '');
399
+ presetSelect.appendChild(option);
400
+ });
401
+ presetSelect.value = initialPresetId;
402
+ let isApplyingPresetFromUrl = false;
403
+ let title;
404
+ const updateExampleLabel = (presetId = presetSelect.value) => {
405
+ const selectedPreset = presetId ? presetOptions.find(({ id }) => id === presetId) : null;
406
+ if (title) title.textContent = selectedPreset?.label || exampleLabel || file;
407
+ };
408
+ if (initialPreset?.source) comparisonBaseline = initialPreset.source;
409
+ presetSelect.addEventListener('change', () => {
410
+ const selectedPreset = presetOptions.find(({ id }) => id === presetSelect.value);
411
+ updateExampleLabel(selectedPreset?.id);
412
+ if (selectedPreset?.source) {
413
+ controlsCssSource = '';
414
+ controlsApi?.reset?.();
415
+ activePresetScriptUrl = getPresetScriptUrl(path, selectedPreset.script);
416
+ if (!isApplyingPresetFromUrl) updatePresetUrl(file, selectedPreset.id);
417
+ comparisonBaseline = selectedPreset.source;
418
+ setEditorValue(selectedPreset.source);
419
+ updateDiff(getEditorValue());
420
+ }
421
+ });
422
+ contentDiv._applyPresetFromUrl = (presetId) => {
423
+ const selectedPreset =
424
+ presetOptions.find(({ id, source }) => id === presetId && source) ||
425
+ presetOptions.find(({ id, source }) => id === contentDiv.dataset.defaultPreset && source) ||
426
+ presetOptions.find(({ source }) => source);
427
+ if (!selectedPreset || presetSelect.value === selectedPreset.id) {
428
+ updateExampleLabel(selectedPreset?.id);
429
+ return;
430
+ }
431
+
432
+ isApplyingPresetFromUrl = true;
433
+ presetSelect.value = selectedPreset.id;
434
+ presetSelect.dispatchEvent(new Event('change'));
435
+ isApplyingPresetFromUrl = false;
436
+ };
437
+ const hasPresets = presets.length > 0;
438
+ presetSelect.hidden = !hasPresets;
508
439
 
509
440
  // 1. Copy Action
510
- const copyAction = createActionButton('fas fa-copy', 'Copiar código', 'Copiar código', async () => {
511
- try {
512
- if (navigator.clipboard?.writeText) {
513
- await navigator.clipboard.writeText(getEditorValue());
514
- } else {
515
- const fallback = document.createElement('textarea');
516
- fallback.value = getEditorValue();
517
- fallback.setAttribute('readonly', '');
518
- fallback.style.position = 'fixed';
519
- fallback.style.opacity = '0';
520
- document.body.appendChild(fallback);
521
- fallback.select();
522
- document.execCommand('copy');
523
- fallback.remove();
441
+ const getCopyText = (target) => {
442
+ const source = getEditorValue();
443
+ if (target === 'vanilla') {
444
+ vanillaSources.html = source;
445
+ return `<!-- index.html -->\n${vanillaSources.html}\n\n/* index.css */\n${vanillaSources.css}\n\n// index.js\n${vanillaSources.javascript}`;
446
+ }
447
+ const files = getFrameworkFiles(source, target);
448
+ if (files?.length) {
449
+ return files
450
+ .map(
451
+ (file) => `${file.language === 'html' ? `<!-- ${file.filename} -->` : `// ${file.filename}`}\n${file.code}`,
452
+ )
453
+ .join('\n\n');
454
+ }
455
+ return getFrameworkCode(source, target);
456
+ };
457
+ const copyText = async (target) => {
458
+ const value = getCopyText(target);
459
+ if (navigator.clipboard?.writeText) {
460
+ await navigator.clipboard.writeText(value);
461
+ } else {
462
+ const fallback = document.createElement('textarea');
463
+ fallback.value = value;
464
+ fallback.setAttribute('readonly', '');
465
+ fallback.className = 'wbc-copy-fallback';
466
+ document.body.appendChild(fallback);
467
+ fallback.select();
468
+ document.execCommand('copy');
469
+ fallback.remove();
470
+ }
471
+ };
472
+ const copyMenu = document.createElement('div');
473
+ copyMenu.className = 'wbc-copy-menu';
474
+ copyMenu.setAttribute('role', 'menu');
475
+ copyMenu.setAttribute('aria-label', 'Formato para copiar');
476
+ copyMenu.hidden = true;
477
+ const copyOptions = [
478
+ ['vanilla', 'HTML/CSS/JS'],
479
+ ['angular', 'Angular'],
480
+ ['react', 'React'],
481
+ ['vue', 'Vue'],
482
+ ];
483
+ let copyAction;
484
+ copyAction = createActionButton('fas fa-copy', 'Escolher formato para copiar', 'Copiar código', () => {
485
+ copyMenu.hidden = !copyMenu.hidden;
486
+ copyAction.button.setAttribute('aria-haspopup', 'menu');
487
+ copyAction.button.setAttribute('aria-expanded', String(!copyMenu.hidden));
488
+ });
489
+ copyAction.button.setAttribute('aria-haspopup', 'menu');
490
+ copyAction.button.setAttribute('aria-expanded', 'false');
491
+ copyOptions.forEach(([target, label]) => {
492
+ const option = document.createElement('button');
493
+ option.type = 'button';
494
+ option.setAttribute('role', 'menuitem');
495
+ option.textContent = label;
496
+ option.addEventListener('click', async () => {
497
+ try {
498
+ await copyText(target);
499
+ copyAction.icon.className = 'fas fa-check text-success';
500
+ copyAction.tooltipContent.textContent = 'Copiado!';
501
+ } catch {
502
+ copyAction.tooltipContent.textContent = 'Erro ao copiar';
524
503
  }
525
- copyAction.icon.className = 'fas fa-check text-success';
526
- copyAction.tooltipContent.textContent = 'Copiado!';
527
- } catch {
528
- copyAction.tooltipContent.textContent = 'Erro ao copiar';
504
+ copyMenu.hidden = true;
505
+ copyAction.button.setAttribute('aria-expanded', 'false');
506
+ setTimeout(() => {
507
+ copyAction.icon.className = 'fas fa-copy';
508
+ copyAction.tooltipContent.textContent = 'Escolher formato para copiar';
509
+ }, 2000);
510
+ });
511
+ copyMenu.appendChild(option);
512
+ });
513
+ const copyMenuContainer = document.createElement('div');
514
+ copyMenuContainer.className = 'wbc-copy-menu-container';
515
+ copyMenuContainer.append(copyAction.tooltip, copyMenu);
516
+ copyMenuContainer.addEventListener('keydown', (event) => {
517
+ if (event.key === 'Escape') {
518
+ copyMenu.hidden = true;
519
+ copyAction.button.setAttribute('aria-expanded', 'false');
529
520
  }
530
- setTimeout(() => {
531
- copyAction.icon.className = 'fas fa-copy';
532
- copyAction.tooltipContent.textContent = 'Copiar código';
533
- }, 2000);
534
521
  });
535
522
 
536
- // 2. Share Action
523
+ const setPreviewReducedMotion = (value) => {
524
+ reducedMotionEnabled = Boolean(value);
525
+ contentDiv.setAttribute('data-wbc-reduced-motion', String(reducedMotionEnabled));
526
+ reducedMotionAction.button.setAttribute('aria-pressed', String(reducedMotionEnabled));
527
+ reducedMotionAction.button.classList.toggle('wbc-reduced-motion-action--active', reducedMotionEnabled);
528
+ reducedMotionAction.tooltipContent.textContent = reducedMotionEnabled
529
+ ? 'Desativar movimento reduzido'
530
+ : 'Ativar movimento reduzido';
531
+ if (previewFrame?.contentWindow) {
532
+ previewFrame.contentWindow.postMessage(
533
+ {
534
+ // biome-ignore lint/style/useNamingConvention: nome reservado do protocolo interno de postMessage.
535
+ __playgroundMode: 'reduced-motion',
536
+ value: reducedMotionEnabled,
537
+ // biome-ignore lint/style/useNamingConvention: nome reservado do protocolo interno de postMessage.
538
+ __playgroundChannelId: previewChannelId,
539
+ },
540
+ '*',
541
+ );
542
+ }
543
+ };
544
+ const reducedMotionAction = createActionButton(
545
+ 'fas fa-running',
546
+ reducedMotionEnabled ? 'Desativar movimento reduzido' : 'Ativar movimento reduzido',
547
+ reducedMotionEnabled ? 'Desativar movimento reduzido' : 'Ativar movimento reduzido',
548
+ () => setPreviewReducedMotion(!reducedMotionEnabled),
549
+ );
550
+ reducedMotionAction.button.classList.add('wbc-reduced-motion-action');
551
+ reducedMotionAction.button.classList.toggle('wbc-reduced-motion-action--active', reducedMotionEnabled);
552
+ reducedMotionAction.button.setAttribute('aria-pressed', String(reducedMotionEnabled));
553
+
554
+ const setPreviewTheme = (dark) => {
555
+ darkThemeEnabled = Boolean(dark);
556
+ preview.style.background = darkThemeEnabled ? '#071d41' : '#fff';
557
+ themeAction.button.setAttribute('aria-pressed', String(darkThemeEnabled));
558
+ themeAction.button.classList.toggle('wbc-theme-action--active', darkThemeEnabled);
559
+ themeAction.tooltipContent.textContent = darkThemeEnabled ? 'Usar fundo claro' : 'Usar fundo escuro';
560
+ previewFrame?.contentWindow?.postMessage(
561
+ {
562
+ // biome-ignore lint/style/useNamingConvention: nome reservado do protocolo interno de postMessage.
563
+ __playgroundMode: 'dark',
564
+ value: darkThemeEnabled,
565
+ // biome-ignore lint/style/useNamingConvention: nome reservado do protocolo interno de postMessage.
566
+ __playgroundChannelId: previewChannelId,
567
+ },
568
+ '*',
569
+ );
570
+ };
571
+ const themeAction = createActionButton('fas fa-adjust', 'Usar fundo escuro', 'Mudar fundo', () =>
572
+ setPreviewTheme(!darkThemeEnabled),
573
+ );
574
+ themeAction.button.classList.add('wbc-theme-action');
575
+ themeAction.button.setAttribute('aria-pressed', 'false');
576
+
577
+ const getPreviewFrameSize = () => {
578
+ const frameRect = previewFrame?.getBoundingClientRect();
579
+ const viewportRect = previewViewport.getBoundingClientRect();
580
+ return {
581
+ width: Math.round(viewportRect.width || frameRect?.width || preview.clientWidth || DEV_PREVIEW_MIN_WIDTH),
582
+ height: Math.round(frameRect?.height || viewportRect.height || preview.clientHeight || DEV_PREVIEW_MIN_HEIGHT),
583
+ };
584
+ };
585
+
586
+ const getMaxPreviewWidth = () =>
587
+ Math.max(DEV_PREVIEW_MIN_WIDTH, Math.round(preview.clientWidth || preview.getBoundingClientRect().width));
588
+
589
+ const getMaxPreviewHeight = () => Math.max(DEV_PREVIEW_MIN_HEIGHT, Math.round(window.innerHeight * 0.75));
590
+
591
+ const updatePreviewResizeA11y = () => {
592
+ const { width, height } = getPreviewFrameSize();
593
+ previewWidthResizeHandle.setAttribute('aria-valuemin', String(DEV_PREVIEW_MIN_WIDTH));
594
+ previewWidthResizeHandle.setAttribute('aria-valuemax', String(Math.max(width, getMaxPreviewWidth())));
595
+ previewWidthResizeHandle.setAttribute('aria-valuenow', String(width));
596
+ previewHeightResizeHandle.setAttribute('aria-valuemin', String(DEV_PREVIEW_MIN_HEIGHT));
597
+ previewHeightResizeHandle.setAttribute('aria-valuemax', String(Math.max(height, getMaxPreviewHeight())));
598
+ previewHeightResizeHandle.setAttribute('aria-valuenow', String(height));
599
+ };
600
+
601
+ const updatePreviewWidth = (width, maximumWidth = getMaxPreviewWidth()) => {
602
+ if (!previewFrame) return;
603
+ const currentWidth = getPreviewFrameSize().width;
604
+ const maxWidth = Math.max(currentWidth, maximumWidth);
605
+ const nextWidth = Math.min(Math.max(Math.round(width), DEV_PREVIEW_MIN_WIDTH), maxWidth);
606
+ previewViewport.style.width = `${nextWidth}px`;
607
+ previewViewport.style.maxWidth = 'none';
608
+ updatePreviewResizeA11y();
609
+ };
610
+
611
+ const updatePreviewHeight = (height) => {
612
+ if (!previewFrame) return;
613
+ const currentHeight = getPreviewFrameSize().height;
614
+ const maxHeight = Math.max(currentHeight, getMaxPreviewHeight());
615
+ const nextHeight = Math.min(Math.max(Math.round(height), DEV_PREVIEW_MIN_HEIGHT), maxHeight);
616
+ previewFrame.style.height = `${nextHeight}px`;
617
+ previewFrame.style.maxHeight = 'none';
618
+ hasManualPreviewHeight = true;
619
+ updatePreviewResizeA11y();
620
+ };
621
+
622
+ const stopPreviewResize = () => {
623
+ previewResizeState = null;
624
+ preview.classList.remove('is-resizing');
625
+ previewWidthResizeHandle.classList.remove('is-active');
626
+ previewHeightResizeHandle.classList.remove('is-active');
627
+ window.removeEventListener('mousemove', handlePreviewResizeMove);
628
+ window.removeEventListener('mouseup', stopPreviewResize);
629
+ };
630
+
631
+ const handlePreviewResizeMove = (event) => {
632
+ if (previewResizeState?.axis === 'vertical') {
633
+ updatePreviewWidth(
634
+ previewResizeState.width + event.clientX - previewResizeState.clientX,
635
+ previewResizeState.maximumWidth,
636
+ );
637
+ } else if (previewResizeState?.axis === 'horizontal') {
638
+ updatePreviewHeight(previewResizeState.height + event.clientY - previewResizeState.clientY);
639
+ }
640
+ };
641
+
642
+ const startPreviewResize = (axis, event) => {
643
+ event.preventDefault();
644
+ event.stopPropagation();
645
+ stopPreviewResize();
646
+ const { width, height } = getPreviewFrameSize();
647
+ const previewRect = preview.getBoundingClientRect();
648
+ const viewportRect = previewViewport.getBoundingClientRect();
649
+ const viewportLeft = Math.max(0, Math.round(viewportRect.left - previewRect.left + preview.scrollLeft));
650
+ const maximumWidth = Math.max(DEV_PREVIEW_MIN_WIDTH, preview.clientWidth - viewportLeft);
651
+ previewResizeState = { axis, clientX: event.clientX, clientY: event.clientY, width, height, maximumWidth };
652
+ if (axis === 'vertical') {
653
+ previewViewport.style.margin = '0';
654
+ previewViewport.style.marginLeft = `${viewportLeft}px`;
655
+ }
656
+ preview.classList.add('is-resizing');
657
+ (axis === 'vertical' ? previewWidthResizeHandle : previewHeightResizeHandle).classList.add('is-active');
658
+ window.addEventListener('mousemove', handlePreviewResizeMove);
659
+ window.addEventListener('mouseup', stopPreviewResize);
660
+ };
661
+
662
+ const handlePreviewResizeKeydown = (axis, event) => {
663
+ const { width, height } = getPreviewFrameSize();
664
+
665
+ if (axis === 'vertical') {
666
+ const delta = getPreviewResizeDelta(event.key, 'ArrowLeft', 'ArrowRight');
667
+ if (!delta) return;
668
+ event.preventDefault();
669
+ updatePreviewWidth(width + delta);
670
+ return;
671
+ }
672
+
673
+ const delta = getPreviewResizeDelta(event.key, 'ArrowUp', 'ArrowDown');
674
+ if (delta) {
675
+ event.preventDefault();
676
+ updatePreviewHeight(height + delta);
677
+ }
678
+ };
679
+
680
+ previewWidthResizeHandle.addEventListener('mousedown', (event) => startPreviewResize('vertical', event));
681
+ previewWidthResizeHandle.addEventListener('keydown', (event) => handlePreviewResizeKeydown('vertical', event));
682
+ previewHeightResizeHandle.addEventListener('mousedown', (event) => startPreviewResize('horizontal', event));
683
+ previewHeightResizeHandle.addEventListener('keydown', (event) => handlePreviewResizeKeydown('horizontal', event));
684
+ window.addEventListener('resize', updatePreviewResizeA11y, { signal: exampleAbortController.signal });
685
+ exampleAbortController.signal.addEventListener('abort', stopPreviewResize, { once: true });
686
+
687
+ const setViewport = (viewport) => {
688
+ activeViewport = viewport;
689
+ hasManualPreviewHeight = false;
690
+ stopPreviewResize();
691
+ const deviceMode = viewport.mode ?? 'web';
692
+ previewViewport.classList.toggle('wbc-example-preview-viewport--device', deviceMode !== 'web');
693
+ previewViewport.classList.toggle('wbc-example-preview-viewport--ios', deviceMode === 'ios');
694
+ previewViewport.classList.toggle('wbc-example-preview-viewport--android', deviceMode === 'android');
695
+ if (!previewFrame) return;
696
+
697
+ if (!viewport.width) {
698
+ preview.classList.remove('wbc-example-preview--viewport');
699
+ preview.style.removeProperty('max-height');
700
+ preview.style.removeProperty('overflow');
701
+ previewFrame.style.removeProperty('width');
702
+ previewFrame.style.removeProperty('height');
703
+ previewFrame.style.removeProperty('max-height');
704
+ previewFrame.style.removeProperty('max-width');
705
+ previewFrame.style.removeProperty('margin');
706
+ previewViewport.style.removeProperty('width');
707
+ previewViewport.style.removeProperty('max-width');
708
+ previewViewport.style.removeProperty('margin');
709
+ previewViewport.style.removeProperty('margin-left');
710
+ updatePreviewResizeA11y();
711
+ return;
712
+ }
713
+
714
+ preview.classList.add('wbc-example-preview--viewport');
715
+ preview.style.maxHeight = '75vh';
716
+ preview.style.overflow = 'auto';
717
+ previewViewport.style.width = `${viewport.width}px`;
718
+ previewViewport.style.maxWidth = 'none';
719
+ previewViewport.style.removeProperty('margin-left');
720
+ previewViewport.style.margin = '0 auto';
721
+ previewFrame.style.width = '100%';
722
+ previewFrame.style.height = `${viewport.height}px`;
723
+ previewFrame.style.maxWidth = 'none';
724
+ previewFrame.style.maxHeight = 'none';
725
+ previewFrame.style.removeProperty('margin');
726
+ updatePreviewResizeA11y();
727
+ };
728
+ const viewportActions = DEV_VIEWPORTS.map((viewport) => {
729
+ const action = createActionButton(viewport.icon, viewport.label, viewport.label, () => {
730
+ setViewport(viewport);
731
+ viewportActions.forEach(({ viewport: item, action: itemAction }) => {
732
+ itemAction.button.classList.toggle('wbc-viewport-action--active', item.id === viewport.id);
733
+ });
734
+ });
735
+ action.viewport = viewport;
736
+ action.button.classList.add('wbc-viewport-action');
737
+ action.button.classList.toggle('wbc-viewport-action--active', viewport.id === activeViewport.id);
738
+ return { viewport, action };
739
+ });
740
+
741
+ let overflowShare;
742
+ const handleShare = async () => {
743
+ try {
744
+ await loadLzString();
745
+ } catch {
746
+ alert('Biblioteca de compartilhamento não carregada.');
747
+ return;
748
+ }
749
+ const state = {
750
+ p: path,
751
+ f: file,
752
+ h: getEditorValue(),
753
+ // Mantém a associação do código compartilhado ao preset para links legados e edição posterior.
754
+ presetId: presetSelect.value || undefined,
755
+ };
756
+ try {
757
+ const json = JSON.stringify(state);
758
+ const encoded = window.LZString.compressToEncodedURIComponent(json);
759
+ const url = new URL(window.location.href);
760
+ url.searchParams.set('pg_state', encoded);
761
+ url.hash = getExampleHash(file, presetSelect.value || undefined);
762
+
763
+ await navigator.clipboard.writeText(url.toString());
764
+
765
+ shareAction.icon.className = 'fas fa-check text-success';
766
+ shareAction.tooltipContent.textContent = 'Link copiado!';
767
+ if (overflowShare) {
768
+ overflowShare.iconEl.className = 'fas fa-check text-success';
769
+ overflowShare.textEl.textContent = 'Link copiado!';
770
+ }
771
+ setTimeout(() => {
772
+ shareAction.icon.className = 'fas fa-share-alt';
773
+ shareAction.tooltipContent.textContent = 'Compartilhar exemplo';
774
+ if (overflowShare) {
775
+ overflowShare.iconEl.className = 'fas fa-share-alt';
776
+ overflowShare.textEl.textContent = 'Compartilhar exemplo';
777
+ }
778
+ }, 2000);
779
+ } catch (err) {
780
+ console.error(err);
781
+ shareAction.tooltipContent.textContent = 'Erro ao compartilhar';
782
+ if (overflowShare) overflowShare.textEl.textContent = 'Erro ao compartilhar';
783
+ setTimeout(() => {
784
+ shareAction.icon.className = 'fas fa-share-alt';
785
+ shareAction.tooltipContent.textContent = 'Compartilhar exemplo';
786
+ if (overflowShare) {
787
+ overflowShare.iconEl.className = 'fas fa-share-alt';
788
+ overflowShare.textEl.textContent = 'Compartilhar exemplo';
789
+ }
790
+ }, 2000);
791
+ }
792
+ };
793
+
537
794
  const shareAction = createActionButton(
538
795
  'fas fa-share-alt',
539
796
  'Compartilhar exemplo',
540
797
  'Compartilhar exemplo',
541
- async () => {
542
- try {
543
- await loadLzString();
544
- } catch {
545
- alert('Biblioteca de compartilhamento não carregada.');
546
- return;
547
- }
548
- const state = {
549
- p: path,
550
- f: file,
551
- h: getEditorValue(),
552
- };
553
- try {
554
- const json = JSON.stringify(state);
555
- const encoded = window.LZString.compressToEncodedURIComponent(json);
556
- const url = new URL(window.location.href);
557
- url.searchParams.set('pg_state', encoded);
558
- url.hash = getExampleHash(file);
559
-
560
- await navigator.clipboard.writeText(url.toString());
561
-
562
- shareAction.icon.className = 'fas fa-check text-success';
563
- shareAction.tooltipContent.textContent = 'Link copiado!';
564
- setTimeout(() => {
565
- shareAction.icon.className = 'fas fa-share-alt';
566
- shareAction.tooltipContent.textContent = 'Compartilhar exemplo';
567
- }, 2000);
568
- } catch (err) {
569
- console.error(err);
570
- shareAction.tooltipContent.textContent = 'Erro ao compartilhar';
571
- setTimeout(() => {
572
- shareAction.icon.className = 'fas fa-share-alt';
573
- shareAction.tooltipContent.textContent = 'Compartilhar exemplo';
574
- }, 2000);
575
- }
576
- },
798
+ handleShare,
577
799
  );
578
800
 
579
801
  // 3. Fullscreen Action
802
+ let isClosingFullscreen = false;
803
+ const closeFullscreen = () => {
804
+ if (!contentDiv.classList.contains('is-fullscreen') || isClosingFullscreen) return;
805
+ isClosingFullscreen = true;
806
+ contentDiv.classList.add('is-fullscreen-exiting');
807
+ setTimeout(() => {
808
+ contentDiv.classList.remove('is-fullscreen');
809
+ contentDiv.classList.remove('is-fullscreen-exiting');
810
+ isClosingFullscreen = false;
811
+ fsAction.icon.className = 'fas fa-expand-arrows-alt';
812
+ fsAction.tooltipContent.textContent = 'Tela cheia';
813
+ fsAction.button.focus();
814
+ }, 200);
815
+ };
816
+
580
817
  const fsAction = createActionButton('fas fa-expand-arrows-alt', 'Tela cheia', 'Tela cheia', () => {
581
- const isFullscreen = contentDiv.classList.toggle('is-fullscreen');
582
- if (isFullscreen) {
818
+ if (contentDiv.classList.contains('is-fullscreen')) {
819
+ closeFullscreen();
820
+ } else {
821
+ contentDiv.classList.add('is-fullscreen');
583
822
  fsAction.icon.className = 'fas fa-compress-arrows-alt';
584
823
  fsAction.tooltipContent.textContent = 'Fechar tela cheia';
585
824
  requestAnimationFrame(() => editorApi?.refresh?.());
586
- } else {
587
- fsAction.icon.className = 'fas fa-expand-arrows-alt';
588
- fsAction.tooltipContent.textContent = 'Tela cheia';
589
825
  }
590
826
  });
827
+ document.addEventListener(
828
+ 'keydown',
829
+ (event) => {
830
+ if (event.key !== 'Escape' || !contentDiv.classList.contains('is-fullscreen')) return;
831
+ event.preventDefault();
832
+ closeFullscreen();
833
+ },
834
+ { signal: exampleAbortController.signal },
835
+ );
591
836
 
592
837
  // --- EXAMPLE CARD HEADER ---
593
838
  const header = document.createElement('div');
594
839
  header.className = 'wbc-example-header';
595
840
 
596
- const title = document.createElement('h3');
597
- title.textContent = file;
841
+ title = document.createElement('h3');
842
+ updateExampleLabel();
598
843
  header.appendChild(title);
599
844
 
600
- // Group all actions and toggle on the right
845
+ // Group actions: expanded toolbar vs compact dropdown
601
846
  const headerActions = document.createElement('div');
602
847
  headerActions.className = 'wbc-example-header-actions';
603
848
 
604
- const exampleToggleTooltip = document.createElement('br-tooltip');
605
- exampleToggleTooltip.setAttribute('position', 'bottom');
849
+ const expandedActions = document.createElement('div');
850
+ expandedActions.className = 'wbc-example-header-actions-expanded';
851
+ expandedActions.append(
852
+ undoAction.tooltip,
853
+ redoAction.tooltip,
854
+ diffAction.tooltip,
855
+ ...viewportActions.map(({ action }) => action.tooltip),
856
+ copyMenuContainer,
857
+ reducedMotionAction.tooltip,
858
+ shareAction.tooltip,
859
+ themeAction.tooltip,
860
+ );
861
+
862
+ // Overflow container for compact toolbar
863
+ const overflowContainer = document.createElement('div');
864
+ overflowContainer.className = 'wbc-toolbar-overflow-container';
606
865
 
607
- const exampleToggle = document.createElement('br-button');
608
- exampleToggle.className = 'wbc-example-toggle';
609
- exampleToggle.setAttribute('density', 'small');
610
- exampleToggle.setAttribute('emphasis', 'secondary');
611
- exampleToggle.setAttribute('shape', 'circle');
612
- exampleToggle.setAttribute('aria-label', isExpanded ? 'Recolher exemplo' : 'Expandir exemplo');
613
- exampleToggle.setAttribute('slot', 'trigger');
866
+ const overflowMenu = document.createElement('div');
867
+ overflowMenu.className = 'wbc-toolbar-overflow-menu';
868
+ overflowMenu.setAttribute('role', 'menu');
869
+ overflowMenu.setAttribute('aria-label', 'Mais opções');
870
+ overflowMenu.hidden = true;
614
871
 
615
- const exampleIcon = document.createElement('i');
616
- exampleIcon.className = `fas fa-chevron-${isExpanded ? 'up' : 'down'}`;
617
- exampleToggle.appendChild(exampleIcon);
872
+ const closeOverflow = () => {
873
+ overflowMenu.hidden = true;
874
+ overflowAction.button.setAttribute('aria-expanded', 'false');
875
+ overflowAction.button.classList.remove('wbc-toolbar-overflow-action--active');
876
+ };
618
877
 
619
- const exampleToggleTooltipContent = document.createElement('div');
620
- exampleToggleTooltipContent.setAttribute('slot', 'content');
621
- exampleToggleTooltipContent.setAttribute('position', 'bottom');
622
- exampleToggleTooltipContent.textContent = isExpanded ? 'Recolher exemplo' : 'Expandir exemplo';
878
+ const createOverflowItem = ({ icon, label, onClick, isCheckbox = false }) => {
879
+ const item = document.createElement('button');
880
+ item.type = 'button';
881
+ item.className = 'wbc-toolbar-overflow-menu-item';
882
+ item.setAttribute('role', isCheckbox ? 'menuitemcheckbox' : 'menuitem');
623
883
 
624
- exampleToggleTooltip.append(exampleToggle, exampleToggleTooltipContent);
884
+ const iconEl = document.createElement('i');
885
+ iconEl.className = icon;
886
+ iconEl.setAttribute('aria-hidden', 'true');
625
887
 
626
- header.setAttribute('slot', 'trigger');
627
- header.addEventListener('click', (event) => {
628
- if (event.target.closest('.wbc-example-header-actions') && !event.target.closest('.wbc-example-toggle')) {
629
- event.stopPropagation();
888
+ const textEl = document.createElement('span');
889
+ textEl.textContent = label;
890
+
891
+ item.append(iconEl, textEl);
892
+ item.addEventListener('click', (event) => {
893
+ onClick(event);
894
+ closeOverflow();
895
+ });
896
+ return { item, iconEl, textEl };
897
+ };
898
+
899
+ overflowUndo = createOverflowItem({
900
+ icon: 'fas fa-undo',
901
+ label: 'Desfazer alteração',
902
+ onClick: () => moveEditorHistory(-1),
903
+ });
904
+
905
+ overflowRedo = createOverflowItem({
906
+ icon: 'fas fa-redo',
907
+ label: 'Refazer alteração',
908
+ onClick: () => moveEditorHistory(1),
909
+ });
910
+
911
+ overflowDiff = createOverflowItem({
912
+ icon: 'fas fa-columns',
913
+ label: 'Comparar alterações',
914
+ onClick: () => {
915
+ diffPanel.hidden = !diffPanel.hidden;
916
+ },
917
+ });
918
+
919
+ const overflowCopy = createOverflowItem({
920
+ icon: 'fas fa-copy',
921
+ label: 'Copiar código',
922
+ onClick: async () => {
923
+ await copyText('vanilla');
924
+ },
925
+ });
926
+
927
+ const overflowViewports = DEV_VIEWPORTS.map((viewport) =>
928
+ createOverflowItem({
929
+ icon: viewport.icon,
930
+ label: viewport.label,
931
+ onClick: () => {
932
+ setViewport(viewport);
933
+ viewportActions.forEach(({ viewport: item, action: itemAction }) => {
934
+ itemAction.button.classList.toggle('wbc-viewport-action--active', item.id === viewport.id);
935
+ });
936
+ },
937
+ }),
938
+ );
939
+
940
+ const overflowReducedMotion = createOverflowItem({
941
+ icon: 'fas fa-running',
942
+ label: `Movimento reduzido (${reducedMotionEnabled ? 'Ativo' : 'Inativo'})`,
943
+ isCheckbox: true,
944
+ onClick: () => setPreviewReducedMotion(!reducedMotionEnabled),
945
+ });
946
+
947
+ overflowShare = createOverflowItem({
948
+ icon: 'fas fa-share-alt',
949
+ label: 'Compartilhar exemplo',
950
+ onClick: () => handleShare(),
951
+ });
952
+
953
+ const overflowTheme = createOverflowItem({
954
+ icon: 'fas fa-adjust',
955
+ label: `Alternar fundo (${darkThemeEnabled ? 'Escuro' : 'Claro'})`,
956
+ onClick: () => setPreviewTheme(!darkThemeEnabled),
957
+ });
958
+
959
+ const updateOverflowMenu = () => {
960
+ overflowUndo.item.disabled = undoAction.button.disabled;
961
+ overflowRedo.item.disabled = redoAction.button.disabled;
962
+ overflowDiff.item.disabled = diffAction.button.disabled;
963
+ DEV_VIEWPORTS.forEach((viewport, index) => {
964
+ overflowViewports[index].item.classList.toggle('is-active', viewport.id === activeViewport.id);
965
+ });
966
+ overflowReducedMotion.item.classList.toggle('is-active', reducedMotionEnabled);
967
+ overflowReducedMotion.item.setAttribute('aria-checked', String(reducedMotionEnabled));
968
+ overflowReducedMotion.textEl.textContent = `Movimento reduzido (${reducedMotionEnabled ? 'Ativo' : 'Inativo'})`;
969
+ overflowTheme.item.classList.toggle('is-active', darkThemeEnabled);
970
+ overflowTheme.textEl.textContent = `Alternar fundo (${darkThemeEnabled ? 'Escuro' : 'Claro'})`;
971
+ };
972
+
973
+ overflowMenu.append(
974
+ overflowUndo.item,
975
+ overflowRedo.item,
976
+ overflowDiff.item,
977
+ overflowCopy.item,
978
+ ...overflowViewports.map(({ item }) => item),
979
+ overflowReducedMotion.item,
980
+ overflowShare.item,
981
+ overflowTheme.item,
982
+ );
983
+
984
+ const overflowAction = createActionButton('fas fa-ellipsis-v', 'Mais opções', 'Mais opções', () => {
985
+ const isHidden = !overflowMenu.hidden;
986
+ if (isHidden) {
987
+ closeOverflow();
988
+ } else {
989
+ updateOverflowMenu();
990
+ overflowMenu.hidden = false;
991
+ overflowAction.button.setAttribute('aria-expanded', 'true');
992
+ overflowAction.button.classList.add('wbc-toolbar-overflow-action--active');
630
993
  }
631
994
  });
995
+ overflowAction.button.classList.add('wbc-toolbar-overflow-action');
996
+ overflowAction.button.setAttribute('aria-haspopup', 'menu');
997
+ overflowAction.button.setAttribute('aria-expanded', 'false');
632
998
 
633
- const updateExampleToggle = (open) => {
634
- exampleIcon.className = `fas fa-chevron-${open ? 'up' : 'down'}`;
635
- exampleToggle.setAttribute('aria-label', open ? 'Recolher exemplo' : 'Expandir exemplo');
636
- exampleToggleTooltipContent.textContent = open ? 'Recolher exemplo' : 'Expandir exemplo';
637
- if (open) requestAnimationFrame(() => editorApi?.refresh?.());
638
- };
639
-
640
- dropdown.addEventListener('brDropdownOpenChange', (event) => {
641
- const open = event.detail.open;
642
- updateExampleToggle(open);
643
- if (open) {
644
- if (!isInitialized) {
645
- dropdown.append(preview, fullscreenBottomPanel);
646
- initializeExample?.();
647
- isInitialized = true;
648
- }
649
- onOpen?.(file, contentDiv);
650
- } else if (window.location.hash === getExampleHash(file)) {
651
- window.history.replaceState({}, '', `${window.location.pathname}${window.location.search}`);
999
+ overflowContainer.append(overflowAction.tooltip, overflowMenu);
1000
+
1001
+ const handleOverflowOutsideClick = (event) => {
1002
+ if (!overflowContainer.contains(event.target)) {
1003
+ closeOverflow();
1004
+ }
1005
+ };
1006
+ document.addEventListener('click', handleOverflowOutsideClick);
1007
+ exampleAbortController.signal.addEventListener(
1008
+ 'abort',
1009
+ () => {
1010
+ document.removeEventListener('click', handleOverflowOutsideClick);
1011
+ },
1012
+ { once: true },
1013
+ );
1014
+
1015
+ overflowContainer.addEventListener('keydown', (event) => {
1016
+ if (event.key === 'Escape') {
1017
+ closeOverflow();
1018
+ overflowAction.button.focus();
652
1019
  }
653
1020
  });
654
1021
 
655
- headerActions.append(copyAction.tooltip, shareAction.tooltip, fsAction.tooltip, exampleToggleTooltip);
1022
+ const collapsedActions = document.createElement('div');
1023
+ collapsedActions.className = 'wbc-example-header-actions-collapsed';
1024
+ collapsedActions.append(overflowContainer);
1025
+
1026
+ headerActions.append(presetSelect, expandedActions, collapsedActions, fsAction.tooltip);
656
1027
  header.appendChild(headerActions);
657
1028
 
1029
+ const updateToolbarLayout = () => {
1030
+ const isCompact = header.clientWidth > 0 && header.clientWidth < 840;
1031
+ header.classList.toggle('is-compact-toolbar', isCompact);
1032
+ };
1033
+ const headerResizeObserver = new ResizeObserver(updateToolbarLayout);
1034
+ headerResizeObserver.observe(header);
1035
+ exampleAbortController.signal.addEventListener('abort', () => headerResizeObserver.disconnect(), { once: true });
1036
+
658
1037
  const editorWrapper = document.createElement('div');
659
1038
  editorWrapper.className = 'wbc-example-editor-wrapper';
1039
+ editorWrapper.addEventListener('keydown', handleEditorKeydown, true);
1040
+
1041
+ const diffPanel = document.createElement('section');
1042
+ diffPanel.className = 'wbc-example-diff';
1043
+ diffPanel.hidden = true;
1044
+ diffPanel.setAttribute('aria-label', 'Diff das alterações do exemplo');
1045
+ const diffTitle = document.createElement('h4');
1046
+ diffTitle.className = 'wbc-example-diff__title';
1047
+ diffTitle.textContent = 'Alterações (formatação ignorada)';
1048
+ const diffCode = document.createElement('pre');
1049
+ diffCode.className = 'wbc-example-diff__code';
1050
+ diffPanel.append(diffTitle, diffCode);
1051
+
1052
+ const renderDiff = (diff) => {
1053
+ const fragment = document.createDocumentFragment();
1054
+ diff.lines.forEach((line) => {
1055
+ const lineElement = document.createElement('span');
1056
+ lineElement.className = 'wbc-example-diff__line';
1057
+ if (line.startsWith('---') || line.startsWith('+++')) lineElement.classList.add('is-header');
1058
+ else if (line.startsWith('+')) lineElement.classList.add('is-added');
1059
+ else if (line.startsWith('-')) lineElement.classList.add('is-removed');
1060
+ else if (line.startsWith('@')) lineElement.classList.add('is-hunk');
1061
+ lineElement.textContent = line || ' ';
1062
+ fragment.appendChild(lineElement);
1063
+ });
1064
+ diffCode.replaceChildren(fragment);
1065
+ };
1066
+ const updateDiff = (source) => {
1067
+ const diff = window.WBCPlaygroundCore?.createUnifiedDiff(comparisonBaseline, source) || {
1068
+ changed: source !== comparisonBaseline,
1069
+ lines: source === comparisonBaseline ? [] : [`- ${comparisonBaseline}`, `+ ${source}`],
1070
+ };
1071
+ const hasChanges = diff.changed;
1072
+ diffAction.button.disabled = !hasChanges;
1073
+ if (overflowDiff) overflowDiff.item.disabled = !hasChanges;
1074
+ if (!hasChanges) diffPanel.hidden = true;
1075
+ renderDiff(diff);
1076
+ };
660
1077
 
661
1078
  const eventsWrapper = document.createElement('div');
662
1079
  eventsWrapper.className = 'wbc-example-events-wrapper';
@@ -666,34 +1083,57 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
666
1083
 
667
1084
  const filterContainer = document.createElement('div');
668
1085
  filterContainer.className = 'wbc-events-filter-container';
669
- filterContainer.style.display = 'flex';
670
- filterContainer.style.gap = '8px';
671
- filterContainer.style.alignItems = 'flex-end';
672
- filterContainer.style.marginBottom = '8px';
673
1086
 
674
1087
  const eventFilterInput = document.createElement('br-input');
1088
+ eventFilterInput.className = 'wbc-events-filter-input';
675
1089
  eventFilterInput.setAttribute('placeholder', 'Filtrar eventos...');
676
1090
  eventFilterInput.setAttribute('density', 'small');
677
- eventFilterInput.style.flex = '1';
1091
+ const eventKindFilter = document.createElement('select');
1092
+ eventKindFilter.className = 'wbc-event-kind-filter';
1093
+ eventKindFilter.setAttribute('aria-label', 'Tipo de evento');
1094
+ [
1095
+ ['all', 'Todos'],
1096
+ ['native', 'Nativos'],
1097
+ ['custom', 'Customizados'],
1098
+ ['component', 'Por componente'],
1099
+ ].forEach(([value, label]) => {
1100
+ eventKindFilter.add(new Option(label, value));
1101
+ });
678
1102
 
679
1103
  const copyEventsAction = createActionButton(
680
1104
  'fas fa-copy',
681
- 'Copiar lista de eventos',
682
- 'Copiar lista de eventos',
1105
+ 'Exportar eventos capturados',
1106
+ 'Exportar eventos capturados',
683
1107
  async () => {
684
- const visibleItems = Array.from(eventsList.querySelectorAll('li')).filter((li) => li.style.display !== 'none');
685
- const textToCopy = visibleItems
686
- .map((li) => {
687
- const name = li.querySelector('.wbc-event-console-event-name').textContent;
688
- const target = li.querySelector('.wbc-event-console-target').textContent;
689
- const payload = li.querySelector('.wbc-event-console-detail')?.textContent || '';
690
- return `${name}${target}${payload ? `\nPayload: ${payload}` : ''}`;
1108
+ const filter = String(eventFilterInput.value ?? '').toLowerCase();
1109
+ const kind = eventKindFilter.value;
1110
+ const textToCopy = eventEntries
1111
+ .filter((entry) => {
1112
+ const kindMatches =
1113
+ kind === 'all' ||
1114
+ (kind === 'native' && !entry.custom) ||
1115
+ (kind === 'custom' && entry.custom) ||
1116
+ (kind === 'component' && /br-[a-z0-9-]+/i.test(`${entry.target} ${entry.currentTarget || ''}`));
1117
+ return (
1118
+ kindMatches &&
1119
+ `${entry.eventType} ${entry.target} ${entry.currentTarget || ''}`.toLowerCase().includes(filter)
1120
+ );
691
1121
  })
1122
+ .map((entry) => serialize(entry))
692
1123
  .join('\n---\n');
693
1124
 
694
1125
  try {
695
1126
  if (navigator.clipboard?.writeText) {
696
1127
  await navigator.clipboard.writeText(textToCopy);
1128
+ } else {
1129
+ const fallback = document.createElement('textarea');
1130
+ fallback.value = textToCopy;
1131
+ fallback.setAttribute('readonly', '');
1132
+ fallback.className = 'wbc-copy-fallback';
1133
+ document.body.appendChild(fallback);
1134
+ fallback.select();
1135
+ document.execCommand('copy');
1136
+ fallback.remove();
697
1137
  }
698
1138
  copyEventsAction.icon.className = 'fas fa-check text-success';
699
1139
  copyEventsAction.tooltipContent.textContent = 'Copiado!';
@@ -702,28 +1142,28 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
702
1142
  }
703
1143
  setTimeout(() => {
704
1144
  copyEventsAction.icon.className = 'fas fa-copy';
705
- copyEventsAction.tooltipContent.textContent = 'Copiar lista de eventos';
1145
+ copyEventsAction.tooltipContent.textContent = 'Exportar eventos capturados';
706
1146
  }, 2000);
707
1147
  },
708
1148
  );
709
1149
 
710
- filterContainer.append(eventFilterInput, copyEventsAction.tooltip);
1150
+ filterContainer.append(eventFilterInput, eventKindFilter, copyEventsAction.tooltip);
711
1151
 
712
1152
  const eventsHelp = document.createElement('p');
713
1153
  eventsHelp.className = 'wbc-events-help';
714
- eventsHelp.textContent = 'Eventos emitidos pelo componente aparecem abaixo.';
1154
+ eventsHelp.textContent = 'Eventos e mensagens de runtime do preview aparecem abaixo.';
715
1155
 
716
1156
  const eventsActions = document.createElement('div');
717
1157
  eventsActions.className = 'wbc-events-actions';
718
- eventsActions.style.display = 'flex';
719
- eventsActions.style.gap = '5px';
720
1158
 
721
1159
  const pauseBtn = document.createElement('br-button');
1160
+ pauseBtn.setAttribute('type', 'button');
722
1161
  pauseBtn.setAttribute('density', 'small');
723
1162
  pauseBtn.setAttribute('emphasis', 'secondary');
724
1163
  pauseBtn.textContent = 'Pausar';
725
1164
 
726
1165
  const clearBtn = document.createElement('br-button');
1166
+ clearBtn.setAttribute('type', 'button');
727
1167
  clearBtn.setAttribute('density', 'small');
728
1168
  clearBtn.setAttribute('emphasis', 'secondary');
729
1169
  clearBtn.textContent = 'Limpar';
@@ -736,31 +1176,48 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
736
1176
 
737
1177
  eventsWrapper.append(eventsHeader, eventsList);
738
1178
 
1179
+ const eventEntries = [];
1180
+ let eventCounter = 0;
1181
+
739
1182
  const applyFilter = () => {
740
1183
  const val = String(eventFilterInput.value ?? '').toLowerCase();
1184
+ const kind = eventKindFilter.value;
741
1185
  Array.from(eventsList.children).forEach((li) => {
742
1186
  const text = li.textContent.toLowerCase();
743
- li.style.display = text.includes(val) ? '' : 'none';
1187
+ const kindMatches =
1188
+ kind === 'all' ||
1189
+ li.dataset.eventKind === kind ||
1190
+ (kind === 'component' && /br-[a-z0-9-]+/i.test(li.dataset.eventTarget || ''));
1191
+ li.hidden = !kindMatches || !text.includes(val);
744
1192
  });
745
1193
  };
746
1194
 
747
1195
  eventFilterInput.addEventListener('input', applyFilter);
748
1196
  eventFilterInput.addEventListener('valueChange', applyFilter);
1197
+ eventKindFilter.addEventListener('change', applyFilter);
749
1198
 
750
1199
  let newEventsCount = 0;
751
1200
  let isPaused = false;
1201
+ const updateConsoleCounter = () => {
1202
+ const count = eventEntries.length + runtimeEntries.length;
1203
+ if (count > 0) eventsTabItem.setAttribute('counter', count > 99 ? '99+' : String(count));
1204
+ else eventsTabItem.removeAttribute('counter');
1205
+ };
1206
+
1207
+ const markConsoleEntry = () => {
1208
+ const isActive = eventsTabItem.getAttribute('is-active') === 'true';
1209
+ if (!isActive) {
1210
+ newEventsCount++;
1211
+ eventsTabItem.setAttribute('label', `Console (${newEventsCount})`);
1212
+ }
1213
+ updateConsoleCounter();
1214
+ };
752
1215
 
753
1216
  pauseBtn.addEventListener('click', () => {
754
1217
  isPaused = !isPaused;
755
1218
  pauseBtn.textContent = isPaused ? 'Continuar' : 'Pausar';
756
1219
  });
757
1220
 
758
- clearBtn.addEventListener('click', () => {
759
- eventsList.replaceChildren();
760
- eventsTabItem.setAttribute('label', 'Console');
761
- newEventsCount = 0;
762
- });
763
-
764
1221
  const serialize = (value) => {
765
1222
  if (value === undefined) return '';
766
1223
  try {
@@ -789,74 +1246,248 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
789
1246
  return `${target.localName}${id}${classes}`;
790
1247
  };
791
1248
 
792
- const addEventEntry = (event, dispatchedBy, targetDescription) => {
793
- if (isPaused) return;
1249
+ const createEventEntry = (event, dispatchedBy, targetDescription, metadata = {}) => {
1250
+ eventCounter += 1;
1251
+ return {
1252
+ id: metadata.eventId || `event-${eventCounter}`,
1253
+ eventType: metadata.eventType || event.type,
1254
+ custom: Boolean(metadata.custom || event instanceof CustomEvent),
1255
+ detail: metadata.detail ?? (event instanceof CustomEvent ? event.detail : undefined),
1256
+ target: metadata.target || targetDescription || describeTarget(event.target || dispatchedBy),
1257
+ currentTarget: metadata.currentTarget,
1258
+ composedPath: metadata.composedPath || [],
1259
+ bubbles: metadata.bubbles ?? Boolean(event.bubbles),
1260
+ composed: metadata.composed ?? Boolean(event.composed),
1261
+ cancelable: metadata.cancelable ?? Boolean(event.cancelable),
1262
+ timeStamp: metadata.timeStamp ?? event.timeStamp,
1263
+ };
1264
+ };
1265
+
1266
+ const createEventDetails = (detail) => {
1267
+ const detailsEl = document.createElement('details');
1268
+ detailsEl.className = 'wbc-event-console-details-container';
1269
+ detailsEl.open = true;
1270
+
1271
+ const summaryEl = document.createElement('summary');
1272
+ summaryEl.textContent = 'Detalhes do evento';
1273
+
1274
+ const preEl = document.createElement('pre');
1275
+ preEl.className = 'wbc-event-console-detail';
1276
+ preEl.textContent = serialize(detail);
1277
+ detailsEl.append(summaryEl, preEl);
1278
+ return detailsEl;
1279
+ };
794
1280
 
1281
+ const createEventMetadata = (eventEntry) => {
1282
+ const metadataEl = document.createElement('dl');
1283
+ metadataEl.className = 'wbc-event-console-metadata';
1284
+ const metadataRows = [
1285
+ ['target', eventEntry.target],
1286
+ ['currentTarget', eventEntry.currentTarget || '—'],
1287
+ ['bubbles', eventEntry.bubbles],
1288
+ ['composed', eventEntry.composed],
1289
+ ['cancelable', eventEntry.cancelable],
1290
+ ];
1291
+ metadataRows.forEach(([label, value]) => {
1292
+ const term = document.createElement('dt');
1293
+ term.textContent = `${label}:`;
1294
+ const description = document.createElement('dd');
1295
+ description.textContent = String(value);
1296
+ metadataEl.append(term, description);
1297
+ });
1298
+ return metadataEl;
1299
+ };
1300
+
1301
+ const createEventItem = (eventEntry) => {
795
1302
  const item = document.createElement('li');
796
1303
  const name = document.createElement('span');
797
1304
  const target = document.createElement('span');
798
1305
 
799
1306
  name.className = 'wbc-event-console-event-name';
800
- name.textContent = event.type;
1307
+ name.textContent = `${eventEntry.eventType}${eventEntry.custom ? ' (customizado)' : ''}`;
801
1308
  target.className = 'wbc-event-console-target';
802
- target.textContent = ` — ${targetDescription || describeTarget(event.target || dispatchedBy)}`;
1309
+ target.textContent = ` — ${eventEntry.target}`;
1310
+ item.dataset.eventKind = eventEntry.custom ? 'custom' : 'native';
1311
+ item.dataset.eventTarget = eventEntry.target;
803
1312
  item.append(name, target);
804
1313
 
805
- if (event instanceof CustomEvent && event.detail !== undefined && event.detail !== null) {
806
- const detailsEl = document.createElement('details');
807
- detailsEl.className = 'wbc-event-console-details-container';
808
-
809
- const summaryEl = document.createElement('summary');
810
- summaryEl.textContent = 'payload';
811
-
812
- const preEl = document.createElement('pre');
813
- preEl.className = 'wbc-event-console-detail';
814
- preEl.textContent = serialize(event.detail);
815
-
816
- detailsEl.append(summaryEl, preEl);
817
- item.appendChild(detailsEl);
1314
+ if (eventEntry.detail !== undefined && eventEntry.detail !== null) {
1315
+ item.appendChild(createEventDetails(eventEntry.detail));
818
1316
  }
819
1317
 
820
- eventsList.prepend(item);
821
- applyFilter(); // Garante que novos eventos respeitem o filtro atual
1318
+ item.appendChild(createEventMetadata(eventEntry));
1319
+ if (eventEntry.composedPath.length > 0) {
1320
+ const pathEl = document.createElement('small');
1321
+ pathEl.className = 'wbc-event-console-path';
1322
+ pathEl.textContent = `path=${eventEntry.composedPath.join(' → ')}`;
1323
+ item.appendChild(pathEl);
1324
+ }
1325
+ return item;
1326
+ };
822
1327
 
1328
+ const trimEventsList = () => {
823
1329
  const maxEntries = 100;
824
1330
  while (eventsList.children.length > maxEntries) {
825
1331
  eventsList.lastElementChild?.remove();
826
1332
  }
1333
+ };
827
1334
 
828
- const isActive = eventsTabItem.getAttribute('is-active') === 'true';
829
- if (!isActive) {
830
- newEventsCount++;
831
- eventsTabItem.setAttribute('label', `Console (${newEventsCount})`);
1335
+ const addEventEntry = (event, dispatchedBy, targetDescription, metadata = {}) => {
1336
+ if (isPaused) return;
1337
+
1338
+ const eventEntry = createEventEntry(event, dispatchedBy, targetDescription, metadata);
1339
+ eventEntries.push(eventEntry);
1340
+ if (eventEntries.length > 100) eventEntries.shift();
1341
+ eventsList.prepend(createEventItem(eventEntry));
1342
+ applyFilter(); // Garante que novos eventos respeitem o filtro atual
1343
+ trimEventsList();
1344
+
1345
+ markConsoleEntry();
1346
+ };
1347
+
1348
+ const runtimeEntries = [];
1349
+ const createRuntimeEntryItem = (entry) => {
1350
+ const item = document.createElement('li');
1351
+ item.className = `wbc-runtime-entry wbc-runtime-entry--${entry.type}`;
1352
+ item.dataset.eventKind = 'runtime';
1353
+ item.dataset.eventTarget = entry.source || '';
1354
+ const heading = document.createElement('strong');
1355
+ heading.textContent = entry.type;
1356
+ item.appendChild(heading);
1357
+ if (entry.source) {
1358
+ const source = document.createElement('code');
1359
+ source.textContent = ` ${entry.source}${entry.line ? `:${entry.line}${entry.column ? `:${entry.column}` : ''}` : ''}`;
1360
+ item.appendChild(source);
832
1361
  }
1362
+ const body = document.createElement('span');
1363
+ body.textContent = ` ${(entry.args || []).map((value) => (typeof value === 'string' ? value : serialize(value))).join(' ')}`;
1364
+ item.appendChild(body);
1365
+ return item;
1366
+ };
1367
+
1368
+ const addRuntimeEntry = (entry) => {
1369
+ if (isPaused) return;
1370
+ runtimeEntries.push(entry);
1371
+ if (runtimeEntries.length > 100) runtimeEntries.shift();
1372
+ eventsList.prepend(createRuntimeEntryItem(entry));
1373
+ applyFilter();
1374
+ trimEventsList();
1375
+ markConsoleEntry();
833
1376
  };
1377
+ const clearConsole = () => {
1378
+ eventsList.replaceChildren();
1379
+ eventEntries.length = 0;
1380
+ runtimeEntries.length = 0;
1381
+ eventsTabItem.setAttribute('label', 'Console');
1382
+ eventsTabItem.removeAttribute('counter');
1383
+ newEventsCount = 0;
1384
+ };
1385
+ clearBtn.addEventListener('click', clearConsole);
834
1386
 
835
1387
  window.WBCActiveRecorders = window.WBCActiveRecorders || [];
836
1388
  const recorder = {
837
1389
  preview,
838
1390
  addEvent: addEventEntry,
839
1391
  };
840
- window.addEventListener('message', (event) => {
841
- if (!previewFrame || event.source !== previewFrame.contentWindow || !event.data?.type?.startsWith('wbc-preview-'))
1392
+
1393
+ const applyPreviewHeight = (height) => {
1394
+ if (activeViewport.width || hasManualPreviewHeight) return;
1395
+ const maxHeight = contentDiv.classList.contains('is-fullscreen') ? Infinity : window.innerHeight * 0.75;
1396
+ const targetHeight = Math.max(1, Math.min(height, maxHeight));
1397
+ const currentHeight = parseFloat(previewFrame.style.height) || 0;
1398
+ if (Math.abs(targetHeight - currentHeight) > 1) {
1399
+ previewFrame.style.height = `${targetHeight}px`;
1400
+ updatePreviewResizeA11y();
1401
+ }
1402
+ };
1403
+
1404
+ const isPreviewMessage = (event) =>
1405
+ previewFrame &&
1406
+ event.source === previewFrame.contentWindow &&
1407
+ event.data?.__playgroundChannelId === previewChannelId &&
1408
+ event.data?.type?.startsWith('wbc-preview-');
1409
+
1410
+ const handlePreviewEventMessage = (data) => {
1411
+ const bridgedEvent = data.custom
1412
+ ? new CustomEvent(data.eventType, {
1413
+ detail: data.detail,
1414
+ bubbles: data.bubbles,
1415
+ composed: data.composed,
1416
+ cancelable: data.cancelable,
1417
+ })
1418
+ : new Event(data.eventType, {
1419
+ bubbles: data.bubbles,
1420
+ composed: data.composed,
1421
+ cancelable: data.cancelable,
1422
+ });
1423
+ addEventEntry(bridgedEvent, previewFrame, data.target, data);
1424
+ };
1425
+
1426
+ const handlePreviewRuntimeMessage = (data) => {
1427
+ const runtimeTypes = ['log', 'warning', 'error', 'exception', 'unhandledrejection', 'component'];
1428
+ const runtimeType = runtimeTypes.includes(data.runtimeType) ? data.runtimeType : 'log';
1429
+ addRuntimeEntry({
1430
+ id: data.id,
1431
+ type: runtimeType,
1432
+ args: data.args || [],
1433
+ source: data.source,
1434
+ line: data.line,
1435
+ column: data.column,
1436
+ message: data.message,
1437
+ });
1438
+ };
1439
+
1440
+ const handlePreviewMessage = (event) => {
1441
+ if (!isPreviewMessage(event)) return;
1442
+ if (event.data.type === 'wbc-preview-exit-fullscreen') {
1443
+ closeFullscreen();
842
1444
  return;
1445
+ }
843
1446
  if (event.data.type === 'wbc-preview-height') {
844
- const maxHeight = contentDiv.classList.contains('is-fullscreen') ? Infinity : window.innerHeight * 0.75;
845
- previewFrame.style.height = `${Math.max(1, Math.min(event.data.height, maxHeight))}px`;
846
- } else if (event.data.type === 'wbc-preview-event') {
847
- const bridgedEvent = event.data.custom
848
- ? new CustomEvent(event.data.eventType, { detail: event.data.detail })
849
- : new Event(event.data.eventType);
850
- addEventEntry(bridgedEvent, previewFrame, event.data.target);
1447
+ applyPreviewHeight(event.data.height);
1448
+ return;
851
1449
  }
852
- });
1450
+ if (event.data.type === 'wbc-preview-event') {
1451
+ handlePreviewEventMessage(event.data);
1452
+ return;
1453
+ }
1454
+ if (event.data.type === 'wbc-preview-runtime') {
1455
+ handlePreviewRuntimeMessage(event.data);
1456
+ }
1457
+ };
1458
+
1459
+ window.addEventListener('message', handlePreviewMessage, { signal: exampleAbortController.signal });
1460
+ recorder.cleanup = () => {
1461
+ exampleAbortController.abort();
1462
+ recorder.cleanupNativeEvents?.();
1463
+ const recorderIndex = window.WBCActiveRecorders?.indexOf(recorder) ?? -1;
1464
+ if (recorderIndex >= 0) window.WBCActiveRecorders.splice(recorderIndex, 1);
1465
+ };
853
1466
  window.WBCActiveRecorders.push(recorder);
854
1467
  window.WBCRegisterNativeEventRecorder?.(recorder);
1468
+ activeExampleCleanups.add(recorder.cleanup);
855
1469
 
856
- const setEditorValue = (value) => {
857
- editorState.value = value;
858
- editorApi?.setValue(value);
859
- applyEditorValue(value);
1470
+ let runAccessibilityAudit;
1471
+ let accessibilityAuditTimer;
1472
+ const scheduleAccessibilityAudit = () => {
1473
+ window.clearTimeout(accessibilityAuditTimer);
1474
+ accessibilityAuditTimer = window.setTimeout(() => runAccessibilityAudit?.(), 650);
1475
+ };
1476
+
1477
+ let vanillaFileTabs;
1478
+ const setEditorValue = (value, { recordHistory = true } = {}) => {
1479
+ const nextValue = String(value ?? '');
1480
+ if (nextValue === editorState.value) return;
1481
+ activeVanillaFile = 'html';
1482
+ vanillaFileTabs?.querySelectorAll('.wbc-framework-file-tab').forEach((item, index) => {
1483
+ const active = index === 0;
1484
+ item.classList.toggle('is-active', active);
1485
+ item.setAttribute('aria-selected', String(active));
1486
+ });
1487
+ isApplyingEditorValue = true;
1488
+ editorApi?.setValue(nextValue);
1489
+ isApplyingEditorValue = false;
1490
+ applyEditorValue(nextValue, { recordHistory });
860
1491
  };
861
1492
 
862
1493
  tabComponent.addEventListener('brTabChange', (event) => {
@@ -870,7 +1501,42 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
870
1501
  }
871
1502
  });
872
1503
 
873
- codeTabItem.appendChild(editorWrapper);
1504
+ vanillaFileTabs = document.createElement('div');
1505
+ vanillaFileTabs.className = 'wbc-framework-file-tabs wbc-vanilla-file-tabs';
1506
+ vanillaFileTabs.setAttribute('role', 'tablist');
1507
+ vanillaFileTabs.setAttribute('aria-label', 'Arquivos HTML/CSS/JS');
1508
+ const vanillaFiles = [
1509
+ ['html', 'index.html'],
1510
+ ['css', 'index.css'],
1511
+ ['javascript', 'index.js'],
1512
+ ];
1513
+ vanillaFiles.forEach(([target, filename], index) => {
1514
+ const fileTab = document.createElement('button');
1515
+ fileTab.className = `wbc-framework-file-tab${index === 0 ? ' is-active' : ''}`;
1516
+ fileTab.type = 'button';
1517
+ fileTab.setAttribute('role', 'tab');
1518
+ fileTab.setAttribute('aria-selected', String(index === 0));
1519
+ fileTab.textContent = filename;
1520
+ fileTab.addEventListener('click', () => {
1521
+ if (target === activeVanillaFile) return;
1522
+ vanillaSources[activeVanillaFile] = getEditorValue();
1523
+ activeVanillaFile = target;
1524
+ vanillaFileTabs.querySelectorAll('.wbc-framework-file-tab').forEach((item, itemIndex) => {
1525
+ const active = itemIndex === vanillaFiles.findIndex(([value]) => value === target);
1526
+ item.classList.toggle('is-active', active);
1527
+ item.setAttribute('aria-selected', String(active));
1528
+ });
1529
+ if (!editorApi) return;
1530
+ isSwitchingVanillaFile = true;
1531
+ editorApi.setLanguage?.(target === 'html' ? 'html' : target === 'css' ? 'css' : 'javascript');
1532
+ editorApi.setValue(vanillaSources[target]);
1533
+ isSwitchingVanillaFile = false;
1534
+ refreshEditor();
1535
+ });
1536
+ vanillaFileTabs.appendChild(fileTab);
1537
+ });
1538
+
1539
+ codeTabItem.append(vanillaFileTabs, editorWrapper, diffPanel);
874
1540
  eventsTabItem.appendChild(eventsWrapper);
875
1541
 
876
1542
  // --- ACCESSIBILITY TAB ---
@@ -878,7 +1544,7 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
878
1544
  a11yTabItem.setAttribute('label', 'Acessibilidade');
879
1545
  a11yTabItem.setAttribute('icon', 'fas fa-universal-access');
880
1546
  a11yTabItem.setAttribute('icon-only', 'true');
881
- a11yTabItem.setAttribute('title', 'Acessibilidade');
1547
+ a11yTabItem.setAttribute('title', 'Auditoria de acessibilidade');
882
1548
  a11yTabItem.setAttribute('tab-item-id', 'a11y-tab');
883
1549
 
884
1550
  const a11yWrapper = document.createElement('div');
@@ -899,25 +1565,32 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
899
1565
  a11yWrapper.append(a11yHeader, a11yResults);
900
1566
  a11yTabItem.appendChild(a11yWrapper);
901
1567
 
902
- const runAccessibilityAudit = async () => {
903
- if (!window.axe) {
904
- a11yResults.innerHTML =
905
- '<p class="text-danger mt-3">Axe-Core não está carregado. Verifique a conexão ou recarregue a página.</p>';
906
- return;
1568
+ const showA11yMessage = (className, message, iconClass) => {
1569
+ const paragraph = document.createElement('p');
1570
+ paragraph.className = className;
1571
+ if (iconClass) {
1572
+ const icon = document.createElement('i');
1573
+ icon.className = `${iconClass} mr-2`;
1574
+ icon.setAttribute('aria-hidden', 'true');
1575
+ paragraph.appendChild(icon);
907
1576
  }
1577
+ paragraph.appendChild(document.createTextNode(message));
1578
+ a11yResults.replaceChildren(paragraph);
1579
+ };
908
1580
 
909
- a11yResults.innerHTML =
910
- '<p class="mt-3"><i class="fas fa-spinner fa-spin mr-2"></i>Analisando acessibilidade...</p>';
1581
+ runAccessibilityAudit = async () => {
1582
+ showA11yMessage('mt-3', 'Analisando acessibilidade...', 'fas fa-spinner fa-spin');
911
1583
 
912
1584
  try {
913
1585
  const { axe, previewContent } = await getPreviewAxeContext(previewFrame);
914
1586
  const results = await axe.run(previewContent);
915
1587
 
916
1588
  if (results.violations.length === 0) {
917
- a11yResults.innerHTML =
918
- '<p class="text-success mt-3"><i class="fas fa-check-circle mr-2"></i>Nenhum problema de acessibilidade detectado!</p>';
1589
+ a11yTabItem.removeAttribute('counter');
1590
+ showA11yMessage('text-success mt-3', 'Nenhum problema de acessibilidade detectado!', 'fas fa-check-circle');
919
1591
  } else {
920
- a11yResults.innerHTML = '';
1592
+ a11yTabItem.setAttribute('counter', String(results.violations.length));
1593
+ a11yResults.replaceChildren();
921
1594
 
922
1595
  const violationsList = document.createElement('ul');
923
1596
  violationsList.className = 'wbc-a11y-violations-list mt-3';
@@ -934,7 +1607,8 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
934
1607
  impactBadge.textContent = violation.impact;
935
1608
 
936
1609
  const helpText = document.createElement('span');
937
- helpText.innerHTML = `<strong>${violation.help}</strong>`;
1610
+ helpText.textContent = violation.help;
1611
+ helpText.style.fontWeight = '700';
938
1612
 
939
1613
  title.append(helpText, impactBadge);
940
1614
 
@@ -955,8 +1629,12 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
955
1629
  a11yResults.appendChild(violationsList);
956
1630
  }
957
1631
  } catch (err) {
1632
+ a11yTabItem.setAttribute('counter', '1');
958
1633
  console.error(err);
959
- a11yResults.innerHTML = `<p class="text-danger mt-3">Erro ao executar a análise: ${err.message}</p>`;
1634
+ showA11yMessage(
1635
+ 'text-danger mt-3',
1636
+ `Erro ao executar a análise: ${err instanceof Error ? err.message : String(err)}`,
1637
+ );
960
1638
  }
961
1639
  };
962
1640
 
@@ -968,8 +1646,6 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
968
1646
  tabComponent.append(
969
1647
  codeTabItem,
970
1648
  controlsTabItem,
971
- javascriptTabItem,
972
- cssTabItem,
973
1649
  eventsTabItem,
974
1650
  angularTabItem,
975
1651
  reactTabItem,
@@ -981,25 +1657,56 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
981
1657
  let controlsCssSource = '';
982
1658
  const renderCurrentPreview = (source) => {
983
1659
  const managedStyle = controlsCssSource ? `<style data-playground-controls-css>${controlsCssSource}</style>` : '';
984
- renderExamplePreview(preview, `${source}${managedStyle}`, path === 'templates');
1660
+ if (previewFrame) {
1661
+ previewFrame.classList.remove('wbc-preview-animate');
1662
+ void previewFrame.offsetWidth;
1663
+ previewFrame.classList.add('wbc-preview-animate');
1664
+ }
1665
+ renderExamplePreview(
1666
+ preview,
1667
+ `${source}${managedStyle}`,
1668
+ path === 'templates',
1669
+ baseScriptUrl,
1670
+ activePresetScriptUrl,
1671
+ previewChannelId,
1672
+ );
1673
+ updatePreviewResizeA11y();
1674
+ };
1675
+
1676
+ const handleEditorChange = (source) => {
1677
+ if (isSwitchingVanillaFile) return;
1678
+ vanillaSources[activeVanillaFile] = String(source ?? '');
1679
+ if (activeVanillaFile === 'html' && !isApplyingEditorValue) applyEditorValue(source);
985
1680
  };
986
1681
 
987
- const applyEditorValue = (source) => {
1682
+ const applyEditorValue = (source, { recordHistory = true } = {}) => {
1683
+ source = String(source ?? '');
1684
+ vanillaSources.html = source;
1685
+ if (recordHistory) recordEditorHistory(source);
988
1686
  editorState.value = source;
989
1687
  updateFrameworkCode(source);
990
1688
  renderCurrentPreview(source);
1689
+ scheduleAccessibilityAudit();
991
1690
  renderedFilesContent[file] = { content: source.toLowerCase(), element: contentDiv };
992
- // The example script lives in the preview iframe and is recreated with it.
1691
+ writePlaygroundDraft(path, file, {
1692
+ html: source,
1693
+ baselineHtml: comparisonBaseline,
1694
+ presetId: presetSelect.value || undefined,
1695
+ });
1696
+ updateHistoryActions();
1697
+ updateDiff(source);
1698
+ if (!isUpdatingFromControls) {
1699
+ controlsApi?.refresh?.();
1700
+ }
1701
+ // A remoção explícita ocorre antes da recriação do srcdoc para evitar que
1702
+ // o script específico do preset anterior permaneça no documento do iframe.
993
1703
  };
994
1704
 
995
1705
  const fullscreenBottomPanel = document.createElement('div');
996
1706
  fullscreenBottomPanel.className = 'wbc-example-fullscreen-bottom-panel';
997
1707
  fullscreenBottomPanel.appendChild(editorContainer);
998
1708
 
999
- preview.setAttribute('slot', 'target');
1000
- fullscreenBottomPanel.setAttribute('slot', 'target');
1001
- dropdown.appendChild(header);
1002
- contentDiv.appendChild(dropdown);
1709
+ contentDiv.append(header, preview, fullscreenBottomPanel);
1003
1710
 
1004
1711
  initializeExample = () => {
1005
1712
  previewFrame = document.createElement('iframe');
@@ -1007,8 +1714,16 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
1007
1714
  previewFrame.title = `Preview do exemplo ${file}`;
1008
1715
  previewFrame.dataset.path = path;
1009
1716
  previewFrame.setAttribute('loading', 'eager');
1010
- preview.appendChild(previewFrame);
1011
- renderCurrentPreview(text);
1717
+ previewFrame.addEventListener('load', () => {
1718
+ setPreviewReducedMotion(reducedMotionEnabled);
1719
+ setPreviewTheme(darkThemeEnabled);
1720
+ });
1721
+ previewViewport.append(previewFrame, previewWidthResizeHandle, previewHeightResizeHandle);
1722
+ preview.appendChild(previewViewport);
1723
+ preview.classList.add('wbc-example-preview--resizable');
1724
+ updatePreviewResizeA11y();
1725
+ renderCurrentPreview(editorState.value);
1726
+ scheduleAccessibilityAudit();
1012
1727
 
1013
1728
  const editorReady = window.WBCCodeEditorReady || Promise.resolve(window.WBCCodeEditor);
1014
1729
  editorReady.then(() => {
@@ -1016,7 +1731,7 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
1016
1731
  editorWrapper.textContent = '';
1017
1732
  editorApi = window.WBCCodeEditor.create({
1018
1733
  ariaLabel: `Código fonte do exemplo ${file}`,
1019
- onChange: applyEditorValue,
1734
+ onChange: handleEditorChange,
1020
1735
  parent: editorWrapper,
1021
1736
  value: editorState.value,
1022
1737
  language: 'html',
@@ -1035,7 +1750,7 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
1035
1750
  parent: editorContainer,
1036
1751
  value: code.textContent || '',
1037
1752
  language: getFrameworkEditorLanguage(framework),
1038
- readOnly: true,
1753
+ readOnly: tab.dataset.editable !== 'true',
1039
1754
  });
1040
1755
  frameworkEditors.set(tab, editor);
1041
1756
  tab.querySelectorAll('.wbc-framework-file-tab').forEach((fileTab) => {
@@ -1065,13 +1780,27 @@ function createExampleElement(path, file, text, isExpanded = false, onOpen) {
1065
1780
  setCss: (value) => {
1066
1781
  controlsCssSource = value;
1067
1782
  renderCurrentPreview(getEditorValue());
1783
+ scheduleAccessibilityAudit();
1068
1784
  },
1069
1785
  setHtml: (value) => {
1070
- setEditorValue(value);
1786
+ isUpdatingFromControls = true;
1787
+ try {
1788
+ setEditorValue(value);
1789
+ } finally {
1790
+ isUpdatingFromControls = false;
1791
+ }
1071
1792
  },
1793
+ }).then((api) => {
1794
+ controlsApi = api;
1072
1795
  });
1073
1796
  };
1074
1797
 
1798
+ queueMicrotask(() => {
1799
+ if (isInitialized) return;
1800
+ initializeExample();
1801
+ isInitialized = true;
1802
+ });
1803
+
1075
1804
  renderedFilesContent[file] = { content: text.toLowerCase(), element: contentDiv };
1076
1805
 
1077
1806
  return contentDiv;
@@ -1081,9 +1810,15 @@ function createComponentTags(metadata) {
1081
1810
  const wrapper = document.createElement('div');
1082
1811
  wrapper.className = 'wbc-component-tags';
1083
1812
  wrapper.setAttribute('aria-label', 'Classificação do componente');
1084
- const colors = { stable: 'var(--success)', beta: 'var(--warning)', deprecated: 'var(--danger)' };
1085
- const labels = { stable: 'Estável', beta: 'Beta', deprecated: 'Depreciado' };
1086
- (metadata?.categories || []).forEach((category) => {
1813
+ const colors = { stable: 'var(--success)', beta: '#ffcd07', deprecated: 'var(--danger)' };
1814
+ const labels = { stable: 'Estável', beta: 'Em testes', deprecated: 'Depreciado' };
1815
+ const categories = Array.from(
1816
+ new Set([
1817
+ ...(Array.isArray(metadata?.categories) ? metadata.categories : []),
1818
+ ...(metadata?.category ? [metadata.category] : []),
1819
+ ]),
1820
+ ).filter((category) => typeof category === 'string' && category.trim());
1821
+ categories.forEach((category) => {
1087
1822
  const tag = document.createElement('br-tag');
1088
1823
  tag.setAttribute('label', category);
1089
1824
  tag.setAttribute('bg-color', 'var(--interactive)');
@@ -1095,10 +1830,60 @@ function createComponentTags(metadata) {
1095
1830
  statusTag.setAttribute('label', labels[status] || labels.stable);
1096
1831
  statusTag.setAttribute('bg-color', colors[status] || colors.stable);
1097
1832
  statusTag.className = `wbc-component-status wbc-component-status--${status}`;
1098
- wrapper.appendChild(statusTag);
1833
+ if (status === 'beta') {
1834
+ statusTag.classList.add('wbc-component-status--beta');
1835
+ const tooltip = document.createElement('br-tooltip');
1836
+ tooltip.setAttribute('position', 'top');
1837
+ tooltip.setAttribute('aria-label', 'Status: Em testes');
1838
+ statusTag.setAttribute('slot', 'trigger');
1839
+ const description = document.createElement('span');
1840
+ description.setAttribute('slot', 'content');
1841
+ description.textContent =
1842
+ 'Componente/funcionalidade ainda em testes. Use com cuidado, pois podemos fazer alterações.';
1843
+ tooltip.append(statusTag, description);
1844
+ wrapper.appendChild(tooltip);
1845
+ } else {
1846
+ wrapper.appendChild(statusTag);
1847
+ }
1099
1848
  return wrapper;
1100
1849
  }
1101
1850
 
1851
+ function createComponentHeading(metadata) {
1852
+ const heading = document.createElement('h1');
1853
+ heading.className = 'wbc-component-title';
1854
+ heading.textContent = metadata?.name || 'Componente';
1855
+ return heading;
1856
+ }
1857
+
1858
+ function getPresetSource(preset) {
1859
+ if (typeof preset?.source === 'string') return preset.source;
1860
+ return preset?.source?.text || '';
1861
+ }
1862
+
1863
+ function getSharedExampleState(path, file) {
1864
+ const sharedState = window.SHARED_STATE;
1865
+ if (sharedState?.p !== path || sharedState?.f !== file) return null;
1866
+
1867
+ const { presetId } = getHashState();
1868
+ if (presetId && sharedState.presetId && presetId !== sharedState.presetId) return null;
1869
+ return sharedState;
1870
+ }
1871
+
1872
+ function getPresetForExample(path, example, presets) {
1873
+ const { file, presetId } = getHashState();
1874
+ const sharedState = getSharedExampleState(path, example.id);
1875
+ const candidateIds = [];
1876
+
1877
+ if (file === example.id && presetId) candidateIds.push(presetId);
1878
+ if (sharedState?.presetId) candidateIds.push(sharedState.presetId);
1879
+ candidateIds.push(example.defaultPreset, ...example.presets);
1880
+
1881
+ return candidateIds
1882
+ .filter(Boolean)
1883
+ .map((id) => presets.find((preset) => preset.id === id))
1884
+ .find((preset) => preset && example.presets.includes(preset.id) && getPresetSource(preset));
1885
+ }
1886
+
1102
1887
  function getInitialExampleFile(path, files) {
1103
1888
  const requestedFile = getRequestedExampleFile();
1104
1889
  if (files.includes(requestedFile)) return { initialFile: requestedFile, requestedFile };
@@ -1106,111 +1891,205 @@ function getInitialExampleFile(path, files) {
1106
1891
  return { initialFile: 'default', requestedFile };
1107
1892
  }
1108
1893
 
1109
- function createExamplesList(path, results, initialFile) {
1894
+ function createExamplesList(
1895
+ path,
1896
+ results,
1897
+ presets = [],
1898
+ exampleConfigs = [],
1899
+ initialFile = 'default',
1900
+ baseScript = '',
1901
+ ) {
1110
1902
  let sharedElementToScroll = null;
1903
+ let initialPresetId = '';
1111
1904
  const examples = document.createElement('br-list');
1112
1905
  examples.className = 'wbc-examples-list';
1113
1906
  examples.setAttribute('list-role', 'group');
1114
1907
  examples.setAttribute('divider', '');
1908
+ const configById = new Map(exampleConfigs.map((example) => [example.id, example]));
1115
1909
  results.sort((a, b) => Number(b.file === 'default') - Number(a.file === 'default'));
1116
- results.forEach(({ file, text }, index) => {
1910
+ results.forEach(({ file, text }) => {
1911
+ const config = configById.get(file);
1912
+ const availableIds = Array.isArray(config?.presets) ? new Set(config.presets) : new Set();
1913
+ const availablePresets = presets.filter(({ id }) => availableIds.has(id));
1914
+ const example = {
1915
+ id: file,
1916
+ presets: [...availableIds],
1917
+ defaultPreset: config?.defaultPreset,
1918
+ };
1919
+ const selectedPreset = getPresetForExample(path, example, availablePresets);
1920
+ const fallbackPreset = availablePresets.find(
1921
+ (preset) => preset.id === config?.defaultPreset && getPresetSource(preset),
1922
+ );
1923
+ const selectedPresetId =
1924
+ selectedPreset?.id || fallbackPreset?.id || availablePresets.find((preset) => getPresetSource(preset))?.id || '';
1117
1925
  const element = createExampleElement(
1118
1926
  path,
1119
1927
  file,
1120
1928
  text,
1121
- file === initialFile || (!initialFile && index === 0),
1122
- (openedFile) => {
1123
- const hash = getExampleHash(openedFile);
1124
- if (window.location.hash !== hash) {
1125
- window.history.replaceState({}, '', `${window.location.pathname}${window.location.search}${hash}`);
1126
- }
1127
- examples.querySelectorAll('br-dropdown').forEach((other) => {
1128
- if (other !== element.querySelector('br-dropdown') && other.isOpen) other.isOpen = false;
1129
- });
1130
- },
1929
+ availablePresets.map(({ source, ...preset }) => ({ ...preset, source: source?.text ?? null })),
1930
+ selectedPresetId,
1931
+ config?.label || file,
1932
+ baseScript,
1131
1933
  );
1934
+ element.dataset.defaultPreset =
1935
+ fallbackPreset?.id || availablePresets.find((preset) => getPresetSource(preset))?.id || '';
1132
1936
  examples.appendChild(element);
1133
- if (window.SHARED_STATE?.p === path && window.SHARED_STATE?.f === file) sharedElementToScroll = element;
1134
- });
1135
- return { examples, sharedElementToScroll };
1136
- }
1137
-
1138
- function openInitialDropdown(examples, initialFile) {
1139
- const initialDropdown = initialFile
1140
- ? examples.querySelector(`[data-example-file="${CSS.escape(initialFile)}"] br-dropdown`)
1141
- : null;
1142
- if (!initialDropdown) return;
1143
- customElements.whenDefined('br-dropdown').then(() => {
1144
- initialDropdown.isOpen = false;
1145
- initialDropdown.open();
1937
+ if (file === initialFile) initialPresetId = selectedPresetId;
1938
+ if (getSharedExampleState(path, file)) sharedElementToScroll = element;
1146
1939
  });
1940
+ return { examples, initialPresetId, sharedElementToScroll };
1147
1941
  }
1148
1942
 
1149
1943
  function scrollToInitialExample(examples, requestedFile, sharedElementToScroll) {
1150
1944
  const hashElement = requestedFile
1151
1945
  ? examples.querySelector(`[data-example-file="${CSS.escape(requestedFile)}"]`)
1152
1946
  : null;
1153
- if (hashElement) setTimeout(() => hashElement.scrollIntoView({ behavior: 'smooth', block: 'center' }), 500);
1947
+ if (hashElement)
1948
+ setTimeout(() => hashElement.scrollIntoView({ behavior: getScrollBehavior(), block: 'center' }), 500);
1154
1949
  if (sharedElementToScroll) {
1155
1950
  setTimeout(() => {
1156
- sharedElementToScroll.scrollIntoView({ behavior: 'smooth', block: 'center' });
1951
+ sharedElementToScroll.scrollIntoView({ behavior: getScrollBehavior(), block: 'center' });
1157
1952
  sharedElementToScroll.classList.add('wbc-example-shared-highlight');
1158
1953
  }, 500);
1159
1954
  }
1160
1955
  }
1161
1956
 
1162
- function renderLoadedPage(path, files, results) {
1957
+ function renderLoadedPage(path, examples, results, presets = [], baseScript = '') {
1163
1958
  const metadata = window.MENU_ITEMS?.find((item) => item.path === path);
1164
- if (metadata) CONTENT_ELEMENT.appendChild(createComponentTags(metadata));
1165
- const { initialFile, requestedFile } = getInitialExampleFile(path, files);
1166
- const { examples, sharedElementToScroll } = createExamplesList(path, results, initialFile);
1167
- CONTENT_ELEMENT.appendChild(examples);
1168
- openInitialDropdown(examples, initialFile);
1169
- if (initialFile && files.includes(initialFile) && window.location.hash !== getExampleHash(initialFile)) {
1170
- window.history.replaceState(
1171
- {},
1172
- '',
1173
- `${window.location.pathname}${window.location.search}${getExampleHash(initialFile)}`,
1174
- );
1959
+ if (metadata) {
1960
+ CONTENT_ELEMENT.appendChild(createComponentHeading(metadata));
1961
+ CONTENT_ELEMENT.appendChild(createComponentTags(metadata));
1175
1962
  }
1176
- scrollToInitialExample(examples, requestedFile, sharedElementToScroll);
1963
+ const exampleIds = examples.map(({ id }) => id);
1964
+ const { initialFile, requestedFile } = getInitialExampleFile(path, exampleIds);
1965
+ const {
1966
+ examples: examplesList,
1967
+ initialPresetId,
1968
+ sharedElementToScroll,
1969
+ } = createExamplesList(path, results, presets, examples, initialFile, baseScript);
1970
+ CONTENT_ELEMENT.appendChild(examplesList);
1971
+ if (initialFile && exampleIds.includes(initialFile)) {
1972
+ const targetHash = getExampleHash(initialFile, initialPresetId || undefined);
1973
+ if (window.location.hash !== targetHash) {
1974
+ const url = new URL(window.location.href);
1975
+ url.hash = targetHash;
1976
+ const currentState = window.history.state;
1977
+ const nextState = currentState && typeof currentState === 'object' ? currentState : {};
1978
+ window.history.replaceState(nextState, '', url.href);
1979
+ }
1980
+ }
1981
+ scrollToInitialExample(examplesList, requestedFile, sharedElementToScroll);
1177
1982
  currentLoadedPath = path;
1178
1983
  }
1179
1984
 
1180
- function loadPage(path, files) {
1985
+ function normalizePageExample(example, presets) {
1986
+ const isLegacyExample = typeof example === 'string';
1987
+ const exampleConfig = isLegacyExample ? {} : example;
1988
+ const exampleId = isLegacyExample ? example : exampleConfig.id;
1989
+ const examplePresetIds = Array.isArray(exampleConfig.presets) ? exampleConfig.presets : [];
1990
+ const requestedPresetId = isLegacyExample ? exampleId : exampleConfig.defaultPreset;
1991
+ const fallbackPreset =
1992
+ presets.find(({ id }) => id === requestedPresetId) ??
1993
+ presets.find(({ id }) => id === `example-${exampleId}`) ??
1994
+ presets.find(({ id }) => examplePresetIds.includes(id)) ??
1995
+ presets[0];
1996
+
1997
+ return {
1998
+ ...exampleConfig,
1999
+ id: exampleId,
2000
+ presets: examplePresetIds.length > 0 ? examplePresetIds : fallbackPreset ? [fallbackPreset.id] : [],
2001
+ defaultPreset: exampleConfig.defaultPreset || fallbackPreset?.id,
2002
+ };
2003
+ }
2004
+
2005
+ function normalizePageExamples(examples, presets) {
2006
+ return examples.map((example) => normalizePageExample(example, presets));
2007
+ }
2008
+
2009
+ const PLAYGROUND_SOURCE_FETCH_ATTEMPTS = 4;
2010
+
2011
+ function waitForPlaygroundSourceRetry(attempt) {
2012
+ return new Promise((resolve) => setTimeout(resolve, attempt * 150));
2013
+ }
2014
+
2015
+ async function fetchPlaygroundSource(path, source) {
2016
+ if (!source) throw new Error(`Fonte ausente para ${path}`);
2017
+
2018
+ let lastError;
2019
+ for (let attempt = 1; attempt <= PLAYGROUND_SOURCE_FETCH_ATTEMPTS; attempt += 1) {
2020
+ try {
2021
+ const response = await fetch(`${getBaseUrl()}/pages/components/${path}/${source}`, { cache: 'no-store' });
2022
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
2023
+ return stripDevServerConnector(await response.text());
2024
+ } catch (error) {
2025
+ lastError = error;
2026
+ if (attempt < PLAYGROUND_SOURCE_FETCH_ATTEMPTS) await waitForPlaygroundSourceRetry(attempt);
2027
+ }
2028
+ }
2029
+
2030
+ throw lastError;
2031
+ }
2032
+
2033
+ function loadPage(path, examples, presets = [], baseScript = '') {
2034
+ const loadGeneration = ++pageLoadGeneration;
2035
+ cleanupExamples();
1181
2036
  window.WBCActiveRecorders = [];
1182
2037
  CONTENT_ELEMENT.innerHTML = '';
1183
2038
  renderedFilesContent = {};
1184
2039
  if (COMPONENTS_FILTER) COMPONENTS_FILTER.value = ''; // Limpa o campo de busca ao trocar de página
1185
- if (CLEAR_COMPONENTS_FILTER) CLEAR_COMPONENTS_FILTER.style.display = 'none'; // Esconde o botão de limpar
1186
-
1187
- const baseUrl = getBaseUrl();
1188
- const promises = files.map((file) => {
1189
- if (window.SHARED_STATE && window.SHARED_STATE.p === path && window.SHARED_STATE.f === file) {
1190
- return Promise.resolve({ file, text: stripDevServerConnector(window.SHARED_STATE.h) });
2040
+ if (CLEAR_COMPONENTS_FILTER) CLEAR_COMPONENTS_FILTER.hidden = true;
2041
+
2042
+ const pageExamples = normalizePageExamples(examples, presets);
2043
+ const presetSources = new Map();
2044
+ const uniquePresetSources = [...new Set(presets.map(({ source }) => source).filter(Boolean))];
2045
+ const presetPromises = uniquePresetSources.map((source) =>
2046
+ fetchPlaygroundSource(path, source)
2047
+ .then((text) => {
2048
+ presetSources.set(source, text);
2049
+ })
2050
+ .catch((error) => {
2051
+ console.warn(`Não foi possível carregar o preset ${path}/${source}:`, error);
2052
+ }),
2053
+ );
2054
+ const promises = pageExamples.map((example) => {
2055
+ const selectedPreset = getPresetForExample(path, example, presets);
2056
+ const source = getPresetSource(selectedPreset);
2057
+ const sharedState = getSharedExampleState(path, example.id);
2058
+ if (sharedState) {
2059
+ return Promise.resolve({ file: example.id, text: stripDevServerConnector(window.SHARED_STATE.h) });
1191
2060
  }
1192
- return fetch(`${baseUrl}/pages/components/${path}/${file}.html`).then((response) =>
1193
- response.text().then((text) => ({ file, text: stripDevServerConnector(text) })),
1194
- );
2061
+ return fetchPlaygroundSource(path, source).then((text) => ({ file: example.id, text }));
1195
2062
  });
1196
2063
 
1197
- Promise.all(promises)
1198
- .then((results) => renderLoadedPage(path, files, results))
2064
+ Promise.all([Promise.all(promises), Promise.all(presetPromises)])
2065
+ .then(([results]) => {
2066
+ if (loadGeneration !== pageLoadGeneration) return;
2067
+ const loadedPresets = presets.map((preset) => ({
2068
+ ...preset,
2069
+ source: presetSources.has(preset.source)
2070
+ ? { text: presetSources.get(preset.source), path: preset.source }
2071
+ : null,
2072
+ }));
2073
+ renderLoadedPage(path, pageExamples, results, loadedPresets, baseScript);
2074
+ })
1199
2075
  .catch((error) => {
1200
2076
  console.log('Erro ao carregar a página:', error);
1201
2077
  });
1202
2078
  }
1203
2079
 
1204
2080
  function loadMarkdown(path) {
2081
+ const loadGeneration = ++pageLoadGeneration;
2082
+ cleanupExamples();
1205
2083
  CONTENT_ELEMENT.innerHTML = '';
1206
2084
  renderedFilesContent = {};
1207
2085
  if (COMPONENTS_FILTER) COMPONENTS_FILTER.value = ''; // Limpa o campo de busca ao trocar de página
1208
- if (CLEAR_COMPONENTS_FILTER) CLEAR_COMPONENTS_FILTER.style.display = 'none'; // Esconde o botão de limpar
2086
+ if (CLEAR_COMPONENTS_FILTER) CLEAR_COMPONENTS_FILTER.hidden = true;
1209
2087
 
1210
2088
  const baseUrl = getBaseUrl();
1211
2089
  fetch(`${baseUrl}/assets/stencil-generated-docs/${path}.md`)
1212
2090
  .then((response) => response.text())
1213
2091
  .then((text) => {
2092
+ if (loadGeneration !== pageLoadGeneration) return;
1214
2093
  const contentDiv = document.createElement('div');
1215
2094
  contentDiv.classList.add('file', 'mt-2', 'mb-5');
1216
2095
  const parsedMarkdown = typeof markdownParser?.parse === 'function' ? markdownParser.parse(text) : text;
@@ -1266,26 +2145,26 @@ function filterContent() {
1266
2145
  const rows = element.querySelectorAll('table tr');
1267
2146
  rows.forEach((row, index) => {
1268
2147
  if (index === 0) {
1269
- row.style.display = '';
2148
+ row.hidden = false;
1270
2149
  } else {
1271
2150
  const rowText = row.textContent
1272
2151
  .toLowerCase()
1273
2152
  .normalize('NFD')
1274
2153
  .replace(/[\u0300-\u036f]/g, '');
1275
- row.style.display = rowText.includes(normalizedFilterValue) ? '' : 'none';
2154
+ row.hidden = !rowText.includes(normalizedFilterValue);
1276
2155
  }
1277
2156
  });
1278
2157
  } else if (
1279
2158
  normalizedFilterValue &&
1280
2159
  (combinedContent.includes(normalizedFilterValue) || normalizedTitleText.includes(normalizedFilterValue))
1281
2160
  ) {
1282
- element.style.display = ''; // Exibe o elemento se o conteúdo combinado inclui o valor filtrado
2161
+ element.hidden = false;
1283
2162
  } else {
1284
- element.style.display = normalizedFilterValue ? 'none' : ''; // Oculta se não houver filtro
2163
+ element.hidden = Boolean(normalizedFilterValue);
1285
2164
  }
1286
2165
  });
1287
2166
 
1288
- if (CLEAR_COMPONENTS_FILTER) CLEAR_COMPONENTS_FILTER.style.display = filterValue ? 'block' : 'none';
2167
+ if (CLEAR_COMPONENTS_FILTER) CLEAR_COMPONENTS_FILTER.hidden = !filterValue;
1289
2168
  }
1290
2169
 
1291
2170
  function processMenuItems(menuItems, menuBody, currentPath) {
@@ -1300,7 +2179,7 @@ function processMenuItems(menuItems, menuBody, currentPath) {
1300
2179
  link.active = true;
1301
2180
  link.classList.add('active');
1302
2181
  }
1303
- if (Array.isArray(page.files)) loadPage(page.path, page.files);
2182
+ if (Array.isArray(page.examples)) loadPage(page.path, page.examples, page.presets, page.baseScript);
1304
2183
  }
1305
2184
  });
1306
2185
  }
@@ -1322,6 +2201,20 @@ function processStaticItems(staticItems, menuBody, currentPath) {
1322
2201
  });
1323
2202
  }
1324
2203
 
2204
+ function requestActiveMenuScroll() {
2205
+ if (typeof window.scrollActiveMenuItemIntoView === 'function') {
2206
+ window.scrollActiveMenuItemIntoView();
2207
+ }
2208
+ }
2209
+
2210
+ function syncRenderedPresetFromLocation() {
2211
+ const { file, presetId } = getHashState();
2212
+ const targetFile = file || 'default';
2213
+
2214
+ const example = CONTENT_ELEMENT?.querySelector(`[data-example-file="${CSS.escape(targetFile)}"]`);
2215
+ example?._applyPresetFromUrl?.(presetId);
2216
+ }
2217
+
1325
2218
  // Liga eventos apenas se os elementos existirem
1326
2219
  if (COMPONENTS_FILTER) {
1327
2220
  COMPONENTS_FILTER.addEventListener('input', filterContent);
@@ -1340,6 +2233,8 @@ function loadPageFromURL() {
1340
2233
 
1341
2234
  // Evita recarregar a mesma rota em chamadas repetidas
1342
2235
  if (currentPath === currentLoadedPath) {
2236
+ syncRenderedPresetFromLocation();
2237
+ requestActiveMenuScroll();
1343
2238
  return;
1344
2239
  }
1345
2240
 
@@ -1358,9 +2253,9 @@ function loadPageFromURL() {
1358
2253
  processStaticItems(window.MENU_STATIC_ITEMS, menuBody, currentPath);
1359
2254
 
1360
2255
  if (currentPath.trim().length === 0 && menuItems.length > 0) {
1361
- const firstPage = menuItems.find((p) => p?.path && Array.isArray(p.files));
2256
+ const firstPage = menuItems.find((p) => p?.path && Array.isArray(p.examples));
1362
2257
  if (firstPage) {
1363
- loadPage(firstPage.path, firstPage.files);
2258
+ loadPage(firstPage.path, firstPage.examples, firstPage.presets, firstPage.baseScript);
1364
2259
  const firstLink = menuBody
1365
2260
  ? Array.from(menuBody.children).find((item) => item.getAttribute('href') === `/${firstPage.path}`)
1366
2261
  : null;
@@ -1371,6 +2266,8 @@ function loadPageFromURL() {
1371
2266
  window.history.pushState({}, '', `${baseUrl}/${firstPage.path}`);
1372
2267
  }
1373
2268
  }
2269
+
2270
+ requestActiveMenuScroll();
1374
2271
  }
1375
2272
 
1376
2273
  // Aguarda DOM e dados do menu antes de tentar carregar a rota atual
@@ -1408,15 +2305,18 @@ if (document.readyState === 'loading') {
1408
2305
  // Garante atualização ao navegar com back/forward
1409
2306
  window.addEventListener('popstate', () => bootstrapRouting());
1410
2307
 
2308
+ // O gerador do playground atualiza o índice enquanto o servidor permanece aberto.
2309
+ // Invalida a rota carregada para que os presets do JSON sejam lidos novamente.
2310
+ window.addEventListener('wbcMenuItemsUpdated', () => {
2311
+ currentLoadedPath = null;
2312
+ bootstrapRouting();
2313
+ });
2314
+
1411
2315
  window.addEventListener('hashchange', () => {
2316
+ syncRenderedPresetFromLocation();
1412
2317
  const file = getRequestedExampleFile();
1413
2318
  const example = file ? document.querySelector(`br-item[data-example-file="${CSS.escape(file)}"]`) : null;
1414
2319
  if (!example) return;
1415
2320
 
1416
- const dropdown = example.querySelector('br-dropdown');
1417
- if (dropdown) dropdown.isOpen = true;
1418
- document.querySelectorAll('.wbc-example-dropdown').forEach((other) => {
1419
- if (other !== dropdown) other.isOpen = false;
1420
- });
1421
- setTimeout(() => example.scrollIntoView({ behavior: 'smooth', block: 'center' }), 100);
2321
+ setTimeout(() => example.scrollIntoView({ behavior: getScrollBehavior(), block: 'center' }), 100);
1422
2322
  });