@epicbagel/saas-kit 1.30.0 → 1.31.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/dist/primitives/chat.cjs +5 -0
- package/dist/primitives/chat.d.cts +13 -1
- package/dist/primitives/chat.d.ts +13 -1
- package/dist/primitives/chat.js +5 -0
- package/dist/primitives/option-picker.cjs +74 -0
- package/dist/primitives/option-picker.d.cts +35 -0
- package/dist/primitives/option-picker.d.ts +35 -0
- package/dist/primitives/option-picker.js +74 -0
- package/package.json +11 -1
package/dist/primitives/chat.cjs
CHANGED
|
@@ -458,6 +458,7 @@ function ChatInput({
|
|
|
458
458
|
compactOnBlur = false,
|
|
459
459
|
header,
|
|
460
460
|
helperText,
|
|
461
|
+
tools,
|
|
461
462
|
privacyNote
|
|
462
463
|
}) {
|
|
463
464
|
const internalRef = _react.useRef.call(void 0, null);
|
|
@@ -608,6 +609,7 @@ function ChatInput({
|
|
|
608
609
|
addFilesLabel
|
|
609
610
|
] }) })
|
|
610
611
|
] }),
|
|
612
|
+
tools ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { "data-slot": "chat-input-tools", className: "flex shrink-0 items-center gap-1", children: tools }) : null,
|
|
611
613
|
helperText ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
612
614
|
"span",
|
|
613
615
|
{
|
|
@@ -1048,6 +1050,7 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
|
|
|
1048
1050
|
composerAppearance = "default",
|
|
1049
1051
|
mobileCompactComposer = false,
|
|
1050
1052
|
composerHelperText,
|
|
1053
|
+
composerTools,
|
|
1051
1054
|
composerPrivacyNote,
|
|
1052
1055
|
emptyFileDropzone = false,
|
|
1053
1056
|
emptyFileDropzoneLabel = "Drop files here, or choose them",
|
|
@@ -1262,6 +1265,7 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
|
|
|
1262
1265
|
uploadingLabel,
|
|
1263
1266
|
appearance: composerAppearance,
|
|
1264
1267
|
helperText: composerHelperText,
|
|
1268
|
+
tools: composerTools,
|
|
1265
1269
|
privacyNote: composerPrivacyNote,
|
|
1266
1270
|
className: workspace ? "rounded-3xl shadow-sm" : void 0
|
|
1267
1271
|
}
|
|
@@ -1380,6 +1384,7 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
|
|
|
1380
1384
|
appearance: composerAppearance,
|
|
1381
1385
|
compactOnBlur: compactComposer,
|
|
1382
1386
|
helperText: composerHelperText,
|
|
1387
|
+
tools: composerTools,
|
|
1383
1388
|
privacyNote: composerPrivacyNote,
|
|
1384
1389
|
className: workspace ? "mx-auto max-w-3xl rounded-3xl shadow-sm" : void 0
|
|
1385
1390
|
}
|
|
@@ -240,6 +240,12 @@ interface ChatInputProps {
|
|
|
240
240
|
header?: ReactNode;
|
|
241
241
|
/** Quiet contextual copy between the composer controls. */
|
|
242
242
|
helperText?: ReactNode;
|
|
243
|
+
/**
|
|
244
|
+
* Controls for the message, in the composer's control row after the `+`
|
|
245
|
+
* menu: a setting the next send uses, such as an `OptionPicker`. Each
|
|
246
|
+
* control keeps a 44px touch target; they stay in the folded composer too.
|
|
247
|
+
*/
|
|
248
|
+
tools?: ReactNode;
|
|
243
249
|
/** Privacy or visibility reassurance rendered below the composer. */
|
|
244
250
|
privacyNote?: ReactNode;
|
|
245
251
|
}
|
|
@@ -260,7 +266,7 @@ interface ChatInputProps {
|
|
|
260
266
|
* `<Chat>` instead of composing `<ChatInput>` directly if you want
|
|
261
267
|
* device-aware default modes.
|
|
262
268
|
*/
|
|
263
|
-
declare function ChatInput({ value, onChange, onSend, pending, disabled, placeholder, size, uploadingLabel, voice, voiceSession, voiceTitle, voiceLang, submitLabel, autoFocus, className, inputRef, attachments, onFilesSelected, onRemoveAttachment, accept, multiple, addFilesLabel, appearance, compactOnBlur, header, helperText, privacyNote, }: ChatInputProps): react_jsx_runtime.JSX.Element;
|
|
269
|
+
declare function ChatInput({ value, onChange, onSend, pending, disabled, placeholder, size, uploadingLabel, voice, voiceSession, voiceTitle, voiceLang, submitLabel, autoFocus, className, inputRef, attachments, onFilesSelected, onRemoveAttachment, accept, multiple, addFilesLabel, appearance, compactOnBlur, header, helperText, tools, privacyNote, }: ChatInputProps): react_jsx_runtime.JSX.Element;
|
|
264
270
|
/** A next step offered in the empty state, under the composer (`emptyActions`). */
|
|
265
271
|
interface ChatEmptyAction {
|
|
266
272
|
/** Stable key. */
|
|
@@ -423,6 +429,12 @@ interface ChatProps {
|
|
|
423
429
|
mobileCompactComposer?: boolean;
|
|
424
430
|
/** Quiet contextual copy inside the composer action row. */
|
|
425
431
|
composerHelperText?: ReactNode;
|
|
432
|
+
/**
|
|
433
|
+
* Controls in the composer's control row, after the `+` menu, on the new
|
|
434
|
+
* conversation's composer and the conversation's alike: a setting the next
|
|
435
|
+
* message uses, such as an `OptionPicker`.
|
|
436
|
+
*/
|
|
437
|
+
composerTools?: ReactNode;
|
|
426
438
|
/** Privacy or visibility reassurance below the composer. */
|
|
427
439
|
composerPrivacyNote?: ReactNode;
|
|
428
440
|
/** Show a prominent file drop target before the empty-state composer. */
|
|
@@ -240,6 +240,12 @@ interface ChatInputProps {
|
|
|
240
240
|
header?: ReactNode;
|
|
241
241
|
/** Quiet contextual copy between the composer controls. */
|
|
242
242
|
helperText?: ReactNode;
|
|
243
|
+
/**
|
|
244
|
+
* Controls for the message, in the composer's control row after the `+`
|
|
245
|
+
* menu: a setting the next send uses, such as an `OptionPicker`. Each
|
|
246
|
+
* control keeps a 44px touch target; they stay in the folded composer too.
|
|
247
|
+
*/
|
|
248
|
+
tools?: ReactNode;
|
|
243
249
|
/** Privacy or visibility reassurance rendered below the composer. */
|
|
244
250
|
privacyNote?: ReactNode;
|
|
245
251
|
}
|
|
@@ -260,7 +266,7 @@ interface ChatInputProps {
|
|
|
260
266
|
* `<Chat>` instead of composing `<ChatInput>` directly if you want
|
|
261
267
|
* device-aware default modes.
|
|
262
268
|
*/
|
|
263
|
-
declare function ChatInput({ value, onChange, onSend, pending, disabled, placeholder, size, uploadingLabel, voice, voiceSession, voiceTitle, voiceLang, submitLabel, autoFocus, className, inputRef, attachments, onFilesSelected, onRemoveAttachment, accept, multiple, addFilesLabel, appearance, compactOnBlur, header, helperText, privacyNote, }: ChatInputProps): react_jsx_runtime.JSX.Element;
|
|
269
|
+
declare function ChatInput({ value, onChange, onSend, pending, disabled, placeholder, size, uploadingLabel, voice, voiceSession, voiceTitle, voiceLang, submitLabel, autoFocus, className, inputRef, attachments, onFilesSelected, onRemoveAttachment, accept, multiple, addFilesLabel, appearance, compactOnBlur, header, helperText, tools, privacyNote, }: ChatInputProps): react_jsx_runtime.JSX.Element;
|
|
264
270
|
/** A next step offered in the empty state, under the composer (`emptyActions`). */
|
|
265
271
|
interface ChatEmptyAction {
|
|
266
272
|
/** Stable key. */
|
|
@@ -423,6 +429,12 @@ interface ChatProps {
|
|
|
423
429
|
mobileCompactComposer?: boolean;
|
|
424
430
|
/** Quiet contextual copy inside the composer action row. */
|
|
425
431
|
composerHelperText?: ReactNode;
|
|
432
|
+
/**
|
|
433
|
+
* Controls in the composer's control row, after the `+` menu, on the new
|
|
434
|
+
* conversation's composer and the conversation's alike: a setting the next
|
|
435
|
+
* message uses, such as an `OptionPicker`.
|
|
436
|
+
*/
|
|
437
|
+
composerTools?: ReactNode;
|
|
426
438
|
/** Privacy or visibility reassurance below the composer. */
|
|
427
439
|
composerPrivacyNote?: ReactNode;
|
|
428
440
|
/** Show a prominent file drop target before the empty-state composer. */
|
package/dist/primitives/chat.js
CHANGED
|
@@ -458,6 +458,7 @@ function ChatInput({
|
|
|
458
458
|
compactOnBlur = false,
|
|
459
459
|
header,
|
|
460
460
|
helperText,
|
|
461
|
+
tools,
|
|
461
462
|
privacyNote
|
|
462
463
|
}) {
|
|
463
464
|
const internalRef = useRef(null);
|
|
@@ -608,6 +609,7 @@ function ChatInput({
|
|
|
608
609
|
addFilesLabel
|
|
609
610
|
] }) })
|
|
610
611
|
] }),
|
|
612
|
+
tools ? /* @__PURE__ */ jsx("div", { "data-slot": "chat-input-tools", className: "flex shrink-0 items-center gap-1", children: tools }) : null,
|
|
611
613
|
helperText ? /* @__PURE__ */ jsx(
|
|
612
614
|
"span",
|
|
613
615
|
{
|
|
@@ -1048,6 +1050,7 @@ var Chat = forwardRef(function Chat2({
|
|
|
1048
1050
|
composerAppearance = "default",
|
|
1049
1051
|
mobileCompactComposer = false,
|
|
1050
1052
|
composerHelperText,
|
|
1053
|
+
composerTools,
|
|
1051
1054
|
composerPrivacyNote,
|
|
1052
1055
|
emptyFileDropzone = false,
|
|
1053
1056
|
emptyFileDropzoneLabel = "Drop files here, or choose them",
|
|
@@ -1262,6 +1265,7 @@ var Chat = forwardRef(function Chat2({
|
|
|
1262
1265
|
uploadingLabel,
|
|
1263
1266
|
appearance: composerAppearance,
|
|
1264
1267
|
helperText: composerHelperText,
|
|
1268
|
+
tools: composerTools,
|
|
1265
1269
|
privacyNote: composerPrivacyNote,
|
|
1266
1270
|
className: workspace ? "rounded-3xl shadow-sm" : void 0
|
|
1267
1271
|
}
|
|
@@ -1380,6 +1384,7 @@ var Chat = forwardRef(function Chat2({
|
|
|
1380
1384
|
appearance: composerAppearance,
|
|
1381
1385
|
compactOnBlur: compactComposer,
|
|
1382
1386
|
helperText: composerHelperText,
|
|
1387
|
+
tools: composerTools,
|
|
1383
1388
|
privacyNote: composerPrivacyNote,
|
|
1384
1389
|
className: workspace ? "mx-auto max-w-3xl rounded-3xl shadow-sm" : void 0
|
|
1385
1390
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
var _chunkZAITUDYDcjs = require('../chunk-ZAITUDYD.cjs');
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
var _chunkJDEXZGIYcjs = require('../chunk-JDEXZGIY.cjs');
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
var _chunkKWLSBTB2cjs = require('../chunk-KWLSBTB2.cjs');
|
|
17
|
+
|
|
18
|
+
// src/primitives/option-picker.tsx
|
|
19
|
+
var _lucidereact = require('lucide-react');
|
|
20
|
+
var _react = require('react');
|
|
21
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
22
|
+
function OptionPicker({
|
|
23
|
+
value,
|
|
24
|
+
onValueChange,
|
|
25
|
+
options,
|
|
26
|
+
label,
|
|
27
|
+
icon,
|
|
28
|
+
disabled = false,
|
|
29
|
+
side = "top",
|
|
30
|
+
align = "start",
|
|
31
|
+
className
|
|
32
|
+
}) {
|
|
33
|
+
const headingId = _react.useId.call(void 0, );
|
|
34
|
+
const current = options.find((option) => option.value === value);
|
|
35
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkZAITUDYDcjs.DropdownMenu, { children: [
|
|
36
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZAITUDYDcjs.DropdownMenuTrigger, { asChild: true, disabled, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
37
|
+
_chunkJDEXZGIYcjs.Button,
|
|
38
|
+
{
|
|
39
|
+
type: "button",
|
|
40
|
+
variant: "ghost",
|
|
41
|
+
"aria-label": `${label}: ${_nullishCoalesce(_optionalChain([current, 'optionalAccess', _ => _.label]), () => ( value))}`,
|
|
42
|
+
"data-slot": "option-picker-trigger",
|
|
43
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0, "min-h-[44px] shrink-0 gap-1.5 px-3 text-sm font-medium", className),
|
|
44
|
+
children: [
|
|
45
|
+
icon,
|
|
46
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: _nullishCoalesce(_optionalChain([current, 'optionalAccess', _2 => _2.label]), () => ( value)) }),
|
|
47
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ChevronUp, { "aria-hidden": true, className: _chunkKWLSBTB2cjs.cn.call(void 0, "h-3.5 w-3.5 opacity-60", side === "bottom" && "rotate-180") })
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
) }),
|
|
51
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkZAITUDYDcjs.DropdownMenuContent, { side, align, className: "w-80 max-w-[calc(100vw-2rem)]", "aria-labelledby": headingId, children: [
|
|
52
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZAITUDYDcjs.DropdownMenuLabel, { id: headingId, className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: label }),
|
|
53
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZAITUDYDcjs.DropdownMenuRadioGroup, { value, onValueChange: (next) => onValueChange(next), children: options.map((option) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
54
|
+
_chunkZAITUDYDcjs.DropdownMenuRadioItem,
|
|
55
|
+
{
|
|
56
|
+
value: option.value,
|
|
57
|
+
"data-slot": "option-picker-option",
|
|
58
|
+
className: "items-start py-2.5 sm:py-2.5 [&>span:first-child]:top-3.5",
|
|
59
|
+
children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "flex min-w-0 flex-col gap-0.5", children: [
|
|
60
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "font-medium", children: [
|
|
61
|
+
option.label,
|
|
62
|
+
option.tag ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "ml-1.5 text-xs font-normal text-muted-foreground", children: option.tag }) : null
|
|
63
|
+
] }),
|
|
64
|
+
option.description ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-xs leading-relaxed text-muted-foreground", children: option.description }) : null
|
|
65
|
+
] })
|
|
66
|
+
},
|
|
67
|
+
option.value
|
|
68
|
+
)) })
|
|
69
|
+
] })
|
|
70
|
+
] });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
exports.OptionPicker = OptionPicker;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface OptionPickerOption<TValue extends string = string> {
|
|
5
|
+
value: TValue;
|
|
6
|
+
/** The option's name, also shown on the button once picked. */
|
|
7
|
+
label: string;
|
|
8
|
+
/** One line on what picking it means. */
|
|
9
|
+
description?: ReactNode;
|
|
10
|
+
/** A quiet note after the name, such as "default". */
|
|
11
|
+
tag?: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
interface OptionPickerProps<TValue extends string = string> {
|
|
14
|
+
value: TValue;
|
|
15
|
+
onValueChange: (value: TValue) => void;
|
|
16
|
+
options: ReadonlyArray<OptionPickerOption<TValue>>;
|
|
17
|
+
/** Names the setting: the list's heading, and the button's accessible name with the value. */
|
|
18
|
+
label: string;
|
|
19
|
+
/** Shown before the value on the button. */
|
|
20
|
+
icon?: ReactNode;
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
/** Where the list opens. Defaults to `top`, for a control in a composer. */
|
|
23
|
+
side?: "top" | "bottom";
|
|
24
|
+
align?: "start" | "end";
|
|
25
|
+
className?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A setting picked from a short list, the way a chat composer picks its effort:
|
|
29
|
+
* a button showing the current value opens a list of options, each a name and
|
|
30
|
+
* one line on what it means, one of them picked. A controlled radio group in a
|
|
31
|
+
* menu, so arrow keys move between options and Enter picks one.
|
|
32
|
+
*/
|
|
33
|
+
declare function OptionPicker<TValue extends string = string>({ value, onValueChange, options, label, icon, disabled, side, align, className, }: OptionPickerProps<TValue>): react_jsx_runtime.JSX.Element;
|
|
34
|
+
|
|
35
|
+
export { OptionPicker, type OptionPickerOption, type OptionPickerProps };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface OptionPickerOption<TValue extends string = string> {
|
|
5
|
+
value: TValue;
|
|
6
|
+
/** The option's name, also shown on the button once picked. */
|
|
7
|
+
label: string;
|
|
8
|
+
/** One line on what picking it means. */
|
|
9
|
+
description?: ReactNode;
|
|
10
|
+
/** A quiet note after the name, such as "default". */
|
|
11
|
+
tag?: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
interface OptionPickerProps<TValue extends string = string> {
|
|
14
|
+
value: TValue;
|
|
15
|
+
onValueChange: (value: TValue) => void;
|
|
16
|
+
options: ReadonlyArray<OptionPickerOption<TValue>>;
|
|
17
|
+
/** Names the setting: the list's heading, and the button's accessible name with the value. */
|
|
18
|
+
label: string;
|
|
19
|
+
/** Shown before the value on the button. */
|
|
20
|
+
icon?: ReactNode;
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
/** Where the list opens. Defaults to `top`, for a control in a composer. */
|
|
23
|
+
side?: "top" | "bottom";
|
|
24
|
+
align?: "start" | "end";
|
|
25
|
+
className?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A setting picked from a short list, the way a chat composer picks its effort:
|
|
29
|
+
* a button showing the current value opens a list of options, each a name and
|
|
30
|
+
* one line on what it means, one of them picked. A controlled radio group in a
|
|
31
|
+
* menu, so arrow keys move between options and Enter picks one.
|
|
32
|
+
*/
|
|
33
|
+
declare function OptionPicker<TValue extends string = string>({ value, onValueChange, options, label, icon, disabled, side, align, className, }: OptionPickerProps<TValue>): react_jsx_runtime.JSX.Element;
|
|
34
|
+
|
|
35
|
+
export { OptionPicker, type OptionPickerOption, type OptionPickerProps };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
import {
|
|
4
|
+
DropdownMenu,
|
|
5
|
+
DropdownMenuContent,
|
|
6
|
+
DropdownMenuLabel,
|
|
7
|
+
DropdownMenuRadioGroup,
|
|
8
|
+
DropdownMenuRadioItem,
|
|
9
|
+
DropdownMenuTrigger
|
|
10
|
+
} from "../chunk-V4LE2HWP.js";
|
|
11
|
+
import {
|
|
12
|
+
Button
|
|
13
|
+
} from "../chunk-W326GKML.js";
|
|
14
|
+
import {
|
|
15
|
+
cn
|
|
16
|
+
} from "../chunk-G6SRSWXB.js";
|
|
17
|
+
|
|
18
|
+
// src/primitives/option-picker.tsx
|
|
19
|
+
import { ChevronUp } from "lucide-react";
|
|
20
|
+
import { useId } from "react";
|
|
21
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
22
|
+
function OptionPicker({
|
|
23
|
+
value,
|
|
24
|
+
onValueChange,
|
|
25
|
+
options,
|
|
26
|
+
label,
|
|
27
|
+
icon,
|
|
28
|
+
disabled = false,
|
|
29
|
+
side = "top",
|
|
30
|
+
align = "start",
|
|
31
|
+
className
|
|
32
|
+
}) {
|
|
33
|
+
const headingId = useId();
|
|
34
|
+
const current = options.find((option) => option.value === value);
|
|
35
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
36
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, disabled, children: /* @__PURE__ */ jsxs(
|
|
37
|
+
Button,
|
|
38
|
+
{
|
|
39
|
+
type: "button",
|
|
40
|
+
variant: "ghost",
|
|
41
|
+
"aria-label": `${label}: ${current?.label ?? value}`,
|
|
42
|
+
"data-slot": "option-picker-trigger",
|
|
43
|
+
className: cn("min-h-[44px] shrink-0 gap-1.5 px-3 text-sm font-medium", className),
|
|
44
|
+
children: [
|
|
45
|
+
icon,
|
|
46
|
+
/* @__PURE__ */ jsx("span", { children: current?.label ?? value }),
|
|
47
|
+
/* @__PURE__ */ jsx(ChevronUp, { "aria-hidden": true, className: cn("h-3.5 w-3.5 opacity-60", side === "bottom" && "rotate-180") })
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
) }),
|
|
51
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { side, align, className: "w-80 max-w-[calc(100vw-2rem)]", "aria-labelledby": headingId, children: [
|
|
52
|
+
/* @__PURE__ */ jsx(DropdownMenuLabel, { id: headingId, className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: label }),
|
|
53
|
+
/* @__PURE__ */ jsx(DropdownMenuRadioGroup, { value, onValueChange: (next) => onValueChange(next), children: options.map((option) => /* @__PURE__ */ jsx(
|
|
54
|
+
DropdownMenuRadioItem,
|
|
55
|
+
{
|
|
56
|
+
value: option.value,
|
|
57
|
+
"data-slot": "option-picker-option",
|
|
58
|
+
className: "items-start py-2.5 sm:py-2.5 [&>span:first-child]:top-3.5",
|
|
59
|
+
children: /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col gap-0.5", children: [
|
|
60
|
+
/* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
|
|
61
|
+
option.label,
|
|
62
|
+
option.tag ? /* @__PURE__ */ jsx("span", { className: "ml-1.5 text-xs font-normal text-muted-foreground", children: option.tag }) : null
|
|
63
|
+
] }),
|
|
64
|
+
option.description ? /* @__PURE__ */ jsx("span", { className: "text-xs leading-relaxed text-muted-foreground", children: option.description }) : null
|
|
65
|
+
] })
|
|
66
|
+
},
|
|
67
|
+
option.value
|
|
68
|
+
)) })
|
|
69
|
+
] })
|
|
70
|
+
] });
|
|
71
|
+
}
|
|
72
|
+
export {
|
|
73
|
+
OptionPicker
|
|
74
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@epicbagel/saas-kit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.31.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": [
|
|
@@ -790,6 +790,16 @@
|
|
|
790
790
|
"default": "./dist/primitives/notes.cjs"
|
|
791
791
|
}
|
|
792
792
|
},
|
|
793
|
+
"./primitives/option-picker": {
|
|
794
|
+
"import": {
|
|
795
|
+
"types": "./dist/primitives/option-picker.d.ts",
|
|
796
|
+
"default": "./dist/primitives/option-picker.js"
|
|
797
|
+
},
|
|
798
|
+
"require": {
|
|
799
|
+
"types": "./dist/primitives/option-picker.d.cts",
|
|
800
|
+
"default": "./dist/primitives/option-picker.cjs"
|
|
801
|
+
}
|
|
802
|
+
},
|
|
793
803
|
"./primitives/page-header-actions": {
|
|
794
804
|
"import": {
|
|
795
805
|
"types": "./dist/primitives/page-header-actions.d.ts",
|