@brightspot/ui 1.3.0 → 1.4.1
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.
- package/dist/custom-elements.json +144 -144
- package/dist/global.d.ts +10 -0
- package/dist/storybook/assets/{Avatar.stories-CpXI9mXR.js → Avatar.stories-QxWs-YfX.js} +1 -1
- package/dist/storybook/assets/{AvatarGroup.stories-D4NymG47.js → AvatarGroup.stories-Cy_Bvn7E.js} +1 -1
- package/dist/storybook/assets/{Badge.stories-BP4Yixze.js → Badge.stories-BpaApWbR.js} +1 -1
- package/dist/storybook/assets/{Button.stories-DDpQzCOq.js → Button.stories-C5h2usmd.js} +1 -1
- package/dist/storybook/assets/{CircularProgress.stories-B82LXwfS.js → CircularProgress.stories-DlPOiGja.js} +1 -1
- package/dist/storybook/assets/{ClipboardMixin.stories-Cr3efF-v.js → ClipboardMixin.stories-Bb45-UOM.js} +1 -1
- package/dist/storybook/assets/Color-6BZIO3FS-CcgGYVAo.js +1 -0
- package/dist/storybook/assets/{Colors.stories-CeKs5FaB.js → Colors.stories-DP2JKWUJ.js} +1 -1
- package/dist/storybook/assets/{ComponentStatesMixin-BkLj42wt.js → ComponentStatesMixin-B7ci0thi.js} +1 -1
- package/dist/storybook/assets/{ComponentStatesMixin.stories--YPoyrpQ.js → ComponentStatesMixin.stories-CyQ2aSTu.js} +1 -1
- package/dist/storybook/assets/{CopyToClipboard.stories-6vqDwd-F.js → CopyToClipboard.stories-DR7pckeV.js} +1 -1
- package/dist/storybook/assets/Debounce.stories-hkqyvqmg.js +199 -0
- package/dist/storybook/assets/DocsRenderer-LL677BLK-Dtw9GMer.js +758 -0
- package/dist/storybook/assets/{Events.stories-DD9wfoHi.js → Events.stories-BAgDzdyl.js} +1 -1
- package/dist/storybook/assets/{Heading.stories-D-Pvm7NG.js → Heading.stories-CN_fPsRf.js} +1 -1
- package/dist/storybook/assets/{Icon.stories-BbR3S56H.js → Icon.stories-CSx_2K8V.js} +1 -1
- package/dist/storybook/assets/{LinearProgress.stories-B9XHLvVn.js → LinearProgress.stories-In48DY2g.js} +1 -1
- package/dist/storybook/assets/Rtc.stories-19d7WXe4.js +281 -0
- package/dist/storybook/assets/{ScrollShadow.stories-CHFpB4Zf.js → ScrollShadow.stories-BFjracVd.js} +1 -1
- package/dist/storybook/assets/{Throttle.stories-BGNJSyDp.js → Throttle.stories-DD6ydiVq.js} +8 -8
- package/dist/storybook/assets/WithTooltip-65CFNBJE-Be1dKqOF.js +9 -0
- package/dist/storybook/assets/formatter-EIJCOSYU-anC2P5HS.js +1 -0
- package/dist/storybook/assets/{iframe-CpEKhsmw.css → iframe-B4njXYq6.css} +1 -1
- package/dist/storybook/assets/iframe-Bl9oHz5c.js +1061 -0
- package/dist/storybook/assets/index-Cn5E5A3G.js +1 -0
- package/dist/storybook/assets/onFind-DqriYjEB.js +1 -0
- package/dist/storybook/assets/onFind.stories-BMDLUk0l.js +1069 -0
- package/dist/storybook/assets/onRemove.stories-C3FcxtYh.js +234 -0
- package/dist/storybook/assets/onVisible.stories-B8Zyu0Th.js +187 -0
- package/dist/storybook/assets/syntaxhighlighter-ED5Y7EFY-BfTKsIVL.js +6 -0
- package/dist/storybook/iframe.html +57 -39
- package/dist/storybook/index.html +11 -4
- package/dist/storybook/index.json +1 -1
- package/dist/storybook/project.json +1 -1
- package/dist/storybook/sb-addons/docs-1/manager-bundle.js +1 -1
- package/dist/storybook/sb-addons/storybook-core-server-presets-0/common-manager-bundle.js +112 -290
- package/dist/storybook/sb-addons/vitest-2/manager-bundle.js +3 -0
- package/dist/storybook/sb-manager/globals-runtime.js +60754 -66346
- package/dist/storybook/sb-manager/globals.js +2 -3
- package/dist/storybook/sb-manager/manager-stores.js +23 -0
- package/dist/storybook/sb-manager/runtime.js +12983 -11699
- package/dist/storybook/vite-inject-mocker-entry.js +2 -2
- package/dist/tailwind-plugin-button.js +3 -0
- package/dist/tailwind-plugin-button.js.map +1 -1
- package/dist/tailwind-plugin-button.ts +4 -0
- package/dist/util/Socket.d.ts +29 -0
- package/dist/util/Socket.d.ts.map +1 -0
- package/dist/util/Socket.js +153 -0
- package/dist/util/Socket.js.map +1 -0
- package/dist/util/Tether.d.ts +18 -0
- package/dist/util/Tether.d.ts.map +1 -0
- package/dist/util/Tether.js +102 -0
- package/dist/util/Tether.js.map +1 -0
- package/dist/util/TetherLayout.d.ts +12 -0
- package/dist/util/TetherLayout.d.ts.map +1 -0
- package/dist/util/TetherLayout.js +121 -0
- package/dist/util/TetherLayout.js.map +1 -0
- package/dist/util/debounce.d.ts +3 -0
- package/dist/util/debounce.d.ts.map +1 -0
- package/dist/util/debounce.js +15 -0
- package/dist/util/debounce.js.map +1 -0
- package/dist/util/focusable.d.ts +9 -0
- package/dist/util/focusable.d.ts.map +1 -0
- package/dist/util/focusable.js +19 -0
- package/dist/util/focusable.js.map +1 -0
- package/dist/util/getComponentKey.d.ts +2 -0
- package/dist/util/getComponentKey.d.ts.map +1 -0
- package/dist/util/getComponentKey.js +21 -0
- package/dist/util/getComponentKey.js.map +1 -0
- package/dist/util/keyboard.d.ts +8 -0
- package/dist/util/keyboard.d.ts.map +1 -0
- package/dist/util/keyboard.js +138 -0
- package/dist/util/keyboard.js.map +1 -0
- package/dist/util/noise.d.ts +6 -0
- package/dist/util/noise.d.ts.map +1 -0
- package/dist/util/noise.js +43 -0
- package/dist/util/noise.js.map +1 -0
- package/dist/util/onFind.d.ts +1 -0
- package/dist/util/onFind.d.ts.map +1 -1
- package/dist/util/onFind.js +73 -48
- package/dist/util/onFind.js.map +1 -1
- package/dist/util/onFindOnce.d.ts +3 -0
- package/dist/util/onFindOnce.d.ts.map +1 -0
- package/dist/util/onFindOnce.js +25 -0
- package/dist/util/onFindOnce.js.map +1 -0
- package/dist/util/onRTEReady.d.ts +22 -0
- package/dist/util/onRTEReady.d.ts.map +1 -0
- package/dist/util/onRTEReady.js +69 -0
- package/dist/util/onRTEReady.js.map +1 -0
- package/dist/util/onRemove.d.ts +7 -0
- package/dist/util/onRemove.d.ts.map +1 -0
- package/dist/util/onRemove.js +24 -0
- package/dist/util/onRemove.js.map +1 -0
- package/dist/util/onVisible.d.ts +3 -0
- package/dist/util/onVisible.d.ts.map +1 -0
- package/dist/util/onVisible.js +33 -0
- package/dist/util/onVisible.js.map +1 -0
- package/dist/util/previousUntil.d.ts +2 -0
- package/dist/util/previousUntil.d.ts.map +1 -0
- package/dist/util/previousUntil.js +21 -0
- package/dist/util/previousUntil.js.map +1 -0
- package/dist/util/repaint.d.ts +3 -0
- package/dist/util/repaint.d.ts.map +1 -0
- package/dist/util/repaint.js +14 -0
- package/dist/util/repaint.js.map +1 -0
- package/dist/util/rtc.d.ts +10 -0
- package/dist/util/rtc.d.ts.map +1 -0
- package/dist/util/rtc.js +184 -0
- package/dist/util/rtc.js.map +1 -0
- package/dist/util/storage.d.ts +6 -0
- package/dist/util/storage.d.ts.map +1 -0
- package/dist/util/storage.js +18 -0
- package/dist/util/storage.js.map +1 -0
- package/dist/util/transition.d.ts +2 -0
- package/dist/util/transition.d.ts.map +1 -0
- package/dist/util/transition.js +4 -0
- package/dist/util/transition.js.map +1 -0
- package/dist/util/types.d.ts +10 -0
- package/dist/util/types.d.ts.map +1 -0
- package/dist/util/types.js +2 -0
- package/dist/util/types.js.map +1 -0
- package/package.json +17 -6
- package/dist/storybook/assets/Color-64QXVMR3-BucypS4O.js +0 -1
- package/dist/storybook/assets/WithTooltip-SK46ZJ2J-QQZnlVfm.js +0 -825
- package/dist/storybook/assets/formatter-OMEEQ6HG-D3LRXsK-.js +0 -1
- package/dist/storybook/assets/iframe-D-tG1MVV.js +0 -1064
- package/dist/storybook/assets/index-mcT8sPvs.js +0 -1
- package/dist/storybook/assets/onFind.stories-Dagoyfc5.js +0 -284
- package/dist/storybook/assets/syntaxhighlighter-CAVLW7PM-BoS99i_u.js +0 -6
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import{x as p}from"./iframe-Bl9oHz5c.js";import"./preload-helper-PPVm8Dsz.js";let l=!1;function m(e,o){const s=new MutationObserver(r=>{for(const v of r)for(const n of v.removedNodes)n.contains(e)&&!l&&(s.disconnect(),o())});s.observe(document,{childList:!0,subtree:!0})}m.pause=()=>{l=!0};m.resume=()=>{l=!1};const b={title:"Utilities/onRemove",tags:["autodocs"],parameters:{docs:{subtitle:"The `onRemove` utility triggers a callback when a DOM element is removed from the document. Uses MutationObserver to watch for removals, with global pause/resume support."},controls:{expanded:!0}},argTypes:{selector:{control:{type:"text"},description:"CSS selector of element to watch"}},args:{selector:".watched-item"}},i={render:()=>{const e=`onremove-${Math.random().toString(36).substring(2,9)}`;let o=0,s=0;const r=()=>{const n=document.getElementById(`${e}-items-count`),t=document.getElementById(`${e}-removed-count`);n&&(n.textContent=String(o)),t&&(t.textContent=String(s))};return p`
|
|
2
|
+
<div class="space-y-4">
|
|
3
|
+
<div class="text-base">
|
|
4
|
+
<p class="mb-2">
|
|
5
|
+
Click "Add Item" to create elements, then click "Remove" on each item. The onRemove callback detects
|
|
6
|
+
removals and logs them.
|
|
7
|
+
</p>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<div class="flex gap-2">
|
|
11
|
+
<button @click=${()=>{o++;const n=document.getElementById(`${e}-container`);if(!n)return;const t=document.createElement("div"),u=o;t.className="flex items-center justify-between rounded border bg-white p-4",t.innerHTML=`<span>Item ${u}</span>`;const d=document.createElement("button");d.className="rounded bg-red-100 px-2 py-1 text-xs text-red-700 hover:bg-red-200",d.textContent="Remove",d.addEventListener("click",()=>t.remove()),t.appendChild(d),n.appendChild(t),m(t,()=>{s++,o--,r();const g=document.getElementById(`${e}-log`);if(g){const c=document.createElement("div");c.className="text-sm text-gray-600",c.textContent=`Item ${u} removed at ${new Date().toLocaleTimeString()}`,g.prepend(c)}}),r()}} class="bg-primary-500 hover:bg-primary-600 rounded px-4 py-2 text-white">
|
|
12
|
+
Add Item
|
|
13
|
+
</button>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<div id="${e}-container" class="min-h-32 space-y-2 rounded border-2 border-gray-300 bg-gray-50 p-4">
|
|
17
|
+
<div class="text-sm text-gray-500">Items will appear here...</div>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div class="flex justify-around">
|
|
21
|
+
<div>
|
|
22
|
+
<div class="text-xs text-gray-500">Active items</div>
|
|
23
|
+
<div id="${e}-items-count" class="text-2xl font-bold text-gray-900">0</div>
|
|
24
|
+
</div>
|
|
25
|
+
<div>
|
|
26
|
+
<div class="text-xs text-gray-500">Removals detected</div>
|
|
27
|
+
<div id="${e}-removed-count" class="text-primary-600 text-2xl font-bold">0</div>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div>
|
|
32
|
+
<h4 class="mb-1 text-xs font-bold text-gray-500">Removal Log</h4>
|
|
33
|
+
<div id="${e}-log" class="max-h-32 overflow-y-auto rounded border border-gray-200 bg-gray-50 p-2">
|
|
34
|
+
<div class="text-sm text-gray-400">No removals yet.</div>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
`},parameters:{docs:{description:{story:"Interactive example showing onRemove detecting when elements are removed from the DOM. Add items, then remove them to see the callback fire."}}}},a={render:()=>p`
|
|
39
|
+
<div class="space-y-4 text-sm">
|
|
40
|
+
<div>
|
|
41
|
+
<h3 class="mb-2 font-bold">Basic Usage</h3>
|
|
42
|
+
<pre
|
|
43
|
+
class="overflow-x-auto rounded bg-gray-900 p-4 text-gray-100"
|
|
44
|
+
><code>import onRemove from '@brightspot/ui/util/onRemove.js'
|
|
45
|
+
|
|
46
|
+
// Clean up when element is removed
|
|
47
|
+
const widget = document.querySelector('.my-widget')
|
|
48
|
+
onRemove(widget, () => {
|
|
49
|
+
console.log('Widget was removed')
|
|
50
|
+
// Tear down event listeners, intervals, etc.
|
|
51
|
+
})</code></pre>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div>
|
|
55
|
+
<h3 class="mb-2 font-bold">Pause and Resume</h3>
|
|
56
|
+
<pre class="overflow-x-auto rounded bg-gray-900 p-4 text-gray-100"><code>// Pause during bulk DOM operations
|
|
57
|
+
onRemove.pause()
|
|
58
|
+
|
|
59
|
+
// Move elements around without triggering callbacks
|
|
60
|
+
container.innerHTML = ''
|
|
61
|
+
container.append(...reorderedElements)
|
|
62
|
+
|
|
63
|
+
// Resume watching
|
|
64
|
+
onRemove.resume()</code></pre>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<div>
|
|
68
|
+
<h3 class="mb-2 font-bold">Common Use Cases</h3>
|
|
69
|
+
<ul class="list-inside list-disc space-y-1 text-gray-700">
|
|
70
|
+
<li>Cleaning up event listeners when elements are removed</li>
|
|
71
|
+
<li>Cancelling intervals or timeouts tied to DOM elements</li>
|
|
72
|
+
<li>Disconnecting observers or WebSocket connections</li>
|
|
73
|
+
<li>Releasing resources when components are destroyed</li>
|
|
74
|
+
</ul>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<div>
|
|
78
|
+
<h3 class="mb-2 font-bold">Parameters</h3>
|
|
79
|
+
<ul class="space-y-2">
|
|
80
|
+
<li><code class="rounded bg-gray-200 px-1">element</code> (Element): The DOM element to watch for removal</li>
|
|
81
|
+
<li>
|
|
82
|
+
<code class="rounded bg-gray-200 px-1">callback</code> (function): Called once when the element is removed
|
|
83
|
+
from the document
|
|
84
|
+
</li>
|
|
85
|
+
</ul>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
`,parameters:{docs:{description:{story:"Code examples and documentation for using the onRemove utility."}}}};i.parameters={...i.parameters,docs:{...i.parameters?.docs,source:{originalSource:`{
|
|
89
|
+
render: () => {
|
|
90
|
+
const instanceId = \`onremove-\${Math.random().toString(36).substring(2, 9)}\`;
|
|
91
|
+
let itemCount = 0;
|
|
92
|
+
let removeCount = 0;
|
|
93
|
+
const updateCounts = () => {
|
|
94
|
+
const itemsEl = document.getElementById(\`\${instanceId}-items-count\`);
|
|
95
|
+
const removedEl = document.getElementById(\`\${instanceId}-removed-count\`);
|
|
96
|
+
if (itemsEl) itemsEl.textContent = String(itemCount);
|
|
97
|
+
if (removedEl) removedEl.textContent = String(removeCount);
|
|
98
|
+
};
|
|
99
|
+
const addItem = () => {
|
|
100
|
+
itemCount++;
|
|
101
|
+
const container = document.getElementById(\`\${instanceId}-container\`);
|
|
102
|
+
if (!container) return;
|
|
103
|
+
const item = document.createElement('div');
|
|
104
|
+
const itemNum = itemCount;
|
|
105
|
+
item.className = 'flex items-center justify-between rounded border bg-white p-4';
|
|
106
|
+
item.innerHTML = \`<span>Item \${itemNum}</span>\`;
|
|
107
|
+
const removeBtn = document.createElement('button');
|
|
108
|
+
removeBtn.className = 'rounded bg-red-100 px-2 py-1 text-xs text-red-700 hover:bg-red-200';
|
|
109
|
+
removeBtn.textContent = 'Remove';
|
|
110
|
+
removeBtn.addEventListener('click', () => item.remove());
|
|
111
|
+
item.appendChild(removeBtn);
|
|
112
|
+
container.appendChild(item);
|
|
113
|
+
|
|
114
|
+
// Watch for this element's removal
|
|
115
|
+
onRemove(item, () => {
|
|
116
|
+
removeCount++;
|
|
117
|
+
itemCount--;
|
|
118
|
+
updateCounts();
|
|
119
|
+
const log = document.getElementById(\`\${instanceId}-log\`);
|
|
120
|
+
if (log) {
|
|
121
|
+
const entry = document.createElement('div');
|
|
122
|
+
entry.className = 'text-sm text-gray-600';
|
|
123
|
+
entry.textContent = \`Item \${itemNum} removed at \${new Date().toLocaleTimeString()}\`;
|
|
124
|
+
log.prepend(entry);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
updateCounts();
|
|
128
|
+
};
|
|
129
|
+
return html\`
|
|
130
|
+
<div class="space-y-4">
|
|
131
|
+
<div class="text-base">
|
|
132
|
+
<p class="mb-2">
|
|
133
|
+
Click "Add Item" to create elements, then click "Remove" on each item. The onRemove callback detects
|
|
134
|
+
removals and logs them.
|
|
135
|
+
</p>
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
<div class="flex gap-2">
|
|
139
|
+
<button @click=\${addItem} class="bg-primary-500 hover:bg-primary-600 rounded px-4 py-2 text-white">
|
|
140
|
+
Add Item
|
|
141
|
+
</button>
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
<div id="\${instanceId}-container" class="min-h-32 space-y-2 rounded border-2 border-gray-300 bg-gray-50 p-4">
|
|
145
|
+
<div class="text-sm text-gray-500">Items will appear here...</div>
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
<div class="flex justify-around">
|
|
149
|
+
<div>
|
|
150
|
+
<div class="text-xs text-gray-500">Active items</div>
|
|
151
|
+
<div id="\${instanceId}-items-count" class="text-2xl font-bold text-gray-900">0</div>
|
|
152
|
+
</div>
|
|
153
|
+
<div>
|
|
154
|
+
<div class="text-xs text-gray-500">Removals detected</div>
|
|
155
|
+
<div id="\${instanceId}-removed-count" class="text-primary-600 text-2xl font-bold">0</div>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
|
|
159
|
+
<div>
|
|
160
|
+
<h4 class="mb-1 text-xs font-bold text-gray-500">Removal Log</h4>
|
|
161
|
+
<div id="\${instanceId}-log" class="max-h-32 overflow-y-auto rounded border border-gray-200 bg-gray-50 p-2">
|
|
162
|
+
<div class="text-sm text-gray-400">No removals yet.</div>
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
\`;
|
|
167
|
+
},
|
|
168
|
+
parameters: {
|
|
169
|
+
docs: {
|
|
170
|
+
description: {
|
|
171
|
+
story: \`Interactive example showing onRemove detecting when elements are removed from the DOM. Add items, then remove them to see the callback fire.\`
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}`,...i.parameters?.docs?.source}}};a.parameters={...a.parameters,docs:{...a.parameters?.docs,source:{originalSource:`{
|
|
176
|
+
render: () => html\`
|
|
177
|
+
<div class="space-y-4 text-sm">
|
|
178
|
+
<div>
|
|
179
|
+
<h3 class="mb-2 font-bold">Basic Usage</h3>
|
|
180
|
+
<pre
|
|
181
|
+
class="overflow-x-auto rounded bg-gray-900 p-4 text-gray-100"
|
|
182
|
+
><code>import onRemove from '@brightspot/ui/util/onRemove.js'
|
|
183
|
+
|
|
184
|
+
// Clean up when element is removed
|
|
185
|
+
const widget = document.querySelector('.my-widget')
|
|
186
|
+
onRemove(widget, () => {
|
|
187
|
+
console.log('Widget was removed')
|
|
188
|
+
// Tear down event listeners, intervals, etc.
|
|
189
|
+
})</code></pre>
|
|
190
|
+
</div>
|
|
191
|
+
|
|
192
|
+
<div>
|
|
193
|
+
<h3 class="mb-2 font-bold">Pause and Resume</h3>
|
|
194
|
+
<pre class="overflow-x-auto rounded bg-gray-900 p-4 text-gray-100"><code>// Pause during bulk DOM operations
|
|
195
|
+
onRemove.pause()
|
|
196
|
+
|
|
197
|
+
// Move elements around without triggering callbacks
|
|
198
|
+
container.innerHTML = ''
|
|
199
|
+
container.append(...reorderedElements)
|
|
200
|
+
|
|
201
|
+
// Resume watching
|
|
202
|
+
onRemove.resume()</code></pre>
|
|
203
|
+
</div>
|
|
204
|
+
|
|
205
|
+
<div>
|
|
206
|
+
<h3 class="mb-2 font-bold">Common Use Cases</h3>
|
|
207
|
+
<ul class="list-inside list-disc space-y-1 text-gray-700">
|
|
208
|
+
<li>Cleaning up event listeners when elements are removed</li>
|
|
209
|
+
<li>Cancelling intervals or timeouts tied to DOM elements</li>
|
|
210
|
+
<li>Disconnecting observers or WebSocket connections</li>
|
|
211
|
+
<li>Releasing resources when components are destroyed</li>
|
|
212
|
+
</ul>
|
|
213
|
+
</div>
|
|
214
|
+
|
|
215
|
+
<div>
|
|
216
|
+
<h3 class="mb-2 font-bold">Parameters</h3>
|
|
217
|
+
<ul class="space-y-2">
|
|
218
|
+
<li><code class="rounded bg-gray-200 px-1">element</code> (Element): The DOM element to watch for removal</li>
|
|
219
|
+
<li>
|
|
220
|
+
<code class="rounded bg-gray-200 px-1">callback</code> (function): Called once when the element is removed
|
|
221
|
+
from the document
|
|
222
|
+
</li>
|
|
223
|
+
</ul>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
\`,
|
|
227
|
+
parameters: {
|
|
228
|
+
docs: {
|
|
229
|
+
description: {
|
|
230
|
+
story: \`Code examples and documentation for using the onRemove utility.\`
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}`,...a.parameters?.docs?.source}}};const y=["Interactive","UsageExample"];export{i as Interactive,a as UsageExample,y as __namedExportsOrder,b as default};
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import{x as d}from"./iframe-Bl9oHz5c.js";import{o as g}from"./onFind-DqriYjEB.js";import"./preload-helper-PPVm8Dsz.js";import"./_commonjsHelpers-CqkleIqs.js";const b=Symbol.for("brightspot.onVisible");let t;function v(){return t||(t=globalThis[b],t||(t={calledIndex:0},globalThis[b]=t),t)}function h(i,r){const s=`_ovc${v().calledIndex++}`,n=new IntersectionObserver(e=>{for(const o of e)if(o.isIntersecting){const c=o.target,m=c.classList;m.contains(s)||(m.add(s),n.unobserve(c),r(c))}});g(i,e=>{n.observe(e)})}const x={title:"Utilities/onVisible",tags:["autodocs"],parameters:{docs:{subtitle:"The `onVisible` utility triggers a callback once when elements matching a selector become visible in the viewport. Combines `onFind` with `IntersectionObserver` for lazy initialization of dynamically added elements."},controls:{expanded:!0}},argTypes:{selector:{control:{type:"text"},description:"CSS selector to watch for visibility"}},args:{selector:".lazy-item"}},l={render:()=>{const i=`onvisible-${Math.random().toString(36).substring(2,9)}`,r=`.lazy-item-${i}`;let s=0;const n=()=>{const e=document.getElementById(`${i}-visible-count`);e&&(e.textContent=String(s))};return h(r,e=>{s++,n(),e.classList.remove("opacity-30"),e.classList.add("ring-2","ring-success-500","opacity-100"),e.textContent+=" — visible!"}),d`
|
|
2
|
+
<div class="space-y-4">
|
|
3
|
+
<div class="text-base">
|
|
4
|
+
<p class="mb-2">
|
|
5
|
+
Scroll down inside the box below. Items start faded and are highlighted when they enter the viewport. Each
|
|
6
|
+
callback fires only once per element.
|
|
7
|
+
</p>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<div class="flex justify-around">
|
|
11
|
+
<div>
|
|
12
|
+
<div class="text-xs text-gray-500">Items detected as visible</div>
|
|
13
|
+
<div id="${i}-visible-count" class="text-primary-600 text-2xl font-bold">0</div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<div class="h-64 overflow-y-scroll rounded border-2 border-gray-300 bg-gray-50 p-4">
|
|
18
|
+
<div class="space-y-4">
|
|
19
|
+
${Array.from({length:30},(e,o)=>d`<div class="${`lazy-item-${i}`} rounded border bg-white p-4 opacity-30 transition-all">
|
|
20
|
+
Item ${o+1}
|
|
21
|
+
</div>`)}
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
`},parameters:{docs:{description:{story:"Interactive example showing onVisible detecting elements as they scroll into view. Elements are highlighted once when they become visible."}}}},a={render:()=>d`
|
|
26
|
+
<div class="space-y-4 text-sm">
|
|
27
|
+
<div>
|
|
28
|
+
<h3 class="mb-2 font-bold">Basic Usage</h3>
|
|
29
|
+
<pre
|
|
30
|
+
class="overflow-x-auto rounded bg-gray-900 p-4 text-gray-100"
|
|
31
|
+
><code>import { onVisible } from '@brightspot/ui/util/onVisible.js'
|
|
32
|
+
|
|
33
|
+
// Lazy-load images when they scroll into view
|
|
34
|
+
onVisible('.lazy-image', (element) => {
|
|
35
|
+
element.src = element.dataset.src
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// Initialize heavy components only when visible
|
|
39
|
+
onVisible('.chart-container', (element) => {
|
|
40
|
+
initChart(element)
|
|
41
|
+
})</code></pre>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div>
|
|
45
|
+
<h3 class="mb-2 font-bold">How It Works</h3>
|
|
46
|
+
<p class="text-gray-700">
|
|
47
|
+
onVisible combines two utilities: <code class="rounded bg-gray-200 px-1">onFind</code> detects when matching
|
|
48
|
+
elements are added to the DOM, then <code class="rounded bg-gray-200 px-1">IntersectionObserver</code> watches
|
|
49
|
+
for when those elements enter the viewport. The callback fires at most once per element.
|
|
50
|
+
</p>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<div>
|
|
54
|
+
<h3 class="mb-2 font-bold">Common Use Cases</h3>
|
|
55
|
+
<ul class="list-inside list-disc space-y-1 text-gray-700">
|
|
56
|
+
<li>Lazy-loading images or iframes</li>
|
|
57
|
+
<li>Deferring expensive component initialization</li>
|
|
58
|
+
<li>Triggering animations on scroll</li>
|
|
59
|
+
<li>Analytics tracking for element impressions</li>
|
|
60
|
+
</ul>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div>
|
|
64
|
+
<h3 class="mb-2 font-bold">Parameters</h3>
|
|
65
|
+
<ul class="space-y-2">
|
|
66
|
+
<li>
|
|
67
|
+
<code class="rounded bg-gray-200 px-1">selectors</code> (string | string[]): CSS selector(s) to watch for
|
|
68
|
+
</li>
|
|
69
|
+
<li>
|
|
70
|
+
<code class="rounded bg-gray-200 px-1">callback</code> (function): Called once per element when it becomes
|
|
71
|
+
visible
|
|
72
|
+
</li>
|
|
73
|
+
</ul>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
`,parameters:{docs:{description:{story:"Code examples and documentation for using the onVisible utility."}}}};l.parameters={...l.parameters,docs:{...l.parameters?.docs,source:{originalSource:`{
|
|
77
|
+
render: () => {
|
|
78
|
+
const instanceId = \`onvisible-\${Math.random().toString(36).substring(2, 9)}\`;
|
|
79
|
+
const uniqueSelector = \`.lazy-item-\${instanceId}\`;
|
|
80
|
+
let visibleCount = 0;
|
|
81
|
+
const updateCount = () => {
|
|
82
|
+
const el = document.getElementById(\`\${instanceId}-visible-count\`);
|
|
83
|
+
if (el) el.textContent = String(visibleCount);
|
|
84
|
+
};
|
|
85
|
+
onVisible(uniqueSelector, (element: HTMLElement) => {
|
|
86
|
+
visibleCount++;
|
|
87
|
+
updateCount();
|
|
88
|
+
element.classList.remove('opacity-30');
|
|
89
|
+
element.classList.add('ring-2', 'ring-success-500', 'opacity-100');
|
|
90
|
+
element.textContent += ' — visible!';
|
|
91
|
+
});
|
|
92
|
+
return html\`
|
|
93
|
+
<div class="space-y-4">
|
|
94
|
+
<div class="text-base">
|
|
95
|
+
<p class="mb-2">
|
|
96
|
+
Scroll down inside the box below. Items start faded and are highlighted when they enter the viewport. Each
|
|
97
|
+
callback fires only once per element.
|
|
98
|
+
</p>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
<div class="flex justify-around">
|
|
102
|
+
<div>
|
|
103
|
+
<div class="text-xs text-gray-500">Items detected as visible</div>
|
|
104
|
+
<div id="\${instanceId}-visible-count" class="text-primary-600 text-2xl font-bold">0</div>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
<div class="h-64 overflow-y-scroll rounded border-2 border-gray-300 bg-gray-50 p-4">
|
|
109
|
+
<div class="space-y-4">
|
|
110
|
+
\${Array.from({
|
|
111
|
+
length: 30
|
|
112
|
+
}, (_, i) => html\`<div class="\${\`lazy-item-\${instanceId}\`} rounded border bg-white p-4 opacity-30 transition-all">
|
|
113
|
+
Item \${i + 1}
|
|
114
|
+
</div>\`)}
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
\`;
|
|
119
|
+
},
|
|
120
|
+
parameters: {
|
|
121
|
+
docs: {
|
|
122
|
+
description: {
|
|
123
|
+
story: \`Interactive example showing onVisible detecting elements as they scroll into view. Elements are highlighted once when they become visible.\`
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}`,...l.parameters?.docs?.source}}};a.parameters={...a.parameters,docs:{...a.parameters?.docs,source:{originalSource:`{
|
|
128
|
+
render: () => html\`
|
|
129
|
+
<div class="space-y-4 text-sm">
|
|
130
|
+
<div>
|
|
131
|
+
<h3 class="mb-2 font-bold">Basic Usage</h3>
|
|
132
|
+
<pre
|
|
133
|
+
class="overflow-x-auto rounded bg-gray-900 p-4 text-gray-100"
|
|
134
|
+
><code>import { onVisible } from '@brightspot/ui/util/onVisible.js'
|
|
135
|
+
|
|
136
|
+
// Lazy-load images when they scroll into view
|
|
137
|
+
onVisible('.lazy-image', (element) => {
|
|
138
|
+
element.src = element.dataset.src
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
// Initialize heavy components only when visible
|
|
142
|
+
onVisible('.chart-container', (element) => {
|
|
143
|
+
initChart(element)
|
|
144
|
+
})</code></pre>
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
<div>
|
|
148
|
+
<h3 class="mb-2 font-bold">How It Works</h3>
|
|
149
|
+
<p class="text-gray-700">
|
|
150
|
+
onVisible combines two utilities: <code class="rounded bg-gray-200 px-1">onFind</code> detects when matching
|
|
151
|
+
elements are added to the DOM, then <code class="rounded bg-gray-200 px-1">IntersectionObserver</code> watches
|
|
152
|
+
for when those elements enter the viewport. The callback fires at most once per element.
|
|
153
|
+
</p>
|
|
154
|
+
</div>
|
|
155
|
+
|
|
156
|
+
<div>
|
|
157
|
+
<h3 class="mb-2 font-bold">Common Use Cases</h3>
|
|
158
|
+
<ul class="list-inside list-disc space-y-1 text-gray-700">
|
|
159
|
+
<li>Lazy-loading images or iframes</li>
|
|
160
|
+
<li>Deferring expensive component initialization</li>
|
|
161
|
+
<li>Triggering animations on scroll</li>
|
|
162
|
+
<li>Analytics tracking for element impressions</li>
|
|
163
|
+
</ul>
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
<div>
|
|
167
|
+
<h3 class="mb-2 font-bold">Parameters</h3>
|
|
168
|
+
<ul class="space-y-2">
|
|
169
|
+
<li>
|
|
170
|
+
<code class="rounded bg-gray-200 px-1">selectors</code> (string | string[]): CSS selector(s) to watch for
|
|
171
|
+
</li>
|
|
172
|
+
<li>
|
|
173
|
+
<code class="rounded bg-gray-200 px-1">callback</code> (function): Called once per element when it becomes
|
|
174
|
+
visible
|
|
175
|
+
</li>
|
|
176
|
+
</ul>
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
\`,
|
|
180
|
+
parameters: {
|
|
181
|
+
docs: {
|
|
182
|
+
description: {
|
|
183
|
+
story: \`Code examples and documentation for using the onVisible utility.\`
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}`,...a.parameters?.docs?.source}}};const w=["Interactive","UsageExample"];export{l as Interactive,a as UsageExample,w as __namedExportsOrder,x as default};
|