@epicbagel/saas-kit 1.12.0 → 1.14.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,259 @@
1
+ "use client";
2
+ "use client";
3
+ import {
4
+ SectionHeader
5
+ } from "../chunk-SRIGG5I5.js";
6
+ import {
7
+ PanelSection
8
+ } from "../chunk-KI7SWNIN.js";
9
+ import {
10
+ Card
11
+ } from "../chunk-35YMAIEL.js";
12
+ import {
13
+ Textarea
14
+ } from "../chunk-6FC65AZQ.js";
15
+ import {
16
+ Stack
17
+ } from "../chunk-WNWBKEWV.js";
18
+ import {
19
+ Text
20
+ } from "../chunk-EIY5LLSP.js";
21
+ import {
22
+ Icon
23
+ } from "../chunk-KN4RPX35.js";
24
+ import "../chunk-H7TETFLB.js";
25
+ import {
26
+ Badge
27
+ } from "../chunk-D4ZL2OEQ.js";
28
+ import {
29
+ EmptyState
30
+ } from "../chunk-ET4THLFX.js";
31
+ import {
32
+ Skeleton
33
+ } from "../chunk-YEW65ASC.js";
34
+ import {
35
+ Button
36
+ } from "../chunk-W326GKML.js";
37
+ import "../chunk-G6SRSWXB.js";
38
+
39
+ // src/primitives/notes.tsx
40
+ import { Loader2, MessageSquare, Mic, Sparkles, StickyNote, Trash2 } from "lucide-react";
41
+ import { useEffect, useId, useRef, useState } from "react";
42
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
43
+ function present(value) {
44
+ return value != null && value !== false && value !== "";
45
+ }
46
+ function NoteList({
47
+ count,
48
+ loading = false,
49
+ title = "Notes",
50
+ empty = { title: "No notes yet" },
51
+ composer,
52
+ children,
53
+ border = "bottom",
54
+ ...props
55
+ }) {
56
+ return /* @__PURE__ */ jsxs(PanelSection, { "data-slot": "note-list", border, ...props, children: [
57
+ /* @__PURE__ */ jsx(SectionHeader, { label: title, count: loading ? void 0 : count }),
58
+ loading ? /* @__PURE__ */ jsx(Stack, { direction: "vertical", gap: "sm", marginTop: "md", children: /* @__PURE__ */ jsx(Skeleton, { preset: "row", radius: "xl" }) }) : count > 0 ? /* @__PURE__ */ jsx(Stack, { direction: "vertical", gap: "sm", marginTop: "md", children }) : /* @__PURE__ */ jsx(
59
+ EmptyState,
60
+ {
61
+ variant: "empty",
62
+ size: "inline",
63
+ icon: StickyNote,
64
+ title: empty.title,
65
+ description: empty.description ?? ""
66
+ }
67
+ ),
68
+ composer
69
+ ] });
70
+ }
71
+ var NOTE_CARD_LABELS = {
72
+ voice: "\xB7 voice",
73
+ delete: "Delete note"
74
+ };
75
+ var NOTE_ICON = { voice: Mic, agent: Sparkles, note: MessageSquare };
76
+ function NoteCard({
77
+ author,
78
+ kind = "note",
79
+ pinned,
80
+ scope,
81
+ date,
82
+ text,
83
+ onDelete,
84
+ revealDelete = "hover",
85
+ labels,
86
+ ...props
87
+ }) {
88
+ const voiceLabel = labels?.voice !== void 0 ? labels.voice : NOTE_CARD_LABELS.voice;
89
+ const deleteLabel = labels?.delete ?? NOTE_CARD_LABELS.delete;
90
+ return /* @__PURE__ */ jsxs(Card, { interaction: "group", surface: pinned ? "card" : "muted", padding: "row", ...props, children: [
91
+ /* @__PURE__ */ jsxs(Stack, { direction: "horizontal", gap: "xs", align: "center", justify: "between", marginBottom: "md", minWidth: "zero", wrap: true, children: [
92
+ /* @__PURE__ */ jsxs(Stack, { direction: "horizontal", gap: "sm", align: "center", textSize: "xs", tone: "muted", minWidth: "zero", className: "max-w-full", wrap: true, children: [
93
+ /* @__PURE__ */ jsxs(Text, { variant: "inherit", as: "span", display: "inline-flex", weight: "medium", tone: "soft", minWidth: "zero", className: "max-w-full", children: [
94
+ /* @__PURE__ */ jsx(Icon, { icon: NOTE_ICON[kind], size: "xs" }),
95
+ /* @__PURE__ */ jsx(Text, { variant: "inherit", as: "span", minWidth: "zero", className: "[overflow-wrap:anywhere]", children: author })
96
+ ] }),
97
+ pinned && /* @__PURE__ */ jsx(Badge, { as: "span", variant: "info", size: "micro", weight: "semibold", title: pinned.title, className: "max-w-full whitespace-normal [overflow-wrap:anywhere]", children: pinned.label }),
98
+ kind === "voice" && present(voiceLabel) && /* @__PURE__ */ jsx(Text, { variant: "inherit", as: "span", tone: "subtle", children: voiceLabel }),
99
+ scope && /* @__PURE__ */ jsx(
100
+ Badge,
101
+ {
102
+ as: "span",
103
+ variant: scope.highlighted ? "info" : "default",
104
+ size: "micro",
105
+ weight: "semibold",
106
+ title: scope.title,
107
+ className: "max-w-full whitespace-normal [overflow-wrap:anywhere]",
108
+ children: scope.label
109
+ }
110
+ )
111
+ ] }),
112
+ /* @__PURE__ */ jsxs(Stack, { direction: "horizontal", gap: "xs", align: "center", minWidth: "zero", className: "max-w-full", children: [
113
+ present(date) ? /* @__PURE__ */ jsx(Text, { variant: "inherit", as: "span", size: "xs", tone: "muted", minWidth: "zero", className: "[overflow-wrap:anywhere]", children: date }) : null,
114
+ onDelete && /* @__PURE__ */ jsx(
115
+ Button,
116
+ {
117
+ type: "button",
118
+ size: "icon-sm",
119
+ reveal: revealDelete === "always" ? "always" : "parent-hover-responsive",
120
+ variant: "ghost-destructive",
121
+ onClick: () => onDelete(),
122
+ title: deleteLabel,
123
+ children: /* @__PURE__ */ jsx(Icon, { icon: Trash2, size: "sm" })
124
+ }
125
+ )
126
+ ] })
127
+ ] }),
128
+ present(text) && /* @__PURE__ */ jsx(Text, { size: "sm", whitespace: "pre-wrap", className: "break-words [overflow-wrap:anywhere]", children: text })
129
+ ] });
130
+ }
131
+ function Notes({ notes, ...props }) {
132
+ return /* @__PURE__ */ jsx(NoteList, { "data-slot": "notes", count: notes.length, ...props, children: notes.map(({ id, ...note }) => /* @__PURE__ */ jsx(NoteCard, { ...note }, id)) });
133
+ }
134
+ var COMPOSER_LABELS = {
135
+ voice: "Tap to speak",
136
+ type: "or type instead",
137
+ input: "Note",
138
+ placeholder: "Type your note\u2026",
139
+ cancel: "Cancel",
140
+ submit: "Add note",
141
+ error: "Could not save your note. Try again."
142
+ };
143
+ function NoteComposer({
144
+ onVoice,
145
+ onSubmit,
146
+ suggestions = [],
147
+ labels,
148
+ value,
149
+ onValueChange,
150
+ editing,
151
+ onEditingChange,
152
+ onCancel,
153
+ disabled = false,
154
+ error,
155
+ maxLength,
156
+ ...props
157
+ }) {
158
+ const copy = { ...COMPOSER_LABELS, ...labels };
159
+ const [draft, setDraft] = useState("");
160
+ const [localEditing, setLocalEditing] = useState(false);
161
+ const [saving, setSaving] = useState(false);
162
+ const [failed, setFailed] = useState(false);
163
+ const pending = useRef(false);
164
+ const mounted = useRef(true);
165
+ const errorId = useId();
166
+ const text = value ?? draft;
167
+ const latestText = useRef(text);
168
+ latestText.current = text;
169
+ const busy = disabled || saving;
170
+ const message = error ?? (failed ? copy.error : null);
171
+ const typing = (editing ?? localEditing) || Boolean(text) || Boolean(message) || !onVoice;
172
+ useEffect(() => {
173
+ mounted.current = true;
174
+ return () => {
175
+ mounted.current = false;
176
+ };
177
+ }, []);
178
+ function changeText(next) {
179
+ if (value === void 0) setDraft(next);
180
+ onValueChange?.(next);
181
+ latestText.current = next;
182
+ }
183
+ function changeEditing(next) {
184
+ if (editing === void 0) setLocalEditing(next);
185
+ onEditingChange?.(next);
186
+ }
187
+ function cancel() {
188
+ if (disabled || pending.current) return;
189
+ changeText("");
190
+ changeEditing(false);
191
+ setFailed(false);
192
+ onCancel?.();
193
+ }
194
+ async function submit(input) {
195
+ const trimmed = input.trim();
196
+ if (disabled || pending.current || !trimmed || maxLength != null && trimmed.length > maxLength) return;
197
+ pending.current = true;
198
+ setSaving(true);
199
+ setFailed(false);
200
+ const previous = latestText.current;
201
+ try {
202
+ await onSubmit(trimmed);
203
+ if (!mounted.current) return;
204
+ if (value === void 0 && latestText.current === previous) {
205
+ changeText("");
206
+ changeEditing(false);
207
+ }
208
+ } catch {
209
+ if (!mounted.current) return;
210
+ if (latestText.current === previous) changeText(input);
211
+ changeEditing(true);
212
+ setFailed(true);
213
+ } finally {
214
+ pending.current = false;
215
+ if (mounted.current) setSaving(false);
216
+ }
217
+ }
218
+ return /* @__PURE__ */ jsxs(Stack, { "data-slot": "note-composer", direction: "vertical", gap: "sm", marginTop: "md", "aria-busy": saving, ...props, children: [
219
+ message ? /* @__PURE__ */ jsx(Text, { id: errorId, role: "alert", size: "sm", tone: "destructive", children: message }) : null,
220
+ typing ? /* @__PURE__ */ jsxs(Fragment, { children: [
221
+ /* @__PURE__ */ jsx(
222
+ Textarea,
223
+ {
224
+ "aria-label": copy.input,
225
+ "aria-describedby": message ? errorId : void 0,
226
+ resize: "vertical",
227
+ placeholder: copy.placeholder,
228
+ value: text,
229
+ onChange: (event) => changeText(event.target.value),
230
+ maxLength,
231
+ disabled: busy,
232
+ autoFocus: Boolean(onVoice)
233
+ }
234
+ ),
235
+ /* @__PURE__ */ jsxs(Stack, { direction: "horizontal", gap: "sm", align: "center", wrap: true, children: [
236
+ /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: cancel, disabled: busy, children: copy.cancel }),
237
+ /* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", onClick: () => void submit(text), disabled: busy || !text.trim() || maxLength != null && text.trim().length > maxLength, children: [
238
+ saving ? /* @__PURE__ */ jsx(Icon, { icon: Loader2, size: "sm", spin: true }) : null,
239
+ copy.submit
240
+ ] })
241
+ ] })
242
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
243
+ /* @__PURE__ */ jsxs(Stack, { direction: "vertical", gap: "sm", align: "center", paddingY: "md", children: [
244
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "voice", "aria-label": copy.voice, disabled: busy, onClick: () => {
245
+ if (!pending.current && !disabled) onVoice?.();
246
+ }, children: /* @__PURE__ */ jsx(Icon, { icon: Mic, size: 28, tone: "muted" }) }),
247
+ /* @__PURE__ */ jsx(Text, { variant: "inherit", as: "span", size: "sm", weight: "medium", children: copy.voice }),
248
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "quiet", size: "bare", disabled: busy, onClick: () => changeEditing(true), children: copy.type })
249
+ ] }),
250
+ suggestions.length > 0 ? /* @__PURE__ */ jsx(Stack, { direction: "horizontal", gap: "xs", justify: "center", wrap: true, children: suggestions.map((suggestion) => /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline-muted", size: "suggestion", disabled: busy, onClick: () => void submit(suggestion), children: suggestion }, suggestion)) }) : null
251
+ ] })
252
+ ] });
253
+ }
254
+ export {
255
+ NoteCard,
256
+ NoteComposer,
257
+ NoteList,
258
+ Notes
259
+ };
@@ -1,52 +1,8 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }"use client";
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
2
2
 
