@lukeashford/aurelius 4.7.0 → 4.8.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.
@@ -19,6 +19,7 @@
19
19
  /* Core RGB helpers (reduce repeated rgba() literals) */
20
20
  --ink-rgb: 0 0 0;
21
21
  --gold-rgb: 201 162 39;
22
+ --obsidian-rgb: 10 10 10;
22
23
  --glass-rgb: 20 20 20;
23
24
 
24
25
  /* Gold spectrum (derived from one base where possible) */
@@ -182,6 +183,7 @@
182
183
  --animate-cursor-blink: cursor-blink 1s steps(1) infinite;
183
184
  --animate-snake-spin: snake-spin 1.5s linear infinite;
184
185
  --animate-snake-travel: snake-travel 1.5s ease-in-out infinite;
186
+ --animate-pulse-once: pulse-once 600ms ease-out;
185
187
 
186
188
  /* ===== LAYOUT TOKENS ===== */
187
189
  --container-sm: 640px;
@@ -252,6 +254,15 @@
252
254
  }
253
255
  }
254
256
 
257
+ @keyframes pulse-once {
258
+ 0% {
259
+ background-color: rgb(var(--gold-rgb) / 0.3);
260
+ }
261
+ 100% {
262
+ background-color: transparent;
263
+ }
264
+ }
265
+
255
266
  @keyframes cursor-blink {
256
267
  0%,
257
268
  50% {
@@ -475,6 +486,54 @@
475
486
  }
476
487
  }
477
488
 
489
+ /* ===== COMPONENT STYLES =====
490
+ These are component-level CSS classes that use design tokens but need
491
+ cascade-based context overrides — something Tailwind utilities applied
492
+ directly on a JSX element can't do without prop drilling. */
493
+
494
+ /* Mention chip — colours come from CSS variables so the parent prose
495
+ context (`.prose-inherit` user bubble vs `.prose-invert` assistant bubble)
496
+ can override them via the cascade. The defaults below are the
497
+ gold-on-dark variant suitable for the standard charcoal background. */
498
+ @utility aurelius-mention {
499
+ --aurelius-mention-bg: rgb(var(--gold-rgb) / 0.1);
500
+ --aurelius-mention-border: rgb(var(--gold-rgb) / 0.3);
501
+ --aurelius-mention-text: var(--color-gold);
502
+ --aurelius-mention-hover-bg: rgb(var(--gold-rgb) / 0.2);
503
+ --aurelius-mention-x: rgb(var(--gold-rgb) / 0.6);
504
+ --aurelius-mention-x-hover: var(--color-gold);
505
+
506
+ background-color: var(--aurelius-mention-bg);
507
+ border-color: var(--aurelius-mention-border);
508
+ color: var(--aurelius-mention-text);
509
+ transition: background-color 150ms ease, color 150ms ease, border-color 150ms ease;
510
+ }
511
+ .aurelius-mention:hover {
512
+ background-color: var(--aurelius-mention-hover-bg);
513
+ }
514
+
515
+ /* × button inside the chip — colour tracks the chip's text contrast so it
516
+ remains visible in both the gold-on-dark and dark-on-gold variants. */
517
+ @utility aurelius-mention-x {
518
+ color: var(--aurelius-mention-x);
519
+ transition: color 150ms ease;
520
+ }
521
+ .aurelius-mention-x:hover {
522
+ color: var(--aurelius-mention-x-hover);
523
+ }
524
+
525
+ /* When the chip lives inside a user bubble (gold background, dark text),
526
+ gold-on-gold disappears. Override the variables to a dark contrast that
527
+ reads cleanly on the gold backdrop. */
528
+ .prose-inherit .aurelius-mention {
529
+ --aurelius-mention-bg: rgb(var(--obsidian-rgb) / 0.12);
530
+ --aurelius-mention-border: rgb(var(--obsidian-rgb) / 0.45);
531
+ --aurelius-mention-text: rgb(var(--obsidian-rgb) / 0.9);
532
+ --aurelius-mention-hover-bg: rgb(var(--obsidian-rgb) / 0.2);
533
+ --aurelius-mention-x: rgb(var(--obsidian-rgb) / 0.6);
534
+ --aurelius-mention-x-hover: var(--color-obsidian);
535
+ }
536
+
478
537
  /* ===== UTILITY CLASSES ===== */
