sb-floating-panel-vue 1.0.0 → 3.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.
@@ -0,0 +1,169 @@
1
+ /** Side of the reference the panel is placed on. */
2
+ export type SbSide = 'top' | 'right' | 'bottom' | 'left';
3
+ /** Alignment of the panel along the side. */
4
+ export type SbAlignment = 'start' | 'end';
5
+ /** Placement of the panel relative to the reference (same values as Floating UI). */
6
+ export type SbPlacement = SbSide | `${SbSide}-${SbAlignment}`;
7
+ /** CSS position strategy of the panel. */
8
+ export type SbStrategy = 'absolute' | 'fixed';
9
+ /**
10
+ * How the reference opens the floating panel.
11
+ * - `click`: clicking (or pressing Enter/Space on) `SbReference` toggles the panel.
12
+ * - `manual`: the panel opens only through `v-model:open`, the slot props or the exposed methods.
13
+ */
14
+ export type SbTrigger = 'click' | 'manual';
15
+ /**
16
+ * Props for the `SbContainer` component: positioning, open state and interaction.
17
+ */
18
+ export interface SbContainerProps {
19
+ /**
20
+ * Preferred placement of the floating panel relative to the reference.
21
+ * The panel flips to the opposite side when there is not enough space.
22
+ * @default 'bottom-start'
23
+ */
24
+ placement?: SbPlacement;
25
+ /**
26
+ * CSS position strategy of the floating panel.
27
+ * Use `fixed` when the reference lives inside a scroll container or a fixed layout.
28
+ * @default 'absolute'
29
+ */
30
+ strategy?: SbStrategy;
31
+ /**
32
+ * Distance in pixels between the reference and the floating panel.
33
+ * @default 8
34
+ */
35
+ offset?: number;
36
+ /**
37
+ * Minimum distance in pixels between the floating panel and the viewport edges.
38
+ * @default 8
39
+ */
40
+ padding?: number;
41
+ /**
42
+ * Makes the floating panel as wide as the reference.
43
+ * - `true`: sets `width` to the reference width.
44
+ * - `'min'`: sets `min-width` to the reference width, so the panel can grow wider.
45
+ * - `false`: no width is set; `--sbf-reference-width` is still available to your CSS.
46
+ * @default false
47
+ */
48
+ matchWidth?: boolean | 'min';
49
+ /**
50
+ * Hides the floating panel (`visibility: hidden`) when the reference is scrolled out of view.
51
+ * @default false
52
+ */
53
+ hideWhenDetached?: boolean;
54
+ /**
55
+ * Open state, bound with `v-model:open`. Leave it unset to let the container manage it.
56
+ */
57
+ open?: boolean;
58
+ /**
59
+ * Initial open state when `v-model:open` is not used.
60
+ * @default false
61
+ */
62
+ defaultOpen?: boolean;
63
+ /**
64
+ * Prevents the panel from opening and closes it if it is open.
65
+ * @default false
66
+ */
67
+ disabled?: boolean;
68
+ /**
69
+ * How the reference opens the panel.
70
+ * @default 'click'
71
+ */
72
+ trigger?: SbTrigger;
73
+ /**
74
+ * Closes the panel when the Escape key is pressed.
75
+ * @default true
76
+ */
77
+ closeOnEscape?: boolean;
78
+ /**
79
+ * Closes the panel on a pointer press outside the reference and the panel.
80
+ * @default true
81
+ */
82
+ closeOnClickOutside?: boolean;
83
+ }
84
+ /**
85
+ * Props passed to the default slot of `SbContainer`.
86
+ */
87
+ export interface SbContainerSlotProps {
88
+ /** Whether the panel is open. */
89
+ isOpen: boolean;
90
+ /** Opens the panel. */
91
+ open: () => void;
92
+ /** Closes the panel. */
93
+ close: () => void;
94
+ /** Toggles the panel. */
95
+ toggle: () => void;
96
+ /** Placement resolved by Floating UI, after `flip`. */
97
+ placement: SbPlacement;
98
+ /** Side of the resolved placement. */
99
+ side: SbSide;
100
+ }
101
+ /**
102
+ * Methods exposed by `SbContainer` through a template ref.
103
+ */
104
+ export interface SbContainerExposed {
105
+ /** Opens the panel. */
106
+ open: () => void;
107
+ /** Closes the panel. */
108
+ close: () => void;
109
+ /** Toggles the panel. */
110
+ toggle: () => void;
111
+ /** Recomputes the panel position. */
112
+ update: () => void;
113
+ }
114
+ /**
115
+ * Props for the `SbReference` component, the element that anchors and toggles the panel.
116
+ */
117
+ export interface SbReferenceProps {
118
+ /**
119
+ * HTML tag to render. A `button` gets `type="button"`; any tag other than `button` and `a`
120
+ * gets `role="button"`, `tabindex="0"` and Enter/Space handling.
121
+ * @default 'button'
122
+ */
123
+ as?: string;
124
+ /**
125
+ * Value of `aria-haspopup`, matching the `role` of `SbFloating`.
126
+ * @default 'dialog'
127
+ */
128
+ ariaHaspopup?: 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid' | 'true' | 'false';
129
+ }
130
+ /**
131
+ * Props for the `SbFloating` component, the teleported floating panel.
132
+ */
133
+ export interface SbFloatingProps {
134
+ /**
135
+ * HTML tag of the panel element (the one that receives your `class`, `style` and attributes).
136
+ * @default 'div'
137
+ */
138
+ as?: string;
139
+ /**
140
+ * ARIA role of the panel.
141
+ * @default 'dialog'
142
+ */
143
+ role?: string;
144
+ /**
145
+ * Name of a Vue `<Transition>` defined by your CSS (`<name>-enter-active`, …).
146
+ * The classes are applied to the panel element. No animation when unset.
147
+ */
148
+ transition?: string;
149
+ /**
150
+ * Teleport target (CSS selector or element).
151
+ * @default 'body'
152
+ */
153
+ teleportTo?: string | HTMLElement;
154
+ /**
155
+ * Renders the panel in place instead of teleporting it.
156
+ * @default false
157
+ */
158
+ teleportDisabled?: boolean;
159
+ /**
160
+ * `z-index` of the positioned wrapper.
161
+ */
162
+ zIndex?: number | string;
163
+ /**
164
+ * Moves focus inside the panel once it is positioned: to the first element with
165
+ * `autofocus`, otherwise to the first focusable element, otherwise to the panel itself.
166
+ * @default false
167
+ */
168
+ autoFocus?: boolean;
169
+ }
package/package.json CHANGED
@@ -1,23 +1,22 @@
1
1
  {
2
2
  "name": "sb-floating-panel-vue",
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.",
3
+ "version": "3.0.0",
4
+ "description": "Headless Vue 3 floating panel components (dropdowns, popovers, menus) powered by @floating-ui/vue: positioning, accessibility and open state handled, zero CSS shipped.",
5
5
  "keywords": [
6
6
  "vue",
7
7
  "vue3",
8
8
  "floating-ui",
9
9
  "floating panel",
10
- "tooltip",
11
10
  "popover",
12
11
  "dropdown",
12
+ "menu",
13
13
  "floating",
14
14
  "positioning",
15
- "arrow",
15
+ "headless",
16
+ "unstyled",
16
17
  "teleport",
17
- "resize",
18
- "resize-observer",
18
+ "accessibility",
19
19
  "vue-components",
20
- "composable",
21
20
  "vue-library"
22
21
  ],
23
22
  "author": {
@@ -25,7 +24,7 @@
25
24
  "url": "https://www.stefano-biddau.com"
26
25
  },
27
26
  "license": "MIT",
28
- "repository": {
27
+ "repository": {
29
28
  "type": "git",
30
29
  "url": "https://github.com/stefanBid/sb-floating-panel-vue"
31
30
  },
@@ -41,14 +40,6 @@
41
40
  "types": "./dist/index.d.ts",
42
41
  "import": "./dist/sb-floating-panel.es.js",
43
42
  "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"]
52
43
  }
