@brightspot/ui 5.0.3 → 5.1.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 (119) hide show
  1. package/dist/components/button-group/ButtonGroup.d.ts +7 -2
  2. package/dist/components/button-group/ButtonGroup.d.ts.map +1 -1
  3. package/dist/components/button-group/ButtonGroup.js +23 -16
  4. package/dist/components/button-group/ButtonGroup.js.map +1 -1
  5. package/dist/components/card/Card.css +7 -0
  6. package/dist/components/card/Card.d.ts +244 -0
  7. package/dist/components/card/Card.d.ts.map +1 -0
  8. package/dist/components/card/Card.js +512 -0
  9. package/dist/components/card/Card.js.map +1 -0
  10. package/dist/components/empty-state/EmptyState.d.ts +11 -2
  11. package/dist/components/empty-state/EmptyState.d.ts.map +1 -1
  12. package/dist/components/empty-state/EmptyState.js +19 -8
  13. package/dist/components/empty-state/EmptyState.js.map +1 -1
  14. package/dist/components/widget/Widget.d.ts +11 -2
  15. package/dist/components/widget/Widget.d.ts.map +1 -1
  16. package/dist/components/widget/Widget.js +21 -10
  17. package/dist/components/widget/Widget.js.map +1 -1
  18. package/dist/custom-elements.json +484 -0
  19. package/dist/storybook/assets/{ActionBar.stories-cyX9vc6C.js → ActionBar.stories-D9ok2eVg.js} +1 -1
  20. package/dist/storybook/assets/{ActionItem.stories-Bs-Kxp5J.js → ActionItem.stories-DjPfYpgA.js} +1 -1
  21. package/dist/storybook/assets/{Avatar.stories-B1Uee53f.js → Avatar.stories-Di3s5wxK.js} +1 -1
  22. package/dist/storybook/assets/{AvatarGroup.stories-W2EtKQBu.js → AvatarGroup.stories-CT7lYX_U.js} +1 -1
  23. package/dist/storybook/assets/{Badge.stories-BotNIO18.js → Badge.stories-9unZqfhH.js} +1 -1
  24. package/dist/storybook/assets/{Button-YTBnP55L.js → Button-DuuAvVjP.js} +1 -1
  25. package/dist/storybook/assets/{Button.stories-B-X7_d_i.js → Button.stories-KDBmJ9xt.js} +1 -1
  26. package/dist/storybook/assets/{ButtonGroup.stories-BM-pxfK2.js → ButtonGroup.stories-BeWYMkDy.js} +1 -1
  27. package/dist/storybook/assets/Card.stories-BNMJ-H5I.js +556 -0
  28. package/dist/storybook/assets/{Celebrate.stories-D9EJwzxo.js → Celebrate.stories-Cue8O4hb.js} +1 -1
  29. package/dist/storybook/assets/{Checkbox.stories-f5VLVSw5.js → Checkbox.stories-DLe4npId.js} +1 -1
  30. package/dist/storybook/assets/{CircularProgress.stories-BI9e372u.js → CircularProgress.stories-BHB2K82M.js} +1 -1
  31. package/dist/storybook/assets/{ClipboardMixin.stories-CsyJDNxc.js → ClipboardMixin.stories-mU-JGoHp.js} +1 -1
  32. package/dist/storybook/assets/{Color-6BZIO3FS-ClVOLIJG.js → Color-6BZIO3FS-D3GAvUXG.js} +1 -1
  33. package/dist/storybook/assets/{Colors.stories-hUYBvymM.js → Colors.stories-a83X2cLQ.js} +1 -1
  34. package/dist/storybook/assets/{CombinedEffects.stories-DkokyKCS.js → CombinedEffects.stories-sLTopxBQ.js} +1 -1
  35. package/dist/storybook/assets/{ComponentStatesMixin-C4I_rtgt.js → ComponentStatesMixin-CJ9pmXHc.js} +1 -1
  36. package/dist/storybook/assets/{ComponentStatesMixin.stories-BeLCYevK.js → ComponentStatesMixin.stories-DSkFzAxR.js} +1 -1
  37. package/dist/storybook/assets/{CopyToClipboard.stories-DN9oagz-.js → CopyToClipboard.stories-DqMxtd4b.js} +1 -1
  38. package/dist/storybook/assets/{Debounce.stories-CtNQAJxO.js → Debounce.stories-DV30whKw.js} +1 -1
  39. package/dist/storybook/assets/{DocsRenderer-LL677BLK-Bx1Fds2q.js → DocsRenderer-LL677BLK-DmVtYsJx.js} +3 -3
  40. package/dist/storybook/assets/{Dropdown.stories-B862-mco.js → Dropdown.stories-sCz8_Hkw.js} +1 -1
  41. package/dist/storybook/assets/{EmptyState.stories-Im3Vr4ZL.js → EmptyState.stories-kBKfr87C.js} +1 -1
  42. package/dist/storybook/assets/{Events.stories-B0tluV0t.js → Events.stories-BXdHEFJR.js} +1 -1
  43. package/dist/storybook/assets/{Heading.stories-6CzGqAAc.js → Heading.stories-B2XJMBD8.js} +1 -1
  44. package/dist/storybook/assets/{HueRipple.stories-DaQiDn9K.js → HueRipple.stories-BfzsAQYM.js} +1 -1
  45. package/dist/storybook/assets/{Icon.stories-CFkYO_7w.js → Icon.stories--pcHe1x-.js} +1 -1
  46. package/dist/storybook/assets/{IconButton.stories-DwBTqvTi.js → IconButton.stories-dbXfrgH3.js} +1 -1
  47. package/dist/storybook/assets/{LinearProgress.stories-Coxmgjmo.js → LinearProgress.stories-CApOBX0x.js} +1 -1
  48. package/dist/storybook/assets/OnFindMixin.stories-df6ckqw3.js +300 -0
  49. package/dist/storybook/assets/{Pagination.stories-CYrKX5iI.js → Pagination.stories-_MiDRipW.js} +1 -1
  50. package/dist/storybook/assets/{Popover.stories-BkGiUOfu.js → Popover.stories-9hVZFeMx.js} +1 -1
  51. package/dist/storybook/assets/{ReadyMixin-CP6tQ4FB.js → ReadyMixin-HHwtCrVi.js} +1 -1
  52. package/dist/storybook/assets/{RovingTabindexMixin.stories-CzkPw8Nl.js → RovingTabindexMixin.stories-B6MPGbVh.js} +1 -1
  53. package/dist/storybook/assets/{Rtc.stories-CVch488H.js → Rtc.stories-D3tZOSkM.js} +1 -1
  54. package/dist/storybook/assets/{ScrollShadow.stories-BGh-Irt7.js → ScrollShadow.stories-B1dTcJR4.js} +1 -1
  55. package/dist/storybook/assets/{Switch.stories-DPfP0QVK.js → Switch.stories-Bp-Guy3z.js} +1 -1
  56. package/dist/storybook/assets/{Tab.stories-CBcuRcDB.js → Tab.stories-Caxi7G_1.js} +1 -1
  57. package/dist/storybook/assets/{Tabs.stories-CDOBjYbs.js → Tabs.stories-g5Nb7YDi.js} +1 -1
  58. package/dist/storybook/assets/{Throttle.stories-Bqyul0aW.js → Throttle.stories-BzWv-mzN.js} +1 -1
  59. package/dist/storybook/assets/{Tooltip.stories-B9dohX1h.js → Tooltip.stories-BlaTc14X.js} +1 -1
  60. package/dist/storybook/assets/{Upload.stories-C7dq2Wdk.js → Upload.stories-a9edmUmW.js} +1 -1
  61. package/dist/storybook/assets/{UploadItem.stories-35zsIKTv.js → UploadItem.stories-BOIu5j_i.js} +1 -1
  62. package/dist/storybook/assets/{Welcome.stories-BuD3fpke.js → Welcome.stories-D33npbIl.js} +1 -1
  63. package/dist/storybook/assets/{Widget.stories-D2UYzfyE.js → Widget.stories-D0vHPAyP.js} +1 -1
  64. package/dist/storybook/assets/{WithTooltip-65CFNBJE-DGiY8cz9.js → WithTooltip-65CFNBJE-WOhnQufs.js} +1 -1
  65. package/dist/storybook/assets/{blocks-YjKl5E55.js → blocks-B17JEOI8.js} +5 -5
  66. package/dist/storybook/assets/{formatter-EIJCOSYU-XYAiuXAN.js → formatter-EIJCOSYU-QKmiwKu7.js} +1 -1
  67. package/dist/storybook/assets/if-defined-0srVwUDm.js +1 -0
  68. package/dist/storybook/assets/{iframe-CufEXQ5F.js → iframe-BqpRijx3.js} +225 -225
  69. package/dist/storybook/assets/iframe-DfU9RLLj.css +1 -0
  70. package/dist/storybook/assets/{index-DbEDIsEB.js → index-CpksO7cK.js} +1 -1
  71. package/dist/storybook/assets/onFind-C_VPLxg8.js +1 -0
  72. package/dist/storybook/assets/{onFind.stories-UpwJxFqR.js → onFind.stories-BuZMC3tk.js} +15 -15
  73. package/dist/storybook/assets/{onRemove.stories-BMwQGBCl.js → onRemove.stories-HDkMhdmO.js} +1 -1
  74. package/dist/storybook/assets/{onVisible.stories-axSo0Zv3.js → onVisible.stories-CRCllRfN.js} +1 -1
  75. package/dist/storybook/assets/{style-map-BkaK9546.js → style-map-DukvFNCc.js} +1 -1
  76. package/dist/storybook/assets/{syntaxhighlighter-ED5Y7EFY-CDDZTVRn.js → syntaxhighlighter-ED5Y7EFY-BUo_WYvV.js} +1 -1
  77. package/dist/storybook/iframe.html +48 -2
  78. package/dist/storybook/index.json +1 -1
  79. package/dist/storybook/project.json +1 -1
  80. package/dist/tailwind-plugin-card.d.ts +2 -0
  81. package/dist/tailwind-plugin-card.d.ts.map +1 -0
  82. package/dist/tailwind-plugin-card.js +438 -0
  83. package/dist/tailwind-plugin-card.js.map +1 -0
  84. package/dist/tailwind-plugin-card.ts +515 -0
  85. package/dist/tailwind.config.d.ts.map +1 -1
  86. package/dist/tailwind.config.js +2 -0
  87. package/dist/tailwind.config.js.map +1 -1
  88. package/dist/tailwind.config.ts +2 -0
  89. package/dist/util/EventEmitterMixin.d.ts +1 -0
  90. package/dist/util/EventEmitterMixin.d.ts.map +1 -1
  91. package/dist/util/EventEmitterMixin.js.map +1 -1
  92. package/dist/util/OnFindMixin.d.ts +55 -0
  93. package/dist/util/OnFindMixin.d.ts.map +1 -0
  94. package/dist/util/OnFindMixin.js +70 -0
  95. package/dist/util/OnFindMixin.js.map +1 -0
  96. package/dist/util/onFind.d.ts +4 -2
  97. package/dist/util/onFind.d.ts.map +1 -1
  98. package/dist/util/onFind.js +12 -0
  99. package/dist/util/onFind.js.map +1 -1
  100. package/docs/components/ButtonGroup.md +7 -3
  101. package/docs/components/Card.md +83 -0
  102. package/docs/components/EmptyState.md +10 -6
  103. package/docs/components/README.md +1 -0
  104. package/docs/components/Widget.md +18 -14
  105. package/package.json +1 -1
  106. package/src/legacy/tool-ui/src/AIInline.css +1 -1
  107. package/src/legacy/tool-ui/src/SearchWidget.ts +10 -1
  108. package/src/legacy/tool-ui/src/main/webapp/dist/{RTEProseMirror.945bd28778b1a3e937c7.js → RTEProseMirror.e8344eaeea387c600257.js} +12 -12
  109. package/src/legacy/tool-ui/src/main/webapp/dist/{v4.c5bcef50efdfa2d2e35f.js → v4.b892feb8ec199202fd18.js} +4 -4
  110. package/src/legacy/tool-ui/src/main/webapp/dist/{v5.86effb9bf858ae7b0640.js → v5.493c3ddf65c4fa599ff0.js} +4 -4
  111. package/src/legacy/tool-ui/src/main/webapp/dist/v5.d49a759cb0b7cffd76e4.css +5 -0
  112. package/src/legacy/tool-ui/src/v5.ts +3 -1
  113. package/dist/storybook/assets/if-defined-f_e-RnGa.js +0 -1
  114. package/dist/storybook/assets/iframe-PeGbyIdX.css +0 -1
  115. package/dist/storybook/assets/onFind-C7Wi8jr6.js +0 -1
  116. package/src/legacy/tool-ui/src/main/webapp/dist/v5.f60c05ef0c9b89aae888.css +0 -5
  117. /package/src/legacy/tool-ui/src/main/webapp/dist/{RTEProseMirror.945bd28778b1a3e937c7.js.LICENSE.txt → RTEProseMirror.e8344eaeea387c600257.js.LICENSE.txt} +0 -0
  118. /package/src/legacy/tool-ui/src/main/webapp/dist/{v4.c5bcef50efdfa2d2e35f.js.LICENSE.txt → v4.b892feb8ec199202fd18.js.LICENSE.txt} +0 -0
  119. /package/src/legacy/tool-ui/src/main/webapp/dist/{v5.86effb9bf858ae7b0640.js.LICENSE.txt → v5.493c3ddf65c4fa599ff0.js.LICENSE.txt} +0 -0
