2 additions and 1 change.
@oztix/roadie-components/css — a Tailwind source-registration entry.Tailwind v4 ignores node_modules, so consumers previously hand-wrote @source "../../node_modules/@oztix/roadie-components/dist" (brittle when globals.css moves). Now @import '@oztix/roadie-components/css' — the package ships its own @source relative to itself. Each package's CSS registers only its own classes, so import every Roadie package you use. - Separator hairline fix — it now renders a true 1px line. The base border applied width to all four sides, so with h-px the top and bottom both painted (~2px). Colour/style now live in the base and each orientation sets a single-side width (border-t / border-l).
SeeSeparator
All changes are additive and backward-compatible.
New standalone CartContents widget
@oztix/roadie-widgets/cart-contents/react and .../vue export
CartContents — the day-grouped event/ticket list (sticky day headers, event
images, reserved-seat range badges, per-event remove with animated exit) — plus
(React) CartContentsProps and the CartDetails / CartEvent / CartTicket
/ CartSeat types. Pulls in only the list (no overlay, drag, focus-trap, or
expiry code).CartContents is now the canonical home of the list and CartDrawer composes
it (the drawer depends on cart-contents, never the reverse — no duplication).container prop picks the layout preset: drawer (default) is the body-only
list; page is the full standalone /cart experience — a fill-height column
with a Cart header (ticket count + live expiry), a sticky edge-to-edge
footer, and a centred empty state. Give the parent a height (e.g.
<div className="min-h-full">); no external flex-1 / mt-auto /
justify-center needed.CartFooter) and CartUrgencyBadge are shared
internal components, so the page and drawer keep identical spacing.removingEventId prop drives a per-event loading state: set it for the
duration of your async remove and the list dims with a danger Removing…
overlay (a blurred, header-aligned panel over that event) until it leaves the
cart. CartDrawer wires this through its own remove flow, replacing the old
centre spinner. The page container also uses the larger (md) empty-state
size; drawer keeps the compact (sm) one.CartDrawer
open prop (React + Vue, with v-model:open on Vue)
opens/closes the drawer from anywhere in your UI (e.g. an inline "View cart"
button), animating with the same spring as a tap. Standard controllable
pattern — open drives it, tap/drag report via onOpenChange. Omit open for
the existing uncontrolled behaviour seeded by initialState.eventEndAtUtc (and venue-local
eventEndDateKey) for a finish time (7pm – 11pm) or multi-day range
(6:30pm – Sun 4 Oct, 9pm) via shared formatEventSchedule / formatDayShort
core helpers.eventTimeZone (IANA id) renders schedule
times in venue-local time via the shared formatTime helper; omitted = browser
time as before; an invalid id safely falls back rather than throwing.CartTicket.seats takes structured CartSeat[]
(section / row / seat); the shared formatSeatRange core helper collapses
consecutive seats into ranges (Stalls B11–12, Mezzanine M3 · Circle C5),
rendered as a seat-icon badge. Omit for general admission.motion (open/
close, drag), surface pop-in and empty-close fades, and the remove-confirm
dialog animate to match; reduced motion gates the ticket bounce. The Vue skin
now imports motion — install it alongside the other Vue peers.Shared core + CSS
@oztix/roadie-widgets/cart — the framework-agnostic core (types,
createCartClient, formatters) promoted out of the cart-drawer folder.
@oztix/roadie-widgets/cart-drawer/core still works as a deprecated
re-export (removed in the next major).@oztix/roadie-widgets/css — a Tailwind source-registration entry that
ships its own @source, so consumers @import '@oztix/roadie-widgets/css'
instead of hand-writing a node_modules path. It registers only the widget
classes; React consumers also import @oztix/roadie-components/css (the React
skins render Roadie components), Vue consumers don't.emphasis-overlay now adapts to the active intent.Its scrim is built from the intent hue (oklch(0.1 0.04 var(--intent-hue) / 0.55)) instead of a fixed rgba(0,0,0,0.5), so intent-danger emphasis-overlay reads as a dark red glass, intent-accent as a dark accent glass, etc. — while neutral stays a near-black scrim. The lightness is fixed so it remains a proper scrim in both light and dark themes (the intent scale flips between them).