3
3
 
4
- var _chunkKWLSBTB2cjs = require('../chunk-KWLSBTB2.cjs');
4
+ var _chunkVKYRB37Ocjs = require('../chunk-VKYRB37O.cjs');
5
+ require('../chunk-KWLSBTB2.cjs');
5
6
 
6
- // src/primitives/panel-section.tsx
7
- var _react = require('react');
8
- var _jsxruntime = require('react/jsx-runtime');
9
- var borders = {
10
- none: "",
11
- top: "border-t",
12
- bottom: "border-b"
13
- };
14
- var paddings = {
15
- none: "",
16
- compact: "px-[22px] py-[18px]",
17
- default: "px-[26px] py-[26px]"
18
- };
19
- var PanelSection = _react.forwardRef.call(void 0,
20
- function PanelSection2({ as, border = "none", padding = "default", paddingX = "none", paddingTop = "none", paddingBottom = "none", paddingY = "none", surface = "default", layout = "block", gap = "none", shrink = true, className, ...props }, ref) {
21
- const Component = _nullishCoalesce(as, () => ( "section"));
22
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
23
- Component,
24
- {
25
- ref,
26
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
27
- borders[border],
28
- paddings[padding],
29
- paddingX === "md" && "px-[22px]",
30
- paddingX === "lg" && "px-[26px]",
31
- paddingTop === "sm" && "pt-2",
32
- paddingTop === "md" && "pt-3",
33
- paddingTop === "lg" && "pt-5",
34
- paddingBottom === "xs" && "pb-1",
35
- paddingBottom === "sm" && "pb-2",
36
- paddingBottom === "md" && "pb-3",
37
- paddingBottom === "lg" && "pb-4",
38
- paddingY === "xl" && "py-12",
39
- surface === "muted" && "bg-muted/40",
40
- layout === "row" && "flex",
41
- gap === "sm" && "gap-2",
42
- !shrink && "shrink-0",
43
- className
44
- ),
45
- ...props
46
- }
47
- );
48
- }
49
- );
50
7
 