@@ -1,4 +1,4 @@
1
- import{g as S,x as t}from"./iframe-CufEXQ5F.js";import{o as f}from"./style-map-BkaK9546.js";import"./preload-helper-PPVm8Dsz.js";const{events:O,args:A,argTypes:n}=S("btu-dropdown"),B={title:"Components/Dropdown",component:"btu-dropdown",tags:["autodocs"],parameters:{docs:{subtitle:"btu-dropdown",description:{component:`
1
+ import{g as S,x as t}from"./iframe-BqpRijx3.js";import{o as f}from"./style-map-DukvFNCc.js";import"./preload-helper-PPVm8Dsz.js";const{events:O,args:A,argTypes:n}=S("btu-dropdown"),B={title:"Components/Dropdown",component:"btu-dropdown",tags:["autodocs"],parameters:{docs:{subtitle:"btu-dropdown",description:{component:`
2
2
  A dropdown menu component that renders a trigger button and manages a floating panel
3
3
  containing a \`btu-dropdown-menu\` with \`btu-dropdown-item\` children.
4
4
 
@@ -1,4 +1,4 @@
1
- import{g as u,x as e}from"./iframe-CufEXQ5F.js";import{o as m}from"./if-defined-f_e-RnGa.js";import{o as h}from"./style-map-BkaK9546.js";import"./preload-helper-PPVm8Dsz.js";const{events:b,args:g,argTypes:s}=u("btu-empty-state"),y=["sm","md","lg"],v=[1,2,3,4,5,6],k={title:"Components/Empty State",component:"btu-empty-state",tags:["autodocs"],parameters:{docs:{subtitle:"A standardized component for communicating the absence of content.",description:{component:`
1
+ import{g as u,x as e}from"./iframe-BqpRijx3.js";import{o as m}from"./if-defined-0srVwUDm.js";import{o as h}from"./style-map-DukvFNCc.js";import"./preload-helper-PPVm8Dsz.js";const{events:b,args:g,argTypes:s}=u("btu-empty-state"),y=["sm","md","lg"],v=[1,2,3,4,5,6],k={title:"Components/Empty State",component:"btu-empty-state",tags:["autodocs"],parameters:{docs:{subtitle:"A standardized component for communicating the absence of content.",description:{component:`
2
2
  <h3>When to use:</h3>
3
3
  <ul>
4
4
  <li>To communicate the absence of content in tables, lists, or search results</li>
@@ -1,4 +1,4 @@
1
- import{x as d}from"./iframe-CufEXQ5F.js";import"./preload-helper-PPVm8Dsz.js";var n=Object.freeze,r=Object.defineProperty,s=(t,i)=>n(r(t,"raw",{value:n(t.slice())})),o;const l={title:"Mixins/Events",tags:["autodocs"],parameters:{docs:{subtitle:"Events inherited from EventEmitterMixin",description:{component:`
1
+ import{x as d}from"./iframe-BqpRijx3.js";import"./preload-helper-PPVm8Dsz.js";var n=Object.freeze,r=Object.defineProperty,s=(t,i)=>n(r(t,"raw",{value:n(t.slice())})),o;const l={title:"Mixins/Events",tags:["autodocs"],parameters:{docs:{subtitle:"Events inherited from EventEmitterMixin",description:{component:`
2
2
  <h3>EventEmitterMixin Events</h3>
3
3
 
4
4
  <p>All Brightspot UI components that extend EventEmitterMixin emit the following lifecycle events in addition to those inherited from LitElement. These events use CustomEvent and bubble through the DOM with <code>composed: true</code>, meaning they cross shadow DOM boundaries.</p>
@@ -1,3 +1,3 @@
1
- import{x as s}from"./iframe-CufEXQ5F.js";import"./preload-helper-PPVm8Dsz.js";const r=({size:t})=>s` <div class=${[`btu-heading-${t}`].join(" ")}>Heading</div> `,o={title:"CSS Plugins/Heading",component:"btu-heading",tags:["autodocs"],parameters:{docs:{subtitle:"This Tailwind CSS plugin provides the `.btu-heading` utility class for styling headings. It supports five different sizes, from 1 (largest) to 5 (smallest). Apply the class to `<h1>` through `<h5>` elements to style them accordingly."},controls:{expanded:!0}},render:t=>r(t),argTypes:{size:{control:{type:"range",min:1,max:5,step:1},description:"Heading size from 1 to 5, where 1 is the largest and 5 is the smallest."}},args:{size:1}},e={args:{}};e.parameters={...e.parameters,docs:{...e.parameters?.docs,source:{originalSource:`{
1
+ import{x as s}from"./iframe-BqpRijx3.js";import"./preload-helper-PPVm8Dsz.js";const r=({size:t})=>s` <div class=${[`btu-heading-${t}`].join(" ")}>Heading</div> `,o={title:"CSS Plugins/Heading",component:"btu-heading",tags:["autodocs"],parameters:{docs:{subtitle:"This Tailwind CSS plugin provides the `.btu-heading` utility class for styling headings. It supports five different sizes, from 1 (largest) to 5 (smallest). Apply the class to `<h1>` through `<h5>` elements to style them accordingly."},controls:{expanded:!0}},render:t=>r(t),argTypes:{size:{control:{type:"range",min:1,max:5,step:1},description:"Heading size from 1 to 5, where 1 is the largest and 5 is the smallest."}},args:{size:1}},e={args:{}};e.parameters={...e.parameters,docs:{...e.parameters?.docs,source:{originalSource:`{
2
2
  args: {}
3
3
  }`,...e.parameters?.docs?.source}}};const n=["Default"];export{e as Default,n as __namedExportsOrder,o as default};
@@ -1,4 +1,4 @@
1
- import{x as i}from"./iframe-CufEXQ5F.js";import{b as l}from"./ripple-DQbyyRUw.js";import{B as e}from"./Button-YTBnP55L.js";import"./preload-helper-PPVm8Dsz.js";import"./position-CFNQy3J6.js";const m={title:"Effects/Hue Ripple",tags:["autodocs"],parameters:{docs:{subtitle:"Click anywhere to send a hue-shifting ripple across the viewport",description:{component:`
1
+ import{x as i}from"./iframe-BqpRijx3.js";import{b as l}from"./ripple-DQbyyRUw.js";import{B as e}from"./Button-DuuAvVjP.js";import"./preload-helper-PPVm8Dsz.js";import"./position-CFNQy3J6.js";const m={title:"Effects/Hue Ripple",tags:["autodocs"],parameters:{docs:{subtitle:"Click anywhere to send a hue-shifting ripple across the viewport",description:{component:`
2
2
  Uses the **View Transition API** to create an expanding ring that reveals OKLCH-shifted colors as it sweeps past each element, then they return to normal.
3
3
 
4
4
  ### Usage
@@ -1,4 +1,4 @@
1
- import{g,x as s}from"./iframe-CufEXQ5F.js";import{o as h}from"./style-map-BkaK9546.js";import{L as u}from"./LucideDynamicLoader-jmdq8YDM.js";import"./preload-helper-PPVm8Dsz.js";const{events:x,args:v,argTypes:i}=g("btu-icon"),b=["xs","sm","md","lg","xl"],f=["ai","error","gray","primary","purple","rose","success","teal","warning"],C={title:"Components/Icon",component:"btu-icon",tags:["autodocs"],parameters:{docs:{subtitle:"An icon component using Lucide icons with built-in support for custom colors and sizes.",description:{component:`
1
+ import{g,x as s}from"./iframe-BqpRijx3.js";import{o as h}from"./style-map-DukvFNCc.js";import{L as u}from"./LucideDynamicLoader-jmdq8YDM.js";import"./preload-helper-PPVm8Dsz.js";const{events:x,args:v,argTypes:i}=g("btu-icon"),b=["xs","sm","md","lg","xl"],f=["ai","error","gray","primary","purple","rose","success","teal","warning"],C={title:"Components/Icon",component:"btu-icon",tags:["autodocs"],parameters:{docs:{subtitle:"An icon component using Lucide icons with built-in support for custom colors and sizes.",description:{component:`
2
2
  <strong>When to use:</strong>
3
3
  <ul>
4
4
  <li>To visually reinforce actions, states, or categories</li>
@@ -1,4 +1,4 @@
1
- import{g as p,x as e}from"./iframe-CufEXQ5F.js";import{o as b}from"./if-defined-f_e-RnGa.js";import{L as d}from"./LucideDynamicLoader-jmdq8YDM.js";import"./preload-helper-PPVm8Dsz.js";const{events:u,args:y,argTypes:o}=p("btu-icon-button"),x={title:"Components/Icon Button",component:"btu-icon-button",tags:["autodocs"],parameters:{docs:{subtitle:"Combines button styles with the icon component along with an opinionated API",description:{component:`
1
+ import{g as p,x as e}from"./iframe-BqpRijx3.js";import{o as b}from"./if-defined-0srVwUDm.js";import{L as d}from"./LucideDynamicLoader-jmdq8YDM.js";import"./preload-helper-PPVm8Dsz.js";const{events:u,args:y,argTypes:o}=p("btu-icon-button"),x={title:"Components/Icon Button",component:"btu-icon-button",tags:["autodocs"],parameters:{docs:{subtitle:"Combines button styles with the icon component along with an opinionated API",description:{component:`
2
2
  <h3>When to use:</h3>
3
3
  <ul>
4
4
  <li>For actions in compact or space-constrained interfaces (toolbars, tables, cards)</li>
@@ -1,4 +1,4 @@
1
- import{g as D,E as h,x as T}from"./iframe-CufEXQ5F.js";import{o as A}from"./style-map-BkaK9546.js";import"./preload-helper-PPVm8Dsz.js";const{events:V,args:k,argTypes:g}=D("btu-linear-progress"),W={title:"Components/Linear Progress",component:"btu-linear-progress",tags:["autodocs"],parameters:{docs:{subtitle:"A horizontal progress bar for showing task completion",description:{component:`
1
+ import{g as D,E as h,x as T}from"./iframe-BqpRijx3.js";import{o as A}from"./style-map-DukvFNCc.js";import"./preload-helper-PPVm8Dsz.js";const{events:V,args:k,argTypes:g}=D("btu-linear-progress"),W={title:"Components/Linear Progress",component:"btu-linear-progress",tags:["autodocs"],parameters:{docs:{subtitle:"A horizontal progress bar for showing task completion",description:{component:`
2
2
  <h3>When to use:</h3>
3
3
  <ul>
4
4
  <li>To show progress of a specific task with known completion percentage</li>
@@ -0,0 +1,300 @@
1
+ import{x as h,i as v}from"./iframe-BqpRijx3.js";import{o as k}from"./onFind-C_VPLxg8.js";import"./preload-helper-PPVm8Dsz.js";const x=e=>{class n extends e{#t=[];onFindRegistration(){return null}#e(){if(this.#t.length)return;const i=this.onFindRegistration();if(!i)return;const d=Array.isArray(i)?i:[i];this.#t=d.map(c=>k(this,c.selectors,c.callback))}connectedCallback(){super.connectedCallback(),this.hasUpdated&&this.#e()}firstUpdated(i){super.firstUpdated(i),this.#e()}disconnectedCallback(){super.disconnectedCallback(),this.#t.forEach(i=>i()),this.#t=[]}}return n},{expect:a,userEvent:l,waitFor:r,within:w}=__STORYBOOK_MODULE_TEST__,b="ofm-demo";if(!customElements.get(b)){class e extends x(v){onFindRegistration(){return{selectors:":scope > .ofm-item",callback:t=>t.classList.add("ring-2","ring-success-500")}}render(){return h`<slot></slot>`}}customElements.define(b,e)}const p="ofm-multi";if(!customElements.get(p)){class e extends x(v){onFindRegistration(){return[{selectors:":scope > .ofm-a",callback:t=>t.classList.add("ring-2","ring-success-500")},{selectors:":scope > .ofm-b",callback:t=>t.classList.add("ring-2","ring-primary-500")}]}render(){return h`<slot></slot>`}}customElements.define(p,e)}function g(){return globalThis[Symbol.for("brightspot.onFind")]?.callbacks?.length??0}const M={title:"Mixins/OnFind Mixin",tags:["autodocs"],parameters:{docs:{description:{component:`
2
+ \`OnFindMixin\` registers an \`onFind\` child-redistribution callback and
3
+ **tears it down on disconnect**, so a detached component is garbage-collectable
4
+ and stops being visited on every document mutation.
5
+
6
+ \`onFind\` is backed by a single global \`MutationObserver\` and a global list of
7
+ callbacks. A component that registers a callback but never removes it keeps
8
+ itself reachable forever and adds permanent per-mutation work. This mixin owns
9
+ that lifecycle so individual components don't have to hand-wire it.
10
+
11
+ <h3>What OnFindMixin Does</h3>
12
+ <ul>
13
+ <li>Registers the component's \`onFind\` callback after first render (in \`firstUpdated\`).</li>
14
+ <li>Disposes the registration in \`disconnectedCallback\` so a removed component can be GC'd.</li>
15
+ <li>Re-arms the registration on reattach — \`firstUpdated\` only fires once, so \`connectedCallback\` re-registers when \`hasUpdated\` is true.</li>
16
+ <li>Stays idempotent: arming while already registered is a no-op.</li>
17
+ </ul>
18
+
19
+ <h3>The Contract</h3>
20
+ <p>A component declares <b>what</b> to register by implementing
21
+ \`onFindRegistration()\`, which returns <code>{ selectors, callback }</code>,
22
+ \`null\` to skip (e.g. when required containers aren't present yet), or an
23
+ <b>array</b> of registrations for several independent sweeps (all disposed
24
+ together on disconnect). It is re-invoked on every registration, so query
25
+ containers <b>inside</b> it rather than capturing them once — a reattach then
26
+ re-binds against the current DOM.</p>
27
+
28
+ <p>The <code>callback</code> must be <b>idempotent</b>: on reattach the mixin
29
+ re-runs \`onFind\`'s initial sweep, so it may be called again for a child that is
30
+ already placed.</p>
31
+
32
+ <p>Subclasses that override \`firstUpdated\` <b>must</b> call
33
+ \`super.firstUpdated()\`, or the initial registration never runs.</p>
34
+
35
+ <h3>Mixin Composition</h3>
36
+
37
+ <p>Place OnFindMixin near the base, just outside ReadyMixin, so it inherits the
38
+ DOM-ready guarantee:</p>
39
+
40
+ <p> ✅ Correct
41
+ EventEmitterMixin(OnFindMixin(ReadyMixin(LitElement)))</p>
42
+
43
+ <h3>Usage</h3>
44
+ \`\`\`typescript
45
+ import { OnFindMixin } from './OnFindMixin'
46
+
47
+ class Card extends OnFindMixin(ReadyMixin(LitElement)) {
48
+ firstUpdated(changed) {
49
+ super.firstUpdated(changed) // arms onFind
50
+ this.emit('btu-card-ready')
51
+ }
52
+
53
+ onFindRegistration() {
54
+ return {
55
+ selectors: ':scope > [slot], :scope > img, :scope > btu-badge, :scope > btu-icon',
56
+ callback: el => this.redistributeChild(el),
57
+ }
58
+ }
59
+ }
60
+ \`\`\`
61
+ `}}}},u={render:()=>{const e=`ofm-${Math.random().toString(36).slice(2,8)}`,n=g();let t=null,i=0;const d=()=>requestAnimationFrame(()=>{const s=document.getElementById(`${e}-count`);s&&(s.textContent=String(g()-n))}),c=()=>{i++;const s=document.createElement("div");return s.className="ofm-item rounded border bg-white p-3 text-sm",s.textContent=`Child ${i}`,s};return h`
62
+ <div class="space-y-4">
63
+ <p class="text-base">
64
+ The element below uses <code>OnFindMixin</code>. <strong>Mount</strong> registers its onFind callback;
65
+ <strong>Unmount</strong> disposes it (no leak); mounting again re-arms it. Watch the global callback count
66
+ rise to 1 on mount and fall back to 0 on unmount. <strong>Add child</strong> shows onFind still detecting and
67
+ highlighting children added at runtime.
68
+ </p>
69
+
70
+ <div class="flex gap-2">
71
+ <button data-testid="mount" @click=${()=>{const s=document.getElementById(`${e}-stage`);s&&(t||(t=document.createElement(b),t.append(c(),c())),t.isConnected||s.appendChild(t),d())}} class="btu-button btu-button-primary btu-button-sm">Mount</button>
72
+ <button data-testid="unmount" @click=${()=>{t?.remove(),d()}} class="btu-button btu-button-gray btu-button-sm">
73
+ Unmount
74
+ </button>
75
+ <button data-testid="add-child" @click=${()=>{t?.isConnected&&t.appendChild(c())}} class="btu-button btu-button-gray btu-button-sm">
76
+ Add child
77
+ </button>
78
+ </div>
79
+
80
+ <div id="${e}-stage" class="min-h-32 space-y-2 rounded border-2 border-gray-300 bg-gray-50 p-4">
81
+ <div class="text-sm text-gray-500">Mount the component to see its children detected and highlighted…</div>
82
+ </div>
83
+
84
+ <div>
85
+ <div class="text-xs text-gray-500">onFind callbacks registered by this demo</div>
86
+ <div data-testid="count" id="${e}-count" class="text-2xl font-bold text-primary-600">0</div>
87
+ </div>
88
+ </div>
89
+ `},parameters:{docs:{description:{story:'Live demo of the OnFindMixin lifecycle. Mounting registers an onFind callback (count → 1), unmounting disposes it (count → 0, so the detached element is collectable), and mounting again re-arms it. "Add child" shows onFind continuing to detect and highlight children added at runtime.'}}},play:async({canvasElement:e,step:n})=>{const t=w(e);await n("Mount registers a callback",async()=>{await l.click(t.getByTestId("mount")),await r(()=>a(t.getByTestId("count")).toHaveTextContent("1"))}),await n("Unmount disposes it (no leak)",async()=>{await l.click(t.getByTestId("unmount")),await r(()=>a(t.getByTestId("count")).toHaveTextContent("0"))}),await n("Re-mount re-arms it",async()=>{await l.click(t.getByTestId("mount")),await r(()=>a(t.getByTestId("count")).toHaveTextContent("1"))})}},m={render:()=>{const e=`ofm-multi-${Math.random().toString(36).slice(2,8)}`,n=g();let t=null;const i=()=>requestAnimationFrame(()=>{const o=document.getElementById(`${e}-count`);o&&(o.textContent=String(g()-n))}),d=(o,y)=>{const s=document.createElement("div");return s.className=`${o} rounded border bg-white p-3 text-sm`,s.textContent=y,s};return h`
90
+ <div class="space-y-4">
91
+ <p class="text-base">
92
+ This element registers <strong>two</strong> independent onFind sweeps via an array (<code
93
+ >onFindRegistration</code
94
+ >
95
+ returns <code>[A, B]</code>). Mounting registers both (count → 2), unmounting disposes both together (count →
96
+ 0), and each sweep highlights only its own child type.
97
+ </p>
98
+
99
+ <div class="flex gap-2">
100
+ <button data-testid="multi-mount" @click=${()=>{const o=document.getElementById(`${e}-stage`);o&&(t||(t=document.createElement(p),t.append(d("ofm-a","Sweep A child"),d("ofm-b","Sweep B child"))),t.isConnected||o.appendChild(t),i())}} class="btu-button btu-button-primary btu-button-sm">
101
+ Mount
102
+ </button>
103
+ <button data-testid="multi-unmount" @click=${()=>{t?.remove(),i()}} class="btu-button btu-button-gray btu-button-sm">
104
+ Unmount
105
+ </button>
106
+ </div>
107
+
108
+ <div id="${e}-stage" class="min-h-32 space-y-2 rounded border-2 border-gray-300 bg-gray-50 p-4">
109
+ <div class="text-sm text-gray-500">Mount to see both sweeps register and highlight their children…</div>
110
+ </div>
111
+
112
+ <div>
113
+ <div class="text-xs text-gray-500">onFind callbacks registered by this demo</div>
114
+ <div data-testid="multi-count" id="${e}-count" class="text-2xl font-bold text-primary-600">0</div>
115
+ </div>
116
+ </div>
117
+ `},parameters:{docs:{description:{story:"Exercises the array form of onFindRegistration: one element registers two independent sweeps. Mounting registers both callbacks (count → 2), each sweep highlights only its own child type, and unmounting disposes both together (count → 0)."}}},play:async({canvasElement:e,step:n})=>{const t=w(e);await n("Mount registers both sweeps",async()=>{await l.click(t.getByTestId("multi-mount")),await r(()=>a(t.getByTestId("multi-count")).toHaveTextContent("2"))}),await n("Each sweep detects its own children",async()=>{await r(()=>{a(e.querySelector(".ofm-a.ring-2")).toBeTruthy(),a(e.querySelector(".ofm-b.ring-2")).toBeTruthy()})}),await n("Unmount disposes both",async()=>{await l.click(t.getByTestId("multi-unmount")),await r(()=>a(t.getByTestId("multi-count")).toHaveTextContent("0"))}),await n("Re-mount re-arms both",async()=>{await l.click(t.getByTestId("multi-mount")),await r(()=>a(t.getByTestId("multi-count")).toHaveTextContent("2"))})}};u.parameters={...u.parameters,docs:{...u.parameters?.docs,source:{originalSource:`{
118
+ render: () => {
119
+ const id = \`ofm-\${Math.random().toString(36).slice(2, 8)}\`;
120
+ const baseline = onFindCallbackCount();
121
+ let demoEl: HTMLElement | null = null;
122
+ let childN = 0;
123
+ const refresh = () => requestAnimationFrame(() => {
124
+ const el = document.getElementById(\`\${id}-count\`);
125
+ if (el) el.textContent = String(onFindCallbackCount() - baseline);
126
+ });
127
+ const makeChild = () => {
128
+ childN++;
129
+ const c = document.createElement('div');
130
+ c.className = 'ofm-item rounded border bg-white p-3 text-sm';
131
+ c.textContent = \`Child \${childN}\`;
132
+ return c;
133
+ };
134
+
135
+ // Mount creates the element on first use, or re-attaches the same detached
136
+ // instance afterwards — that re-attach is what exercises the mixin's reattach
137
+ // re-arm path.
138
+ const mount = () => {
139
+ const stage = document.getElementById(\`\${id}-stage\`);
140
+ if (!stage) return;
141
+ if (!demoEl) {
142
+ demoEl = document.createElement(DEMO_TAG);
143
+ demoEl.append(makeChild(), makeChild());
144
+ }
145
+ if (!demoEl.isConnected) stage.appendChild(demoEl);
146
+ refresh();
147
+ };
148
+ const unmount = () => {
149
+ demoEl?.remove();
150
+ refresh();
151
+ };
152
+ const addChild = () => {
153
+ if (demoEl?.isConnected) demoEl.appendChild(makeChild());
154
+ };
155
+ return html\`
156
+ <div class="space-y-4">
157
+ <p class="text-base">
158
+ The element below uses <code>OnFindMixin</code>. <strong>Mount</strong> registers its onFind callback;
159
+ <strong>Unmount</strong> disposes it (no leak); mounting again re-arms it. Watch the global callback count
160
+ rise to 1 on mount and fall back to 0 on unmount. <strong>Add child</strong> shows onFind still detecting and
161
+ highlighting children added at runtime.
162
+ </p>
163
+
164
+ <div class="flex gap-2">
165
+ <button data-testid="mount" @click=\${mount} class="btu-button btu-button-primary btu-button-sm">Mount</button>
166
+ <button data-testid="unmount" @click=\${unmount} class="btu-button btu-button-gray btu-button-sm">
167
+ Unmount
168
+ </button>
169
+ <button data-testid="add-child" @click=\${addChild} class="btu-button btu-button-gray btu-button-sm">
170
+ Add child
171
+ </button>
172
+ </div>
173
+
174
+ <div id="\${id}-stage" class="min-h-32 space-y-2 rounded border-2 border-gray-300 bg-gray-50 p-4">
175
+ <div class="text-sm text-gray-500">Mount the component to see its children detected and highlighted…</div>
176
+ </div>
177
+
178
+ <div>
179
+ <div class="text-xs text-gray-500">onFind callbacks registered by this demo</div>
180
+ <div data-testid="count" id="\${id}-count" class="text-2xl font-bold text-primary-600">0</div>
181
+ </div>
182
+ </div>
183
+ \`;
184
+ },
185
+ parameters: {
186
+ docs: {
187
+ description: {
188
+ story: 'Live demo of the OnFindMixin lifecycle. Mounting registers an onFind callback (count → 1), unmounting disposes it (count → 0, so the detached element is collectable), and mounting again re-arms it. "Add child" shows onFind continuing to detect and highlight children added at runtime.'
189
+ }
190
+ }
191
+ },
192
+ play: async ({
193
+ canvasElement,
194
+ step
195
+ }) => {
196
+ const canvas = within(canvasElement);
197
+ await step('Mount registers a callback', async () => {
198
+ await userEvent.click(canvas.getByTestId('mount'));
199
+ await waitFor(() => expect(canvas.getByTestId('count')).toHaveTextContent('1'));
200
+ });
201
+ await step('Unmount disposes it (no leak)', async () => {
202
+ await userEvent.click(canvas.getByTestId('unmount'));
203
+ await waitFor(() => expect(canvas.getByTestId('count')).toHaveTextContent('0'));
204
+ });
205
+ await step('Re-mount re-arms it', async () => {
206
+ await userEvent.click(canvas.getByTestId('mount'));
207
+ await waitFor(() => expect(canvas.getByTestId('count')).toHaveTextContent('1'));
208
+ });
209
+ }
210
+ }`,...u.parameters?.docs?.source}}};m.parameters={...m.parameters,docs:{...m.parameters?.docs,source:{originalSource:`{
211
+ render: () => {
212
+ const id = \`ofm-multi-\${Math.random().toString(36).slice(2, 8)}\`;
213
+ const baseline = onFindCallbackCount();
214
+ let demoEl: HTMLElement | null = null;
215
+ const refresh = () => requestAnimationFrame(() => {
216
+ const el = document.getElementById(\`\${id}-count\`);
217
+ if (el) el.textContent = String(onFindCallbackCount() - baseline);
218
+ });
219
+ const makeChild = (cls: string, label: string) => {
220
+ const c = document.createElement('div');
221
+ c.className = \`\${cls} rounded border bg-white p-3 text-sm\`;
222
+ c.textContent = label;
223
+ return c;
224
+ };
225
+ const mount = () => {
226
+ const stage = document.getElementById(\`\${id}-stage\`);
227
+ if (!stage) return;
228
+ if (!demoEl) {
229
+ demoEl = document.createElement(MULTI_TAG);
230
+ demoEl.append(makeChild('ofm-a', 'Sweep A child'), makeChild('ofm-b', 'Sweep B child'));
231
+ }
232
+ if (!demoEl.isConnected) stage.appendChild(demoEl);
233
+ refresh();
234
+ };
235
+ const unmount = () => {
236
+ demoEl?.remove();
237
+ refresh();
238
+ };
239
+ return html\`
240
+ <div class="space-y-4">
241
+ <p class="text-base">
242
+ This element registers <strong>two</strong> independent onFind sweeps via an array (<code
243
+ >onFindRegistration</code
244
+ >
245
+ returns <code>[A, B]</code>). Mounting registers both (count → 2), unmounting disposes both together (count →
246
+ 0), and each sweep highlights only its own child type.
247
+ </p>
248
+
249
+ <div class="flex gap-2">
250
+ <button data-testid="multi-mount" @click=\${mount} class="btu-button btu-button-primary btu-button-sm">
251
+ Mount
252
+ </button>
253
+ <button data-testid="multi-unmount" @click=\${unmount} class="btu-button btu-button-gray btu-button-sm">
254
+ Unmount
255
+ </button>
256
+ </div>
257
+
258
+ <div id="\${id}-stage" class="min-h-32 space-y-2 rounded border-2 border-gray-300 bg-gray-50 p-4">
259
+ <div class="text-sm text-gray-500">Mount to see both sweeps register and highlight their children…</div>
260
+ </div>
261
+
262
+ <div>
263
+ <div class="text-xs text-gray-500">onFind callbacks registered by this demo</div>
264
+ <div data-testid="multi-count" id="\${id}-count" class="text-2xl font-bold text-primary-600">0</div>
265
+ </div>
266
+ </div>
267
+ \`;
268
+ },
269
+ parameters: {
270
+ docs: {
271
+ description: {
272
+ story: 'Exercises the array form of onFindRegistration: one element registers two independent sweeps. Mounting registers both callbacks (count → 2), each sweep highlights only its own child type, and unmounting disposes both together (count → 0).'
273
+ }
274
+ }
275
+ },
276
+ play: async ({
277
+ canvasElement,
278
+ step
279
+ }) => {
280
+ const canvas = within(canvasElement);
281
+ await step('Mount registers both sweeps', async () => {
282
+ await userEvent.click(canvas.getByTestId('multi-mount'));
283
+ await waitFor(() => expect(canvas.getByTestId('multi-count')).toHaveTextContent('2'));
284
+ });
285
+ await step('Each sweep detects its own children', async () => {
286
+ await waitFor(() => {
287
+ expect(canvasElement.querySelector('.ofm-a.ring-2')).toBeTruthy();
288
+ expect(canvasElement.querySelector('.ofm-b.ring-2')).toBeTruthy();
289
+ });
290
+ });
291
+ await step('Unmount disposes both', async () => {
292
+ await userEvent.click(canvas.getByTestId('multi-unmount'));
293
+ await waitFor(() => expect(canvas.getByTestId('multi-count')).toHaveTextContent('0'));
294
+ });
295
+ await step('Re-mount re-arms both', async () => {
296
+ await userEvent.click(canvas.getByTestId('multi-mount'));
297
+ await waitFor(() => expect(canvas.getByTestId('multi-count')).toHaveTextContent('2'));
298
+ });
299
+ }
300
+ }`,...m.parameters?.docs?.source}}};const T=["Demo","MultipleSweeps"];export{u as Demo,m as MultipleSweeps,T as __namedExportsOrder,M as default};
@@ -1,4 +1,4 @@
1
- import{g as m,x as u}from"./iframe-CufEXQ5F.js";import{o as g}from"./style-map-BkaK9546.js";import"./preload-helper-PPVm8Dsz.js";const{events:b,args:h,argTypes:y}=m("btu-pagination"),c=e=>{const t={};return e.customBackgroundColor&&(t["--pagination-color-background"]=e.customBackgroundColor),e.customForegroundColor&&(t["--pagination-color-foreground"]=e.customForegroundColor),t},$={title:"Components/Pagination",component:"btu-pagination",tags:["autodocs"],parameters:{docs:{subtitle:"A component for navigating through paged content",description:{component:`
1
+ import{g as m,x as u}from"./iframe-BqpRijx3.js";import{o as g}from"./style-map-DukvFNCc.js";import"./preload-helper-PPVm8Dsz.js";const{events:b,args:h,argTypes:y}=m("btu-pagination"),c=e=>{const t={};return e.customBackgroundColor&&(t["--pagination-color-background"]=e.customBackgroundColor),e.customForegroundColor&&(t["--pagination-color-foreground"]=e.customForegroundColor),t},$={title:"Components/Pagination",component:"btu-pagination",tags:["autodocs"],parameters:{docs:{subtitle:"A component for navigating through paged content",description:{component:`
2
2
  <h3>When to use:</h3>
3
3
  <ul>
4
4
  <li>To navigate through large sets of data</li>
@@ -1,4 +1,4 @@
1
- import{g as p,x as l}from"./iframe-CufEXQ5F.js";import{o as a}from"./if-defined-f_e-RnGa.js";import{o as c}from"./style-map-BkaK9546.js";import"./preload-helper-PPVm8Dsz.js";const{events:d,args:u,argTypes:t}=p("btu-popover"),h={title:"Components/Popover",component:"btu-popover",tags:["autodocs"],parameters:{docs:{subtitle:"Rich interactive content anchored to a trigger element",description:{component:`
1
+ import{g as p,x as l}from"./iframe-BqpRijx3.js";import{o as a}from"./if-defined-0srVwUDm.js";import{o as c}from"./style-map-DukvFNCc.js";import"./preload-helper-PPVm8Dsz.js";const{events:d,args:u,argTypes:t}=p("btu-popover"),h={title:"Components/Popover",component:"btu-popover",tags:["autodocs"],parameters:{docs:{subtitle:"Rich interactive content anchored to a trigger element",description:{component:`
2
2
  \`btu-popover\` displays rich interactive content anchored to a trigger element using CSS anchor positioning and the native Popover API.
3
3
 
4
4
  <h3>When to use:</h3>
@@ -1 +1 @@
1
- import"./iframe-CufEXQ5F.js";const l=t=>{class n extends t{connectedCallback(){super.connectedCallback(),Promise.resolve().then(()=>this.emit("btu-element-connected",{}),e=>this.emit("btu-element-error",{error:e}))}disconnectedCallback(){super.disconnectedCallback(),this.emit("btu-element-disconnected")}emit(e,c){const a=new CustomEvent(e,{bubbles:!0,cancelable:!1,composed:!0,detail:c});return this.dispatchEvent(a)}}return n},d=t=>{class n extends t{connectedCallback(){const e=()=>{super.connectedCallback()};document.readyState!=="loading"?e():document.addEventListener("DOMContentLoaded",()=>e())}}return n};export{l as E,d as R};
1
+ import"./iframe-BqpRijx3.js";const l=t=>{class n extends t{connectedCallback(){super.connectedCallback(),Promise.resolve().then(()=>this.emit("btu-element-connected",{}),e=>this.emit("btu-element-error",{error:e}))}disconnectedCallback(){super.disconnectedCallback(),this.emit("btu-element-disconnected")}emit(e,c){const a=new CustomEvent(e,{bubbles:!0,cancelable:!1,composed:!0,detail:c});return this.dispatchEvent(a)}}return n},d=t=>{class n extends t{connectedCallback(){const e=()=>{super.connectedCallback()};document.readyState!=="loading"?e():document.addEventListener("DOMContentLoaded",()=>e())}}return n};export{l as E,d as R};
@@ -1,4 +1,4 @@
1
- import{x as l,i as v}from"./iframe-CufEXQ5F.js";import{t as m}from"./custom-element-UsVr97OX.js";import"./preload-helper-PPVm8Dsz.js";const h=n=>{class i extends n{constructor(){super(...arguments),this._rovingIndex=0}_getRovingTargets(){return[]}_rovingFocus(t,e=!0){const o=this._getRovingTargets();if(o.length===0)return;const r=Math.max(0,Math.min(t,o.length-1));o.forEach((u,b)=>u.setAttribute("tabindex",b===r?"0":"-1")),e&&o[r]?.focus(),this._rovingIndex=r}_rovingNext(){const t=this._getRovingTargets();if(t.length===0)return;const e=this._rovingCurrentIndex(),o=e<t.length-1?e+1:0;this._rovingFocus(o)}_rovingPrev(){const t=this._getRovingTargets();if(t.length===0)return;const e=this._rovingCurrentIndex(),o=e>0?e-1:t.length-1;this._rovingFocus(o)}_rovingFirst(){this._rovingFocus(0)}_rovingLast(){const t=this._getRovingTargets();t.length>0&&this._rovingFocus(t.length-1)}_rovingCurrentIndex(){const t=document.activeElement;return this._getRovingTargets().findIndex(e=>e===t||e.contains(t))}}return i};var a=Object.freeze,x=Object.defineProperty,p=Object.getOwnPropertyDescriptor,f=(n,i,d,t)=>{for(var e=t>1?void 0:t?p(i,d):i,o=n.length-1,r;o>=0;o--)(r=n[o])&&(e=r(e)||e);return e},y=(n,i)=>a(x(n,"raw",{value:a(n.slice())})),c;const T={title:"Mixins/Roving Tabindex",tags:["autodocs"],parameters:{docs:{description:{component:`
1
+ import{x as l,i as v}from"./iframe-BqpRijx3.js";import{t as m}from"./custom-element-UsVr97OX.js";import"./preload-helper-PPVm8Dsz.js";const h=n=>{class i extends n{constructor(){super(...arguments),this._rovingIndex=0}_getRovingTargets(){return[]}_rovingFocus(t,e=!0){const o=this._getRovingTargets();if(o.length===0)return;const r=Math.max(0,Math.min(t,o.length-1));o.forEach((u,b)=>u.setAttribute("tabindex",b===r?"0":"-1")),e&&o[r]?.focus(),this._rovingIndex=r}_rovingNext(){const t=this._getRovingTargets();if(t.length===0)return;const e=this._rovingCurrentIndex(),o=e<t.length-1?e+1:0;this._rovingFocus(o)}_rovingPrev(){const t=this._getRovingTargets();if(t.length===0)return;const e=this._rovingCurrentIndex(),o=e>0?e-1:t.length-1;this._rovingFocus(o)}_rovingFirst(){this._rovingFocus(0)}_rovingLast(){const t=this._getRovingTargets();t.length>0&&this._rovingFocus(t.length-1)}_rovingCurrentIndex(){const t=document.activeElement;return this._getRovingTargets().findIndex(e=>e===t||e.contains(t))}}return i};var a=Object.freeze,x=Object.defineProperty,p=Object.getOwnPropertyDescriptor,f=(n,i,d,t)=>{for(var e=t>1?void 0:t?p(i,d):i,o=n.length-1,r;o>=0;o--)(r=n[o])&&(e=r(e)||e);return e},y=(n,i)=>a(x(n,"raw",{value:a(n.slice())})),c;const T={title:"Mixins/Roving Tabindex",tags:["autodocs"],parameters:{docs:{description:{component:`
2
2
  \`RovingTabindexMixin\` provides **roving tabindex** navigation primitives for toolbar and menu components following the <a href="https://www.w3.org/WAI/ARIA/apd/practices/keyboard-interface/#kbd_roving_tabindex" target="_blank">WAI-ARIA Keyboard Interface Pattern</a>.
3
3
 
4
4
  In a roving tabindex, only one element in the group has \`tabindex="0"\` (reachable via Tab), while all others have \`tabindex="-1"\`. Arrow keys move focus between items, wrapping at both ends.
@@ -1,4 +1,4 @@
1
- import{x as o}from"./iframe-CufEXQ5F.js";import"./preload-helper-PPVm8Dsz.js";const r={title:"Utilities/RTC",tags:["autodocs"],parameters:{docs:{subtitle:"The `rtc` module provides real-time communication between browser tabs and the Brightspot CMS server. Uses BroadcastChannel for cross-tab coordination with leader election, and Server-Sent Events for server communication."},controls:{expanded:!0}}},e={render:()=>o`
1
+ import{x as o}from"./iframe-BqpRijx3.js";import"./preload-helper-PPVm8Dsz.js";const r={title:"Utilities/RTC",tags:["autodocs"],parameters:{docs:{subtitle:"The `rtc` module provides real-time communication between browser tabs and the Brightspot CMS server. Uses BroadcastChannel for cross-tab coordination with leader election, and Server-Sent Events for server communication."},controls:{expanded:!0}}},e={render:()=>o`
2
2
  <div class="space-y-6 text-sm">
3
3
  <div>
4
4
  <h3 class="mb-2 font-bold">Overview</h3>
@@ -1,4 +1,4 @@
1
- import{x as a}from"./iframe-CufEXQ5F.js";import"./preload-helper-PPVm8Dsz.js";const l=({theme:e="btu-scrollshadow-25"})=>{const r=new Array(100).fill(0).map((s,t)=>`Item ${t+1}`);return a`
1
+ import{x as a}from"./iframe-BqpRijx3.js";import"./preload-helper-PPVm8Dsz.js";const l=({theme:e="btu-scrollshadow-25"})=>{const r=new Array(100).fill(0).map((s,t)=>`Item ${t+1}`);return a`
2
2
  <style>
3
3
  :root {
4
4
  --can-scroll: ;
@@ -1,4 +1,4 @@
1
- import{g as k,x as c}from"./iframe-CufEXQ5F.js";import{o as s}from"./if-defined-f_e-RnGa.js";import{o as f}from"./style-map-BkaK9546.js";import{L as w}from"./LucideDynamicLoader-jmdq8YDM.js";import"./preload-helper-PPVm8Dsz.js";const{events:v,args:y,argTypes:g}=k("btu-switch"),x={customColorOn:"--switch-color-track-on",customColorOff:"--switch-color-track-off",customKnobColor:"--switch-color-knob",customLabelSpacing:"--switch-label-spacing",customIconSize:"--switch-track-icon-size"},S=e=>Object.entries(x).reduce((o,[t,n])=>(e[t]&&(o[n]=e[t]),o),{}),L={title:"Components/Switch",component:"btu-switch",tags:["autodocs"],parameters:{docs:{subtitle:"A toggle switch for binary on/off states",description:{component:`
1
+ import{g as k,x as c}from"./iframe-BqpRijx3.js";import{o as s}from"./if-defined-0srVwUDm.js";import{o as f}from"./style-map-DukvFNCc.js";import{L as w}from"./LucideDynamicLoader-jmdq8YDM.js";import"./preload-helper-PPVm8Dsz.js";const{events:v,args:y,argTypes:g}=k("btu-switch"),x={customColorOn:"--switch-color-track-on",customColorOff:"--switch-color-track-off",customKnobColor:"--switch-color-knob",customLabelSpacing:"--switch-label-spacing",customIconSize:"--switch-track-icon-size"},S=e=>Object.entries(x).reduce((o,[t,n])=>(e[t]&&(o[n]=e[t]),o),{}),L={title:"Components/Switch",component:"btu-switch",tags:["autodocs"],parameters:{docs:{subtitle:"A toggle switch for binary on/off states",description:{component:`
2
2
  <h3>When to use:</h3>
3
3
  <ul>
4
4
  <li>For toggling a setting or preference on/off</li>
@@ -1,4 +1,4 @@
1
- import{g as u,x as e}from"./iframe-CufEXQ5F.js";import{o as d}from"./style-map-BkaK9546.js";import"./preload-helper-PPVm8Dsz.js";const{events:c,args:m,argTypes:t}=u("btu-tab"),y={title:"Components/Tabs/Tab",component:"btu-tab",tags:["autodocs"],parameters:{docs:{subtitle:"btu-tab",description:{component:`
1
+ import{g as u,x as e}from"./iframe-BqpRijx3.js";import{o as d}from"./style-map-DukvFNCc.js";import"./preload-helper-PPVm8Dsz.js";const{events:c,args:m,argTypes:t}=u("btu-tab"),y={title:"Components/Tabs/Tab",component:"btu-tab",tags:["autodocs"],parameters:{docs:{subtitle:"btu-tab",description:{component:`
2
2
  An individual tab within a \`btu-tabs\` group.
3
3
 
4
4
  Renders a button with \`role="tab"\` that participates in keyboard navigation and selection state managed by the parent \`btu-tabs\` container.
@@ -1,4 +1,4 @@
1
- import{g as b,E as i,x as s}from"./iframe-CufEXQ5F.js";import{o as c}from"./style-map-BkaK9546.js";import"./preload-helper-PPVm8Dsz.js";const{events:d,args:u,argTypes:a}=b("btu-tabs"),h={title:"Components/Tabs",component:"btu-tabs",tags:["autodocs"],parameters:{docs:{subtitle:"btu-tabs",description:{component:`
1
+ import{g as b,E as i,x as s}from"./iframe-BqpRijx3.js";import{o as c}from"./style-map-DukvFNCc.js";import"./preload-helper-PPVm8Dsz.js";const{events:d,args:u,argTypes:a}=b("btu-tabs"),h={title:"Components/Tabs",component:"btu-tabs",tags:["autodocs"],parameters:{docs:{subtitle:"btu-tabs",description:{component:`
2
2
  A tab group component that manages selection state across a set of \`btu-tab\` children.
3
3
 
4
4
  <h3>When to use:</h3>
@@ -1,4 +1,4 @@
1
- import{x as u}from"./iframe-CufEXQ5F.js";import"./preload-helper-PPVm8Dsz.js";function v(e,t){if(e<=0)return t;let n,o=0;return function(){if(n)return;const r=Date.now(),s=e-r+o;s<=0?(o=r,t.apply(this,[...arguments])):n=setTimeout(()=>{o=r,n=void 0,t.apply(this,[...arguments])},s)}}const x={title:"Utilities/Throttle",tags:["autodocs"],parameters:{docs:{subtitle:"The `throttle` utility function limits how often a function can execute, ensuring it runs at most once per specified interval. Useful for high-frequency events like scroll, resize, or mousemove."},controls:{expanded:!0}},argTypes:{interval:{control:{type:"number",min:0,max:2e3,step:50},description:"Throttle interval in milliseconds"}},args:{interval:200}},d={render:e=>{const t=`throttle-${Math.random().toString(36).substring(2,9)}`;let n=0,o=0;const r=()=>{const m=document.getElementById(`${t}-normal-count`),h=document.getElementById(`${t}-throttled-count`);m&&(m.textContent=String(n)),h&&(h.textContent=String(o))},s=v(e.interval,()=>{o++,r()}),a=()=>{n++,r()},l=()=>{a(),s()};return u`
1
+ import{x as u}from"./iframe-BqpRijx3.js";import"./preload-helper-PPVm8Dsz.js";function v(e,t){if(e<=0)return t;let n,o=0;return function(){if(n)return;const r=Date.now(),s=e-r+o;s<=0?(o=r,t.apply(this,[...arguments])):n=setTimeout(()=>{o=r,n=void 0,t.apply(this,[...arguments])},s)}}const x={title:"Utilities/Throttle",tags:["autodocs"],parameters:{docs:{subtitle:"The `throttle` utility function limits how often a function can execute, ensuring it runs at most once per specified interval. Useful for high-frequency events like scroll, resize, or mousemove."},controls:{expanded:!0}},argTypes:{interval:{control:{type:"number",min:0,max:2e3,step:50},description:"Throttle interval in milliseconds"}},args:{interval:200}},d={render:e=>{const t=`throttle-${Math.random().toString(36).substring(2,9)}`;let n=0,o=0;const r=()=>{const m=document.getElementById(`${t}-normal-count`),h=document.getElementById(`${t}-throttled-count`);m&&(m.textContent=String(n)),h&&(h.textContent=String(o))},s=v(e.interval,()=>{o++,r()}),a=()=>{n++,r()},l=()=>{a(),s()};return u`
2
2
  <div class="space-y-4">
3
3
  <div class="text-base">
4
4
  <p class="mb-2">
@@ -1,4 +1,4 @@
1
- import{ah as v,ai as x,x as c,i as w}from"./iframe-CufEXQ5F.js";import{t as E}from"./custom-element-UsVr97OX.js";import{o as T}from"./if-defined-f_e-RnGa.js";import{o as k}from"./style-map-BkaK9546.js";import{E as C,R as L}from"./ReadyMixin-CP6tQ4FB.js";import"./preload-helper-PPVm8Dsz.js";const D={attribute:!0,type:String,converter:x,reflect:!1,hasChanged:v},S=(o=D,i,l)=>{const{kind:t,metadata:e}=l;let s=globalThis.litPropertyMetadata.get(e);if(s===void 0&&globalThis.litPropertyMetadata.set(e,s=new Map),t==="setter"&&((o=Object.create(o)).wrapped=!0),s.set(l.name,o),t==="accessor"){const{name:r}=l;return{set(n){const g=i.get.call(this);i.set.call(this,n),this.requestUpdate(r,g,o)},init(n){return n!==void 0&&this.C(r,void 0,o,n),n}}}if(t==="setter"){const{name:r}=l;return function(n){const g=this[r];i.call(this,n),this.requestUpdate(r,g,o)}}throw Error("Unsupported decorator location: "+t)};function p(o){return(i,l)=>typeof l=="object"?S(o,i,l):((t,e,s)=>{const r=e.hasOwnProperty(s);return e.constructor.createProperty(s,t),r?Object.getOwnPropertyDescriptor(e,s):void 0})(o,i,l)}var A=Object.defineProperty,a=(o,i,l,t)=>{for(var e=void 0,s=o.length-1,r;s>=0;s--)(r=o[s])&&(e=r(i,l,e)||e);return e&&A(i,l,e),e};const M={top:"btu-tooltip-top",bottom:"btu-tooltip-bottom",left:"btu-tooltip-left",right:"btu-tooltip-right"},_={sm:"btu-tooltip-offset-sm",md:"btu-tooltip-offset-md",lg:"btu-tooltip-offset-lg",xl:"btu-tooltip-offset-xl"},O=o=>{class i extends o{constructor(){super(...arguments),this.tooltip="",this.tooltipPosition="top",this.tooltipDelay=300,this.tooltipOffset=null,this.tooltipNoArrow=!1,this.tooltipTrigger="hover focus",this._tooltipEl=null,this._tooltipId=`btu-tooltip-${crypto.randomUUID()}`,this._anchorName=`--btu-trigger-${crypto.randomUUID()}`,this._showTimer=null,this._isVisible=!1,this._activeTriggers=new Set,this._onMouseEnter=this._handleMouseEnter.bind(this),this._onMouseLeave=this._handleMouseLeave.bind(this),this._onFocusIn=this._handleFocusIn.bind(this),this._onFocusOut=this._handleFocusOut.bind(this),this._onClick=this._handleClick.bind(this),this._onNativeToggle=this._handleNativeToggle.bind(this),this._onKeyDown=this._handleKeyDown.bind(this),this._onDocumentClick=null}connectedCallback(){super.connectedCallback(),this._bindTriggerListeners()}disconnectedCallback(){if(this._clearShowTimer(),this._removeDocumentClickListener(),this._unbindTriggerListeners(),this._tooltipEl){try{this._tooltipEl.hidePopover()}catch(t){t instanceof DOMException&&t.name==="InvalidStateError"||console.warn("[btu-tooltip] Failed to hide tooltip during disconnect:",t)}this._tooltipEl.removeEventListener("toggle",this._onNativeToggle),this._tooltipEl.remove(),this._tooltipEl=null}this._removeAriaDescribedBy(),this.style.removeProperty("anchor-name"),this._isVisible=!1,super.disconnectedCallback()}updated(t){super.updated(t),t.has("tooltipTrigger")&&(this._unbindTriggerListeners(),this._bindTriggerListeners(),this._tooltipEl&&(this._isVisible&&this._hide(),this._tooltipEl.setAttribute("popover",this._getPopoverMode()))),(t.has("tooltip")||t.has("tooltipPosition")||t.has("tooltipDelay")||t.has("tooltipOffset")||t.has("tooltipNoArrow"))&&this._syncTooltipElement()}_getPopoverMode(){return"manual"}_syncTooltipElement(){if(!this.tooltip){this._tooltipEl&&(this._hide(),this._tooltipEl.removeEventListener("toggle",this._onNativeToggle),this._tooltipEl.remove(),this._tooltipEl=null,this._removeAriaDescribedBy(),this.style.removeProperty("anchor-name"),document.removeEventListener("keydown",this._onKeyDown));return}this.style.setProperty("anchor-name",this._anchorName),this._tooltipEl||(this._tooltipEl=this._createTooltipElement(),this.appendChild(this._tooltipEl),this._appendAriaDescribedBy(),document.addEventListener("keydown",this._onKeyDown)),this._tooltipEl.textContent=this.tooltip,this._tooltipEl.className=this._buildTooltipClasses()}_createTooltipElement(){const t=document.createElement("div");return t.id=this._tooltipId,t.className=this._buildTooltipClasses(),t.setAttribute("role","tooltip"),t.setAttribute("data-tooltip-internal",""),t.setAttribute("popover",this._getPopoverMode()),t.style.setProperty("position-anchor",this._anchorName),t.textContent=this.tooltip,t.addEventListener("toggle",this._onNativeToggle),t}_buildTooltipClasses(){const t=["btu-tooltip",M[this.tooltipPosition]];return this.tooltipOffset&&_[this.tooltipOffset]&&t.push(_[this.tooltipOffset]),this.tooltipNoArrow&&t.push("btu-tooltip-no-arrow"),t.join(" ")}_hasTrigger(t){return this._activeTriggers.has(t)}_bindTriggerListeners(){const t=new Set(["hover","focus","click"]);this._activeTriggers=new Set(this.tooltipTrigger.trim().split(/\s+/));for(const e of this._activeTriggers)t.has(e)||console.warn(`[btu-tooltip] Unrecognized tooltip-trigger value: "${e}". Valid values: hover, focus, click.`);this._hasTrigger("hover")&&(this.addEventListener("mouseenter",this._onMouseEnter),this.addEventListener("mouseleave",this._onMouseLeave)),this._hasTrigger("focus")&&(this.addEventListener("focusin",this._onFocusIn),this.addEventListener("focusout",this._onFocusOut)),this._hasTrigger("click")&&this.addEventListener("click",this._onClick)}_unbindTriggerListeners(){this.removeEventListener("mouseenter",this._onMouseEnter),this.removeEventListener("mouseleave",this._onMouseLeave),this.removeEventListener("focusin",this._onFocusIn),this.removeEventListener("focusout",this._onFocusOut),this.removeEventListener("click",this._onClick),document.removeEventListener("keydown",this._onKeyDown)}_show(){if(!(this._isVisible||!this._tooltipEl)){try{this._tooltipEl.showPopover()}catch(t){t instanceof DOMException&&t.name==="InvalidStateError"||console.warn("[btu-tooltip] Failed to show tooltip:",t)}this._hasTrigger("click")&&setTimeout(()=>{this._removeDocumentClickListener(),this._onDocumentClick=t=>{const e=t.composedPath();!e.includes(this)&&(!this._tooltipEl||!e.includes(this._tooltipEl))&&this._hide()},document.addEventListener("click",this._onDocumentClick)},0)}}_hide(){if(this._clearShowTimer(),this._removeDocumentClickListener(),!(!this._isVisible||!this._tooltipEl))try{this._tooltipEl.hidePopover()}catch(t){t instanceof DOMException&&t.name==="InvalidStateError"||console.warn("[btu-tooltip] Failed to hide tooltip:",t)}}_removeDocumentClickListener(){this._onDocumentClick&&(document.removeEventListener("click",this._onDocumentClick),this._onDocumentClick=null)}_handleNativeToggle(t){const{newState:e}=t;this._isVisible=e==="open";const s=this._isVisible?"btu-tooltip-show":"btu-tooltip-hide",r=new CustomEvent(s,{bubbles:!0,composed:!0});this.dispatchEvent(r)}_handleKeyDown(t){t.key==="Escape"&&(this._clearShowTimer(),this._hide())}_clearShowTimer(){this._showTimer!==null&&(clearTimeout(this._showTimer),this._showTimer=null)}_handleMouseEnter(){this._clearShowTimer(),this._showTimer=setTimeout(()=>{this._show()},this.tooltipDelay)}_handleMouseLeave(){this._clearShowTimer(),this._hide()}_handleFocusIn(){this._clearShowTimer(),this._show()}_handleFocusOut(){this._clearShowTimer(),this._hide()}_handleClick(){this._clearShowTimer(),this._isVisible?this._hide():this._show()}_appendAriaDescribedBy(){const t=this.getAttribute("aria-describedby");t?t.includes(this._tooltipId)||this.setAttribute("aria-describedby",`${t} ${this._tooltipId}`):this.setAttribute("aria-describedby",this._tooltipId)}_removeAriaDescribedBy(){const t=this.getAttribute("aria-describedby");if(!t)return;const e=t.split(/\s+/).filter(s=>s!==this._tooltipId).join(" ").trim();e?this.setAttribute("aria-describedby",e):this.removeAttribute("aria-describedby")}}return a([p({attribute:"tooltip"})],i.prototype,"tooltip"),a([p({attribute:"tooltip-position"})],i.prototype,"tooltipPosition"),a([p({attribute:"tooltip-delay",type:Number})],i.prototype,"tooltipDelay"),a([p({attribute:"tooltip-offset"})],i.prototype,"tooltipOffset"),a([p({attribute:"tooltip-no-arrow",type:Boolean})],i.prototype,"tooltipNoArrow"),a([p({attribute:"tooltip-trigger"})],i.prototype,"tooltipTrigger"),i};var P=Object.defineProperty,$=Object.getOwnPropertyDescriptor,y=(o,i,l,t)=>{for(var e=t>1?void 0:t?$(i,l):i,s=o.length-1,r;s>=0;s--)(r=o[s])&&(e=(t?r(i,l,e):r(e))||e);return t&&e&&P(i,l,e),e};let b=class extends O(C(L(w))){constructor(){super(...arguments),this.label="Hover me",this.initialClasses=[]}connectedCallback(){super.connectedCallback(),this.className&&(this.initialClasses=this.className.split(" ").filter(o=>o.trim()))}createRenderRoot(){return this}willUpdate(){const o=[...this.initialClasses,"tooltip-demo"];this.className=o.filter(Boolean).join(" ")}render(){return c`${this.label}`}};y([p({type:String})],b.prototype,"label",2);b=y([E("tooltip-demo")],b);const f=`
1
+ import{ah as v,ai as x,x as c,i as w}from"./iframe-BqpRijx3.js";import{t as E}from"./custom-element-UsVr97OX.js";import{o as T}from"./if-defined-0srVwUDm.js";import{o as k}from"./style-map-DukvFNCc.js";import{E as C,R as L}from"./ReadyMixin-HHwtCrVi.js";import"./preload-helper-PPVm8Dsz.js";const D={attribute:!0,type:String,converter:x,reflect:!1,hasChanged:v},S=(o=D,i,l)=>{const{kind:t,metadata:e}=l;let s=globalThis.litPropertyMetadata.get(e);if(s===void 0&&globalThis.litPropertyMetadata.set(e,s=new Map),t==="setter"&&((o=Object.create(o)).wrapped=!0),s.set(l.name,o),t==="accessor"){const{name:r}=l;return{set(n){const g=i.get.call(this);i.set.call(this,n),this.requestUpdate(r,g,o)},init(n){return n!==void 0&&this.C(r,void 0,o,n),n}}}if(t==="setter"){const{name:r}=l;return function(n){const g=this[r];i.call(this,n),this.requestUpdate(r,g,o)}}throw Error("Unsupported decorator location: "+t)};function p(o){return(i,l)=>typeof l=="object"?S(o,i,l):((t,e,s)=>{const r=e.hasOwnProperty(s);return e.constructor.createProperty(s,t),r?Object.getOwnPropertyDescriptor(e,s):void 0})(o,i,l)}var A=Object.defineProperty,a=(o,i,l,t)=>{for(var e=void 0,s=o.length-1,r;s>=0;s--)(r=o[s])&&(e=r(i,l,e)||e);return e&&A(i,l,e),e};const M={top:"btu-tooltip-top",bottom:"btu-tooltip-bottom",left:"btu-tooltip-left",right:"btu-tooltip-right"},_={sm:"btu-tooltip-offset-sm",md:"btu-tooltip-offset-md",lg:"btu-tooltip-offset-lg",xl:"btu-tooltip-offset-xl"},O=o=>{class i extends o{constructor(){super(...arguments),this.tooltip="",this.tooltipPosition="top",this.tooltipDelay=300,this.tooltipOffset=null,this.tooltipNoArrow=!1,this.tooltipTrigger="hover focus",this._tooltipEl=null,this._tooltipId=`btu-tooltip-${crypto.randomUUID()}`,this._anchorName=`--btu-trigger-${crypto.randomUUID()}`,this._showTimer=null,this._isVisible=!1,this._activeTriggers=new Set,this._onMouseEnter=this._handleMouseEnter.bind(this),this._onMouseLeave=this._handleMouseLeave.bind(this),this._onFocusIn=this._handleFocusIn.bind(this),this._onFocusOut=this._handleFocusOut.bind(this),this._onClick=this._handleClick.bind(this),this._onNativeToggle=this._handleNativeToggle.bind(this),this._onKeyDown=this._handleKeyDown.bind(this),this._onDocumentClick=null}connectedCallback(){super.connectedCallback(),this._bindTriggerListeners()}disconnectedCallback(){if(this._clearShowTimer(),this._removeDocumentClickListener(),this._unbindTriggerListeners(),this._tooltipEl){try{this._tooltipEl.hidePopover()}catch(t){t instanceof DOMException&&t.name==="InvalidStateError"||console.warn("[btu-tooltip] Failed to hide tooltip during disconnect:",t)}this._tooltipEl.removeEventListener("toggle",this._onNativeToggle),this._tooltipEl.remove(),this._tooltipEl=null}this._removeAriaDescribedBy(),this.style.removeProperty("anchor-name"),this._isVisible=!1,super.disconnectedCallback()}updated(t){super.updated(t),t.has("tooltipTrigger")&&(this._unbindTriggerListeners(),this._bindTriggerListeners(),this._tooltipEl&&(this._isVisible&&this._hide(),this._tooltipEl.setAttribute("popover",this._getPopoverMode()))),(t.has("tooltip")||t.has("tooltipPosition")||t.has("tooltipDelay")||t.has("tooltipOffset")||t.has("tooltipNoArrow"))&&this._syncTooltipElement()}_getPopoverMode(){return"manual"}_syncTooltipElement(){if(!this.tooltip){this._tooltipEl&&(this._hide(),this._tooltipEl.removeEventListener("toggle",this._onNativeToggle),this._tooltipEl.remove(),this._tooltipEl=null,this._removeAriaDescribedBy(),this.style.removeProperty("anchor-name"),document.removeEventListener("keydown",this._onKeyDown));return}this.style.setProperty("anchor-name",this._anchorName),this._tooltipEl||(this._tooltipEl=this._createTooltipElement(),this.appendChild(this._tooltipEl),this._appendAriaDescribedBy(),document.addEventListener("keydown",this._onKeyDown)),this._tooltipEl.textContent=this.tooltip,this._tooltipEl.className=this._buildTooltipClasses()}_createTooltipElement(){const t=document.createElement("div");return t.id=this._tooltipId,t.className=this._buildTooltipClasses(),t.setAttribute("role","tooltip"),t.setAttribute("data-tooltip-internal",""),t.setAttribute("popover",this._getPopoverMode()),t.style.setProperty("position-anchor",this._anchorName),t.textContent=this.tooltip,t.addEventListener("toggle",this._onNativeToggle),t}_buildTooltipClasses(){const t=["btu-tooltip",M[this.tooltipPosition]];return this.tooltipOffset&&_[this.tooltipOffset]&&t.push(_[this.tooltipOffset]),this.tooltipNoArrow&&t.push("btu-tooltip-no-arrow"),t.join(" ")}_hasTrigger(t){return this._activeTriggers.has(t)}_bindTriggerListeners(){const t=new Set(["hover","focus","click"]);this._activeTriggers=new Set(this.tooltipTrigger.trim().split(/\s+/));for(const e of this._activeTriggers)t.has(e)||console.warn(`[btu-tooltip] Unrecognized tooltip-trigger value: "${e}". Valid values: hover, focus, click.`);this._hasTrigger("hover")&&(this.addEventListener("mouseenter",this._onMouseEnter),this.addEventListener("mouseleave",this._onMouseLeave)),this._hasTrigger("focus")&&(this.addEventListener("focusin",this._onFocusIn),this.addEventListener("focusout",this._onFocusOut)),this._hasTrigger("click")&&this.addEventListener("click",this._onClick)}_unbindTriggerListeners(){this.removeEventListener("mouseenter",this._onMouseEnter),this.removeEventListener("mouseleave",this._onMouseLeave),this.removeEventListener("focusin",this._onFocusIn),this.removeEventListener("focusout",this._onFocusOut),this.removeEventListener("click",this._onClick),document.removeEventListener("keydown",this._onKeyDown)}_show(){if(!(this._isVisible||!this._tooltipEl)){try{this._tooltipEl.showPopover()}catch(t){t instanceof DOMException&&t.name==="InvalidStateError"||console.warn("[btu-tooltip] Failed to show tooltip:",t)}this._hasTrigger("click")&&setTimeout(()=>{this._removeDocumentClickListener(),this._onDocumentClick=t=>{const e=t.composedPath();!e.includes(this)&&(!this._tooltipEl||!e.includes(this._tooltipEl))&&this._hide()},document.addEventListener("click",this._onDocumentClick)},0)}}_hide(){if(this._clearShowTimer(),this._removeDocumentClickListener(),!(!this._isVisible||!this._tooltipEl))try{this._tooltipEl.hidePopover()}catch(t){t instanceof DOMException&&t.name==="InvalidStateError"||console.warn("[btu-tooltip] Failed to hide tooltip:",t)}}_removeDocumentClickListener(){this._onDocumentClick&&(document.removeEventListener("click",this._onDocumentClick),this._onDocumentClick=null)}_handleNativeToggle(t){const{newState:e}=t;this._isVisible=e==="open";const s=this._isVisible?"btu-tooltip-show":"btu-tooltip-hide",r=new CustomEvent(s,{bubbles:!0,composed:!0});this.dispatchEvent(r)}_handleKeyDown(t){t.key==="Escape"&&(this._clearShowTimer(),this._hide())}_clearShowTimer(){this._showTimer!==null&&(clearTimeout(this._showTimer),this._showTimer=null)}_handleMouseEnter(){this._clearShowTimer(),this._showTimer=setTimeout(()=>{this._show()},this.tooltipDelay)}_handleMouseLeave(){this._clearShowTimer(),this._hide()}_handleFocusIn(){this._clearShowTimer(),this._show()}_handleFocusOut(){this._clearShowTimer(),this._hide()}_handleClick(){this._clearShowTimer(),this._isVisible?this._hide():this._show()}_appendAriaDescribedBy(){const t=this.getAttribute("aria-describedby");t?t.includes(this._tooltipId)||this.setAttribute("aria-describedby",`${t} ${this._tooltipId}`):this.setAttribute("aria-describedby",this._tooltipId)}_removeAriaDescribedBy(){const t=this.getAttribute("aria-describedby");if(!t)return;const e=t.split(/\s+/).filter(s=>s!==this._tooltipId).join(" ").trim();e?this.setAttribute("aria-describedby",e):this.removeAttribute("aria-describedby")}}return a([p({attribute:"tooltip"})],i.prototype,"tooltip"),a([p({attribute:"tooltip-position"})],i.prototype,"tooltipPosition"),a([p({attribute:"tooltip-delay",type:Number})],i.prototype,"tooltipDelay"),a([p({attribute:"tooltip-offset"})],i.prototype,"tooltipOffset"),a([p({attribute:"tooltip-no-arrow",type:Boolean})],i.prototype,"tooltipNoArrow"),a([p({attribute:"tooltip-trigger"})],i.prototype,"tooltipTrigger"),i};var P=Object.defineProperty,$=Object.getOwnPropertyDescriptor,y=(o,i,l,t)=>{for(var e=t>1?void 0:t?$(i,l):i,s=o.length-1,r;s>=0;s--)(r=o[s])&&(e=(t?r(i,l,e):r(e))||e);return t&&e&&P(i,l,e),e};let b=class extends O(C(L(w))){constructor(){super(...arguments),this.label="Hover me",this.initialClasses=[]}connectedCallback(){super.connectedCallback(),this.className&&(this.initialClasses=this.className.split(" ").filter(o=>o.trim()))}createRenderRoot(){return this}willUpdate(){const o=[...this.initialClasses,"tooltip-demo"];this.className=o.filter(Boolean).join(" ")}render(){return c`${this.label}`}};y([p({type:String})],b.prototype,"label",2);b=y([E("tooltip-demo")],b);const f=`
2
2
  .tooltip-demo {
3
3
  display: inline-flex;
4
4
  align-items: center;
@@ -1,4 +1,4 @@
1
- import{g as C,x as S}from"./iframe-CufEXQ5F.js";import{o as E}from"./if-defined-f_e-RnGa.js";import{o as x}from"./style-map-BkaK9546.js";import"./preload-helper-PPVm8Dsz.js";const{events:B,args:U,argTypes:c}=C("btu-upload"),F=e=>{const o={};return e.dropzoneBg&&(o["--upload-dropzone-bg"]=e.dropzoneBg),e.dropzoneBorderColor&&(o["--upload-dropzone-border-color"]=e.dropzoneBorderColor),e.dropzoneBorderRadius&&(o["--upload-dropzone-border-radius"]=e.dropzoneBorderRadius),e.dropzoneHoverBg&&(o["--upload-dropzone-hover-bg"]=e.dropzoneHoverBg),e.dropzoneHoverBorderColor&&(o["--upload-dropzone-hover-border-color"]=e.dropzoneHoverBorderColor),e.dropzoneFocusRingColor&&(o["--upload-dropzone-focus-ring-color"]=e.dropzoneFocusRingColor),e.itemBg&&(o["--upload-item-bg"]=e.itemBg),e.itemBorderColor&&(o["--upload-item-border-color"]=e.itemBorderColor),e.itemActiveBorderColor&&(o["--upload-item-active-border-color"]=e.itemActiveBorderColor),e.itemCompleteBorderColor&&(o["--upload-item-complete-border-color"]=e.itemCompleteBorderColor),e.itemErrorBg&&(o["--upload-item-error-bg"]=e.itemErrorBg),e.itemErrorBorderColor&&(o["--upload-item-error-border-color"]=e.itemErrorBorderColor),o},T={title:"Components/Upload",component:"btu-upload",tags:["autodocs"],parameters:{docs:{subtitle:"btu-upload",description:{component:`
1
+ import{g as C,x as S}from"./iframe-BqpRijx3.js";import{o as E}from"./if-defined-0srVwUDm.js";import{o as x}from"./style-map-DukvFNCc.js";import"./preload-helper-PPVm8Dsz.js";const{events:B,args:U,argTypes:c}=C("btu-upload"),F=e=>{const o={};return e.dropzoneBg&&(o["--upload-dropzone-bg"]=e.dropzoneBg),e.dropzoneBorderColor&&(o["--upload-dropzone-border-color"]=e.dropzoneBorderColor),e.dropzoneBorderRadius&&(o["--upload-dropzone-border-radius"]=e.dropzoneBorderRadius),e.dropzoneHoverBg&&(o["--upload-dropzone-hover-bg"]=e.dropzoneHoverBg),e.dropzoneHoverBorderColor&&(o["--upload-dropzone-hover-border-color"]=e.dropzoneHoverBorderColor),e.dropzoneFocusRingColor&&(o["--upload-dropzone-focus-ring-color"]=e.dropzoneFocusRingColor),e.itemBg&&(o["--upload-item-bg"]=e.itemBg),e.itemBorderColor&&(o["--upload-item-border-color"]=e.itemBorderColor),e.itemActiveBorderColor&&(o["--upload-item-active-border-color"]=e.itemActiveBorderColor),e.itemCompleteBorderColor&&(o["--upload-item-complete-border-color"]=e.itemCompleteBorderColor),e.itemErrorBg&&(o["--upload-item-error-bg"]=e.itemErrorBg),e.itemErrorBorderColor&&(o["--upload-item-error-border-color"]=e.itemErrorBorderColor),o},T={title:"Components/Upload",component:"btu-upload",tags:["autodocs"],parameters:{docs:{subtitle:"btu-upload",description:{component:`
2
2
  A file upload component with drop zone and file list.
3
3
 
4
4
  The component is **presentation + file-selection only**. It handles file browsing
@@ -1,4 +1,4 @@
1
- import{g as y,x as c}from"./iframe-CufEXQ5F.js";import"./preload-helper-PPVm8Dsz.js";const{events:b,args:f,argTypes:h}=y("btu-upload-item"),e=r=>{const l=`upload-item-${crypto.randomUUID().slice(0,8)}`;return setTimeout(()=>{const m=document.getElementById(l)?.querySelector("btu-upload-item");if(!m)return;const u=new File([""],r.name,{type:r.mimeType??""});Object.defineProperty(u,"size",{value:r.size??0});const p=r.status??"uploading",d={id:crypto.randomUUID().slice(0,8),file:u,symbol:r.symbol},g=p==="pending"?{...d,status:"pending",progress:0}:p==="complete"?{...d,status:"complete",progress:100}:p==="error"?{...d,status:"error",progress:r.progress??0,errorMessage:r.errorMessage??""}:{...d,status:"uploading",progress:r.progress??0};m._configure(g)},50),c`<div id="${l}" style="max-width: 480px;"><btu-upload-item></btu-upload-item></div>`},k={title:"Components/Upload/Upload Item",component:"btu-upload-item",tags:["autodocs"],parameters:{docs:{subtitle:"Individual file row rendered inside btu-upload",description:{component:`
1
+ import{g as y,x as c}from"./iframe-BqpRijx3.js";import"./preload-helper-PPVm8Dsz.js";const{events:b,args:f,argTypes:h}=y("btu-upload-item"),e=r=>{const l=`upload-item-${crypto.randomUUID().slice(0,8)}`;return setTimeout(()=>{const m=document.getElementById(l)?.querySelector("btu-upload-item");if(!m)return;const u=new File([""],r.name,{type:r.mimeType??""});Object.defineProperty(u,"size",{value:r.size??0});const p=r.status??"uploading",d={id:crypto.randomUUID().slice(0,8),file:u,symbol:r.symbol},g=p==="pending"?{...d,status:"pending",progress:0}:p==="complete"?{...d,status:"complete",progress:100}:p==="error"?{...d,status:"error",progress:r.progress??0,errorMessage:r.errorMessage??""}:{...d,status:"uploading",progress:r.progress??0};m._configure(g)},50),c`<div id="${l}" style="max-width: 480px;"><btu-upload-item></btu-upload-item></div>`},k={title:"Components/Upload/Upload Item",component:"btu-upload-item",tags:["autodocs"],parameters:{docs:{subtitle:"Individual file row rendered inside btu-upload",description:{component:`
2
2
  \`btu-upload-item\` renders a single file's state inside a \`btu-upload\` file list. It is an **internal sub-component** — consumers should not create, query, or modify items directly. All interaction goes through \`btu-upload\` methods (\`setFileProgress\`, \`setFileStatus\`, \`setFileSymbol\`, \`removeFile\`).
3
3
 
4
4
  These stories exist for design documentation and visual QA of each status state in isolation. In practice, items are always created, configured, and destroyed by their parent \`btu-upload\`.
@@ -1,4 +1,4 @@
1
- import{S as U}from"./blocks-YjKl5E55.js";import{e as X,f as _,E as B,r as j,x as A}from"./iframe-CufEXQ5F.js";import"./preload-helper-PPVm8Dsz.js";const C=()=>new J;class J{}const w=new WeakMap,k=X(class extends _{render(e){return B}update(e,[o]){const t=o!==this.G;return t&&this.G!==void 0&&this.rt(void 0),(t||this.lt!==this.ct)&&(this.G=o,this.ht=e.options?.host,this.rt(this.ct=e.element)),B}rt(e){if(this.isConnected||(e=void 0),typeof this.G=="function"){const o=this.ht??globalThis;let t=w.get(o);t===void 0&&(t=new WeakMap,w.set(o,t)),t.get(this.G)!==void 0&&this.G.call(this.ht,void 0),t.set(this.G,e),e!==void 0&&this.G.call(this.ht,e)}else this.G.value=e}get lt(){return typeof this.G=="function"?w.get(this.ht??globalThis)?.get(this.G):this.G?.value}disconnected(){this.lt===this.ct&&this.rt(void 0)}reconnected(){this.rt(this.ct)}}),ee={title:"Welcome",tags:["autodocs","!dev"],parameters:{layout:"fullscreen",controls:{disable:!0},actions:{disable:!0},options:{showPanel:!1},docs:{page:()=>j.createElement("div",{className:"welcome-docs"},j.createElement(U))}}},$=[[13,52,158],[19,183,158],[99,43,176],[95,233,208],[240,67,62],[83,36,148]],d=(e,o)=>e+Math.random()*(o-e),M=e=>e[Math.floor(Math.random()*e.length)];function I(e,o){if(matchMedia("(prefers-reduced-motion: reduce)").matches)return;const t=e.getContext("2d"),l=Array.from({length:3},()=>({x:0,y:0,rgb:M($),opacity:0,radius:d(250,350)}));let h=null;function O(){const s=5*devicePixelRatio,n=Object.assign(document.createElement("canvas"),{width:s,height:s}),r=n.getContext("2d");r.fillStyle="#000",r.arc(s/2,s/2,1.6*devicePixelRatio,0,Math.PI*2),r.fill(),h=t.createPattern(n,"repeat")}function R(){const{width:s,height:n}=e.getBoundingClientRect();e.width=s*devicePixelRatio,e.height=n*devicePixelRatio,t.setTransform(devicePixelRatio,0,0,devicePixelRatio,0,0),O()}R(),addEventListener("resize",R);const a=o?l[0]:null;a&&(a.rgb=M($),a.radius=300),(function s(){if(!e.isConnected)return;const n=e.width/devicePixelRatio,r=e.height/devicePixelRatio;t.clearRect(0,0,n,r),a&&o&&(o.active?(a.x+=(o.tx-a.x)*.06,a.y+=(o.ty-a.y)*.06,a.opacity+=(.35-a.opacity)*.08):a.opacity+=(0-a.opacity)*.04);for(const i of l){if(i.opacity<=0)continue;const[u,p,b]=i.rgb,c=t.createRadialGradient(i.x,i.y,0,i.x,i.y,i.radius);c.addColorStop(0,`rgba(${u},${p},${b},${i.opacity})`),c.addColorStop(1,`rgba(${u},${p},${b},0)`),t.fillStyle=c,t.fillRect(i.x-i.radius,i.y-i.radius,i.radius*2,i.radius*2)}h&&(t.globalCompositeOperation="destination-in",t.fillStyle=h,t.fillRect(0,0,n,r),t.globalCompositeOperation="source-over"),requestAnimationFrame(s)})();function S(s){if(!e.isConnected)return;const{width:n,height:r}=e.getBoundingClientRect(),i=300,u=m=>m<2?{x:d(.15*n,.85*n),y:m===0?-i:r+i}:{x:m===2?-i:n+i,y:d(.15*r,.85*r)},p=Math.floor(Math.random()*4),b=(p+(Math.random()<.5?2:[1,3][Math.floor(Math.random()*2)]))%4,c=u(p),z=u(b),y=z.x-c.x,x=z.y-c.y,E=Math.hypot(y,x)||1,Y=Math.min(n,r)*d(.15,.35),D=d(1.2,2.2);s.rgb=M($),s.radius=d(250,350);let P=null;const F=d(6e3,7500);(function m(G){if(!e.isConnected)return;P??=G;const f=Math.min((G-P)/F,1),L=.5-.5*Math.cos(f*Math.PI),T=Math.sin(f*D*Math.PI)*Y;s.x=c.x+y*L+-x/E*T,s.y=c.y+x*L+y/E*T,s.opacity=.35*Math.min(f/.2,1)*Math.min((1-f)/.2,1),f<1?requestAnimationFrame(m):s.opacity=0})(performance.now())}(o?l.slice(1):l).forEach((s,n)=>setTimeout(()=>{S(s),setInterval(()=>e.isConnected&&S(s),7500)},1e3+n*2500))}const q="position:absolute;inset:0;width:100%;height:100%;pointer-events:none;",N=C(),W=C(),H=C(),v={active:!1,tx:0,ty:0},g={render:()=>(queueMicrotask(()=>{const e=N.value;e&&!e.dataset.init&&(e.dataset.init="1",I(e));const o=W.value;o&&!o.dataset.init&&(o.dataset.init="1",I(o,v));const t=H.value;t&&!t.dataset.init&&(t.dataset.init="1",t.addEventListener("mousemove",l=>{const h=t.getBoundingClientRect();v.tx=l.clientX-h.left,v.ty=l.clientY-h.top,v.active=!0}),t.addEventListener("mouseleave",()=>{v.active=!1}))}),A`
1
+ import{S as U}from"./blocks-B17JEOI8.js";import{e as X,f as _,E as B,r as j,x as A}from"./iframe-BqpRijx3.js";import"./preload-helper-PPVm8Dsz.js";const C=()=>new J;class J{}const w=new WeakMap,k=X(class extends _{render(e){return B}update(e,[o]){const t=o!==this.G;return t&&this.G!==void 0&&this.rt(void 0),(t||this.lt!==this.ct)&&(this.G=o,this.ht=e.options?.host,this.rt(this.ct=e.element)),B}rt(e){if(this.isConnected||(e=void 0),typeof this.G=="function"){const o=this.ht??globalThis;let t=w.get(o);t===void 0&&(t=new WeakMap,w.set(o,t)),t.get(this.G)!==void 0&&this.G.call(this.ht,void 0),t.set(this.G,e),e!==void 0&&this.G.call(this.ht,e)}else this.G.value=e}get lt(){return typeof this.G=="function"?w.get(this.ht??globalThis)?.get(this.G):this.G?.value}disconnected(){this.lt===this.ct&&this.rt(void 0)}reconnected(){this.rt(this.ct)}}),ee={title:"Welcome",tags:["autodocs","!dev"],parameters:{layout:"fullscreen",controls:{disable:!0},actions:{disable:!0},options:{showPanel:!1},docs:{page:()=>j.createElement("div",{className:"welcome-docs"},j.createElement(U))}}},$=[[13,52,158],[19,183,158],[99,43,176],[95,233,208],[240,67,62],[83,36,148]],d=(e,o)=>e+Math.random()*(o-e),M=e=>e[Math.floor(Math.random()*e.length)];function I(e,o){if(matchMedia("(prefers-reduced-motion: reduce)").matches)return;const t=e.getContext("2d"),l=Array.from({length:3},()=>({x:0,y:0,rgb:M($),opacity:0,radius:d(250,350)}));let h=null;function O(){const s=5*devicePixelRatio,n=Object.assign(document.createElement("canvas"),{width:s,height:s}),r=n.getContext("2d");r.fillStyle="#000",r.arc(s/2,s/2,1.6*devicePixelRatio,0,Math.PI*2),r.fill(),h=t.createPattern(n,"repeat")}function R(){const{width:s,height:n}=e.getBoundingClientRect();e.width=s*devicePixelRatio,e.height=n*devicePixelRatio,t.setTransform(devicePixelRatio,0,0,devicePixelRatio,0,0),O()}R(),addEventListener("resize",R);const a=o?l[0]:null;a&&(a.rgb=M($),a.radius=300),(function s(){if(!e.isConnected)return;const n=e.width/devicePixelRatio,r=e.height/devicePixelRatio;t.clearRect(0,0,n,r),a&&o&&(o.active?(a.x+=(o.tx-a.x)*.06,a.y+=(o.ty-a.y)*.06,a.opacity+=(.35-a.opacity)*.08):a.opacity+=(0-a.opacity)*.04);for(const i of l){if(i.opacity<=0)continue;const[u,p,b]=i.rgb,c=t.createRadialGradient(i.x,i.y,0,i.x,i.y,i.radius);c.addColorStop(0,`rgba(${u},${p},${b},${i.opacity})`),c.addColorStop(1,`rgba(${u},${p},${b},0)`),t.fillStyle=c,t.fillRect(i.x-i.radius,i.y-i.radius,i.radius*2,i.radius*2)}h&&(t.globalCompositeOperation="destination-in",t.fillStyle=h,t.fillRect(0,0,n,r),t.globalCompositeOperation="source-over"),requestAnimationFrame(s)})();function S(s){if(!e.isConnected)return;const{width:n,height:r}=e.getBoundingClientRect(),i=300,u=m=>m<2?{x:d(.15*n,.85*n),y:m===0?-i:r+i}:{x:m===2?-i:n+i,y:d(.15*r,.85*r)},p=Math.floor(Math.random()*4),b=(p+(Math.random()<.5?2:[1,3][Math.floor(Math.random()*2)]))%4,c=u(p),z=u(b),y=z.x-c.x,x=z.y-c.y,E=Math.hypot(y,x)||1,Y=Math.min(n,r)*d(.15,.35),D=d(1.2,2.2);s.rgb=M($),s.radius=d(250,350);let P=null;const F=d(6e3,7500);(function m(G){if(!e.isConnected)return;P??=G;const f=Math.min((G-P)/F,1),L=.5-.5*Math.cos(f*Math.PI),T=Math.sin(f*D*Math.PI)*Y;s.x=c.x+y*L+-x/E*T,s.y=c.y+x*L+y/E*T,s.opacity=.35*Math.min(f/.2,1)*Math.min((1-f)/.2,1),f<1?requestAnimationFrame(m):s.opacity=0})(performance.now())}(o?l.slice(1):l).forEach((s,n)=>setTimeout(()=>{S(s),setInterval(()=>e.isConnected&&S(s),7500)},1e3+n*2500))}const q="position:absolute;inset:0;width:100%;height:100%;pointer-events:none;",N=C(),W=C(),H=C(),v={active:!1,tx:0,ty:0},g={render:()=>(queueMicrotask(()=>{const e=N.value;e&&!e.dataset.init&&(e.dataset.init="1",I(e));const o=W.value;o&&!o.dataset.init&&(o.dataset.init="1",I(o,v));const t=H.value;t&&!t.dataset.init&&(t.dataset.init="1",t.addEventListener("mousemove",l=>{const h=t.getBoundingClientRect();v.tx=l.clientX-h.left,v.ty=l.clientY-h.top,v.active=!0}),t.addEventListener("mouseleave",()=>{v.active=!1}))}),A`
2
2
  <div
3
3
  ${k(H)}
4
4
  style="
@@ -1,4 +1,4 @@
1
- import{g as h,x as l}from"./iframe-CufEXQ5F.js";import{o as m}from"./style-map-BkaK9546.js";import"./preload-helper-PPVm8Dsz.js";const{events:y,args:w,argTypes:a}=h("btu-widget"),$={title:"Components/Widget",component:"btu-widget",tags:["autodocs"],parameters:{docs:{subtitle:"btu-widget",description:{component:`
1
+ import{g as h,x as l}from"./iframe-BqpRijx3.js";import{o as m}from"./style-map-DukvFNCc.js";import"./preload-helper-PPVm8Dsz.js";const{events:y,args:w,argTypes:a}=h("btu-widget"),$={title:"Components/Widget",component:"btu-widget",tags:["autodocs"],parameters:{docs:{subtitle:"btu-widget",description:{component:`
2
2
  <h3>When to use:</h3>
3
3
  <ul>
4
4
  <li>To display content in a structured widget layout</li>