@versini/ui-panel 2.2.6 → 2.2.8
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 +90 -6
- package/dist/components/Panel/Panel.js +17 -17
- package/dist/index.js +5 -5
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -4,14 +4,29 @@
|
|
|
4
4
|
|
|
5
5
|
> An accessible React slide-out panel component built with TypeScript and TailwindCSS.
|
|
6
6
|
|
|
7
|
-
The Panel component provides slide-out panels and drawers with focus management, keyboard navigation, and customizable positioning.
|
|
8
|
-
|
|
7
|
+
The Panel component provides slide-out panels and drawers with focus management, keyboard navigation, document title management, optional animations, and customizable positioning / sizing.
|
|
9
8
|
|
|
10
9
|
## Table of Contents
|
|
11
10
|
|
|
11
|
+
- [Table of Contents](#table-of-contents)
|
|
12
12
|
- [Features](#features)
|
|
13
13
|
- [Installation](#installation)
|
|
14
14
|
- [Usage](#usage)
|
|
15
|
+
- [Examples](#examples)
|
|
16
|
+
- [Message Box Variant](#message-box-variant)
|
|
17
|
+
- [Animated Panel (Fade)](#animated-panel-fade)
|
|
18
|
+
- [API](#api)
|
|
19
|
+
- [Panel Props](#panel-props)
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- **🪟 Versatile Layouts**: Standard panel and message box variants (`kind` prop)
|
|
24
|
+
- **🎯 Focus Management**: Uses underlying modal primitives for proper focus trapping & return
|
|
25
|
+
- **♿ Accessible**: ARIA compliant structure with heading, description, close control
|
|
26
|
+
- **🎬 Optional Animations**: Slide or fade entrance animations (`animation` / `animationType`)
|
|
27
|
+
- **📐 Responsive Sizing**: Predefined max widths (`small`, `medium`, `large`) above md breakpoint
|
|
28
|
+
- **🧩 Composable**: Footer slot for actions / extra content
|
|
29
|
+
- **🧪 Type Safe**: Fully typed props with inline documentation
|
|
15
30
|
|
|
16
31
|
## Installation
|
|
17
32
|
|
|
@@ -19,7 +34,7 @@ The Panel component provides slide-out panels and drawers with focus management,
|
|
|
19
34
|
npm install @versini/ui-panel
|
|
20
35
|
```
|
|
21
36
|
|
|
22
|
-
> **Note**: This component requires TailwindCSS and the `@versini/ui-styles` plugin for proper styling. See the [
|
|
37
|
+
> **Note**: This component requires TailwindCSS and the `@versini/ui-styles` plugin for proper styling. See the [installation documentation](https://versini-org.github.io/ui-components/?path=/docs/getting-started-installation--docs) for complete setup instructions.
|
|
23
38
|
|
|
24
39
|
## Usage
|
|
25
40
|
|
|
@@ -29,18 +44,87 @@ import { useState } from "react";
|
|
|
29
44
|
|
|
30
45
|
function App() {
|
|
31
46
|
const [open, setOpen] = useState(false);
|
|
32
|
-
|
|
47
|
+
|
|
33
48
|
return (
|
|
34
49
|
<>
|
|
35
50
|
<button onClick={() => setOpen(true)}>Open Panel</button>
|
|
51
|
+
<Panel title="Panel Title" open={open} onOpenChange={setOpen}>
|
|
52
|
+
Panel content goes here.
|
|
53
|
+
</Panel>
|
|
54
|
+
</>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Examples
|
|
60
|
+
|
|
61
|
+
### Message Box Variant
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import { Panel } from "@versini/ui-panel";
|
|
65
|
+
import { useState } from "react";
|
|
66
|
+
|
|
67
|
+
function MessageBoxExample() {
|
|
68
|
+
const [open, setOpen] = useState(false);
|
|
69
|
+
return (
|
|
70
|
+
<>
|
|
71
|
+
<button onClick={() => setOpen(true)}>Show Message</button>
|
|
36
72
|
<Panel
|
|
37
|
-
|
|
73
|
+
kind="messagebox"
|
|
74
|
+
title="Session Expired"
|
|
38
75
|
open={open}
|
|
39
76
|
onOpenChange={setOpen}
|
|
77
|
+
footer={
|
|
78
|
+
<div className="flex justify-end gap-2">
|
|
79
|
+
<button
|
|
80
|
+
className="px-3 py-1 rounded bg-surface-lighter"
|
|
81
|
+
onClick={() => setOpen(false)}
|
|
82
|
+
>
|
|
83
|
+
Dismiss
|
|
84
|
+
</button>
|
|
85
|
+
<button className="px-3 py-1 rounded bg-blue-600 text-white">
|
|
86
|
+
Re‑authenticate
|
|
87
|
+
</button>
|
|
88
|
+
</div>
|
|
89
|
+
}
|
|
40
90
|
>
|
|
41
|
-
|
|
91
|
+
Your session has expired. Please sign in again to continue.
|
|
42
92
|
</Panel>
|
|
43
93
|
</>
|
|
44
94
|
);
|
|
45
95
|
}
|
|
46
96
|
```
|
|
97
|
+
|
|
98
|
+
### Animated Panel (Fade)
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
<Panel
|
|
102
|
+
title="Animated Panel"
|
|
103
|
+
open={open}
|
|
104
|
+
onOpenChange={setOpen}
|
|
105
|
+
animation
|
|
106
|
+
animationType="fade"
|
|
107
|
+
>
|
|
108
|
+
Content with fade animation.
|
|
109
|
+
</Panel>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## API
|
|
113
|
+
|
|
114
|
+
### Panel Props
|
|
115
|
+
|
|
116
|
+
| Prop | Type | Default | Description |
|
|
117
|
+
| --------------- | ------------------------- | ------------- | ---------------------------------------------------------------------- | ------------------------------------------------ | ------------------------------------------------------- |
|
|
118
|
+
| `open` | `boolean` | - | Whether the panel is open. |
|
|
119
|
+
| `onOpenChange` | `(open: boolean) => void` | - | Callback fired when open state changes. |
|
|
120
|
+
| `title` | `string` | - | Title displayed in the header (also used to augment `document.title`). |
|
|
121
|
+
| `children` | `React.ReactNode` | - | Main content of the panel. |
|
|
122
|
+
| `footer` | `React.ReactNode` | - | Optional footer content (actions, etc.). |
|
|
123
|
+
| `className` | `string` | - | Extra classes applied to width wrapper (overrides default width). |
|
|
124
|
+
| `borderMode` | `"dark" | "light"` | `"light"` | Visual style of border / surface. |
|
|
125
|
+
| `kind` | `"panel" | "messagebox"` | `"panel"` | Layout variant. |
|
|
126
|
+
| `animation` | `boolean` | `false` | Enable entrance animation. |
|
|
127
|
+
| `animationType` | `"slide" | "fade"` | `"slide"` | Animation style (only when `animation` is true). |
|
|
128
|
+
| `maxWidth` | `"small" | "medium" | "large"` | `"medium"` | Max width applied (≥ md breakpoint) for `kind="panel"`. |
|
|
129
|
+
|
|
130
|
+
> Also inherits any valid props for the underlying modal primitives where relevant.
|
|
@@ -349,7 +349,7 @@ function $e() {
|
|
|
349
349
|
e.current = !1;
|
|
350
350
|
}), []), me(() => e.current, []);
|
|
351
351
|
}
|
|
352
|
-
function
|
|
352
|
+
function Ae(e) {
|
|
353
353
|
return Z(() => e.every((r) => r == null) ? () => {
|
|
354
354
|
} : (r) => {
|
|
355
355
|
e.forEach((t) => {
|
|
@@ -357,7 +357,7 @@ function Oe(e) {
|
|
|
357
357
|
});
|
|
358
358
|
}, [...e]);
|
|
359
359
|
}
|
|
360
|
-
const
|
|
360
|
+
const Oe = {
|
|
361
361
|
x: 0,
|
|
362
362
|
y: 0,
|
|
363
363
|
width: 0,
|
|
@@ -367,8 +367,8 @@ const Ae = {
|
|
|
367
367
|
bottom: 0,
|
|
368
368
|
right: 0
|
|
369
369
|
};
|
|
370
|
-
function
|
|
371
|
-
const r = $e(), t = N(0), a = N(null), [i, o] = Q(
|
|
370
|
+
function P(e) {
|
|
371
|
+
const r = $e(), t = N(0), a = N(null), [i, o] = Q(Oe), s = Z(() => typeof ResizeObserver > "u" ? null : new ResizeObserver((d) => {
|
|
372
372
|
const c = d[0];
|
|
373
373
|
c && (cancelAnimationFrame(t.current), t.current = requestAnimationFrame(() => {
|
|
374
374
|
a.current && r() && o(c.contentRect);
|
|
@@ -385,14 +385,14 @@ const M = {
|
|
|
385
385
|
// w-8
|
|
386
386
|
large: 48
|
|
387
387
|
// w-12
|
|
388
|
-
},
|
|
388
|
+
}, ze = {
|
|
389
389
|
small: 16,
|
|
390
390
|
// px-2 x 2
|
|
391
391
|
medium: 24,
|
|
392
392
|
// px-3 x 2
|
|
393
393
|
large: 32
|
|
394
394
|
// px-4 x 2
|
|
395
|
-
},
|
|
395
|
+
}, Pe = 2, De = 300, U = F.forwardRef(
|
|
396
396
|
({
|
|
397
397
|
children: e,
|
|
398
398
|
disabled: r = !1,
|
|
@@ -433,21 +433,21 @@ const M = {
|
|
|
433
433
|
radius: I,
|
|
434
434
|
variant: j,
|
|
435
435
|
animated: k
|
|
436
|
-
}), se = Re({ mode: t, raw: d, iconClassName: ie, variant: j }), G = Me({ animated: k }), ce = "flex items-center justify-center relative w-full h-full overflow-hidden", [v,
|
|
436
|
+
}), se = Re({ mode: t, raw: d, iconClassName: ie, variant: j }), G = Me({ animated: k }), ce = "flex items-center justify-center relative w-full h-full overflow-hidden", [v, A] = P(), [p, O] = P(), [S, Y] = P(), z = N(0), x = N(null), E = N(null), de = Ae([ne, x]);
|
|
437
437
|
return H(() => {
|
|
438
|
-
S && S.current && k && (
|
|
438
|
+
S && S.current && k && (z.current = Y.width + ze[m] + (c ? 0 : Pe), x.current && !x.current.style.width && (x.current.style.width = `${M[m]}px`));
|
|
439
439
|
}, [Y, S, m, c, k]), H(() => {
|
|
440
440
|
if (x && x.current && k) {
|
|
441
441
|
let C = M[m];
|
|
442
|
-
u && v &&
|
|
442
|
+
u && v && A.width > 0 ? C = A.width + z.current : f && p && O.width > 0 && (C = O.width + z.current), E.current && clearTimeout(E.current), C !== parseInt(x.current.style.width || "0", 10) && (v.current && (v.current.style.opacity = "0"), p.current && (p.current.style.opacity = "0"), x.current.style.width = `${C}px`, C > M[m] && (E.current = setTimeout(() => {
|
|
443
443
|
v.current && u && (v.current.style.opacity = "1"), p.current && f && (p.current.style.opacity = "1"), E.current = null;
|
|
444
444
|
}, De * 0.8))), C === M[m] && (v.current && (v.current.style.opacity = "0"), p.current && (p.current.style.opacity = "0"));
|
|
445
445
|
}
|
|
446
446
|
}, [
|
|
447
|
-
|
|
447
|
+
A,
|
|
448
448
|
u,
|
|
449
449
|
v,
|
|
450
|
-
|
|
450
|
+
O,
|
|
451
451
|
f,
|
|
452
452
|
p,
|
|
453
453
|
m,
|
|
@@ -506,13 +506,13 @@ const M = {
|
|
|
506
506
|
);
|
|
507
507
|
U.displayName = "ButtonIcon";
|
|
508
508
|
/*!
|
|
509
|
-
@versini/ui-button v7.1.
|
|
509
|
+
@versini/ui-button v7.1.4
|
|
510
510
|
© 2025 gizmette.com
|
|
511
511
|
*/
|
|
512
512
|
try {
|
|
513
513
|
window.__VERSINI_UI_BUTTON__ || (window.__VERSINI_UI_BUTTON__ = {
|
|
514
|
-
version: "7.1.
|
|
515
|
-
buildTime: "08/
|
|
514
|
+
version: "7.1.4",
|
|
515
|
+
buildTime: "08/23/2025 10:05 AM EDT",
|
|
516
516
|
homepage: "https://github.com/aversini/ui-components",
|
|
517
517
|
license: "MIT"
|
|
518
518
|
});
|
|
@@ -714,13 +714,13 @@ const Ye = h.forwardRef(function(e, r) {
|
|
|
714
714
|
}) });
|
|
715
715
|
});
|
|
716
716
|
/*!
|
|
717
|
-
@versini/ui-modal v2.0.
|
|
717
|
+
@versini/ui-modal v2.0.8
|
|
718
718
|
© 2025 gizmette.com
|
|
719
719
|
*/
|
|
720
720
|
try {
|
|
721
721
|
window.__VERSINI_UI_MODAL__ || (window.__VERSINI_UI_MODAL__ = {
|
|
722
|
-
version: "2.0.
|
|
723
|
-
buildTime: "08/
|
|
722
|
+
version: "2.0.8",
|
|
723
|
+
buildTime: "08/23/2025 10:06 AM EDT",
|
|
724
724
|
homepage: "https://github.com/aversini/ui-components",
|
|
725
725
|
license: "MIT"
|
|
726
726
|
});
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { MESSAGEBOX_CLASSNAME as o, PANEL_CLASSNAME as E, Panel as
|
|
1
|
+
import { MESSAGEBOX_CLASSNAME as o, PANEL_CLASSNAME as E, Panel as A } from "./components/Panel/Panel.js";
|
|
2
2
|
/*!
|
|
3
|
-
@versini/ui-panel v2.2.
|
|
3
|
+
@versini/ui-panel v2.2.8
|
|
4
4
|
© 2025 gizmette.com
|
|
5
5
|
*/
|
|
6
6
|
try {
|
|
7
7
|
window.__VERSINI_UI_PANEL__ || (window.__VERSINI_UI_PANEL__ = {
|
|
8
|
-
version: "2.2.
|
|
9
|
-
buildTime: "08/
|
|
8
|
+
version: "2.2.8",
|
|
9
|
+
buildTime: "08/23/2025 10:06 AM EDT",
|
|
10
10
|
homepage: "https://github.com/aversini/ui-components",
|
|
11
11
|
license: "MIT"
|
|
12
12
|
});
|
|
@@ -15,5 +15,5 @@ try {
|
|
|
15
15
|
export {
|
|
16
16
|
o as MESSAGEBOX_CLASSNAME,
|
|
17
17
|
E as PANEL_CLASSNAME,
|
|
18
|
-
|
|
18
|
+
A as Panel
|
|
19
19
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@versini/ui-panel",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.8",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Arno Versini",
|
|
6
6
|
"publishConfig": {
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"main": "dist/index.js",
|
|
16
16
|
"types": "dist/index.d.ts",
|
|
17
17
|
"files": [
|
|
18
|
-
"dist"
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md"
|
|
19
20
|
],
|
|
20
21
|
"scripts": {
|
|
21
22
|
"build:check": "tsc",
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
"react-dom": "^18.3.1 || ^19.0.0"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
|
-
"@testing-library/jest-dom": "6.
|
|
44
|
+
"@testing-library/jest-dom": "6.8.0"
|
|
44
45
|
},
|
|
45
46
|
"dependencies": {
|
|
46
47
|
"@tailwindcss/typography": "0.5.16",
|
|
@@ -53,5 +54,5 @@
|
|
|
53
54
|
"sideEffects": [
|
|
54
55
|
"**/*.css"
|
|
55
56
|
],
|
|
56
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "a1afd6e4613b1da7abf61d10a72614611521fb39"
|
|
57
58
|
}
|