@brightspot/ui 1.0.1-wc.4 → 1.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 (131) hide show
  1. package/README.md +7 -90
  2. package/dist/LucideDynamicLoader.d.ts +1 -0
  3. package/dist/LucideDynamicLoader.d.ts.map +1 -1
  4. package/dist/LucideDynamicLoader.js +2 -0
  5. package/dist/LucideDynamicLoader.js.map +1 -1
  6. package/dist/LucideDynamicLoader.ts +3 -0
  7. package/dist/components/avatar/Avatar.d.ts +82 -0
  8. package/dist/components/avatar/Avatar.d.ts.map +1 -0
  9. package/dist/components/avatar/Avatar.js +162 -0
  10. package/dist/components/avatar/Avatar.js.map +1 -0
  11. package/dist/components/avatar/AvatarGroup.d.ts +70 -0
  12. package/dist/components/avatar/AvatarGroup.d.ts.map +1 -0
  13. package/dist/components/avatar/AvatarGroup.js +145 -0
  14. package/dist/components/avatar/AvatarGroup.js.map +1 -0
  15. package/dist/components/badge/Badge.d.ts +75 -0
  16. package/dist/components/badge/Badge.d.ts.map +1 -0
  17. package/dist/components/badge/Badge.js +118 -0
  18. package/dist/components/badge/Badge.js.map +1 -0
  19. package/dist/components/circular-progress/CircularProgress.d.ts +57 -0
  20. package/dist/components/circular-progress/CircularProgress.d.ts.map +1 -0
  21. package/dist/components/circular-progress/CircularProgress.js +173 -0
  22. package/dist/components/circular-progress/CircularProgress.js.map +1 -0
  23. package/dist/components/icon/Icon.d.ts +90 -0
  24. package/dist/components/icon/Icon.d.ts.map +1 -0
  25. package/dist/components/icon/Icon.js +172 -0
  26. package/dist/components/icon/Icon.js.map +1 -0
  27. package/dist/components/linear-progress/LinearProgress.d.ts +40 -0
  28. package/dist/components/linear-progress/LinearProgress.d.ts.map +1 -0
  29. package/dist/components/linear-progress/LinearProgress.js +95 -0
  30. package/dist/components/linear-progress/LinearProgress.js.map +1 -0
  31. package/dist/custom-elements.json +772 -0
  32. package/dist/global.d.ts +4 -0
  33. package/dist/storybook/assets/Avatar.stories-BlxrclP0.js +209 -0
  34. package/dist/storybook/assets/AvatarGroup.stories-E3VUvBae.js +211 -0
  35. package/dist/storybook/assets/Badge.stories-f4YvPz0W.js +121 -0
  36. package/dist/storybook/assets/Button.stories-N66xrq4q.js +63 -0
  37. package/dist/storybook/assets/CircularProgress.stories-zWyELtfc.js +451 -0
  38. package/dist/storybook/assets/{Color-64QXVMR3-BV_8WWIP.js → Color-64QXVMR3-B3Y5c9dl.js} +1 -1
  39. package/dist/storybook/assets/{Colors.stories-CcpJ2Txp.js → Colors.stories-nEoNeHhf.js} +1 -1
  40. package/dist/storybook/assets/Events.stories-BP3ensxX.js +108 -0
  41. package/dist/storybook/assets/Heading.stories-DGqWaBpi.js +3 -0
  42. package/dist/storybook/assets/Icon.stories-BWWjh4NZ.js +245 -0
  43. package/dist/storybook/assets/LinearProgress.stories-DMVolkoE.js +397 -0
  44. package/dist/storybook/assets/ReadyMixin.stories-DavcxbQ0.js +55 -0
  45. package/dist/storybook/assets/ScrollShadow.stories-BmwSRNje.js +17 -0
  46. package/dist/storybook/assets/Throttle.stories-DBj-9rhV.js +303 -0
  47. package/dist/storybook/assets/{WithTooltip-SK46ZJ2J-DyavE1Bj.js → WithTooltip-SK46ZJ2J-DW4NXFWt.js} +5 -5
  48. package/dist/storybook/assets/formatter-OMEEQ6HG-BBn014aZ.js +1 -0
  49. package/dist/storybook/assets/iframe-CxsKJSj-.css +1 -0
  50. package/dist/storybook/assets/{iframe-mIh0R_Av.js → iframe-Z4F0Cgki.js} +87 -100
  51. package/dist/storybook/assets/{index-C8IjQgz6.js → index-BUj5S-B7.js} +1 -1
  52. package/dist/storybook/assets/{syntaxhighlighter-CAVLW7PM-36bUIV4n.js → syntaxhighlighter-CAVLW7PM-CsQveU1N.js} +1 -1
  53. package/dist/storybook/iframe.html +2 -2
  54. package/dist/storybook/index.json +1 -1
  55. package/dist/storybook/project.json +1 -1
  56. package/dist/tailwind-plugin-avatar.d.ts +2 -0
  57. package/dist/tailwind-plugin-avatar.d.ts.map +1 -0
  58. package/dist/tailwind-plugin-avatar.js +130 -0
  59. package/dist/tailwind-plugin-avatar.js.map +1 -0
  60. package/dist/tailwind-plugin-avatar.ts +181 -0
  61. package/dist/tailwind-plugin-badge.js +24 -9
  62. package/dist/tailwind-plugin-badge.js.map +1 -1
  63. package/dist/tailwind-plugin-badge.ts +30 -11
  64. package/dist/tailwind-plugin-button.js +14 -15
  65. package/dist/tailwind-plugin-button.js.map +1 -1
  66. package/dist/tailwind-plugin-button.ts +14 -17
  67. package/dist/tailwind-plugin-contrast.d.ts +2 -0
  68. package/dist/tailwind-plugin-contrast.d.ts.map +1 -0
  69. package/dist/tailwind-plugin-contrast.js +17 -0
  70. package/dist/tailwind-plugin-contrast.js.map +1 -0
  71. package/dist/tailwind-plugin-contrast.ts +18 -0
  72. package/dist/tailwind-plugin-icon.js +17 -10
  73. package/dist/tailwind-plugin-icon.js.map +1 -1
  74. package/dist/tailwind-plugin-icon.ts +17 -10
  75. package/dist/tailwind-plugin-ring-contrast.d.ts +2 -0
  76. package/dist/tailwind-plugin-ring-contrast.d.ts.map +1 -0
  77. package/dist/tailwind-plugin-ring-contrast.js +76 -0
  78. package/dist/tailwind-plugin-ring-contrast.js.map +1 -0
  79. package/dist/tailwind-plugin-ring-contrast.ts +90 -0
  80. package/dist/tailwind.config.d.ts +21 -0
  81. package/dist/tailwind.config.d.ts.map +1 -1
  82. package/dist/tailwind.config.js +27 -2
  83. package/dist/tailwind.config.js.map +1 -1
  84. package/dist/tailwind.config.ts +27 -2
  85. package/dist/{utils → util}/EventEmitterMixin.d.ts +23 -17
  86. package/dist/util/EventEmitterMixin.d.ts.map +1 -0
  87. package/dist/{utils → util}/EventEmitterMixin.js +7 -7
  88. package/dist/util/EventEmitterMixin.js.map +1 -0
  89. package/dist/util/ProgressMixin.d.ts +52 -0
  90. package/dist/util/ProgressMixin.d.ts.map +1 -0
  91. package/dist/util/ProgressMixin.js +190 -0
  92. package/dist/util/ProgressMixin.js.map +1 -0
  93. package/dist/util/ReadyMixin.d.ts +31 -0
  94. package/dist/util/ReadyMixin.d.ts.map +1 -0
  95. package/dist/util/ReadyMixin.js +42 -0
  96. package/dist/util/ReadyMixin.js.map +1 -0
  97. package/dist/util/aria.d.ts +3 -0
  98. package/dist/util/aria.d.ts.map +1 -0
  99. package/dist/util/aria.js +44 -0
  100. package/dist/util/aria.js.map +1 -0
  101. package/dist/util/svg.d.ts +9 -0
  102. package/dist/util/svg.d.ts.map +1 -1
  103. package/dist/util/svg.js +22 -0
  104. package/dist/util/svg.js.map +1 -1
  105. package/dist/util/throttle.d.ts +4 -0
  106. package/dist/util/throttle.d.ts.map +1 -0
  107. package/dist/util/throttle.js +30 -0
  108. package/dist/util/throttle.js.map +1 -0
  109. package/package.json +7 -6
  110. package/custom-elements.json +0 -214
  111. package/dist/components/widget/Widget.css +0 -118
  112. package/dist/components/widget/Widget.d.ts +0 -90
  113. package/dist/components/widget/Widget.d.ts.map +0 -1
  114. package/dist/components/widget/Widget.js +0 -196
  115. package/dist/components/widget/Widget.js.map +0 -1
  116. package/dist/components/widget/WidgetUtils.d.ts +0 -14
  117. package/dist/components/widget/WidgetUtils.d.ts.map +0 -1
  118. package/dist/components/widget/WidgetUtils.js +0 -42
  119. package/dist/components/widget/WidgetUtils.js.map +0 -1
  120. package/dist/storybook/assets/Badge.stories-cKvztBhm.js +0 -43
  121. package/dist/storybook/assets/Button.stories-BH3fEuOH.js +0 -63
  122. package/dist/storybook/assets/Heading.stories-cqZamo-6.js +0 -3
  123. package/dist/storybook/assets/Icon.stories-uPhO3RBG.js +0 -28543
  124. package/dist/storybook/assets/Loader.stories-D7Bl-LN9.js +0 -3
  125. package/dist/storybook/assets/ScrollShadow.stories-CWKYDYLk.js +0 -17
  126. package/dist/storybook/assets/Widget-CRTwFkFc.css +0 -1
  127. package/dist/storybook/assets/Widget.stories-CcjywoYR.js +0 -300
  128. package/dist/storybook/assets/formatter-OMEEQ6HG-DBJ97XaR.js +0 -1
  129. package/dist/storybook/assets/iframe-BdHEYpHD.css +0 -1
  130. package/dist/utils/EventEmitterMixin.d.ts.map +0 -1
  131. package/dist/utils/EventEmitterMixin.js.map +0 -1