479
538
  @utility text-gradient-gold {
480
539
  background: linear-gradient(
@@ -506,7 +565,7 @@
506
565
 
507
566
  /* Flex utility for collapsing to zero size (0 0 0%) - use with flex-1 for expand/collapse animations */
508
567
  @utility flex-zero {
509
- flex: 0 0 0%;
568
+ flex: 0 0 0;
510
569
  }
511
570
 
512
571
  @utility font-heading {
package/llms.md CHANGED
@@ -105,41 +105,43 @@ Import from `@lukeashford/aurelius`:
105
105
  | ArtifactLightboxBody | artifact |
106
106
  | ArtifactVariantStack | node, onExpandArtifact, onGroupClick |
107
107
  | AttachmentPreview | attachments, onRemove, removable, maxVisible, onOpen |
108
- | AudioCard | src, title, subtitle, playing, controls, volume, muted, loop, mediaClassName, contentClassName, playerProps, height, loading |
108
+ | AudioCard | src, title, subtitle, handle, playing, controls, volume, muted, loop, mediaClassName, contentClassName, playerProps, height, loading |
109
109
  | Avatar | src, alt, name, size (xs, sm, md, lg, xl, 2xl), status (online, offline, busy) |
110
110
  | Badge | variant (default, gold, success, error, warning, info) |
111
111
  | BrandIcon | size (sm, md, lg), variant (solid, outline) |
112
112
  | Breadcrumb | separator, current |
113
113
  | Button | variant (primary, important, elevated, outlined, featured, ghost, danger), size (sm, md, lg, xl), loading |
114
- | Card | variant (default, elevated, outlined, ghost, featured), interactive, selected, noPadding, loading, title, subtitle, action, align, aspect, position |
114
+ | Card | variant (default, elevated, outlined, ghost, featured), interactive, selected, noPadding, loading, title, subtitle, action, handle, handle, align, aspect, position |
115
115
  | Checkbox | label |
116
116
  | Col | span, offset, order |
117
117
  | ColorSwatch | color, label |
118
+ | Combobox | items, selectedIndex, renderItem, onSelectItem, getItemKey, emptyState, maxHeight |
118
119
  | Container | size (sm, md, lg, xl, fluid, responsive) |
119
- | DeliverableCard | deliverable, title, subtitle, loading |
120
+ | DeliverableCard | deliverable, title, subtitle, handle, loading |
120
121
  | Dialog | description, confirmText, cancelText, onConfirm, onCancel, confirmVariant, isLoading, description, acknowledgeText, variant, description, placeholder, defaultValue, submitText, cancelText, onSubmit, onCancel, isLoading |
121
122
  | Divider | orientation (horizontal, vertical), variant (solid, dashed, dotted), label, color |
122
123
  | Drawer | isOpen, onClose, position (left, right, top, bottom), title, size, children, className |
123
124
  | FileChip | name, size, type, status (pending, uploading, uploaded, analyzing, analyzed, upload_failed, analysis_failed), previewUrl, onRemove, removable, error, artifactId, onOpen |
124
125
  | HelperText | error |
125
- | ImageCard | src, alt, title, subtitle, aspectRatio (${number}/${number}), objectFit, overlay, mediaClassName, contentClassName, loading |
126
+ | ImageCard | src, alt, title, subtitle, handle, aspectRatio (${number}/${number}), objectFit, overlay, mediaClassName, contentClassName, loading |
126
127
  | Input | error, leadingIcon, trailingIcon |
127
128
  | InputGroup | children |
128
129
  | Label | required |
129
130
  | Lightbox | onClose, actions, caption, children, className |
130
131
  | List | variant, ordered, leading, trailing, interactive, selected, disabled, primary, secondary |
131
- | MarkdownContent | content, isMarkdown, sanitizeConfig, isStreaming, cursorClassName |
132
+ | MarkdownContent | children |
133
+ | MentionChip | name, title, leadingIcon, onClick, onRemove |
132
134
  | Menu | children, open, onOpenChange, asChild, align, side, icon, destructive |
133
135
  | Message | variant (user, assistant), content, isStreaming, branchInfo, actions, hideActions, attachments, onAttachmentOpen, onJumpHere, isActive, onClick, label, children, disabled |
134
136
  | Modal | isOpen, onClose, title, children, className |
135
137
  | Navbar | fixed, bordered, position, active, active |
136
138
  | Pagination | page, totalPages, onPageChange, siblingCount, showEdges |
137
- | PdfCard | src, title, subtitle, height, mediaClassName, contentClassName, loading |
139
+ | PdfCard | src, title, subtitle, handle, height, mediaClassName, contentClassName, loading |
138
140
  | Popover | children, trigger, position (top, bottom, left, right), align (start, center, end), open, onOpenChange, closeOnClickOutside |
139
141
  | Progress | value, max, size (sm, md, lg), variant (default, success, warning, error), showValue, formatValue, indeterminate |
140
142
  | Radio | label |
141
143
  | Row | gutter, gutterX, gutterY, justify (start, center, end, between, around, evenly), align (start, center, end, stretch, baseline) |
142
- | ScriptCard | title, subtitle, elements, maxHeight, loading |
144
+ | ScriptCard | title, subtitle, handle, elements, maxHeight, loading |
143
145
  | SectionHeading | level (h2, h3) |
144
146
  | Select | error, options |
145
147
  | Skeleton | children |
@@ -151,14 +153,14 @@ Import from `@lukeashford/aurelius`:
151
153
  | Switch | checked, defaultChecked, onCheckedChange, label |
152
154
  | Table | responsive, hoverable, selected, sortable, sortDirection |
153
155
  | Tabs | defaultValue, value, onValueChange, value, value, forceMount |
154
- | TextCard | content, title, subtitle, isMarkdown, maxHeight, contentClassName, loading |
156
+ | TextCard | content, title, subtitle, handle, isMarkdown, maxHeight, contentClassName, loading |
155
157
  | Textarea | error |
156
158
  | Toast | children, position (top-right, top-left, bottom-right, bottom-left, top-center, bottom-center), defaultDuration |
157
159
  | Tooltip | content, children, open, side (top, right, bottom, left) |
158
- | VideoCard | src, title, subtitle, aspectRatio (${number}/${number}), playing, controls, light, volume, muted, loop, mediaClassName, contentClassName, playerProps, loading |
160
+ | VideoCard | src, title, subtitle, handle, aspectRatio (${number}/${number}), playing, controls, light, volume, muted, loop, mediaClassName, contentClassName, playerProps, loading |
159
161
  | ArtifactsPanel | nodes, loading, openArtifactId, onArtifactClosed, getArtifactActions, artifact, ctx, artifactCount, onExpand |
160
162
  | BranchNavigator | current, total, onPrevious, onNext, size, showIcon |
161
- | ChatInput | position (centered, bottom), placeholder, helperText, onSubmit, disabled, animate, isStreaming, onStop, attachments, onAttachmentsChange, onAttachmentRemove, showAttachmentButton, acceptedFileTypes, notice, onInputChange, initialInputValue, autoFocus |
163
+ | ChatInput | position (centered, bottom), placeholder, helperText, onSubmit, disabled, animate, isStreaming, onStop, attachments, onAttachmentsChange, onAttachmentRemove, showAttachmentButton, acceptedFileTypes, notice, onInputChange, initialInputValue, autoFocus, textareaRef, onTextareaKeyDown |
162
164
  | ChatInterface | messages, conversationTree, onTreeChange, conversations, onMessageSubmit, onEditMessage, onRetryMessage, onJumpHere, onJumpToLatest, onStop, onSelectConversation, onNewChat, onRenameConversation, isStreaming, isThinking, thinkingLabel, placeholder, emptyStateHelper, emptyState, showAttachmentButton, enableMessageActions, attachments, onAttachmentsChange, onAttachmentRemove, onAttachmentOpen, artifactNodes, isArtifactsPanelOpen, onArtifactsPanelOpenChange, getArtifactActions, artifact, ctx |
163
165
  | ChatView | items, latestUserMessageIndex |
164
166
  | Checkpoint | name, executionKind (task, submit, rename, init, ingest), status (completed, failed, cancelled), isActive, muted, branchInfo, onJumpHere |
@@ -267,8 +269,32 @@ navigate for groups).
267
269
  - **onOpen**: * Click handler for chips with an artifactId. When set, chips that carry an artifactId become clickable and forward the id to this handler.
268
270
 
269
271
  **AudioCard**
272
+ - **handle**: The artifact's `@-handle` — see `Card.Header.handle`.
270
273
  - **playerProps**: Forwarded to the underlying ReactPlayer.
271
274
 
275
+ **Card**
276
+ - **handle**: * Optional addressable handle (the artifact's `name` / `@-handle`). Renders as a tertiary monospace line below the subtitle, prefixed with `@`. Click copies `@<handle>` to the clipboard and pulses the handle once. Use to surface the typed identifier filmmakers reference in chat.
277
+
278
+ **Combobox**
279
+ Floating panel for inline autocompletes — `@`-mention pickers, slash-command menus, and
280
+ the like. The panel is unstyled-positioned (`absolute`) so the caller controls placement
281
+ via wrapper, `style`, or by mounting it inside their own positioned container; this keeps
282
+ the component agnostic to how the trigger position is computed (caret coordinates, ref
283
+ rect, popover anchor).
284
+
285
+ Pair with `useComboboxNav` for the standard arrow-key + Enter/Escape behaviour.
286
+
287
+ - **items**: * Items to display in the panel. The caller is responsible for filtering before passing.
288
+ - **selectedIndex**: * Index of the currently highlighted (focused, not yet picked) item. Drive this from `useComboboxNav` for the standard arrow-key behaviour, or manage it yourself.
289
+ - **renderItem**: * Render one row. `isSelected` reflects the keyboard highlight; click and hover styling are applied by the panel.
290
+ - **onSelectItem**: * Called when the user clicks a row. Use the same handler you call from the keyboard's Enter key to keep mouse and keyboard paths consistent.
291
+ - **getItemKey**: * Stable key per item. Required because the panel re-mounts rows when `items` changes.
292
+ - **emptyState**: * Optional node rendered when `items` is empty. Skip the panel entirely if you'd rather hide it on no-match.
293
+ - **maxHeight**: * Maximum pixel height of the scrollable list. The panel itself sizes to its content up to this cap; rows beyond it scroll within the panel. @default 256
294
+ - **ComboboxNav.handleKeyDown**: * Standard handler for ArrowUp / ArrowDown / Enter / Escape. Returns true when a key was consumed — the caller should skip its own handling for those events.
295
+ - **UseComboboxNavOptions.onSelect**: * Called when the user presses Enter on the highlighted item.
296
+ - **UseComboboxNavOptions.onDismiss**: * Called when the user presses Escape.
297
+
272
298
  **DeliverableCard**
273
299
  Compact preview of a deliverable for surfaces that can't host the full
274
300
  multi-page renderer (chat tree, artifact lists). Surfaces the deliverable's
@@ -279,6 +305,7 @@ for every artifact kind, so we don't add a "Open preview" lure here.
279
305
  - **deliverable**: * Resolved deliverable spec — every artifact reference already inflated. Same shape the full DeliverableRenderer accepts.
280
306
  - **title**: Optional override for the cover title (otherwise derived from the spec).
281
307
  - **subtitle**: Optional subtitle shown below the title.
308
+ - **handle**: The artifact's `@-handle` — see `Card.Header.handle`.
282
309
 
283
310
  **FileChip**
284
311
  - **name**: * File name to display
@@ -292,6 +319,9 @@ for every artifact kind, so we don't add a "Open preview" lure here.
292
319
  - **artifactId**: * Backend artifact id, set once the upload has been integrated. When both `artifactId` and `onOpen` are present, the chip becomes clickable.
293
320
  - **onOpen**: * Click handler invoked with `artifactId` when the chip is clicked. Compose-box (pre-integrate) chips should not pass this — the chip stays non-clickable except for its remove button.
294
321
 
322
+ **ImageCard**
323
+ - **handle**: The artifact's `@-handle` — see `Card.Header.handle`.
324
+
295
325
  **Lightbox**
296
326
  Full-bleed modal canvas for one piece of content. Premium-haptic alternative
297
327
  to a bordered modal: deep void backdrop, scale-fade entrance, no inner frame,
@@ -311,10 +341,29 @@ close button in the action cluster.
311
341
  - **children**: * The artifact body. Sits directly on the backdrop with no inner frame — the body is responsible for its own layout (object-contain image, scrollable deliverable, readable text column, etc.). Click events whose target is the sized content wrapper (i.e. the empty area around the body) dismiss the lightbox; clicks on the body itself do not.
312
342
 
313
343
  **MarkdownContent**
314
- - **content**: * Content to display (can be Markdown or HTML)
315
- - **isMarkdown**: * Whether the content should be treated as Markdown @default true
316
- - **isStreaming**: * When true, injects a streaming cursor at the end of the content
317
- - **cursorClassName**: * Additional classes for the streaming cursor
344
+ Renders Markdown content into a real React tree via `react-markdown`. Drop-in for prose
345
+ surfaces (chat messages, artifact bodies, deliverable text). Optional `mentionRenderer`
346
+ adds inline `@artifact_name` chip rendering see prop docs.
347
+
348
+ Raw HTML in the source is escaped (not rendered) by react-markdown's defaults; this is
349
+ intentional and safer than the previous pipeline. Pass markdown.
350
+
351
+
352
+ **MentionChip**
353
+ Inline chip representing an `@name` artifact mention. Use anywhere a stable reference to a
354
+ project artifact appears — typed input previews, rendered chat messages, deliverable
355
+ descriptions. Renders the name in monospace with a leading `@` glyph and a gold-tinted border,
356
+ mirroring the addressable handle the user sees on the artifact card.
357
+
358
+ Pair with the `Combobox` primitive for the typing surface, and with the
359
+ `MarkdownContent` `mentionRenderer` prop to render mentions inline inside rendered chat
360
+ messages — typically `mentionRenderer={(name) => <MentionChip name={name} … />}`.
361
+
362
+ - **name**: * The artifact name (the @-handle, without the leading @).
363
+ - **title**: * Optional human-readable title; shown in the hover tooltip alongside the name.
364
+ - **leadingIcon**: * Optional icon rendered before the name — typically a kind glyph (e.g. `FileImage`, `FileVideo`) or `HelpCircle` for unknown / stale references. Sized at `w-3 h-3` to match the chip's text scale.
365
+ - **onClick**: * Called when the chip is clicked. When provided, the chip becomes keyboard-focusable and gains a hover affordance.
366
+ - **onRemove**: * Called when the remove (×) button is clicked. When provided, an × appears on hover/focus. Use only on input-side previews; rendered messages should leave this unset.
318
367
 
319
368
  **Message**
320
369
  - **MessageBranchInfo.current**: * Current branch index (1-based)
@@ -341,6 +390,7 @@ A card for displaying PDF documents with an embedded viewer.
341
390
  - **src**: * URL of the PDF file
342
391
  - **title**: * Title of the document
343
392
  - **subtitle**: * Subtitle or document metadata
393
+ - **handle**: The artifact's `@-handle` — see `Card.Header.handle`.
344
394
  - **height**: * Height of the PDF viewer
345
395
  - **mediaClassName**: * Optional class name for the media container
346
396
  - **contentClassName**: * Optional class name for the content container
@@ -380,6 +430,7 @@ Follows standard screenplay formatting conventions:
380
430
  - **ScriptElement.content**: * The text content of the element
381
431
  - **title**: * Title of the script (shown at top)
382
432
  - **subtitle**: * Subtitle/metadata (e.g., "30-second spot • Directed by AI Creative")
433
+ - **handle**: The artifact's `@-handle` — see `Card.Header.handle`.
383
434
  - **elements**: * Array of script elements in order. Available types: 'scene-heading', 'action', 'character', 'dialogue', 'parenthetical', 'transition', 'title', 'subtitle'
384
435
  - **maxHeight**: * Maximum height before scrolling (default: 16rem / 256px)
385
436
 
@@ -401,11 +452,13 @@ A card for displaying text content, supporting Markdown and HTML formatting.
401
452
  - **content**: * Text content to display (Markdown, HTML, or plain text)
402
453
  - **title**: * Optional title for the card
403
454
  - **subtitle**: * Optional subtitle or metadata
455
+ - **handle**: The artifact's `@-handle` — see `Card.Header.handle`.
404
456
  - **isMarkdown**: * Whether the content should be treated as Markdown @default true
405
457
  - **maxHeight**: * Maximum height of the content area before scrolling @default '16rem'
406
458
  - **contentClassName**: * Optional class name for the content container
407
459
 
408
460
  **VideoCard**
461
+ - **handle**: The artifact's `@-handle` — see `Card.Header.handle`.
409
462
  - **playerProps**: Forwarded to the underlying ReactPlayer.
410
463
 
411
464
  **ArtifactsPanel**
@@ -472,6 +525,8 @@ Features:
472
525
  - **onInputChange**: * Called whenever the input value changes, giving the consumer access to the current text
473
526
  - **initialInputValue**: * Initial value for the input, used for state restoration (e.g. from DB or localStorage)
474
527
  - **autoFocus**: * Whether to automatically focus the input when it becomes enabled
528
+ - **textareaRef**: * Optional ref forwarded to the underlying `<textarea>`. Use this to drive an inline autocomplete (e.g. an `@`-mention picker) — read selection/caret position, mirror the textarea for caret coordinates, or imperatively update its value.
529
+ - **onTextareaKeyDown**: * Optional keydown hook that runs before the input's own handling. Call `e.preventDefault()` to stop ChatInput from acting on the event — for example, to keep Enter from submitting while an autocomplete is consuming it. The submit-on-Enter and default newline behaviours both check `defaultPrevented` and skip when set.
475
530
 
476
531
  **ChatInterface**
477
532
  ChatInterface is the main orchestrator for a full-featured chat experience.
@@ -783,7 +838,7 @@ Standard Tailwind classes for size (`text-sm`, `text-lg`, etc.), weight (`font-m
783
838
  **Columns (Tailwind built-in):** `col-span-{1-12}`, `col-span-full`, `col-auto`, `sm:col-span-*`, `md:col-span-*`, `lg:col-span-*`, `xl:col-span-*`
784
839
 
785
840
  ### Custom Utilities
786
- text-gradient-gold, glow, glow-sm, glow-md, glow-lg, flex-zero, font-heading, font-body, scroll-smooth, scrollbar-hide, backdrop-glass, focus-ring, line-clamp-2, line-clamp-3, center-absolute, aspect-wide, container, container-sm, container-md, container-lg, container-xl, container-fluid, row
841
+ aurelius-mention, aurelius-mention-x, text-gradient-gold, glow, glow-sm, glow-md, glow-lg, flex-zero, font-heading, font-body, scroll-smooth, scrollbar-hide, backdrop-glass, focus-ring, line-clamp-2, line-clamp-3, center-absolute, aspect-wide, container, container-sm, container-md, container-lg, container-xl, container-fluid, row
787
842
 
788
843
  ### Opacity modifiers
789
844
  Append `/10`, `/20`, `/30`, etc. to colors: `bg-gold/20`, `border-ash/50`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lukeashford/aurelius",
3
- "version": "4.7.0",
3
+ "version": "4.8.0",
4
4
  "description": "Design system for Aurelius applications — A cohesive visual language for creative technologists",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -86,7 +86,6 @@
86
86
  "@testing-library/jest-dom": "^6.6.3",
87
87
  "@testing-library/react": "^16.1.0",
88
88
  "@testing-library/user-event": "^14.5.2",
89
- "@types/dompurify": "^3.0.5",
90
89
  "@types/jest": "^29.5.14",
91
90
  "@types/marked": "^5.0.2",
92
91
  "@types/node": "^20.0.0",
@@ -129,11 +128,12 @@
129
128
  "dependencies": {
130
129
  "@tailwindcss/typography": "^0.5.15",
131
130
  "clsx": "^2.1.1",
132
- "dompurify": "^3.3.1",
133
131
  "lucide-react": "^0.555.0",
134
- "marked": "^15.0.12",
132
+ "react-markdown": "^10.1.0",
135
133
  "react-player": "^3.4.0",
136
- "tailwind-merge": "^3.4.0"
134
+ "remark-gfm": "^4.0.1",
135
+ "tailwind-merge": "^3.4.0",
136
+ "unist-util-visit": "^5.1.0"
137
137
  },
138
138
  "overrides": {
139
139
  "@tootallnate/once": "3.0.1",