53
44
  },
54
45
  "files": [
@@ -58,28 +49,35 @@
58
49
  "scripts": {
59
50
  "dev": "vite",
60
51
  "build": "vite build",
61
- "lint": "eslint . --ext .ts",
62
- "check": "vue-tsc --noEmit"
52
+ "lint": "eslint .",
53
+ "check": "vue-tsc --noEmit && vue-tsc --noEmit -p tsconfig.playground.json",
54
+ "test": "vitest run",
55
+ "test:coverage": "vitest run --coverage"
63
56
  },
64
57
  "peerDependencies": {
58
+ "@floating-ui/vue": "^2.0.1",
65
59
  "vue": "^3.5.13"
66
60
  },
67
- "dependencies": {
68
- "@floating-ui/vue": "^1.1.6"
69
- },
70
61
  "devDependencies": {
71
- "@types/node": "^22.15.18",
72
- "@typescript-eslint/eslint-plugin": "^8.32.1",
73
- "@typescript-eslint/parser": "^8.32.1",
74
- "@vitejs/plugin-vue": "^5.2.4",
75
- "eslint": "^9.26.0",
76
- "eslint-plugin-prettier": "^5.4.0",
77
- "eslint-plugin-vue": "^10.1.0",
78
- "vue-eslint-parser": "10.1.3",
79
- "prettier": "^3.5.3",
80
- "typescript": "~5.7.2",
81
- "vite": "^6.3.5",
82
- "vite-plugin-dts": "^4.5.3",
83
- "vue-tsc": "^2.2.10"
62
+ "@floating-ui/vue": "^2.0.1",
63
+ "@types/node": "^26.6.5",
64
+ "@typescript-eslint/eslint-plugin": "^8.71.2",
65
+ "@typescript-eslint/parser": "^8.71.2",
66
+ "@vitejs/plugin-vue": "^6.0.10",
67
+ "@vitest/coverage-v8": "^5.0.5",
68
+ "@vue/language-core": "^3.3.13",
69
+ "@vue/test-utils": "^2.5.1",
70
+ "eslint": "^10.13.0",
71
+ "eslint-plugin-prettier": "^5.5.7",
72
+ "eslint-plugin-vue": "^10.11.1",
73
+ "happy-dom": "^21.0.3",
74
+ "prettier": "^3.9.10",
75
+ "typescript": "^6.0.3",
76
+ "vite": "^8.3.4",
77
+ "vite-plugin-dts": "^5.1.2",
78
+ "vitest": "^5.0.5",
79
+ "vue": "^3.5.44",
80
+ "vue-eslint-parser": "10.4.1",
81
+ "vue-tsc": "^3.3.13"
84
82
  }
85
83
  }
@@ -1 +0,0 @@
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)}