51
-
52
- exports.PanelSection = PanelSection;
8
+ exports.PanelSection = _chunkVKYRB37Ocjs.PanelSection;
@@ -1,52 +1,8 @@
1
1
  "use client";
2
2
  import {
3
- cn
4
- } from "../chunk-G6SRSWXB.js";
5
-
6
- // src/primitives/panel-section.tsx
7
- import { forwardRef } from "react";
8
- import { jsx } from "react/jsx-runtime";
9
- var borders = {
10
- none: "",
11
- top: "border-t",
12
- bottom: "border-b"
13
- };
14
- var paddings = {
15
- none: "",
16
- compact: "px-[22px] py-[18px]",
17
- default: "px-[26px] py-[26px]"
18
- };
19
- var PanelSection = forwardRef(
20
- function PanelSection2({ as, border = "none", padding = "default", paddingX = "none", paddingTop = "none", paddingBottom = "none", paddingY = "none", surface = "default", layout = "block", gap = "none", shrink = true, className, ...props }, ref) {
21
- const Component = as ?? "section";
22
- return /* @__PURE__ */ jsx(
23
- Component,
24
- {
25
- ref,
26
- className: cn(
27
- borders[border],
28
- paddings[padding],
29
- paddingX === "md" && "px-[22px]",
30
- paddingX === "lg" && "px-[26px]",
31
- paddingTop === "sm" && "pt-2",
32
- paddingTop === "md" && "pt-3",
33
- paddingTop === "lg" && "pt-5",
34
- paddingBottom === "xs" && "pb-1",
35
- paddingBottom === "sm" && "pb-2",
36
- paddingBottom === "md" && "pb-3",
37
- paddingBottom === "lg" && "pb-4",
38
- paddingY === "xl" && "py-12",
39
- surface === "muted" && "bg-muted/40",
40
- layout === "row" && "flex",
41
- gap === "sm" && "gap-2",
42
- !shrink && "shrink-0",
43
- className
44
- ),
45
- ...props
46
- }
47
- );
48
- }
49
- );
3
+ PanelSection
4
+ } from "../chunk-KI7SWNIN.js";
5
+ import "../chunk-G6SRSWXB.js";
50
6
  export {
51
7
  PanelSection
52
8
  };
