@epicbagel/saas-kit 1.17.0 → 1.18.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 +14 -0
- package/dist/{chunk-6S6GD43V.js → chunk-2UYEMPOJ.js} +5 -3
- package/dist/{chunk-6YXKFVZU.cjs → chunk-AU5GUDOW.cjs} +5 -3
- package/dist/primitives/connection.cjs +2 -2
- package/dist/primitives/connection.js +1 -1
- package/dist/primitives/page-header-actions.cjs +2 -2
- package/dist/primitives/page-header-actions.d.cts +7 -4
- package/dist/primitives/page-header-actions.d.ts +7 -4
- package/dist/primitives/page-header-actions.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,6 +15,20 @@ npm install @epicbagel/saas-kit
|
|
|
15
15
|
Peer dependencies: `react` and `react-dom` (18 or 19), `lucide-react`
|
|
16
16
|
(`>=0.400.0 <2`), `react-icons` (5) and `tailwindcss` (4.3 or later).
|
|
17
17
|
|
|
18
|
+
## Page header actions
|
|
19
|
+
|
|
20
|
+
`PageHeaderActions` expands its actions on desktop and collapses them into
|
|
21
|
+
one menu on mobile. Use `presentation="menu"` to keep the same menu at every
|
|
22
|
+
width, giving long page titles more room. Its action order, nested menus,
|
|
23
|
+
disabled state, destructive treatment and callbacks stay the same.
|
|
24
|
+
`mobileLabel` and `mobileAriaLabel` name the menu trigger in either layout.
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
<PageHeader title="Senior Enterprise Account Executive · Example Company">
|
|
28
|
+
<PageHeaderActions presentation="menu" actions={actions} />
|
|
29
|
+
</PageHeader>
|
|
30
|
+
```
|
|
31
|
+
|
|
18
32
|
## Live voice in Chat
|
|
19
33
|
|
|
20
34
|
Pass a controlled `voiceSession` to `Chat` or `ChatInput` to show start, mute,
|
|
@@ -33,13 +33,14 @@ function MenuActions({ actions }) {
|
|
|
33
33
|
return actions.map((action) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
34
34
|
action.separatorBefore && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
35
35
|
action.items?.length ? /* @__PURE__ */ jsxs(DropdownMenuSub, { children: [
|
|
36
|
-
/* @__PURE__ */ jsx(DropdownMenuSubTrigger, { disabled: action.disabled, children: /* @__PURE__ */ jsx(MenuActionContent, { action }) }),
|
|
36
|
+
/* @__PURE__ */ jsx(DropdownMenuSubTrigger, { disabled: action.disabled, title: action.title, children: /* @__PURE__ */ jsx(MenuActionContent, { action }) }),
|
|
37
37
|
/* @__PURE__ */ jsx(DropdownMenuSubContent, { children: /* @__PURE__ */ jsx(MenuActions, { actions: action.items }) })
|
|
38
38
|
] }) : /* @__PURE__ */ jsx(
|
|
39
39
|
DropdownMenuItem,
|
|
40
40
|
{
|
|
41
41
|
disabled: action.disabled,
|
|
42
42
|
tone: action.tone,
|
|
43
|
+
title: action.title,
|
|
43
44
|
onSelect: action.onSelect,
|
|
44
45
|
className: action.description ? "items-start" : void 0,
|
|
45
46
|
children: /* @__PURE__ */ jsx(MenuActionContent, { action })
|
|
@@ -49,6 +50,7 @@ function MenuActions({ actions }) {
|
|
|
49
50
|
}
|
|
50
51
|
function PageHeaderActions({
|
|
51
52
|
actions,
|
|
53
|
+
presentation = "responsive",
|
|
52
54
|
mobileLabel = "Actions",
|
|
53
55
|
mobileAriaLabel,
|
|
54
56
|
className
|
|
@@ -68,7 +70,7 @@ function PageHeaderActions({
|
|
|
68
70
|
return rank[priorityFor(left.action)] - rank[priorityFor(right.action)] || left.index - right.index;
|
|
69
71
|
}).map(({ action }) => action) : actions;
|
|
70
72
|
return /* @__PURE__ */ jsxs("div", { className: cn("shrink-0", className), children: [
|
|
71
|
-
/* @__PURE__ */ jsx(
|
|
73
|
+
presentation === "responsive" && /* @__PURE__ */ jsx(
|
|
72
74
|
"div",
|
|
73
75
|
{
|
|
74
76
|
className: "hidden items-center gap-2 sm:flex",
|
|
@@ -110,7 +112,7 @@ function PageHeaderActions({
|
|
|
110
112
|
)
|
|
111
113
|
}
|
|
112
114
|
),
|
|
113
|
-
/* @__PURE__ */ jsx("div", { className: "sm:hidden", "data-slot": "page-header-actions-mobile", children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
115
|
+
/* @__PURE__ */ jsx("div", { className: presentation === "responsive" ? "sm:hidden" : void 0, "data-slot": "page-header-actions-mobile", children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
114
116
|
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", variant: "outline", "aria-label": mobileAriaLabel, children: [
|
|
115
117
|
mobileLabel,
|
|
116
118
|
/* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": "true" })
|
|
@@ -33,13 +33,14 @@ function MenuActions({ actions }) {
|
|
|
33
33
|
return actions.map((action) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _react.Fragment, { children: [
|
|
34
34
|
action.separatorBefore && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZAITUDYDcjs.DropdownMenuSeparator, {}),
|
|
35
35
|
_optionalChain([action, 'access', _ => _.items, 'optionalAccess', _2 => _2.length]) ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkZAITUDYDcjs.DropdownMenuSub, { children: [
|
|
36
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZAITUDYDcjs.DropdownMenuSubTrigger, { disabled: action.disabled, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MenuActionContent, { action }) }),
|
|
36
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZAITUDYDcjs.DropdownMenuSubTrigger, { disabled: action.disabled, title: action.title, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MenuActionContent, { action }) }),
|
|
37
37
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZAITUDYDcjs.DropdownMenuSubContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MenuActions, { actions: action.items }) })
|
|
38
38
|
] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
39
39
|
_chunkZAITUDYDcjs.DropdownMenuItem,
|
|
40
40
|
{
|
|
41
41
|
disabled: action.disabled,
|
|
42
42
|
tone: action.tone,
|
|
43
|
+
title: action.title,
|
|
43
44
|
onSelect: action.onSelect,
|
|
44
45
|
className: action.description ? "items-start" : void 0,
|
|
45
46
|
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MenuActionContent, { action })
|
|
@@ -49,6 +50,7 @@ function MenuActions({ actions }) {
|
|
|
49
50
|
}
|
|
50
51
|
function PageHeaderActions({
|
|
51
52
|
actions,
|
|
53
|
+
presentation = "responsive",
|
|
52
54
|
mobileLabel = "Actions",
|
|
53
55
|
mobileAriaLabel,
|
|
54
56
|
className
|
|
@@ -68,7 +70,7 @@ function PageHeaderActions({
|
|
|
68
70
|
return rank[priorityFor(left.action)] - rank[priorityFor(right.action)] || left.index - right.index;
|
|
69
71
|
}).map(({ action }) => action) : actions;
|
|
70
72
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkKWLSBTB2cjs.cn.call(void 0, "shrink-0", className), children: [
|
|
71
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
73
|
+
presentation === "responsive" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
72
74
|
"div",
|
|
73
75
|
{
|
|
74
76
|
className: "hidden items-center gap-2 sm:flex",
|
|
@@ -110,7 +112,7 @@ function PageHeaderActions({
|
|
|
110
112
|
)
|
|
111
113
|
}
|
|
112
114
|
),
|
|
113
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "sm:hidden", "data-slot": "page-header-actions-mobile", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkZAITUDYDcjs.DropdownMenu, { children: [
|
|
115
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: presentation === "responsive" ? "sm:hidden" : void 0, "data-slot": "page-header-actions-mobile", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkZAITUDYDcjs.DropdownMenu, { children: [
|
|
114
116
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZAITUDYDcjs.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkJDEXZGIYcjs.Button, { type: "button", size: "sm", variant: "outline", "aria-label": mobileAriaLabel, children: [
|
|
115
117
|
mobileLabel,
|
|
116
118
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ChevronDown, { "aria-hidden": "true" })
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
var _chunk2HTYXBDUcjs = require('../chunk-2HTYXBDU.cjs');
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
var
|
|
7
|
+
var _chunkAU5GUDOWcjs = require('../chunk-AU5GUDOW.cjs');
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
@@ -141,7 +141,7 @@ function Connection({
|
|
|
141
141
|
),
|
|
142
142
|
children: [
|
|
143
143
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2HTYXBDUcjs.StatusBadge, { tone: s.tone, children: _nullishCoalesce(statusLabel, () => ( s.label)) }),
|
|
144
|
-
responsiveActions.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
144
|
+
responsiveActions.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkAU5GUDOWcjs.PageHeaderActions, { actions: responsiveActions, mobileLabel: "Actions" })
|
|
145
145
|
]
|
|
146
146
|
}
|
|
147
147
|
),
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"use client";
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var _chunkAU5GUDOWcjs = require('../chunk-AU5GUDOW.cjs');
|
|
6
6
|
require('../chunk-ZAITUDYD.cjs');
|
|
7
7
|
require('../chunk-JDEXZGIY.cjs');
|
|
8
8
|
require('../chunk-KWLSBTB2.cjs');
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
exports.PageHeaderActions =
|
|
11
|
+
exports.PageHeaderActions = _chunkAU5GUDOWcjs.PageHeaderActions;
|
|
@@ -10,7 +10,7 @@ interface PageHeaderAction {
|
|
|
10
10
|
label: ReactNode;
|
|
11
11
|
icon?: ReactNode;
|
|
12
12
|
onSelect?: () => void;
|
|
13
|
-
/** Optional nested actions.
|
|
13
|
+
/** Optional nested actions. Expanded layout renders a menu button; collapsed layout nests it inside Actions. */
|
|
14
14
|
items?: PageHeaderAction[];
|
|
15
15
|
/** Optional supporting copy shown when the action appears in a menu. */
|
|
16
16
|
description?: ReactNode;
|
|
@@ -23,7 +23,7 @@ interface PageHeaderAction {
|
|
|
23
23
|
* the button variant.
|
|
24
24
|
*/
|
|
25
25
|
priority?: "primary" | "secondary" | "tertiary";
|
|
26
|
-
/** Semantic treatment used in the collapsed
|
|
26
|
+
/** Semantic treatment used in the collapsed menu. */
|
|
27
27
|
tone?: "default" | "muted" | "destructive";
|
|
28
28
|
/** Visually separates destructive or lower-priority actions in the menu. */
|
|
29
29
|
separatorBefore?: boolean;
|
|
@@ -31,7 +31,9 @@ interface PageHeaderAction {
|
|
|
31
31
|
}
|
|
32
32
|
interface PageHeaderActionsProps {
|
|
33
33
|
actions: PageHeaderAction[];
|
|
34
|
-
/**
|
|
34
|
+
/** Responsive by default; menu keeps the same collapsed Actions menu at every width. */
|
|
35
|
+
presentation?: "responsive" | "menu";
|
|
36
|
+
/** Visible menu-trigger label, also used on desktop when presentation is menu. */
|
|
35
37
|
mobileLabel?: ReactNode;
|
|
36
38
|
/** Accessible label when `mobileLabel` is not plain text. */
|
|
37
39
|
mobileAriaLabel?: string;
|
|
@@ -42,8 +44,9 @@ interface PageHeaderActionsProps {
|
|
|
42
44
|
*
|
|
43
45
|
* Desktop keeps every action visible for fast scanning. Mobile collapses the
|
|
44
46
|
* same action definitions into one menu so page titles retain useful space.
|
|
47
|
+
* Use `presentation="menu"` to keep that menu at every viewport width.
|
|
45
48
|
* Status and other non-interactive metadata should remain beside the title.
|
|
46
49
|
*/
|
|
47
|
-
declare function PageHeaderActions({ actions, mobileLabel, mobileAriaLabel, className, }: PageHeaderActionsProps): react_jsx_runtime.JSX.Element | null;
|
|
50
|
+
declare function PageHeaderActions({ actions, presentation, mobileLabel, mobileAriaLabel, className, }: PageHeaderActionsProps): react_jsx_runtime.JSX.Element | null;
|
|
48
51
|
|
|
49
52
|
export { type PageHeaderAction, PageHeaderActions, type PageHeaderActionsProps };
|
|
@@ -10,7 +10,7 @@ interface PageHeaderAction {
|
|
|
10
10
|
label: ReactNode;
|
|
11
11
|
icon?: ReactNode;
|
|
12
12
|
onSelect?: () => void;
|
|
13
|
-
/** Optional nested actions.
|
|
13
|
+
/** Optional nested actions. Expanded layout renders a menu button; collapsed layout nests it inside Actions. */
|
|
14
14
|
items?: PageHeaderAction[];
|
|
15
15
|
/** Optional supporting copy shown when the action appears in a menu. */
|
|
16
16
|
description?: ReactNode;
|
|
@@ -23,7 +23,7 @@ interface PageHeaderAction {
|
|
|
23
23
|
* the button variant.
|
|
24
24
|
*/
|
|
25
25
|
priority?: "primary" | "secondary" | "tertiary";
|
|
26
|
-
/** Semantic treatment used in the collapsed
|
|
26
|
+
/** Semantic treatment used in the collapsed menu. */
|
|
27
27
|
tone?: "default" | "muted" | "destructive";
|
|
28
28
|
/** Visually separates destructive or lower-priority actions in the menu. */
|
|
29
29
|
separatorBefore?: boolean;
|
|
@@ -31,7 +31,9 @@ interface PageHeaderAction {
|
|
|
31
31
|
}
|
|
32
32
|
interface PageHeaderActionsProps {
|
|
33
33
|
actions: PageHeaderAction[];
|
|
34
|
-
/**
|
|
34
|
+
/** Responsive by default; menu keeps the same collapsed Actions menu at every width. */
|
|
35
|
+
presentation?: "responsive" | "menu";
|
|
36
|
+
/** Visible menu-trigger label, also used on desktop when presentation is menu. */
|
|
35
37
|
mobileLabel?: ReactNode;
|
|
36
38
|
/** Accessible label when `mobileLabel` is not plain text. */
|
|
37
39
|
mobileAriaLabel?: string;
|
|
@@ -42,8 +44,9 @@ interface PageHeaderActionsProps {
|
|
|
42
44
|
*
|
|
43
45
|
* Desktop keeps every action visible for fast scanning. Mobile collapses the
|
|
44
46
|
* same action definitions into one menu so page titles retain useful space.
|
|
47
|
+
* Use `presentation="menu"` to keep that menu at every viewport width.
|
|
45
48
|
* Status and other non-interactive metadata should remain beside the title.
|
|
46
49
|
*/
|
|
47
|
-
declare function PageHeaderActions({ actions, mobileLabel, mobileAriaLabel, className, }: PageHeaderActionsProps): react_jsx_runtime.JSX.Element | null;
|
|
50
|
+
declare function PageHeaderActions({ actions, presentation, mobileLabel, mobileAriaLabel, className, }: PageHeaderActionsProps): react_jsx_runtime.JSX.Element | null;
|
|
48
51
|
|
|
49
52
|
export { type PageHeaderAction, PageHeaderActions, type PageHeaderActionsProps };
|
package/package.json
CHANGED