raft-ui 0.0.1

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.
Files changed (134) hide show
  1. package/README.md +24 -0
  2. package/dist/cn.d.mts +2 -0
  3. package/dist/cn.mjs +2 -0
  4. package/dist/index.d.mts +2710 -0
  5. package/dist/index.mjs +4821 -0
  6. package/dist/label-DWq4ia5I.mjs +115 -0
  7. package/dist/styled-props-B3SNekJg.d.mts +16 -0
  8. package/dist/wip.d.mts +1238 -0
  9. package/dist/wip.mjs +1416 -0
  10. package/package.json +70 -0
  11. package/src/components/avatar/avatar.tsx +375 -0
  12. package/src/components/avatar/index.ts +17 -0
  13. package/src/components/badge/badge.tsx +393 -0
  14. package/src/components/badge/index.ts +2 -0
  15. package/src/components/banner/banner.tsx +269 -0
  16. package/src/components/banner/index.ts +8 -0
  17. package/src/components/bottom-sheet/bottom-sheet.tsx +152 -0
  18. package/src/components/bottom-sheet/index.ts +22 -0
  19. package/src/components/button/button.tsx +497 -0
  20. package/src/components/button/index.ts +2 -0
  21. package/src/components/checkbox/checkbox-indicator.tsx +128 -0
  22. package/src/components/checkbox/checkbox.tsx +350 -0
  23. package/src/components/checkbox/index.ts +2 -0
  24. package/src/components/combobox/combobox.tsx +603 -0
  25. package/src/components/combobox/index.ts +52 -0
  26. package/src/components/context-menu/context-menu.tsx +380 -0
  27. package/src/components/context-menu/index.ts +34 -0
  28. package/src/components/conversation-preview-card/conversation-preview-card.tsx +336 -0
  29. package/src/components/conversation-preview-card/index.ts +32 -0
  30. package/src/components/description-list/description-list.tsx +116 -0
  31. package/src/components/description-list/index.ts +14 -0
  32. package/src/components/dropdown-menu/dropdown-menu.tsx +405 -0
  33. package/src/components/dropdown-menu/index.ts +38 -0
  34. package/src/components/empty-state/empty-state.tsx +177 -0
  35. package/src/components/empty-state/index.ts +16 -0
  36. package/src/components/field/field.tsx +125 -0
  37. package/src/components/field/index.ts +18 -0
  38. package/src/components/inline-code/index.ts +2 -0
  39. package/src/components/inline-code/inline-code.tsx +33 -0
  40. package/src/components/input/index.ts +2 -0
  41. package/src/components/input/input.tsx +76 -0
  42. package/src/components/input-group/index.ts +7 -0
  43. package/src/components/input-group/input-group.tsx +215 -0
  44. package/src/components/kbd/index.ts +2 -0
  45. package/src/components/kbd/kbd.tsx +43 -0
  46. package/src/components/label/index.ts +7 -0
  47. package/src/components/label/label.tsx +99 -0
  48. package/src/components/lightbox/index.ts +24 -0
  49. package/src/components/lightbox/lightbox.tsx +245 -0
  50. package/src/components/list-item/index.ts +20 -0
  51. package/src/components/list-item/list-item.tsx +263 -0
  52. package/src/components/media-list-item/index.ts +20 -0
  53. package/src/components/media-list-item/media-list-item.tsx +169 -0
  54. package/src/components/notification-center/index.ts +39 -0
  55. package/src/components/notification-center/notification-center.tsx +558 -0
  56. package/src/components/panel-header/index.ts +22 -0
  57. package/src/components/panel-header/panel-header.tsx +199 -0
  58. package/src/components/popover/index.ts +30 -0
  59. package/src/components/popover/popover.tsx +248 -0
  60. package/src/components/preview-shell/index.ts +2 -0
  61. package/src/components/preview-shell/preview-shell.tsx +51 -0
  62. package/src/components/quoted-message-card/index.ts +36 -0
  63. package/src/components/quoted-message-card/quoted-message-card.tsx +391 -0
  64. package/src/components/radio-group/index.ts +6 -0
  65. package/src/components/radio-group/radio-group.tsx +119 -0
  66. package/src/components/section-header/index.ts +16 -0
  67. package/src/components/section-header/section-header.tsx +117 -0
  68. package/src/components/section-label/index.ts +2 -0
  69. package/src/components/section-label/section-label.tsx +38 -0
  70. package/src/components/segmented-control/index.ts +12 -0
  71. package/src/components/segmented-control/segmented-control.tsx +129 -0
  72. package/src/components/select/index.ts +40 -0
  73. package/src/components/select/select.tsx +382 -0
  74. package/src/components/spinner/index.ts +2 -0
  75. package/src/components/spinner/spinner.tsx +228 -0
  76. package/src/components/status/index.ts +2 -0
  77. package/src/components/status/status.tsx +152 -0
  78. package/src/components/tabs/index.ts +24 -0
  79. package/src/components/tabs/tabs.tsx +417 -0
  80. package/src/components/text/index.ts +2 -0
  81. package/src/components/text/text.tsx +130 -0
  82. package/src/components/textarea/index.ts +2 -0
  83. package/src/components/textarea/textarea.tsx +136 -0
  84. package/src/components/toggle-group/index.ts +12 -0
  85. package/src/components/toggle-group/toggle-group.tsx +111 -0
  86. package/src/components/tooltip/index.ts +14 -0
  87. package/src/components/tooltip/tooltip.tsx +186 -0
  88. package/src/fonts/brutal.css +2 -0
  89. package/src/index.ts +404 -0
  90. package/src/legacy/AttentionDot.tsx +28 -0
  91. package/src/legacy/AvatarListRow.tsx +87 -0
  92. package/src/legacy/AvatarSlot.tsx +157 -0
  93. package/src/legacy/Badge.tsx +95 -0
  94. package/src/legacy/Banner.tsx +74 -0
  95. package/src/legacy/BottomSheet.tsx +76 -0
  96. package/src/legacy/CheckMarker.tsx +72 -0
  97. package/src/legacy/Checkbox.tsx +81 -0
  98. package/src/legacy/ConversationPreviewCard.tsx +169 -0
  99. package/src/legacy/DismissBackdrop.tsx +68 -0
  100. package/src/legacy/EmptyState.tsx +63 -0
  101. package/src/legacy/ExperimentalBadge.tsx +19 -0
  102. package/src/legacy/FormField.tsx +106 -0
  103. package/src/legacy/KeyValueRow.tsx +67 -0
  104. package/src/legacy/Lightbox.tsx +119 -0
  105. package/src/legacy/NotificationCenter.tsx +217 -0
  106. package/src/legacy/PanelHeader.tsx +94 -0
  107. package/src/legacy/PreviewShell.tsx +40 -0
  108. package/src/legacy/QuotedMessageCard.tsx +181 -0
  109. package/src/legacy/ReorderablePanelTabs.tsx +151 -0
  110. package/src/legacy/SandboxedPreviewFrame.tsx +59 -0
  111. package/src/legacy/SearchInput.tsx +23 -0
  112. package/src/legacy/SectionEyebrow.tsx +60 -0
  113. package/src/legacy/SectionHeader.tsx +68 -0
  114. package/src/legacy/SegmentedControl.tsx +74 -0
  115. package/src/legacy/SlugInput.tsx +29 -0
  116. package/src/legacy/Spinner.tsx +89 -0
  117. package/src/legacy/StatusDot.tsx +51 -0
  118. package/src/legacy/SurfaceListItem.tsx +32 -0
  119. package/src/legacy/Textarea.tsx +137 -0
  120. package/src/legacy/button.tsx +100 -0
  121. package/src/legacy/context-menu-divider.tsx +12 -0
  122. package/src/legacy/menu-item.tsx +66 -0
  123. package/src/legacy/selection-popover.tsx +212 -0
  124. package/src/legacy/server-switcher-menu.tsx +203 -0
  125. package/src/legacy/source.css +240 -0
  126. package/src/lib/cn.ts +1 -0
  127. package/src/lib/styled-props.ts +11 -0
  128. package/src/lib/theme/theme-context.ts +28 -0
  129. package/src/lib/theme/theme-provider.tsx +181 -0
  130. package/src/lib/theme/use-theme.ts +12 -0
  131. package/src/lib/tv.ts +29 -0
  132. package/src/lib/without-children.ts +6 -0
  133. package/src/styles.css +467 -0
  134. package/src/wip.ts +255 -0
