From ba94f74b91e09ce7ffd4a666562d555b3fbd2fb9 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Wed, 25 Feb 2026 14:38:57 +1100 Subject: [PATCH] feat(skin): add error dialogs (#603) --- commitlint.config.js | 1 + .../react/src/presets/video/minimal-skin.css | 437 ++++++++---- .../presets/video/minimal-skin.tailwind.tsx | 127 ++-- .../react/src/presets/video/minimal-skin.tsx | 37 +- packages/react/src/presets/video/skin.css | 455 +++++++++---- .../react/src/presets/video/skin.tailwind.tsx | 127 ++-- packages/react/src/presets/video/skin.tsx | 39 +- .../src/ui/error-dialog/error-dialog.tsx | 83 +++ packages/react/src/ui/error-dialog/index.ts | 1 + packages/react/src/utils/use-render.tsx | 2 +- packages/sandbox/package.json | 7 +- packages/sandbox/src/index.html | 3 +- packages/sandbox/templates/constants.ts | 1 + packages/sandbox/templates/html/main.ts | 2 +- packages/sandbox/templates/index.html | 18 + .../templates/react-tailwind/index.html | 13 + .../sandbox/templates/react-tailwind/main.tsx | 46 ++ packages/sandbox/templates/react/main.tsx | 28 +- packages/sandbox/templates/react/skins.tsx | 34 + packages/sandbox/templates/styles.css | 2 + packages/sandbox/templates/types.ts | 3 + packages/sandbox/templates/vite-env.d.ts | 1 + packages/sandbox/vite.config.ts | 3 +- pnpm-lock.yaml | 642 +++++++++++++++--- site/package.json | 6 +- 25 files changed, 1641 insertions(+), 477 deletions(-) create mode 100644 packages/react/src/ui/error-dialog/error-dialog.tsx create mode 100644 packages/react/src/ui/error-dialog/index.ts create mode 100644 packages/sandbox/templates/constants.ts create mode 100644 packages/sandbox/templates/index.html create mode 100644 packages/sandbox/templates/react-tailwind/index.html create mode 100644 packages/sandbox/templates/react-tailwind/main.tsx create mode 100644 packages/sandbox/templates/react/skins.tsx create mode 100644 packages/sandbox/templates/types.ts create mode 100644 packages/sandbox/templates/vite-env.d.ts diff --git a/commitlint.config.js b/commitlint.config.js index 2d5dc413..cbe21528 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -30,6 +30,7 @@ export default { 'root', 'sandbox', 'site', + 'skin', 'store', 'test', 'utils', diff --git a/packages/react/src/presets/video/minimal-skin.css b/packages/react/src/presets/video/minimal-skin.css index 5de21ec4..de1abc5c 100644 --- a/packages/react/src/presets/video/minimal-skin.css +++ b/packages/react/src/presets/video/minimal-skin.css @@ -1,141 +1,265 @@ +/* ========================================================================== + Reset + ========================================================================== */ + +.media-minimal-skin *, +.media-minimal-skin *::before, +.media-minimal-skin *::after { + box-sizing: border-box; + margin: 0; +} +.media-minimal-skin img, +.media-minimal-skin video, +.media-minimal-skin svg { + display: block; + max-width: 100%; +} +.media-minimal-skin button { + font: inherit; +} +@media (prefers-reduced-motion: no-preference) { + .media-minimal-skin { + interpolate-size: allow-keywords; + } +} + +/* ========================================================================== + Root Container + ========================================================================== */ + .media-minimal-skin { position: relative; isolation: isolate; container: media-root / inline-size; overflow: clip; border-radius: var(--media-border-radius, 0.75rem); - background: oklab(0 0 0); - font-family: ui-sans-serif, system-ui, sans-serif; + background: oklch(0 0 0); + font-family: + Inter Variable, + Inter, + ui-sans-serif, + system-ui, + sans-serif; font-size: 0.8125rem; line-height: 1.5; + letter-spacing: normal; -webkit-font-smoothing: auto; -moz-osx-font-smoothing: auto; } -.media-minimal-skin * { - box-sizing: border-box; -} + +/* Border ring */ .media-minimal-skin::after { content: ""; position: absolute; - pointer-events: none; - border-radius: inherit; - z-index: 10; inset: 0; - box-shadow: inset 0 0 0 1px oklab(0 0 0 / 0.15); + z-index: 10; + border-radius: inherit; + box-shadow: inset 0 0 0 1px oklch(0 0 0 / 0.15); + pointer-events: none; } @media (prefers-color-scheme: dark) { .media-minimal-skin::after { - box-shadow: inset 0 0 0 1px oklab(1 0 0 / 0.15); + box-shadow: inset 0 0 0 1px oklch(1 0 0 / 0.15); } } -/* Buffering indicator */ -.media-minimal-skin .media-buffering-indicator { - position: absolute; - inset: 0; - display: flex; - align-items: center; - justify-content: center; - pointer-events: none; - z-index: 10; - color: #fff; -} - -/* Poster image */ -.media-minimal-skin > img { - position: absolute; - inset: 0; - width: 100%; - height: 100%; - object-fit: cover; - pointer-events: none; - transition: opacity 0.25s; -} -.media-minimal-skin > img:not([data-visible]) { - opacity: 0; -} - /* Fullscreen */ .media-minimal-skin:fullscreen { border-radius: 0; } +/* ========================================================================== + Media Element + ========================================================================== */ + .media-minimal-skin > video { - display: block; width: 100%; height: 100%; } -/* Media Container UI Overlay Styling */ +/* ========================================================================== + Poster Image + ========================================================================== */ + +.media-minimal-skin > img { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + transition: opacity 0.25s; + pointer-events: none; +} +.media-minimal-skin > img:not([data-visible]) { + opacity: 0; +} + +/* ========================================================================== + Overlay / Scrim + ========================================================================== */ + .media-minimal-skin .media-overlay { position: absolute; inset: 0; - pointer-events: none; border-radius: inherit; - background-image: linear-gradient(to top, oklab(0 0 0 / 0.7), oklab(0 0 0 / 0.5) 7.5rem, rgba(0, 0, 0, 0)); - backdrop-filter: saturate(1.5) brightness(0.9); - transition-delay: 500ms; - transition-duration: 500ms; - transition-behavior: allow-discrete; - transition-property: opacity, display; - transition-timing-function: ease-out; + background-image: linear-gradient(to top, oklch(0 0 0 / 0.7), oklch(0 0 0 / 0.5) 7.5rem, oklch(0 0 0 / 0)); + backdrop-filter: blur(0) saturate(1.5) brightness(0.9); opacity: 0; - display: none; + transition-property: opacity, backdrop-filter; + transition-duration: 500ms; + transition-delay: 500ms; + transition-timing-function: ease-out; + pointer-events: none; } @media (prefers-reduced-motion: reduce) { .media-minimal-skin .media-overlay { transition-duration: 100ms; } } -.media-minimal-skin .media-controls[data-visible] ~ .media-overlay { - transition-duration: 50ms; - transition-delay: 0ms; +.media-minimal-skin .media-controls[data-visible] ~ .media-overlay, +.media-minimal-skin .media-error[data-visible] ~ .media-overlay { opacity: 1; - display: block; + transition-duration: 150ms; + transition-delay: 0ms; +} +.media-minimal-skin .media-error[data-visible] ~ .media-overlay { + backdrop-filter: blur(8px) saturate(1.5) brightness(0.9); } -/* Media Control Bar UI/Styles */ +/* ========================================================================== + Buffering Indicator + ========================================================================== */ + +.media-minimal-skin .media-buffering-indicator { + position: absolute; + inset: 0; + z-index: 10; + display: flex; + align-items: center; + justify-content: center; + color: oklch(1 0 0); + pointer-events: none; +} + +/* ========================================================================== + Error Dialog + ========================================================================== */ + +.media-minimal-skin .media-error { + display: none; +} +.media-minimal-skin .media-error[data-visible] { + position: absolute; + inset: 0; + z-index: 20; + display: flex; + align-items: center; + justify-content: center; + pointer-events: none; +} +.media-minimal-skin .media-error__dialog { + display: none; + transition-property: display, opacity, transform; + transition-duration: 500ms; + transition-delay: 100ms; + transition-behavior: allow-discrete; + transition-timing-function: linear( + 0, + 0.034 1.5%, + 0.763 9.7%, + 1.066 13.9%, + 1.198 19.9%, + 1.184 21.8%, + 0.963 37.5%, + 0.997 50.9%, + 1 + ); +} +.media-minimal-skin .media-error[data-visible] .media-error__dialog { + display: flex; + flex-direction: column; + gap: 0.75rem; + max-width: 16rem; + padding: 1rem; + color: oklch(1 0 0); + font-size: 0.875rem; + text-shadow: 0 1px 0 oklch(0 0 0 / 0.5); + pointer-events: auto; + transform: scale(1); + opacity: 1; + color: oklch(1 0 0); + + @starting-style { + transform: scale(0.5); + opacity: 0; + } +} +.media-minimal-skin .media-error__content { + display: flex; + flex-direction: column; + gap: 0.5rem; + padding: 0.375rem 0; +} +.media-minimal-skin .media-error__title { + font-weight: 600; + line-height: 1.25; +} +.media-minimal-skin .media-error__actions { + display: flex; + gap: 0.5rem; +} +.media-minimal-skin .media-error__actions > * { + flex: 1; +} + +/* ========================================================================== + Controls + ========================================================================== */ + .media-minimal-skin .media-controls { position: absolute; - container: media-controls / inline-size; bottom: 0; inset-inline: 0; - padding: 2rem 0.375rem 0.375rem 0.375rem; + z-index: 10; + container: media-controls / inline-size; display: flex; align-items: center; gap: 0.5rem; + padding: 2rem 0.375rem 0.375rem 0.375rem; + color: oklch(1 0 0); will-change: transform, filter, opacity; transition-property: transform, filter, opacity; - transition-delay: 0ms; transition-duration: 75ms; + transition-delay: 0ms; transition-timing-function: ease-out; - color: oklab(1 0 0); - z-index: 10; } .media-minimal-skin .media-controls:not([data-visible]) { opacity: 0; transform: translateY(100%); filter: blur(8px); - transition-delay: 500ms; transition-duration: 500ms; + transition-delay: 500ms; pointer-events: none; } @media (prefers-reduced-motion: reduce) { .media-minimal-skin .media-controls:not([data-visible]) { - transition-duration: 100ms; + scale: 1; transform: translateY(0); filter: blur(0); - scale: 1; + transition-duration: 100ms; } } @container media-root (width > 40rem) { .media-minimal-skin .media-controls { - padding: 2.5rem 0.75rem 0.75rem 0.75rem; gap: 0.875rem; + padding: 2.5rem 0.75rem 0.75rem 0.75rem; } } -/* Time Controls */ +/* ========================================================================== + Time Controls & Display + ========================================================================== */ + .media-minimal-skin .media-time-controls { display: flex; flex-direction: row-reverse; @@ -148,21 +272,21 @@ align-items: center; gap: 0.25rem; } +.media-minimal-skin .media-time__value { + font-variant-numeric: tabular-nums; + text-shadow: 0 1px 0 oklch(0 0 0 / 0.2); +} .media-minimal-skin .media-time__value--current, .media-minimal-skin .media-time__separator { display: none; } -.media-minimal-skin .media-time__value { - text-shadow: 0 1px 0 oklab(0 0 0 / 0.2); - font-variant-numeric: tabular-nums; -} @container media-controls (width > 28rem) { .media-minimal-skin .media-time-controls { flex-direction: row; } .media-minimal-skin .media-time__value--duration, .media-minimal-skin .media-time__separator { - color: oklab(1 0 0 / 0.5); + color: oklch(1 0 0 / 0.5); } .media-minimal-skin .media-time__value--current, .media-minimal-skin .media-time__separator { @@ -170,7 +294,10 @@ } } -/* Button Groups (layout only) */ +/* ========================================================================== + Button Groups + ========================================================================== */ + .media-minimal-skin .media-button-group { display: flex; align-items: center; @@ -182,45 +309,68 @@ } } -/* Buttons */ +/* ========================================================================== + Buttons + ========================================================================== */ + +/* Base button */ .media-minimal-skin .media-button { - display: grid; + display: flex; + align-items: center; + justify-content: center; flex-shrink: 0; - padding: 0.625rem; - cursor: pointer; - background: transparent; + padding: 0.5rem 1rem; + background: oklch(1 0 0); border: none; - border-radius: 0.375rem; - color: oklab(1 0 0); - user-select: none; + border-radius: 0.5rem; outline: 2px solid transparent; outline-offset: -2px; + color: oklch(0 0 0); + font-weight: 500; transition-property: background-color, color, outline-offset; transition-duration: 150ms; transition-timing-function: ease-out; -} -.media-minimal-skin .media-button:hover, -.media-minimal-skin .media-button:focus-visible, -.media-minimal-skin .media-button[aria-expanded="true"] { - color: oklab(1 0 0 / 0.8); - text-decoration: none; + cursor: pointer; + user-select: none; } .media-minimal-skin .media-button:focus-visible { - outline-color: oklab(1 0 0); + outline-color: oklch(1 0 0); outline-offset: 2px; } .media-minimal-skin .media-button[disabled] { - cursor: not-allowed; opacity: 0.5; filter: grayscale(1); + cursor: not-allowed; } + +/* Icon button variant */ +.media-minimal-skin .media-button--icon { + display: grid; + padding: 0.625rem; + background: transparent; + color: oklch(1 0 0); +} +.media-minimal-skin .media-button--icon:hover, +.media-minimal-skin .media-button--icon:focus-visible, +.media-minimal-skin .media-button--icon[aria-expanded="true"] { + color: oklch(1 0 0 / 0.8); + text-decoration: none; +} +.media-minimal-skin .media-button--icon .media-icon { + filter: drop-shadow(0 1px 0 oklch(0 0 0 / 0.25)); +} + +/* Seek button variant — hidden at small sizes */ @container media-controls (width < 28rem) { .media-minimal-skin .media-button--seek { display: none; } } -/* Icons */ +/* ========================================================================== + Icons + ========================================================================== */ + .media-minimal-skin .media-icon__container { position: relative; } @@ -228,7 +378,6 @@ grid-area: 1 / 1; width: 18px; height: 18px; - filter: drop-shadow(0 1px 0 oklab(0 0 0 / 0.25)); transition-behavior: allow-discrete; transition-property: display, opacity; transition-duration: 150ms; @@ -241,89 +390,92 @@ .media-minimal-skin .media-icon--flipped { scale: -1 1; } + +/* Seek icon label positioning */ .media-minimal-skin .media-icon--seek ~ .media-icon__label { position: absolute; right: 0; bottom: -3px; font-size: 0.75em; font-weight: 480; + font-variant-numeric: tabular-nums; } .media-minimal-skin .media-icon--seek.media-icon--flipped ~ .media-icon__label { - left: 0; right: unset; + left: 0; } -/* TimeSlider Component Styles */ +/* ========================================================================== + Slider + ========================================================================== */ + .media-minimal-skin .media-slider { - flex: 1; + position: relative; display: flex; align-items: center; justify-content: center; - position: relative; + flex: 1; border-radius: calc(infinity * 1px); outline: none; } -/* Horizontal orientation styles */ +/* Horizontal orientation */ .media-minimal-skin .media-slider[data-orientation="horizontal"] { min-width: 5rem; width: 100%; height: 1.25rem; } -/* Vertical orientation styles */ +/* Vertical orientation */ .media-minimal-skin .media-slider[data-orientation="vertical"] { - height: 4.5rem; width: 1.25rem; + height: 4.5rem; } +/* Track */ .media-minimal-skin .media-slider__track { position: relative; isolation: isolate; - background-color: oklab(1 0 0 / 0.2); - border-radius: inherit; overflow: hidden; - user-select: none; + background-color: oklch(1 0 0 / 0.2); + border-radius: inherit; outline: 2px solid transparent; outline-offset: -2px; + box-shadow: 0 0 0 1px oklch(0 0 0 / 0.05); transition: outline-offset 150ms ease-out; - box-shadow: 0 0 0 1px oklab(0 0 0 / 0.05); + user-select: none; } - -/* Horizontal track styles */ .media-minimal-skin .media-slider__track[data-orientation="horizontal"] { width: 100%; height: 0.1875rem; } - -/* Vertical track styles */ .media-minimal-skin .media-slider__track[data-orientation="vertical"] { width: 0.1875rem; height: 100%; } - .media-minimal-skin .media-slider:focus-visible .media-slider__track { - outline-color: oklab(1 0 0); + outline-color: oklch(1 0 0); outline-offset: 6px; } +/* Thumb */ .media-minimal-skin .media-slider__thumb { + z-index: 10; width: 0.75rem; height: 0.75rem; - background-color: oklab(1 0 0); + background-color: oklch(1 0 0); border-radius: calc(infinity * 1px); - user-select: none; - z-index: 10; box-shadow: - 0 0 0 1px oklab(0 0 0 / 0.1), - 0 1px 3px 0 oklab(0 0 0 / 0.15), - 0 1px 2px -1px oklab(0 0 0 / 0.15); + 0 0 0 1px oklch(0 0 0 / 0.1), + 0 1px 3px 0 oklch(0 0 0 / 0.15), + 0 1px 2px -1px oklch(0 0 0 / 0.15); opacity: 0; scale: 0.7; transform-origin: center; transition-property: opacity, scale; transition-duration: 150ms; transition-timing-function: ease-out; + user-select: none; } .media-minimal-skin .media-slider:hover .media-slider__thumb, .media-minimal-skin .media-slider:focus-within .media-slider__thumb { @@ -337,31 +489,38 @@ cursor: ns-resize; } +/* Pointer (hidden in minimal skin) */ .media-minimal-skin .media-slider__pointer { display: none; } +/* Progress fill */ .media-minimal-skin .media-slider__progress { - background-color: oklab(1 0 0); + background-color: oklch(1 0 0); border-radius: inherit; } +/* Time display within slider */ .media-minimal-skin .media-slider__time-display { font-variant-numeric: tabular-nums; } +/* ========================================================================== + Popups & Animations + ========================================================================== */ + .media-minimal-skin .media-popup-animation { - transition-property: transform, scale, opacity, filter; - transition-duration: 200ms; + opacity: 1; transform: scale(1); transform-origin: bottom; - opacity: 1; filter: blur(0px); + transition-property: transform, scale, opacity, filter; + transition-duration: 200ms; } .media-minimal-skin .media-popup-animation[data-starting-style], .media-minimal-skin .media-popup-animation[data-ending-style] { - transform: scale(0); opacity: 0; + transform: scale(0); filter: blur(8px); } .media-minimal-skin .media-popup-animation[data-instant] { @@ -369,49 +528,55 @@ } .media-minimal-skin .media-popover-popup { - padding: 0.5rem; margin: 0; + padding: 0.5rem; border: 0; background: transparent; } -/* Tooltip Component Styles */ +/* ========================================================================== + Tooltips + ========================================================================== */ + .media-minimal-skin .media-tooltip { white-space: nowrap; } .media-minimal-skin .media-tooltip-popup { - color: oklab(1 0 0); padding: 0.25rem 0.5rem; border-radius: 0.25rem; - font-size: 0.75rem; - background-color: oklab(1 0 0 / 0.1); + background-color: oklch(1 0 0 / 0.1); backdrop-filter: blur(64px) brightness(0.9) saturate(1.5); box-shadow: - 0 4px 6px -1px oklab(0 0 0 / 0.1), - 0 2px 4px -2px oklab(0 0 0 / 0.1); + 0 4px 6px -1px oklch(0 0 0 / 0.1), + 0 2px 4px -2px oklch(0 0 0 / 0.1); + color: oklch(1 0 0); + font-size: 0.75rem; } @media (prefers-reduced-transparency: reduce) { .media-minimal-skin .media-tooltip-popup { - background-color: oklab(0 0 0 / 0.7); + background-color: oklch(0 0 0 / 0.7); } } @media (prefers-contrast: more) { .media-minimal-skin .media-tooltip-popup { - background-color: oklab(0 0 0 / 0.9); + background-color: oklch(0 0 0 / 0.9); } } -/* Captions */ +/* ========================================================================== + Captions + ========================================================================== */ + .media-minimal-skin .media-captions { position: absolute; inset: auto 1rem 1.5rem 1rem; z-index: 20; - transition: transform 150ms ease-out; + font-size: 1rem; + text-wrap: balance; /* The delay must account for the controls delay/duration */ + transition: transform 150ms ease-out; transition-delay: 600ms; pointer-events: none; - text-wrap: balance; - font-size: 1rem; } @media (prefers-reduced-motion: reduce) { .media-minimal-skin .media-captions { @@ -419,34 +584,36 @@ } } .media-minimal-skin .media-captions__container { - max-width: 42ch; - margin: 0 auto; - text-align: center; display: flex; flex-direction: column; align-items: center; + max-width: 42ch; + margin: 0 auto; + text-align: center; } .media-minimal-skin .media-captions__text { display: block; padding: 0.125rem 0.5rem; + color: oklch(1 0 0); text-shadow: - 0 0 1px oklab(0 0 0 / 0.7), - 0 0 8px oklab(0 0 0 / 0.7); - color: #fff; + 0 0 1px oklch(0 0 0 / 0.7), + 0 0 8px oklch(0 0 0 / 0.7); text-align: center; white-space: pre-wrap; line-height: 1.2; } @media (prefers-contrast: more) { .media-minimal-skin .media-captions__text { + background: oklch(0 0 0 / 0.7); text-shadow: none; box-decoration-break: clone; - background: oklab(0 0 0 / 0.7); } } .media-minimal-skin .media-captions__text > * { display: inline; } + +/* Responsive caption sizing */ @container media-root (width > 20rem) { .media-minimal-skin .media-captions { font-size: 1.5rem; @@ -462,6 +629,8 @@ font-size: 2.25rem; } } + +/* Shift captions up when controls visible */ .media-minimal-skin .media-controls[data-visible] ~ .media-captions { transform: translateY(-2.5rem); transition-delay: 25ms; diff --git a/packages/react/src/presets/video/minimal-skin.tailwind.tsx b/packages/react/src/presets/video/minimal-skin.tailwind.tsx index e1c0f026..16d7974e 100644 --- a/packages/react/src/presets/video/minimal-skin.tailwind.tsx +++ b/packages/react/src/presets/video/minimal-skin.tailwind.tsx @@ -17,6 +17,7 @@ import { type ComponentProps, forwardRef, type ReactNode } from 'react'; import { Container } from '@/player/context'; import { BufferingIndicator } from '@/ui/buffering-indicator'; import { Controls } from '@/ui/controls'; +import { ErrorDialog } from '@/ui/error-dialog'; import { FullscreenButton } from '@/ui/fullscreen-button'; import { MuteButton } from '@/ui/mute-button'; import { PiPButton } from '@/ui/pip-button'; @@ -31,7 +32,7 @@ const SEEK_TIME = 10; const icon = cn( '[grid-area:1/1] size-4.5', - 'drop-shadow-[0_1px_0_var(--tw-shadow-color)] shadow-black/25', + 'drop-shadow-[0_1px_0_var(--tw-drop-shadow-color)] drop-shadow-black/25', 'transition-discrete transition-[display,opacity] duration-150 ease-out' ); @@ -39,25 +40,35 @@ const iconHidden = 'hidden opacity-0'; /* --------------------------------------- Components ---------------------------------------- */ -const Button = forwardRef>(function Button({ className, ...props }, ref) { +const Button = forwardRef & { variant?: 'icon' }>(function Button( + { className, variant, ...props }, + ref +) { return ( + + + + )} + /> + ( - )} @@ -181,10 +226,12 @@ export function MinimalVideoSkinTailwind(props: MinimalVideoSkinProps): ReactNod ( - )} @@ -193,10 +240,12 @@ export function MinimalVideoSkinTailwind(props: MinimalVideoSkinProps): ReactNod ( - )} @@ -207,18 +256,12 @@ export function MinimalVideoSkinTailwind(props: MinimalVideoSkinProps): ReactNod @@ -229,7 +272,7 @@ export function MinimalVideoSkinTailwind(props: MinimalVideoSkinProps): ReactNod ( - )} @@ -237,7 +280,7 @@ export function MinimalVideoSkinTailwind(props: MinimalVideoSkinProps): ReactNod ( - )} @@ -245,7 +288,7 @@ export function MinimalVideoSkinTailwind(props: MinimalVideoSkinProps): ReactNod ( - )} @@ -284,16 +327,24 @@ export function MinimalVideoSkinTailwind(props: MinimalVideoSkinProps): ReactNod // Layout 'absolute inset-0 flex flex-col items-start', 'pointer-events-none rounded-[inherit]', - // Gradient overlay (heavier gradient with positioned stop) + // Default: hidden + 'opacity-0', 'bg-gradient-to-t from-black/70 via-black/50 via-[7.5rem] to-transparent', + 'backdrop-blur-[0px] backdrop-saturate-150 backdrop-brightness-90', // Transitions - 'transition-opacity ease-out duration-75 delay-0', - // Hidden when controls hidden (peer sibling) - 'peer-not-data-[visible]/controls:opacity-0', - 'peer-not-data-[visible]/controls:delay-500', - 'peer-not-data-[visible]/controls:duration-500', + 'transition-[opacity,backdrop-filter] ease-out', + 'duration-500 delay-500', + // Shown when controls visible + 'peer-data-[visible]/controls:opacity-100', + 'peer-data-[visible]/controls:duration-150', + 'peer-data-[visible]/controls:delay-0', + // Shown when error visible (+ blur) + 'peer-data-[visible]/error:opacity-100', + 'peer-data-[visible]/error:duration-150', + 'peer-data-[visible]/error:delay-0', + 'peer-data-[visible]/error:backdrop-blur-[8px]', // Reduced motion - 'motion-reduce:peer-not-data-[visible]/controls:duration-100' + 'motion-reduce:duration-100' )} /> diff --git a/packages/react/src/presets/video/minimal-skin.tsx b/packages/react/src/presets/video/minimal-skin.tsx index 044fa092..1996fbb0 100644 --- a/packages/react/src/presets/video/minimal-skin.tsx +++ b/packages/react/src/presets/video/minimal-skin.tsx @@ -17,6 +17,7 @@ import { type ComponentProps, forwardRef, type ReactNode } from 'react'; import { Container } from '@/player/context'; import { BufferingIndicator } from '@/ui/buffering-indicator'; import { Controls } from '@/ui/controls'; +import { ErrorDialog } from '@/ui/error-dialog'; import { FullscreenButton } from '@/ui/fullscreen-button'; import { MuteButton } from '@/ui/mute-button'; import { PiPButton } from '@/ui/pip-button'; @@ -82,11 +83,33 @@ export function MinimalVideoSkin(props: MinimalVideoSkinProps): ReactNode { } /> + ( +
+
+
+

+ Something went wrong. +

+

+ An error occurred while trying to play the video. Please try again. +

+
+
+ +
+
+
+ )} + /> + ( - )} @@ -95,7 +118,7 @@ export function MinimalVideoSkin(props: MinimalVideoSkinProps): ReactNode { ( - )} @@ -139,7 +162,7 @@ export function MinimalVideoSkin(props: MinimalVideoSkinProps): ReactNode { ( - )} @@ -147,7 +170,7 @@ export function MinimalVideoSkin(props: MinimalVideoSkinProps): ReactNode { ( - )} diff --git a/packages/react/src/presets/video/skin.css b/packages/react/src/presets/video/skin.css index a1aff366..3a7eebf1 100644 --- a/packages/react/src/presets/video/skin.css +++ b/packages/react/src/presets/video/skin.css @@ -1,64 +1,68 @@ +/* ========================================================================== + Reset + ========================================================================== */ + +.media-default-skin *, +.media-default-skin *::before, +.media-default-skin *::after { + box-sizing: border-box; + margin: 0; +} +.media-default-skin img, +.media-default-skin video, +.media-default-skin svg { + display: block; + max-width: 100%; +} +.media-default-skin button { + font: inherit; +} +@media (prefers-reduced-motion: no-preference) { + .media-default-skin { + interpolate-size: allow-keywords; + } +} + +/* ========================================================================== + Root Container + ========================================================================== */ + .media-default-skin { position: relative; isolation: isolate; container: media-root / inline-size; overflow: clip; border-radius: var(--media-border-radius, 2rem); - background: oklab(0 0 0); - font-family: ui-sans-serif, system-ui, sans-serif; + background: oklch(0 0 0); + font-family: + Inter Variable, + Inter, + ui-sans-serif, + system-ui, + sans-serif; font-size: 0.8125rem; line-height: 1.5; + letter-spacing: normal; -webkit-font-smoothing: auto; -moz-osx-font-smoothing: auto; } -.media-default-skin * { - box-sizing: border-box; -} + +/* Inner border rings */ .media-default-skin::before, .media-default-skin::after { content: ""; position: absolute; - pointer-events: none; - border-radius: inherit; z-index: 10; + border-radius: inherit; + pointer-events: none; } .media-default-skin::before { inset: 1px; - box-shadow: inset 0 0 0 1px oklab(1 0 0 / 0.15); + box-shadow: inset 0 0 0 1px oklch(1 0 0 / 0.15); } .media-default-skin::after { inset: 0; - box-shadow: inset 0 0 0 1px oklab(0 0 0 / 0.1); -} - -/* Buffering indicator */ -.media-default-skin .media-buffering-indicator { - position: absolute; - inset: 0; - display: flex; - align-items: center; - justify-content: center; - pointer-events: none; - z-index: 10; - color: #fff; -} -.media-default-skin .media-buffering-indicator .media-surface { - padding: 0.25rem; - border-radius: 100%; -} - -/* Poster image */ -.media-default-skin > img { - position: absolute; - inset: 0; - width: 100%; - height: 100%; - object-fit: cover; - pointer-events: none; - transition: opacity 0.25s; -} -.media-default-skin > img:not([data-visible]) { - opacity: 0; + box-shadow: inset 0 0 0 1px oklch(0 0 0 / 0.1); } /* Fullscreen */ @@ -66,111 +70,236 @@ border-radius: 0; } +/* ========================================================================== + Media Element + ========================================================================== */ + .media-default-skin > video { display: block; width: 100%; height: 100%; } -/* Media Container UI Overlay Styling */ +/* ========================================================================== + Poster Image + ========================================================================== */ + +.media-default-skin > img { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + transition: opacity 0.25s; + pointer-events: none; +} +.media-default-skin > img:not([data-visible]) { + opacity: 0; +} + +/* ========================================================================== + Overlay / Scrim + ========================================================================== */ + .media-default-skin .media-overlay { position: absolute; inset: 0; - pointer-events: none; border-radius: inherit; - background-image: linear-gradient(to top, oklab(0 0 0 / 0.5), oklab(0 0 0 / 0.3), rgba(0, 0, 0, 0)); - backdrop-filter: saturate(1.5) brightness(0.9); - transition-delay: 500ms; - transition-duration: 300ms; - transition-behavior: allow-discrete; - transition-property: opacity, display; - transition-timing-function: ease-out; + background-image: linear-gradient(to top, oklch(0 0 0 / 0.5), oklch(0 0 0 / 0.3), oklch(0 0 0 / 0)); + backdrop-filter: blur(0) saturate(1.5) brightness(0.9); opacity: 0; - display: none; + transition-property: opacity, backdrop-filter; + transition-duration: 300ms; + transition-delay: 500ms; + transition-timing-function: ease-out; + pointer-events: none; } @media (prefers-reduced-motion: reduce) { .media-default-skin .media-overlay { transition-duration: 100ms; } } -.media-default-skin .media-controls[data-visible] ~ .media-overlay { +.media-default-skin .media-controls[data-visible] ~ .media-overlay, +.media-default-skin .media-error[data-visible] ~ .media-overlay { + opacity: 1; transition-duration: 150ms; transition-delay: 0ms; - opacity: 1; - display: block; +} +.media-default-skin .media-error[data-visible] ~ .media-overlay { + backdrop-filter: blur(8px) saturate(1.5) brightness(0.9); } -/* Common Surface Styles - e.g. tooltips, popovers, controls */ +/* ========================================================================== + Buffering Indicator + ========================================================================== */ + +.media-default-skin .media-buffering-indicator { + position: absolute; + inset: 0; + z-index: 10; + display: flex; + align-items: center; + justify-content: center; + color: oklch(1 0 0); + pointer-events: none; +} +.media-default-skin .media-buffering-indicator .media-surface { + padding: 0.25rem; + border-radius: 100%; +} + +/* ========================================================================== + Error Dialog + ========================================================================== */ + +.media-default-skin .media-error { + display: none; +} +.media-default-skin .media-error[data-visible] { + position: absolute; + inset: 0; + z-index: 20; + display: flex; + align-items: center; + justify-content: center; + pointer-events: none; +} +.media-default-skin .media-error__dialog { + display: none; + transition-property: display, opacity, transform; + transition-duration: 500ms; + transition-delay: 100ms; + transition-behavior: allow-discrete; + transition-timing-function: linear( + 0, + 0.034 1.5%, + 0.763 9.7%, + 1.066 13.9%, + 1.198 19.9%, + 1.184 21.8%, + 0.963 37.5%, + 0.997 50.9%, + 1 + ); +} +.media-default-skin .media-error[data-visible] .media-error__dialog { + display: flex; + flex-direction: column; + gap: 0.75rem; + max-width: 18rem; + padding: 0.75rem; + border-radius: 1.75rem; + color: oklch(1 0 0); + font-size: 0.875rem; + pointer-events: auto; + transform: scale(1); + opacity: 1; + + @starting-style { + transform: scale(0.5); + opacity: 0; + } +} +.media-default-skin .media-error__content { + display: flex; + flex-direction: column; + gap: 0.5rem; + padding: 0.5rem 0.5rem 0.375rem; +} +.media-default-skin .media-error__title { + font-weight: 600; + line-height: 1.25; +} +.media-default-skin .media-error__description { + opacity: 0.7; +} +.media-default-skin .media-error__actions { + display: flex; + gap: 0.5rem; +} +.media-default-skin .media-error__actions > * { + flex: 1; +} + +/* ========================================================================== + Surface (shared glass effect for tooltips, popovers, controls) + ========================================================================== */ + .media-default-skin .media-surface { - background-color: oklab(1 0 0 / 0.1); + background-color: oklch(1 0 0 / 0.1); backdrop-filter: blur(64px) brightness(0.9) saturate(1.5); box-shadow: - inset 0 0 0 1px oklab(1 0 0 / 0.05), - 0 0 0 1px oklab(0 0 0 / 0.15), - oklab(0 0 0 / 0.15) 0px 1px 3px 0px, - oklab(0 0 0 / 0.15) 0px 1px 2px -1px; + inset 0 0 0 1px oklch(1 0 0 / 0.05), + 0 0 0 1px oklch(0 0 0 / 0.15), + oklch(0 0 0 / 0.15) 0px 1px 3px 0px, + oklch(0 0 0 / 0.15) 0px 1px 2px -1px; } @media (prefers-reduced-transparency: reduce) { .media-default-skin .media-surface { - background-color: oklab(0 0 0 / 0.7); + background-color: oklch(0 0 0 / 0.7); box-shadow: - inset 0 0 0 1px oklab(0 0 0), - 0 0 0 1px oklab(1 0 0 / 0.2); + inset 0 0 0 1px oklch(0 0 0), + 0 0 0 1px oklch(1 0 0 / 0.2); } } @media (prefers-contrast: more) { .media-default-skin .media-surface { - background-color: oklab(0 0 0 / 0.9); + background-color: oklch(0 0 0 / 0.9); box-shadow: - inset 0 0 0 1px oklab(0 0 0), - 0 0 0 1px oklab(1 0 0 / 0.2); + inset 0 0 0 1px oklch(0 0 0), + 0 0 0 1px oklch(1 0 0 / 0.2); } } -/* Media Control Bar UI/Styles */ +/* ========================================================================== + Controls + ========================================================================== */ + .media-default-skin .media-controls { position: absolute; - container: media-controls / inline-size; bottom: 0.75rem; inset-inline: 0.75rem; - padding: 0.175rem; + z-index: 10; + container: media-controls / inline-size; display: flex; align-items: center; gap: 0.075rem; - color: oklab(1 0 0); + padding: 0.175rem; border-radius: calc(infinity * 1px); + color: oklch(1 0 0); will-change: scale, transform, filter, opacity; transition-property: scale, transform, filter, opacity; - transition-timing-function: ease-out; - transition-delay: 0ms; transition-duration: 100ms; + transition-delay: 0ms; + transition-timing-function: ease-out; transform-origin: bottom; - z-index: 10; } .media-default-skin .media-controls:not([data-visible]) { - pointer-events: none; - filter: blur(8px); - scale: 0.9; opacity: 0; - transition-delay: 500ms; + scale: 0.9; + filter: blur(8px); transition-duration: 300ms; + transition-delay: 500ms; + pointer-events: none; } @media (prefers-reduced-motion: reduce) { .media-default-skin .media-controls:not([data-visible]) { - /* FIXME: Make this a custom property that we can share */ - transition-duration: 100ms; - filter: blur(0); scale: 1; + filter: blur(0); + transition-duration: 100ms; } } @container media-root (width > 40rem) { .media-default-skin .media-controls { - padding: 0.25rem; gap: 0.125rem; + padding: 0.25rem; } } -/* Time Display */ +/* ========================================================================== + Time Display + ========================================================================== */ + .media-default-skin .media-time { container: media-time / inline-size; display: flex; @@ -180,8 +309,8 @@ padding-inline: 0.5rem; } .media-default-skin .media-time__value { - text-shadow: 0 1px 0 oklab(0 0 0 / 0.25); font-variant-numeric: tabular-nums; + text-shadow: 0 1px 0 oklch(0 0 0 / 0.25); } .media-default-skin .media-time .media-time__value:first-child { display: none; @@ -192,47 +321,70 @@ } } -/* Buttons */ +/* ========================================================================== + Buttons + ========================================================================== */ + +/* Base button */ .media-default-skin .media-button { - display: grid; + display: flex; + align-items: center; + justify-content: center; flex-shrink: 0; - padding: 0.5rem; - cursor: pointer; - background: transparent; + padding: 0.5rem 1rem; + background: oklch(1 0 0); border: none; border-radius: calc(infinity * 1px); - color: oklab(1 0 0 / 0.9); - user-select: none; outline: 2px solid transparent; outline-offset: -2px; + color: oklch(0 0 0); + font-weight: 500; transition-property: background-color, color, outline-offset; transition-duration: 150ms; transition-timing-function: ease-out; - text-shadow: 0 1px 0 oklab(0 0 0 / 0.25); -} -.media-default-skin .media-button:hover, -.media-default-skin .media-button:focus-visible, -.media-default-skin .media-button[aria-expanded="true"] { - background-color: oklab(1 0 0 / 0.1); - color: oklab(1 0 0); - text-decoration: none; + cursor: pointer; + user-select: none; } .media-default-skin .media-button:focus-visible { outline-color: oklch(62.3% 0.214 259.815); outline-offset: 2px; } .media-default-skin .media-button[disabled] { - cursor: not-allowed; opacity: 0.5; filter: grayscale(1); + cursor: not-allowed; } + +/* Icon button variant */ +.media-default-skin .media-button--icon { + display: grid; + padding: 0.5rem; + background: transparent; + color: oklch(1 0 0 / 0.9); + text-shadow: 0 1px 0 oklch(0 0 0 / 0.25); +} +.media-default-skin .media-button--icon:hover, +.media-default-skin .media-button--icon:focus-visible, +.media-default-skin .media-button--icon[aria-expanded="true"] { + background-color: oklch(1 0 0 / 0.1); + color: oklch(1 0 0); + text-decoration: none; +} +.media-default-skin .media-button--icon .media-icon { + filter: drop-shadow(0 1px 0 oklch(0 0 0 / 0.25)); +} + +/* Seek button variant — hidden at small sizes */ @container media-controls (width < 28rem) { .media-default-skin .media-button--seek { display: none; } } -/* Icons */ +/* ========================================================================== + Icons + ========================================================================== */ + .media-default-skin .media-icon__container { position: relative; } @@ -240,7 +392,6 @@ grid-area: 1 / 1; width: 18px; height: 18px; - filter: drop-shadow(0 1px 0 oklab(0 0 0 / 0.25)); transition-behavior: allow-discrete; transition-property: display, opacity; transition-duration: 150ms; @@ -253,87 +404,90 @@ .media-default-skin .media-icon--flipped { scale: -1 1; } + +/* Seek icon label positioning */ .media-default-skin .media-icon--seek ~ .media-icon__label { position: absolute; right: 0; bottom: -3px; font-size: 0.75em; font-weight: 480; + font-variant-numeric: tabular-nums; } .media-default-skin .media-icon--seek.media-icon--flipped ~ .media-icon__label { - left: 0; right: unset; + left: 0; } -/* TimeSlider Component Styles */ +/* ========================================================================== + Slider + ========================================================================== */ + .media-default-skin .media-slider { - flex: 1; + position: relative; display: flex; align-items: center; justify-content: center; - position: relative; + flex: 1; border-radius: calc(infinity * 1px); outline: none; } -/* Horizontal orientation styles */ +/* Horizontal orientation */ .media-default-skin .media-slider[data-orientation="horizontal"] { min-width: 5rem; width: 100%; height: 1.25rem; } -/* Vertical orientation styles */ +/* Vertical orientation */ .media-default-skin .media-slider[data-orientation="vertical"] { - height: 5rem; width: 1.25rem; + height: 5rem; } +/* Track */ .media-default-skin .media-slider__track { position: relative; isolation: isolate; - background-color: oklab(1 0 0 / 0.2); - border-radius: inherit; overflow: hidden; - user-select: none; + background-color: oklch(1 0 0 / 0.2); + border-radius: inherit; outline: 2px solid transparent; outline-offset: -2px; + box-shadow: 0 0 0 1px oklch(0 0 0 / 0.05); transition: outline-offset 150ms ease-out; - box-shadow: 0 0 0 1px oklab(0 0 0 / 0.05); + user-select: none; } - -/* Horizontal track styles */ .media-default-skin .media-slider__track[data-orientation="horizontal"] { width: 100%; height: 0.25rem; } - -/* Vertical track styles */ .media-default-skin .media-slider__track[data-orientation="vertical"] { width: 0.25rem; height: 100%; } - .media-default-skin .media-slider:focus-visible .media-slider__track { outline-color: oklch(62.3% 0.214 259.815); outline-offset: 6px; } +/* Thumb */ .media-default-skin .media-slider__thumb { + z-index: 10; width: 0.625rem; height: 0.625rem; - background-color: oklab(1 0 0); + background-color: oklch(1 0 0); border-radius: calc(infinity * 1px); - user-select: none; - z-index: 10; box-shadow: - 0 0 0 1px oklab(0 0 0 / 0.1), - 0 1px 3px 0 oklab(0 0 0 / 0.15), - 0 1px 2px -1px oklab(0 0 0 / 0.15); + 0 0 0 1px oklch(0 0 0 / 0.1), + 0 1px 3px 0 oklch(0 0 0 / 0.15), + 0 1px 2px -1px oklch(0 0 0 / 0.15); opacity: 0; transition-property: opacity, height, width; transition-duration: 150ms; transition-timing-function: ease-out; + user-select: none; } .media-default-skin .media-slider__thumb:active { width: 0.75rem; @@ -350,32 +504,39 @@ cursor: ns-resize; } +/* Pointer (hover preview) */ .media-default-skin .media-slider__pointer { - background-color: oklab(1 0 0 / 0.2); + background-color: oklch(1 0 0 / 0.2); border-radius: inherit; } +/* Progress fill */ .media-default-skin .media-slider__progress { - background-color: oklab(1 0 0); + background-color: oklch(1 0 0); border-radius: inherit; } +/* Time display within slider */ .media-default-skin .media-slider__time-display { font-variant-numeric: tabular-nums; } +/* ========================================================================== + Popups & Animations + ========================================================================== */ + .media-default-skin .media-popup-animation { - transition-property: transform, scale, opacity, filter; - transition-duration: 200ms; + opacity: 1; transform: scale(1); transform-origin: bottom; - opacity: 1; filter: blur(0px); + transition-property: transform, scale, opacity, filter; + transition-duration: 200ms; } .media-default-skin .media-popup-animation[data-starting-style], .media-default-skin .media-popup-animation[data-ending-style] { - transform: scale(0); opacity: 0; + transform: scale(0); filter: blur(8px); } .media-default-skin .media-popup-animation[data-instant] { @@ -383,34 +544,40 @@ } .media-default-skin .media-popover-popup { - padding: 0.75rem 0.25rem; - border-radius: calc(infinity * 1px); margin: 0; + padding: 0.75rem 0.25rem; border: 0; + border-radius: calc(infinity * 1px); } -/* Tooltip Component Styles */ +/* ========================================================================== + Tooltips + ========================================================================== */ + .media-default-skin .media-tooltip { white-space: nowrap; } .media-default-skin .media-tooltip-popup { - color: oklab(1 0 0); padding: 0.25rem 0.625rem; border-radius: calc(infinity * 1px); + color: oklch(1 0 0); font-size: 0.75rem; } -/* Captions */ +/* ========================================================================== + Captions + ========================================================================== */ + .media-default-skin .media-captions { position: absolute; inset: auto 1rem 1.5rem 1rem; z-index: 20; - transition: transform 150ms ease-out; + font-size: 1rem; + text-wrap: balance; /* The delay must account for the controls delay/duration */ + transition: transform 150ms ease-out; transition-delay: 600ms; pointer-events: none; - text-wrap: balance; - font-size: 1rem; } @media (prefers-reduced-motion: reduce) { .media-default-skin .media-captions { @@ -418,34 +585,36 @@ } } .media-default-skin .media-captions__container { - max-width: 42ch; - margin: 0 auto; - text-align: center; display: flex; flex-direction: column; align-items: center; + max-width: 42ch; + margin: 0 auto; + text-align: center; } .media-default-skin .media-captions__text { display: block; padding: 0.125rem 0.5rem; + color: oklch(1 0 0); text-shadow: - 0 0 1px oklab(0 0 0 / 0.7), - 0 0 8px oklab(0 0 0 / 0.7); - color: #fff; + 0 0 1px oklch(0 0 0 / 0.7), + 0 0 8px oklch(0 0 0 / 0.7); text-align: center; white-space: pre-wrap; line-height: 1.2; } @media (prefers-contrast: more) { .media-default-skin .media-captions__text { + background: oklch(0 0 0 / 0.7); text-shadow: none; box-decoration-break: clone; - background: oklab(0 0 0 / 0.7); } } .media-default-skin .media-captions__text > * { display: inline; } + +/* Responsive caption sizing */ @container media-root (width > 20rem) { .media-default-skin .media-captions { font-size: 1.5rem; @@ -461,6 +630,8 @@ font-size: 2.25rem; } } + +/* Shift captions up when controls visible */ .media-default-skin .media-controls[data-visible] ~ .media-captions { transform: translateY(-3rem); transition-delay: 25ms; diff --git a/packages/react/src/presets/video/skin.tailwind.tsx b/packages/react/src/presets/video/skin.tailwind.tsx index cd8869a9..9853ae86 100644 --- a/packages/react/src/presets/video/skin.tailwind.tsx +++ b/packages/react/src/presets/video/skin.tailwind.tsx @@ -17,6 +17,7 @@ import { type ComponentProps, forwardRef, type ReactNode } from 'react'; import { Container } from '@/player/context'; import { BufferingIndicator } from '@/ui/buffering-indicator'; import { Controls } from '@/ui/controls'; +import { ErrorDialog } from '@/ui/error-dialog'; import { FullscreenButton } from '@/ui/fullscreen-button'; import { MuteButton } from '@/ui/mute-button'; import { PiPButton } from '@/ui/pip-button'; @@ -37,14 +38,14 @@ const surface = cn( // Border to enhance contrast on lighter videos 'after:absolute after:inset-0 after:ring after:rounded-[inherit] after:ring-black/15 after:pointer-events-none after:z-10', // Reduced transparency for users with preference - '[@media(prefers-reduced-transparency:reduce)]:bg-black/70 [@media(prefers-reduced-transparency:reduce)]:bg-black/70 [@media(prefers-reduced-transparency:reduce)]:ring-black [@media(prefers-reduced-transparency:reduce)]:after:ring-white/20', + '[@media(prefers-reduced-transparency:reduce)]:bg-black/70 [@media(prefers-reduced-transparency:reduce)]:ring-black [@media(prefers-reduced-transparency:reduce)]:after:ring-white/20', // High contrast mode 'contrast-more:bg-black/90 contrast-more:ring-black contrast-more:after:ring-white/20' ); const icon = cn( '[grid-area:1/1] size-4.5 shrink-0', - 'drop-shadow-[0_1px_0_var(--tw-shadow-color)] shadow-black/25', + 'drop-shadow-[0_1px_0_var(--tw-drop-shadow-color)] drop-shadow-black/25', 'transition-discrete transition-[display,opacity] duration-150 ease-out' ); @@ -52,26 +53,36 @@ const iconHidden = 'hidden opacity-0'; /* --------------------------------------- Components ---------------------------------------- */ -const Button = forwardRef>(function Button({ className, ...props }, ref) { +const Button = forwardRef & { variant?: 'icon' }>(function Button( + { className, variant, ...props }, + ref +) { return ( + + + + )} + /> + ( - )} @@ -199,10 +246,10 @@ export function VideoSkinTailwind(props: VideoSkinProps): ReactNode { ( - )} @@ -211,10 +258,10 @@ export function VideoSkinTailwind(props: VideoSkinProps): ReactNode { ( - )} @@ -223,19 +270,16 @@ export function VideoSkinTailwind(props: VideoSkinProps): ReactNode { {/* Temporary spacer */}
- + ( - )} @@ -243,7 +287,7 @@ export function VideoSkinTailwind(props: VideoSkinProps): ReactNode { ( - )} @@ -251,7 +295,7 @@ export function VideoSkinTailwind(props: VideoSkinProps): ReactNode { ( - )} @@ -289,17 +333,24 @@ export function VideoSkinTailwind(props: VideoSkinProps): ReactNode { // Layout 'absolute inset-0 flex flex-col items-start', 'pointer-events-none rounded-[inherit]', - // Gradient overlay + // Default: hidden + 'opacity-0', 'bg-gradient-to-t from-black/50 via-black/30 to-transparent', - 'backdrop-saturate-150 backdrop-brightness-90', + 'backdrop-blur-[0px] backdrop-saturate-150 backdrop-brightness-90', // Transitions - 'transition-opacity ease-out duration-100 delay-0', - // Hidden when controls hidden (peer sibling) - 'peer-not-data-[visible]/controls:opacity-0', - 'peer-not-data-[visible]/controls:delay-500', - 'peer-not-data-[visible]/controls:duration-300', + 'transition-[opacity,backdrop-filter] ease-out', + 'duration-300 delay-500', + // Shown when controls visible + 'peer-data-[visible]/controls:opacity-100', + 'peer-data-[visible]/controls:duration-150', + 'peer-data-[visible]/controls:delay-0', + // Shown when error visible (+ blur) + 'peer-data-[visible]/error:opacity-100', + 'peer-data-[visible]/error:duration-150', + 'peer-data-[visible]/error:delay-0', + 'peer-data-[visible]/error:backdrop-blur-[8px]', // Reduced motion - 'motion-reduce:peer-not-data-[visible]/controls:duration-100' + 'motion-reduce:duration-100' )} /> diff --git a/packages/react/src/presets/video/skin.tsx b/packages/react/src/presets/video/skin.tsx index 7e14fec0..118395e4 100644 --- a/packages/react/src/presets/video/skin.tsx +++ b/packages/react/src/presets/video/skin.tsx @@ -17,6 +17,7 @@ import { type ComponentProps, forwardRef, type ReactNode } from 'react'; import { Container } from '@/player/context'; import { BufferingIndicator } from '@/ui/buffering-indicator'; import { Controls } from '@/ui/controls'; +import { ErrorDialog } from '@/ui/error-dialog'; import { FullscreenButton } from '@/ui/fullscreen-button'; import { MuteButton } from '@/ui/mute-button'; import { PiPButton } from '@/ui/pip-button'; @@ -84,10 +85,32 @@ export function VideoSkin(props: VideoSkinProps): ReactNode { } /> + ( +
+
+
+

+ Something went wrong. +

+

+ An error occurred while trying to play the video. Please try again. +

+
+
+ +
+
+
+ )} + /> + ( - )} @@ -96,7 +119,7 @@ export function VideoSkin(props: VideoSkinProps): ReactNode { ( - )} @@ -134,7 +157,7 @@ export function VideoSkin(props: VideoSkinProps): ReactNode { ( - )} @@ -142,21 +165,21 @@ export function VideoSkin(props: VideoSkinProps): ReactNode { ( - )} /> - {/*
+ {/*
An example cue

Another example cue with HTML

-
*/} +
*/}
diff --git a/packages/react/src/ui/error-dialog/error-dialog.tsx b/packages/react/src/ui/error-dialog/error-dialog.tsx new file mode 100644 index 00000000..a5fbb6c4 --- /dev/null +++ b/packages/react/src/ui/error-dialog/error-dialog.tsx @@ -0,0 +1,83 @@ +'use client'; + +import type { ForwardedRef } from 'react'; +import { forwardRef, useEffect, useRef, useState } from 'react'; +import type { UIComponentProps } from '../../utils/types'; +import { renderElement } from '../../utils/use-render'; + +type ErrorDialogState = { visible: boolean; onDismiss: () => void }; + +export interface ErrorDialogProps extends UIComponentProps<'div', ErrorDialogState> { + 'aria-labelledby': string; + 'aria-describedby'?: string; + dismiss?: () => void; +} + +const DEBUG = false; + +/** + * Displays an error dialog when media playback encounters an error. + * + * @example + * ```tsx + * + * + * ( + *
Something went wrong
+ * )} + * /> + * ``` + */ +export const ErrorDialog = forwardRef(function ErrorDialog( + componentProps: ErrorDialogProps, + forwardedRef: ForwardedRef +) { + const { render, className, style, ...elementProps } = componentProps; + const dialogRef = useRef(null); + + const [hasError, setHasError] = useState(false); + + // FIXME: This is just debugging code + useEffect(() => { + const handle = setTimeout(() => { + if (!DEBUG) return; + setHasError(true); + }, 2000); + + return () => clearTimeout(handle); + }, []); + + // Focus the dialog when it becomes visible to ensure it's announced by screen readers. + // Wait a frame for the accessibility tree to update with the dialog before focusing. + useEffect(() => { + if (!hasError) return; + requestAnimationFrame(() => { + dialogRef.current?.focus(); + }); + }, [hasError]); + + return renderElement( + 'div', + { render, className, style }, + { + state: { + visible: hasError, + onDismiss: () => setHasError(false), + }, + ref: [forwardedRef, dialogRef], + props: [ + { + role: 'alertdialog', + tabIndex: -1, + }, + elementProps, + ], + } + ); +}); + +export namespace ErrorDialog { + export type Props = ErrorDialogProps; + export type State = ErrorDialogState; +} diff --git a/packages/react/src/ui/error-dialog/index.ts b/packages/react/src/ui/error-dialog/index.ts new file mode 100644 index 00000000..4baeefc4 --- /dev/null +++ b/packages/react/src/ui/error-dialog/index.ts @@ -0,0 +1 @@ +export * from './error-dialog'; diff --git a/packages/react/src/utils/use-render.tsx b/packages/react/src/utils/use-render.tsx index 9bc88b85..db14ce3b 100644 --- a/packages/react/src/utils/use-render.tsx +++ b/packages/react/src/utils/use-render.tsx @@ -72,7 +72,7 @@ export function renderElement< element: TagName, componentProps: UseRenderComponentProps, params: UseRenderParameters -): ReactElement { +): ReactElement | null { const { className: classNameProp, style: styleProp, render } = componentProps; const { state, ref, props, stateAttrMap } = params; diff --git a/packages/sandbox/package.json b/packages/sandbox/package.json index 98f313c1..c498d0c2 100644 --- a/packages/sandbox/package.json +++ b/packages/sandbox/package.json @@ -11,6 +11,7 @@ "dependencies": { "@videojs/core": "workspace:*", "@videojs/html": "workspace:*", + "@videojs/icons": "workspace:*", "@videojs/react": "workspace:*", "@videojs/store": "workspace:*", "@videojs/utils": "workspace:*" @@ -18,9 +19,9 @@ "devDependencies": { "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", - "@tailwindcss/vite": "^4.1.17", - "@vitejs/plugin-react": "^4.0.0", - "tailwindcss": "^4.1.17", + "@tailwindcss/vite": "^4.2.0", + "@vitejs/plugin-react": "^5.1.4", + "tailwindcss": "^4.2.0", "react": "^19.0.0", "react-dom": "^19.0.0", "tsx": "^4.0.0", diff --git a/packages/sandbox/src/index.html b/packages/sandbox/src/index.html index 3d44cbce..21b7419b 100644 --- a/packages/sandbox/src/index.html +++ b/packages/sandbox/src/index.html @@ -4,7 +4,7 @@ Sandbox - +

Sandbox

@@ -12,6 +12,7 @@
  • Core
  • HTML
  • React
  • +
  • React & Tailwind
  • diff --git a/packages/sandbox/templates/constants.ts b/packages/sandbox/templates/constants.ts new file mode 100644 index 00000000..c7e91ff8 --- /dev/null +++ b/packages/sandbox/templates/constants.ts @@ -0,0 +1 @@ +export const SKINS = ['default', 'minimal'] as const; diff --git a/packages/sandbox/templates/html/main.ts b/packages/sandbox/templates/html/main.ts index 9fae361c..d685fa3e 100644 --- a/packages/sandbox/templates/html/main.ts +++ b/packages/sandbox/templates/html/main.ts @@ -1,7 +1,7 @@ // HTML sandbox — Web player (DOM/Browser) // http://localhost:5173/html/ -import { createPlayer, features, MediaElement } from '@videojs/html'; +import { createPlayer, features } from '@videojs/html'; const { PlayerElement } = createPlayer({ features: features.video, diff --git a/packages/sandbox/templates/index.html b/packages/sandbox/templates/index.html new file mode 100644 index 00000000..21b7419b --- /dev/null +++ b/packages/sandbox/templates/index.html @@ -0,0 +1,18 @@ + + + + + + Sandbox + + + +

    Sandbox

    + + + diff --git a/packages/sandbox/templates/react-tailwind/index.html b/packages/sandbox/templates/react-tailwind/index.html new file mode 100644 index 00000000..bd39b8b5 --- /dev/null +++ b/packages/sandbox/templates/react-tailwind/index.html @@ -0,0 +1,13 @@ + + + + + + Sandbox — React & Tailwind + + + +
    + + + diff --git a/packages/sandbox/templates/react-tailwind/main.tsx b/packages/sandbox/templates/react-tailwind/main.tsx new file mode 100644 index 00000000..7f20eea7 --- /dev/null +++ b/packages/sandbox/templates/react-tailwind/main.tsx @@ -0,0 +1,46 @@ +// React & Tailwind Sandbox +// http://localhost:5173/react-tailwind/ + +import { createPlayer, features } from '@videojs/react'; +import { MinimalVideoSkinTailwind, Video, type VideoSkinProps, VideoSkinTailwind } from '@videojs/react/video'; +import { useState } from 'react'; +import { createRoot } from 'react-dom/client'; +import { SKINS } from '../constants'; +import type { Skin } from '../types'; + +const { Provider } = createPlayer({ + features: features.video, +}); + +function SkinComponent({ skin, ...props }: { skin: Skin } & VideoSkinProps) { + switch (skin) { + case 'default': + return ; + case 'minimal': + return ; + } +} + +function App() { + const [skin, setSkin] = useState('default'); + + return ( +
    + + + + + + +
    + ); +} + +createRoot(document.getElementById('root')!).render(); diff --git a/packages/sandbox/templates/react/main.tsx b/packages/sandbox/templates/react/main.tsx index 39ab2b32..225fce65 100644 --- a/packages/sandbox/templates/react/main.tsx +++ b/packages/sandbox/templates/react/main.tsx @@ -1,21 +1,37 @@ // React sandbox — React player // http://localhost:5173/react/ -import { Container, createPlayer, features } from '@videojs/react'; +import { createPlayer, features } from '@videojs/react'; import { Video } from '@videojs/react/video'; +import { useState } from 'react'; import { createRoot } from 'react-dom/client'; +import { SKINS } from '../constants'; +import type { Skin } from '../types'; +import { SkinComponent } from './skins'; const { Provider } = createPlayer({ features: features.video, }); function App() { + const [skin, setSkin] = useState('default'); + return ( - - - - +
    + + + + + + +
    ); } diff --git a/packages/sandbox/templates/react/skins.tsx b/packages/sandbox/templates/react/skins.tsx new file mode 100644 index 00000000..ae7e4074 --- /dev/null +++ b/packages/sandbox/templates/react/skins.tsx @@ -0,0 +1,34 @@ +import type { VideoSkinProps } from '@videojs/react/video'; +import { MinimalVideoSkin, VideoSkin } from '@videojs/react/video'; +import minimalSkinUrl from '@videojs/react/video/minimal-skin.css?url'; +import defaultSkinUrl from '@videojs/react/video/skin.css?url'; +import { useEffect } from 'react'; +import type { Skin } from '../types'; + +const stylesheets: Record = { + default: defaultSkinUrl, + minimal: minimalSkinUrl, +}; + +function useStylesheet(url: string) { + useEffect(() => { + const link = document.createElement('link'); + link.rel = 'stylesheet'; + link.href = url; + document.head.appendChild(link); + return () => { + link.remove(); + }; + }, [url]); +} + +export function SkinComponent({ skin, ...props }: { skin: Skin } & VideoSkinProps) { + useStylesheet(stylesheets[skin]); + + switch (skin) { + case 'default': + return ; + case 'minimal': + return ; + } +} diff --git a/packages/sandbox/templates/styles.css b/packages/sandbox/templates/styles.css index f1d8c73c..b3737615 100644 --- a/packages/sandbox/templates/styles.css +++ b/packages/sandbox/templates/styles.css @@ -1 +1,3 @@ @import "tailwindcss"; +@source "../templates"; +@source "../node_modules/@videojs/react"; diff --git a/packages/sandbox/templates/types.ts b/packages/sandbox/templates/types.ts new file mode 100644 index 00000000..f6871e70 --- /dev/null +++ b/packages/sandbox/templates/types.ts @@ -0,0 +1,3 @@ +import type { SKINS } from './constants'; + +export type Skin = (typeof SKINS)[number]; diff --git a/packages/sandbox/templates/vite-env.d.ts b/packages/sandbox/templates/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/packages/sandbox/templates/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/sandbox/vite.config.ts b/packages/sandbox/vite.config.ts index 2e7b2fcd..dad9fc00 100644 --- a/packages/sandbox/vite.config.ts +++ b/packages/sandbox/vite.config.ts @@ -10,7 +10,7 @@ export default defineConfig({ dedupe: ['react', 'react-dom'], }, optimizeDeps: { - exclude: ['@videojs/core', '@videojs/html', '@videojs/react', '@videojs/store', '@videojs/utils'], + exclude: ['@videojs/core', '@videojs/html', '@videojs/icons', '@videojs/react', '@videojs/store', '@videojs/utils'], }, build: { outDir: resolve(__dirname, 'dist'), @@ -21,6 +21,7 @@ export default defineConfig({ core: resolve(__dirname, 'src/core/index.html'), html: resolve(__dirname, 'src/html/index.html'), react: resolve(__dirname, 'src/react/index.html'), + 'react-tailwind': resolve(__dirname, 'src/react-tailwind/index.html'), }, }, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 82e243d8..55158fa9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -121,7 +121,7 @@ importers: devDependencies: '@svgr/babel-plugin-add-jsx-attribute': specifier: ^8.0.0 - version: 8.0.0(@babel/core@7.28.5) + version: 8.0.0(@babel/core@7.29.0) '@svgr/cli': specifier: ^8.1.0 version: 8.1.0(typescript@5.9.3) @@ -191,7 +191,7 @@ importers: version: 5.9.3 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) packages/element: dependencies: @@ -210,7 +210,7 @@ importers: version: 5.9.3 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) packages/html: dependencies: @@ -241,7 +241,7 @@ importers: version: 5.9.3 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) packages/icons: dependencies: @@ -312,7 +312,7 @@ importers: version: 5.9.3 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) packages/sandbox: dependencies: @@ -322,6 +322,9 @@ importers: '@videojs/html': specifier: workspace:* version: link:../html + '@videojs/icons': + specifier: workspace:* + version: link:../icons '@videojs/react': specifier: workspace:* version: link:../react @@ -333,8 +336,8 @@ importers: version: link:../utils devDependencies: '@tailwindcss/vite': - specifier: ^4.1.17 - version: 4.1.18(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + specifier: ^4.2.0 + version: 4.2.1(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2)) '@types/react': specifier: ^19.0.0 version: 19.2.7 @@ -342,8 +345,8 @@ importers: specifier: ^19.0.0 version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': - specifier: ^4.0.0 - version: 4.7.0(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + specifier: ^5.1.4 + version: 5.1.4(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2)) react: specifier: ^19.0.0 version: 19.2.3 @@ -351,8 +354,8 @@ importers: specifier: ^19.0.0 version: 19.2.3(react@19.2.3) tailwindcss: - specifier: ^4.1.17 - version: 4.1.18 + specifier: ^4.2.0 + version: 4.2.1 tsx: specifier: ^4.0.0 version: 4.21.0 @@ -361,7 +364,7 @@ importers: version: 5.9.3 vite: specifier: ^6.0.0 - version: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + version: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) packages/store: dependencies: @@ -395,7 +398,7 @@ importers: version: 5.9.3 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) packages/utils: devDependencies: @@ -407,19 +410,19 @@ importers: version: 5.9.3 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) site: dependencies: '@astrojs/mdx': specifier: ^4.3.7 - version: 4.3.13(astro@5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)) + version: 4.3.13(astro@5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)) '@astrojs/netlify': specifier: ^6.6.4 - version: 6.6.4(@netlify/api@14.0.13)(@types/node@22.19.3)(@vercel/functions@2.2.13)(astro@5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(yaml@2.8.2) + version: 6.6.4(@netlify/api@14.0.13)(@types/node@22.19.3)(@vercel/functions@2.2.13)(astro@5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.3)(tsx@4.21.0)(yaml@2.8.2) '@astrojs/react': specifier: ^4.4.0 - version: 4.4.2(@types/node@22.19.3)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tsx@4.21.0)(yaml@2.8.2) + version: 4.4.2(@types/node@22.19.3)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(jiti@2.6.1)(lightningcss@1.31.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tsx@4.21.0)(yaml@2.8.2) '@astrojs/rss': specifier: ^4.0.12 version: 4.0.14 @@ -443,10 +446,10 @@ importers: version: 1.4.0 '@sentry/astro': specifier: ^10.32.1 - version: 10.32.1(astro@5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)) + version: 10.32.1(astro@5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)) '@tailwindcss/vite': - specifier: ^4.1.17 - version: 4.1.18(vite@7.2.7(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + specifier: ^4.2.0 + version: 4.2.1(vite@7.2.7(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2)) '@videojs/html': specifier: workspace:* version: link:../packages/html @@ -461,7 +464,7 @@ importers: version: link:../packages/__tech-preview__/react astro: specifier: ^5.14.4 - version: 5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) + version: 5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) clsx: specifier: ^2.1.1 version: 2.1.1 @@ -520,8 +523,8 @@ importers: specifier: ^3.3.1 version: 3.4.0 tailwindcss: - specifier: ^4.1.17 - version: 4.1.18 + specifier: ^4.2.0 + version: 4.2.1 unist-util-visit: specifier: ^5.0.0 version: 5.0.0 @@ -551,8 +554,8 @@ importers: specifier: ^5.0.6 version: 5.0.6 '@vitejs/plugin-react': - specifier: ^5.0.3 - version: 5.1.2(vite@7.2.7(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + specifier: ^5.1.4 + version: 5.1.4(vite@7.2.7(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/coverage-v8': specifier: ^3.2.4 version: 3.2.4(vitest@3.2.4) @@ -582,7 +585,7 @@ importers: version: 1.0.0-alpha.13(typescript@5.9.3) vitest: specifier: ^3.2.4 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) packages: @@ -703,18 +706,34 @@ packages: resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} + engines: {node: '>=6.9.0'} + '@babel/compat-data@7.28.5': resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} engines: {node: '>=6.9.0'} + '@babel/compat-data@7.29.0': + resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} + engines: {node: '>=6.9.0'} + '@babel/core@7.28.5': resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} engines: {node: '>=6.9.0'} + '@babel/core@7.29.0': + resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} + engines: {node: '>=6.9.0'} + '@babel/generator@7.28.5': resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} engines: {node: '>=6.9.0'} + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} + engines: {node: '>=6.9.0'} + '@babel/generator@8.0.0-rc.1': resolution: {integrity: sha512-3ypWOOiC4AYHKr8vYRVtWtWmyvcoItHtVqF8paFax+ydpmUdPsJpLBkBBs5ItmhdrwC3a0ZSqqFAdzls4ODP3w==} engines: {node: ^20.19.0 || >=22.12.0} @@ -723,6 +742,10 @@ packages: resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.28.6': + resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + engines: {node: '>=6.9.0'} + '@babel/helper-globals@7.28.0': resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} engines: {node: '>=6.9.0'} @@ -731,12 +754,22 @@ packages: resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.28.6': + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + engines: {node: '>=6.9.0'} + '@babel/helper-module-transforms@7.28.3': resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 + '@babel/helper-module-transforms@7.28.6': + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@babel/helper-plugin-utils@7.27.1': resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} engines: {node: '>=6.9.0'} @@ -765,11 +798,20 @@ packages: resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} engines: {node: '>=6.9.0'} + '@babel/helpers@7.28.6': + resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} + engines: {node: '>=6.9.0'} + '@babel/parser@7.28.5': resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.29.0': + resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/parser@8.0.0-rc.1': resolution: {integrity: sha512-6HyyU5l1yK/7h9Ki52i5h6mDAx4qJdiLQO4FdCyJNoB/gy3T3GGJdhQzzbZgvgZCugYBvwtQiWRt94QKedHnkA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -795,14 +837,26 @@ packages: resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} + '@babel/template@7.28.6': + resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + engines: {node: '>=6.9.0'} + '@babel/traverse@7.28.5': resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} engines: {node: '>=6.9.0'} + '@babel/traverse@7.29.0': + resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} + engines: {node: '>=6.9.0'} + '@babel/types@7.28.5': resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + '@babel/types@8.0.0-rc.1': resolution: {integrity: sha512-ubmJ6TShyaD69VE9DQrlXcdkvJbmwWPB8qYj0H2kaJi29O7vJT9ajSdBd2W8CG34pwL9pYA74fi7RHC1qbLoVQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2492,9 +2546,6 @@ packages: '@rolldown/pluginutils@1.0.0-beta.45': resolution: {integrity: sha512-Le9ulGCrD8ggInzWw/k2J8QcbPz7eGIOWqfJ2L+1R0Opm7n6J37s2hiDWlh6LJN0Lk9L5sUzMvRHKW7UxBZsQA==} - '@rolldown/pluginutils@1.0.0-beta.53': - resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==} - '@rolldown/pluginutils@1.0.0-rc.3': resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} @@ -2867,36 +2918,69 @@ packages: '@tailwindcss/node@4.1.18': resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==} + '@tailwindcss/node@4.2.1': + resolution: {integrity: sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==} + '@tailwindcss/oxide-android-arm64@4.1.18': resolution: {integrity: sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==} engines: {node: '>= 10'} cpu: [arm64] os: [android] + '@tailwindcss/oxide-android-arm64@4.2.1': + resolution: {integrity: sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + '@tailwindcss/oxide-darwin-arm64@4.1.18': resolution: {integrity: sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] + '@tailwindcss/oxide-darwin-arm64@4.2.1': + resolution: {integrity: sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + '@tailwindcss/oxide-darwin-x64@4.1.18': resolution: {integrity: sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] + '@tailwindcss/oxide-darwin-x64@4.2.1': + resolution: {integrity: sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + '@tailwindcss/oxide-freebsd-x64@4.1.18': resolution: {integrity: sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] + '@tailwindcss/oxide-freebsd-x64@4.2.1': + resolution: {integrity: sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18': resolution: {integrity: sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==} engines: {node: '>= 10'} cpu: [arm] os: [linux] + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1': + resolution: {integrity: sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + '@tailwindcss/oxide-linux-arm64-gnu@4.1.18': resolution: {integrity: sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==} engines: {node: '>= 10'} @@ -2904,6 +2988,13 @@ packages: os: [linux] libc: [glibc] + '@tailwindcss/oxide-linux-arm64-gnu@4.2.1': + resolution: {integrity: sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@tailwindcss/oxide-linux-arm64-musl@4.1.18': resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==} engines: {node: '>= 10'} @@ -2911,6 +3002,13 @@ packages: os: [linux] libc: [musl] + '@tailwindcss/oxide-linux-arm64-musl@4.2.1': + resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + libc: [musl] + '@tailwindcss/oxide-linux-x64-gnu@4.1.18': resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==} engines: {node: '>= 10'} @@ -2918,6 +3016,13 @@ packages: os: [linux] libc: [glibc] + '@tailwindcss/oxide-linux-x64-gnu@4.2.1': + resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + libc: [glibc] + '@tailwindcss/oxide-linux-x64-musl@4.1.18': resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==} engines: {node: '>= 10'} @@ -2925,6 +3030,13 @@ packages: os: [linux] libc: [musl] + '@tailwindcss/oxide-linux-x64-musl@4.2.1': + resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + libc: [musl] + '@tailwindcss/oxide-wasm32-wasi@4.1.18': resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==} engines: {node: '>=14.0.0'} @@ -2937,24 +3049,52 @@ packages: - '@emnapi/wasi-threads' - tslib + '@tailwindcss/oxide-wasm32-wasi@4.2.1': + resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + '@tailwindcss/oxide-win32-arm64-msvc@4.1.18': resolution: {integrity: sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] + '@tailwindcss/oxide-win32-arm64-msvc@4.2.1': + resolution: {integrity: sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + '@tailwindcss/oxide-win32-x64-msvc@4.1.18': resolution: {integrity: sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==} engines: {node: '>= 10'} cpu: [x64] os: [win32] + '@tailwindcss/oxide-win32-x64-msvc@4.2.1': + resolution: {integrity: sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + '@tailwindcss/oxide@4.1.18': resolution: {integrity: sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==} engines: {node: '>= 10'} - '@tailwindcss/vite@4.1.18': - resolution: {integrity: sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==} + '@tailwindcss/oxide@4.2.1': + resolution: {integrity: sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==} + engines: {node: '>= 20'} + + '@tailwindcss/vite@4.2.1': + resolution: {integrity: sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w==} peerDependencies: vite: ^5.2.0 || ^6 || ^7 @@ -3180,8 +3320,8 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - '@vitejs/plugin-react@5.1.2': - resolution: {integrity: sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==} + '@vitejs/plugin-react@5.1.4': + resolution: {integrity: sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 @@ -4097,6 +4237,10 @@ packages: resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==} engines: {node: '>=10.13.0'} + enhanced-resolve@5.19.0: + resolution: {integrity: sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==} + engines: {node: '>=10.13.0'} + entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -4918,30 +5062,60 @@ packages: cpu: [arm64] os: [android] + lightningcss-android-arm64@1.31.1: + resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + lightningcss-darwin-arm64@1.30.2: resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] + lightningcss-darwin-arm64@1.31.1: + resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + lightningcss-darwin-x64@1.30.2: resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] + lightningcss-darwin-x64@1.31.1: + resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + lightningcss-freebsd-x64@1.30.2: resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] + lightningcss-freebsd-x64@1.31.1: + resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + lightningcss-linux-arm-gnueabihf@1.30.2: resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] + lightningcss-linux-arm-gnueabihf@1.31.1: + resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + lightningcss-linux-arm64-gnu@1.30.2: resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} engines: {node: '>= 12.0.0'} @@ -4949,6 +5123,13 @@ packages: os: [linux] libc: [glibc] + lightningcss-linux-arm64-gnu@1.31.1: + resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + lightningcss-linux-arm64-musl@1.30.2: resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} engines: {node: '>= 12.0.0'} @@ -4956,6 +5137,13 @@ packages: os: [linux] libc: [musl] + lightningcss-linux-arm64-musl@1.31.1: + resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + lightningcss-linux-x64-gnu@1.30.2: resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} engines: {node: '>= 12.0.0'} @@ -4963,6 +5151,13 @@ packages: os: [linux] libc: [glibc] + lightningcss-linux-x64-gnu@1.31.1: + resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + lightningcss-linux-x64-musl@1.30.2: resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} engines: {node: '>= 12.0.0'} @@ -4970,22 +5165,45 @@ packages: os: [linux] libc: [musl] + lightningcss-linux-x64-musl@1.31.1: + resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + lightningcss-win32-arm64-msvc@1.30.2: resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] + lightningcss-win32-arm64-msvc@1.31.1: + resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + lightningcss-win32-x64-msvc@1.30.2: resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] + lightningcss-win32-x64-msvc@1.31.1: + resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + lightningcss@1.30.2: resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} engines: {node: '>= 12.0.0'} + lightningcss@1.31.1: + resolution: {integrity: sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==} + engines: {node: '>= 12.0.0'} + lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -6316,6 +6534,9 @@ packages: tailwindcss@4.1.18: resolution: {integrity: sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==} + tailwindcss@4.2.1: + resolution: {integrity: sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==} + tapable@2.3.0: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} @@ -7359,12 +7580,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/mdx@4.3.13(astro@5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))': + '@astrojs/mdx@4.3.13(astro@5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))': dependencies: '@astrojs/markdown-remark': 6.3.10 '@mdx-js/mdx': 3.1.1 acorn: 8.15.0 - astro: 5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) + astro: 5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) es-module-lexer: 1.7.0 estree-util-visit: 2.0.0 hast-util-to-html: 9.0.5 @@ -7378,18 +7599,18 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/netlify@6.6.4(@netlify/api@14.0.13)(@types/node@22.19.3)(@vercel/functions@2.2.13)(astro@5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(yaml@2.8.2)': + '@astrojs/netlify@6.6.4(@netlify/api@14.0.13)(@types/node@22.19.3)(@vercel/functions@2.2.13)(astro@5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.3)(tsx@4.21.0)(yaml@2.8.2)': dependencies: '@astrojs/internal-helpers': 0.7.5 '@astrojs/underscore-redirects': 1.0.0 '@netlify/blobs': 10.5.0 '@netlify/functions': 5.1.2 - '@netlify/vite-plugin': 2.8.0(@netlify/api@14.0.13)(@vercel/functions@2.2.13)(rollup@4.53.3)(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + '@netlify/vite-plugin': 2.8.0(@netlify/api@14.0.13)(@vercel/functions@2.2.13)(rollup@4.53.3)(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2)) '@vercel/nft': 0.30.4(rollup@4.53.3) - astro: 5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) + astro: 5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) esbuild: 0.25.12 tinyglobby: 0.2.15 - vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -7432,15 +7653,15 @@ snapshots: dependencies: prismjs: 1.30.0 - '@astrojs/react@4.4.2(@types/node@22.19.3)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tsx@4.21.0)(yaml@2.8.2)': + '@astrojs/react@4.4.2(@types/node@22.19.3)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(jiti@2.6.1)(lightningcss@1.31.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(tsx@4.21.0)(yaml@2.8.2)': dependencies: '@types/react': 19.2.7 '@types/react-dom': 19.2.3(@types/react@19.2.7) - '@vitejs/plugin-react': 4.7.0(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + '@vitejs/plugin-react': 4.7.0(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2)) react: 19.2.3 react-dom: 19.2.3(react@19.2.3) ultrahtml: 1.6.0 - vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - '@types/node' - jiti @@ -7490,8 +7711,16 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/code-frame@7.29.0': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + '@babel/compat-data@7.28.5': {} + '@babel/compat-data@7.29.0': {} + '@babel/core@7.28.5': dependencies: '@babel/code-frame': 7.27.1 @@ -7512,6 +7741,26 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/core@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helpers': 7.28.6 + '@babel/parser': 7.29.0 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + '@babel/generator@7.28.5': dependencies: '@babel/parser': 7.28.5 @@ -7520,6 +7769,14 @@ snapshots: '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 + '@babel/generator@7.29.1': + dependencies: + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + '@babel/generator@8.0.0-rc.1': dependencies: '@babel/parser': 8.0.0-rc.1 @@ -7537,6 +7794,14 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 + '@babel/helper-compilation-targets@7.28.6': + dependencies: + '@babel/compat-data': 7.29.0 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.28.1 + lru-cache: 5.1.1 + semver: 6.3.1 + '@babel/helper-globals@7.28.0': {} '@babel/helper-module-imports@7.27.1': @@ -7546,6 +7811,13 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-imports@7.28.6': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': dependencies: '@babel/core': 7.28.5 @@ -7555,6 +7827,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + '@babel/helper-plugin-utils@7.27.1': {} '@babel/helper-string-parser@7.27.1': {} @@ -7572,10 +7853,19 @@ snapshots: '@babel/template': 7.27.2 '@babel/types': 7.28.5 + '@babel/helpers@7.28.6': + dependencies: + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + '@babel/parser@7.28.5': dependencies: '@babel/types': 7.28.5 + '@babel/parser@7.29.0': + dependencies: + '@babel/types': 7.29.0 + '@babel/parser@8.0.0-rc.1': dependencies: '@babel/types': 8.0.0-rc.1 @@ -7585,11 +7875,21 @@ snapshots: '@babel/core': 7.28.5 '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.5)': dependencies: '@babel/core': 7.28.5 '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/runtime@7.28.4': {} '@babel/template@7.27.2': @@ -7598,6 +7898,12 @@ snapshots: '@babel/parser': 7.28.5 '@babel/types': 7.28.5 + '@babel/template@7.28.6': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 + '@babel/traverse@7.28.5': dependencies: '@babel/code-frame': 7.27.1 @@ -7610,11 +7916,28 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/traverse@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.29.0 + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + '@babel/types@7.28.5': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/types@8.0.0-rc.1': dependencies: '@babel/helper-string-parser': 8.0.0-rc.1 @@ -8508,7 +8831,7 @@ snapshots: p-wait-for: 5.0.2 parse-imports: 2.2.1 path-key: 4.0.0 - semver: 7.7.3 + semver: 7.7.4 tar: 7.5.7 tmp-promise: 3.0.3 urlpattern-polyfill: 8.0.2 @@ -8638,12 +8961,12 @@ snapshots: '@netlify/types@2.3.0': {} - '@netlify/vite-plugin@2.8.0(@netlify/api@14.0.13)(@vercel/functions@2.2.13)(rollup@4.53.3)(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': + '@netlify/vite-plugin@2.8.0(@netlify/api@14.0.13)(@vercel/functions@2.2.13)(rollup@4.53.3)(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@netlify/dev': 4.9.0(@netlify/api@14.0.13)(@vercel/functions@2.2.13)(rollup@4.53.3) '@netlify/dev-utils': 4.3.3 dedent: 1.7.1 - vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -8698,7 +9021,7 @@ snapshots: precinct: 12.2.0 require-package-name: 2.0.1 resolve: 2.0.0-next.5 - semver: 7.7.3 + semver: 7.7.4 tmp-promise: 3.0.3 toml: 3.0.0 unixify: 1.0.0 @@ -9243,8 +9566,6 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.45': {} - '@rolldown/pluginutils@1.0.0-beta.53': {} - '@rolldown/pluginutils@1.0.0-rc.3': {} '@rollup/pluginutils@5.3.0(rollup@4.53.3)': @@ -9339,13 +9660,13 @@ snapshots: '@sentry-internal/browser-utils': 10.32.1 '@sentry/core': 10.32.1 - '@sentry/astro@10.32.1(astro@5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))': + '@sentry/astro@10.32.1(astro@5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))': dependencies: '@sentry/browser': 10.32.1 '@sentry/core': 10.32.1 '@sentry/node': 10.32.1 '@sentry/vite-plugin': 4.6.1 - astro: 5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) + astro: 5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) transitivePeerDependencies: - encoding - supports-color @@ -9535,6 +9856,10 @@ snapshots: dependencies: '@babel/core': 7.28.5 + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.28.5)': dependencies: '@babel/core': 7.28.5 @@ -9656,42 +9981,88 @@ snapshots: source-map-js: 1.2.1 tailwindcss: 4.1.18 + '@tailwindcss/node@4.2.1': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.19.0 + jiti: 2.6.1 + lightningcss: 1.31.1 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.2.1 + '@tailwindcss/oxide-android-arm64@4.1.18': optional: true + '@tailwindcss/oxide-android-arm64@4.2.1': + optional: true + '@tailwindcss/oxide-darwin-arm64@4.1.18': optional: true + '@tailwindcss/oxide-darwin-arm64@4.2.1': + optional: true + '@tailwindcss/oxide-darwin-x64@4.1.18': optional: true + '@tailwindcss/oxide-darwin-x64@4.2.1': + optional: true + '@tailwindcss/oxide-freebsd-x64@4.1.18': optional: true + '@tailwindcss/oxide-freebsd-x64@4.2.1': + optional: true + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18': optional: true + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1': + optional: true + '@tailwindcss/oxide-linux-arm64-gnu@4.1.18': optional: true + '@tailwindcss/oxide-linux-arm64-gnu@4.2.1': + optional: true + '@tailwindcss/oxide-linux-arm64-musl@4.1.18': optional: true + '@tailwindcss/oxide-linux-arm64-musl@4.2.1': + optional: true + '@tailwindcss/oxide-linux-x64-gnu@4.1.18': optional: true + '@tailwindcss/oxide-linux-x64-gnu@4.2.1': + optional: true + '@tailwindcss/oxide-linux-x64-musl@4.1.18': optional: true + '@tailwindcss/oxide-linux-x64-musl@4.2.1': + optional: true + '@tailwindcss/oxide-wasm32-wasi@4.1.18': optional: true + '@tailwindcss/oxide-wasm32-wasi@4.2.1': + optional: true + '@tailwindcss/oxide-win32-arm64-msvc@4.1.18': optional: true + '@tailwindcss/oxide-win32-arm64-msvc@4.2.1': + optional: true + '@tailwindcss/oxide-win32-x64-msvc@4.1.18': optional: true + '@tailwindcss/oxide-win32-x64-msvc@4.2.1': + optional: true + '@tailwindcss/oxide@4.1.18': optionalDependencies: '@tailwindcss/oxide-android-arm64': 4.1.18 @@ -9707,19 +10078,34 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18 '@tailwindcss/oxide-win32-x64-msvc': 4.1.18 - '@tailwindcss/vite@4.1.18(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': - dependencies: - '@tailwindcss/node': 4.1.18 - '@tailwindcss/oxide': 4.1.18 - tailwindcss: 4.1.18 - vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + '@tailwindcss/oxide@4.2.1': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.2.1 + '@tailwindcss/oxide-darwin-arm64': 4.2.1 + '@tailwindcss/oxide-darwin-x64': 4.2.1 + '@tailwindcss/oxide-freebsd-x64': 4.2.1 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.1 + '@tailwindcss/oxide-linux-arm64-gnu': 4.2.1 + '@tailwindcss/oxide-linux-arm64-musl': 4.2.1 + '@tailwindcss/oxide-linux-x64-gnu': 4.2.1 + '@tailwindcss/oxide-linux-x64-musl': 4.2.1 + '@tailwindcss/oxide-wasm32-wasi': 4.2.1 + '@tailwindcss/oxide-win32-arm64-msvc': 4.2.1 + '@tailwindcss/oxide-win32-x64-msvc': 4.2.1 - '@tailwindcss/vite@4.1.18(vite@7.2.7(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': + '@tailwindcss/vite@4.2.1(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: - '@tailwindcss/node': 4.1.18 - '@tailwindcss/oxide': 4.1.18 - tailwindcss: 4.1.18 - vite: 7.2.7(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + '@tailwindcss/node': 4.2.1 + '@tailwindcss/oxide': 4.2.1 + tailwindcss: 4.2.1 + vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) + + '@tailwindcss/vite@4.2.1(vite@7.2.7(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2))': + dependencies: + '@tailwindcss/node': 4.2.1 + '@tailwindcss/oxide': 4.2.1 + tailwindcss: 4.2.1 + vite: 7.2.7(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) '@testing-library/dom@10.4.1': dependencies: @@ -9997,7 +10383,7 @@ snapshots: ms: 2.1.3 optional: true - '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': + '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@babel/core': 7.28.5 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) @@ -10005,19 +10391,31 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - supports-color - '@vitejs/plugin-react@5.1.2(vite@7.2.7(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': + '@vitejs/plugin-react@5.1.4(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: - '@babel/core': 7.28.5 - '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) - '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.5) - '@rolldown/pluginutils': 1.0.0-beta.53 + '@babel/core': 7.29.0 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) + '@rolldown/pluginutils': 1.0.0-rc.3 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: 7.2.7(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) + transitivePeerDependencies: + - supports-color + + '@vitejs/plugin-react@5.1.4(vite@7.2.7(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2))': + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) + '@rolldown/pluginutils': 1.0.0-rc.3 + '@types/babel__core': 7.20.5 + react-refresh: 0.18.0 + vite: 7.2.7(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - supports-color @@ -10036,7 +10434,7 @@ snapshots: std-env: 3.10.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - supports-color @@ -10048,13 +10446,13 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/mocker@3.2.4(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) '@vitest/pretty-format@3.2.4': dependencies: @@ -10085,7 +10483,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.15 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) '@vitest/utils@3.2.4': dependencies: @@ -10339,7 +10737,7 @@ snapshots: astring@1.9.0: {} - astro@5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2): + astro@5.16.5(@netlify/blobs@10.5.0)(@types/node@22.19.3)(@vercel/functions@2.2.13)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.3)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2): dependencies: '@astrojs/compiler': 2.13.0 '@astrojs/internal-helpers': 0.7.5 @@ -10396,8 +10794,8 @@ snapshots: unist-util-visit: 5.0.0 unstorage: 1.17.3(@netlify/blobs@10.5.0)(@vercel/functions@2.2.13) vfile: 6.0.3 - vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) - vitefu: 1.1.1(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) + vitefu: 1.1.1(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2)) xxhash-wasm: 1.1.0 yargs-parser: 21.1.1 yocto-spinner: 0.2.3 @@ -11032,6 +11430,11 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.3.0 + enhanced-resolve@5.19.0: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.0 + entities@4.5.0: {} entities@6.0.1: {} @@ -12002,7 +12405,7 @@ snapshots: lodash.isstring: 4.0.1 lodash.once: 4.1.1 ms: 2.1.3 - semver: 7.7.3 + semver: 7.7.4 junk@4.0.1: {} @@ -12044,36 +12447,69 @@ snapshots: lightningcss-android-arm64@1.30.2: optional: true + lightningcss-android-arm64@1.31.1: + optional: true + lightningcss-darwin-arm64@1.30.2: optional: true + lightningcss-darwin-arm64@1.31.1: + optional: true + lightningcss-darwin-x64@1.30.2: optional: true + lightningcss-darwin-x64@1.31.1: + optional: true + lightningcss-freebsd-x64@1.30.2: optional: true + lightningcss-freebsd-x64@1.31.1: + optional: true + lightningcss-linux-arm-gnueabihf@1.30.2: optional: true + lightningcss-linux-arm-gnueabihf@1.31.1: + optional: true + lightningcss-linux-arm64-gnu@1.30.2: optional: true + lightningcss-linux-arm64-gnu@1.31.1: + optional: true + lightningcss-linux-arm64-musl@1.30.2: optional: true + lightningcss-linux-arm64-musl@1.31.1: + optional: true + lightningcss-linux-x64-gnu@1.30.2: optional: true + lightningcss-linux-x64-gnu@1.31.1: + optional: true + lightningcss-linux-x64-musl@1.30.2: optional: true + lightningcss-linux-x64-musl@1.31.1: + optional: true + lightningcss-win32-arm64-msvc@1.30.2: optional: true + lightningcss-win32-arm64-msvc@1.31.1: + optional: true + lightningcss-win32-x64-msvc@1.30.2: optional: true + lightningcss-win32-x64-msvc@1.31.1: + optional: true + lightningcss@1.30.2: dependencies: detect-libc: 2.1.2 @@ -12090,6 +12526,22 @@ snapshots: lightningcss-win32-arm64-msvc: 1.30.2 lightningcss-win32-x64-msvc: 1.30.2 + lightningcss@1.31.1: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.31.1 + lightningcss-darwin-arm64: 1.31.1 + lightningcss-darwin-x64: 1.31.1 + lightningcss-freebsd-x64: 1.31.1 + lightningcss-linux-arm-gnueabihf: 1.31.1 + lightningcss-linux-arm64-gnu: 1.31.1 + lightningcss-linux-arm64-musl: 1.31.1 + lightningcss-linux-x64-gnu: 1.31.1 + lightningcss-linux-x64-musl: 1.31.1 + lightningcss-win32-arm64-msvc: 1.31.1 + lightningcss-win32-x64-msvc: 1.31.1 + lines-and-columns@1.2.4: {} lint-staged@16.2.7: @@ -12823,7 +13275,7 @@ snapshots: normalize-package-data@6.0.2: dependencies: hosted-git-info: 7.0.2 - semver: 7.7.3 + semver: 7.7.4 validate-npm-package-license: 3.0.4 normalize-path@2.1.1: @@ -13801,6 +14253,8 @@ snapshots: tailwindcss@4.1.18: {} + tailwindcss@4.2.1: {} + tapable@2.3.0: {} tar-stream@3.1.7: @@ -14219,13 +14673,13 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite-node@3.2.4(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2): + vite-node@3.2.4(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - '@types/node' - jiti @@ -14240,7 +14694,7 @@ snapshots: - tsx - yaml - vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2): + vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) @@ -14252,11 +14706,11 @@ snapshots: '@types/node': 22.19.3 fsevents: 2.3.3 jiti: 2.6.1 - lightningcss: 1.30.2 + lightningcss: 1.31.1 tsx: 4.21.0 yaml: 2.8.2 - vite@7.2.7(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2): + vite@7.2.7(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) @@ -14268,19 +14722,19 @@ snapshots: '@types/node': 22.19.3 fsevents: 2.3.3 jiti: 2.6.1 - lightningcss: 1.30.2 + lightningcss: 1.31.1 tsx: 4.21.0 yaml: 2.8.2 - vitefu@1.1.1(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)): + vitefu@1.1.1(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2)): optionalDependencies: - vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) - vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/mocker': 3.2.4(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -14298,8 +14752,8 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) - vite-node: 3.2.4(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) + vite-node: 3.2.4(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 @@ -14321,11 +14775,11 @@ snapshots: - tsx - yaml - vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.19.3)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.3.0(postcss@8.5.6))(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/mocker': 3.2.4(vite@6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -14343,8 +14797,8 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) - vite-node: 3.2.4(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + vite: 6.4.1(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) + vite-node: 3.2.4(@types/node@22.19.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 diff --git a/site/package.json b/site/package.json index d371b48f..1413639a 100644 --- a/site/package.json +++ b/site/package.json @@ -26,7 +26,7 @@ "@nanostores/react": "^1.0.0", "@pagefind/default-ui": "^1.4.0", "@sentry/astro": "^10.32.1", - "@tailwindcss/vite": "^4.1.17", + "@tailwindcss/vite": "^4.2.0", "@videojs/html": "workspace:*", "@videojs/html-preview": "workspace:*", "@videojs/react": "workspace:*", @@ -51,7 +51,7 @@ "shiki": "^3.13.0", "simple-git": "^3.28.0", "tailwind-merge": "^3.3.1", - "tailwindcss": "^4.1.17", + "tailwindcss": "^4.2.0", "unist-util-visit": "^5.0.0" }, "devDependencies": { @@ -63,7 +63,7 @@ "@types/react": "^19.2.2", "@types/react-dom": "^19.2.1", "@types/turndown": "^5.0.6", - "@vitejs/plugin-react": "^5.0.3", + "@vitejs/plugin-react": "^5.1.4", "@vitest/coverage-v8": "^3.2.4", "@vitest/ui": "^3.2.4", "babel-plugin-react-compiler": "1.0.0",