@@ -0,0 +1,10 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
2
+ "use client";
3
+
4
+
5
+ var _chunk34AS3OCCcjs = require('../chunk-34AS3OCC.cjs');
6
+ require('../chunk-WABCLRBR.cjs');
7
+ require('../chunk-KWLSBTB2.cjs');
8
+
9
+
10
+ exports.ScrollNavigator = _chunk34AS3OCCcjs.ScrollNavigator;
@@ -0,0 +1,40 @@
1
+ import * as React from 'react';
2
+ import { HTMLAttributes, ReactNode } from 'react';
3
+
4
+ interface ScrollNavigatorItem {
5
+ /** Stable within this list. Separate lists can contain the same IDs. */
6
+ id: string;
7
+ label: string;
8
+ imageSrc?: string | null;
9
+ /** Initials or an icon; defaults to the label's initials. */
10
+ fallback?: ReactNode;
11
+ content: ReactNode;
12
+ }
13
+ interface ScrollNavigatorScrollOptions {
14
+ /** Space above the target, including the horizontal navigator when present. */
15
+ offset: number;
16
+ behavior: ScrollBehavior;
17
+ }
18
+ interface ScrollNavigatorProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
19
+ items: readonly ScrollNavigatorItem[];
20
+ label?: string;
21
+ /** Space below a sticky header inside the scroll viewport, in pixels. */
22
+ topOffset?: number;
23
+ /** The nearest vertically scrolling ancestor is detected by default. */
24
+ scrollRoot?: HTMLElement | null;
25
+ /** Return true when a host scroller has handled the jump. */
26
+ onNavigate?: (id: string, target: HTMLElement, options: ScrollNavigatorScrollOptions) => boolean | void;
27
+ }
28
+ /**
29
+ * A list with an avatar index which follows the first item at the viewport's
30
+ * reading edge. The index lives only beside this list: it disappears before
31
+ * and after it. With no room in the left gutter it becomes a horizontal row.
32
+ * The row reserves space above the first item; later items scroll beneath it.
33
+ *
34
+ * Portalling the controls avoids clipping by cards, message bubbles and
35
+ * content-visibility containers. Their bounds still follow the list and its
36
+ * actual scroll viewport, never the full browser height of a nested pane.
37
+ */
38
+ declare const ScrollNavigator: React.ForwardRefExoticComponent<ScrollNavigatorProps & React.RefAttributes<HTMLDivElement>>;
39
+
40
+ export { ScrollNavigator, type ScrollNavigatorItem, type ScrollNavigatorProps, type ScrollNavigatorScrollOptions };
@@ -0,0 +1,40 @@
1
+ import * as React from 'react';
2
+ import { HTMLAttributes, ReactNode } from 'react';
3
+
4
+ interface ScrollNavigatorItem {
5
+ /** Stable within this list. Separate lists can contain the same IDs. */
6
+ id: string;
7
+ label: string;
8
+ imageSrc?: string | null;
9
+ /** Initials or an icon; defaults to the label's initials. */
10
+ fallback?: ReactNode;
11
+ content: ReactNode;
12
+ }
13
+ interface ScrollNavigatorScrollOptions {
14
+ /** Space above the target, including the horizontal navigator when present. */
15
+ offset: number;
16
+ behavior: ScrollBehavior;
17
+ }
18
+ interface ScrollNavigatorProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
19
+ items: readonly ScrollNavigatorItem[];
20
+ label?: string;
21
+ /** Space below a sticky header inside the scroll viewport, in pixels. */
22
+ topOffset?: number;
23
+ /** The nearest vertically scrolling ancestor is detected by default. */
24
+ scrollRoot?: HTMLElement | null;
25
+ /** Return true when a host scroller has handled the jump. */
26
+ onNavigate?: (id: string, target: HTMLElement, options: ScrollNavigatorScrollOptions) => boolean | void;
27
+ }
28
+ /**
29
+ * A list with an avatar index which follows the first item at the viewport's
30
+ * reading edge. The index lives only beside this list: it disappears before
31
+ * and after it. With no room in the left gutter it becomes a horizontal row.
32
+ * The row reserves space above the first item; later items scroll beneath it.
33
+ *
34
+ * Portalling the controls avoids clipping by cards, message bubbles and
35
+ * content-visibility containers. Their bounds still follow the list and its
36
+ * actual scroll viewport, never the full browser height of a nested pane.
37
+ */
38
+ declare const ScrollNavigator: React.ForwardRefExoticComponent<ScrollNavigatorProps & React.RefAttributes<HTMLDivElement>>;
39
+
40
+ export { ScrollNavigator, type ScrollNavigatorItem, type ScrollNavigatorProps, type ScrollNavigatorScrollOptions };
@@ -0,0 +1,10 @@
1
+ "use client";
2
+ "use client";
3
+ import {
4
+ ScrollNavigator
5
+ } from "../chunk-VT2WDFSU.js";
6
+ import "../chunk-3OWGL4Q2.js";
7
+ import "../chunk-G6SRSWXB.js";
8
+ export {
9
+ ScrollNavigator
10
+ };
@@ -1,51 +1,10 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
2
2
 