@@ -0,0 +1,397 @@
1
+ import{g as I,E as h,x as T}from"./iframe-Z4F0Cgki.js";import"./preload-helper-PPVm8Dsz.js";const{events:D,args:V,argTypes:g}=I("btu-linear-progress"),k={title:"Components/Linear Progress",component:"btu-linear-progress",tags:["autodocs"],parameters:{docs:{subtitle:"A horizontal progress bar for showing task completion",description:{component:`
2
+ <h3>When to use:</h3>
3
+ <ul>
4
+ <li>To show progress of a specific task with known completion percentage</li>
5
+ <li>For file uploads, downloads, or processing steps</li>
6
+ <li>When progress needs to be communicated numerically</li>
7
+ </ul>
8
+ `}},actions:{handles:D},controls:{expanded:!0}},args:{...V,color:"primary",thickness:8,progress:0,initialAnimation:!0},argTypes:{...g,"--progress-color":{table:{disable:!0}},"--track-color":{table:{disable:!0}},size:{table:{disable:!0}},customSize:{table:{disable:!0}},color:{...g.color,control:{type:"select"},options:["black","white","primary","teal","gray","purple","rose","error","warning","success"],description:"Theme color of the progress bar.",table:{category:"Attributes",defaultValue:{summary:"primary"}}},thickness:{...g.thickness,control:{type:"number",min:1,max:10},description:"Height of the progress bar.",table:{category:"Attributes",defaultValue:{summary:"8"}}},progress:{...g.progress,control:{type:"range",min:0,max:100,step:1},description:"Progress value between 0 and 100.",table:{category:"Attributes",defaultValue:{summary:"0"}}},label:{...g.label,control:{type:"text"},description:"Optional label text to display to the right of the progress bar.",table:{category:"Attributes",defaultValue:{summary:"undefined"}}},initialAnimation:{...g.initialAnimation,control:{type:"boolean"},description:"Whether to animate progress from 0 to target value when component first becomes visible in viewport. Defaults to true.",table:{category:"Attributes",defaultValue:{summary:"true"}}},ariaLabel:{...g.ariaLabel,control:{type:"text"},description:'Optional aria-label attribute for screen readers. Describes what the progress indicator represents (e.g., "File upload progress").',table:{category:"Attributes",defaultValue:{summary:"undefined"}}},ariaLabelledBy:{...g.ariaLabelledBy,control:{type:"text"},description:"Optional aria-labelledby attribute for screen readers. References the ID of an element that labels the progress indicator.",table:{category:"Attributes",defaultValue:{summary:"undefined"}}},ariaValueText:{...g.ariaValueText,control:{type:"text"},description:"Optional aria-valuetext attribute for screen readers. Provides human-readable text alternative for the progress value.",table:{category:"Attributes",defaultValue:{summary:"undefined"}}},completionAnnouncement:{...g.completionAnnouncement,control:{type:"text"},description:"Optional message to announce to screen readers when progress reaches 100%. If not provided, no announcement will be made on completion.",table:{category:"Attributes",defaultValue:{summary:"undefined"}}},customColor:{name:"--progress-color",control:{type:"color"},description:"Custom progress bar color - overrides the theme color",table:{category:"CSS Properties"}},customTrackColor:{name:"--track-color",control:{type:"color"},description:"Custom track/background color - overrides default gray-100",table:{category:"CSS Properties"}}},render:e=>{const t=[];e.customColor&&t.push(`--progress-color: ${e.customColor}`),e.customTrackColor&&t.push(`--track-color: ${e.customTrackColor}`);const r=t.length>0?t.join("; "):"";return T`<btu-linear-progress
9
+ color="${e.color}"
10
+ thickness="${e.thickness}"
11
+ progress="${e.progress}"
12
+ label="${e.label||h}"
13
+ aria-label="${e.ariaLabel||h}"
14
+ aria-labelledby="${e.ariaLabelledBy||h}"
15
+ aria-valuetext="${e.ariaValueText||h}"
16
+ completion-announcement="${e.completionAnnouncement||h}"
17
+ ?initial-animation="${e.initialAnimation}"
18
+ style="${r}"
19
+ ></btu-linear-progress>`}},v={args:{progress:25},parameters:{docs:{description:{story:"Default horizontal progress bar with primary color. Width fills the container (100%)."}}}},f={render:()=>T`<div class="flex flex-col gap-4">
20
+ <btu-linear-progress progress="25" color="primary"></btu-linear-progress>
21
+ <btu-linear-progress progress="50" color="teal"></btu-linear-progress>
22
+ <btu-linear-progress progress="75" color="warning"></btu-linear-progress>
23
+ <btu-linear-progress progress="100" color="success"></btu-linear-progress>
24
+ </div>`,parameters:{docs:{description:{story:"Progress bars at various completion levels (25%, 50%, 75%, 100%) with different colors. Each bar fills the container width."}}}},x={render:()=>{const e=document.createElement("div");e.className="flex flex-col gap-8";let t=0;const r=document.createElement("btu-linear-progress");r.progress=0,r.color="primary",r.label="0%";const o=setInterval(()=>{t=(t+1)%101,r.progress=t,r.label=`${t}%`,t===100&&setTimeout(()=>{t=0},1e3)},100);let s=0;const n=document.createElement("btu-linear-progress");n.progress=0,n.color="teal",n.label="0/5 files",n.ariaValueText="0 of 5 files uploaded";const l=setInterval(()=>{s=(s+1)%6,n.progress=s*20,n.label=`${s}/5 files`,n.ariaValueText=`${s} of 5 files uploaded`,s===5&&setTimeout(()=>{s=0},3e3)},3e3),a=new MutationObserver(i=>{i.forEach(p=>{p.removedNodes.forEach(d=>{(d===e||d.contains(e))&&(clearInterval(o),clearInterval(l),a.disconnect())})})});return setTimeout(()=>{e.parentNode&&a.observe(e.parentNode,{childList:!0})},0),e.appendChild(r),e.appendChild(n),e},parameters:{docs:{description:{story:`
25
+ Animated progress bars.
26
+
27
+ Top: continuous percentage increments.
28
+
29
+ Bottom: step-based progress with 20% increments every 3 seconds and \`aria-valuetext\` for accessibility (e.g., "3 of 5 files uploaded").`}}}},y={render:()=>{let e;const t=()=>{const r=document.createElement("div"),o=document.createElement("div");o.className="flex flex-col mb-4 items-center";const s=document.createElement("h3");s.className="text-lg font-semibold mb-2",s.textContent="Scroll within the container to see progress bars animate in";const n=document.createElement("button");n.textContent="Reset",n.className="px-4 py-2 bg-primary-500 text-white rounded hover:bg-primary-600",n.onclick=()=>{e.innerHTML="",e.appendChild(t())},o.appendChild(s),o.appendChild(n),r.appendChild(o);const l=document.createElement("div");l.style.height="150px",l.style.overflowY="auto",l.style.border="1px solid #e5e7eb",l.style.borderRadius="4px",l.style.padding="1rem";const a=document.createElement("div");a.className="flex flex-col gap-8",a.style.minHeight="150vh";const i=document.createElement("btu-linear-progress");i.progress=30,i.color="primary",i.label="30%",a.appendChild(i);const p=document.createElement("div");p.style.marginTop="30vh";const d=document.createElement("btu-linear-progress");d.progress=50,d.color="teal",d.label="50%",p.appendChild(d),a.appendChild(p);const b=document.createElement("div");b.style.marginTop="30vh";const m=document.createElement("btu-linear-progress");m.progress=75,m.color="purple",m.label="75%",b.appendChild(m),a.appendChild(b);const u=document.createElement("div");u.style.marginTop="30vh";const c=document.createElement("btu-linear-progress");return c.progress=100,c.color="success",c.label="100%",u.appendChild(c),a.appendChild(u),l.appendChild(a),r.appendChild(l),r};return e=t(),e},parameters:{docs:{description:{story:'Demonstrates the viewport animation - progress bars animate from 0 to their target value when they become visible. Scroll within the container to see each progress bar animate in. Click "Reset" to restart.'}}}},C={render:()=>{const e=document.createElement("div");e.className="flex flex-col items-start gap-4";let t=0;const r=document.createElement("btu-linear-progress");r.progress=0,r.color="primary",r.label="0%";const o=document.createElement("div");o.className="text-sm text-gray-600",o.textContent="Status: In Progress...";const s=document.createElement("div");s.className="text-xs text-gray-500 mt-2",s.textContent="Event Log: (waiting for completion)",r.addEventListener("btu-progress-complete",()=>{o.textContent="Status: Complete! ✓",o.className="text-sm text-green-600 font-semibold",s.textContent=`Event Log: btu-progress-complete fired at ${new Date().toLocaleTimeString()}`,s.className="text-xs text-green-600 mt-2"});let n=!1;const l=setInterval(()=>{n||(t=t+1,r.progress=t,r.label=`${t}%`,t<100&&(o.textContent="Status: In Progress...",o.className="text-sm text-gray-600"),t===100&&(n=!0,setTimeout(()=>{t=0,n=!1},3e3)))},50),a=new MutationObserver(i=>{i.forEach(p=>{p.removedNodes.forEach(d=>{(d===e||d.contains(e))&&(clearInterval(l),a.disconnect())})})});return setTimeout(()=>{e.parentNode&&a.observe(e.parentNode,{childList:!0})},0),e.appendChild(r),e.appendChild(o),e.appendChild(s),e},parameters:{docs:{description:{story:"Demonstrates the btu-progress-complete event that fires when progress reaches 100%. The event fires each time progress completes a cycle."}}}},E={render:()=>{const e=document.createElement("div");e.className="flex flex-col gap-8";const t=document.createElement("div");t.className="flex flex-col gap-2";const r=document.createElement("h4");r.className="text-sm font-semibold text-gray-900",r.textContent="Progress bar with aria-label";const o=document.createElement("p");o.className="text-xs text-gray-600 mb-2",o.textContent='Screen readers announce: "Page loading progress"';const s=document.createElement("btu-linear-progress");s.progress=40,s.color="primary",s.ariaLabel="Page loading progress",t.appendChild(r),t.appendChild(o),t.appendChild(s);const n=document.createElement("div");n.className="flex flex-col gap-2";const l=document.createElement("h4");l.className="text-sm font-semibold text-gray-900",l.textContent="With custom aria-valuetext";const a=document.createElement("p");a.className="text-xs text-gray-600 mb-2",a.textContent='Screen readers announce: "File upload progress, 3 of 5 files uploaded"';const i=document.createElement("btu-linear-progress");i.progress=60,i.color="teal",i.label="3/5 files",i.ariaLabel="File upload progress",i.ariaValueText="3 of 5 files uploaded",n.appendChild(l),n.appendChild(a),n.appendChild(i);const p=document.createElement("div");p.className="flex flex-col gap-2";const d=document.createElement("h4");d.className="text-sm font-semibold text-gray-900",d.textContent="With completion announcement";const b=document.createElement("p");b.className="text-xs text-gray-600 mb-2",b.textContent='Screen readers auto-announce when complete: "Installation complete!"';const m=document.createElement("div");m.className="text-xs text-gray-500 mt-2",m.textContent="Announcement status: (waiting...)";let u=0;const c=document.createElement("btu-linear-progress");c.progress=0,c.color="success",c.label="0%",c.ariaLabel="Installation progress",c.completionAnnouncement="Installation complete!",c.addEventListener("btu-progress-complete",()=>{m.textContent='Announcement status: "Installation complete!" announced at '+new Date().toLocaleTimeString(),m.className="text-xs text-green-600 mt-2"});const w=setInterval(()=>{u<100?(u+=2,c.progress=u,c.label=`${u}%`,c.ariaValueText=`${u} percent complete`):clearInterval(w)},100);p.appendChild(d),p.appendChild(b),p.appendChild(c),p.appendChild(m);const N=new MutationObserver(S=>{S.forEach(A=>{A.removedNodes.forEach(L=>{(L===e||L.contains(e))&&(clearInterval(w),N.disconnect())})})});return setTimeout(()=>{e.parentNode&&N.observe(e.parentNode,{childList:!0})},0),e.appendChild(t),e.appendChild(n),e.appendChild(p),e},parameters:{docs:{description:{story:`
30
+ Demonstrates accessibility best practices for screen reader users:
31
+
32
+ **1. Basic usage:** Set \`ariaLabel\` to describe what's progressing.
33
+
34
+ **2. Detailed progress:** Combine \`ariaLabel\` (what's progressing) with \`ariaValueText\` (human-readable progress like "3 of 5 files uploaded").
35
+
36
+ **3. Completion announcements:** Set \`completionAnnouncement\` to automatically notify screen readers when progress reaches 100%.
37
+ `}}}};v.parameters={...v.parameters,docs:{...v.parameters?.docs,source:{originalSource:`{
38
+ args: {
39
+ progress: 25
40
+ },
41
+ parameters: {
42
+ docs: {
43
+ description: {
44
+ story: 'Default horizontal progress bar with primary color. Width fills the container (100%).'
45
+ }
46
+ }
47
+ }
48
+ }`,...v.parameters?.docs?.source}}};f.parameters={...f.parameters,docs:{...f.parameters?.docs,source:{originalSource:`{
49
+ render: () => html\`<div class="flex flex-col gap-4">
50
+ <btu-linear-progress progress="25" color="primary"></btu-linear-progress>
51
+ <btu-linear-progress progress="50" color="teal"></btu-linear-progress>
52
+ <btu-linear-progress progress="75" color="warning"></btu-linear-progress>
53
+ <btu-linear-progress progress="100" color="success"></btu-linear-progress>
54
+ </div>\`,
55
+ parameters: {
56
+ docs: {
57
+ description: {
58
+ story: 'Progress bars at various completion levels (25%, 50%, 75%, 100%) with different colors. Each bar fills the container width.'
59
+ }
60
+ }
61
+ }
62
+ }`,...f.parameters?.docs?.source}}};x.parameters={...x.parameters,docs:{...x.parameters?.docs,source:{originalSource:`{
63
+ render: () => {
64
+ const container = document.createElement('div');
65
+ container.className = 'flex flex-col gap-8';
66
+
67
+ // First progress: continuous 0-100%
68
+ let progress = 0;
69
+ const progressEl = document.createElement('btu-linear-progress') as any;
70
+ progressEl.progress = 0;
71
+ progressEl.color = 'primary';
72
+ progressEl.label = '0%';
73
+ const interval1 = setInterval(() => {
74
+ progress = (progress + 1) % 101;
75
+ progressEl.progress = progress;
76
+ progressEl.label = \`\${progress}%\`;
77
+ if (progress === 100) {
78
+ setTimeout(() => {
79
+ progress = 0;
80
+ }, 1000);
81
+ }
82
+ }, 100);
83
+
84
+ // Second progress: 20% increments every 3 seconds
85
+ let step = 0;
86
+ const progressEl2 = document.createElement('btu-linear-progress') as any;
87
+ progressEl2.progress = 0;
88
+ progressEl2.color = 'teal';
89
+ progressEl2.label = '0/5 files';
90
+ progressEl2.ariaValueText = '0 of 5 files uploaded';
91
+ const interval2 = setInterval(() => {
92
+ step = (step + 1) % 6;
93
+ progressEl2.progress = step * 20;
94
+ progressEl2.label = \`\${step}/5 files\`;
95
+ progressEl2.ariaValueText = \`\${step} of 5 files uploaded\`;
96
+ if (step === 5) {
97
+ setTimeout(() => {
98
+ step = 0;
99
+ }, 3000);
100
+ }
101
+ }, 3000);
102
+
103
+ // Cleanup intervals when story unmounts
104
+ const observer = new MutationObserver(mutations => {
105
+ mutations.forEach(mutation => {
106
+ mutation.removedNodes.forEach(node => {
107
+ if (node === container || node.contains(container)) {
108
+ clearInterval(interval1);
109
+ clearInterval(interval2);
110
+ observer.disconnect();
111
+ }
112
+ });
113
+ });
114
+ });
115
+ setTimeout(() => {
116
+ if (container.parentNode) {
117
+ observer.observe(container.parentNode, {
118
+ childList: true
119
+ });
120
+ }
121
+ }, 0);
122
+ container.appendChild(progressEl);
123
+ container.appendChild(progressEl2);
124
+ return container;
125
+ },
126
+ parameters: {
127
+ docs: {
128
+ description: {
129
+ story: \`
130
+ Animated progress bars.
131
+
132
+ Top: continuous percentage increments.
133
+
134
+ Bottom: step-based progress with 20% increments every 3 seconds and \\\`aria-valuetext\\\` for accessibility (e.g., "3 of 5 files uploaded").\`
135
+ }
136
+ }
137
+ }
138
+ }`,...x.parameters?.docs?.source}}};y.parameters={...y.parameters,docs:{...y.parameters?.docs,source:{originalSource:`{
139
+ render: () => {
140
+ let rootContainer: HTMLElement;
141
+ const createProgressBars = () => {
142
+ const container = document.createElement('div');
143
+ const header = document.createElement('div');
144
+ header.className = 'flex flex-col mb-4 items-center';
145
+ const h3 = document.createElement('h3');
146
+ h3.className = 'text-lg font-semibold mb-2';
147
+ h3.textContent = 'Scroll within the container to see progress bars animate in';
148
+ const resetBtn = document.createElement('button');
149
+ resetBtn.textContent = 'Reset';
150
+ resetBtn.className = 'px-4 py-2 bg-primary-500 text-white rounded hover:bg-primary-600';
151
+ resetBtn.onclick = () => {
152
+ rootContainer.innerHTML = '';
153
+ rootContainer.appendChild(createProgressBars());
154
+ };
155
+ header.appendChild(h3);
156
+ header.appendChild(resetBtn);
157
+ container.appendChild(header);
158
+ const scrollContainer = document.createElement('div');
159
+ scrollContainer.style.height = '150px';
160
+ scrollContainer.style.overflowY = 'auto';
161
+ scrollContainer.style.border = '1px solid #e5e7eb';
162
+ scrollContainer.style.borderRadius = '4px';
163
+ scrollContainer.style.padding = '1rem';
164
+ const wrapper = document.createElement('div');
165
+ wrapper.className = 'flex flex-col gap-8';
166
+ wrapper.style.minHeight = '150vh';
167
+ const progress1 = document.createElement('btu-linear-progress') as any;
168
+ progress1.progress = 30;
169
+ progress1.color = 'primary';
170
+ progress1.label = '30%';
171
+ wrapper.appendChild(progress1);
172
+ const div2 = document.createElement('div');
173
+ div2.style.marginTop = '30vh';
174
+ const progress2 = document.createElement('btu-linear-progress') as any;
175
+ progress2.progress = 50;
176
+ progress2.color = 'teal';
177
+ progress2.label = '50%';
178
+ div2.appendChild(progress2);
179
+ wrapper.appendChild(div2);
180
+ const div3 = document.createElement('div');
181
+ div3.style.marginTop = '30vh';
182
+ const progress3 = document.createElement('btu-linear-progress') as any;
183
+ progress3.progress = 75;
184
+ progress3.color = 'purple';
185
+ progress3.label = '75%';
186
+ div3.appendChild(progress3);
187
+ wrapper.appendChild(div3);
188
+ const div4 = document.createElement('div');
189
+ div4.style.marginTop = '30vh';
190
+ const progress4 = document.createElement('btu-linear-progress') as any;
191
+ progress4.progress = 100;
192
+ progress4.color = 'success';
193
+ progress4.label = '100%';
194
+ div4.appendChild(progress4);
195
+ wrapper.appendChild(div4);
196
+ scrollContainer.appendChild(wrapper);
197
+ container.appendChild(scrollContainer);
198
+ return container;
199
+ };
200
+ rootContainer = createProgressBars();
201
+ return rootContainer;
202
+ },
203
+ parameters: {
204
+ docs: {
205
+ description: {
206
+ story: 'Demonstrates the viewport animation - progress bars animate from 0 to their target value when they become visible. Scroll within the container to see each progress bar animate in. Click "Reset" to restart.'
207
+ }
208
+ }
209
+ }
210
+ }`,...y.parameters?.docs?.source}}};C.parameters={...C.parameters,docs:{...C.parameters?.docs,source:{originalSource:`{
211
+ render: () => {
212
+ const container = document.createElement('div');
213
+ container.className = 'flex flex-col items-start gap-4';
214
+ let progress = 0;
215
+ const progressEl = document.createElement('btu-linear-progress') as any;
216
+ progressEl.progress = 0;
217
+ progressEl.color = 'primary';
218
+ progressEl.label = '0%';
219
+ const statusDiv = document.createElement('div');
220
+ statusDiv.className = 'text-sm text-gray-600';
221
+ statusDiv.textContent = 'Status: In Progress...';
222
+ const eventLog = document.createElement('div');
223
+ eventLog.className = 'text-xs text-gray-500 mt-2';
224
+ eventLog.textContent = 'Event Log: (waiting for completion)';
225
+ progressEl.addEventListener('btu-progress-complete', () => {
226
+ statusDiv.textContent = 'Status: Complete! ✓';
227
+ statusDiv.className = 'text-sm text-green-600 font-semibold';
228
+ eventLog.textContent = \`Event Log: btu-progress-complete fired at \${new Date().toLocaleTimeString()}\`;
229
+ eventLog.className = 'text-xs text-green-600 mt-2';
230
+ });
231
+ let isWaiting = false;
232
+ const interval = setInterval(() => {
233
+ if (isWaiting) return;
234
+ progress = progress + 1;
235
+ progressEl.progress = progress;
236
+ progressEl.label = \`\${progress}%\`;
237
+ if (progress < 100) {
238
+ statusDiv.textContent = 'Status: In Progress...';
239
+ statusDiv.className = 'text-sm text-gray-600';
240
+ }
241
+ if (progress === 100) {
242
+ isWaiting = true;
243
+ setTimeout(() => {
244
+ progress = 0;
245
+ isWaiting = false;
246
+ }, 3000);
247
+ }
248
+ }, 50);
249
+
250
+ // Cleanup interval when story unmounts
251
+ const observer = new MutationObserver(mutations => {
252
+ mutations.forEach(mutation => {
253
+ mutation.removedNodes.forEach(node => {
254
+ if (node === container || node.contains(container)) {
255
+ clearInterval(interval);
256
+ observer.disconnect();
257
+ }
258
+ });
259
+ });
260
+ });
261
+ setTimeout(() => {
262
+ if (container.parentNode) {
263
+ observer.observe(container.parentNode, {
264
+ childList: true
265
+ });
266
+ }
267
+ }, 0);
268
+ container.appendChild(progressEl);
269
+ container.appendChild(statusDiv);
270
+ container.appendChild(eventLog);
271
+ return container;
272
+ },
273
+ parameters: {
274
+ docs: {
275
+ description: {
276
+ story: 'Demonstrates the btu-progress-complete event that fires when progress reaches 100%. The event fires each time progress completes a cycle.'
277
+ }
278
+ }
279
+ }
280
+ }`,...C.parameters?.docs?.source}}};E.parameters={...E.parameters,docs:{...E.parameters?.docs,source:{originalSource:`{
281
+ render: () => {
282
+ const container = document.createElement('div');
283
+ container.className = 'flex flex-col gap-8';
284
+
285
+ // Example 1: Basic with aria-label
286
+ const section1 = document.createElement('div');
287
+ section1.className = 'flex flex-col gap-2';
288
+ const heading1 = document.createElement('h4');
289
+ heading1.className = 'text-sm font-semibold text-gray-900';
290
+ heading1.textContent = 'Progress bar with aria-label';
291
+ const desc1 = document.createElement('p');
292
+ desc1.className = 'text-xs text-gray-600 mb-2';
293
+ desc1.textContent = 'Screen readers announce: "Page loading progress"';
294
+ const progress1 = document.createElement('btu-linear-progress') as any;
295
+ progress1.progress = 40;
296
+ progress1.color = 'primary';
297
+ progress1.ariaLabel = 'Page loading progress';
298
+ section1.appendChild(heading1);
299
+ section1.appendChild(desc1);
300
+ section1.appendChild(progress1);
301
+
302
+ // Example 2: With aria-valuetext
303
+ const section2 = document.createElement('div');
304
+ section2.className = 'flex flex-col gap-2';
305
+ const heading2 = document.createElement('h4');
306
+ heading2.className = 'text-sm font-semibold text-gray-900';
307
+ heading2.textContent = 'With custom aria-valuetext';
308
+ const desc2 = document.createElement('p');
309
+ desc2.className = 'text-xs text-gray-600 mb-2';
310
+ desc2.textContent = 'Screen readers announce: "File upload progress, 3 of 5 files uploaded"';
311
+ const progress2 = document.createElement('btu-linear-progress') as any;
312
+ progress2.progress = 60;
313
+ progress2.color = 'teal';
314
+ progress2.label = '3/5 files';
315
+ progress2.ariaLabel = 'File upload progress';
316
+ progress2.ariaValueText = '3 of 5 files uploaded';
317
+ section2.appendChild(heading2);
318
+ section2.appendChild(desc2);
319
+ section2.appendChild(progress2);
320
+
321
+ // Example 3: With completion announcement
322
+ const section3 = document.createElement('div');
323
+ section3.className = 'flex flex-col gap-2';
324
+ const heading3 = document.createElement('h4');
325
+ heading3.className = 'text-sm font-semibold text-gray-900';
326
+ heading3.textContent = 'With completion announcement';
327
+ const desc3 = document.createElement('p');
328
+ desc3.className = 'text-xs text-gray-600 mb-2';
329
+ desc3.textContent = 'Screen readers auto-announce when complete: "Installation complete!"';
330
+ const announceLog = document.createElement('div');
331
+ announceLog.className = 'text-xs text-gray-500 mt-2';
332
+ announceLog.textContent = 'Announcement status: (waiting...)';
333
+ let progress3Value = 0;
334
+ const progress3 = document.createElement('btu-linear-progress') as any;
335
+ progress3.progress = 0;
336
+ progress3.color = 'success';
337
+ progress3.label = '0%';
338
+ progress3.ariaLabel = 'Installation progress';
339
+ progress3.completionAnnouncement = 'Installation complete!';
340
+ progress3.addEventListener('btu-progress-complete', () => {
341
+ announceLog.textContent = 'Announcement status: "Installation complete!" announced at ' + new Date().toLocaleTimeString();
342
+ announceLog.className = 'text-xs text-green-600 mt-2';
343
+ });
344
+ const interval3 = setInterval(() => {
345
+ if (progress3Value < 100) {
346
+ progress3Value += 2;
347
+ progress3.progress = progress3Value;
348
+ progress3.label = \`\${progress3Value}%\`;
349
+ progress3.ariaValueText = \`\${progress3Value} percent complete\`;
350
+ } else {
351
+ clearInterval(interval3);
352
+ }
353
+ }, 100);
354
+ section3.appendChild(heading3);
355
+ section3.appendChild(desc3);
356
+ section3.appendChild(progress3);
357
+ section3.appendChild(announceLog);
358
+
359
+ // Cleanup interval when story unmounts
360
+ const observer = new MutationObserver(mutations => {
361
+ mutations.forEach(mutation => {
362
+ mutation.removedNodes.forEach(node => {
363
+ if (node === container || node.contains(container)) {
364
+ clearInterval(interval3);
365
+ observer.disconnect();
366
+ }
367
+ });
368
+ });
369
+ });
370
+ setTimeout(() => {
371
+ if (container.parentNode) {
372
+ observer.observe(container.parentNode, {
373
+ childList: true
374
+ });
375
+ }
376
+ }, 0);
377
+ container.appendChild(section1);
378
+ container.appendChild(section2);
379
+ container.appendChild(section3);
380
+ return container;
381
+ },
382
+ parameters: {
383
+ docs: {
384
+ description: {
385
+ story: \`
386
+ Demonstrates accessibility best practices for screen reader users:
387
+
388
+ **1. Basic usage:** Set \\\`ariaLabel\\\` to describe what's progressing.
389
+
390
+ **2. Detailed progress:** Combine \\\`ariaLabel\\\` (what's progressing) with \\\`ariaValueText\\\` (human-readable progress like "3 of 5 files uploaded").
391
+
392
+ **3. Completion announcements:** Set \\\`completionAnnouncement\\\` to automatically notify screen readers when progress reaches 100%.
393
+ \`
394
+ }
395
+ }
396
+ }
397
+ }`,...E.parameters?.docs?.source}}};const B=["Default","DeterminateProgress","AnimatedProgress","InitialAnimation","CompletionEvent","Accessibility"];export{E as Accessibility,x as AnimatedProgress,C as CompletionEvent,v as Default,f as DeterminateProgress,y as InitialAnimation,B as __namedExportsOrder,k as default};
@@ -0,0 +1,55 @@
1
+ const i={title:"Mixins/Ready Mixin",tags:["autodocs"],parameters:{docs:{description:{component:`
2
+ \`ReadyMixin\` ensures the DOM is fully loaded **before initializing web
3
+ components**.
4
+
5
+ Prevents components from querying or manipulating DOM elements before
6
+ they're available by deferring \`super.connectedCallback()\` until the DOM
7
+ is ready.
8
+
9
+ <h3>What ReadyMixin Does</h3>
10
+ <ul>
11
+ <li>Checks document.readyState when connectedCallback() is called</li>
12
+ <li>DOM is ready: calls \`super.connectedCallback()\` immediately</li>
13
+ <li>If DOM is loading: waits for <b>DOMContentLoaded</b> event, then calls \`super.connectedCallback()\`</li>
14
+ </ul>
15
+
16
+ <h3>Mixin Composition</h3>
17
+
18
+ <p>Place ReadyMixin close to LitElement in the composition chain:</p>
19
+
20
+ <p> ✅ Correct - ReadyMixin near the base
21
+ ComponentStatesMixin(EventEmitterMixin(ReadyMixin(LitElement)))</p>
22
+
23
+ <p> ❌ Incorrect - ReadyMixin too far out
24
+ ReadyMixin(ComponentStatesMixin(EventEmitterMixin(LitElement)))</p>
25
+
26
+ <p>This ensures the DOM-ready check happens before other mixins'
27
+ initialization logic.</p>
28
+
29
+ <h3>Usage</h3>
30
+ \`\`\`typescript
31
+ import { ReadyMixin } from './ReadyMixin'
32
+
33
+ // Basic usage
34
+ class MyComponent extends ReadyMixin(LitElement) {
35
+ connectedCallback() {
36
+ super.connectedCallback()
37
+ // DOM is guaranteed to be ready here
38
+ const child = this.querySelector('.child')
39
+ }
40
+ }
41
+
42
+ // With multiple mixins
43
+ class NavRail extends EventEmitterMixin(ReadyMixin(LitElement)) {
44
+ // All mixins benefit from DOM-ready guarantee
45
+ }
46
+ `}}}},e={parameters:{docs:{description:{story:"ReadyMixin provides lifecycle behavior only. It has no visual output, so this story is empty."}}},render:()=>""};e.parameters={...e.parameters,docs:{...e.parameters?.docs,source:{originalSource:`{
47
+ parameters: {
48
+ docs: {
49
+ description: {
50
+ story: 'ReadyMixin provides lifecycle behavior only. It has no visual output, so this story is empty.'
51
+ }
52
+ }
53
+ },
54
+ render: () => ''
55
+ }`,...e.parameters?.docs?.source}}};const t=["ReadyMixin"];export{e as ReadyMixin,t as __namedExportsOrder,i as default};
@@ -0,0 +1,17 @@
1
+ import{x as a}from"./iframe-Z4F0Cgki.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
+ <style>
3
+ :root {
4
+ --can-scroll: ;
5
+ }
6
+ </style>
7
+ <div class=${["flex","gap-2","bg-gray-500",e].join(" ")}>
8
+ ${r.map((s,t)=>a`<div
9
+ class="text-md flex aspect-square h-[100px] items-center justify-center"
10
+ style="background:oklch(80% 50% ${Math.floor(Math.random()*710)+10});"
11
+ >
12
+ ${s}
13
+ </div>`)}
14
+ </div>
15
+ `},n={title:"CSS Plugins/ScrollShadow",component:"btu-scrollshadow",tags:["autodocs"],parameters:{docs:{subtitle:"This Tailwind CSS plugin provides the `.btu-scrollshadow` utility class for adding shadows to the edges of a scrollable container once the content overflows. The shadows use our gray color palette. You can choose which shade of gray you want. The scroll container must not already use before & after pseudo elements. But, if you need to use before/after modifiers on the container, make sure you also manually set the content property to the `--whitespace` variable. This is a workaround for TWCSS automatically adding a content property to the before/after pseudo-elements, which overrides the `--whitespace` variable by default. Note: this currently only supports x-axis scrolling."},controls:{expanded:!0}},render:e=>l(e),argTypes:{theme:{control:{type:"select"},description:"Choose a shade of gray for the scroll shadow. 25 is almost white, and 900 is almost black.",options:["btu-scrollshadow-25","btu-scrollshadow-50","btu-scrollshadow-100","btu-scrollshadow-200","btu-scrollshadow-300","btu-scrollshadow-400","btu-scrollshadow-500","btu-scrollshadow-600","btu-scrollshadow-700","btu-scrollshadow-800","btu-scrollshadow-900"]}},args:{}},o={args:{}};o.parameters={...o.parameters,docs:{...o.parameters?.docs,source:{originalSource:`{
16
+ args: {}
17
+ }`,...o.parameters?.docs?.source}}};const i=["Default"];export{o as Default,i as __namedExportsOrder,n as default};