@gnireeg/float-bar 0.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.
package/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # @gnireeg/float-bar
2
+
3
+ Floating bar web component that automatically hides when scrolling down and reveals when scrolling up.
4
+
5
+ ## Features
6
+
7
+ - ✨ Smooth animations using requestAnimationFrame
8
+ - 📍 Auto-hide on scroll down, auto-show on scroll up
9
+ - 🎯 Works with both window scroll and container scroll
10
+ - ⚙️ Configurable offset to account for sticky elements
11
+ - 📦 Zero dependencies
12
+ - 🎯 TypeScript support
13
+ - 💨 Lightweight and performant
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @gnireeg/float-bar
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ### Basic Usage
24
+
25
+ ```html
26
+ <script type="module">
27
+ import '@gnireeg/float-bar';
28
+ </script>
29
+
30
+ <float-bar class="bg-slate-800 text-white px-6 py-4">
31
+ <nav>Your navigation content</nav>
32
+ </float-bar>
33
+ ```
34
+
35
+ ### With Offset
36
+
37
+ Use the `offset` attribute to account for sticky elements above the float bar:
38
+
39
+ ```html
40
+ <float-bar offset="80" class="bg-white shadow-md">
41
+ <nav>Your navigation content</nav>
42
+ </float-bar>
43
+ ```
44
+
45
+ ### With Offset Element
46
+
47
+ Automatically use another element's height as offset:
48
+
49
+ ```html
50
+ <header id="top-header" style="height: 60px;">Fixed header</header>
51
+
52
+ <float-bar offset-element="#top-header" class="bg-white shadow-md">
53
+ <nav>Your navigation content</nav>
54
+ </float-bar>
55
+ ```
56
+
57
+ ### In Scrollable Container
58
+
59
+ The float bar automatically detects its scroll container:
60
+
61
+ ```html
62
+ <div style="position: relative; overflow: auto; height: 500px;">
63
+ <float-bar class="bg-white shadow-md">
64
+ <nav>Your navigation content</nav>
65
+ </float-bar>
66
+ <div>Scrollable content...</div>
67
+ </div>
68
+ ```
69
+
70
+ ### Disabled (Static)
71
+
72
+ Disable the auto-hide behavior:
73
+
74
+ ```html
75
+ <float-bar disabled class="bg-white shadow-md">
76
+ <nav>Static navigation</nav>
77
+ </float-bar>
78
+ ```
79
+
80
+ ## API
81
+
82
+ ### Attributes
83
+
84
+ | Attribute | Type | Default | Description |
85
+ |-----------|------|---------|-------------|
86
+ | `offset` | number | `0` | Offset in pixels from the top |
87
+ | `offset-element` | string | - | CSS selector for an element whose height will be used as offset |
88
+ | `disabled` | boolean | `false` | Disables auto-hide behavior |
89
+
90
+ ## Styling
91
+
92
+ The float bar uses CSS transforms for smooth animations. You can style it like any other element:
93
+
94
+ ```css
95
+ float-bar {
96
+ background: white;
97
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
98
+ padding: 1rem;
99
+ }
100
+ ```
101
+
102
+ ## How it Works
103
+
104
+ The float bar:
105
+ 1. Automatically detects its scroll container (window or parent element)
106
+ 2. Monitors scroll direction
107
+ 3. Hides when scrolling down (using translateY transform)
108
+ 4. Shows when scrolling up
109
+ 5. Uses requestAnimationFrame for smooth 60fps animations
110
+
111
+ ## Browser Support
112
+
113
+ Works in all modern browsers that support:
114
+ - Custom Elements v1
115
+ - Shadow DOM v1
116
+ - ES Modules
117
+
118
+ ## License
119
+
120
+ MIT
121
+
122
+ ## Author
123
+
124
+ Joel Geering
@@ -0,0 +1,2 @@
1
+ export type { FloatBarElement, FloatBarAttributes, } from './types';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,eAAe,EACf,kBAAkB,GACnB,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,225 @@
1
+ // SSR-safe: Only define and register components in browser environment
2
+ if (typeof window !== 'undefined' && typeof HTMLElement !== 'undefined') {
3
+ /**
4
+ * A floating bar component with scroll spy, automatic positioning, and sticky behavior.
5
+ *
6
+ * Works with both window scroll and container scroll. The scroll container is automatically
7
+ * detected based on the element's offsetParent. If offsetParent is null or document.body,
8
+ * it will listen to window/document scroll events. Otherwise, it listens to the scroll
9
+ * events of the offsetParent element.
10
+ *
11
+ * @example
12
+ * <!-- Window scroll -->
13
+ * <float-bar>
14
+ * <nav>Your navigation content</nav>
15
+ * </float-bar>
16
+ *
17
+ * @example
18
+ * <!-- Container scroll -->
19
+ * <div style="position: relative; overflow: auto; height: 500px;">
20
+ * <float-bar>
21
+ * <nav>Your navigation content</nav>
22
+ * </float-bar>
23
+ * <div>Scrollable content...</div>
24
+ * </div>
25
+ *
26
+ * @example
27
+ * <!-- With offset (e.g., when a fixed header is above) -->
28
+ * <float-bar offset="80">
29
+ * <nav>Your navigation content</nav>
30
+ * </float-bar>
31
+ *
32
+ * @example
33
+ * <!-- With offset-element (automatically uses another element's height as offset) -->
34
+ * <header id="top-header">Fixed header</header>
35
+ * <float-bar offset-element="#top-header">
36
+ * <nav>Your navigation content</nav>
37
+ * </float-bar>
38
+ *
39
+ * @example
40
+ * <!-- Disabled (bar scrolls normally without hiding) -->
41
+ * <float-bar disabled>
42
+ * <nav>Your navigation content</nav>
43
+ * </float-bar>
44
+ */
45
+ class FloatBar extends HTMLElement {
46
+ static get observedAttributes() {
47
+ return ['offset', 'disabled'];
48
+ }
49
+ constructor() {
50
+ super();
51
+ this.lastScroll = 0;
52
+ this.translateAmount = 0;
53
+ this.navbarHeight = 0;
54
+ this.ticking = false;
55
+ this.resizeTimeout = null;
56
+ this.scrollParent = document;
57
+ this.disabled = false;
58
+ this.offset = 0;
59
+ this.offsetElement = null;
60
+ this.totalOffset = 0;
61
+ this.offsetElementObserver = null;
62
+ this.isResizing = false;
63
+ this.handleScroll = () => {
64
+ if (this.isResizing) {
65
+ return;
66
+ }
67
+ if (!this.ticking) {
68
+ requestAnimationFrame(() => {
69
+ this.calculateTranslateAmount();
70
+ this.applyTransform();
71
+ this.ticking = false;
72
+ });
73
+ this.ticking = true;
74
+ }
75
+ };
76
+ this.handleResize = () => {
77
+ if (this.resizeTimeout)
78
+ clearTimeout(this.resizeTimeout);
79
+ this.resizeTimeout = setTimeout(() => {
80
+ this.handleResizeUpdate();
81
+ }, 150);
82
+ };
83
+ this.disabled = this.hasAttribute('disabled');
84
+ const offsetAttr = this.getAttribute('offset');
85
+ //this.offset = offsetAttr ? parseInt(offsetAttr, 10) : 0;
86
+ this.shadow = this.attachShadow({ mode: 'open' });
87
+ this.shadow.innerHTML = `
88
+ <style>
89
+ :host {
90
+ display: block;
91
+ position: sticky;
92
+ top: var(--sticky-top, 0px);
93
+ left: 0;
94
+ width: 100%;
95
+ }
96
+ </style>
97
+ <slot></slot>
98
+ `;
99
+ this.updateStickyTop();
100
+ }
101
+ updateStickyTop() {
102
+ this.style.setProperty('--sticky-top', `${this.totalOffset}px`);
103
+ }
104
+ calculateTotalOffset() {
105
+ this.totalOffset = this.offset + (this.offsetElement ? this.offsetElement.clientHeight : 0);
106
+ }
107
+ attributeChangedCallback(name, oldValue, newValue) {
108
+ if (oldValue === newValue)
109
+ return;
110
+ if (name === 'offset') {
111
+ this.offset = newValue ? parseInt(newValue, 10) : 0;
112
+ this.calculateTotalOffset();
113
+ this.updateStickyTop();
114
+ }
115
+ if (name === 'disabled') {
116
+ const wasDisabled = this.disabled;
117
+ this.disabled = newValue !== null;
118
+ // Reset navbar position when disabled state changes
119
+ this.translateAmount = 0;
120
+ this.applyTransform();
121
+ // If re-enabled, reset scroll tracking
122
+ if (wasDisabled && !this.disabled) {
123
+ this.lastScroll = this.getScrollPosition();
124
+ }
125
+ }
126
+ }
127
+ connectedCallback() {
128
+ this.scrollParent = this.offsetParent ?? document;
129
+ if (this.scrollParent === document.body) {
130
+ this.scrollParent = document;
131
+ }
132
+ const offsetElementSelector = this.getAttribute('offset-element');
133
+ if (offsetElementSelector) {
134
+ const el = document.querySelector(offsetElementSelector);
135
+ if (el) {
136
+ this.offsetElement = el;
137
+ this.addObserverToOffsetElement();
138
+ }
139
+ }
140
+ requestAnimationFrame(() => {
141
+ this.measureNavbarHeight();
142
+ this.calculateTotalOffset();
143
+ this.updateStickyTop();
144
+ this.lastScroll = this.getScrollPosition();
145
+ });
146
+ this.scrollParent.addEventListener('scroll', this.handleScroll, { passive: true });
147
+ window.addEventListener('resize', this.handleResize);
148
+ }
149
+ disconnectedCallback() {
150
+ this.scrollParent.removeEventListener('scroll', this.handleScroll);
151
+ window.removeEventListener('resize', this.handleResize);
152
+ if (this.resizeTimeout) {
153
+ clearTimeout(this.resizeTimeout);
154
+ }
155
+ }
156
+ addObserverToOffsetElement() {
157
+ if (this.offsetElement) {
158
+ this.offsetElementObserver = new ResizeObserver(() => {
159
+ this.handleResizeUpdate();
160
+ });
161
+ this.offsetElementObserver.observe(this.offsetElement);
162
+ }
163
+ }
164
+ handleResizeUpdate() {
165
+ this.isResizing = true;
166
+ this.measureNavbarHeight();
167
+ this.calculateTotalOffset();
168
+ this.updateStickyTop();
169
+ // Update lastScroll after a short delay to ensure layout has settled
170
+ // and any scroll events triggered by the resize have fired
171
+ setTimeout(() => {
172
+ this.lastScroll = this.getScrollPosition();
173
+ this.isResizing = false;
174
+ }, 0);
175
+ }
176
+ measureNavbarHeight() {
177
+ this.navbarHeight = this.offsetHeight;
178
+ }
179
+ getScrollPosition() {
180
+ if (this.scrollParent === document) {
181
+ return window.scrollY || document.documentElement.scrollTop;
182
+ }
183
+ return this.scrollParent.scrollTop;
184
+ }
185
+ isSticky() {
186
+ if (this.scrollParent === document) {
187
+ return this.getBoundingClientRect().top <= this.totalOffset;
188
+ }
189
+ const parent = this.scrollParent;
190
+ const parentRect = parent.getBoundingClientRect();
191
+ const navbarRect = this.getBoundingClientRect();
192
+ // Account for parent's border
193
+ const computedStyle = window.getComputedStyle(parent);
194
+ const borderTop = parseFloat(computedStyle.borderTopWidth) || 0;
195
+ const threshold = parentRect.top + borderTop + this.totalOffset;
196
+ // Use small tolerance (1px) to account for floating point precision
197
+ return navbarRect.top <= threshold + 1;
198
+ }
199
+ calculateTranslateAmount() {
200
+ if (this.disabled) {
201
+ return;
202
+ }
203
+ const currentScroll = this.getScrollPosition();
204
+ const scrollDiff = currentScroll - this.lastScroll;
205
+ const isSticky = this.isSticky();
206
+ if (currentScroll <= 0 || !isSticky) {
207
+ this.translateAmount = 0;
208
+ }
209
+ else if (scrollDiff > 0) {
210
+ this.translateAmount = Math.min(this.translateAmount + scrollDiff, this.navbarHeight);
211
+ }
212
+ else {
213
+ this.translateAmount = Math.max(this.translateAmount + scrollDiff, 0);
214
+ }
215
+ this.lastScroll = currentScroll;
216
+ }
217
+ applyTransform() {
218
+ this.style.transform = `translateY(-${this.translateAmount}px)`;
219
+ }
220
+ }
221
+ // Register custom element
222
+ customElements.define('float-bar', FloatBar);
223
+ }
224
+ export {};
225
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,uEAAuE;AACvE,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,WAAW,KAAK,WAAW,EAAE,CAAC;IAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAyCG;IACH,MAAM,QAAS,SAAQ,WAAW;QAehC,MAAM,KAAK,kBAAkB;YAC3B,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAChC,CAAC;QAED;YACE,KAAK,EAAE,CAAC;YAnBF,eAAU,GAAG,CAAC,CAAC;YACf,oBAAe,GAAG,CAAC,CAAC;YACpB,iBAAY,GAAG,CAAC,CAAC;YACjB,YAAO,GAAG,KAAK,CAAC;YAEhB,kBAAa,GAAyC,IAAI,CAAC;YAC3D,iBAAY,GAAuB,QAAQ,CAAC;YAC5C,aAAQ,GAAG,KAAK,CAAC;YACjB,WAAM,GAAG,CAAC,CAAC;YACX,kBAAa,GAAmB,IAAI,CAAC;YACrC,gBAAW,GAAG,CAAC,CAAC;YAChB,0BAAqB,GAA0B,IAAI,CAAC;YACpD,eAAU,GAAG,KAAK,CAAC;YA8KnB,iBAAY,GAAG,GAAG,EAAE;gBAC1B,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;oBACpB,OAAO;gBACT,CAAC;gBAED,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;oBAClB,qBAAqB,CAAC,GAAG,EAAE;wBACzB,IAAI,CAAC,wBAAwB,EAAE,CAAC;wBAChC,IAAI,CAAC,cAAc,EAAE,CAAC;wBACtB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;oBACvB,CAAC,CAAC,CAAC;oBACH,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;gBACtB,CAAC;YACH,CAAC,CAAA;YAEO,iBAAY,GAAG,GAAG,EAAE;gBAC1B,IAAI,IAAI,CAAC,aAAa;oBAAE,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBACzD,IAAI,CAAC,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;oBACnC,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBAC5B,CAAC,EAAE,GAAG,CAAC,CAAC;YACV,CAAC,CAAA;YAzLC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;YAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YAC/C,0DAA0D;YAE1D,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG;;;;;;;;;;;KAWvB,CAAC;YACF,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC;QAEO,eAAe;YACrB,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,cAAc,EAAE,GAAG,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC;QAClE,CAAC;QAEO,oBAAoB;YAC1B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9F,CAAC;QAED,wBAAwB,CAAC,IAAY,EAAE,QAAuB,EAAE,QAAuB;YACrF,IAAI,QAAQ,KAAK,QAAQ;gBAAE,OAAO;YAElC,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtB,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACpD,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAC5B,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,CAAC;YAED,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;gBACxB,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC;gBAClC,IAAI,CAAC,QAAQ,GAAG,QAAQ,KAAK,IAAI,CAAC;gBAElC,oDAAoD;gBACpD,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC;gBACzB,IAAI,CAAC,cAAc,EAAE,CAAC;gBAEtB,uCAAuC;gBACvC,IAAI,WAAW,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;oBAClC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAC7C,CAAC;YACH,CAAC;QACH,CAAC;QAED,iBAAiB;YACf,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,QAAQ,CAAC;YAClD,IAAG,IAAI,CAAC,YAAY,KAAK,QAAQ,CAAC,IAAI,EAAC,CAAC;gBACpC,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC;YACjC,CAAC;YAED,MAAM,qBAAqB,GAAG,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;YAClE,IAAG,qBAAqB,EAAC,CAAC;gBACxB,MAAM,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAA;gBACxD,IAAG,EAAE,EAAC,CAAC;oBACL,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;oBACxB,IAAI,CAAC,0BAA0B,EAAE,CAAA;gBACnC,CAAC;YACH,CAAC;YAED,qBAAqB,CAAC,GAAG,EAAE;gBACzB,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAC3B,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAC5B,IAAI,CAAC,eAAe,EAAE,CAAC;gBACvB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC7C,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACnF,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAEvD,CAAC;QAED,oBAAoB;YAClB,IAAI,CAAC,YAAY,CAAC,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YACnE,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YAExD,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACvB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;QAEO,0BAA0B;YAChC,IAAG,IAAI,CAAC,aAAa,EAAC,CAAC;gBACrB,IAAI,CAAC,qBAAqB,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE;oBACnD,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBAC5B,CAAC,CAAC,CAAC;gBAEH,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;YACxD,CAAC;QACH,CAAC;QAEO,kBAAkB;YACxB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACvB,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC3B,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC5B,IAAI,CAAC,eAAe,EAAE,CAAC;YAEvB,qEAAqE;YACrE,2DAA2D;YAC3D,UAAU,CAAC,GAAG,EAAE;gBACd,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAC3C,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;YAC1B,CAAC,EAAE,CAAC,CAAC,CAAC;QACR,CAAC;QAEO,mBAAmB;YACzB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QACxC,CAAC;QAEO,iBAAiB;YACvB,IAAI,IAAI,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;gBACnC,OAAO,MAAM,CAAC,OAAO,IAAI,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC;YAC9D,CAAC;YACD,OAAQ,IAAI,CAAC,YAAwB,CAAC,SAAS,CAAC;QAClD,CAAC;QAEO,QAAQ;YACd,IAAI,IAAI,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;gBACnC,OAAO,IAAI,CAAC,qBAAqB,EAAE,CAAC,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC;YAC9D,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,CAAC,YAAuB,CAAC;YAC5C,MAAM,UAAU,GAAG,MAAM,CAAC,qBAAqB,EAAE,CAAC;YAClD,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAEhD,8BAA8B;YAC9B,MAAM,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;YACtD,MAAM,SAAS,GAAG,UAAU,CAAC,aAAa,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;YAEhE,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,GAAG,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC;YAChE,oEAAoE;YACpE,OAAO,UAAU,CAAC,GAAG,IAAI,SAAS,GAAG,CAAC,CAAC;QACzC,CAAC;QAEO,wBAAwB;YAC9B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,OAAO;YACT,CAAC;YAED,MAAM,aAAa,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC/C,MAAM,UAAU,GAAG,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC;YACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAEjC,IAAI,aAAa,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClC,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC;YAC7B,CAAC;iBAAM,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;gBACxB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,GAAG,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YAC1F,CAAC;iBAAM,CAAC;gBACJ,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC;YAC1E,CAAC;YAED,IAAI,CAAC,UAAU,GAAG,aAAa,CAAC;QAChC,CAAC;QAEK,cAAc;YACpB,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,eAAe,IAAI,CAAC,eAAe,KAAK,CAAC;QAClE,CAAC;KAuBF;IAED,0BAA0B;IAC1B,cAAc,CAAC,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;AAE7C,CAAC"}
package/dist/jsx.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * JSX type definitions for float-bar web component
3
+ *
4
+ * This file augments the JSX namespace to add type definitions for custom elements.
5
+ * Works with both React and Preact without requiring React-specific types.
6
+ */
7
+
8
+ import type {
9
+ FloatBarAttributes,
10
+ } from './types';
11
+
12
+ declare global {
13
+ namespace JSX {
14
+ interface IntrinsicElements {
15
+ 'float-bar': FloatBarAttributes;
16
+ }
17
+ }
18
+ namespace React.JSX {
19
+ interface IntrinsicElements {
20
+ 'float-bar': FloatBarAttributes;
21
+ }
22
+ }
23
+ }
24
+
25
+ // This export is required to make this file a module
26
+ export {};
@@ -0,0 +1,3 @@
1
+ /// <reference path="./jsx.d.ts" />
2
+
3
+ export * from './types';
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Custom element interfaces for float-bar components
3
+ */
4
+ /**
5
+ * FloatBar custom element interface
6
+ */
7
+ export interface FloatBarElement extends HTMLElement {
8
+ }
9
+ /**
10
+ * HTML attributes for float-bar element
11
+ */
12
+ export interface FloatBarAttributes {
13
+ /**
14
+ * Offset in pixels from the top
15
+ */
16
+ offset?: string | number;
17
+ /**
18
+ * CSS selector for an element whose height will be used as offset
19
+ */
20
+ 'offset-element'?: string;
21
+ /**
22
+ * Disables auto-hide behavior
23
+ */
24
+ disabled?: boolean;
25
+ /**
26
+ * Children and standard HTML attributes
27
+ */
28
+ children?: any;
29
+ slot?: string;
30
+ className?: string;
31
+ class?: string;
32
+ style?: string | Record<string, any>;
33
+ id?: string;
34
+ }
35
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,WAAW;CAAG;AAEvD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAEzB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACrC,EAAE,CAAC,EAAE,MAAM,CAAC;CACb"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Custom element interfaces for float-bar components
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@gnireeg/float-bar",
3
+ "version": "0.1.0",
4
+ "description": "Floating bar web component with automatic positioning and sticky behavior",
5
+ "type": "module",
6
+
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/types-entry.d.ts",
9
+
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/types-entry.d.ts",
13
+ "default": "./dist/index.js"
14
+ }
15
+ },
16
+
17
+ "files": [
18
+ "dist",
19
+ "README.md"
20
+ ],
21
+
22
+ "keywords": [
23
+ "float-bar",
24
+ "floating-bar",
25
+ "navigation",
26
+ "tabs",
27
+ "sticky",
28
+ "web-components",
29
+ "custom-elements",
30
+ "accessible",
31
+ "a11y",
32
+ "typescript",
33
+ "ui-components"
34
+ ],
35
+
36
+ "author": "Joel Geering <joel@geering.dev> (https://geering.dev)",
37
+ "license": "MIT",
38
+
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/gnireeG/web-components.git",
42
+ "directory": "packages/float-bar"
43
+ },
44
+
45
+ "scripts": {
46
+ "build": "tsc && node -e \"const fs = require('fs'); fs.copyFileSync('src/jsx.d.ts', 'dist/jsx.d.ts'); fs.copyFileSync('src/types-entry.d.ts', 'dist/types-entry.d.ts');\"",
47
+ "dev": "tsc --watch",
48
+ "prepublishOnly": "npm run build"
49
+ },
50
+
51
+ "devDependencies": {
52
+ "typescript": "^5.4.0"
53
+ }
54
+ }