3
3
 
4
- var _chunkVGTINL5Qcjs = require('../chunk-VGTINL5Q.cjs');
4
+ var _chunkSJB4DPGQcjs = require('../chunk-SJB4DPGQ.cjs');
5
+ require('../chunk-VGTINL5Q.cjs');
5
6
  require('../chunk-I6GUOEBO.cjs');
7
+ require('../chunk-KWLSBTB2.cjs');
6
8
 
7
9
 
8
- var _chunkKWLSBTB2cjs = require('../chunk-KWLSBTB2.cjs');
9
-
10
- // src/primitives/section-header.tsx
11
- var _react = require('react');
12
- var _classvarianceauthority = require('class-variance-authority');
13
- var _jsxruntime = require('react/jsx-runtime');
14
- var sectionHeaderVariants = _classvarianceauthority.cva.call(void 0, "flex items-center gap-1", {
15
- variants: {
16
- variant: {
17
- muted: "text-xs font-semibold text-muted-foreground uppercase tracking-wide",
18
- plain: "text-sm font-medium text-foreground"
19
- },
20
- spacing: {
21
- tight: "mb-2",
22
- loose: "mb-3",
23
- none: ""
24
- }
25
- },
26
- defaultVariants: {
27
- variant: "muted",
28
- spacing: "tight"
29
- }
30
- });
31
- var SectionHeader = _react.forwardRef.call(void 0,
32
- function SectionHeader2({ icon, label, count, action, variant, spacing, className, ...rest }, ref) {
33
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
34
- "h3",
35
- {
36
- ref,
37
- className: _chunkKWLSBTB2cjs.cn.call(void 0, sectionHeaderVariants({ variant, spacing }), className),
38
- ...rest,
39
- children: [
40
- icon,
41
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: label }),
42
- typeof count === "number" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVGTINL5Qcjs.CountBadge, { value: count, variant: "secondary" }),
43
- action && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "ml-auto", children: action })
44
- ]
45
- }
46
- );
47
- }
48
- );
49
-
50
-
51
- exports.SectionHeader = SectionHeader;
10
+ exports.SectionHeader = _chunkSJB4DPGQcjs.SectionHeader;
@@ -1,51 +1,10 @@
1
1
  "use client";
