@epicbagel/saas-kit 1.3.0 → 1.5.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 +91 -0
- package/dist/chunk-D5EHW3O2.cjs +52 -0
- package/dist/chunk-F3DAFAMD.js +271 -0
- package/dist/{chunk-JZOBIPFC.js → chunk-FGISSYXG.js} +61 -2
- package/dist/chunk-HAP6USTP.cjs +46 -0
- package/dist/chunk-HAQOT2CD.js +46 -0
- package/dist/{chunk-2AU7ZRGX.cjs → chunk-LAN3K2JI.cjs} +61 -2
- package/dist/chunk-TWCJMFST.js +260 -0
- package/dist/chunk-U3YFP6ZV.cjs +273 -0
- package/dist/chunk-X3PRMR5G.js +52 -0
- package/dist/chunk-ZJFYOXSM.cjs +260 -0
- package/dist/lib/neutral-theme.cjs +39 -236
- package/dist/lib/neutral-theme.d.cts +44 -2
- package/dist/lib/neutral-theme.d.ts +44 -2
- package/dist/lib/neutral-theme.js +23 -219
- package/dist/primitives/chat.cjs +65 -12
- package/dist/primitives/chat.d.cts +46 -2
- package/dist/primitives/chat.d.ts +46 -2
- package/dist/primitives/chat.js +55 -2
- package/dist/primitives/field.cjs +12 -239
- package/dist/primitives/field.js +16 -243
- package/dist/primitives/message.cjs +8 -2
- package/dist/primitives/message.d.cts +35 -1
- package/dist/primitives/message.d.ts +35 -1
- package/dist/primitives/message.js +7 -1
- package/dist/primitives/radio-group.cjs +4 -39
- package/dist/primitives/radio-group.js +4 -39
- package/dist/primitives/theme-selector.cjs +188 -0
- package/dist/primitives/theme-selector.d.cts +78 -0
- package/dist/primitives/theme-selector.d.ts +78 -0
- package/dist/primitives/theme-selector.js +188 -0
- package/dist/primitives/toggle-group.cjs +5 -45
- package/dist/primitives/toggle-group.js +5 -45
- package/package.json +11 -1
package/README.md
CHANGED
|
@@ -160,6 +160,41 @@ public in 1.1.0, and these were the decisions about its props then:
|
|
|
160
160
|
scroller neither anchors it nor tracks it. It has no time marker, files or
|
|
161
161
|
rich `content`, and the turns either side of it keep their time grouping.
|
|
162
162
|
|
|
163
|
+
### A turn's actions (1.5.0)
|
|
164
|
+
|
|
165
|
+
- **Under a reply, a row of actions.** `messageActions(message)` returns the
|
|
166
|
+
actions under a turn, after prompt-kit's "Message with Actions": small
|
|
167
|
+
icon-only ghost buttons with tooltips, drawn in a `MessageActions` row at
|
|
168
|
+
the message's side. `ChatCopyAction` is the ready one: it copies the turn's
|
|
169
|
+
`text`, its Markdown source, and shows a check and "Copied" for a moment.
|
|
170
|
+
Add your own after it with `MessageAction` (an icon child, a `tooltip`, and
|
|
171
|
+
`label` when the tooltip isn't text).
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
<Chat
|
|
175
|
+
messages={messages}
|
|
176
|
+
onSend={send}
|
|
177
|
+
messageActions={(message) => (
|
|
178
|
+
<>
|
|
179
|
+
<ChatCopyAction message={message} onCopy={(ok) => ok && track("copy")} />
|
|
180
|
+
<MessageAction tooltip="Good reply" onClick={() => rate(message.id, "up")}>
|
|
181
|
+
<ThumbsUp />
|
|
182
|
+
</MessageAction>
|
|
183
|
+
</>
|
|
184
|
+
)}
|
|
185
|
+
/>
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
- **Which turns.** Assistant turns, by default. `ChatMessage.actions: false`
|
|
189
|
+
drops them from a turn that isn't a reply (a progress line), `true` gives
|
|
190
|
+
them to a user turn. The running line, a running turn, a turn with
|
|
191
|
+
`status: "sending"` (the user's own turn shown optimistically, until its
|
|
192
|
+
stored copy replaces it) and the footer never have them.
|
|
193
|
+
- **Always there.** The row shows on every screen, a phone included, rather
|
|
194
|
+
than on hover, so nothing moves when a pointer reaches it, and the copied
|
|
195
|
+
state swaps one icon for another of the same size. A button is 2rem
|
|
196
|
+
square, 2.75rem on a touch screen, where the tooltip can't show.
|
|
197
|
+
|
|
163
198
|
## File preview (1.3.0)
|
|
164
199
|
|
|
165
200
|
`primitives/file-preview` shows a file in a dialog without leaving the page:
|
|
@@ -219,6 +254,62 @@ import { FilePreview } from "@epicbagel/saas-kit/primitives/file-preview";
|
|
|
219
254
|
`primitives/document-preview` is the same dialog with every `src` in the
|
|
220
255
|
browser's viewer, as it was in ui-kit; its API is unchanged.
|
|
221
256
|
|
|
257
|
+
## Theme selector (1.4.0)
|
|
258
|
+
|
|
259
|
+
`primitives/theme-selector` is a page of appearance settings: light, dark or
|
|
260
|
+
system, then a grid of palettes, each previewing both modes. It owns no
|
|
261
|
+
state: it shows the `palette` and `mode` it is given and reports picks, and
|
|
262
|
+
the app applies and stores them. The palette is a `data-theme` attribute on
|
|
263
|
+
`<html>` and the mode the `.dark` class: two independent axes.
|
|
264
|
+
|
|
265
|
+
```tsx
|
|
266
|
+
import { ThemeSelector, type ThemeSelectorMode } from "@epicbagel/saas-kit/primitives/theme-selector";
|
|
267
|
+
import { NEUTRAL_PALETTE, type ThemePalette } from "@epicbagel/saas-kit/lib/neutral-theme";
|
|
268
|
+
|
|
269
|
+
const PALETTES: ThemePalette[] = [NEUTRAL_PALETTE, ...yourPalettes];
|
|
270
|
+
|
|
271
|
+
export function Appearance() {
|
|
272
|
+
const [palette, setPalette] = useState(NEUTRAL_PALETTE.id);
|
|
273
|
+
const [mode, setMode] = useState<ThemeSelectorMode>("system");
|
|
274
|
+
// Apply them: set `data-theme` on <html> to the palette, and toggle
|
|
275
|
+
// `.dark` for the mode (next-themes does that part for you).
|
|
276
|
+
return (
|
|
277
|
+
<ThemeSelector
|
|
278
|
+
palettes={PALETTES}
|
|
279
|
+
palette={palette}
|
|
280
|
+
onPaletteChange={setPalette}
|
|
281
|
+
mode={mode}
|
|
282
|
+
onModeChange={setMode}
|
|
283
|
+
/>
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
- **Palettes come in.** The selector knows only the kit's neutral palette,
|
|
289
|
+
`NEUTRAL_PALETTE` (`lib/neutral-theme`), which it offers alone when given
|
|
290
|
+
no `palettes`. Its id is `minimal`, the value the stylesheet's default
|
|
291
|
+
already answers to, so storing it changes nothing on screen.
|
|
292
|
+
- **A `ThemePalette`** is an `id` (its `data-theme` value, and what you
|
|
293
|
+
store), a `label`, and optionally a `description`, a `radius` and each
|
|
294
|
+
mode's semantic tokens as hex (`light`, `dark`: the token contract in
|
|
295
|
+
`lib/neutral-theme`). Given the tokens, a preview paints from them inline
|
|
296
|
+
(`paletteStyle`), whatever palette the page is in. Without them it carries
|
|
297
|
+
`data-theme` and `data-mode`, so your palette CSS must select any element
|
|
298
|
+
(`[data-theme="<id>"]`, not `:root[data-theme="<id>"]`), re-declare the
|
|
299
|
+
`--color-*` aliases there (`paletteDeclarations` writes them) and answer
|
|
300
|
+
`[data-mode="light"]` and `[data-mode="dark"]`.
|
|
301
|
+
- **Before the stored pick is known**, pass `null` for `palette` or `mode`:
|
|
302
|
+
nothing is marked rather than the wrong option. Omitted, they default to
|
|
303
|
+
the neutral palette and `system`.
|
|
304
|
+
- **Layout.** One column on a phone (below `sm`). Otherwise the grid
|
|
305
|
+
follows the selector's own width, so the same component fits a dialog and
|
|
306
|
+
a settings page: one column while it is narrower than 24rem, two from
|
|
307
|
+
there, three from 42rem.
|
|
308
|
+
- **Words.** `modeLabel` ("Mode"), `paletteLabel` ("Theme"), `lightLabel`,
|
|
309
|
+
`darkLabel`, `systemLabel`, and optional `modeDescription` and
|
|
310
|
+
`paletteDescription`. Each palette's card is named by its `label` and
|
|
311
|
+
described by its `description`.
|
|
312
|
+
|
|
222
313
|
## License
|
|
223
314
|
|
|
224
315
|
MIT. Some components and styles are adapted from shadcn/ui, and the file
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } }"use client";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkGXHGMI3Zcjs = require('./chunk-GXHGMI3Z.cjs');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
var _chunkKWLSBTB2cjs = require('./chunk-KWLSBTB2.cjs');
|
|
8
|
+
|
|
9
|
+
// src/primitives/toggle-group.tsx
|
|
10
|
+
var _react = require('react'); var React = _interopRequireWildcard(_react);
|
|
11
|
+
var _reacttogglegroup = require('@radix-ui/react-toggle-group'); var ToggleGroupPrimitive = _interopRequireWildcard(_reacttogglegroup);
|
|
12
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
13
|
+
var ToggleGroupContext = React.createContext({
|
|
14
|
+
size: "default",
|
|
15
|
+
variant: "default"
|
|
16
|
+
});
|
|
17
|
+
var ToggleGroup = React.forwardRef(({ className, variant, size, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
18
|
+
ToggleGroupPrimitive.Root,
|
|
19
|
+
{
|
|
20
|
+
ref,
|
|
21
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0, "flex items-center justify-center gap-1", className),
|
|
22
|
+
...props,
|
|
23
|
+
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ToggleGroupContext.Provider, { value: { variant, size }, children })
|
|
24
|
+
}
|
|
25
|
+
));
|
|
26
|
+
ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName;
|
|
27
|
+
var ToggleGroupItem = React.forwardRef(({ className, children, variant, size, grow = false, textSize = "inherit", ...props }, ref) => {
|
|
28
|
+
const context = React.useContext(ToggleGroupContext);
|
|
29
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
30
|
+
ToggleGroupPrimitive.Item,
|
|
31
|
+
{
|
|
32
|
+
ref,
|
|
33
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0,
|
|
34
|
+
_chunkGXHGMI3Zcjs.toggleVariants.call(void 0, {
|
|
35
|
+
variant: context.variant || variant,
|
|
36
|
+
size: context.size || size
|
|
37
|
+
}),
|
|
38
|
+
grow && "flex-1",
|
|
39
|
+
textSize === "xs" && "text-xs",
|
|
40
|
+
className
|
|
41
|
+
),
|
|
42
|
+
...props,
|
|
43
|
+
children
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
exports.ToggleGroup = ToggleGroup; exports.ToggleGroupItem = ToggleGroupItem;
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
// src/lib/neutral-theme.ts
|
|
2
|
+
var SEMANTIC_TOKENS = [
|
|
3
|
+
"background",
|
|
4
|
+
"foreground",
|
|
5
|
+
"card",
|
|
6
|
+
"card-foreground",
|
|
7
|
+
"popover",
|
|
8
|
+
"popover-foreground",
|
|
9
|
+
"primary",
|
|
10
|
+
"primary-foreground",
|
|
11
|
+
"secondary",
|
|
12
|
+
"secondary-foreground",
|
|
13
|
+
"muted",
|
|
14
|
+
"muted-foreground",
|
|
15
|
+
"accent",
|
|
16
|
+
"accent-foreground",
|
|
17
|
+
"destructive",
|
|
18
|
+
"destructive-foreground",
|
|
19
|
+
"border",
|
|
20
|
+
"input",
|
|
21
|
+
"ring",
|
|
22
|
+
"chart-1",
|
|
23
|
+
"chart-2",
|
|
24
|
+
"chart-3",
|
|
25
|
+
"chart-4",
|
|
26
|
+
"chart-5",
|
|
27
|
+
"sidebar-background",
|
|
28
|
+
"sidebar-foreground",
|
|
29
|
+
"sidebar-primary",
|
|
30
|
+
"sidebar-primary-foreground",
|
|
31
|
+
"sidebar-accent",
|
|
32
|
+
"sidebar-accent-foreground",
|
|
33
|
+
"sidebar-border",
|
|
34
|
+
"sidebar-ring"
|
|
35
|
+
];
|
|
36
|
+
function hexToRgb(hex) {
|
|
37
|
+
const h = hex.replace("#", "").trim();
|
|
38
|
+
const full = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
|
|
39
|
+
if (!/^[0-9a-fA-F]{6}$/.test(full)) {
|
|
40
|
+
throw new Error(`Not a hex colour: ${hex}`);
|
|
41
|
+
}
|
|
42
|
+
return [
|
|
43
|
+
parseInt(full.slice(0, 2), 16),
|
|
44
|
+
parseInt(full.slice(2, 4), 16),
|
|
45
|
+
parseInt(full.slice(4, 6), 16)
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
function hexToHsl(hex) {
|
|
49
|
+
const [r255, g255, b255] = hexToRgb(hex);
|
|
50
|
+
const r = r255 / 255;
|
|
51
|
+
const g = g255 / 255;
|
|
52
|
+
const b = b255 / 255;
|
|
53
|
+
const max = Math.max(r, g, b);
|
|
54
|
+
const min = Math.min(r, g, b);
|
|
55
|
+
const l = (max + min) / 2;
|
|
56
|
+
const d = max - min;
|
|
57
|
+
let h = 0;
|
|
58
|
+
let s = 0;
|
|
59
|
+
if (d !== 0) {
|
|
60
|
+
s = d / (1 - Math.abs(2 * l - 1));
|
|
61
|
+
if (max === r) h = (g - b) / d % 6;
|
|
62
|
+
else if (max === g) h = (b - r) / d + 2;
|
|
63
|
+
else h = (r - g) / d + 4;
|
|
64
|
+
h *= 60;
|
|
65
|
+
if (h < 0) h += 360;
|
|
66
|
+
}
|
|
67
|
+
const round = (n) => Math.round(n * 10) / 10;
|
|
68
|
+
return `${round(h)} ${round(s * 100)}% ${round(l * 100)}%`;
|
|
69
|
+
}
|
|
70
|
+
function luminance(hex) {
|
|
71
|
+
const [r, g, b] = hexToRgb(hex).map((v) => {
|
|
72
|
+
const c = v / 255;
|
|
73
|
+
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
74
|
+
});
|
|
75
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
76
|
+
}
|
|
77
|
+
function contrastRatio(a, b) {
|
|
78
|
+
const la = luminance(a);
|
|
79
|
+
const lb = luminance(b);
|
|
80
|
+
const [hi, lo] = la > lb ? [la, lb] : [lb, la];
|
|
81
|
+
return (hi + 0.05) / (lo + 0.05);
|
|
82
|
+
}
|
|
83
|
+
function bestForeground(bg, candidates) {
|
|
84
|
+
let best = candidates[0];
|
|
85
|
+
let bestRatio = 0;
|
|
86
|
+
for (const c of candidates) {
|
|
87
|
+
const ratio = contrastRatio(bg, c);
|
|
88
|
+
if (ratio > bestRatio) {
|
|
89
|
+
best = c;
|
|
90
|
+
bestRatio = ratio;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return best;
|
|
94
|
+
}
|
|
95
|
+
var NEUTRAL_RADIUS = "0rem";
|
|
96
|
+
function neutral(mode) {
|
|
97
|
+
const light = mode === "light";
|
|
98
|
+
const danger = "#d71921";
|
|
99
|
+
const mono = light ? {
|
|
100
|
+
bg: "#ffffff",
|
|
101
|
+
fg: "#000000",
|
|
102
|
+
surface: "#f5f5f5",
|
|
103
|
+
subtle: "#666666",
|
|
104
|
+
border: "#e5e5e5",
|
|
105
|
+
sidebar: "#fafafa",
|
|
106
|
+
strong: "#333333"
|
|
107
|
+
} : {
|
|
108
|
+
bg: "#000000",
|
|
109
|
+
fg: "#ffffff",
|
|
110
|
+
surface: "#1a1a1a",
|
|
111
|
+
subtle: "#999999",
|
|
112
|
+
border: "#333333",
|
|
113
|
+
sidebar: "#0d0d0d",
|
|
114
|
+
strong: "#cccccc"
|
|
115
|
+
};
|
|
116
|
+
return {
|
|
117
|
+
background: mono.bg,
|
|
118
|
+
foreground: mono.fg,
|
|
119
|
+
card: mono.bg,
|
|
120
|
+
"card-foreground": mono.fg,
|
|
121
|
+
popover: mono.bg,
|
|
122
|
+
"popover-foreground": mono.fg,
|
|
123
|
+
primary: mono.fg,
|
|
124
|
+
"primary-foreground": mono.bg,
|
|
125
|
+
secondary: mono.surface,
|
|
126
|
+
"secondary-foreground": mono.fg,
|
|
127
|
+
muted: mono.surface,
|
|
128
|
+
"muted-foreground": mono.subtle,
|
|
129
|
+
accent: mono.surface,
|
|
130
|
+
"accent-foreground": mono.fg,
|
|
131
|
+
destructive: danger,
|
|
132
|
+
"destructive-foreground": bestForeground(danger, ["#ffffff", "#000000"]),
|
|
133
|
+
border: mono.border,
|
|
134
|
+
input: mono.border,
|
|
135
|
+
ring: mono.fg,
|
|
136
|
+
"chart-1": light ? "#333333" : "#cccccc",
|
|
137
|
+
"chart-2": light ? "#4d4d4d" : "#b3b3b3",
|
|
138
|
+
"chart-3": light ? "#666666" : "#999999",
|
|
139
|
+
"chart-4": light ? "#808080" : "#808080",
|
|
140
|
+
"chart-5": light ? "#999999" : "#666666",
|
|
141
|
+
"sidebar-background": mono.sidebar,
|
|
142
|
+
"sidebar-foreground": mono.fg,
|
|
143
|
+
"sidebar-primary": mono.fg,
|
|
144
|
+
"sidebar-primary-foreground": mono.bg,
|
|
145
|
+
"sidebar-accent": mono.surface,
|
|
146
|
+
"sidebar-accent-foreground": mono.fg,
|
|
147
|
+
"sidebar-border": mono.border,
|
|
148
|
+
"sidebar-ring": mono.border
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
var NEUTRAL = {
|
|
152
|
+
light: neutral("light"),
|
|
153
|
+
dark: neutral("dark")
|
|
154
|
+
};
|
|
155
|
+
var NEUTRAL_THEME_ID = "minimal";
|
|
156
|
+
var NEUTRAL_PALETTE = {
|
|
157
|
+
id: NEUTRAL_THEME_ID,
|
|
158
|
+
label: "Neutral",
|
|
159
|
+
description: "Black and white, square corners.",
|
|
160
|
+
radius: NEUTRAL_RADIUS,
|
|
161
|
+
light: NEUTRAL.light,
|
|
162
|
+
dark: NEUTRAL.dark
|
|
163
|
+
};
|
|
164
|
+
function colorAlias(token) {
|
|
165
|
+
if (token.startsWith("chart-")) return null;
|
|
166
|
+
if (token === "sidebar-background") return "--color-sidebar";
|
|
167
|
+
return `--color-${token}`;
|
|
168
|
+
}
|
|
169
|
+
var RADIUS_SCALE = [
|
|
170
|
+
["--radius-sm", "calc(var(--radius) - 4px)"],
|
|
171
|
+
["--radius-md", "calc(var(--radius) - 2px)"],
|
|
172
|
+
["--radius-lg", "var(--radius)"],
|
|
173
|
+
["--radius-xl", "calc(var(--radius) + 4px)"],
|
|
174
|
+
["--radius-2xl", "calc(var(--radius) + 8px)"]
|
|
175
|
+
];
|
|
176
|
+
function paletteDeclarations(tokens, names, radius, { indent = " ", aliasSource = "neutral-theme.ts" } = {}) {
|
|
177
|
+
const value = (token) => {
|
|
178
|
+
const hex = tokens[token];
|
|
179
|
+
if (hex === void 0) throw new Error(`Missing token: ${token}`);
|
|
180
|
+
return hexToHsl(hex);
|
|
181
|
+
};
|
|
182
|
+
const lines = [`${indent}--radius: ${radius};`];
|
|
183
|
+
for (const token of names) {
|
|
184
|
+
lines.push(`${indent}--${token}: ${value(token)};`);
|
|
185
|
+
}
|
|
186
|
+
lines.push(`${indent}--sidebar: ${value("sidebar-background")};`);
|
|
187
|
+
lines.push(`${indent}/* Tailwind-facing aliases \u2014 see ${aliasSource} */`);
|
|
188
|
+
for (const token of names) {
|
|
189
|
+
const alias = colorAlias(token);
|
|
190
|
+
if (alias) lines.push(`${indent}${alias}: hsl(var(--${token}));`);
|
|
191
|
+
}
|
|
192
|
+
for (const [name, scale] of RADIUS_SCALE) {
|
|
193
|
+
lines.push(`${indent}${name}: ${scale};`);
|
|
194
|
+
}
|
|
195
|
+
return lines.join("\n");
|
|
196
|
+
}
|
|
197
|
+
function paletteStyle(tokens, radius, names = SEMANTIC_TOKENS) {
|
|
198
|
+
const value = (token) => {
|
|
199
|
+
const hex = tokens[token];
|
|
200
|
+
if (hex === void 0) throw new Error(`Missing token: ${token}`);
|
|
201
|
+
return hexToHsl(hex);
|
|
202
|
+
};
|
|
203
|
+
const style = {};
|
|
204
|
+
if (radius !== void 0) style["--radius"] = radius;
|
|
205
|
+
for (const token of names) style[`--${token}`] = value(token);
|
|
206
|
+
style["--sidebar"] = value("sidebar-background");
|
|
207
|
+
for (const token of names) {
|
|
208
|
+
const alias = colorAlias(token);
|
|
209
|
+
if (alias) style[alias] = `hsl(var(--${token}))`;
|
|
210
|
+
}
|
|
211
|
+
for (const [name, scale] of RADIUS_SCALE) style[name] = scale;
|
|
212
|
+
return style;
|
|
213
|
+
}
|
|
214
|
+
function paletteBlock(selector, declarations, indent = "") {
|
|
215
|
+
const head = selector.split("\n").map((line) => indent + line).join("\n");
|
|
216
|
+
return `${head} {
|
|
217
|
+
${declarations}
|
|
218
|
+
${indent}}
|
|
219
|
+
`;
|
|
220
|
+
}
|
|
221
|
+
function layerBlock(name, rules) {
|
|
222
|
+
return `@layer ${name} {
|
|
223
|
+
${rules.join("\n")}}
|
|
224
|
+
`;
|
|
225
|
+
}
|
|
226
|
+
var DARK_ROOT_SELECTOR = ":root:where(.dark)";
|
|
227
|
+
function baseLayerPalette(light, dark, indent = " ") {
|
|
228
|
+
return layerBlock("base", [
|
|
229
|
+
paletteBlock(":root", light, indent),
|
|
230
|
+
paletteBlock(DARK_ROOT_SELECTOR, dark, indent)
|
|
231
|
+
]);
|
|
232
|
+
}
|
|
233
|
+
var PALETTE_GENERATED_HEADER = `/* GENERATED FILE \u2014 do not edit.
|
|
234
|
+
* Source: src/lib/neutral-theme.ts \xB7 Regenerate: pnpm gen:themes
|
|
235
|
+
*
|
|
236
|
+
* The neutral palette: light on :root, dark when the root carries the
|
|
237
|
+
* \`.dark\` class. It sits in \`@layer base\`, so any unlayered palette rule
|
|
238
|
+
* or a host's own :root overrides wins on layer order alone. Imported by
|
|
239
|
+
* tokens.css; every --color-* alias and the radius scale are re-declared
|
|
240
|
+
* alongside the tokens they read.
|
|
241
|
+
*/`;
|
|
242
|
+
function renderPaletteCss() {
|
|
243
|
+
const declarations = (mode) => paletteDeclarations(NEUTRAL[mode], SEMANTIC_TOKENS, NEUTRAL_RADIUS, {
|
|
244
|
+
indent: " "
|
|
245
|
+
});
|
|
246
|
+
return [
|
|
247
|
+
PALETTE_GENERATED_HEADER,
|
|
248
|
+
baseLayerPalette(declarations("light"), declarations("dark"))
|
|
249
|
+
].join("\n");
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export {
|
|
253
|
+
SEMANTIC_TOKENS,
|
|
254
|
+
hexToRgb,
|
|
255
|
+
hexToHsl,
|
|
256
|
+
luminance,
|
|
257
|
+
contrastRatio,
|
|
258
|
+
bestForeground,
|
|
259
|
+
NEUTRAL_RADIUS,
|
|
260
|
+
NEUTRAL,
|
|
261
|
+
NEUTRAL_THEME_ID,
|
|
262
|
+
NEUTRAL_PALETTE,
|
|
263
|
+
colorAlias,
|
|
264
|
+
paletteDeclarations,
|
|
265
|
+
paletteStyle,
|
|
266
|
+
paletteBlock,
|
|
267
|
+
layerBlock,
|
|
268
|
+
baseLayerPalette,
|
|
269
|
+
PALETTE_GENERATED_HEADER,
|
|
270
|
+
renderPaletteCss
|
|
271
|
+
};
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import {
|
|
3
|
+
Tooltip,
|
|
4
|
+
TooltipContent,
|
|
5
|
+
TooltipProvider,
|
|
6
|
+
TooltipTrigger
|
|
7
|
+
} from "./chunk-ZRLUUZHK.js";
|
|
8
|
+
import {
|
|
9
|
+
Button
|
|
10
|
+
} from "./chunk-HQRWRRZJ.js";
|
|
2
11
|
import {
|
|
3
12
|
cn
|
|
4
13
|
} from "./chunk-G6SRSWXB.js";
|
|
5
14
|
|
|
6
15
|
// src/primitives/message.tsx
|
|
7
|
-
import
|
|
16
|
+
import * as React from "react";
|
|
17
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
18
|
function MessageGroup({ className, ...props }) {
|
|
9
19
|
return /* @__PURE__ */ jsx(
|
|
10
20
|
"div",
|
|
@@ -85,6 +95,53 @@ function MessageFooter({ className, ...props }) {
|
|
|
85
95
|
}
|
|
86
96
|
);
|
|
87
97
|
}
|
|
98
|
+
function MessageActions({ className, ...props }) {
|
|
99
|
+
return /* @__PURE__ */ jsx(
|
|
100
|
+
"div",
|
|
101
|
+
{
|
|
102
|
+
"data-slot": "message-actions",
|
|
103
|
+
className: cn(
|
|
104
|
+
"cn-message-actions flex max-w-full min-w-0 items-center gap-0.5 text-muted-foreground empty:hidden group-data-[align=end]/message:justify-end",
|
|
105
|
+
className
|
|
106
|
+
),
|
|
107
|
+
...props
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
var MessageAction = React.forwardRef(
|
|
112
|
+
function MessageAction2({
|
|
113
|
+
tooltip,
|
|
114
|
+
label,
|
|
115
|
+
side = "bottom",
|
|
116
|
+
variant = "quiet",
|
|
117
|
+
type = "button",
|
|
118
|
+
className,
|
|
119
|
+
children,
|
|
120
|
+
...props
|
|
121
|
+
}, ref) {
|
|
122
|
+
const name = label ?? (typeof tooltip === "string" ? tooltip : void 0);
|
|
123
|
+
return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
124
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
125
|
+
Button,
|
|
126
|
+
{
|
|
127
|
+
ref,
|
|
128
|
+
type,
|
|
129
|
+
variant,
|
|
130
|
+
size: "icon-compact",
|
|
131
|
+
"aria-label": name,
|
|
132
|
+
"data-slot": "message-action",
|
|
133
|
+
className: cn(
|
|
134
|
+
"cn-message-action size-8 shrink-0 rounded-full pointer-coarse:size-11",
|
|
135
|
+
className
|
|
136
|
+
),
|
|
137
|
+
...props,
|
|
138
|
+
children
|
|
139
|
+
}
|
|
140
|
+
) }),
|
|
141
|
+
/* @__PURE__ */ jsx(TooltipContent, { side, children: tooltip })
|
|
142
|
+
] }) });
|
|
143
|
+
}
|
|
144
|
+
);
|
|
88
145
|
|
|
89
146
|
export {
|
|
90
147
|
MessageGroup,
|
|
@@ -92,5 +149,7 @@ export {
|
|
|
92
149
|
MessageAvatar,
|
|
93
150
|
MessageContent,
|
|
94
151
|
MessageHeader,
|
|
95
|
-
MessageFooter
|
|
152
|
+
MessageFooter,
|
|
153
|
+
MessageActions,
|
|
154
|
+
MessageAction
|
|
96
155
|
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } }"use client";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkKWLSBTB2cjs = require('./chunk-KWLSBTB2.cjs');
|
|
5
|
+
|
|
6
|
+
// src/primitives/radio-group.tsx
|
|
7
|
+
var _reactradiogroup = require('@radix-ui/react-radio-group'); var RadioGroupPrimitive = _interopRequireWildcard(_reactradiogroup);
|
|
8
|
+
var _react = require('react'); var React = _interopRequireWildcard(_react);
|
|
9
|
+
var _lucidereact = require('lucide-react');
|
|
10
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
11
|
+
var RadioGroup = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
12
|
+
RadioGroupPrimitive.Root,
|
|
13
|
+
{
|
|
14
|
+
ref,
|
|
15
|
+
"data-slot": "radio-group",
|
|
16
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0, "grid gap-3", className),
|
|
17
|
+
...props
|
|
18
|
+
}
|
|
19
|
+
));
|
|
20
|
+
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
|
|
21
|
+
var RadioGroupItem = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
22
|
+
RadioGroupPrimitive.Item,
|
|
23
|
+
{
|
|
24
|
+
ref,
|
|
25
|
+
"data-slot": "radio-group-item",
|
|
26
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0,
|
|
27
|
+
"aspect-square size-4 shrink-0 rounded-full border border-input text-primary shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 dark:aria-invalid:ring-destructive/40",
|
|
28
|
+
className
|
|
29
|
+
),
|
|
30
|
+
...props,
|
|
31
|
+
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
32
|
+
RadioGroupPrimitive.Indicator,
|
|
33
|
+
{
|
|
34
|
+
"data-slot": "radio-group-indicator",
|
|
35
|
+
className: "relative flex items-center justify-center",
|
|
36
|
+
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.CircleIcon, { className: "absolute left-1/2 top-1/2 size-2 -translate-x-1/2 -translate-y-1/2 fill-primary" })
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
));
|
|
41
|
+
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
exports.RadioGroup = RadioGroup; exports.RadioGroupItem = RadioGroupItem;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
cn
|
|
4
|
+
} from "./chunk-G6SRSWXB.js";
|
|
5
|
+
|
|
6
|
+
// src/primitives/radio-group.tsx
|
|
7
|
+
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
|
|
8
|
+
import * as React from "react";
|
|
9
|
+
import { CircleIcon } from "lucide-react";
|
|
10
|
+
import { jsx } from "react/jsx-runtime";
|
|
11
|
+
var RadioGroup = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
12
|
+
RadioGroupPrimitive.Root,
|
|
13
|
+
{
|
|
14
|
+
ref,
|
|
15
|
+
"data-slot": "radio-group",
|
|
16
|
+
className: cn("grid gap-3", className),
|
|
17
|
+
...props
|
|
18
|
+
}
|
|
19
|
+
));
|
|
20
|
+
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
|
|
21
|
+
var RadioGroupItem = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
22
|
+
RadioGroupPrimitive.Item,
|
|
23
|
+
{
|
|
24
|
+
ref,
|
|
25
|
+
"data-slot": "radio-group-item",
|
|
26
|
+
className: cn(
|
|
27
|
+
"aspect-square size-4 shrink-0 rounded-full border border-input text-primary shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 dark:aria-invalid:ring-destructive/40",
|
|
28
|
+
className
|
|
29
|
+
),
|
|
30
|
+
...props,
|
|
31
|
+
children: /* @__PURE__ */ jsx(
|
|
32
|
+
RadioGroupPrimitive.Indicator,
|
|
33
|
+
{
|
|
34
|
+
"data-slot": "radio-group-indicator",
|
|
35
|
+
className: "relative flex items-center justify-center",
|
|
36
|
+
children: /* @__PURE__ */ jsx(CircleIcon, { className: "absolute left-1/2 top-1/2 size-2 -translate-x-1/2 -translate-y-1/2 fill-primary" })
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
));
|
|
41
|
+
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
RadioGroup,
|
|
45
|
+
RadioGroupItem
|
|
46
|
+
};
|
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }"use client";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
var _chunkU2NES7VRcjs = require('./chunk-U2NES7VR.cjs');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
var _chunkL4DH72UFcjs = require('./chunk-L4DH72UF.cjs');
|
|
2
11
|
|
|
3
12
|
|
|
4
13
|
var _chunkKWLSBTB2cjs = require('./chunk-KWLSBTB2.cjs');
|
|
5
14
|
|
|
6
15
|
// src/primitives/message.tsx
|
|
16
|
+
var _react = require('react'); var React = _interopRequireWildcard(_react);
|
|
7
17
|
var _jsxruntime = require('react/jsx-runtime');
|
|
8
18
|
function MessageGroup({ className, ...props }) {
|
|
9
19
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
@@ -85,6 +95,55 @@ function MessageFooter({ className, ...props }) {
|
|
|
85
95
|
}
|
|
86
96
|
);
|
|
87
97
|
}
|
|
98
|
+
function MessageActions({ className, ...props }) {
|
|
99
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
100
|
+
"div",
|
|
101
|
+
{
|
|
102
|
+
"data-slot": "message-actions",
|
|
103
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0,
|
|
104
|
+
"cn-message-actions flex max-w-full min-w-0 items-center gap-0.5 text-muted-foreground empty:hidden group-data-[align=end]/message:justify-end",
|
|
105
|
+
className
|
|
106
|
+
),
|
|
107
|
+
...props
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
var MessageAction = React.forwardRef(
|
|
112
|
+
function MessageAction2({
|
|
113
|
+
tooltip,
|
|
114
|
+
label,
|
|
115
|
+
side = "bottom",
|
|
116
|
+
variant = "quiet",
|
|
117
|
+
type = "button",
|
|
118
|
+
className,
|
|
119
|
+
children,
|
|
120
|
+
...props
|
|
121
|
+
}, ref) {
|
|
122
|
+
const name = _nullishCoalesce(label, () => ( (typeof tooltip === "string" ? tooltip : void 0)));
|
|
123
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkU2NES7VRcjs.TooltipProvider, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkU2NES7VRcjs.Tooltip, { children: [
|
|
124
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkU2NES7VRcjs.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
125
|
+
_chunkL4DH72UFcjs.Button,
|
|
126
|
+
{
|
|
127
|
+
ref,
|
|
128
|
+
type,
|
|
129
|
+
variant,
|
|
130
|
+
size: "icon-compact",
|
|
131
|
+
"aria-label": name,
|
|
132
|
+
"data-slot": "message-action",
|
|
133
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0,
|
|
134
|
+
"cn-message-action size-8 shrink-0 rounded-full pointer-coarse:size-11",
|
|
135
|
+
className
|
|
136
|
+
),
|
|
137
|
+
...props,
|
|
138
|
+
children
|
|
139
|
+
}
|
|
140
|
+
) }),
|
|
141
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkU2NES7VRcjs.TooltipContent, { side, children: tooltip })
|
|
142
|
+
] }) });
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
|
|
88
147
|
|
|
89
148
|
|
|
90
149
|
|
|
@@ -93,4 +152,4 @@ function MessageFooter({ className, ...props }) {
|
|
|
93
152
|
|
|
94
153
|
|
|
95
154
|
|
|
96
|
-
exports.MessageGroup = MessageGroup; exports.Message = Message; exports.MessageAvatar = MessageAvatar; exports.MessageContent = MessageContent; exports.MessageHeader = MessageHeader; exports.MessageFooter = MessageFooter;
|
|
155
|
+
exports.MessageGroup = MessageGroup; exports.Message = Message; exports.MessageAvatar = MessageAvatar; exports.MessageContent = MessageContent; exports.MessageHeader = MessageHeader; exports.MessageFooter = MessageFooter; exports.MessageActions = MessageActions; exports.MessageAction = MessageAction;
|