sb-floating-panel-vue 0.1.5 โ†’ 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Stefano Biddau
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md CHANGED
@@ -1,158 +1,228 @@
1
1
  # sb-floating-panel-vue
2
+
2
3
  [![npm](https://img.shields.io/npm/v/sb-floating-panel-vue.svg)](https://www.npmjs.com/package/sb-floating-panel-vue)
3
- [![license](https://img.shields.io/npm/l/sb-floating-panel-vue.svg)](https://github.com/stefanobiddau/sb-floating-panel-vue/blob/main/LICENSE)
4
+ [![license](https://img.shields.io/npm/l/sb-floating-panel-vue.svg)](https://github.com/stefanBid/sb-floating-panel-vue/blob/main/LICENSE)
5
+ [![Vue 3](https://img.shields.io/badge/vue-3.x-brightgreen.svg)](https://vuejs.org)
6
+ [![build](https://img.shields.io/badge/build-passing-brightgreen.svg)](#)
7
+
8
+ ## ๐Ÿ”ฅ Features
9
+
10
+ - ๐Ÿงฉ Floating panel positioning with arrow and smart shifting
11
+ - โšก Built on top of [`@floating-ui/vue`](https://floating-ui.com/)
12
+ - ๐ŸŽฏ Support for resize syncing and animated transitions
13
+ - ๐Ÿงช Dual usage: composable or plug-and-play components
14
+
15
+ ---
16
+
17
+ ## ๐Ÿ‘ค Author
4
18
 
5
- > A lightweight Vue 3 composable hook built on top of [@floating-ui/vue](https://github.com/floating-ui/floating-ui) to manage floating panels with arrow and resize support.
19
+ Created with โค๏ธ by [Stefano Biddau](https://www.stefano-biddau.com/)
6
20
 
7
21
  ---
8
22
 
9
- ## โœจ Features
23
+ ## โ“ Why This Library?
10
24
 
11
- - ๐Ÿ“ฆ Minimal and composable API
12
- - ๐ŸŽฏ Precise floating panel positioning via `@floating-ui/vue`
13
- - ๐ŸŽˆ Optional arrow positioning
14
- - ๐Ÿ“ Auto-resize support
15
- - ๐Ÿง  TypeScript-first
25
+ `sb-floating-panel-vue` was designed to make it extremely easy to implement dropdowns, tooltips, and floating panels in Vue 3, without worrying about placement logic, arrow positioning, or responsive syncing. It wraps `@floating-ui/vue` into a more ergonomic composable or ready-to-use components.
16
26
 
17
27
  ---
18
28
 
19
- ## ๐Ÿš€ Installation
29
+ ## ๐Ÿ“ฆ Installation
20
30
 
21
31
  ```bash
32
+ # npm
22
33
  npm install sb-floating-panel-vue
23
- # or
34
+
35
+ # yarn
24
36
  yarn add sb-floating-panel-vue
37
+
38
+ # pnpm
39
+ pnpm add sb-floating-panel-vue
25
40
  ```
26
41
 
27
42
  ---
28
43
 
29
- ## ๐Ÿงฉ Usage
44
+ ## ๐Ÿง  Composable Usage
30
45
 
31
- The `useSbFloatingPanel` composable provides an easy-to-integrate API to handle floating panels, such as tooltips, popovers, dropdowns, and other UI overlays.
46
+ Use the composable `useSbFloatingPanel()` for complete control.
32
47
 
33
- ### Importing
48
+ ### Options
49
+
50
+
51
+ | Option | Type | Required | Default | Description |
52
+ |------------|------------|----------|---------|--------------------------------------------------|
53
+ | placement | `Placement` | Yes | โ€” | Placement of the floating panel |
54
+ | strategy | `'absolute'` \| `'fixed'` | Yes | โ€” | CSS positioning strategy |
55
+ | offsetValue| `number` | Yes | โ€” | Offset between reference and floating |
56
+ | hasArrow | `boolean` | No | `false` | Whether to render arrow |
57
+ | hasResize | `boolean` | No | `false` | Sync width of floating to reference |
58
+
59
+ ### Return Values
60
+
61
+ | Property | Type | Description |
62
+ |-----------------------|--------------------------------------|----------------------------------------|
63
+ | reference | `Ref<HTMLElement \| null>` | Ref for the trigger element |
64
+ | floating | `Ref<FloatingElement \| null>` | Ref for the floating panel |
65
+ | floatingArrow | `Ref<HTMLElement \| null>` | Ref for the arrow element |
66
+ | floatingPlacement | `Ref<Placement>` | The actual resolved placement |
67
+ | floatingStyle | `ComputedRef<CSSProperties>` | Style for the floating panel |
68
+ | floatingArrowStyle | `ComputedRef<CSSProperties>` | Style for the arrow |
69
+ | isOpen | `Ref<boolean>` | Panel visibility |
70
+ | toggle / open / close | `() => void` | Control methods to toggle visibility |
34
71
 
35
- ```ts
36
- import { useSbFloatingPanel } from 'sb-floating-panel-vue';
37
- ```
38
72
 
39
- ### ๐Ÿง  API
73
+ ### Example
74
+ In your Vue component, you can use the composable like this:
40
75
 
76
+ In your script tag, import the composable and use it:
41
77
  ```ts
78
+ import { useSbFloatingPanel } from 'sb-floating-panel-vue';
79
+
42
80
  const {
43
81
  reference,
44
82
  floating,
45
- popperArrow,
83
+ floatingArrow,
84
+ floatingStyle,
85
+ floatingArrowStyle,
46
86
  isOpen,
47
- floatingPosition,
48
- floatingStyles,
49
- floatingArrowStyles,
50
- changeFloatingVisibility,
51
- } = useSbFloatingPanel(settings);
87
+ toggle,
88
+ } = useSbFloatingPanel({
89
+ placement: 'bottom-start',
90
+ strategy: 'absolute',
91
+ offsetValue: 12,
92
+ hasArrow: true,
93
+ });
52
94
  ```
95
+ In your template, you can bind the refs and styles:
96
+ ```html
97
+ <template>
98
+ <button ref="reference" @click="toggle()">Open Panel</button>
99
+ <div v-if="isOpen" ref="floating" :style="floatingStyle">
100
+ Panel
101
+ <div ref="floatingArrow" :style="floatingArrowStyle" />
102
+ </div>
103
+ </template>
104
+ ```
105
+
106
+ ---
53
107
 
54
- ### Parameters
108
+ ## ๐Ÿงฑ Component-Based Usage
55
109
 
56
- The composable takes a `settings` object:
110
+ ### Import the style
111
+
112
+ If you use components, you **must** import styles in `main.ts`:
57
113
 
58
114
  ```ts
59
- interface FloatingSettings {
60
- placement: Placement; // e.g., 'bottom', 'top-start', etc.
61
- strategy: Strategy; // 'absolute' | 'fixed'
62
- offsetValue: number; // offset in pixels from the reference element
63
- hasArrow?: boolean; // enable arrow positioning
64
- hasResize?: boolean; // enable auto-resizing with anchor element
65
- }
115
+ import 'sb-floating-panel-vue/style.css';
66
116
  ```
67
117
 
68
- ---
118
+ ### Available Components
69
119
 
70
- ## ๐Ÿ” Computed Values Explained
120
+ #### `<SbContainer>`
71
121
 
72
- ### `floatingStyles`
122
+ Wraps everything and provides the context.
73
123
 
74
- A Vue `computed` value containing the CSS style object that must be applied to your floating panel. It is dynamically calculated by `@floating-ui/vue` to maintain optimal placement relative to the reference element.
124
+ | Prop | Type | Default | Description |
125
+ |-------------|---------------------------|-----------------|-----------------------------------------------------------------------------|
126
+ | placement | `Placement` | `'bottom-start'`| Placement of the floating panel relative to the reference element |
127
+ | strategy | `'absolute' \| 'fixed'` | `'absolute'` | CSS positioning strategy for the floating panel |
128
+ | offsetValue | `number` | `15` | Offset in pixels between reference and floating panel |
129
+ | hasArrow | `boolean` | `false` | Whether to render an arrow pointing to the reference |
130
+ | hasResize | `boolean` | `false` | Whether the floating panel should sync its width with the reference |
75
131
 
76
- ### `floatingPosition`
77
132
 
78
- The actual resolved placement string, e.g., `'bottom-start'`, useful for adding custom animations or behavior depending on where the panel is placed.
79
133
 
80
- ### `floatingArrowStyles`
134
+ #### `<SbReference>`
81
135
 
82
- An object that includes styles for positioning the optional arrow element (enabled via the `hasArrow` setting). You can directly bind this to the arrowโ€™s `style` attribute.
136
+ Trigger element
83
137
 
84
- ---
138
+ | Prop | Type | Default | Description |
139
+ |--------------|-----------------------------------|--------------|------------------------------------------------------------------------------|
140
+ | referenceRef | `Ref<HTMLElement \| null>` | **required** | Reference element to which the floating panel is attached |
141
+ | as | `'button' \| 'div' \| 'span' \| etc.` | `'button'` | HTML tag to render. Defaults to `<button>` for accessibility |
142
+ | onClick | `() => void` | โ€” | Optional click handler, often used to toggle the floating panel visibility |
85
143
 
86
- ## ๐Ÿงช Example
87
144
 
88
- ```ts
89
- <script setup lang="ts">
90
- import { ref } from 'vue';
91
- import { useSbFloatingPanel } from 'sb-floating-panel-vue';
145
+ #### `<SbFloating>`
92
146
 
93
- const {
94
- reference,
95
- floating,
96
- popperArrow,
97
- isOpen,
98
- floatingStyles,
99
- floatingArrowStyles,
100
- changeFloatingVisibility,
101
- } = useSbFloatingPanel({
102
- placement: 'bottom',
103
- strategy: 'absolute',
104
- offsetValue: 8,
105
- hasArrow: true,
106
- hasResize: true,
107
- });
147
+ Floating panel
148
+
149
+ | Prop | Type | Default | Description |
150
+ |---------------------|----------------------------------------------|-----------------|-----------------------------------------------------------------------------|
151
+ | floatingRef | `Ref<HTMLElement \| null>` | **required** | The target element for the floating panel (popover, tooltip, etc.) |
152
+ | floatingArrowRef | `Ref<HTMLElement \| null>` | optional | The element used as the floating arrow |
153
+ | isOpen | `boolean` | **required** | Controls visibility of the floating panel |
154
+ | floatingPlacement | `Placement` | **required** | Current placement as resolved by `@floating-ui/vue` |
155
+ | floatingStyle | `CSSProperties` | **required** | Inline style object applied to the floating panel |
156
+ | floatingArrowStyle | `CSSProperties` | optional | Inline style object applied to the arrow element |
157
+ | arrowDimensions | `number` | optional | Size (width/height) of the arrow in pixels |
158
+ | zIndex | `number` | `undefined` | Custom z-index applied to the floating and arrow elements |
159
+ | animation | `'fade' \| 'scale-fade' \| 'none'` | `'scale-fade'` | Defines the animation style for enter/leave transitions |
160
+ | duration | `number` | `300` | Duration in ms for the transition animations |
161
+
162
+
163
+ ---
164
+
165
+ ### ๐Ÿงช Component Usage Example
108
166
 
109
- const togglePanel = () => {
110
- changeFloatingVisibility(!isOpen.value);
111
- };
112
- </script>
167
+ In your project, you can use the components like this:
168
+
169
+ In your script tag, import the components:
170
+ ```ts
171
+ import { SbContainer, SbFloating, SbReference } from 'sb-floating-panel-vue';
113
172
  ```
114
173
 
115
- ```vue
116
- <template>
117
- <button ref="reference" @click="togglePanel">Toggle Panel</button>
118
- <div
119
- v-if="isOpen"
120
- ref="floating"
121
- :style="floatingStyles"
122
- class="popover"
123
- >
124
- I'm a floating panel!
125
- <div ref="popperArrow" :style="floatingArrowStyles.arrow" class="arrow" />
126
- </div>
127
- </template>
174
+ In your template, you can use the components as follows:
175
+ ```html
176
+ <SbContainer :has-arrow="true" strategy="fixed">
177
+ <template #default="{
178
+ reference,
179
+ floating,
180
+ floatingArrow,
181
+ floatingPlacement,
182
+ floatingStyle,
183
+ floatingArrowStyle,
184
+ isOpen,
185
+ toggle
186
+ }">
187
+ <SbReference :reference-ref="reference" :onClick="toggle">Toggle</SbReference>
188
+ <SbFloating
189
+ :is-open="isOpen.value"
190
+ :floating-ref="floating"
191
+ :floating-arrow-ref="floatingArrow"
192
+ :floating-placement="floatingPlacement.value"
193
+ :floating-style="floatingStyle.value"
194
+ :floating-arrow-style="floatingArrowStyle.value"
195
+ :arrow-dimensions="12"
196
+ :z-index="200"
197
+ >
198
+ Hello Panel!
199
+ </SbFloating>
200
+ </template>
201
+ </SbContainer>
128
202
  ```
129
203
 
130
204
  ---
131
205
 
132
- ## ๐ŸŽจ Styling
133
-
134
- You can use your own CSS or utility classes (like Tailwind CSS) to style the panel and the arrow. Example:
135
-
136
- ```css
137
- .popover {
138
- background: white;
139
- border: 1px solid #ccc;
140
- padding: 0.75rem;
141
- border-radius: 0.5rem;
142
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
143
- }
144
-
145
- .arrow {
146
- width: 10px;
147
- height: 10px;
148
- background: white;
149
- transform: rotate(45deg);
150
- position: absolute;
151
- }
206
+ ## โš ๏ธ Directive Note (Teleport Limitation)
207
+
208
+ Due to `<teleport>` in `<SbFloating>`, if you apply custom directives directly to the component, Vue will warn:
209
+
210
+ ```
211
+ [Vue warn]: Extraneous non-props attributes ([directive-name]) were passed to component but could not be automatically inherited because component renders fragment or text or teleport root nodes.
212
+ ```
213
+
214
+ **Solution**: Move the directive to an inner element using the slot.
215
+
216
+ ### Example Fix
217
+
218
+ ```vue
219
+ <SbFloating ...>
220
+ <div v-click-outside>...</div>
221
+ </SbFloating>
152
222
  ```
153
223
 
154
224
  ---
155
225
 
156
226
  ## ๐Ÿ“„ License
157
227
 
158
- MIT ยฉ [Stefano Biddau](https://github.com/stefanobiddau)
228
+ [MIT License](https://github.com/stefanBid/sb-floating-panel-vue/blob/main/LICENSE) ยฉ [Stefano Biddau](https://www.stefano-biddau.com/)
@@ -0,0 +1,66 @@
1
+ import { Placement, Strategy } from '@floating-ui/vue';
2
+ /**
3
+ * Props for the SbContainer component.
4
+ * Serves as a controller and provider for the floating panel system.
5
+ */
6
+ interface SbContainerProps {
7
+ /**
8
+ * Placement of the floating panel relative to the reference.
9
+ * @default 'bottom-start'
10
+ */
11
+ placement?: Placement;
12
+ /**
13
+ * Positioning strategy to use ('absolute' or 'fixed').
14
+ * @default 'absolute'
15
+ */
16
+ strategy?: Strategy;
17
+ /**
18
+ * Pixel offset between the reference and floating panel.
19
+ * @default 15
20
+ */
21
+ offsetValue?: number;
22
+ /**
23
+ * Whether to render an arrow pointing toward the reference element.
24
+ * @default false
25
+ */
26
+ hasArrow?: boolean;
27
+ /**
28
+ * When true, syncs the floating panel width to the reference width.
29
+ * @default false
30
+ */
31
+ hasResize?: boolean;
32
+ }
33
+ declare function __VLS_template(): {
34
+ attrs: Partial<{}>;
35
+ slots: {
36
+ default?(_: {
37
+ reference: import('vue').Ref<HTMLElement | null, HTMLElement | null>;
38
+ floating: import('vue').Ref<HTMLElement | null, HTMLElement | null>;
39
+ floatingArrow: import('vue').Ref<HTMLElement | null, HTMLElement | null>;
40
+ floatingPlacement: import('vue').Ref<Placement, Placement>;
41
+ floatingStyle: import('vue').ComputedRef<import('vue').CSSProperties>;
42
+ floatingArrowStyle: import('vue').ComputedRef<import('vue').CSSProperties>;
43
+ isOpen: import('vue').Ref<boolean, boolean>;
44
+ toggle: () => void;
45
+ open: () => void;
46
+ close: () => void;
47
+ }): any;
48
+ };
49
+ refs: {};
50
+ rootEl: any;
51
+ };
52
+ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
53
+ declare const __VLS_component: import('vue').DefineComponent<SbContainerProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<SbContainerProps> & Readonly<{}>, {
54
+ placement: Placement;
55
+ strategy: Strategy;
56
+ offsetValue: number;
57
+ hasArrow: boolean;
58
+ hasResize: boolean;
59
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
60
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
61
+ export default _default;
62
+ type __VLS_WithTemplateSlots<T, S> = T & {
63
+ new (): {
64
+ $slots: S;
65
+ };
66
+ };
@@ -0,0 +1,76 @@
1
+ import { Placement } from '@floating-ui/vue';
2
+ import { CSSProperties, Ref } from 'vue';
3
+ /**
4
+ * Props for the SbFloating component.
5
+ * This component renders the floating panel and (optionally) its arrow using teleport.
6
+ */
7
+ interface SbFloatingProps {
8
+ /**
9
+ * The ref to bind to the floating panel element.
10
+ */
11
+ floatingRef: Ref<HTMLElement | null>;
12
+ /**
13
+ * Optional ref to bind to the floating arrow element.
14
+ */
15
+ floatingArrowRef?: Ref<HTMLElement | null>;
16
+ /**
17
+ * Whether the floating panel is open (visible).
18
+ */
19
+ isOpen: boolean;
20
+ /**
21
+ * The final placement resolved by Floating UI (e.g., 'bottom-start').
22
+ */
23
+ floatingPlacement: Placement;
24
+ /**
25
+ * Computed inline styles for the floating panel.
26
+ */
27
+ floatingStyle: CSSProperties;
28
+ /**
29
+ * Computed inline styles for the floating arrow (optional).
30
+ */
31
+ floatingArrowStyle?: CSSProperties;
32
+ /**
33
+ * Optional dimension (width & height) of the floating arrow.
34
+ * If provided, will override default arrow size.
35
+ */
36
+ arrowDimensions?: number;
37
+ /**
38
+ * Optional z-index to apply to the floating panel and arrow.
39
+ */
40
+ zIndex?: number;
41
+ /**
42
+ * Animation name used in Vue <transition>.
43
+ * Supported values: 'fade', 'scale-fade', 'none'.
44
+ * @default 'scale-fade'
45
+ */
46
+ animation?: 'fade' | 'scale-fade' | 'none';
47
+ /**
48
+ * Duration of the transition animation in milliseconds.
49
+ * @default 300
50
+ */
51
+ duration?: number;
52
+ }
53
+ declare function __VLS_template(): {
54
+ attrs: Partial<{}>;
55
+ slots: {
56
+ default?(_: {}): any;
57
+ };
58
+ refs: {};
59
+ rootEl: any;
60
+ };
61
+ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
62
+ declare const __VLS_component: import('vue').DefineComponent<SbFloatingProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<SbFloatingProps> & Readonly<{}>, {
63
+ floatingArrowStyle: CSSProperties;
64
+ floatingArrowRef: Ref<HTMLElement | null>;
65
+ arrowDimensions: number;
66
+ zIndex: number;
67
+ animation: "fade" | "scale-fade" | "none";
68
+ duration: number;
69
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
70
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
71
+ export default _default;
72
+ type __VLS_WithTemplateSlots<T, S> = T & {
73
+ new (): {
74
+ $slots: S;
75
+ };
76
+ };
@@ -0,0 +1,41 @@
1
+ import { Ref } from 'vue';
2
+ /**
3
+ * Props for the SbReference component.
4
+ * Renders the reference element for the floating panel system.
5
+ */
6
+ interface SbReferenceProps {
7
+ /**
8
+ * The ref to bind to the reference DOM element.
9
+ */
10
+ referenceRef: Ref<HTMLElement | null>;
11
+ /**
12
+ * HTML tag to render as the reference.
13
+ * Useful for accessibility and customization.
14
+ * @default 'button'
15
+ */
16
+ as?: 'button' | 'a' | 'div' | 'span';
17
+ /**
18
+ * Optional click handler for toggling the floating panel.
19
+ */
20
+ onClick?: () => void;
21
+ }
22
+ declare function __VLS_template(): {
23
+ attrs: Partial<{}>;
24
+ slots: {
25
+ default?(_: {}): any;
26
+ };
27
+ refs: {};
28
+ rootEl: any;
29
+ };
30
+ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
31
+ declare const __VLS_component: import('vue').DefineComponent<SbReferenceProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<SbReferenceProps> & Readonly<{}>, {
32
+ onClick: () => void;
33
+ as: "button" | "a" | "div" | "span";
34
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
35
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
36
+ export default _default;
37
+ type __VLS_WithTemplateSlots<T, S> = T & {
38
+ new (): {
39
+ $slots: S;
40
+ };
41
+ };
@@ -0,0 +1,81 @@
1
+ import { FloatingElement, Placement, Strategy } from '@floating-ui/vue';
2
+ import { CSSProperties, Ref, ComputedRef } from 'vue';
3
+ /**
4
+ * Configuration options for the `useSbFloatingPanel` composable.
5
+ */
6
+ interface FloatingSettings {
7
+ /**
8
+ * Defines the preferred placement of the floating element relative to the reference.
9
+ * Example: 'top', 'bottom-start', 'right-end', etc.
10
+ */
11
+ placement: Placement;
12
+ /**
13
+ * Determines the positioning strategy for the floating element.
14
+ * Can be either 'absolute' or 'fixed'.
15
+ */
16
+ strategy: Strategy;
17
+ /**
18
+ * Specifies the distance (in pixels) between the reference and floating elements.
19
+ */
20
+ offsetValue: number;
21
+ /**
22
+ * Enables the use of a directional arrow pointing from the floating element to the reference.
23
+ */
24
+ hasArrow?: boolean;
25
+ /**
26
+ * When enabled, synchronizes the width of the floating element to match the reference element.
27
+ * Useful for dropdowns or inputs.
28
+ */
29
+ hasResize?: boolean;
30
+ }
31
+ /**
32
+ * `useSbFloatingPanel` is a composable that wraps Floating UI logic to manage
33
+ * floating elements with optional arrow and dynamic width support.
34
+ *
35
+ * It provides bindings and style objects ready to apply to your `ref` elements in Vue templates.
36
+ *
37
+ * @param settings - Configuration options for placement, offset, and behavior.
38
+ * @returns Bindings and utility functions to control the floating panel.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * const {
43
+ * reference,
44
+ * floating,
45
+ * floatingArrow,
46
+ * floatingPlacement,
47
+ * floatingStyle,
48
+ * floatingArrowStyle,
49
+ * isOpen,
50
+ * toggle,
51
+ * open,
52
+ * close
53
+ * } = useSbFloatingPanel({
54
+ * placement: 'bottom',
55
+ * strategy: 'absolute',
56
+ * offsetValue: 10,
57
+ * hasArrow: true,
58
+ * hasResize: false
59
+ * });
60
+ * ```
61
+ *
62
+ * @example
63
+ * ```html
64
+ * <div ref="reference">Anchor</div>
65
+ * <div ref="floating" v-if="isOpen">Panel</div>
66
+ * <div ref="floatingArrow" v-if="isOpen">Arrow</div>
67
+ * ```
68
+ */
69
+ export declare function useSbFloatingPanel(settings: FloatingSettings): {
70
+ reference: Ref<HTMLElement | null>;
71
+ floating: Ref<FloatingElement | null>;
72
+ floatingArrow: Ref<HTMLElement | null>;
73
+ floatingPlacement: Ref<Placement>;
74
+ floatingStyle: ComputedRef<CSSProperties>;
75
+ floatingArrowStyle: ComputedRef<CSSProperties>;
76
+ isOpen: Ref<boolean>;
77
+ toggle: () => void;
78
+ open: () => void;
79
+ close: () => void;
80
+ };
81
+ export {};
package/dist/index.d.ts CHANGED
@@ -1 +1,4 @@
1
- export { useSbFloatingPanel } from './use-sb-floating-panel/useSbFloatingPanel';
1
+ export { useSbFloatingPanel } from './composables/useSbFloatingPanel';
2
+ export { default as SbContainer } from './components/SbContainer.vue';
3
+ export { default as SbReference } from './components/SbReference.vue';
4
+ export { default as SbFloating } from './components/SbFloating.vue';
@@ -0,0 +1 @@
1
+ .floating-container[data-v-33e40585]{width:fit-content;height:fit-content}.fade-enter-active[data-v-366682ad],.fade-leave-active[data-v-366682ad]{transition:opacity var(--sb-transition-duration) ease-in-out}.fade-enter-from[data-v-366682ad],.fade-leave-to[data-v-366682ad]{opacity:0}.fade-enter-to[data-v-366682ad],.fade-leave-from[data-v-366682ad]{opacity:1}.scale-fade-enter-active[data-v-366682ad],.scale-fade-leave-active[data-v-366682ad]{transition:opacity var(--sb-transition-duration) ease-in-out,transform var(--sb-transition-duration) ease-in-out}.scale-fade-enter-from[data-v-366682ad],.scale-fade-leave-to[data-v-366682ad]{opacity:0;transform:scale(.95)}.scale-fade-enter-to[data-v-366682ad],.scale-fade-leave-from[data-v-366682ad]{opacity:1;transform:scale(1)}
@@ -1,45 +1,219 @@
1
- import { useFloating as m, autoUpdate as d, offset as w, flip as b, shift as y, arrow as z } from "@floating-ui/vue";
2
- import { ref as t, watch as f, onMounted as O, onUnmounted as R, nextTick as g } from "vue";
3
- function F(a) {
4
- const l = t(null), n = t(null), u = t(null), r = t(!1), o = t(null);
5
- let i = !1;
6
- const { floatingStyles: c, placement: v, middlewareData: p } = m(l, n, {
7
- open: r,
1
+ import { useFloating as V, autoUpdate as B, offset as M, flip as T, shift as W, arrow as D } from "@floating-ui/vue";
2
+ import { ref as c, computed as u, watch as S, onMounted as E, onUnmounted as K, nextTick as N, defineComponent as k, createElementBlock as x, openBlock as v, renderSlot as z, normalizeProps as U, guardReactiveProps as j, createBlock as A, resolveDynamicComponent as q, mergeProps as $, withKeys as _, withModifiers as w, withCtx as C, useAttrs as G, Teleport as H, createVNode as J, Transition as L, createCommentVNode as R, unref as Q, normalizeStyle as X } from "vue";
3
+ function Y(a) {
4
+ const e = c(null), l = c(null), r = c(null), o = c(!1), s = c(null);
5
+ let t = !1;
6
+ const { floatingStyles: f, placement: i, middlewareData: m } = V(e, l, {
7
+ open: o,
8
8
  placement: a.placement,
9
9
  strategy: a.strategy,
10
10
  transform: !1,
11
- middleware: [
12
- w(a.offsetValue),
13
- b(),
14
- y(),
15
- ...a.hasArrow ? [z({ element: u })] : []
16
- ],
17
- whileElementsMounted: d
18
- }), h = (e) => {
19
- r.value = e;
20
- }, s = () => {
21
- n.value && l.value && (n.value.style.width = `${l.value.offsetWidth}px`);
22
- };
23
- return f(r, async (e) => {
24
- e && a.hasResize && i && (await g(), s());
25
- }), f(l, (e) => {
26
- e && a.hasResize && !i && (i = !0, o.value = new ResizeObserver(s), o.value.observe(e));
27
- }), O(() => {
28
- a.hasResize && l.value && (i = !0, o.value = new ResizeObserver(s), o.value.observe(l.value));
29
- }), R(() => {
30
- var e;
31
- a.hasResize && ((e = o.value) == null || e.disconnect());
11
+ middleware: [M(a.offsetValue), T(), W(), D({ element: r })],
12
+ whileElementsMounted: B
13
+ }), d = (n) => {
14
+ o.value = n;
15
+ }, b = () => d(!0), y = () => d(!1), h = () => d(!o.value), g = () => {
16
+ l.value && e.value && (l.value.style.width = `${e.value.offsetWidth}px`);
17
+ }, O = u(() => ({
18
+ ...f.value
19
+ })), P = u(() => {
20
+ const n = m.value.arrow, F = i.value.split("-")[0], p = {
21
+ position: "absolute",
22
+ transform: "rotate(45deg)",
23
+ background: "inherit",
24
+ width: "8px",
25
+ height: "8px",
26
+ left: (n == null ? void 0 : n.x) != null ? `${n.x}px` : "",
27
+ top: (n == null ? void 0 : n.y) != null ? `${n.y}px` : ""
28
+ };
29
+ switch (F) {
30
+ case "top":
31
+ p.bottom = "-4px";
32
+ break;
33
+ case "bottom":
34
+ p.top = "-4px";
35
+ break;
36
+ case "left":
37
+ p.right = "-4px";
38
+ break;
39
+ case "right":
40
+ p.left = "-4px";
41
+ break;
42
+ }
43
+ return p;
44
+ });
45
+ return S(o, async (n) => {
46
+ n && a.hasResize && t && (await N(), g());
47
+ }), S(e, (n) => {
48
+ n && a.hasResize && !t && (t = !0, s.value = new ResizeObserver(g), s.value.observe(n));
49
+ }), E(() => {
50
+ a.hasResize && e.value && (t = !0, s.value = new ResizeObserver(g), s.value.observe(e.value));
51
+ }), K(() => {
52
+ var n;
53
+ a.hasResize && ((n = s.value) == null || n.disconnect());
32
54
  }), {
33
- reference: l,
34
- floating: n,
35
- popperArrow: u,
36
- isOpen: r,
37
- floatingPosition: v,
38
- floatingStyles: c,
39
- floatingArrowStyles: p,
40
- changeFloatingVisibility: h
55
+ reference: e,
56
+ floating: l,
57
+ floatingArrow: r,
58
+ floatingPlacement: i,
59
+ floatingStyle: O,
60
+ floatingArrowStyle: P,
61
+ isOpen: o,
62
+ toggle: h,
63
+ open: b,
64
+ close: y
41
65
  };
42
66
  }
67
+ const Z = { class: "floating-container" }, ee = /* @__PURE__ */ k({
68
+ __name: "SbContainer",
69
+ props: {
70
+ placement: { default: "bottom-start" },
71
+ strategy: { default: "absolute" },
72
+ offsetValue: { default: 15 },
73
+ hasArrow: { type: Boolean, default: !1 },
74
+ hasResize: { type: Boolean, default: !1 }
75
+ },
76
+ setup(a) {
77
+ const e = a, {
78
+ isOpen: l,
79
+ reference: r,
80
+ floating: o,
81
+ floatingArrow: s,
82
+ floatingPlacement: t,
83
+ floatingStyle: f,
84
+ floatingArrowStyle: i,
85
+ toggle: m,
86
+ open: d,
87
+ close: b
88
+ } = Y({
89
+ placement: e.placement,
90
+ strategy: e.strategy,
91
+ offsetValue: e.offsetValue,
92
+ hasArrow: e.hasArrow,
93
+ hasResize: e.hasResize
94
+ }), y = {
95
+ reference: r,
96
+ floating: o,
97
+ floatingArrow: s,
98
+ floatingPlacement: t,
99
+ floatingStyle: f,
100
+ floatingArrowStyle: i,
101
+ isOpen: l,
102
+ toggle: m,
103
+ open: d,
104
+ close: b
105
+ };
106
+ return (h, g) => (v(), x("div", Z, [
107
+ z(h.$slots, "default", U(j(y)), void 0, !0)
108
+ ]));
109
+ }
110
+ }), I = (a, e) => {
111
+ const l = a.__vccOpts || a;
112
+ for (const [r, o] of e)
113
+ l[r] = o;
114
+ return l;
115
+ }, ae = /* @__PURE__ */ I(ee, [["__scopeId", "data-v-33e40585"]]), le = /* @__PURE__ */ k({
116
+ __name: "SbReference",
117
+ props: {
118
+ referenceRef: {},
119
+ as: { default: "button" },
120
+ onClick: { type: Function, default: void 0 }
121
+ },
122
+ setup(a) {
123
+ const e = a, l = u(() => e.as === "button" || e.as === "a");
124
+ return (r, o) => (v(), A(q(e.as), $(r.$attrs, {
125
+ ref: e.referenceRef,
126
+ role: l.value ? "button" : void 0,
127
+ tabindex: l.value ? 0 : void 0,
128
+ onClick: o[0] || (o[0] = w((s) => {
129
+ var t;
130
+ return (t = e.onClick) == null ? void 0 : t.call(e);
131
+ }, ["stop"])),
132
+ onKeydown: [
133
+ o[1] || (o[1] = _(w((s) => {
134
+ var t;
135
+ return l.value && ((t = e.onClick) == null ? void 0 : t.call(e));
136
+ }, ["prevent", "stop"]), ["space"])),
137
+ o[2] || (o[2] = _(w((s) => {
138
+ var t;
139
+ return l.value && ((t = e.onClick) == null ? void 0 : t.call(e));
140
+ }, ["prevent", "stop"]), ["enter"]))
141
+ ]
142
+ }), {
143
+ default: C(() => [
144
+ z(r.$slots, "default")
145
+ ]),
146
+ _: 3
147
+ }, 16, ["role", "tabindex"]));
148
+ }
149
+ }), te = /* @__PURE__ */ k({
150
+ inheritAttrs: !1,
151
+ __name: "SbFloating",
152
+ props: {
153
+ floatingRef: {},
154
+ floatingArrowRef: { default: () => c(null) },
155
+ isOpen: { type: Boolean },
156
+ floatingPlacement: {},
157
+ floatingStyle: {},
158
+ floatingArrowStyle: { default: void 0 },
159
+ arrowDimensions: { default: void 0 },
160
+ zIndex: { default: void 0 },
161
+ animation: { default: "scale-fade" },
162
+ duration: { default: 300 }
163
+ },
164
+ setup(a) {
165
+ const e = a, l = G(), r = u(() => {
166
+ const t = {
167
+ ...e.floatingStyle,
168
+ "--sb-transition-duration": e.duration + "ms"
169
+ };
170
+ return e.zIndex !== void 0 && (t.zIndex = e.zIndex), t;
171
+ }), o = u(() => {
172
+ const t = { ...e.floatingArrowStyle || {} };
173
+ if (e.arrowDimensions) {
174
+ const f = e.arrowDimensions, i = `-${f / 2}px`;
175
+ switch (e.floatingPlacement.split("-")[0]) {
176
+ case "top":
177
+ t.bottom = i;
178
+ break;
179
+ case "bottom":
180
+ t.top = i;
181
+ break;
182
+ case "left":
183
+ t.right = i;
184
+ break;
185
+ case "right":
186
+ t.left = i;
187
+ break;
188
+ }
189
+ t.width = `${f}px`, t.height = `${f}px`;
190
+ }
191
+ return e.zIndex !== void 0 && (t.zIndex = e.zIndex), t;
192
+ }), s = u(() => e.animation === "fade" ? "fade" : e.animation === "scale-fade" ? "scale-fade" : "");
193
+ return (t, f) => (v(), A(H, { to: "body" }, [
194
+ J(L, { name: s.value }, {
195
+ default: C(() => [
196
+ e.isOpen ? (v(), x("div", $({
197
+ key: 0,
198
+ ref: e.floatingRef,
199
+ style: r.value
200
+ }, Q(l)), [
201
+ z(t.$slots, "default", {}, void 0, !0),
202
+ e.floatingArrowRef ? (v(), x("div", {
203
+ key: 0,
204
+ ref: e.floatingArrowRef,
205
+ style: X(o.value)
206
+ }, null, 4)) : R("", !0)
207
+ ], 16)) : R("", !0)
208
+ ]),
209
+ _: 3
210
+ }, 8, ["name"])
211
+ ]));
212
+ }
213
+ }), se = /* @__PURE__ */ I(te, [["__scopeId", "data-v-366682ad"]]);
43
214
  export {
44
- F as useSbFloatingPanel
215
+ ae as SbContainer,
216
+ se as SbFloating,
217
+ le as SbReference,
218
+ Y as useSbFloatingPanel
45
219
  };
@@ -1 +1 @@
1
- (function(i,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("@floating-ui/vue"),require("vue")):typeof define=="function"&&define.amd?define(["exports","@floating-ui/vue","vue"],e):(i=typeof globalThis<"u"?globalThis:i||self,e(i.SbFloatingPanel={},i.FloatingUIVue,i.Vue))})(this,function(i,e,n){"use strict";function d(o){const a=n.ref(null),r=n.ref(null),c=n.ref(null),s=n.ref(!1),l=n.ref(null);let f=!1;const{floatingStyles:p,placement:h,middlewareData:m}=e.useFloating(a,r,{open:s,placement:o.placement,strategy:o.strategy,transform:!1,middleware:[e.offset(o.offsetValue),e.flip(),e.shift(),...o.hasArrow?[e.arrow({element:c})]:[]],whileElementsMounted:e.autoUpdate}),w=t=>{s.value=t},u=()=>{r.value&&a.value&&(r.value.style.width=`${a.value.offsetWidth}px`)};return n.watch(s,async t=>{t&&o.hasResize&&f&&(await n.nextTick(),u())}),n.watch(a,t=>{t&&o.hasResize&&!f&&(f=!0,l.value=new ResizeObserver(u),l.value.observe(t))}),n.onMounted(()=>{o.hasResize&&a.value&&(f=!0,l.value=new ResizeObserver(u),l.value.observe(a.value))}),n.onUnmounted(()=>{var t;o.hasResize&&((t=l.value)==null||t.disconnect())}),{reference:a,floating:r,popperArrow:c,isOpen:s,floatingPosition:h,floatingStyles:p,floatingArrowStyles:m,changeFloatingVisibility:w}}i.useSbFloatingPanel=d,Object.defineProperty(i,Symbol.toStringTag,{value:"Module"})});
1
+ (function(s,c){typeof exports=="object"&&typeof module<"u"?c(exports,require("@floating-ui/vue"),require("vue")):typeof define=="function"&&define.amd?define(["exports","@floating-ui/vue","vue"],c):(s=typeof globalThis<"u"?globalThis:s||self,c(s.SbFloatingPanelVue={},s.FloatingUIVue,s.Vue))})(this,function(s,c,e){"use strict";function k(l){const t=e.ref(null),i=e.ref(null),f=e.ref(null),n=e.ref(!1),r=e.ref(null);let o=!1;const{floatingStyles:p,placement:d,middlewareData:g}=c.useFloating(t,i,{open:n,placement:l.placement,strategy:l.strategy,transform:!1,middleware:[c.offset(l.offsetValue),c.flip(),c.shift(),c.arrow({element:f})],whileElementsMounted:c.autoUpdate}),u=a=>{n.value=a},h=()=>u(!0),y=()=>u(!1),w=()=>u(!n.value),b=()=>{i.value&&t.value&&(i.value.style.width=`${t.value.offsetWidth}px`)},C=e.computed(()=>({...p.value})),B=e.computed(()=>{const a=g.value.arrow,P=d.value.split("-")[0],m={position:"absolute",transform:"rotate(45deg)",background:"inherit",width:"8px",height:"8px",left:(a==null?void 0:a.x)!=null?`${a.x}px`:"",top:(a==null?void 0:a.y)!=null?`${a.y}px`:""};switch(P){case"top":m.bottom="-4px";break;case"bottom":m.top="-4px";break;case"left":m.right="-4px";break;case"right":m.left="-4px";break}return m});return e.watch(n,async a=>{a&&l.hasResize&&o&&(await e.nextTick(),b())}),e.watch(t,a=>{a&&l.hasResize&&!o&&(o=!0,r.value=new ResizeObserver(b),r.value.observe(a))}),e.onMounted(()=>{l.hasResize&&t.value&&(o=!0,r.value=new ResizeObserver(b),r.value.observe(t.value))}),e.onUnmounted(()=>{var a;l.hasResize&&((a=r.value)==null||a.disconnect())}),{reference:t,floating:i,floatingArrow:f,floatingPlacement:d,floatingStyle:C,floatingArrowStyle:B,isOpen:n,toggle:w,open:h,close:y}}const x={class:"floating-container"},_=e.defineComponent({__name:"SbContainer",props:{placement:{default:"bottom-start"},strategy:{default:"absolute"},offsetValue:{default:15},hasArrow:{type:Boolean,default:!1},hasResize:{type:Boolean,default:!1}},setup(l){const t=l,{isOpen:i,reference:f,floating:n,floatingArrow:r,floatingPlacement:o,floatingStyle:p,floatingArrowStyle:d,toggle:g,open:u,close:h}=k({placement:t.placement,strategy:t.strategy,offsetValue:t.offsetValue,hasArrow:t.hasArrow,hasResize:t.hasResize}),y={reference:f,floating:n,floatingArrow:r,floatingPlacement:o,floatingStyle:p,floatingArrowStyle:d,isOpen:i,toggle:g,open:u,close:h};return(w,b)=>(e.openBlock(),e.createElementBlock("div",x,[e.renderSlot(w.$slots,"default",e.normalizeProps(e.guardReactiveProps(y)),void 0,!0)]))}}),S=(l,t)=>{const i=l.__vccOpts||l;for(const[f,n]of t)i[f]=n;return i},z=S(_,[["__scopeId","data-v-33e40585"]]),R=e.defineComponent({__name:"SbReference",props:{referenceRef:{},as:{default:"button"},onClick:{type:Function,default:void 0}},setup(l){const t=l,i=e.computed(()=>t.as==="button"||t.as==="a");return(f,n)=>(e.openBlock(),e.createBlock(e.resolveDynamicComponent(t.as),e.mergeProps(f.$attrs,{ref:t.referenceRef,role:i.value?"button":void 0,tabindex:i.value?0:void 0,onClick:n[0]||(n[0]=e.withModifiers(r=>{var o;return(o=t.onClick)==null?void 0:o.call(t)},["stop"])),onKeydown:[n[1]||(n[1]=e.withKeys(e.withModifiers(r=>{var o;return i.value&&((o=t.onClick)==null?void 0:o.call(t))},["prevent","stop"]),["space"])),n[2]||(n[2]=e.withKeys(e.withModifiers(r=>{var o;return i.value&&((o=t.onClick)==null?void 0:o.call(t))},["prevent","stop"]),["enter"]))]}),{default:e.withCtx(()=>[e.renderSlot(f.$slots,"default")]),_:3},16,["role","tabindex"]))}}),A=S(e.defineComponent({inheritAttrs:!1,__name:"SbFloating",props:{floatingRef:{},floatingArrowRef:{default:()=>e.ref(null)},isOpen:{type:Boolean},floatingPlacement:{},floatingStyle:{},floatingArrowStyle:{default:void 0},arrowDimensions:{default:void 0},zIndex:{default:void 0},animation:{default:"scale-fade"},duration:{default:300}},setup(l){const t=l,i=e.useAttrs(),f=e.computed(()=>{const o={...t.floatingStyle,"--sb-transition-duration":t.duration+"ms"};return t.zIndex!==void 0&&(o.zIndex=t.zIndex),o}),n=e.computed(()=>{const o={...t.floatingArrowStyle||{}};if(t.arrowDimensions){const p=t.arrowDimensions,d=`-${p/2}px`;switch(t.floatingPlacement.split("-")[0]){case"top":o.bottom=d;break;case"bottom":o.top=d;break;case"left":o.right=d;break;case"right":o.left=d;break}o.width=`${p}px`,o.height=`${p}px`}return t.zIndex!==void 0&&(o.zIndex=t.zIndex),o}),r=e.computed(()=>t.animation==="fade"?"fade":t.animation==="scale-fade"?"scale-fade":"");return(o,p)=>(e.openBlock(),e.createBlock(e.Teleport,{to:"body"},[e.createVNode(e.Transition,{name:r.value},{default:e.withCtx(()=>[t.isOpen?(e.openBlock(),e.createElementBlock("div",e.mergeProps({key:0,ref:t.floatingRef,style:f.value},e.unref(i)),[e.renderSlot(o.$slots,"default",{},void 0,!0),t.floatingArrowRef?(e.openBlock(),e.createElementBlock("div",{key:0,ref:t.floatingArrowRef,style:e.normalizeStyle(n.value)},null,4)):e.createCommentVNode("",!0)],16)):e.createCommentVNode("",!0)]),_:3},8,["name"])]))}}),[["__scopeId","data-v-366682ad"]]);s.SbContainer=z,s.SbFloating=A,s.SbReference=R,s.useSbFloatingPanel=k,Object.defineProperty(s,Symbol.toStringTag,{value:"Module"})});
package/package.json CHANGED
@@ -1,7 +1,38 @@
1
1
  {
2
2
  "name": "sb-floating-panel-vue",
3
- "version": "0.1.5",
4
- "description": "A lightweight Vue 3 composable hook built on top of @floating-ui/vue to manage floating panels with arrow and resize support.",
3
+ "version": "1.0.0",
4
+ "description": "A flexible and lightweight Vue 3 floating panel system powered by @floating-ui/vue โ€” includes composable hooks and plug-and-play components with arrow and resize support.",
5
+ "keywords": [
6
+ "vue",
7
+ "vue3",
8
+ "floating-ui",
9
+ "floating panel",
10
+ "tooltip",
11
+ "popover",
12
+ "dropdown",
13
+ "floating",
14
+ "positioning",
15
+ "arrow",
16
+ "teleport",
17
+ "resize",
18
+ "resize-observer",
19
+ "vue-components",
20
+ "composable",
21
+ "vue-library"
22
+ ],
23
+ "author": {
24
+ "name": "Stefano Biddau",
25
+ "url": "https://www.stefano-biddau.com"
26
+ },
27
+ "license": "MIT",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/stefanBid/sb-floating-panel-vue"
31
+ },
32
+ "bugs": {
33
+ "url": "https://github.com/stefanBid/sb-floating-panel-vue/issues"
34
+ },
35
+ "homepage": "https://github.com/stefanBid/sb-floating-panel-vue#readme",
5
36
  "main": "dist/sb-floating-panel.umd.js",
6
37
  "module": "dist/sb-floating-panel.es.js",
7
38
  "types": "dist/index.d.ts",
@@ -10,26 +41,26 @@
10
41
  "types": "./dist/index.d.ts",
11
42
  "import": "./dist/sb-floating-panel.es.js",
12
43
  "require": "./dist/sb-floating-panel.umd.js"
44
+ },
45
+ "./style.css": {
46
+ "default": "./dist/sb-floating-panel-vue.css"
47
+ }
48
+ },
49
+ "typesVersions": {
50
+ "*": {
51
+ "*": ["dist/index.d.ts"]
13
52
  }
14
53
  },
15
54
  "files": [
16
55
  "dist"
17
56
  ],
57
+ "sideEffects": false,
18
58
  "scripts": {
19
59
  "dev": "vite",
20
60
  "build": "vite build",
21
61
  "lint": "eslint . --ext .ts",
22
62
  "check": "vue-tsc --noEmit"
23
63
  },
24
- "keywords": [
25
- "vue",
26
- "floating-ui",
27
- "hook",
28
- "composable",
29
- "floating panel"
30
- ],
31
- "author": "Stefano Biddau",
32
- "license": "MIT",
33
64
  "peerDependencies": {
34
65
  "vue": "^3.5.13"
35
66
  },
@@ -37,13 +68,14 @@
37
68
  "@floating-ui/vue": "^1.1.6"
38
69
  },
39
70
  "devDependencies": {
40
- "@types/node": "^22.15.17",
41
- "@typescript-eslint/eslint-plugin": "^8.32.0",
42
- "@typescript-eslint/parser": "^8.32.0",
71
+ "@types/node": "^22.15.18",
72
+ "@typescript-eslint/eslint-plugin": "^8.32.1",
73
+ "@typescript-eslint/parser": "^8.32.1",
43
74
  "@vitejs/plugin-vue": "^5.2.4",
44
75
  "eslint": "^9.26.0",
45
76
  "eslint-plugin-prettier": "^5.4.0",
46
77
  "eslint-plugin-vue": "^10.1.0",
78
+ "vue-eslint-parser": "10.1.3",
47
79
  "prettier": "^3.5.3",
48
80
  "typescript": "~5.7.2",
49
81
  "vite": "^6.3.5",
@@ -1,31 +0,0 @@
1
- import { Placement, Strategy } from '@floating-ui/vue';
2
- interface FloatingSettings {
3
- placement: Placement;
4
- strategy: Strategy;
5
- offsetValue: number;
6
- hasArrow?: boolean;
7
- hasResize?: boolean;
8
- }
9
- export declare function useSbFloatingPanel(settings: FloatingSettings): {
10
- reference: import('vue').Ref<HTMLElement | null, HTMLElement | null>;
11
- floating: import('vue').Ref<HTMLElement | null, HTMLElement | null>;
12
- popperArrow: import('vue').Ref<HTMLElement | null, HTMLElement | null>;
13
- isOpen: import('vue').Ref<boolean, boolean>;
14
- floatingPosition: Readonly<import('vue').Ref<Placement, Placement>>;
15
- floatingStyles: Readonly<import('vue').Ref<{
16
- position: Strategy;
17
- top: string;
18
- left: string;
19
- transform?: string;
20
- willChange?: string;
21
- }, {
22
- position: Strategy;
23
- top: string;
24
- left: string;
25
- transform?: string;
26
- willChange?: string;
27
- }>>;
28
- floatingArrowStyles: Readonly<import('vue').Ref<import('@floating-ui/core').MiddlewareData, import('@floating-ui/core').MiddlewareData>>;
29
- changeFloatingVisibility: (newState: boolean) => void;
30
- };
31
- export {};