@epicbagel/saas-kit 1.12.0 → 1.13.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 +22 -0
- package/THIRD_PARTY_NOTICES.md +20 -0
- package/dist/chunk-KI7SWNIN.js +53 -0
- package/dist/chunk-SJB4DPGQ.cjs +51 -0
- package/dist/chunk-SRIGG5I5.js +51 -0
- package/dist/chunk-VKYRB37O.cjs +53 -0
- package/dist/primitives/chat.cjs +3 -3
- package/dist/primitives/chat.js +3 -3
- package/dist/primitives/notes.cjs +259 -0
- package/dist/primitives/notes.d.cts +123 -0
- package/dist/primitives/notes.d.ts +123 -0
- package/dist/primitives/notes.js +259 -0
- package/dist/primitives/panel-section.cjs +4 -48
- package/dist/primitives/panel-section.js +3 -47
- package/dist/primitives/section-header.cjs +4 -45
- package/dist/primitives/section-header.js +4 -45
- package/package.json +11 -1
package/README.md
CHANGED
|
@@ -439,3 +439,25 @@ export function Appearance() {
|
|
|
439
439
|
|
|
440
440
|
MIT. Some components and styles are adapted from shadcn/ui, and the file
|
|
441
441
|
drop handling from AI SDK Elements (Apache-2.0); see `THIRD_PARTY_NOTICES.md`.
|
|
442
|
+
|
|
443
|
+
## Notes
|
|
444
|
+
|
|
445
|
+
`primitives/notes` provides a reusable `Notes` area and `NoteComposer` for any
|
|
446
|
+
record. Pass display data with stable IDs; the list owns rendering and count,
|
|
447
|
+
preserves order, and accepts author/date nodes and optional context, pinned,
|
|
448
|
+
voice/assistant and deletion metadata. Hosts resolve identity, authorize saves
|
|
449
|
+
and confirm deletions.
|
|
450
|
+
|
|
451
|
+
```tsx
|
|
452
|
+
<Notes
|
|
453
|
+
notes={[{ id: "note-1", author: "You", date: "Today", text: "Follow up next week." }]}
|
|
454
|
+
composer={<NoteComposer onSubmit={saveNote} onVoice={openRecorder} />}
|
|
455
|
+
/>
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
Omit `onVoice` for a text-only composer. A rejected save retains the draft; all
|
|
459
|
+
conflicting actions are disabled during a save. `value` / `onValueChange` and
|
|
460
|
+
`editing` / `onEditingChange` support host-owned drafts, including failed voice
|
|
461
|
+
transcripts. A controlled host clears or replaces `value` after saving. Set
|
|
462
|
+
`maxLength` to the application's limit. `NoteList` and `NoteCard` are available
|
|
463
|
+
for existing compositions.
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -52,6 +52,26 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
52
52
|
SOFTWARE.
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
## Attributed notes
|
|
56
|
+
|
|
57
|
+
`primitives/notes` adapts the attributed note cards and voice/text composer
|
|
58
|
+
from the public `@recruiteros/recruit-ui` package, version 0.16.0. The adaptation
|
|
59
|
+
adds a generic notes-array API, controlled drafts, accessible labels and
|
|
60
|
+
serialized asynchronous saves. It contains no application data or persistence.
|
|
61
|
+
|
|
62
|
+
These adapted portions are licensed under the Apache License, Version 2.0,
|
|
63
|
+
reproduced below. The upstream notice is retained here:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
Recruit UI
|
|
67
|
+
Copyright 2026 RecruiterOS
|
|
68
|
+
|
|
69
|
+
RecruiterOS-authored portions are licensed under the Apache License,
|
|
70
|
+
Version 2.0. The UI primitives come from the separately installed
|
|
71
|
+
@epicbagel/saas-kit package (MIT). Third-party runtime dependencies retain
|
|
72
|
+
their own licenses and copyright notices. See THIRD_PARTY_NOTICES.md.
|
|
73
|
+
```
|
|
74
|
+
|
|
55
75
|
## AI SDK Elements
|
|
56
76
|
|
|
57
77
|
Source: https://github.com/vercel/ai-elements (`packages/elements/src/prompt-input.tsx`,
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use client";
|
|
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
|
+
);
|
|
50
|
+
|
|
51
|
+
export {
|
|
52
|
+
PanelSection
|
|
53
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkVGTINL5Qcjs = require('./chunk-VGTINL5Q.cjs');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
var _chunkKWLSBTB2cjs = require('./chunk-KWLSBTB2.cjs');
|
|
8
|
+
|
|
9
|
+
// src/primitives/section-header.tsx
|
|
10
|
+
var _react = require('react');
|
|
11
|
+
var _classvarianceauthority = require('class-variance-authority');
|
|
12
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
13
|
+
var sectionHeaderVariants = _classvarianceauthority.cva.call(void 0, "flex items-center gap-1", {
|
|
14
|
+
variants: {
|
|
15
|
+
variant: {
|
|
16
|
+
muted: "text-xs font-semibold text-muted-foreground uppercase tracking-wide",
|
|
17
|
+
plain: "text-sm font-medium text-foreground"
|
|
18
|
+
},
|
|
19
|
+
spacing: {
|
|
20
|
+
tight: "mb-2",
|
|
21
|
+
loose: "mb-3",
|
|
22
|
+
none: ""
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
defaultVariants: {
|
|
26
|
+
variant: "muted",
|
|
27
|
+
spacing: "tight"
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
var SectionHeader = _react.forwardRef.call(void 0,
|
|
31
|
+
function SectionHeader2({ icon, label, count, action, variant, spacing, className, ...rest }, ref) {
|
|
32
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
33
|
+
"h3",
|
|
34
|
+
{
|
|
35
|
+
ref,
|
|
36
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0, sectionHeaderVariants({ variant, spacing }), className),
|
|
37
|
+
...rest,
|
|
38
|
+
children: [
|
|
39
|
+
icon,
|
|
40
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: label }),
|
|
41
|
+
typeof count === "number" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVGTINL5Qcjs.CountBadge, { value: count, variant: "secondary" }),
|
|
42
|
+
action && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "ml-auto", children: action })
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
exports.SectionHeader = SectionHeader;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
CountBadge
|
|
4
|
+
} from "./chunk-H7TETFLB.js";
|
|
5
|
+
import {
|
|
6
|
+
cn
|
|
7
|
+
} from "./chunk-G6SRSWXB.js";
|
|
8
|
+
|
|
9
|
+
// src/primitives/section-header.tsx
|
|
10
|
+
import { forwardRef } from "react";
|
|
11
|
+
import { cva } from "class-variance-authority";
|
|
12
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
+
var sectionHeaderVariants = cva("flex items-center gap-1", {
|
|
14
|
+
variants: {
|
|
15
|
+
variant: {
|
|
16
|
+
muted: "text-xs font-semibold text-muted-foreground uppercase tracking-wide",
|
|
17
|
+
plain: "text-sm font-medium text-foreground"
|
|
18
|
+
},
|
|
19
|
+
spacing: {
|
|
20
|
+
tight: "mb-2",
|
|
21
|
+
loose: "mb-3",
|
|
22
|
+
none: ""
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
defaultVariants: {
|
|
26
|
+
variant: "muted",
|
|
27
|
+
spacing: "tight"
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
var SectionHeader = forwardRef(
|
|
31
|
+
function SectionHeader2({ icon, label, count, action, variant, spacing, className, ...rest }, ref) {
|
|
32
|
+
return /* @__PURE__ */ jsxs(
|
|
33
|
+
"h3",
|
|
34
|
+
{
|
|
35
|
+
ref,
|
|
36
|
+
className: cn(sectionHeaderVariants({ variant, spacing }), className),
|
|
37
|
+
...rest,
|
|
38
|
+
children: [
|
|
39
|
+
icon,
|
|
40
|
+
/* @__PURE__ */ jsx("span", { children: label }),
|
|
41
|
+
typeof count === "number" && /* @__PURE__ */ jsx(CountBadge, { value: count, variant: "secondary" }),
|
|
42
|
+
action && /* @__PURE__ */ jsx("span", { className: "ml-auto", children: action })
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
export {
|
|
50
|
+
SectionHeader
|
|
51
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }"use client";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkKWLSBTB2cjs = require('./chunk-KWLSBTB2.cjs');
|
|
5
|
+
|
|
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
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
exports.PanelSection = PanelSection;
|
package/dist/primitives/chat.cjs
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
"use client";
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var _chunkQWUMIAYDcjs = require('../chunk-QWUMIAYD.cjs');
|
|
6
6
|
|
|
7
7
|
|
|
8
|
+
var _chunkYMI3X2YLcjs = require('../chunk-YMI3X2YL.cjs');
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
var _chunk2BTDBZYNcjs = require('../chunk-2BTDBZYN.cjs');
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
var
|
|
13
|
+
var _chunk2BTDBZYNcjs = require('../chunk-2BTDBZYN.cjs');
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
|
package/dist/primitives/chat.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
"use client";
|
|
3
|
+
import {
|
|
4
|
+
VoiceDictationButton
|
|
5
|
+
} from "../chunk-JKVVTFAP.js";
|
|
3
6
|
import {
|
|
4
7
|
VoiceSessionControls
|
|
5
8
|
} from "../chunk-KF4X37DP.js";
|
|
@@ -8,9 +11,6 @@ import {
|
|
|
8
11
|
TraceLine,
|
|
9
12
|
TraceTitle
|
|
10
13
|
} from "../chunk-Z45YKVAM.js";
|
|
11
|
-
import {
|
|
12
|
-
VoiceDictationButton
|
|
13
|
-
} from "../chunk-JKVVTFAP.js";
|
|
14
14
|
import {
|
|
15
15
|
Suggestion,
|
|
16
16
|
Suggestions
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
var _chunkSJB4DPGQcjs = require('../chunk-SJB4DPGQ.cjs');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
var _chunkVKYRB37Ocjs = require('../chunk-VKYRB37O.cjs');
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
var _chunkR3DQS6U4cjs = require('../chunk-R3DQS6U4.cjs');
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
var _chunk2HV2KKOEcjs = require('../chunk-2HV2KKOE.cjs');
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
var _chunkJ467F76Icjs = require('../chunk-J467F76I.cjs');
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
var _chunk373W6VADcjs = require('../chunk-373W6VAD.cjs');
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
var _chunkT2ZFSPE4cjs = require('../chunk-T2ZFSPE4.cjs');
|
|
24
|
+
require('../chunk-VGTINL5Q.cjs');
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
var _chunkI6GUOEBOcjs = require('../chunk-I6GUOEBO.cjs');
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
var _chunkCLYAASFNcjs = require('../chunk-CLYAASFN.cjs');
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
var _chunkVBPPFC7Xcjs = require('../chunk-VBPPFC7X.cjs');
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
var _chunkJDEXZGIYcjs = require('../chunk-JDEXZGIY.cjs');
|
|
37
|
+
require('../chunk-KWLSBTB2.cjs');
|
|
38
|
+
|
|
39
|
+
// src/primitives/notes.tsx
|
|
40
|
+
var _lucidereact = require('lucide-react');
|
|
41
|
+
var _react = require('react');
|
|
42
|
+
var _jsxruntime = require('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__ */ _jsxruntime.jsxs.call(void 0, _chunkVKYRB37Ocjs.PanelSection, { "data-slot": "note-list", border, ...props, children: [
|
|
57
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSJB4DPGQcjs.SectionHeader, { label: title, count: loading ? void 0 : count }),
|
|
58
|
+
loading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJ467F76Icjs.Stack, { direction: "vertical", gap: "sm", marginTop: "md", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVBPPFC7Xcjs.Skeleton, { preset: "row", radius: "xl" }) }) : count > 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJ467F76Icjs.Stack, { direction: "vertical", gap: "sm", marginTop: "md", children }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
59
|
+
_chunkCLYAASFNcjs.EmptyState,
|
|
60
|
+
{
|
|
61
|
+
variant: "empty",
|
|
62
|
+
size: "inline",
|
|
63
|
+
icon: _lucidereact.StickyNote,
|
|
64
|
+
title: empty.title,
|
|
65
|
+
description: _nullishCoalesce(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: _lucidereact.Mic, agent: _lucidereact.Sparkles, note: _lucidereact.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 = _optionalChain([labels, 'optionalAccess', _ => _.voice]) !== void 0 ? labels.voice : NOTE_CARD_LABELS.voice;
|
|
89
|
+
const deleteLabel = _nullishCoalesce(_optionalChain([labels, 'optionalAccess', _2 => _2.delete]), () => ( NOTE_CARD_LABELS.delete));
|
|
90
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkR3DQS6U4cjs.Card, { interaction: "group", surface: pinned ? "card" : "muted", padding: "row", ...props, children: [
|
|
91
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkJ467F76Icjs.Stack, { direction: "horizontal", gap: "xs", align: "center", justify: "between", marginBottom: "md", minWidth: "zero", wrap: true, children: [
|
|
92
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkJ467F76Icjs.Stack, { direction: "horizontal", gap: "sm", align: "center", textSize: "xs", tone: "muted", minWidth: "zero", className: "max-w-full", wrap: true, children: [
|
|
93
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk373W6VADcjs.Text, { variant: "inherit", as: "span", display: "inline-flex", weight: "medium", tone: "soft", minWidth: "zero", className: "max-w-full", children: [
|
|
94
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkT2ZFSPE4cjs.Icon, { icon: NOTE_ICON[kind], size: "xs" }),
|
|
95
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk373W6VADcjs.Text, { variant: "inherit", as: "span", minWidth: "zero", className: "[overflow-wrap:anywhere]", children: author })
|
|
96
|
+
] }),
|
|
97
|
+
pinned && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkI6GUOEBOcjs.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__ */ _jsxruntime.jsx.call(void 0, _chunk373W6VADcjs.Text, { variant: "inherit", as: "span", tone: "subtle", children: voiceLabel }),
|
|
99
|
+
scope && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
100
|
+
_chunkI6GUOEBOcjs.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__ */ _jsxruntime.jsxs.call(void 0, _chunkJ467F76Icjs.Stack, { direction: "horizontal", gap: "xs", align: "center", minWidth: "zero", className: "max-w-full", children: [
|
|
113
|
+
present(date) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk373W6VADcjs.Text, { variant: "inherit", as: "span", size: "xs", tone: "muted", minWidth: "zero", className: "[overflow-wrap:anywhere]", children: date }) : null,
|
|
114
|
+
onDelete && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
115
|
+
_chunkJDEXZGIYcjs.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__ */ _jsxruntime.jsx.call(void 0, _chunkT2ZFSPE4cjs.Icon, { icon: _lucidereact.Trash2, size: "sm" })
|
|
124
|
+
}
|
|
125
|
+
)
|
|
126
|
+
] })
|
|
127
|
+
] }),
|
|
128
|
+
present(text) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk373W6VADcjs.Text, { size: "sm", whitespace: "pre-wrap", className: "break-words [overflow-wrap:anywhere]", children: text })
|
|
129
|
+
] });
|
|
130
|
+
}
|
|
131
|
+
function Notes({ notes, ...props }) {
|
|
132
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, NoteList, { "data-slot": "notes", count: notes.length, ...props, children: notes.map(({ id, ...note }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, 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] = _react.useState.call(void 0, "");
|
|
160
|
+
const [localEditing, setLocalEditing] = _react.useState.call(void 0, false);
|
|
161
|
+
const [saving, setSaving] = _react.useState.call(void 0, false);
|
|
162
|
+
const [failed, setFailed] = _react.useState.call(void 0, false);
|
|
163
|
+
const pending = _react.useRef.call(void 0, false);
|
|
164
|
+
const mounted = _react.useRef.call(void 0, true);
|
|
165
|
+
const errorId = _react.useId.call(void 0, );
|
|
166
|
+
const text = _nullishCoalesce(value, () => ( draft));
|
|
167
|
+
const latestText = _react.useRef.call(void 0, text);
|
|
168
|
+
latestText.current = text;
|
|
169
|
+
const busy = disabled || saving;
|
|
170
|
+
const message = _nullishCoalesce(error, () => ( (failed ? copy.error : null)));
|
|
171
|
+
const typing = (_nullishCoalesce(editing, () => ( localEditing))) || Boolean(text) || Boolean(message) || !onVoice;
|
|
172
|
+
_react.useEffect.call(void 0, () => {
|
|
173
|
+
mounted.current = true;
|
|
174
|
+
return () => {
|
|
175
|
+
mounted.current = false;
|
|
176
|
+
};
|
|
177
|
+
}, []);
|
|
178
|
+
function changeText(next) {
|
|
179
|
+
if (value === void 0) setDraft(next);
|
|
180
|
+
_optionalChain([onValueChange, 'optionalCall', _3 => _3(next)]);
|
|
181
|
+
latestText.current = next;
|
|
182
|
+
}
|
|
183
|
+
function changeEditing(next) {
|
|
184
|
+
if (editing === void 0) setLocalEditing(next);
|
|
185
|
+
_optionalChain([onEditingChange, 'optionalCall', _4 => _4(next)]);
|
|
186
|
+
}
|
|
187
|
+
function cancel() {
|
|
188
|
+
if (disabled || pending.current) return;
|
|
189
|
+
changeText("");
|
|
190
|
+
changeEditing(false);
|
|
191
|
+
setFailed(false);
|
|
192
|
+
_optionalChain([onCancel, 'optionalCall', _5 => _5()]);
|
|
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 (e) {
|
|
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__ */ _jsxruntime.jsxs.call(void 0, _chunkJ467F76Icjs.Stack, { "data-slot": "note-composer", direction: "vertical", gap: "sm", marginTop: "md", "aria-busy": saving, ...props, children: [
|
|
219
|
+
message ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk373W6VADcjs.Text, { id: errorId, role: "alert", size: "sm", tone: "destructive", children: message }) : null,
|
|
220
|
+
typing ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
221
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
222
|
+
_chunk2HV2KKOEcjs.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__ */ _jsxruntime.jsxs.call(void 0, _chunkJ467F76Icjs.Stack, { direction: "horizontal", gap: "sm", align: "center", wrap: true, children: [
|
|
236
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJDEXZGIYcjs.Button, { type: "button", size: "sm", variant: "ghost", onClick: cancel, disabled: busy, children: copy.cancel }),
|
|
237
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkJDEXZGIYcjs.Button, { type: "button", size: "sm", onClick: () => void submit(text), disabled: busy || !text.trim() || maxLength != null && text.trim().length > maxLength, children: [
|
|
238
|
+
saving ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkT2ZFSPE4cjs.Icon, { icon: _lucidereact.Loader2, size: "sm", spin: true }) : null,
|
|
239
|
+
copy.submit
|
|
240
|
+
] })
|
|
241
|
+
] })
|
|
242
|
+
] }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
243
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkJ467F76Icjs.Stack, { direction: "vertical", gap: "sm", align: "center", paddingY: "md", children: [
|
|
244
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJDEXZGIYcjs.Button, { type: "button", variant: "outline", size: "voice", "aria-label": copy.voice, disabled: busy, onClick: () => {
|
|
245
|
+
if (!pending.current && !disabled) _optionalChain([onVoice, 'optionalCall', _6 => _6()]);
|
|
246
|
+
}, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkT2ZFSPE4cjs.Icon, { icon: _lucidereact.Mic, size: 28, tone: "muted" }) }),
|
|
247
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk373W6VADcjs.Text, { variant: "inherit", as: "span", size: "sm", weight: "medium", children: copy.voice }),
|
|
248
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJDEXZGIYcjs.Button, { type: "button", variant: "quiet", size: "bare", disabled: busy, onClick: () => changeEditing(true), children: copy.type })
|
|
249
|
+
] }),
|
|
250
|
+
suggestions.length > 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJ467F76Icjs.Stack, { direction: "horizontal", gap: "xs", justify: "center", wrap: true, children: suggestions.map((suggestion) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJDEXZGIYcjs.Button, { type: "button", variant: "outline-muted", size: "suggestion", disabled: busy, onClick: () => void submit(suggestion), children: suggestion }, suggestion)) }) : null
|
|
251
|
+
] })
|
|
252
|
+
] });
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
exports.NoteCard = NoteCard; exports.NoteComposer = NoteComposer; exports.NoteList = NoteList; exports.Notes = Notes;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface NotesEmptyCopy {
|
|
5
|
+
title: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
}
|
|
8
|
+
interface NoteListProps extends Omit<HTMLAttributes<HTMLElement>, "title" | "children"> {
|
|
9
|
+
/** How many notes there are. Zero shows the empty state instead of `children`. */
|
|
10
|
+
count: number;
|
|
11
|
+
/** A skeleton row in place of the list, and no count yet. */
|
|
12
|
+
loading?: boolean;
|
|
13
|
+
/** The section heading. */
|
|
14
|
+
title?: ReactNode;
|
|
15
|
+
/** The blank slate's wording. Defaults to "No notes yet". */
|
|
16
|
+
empty?: NotesEmptyCopy;
|
|
17
|
+
/** Below the notes, usually a NoteComposer. */
|
|
18
|
+
composer?: ReactNode;
|
|
19
|
+
/** The notes, usually NoteCards, newest or pinned first. */
|
|
20
|
+
children?: ReactNode;
|
|
21
|
+
/** The kit PanelSection's divider. */
|
|
22
|
+
border?: "none" | "top" | "bottom";
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A notes section, as a counted section: a skeleton row while they
|
|
26
|
+
* load, then the host's note cards, or the kit's empty state when there are
|
|
27
|
+
* none, with the composer underneath so a new note lands below the last.
|
|
28
|
+
*
|
|
29
|
+
* The root is the kit PanelSection, marked `data-slot="note-list"`.
|
|
30
|
+
*/
|
|
31
|
+
declare function NoteList({ count, loading, title, empty, composer, children, border, ...props }: NoteListProps): react_jsx_runtime.JSX.Element;
|
|
32
|
+
/** How a note was left, which picks its glyph: dictated, written by an assistant, or typed. */
|
|
33
|
+
type NoteKind = "voice" | "agent" | "note";
|
|
34
|
+
/** Marks a note that stays at the top of the list and is edited elsewhere. */
|
|
35
|
+
interface NotePinned {
|
|
36
|
+
/** The badge text, such as "Client note · pinned". */
|
|
37
|
+
label: ReactNode;
|
|
38
|
+
/** The badge tooltip, such as where to edit it. */
|
|
39
|
+
title?: string;
|
|
40
|
+
}
|
|
41
|
+
/** The context this note belongs to. */
|
|
42
|
+
interface NoteScope {
|
|
43
|
+
/** The badge text, such as a project name or "General". */
|
|
44
|
+
label: ReactNode;
|
|
45
|
+
/** The badge tooltip. */
|
|
46
|
+
title?: string;
|
|
47
|
+
/** An info-toned badge, for a note tied to a context, instead of the neutral one. */
|
|
48
|
+
highlighted?: boolean;
|
|
49
|
+
}
|
|
50
|
+
interface NoteCardLabels {
|
|
51
|
+
/** After the author on a dictated note. Pass `null` to leave it out. */
|
|
52
|
+
voice: ReactNode;
|
|
53
|
+
/** The delete button's tooltip and accessible name. */
|
|
54
|
+
delete: string;
|
|
55
|
+
}
|
|
56
|
+
interface NoteCardProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
|
|
57
|
+
/** Who left it, already resolved to a display name. */
|
|
58
|
+
author: ReactNode;
|
|
59
|
+
kind?: NoteKind;
|
|
60
|
+
/** Pins the note: it sits on the card surface, not the muted one, with this badge. */
|
|
61
|
+
pinned?: NotePinned;
|
|
62
|
+
scope?: NoteScope;
|
|
63
|
+
/** When it was left, already formatted. */
|
|
64
|
+
date?: ReactNode;
|
|
65
|
+
/** The note, kept as written: line breaks are preserved. */
|
|
66
|
+
text?: ReactNode;
|
|
67
|
+
/** Adds a delete button. Confirm in the host before deleting anything. */
|
|
68
|
+
onDelete?: () => void;
|
|
69
|
+
/** Whether the delete button is always shown or appears on hover. Use `always` on touch screens. */
|
|
70
|
+
revealDelete?: "always" | "hover";
|
|
71
|
+
labels?: Partial<NoteCardLabels>;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* One attributed note: who left it and how, an optional pinned badge, its
|
|
75
|
+
* optional context, when, and the text, with a delete button that appears
|
|
76
|
+
* on hover or always. The host resolves authors and context and confirms
|
|
77
|
+
* deletes.
|
|
78
|
+
*
|
|
79
|
+
* The root is the kit Card and keeps the kit's own `data-slot="card"`, which
|
|
80
|
+
* theme stylesheets select on.
|
|
81
|
+
*/
|
|
82
|
+
declare function NoteCard({ author, kind, pinned, scope, date, text, onDelete, revealDelete, labels, ...props }: NoteCardProps): react_jsx_runtime.JSX.Element;
|
|
83
|
+
/** A display record: hosts resolve identity, context and dates before rendering. */
|
|
84
|
+
interface NoteItem extends Pick<NoteCardProps, "author" | "kind" | "pinned" | "scope" | "date" | "text" | "onDelete" | "revealDelete" | "labels"> {
|
|
85
|
+
id: string | number;
|
|
86
|
+
}
|
|
87
|
+
interface NotesProps extends Omit<NoteListProps, "count" | "children"> {
|
|
88
|
+
/** Displayed in the supplied order. Stable IDs keep each note's identity. */
|
|
89
|
+
notes: readonly NoteItem[];
|
|
90
|
+
}
|
|
91
|
+
/** Reusable notes area. The array owns the count and the rendered cards. */
|
|
92
|
+
declare function Notes({ notes, ...props }: NotesProps): react_jsx_runtime.JSX.Element;
|
|
93
|
+
interface NoteComposerLabels {
|
|
94
|
+
voice: string;
|
|
95
|
+
type: string;
|
|
96
|
+
input: string;
|
|
97
|
+
placeholder: string;
|
|
98
|
+
cancel: string;
|
|
99
|
+
submit: string;
|
|
100
|
+
error: string;
|
|
101
|
+
}
|
|
102
|
+
interface NoteComposerProps extends Omit<HTMLAttributes<HTMLElement>, "children" | "onSubmit" | "onChange"> {
|
|
103
|
+
/** Starts the host's recorder. Without it the composer opens for typing. */
|
|
104
|
+
onVoice?: () => void;
|
|
105
|
+
/** Receives trimmed text. Resolve only once saved; reject to preserve the draft. */
|
|
106
|
+
onSubmit: (text: string) => Promise<void>;
|
|
107
|
+
suggestions?: readonly string[];
|
|
108
|
+
labels?: Partial<NoteComposerLabels>;
|
|
109
|
+
/** Controlled text. In this mode the host clears or replaces it after saving. */
|
|
110
|
+
value?: string;
|
|
111
|
+
onValueChange?: (text: string) => void;
|
|
112
|
+
/** The host can keep a recovered draft open even when its text becomes empty. */
|
|
113
|
+
editing?: boolean;
|
|
114
|
+
onEditingChange?: (editing: boolean) => void;
|
|
115
|
+
onCancel?: () => void;
|
|
116
|
+
disabled?: boolean;
|
|
117
|
+
error?: ReactNode;
|
|
118
|
+
maxLength?: number;
|
|
119
|
+
}
|
|
120
|
+
/** Voice or text composer with one pending save and recoverable drafts. */
|
|
121
|
+
declare function NoteComposer({ onVoice, onSubmit, suggestions, labels, value, onValueChange, editing, onEditingChange, onCancel, disabled, error, maxLength, ...props }: NoteComposerProps): react_jsx_runtime.JSX.Element;
|
|
122
|
+
|
|
123
|
+
export { NoteCard, type NoteCardLabels, type NoteCardProps, NoteComposer, type NoteComposerLabels, type NoteComposerProps, type NoteItem, type NoteKind, NoteList, type NoteListProps, type NotePinned, type NoteScope, Notes, type NotesEmptyCopy, type NotesProps };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface NotesEmptyCopy {
|
|
5
|
+
title: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
}
|
|
8
|
+
interface NoteListProps extends Omit<HTMLAttributes<HTMLElement>, "title" | "children"> {
|
|
9
|
+
/** How many notes there are. Zero shows the empty state instead of `children`. */
|
|
10
|
+
count: number;
|
|
11
|
+
/** A skeleton row in place of the list, and no count yet. */
|
|
12
|
+
loading?: boolean;
|
|
13
|
+
/** The section heading. */
|
|
14
|
+
title?: ReactNode;
|
|
15
|
+
/** The blank slate's wording. Defaults to "No notes yet". */
|
|
16
|
+
empty?: NotesEmptyCopy;
|
|
17
|
+
/** Below the notes, usually a NoteComposer. */
|
|
18
|
+
composer?: ReactNode;
|
|
19
|
+
/** The notes, usually NoteCards, newest or pinned first. */
|
|
20
|
+
children?: ReactNode;
|
|
21
|
+
/** The kit PanelSection's divider. */
|
|
22
|
+
border?: "none" | "top" | "bottom";
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A notes section, as a counted section: a skeleton row while they
|
|
26
|
+
* load, then the host's note cards, or the kit's empty state when there are
|
|
27
|
+
* none, with the composer underneath so a new note lands below the last.
|
|
28
|
+
*
|
|
29
|
+
* The root is the kit PanelSection, marked `data-slot="note-list"`.
|
|
30
|
+
*/
|
|
31
|
+
declare function NoteList({ count, loading, title, empty, composer, children, border, ...props }: NoteListProps): react_jsx_runtime.JSX.Element;
|
|
32
|
+
/** How a note was left, which picks its glyph: dictated, written by an assistant, or typed. */
|
|
33
|
+
type NoteKind = "voice" | "agent" | "note";
|
|
34
|
+
/** Marks a note that stays at the top of the list and is edited elsewhere. */
|
|
35
|
+
interface NotePinned {
|
|
36
|
+
/** The badge text, such as "Client note · pinned". */
|
|
37
|
+
label: ReactNode;
|
|
38
|
+
/** The badge tooltip, such as where to edit it. */
|
|
39
|
+
title?: string;
|
|
40
|
+
}
|
|
41
|
+
/** The context this note belongs to. */
|
|
42
|
+
interface NoteScope {
|
|
43
|
+
/** The badge text, such as a project name or "General". */
|
|
44
|
+
label: ReactNode;
|
|
45
|
+
/** The badge tooltip. */
|
|
46
|
+
title?: string;
|
|
47
|
+
/** An info-toned badge, for a note tied to a context, instead of the neutral one. */
|
|
48
|
+
highlighted?: boolean;
|
|
49
|
+
}
|
|
50
|
+
interface NoteCardLabels {
|
|
51
|
+
/** After the author on a dictated note. Pass `null` to leave it out. */
|
|
52
|
+
voice: ReactNode;
|
|
53
|
+
/** The delete button's tooltip and accessible name. */
|
|
54
|
+
delete: string;
|
|
55
|
+
}
|
|
56
|
+
interface NoteCardProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
|
|
57
|
+
/** Who left it, already resolved to a display name. */
|
|
58
|
+
author: ReactNode;
|
|
59
|
+
kind?: NoteKind;
|
|
60
|
+
/** Pins the note: it sits on the card surface, not the muted one, with this badge. */
|
|
61
|
+
pinned?: NotePinned;
|
|
62
|
+
scope?: NoteScope;
|
|
63
|
+
/** When it was left, already formatted. */
|
|
64
|
+
date?: ReactNode;
|
|
65
|
+
/** The note, kept as written: line breaks are preserved. */
|
|
66
|
+
text?: ReactNode;
|
|
67
|
+
/** Adds a delete button. Confirm in the host before deleting anything. */
|
|
68
|
+
onDelete?: () => void;
|
|
69
|
+
/** Whether the delete button is always shown or appears on hover. Use `always` on touch screens. */
|
|
70
|
+
revealDelete?: "always" | "hover";
|
|
71
|
+
labels?: Partial<NoteCardLabels>;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* One attributed note: who left it and how, an optional pinned badge, its
|
|
75
|
+
* optional context, when, and the text, with a delete button that appears
|
|
76
|
+
* on hover or always. The host resolves authors and context and confirms
|
|
77
|
+
* deletes.
|
|
78
|
+
*
|
|
79
|
+
* The root is the kit Card and keeps the kit's own `data-slot="card"`, which
|
|
80
|
+
* theme stylesheets select on.
|
|
81
|
+
*/
|
|
82
|
+
declare function NoteCard({ author, kind, pinned, scope, date, text, onDelete, revealDelete, labels, ...props }: NoteCardProps): react_jsx_runtime.JSX.Element;
|
|
83
|
+
/** A display record: hosts resolve identity, context and dates before rendering. */
|
|
84
|
+
interface NoteItem extends Pick<NoteCardProps, "author" | "kind" | "pinned" | "scope" | "date" | "text" | "onDelete" | "revealDelete" | "labels"> {
|
|
85
|
+
id: string | number;
|
|
86
|
+
}
|
|
87
|
+
interface NotesProps extends Omit<NoteListProps, "count" | "children"> {
|
|
88
|
+
/** Displayed in the supplied order. Stable IDs keep each note's identity. */
|
|
89
|
+
notes: readonly NoteItem[];
|
|
90
|
+
}
|
|
91
|
+
/** Reusable notes area. The array owns the count and the rendered cards. */
|
|
92
|
+
declare function Notes({ notes, ...props }: NotesProps): react_jsx_runtime.JSX.Element;
|
|
93
|
+
interface NoteComposerLabels {
|
|
94
|
+
voice: string;
|
|
95
|
+
type: string;
|
|
96
|
+
input: string;
|
|
97
|
+
placeholder: string;
|
|
98
|
+
cancel: string;
|
|
99
|
+
submit: string;
|
|
100
|
+
error: string;
|
|
101
|
+
}
|
|
102
|
+
interface NoteComposerProps extends Omit<HTMLAttributes<HTMLElement>, "children" | "onSubmit" | "onChange"> {
|
|
103
|
+
/** Starts the host's recorder. Without it the composer opens for typing. */
|
|
104
|
+
onVoice?: () => void;
|
|
105
|
+
/** Receives trimmed text. Resolve only once saved; reject to preserve the draft. */
|
|
106
|
+
onSubmit: (text: string) => Promise<void>;
|
|
107
|
+
suggestions?: readonly string[];
|
|
108
|
+
labels?: Partial<NoteComposerLabels>;
|
|
109
|
+
/** Controlled text. In this mode the host clears or replaces it after saving. */
|
|
110
|
+
value?: string;
|
|
111
|
+
onValueChange?: (text: string) => void;
|
|
112
|
+
/** The host can keep a recovered draft open even when its text becomes empty. */
|
|
113
|
+
editing?: boolean;
|
|
114
|
+
onEditingChange?: (editing: boolean) => void;
|
|
115
|
+
onCancel?: () => void;
|
|
116
|
+
disabled?: boolean;
|
|
117
|
+
error?: ReactNode;
|
|
118
|
+
maxLength?: number;
|
|
119
|
+
}
|
|
120
|
+
/** Voice or text composer with one pending save and recoverable drafts. */
|
|
121
|
+
declare function NoteComposer({ onVoice, onSubmit, suggestions, labels, value, onValueChange, editing, onEditingChange, onCancel, disabled, error, maxLength, ...props }: NoteComposerProps): react_jsx_runtime.JSX.Element;
|
|
122
|
+
|
|
123
|
+
export { NoteCard, type NoteCardLabels, type NoteCardProps, NoteComposer, type NoteComposerLabels, type NoteComposerProps, type NoteItem, type NoteKind, NoteList, type NoteListProps, type NotePinned, type NoteScope, Notes, type NotesEmptyCopy, type NotesProps };
|
|
@@ -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});
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
var
|
|
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
|
-
|
|
4
|
-
} from "../chunk-
|
|
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
|
};
|
|
@@ -1,51 +1,10 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
var
|
|
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
|
-
|
|
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
|
-
|
|
4
|
-
} from "../chunk-
|
|
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.
|
|
3
|
+
"version": "1.13.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",
|