@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 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 [root README](../../README.md#tailwindcss-setup) for complete setup instructions.
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
- title="Panel Title"
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
- Panel content goes here.
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 Oe(e) {
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 Ae = {
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 z(e) {
371
- const r = $e(), t = N(0), a = N(null), [i, o] = Q(Ae), s = Z(() => typeof ResizeObserver > "u" ? null : new ResizeObserver((d) => {
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
- }, Pe = {
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
- }, ze = 2, De = 300, U = F.forwardRef(
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, O] = z(), [p, A] = z(), [S, Y] = z(), P = N(0), x = N(null), E = N(null), de = Oe([ne, x]);
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 && (P.current = Y.width + Pe[m] + (c ? 0 : ze), x.current && !x.current.style.width && (x.current.style.width = `${M[m]}px`));
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 && O.width > 0 ? C = O.width + P.current : f && p && A.width > 0 && (C = A.width + P.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(() => {
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
- O,
447
+ A,
448
448
  u,
449
449
  v,
450
- A,
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.2
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.2",
515
- buildTime: "08/14/2025 06:04 PM EDT",
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.6
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.6",
723
- buildTime: "08/14/2025 06:05 PM EDT",
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 n } from "./components/Panel/Panel.js";
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.6
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.6",
9
- buildTime: "08/14/2025 06:05 PM EDT",
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
- n as Panel
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.6",
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.7.0"
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": "a2a11904039a5bc55ff17a954e4a16073abbe0bf"
57
+ "gitHead": "a1afd6e4613b1da7abf61d10a72614611521fb39"
57
58
  }