package/dist/wip.mjs ADDED
@@ -0,0 +1,1416 @@
1
+ import { l as tv, n as LabelAsterisk, o as useThemeFamily, r as LabelOptional } from "./label-DWq4ia5I.mjs";
2
+ import { cn } from "./cn.mjs";
3
+ import { Button } from "@base-ui/react/button";
4
+ import { useCallback, useRef, useState } from "react";
5
+ import { mergeProps } from "@base-ui/react/merge-props";
6
+ import { useRender } from "@base-ui/react/use-render";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ import { MessageSquare } from "lucide-react";
9
+ import { Field as Field$1 } from "@base-ui/react/field";
10
+ import { Toggle } from "@base-ui/react/toggle";
11
+ import { ToggleGroup as ToggleGroup$1 } from "@base-ui/react/toggle-group";
12
+ import { Dialog } from "@base-ui/react/dialog";
13
+ import { useHotkey } from "@tanstack/react-hotkeys";
14
+ //#region src/components/field/field.tsx
15
+ const field = tv({
16
+ slots: {
17
+ root: ["group/field flex flex-col gap-1.5"],
18
+ item: ["group/field-item flex items-start gap-2", "[&>[data-slot=checkbox]]:mt-px"],
19
+ label: ["block leading-none", "group-data-[disabled]/field:text-foreground-disabled"],
20
+ description: ["text-xs leading-5", "group-data-[disabled]/field:text-foreground-disabled"],
21
+ error: ["text-xs leading-5", "group-data-[disabled]/field:text-foreground-disabled"]
22
+ },
23
+ variants: {
24
+ theme: {
25
+ brutal: {
26
+ root: ["gap-1"],
27
+ label: ["font-bold text-foreground-strong"],
28
+ description: ["text-foreground/50"],
29
+ error: ["text-danger-base"]
30
+ },
31
+ elegant: {
32
+ label: ["font-medium text-foreground"],
33
+ description: ["text-[13px] text-[oklch(0.48_0_0)] dark:text-[oklch(0.76_0_0)]", "group-data-[disabled]/field:text-foreground-disabled"],
34
+ error: ["text-[13px] text-danger-base"]
35
+ }
36
+ },
37
+ size: {
38
+ sm: { label: "text-xs" },
39
+ md: { label: "text-sm" }
40
+ }
41
+ },
42
+ compoundVariants: [{
43
+ theme: "brutal",
44
+ size: "sm",
45
+ class: { label: "text-foreground/60" }
46
+ }],
47
+ defaultVariants: { size: "md" }
48
+ });
49
+ function Field({ className, ...props }) {
50
+ const { root } = field({ theme: useThemeFamily() });
51
+ return /* @__PURE__ */ jsx(Field$1.Root, {
52
+ "data-slot": "field",
53
+ className: root({ className }),
54
+ ...props
55
+ });
56
+ }
57
+ function FieldItem({ className, ...props }) {
58
+ const { item } = field({ theme: useThemeFamily() });
59
+ return /* @__PURE__ */ jsx(Field$1.Item, {
60
+ "data-slot": "field-item",
61
+ className: item({ className }),
62
+ ...props
63
+ });
64
+ }
65
+ function FieldLabel({ size, required, optional, className, children, ...props }) {
66
+ const { label } = field({
67
+ theme: useThemeFamily(),
68
+ size
69
+ });
70
+ return /* @__PURE__ */ jsxs(Field$1.Label, {
71
+ "data-slot": "field-label",
72
+ className: label({ className }),
73
+ ...props,
74
+ children: [
75
+ children,
76
+ required ? /* @__PURE__ */ jsx(LabelAsterisk, { className: "ml-1" }) : null,
77
+ optional ? /* @__PURE__ */ jsx(LabelOptional, { className: "ml-1" }) : null
78
+ ]
79
+ });
80
+ }
81
+ function FieldDescription({ className, ...props }) {
82
+ const { description } = field({ theme: useThemeFamily() });
83
+ return /* @__PURE__ */ jsx(Field$1.Description, {
84
+ "data-slot": "field-description",
85
+ className: description({ className }),
86
+ ...props
87
+ });
88
+ }
89
+ function FieldError({ className, role = "alert", ...props }) {
90
+ const { error } = field({ theme: useThemeFamily() });
91
+ return /* @__PURE__ */ jsx(Field$1.Error, {
92
+ "data-slot": "field-error",
93
+ role,
94
+ className: error({ className }),
95
+ ...props
96
+ });
97
+ }
98
+ function FieldControl(props) {
99
+ return /* @__PURE__ */ jsx(Field$1.Control, {
100
+ "data-slot": "field-control",
101
+ ...props
102
+ });
103
+ }
104
+ function FieldValidity(props) {
105
+ return /* @__PURE__ */ jsx(Field$1.Validity, { ...props });
106
+ }
107
+ //#endregion
108
+ //#region src/components/text/text.tsx
109
+ const textColorVariants = {
110
+ default: ["text-foreground-strong"],
111
+ primary: ["text-primary-700"],
112
+ information: ["text-info-dark"],
113
+ muted: ["text-foreground-muted"],
114
+ accent: ["text-accent-700"],
115
+ success: ["text-success-base"],
116
+ warning: ["text-warning-base"],
117
+ danger: ["text-danger-base"]
118
+ };
119
+ const heading = tv({
120
+ base: ["m-0 font-heading font-medium text-foreground-strong"],
121
+ variants: {
122
+ level: {
123
+ 1: ["text-[3.5rem] tracking-[-0.01em] leading-[64px]"],
124
+ 2: ["text-[3rem] tracking-[-0.01em] leading-[56px]"],
125
+ 3: ["text-[2.5rem] tracking-[-0.01em] leading-[48px]"],
126
+ 4: ["text-[2rem] tracking-[-0.005em] leading-[40px]"],
127
+ 5: ["text-[1.5rem] leading-8"],
128
+ 6: ["text-[1.25rem] leading-7"]
129
+ },
130
+ variant: textColorVariants
131
+ },
132
+ defaultVariants: { level: 1 }
133
+ });
134
+ const sans = tv({
135
+ base: ["m-0 font-sans font-normal"],
136
+ variants: {
137
+ size: {
138
+ large: ["text-lg leading-7 text-foreground"],
139
+ body: ["text-base leading-6 text-foreground"],
140
+ small: ["text-sm leading-5 text-foreground-muted"],
141
+ caption: ["text-xs leading-4 text-foreground-muted"]
142
+ },
143
+ variant: textColorVariants
144
+ },
145
+ defaultVariants: { size: "body" }
146
+ });
147
+ const mono = tv({
148
+ base: ["m-0 font-mono font-normal"],
149
+ variants: {
150
+ size: {
151
+ code: ["text-sm leading-5 text-foreground"],
152
+ meta: ["text-xs leading-4 text-foreground-muted"],
153
+ eyebrow: ["text-[10px] font-medium uppercase tracking-wide leading-none", "text-foreground-placeholder"],
154
+ tabular: ["text-sm tabular-nums leading-5 text-foreground"]
155
+ },
156
+ variant: textColorVariants
157
+ },
158
+ defaultVariants: { size: "code" }
159
+ });
160
+ function TextHeading({ level = 1, variant, className, render, ...props }) {
161
+ const defaultProps = { className: heading({
162
+ level,
163
+ variant,
164
+ className
165
+ }) };
166
+ return useRender({
167
+ defaultTagName: `h${level}`,
168
+ render,
169
+ props: mergeProps(defaultProps, props),
170
+ state: {
171
+ slot: "text-heading",
172
+ level,
173
+ variant
174
+ }
175
+ });
176
+ }
177
+ function TextSans({ size = "body", variant, className, render, ...props }) {
178
+ return useRender({
179
+ defaultTagName: "p",
180
+ render,
181
+ props: mergeProps({ className: sans({
182
+ size,
183
+ variant,
184
+ className
185
+ }) }, props),
186
+ state: {
187
+ slot: "text-sans",
188
+ size,
189
+ variant
190
+ }
191
+ });
192
+ }
193
+ function TextMono({ size = "code", variant, className, render, ...props }) {
194
+ return useRender({
195
+ defaultTagName: "p",
196
+ render,
197
+ props: mergeProps({ className: mono({
198
+ size,
199
+ variant,
200
+ className
201
+ }) }, props),
202
+ state: {
203
+ slot: "text-mono",
204
+ size,
205
+ variant
206
+ }
207
+ });
208
+ }
209
+ const Text = {
210
+ Heading: TextHeading,
211
+ Sans: TextSans,
212
+ Mono: TextMono
213
+ };
214
+ //#endregion
215
+ //#region src/components/toggle-group/toggle-group.tsx
216
+ const toggleGroup = tv({
217
+ slots: {
218
+ root: ["inline-flex max-w-full flex-wrap items-center gap-1"],
219
+ item: [
220
+ "flex h-7 min-w-0 shrink-0 items-center gap-1 px-2",
221
+ "text-xs font-bold transition-colors",
222
+ "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5"
223
+ ],
224
+ label: ["truncate"],
225
+ count: ["font-mono text-[10px] leading-none"]
226
+ },
227
+ variants: {
228
+ theme: {
229
+ brutal: {
230
+ item: [
231
+ "border-2 border-line-strong bg-layer-panel text-foreground-strong",
232
+ "hover:bg-primary-400/30 data-[pressed]:bg-primary-400 data-[pressed]:text-foreground-strong",
233
+ "data-[pressed]:shadow-sm data-[disabled]:cursor-not-allowed"
234
+ ],
235
+ count: ["text-foreground/40", "group-data-[pressed]/toggle-group-item:text-foreground/60"]
236
+ },
237
+ elegant: {}
238
+ },
239
+ disabled: {
240
+ true: { root: "opacity-50" },
241
+ false: { root: "" }
242
+ }
243
+ },
244
+ defaultVariants: { disabled: false }
245
+ });
246
+ function ToggleGroup({ value, onValueChange, ariaLabel, disabled = false, className, ...props }) {
247
+ const { root } = toggleGroup({ disabled });
248
+ return /* @__PURE__ */ jsx(ToggleGroup$1, {
249
+ value: [value],
250
+ onValueChange: (nextValue, eventDetails) => {
251
+ const selectedValue = nextValue[0];
252
+ if (selectedValue) onValueChange(selectedValue, eventDetails);
253
+ },
254
+ "aria-label": ariaLabel,
255
+ disabled,
256
+ "data-slot": "toggle-group",
257
+ className: root({ className }),
258
+ ...props
259
+ });
260
+ }
261
+ function ToggleGroupItem({ className, ...props }) {
262
+ const { item } = toggleGroup({ theme: useThemeFamily() });
263
+ return /* @__PURE__ */ jsx(Toggle, {
264
+ type: "button",
265
+ "data-slot": "toggle-group-item",
266
+ className: item({ className: `group/toggle-group-item ${className ?? ""}`.trim() }),
267
+ ...props
268
+ });
269
+ }
270
+ function ToggleGroupLabel({ className, ...props }) {
271
+ const { label } = toggleGroup();
272
+ return /* @__PURE__ */ jsx("span", {
273
+ "data-slot": "toggle-group-label",
274
+ className: label({ className }),
275
+ ...props
276
+ });
277
+ }
278
+ function ToggleGroupCount({ className, ...props }) {
279
+ const { count } = toggleGroup({ theme: useThemeFamily() });
280
+ return /* @__PURE__ */ jsx("span", {
281
+ "data-slot": "toggle-group-count",
282
+ className: count({ className }),
283
+ ...props
284
+ });
285
+ }
286
+ //#endregion
287
+ //#region src/components/preview-shell/preview-shell.tsx
288
+ const previewShell = tv({
289
+ slots: { root: [] },
290
+ variants: {
291
+ theme: {
292
+ brutal: {},
293
+ elegant: {}
294
+ },
295
+ variant: {
296
+ default: { root: "border border-line-muted bg-layer-panel hover:border-line-subtle hover:bg-layer-muted" },
297
+ muted: { root: "border-2 border-line-subtle bg-layer-muted italic text-foreground/40 hover:shadow-sm" }
298
+ }
299
+ },
300
+ defaultVariants: { variant: "default" }
301
+ });
302
+ function PreviewShell({ variant, className, render, ...props }) {
303
+ const { root } = previewShell({
304
+ theme: useThemeFamily(),
305
+ variant
306
+ });
307
+ return useRender({
308
+ defaultTagName: "div",
309
+ render,
310
+ props: mergeProps({ className: root({ className }) }, props),
311
+ state: {
312
+ slot: "preview-shell",
313
+ variant
314
+ }
315
+ });
316
+ }
317
+ //#endregion
318
+ //#region src/components/list-item/list-item.tsx
319
+ const listItem = tv({
320
+ slots: {
321
+ root: ["px-4 py-3 transition-colors"],
322
+ body: [
323
+ "min-w-0",
324
+ "grid grid-cols-[minmax(0,1fr)]",
325
+ "has-[>[data-slot=list-item-icon]]:grid-cols-[auto_minmax(0,1fr)]",
326
+ "has-[>[data-slot=list-item-icon]]:items-start",
327
+ "has-[>[data-slot=list-item-icon]]:gap-x-2",
328
+ "has-[>[data-slot=list-item-icon]]:[&>[data-slot=list-item-icon]]:col-start-1",
329
+ "has-[>[data-slot=list-item-icon]]:[&>[data-slot=list-item-icon]]:row-start-1",
330
+ "has-[>[data-slot=list-item-icon]]:[&>[data-slot=list-item-row]]:col-start-2",
331
+ "has-[>[data-slot=list-item-icon]]:[&>[data-slot=list-item-description]]:col-span-2",
332
+ "has-[>[data-slot=list-item-icon]]:[&>[data-slot=list-item-description]]:col-start-1",
333
+ "has-[>[data-slot=list-item-icon]]:[&>[data-slot=list-item-description]]:row-start-2",
334
+ "has-[>[data-slot=list-item-icon]]:[&>[data-slot=list-item-meta]]:col-start-2",
335
+ "has-[>[data-slot=list-item-icon]]:[&>[data-slot=list-item-action-group]]:col-start-2"
336
+ ],
337
+ icon: ["shrink-0 self-start", "[&_svg]:size-3.5 [&_svg]:shrink-0"],
338
+ row: ["flex min-w-0 flex-wrap items-center gap-2", "[&_svg]:size-3.5 [&_svg]:shrink-0"],
339
+ title: ["break-words text-sm font-bold"],
340
+ description: ["mt-1 text-xs"],
341
+ meta: ["mt-1 flex min-w-0 flex-wrap items-center gap-2 text-xs", "[&_svg]:size-3 [&_svg]:shrink-0"],
342
+ actionGroup: ["mt-2 flex flex-wrap items-center gap-2", "[&_svg]:size-3 [&_svg]:shrink-0"]
343
+ },
344
+ variants: {
345
+ theme: {
346
+ brutal: {
347
+ root: ["border-2"],
348
+ icon: ["mt-0.5 text-foreground/50"],
349
+ title: "text-foreground-strong",
350
+ description: "text-foreground/60",
351
+ meta: "text-foreground/50"
352
+ },
353
+ elegant: {
354
+ root: [
355
+ "rounded-sm border",
356
+ "border-line-muted bg-layer-panel",
357
+ "outline-none",
358
+ "transition-[background-color,border-color] duration-150",
359
+ "focus-visible:ring-2 focus-visible:ring-line-focus"
360
+ ],
361
+ icon: ["mt-0.5 text-foreground-muted"],
362
+ row: ["items-center gap-2"],
363
+ title: ["text-sm font-medium leading-snug tracking-[-0.005em]", "text-foreground-strong"],
364
+ description: ["mt-1 text-[0.8125rem] font-normal leading-normal", "text-foreground-muted"],
365
+ meta: ["text-foreground-muted"],
366
+ actionGroup: ["mt-2 gap-2"]
367
+ }
368
+ },
369
+ selected: {
370
+ true: { root: "" },
371
+ false: { root: "" }
372
+ },
373
+ interactive: {
374
+ true: { root: "" },
375
+ false: { root: "" }
376
+ }
377
+ },
378
+ compoundVariants: [
379
+ {
380
+ theme: "brutal",
381
+ selected: true,
382
+ class: { root: "border-line-strong bg-info-base/15 shadow-sm" }
383
+ },
384
+ {
385
+ theme: "brutal",
386
+ selected: false,
387
+ class: { root: "border-line-subtle bg-layer-panel" }
388
+ },
389
+ {
390
+ theme: "brutal",
391
+ selected: false,
392
+ interactive: true,
393
+ class: { root: "hover:border-line-strong hover:shadow-sm" }
394
+ },
395
+ {
396
+ theme: "elegant",
397
+ selected: true,
398
+ class: { root: ["border-info-light", "bg-info-lighter"] }
399
+ },
400
+ {
401
+ theme: "elegant",
402
+ selected: false,
403
+ interactive: true,
404
+ class: { root: "hover:bg-layer-muted" }
405
+ }
406
+ ],
407
+ defaultVariants: {
408
+ selected: false,
409
+ interactive: true
410
+ }
411
+ });
412
+ function ListItem({ selected, interactive, className, render, ...props }) {
413
+ const { root } = listItem({
414
+ theme: useThemeFamily(),
415
+ selected,
416
+ interactive
417
+ });
418
+ return useRender({
419
+ defaultTagName: "div",
420
+ render,
421
+ props: mergeProps({ className: root({ className }) }, props),
422
+ state: { slot: "list-item" }
423
+ });
424
+ }
425
+ function ListItemBody({ className, render, ...props }) {
426
+ const { body } = listItem();
427
+ return useRender({
428
+ defaultTagName: "div",
429
+ render,
430
+ props: mergeProps({ className: body({ className }) }, props),
431
+ state: { slot: "list-item-body" }
432
+ });
433
+ }
434
+ function ListItemIcon({ className, render, ...props }) {
435
+ const { icon } = listItem({ theme: useThemeFamily() });
436
+ return useRender({
437
+ defaultTagName: "div",
438
+ render,
439
+ props: mergeProps({ className: icon({ className }) }, props),
440
+ state: { slot: "list-item-icon" }
441
+ });
442
+ }
443
+ function ListItemRow({ className, render, ...props }) {
444
+ const { row } = listItem({ theme: useThemeFamily() });
445
+ return useRender({
446
+ defaultTagName: "div",
447
+ render,
448
+ props: mergeProps({ className: row({ className }) }, props),
449
+ state: { slot: "list-item-row" }
450
+ });
451
+ }
452
+ function ListItemTitle({ className, render, ...props }) {
453
+ const { title } = listItem({ theme: useThemeFamily() });
454
+ return useRender({
455
+ defaultTagName: "div",
456
+ render,
457
+ props: mergeProps({ className: title({ className }) }, props),
458
+ state: { slot: "list-item-title" }
459
+ });
460
+ }
461
+ function ListItemDescription({ className, render, ...props }) {
462
+ const { description } = listItem({ theme: useThemeFamily() });
463
+ return useRender({
464
+ defaultTagName: "p",
465
+ render,
466
+ props: mergeProps({ className: description({ className }) }, props),
467
+ state: { slot: "list-item-description" }
468
+ });
469
+ }
470
+ function ListItemMeta({ className, render, ...props }) {
471
+ const { meta } = listItem({ theme: useThemeFamily() });
472
+ return useRender({
473
+ defaultTagName: "div",
474
+ render,
475
+ props: mergeProps({ className: meta({ className }) }, props),
476
+ state: { slot: "list-item-meta" }
477
+ });
478
+ }
479
+ function ListItemActionGroup({ className, render, ...props }) {
480
+ const { actionGroup } = listItem({ theme: useThemeFamily() });
481
+ return useRender({
482
+ defaultTagName: "div",
483
+ render,
484
+ props: mergeProps({ className: actionGroup({ className }) }, props),
485
+ state: { slot: "list-item-action-group" }
486
+ });
487
+ }
488
+ //#endregion
489
+ //#region src/components/media-list-item/media-list-item.tsx
490
+ const mediaItem = tv({
491
+ slots: {
492
+ row: ["group/media-item flex w-full min-w-0 gap-3"],
493
+ body: ["flex min-w-0 flex-1 gap-3", "items-center group-data-[align=start]/media-item:items-start"],
494
+ text: ["min-w-0 flex-1"],
495
+ textInner: ["flex min-w-0 flex-wrap items-baseline gap-x-2", "group-data-[align=start]/media-item:flex-col group-data-[align=start]/media-item:flex-nowrap group-data-[align=start]/media-item:items-stretch group-data-[align=start]/media-item:gap-x-1 group-data-[align=start]/media-item:gap-y-1"],
496
+ visual: ["shrink-0"],
497
+ title: ["truncate text-sm font-bold"],
498
+ subtitle: [
499
+ "font-mono text-xs",
500
+ "[&_svg]:size-3 [&_svg]:shrink-0",
501
+ "group-data-[align=start]/media-item:flex group-data-[align=start]/media-item:min-w-0 group-data-[align=start]/media-item:flex-wrap group-data-[align=start]/media-item:items-center group-data-[align=start]/media-item:gap-x-2 group-data-[align=start]/media-item:gap-y-1"
502
+ ],
503
+ aside: ["flex shrink-0 items-center gap-1.5 self-center", "[&_svg]:size-3.5 [&_svg]:shrink-0"],
504
+ actionGroup: ["flex shrink-0 items-center gap-1.5 self-center", "[&_svg]:size-3.5 [&_svg]:shrink-0"]
505
+ },
506
+ variants: {
507
+ theme: {
508
+ brutal: {
509
+ title: "text-foreground-strong",
510
+ subtitle: "text-foreground/50"
511
+ },
512
+ elegant: {}
513
+ },
514
+ align: {
515
+ start: { row: "items-start" },
516
+ center: { row: "items-center" }
517
+ },
518
+ interactive: {
519
+ true: { body: "text-left" },
520
+ false: { body: "" }
521
+ }
522
+ },
523
+ defaultVariants: { align: "center" }
524
+ });
525
+ function MediaListItem({ align = "center", selected, interactive, className, children, ...props }) {
526
+ const { row } = mediaItem({ align });
527
+ return /* @__PURE__ */ jsx(ListItem, {
528
+ "data-slot": "media-list-item",
529
+ selected,
530
+ interactive: interactive ?? false,
531
+ className: cn("group px-3 py-2 has-[[data-interactive=true]]:hover:border-line-strong has-[[data-interactive=true]]:hover:shadow-sm", className),
532
+ children: /* @__PURE__ */ jsx("div", {
533
+ "data-align": align,
534
+ className: row(),
535
+ ...props,
536
+ children
537
+ })
538
+ });
539
+ }
540
+ function MediaListItemBody({ render, onClick, className, ...props }) {
541
+ const interactive = onClick !== void 0;
542
+ const { body } = mediaItem({ interactive });
543
+ const defaultProps = {
544
+ "data-slot": "media-list-item-body",
545
+ "data-interactive": interactive ? "true" : void 0,
546
+ onClick,
547
+ className: body({ className })
548
+ };
549
+ return useRender({
550
+ render: render ?? (interactive ? /* @__PURE__ */ jsx(Button, { type: "button" }) : /* @__PURE__ */ jsx("div", {})),
551
+ props: mergeProps(defaultProps, props)
552
+ });
553
+ }
554
+ function MediaListItemText({ className, children, ...props }) {
555
+ const { text, textInner } = mediaItem();
556
+ return /* @__PURE__ */ jsx("div", {
557
+ "data-slot": "media-list-item-text",
558
+ className: text({ className }),
559
+ ...props,
560
+ children: /* @__PURE__ */ jsx("div", {
561
+ className: textInner(),
562
+ children
563
+ })
564
+ });
565
+ }
566
+ function MediaListItemVisual({ className, ...props }) {
567
+ const { visual } = mediaItem();
568
+ return /* @__PURE__ */ jsx("div", {
569
+ "data-slot": "media-list-item-visual",
570
+ className: visual({ className }),
571
+ ...props
572
+ });
573
+ }
574
+ function MediaListItemTitle({ className, ...props }) {
575
+ const { title } = mediaItem({ theme: useThemeFamily() });
576
+ return /* @__PURE__ */ jsx("span", {
577
+ "data-slot": "media-list-item-title",
578
+ className: title({ className }),
579
+ ...props
580
+ });
581
+ }
582
+ function MediaListItemSubtitle({ className, ...props }) {
583
+ const { subtitle } = mediaItem({ theme: useThemeFamily() });
584
+ return /* @__PURE__ */ jsx("span", {
585
+ "data-slot": "media-list-item-subtitle",
586
+ className: subtitle({ className }),
587
+ ...props
588
+ });
589
+ }
590
+ function MediaListItemAside({ className, ...props }) {
591
+ const { aside } = mediaItem();
592
+ return /* @__PURE__ */ jsx("div", {
593
+ "data-slot": "media-list-item-aside",
594
+ className: aside({ className }),
595
+ ...props
596
+ });
597
+ }
598
+ function MediaListItemActionGroup({ className, ...props }) {
599
+ const { actionGroup } = mediaItem();
600
+ return /* @__PURE__ */ jsx("div", {
601
+ "data-slot": "media-list-item-action-group",
602
+ className: actionGroup({ className }),
603
+ ...props
604
+ });
605
+ }
606
+ //#endregion
607
+ //#region src/components/panel-header/panel-header.tsx
608
+ const panelHeader = tv({
609
+ slots: {
610
+ root: ["flex h-[62px] items-center gap-3 px-5", "[@media(max-height:600px)]:h-12"],
611
+ icon: ["hidden size-9 shrink-0 items-center justify-center border-2 md:flex", "[&_svg]:size-[18px]"],
612
+ visual: ["hidden shrink-0 md:flex"],
613
+ content: ["min-w-0 flex-1"],
614
+ titleRow: ["flex min-w-0 items-center gap-2"],
615
+ title: ["truncate text-base font-bold leading-tight"],
616
+ suffix: ["shrink-0"],
617
+ subtitle: ["truncate font-mono text-xs"],
618
+ actions: ["flex shrink-0 items-center gap-1.5"]
619
+ },
620
+ variants: { theme: {
621
+ brutal: {
622
+ root: "border-b-2 border-line-strong bg-layer-panel",
623
+ icon: "border-line-strong",
624
+ title: "text-foreground-strong",
625
+ subtitle: "text-foreground/50"
626
+ },
627
+ elegant: {}
628
+ } }
629
+ });
630
+ function PanelHeader({ className, render, ...props }) {
631
+ const { root } = panelHeader({ theme: useThemeFamily() });
632
+ return useRender({
633
+ defaultTagName: "div",
634
+ render,
635
+ props: mergeProps({ className: root({ className }) }, props),
636
+ state: { slot: "panel-header" }
637
+ });
638
+ }
639
+ function PanelHeaderIcon({ className, render, ...props }) {
640
+ const { icon } = panelHeader({ theme: useThemeFamily() });
641
+ return useRender({
642
+ defaultTagName: "div",
643
+ render,
644
+ props: mergeProps({ className: icon({ className }) }, props),
645
+ state: { slot: "panel-header-icon" }
646
+ });
647
+ }
648
+ function PanelHeaderVisual({ className, render, ...props }) {
649
+ const { visual } = panelHeader();
650
+ return useRender({
651
+ defaultTagName: "div",
652
+ render,
653
+ props: mergeProps({ className: visual({ className }) }, props),
654
+ state: { slot: "panel-header-visual" }
655
+ });
656
+ }
657
+ function PanelHeaderContent({ className, render, ...props }) {
658
+ const { content } = panelHeader();
659
+ return useRender({
660
+ defaultTagName: "div",
661
+ render,
662
+ props: mergeProps({ className: content({ className }) }, props),
663
+ state: { slot: "panel-header-content" }
664
+ });
665
+ }
666
+ function PanelHeaderTitleRow({ className, render, ...props }) {
667
+ const { titleRow } = panelHeader();
668
+ return useRender({
669
+ defaultTagName: "div",
670
+ render,
671
+ props: mergeProps({ className: titleRow({ className }) }, props),
672
+ state: { slot: "panel-header-title-row" }
673
+ });
674
+ }
675
+ function PanelHeaderTitle({ className, render, ...props }) {
676
+ const { title } = panelHeader({ theme: useThemeFamily() });
677
+ return useRender({
678
+ defaultTagName: "h2",
679
+ render,
680
+ props: mergeProps({ className: title({ className }) }, props),
681
+ state: { slot: "panel-header-title" }
682
+ });
683
+ }
684
+ function PanelHeaderSuffix({ className, render, ...props }) {
685
+ const { suffix } = panelHeader();
686
+ return useRender({
687
+ defaultTagName: "div",
688
+ render,
689
+ props: mergeProps({ className: suffix({ className }) }, props),
690
+ state: { slot: "panel-header-suffix" }
691
+ });
692
+ }
693
+ function PanelHeaderSubtitle({ className, render, ...props }) {
694
+ const { subtitle } = panelHeader({ theme: useThemeFamily() });
695
+ return useRender({
696
+ defaultTagName: "p",
697
+ render,
698
+ props: mergeProps({ className: subtitle({ className }) }, props),
699
+ state: { slot: "panel-header-subtitle" }
700
+ });
701
+ }
702
+ function PanelHeaderActions({ className, render, ...props }) {
703
+ const { actions } = panelHeader();
704
+ return useRender({
705
+ defaultTagName: "div",
706
+ render,
707
+ props: mergeProps({ className: actions({ className }) }, props),
708
+ state: { slot: "panel-header-actions" }
709
+ });
710
+ }
711
+ //#endregion
712
+ //#region src/components/quoted-message-card/quoted-message-card.tsx
713
+ const quotedMessageCard = tv({
714
+ slots: {
715
+ root: ["group block w-full text-left"],
716
+ body: ["px-2.5 py-2 sm:px-3 sm:py-2.5"],
717
+ unavailable: ["text-[13px] leading-snug"],
718
+ header: ["mb-1 flex items-start gap-2 sm:mb-1.5"],
719
+ meta: ["flex min-w-0 flex-1 flex-wrap items-center gap-x-1.5 gap-y-1 text-xs leading-none"],
720
+ channel: ["inline-flex items-center gap-1 font-bold", "[&_svg]:size-[11px] [&_svg]:shrink-0"],
721
+ separator: ["text-foreground/30"],
722
+ author: ["inline-flex min-w-0 items-center gap-1.5"],
723
+ authorName: ["truncate font-bold"],
724
+ authorSubtitle: ["truncate font-mono text-[10px]"],
725
+ thread: ["inline-flex items-center gap-1 font-bold", "[&_svg]:size-2.5 [&_svg]:shrink-0"],
726
+ tag: ["inline-flex items-center gap-1 border-[1.5px] border-line-strong px-1.5 py-0.5", "text-[11px] font-bold leading-none"],
727
+ timestamp: ["shrink-0 font-mono text-[10px]"],
728
+ contentWrap: ["min-w-0"],
729
+ content: ["line-clamp-2 text-xs leading-snug sm:text-[13px]"],
730
+ attachments: ["mt-2 flex flex-wrap gap-1.5"]
731
+ },
732
+ variants: { theme: {
733
+ brutal: {
734
+ channel: "text-foreground/70",
735
+ authorName: "text-foreground/70",
736
+ authorSubtitle: "text-foreground/40",
737
+ thread: "text-accent-400",
738
+ timestamp: "text-foreground/40",
739
+ content: "text-foreground-strong"
740
+ },
741
+ elegant: {}
742
+ } }
743
+ });
744
+ function QuotedMessageCard({ className, "data-testid": testId = "quoted-message-card", ...props }) {
745
+ const { root } = quotedMessageCard();
746
+ return /* @__PURE__ */ jsx(PreviewShell, {
747
+ "data-testid": testId,
748
+ className: root({ className }),
749
+ ...props
750
+ });
751
+ }
752
+ function QuotedMessageCardBody({ className, render, ...props }) {
753
+ const { body } = quotedMessageCard();
754
+ return useRender({
755
+ defaultTagName: "div",
756
+ render,
757
+ props: mergeProps({ className: body({ className }) }, props),
758
+ state: { slot: "quoted-message-card-body" }
759
+ });
760
+ }
761
+ function QuotedMessageCardUnavailable({ className, render, ...props }) {
762
+ const { unavailable } = quotedMessageCard();
763
+ return useRender({
764
+ defaultTagName: "div",
765
+ render,
766
+ props: mergeProps({ className: unavailable({ className }) }, props),
767
+ state: { slot: "quoted-message-card-unavailable" }
768
+ });
769
+ }
770
+ function QuotedMessageCardHeader({ className, render, ...props }) {
771
+ const { header } = quotedMessageCard();
772
+ return useRender({
773
+ defaultTagName: "div",
774
+ render,
775
+ props: mergeProps({ className: header({ className }) }, props),
776
+ state: { slot: "quoted-message-card-header" }
777
+ });
778
+ }
779
+ function QuotedMessageCardMeta({ className, render, ...props }) {
780
+ const { meta } = quotedMessageCard();
781
+ return useRender({
782
+ defaultTagName: "div",
783
+ render,
784
+ props: mergeProps({ className: meta({ className }) }, props),
785
+ state: { slot: "quoted-message-card-meta" }
786
+ });
787
+ }
788
+ function QuotedMessageCardChannel({ className, render, ...props }) {
789
+ const { channel } = quotedMessageCard({ theme: useThemeFamily() });
790
+ return useRender({
791
+ defaultTagName: "span",
792
+ render,
793
+ props: mergeProps({ className: channel({ className }) }, props),
794
+ state: { slot: "quoted-message-card-channel" }
795
+ });
796
+ }
797
+ function QuotedMessageCardSeparator({ className, render, ...props }) {
798
+ const { separator } = quotedMessageCard();
799
+ return useRender({
800
+ defaultTagName: "span",
801
+ render,
802
+ props: mergeProps({
803
+ className: separator({ className }),
804
+ children: "·"
805
+ }, props),
806
+ state: { slot: "quoted-message-card-separator" }
807
+ });
808
+ }
809
+ function QuotedMessageCardAuthor({ className, render, ...props }) {
810
+ const { author } = quotedMessageCard();
811
+ return useRender({
812
+ defaultTagName: "span",
813
+ render,
814
+ props: mergeProps({ className: author({ className }) }, props),
815
+ state: { slot: "quoted-message-card-author" }
816
+ });
817
+ }
818
+ function QuotedMessageCardAuthorName({ className, render, ...props }) {
819
+ const { authorName } = quotedMessageCard({ theme: useThemeFamily() });
820
+ return useRender({
821
+ defaultTagName: "span",
822
+ render,
823
+ props: mergeProps({ className: authorName({ className }) }, props),
824
+ state: { slot: "quoted-message-card-author-name" }
825
+ });
826
+ }
827
+ function QuotedMessageCardAuthorSubtitle({ className, render, ...props }) {
828
+ const { authorSubtitle } = quotedMessageCard({ theme: useThemeFamily() });
829
+ return useRender({
830
+ defaultTagName: "span",
831
+ render,
832
+ props: mergeProps({ className: authorSubtitle({ className }) }, props),
833
+ state: { slot: "quoted-message-card-author-subtitle" }
834
+ });
835
+ }
836
+ function QuotedMessageCardThread({ className, render, children = "Thread", ...props }) {
837
+ const { thread } = quotedMessageCard({ theme: useThemeFamily() });
838
+ return useRender({
839
+ defaultTagName: "span",
840
+ render,
841
+ props: mergeProps({
842
+ className: thread({ className }),
843
+ children: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(MessageSquare, {}), children] })
844
+ }, props),
845
+ state: { slot: "quoted-message-card-thread" }
846
+ });
847
+ }
848
+ function QuotedMessageCardTag({ className, render, ...props }) {
849
+ const { tag } = quotedMessageCard();
850
+ return useRender({
851
+ defaultTagName: "span",
852
+ render,
853
+ props: mergeProps({ className: tag({ className }) }, props),
854
+ state: { slot: "quoted-message-card-tag" }
855
+ });
856
+ }
857
+ function QuotedMessageCardTimestamp({ className, render, ...props }) {
858
+ const { timestamp } = quotedMessageCard({ theme: useThemeFamily() });
859
+ return useRender({
860
+ defaultTagName: "span",
861
+ render,
862
+ props: mergeProps({ className: timestamp({ className }) }, props),
863
+ state: { slot: "quoted-message-card-timestamp" }
864
+ });
865
+ }
866
+ function QuotedMessageCardContentWrap({ className, render, ...props }) {
867
+ const { contentWrap } = quotedMessageCard();
868
+ return useRender({
869
+ defaultTagName: "div",
870
+ render,
871
+ props: mergeProps({ className: contentWrap({ className }) }, props),
872
+ state: { slot: "quoted-message-card-content-wrap" }
873
+ });
874
+ }
875
+ function QuotedMessageCardContent({ className, render, ...props }) {
876
+ const { content } = quotedMessageCard({ theme: useThemeFamily() });
877
+ return useRender({
878
+ defaultTagName: "div",
879
+ render,
880
+ props: mergeProps({ className: content({ className }) }, props),
881
+ state: { slot: "quoted-message-card-content" }
882
+ });
883
+ }
884
+ function QuotedMessageCardAttachments({ className, render, ...props }) {
885
+ const { attachments } = quotedMessageCard();
886
+ return useRender({
887
+ defaultTagName: "div",
888
+ render,
889
+ props: mergeProps({ className: attachments({ className }) }, props),
890
+ state: { slot: "quoted-message-card-attachments" }
891
+ });
892
+ }
893
+ //#endregion
894
+ //#region src/components/conversation-preview-card/conversation-preview-card.tsx
895
+ const conversationPreviewCard = tv({
896
+ slots: {
897
+ root: ["relative flex w-full items-start gap-3 border-2 p-3 text-left transition-colors"],
898
+ content: ["min-w-0 flex-1"],
899
+ meta: ["mb-1 flex flex-wrap items-center gap-x-2.5 gap-y-1 text-xs leading-4"],
900
+ channel: ["font-bold"],
901
+ author: ["inline-flex min-w-0 items-center gap-1 font-bold"],
902
+ authorName: ["truncate"],
903
+ authorSubtitle: ["font-mono text-[10px]"],
904
+ timestamp: ["font-mono text-xs leading-4"],
905
+ preview: ["text-sm"],
906
+ previewLeading: ["mr-1 inline-flex align-[-1px]", "[&_svg]:size-[13px] [&_svg]:shrink-0"],
907
+ previewAuthor: ["font-bold"],
908
+ secondaryPreview: ["mt-1 line-clamp-1 text-xs"],
909
+ footer: ["mt-1 flex items-center gap-3"],
910
+ action: ["shrink-0"]
911
+ },
912
+ variants: {
913
+ theme: {
914
+ brutal: {
915
+ root: [
916
+ "border-line-subtle bg-layer-panel hover:border-line-strong hover:shadow-sm",
917
+ "data-[state=active]:border-line-strong data-[state=active]:bg-layer-panel data-[state=active]:shadow-sm",
918
+ "data-[highlighted=true]:border-line-strong data-[highlighted=true]:bg-info-base/25 data-[highlighted=true]:shadow-md"
919
+ ],
920
+ channel: "text-foreground/50",
921
+ author: "text-foreground-strong",
922
+ authorSubtitle: "text-foreground/40",
923
+ timestamp: "text-foreground/40",
924
+ previewAuthor: "text-foreground/70",
925
+ secondaryPreview: "text-foreground/45"
926
+ },
927
+ elegant: {}
928
+ },
929
+ interactive: {
930
+ true: { root: "active:border-line-strong active:shadow-sm" },
931
+ false: { root: "cursor-default" }
932
+ }
933
+ },
934
+ defaultVariants: { interactive: false }
935
+ });
936
+ function ConversationPreviewCard({ onClick, className, render, testId, ...props }) {
937
+ const theme = useThemeFamily();
938
+ const interactive = Boolean(onClick);
939
+ const { root } = conversationPreviewCard({
940
+ theme,
941
+ interactive
942
+ });
943
+ const defaultProps = {
944
+ onClick,
945
+ "data-slot": "conversation-preview-card",
946
+ "data-testid": testId,
947
+ className: root({ className })
948
+ };
949
+ return useRender({
950
+ render: render ?? (interactive ? /* @__PURE__ */ jsx(Button, { type: "button" }) : /* @__PURE__ */ jsx("div", {})),
951
+ props: mergeProps(defaultProps, props)
952
+ });
953
+ }
954
+ function ConversationPreviewCardContent({ className, render, ...props }) {
955
+ const { content } = conversationPreviewCard();
956
+ return useRender({
957
+ defaultTagName: "div",
958
+ render,
959
+ props: mergeProps({ className: content({ className }) }, props)
960
+ });
961
+ }
962
+ function ConversationPreviewCardMeta({ className, render, ...props }) {
963
+ const { meta } = conversationPreviewCard();
964
+ return useRender({
965
+ defaultTagName: "div",
966
+ render,
967
+ props: mergeProps({ className: meta({ className }) }, props)
968
+ });
969
+ }
970
+ function ConversationPreviewCardChannel({ className, render, ...props }) {
971
+ const { channel } = conversationPreviewCard({ theme: useThemeFamily() });
972
+ return useRender({
973
+ defaultTagName: "span",
974
+ render,
975
+ props: mergeProps({ className: channel({ className }) }, props)
976
+ });
977
+ }
978
+ function ConversationPreviewCardAuthor({ className, render, ...props }) {
979
+ const { author } = conversationPreviewCard({ theme: useThemeFamily() });
980
+ return useRender({
981
+ defaultTagName: "span",
982
+ render,
983
+ props: mergeProps({ className: author({ className }) }, props)
984
+ });
985
+ }
986
+ function ConversationPreviewCardAuthorName({ className, render, ...props }) {
987
+ const { authorName } = conversationPreviewCard();
988
+ return useRender({
989
+ defaultTagName: "span",
990
+ render,
991
+ props: mergeProps({ className: authorName({ className }) }, props)
992
+ });
993
+ }
994
+ function ConversationPreviewCardAuthorSubtitle({ className, render, ...props }) {
995
+ const { authorSubtitle } = conversationPreviewCard({ theme: useThemeFamily() });
996
+ return useRender({
997
+ defaultTagName: "span",
998
+ render,
999
+ props: mergeProps({ className: authorSubtitle({ className }) }, props)
1000
+ });
1001
+ }
1002
+ function ConversationPreviewCardTimestamp({ className, render, ...props }) {
1003
+ const { timestamp } = conversationPreviewCard({ theme: useThemeFamily() });
1004
+ return useRender({
1005
+ defaultTagName: "span",
1006
+ render,
1007
+ props: mergeProps({ className: timestamp({ className }) }, props)
1008
+ });
1009
+ }
1010
+ function ConversationPreviewCardPreview({ className, render, ...props }) {
1011
+ const { preview } = conversationPreviewCard();
1012
+ return useRender({
1013
+ defaultTagName: "p",
1014
+ render,
1015
+ props: mergeProps({ className: preview({ className }) }, props)
1016
+ });
1017
+ }
1018
+ function ConversationPreviewCardPreviewLeading({ className, render, ...props }) {
1019
+ const { previewLeading } = conversationPreviewCard();
1020
+ return useRender({
1021
+ defaultTagName: "span",
1022
+ render,
1023
+ props: mergeProps({ className: previewLeading({ className }) }, props)
1024
+ });
1025
+ }
1026
+ function ConversationPreviewCardPreviewAuthor({ className, render, ...props }) {
1027
+ const { previewAuthor } = conversationPreviewCard({ theme: useThemeFamily() });
1028
+ return useRender({
1029
+ defaultTagName: "span",
1030
+ render,
1031
+ props: mergeProps({ className: previewAuthor({ className }) }, props)
1032
+ });
1033
+ }
1034
+ function ConversationPreviewCardSecondaryPreview({ className, render, ...props }) {
1035
+ const { secondaryPreview } = conversationPreviewCard({ theme: useThemeFamily() });
1036
+ return useRender({
1037
+ defaultTagName: "p",
1038
+ render,
1039
+ props: mergeProps({ className: secondaryPreview({ className }) }, props)
1040
+ });
1041
+ }
1042
+ function ConversationPreviewCardFooter({ className, render, ...props }) {
1043
+ const { footer } = conversationPreviewCard();
1044
+ return useRender({
1045
+ defaultTagName: "div",
1046
+ render,
1047
+ props: mergeProps({ className: footer({ className }) }, props)
1048
+ });
1049
+ }
1050
+ function ConversationPreviewCardAction({ className, render, ...props }) {
1051
+ const { action } = conversationPreviewCard();
1052
+ return useRender({
1053
+ defaultTagName: "div",
1054
+ render,
1055
+ props: mergeProps({ className: action({ className }) }, props)
1056
+ });
1057
+ }
1058
+ //#endregion
1059
+ //#region src/components/section-label/section-label.tsx
1060
+ const sectionLabel = tv({
1061
+ slots: { root: ["text-xs font-bold uppercase tracking-widest"] },
1062
+ variants: { theme: {
1063
+ brutal: { root: "text-foreground/60" },
1064
+ elegant: {}
1065
+ } }
1066
+ });
1067
+ function SectionLabel({ className, render, ...props }) {
1068
+ const { root } = sectionLabel({ theme: useThemeFamily() });
1069
+ return useRender({
1070
+ defaultTagName: "span",
1071
+ render,
1072
+ props: mergeProps({ className: root({ className }) }, props),
1073
+ state: { slot: "section-label" }
1074
+ });
1075
+ }
1076
+ //#endregion
1077
+ //#region src/components/section-header/section-header.tsx
1078
+ const sectionHeader = tv({
1079
+ slots: {
1080
+ root: ["flex items-center justify-between gap-2"],
1081
+ content: ["flex min-w-0 items-center gap-2"],
1082
+ icon: ["shrink-0 text-foreground/60", "[&_svg]:size-4 [&_svg]:shrink-0"],
1083
+ count: ["ml-2 font-mono text-foreground/40"],
1084
+ actions: ["flex shrink-0 items-center gap-1.5"]
1085
+ },
1086
+ variants: { theme: {
1087
+ brutal: {},
1088
+ elegant: {}
1089
+ } }
1090
+ });
1091
+ function SectionHeader({ className, render, ...props }) {
1092
+ const { root } = sectionHeader();
1093
+ return useRender({
1094
+ defaultTagName: "div",
1095
+ render,
1096
+ props: mergeProps({ className: root({ className }) }, props),
1097
+ state: { slot: "section-header" }
1098
+ });
1099
+ }
1100
+ function SectionHeaderContent({ className, render, ...props }) {
1101
+ const { content } = sectionHeader();
1102
+ return useRender({
1103
+ defaultTagName: "div",
1104
+ render,
1105
+ props: mergeProps({ className: content({ className }) }, props),
1106
+ state: { slot: "section-header-content" }
1107
+ });
1108
+ }
1109
+ function SectionHeaderIcon({ className, render, ...props }) {
1110
+ const { icon } = sectionHeader();
1111
+ return useRender({
1112
+ defaultTagName: "span",
1113
+ render,
1114
+ props: mergeProps({ className: icon({ className }) }, props),
1115
+ state: { slot: "section-header-icon" }
1116
+ });
1117
+ }
1118
+ function SectionHeaderTitle({ render, ...props }) {
1119
+ return /* @__PURE__ */ jsx(SectionLabel, {
1120
+ render: render ?? /* @__PURE__ */ jsx("div", {}),
1121
+ ...props,
1122
+ "data-slot": "section-header-title"
1123
+ });
1124
+ }
1125
+ function SectionHeaderCount({ className, render, ...props }) {
1126
+ const { count } = sectionHeader();
1127
+ return useRender({
1128
+ defaultTagName: "span",
1129
+ render,
1130
+ props: mergeProps({ className: count({ className }) }, props),
1131
+ state: { slot: "section-header-count" }
1132
+ });
1133
+ }
1134
+ function SectionHeaderActions({ className, render, ...props }) {
1135
+ const { actions } = sectionHeader();
1136
+ return useRender({
1137
+ defaultTagName: "div",
1138
+ render,
1139
+ props: mergeProps({ className: actions({ className }) }, props),
1140
+ state: { slot: "section-header-actions" }
1141
+ });
1142
+ }
1143
+ //#endregion
1144
+ //#region src/components/description-list/description-list.tsx
1145
+ const descriptionList = tv({
1146
+ slots: {
1147
+ root: ["m-0"],
1148
+ item: [""],
1149
+ term: ["mb-1 flex items-center gap-2 text-xs"],
1150
+ details: ["m-0 text-sm"],
1151
+ action: ["inline-flex shrink-0 items-center", "[&_svg]:size-3 [&_svg]:shrink-0"]
1152
+ },
1153
+ variants: { theme: {
1154
+ brutal: {
1155
+ term: "text-foreground/50",
1156
+ details: "text-foreground-strong"
1157
+ },
1158
+ elegant: {}
1159
+ } }
1160
+ });
1161
+ function DescriptionList({ className, render, ...props }) {
1162
+ const { root } = descriptionList();
1163
+ return useRender({
1164
+ defaultTagName: "dl",
1165
+ render,
1166
+ props: mergeProps({ className: root({ className }) }, props),
1167
+ state: { slot: "description-list" }
1168
+ });
1169
+ }
1170
+ function DescriptionItem({ className, render, ...props }) {
1171
+ const { item } = descriptionList();
1172
+ return useRender({
1173
+ defaultTagName: "div",
1174
+ render,
1175
+ props: mergeProps({ className: item({ className }) }, props),
1176
+ state: { slot: "description-item" }
1177
+ });
1178
+ }
1179
+ function DescriptionTerm({ className, render, ...props }) {
1180
+ const { term } = descriptionList({ theme: useThemeFamily() });
1181
+ return useRender({
1182
+ defaultTagName: "dt",
1183
+ render,
1184
+ props: mergeProps({ className: term({ className }) }, props),
1185
+ state: { slot: "description-term" }
1186
+ });
1187
+ }
1188
+ function DescriptionDetails({ className, render, ...props }) {
1189
+ const { details } = descriptionList({ theme: useThemeFamily() });
1190
+ return useRender({
1191
+ defaultTagName: "dd",
1192
+ render,
1193
+ props: mergeProps({ className: details({ className }) }, props),
1194
+ state: { slot: "description-details" }
1195
+ });
1196
+ }
1197
+ function DescriptionAction({ className, render, ...props }) {
1198
+ const { action } = descriptionList();
1199
+ return useRender({
1200
+ defaultTagName: "span",
1201
+ render,
1202
+ props: mergeProps({ className: action({ className }) }, props),
1203
+ state: { slot: "description-action" }
1204
+ });
1205
+ }
1206
+ //#endregion
1207
+ //#region src/components/lightbox/lightbox.tsx
1208
+ const lightbox = tv({
1209
+ slots: {
1210
+ backdrop: ["fixed inset-0 z-[70] bg-layer-backdrop data-[closed]:hidden"],
1211
+ content: ["pointer-events-none fixed inset-0 z-[71] data-[closed]:hidden"],
1212
+ header: ["safe-top safe-left safe-right pointer-events-auto shrink-0"],
1213
+ title: ["min-w-0 flex-1 truncate font-heading text-sm font-bold"],
1214
+ actions: ["flex shrink-0 items-center gap-1.5"],
1215
+ stage: ["pointer-events-none relative flex min-h-0 flex-1 items-center justify-center overflow-hidden"],
1216
+ media: ["pointer-events-auto max-h-[80vh] max-w-[86vw] border-2"],
1217
+ close: []
1218
+ },
1219
+ variants: { theme: {
1220
+ brutal: {
1221
+ header: ["border-b-2 border-line-strong bg-layer-panel"],
1222
+ title: ["text-foreground-strong"],
1223
+ media: ["border-line-strong bg-layer-panel shadow-xl"]
1224
+ },
1225
+ elegant: {}
1226
+ } }
1227
+ });
1228
+ function Lightbox({ closeOnModW = true, defaultOpen = false, modal = true, onOpenChange, open, children, ...props }) {
1229
+ const dialogRef = useRef(null);
1230
+ const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
1231
+ const effectiveOpen = open ?? uncontrolledOpen;
1232
+ const handleOpenChange = useCallback((nextOpen, eventDetails) => {
1233
+ if (open === void 0) setUncontrolledOpen(nextOpen);
1234
+ onOpenChange?.(nextOpen, eventDetails);
1235
+ }, [onOpenChange, open]);
1236
+ const modWClose = closeOnModW && effectiveOpen ? /* @__PURE__ */ jsx(LightboxModWClose, { dialogRef }) : null;
1237
+ return /* @__PURE__ */ jsxs(Dialog.Root, {
1238
+ actionsRef: dialogRef,
1239
+ defaultOpen,
1240
+ modal,
1241
+ onOpenChange: handleOpenChange,
1242
+ open,
1243
+ ...props,
1244
+ children: [modWClose, children]
1245
+ });
1246
+ }
1247
+ function LightboxModWClose({ dialogRef }) {
1248
+ useHotkey("Mod+W", (event) => {
1249
+ event.preventDefault();
1250
+ event.stopPropagation();
1251
+ dialogRef.current?.close();
1252
+ }, { meta: {
1253
+ name: "Close lightbox",
1254
+ description: "Close the active lightbox before the browser closes the tab."
1255
+ } });
1256
+ return null;
1257
+ }
1258
+ function LightboxTrigger(props) {
1259
+ return /* @__PURE__ */ jsx(Dialog.Trigger, {
1260
+ "data-slot": "lightbox-trigger",
1261
+ ...props
1262
+ });
1263
+ }
1264
+ function LightboxPortal(props) {
1265
+ return /* @__PURE__ */ jsx(Dialog.Portal, {
1266
+ "data-slot": "lightbox-portal",
1267
+ ...props
1268
+ });
1269
+ }
1270
+ function LightboxContent({ className, initialFocus = false, finalFocus = false, ...props }) {
1271
+ const { backdrop, content } = lightbox({ theme: useThemeFamily() });
1272
+ return /* @__PURE__ */ jsxs(LightboxPortal, { children: [/* @__PURE__ */ jsx(Dialog.Backdrop, {
1273
+ "data-slot": "lightbox-backdrop",
1274
+ className: backdrop()
1275
+ }), /* @__PURE__ */ jsx(Dialog.Popup, {
1276
+ "data-slot": "lightbox-content",
1277
+ initialFocus,
1278
+ finalFocus,
1279
+ className: content({ className }),
1280
+ ...props
1281
+ })] });
1282
+ }
1283
+ function LightboxHeader({ render, className, ...props }) {
1284
+ const { header } = lightbox({ theme: useThemeFamily() });
1285
+ return useRender({
1286
+ defaultTagName: "div",
1287
+ render,
1288
+ props: mergeProps({ className: header({ className }) }, props),
1289
+ state: { slot: "lightbox-header" }
1290
+ });
1291
+ }
1292
+ function LightboxTitle({ render, className, ...props }) {
1293
+ const { title } = lightbox({ theme: useThemeFamily() });
1294
+ return useRender({
1295
+ defaultTagName: "div",
1296
+ render,
1297
+ props: mergeProps({ className: title({ className }) }, props),
1298
+ state: { slot: "lightbox-title" }
1299
+ });
1300
+ }
1301
+ function LightboxActions({ render, className, ...props }) {
1302
+ const { actions } = lightbox({ theme: useThemeFamily() });
1303
+ return useRender({
1304
+ defaultTagName: "div",
1305
+ render,
1306
+ props: mergeProps({ className: actions({ className }) }, props),
1307
+ state: { slot: "lightbox-actions" }
1308
+ });
1309
+ }
1310
+ function LightboxStage({ render, className, ...props }) {
1311
+ const { stage } = lightbox({ theme: useThemeFamily() });
1312
+ return useRender({
1313
+ defaultTagName: "div",
1314
+ render,
1315
+ props: mergeProps({ className: stage({ className }) }, props),
1316
+ state: { slot: "lightbox-stage" }
1317
+ });
1318
+ }
1319
+ function LightboxMedia({ render, className, ...props }) {
1320
+ const { media } = lightbox({ theme: useThemeFamily() });
1321
+ return useRender({
1322
+ defaultTagName: "div",
1323
+ render,
1324
+ props: mergeProps({ className: media({ className }) }, props),
1325
+ state: { slot: "lightbox-media" }
1326
+ });
1327
+ }
1328
+ function LightboxClose({ className, ...props }) {
1329
+ const { close } = lightbox({ theme: useThemeFamily() });
1330
+ return /* @__PURE__ */ jsx(Dialog.Close, {
1331
+ "data-slot": "lightbox-close",
1332
+ className: close({ className }),
1333
+ ...props
1334
+ });
1335
+ }
1336
+ //#endregion
1337
+ //#region src/components/bottom-sheet/bottom-sheet.tsx
1338
+ const bottomSheet = tv({
1339
+ slots: {
1340
+ content: ["fixed inset-x-3 bottom-[max(12px,env(safe-area-inset-bottom))] z-50 mx-auto max-w-md"],
1341
+ header: ["flex flex-col gap-1 p-4"],
1342
+ footer: ["mt-auto flex flex-col gap-2 p-4"],
1343
+ title: ["text-base font-bold text-foreground-strong"],
1344
+ description: ["text-sm text-foreground/60"]
1345
+ },
1346
+ variants: { theme: {
1347
+ brutal: { content: ["border-2 border-line-strong bg-layer-panel shadow-xl"] },
1348
+ elegant: {}
1349
+ } }
1350
+ });
1351
+ function BottomSheet(props) {
1352
+ return /* @__PURE__ */ jsx(Dialog.Root, { ...props });
1353
+ }
1354
+ function BottomSheetTrigger(props) {
1355
+ return /* @__PURE__ */ jsx(Dialog.Trigger, {
1356
+ "data-slot": "bottom-sheet-trigger",
1357
+ ...props
1358
+ });
1359
+ }
1360
+ function BottomSheetPortal(props) {
1361
+ return /* @__PURE__ */ jsx(Dialog.Portal, {
1362
+ "data-slot": "bottom-sheet-portal",
1363
+ ...props
1364
+ });
1365
+ }
1366
+ function BottomSheetContent({ className, ...props }) {
1367
+ const { content } = bottomSheet({ theme: useThemeFamily() });
1368
+ return /* @__PURE__ */ jsx(BottomSheetPortal, { children: /* @__PURE__ */ jsx(Dialog.Popup, {
1369
+ "data-slot": "bottom-sheet-content",
1370
+ "data-side": "bottom",
1371
+ className: content({ className }),
1372
+ ...props
1373
+ }) });
1374
+ }
1375
+ function BottomSheetClose(props) {
1376
+ return /* @__PURE__ */ jsx(Dialog.Close, {
1377
+ "data-slot": "bottom-sheet-close",
1378
+ ...props
1379
+ });
1380
+ }
1381
+ function BottomSheetHeader({ className, render, ...props }) {
1382
+ const { header } = bottomSheet({ theme: useThemeFamily() });
1383
+ return useRender({
1384
+ defaultTagName: "div",
1385
+ render,
1386
+ props: mergeProps({ className: header({ className }) }, props),
1387
+ state: { slot: "bottom-sheet-header" }
1388
+ });
1389
+ }
1390
+ function BottomSheetFooter({ className, render, ...props }) {
1391
+ const { footer } = bottomSheet({ theme: useThemeFamily() });
1392
+ return useRender({
1393
+ defaultTagName: "div",
1394
+ render,
1395
+ props: mergeProps({ className: footer({ className }) }, props),
1396
+ state: { slot: "bottom-sheet-footer" }
1397
+ });
1398
+ }
1399
+ function BottomSheetTitle({ className, ...props }) {
1400
+ const { title } = bottomSheet({ theme: useThemeFamily() });
1401
+ return /* @__PURE__ */ jsx(Dialog.Title, {
1402
+ "data-slot": "bottom-sheet-title",
1403
+ className: title({ className }),
1404
+ ...props
1405
+ });
1406
+ }
1407
+ function BottomSheetDescription({ className, ...props }) {
1408
+ const { description } = bottomSheet({ theme: useThemeFamily() });
1409
+ return /* @__PURE__ */ jsx(Dialog.Description, {
1410
+ "data-slot": "bottom-sheet-description",
1411
+ className: description({ className }),
1412
+ ...props
1413
+ });
1414
+ }
1415
+ //#endregion
1416
+ export { BottomSheet, BottomSheetClose, BottomSheetContent, BottomSheetDescription, BottomSheetFooter, BottomSheetHeader, BottomSheetPortal, BottomSheetTitle, BottomSheetTrigger, ConversationPreviewCard, ConversationPreviewCardAction, ConversationPreviewCardAuthor, ConversationPreviewCardAuthorName, ConversationPreviewCardAuthorSubtitle, ConversationPreviewCardChannel, ConversationPreviewCardContent, ConversationPreviewCardFooter, ConversationPreviewCardMeta, ConversationPreviewCardPreview, ConversationPreviewCardPreviewAuthor, ConversationPreviewCardPreviewLeading, ConversationPreviewCardSecondaryPreview, ConversationPreviewCardTimestamp, DescriptionAction, DescriptionDetails, DescriptionItem, DescriptionList, DescriptionTerm, Field, FieldControl, FieldDescription, FieldError, FieldItem, FieldLabel, FieldValidity, Lightbox, LightboxActions, LightboxClose, LightboxContent, LightboxHeader, LightboxMedia, LightboxPortal, LightboxStage, LightboxTitle, LightboxTrigger, ListItem, ListItemActionGroup, ListItemBody, ListItemDescription, ListItemIcon, ListItemMeta, ListItemRow, ListItemTitle, MediaListItem, MediaListItemActionGroup, MediaListItemAside, MediaListItemBody, MediaListItemSubtitle, MediaListItemText, MediaListItemTitle, MediaListItemVisual, PanelHeader, PanelHeaderActions, PanelHeaderContent, PanelHeaderIcon, PanelHeaderSubtitle, PanelHeaderSuffix, PanelHeaderTitle, PanelHeaderTitleRow, PanelHeaderVisual, PreviewShell, QuotedMessageCard, QuotedMessageCardAttachments, QuotedMessageCardAuthor, QuotedMessageCardAuthorName, QuotedMessageCardAuthorSubtitle, QuotedMessageCardBody, QuotedMessageCardChannel, QuotedMessageCardContent, QuotedMessageCardContentWrap, QuotedMessageCardHeader, QuotedMessageCardMeta, QuotedMessageCardSeparator, QuotedMessageCardTag, QuotedMessageCardThread, QuotedMessageCardTimestamp, QuotedMessageCardUnavailable, SectionHeader, SectionHeaderActions, SectionHeaderContent, SectionHeaderCount, SectionHeaderIcon, SectionHeaderTitle, SectionLabel, Text, TextHeading, TextMono, TextSans, ToggleGroup, ToggleGroupCount, ToggleGroupItem, ToggleGroupLabel };