2
2
  import {
3
- CountBadge
4
- } from "../chunk-H7TETFLB.js";
3
+ SectionHeader
4
+ } from "../chunk-SRIGG5I5.js";
5
+ import "../chunk-H7TETFLB.js";
5
6
  import "../chunk-D4ZL2OEQ.js";
6
- import {
7
- cn
8
- } from "../chunk-G6SRSWXB.js";
9
-
10
- // src/primitives/section-header.tsx
11
- import { forwardRef } from "react";
12
- import { cva } from "class-variance-authority";
13
- import { jsx, jsxs } from "react/jsx-runtime";
14
- var sectionHeaderVariants = cva("flex items-center gap-1", {
15
- variants: {
16
- variant: {
17
- muted: "text-xs font-semibold text-muted-foreground uppercase tracking-wide",
18
- plain: "text-sm font-medium text-foreground"
19
- },
20
- spacing: {
21
- tight: "mb-2",
22
- loose: "mb-3",
23
- none: ""
24
- }
25
- },
26
- defaultVariants: {
27
- variant: "muted",
28
- spacing: "tight"
29
- }
30
- });
31
- var SectionHeader = forwardRef(
32
- function SectionHeader2({ icon, label, count, action, variant, spacing, className, ...rest }, ref) {
33
- return /* @__PURE__ */ jsxs(
34
- "h3",
35
- {
36
- ref,
37
- className: cn(sectionHeaderVariants({ variant, spacing }), className),
38
- ...rest,
39
- children: [
40
- icon,
41
- /* @__PURE__ */ jsx("span", { children: label }),
42
- typeof count === "number" && /* @__PURE__ */ jsx(CountBadge, { value: count, variant: "secondary" }),
43
- action && /* @__PURE__ */ jsx("span", { className: "ml-auto", children: action })
44
- ]
45
- }
46
- );
47
- }
48
- );
7
+ import "../chunk-G6SRSWXB.js";
49
8
  export {
50
9
  SectionHeader
51
10
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epicbagel/saas-kit",
3
- "version": "1.12.0",
3
+ "version": "1.14.0",
4
4
  "description": "Accessible React primitives, layout components and design tokens for SaaS apps, built on Radix UI and Tailwind CSS v4.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -770,6 +770,16 @@
770
770
  "default": "./dist/primitives/native-select.cjs"
771
771
  }
772
772
  },
773
+ "./primitives/notes": {
774
+ "import": {
775
+ "types": "./dist/primitives/notes.d.ts",
776
+ "default": "./dist/primitives/notes.js"
777
+ },
778
+ "require": {
779
+ "types": "./dist/primitives/notes.d.cts",
780
+ "default": "./dist/primitives/notes.cjs"
781
+ }
782
+ },
773
783
  "./primitives/page-header-actions": {
774
784
  "import": {
775
785
  "types": "./dist/primitives/page-header-actions.d.ts",
@@ -940,6 +950,16 @@
940
950
  "default": "./dist/primitives/scroll-area.cjs"
941
951
  }
942
952
  },
953
+ "./primitives/scroll-navigator": {
954
+ "import": {
955
+ "types": "./dist/primitives/scroll-navigator.d.ts",
956
+ "default": "./dist/primitives/scroll-navigator.js"
957
+ },
958
+ "require": {
959
+ "types": "./dist/primitives/scroll-navigator.d.cts",
960
+ "default": "./dist/primitives/scroll-navigator.cjs"
961
+ }
962
+ },
943
963
  "./primitives/search-input": {
944
964
  "import": {
945
965
  "types": "./dist/primitives/search-input.d.ts",