@getmicdrop/venue-calendar 4.1.52 → 4.1.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{BlockPlaceholder-oM2MmZuu.js → BlockPlaceholder-CqhToSye.js} +2 -2
- package/dist/{BlockPlaceholder-oM2MmZuu.js.map → BlockPlaceholder-CqhToSye.js.map} +1 -1
- package/dist/{CalendarFoundryView-BJv0QDcv.js → CalendarFoundryView-CMO7-AQi.js} +17 -17
- package/dist/{CalendarFoundryView-BJv0QDcv.js.map → CalendarFoundryView-CMO7-AQi.js.map} +1 -1
- package/dist/{CalendarIcon-BAz0d_Pj.js → CalendarIcon-BXHIKvAr.js} +2 -2
- package/dist/{CalendarIcon-BAz0d_Pj.js.map → CalendarIcon-BXHIKvAr.js.map} +1 -1
- package/dist/{CartView-DLjJPQbt.js → CartView-DXP-NdfF.js} +12 -12
- package/dist/{CartView-DLjJPQbt.js.map → CartView-DXP-NdfF.js.map} +1 -1
- package/dist/{Checkout-U0zc-Ws2.js → Checkout-DbYfIm3T.js} +7 -7
- package/dist/{Checkout-U0zc-Ws2.js.map → Checkout-DbYfIm3T.js.map} +1 -1
- package/dist/{Checkout-CnnLbRNr.js → Checkout-V9_dY_sS.js} +11 -11
- package/dist/{Checkout-CnnLbRNr.js.map → Checkout-V9_dY_sS.js.map} +1 -1
- package/dist/{CheckoutTimer-CoV5cHRL.js → CheckoutTimer--6OOtdTB.js} +3 -3
- package/dist/{CheckoutTimer-CoV5cHRL.js.map → CheckoutTimer--6OOtdTB.js.map} +1 -1
- package/dist/{ClockIcon-CRdviY8o.js → ClockIcon-CxfsowHx.js} +2 -2
- package/dist/{ClockIcon-CRdviY8o.js.map → ClockIcon-CxfsowHx.js.map} +1 -1
- package/dist/{CloseIcon-JYYIdhBY.js → CloseIcon-C5SCeQOk.js} +2 -2
- package/dist/{CloseIcon-JYYIdhBY.js.map → CloseIcon-C5SCeQOk.js.map} +1 -1
- package/dist/{CollectionView-C660avPQ.js → CollectionView-Bq8xpn6T.js} +6 -6
- package/dist/{CollectionView-C660avPQ.js.map → CollectionView-Bq8xpn6T.js.map} +1 -1
- package/dist/{Event-DlxxdMrP.js → Event-DJusXK29.js} +13 -13
- package/dist/{Event-DlxxdMrP.js.map → Event-DJusXK29.js.map} +1 -1
- package/dist/{EventPage-jhF3OOpv.js → EventPage-c9woM8dq.js} +9 -9
- package/dist/{EventPage-jhF3OOpv.js.map → EventPage-c9woM8dq.js.map} +1 -1
- package/dist/{Heading-B9gB4-Za.js → Heading-D81DQHoP.js} +2 -2
- package/dist/{Heading-B9gB4-Za.js.map → Heading-D81DQHoP.js.map} +1 -1
- package/dist/{Image-BrI6RXFh.js → Image-BktsxRho.js} +2 -2
- package/dist/{Image-BrI6RXFh.js.map → Image-BktsxRho.js.map} +1 -1
- package/dist/{MailIcon-Nxg7y-ub.js → MailIcon-3o_dDUzN.js} +2 -2
- package/dist/{MailIcon-Nxg7y-ub.js.map → MailIcon-3o_dDUzN.js.map} +1 -1
- package/dist/{Modal-CIRQUVSH.js → Modal-aWfERkXe.js} +3 -3
- package/dist/{Modal-CIRQUVSH.js.map → Modal-aWfERkXe.js.map} +1 -1
- package/dist/{PasswordInput-URDphAa4.js → PasswordInput-CLFuYYgC.js} +2 -2
- package/dist/{PasswordInput-URDphAa4.js.map → PasswordInput-CLFuYYgC.js.map} +1 -1
- package/dist/{ScarcityBadge-Dwah85WZ.js → ScarcityBadge-5RMumV4l.js} +3 -3
- package/dist/{ScarcityBadge-Dwah85WZ.js.map → ScarcityBadge-5RMumV4l.js.map} +1 -1
- package/dist/{SeriesPage-phkzskyq.js → SeriesPage-Dy28yKRV.js} +5 -5
- package/dist/{SeriesPage-phkzskyq.js.map → SeriesPage-Dy28yKRV.js.map} +1 -1
- package/dist/{Spinner-DsGKt_54.js → Spinner-D-c4nFeN.js} +2 -2
- package/dist/{Spinner-DsGKt_54.js.map → Spinner-D-c4nFeN.js.map} +1 -1
- package/dist/{Success-D1Voif89.js → Success-Zx8HLwlN.js} +11 -11
- package/dist/{Success-D1Voif89.js.map → Success-Zx8HLwlN.js.map} +1 -1
- package/dist/{VenueCalendar-DcX-R9GN.js → VenueCalendar-Ys8-209-.js} +14 -14
- package/dist/{VenueCalendar-DcX-R9GN.js.map → VenueCalendar-Ys8-209-.js.map} +1 -1
- package/dist/{ViewTicketsEmbed-pVa7jt9E.js → ViewTicketsEmbed-BjVMnRnA.js} +5 -5
- package/dist/{ViewTicketsEmbed-pVa7jt9E.js.map → ViewTicketsEmbed-BjVMnRnA.js.map} +1 -1
- package/dist/{WarningCircleIcon-CRvgz4mx.js → WarningCircleIcon-eOM57ZiU.js} +2 -2
- package/dist/{WarningCircleIcon-CRvgz4mx.js.map → WarningCircleIcon-eOM57ZiU.js.map} +1 -1
- package/dist/{allowlist-BB9UJJQv.js → allowlist-BVbx-J6B.js} +3 -3
- package/dist/{allowlist-BB9UJJQv.js.map → allowlist-BVbx-J6B.js.map} +1 -1
- package/dist/{cancel-CywDLP7Z.js → cancel-BIH3xozo.js} +2 -2
- package/dist/{cancel-CywDLP7Z.js.map → cancel-BIH3xozo.js.map} +1 -1
- package/dist/{copyToClipboard-iOR2YHXj.js → copyToClipboard-Ct55SL-r.js} +2 -2
- package/dist/{copyToClipboard-iOR2YHXj.js.map → copyToClipboard-Ct55SL-r.js.map} +1 -1
- package/dist/{index-C70I4S7a.js → index-B5pEXtmb.js} +2 -2
- package/dist/{index-C70I4S7a.js.map → index-B5pEXtmb.js.map} +1 -1
- package/dist/{modalManager.svelte-DUrbp7PG.js → modalManager.svelte-C6kq14zr.js} +2 -2
- package/dist/{modalManager.svelte-DUrbp7PG.js.map → modalManager.svelte-C6kq14zr.js.map} +1 -1
- package/dist/{promo-CytPOSIe.js → promo-Iv83zhP5.js} +2 -2
- package/dist/{promo-CytPOSIe.js.map → promo-Iv83zhP5.js.map} +1 -1
- package/dist/{serverTotals-BGK9EZcX.js → serverTotals-Bx9REXQW.js} +2 -2
- package/dist/{serverTotals-BGK9EZcX.js.map → serverTotals-Bx9REXQW.js.map} +1 -1
- package/dist/{showcase-state-options-B7OzbBdo.js → showcase-state-options-QYvDSYq0.js} +2 -2
- package/dist/{showcase-state-options-B7OzbBdo.js.map → showcase-state-options-QYvDSYq0.js.map} +1 -1
- package/dist/{transform-BaKV88mB.js → transform-DiYvD4iM.js} +3 -3
- package/dist/{transform-BaKV88mB.js.map → transform-DiYvD4iM.js.map} +1 -1
- package/dist/{utm-DBME8yC6.js → utm-TGZ2W8Ii.js} +2 -2
- package/dist/{utm-DBME8yC6.js.map → utm-TGZ2W8Ii.js.map} +1 -1
- package/dist/venue-calendar.es.js +1 -1
- package/dist/venue-calendar.iife.js +1 -1
- package/dist/venue-calendar.umd.js +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Image-BrI6RXFh.js","sources":["../node_modules/@getmicdrop/svelte-components/dist/primitives/Image/Image.svelte"],"sourcesContent":["<!--\r\n Image.svelte\r\n\r\n The canonical image primitive for Micdrop. Variable-aspect, user-uploaded\r\n sources (event posters, performer headshots, venue photos) where we do NOT\r\n control the aspect ratio. This component is now the single home for the\r\n whole image family — `Avatar` composes it, and `BlurBackdropImage` is a\r\n thin `@deprecated` shim.\r\n\r\n Premium contract (Atlas brief 04 — perf 5 / completeness 5):\r\n\r\n 1. ZERO CLS — pass `width`/`height` (intrinsic px) or `aspectRatio`\r\n (e.g. `'2/3'`, `'16/9'`, `'1'`). The component reserves that space\r\n BEFORE the image loads so the page never reflows when it arrives.\r\n A height-only sizing class (`h-8`, `size-10`, `aspect-video`) counts\r\n too — see `DEFINITE_BOX_CLASS` below for exactly which spellings.\r\n Dev-only `console.warn` if you provide neither dimensions nor one of\r\n those classes (we can't reserve space and CLS can creep back in).\r\n\r\n The width is still free: in normal block flow it fills the parent,\r\n and in a shrink-to-fit context (flex item, grid item, inline-block,\r\n absolutely positioned) it takes the width the bitmap's own ratio\r\n gives it at that height. `<Image class=\"h-8 w-auto\" />` inside a\r\n flex row is the auth-page wordmark and it renders at its natural\r\n ratio. That was NOT true before pad-endgame x162: the wrapper was a\r\n `container-type: inline-size` size container, which makes an element\r\n compute its inline size as if it had no contents, so every one of\r\n those shrink-to-fit contexts collapsed it — to ZERO as a flex item or\r\n absolutely positioned, to a 3.9px sliver as an inline-block — and\r\n `overflow: hidden` clipped the image away. The size container now lives on the\r\n absolutely-positioned blur layer, which contributes nothing to the\r\n wrapper's width by construction.\r\n\r\n 2. BLUR-UP LOADING — the main image starts slightly blurred and SHARPENS\r\n (blur → 0) once the real bitmap has decoded (`img.decode()` +\r\n `decoding=\"async\"`). In blur-backdrop framing a blurred copy of the\r\n SAME already-fetched bitmap fills the letterbox gaps — no second\r\n network fetch, no LQIP asset to ship. Fade timing reads the motion\r\n tokens, so `prefers-reduced-motion` collapses it automatically.\r\n\r\n 3. BLUR-BACKDROP IS THE DEFAULT FRAMING — `fit` defaults to\r\n `'blur-backdrop'`: the image is `object-fit: contain` (never cropped)\r\n and a blurred copy of itself fills the letterbox gaps. This handles\r\n BOTH tall posters and wide photos with no cropping and no flat-gray\r\n bars. `'cover'` / `'contain'` / `'fill'` / `'scale-down'` / `'none'`\r\n remain as escape hatches and render the plain single-`<img>` path\r\n (identical DOM to the pre-premium component).\r\n\r\n 4. BRANDED FALLBACK — when `src` (and `fallback`) are missing or both\r\n error, we render a branded placeholder (the Micdrop mark on a tint)\r\n instead of a flat gray div. Override the asset with `fallback`, or\r\n suppress the mark with `branded={false}`.\r\n\r\n Passthrough props for raw-<img> parity (so consumers can migrate\r\n existing `<img>` sites to `<Image>`):\r\n - `draggable` — forwarded to the underlying `<img draggable>`.\r\n - `onload` — forwarded to the `<img>` load event.\r\n - `fetchpriority` — forwarded to `<img fetchpriority>` (resource hint).\r\n - `onError` — fires ONCE, only after the internal fallback chain is\r\n exhausted (i.e. the branded placeholder takes over). It does NOT fire\r\n on the first error while a distinct `fallback` is still going to be\r\n tried. The raw `onerror` handler stays owned internally to drive the\r\n src→fallback→placeholder degradation; `onError` composes with it\r\n rather than replacing it.\r\n Deliberately NOT exposed (closed-interface rulings, sc#682):\r\n - `srcset`/`sizes` — zero consumer demand.\r\n - `onclick` — interactive semantics belong on an interactive WRAPPER\r\n (`<a>` for navigation, `<button type=\"button\">` otherwise) around\r\n `<Image>`, never on the img itself. A clickable img is a keyboard trap\r\n that only compiles behind a11y suppressions; the wrapper gets focus +\r\n key handling for free and nothing in this interface blocks it.\r\n - `aria-hidden` — redundant. `alt=\"\"` (the default) maps the img to role\r\n none/presentation per HTML-AAM, removing it from the accessibility\r\n tree already. Decorative icons: `alt=\"\"` + `fit=\"contain\"` +\r\n `blurUp={false}` (plain single-<img> DOM).\r\n - an errored-element `onError(event)` — the src-swap-on-error use case IS\r\n the `fallback` prop (src → fallback → branded placeholder, loop-safe).\r\n Consumers never need the raw element.\r\n\r\n Example:\r\n <Image src={event.posterUrl} alt={event.name} aspectRatio=\"2/3\" class=\"w-full rounded-xl\" />\r\n <Image src={user.avatarUrl} alt={user.name} width={80} height={80} fit=\"cover\" class=\"rounded-xl\" />\r\n <Image src={banner.url} alt=\"\" aspectRatio=\"16/9\" class=\"w-full\" loading=\"eager\" fetchpriority=\"high\" />\r\n-->\r\n<script lang=\"ts\">\r\n import { DEV } from 'esm-env';\r\n import { cn } from '../../utils/classNames.js';\r\n import { createLogger } from '../../utils/logger.js';\r\n\r\n const log = createLogger('Image');\r\n\r\n // Silence the dev CLS nudge under the test runner (the suite intentionally\r\n // renders without dimensions to exercise other behaviour). Reads the Node\r\n // env var Vitest sets — bundler-agnostic.\r\n const IS_TEST =\r\n typeof process !== 'undefined' && !!process.env?.VITEST;\r\n\r\n interface Props {\r\n /** Image source URL. When empty/missing, falls back to `fallback`. */\r\n src?: string;\r\n /** Alt text. Empty string marks decorative images per WCAG. */\r\n alt?: string;\r\n /** Additional CSS classes (sizing, shape, rounded corners). Wins last. */\r\n class?: string;\r\n /** Fallback URL used when src is empty or errors (before the branded mark). */\r\n fallback?: string;\r\n /** Loading strategy. Default 'lazy'; pass 'eager' for above-fold. */\r\n loading?: 'eager' | 'lazy';\r\n /**\r\n * Framing mode. Default `'blur-backdrop'` — `object-fit: contain` over a\r\n * blurred copy of the same image so tall AND wide sources are never\r\n * cropped and never letterboxed with flat gray. The remaining values are\r\n * escape hatches that render a plain single `<img object-fit:…>`.\r\n */\r\n fit?: 'blur-backdrop' | 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';\r\n /**\r\n * Intrinsic width in CSS px — reserves space before load (zero CLS) and\r\n * sets the `<img width>` attribute. Pair with `height` for a fixed box.\r\n */\r\n width?: number;\r\n /**\r\n * Intrinsic height in CSS px — reserves space before load (zero CLS) and\r\n * sets the `<img height>` attribute. Pair with `width` for a fixed box.\r\n */\r\n height?: number;\r\n /**\r\n * CSS `aspect-ratio` string (e.g. `'2/3'` posters, `'16/9'` banners,\r\n * `'1'` square). Reserves space before load when you size by one axis\r\n * (`w-full`) — the zero-CLS path for fluid layouts.\r\n */\r\n aspectRatio?: string;\r\n /**\r\n * Blur-up loading: render blurred, then sharpen once the real bitmap\r\n * decodes. Default true. Set false to skip the effect (e.g. tiny icons\r\n * where the blur is imperceptible but the extra work isn't worth it).\r\n */\r\n blurUp?: boolean;\r\n /**\r\n * When the fallback chain is exhausted, show the branded Micdrop mark on\r\n * a tint. Default true. Set false for a plain tinted placeholder.\r\n */\r\n branded?: boolean;\r\n /** Forwarded to `<img draggable>`. Omitted when undefined. */\r\n draggable?: boolean;\r\n /** Forwarded to the `<img>` load event. */\r\n // eslint-disable-next-line no-unused-vars -- intentionally retained (prop/slot/forward-compat or Svelte-5 reactive binding eslint cannot see)\r\n onload?: (e: Event) => void;\r\n /** Forwarded to `<img fetchpriority>` (fetch-priority resource hint). */\r\n fetchpriority?: 'high' | 'low' | 'auto';\r\n /**\r\n * Fires once when the fallback chain is exhausted and the branded\r\n * placeholder takes over — NOT on the first error if a distinct\r\n * `fallback` is still going to be tried. Composes with the internal\r\n * `onerror` machine.\r\n */\r\n onError?: () => void;\r\n }\r\n\r\n let {\r\n src = '',\r\n alt = '',\r\n class: className = '',\r\n fallback = '',\r\n loading = 'lazy',\r\n fit = 'blur-backdrop',\r\n width,\r\n height,\r\n aspectRatio,\r\n blurUp = true,\r\n branded = true,\r\n draggable,\r\n onload,\r\n fetchpriority,\r\n onError,\r\n }: Props = $props();\r\n\r\n // Track loading attempts: which URL we're showing right now.\r\n // When the current URL errors, drop to 'failed' and render the placeholder.\r\n // Distinct from src/fallback inputs because we need to remember which\r\n // candidate we already tried. Reset whenever inputs change.\r\n let attempt: 'src' | 'fallback' | 'failed' = $state(\r\n // eslint-disable-next-line svelte/valid-compile -- known Svelte compiler note, accepted for this primitive\r\n src ? 'src' : fallback ? 'fallback' : 'failed'\r\n );\r\n\r\n // Guard so `onError` fires at most once per input set, even if a stale\r\n // <img> re-emits a duplicate final `error`. Reset when inputs change so a\r\n // fresh src/fallback can legitimately fail-and-notify again.\r\n let notifiedError = $state(false);\r\n\r\n // Blur-up: starts blurred, sharpens once the real bitmap decodes. Reset on\r\n // every new candidate URL so each swap re-runs the blur-up reveal.\r\n let decoded = $state(false);\r\n\r\n // The rendered main <img>, so we can detect an already-decoded bitmap that\r\n // won't fire `load` again (a cached src re-assigned, or a re-mount onto a\r\n // cached URL). Without this, `decoded` sticks at false and the image stays\r\n // blurred forever — the \"avatar goes blurry after save\" bug.\r\n let mainImg: HTMLImageElement | undefined = $state();\r\n\r\n $effect(() => {\r\n // Re-derive when inputs change. (Read both to register dependencies.)\r\n const _s = src;\r\n const _f = fallback;\r\n attempt = _s ? 'src' : _f ? 'fallback' : 'failed';\r\n notifiedError = false;\r\n decoded = false;\r\n });\r\n\r\n let activeSrc = $derived(\r\n attempt === 'src' ? src : attempt === 'fallback' ? fallback : ''\r\n );\r\n\r\n // Cached-bitmap reveal: after the shown URL settles, a browser that already\r\n // has the image marks the <img> `complete` WITHOUT re-firing `load` (cache\r\n // hit, or a mount whose load event landed before the handler attached). Reveal\r\n // it immediately so it never sticks blurred; a genuinely-loading image is\r\n // `complete: false` here and still waits for `handleLoad`. Depends on the SAME\r\n // inputs as the reset effect (src/fallback) — plus activeSrc — so it always\r\n // re-runs right after the reset (declaration order) and reads the post-update\r\n // <img>, even when the resolved URL is unchanged.\r\n $effect(() => {\r\n void src;\r\n void fallback;\r\n void activeSrc;\r\n if (mainImg?.complete && mainImg.naturalWidth > 0) decoded = true;\r\n });\r\n let showImg = $derived(attempt !== 'failed' && !!activeSrc);\r\n\r\n // blur-backdrop is the only framing mode that wraps; everything else is a\r\n // plain single <img object-fit:…> (identical DOM to the legacy component).\r\n let backdrop = $derived(fit === 'blur-backdrop');\r\n let objectFit = $derived(backdrop ? 'contain' : fit);\r\n\r\n // Does the consumer reserve a DEFINITE box — one that fixes the rendered\r\n // HEIGHT before the bitmap's intrinsic dimensions are known? Only these\r\n // prevent vertical CLS:\r\n // - aspectRatio (height derives from width via the ratio), OR\r\n // - both width AND height (a fully fixed box), OR\r\n // - a `size-*` utility (sets width AND height together), OR\r\n // - a definite height / aspect-ratio class (`h-*`, `aspect-*`).\r\n // Deliberately NOT counted: width alone, `w-full`, `max-h-*`, `h-auto`,\r\n // AND `min-h-*` — min-h only reserves a FLOOR, so a taller bitmap still\r\n // grows the box and shifts the page. None of these reserve the actual\r\n // vertical extent before metadata, so CLS can still creep in. (`max-h-*`\r\n // and `min-h-*` are excluded by the leading `(?:^|\\s)` — the `h-` in them\r\n // is preceded by `-`, never by whitespace.)\r\n //\r\n // KNOWN LIMIT, stated because the reserved-box rules drive layout and not\r\n // just the warning: the same leading `(?:^|\\s)` means a VARIANT-PREFIXED\r\n // class does not match either — `md:h-8`, `sm:size-8`, `dark:aspect-video`\r\n // all read as NO reserved box. Such a consumer gets the dev CLS warning at\r\n // every width, and above the breakpoint the wrapper has a definite height\r\n // while the main image is still on the `height:auto` path, so a tall bitmap\r\n // is clipped by the wrapper instead of contained inside it. No live\r\n // consumer sizes an Image that way today (checked across micdrop-frontend\r\n // 2026-08-01), which is why this is recorded rather than widened here:\r\n // matching them means matching `h-` after `:` too, and that also matches\r\n // arbitrary values like `[&>img]:h-8`, so it is its own change with its own\r\n // test, not a regex tweak smuggled into a sizing fix.\r\n const DEFINITE_BOX_CLASS = /(?:^|\\s)(?:aspect-|size-|h-(?!auto\\b))/;\r\n let hasReservedBox = $derived(\r\n !!aspectRatio ||\r\n (width != null && height != null) ||\r\n DEFINITE_BOX_CLASS.test(className)\r\n );\r\n\r\n // Dev-only nudge: without a definite box we cannot reserve VERTICAL space,\r\n // so CLS can creep back in. Warn, never throw.\r\n $effect(() => {\r\n // Dev-only (tree-shaken from prod via esm-env DEV) and never under test.\r\n if (DEV && !IS_TEST && !hasReservedBox) {\r\n log.warn(\r\n 'No aspectRatio, no width+height pair, and no definite height/aspect ' +\r\n 'sizing class — vertical layout space cannot be reserved and the ' +\r\n 'page may shift when the image loads (CLS). Pass aspectRatio=\"2/3\", ' +\r\n 'both width and height, or an h-*/aspect-* class. (width alone or ' +\r\n 'w-full does not reserve vertical space.)'\r\n );\r\n }\r\n });\r\n\r\n // Reserve intrinsic space on the box that owns layout. For blur-backdrop\r\n // that's the wrapper; for the plain path it's the <img> itself.\r\n let reserveStyle = $derived(\r\n [\r\n width != null ? `width:${width}px` : '',\r\n height != null ? `height:${height}px` : '',\r\n aspectRatio ? `aspect-ratio:${aspectRatio}` : '',\r\n ]\r\n .filter(Boolean)\r\n .join(';')\r\n );\r\n\r\n // mark the real bitmap as decoded → triggers the blur→sharp fade.\r\n async function handleLoad(e: Event) {\r\n const img = e.currentTarget as HTMLImageElement;\r\n // Capture which URL this load is FOR. If `src` swaps mid-decode (the\r\n // active candidate changes), this stale resolution must NOT sharpen — or\r\n // fire onload for — the new image. Compare against the live activeSrc\r\n // after the await and bail if it moved on.\r\n const loadedSrc = activeSrc;\r\n try {\r\n // decode() resolves once the bitmap is paint-ready; avoids revealing a\r\n // half-painted image. Falls through if unsupported / aborted.\r\n await img.decode?.();\r\n } catch {\r\n // decode can reject on detached/aborted images — reveal anyway.\r\n }\r\n // Src swapped while we awaited decode() → this is a stale load. Drop it;\r\n // the new candidate's own load event will drive the reveal.\r\n if (activeSrc !== loadedSrc) return;\r\n decoded = true;\r\n onload?.(e);\r\n }\r\n\r\n function handleError() {\r\n // If we were on src and have a distinct fallback to try, advance.\r\n if (attempt === 'src' && fallback && fallback !== src) {\r\n attempt = 'fallback';\r\n return;\r\n }\r\n // Either fallback already attempted, or no distinct fallback exists.\r\n // The chain is exhausted — the branded placeholder takes over. Notify the\r\n // consumer exactly here (final failure only), never on the transient\r\n // src→fallback hop, and at most once per input set.\r\n attempt = 'failed';\r\n if (!notifiedError) {\r\n notifiedError = true;\r\n onError?.();\r\n }\r\n }\r\n</script>\r\n\r\n{#if showImg && backdrop}\r\n <!-- blur-backdrop framing (default): contain + same-image blurred fill.\r\n The wrapper owns layout + reserves space; the blur layer is a second\r\n cheap reuse of the already-fetched bitmap (no extra network fetch). -->\r\n <div\r\n class={cn('sc-image sc-image--backdrop', className)}\r\n class:sc-image--backdrop-reserved={hasReservedBox}\r\n style={reserveStyle || undefined}\r\n >\r\n <div class=\"sc-image__blur-layer\">\r\n <img\r\n src={activeSrc}\r\n alt=\"\"\r\n class=\"sc-image__blur\"\r\n aria-hidden=\"true\"\r\n decoding=\"async\"\r\n {loading}\r\n {draggable}\r\n {fetchpriority}\r\n />\r\n </div>\r\n <img\r\n bind:this={mainImg}\r\n src={activeSrc}\r\n {alt}\r\n class=\"sc-image__main\"\r\n class:sc-image__main--reserved={hasReservedBox}\r\n class:sc-image__main--loading={blurUp && !decoded}\r\n style:object-fit={objectFit}\r\n {width}\r\n {height}\r\n {loading}\r\n {draggable}\r\n {fetchpriority}\r\n decoding=\"async\"\r\n onerror={handleError}\r\n onload={handleLoad}\r\n />\r\n </div>\r\n{:else if showImg}\r\n <!-- escape-hatch framing (cover/contain/fill/none/scale-down): plain single\r\n <img>, identical DOM to the legacy component, plus blur-up + dims. -->\r\n <img\r\n bind:this={mainImg}\r\n src={activeSrc}\r\n {alt}\r\n {loading}\r\n {draggable}\r\n {fetchpriority}\r\n {width}\r\n {height}\r\n class={cn(\r\n 'sc-image image',\r\n blurUp && !decoded && 'sc-image--loading',\r\n className\r\n )}\r\n style:object-fit={objectFit}\r\n style:aspect-ratio={aspectRatio || undefined}\r\n decoding=\"async\"\r\n onerror={handleError}\r\n onload={handleLoad}\r\n />\r\n{:else}\r\n <!-- No usable src — branded placeholder (Micdrop mark on a tint), or a plain\r\n tinted box when branded={false}. Empty alt marks decorative images (per\r\n WCAG); hide from assistive tech via aria-hidden + no role. -->\r\n {#if alt}\r\n <div\r\n class={cn(\r\n 'sc-image image sc-image-placeholder image-placeholder',\r\n branded && 'sc-image-placeholder--branded',\r\n className\r\n )}\r\n style={reserveStyle || undefined}\r\n role=\"img\"\r\n aria-label={alt}\r\n ></div>\r\n {:else}\r\n <div\r\n class={cn(\r\n 'sc-image image sc-image-placeholder image-placeholder',\r\n branded && 'sc-image-placeholder--branded',\r\n className\r\n )}\r\n style={reserveStyle || undefined}\r\n aria-hidden=\"true\"\r\n ></div>\r\n {/if}\r\n{/if}\r\n\r\n<style>\r\n /* `.image` is a legacy back-compat alias of `.sc-image` on the plain\r\n escape-hatch <img> + placeholder (consumer CSS / tests may target it). */\r\n .sc-image,\r\n .image {\r\n display: block;\r\n max-width: 100%;\r\n }\r\n\r\n /* --- blur-backdrop framing ---\r\n THE WRAPPER IS NOT A SIZE CONTAINER, AND MUST NOT BECOME ONE AGAIN (x162).\r\n It used to carry `container-type: inline-size` for the small-container blur\r\n rule below. Inline-size containment makes an element compute its inline size\r\n AS IF IT HAD NO CONTENTS — so in every shrink-to-fit context (flex item,\r\n inline-block, absolutely positioned) `width: auto` collapsed, the main image\r\n at `width: 100%` collapsed with it, and `overflow: hidden` clipped the whole\r\n thing away. Measured in Chromium at 104x30 natural size: as a flex item and\r\n absolutely positioned it is exactly 0 (wrapper 0x32, main image 0x32); as an\r\n inline-block it is a 3.9px sliver. Every wordmark on the auth pages\r\n rendered as nothing. Normal block flow was unaffected (the parent's width is\r\n definite there), which is why it survived so long. */\r\n .sc-image--backdrop {\r\n position: relative;\r\n overflow: hidden;\r\n background: hsl(var(--bg-quaternary));\r\n }\r\n\r\n /* The size container lives HERE instead. This layer is absolutely positioned,\r\n so it contributes nothing to the wrapper's intrinsic width BY CONSTRUCTION —\r\n containment on it can never collapse the box the way it did on the wrapper.\r\n\r\n ONE MEASUREMENT CHANGED WITH IT, deliberately: the query below now reads the\r\n wrapper's PADDING box (this layer's own box) where the old wrapper container\r\n read its CONTENT box. On a padded wrapper those differ. The padding box is\r\n the right one — the rule exists so the blur's opaque area still reaches the\r\n visible edge after the halo grows, and the blur fills the padding box, not\r\n the content box. No consumer pads an Image today either way. */\r\n .sc-image__blur-layer {\r\n position: absolute;\r\n inset: 0;\r\n container-type: inline-size;\r\n /* decorative; never take a hit that belongs to the wrapper */\r\n pointer-events: none;\r\n }\r\n\r\n .sc-image__blur {\r\n display: block;\r\n width: 100%;\r\n height: 100%;\r\n max-width: none;\r\n object-fit: cover;\r\n transform: scale(1.15);\r\n filter: blur(16px) saturate(1.2);\r\n /* purely decorative fill; the absolutely-positioned blur layer paints first\r\n and the in-flow main layer (position:relative) stacks above it by source\r\n order — no explicit z-index needed. */\r\n }\r\n\r\n /* Small containers (<=80px): blur() applies before scale() in the render\r\n pipeline, so the blur halo gets scaled too. Need enough scale that the\r\n opaque image extends past the container edge even after the halo grows.\r\n Measured unchanged by the containment move (Chromium): a 40px avatar box\r\n still resolves to scale(2), a 160px box still resolves to scale(1.15). */\r\n @container (max-width: 5rem) {\r\n .sc-image__blur {\r\n transform: scale(2);\r\n filter: blur(6px) saturate(1.2);\r\n }\r\n }\r\n\r\n .sc-image__main {\r\n position: relative;\r\n display: block;\r\n width: 100%;\r\n /* No reserved box (legacy / no-fit default): the in-flow main image\r\n DRIVES the wrapper height and sizes ITSELF to the consumer's sizing\r\n classes — which land on the wrapper. `max-height: inherit` /\r\n `max-width: inherit` pull the wrapper's `max-h-*` / `max-w-*` onto the\r\n image so object-fit:contain shrinks it to fit (image height == wrapper\r\n height). The image therefore NEVER exceeds the wrapper, so the wrapper's\r\n overflow:hidden (which clips the decorative blur fill) cannot clip the\r\n MAIN image — it renders exactly as the pre-premium single <img> did,\r\n constrained by max-h-* / h-auto, no reflow. Only force the image to fill\r\n a fixed box when the consumer reserved a DEFINITE one (explicit height /\r\n aspectRatio / size-* / h-* / aspect-*) — there the wrapper owns layout\r\n and the image fills it (true zero-CLS letterbox). */\r\n height: auto;\r\n max-width: inherit;\r\n max-height: inherit;\r\n object-fit: contain;\r\n }\r\n\r\n .sc-image--backdrop-reserved .sc-image__main--reserved {\r\n height: 100%;\r\n max-width: none;\r\n max-height: none;\r\n }\r\n\r\n /* --- blur-up reveal (CSS-only; reduced-motion gated via motion tokens) ---\r\n The main image / plain image starts slightly blurred + scaled and\r\n sharpens on decode. Durations read from --motion-* so\r\n prefers-reduced-motion collapses them. */\r\n .sc-image--loading,\r\n .sc-image__main {\r\n transition:\r\n filter var(--motion-normal) var(--ease-smooth),\r\n transform var(--motion-normal) var(--ease-smooth);\r\n }\r\n\r\n .sc-image--loading,\r\n .sc-image__main--loading {\r\n filter: blur(12px);\r\n transform: scale(1.02);\r\n }\r\n\r\n /* --- placeholder --- */\r\n .sc-image-placeholder {\r\n background: hsl(var(--bg-quaternary));\r\n }\r\n\r\n /* DARK ONLY. `--bg-quaternary` is the deepest surface token, and in dark that is\r\n literally `0 0% 0%` (tokens.css) against a card at 10% lightness — so an empty\r\n image slot painted pure black reads as a hole punched in the card, not as an empty\r\n box. `--muted` is 16.9% in dark, a 6.9-point step ABOVE the card, which is what\r\n an empty box is supposed to look like. Peet ruled the no-artwork state must be a\r\n grey box (2026-07-29, on the x48 deck); this is the half of that ruling the dark\r\n theme was failing.\r\n LIGHT IS DELIBERATELY UNTOUCHED: `--bg-quaternary` is 91% there and reads correctly\r\n on a white card, and `--muted` at 95.9% would fade the box Peet just approved. One\r\n token per theme, both already in the palette — no new token minted for this. */\r\n :global([data-theme='dark']) .sc-image-placeholder {\r\n background: hsl(var(--muted));\r\n }\r\n\r\n .sc-image-placeholder--branded {\r\n background-color: hsl(var(--bg-tertiary));\r\n background-image: url('../../assets/images/micdrop-logo.png');\r\n background-repeat: no-repeat;\r\n background-position: center;\r\n /* keep the mark a small, calm watermark — never edge-to-edge */\r\n background-size: min(48%, 96px) auto;\r\n opacity: 0.92;\r\n }\r\n</style>\r\n"],"names":["createLogger","src","$","$$props","alt","className","fallback","loading","fit","blurUp","branded","attempt","notifiedError","decoded","mainImg","_s","_f","activeSrc","showImg","backdrop","objectFit","DEFINITE_BOX_CLASS","hasReservedBox","reserveStyle","handleLoad","e","img","loadedSrc","handleError","div","root","div_1","img_1","img_2","$$value","classes","classes_1","styles","cn","img_3","root_1","$0","styles_1","div_2","root_2","div_3","root_3","$$render","consequent_2","alternate","consequent","consequent_1","alternate_1"],"mappings":";;;;iBAoFA;iBAKcA,EAAa,OAAO,GAKnB,OACJ,UAAY,OAAiB,QAAQ,KAAK;AA+DnD,MACEC,IAAGC,EAAA,KAAAC,GAAA,OAAA,GAAG,EAAE,GACRC,wBAAM,EAAE,GACDC,0BAAY,EAAE,GACrBC,6BAAW,EAAE,GACbC,4BAAU,MAAM,GAChBC,wBAAM,eAAe,GAIrBC,2BAAS,EAAI,GACbC,4BAAU,EAAI,GAWZC,IAAyCT,EAAA,MAAMA,EAAA;AAAA;AAAA,IAEjDD,MAAM,QAAQK,EAAQ,IAAG,aAAa;AAAA,MAMpCM,IAAgBV,EAAA,MAAO,EAAK,GAI5BW,IAAUX,EAAA,MAAO,EAAK,GAMtBY,IAAwCZ,EAAA,MAAM,MAAA;AAElD,EAAAA,EAAA,kBAAc;AAEZ,UAAMa,IAAKd,EAAG,GACRe,IAAKV,EAAQ;UACnBK,GAAUI,IAAK,QAAQC,IAAK,aAAa,UAAQ,EAAA,GACjDd,EAAA,IAAAU,GAAgB,EAAK,GACrBV,EAAA,IAAAW,GAAU,EAAK;AAAA,EACjB,CAAC;AAED,MAAII,IAASf,EAAA,QAAA,MAAAA,EAAA,IACXS,CAAO,MAAK,QAAQV,EAAG,IAAGC,EAAA,IAAAS,CAAO,MAAK,aAAaL,EAAQ,IAAG,EAAE;AAWlE,EAAAJ,EAAA,kBAAc;IACPD,EAAG,GACHK,EAAQ,SACRW,CAAS,GACZf,EAAA,IAAEY,CAAO,GAAE,YAAQZ,EAAA,IAAIY,CAAO,EAAC,eAAe,KAACZ,EAAA,IAAEW,GAAU,EAAI;AAAA,EACnE,CAAC;AACD,MAAIK,IAAOhB,EAAA,QAAA,MAAAA,EAAA,IAAYS,CAAO,MAAK,oBAAcM,CAAS,CAAA,GAItDE,IAAQjB,EAAA,QAAA,MAAYM,EAAG,MAAK,eAAe,GAC3CY,IAASlB,EAAA,QAAA,MAAAA,EAAA,IAAYiB,CAAQ,IAAG,YAAYX,GAAG;AA4BnD,QAAMa,IAAqB;AAC3B,MAAIC,IAAcpB,EAAA,QAAA,MAAA,CAAA,CAAAC,EAAA,eAAAA,EAAA,SAEJ,QAAIA,EAAA,UAAc,QAC5BkB,EAAmB,KAAKhB,EAAS,CAAA,CAAA;AAKrC,EAAAH,EAAA,kBAAc;AAAA,EAWd,CAAC;AAID,MAAIqB,IAAYrB,EAAA,QAAA,MAAA;AAAA,IAEHC,EAAA,SAAA,8BAA4B;AAAA,IAC3BA,EAAA,UAAA,gCAA8B;AAAA,sDACM;AAAA,EAE7C,EAAA,OAAO,OAAO,EACd,KAAK,GAAG,CAAA;AAIb,iBAAeqB,EAAWC,GAAU;AAClC,UAAMC,IAAMD,EAAE,eAKRE,UAAYV,CAAS;AAC3B,QAAI;AAGF,YAAMS,EAAI,SAAM;AAAA,IAClB,QAAQ;AAAA,IAER;AAGA,IAAExB,EAAA,IAAEe,CAAS,MAAKU,MAClBzB,EAAA,IAAAW,GAAU,EAAI,cACLY,CAAC;AAAA,EACZ;AAEA,WAASG,IAAc;AAErB,QAAE1B,EAAA,IAAES,CAAO,MAAK,SAASL,OAAYA,QAAaL,KAAK;AACrD,MAAAC,EAAA,IAAAS,GAAU,UAAU;AACpB;AAAA,IACF;AAKA,IAAAT,EAAA,IAAAS,GAAU,QAAQ,GAChBT,EAAA,IAAGU,CAAa,MAChBV,EAAA,IAAAU,GAAgB,EAAI;EAGxB;;;;UAOCiB,IAAGC,EAAA;;AAKD,UAAAC,YALFF,CAAG,GAMCG,YADFD,CAAG;cAAHA,CAAG;AAYH,UAAAE,cAZAF,GAAG,CAAA;;kBAYHE,GAAG,CAAAC,MAAAhC,EAAA,IACSY,GAAOoB,CAAA,GAAA,MAAAhC,EAAA,IAAPY,CAAO,CAAA,WAlBrBe,CAAG;;AAAH,UAAAM,IAAAjC,EAAA,UAAA2B,qEAEoCP,CAAc,EAAA,CAAA,eAFlDO,GAAG3B,EAAA,IAGKqB,CAAY,KAAI,MAAS,GAG7BrB,EAAA,cAAA8B,gBACMf,CAAS,CAAA,GADff,EAAA,cAAA8B,cAMEzB,EAAO,CAAA,mBANTyB,GAAG,aAAA7B,EAAA,SAAA,mBAAH6B,GAAG,iBAAA7B,EAAA,aAAA,GAWLD,EAAA,cAAA+B,gBAEMhB,CAAS,CAAA,GAFff,EAAA,cAAA+B,UAGE7B,EAAG,CAAA,mBAHL6B,GAAG,GAAA,iCAAA,MAAAG,GAAA;AAAA,8CAK8Bd,CAAc;AAAA,YACf,2BAAAb,EAAM,YAAKI,CAAO;AAAA,8BANlDoB,GAAG,SAAA9B,EAAA,KAAA,mBAAH8B,GAAG,UAAA9B,EAAA,MAAA,GAAHD,EAAA,cAAA+B,cAUE1B,EAAO,CAAA,mBAVT0B,GAAG,aAAA9B,EAAA,SAAA,mBAAH8B,GAAG,iBAAA9B,EAAA,aAAA,GAAHkC,IAAAnC,EAAA,UAAA+B,gCAOmBb,CAAS,EAAA,CAAA;AAAA;sBAvBtBkB,EAAG,+BAA+BjC,EAAS,CAAA,CAAA,CAAA;AAAA,SAgBjDH,EAAA,MAAA,SAAA+B,GAcUL,CAAW,GAdrB1B,EAAA,MAAA,QAAA+B,GAeST,CAAU,mBAfnBS,CAAG,eAjBLJ,CAAG;AAAA;UAsCHU,IAAGC,EAAA;;kBAAHD,GAAG,CAAAL,MAAAhC,EAAA,IACSY,GAAOoB,CAAA,GAAA,MAAAhC,EAAA,IAAPY,CAAO,CAAA;;AADnB,UAAAZ,EAAA,cAAAqC,gBAEMtB,CAAS,CAAA,GAFff,EAAA,cAAAqC,UAGEnC,EAAG,CAAA,GAHLF,EAAA,cAAAqC,cAIEhC,EAAO,CAAA,mBAJTgC,GAAG,aAAApC,EAAA,SAAA,mBAAHoC,GAAG,iBAAApC,EAAA,aAAA,mBAAHoC,GAAG,SAAApC,EAAA,KAAA,mBAAHoC,GAAG,UAAApC,EAAA,MAAA,eAAHoC,GAAG,GAAAE,GAAA,gBAAA,mBAAHF,GAAG,IAAAG,GAAA;AAAA,gCAcgBtB,CAAS;AAAA,6CACQ;AAAA;;;uBAN5BkB,EACL,kBACA7B,EAAM,YAAKI,CAAO,KAAI,qBACtBR,EAAS,CAAA,CAAA;AAAA;SAZZH,EAAA,MAAA,SAAAqC,GAiBUX,CAAW,GAjBrB1B,EAAA,MAAA,QAAAqC,GAkBSf,CAAU,mBAlBnBe,CAAG,eAAHA,CAAG;AAAA;;;;cAyBDI,IAAGC,EAAA;;;0BAAHD,GAAG,GAAAF,GAAA,gBAAA,eAAHE,GAAGzC,EAAA,IAMKqB,CAAY,KAAI,MAAS,GANjCrB,EAAA,cAAAyC,iBAQavC,EAAG,CAAA;AAAA;;cAPR,MAAAF,EAAA,KAAAoC,EACL,yDACA5B,OAAW,iCACXL,GAAS,CAAA;AAAA;yBAJZsC,CAAG;AAAA;cAWHE,IAAGC,EAAA;;;0BAAHD,GAAG,GAAAJ,GAAA,gBAAA,eAAHI,GAAG3C,EAAA,IAMKqB,CAAY,KAAI,MAAS;AAAA;;cALzB,MAAArB,EAAA,KAAAoC,EACL,yDACA5B,OAAW,iCACXL,GAAS,CAAA;AAAA;yBAJZwC,CAAG;AAAA;;UAZDzC,EAAG,IAAA2C,EAAAC,CAAA,IAAAD,EAAAE,GAAA,EAAA;AAAA;;;;;YAlEL/B,CAAO,KAAAhB,EAAA,IAAIiB,CAAQ,IAAA4B,EAAAG,CAAA,IAAAhD,EAAA,IAuCdgB,CAAO,IAAA6B,EAAAI,GAAA,CAAA,IAAAJ,EAAAK,GAAA,EAAA;AAAA;;;AAzCT;","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"Image-BktsxRho.js","sources":["../node_modules/@getmicdrop/svelte-components/dist/primitives/Image/Image.svelte"],"sourcesContent":["<!--\r\n Image.svelte\r\n\r\n The canonical image primitive for Micdrop. Variable-aspect, user-uploaded\r\n sources (event posters, performer headshots, venue photos) where we do NOT\r\n control the aspect ratio. This component is now the single home for the\r\n whole image family — `Avatar` composes it, and `BlurBackdropImage` is a\r\n thin `@deprecated` shim.\r\n\r\n Premium contract (Atlas brief 04 — perf 5 / completeness 5):\r\n\r\n 1. ZERO CLS — pass `width`/`height` (intrinsic px) or `aspectRatio`\r\n (e.g. `'2/3'`, `'16/9'`, `'1'`). The component reserves that space\r\n BEFORE the image loads so the page never reflows when it arrives.\r\n A height-only sizing class (`h-8`, `size-10`, `aspect-video`) counts\r\n too — see `DEFINITE_BOX_CLASS` below for exactly which spellings.\r\n Dev-only `console.warn` if you provide neither dimensions nor one of\r\n those classes (we can't reserve space and CLS can creep back in).\r\n\r\n The width is still free: in normal block flow it fills the parent,\r\n and in a shrink-to-fit context (flex item, grid item, inline-block,\r\n absolutely positioned) it takes the width the bitmap's own ratio\r\n gives it at that height. `<Image class=\"h-8 w-auto\" />` inside a\r\n flex row is the auth-page wordmark and it renders at its natural\r\n ratio. That was NOT true before pad-endgame x162: the wrapper was a\r\n `container-type: inline-size` size container, which makes an element\r\n compute its inline size as if it had no contents, so every one of\r\n those shrink-to-fit contexts collapsed it — to ZERO as a flex item or\r\n absolutely positioned, to a 3.9px sliver as an inline-block — and\r\n `overflow: hidden` clipped the image away. The size container now lives on the\r\n absolutely-positioned blur layer, which contributes nothing to the\r\n wrapper's width by construction.\r\n\r\n 2. BLUR-UP LOADING — the main image starts slightly blurred and SHARPENS\r\n (blur → 0) once the real bitmap has decoded (`img.decode()` +\r\n `decoding=\"async\"`). In blur-backdrop framing a blurred copy of the\r\n SAME already-fetched bitmap fills the letterbox gaps — no second\r\n network fetch, no LQIP asset to ship. Fade timing reads the motion\r\n tokens, so `prefers-reduced-motion` collapses it automatically.\r\n\r\n 3. BLUR-BACKDROP IS THE DEFAULT FRAMING — `fit` defaults to\r\n `'blur-backdrop'`: the image is `object-fit: contain` (never cropped)\r\n and a blurred copy of itself fills the letterbox gaps. This handles\r\n BOTH tall posters and wide photos with no cropping and no flat-gray\r\n bars. `'cover'` / `'contain'` / `'fill'` / `'scale-down'` / `'none'`\r\n remain as escape hatches and render the plain single-`<img>` path\r\n (identical DOM to the pre-premium component).\r\n\r\n 4. BRANDED FALLBACK — when `src` (and `fallback`) are missing or both\r\n error, we render a branded placeholder (the Micdrop mark on a tint)\r\n instead of a flat gray div. Override the asset with `fallback`, or\r\n suppress the mark with `branded={false}`.\r\n\r\n Passthrough props for raw-<img> parity (so consumers can migrate\r\n existing `<img>` sites to `<Image>`):\r\n - `draggable` — forwarded to the underlying `<img draggable>`.\r\n - `onload` — forwarded to the `<img>` load event.\r\n - `fetchpriority` — forwarded to `<img fetchpriority>` (resource hint).\r\n - `onError` — fires ONCE, only after the internal fallback chain is\r\n exhausted (i.e. the branded placeholder takes over). It does NOT fire\r\n on the first error while a distinct `fallback` is still going to be\r\n tried. The raw `onerror` handler stays owned internally to drive the\r\n src→fallback→placeholder degradation; `onError` composes with it\r\n rather than replacing it.\r\n Deliberately NOT exposed (closed-interface rulings, sc#682):\r\n - `srcset`/`sizes` — zero consumer demand.\r\n - `onclick` — interactive semantics belong on an interactive WRAPPER\r\n (`<a>` for navigation, `<button type=\"button\">` otherwise) around\r\n `<Image>`, never on the img itself. A clickable img is a keyboard trap\r\n that only compiles behind a11y suppressions; the wrapper gets focus +\r\n key handling for free and nothing in this interface blocks it.\r\n - `aria-hidden` — redundant. `alt=\"\"` (the default) maps the img to role\r\n none/presentation per HTML-AAM, removing it from the accessibility\r\n tree already. Decorative icons: `alt=\"\"` + `fit=\"contain\"` +\r\n `blurUp={false}` (plain single-<img> DOM).\r\n - an errored-element `onError(event)` — the src-swap-on-error use case IS\r\n the `fallback` prop (src → fallback → branded placeholder, loop-safe).\r\n Consumers never need the raw element.\r\n\r\n Example:\r\n <Image src={event.posterUrl} alt={event.name} aspectRatio=\"2/3\" class=\"w-full rounded-xl\" />\r\n <Image src={user.avatarUrl} alt={user.name} width={80} height={80} fit=\"cover\" class=\"rounded-xl\" />\r\n <Image src={banner.url} alt=\"\" aspectRatio=\"16/9\" class=\"w-full\" loading=\"eager\" fetchpriority=\"high\" />\r\n-->\r\n<script lang=\"ts\">\r\n import { DEV } from 'esm-env';\r\n import { cn } from '../../utils/classNames.js';\r\n import { createLogger } from '../../utils/logger.js';\r\n\r\n const log = createLogger('Image');\r\n\r\n // Silence the dev CLS nudge under the test runner (the suite intentionally\r\n // renders without dimensions to exercise other behaviour). Reads the Node\r\n // env var Vitest sets — bundler-agnostic.\r\n const IS_TEST =\r\n typeof process !== 'undefined' && !!process.env?.VITEST;\r\n\r\n interface Props {\r\n /** Image source URL. When empty/missing, falls back to `fallback`. */\r\n src?: string;\r\n /** Alt text. Empty string marks decorative images per WCAG. */\r\n alt?: string;\r\n /** Additional CSS classes (sizing, shape, rounded corners). Wins last. */\r\n class?: string;\r\n /** Fallback URL used when src is empty or errors (before the branded mark). */\r\n fallback?: string;\r\n /** Loading strategy. Default 'lazy'; pass 'eager' for above-fold. */\r\n loading?: 'eager' | 'lazy';\r\n /**\r\n * Framing mode. Default `'blur-backdrop'` — `object-fit: contain` over a\r\n * blurred copy of the same image so tall AND wide sources are never\r\n * cropped and never letterboxed with flat gray. The remaining values are\r\n * escape hatches that render a plain single `<img object-fit:…>`.\r\n */\r\n fit?: 'blur-backdrop' | 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';\r\n /**\r\n * Intrinsic width in CSS px — reserves space before load (zero CLS) and\r\n * sets the `<img width>` attribute. Pair with `height` for a fixed box.\r\n */\r\n width?: number;\r\n /**\r\n * Intrinsic height in CSS px — reserves space before load (zero CLS) and\r\n * sets the `<img height>` attribute. Pair with `width` for a fixed box.\r\n */\r\n height?: number;\r\n /**\r\n * CSS `aspect-ratio` string (e.g. `'2/3'` posters, `'16/9'` banners,\r\n * `'1'` square). Reserves space before load when you size by one axis\r\n * (`w-full`) — the zero-CLS path for fluid layouts.\r\n */\r\n aspectRatio?: string;\r\n /**\r\n * Blur-up loading: render blurred, then sharpen once the real bitmap\r\n * decodes. Default true. Set false to skip the effect (e.g. tiny icons\r\n * where the blur is imperceptible but the extra work isn't worth it).\r\n */\r\n blurUp?: boolean;\r\n /**\r\n * When the fallback chain is exhausted, show the branded Micdrop mark on\r\n * a tint. Default true. Set false for a plain tinted placeholder.\r\n */\r\n branded?: boolean;\r\n /** Forwarded to `<img draggable>`. Omitted when undefined. */\r\n draggable?: boolean;\r\n /** Forwarded to the `<img>` load event. */\r\n // eslint-disable-next-line no-unused-vars -- intentionally retained (prop/slot/forward-compat or Svelte-5 reactive binding eslint cannot see)\r\n onload?: (e: Event) => void;\r\n /** Forwarded to `<img fetchpriority>` (fetch-priority resource hint). */\r\n fetchpriority?: 'high' | 'low' | 'auto';\r\n /**\r\n * Fires once when the fallback chain is exhausted and the branded\r\n * placeholder takes over — NOT on the first error if a distinct\r\n * `fallback` is still going to be tried. Composes with the internal\r\n * `onerror` machine.\r\n */\r\n onError?: () => void;\r\n }\r\n\r\n let {\r\n src = '',\r\n alt = '',\r\n class: className = '',\r\n fallback = '',\r\n loading = 'lazy',\r\n fit = 'blur-backdrop',\r\n width,\r\n height,\r\n aspectRatio,\r\n blurUp = true,\r\n branded = true,\r\n draggable,\r\n onload,\r\n fetchpriority,\r\n onError,\r\n }: Props = $props();\r\n\r\n // Track loading attempts: which URL we're showing right now.\r\n // When the current URL errors, drop to 'failed' and render the placeholder.\r\n // Distinct from src/fallback inputs because we need to remember which\r\n // candidate we already tried. Reset whenever inputs change.\r\n let attempt: 'src' | 'fallback' | 'failed' = $state(\r\n // eslint-disable-next-line svelte/valid-compile -- known Svelte compiler note, accepted for this primitive\r\n src ? 'src' : fallback ? 'fallback' : 'failed'\r\n );\r\n\r\n // Guard so `onError` fires at most once per input set, even if a stale\r\n // <img> re-emits a duplicate final `error`. Reset when inputs change so a\r\n // fresh src/fallback can legitimately fail-and-notify again.\r\n let notifiedError = $state(false);\r\n\r\n // Blur-up: starts blurred, sharpens once the real bitmap decodes. Reset on\r\n // every new candidate URL so each swap re-runs the blur-up reveal.\r\n let decoded = $state(false);\r\n\r\n // The rendered main <img>, so we can detect an already-decoded bitmap that\r\n // won't fire `load` again (a cached src re-assigned, or a re-mount onto a\r\n // cached URL). Without this, `decoded` sticks at false and the image stays\r\n // blurred forever — the \"avatar goes blurry after save\" bug.\r\n let mainImg: HTMLImageElement | undefined = $state();\r\n\r\n $effect(() => {\r\n // Re-derive when inputs change. (Read both to register dependencies.)\r\n const _s = src;\r\n const _f = fallback;\r\n attempt = _s ? 'src' : _f ? 'fallback' : 'failed';\r\n notifiedError = false;\r\n decoded = false;\r\n });\r\n\r\n let activeSrc = $derived(\r\n attempt === 'src' ? src : attempt === 'fallback' ? fallback : ''\r\n );\r\n\r\n // Cached-bitmap reveal: after the shown URL settles, a browser that already\r\n // has the image marks the <img> `complete` WITHOUT re-firing `load` (cache\r\n // hit, or a mount whose load event landed before the handler attached). Reveal\r\n // it immediately so it never sticks blurred; a genuinely-loading image is\r\n // `complete: false` here and still waits for `handleLoad`. Depends on the SAME\r\n // inputs as the reset effect (src/fallback) — plus activeSrc — so it always\r\n // re-runs right after the reset (declaration order) and reads the post-update\r\n // <img>, even when the resolved URL is unchanged.\r\n $effect(() => {\r\n void src;\r\n void fallback;\r\n void activeSrc;\r\n if (mainImg?.complete && mainImg.naturalWidth > 0) decoded = true;\r\n });\r\n let showImg = $derived(attempt !== 'failed' && !!activeSrc);\r\n\r\n // blur-backdrop is the only framing mode that wraps; everything else is a\r\n // plain single <img object-fit:…> (identical DOM to the legacy component).\r\n let backdrop = $derived(fit === 'blur-backdrop');\r\n let objectFit = $derived(backdrop ? 'contain' : fit);\r\n\r\n // Does the consumer reserve a DEFINITE box — one that fixes the rendered\r\n // HEIGHT before the bitmap's intrinsic dimensions are known? Only these\r\n // prevent vertical CLS:\r\n // - aspectRatio (height derives from width via the ratio), OR\r\n // - both width AND height (a fully fixed box), OR\r\n // - a `size-*` utility (sets width AND height together), OR\r\n // - a definite height / aspect-ratio class (`h-*`, `aspect-*`).\r\n // Deliberately NOT counted: width alone, `w-full`, `max-h-*`, `h-auto`,\r\n // AND `min-h-*` — min-h only reserves a FLOOR, so a taller bitmap still\r\n // grows the box and shifts the page. None of these reserve the actual\r\n // vertical extent before metadata, so CLS can still creep in. (`max-h-*`\r\n // and `min-h-*` are excluded by the leading `(?:^|\\s)` — the `h-` in them\r\n // is preceded by `-`, never by whitespace.)\r\n //\r\n // KNOWN LIMIT, stated because the reserved-box rules drive layout and not\r\n // just the warning: the same leading `(?:^|\\s)` means a VARIANT-PREFIXED\r\n // class does not match either — `md:h-8`, `sm:size-8`, `dark:aspect-video`\r\n // all read as NO reserved box. Such a consumer gets the dev CLS warning at\r\n // every width, and above the breakpoint the wrapper has a definite height\r\n // while the main image is still on the `height:auto` path, so a tall bitmap\r\n // is clipped by the wrapper instead of contained inside it. No live\r\n // consumer sizes an Image that way today (checked across micdrop-frontend\r\n // 2026-08-01), which is why this is recorded rather than widened here:\r\n // matching them means matching `h-` after `:` too, and that also matches\r\n // arbitrary values like `[&>img]:h-8`, so it is its own change with its own\r\n // test, not a regex tweak smuggled into a sizing fix.\r\n const DEFINITE_BOX_CLASS = /(?:^|\\s)(?:aspect-|size-|h-(?!auto\\b))/;\r\n let hasReservedBox = $derived(\r\n !!aspectRatio ||\r\n (width != null && height != null) ||\r\n DEFINITE_BOX_CLASS.test(className)\r\n );\r\n\r\n // Dev-only nudge: without a definite box we cannot reserve VERTICAL space,\r\n // so CLS can creep back in. Warn, never throw.\r\n $effect(() => {\r\n // Dev-only (tree-shaken from prod via esm-env DEV) and never under test.\r\n if (DEV && !IS_TEST && !hasReservedBox) {\r\n log.warn(\r\n 'No aspectRatio, no width+height pair, and no definite height/aspect ' +\r\n 'sizing class — vertical layout space cannot be reserved and the ' +\r\n 'page may shift when the image loads (CLS). Pass aspectRatio=\"2/3\", ' +\r\n 'both width and height, or an h-*/aspect-* class. (width alone or ' +\r\n 'w-full does not reserve vertical space.)'\r\n );\r\n }\r\n });\r\n\r\n // Reserve intrinsic space on the box that owns layout. For blur-backdrop\r\n // that's the wrapper; for the plain path it's the <img> itself.\r\n let reserveStyle = $derived(\r\n [\r\n width != null ? `width:${width}px` : '',\r\n height != null ? `height:${height}px` : '',\r\n aspectRatio ? `aspect-ratio:${aspectRatio}` : '',\r\n ]\r\n .filter(Boolean)\r\n .join(';')\r\n );\r\n\r\n // mark the real bitmap as decoded → triggers the blur→sharp fade.\r\n async function handleLoad(e: Event) {\r\n const img = e.currentTarget as HTMLImageElement;\r\n // Capture which URL this load is FOR. If `src` swaps mid-decode (the\r\n // active candidate changes), this stale resolution must NOT sharpen — or\r\n // fire onload for — the new image. Compare against the live activeSrc\r\n // after the await and bail if it moved on.\r\n const loadedSrc = activeSrc;\r\n try {\r\n // decode() resolves once the bitmap is paint-ready; avoids revealing a\r\n // half-painted image. Falls through if unsupported / aborted.\r\n await img.decode?.();\r\n } catch {\r\n // decode can reject on detached/aborted images — reveal anyway.\r\n }\r\n // Src swapped while we awaited decode() → this is a stale load. Drop it;\r\n // the new candidate's own load event will drive the reveal.\r\n if (activeSrc !== loadedSrc) return;\r\n decoded = true;\r\n onload?.(e);\r\n }\r\n\r\n function handleError() {\r\n // If we were on src and have a distinct fallback to try, advance.\r\n if (attempt === 'src' && fallback && fallback !== src) {\r\n attempt = 'fallback';\r\n return;\r\n }\r\n // Either fallback already attempted, or no distinct fallback exists.\r\n // The chain is exhausted — the branded placeholder takes over. Notify the\r\n // consumer exactly here (final failure only), never on the transient\r\n // src→fallback hop, and at most once per input set.\r\n attempt = 'failed';\r\n if (!notifiedError) {\r\n notifiedError = true;\r\n onError?.();\r\n }\r\n }\r\n</script>\r\n\r\n{#if showImg && backdrop}\r\n <!-- blur-backdrop framing (default): contain + same-image blurred fill.\r\n The wrapper owns layout + reserves space; the blur layer is a second\r\n cheap reuse of the already-fetched bitmap (no extra network fetch). -->\r\n <div\r\n class={cn('sc-image sc-image--backdrop', className)}\r\n class:sc-image--backdrop-reserved={hasReservedBox}\r\n style={reserveStyle || undefined}\r\n >\r\n <div class=\"sc-image__blur-layer\">\r\n <img\r\n src={activeSrc}\r\n alt=\"\"\r\n class=\"sc-image__blur\"\r\n aria-hidden=\"true\"\r\n decoding=\"async\"\r\n {loading}\r\n {draggable}\r\n {fetchpriority}\r\n />\r\n </div>\r\n <img\r\n bind:this={mainImg}\r\n src={activeSrc}\r\n {alt}\r\n class=\"sc-image__main\"\r\n class:sc-image__main--reserved={hasReservedBox}\r\n class:sc-image__main--loading={blurUp && !decoded}\r\n style:object-fit={objectFit}\r\n {width}\r\n {height}\r\n {loading}\r\n {draggable}\r\n {fetchpriority}\r\n decoding=\"async\"\r\n onerror={handleError}\r\n onload={handleLoad}\r\n />\r\n </div>\r\n{:else if showImg}\r\n <!-- escape-hatch framing (cover/contain/fill/none/scale-down): plain single\r\n <img>, identical DOM to the legacy component, plus blur-up + dims. -->\r\n <img\r\n bind:this={mainImg}\r\n src={activeSrc}\r\n {alt}\r\n {loading}\r\n {draggable}\r\n {fetchpriority}\r\n {width}\r\n {height}\r\n class={cn(\r\n 'sc-image image',\r\n blurUp && !decoded && 'sc-image--loading',\r\n className\r\n )}\r\n style:object-fit={objectFit}\r\n style:aspect-ratio={aspectRatio || undefined}\r\n decoding=\"async\"\r\n onerror={handleError}\r\n onload={handleLoad}\r\n />\r\n{:else}\r\n <!-- No usable src — branded placeholder (Micdrop mark on a tint), or a plain\r\n tinted box when branded={false}. Empty alt marks decorative images (per\r\n WCAG); hide from assistive tech via aria-hidden + no role. -->\r\n {#if alt}\r\n <div\r\n class={cn(\r\n 'sc-image image sc-image-placeholder image-placeholder',\r\n branded && 'sc-image-placeholder--branded',\r\n className\r\n )}\r\n style={reserveStyle || undefined}\r\n role=\"img\"\r\n aria-label={alt}\r\n ></div>\r\n {:else}\r\n <div\r\n class={cn(\r\n 'sc-image image sc-image-placeholder image-placeholder',\r\n branded && 'sc-image-placeholder--branded',\r\n className\r\n )}\r\n style={reserveStyle || undefined}\r\n aria-hidden=\"true\"\r\n ></div>\r\n {/if}\r\n{/if}\r\n\r\n<style>\r\n /* `.image` is a legacy back-compat alias of `.sc-image` on the plain\r\n escape-hatch <img> + placeholder (consumer CSS / tests may target it). */\r\n .sc-image,\r\n .image {\r\n display: block;\r\n max-width: 100%;\r\n }\r\n\r\n /* --- blur-backdrop framing ---\r\n THE WRAPPER IS NOT A SIZE CONTAINER, AND MUST NOT BECOME ONE AGAIN (x162).\r\n It used to carry `container-type: inline-size` for the small-container blur\r\n rule below. Inline-size containment makes an element compute its inline size\r\n AS IF IT HAD NO CONTENTS — so in every shrink-to-fit context (flex item,\r\n inline-block, absolutely positioned) `width: auto` collapsed, the main image\r\n at `width: 100%` collapsed with it, and `overflow: hidden` clipped the whole\r\n thing away. Measured in Chromium at 104x30 natural size: as a flex item and\r\n absolutely positioned it is exactly 0 (wrapper 0x32, main image 0x32); as an\r\n inline-block it is a 3.9px sliver. Every wordmark on the auth pages\r\n rendered as nothing. Normal block flow was unaffected (the parent's width is\r\n definite there), which is why it survived so long. */\r\n .sc-image--backdrop {\r\n position: relative;\r\n overflow: hidden;\r\n background: hsl(var(--bg-quaternary));\r\n }\r\n\r\n /* The size container lives HERE instead. This layer is absolutely positioned,\r\n so it contributes nothing to the wrapper's intrinsic width BY CONSTRUCTION —\r\n containment on it can never collapse the box the way it did on the wrapper.\r\n\r\n ONE MEASUREMENT CHANGED WITH IT, deliberately: the query below now reads the\r\n wrapper's PADDING box (this layer's own box) where the old wrapper container\r\n read its CONTENT box. On a padded wrapper those differ. The padding box is\r\n the right one — the rule exists so the blur's opaque area still reaches the\r\n visible edge after the halo grows, and the blur fills the padding box, not\r\n the content box. No consumer pads an Image today either way. */\r\n .sc-image__blur-layer {\r\n position: absolute;\r\n inset: 0;\r\n container-type: inline-size;\r\n /* decorative; never take a hit that belongs to the wrapper */\r\n pointer-events: none;\r\n }\r\n\r\n .sc-image__blur {\r\n display: block;\r\n width: 100%;\r\n height: 100%;\r\n max-width: none;\r\n object-fit: cover;\r\n transform: scale(1.15);\r\n filter: blur(16px) saturate(1.2);\r\n /* purely decorative fill; the absolutely-positioned blur layer paints first\r\n and the in-flow main layer (position:relative) stacks above it by source\r\n order — no explicit z-index needed. */\r\n }\r\n\r\n /* Small containers (<=80px): blur() applies before scale() in the render\r\n pipeline, so the blur halo gets scaled too. Need enough scale that the\r\n opaque image extends past the container edge even after the halo grows.\r\n Measured unchanged by the containment move (Chromium): a 40px avatar box\r\n still resolves to scale(2), a 160px box still resolves to scale(1.15). */\r\n @container (max-width: 5rem) {\r\n .sc-image__blur {\r\n transform: scale(2);\r\n filter: blur(6px) saturate(1.2);\r\n }\r\n }\r\n\r\n .sc-image__main {\r\n position: relative;\r\n display: block;\r\n width: 100%;\r\n /* No reserved box (legacy / no-fit default): the in-flow main image\r\n DRIVES the wrapper height and sizes ITSELF to the consumer's sizing\r\n classes — which land on the wrapper. `max-height: inherit` /\r\n `max-width: inherit` pull the wrapper's `max-h-*` / `max-w-*` onto the\r\n image so object-fit:contain shrinks it to fit (image height == wrapper\r\n height). The image therefore NEVER exceeds the wrapper, so the wrapper's\r\n overflow:hidden (which clips the decorative blur fill) cannot clip the\r\n MAIN image — it renders exactly as the pre-premium single <img> did,\r\n constrained by max-h-* / h-auto, no reflow. Only force the image to fill\r\n a fixed box when the consumer reserved a DEFINITE one (explicit height /\r\n aspectRatio / size-* / h-* / aspect-*) — there the wrapper owns layout\r\n and the image fills it (true zero-CLS letterbox). */\r\n height: auto;\r\n max-width: inherit;\r\n max-height: inherit;\r\n object-fit: contain;\r\n }\r\n\r\n .sc-image--backdrop-reserved .sc-image__main--reserved {\r\n height: 100%;\r\n max-width: none;\r\n max-height: none;\r\n }\r\n\r\n /* --- blur-up reveal (CSS-only; reduced-motion gated via motion tokens) ---\r\n The main image / plain image starts slightly blurred + scaled and\r\n sharpens on decode. Durations read from --motion-* so\r\n prefers-reduced-motion collapses them. */\r\n .sc-image--loading,\r\n .sc-image__main {\r\n transition:\r\n filter var(--motion-normal) var(--ease-smooth),\r\n transform var(--motion-normal) var(--ease-smooth);\r\n }\r\n\r\n .sc-image--loading,\r\n .sc-image__main--loading {\r\n filter: blur(12px);\r\n transform: scale(1.02);\r\n }\r\n\r\n /* --- placeholder --- */\r\n .sc-image-placeholder {\r\n background: hsl(var(--bg-quaternary));\r\n }\r\n\r\n /* DARK ONLY. `--bg-quaternary` is the deepest surface token, and in dark that is\r\n literally `0 0% 0%` (tokens.css) against a card at 10% lightness — so an empty\r\n image slot painted pure black reads as a hole punched in the card, not as an empty\r\n box. `--muted` is 16.9% in dark, a 6.9-point step ABOVE the card, which is what\r\n an empty box is supposed to look like. Peet ruled the no-artwork state must be a\r\n grey box (2026-07-29, on the x48 deck); this is the half of that ruling the dark\r\n theme was failing.\r\n LIGHT IS DELIBERATELY UNTOUCHED: `--bg-quaternary` is 91% there and reads correctly\r\n on a white card, and `--muted` at 95.9% would fade the box Peet just approved. One\r\n token per theme, both already in the palette — no new token minted for this. */\r\n :global([data-theme='dark']) .sc-image-placeholder {\r\n background: hsl(var(--muted));\r\n }\r\n\r\n .sc-image-placeholder--branded {\r\n background-color: hsl(var(--bg-tertiary));\r\n background-image: url('../../assets/images/micdrop-logo.png');\r\n background-repeat: no-repeat;\r\n background-position: center;\r\n /* keep the mark a small, calm watermark — never edge-to-edge */\r\n background-size: min(48%, 96px) auto;\r\n opacity: 0.92;\r\n }\r\n</style>\r\n"],"names":["createLogger","src","$","$$props","alt","className","fallback","loading","fit","blurUp","branded","attempt","notifiedError","decoded","mainImg","_s","_f","activeSrc","showImg","backdrop","objectFit","DEFINITE_BOX_CLASS","hasReservedBox","reserveStyle","handleLoad","e","img","loadedSrc","handleError","div","root","div_1","img_1","img_2","$$value","classes","classes_1","styles","cn","img_3","root_1","$0","styles_1","div_2","root_2","div_3","root_3","$$render","consequent_2","alternate","consequent","consequent_1","alternate_1"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "svelte/internal/disclose-version";
|
|
2
2
|
import * as e from "svelte/internal/client";
|
|
3
|
-
import { Z as f } from "./VenueCalendar-
|
|
3
|
+
import { Z as f } from "./VenueCalendar-Ys8-209-.js";
|
|
4
4
|
var g = e.from_svg('<path d="M224,144v64a8,8,0,0,1-8,8H40a8,8,0,0,1-8-8V144a8,8,0,0,1,16,0v56H208V144a8,8,0,0,1,16,0Zm-101.66,5.66a8,8,0,0,0,11.32,0l40-40A8,8,0,0,0,168,96H136V32a8,8,0,0,0-16,0V96H88a8,8,0,0,0-5.66,13.66Z"></path>'), k = e.from_svg('<line x1="128" y1="144" x2="128" y2="32" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"></line><polyline points="216 144 216 208 40 208 40 144" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"></polyline><polyline points="168 104 128 144 88 104" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"></polyline>', 1), w = e.from_svg('<svg aria-hidden="true" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><!></svg>');
|
|
5
5
|
function V(a, t) {
|
|
6
6
|
e.push(t, !0);
|
|
@@ -55,4 +55,4 @@ export {
|
|
|
55
55
|
V as D,
|
|
56
56
|
H as M
|
|
57
57
|
};
|
|
58
|
-
//# sourceMappingURL=MailIcon-
|
|
58
|
+
//# sourceMappingURL=MailIcon-3o_dDUzN.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MailIcon-
|
|
1
|
+
{"version":3,"file":"MailIcon-3o_dDUzN.js","sources":["../node_modules/@getmicdrop/svelte-components/dist/primitives/Icons/phosphor/DownloadIcon.svelte","../node_modules/@getmicdrop/svelte-components/dist/primitives/Icons/phosphor/MailIcon.svelte"],"sourcesContent":["<script lang=\"ts\">\n /**\n * Download — Phosphor icon (canonical Micdrop icon family).\n * Outline by default; pass `weight=\"fill\"` for solid, or let a stateful parent\n * (NavItem / Tabs / BottomNav / status badge) drive it via icon-weight context.\n */\n import { useIconWeight, type IconWeight } from './iconWeight.js';\n\n interface Props {\n /** Pixel size (width + height). */\n size?: string;\n /** Icon color; defaults to `currentColor` (inherits text color). */\n color?: string;\n /** Extra classes. */\n class?: string;\n /** `regular` (outline) or `fill` (solid). Overrides ambient state weight. */\n weight?: IconWeight;\n }\n\n let { size = '24', color = 'currentColor', class: className = '', weight }: Props = $props();\n\n const ctx = useIconWeight();\n let resolved: IconWeight = $derived(weight ?? ctx?.weight ?? 'regular');\n</script>\n\n<svg\n class={className}\n aria-hidden=\"true\"\n width={size}\n height={size}\n viewBox=\"0 0 256 256\"\n fill=\"currentColor\"\n style:color={color === 'currentColor' ? undefined : color}\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n {#if resolved === 'fill'}<path d=\"M224,144v64a8,8,0,0,1-8,8H40a8,8,0,0,1-8-8V144a8,8,0,0,1,16,0v56H208V144a8,8,0,0,1,16,0Zm-101.66,5.66a8,8,0,0,0,11.32,0l40-40A8,8,0,0,0,168,96H136V32a8,8,0,0,0-16,0V96H88a8,8,0,0,0-5.66,13.66Z\"/>{:else}<line x1=\"128\" y1=\"144\" x2=\"128\" y2=\"32\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><polyline points=\"216 144 216 208 40 208 40 144\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><polyline points=\"168 104 128 144 88 104\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/>{/if}\n</svg>\n","<script lang=\"ts\">\n /**\n * Mail — Phosphor icon (canonical Micdrop icon family).\n * Outline by default; pass `weight=\"fill\"` for solid, or let a stateful parent\n * (NavItem / Tabs / BottomNav / status badge) drive it via icon-weight context.\n */\n import { useIconWeight, type IconWeight } from './iconWeight.js';\n\n interface Props {\n /** Pixel size (width + height). */\n size?: string;\n /** Icon color; defaults to `currentColor` (inherits text color). */\n color?: string;\n /** Extra classes. */\n class?: string;\n /** `regular` (outline) or `fill` (solid). Overrides ambient state weight. */\n weight?: IconWeight;\n }\n\n let { size = '24', color = 'currentColor', class: className = '', weight }: Props = $props();\n\n const ctx = useIconWeight();\n let resolved: IconWeight = $derived(weight ?? ctx?.weight ?? 'regular');\n</script>\n\n<svg\n class={className}\n aria-hidden=\"true\"\n width={size}\n height={size}\n viewBox=\"0 0 256 256\"\n fill=\"currentColor\"\n style:color={color === 'currentColor' ? undefined : color}\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n {#if resolved === 'fill'}<path d=\"M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48ZM98.71,128,40,181.81V74.19Zm11.84,10.85,12,11.05a8,8,0,0,0,10.82,0l12-11.05,58,53.15H52.57ZM157.29,128,216,74.18V181.82Z\"/>{:else}<polyline points=\"224 56 128 144 32 56\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><path d=\"M32,56H224a0,0,0,0,1,0,0V192a8,8,0,0,1-8,8H40a8,8,0,0,1-8-8V56A0,0,0,0,1,32,56Z\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><line x1=\"110.55\" y1=\"128\" x2=\"34.47\" y2=\"197.74\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/><line x1=\"221.53\" y1=\"197.74\" x2=\"145.45\" y2=\"128\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/>{/if}\n</svg>\n"],"names":["size","$","$$props","color","className","ctx","useIconWeight","resolved","svg","root_2","path","root","$$render","consequent","alternate","styles"],"mappings":";;;;iBAAA;;AAmBE,MAAMA,IAAIC,EAAA,KAAAC,GAAA,QAAA,GAAG,IAAI,GAAEC,0BAAQ,cAAc,GAASC,0BAAY,EAAE;AAEhE,QAAMC,IAAMC,EAAa;AACzB,MAAIC,IAAoBN,EAAA,QAAA,MAAAC,EAAA,UAAsBG,GAAK,UAAU,SAAS;MAGvEG,IAAEC,EAAA;;kBAAFD,CAAE;;;UAUyBE,IAAIC,EAAA;kBAAJD,CAAI;AAAA;;;;;AAAzB,MAAAT,EAAA,IAAAM,CAAQ,MAAK,SAAMK,EAAAC,CAAA,IAAAD,EAAAE,GAAA,EAAA;AAAA;;UAVzBN,CAAE;AAAF,IAAAP,EAAA,UAAAO,aACQJ,EAAS,CAAA,CAAA,GADjBH,EAAA,cAAAO,YAGQR,EAAI,CAAA,GAHZC,EAAA,cAAAO,aAISR,EAAI,CAAA,GAJbe,IAAAd,EAAA,UAAAO,mBAOcL,EAAK,MAAK,iBAAiB,SAAYA,EAAK,EAAA,CAAA;AAAA,kBAP1DK,CAAE;AAFK;;iBCvBR;;AAmBE,MAAMR,IAAIC,EAAA,KAAAC,GAAA,QAAA,GAAG,IAAI,GAAEC,0BAAQ,cAAc,GAASC,0BAAY,EAAE;AAEhE,QAAMC,IAAMC,EAAa;AACzB,MAAIC,IAAoBN,EAAA,QAAA,MAAAC,EAAA,UAAsBG,GAAK,UAAU,SAAS;MAGvEG,IAAEC,EAAA;;kBAAFD,CAAE;;;UAUyBE,IAAIC,EAAA;kBAAJD,CAAI;AAAA;;;;;AAAzB,MAAAT,EAAA,IAAAM,CAAQ,MAAK,SAAMK,EAAAC,CAAA,IAAAD,EAAAE,GAAA,EAAA;AAAA;;UAVzBN,CAAE;AAAF,IAAAP,EAAA,UAAAO,aACQJ,EAAS,CAAA,CAAA,GADjBH,EAAA,cAAAO,YAGQR,EAAI,CAAA,GAHZC,EAAA,cAAAO,aAISR,EAAI,CAAA,GAJbe,IAAAd,EAAA,UAAAO,mBAOcL,EAAK,MAAK,iBAAiB,SAAYA,EAAK,EAAA,CAAA;AAAA,kBAP1DK,CAAE;AAFK;","x_google_ignoreList":[0,1]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "svelte/internal/disclose-version";
|
|
2
2
|
import * as e from "svelte/internal/client";
|
|
3
|
-
import { M as O, a as R, b as j, c as _, e as k } from "./VenueCalendar-
|
|
4
|
-
import { M as q } from "./modalManager.svelte-
|
|
3
|
+
import { M as O, a as R, b as j, c as _, e as k } from "./VenueCalendar-Ys8-209-.js";
|
|
4
|
+
import { M as q } from "./modalManager.svelte-C6kq14zr.js";
|
|
5
5
|
var w = e.from_html("<!> <!> <!> <!>", 1), A = e.from_html("<!> <!>", 1);
|
|
6
6
|
function J(h, t) {
|
|
7
7
|
e.push(t, !0);
|
|
@@ -111,4 +111,4 @@ function J(h, t) {
|
|
|
111
111
|
export {
|
|
112
112
|
J as M
|
|
113
113
|
};
|
|
114
|
-
//# sourceMappingURL=Modal-
|
|
114
|
+
//# sourceMappingURL=Modal-aWfERkXe.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal-
|
|
1
|
+
{"version":3,"file":"Modal-aWfERkXe.js","sources":["../node_modules/@getmicdrop/svelte-components/dist/primitives/Modal/Modal.svelte"],"sourcesContent":["<script lang=\"ts\">\n /**\n * Legacy Modal API — backward-compatible wrapper around ModalRoot + ModalOverlay + ModalPanel.\n * Accepts the old flat API: bind:open, header/body/footer snippets, size, persistent, oncancel.\n * New code should use ModalRoot + ModalOverlay + ModalPanel directly.\n */\n import type { Snippet } from 'svelte';\n import ModalRoot from './ModalRoot.svelte';\n import ModalOverlay from './ModalOverlay.svelte';\n import ModalPanel from './ModalPanel.svelte';\n import ModalHeader from './ModalHeader.svelte';\n import ModalBody from './ModalBody.svelte';\n import ModalFooter from './ModalFooter.svelte';\n\n interface Props {\n open?: boolean;\n size?: 'sm' | 'md' | 'lg' | 'xl';\n persistent?: boolean;\n haptic?: boolean;\n oncancel?: () => void;\n header?: Snippet;\n body?: Snippet;\n footer?: Snippet;\n children?: Snippet;\n class?: string;\n 'aria-labelledby'?: string;\n /**\n * Layout variant. `'sheet'` (default) = bottom-sheet on mobile, centered\n * on md+. `'dialog'` = centered on all viewports. See ModalRoot for details.\n */\n variant?: 'sheet' | 'dialog';\n }\n\n let {\n open = $bindable(false),\n size = 'md',\n persistent = false,\n haptic = true,\n oncancel,\n header,\n body,\n footer,\n children,\n class: className,\n 'aria-labelledby': ariaLabelledby,\n variant = 'sheet',\n }: Props = $props();\n</script>\n\n<ModalRoot bind:open {size} {persistent} {haptic} {oncancel} {variant} class={className} aria-labelledby={ariaLabelledby}>\n <ModalOverlay />\n <ModalPanel>\n {#if header}<ModalHeader>{@render header()}</ModalHeader>{/if}\n {#if body}<ModalBody>{@render body()}</ModalBody>{/if}\n {#if children}<ModalBody>{@render children()}</ModalBody>{/if}\n {#if footer}<ModalFooter>{@render footer()}</ModalFooter>{/if}\n </ModalPanel>\n</ModalRoot>\n"],"names":["open","$","$$props","size","persistent","haptic","variant","ModalRoot","$$anchor","$$value","ModalOverlay","node","ModalPanel","node_1","ModalHeader","ModalBody","ModalFooter"],"mappings":";;;;;iBAAA;;AAiCE,MACEA,IAAIC,EAAA,KAAAC,GAAA,QAAA,IAAa,EAAK,GACtBC,yBAAO,IAAI,GACXC,+BAAa,EAAK,GAClBC,2BAAS,EAAI,GAQbC,4BAAU,OAAO;AAIpB,EAAAC,EAASC,GAAA;AAAA;aAAYL,EAAI;AAAA;;aAAGC,EAAU;AAAA;;aAAGC,EAAM;AAAA;;;;;aAAcC,EAAO;AAAA;;;;;;;QAA1D,OAAS;;;QAAT,KAASG,GAAA;;;;;AACjB,MAAAC,EAAYC,GAAA,EAAA;;AACZ,MAAAC,EAAUC,GAAA;AAAA;;;;AACI,cAAAC,EAAWN,GAAA;AAAA;;;;;;;;;;;;;;AACb,cAAAO,EAASP,GAAA;AAAA;;;;;;;;;;;;;;AACL,cAAAO,EAASP,GAAA;AAAA;;;;;;;;;;;;;;AACX,cAAAQ,EAAWR,GAAA;AAAA;;;;;;;;;;;;;;;;;;AARpB;","x_google_ignoreList":[0]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "svelte/internal/disclose-version";
|
|
2
2
|
import * as e from "svelte/internal/client";
|
|
3
|
-
import { m as N, D as A, aj as E, E as F, bw as G, I as R } from "./VenueCalendar-
|
|
3
|
+
import { m as N, D as A, aj as E, E as F, bw as G, I as R } from "./VenueCalendar-Ys8-209-.js";
|
|
4
4
|
import { untrack as B } from "svelte";
|
|
5
5
|
var V = e.from_html("<div></div>"), j = e.from_html('<div class="pt-2 space-y-2"><div class="flex gap-1.5"></div> <!></div>');
|
|
6
6
|
function M(_, t) {
|
|
@@ -193,4 +193,4 @@ function Y(_, t) {
|
|
|
193
193
|
export {
|
|
194
194
|
Y as P
|
|
195
195
|
};
|
|
196
|
-
//# sourceMappingURL=PasswordInput-
|
|
196
|
+
//# sourceMappingURL=PasswordInput-CLFuYYgC.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PasswordInput-URDphAa4.js","sources":["../node_modules/@getmicdrop/svelte-components/dist/recipes/inputs/PasswordStrengthIndicator/PasswordStrengthIndicator.svelte","../node_modules/@getmicdrop/svelte-components/dist/recipes/inputs/PasswordInput.svelte"],"sourcesContent":["<script lang=\"ts\">\n import { mergeLabels, type SCLabels } from '../../../utils/labels.js';\n import type { Snippet } from 'svelte';\n import type { Options } from 'check-password-strength';\n import { DURATION, safeSlide, EASING } from \"../../../utils/transitions.js\";\n import { lazyOnce } from \"../../../utils/lazyOnce.js\";\n import { untrack } from \"svelte\";\n\n const defaultLabels = {\n tooWeak: 'Too weak',\n weak: 'Weak',\n good: 'Good',\n strong: 'Strong',\n };\n\n interface Props {\n password?: string;\n strengthText?: string;\n score?: number;\n textColor?: string;\n children?: Snippet;\n labels?: SCLabels<typeof defaultLabels>;\n }\n\n let {\n password = \"\",\n strengthText = $bindable(\"\"),\n score = $bindable(-1),\n textColor = $bindable(\"\"),\n children,\n labels: userLabels = {},\n }: Props = $props();\n\n let labels = $derived(mergeLabels(defaultLabels, userLabels));\n\n let debouncedPassword = $state(\"\");\n // Use a plain variable for timer to avoid reactive dependency\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n // Lazily load the (~10 KB) strength library only once a password exists.\n // Until it resolves, `strengthFn` is null and the indicator shows its\n // neutral (no-result) state — the debounce window absorbs the load latency.\n //\n // lazyOnce memoizes the import on success but RESETS on rejection: a\n // transient chunk-load failure must not be cached, or the indicator would\n // stay bricked until a page reload. On failure the next keystroke retries.\n // Explicit type ARGUMENT (not annotation) on purpose: with `$state(null)` TS\n // infers T = null, so control-flow analysis proves the variable is `null` at\n // the $derived read below and collapses the truthy branch to `never`\n // (\"This expression is not callable\"). The type argument keeps the union.\n let strengthFn = $state<typeof import('check-password-strength').passwordStrength | null>(null);\n const loadStrengthModule = lazyOnce(() => import('check-password-strength'));\n function ensureStrengthFn() {\n void loadStrengthModule()\n .then((m) => {\n strengthFn = m.passwordStrength;\n })\n .catch(() => {\n // Swallow — strengthFn stays null (neutral state) and lazyOnce\n // has already dropped its memo, so a later keystroke retries.\n });\n }\n\n // Kick off the load on the first keystroke, before the debounce fires.\n // Retries naturally on subsequent keystrokes after a transient failure\n // because lazyOnce does not cache the rejection.\n $effect(() => {\n if (password && !strengthFn) ensureStrengthFn();\n });\n\n // Typed as the library's own `Options<string>` so the strength call needs no\n // cast: the tuple's first entry satisfies `FirstOption` (minDiversity/minLength 0)\n // and the rest satisfy `Option`, checked contextually against this annotation.\n let customOptions: Options<string> = $derived([\n {\n id: 0,\n value: labels.tooWeak,\n minDiversity: 0,\n minLength: 0,\n },\n {\n id: 1,\n value: labels.weak,\n minDiversity: 1,\n minLength: 6,\n },\n {\n id: 2,\n value: labels.good,\n minDiversity: 2,\n minLength: 8,\n },\n {\n id: 3,\n value: labels.strong,\n minDiversity: 3,\n minLength: 10,\n },\n ]);\n\n // Debounce password updates - timer is not reactive to avoid dependency cycle\n $effect(() => {\n clearTimeout(timer);\n if (password.length === 0) {\n debouncedPassword = \"\";\n } else {\n timer = setTimeout(() => {\n debouncedPassword = password;\n }, 400); // 400ms delay as requested\n }\n return () => clearTimeout(timer);\n });\n\n let strength = $derived(debouncedPassword && strengthFn\n ? strengthFn(debouncedPassword, customOptions)\n : null);\n\n // Derive score based on password length and strength\n let computedScore = $derived(debouncedPassword.length > 12 ? 3 : (strength?.id ?? -1));\n\n // Sync computed values to bindable props using effects with untrack\n $effect(() => {\n const newScore = computedScore;\n if (untrack(() => score) !== newScore) {\n score = newScore;\n }\n });\n\n // Derive text and color from computedScore (not from bindable score)\n let computedStrengthText = $derived(\n computedScore === 0 ? labels.tooWeak :\n computedScore === 1 ? labels.weak :\n computedScore === 2 ? labels.good :\n computedScore === 3 ? labels.strong : \"\"\n );\n\n // No color until a real strength result exists. computedScore is -1 while\n // the lazily-loaded strength library is still in flight (and during the\n // debounce window), so emitting danger here would flash a red \"Password\n // strength\" line with empty text in consumers (e.g. PasswordInput).\n let computedTextColor = $derived(\n computedScore < 0 ? \"\" :\n computedScore <= 1 ? \"text-accent-danger\" : \"text-accent-success\"\n );\n\n $effect(() => {\n const newText = computedStrengthText;\n if (untrack(() => strengthText) !== newText) {\n strengthText = newText;\n }\n });\n\n let strengthColor = $derived(computedScore <= 1 ? \"bg-accent-danger\" : \"bg-accent-success\");\n\n $effect(() => {\n const newColor = computedTextColor;\n if (untrack(() => textColor) !== newColor) {\n textColor = newColor;\n }\n });\n\n // Calculate how many bars to fill (1-3)\n let filledBars = $derived(computedScore === 0 ? 1 : computedScore === 1 ? 2 : computedScore >= 2 ? 3 : 0);\n</script>\n\n{#if debouncedPassword.length > 0}\n <div\n transition:safeSlide={{ duration: DURATION.elaborate, easing: EASING.out }}\n class=\"pt-2 space-y-2\"\n >\n <!-- 3 segment bars -->\n <div class=\"flex gap-1.5\">\n {#each [0, 1, 2] as barIndex (barIndex)}\n <div\n class=\"h-1 flex-1 rounded-full transition-colors duration-normal {barIndex <\n filledBars\n ? strengthColor\n : 'bg-bg-tertiary'}\"\n ></div>\n {/each}\n </div>\n {@render children?.()}\n </div>\n{/if}\n","<script lang=\"ts\">\n import { mergeLabels, type SCLabels } from '../../utils/labels.js';\n /**\n * PasswordInput - Password field with show/hide toggle and strength indicator\n *\n * Combines Input (password type) with PasswordStrengthIndicator for\n * a complete password entry experience.\n *\n * @example\n * <PasswordInput\n * label=\"New Password\"\n * bind:value={password}\n * showStrength\n * error={$errors.password}\n * required\n * />\n *\n * @example Consumer-owned validation (e.g. Zod): opt out of the built-in\n * `required` constraint so the consuming form is the single source of truth.\n * <PasswordInput\n * label=\"Password\"\n * bind:value={password}\n * required\n * disableBuiltInValidation\n * error={$errors.password}\n * />\n */\n import Input from '../../primitives/Input/Input.svelte';\n import PasswordStrengthIndicator from './PasswordStrengthIndicator/PasswordStrengthIndicator.svelte';\n\n const defaultLabels = {\n passwordStrength: 'Password strength:',\n };\n\n interface Props {\n /** Password value */\n value?: string;\n /** Label text */\n label?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Input name attribute */\n name?: string;\n /** Input id attribute */\n id?: string;\n /** Whether the field is required */\n required?: boolean;\n /**\n * Opt out of the component's built-in `required` validation so the\n * consumer owns validation entirely (e.g. a Zod schema on the form).\n * When `true`, the `required` constraint is NOT forwarded to the\n * underlying field (no `aria-required`, no required asterisk). The\n * visual error/hint still render via `error`/`hint`. Defaults to\n * `false`, preserving the existing built-in behavior exactly.\n */\n disableBuiltInValidation?: boolean;\n /** Whether the field is disabled */\n disabled?: boolean;\n /** Error message to display */\n error?: string;\n /** Hint text shown below input */\n hint?: string;\n /** Show password strength indicator */\n showStrength?: boolean;\n /** Size variant */\n size?: 'sm' | 'md' | 'lg';\n /** Minimum password length */\n minlength?: number | null;\n /** Maximum password length */\n maxlength?: number | null;\n /** Autocomplete attribute */\n autocomplete?: string;\n /** Whether to show the password toggle button */\n showPasswordToggle?: boolean;\n /** Additional class for the wrapper div */\n class?: string;\n // Optional callbacks (matching Input component signatures)\n // eslint-disable-next-line no-unused-vars -- intentionally retained (prop/slot/forward-compat or Svelte-5 reactive binding eslint cannot see)\n oninput?: (value: string) => void;\n onblur?: () => void;\n onfocus?: () => void;\n /** Override user-visible strings */\n labels?: SCLabels<typeof defaultLabels>;\n }\n\n let {\n value = $bindable(''),\n label = '',\n placeholder = '',\n name = '',\n id = '',\n required = false,\n disableBuiltInValidation = false,\n disabled = false,\n error = '',\n hint = '',\n showStrength = false,\n size = 'md',\n minlength = null,\n maxlength = null,\n autocomplete = 'new-password',\n showPasswordToggle = true,\n class: className = '',\n oninput,\n onblur,\n onfocus,\n labels: userLabels = {},\n }: Props = $props();\n\n let labels = $derived(mergeLabels(defaultLabels, userLabels));\n\n // When the consumer opts out of built-in validation, do NOT forward the\n // `required` constraint to the underlying field — the consuming form owns\n // validation entirely. Default (false) forwards `required` as-is, exactly\n // preserving existing behavior.\n let effectiveRequired = $derived(disableBuiltInValidation ? false : required);\n\n // Password strength tracking\n let strengthScore = $state(-1);\n let strengthText = $state('');\n let strengthColor = $state('');\n</script>\n\n<div class={className}>\n <Input\n type=\"password\"\n {id}\n {name}\n {placeholder}\n {label}\n required={effectiveRequired}\n {disabled}\n {size}\n {minlength}\n {maxlength}\n {autocomplete}\n {showPasswordToggle}\n errorText={error}\n hintText={hint}\n bind:value\n oninputchange={oninput}\n {onblur}\n {onfocus}\n />\n\n {#if showStrength && value}\n <PasswordStrengthIndicator\n password={value}\n bind:score={strengthScore}\n bind:strengthText\n bind:textColor={strengthColor}\n >\n <p class=\"type-caption {strengthColor}\">\n {labels.passwordStrength} {strengthText}\n </p>\n </PasswordStrengthIndicator>\n {/if}\n</div>\n"],"names":["defaultLabels","password","$","$$props","strengthText","score","textColor","userLabels","labels","mergeLabels","debouncedPassword","timer","strengthFn","loadStrengthModule","lazyOnce","ensureStrengthFn","m","customOptions","strength","computedScore","newScore","untrack","computedStrengthText","computedTextColor","newText","strengthColor","newColor","filledBars","div","root_1","div_1","barIndex","$$anchor","div_2","root","safeSlide","DURATION","EASING","$$render","consequent","value","label","placeholder","name","id","required","disableBuiltInValidation","disabled","error","hint","showStrength","size","minlength","maxlength","autocomplete","showPasswordToggle","className","effectiveRequired","strengthScore","Input","node","$$value","PasswordStrengthIndicator","p"],"mappings":"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","x_google_ignoreList":[0,1]}
|
|
1
|
+
{"version":3,"file":"PasswordInput-CLFuYYgC.js","sources":["../node_modules/@getmicdrop/svelte-components/dist/recipes/inputs/PasswordStrengthIndicator/PasswordStrengthIndicator.svelte","../node_modules/@getmicdrop/svelte-components/dist/recipes/inputs/PasswordInput.svelte"],"sourcesContent":["<script lang=\"ts\">\n import { mergeLabels, type SCLabels } from '../../../utils/labels.js';\n import type { Snippet } from 'svelte';\n import type { Options } from 'check-password-strength';\n import { DURATION, safeSlide, EASING } from \"../../../utils/transitions.js\";\n import { lazyOnce } from \"../../../utils/lazyOnce.js\";\n import { untrack } from \"svelte\";\n\n const defaultLabels = {\n tooWeak: 'Too weak',\n weak: 'Weak',\n good: 'Good',\n strong: 'Strong',\n };\n\n interface Props {\n password?: string;\n strengthText?: string;\n score?: number;\n textColor?: string;\n children?: Snippet;\n labels?: SCLabels<typeof defaultLabels>;\n }\n\n let {\n password = \"\",\n strengthText = $bindable(\"\"),\n score = $bindable(-1),\n textColor = $bindable(\"\"),\n children,\n labels: userLabels = {},\n }: Props = $props();\n\n let labels = $derived(mergeLabels(defaultLabels, userLabels));\n\n let debouncedPassword = $state(\"\");\n // Use a plain variable for timer to avoid reactive dependency\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n // Lazily load the (~10 KB) strength library only once a password exists.\n // Until it resolves, `strengthFn` is null and the indicator shows its\n // neutral (no-result) state — the debounce window absorbs the load latency.\n //\n // lazyOnce memoizes the import on success but RESETS on rejection: a\n // transient chunk-load failure must not be cached, or the indicator would\n // stay bricked until a page reload. On failure the next keystroke retries.\n // Explicit type ARGUMENT (not annotation) on purpose: with `$state(null)` TS\n // infers T = null, so control-flow analysis proves the variable is `null` at\n // the $derived read below and collapses the truthy branch to `never`\n // (\"This expression is not callable\"). The type argument keeps the union.\n let strengthFn = $state<typeof import('check-password-strength').passwordStrength | null>(null);\n const loadStrengthModule = lazyOnce(() => import('check-password-strength'));\n function ensureStrengthFn() {\n void loadStrengthModule()\n .then((m) => {\n strengthFn = m.passwordStrength;\n })\n .catch(() => {\n // Swallow — strengthFn stays null (neutral state) and lazyOnce\n // has already dropped its memo, so a later keystroke retries.\n });\n }\n\n // Kick off the load on the first keystroke, before the debounce fires.\n // Retries naturally on subsequent keystrokes after a transient failure\n // because lazyOnce does not cache the rejection.\n $effect(() => {\n if (password && !strengthFn) ensureStrengthFn();\n });\n\n // Typed as the library's own `Options<string>` so the strength call needs no\n // cast: the tuple's first entry satisfies `FirstOption` (minDiversity/minLength 0)\n // and the rest satisfy `Option`, checked contextually against this annotation.\n let customOptions: Options<string> = $derived([\n {\n id: 0,\n value: labels.tooWeak,\n minDiversity: 0,\n minLength: 0,\n },\n {\n id: 1,\n value: labels.weak,\n minDiversity: 1,\n minLength: 6,\n },\n {\n id: 2,\n value: labels.good,\n minDiversity: 2,\n minLength: 8,\n },\n {\n id: 3,\n value: labels.strong,\n minDiversity: 3,\n minLength: 10,\n },\n ]);\n\n // Debounce password updates - timer is not reactive to avoid dependency cycle\n $effect(() => {\n clearTimeout(timer);\n if (password.length === 0) {\n debouncedPassword = \"\";\n } else {\n timer = setTimeout(() => {\n debouncedPassword = password;\n }, 400); // 400ms delay as requested\n }\n return () => clearTimeout(timer);\n });\n\n let strength = $derived(debouncedPassword && strengthFn\n ? strengthFn(debouncedPassword, customOptions)\n : null);\n\n // Derive score based on password length and strength\n let computedScore = $derived(debouncedPassword.length > 12 ? 3 : (strength?.id ?? -1));\n\n // Sync computed values to bindable props using effects with untrack\n $effect(() => {\n const newScore = computedScore;\n if (untrack(() => score) !== newScore) {\n score = newScore;\n }\n });\n\n // Derive text and color from computedScore (not from bindable score)\n let computedStrengthText = $derived(\n computedScore === 0 ? labels.tooWeak :\n computedScore === 1 ? labels.weak :\n computedScore === 2 ? labels.good :\n computedScore === 3 ? labels.strong : \"\"\n );\n\n // No color until a real strength result exists. computedScore is -1 while\n // the lazily-loaded strength library is still in flight (and during the\n // debounce window), so emitting danger here would flash a red \"Password\n // strength\" line with empty text in consumers (e.g. PasswordInput).\n let computedTextColor = $derived(\n computedScore < 0 ? \"\" :\n computedScore <= 1 ? \"text-accent-danger\" : \"text-accent-success\"\n );\n\n $effect(() => {\n const newText = computedStrengthText;\n if (untrack(() => strengthText) !== newText) {\n strengthText = newText;\n }\n });\n\n let strengthColor = $derived(computedScore <= 1 ? \"bg-accent-danger\" : \"bg-accent-success\");\n\n $effect(() => {\n const newColor = computedTextColor;\n if (untrack(() => textColor) !== newColor) {\n textColor = newColor;\n }\n });\n\n // Calculate how many bars to fill (1-3)\n let filledBars = $derived(computedScore === 0 ? 1 : computedScore === 1 ? 2 : computedScore >= 2 ? 3 : 0);\n</script>\n\n{#if debouncedPassword.length > 0}\n <div\n transition:safeSlide={{ duration: DURATION.elaborate, easing: EASING.out }}\n class=\"pt-2 space-y-2\"\n >\n <!-- 3 segment bars -->\n <div class=\"flex gap-1.5\">\n {#each [0, 1, 2] as barIndex (barIndex)}\n <div\n class=\"h-1 flex-1 rounded-full transition-colors duration-normal {barIndex <\n filledBars\n ? strengthColor\n : 'bg-bg-tertiary'}\"\n ></div>\n {/each}\n </div>\n {@render children?.()}\n </div>\n{/if}\n","<script lang=\"ts\">\n import { mergeLabels, type SCLabels } from '../../utils/labels.js';\n /**\n * PasswordInput - Password field with show/hide toggle and strength indicator\n *\n * Combines Input (password type) with PasswordStrengthIndicator for\n * a complete password entry experience.\n *\n * @example\n * <PasswordInput\n * label=\"New Password\"\n * bind:value={password}\n * showStrength\n * error={$errors.password}\n * required\n * />\n *\n * @example Consumer-owned validation (e.g. Zod): opt out of the built-in\n * `required` constraint so the consuming form is the single source of truth.\n * <PasswordInput\n * label=\"Password\"\n * bind:value={password}\n * required\n * disableBuiltInValidation\n * error={$errors.password}\n * />\n */\n import Input from '../../primitives/Input/Input.svelte';\n import PasswordStrengthIndicator from './PasswordStrengthIndicator/PasswordStrengthIndicator.svelte';\n\n const defaultLabels = {\n passwordStrength: 'Password strength:',\n };\n\n interface Props {\n /** Password value */\n value?: string;\n /** Label text */\n label?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Input name attribute */\n name?: string;\n /** Input id attribute */\n id?: string;\n /** Whether the field is required */\n required?: boolean;\n /**\n * Opt out of the component's built-in `required` validation so the\n * consumer owns validation entirely (e.g. a Zod schema on the form).\n * When `true`, the `required` constraint is NOT forwarded to the\n * underlying field (no `aria-required`, no required asterisk). The\n * visual error/hint still render via `error`/`hint`. Defaults to\n * `false`, preserving the existing built-in behavior exactly.\n */\n disableBuiltInValidation?: boolean;\n /** Whether the field is disabled */\n disabled?: boolean;\n /** Error message to display */\n error?: string;\n /** Hint text shown below input */\n hint?: string;\n /** Show password strength indicator */\n showStrength?: boolean;\n /** Size variant */\n size?: 'sm' | 'md' | 'lg';\n /** Minimum password length */\n minlength?: number | null;\n /** Maximum password length */\n maxlength?: number | null;\n /** Autocomplete attribute */\n autocomplete?: string;\n /** Whether to show the password toggle button */\n showPasswordToggle?: boolean;\n /** Additional class for the wrapper div */\n class?: string;\n // Optional callbacks (matching Input component signatures)\n // eslint-disable-next-line no-unused-vars -- intentionally retained (prop/slot/forward-compat or Svelte-5 reactive binding eslint cannot see)\n oninput?: (value: string) => void;\n onblur?: () => void;\n onfocus?: () => void;\n /** Override user-visible strings */\n labels?: SCLabels<typeof defaultLabels>;\n }\n\n let {\n value = $bindable(''),\n label = '',\n placeholder = '',\n name = '',\n id = '',\n required = false,\n disableBuiltInValidation = false,\n disabled = false,\n error = '',\n hint = '',\n showStrength = false,\n size = 'md',\n minlength = null,\n maxlength = null,\n autocomplete = 'new-password',\n showPasswordToggle = true,\n class: className = '',\n oninput,\n onblur,\n onfocus,\n labels: userLabels = {},\n }: Props = $props();\n\n let labels = $derived(mergeLabels(defaultLabels, userLabels));\n\n // When the consumer opts out of built-in validation, do NOT forward the\n // `required` constraint to the underlying field — the consuming form owns\n // validation entirely. Default (false) forwards `required` as-is, exactly\n // preserving existing behavior.\n let effectiveRequired = $derived(disableBuiltInValidation ? false : required);\n\n // Password strength tracking\n let strengthScore = $state(-1);\n let strengthText = $state('');\n let strengthColor = $state('');\n</script>\n\n<div class={className}>\n <Input\n type=\"password\"\n {id}\n {name}\n {placeholder}\n {label}\n required={effectiveRequired}\n {disabled}\n {size}\n {minlength}\n {maxlength}\n {autocomplete}\n {showPasswordToggle}\n errorText={error}\n hintText={hint}\n bind:value\n oninputchange={oninput}\n {onblur}\n {onfocus}\n />\n\n {#if showStrength && value}\n <PasswordStrengthIndicator\n password={value}\n bind:score={strengthScore}\n bind:strengthText\n bind:textColor={strengthColor}\n >\n <p class=\"type-caption {strengthColor}\">\n {labels.passwordStrength} {strengthText}\n </p>\n </PasswordStrengthIndicator>\n {/if}\n</div>\n"],"names":["defaultLabels","password","$","$$props","strengthText","score","textColor","userLabels","labels","mergeLabels","debouncedPassword","timer","strengthFn","loadStrengthModule","lazyOnce","ensureStrengthFn","m","customOptions","strength","computedScore","newScore","untrack","computedStrengthText","computedTextColor","newText","strengthColor","newColor","filledBars","div","root_1","div_1","barIndex","$$anchor","div_2","root","safeSlide","DURATION","EASING","$$render","consequent","value","label","placeholder","name","id","required","disableBuiltInValidation","disabled","error","hint","showStrength","size","minlength","maxlength","autocomplete","showPasswordToggle","className","effectiveRequired","strengthScore","Input","node","$$value","PasswordStrengthIndicator","p"],"mappings":"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","x_google_ignoreList":[0,1]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "svelte/internal/disclose-version";
|
|
2
2
|
import * as e from "svelte/internal/client";
|
|
3
|
-
import { Z as O, g as L, an as N, a$ as z, aS as k } from "./VenueCalendar-
|
|
4
|
-
import { W as C } from "./WarningCircleIcon-
|
|
3
|
+
import { Z as O, g as L, an as N, a$ as z, aS as k } from "./VenueCalendar-Ys8-209-.js";
|
|
4
|
+
import { W as C } from "./WarningCircleIcon-eOM57ZiU.js";
|
|
5
5
|
var B = e.from_svg('<path d="M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM184,136H72a8,8,0,0,1,0-16H184a8,8,0,0,1,0,16Z"></path>'), H = e.from_svg('<line x1="40" y1="128" x2="216" y2="128" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"></line>'), T = e.from_svg('<svg aria-hidden="true" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><!></svg>');
|
|
6
6
|
function R(r, a) {
|
|
7
7
|
e.push(a, !0);
|
|
@@ -115,4 +115,4 @@ export {
|
|
|
115
115
|
R as a,
|
|
116
116
|
U as g
|
|
117
117
|
};
|
|
118
|
-
//# sourceMappingURL=ScarcityBadge-
|
|
118
|
+
//# sourceMappingURL=ScarcityBadge-5RMumV4l.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScarcityBadge-Dwah85WZ.js","sources":["../node_modules/@getmicdrop/svelte-components/dist/primitives/Icons/phosphor/SubtractIcon.svelte","../__SKIP_NAVIGATION__","../src/components/ScarcityBadge.svelte"],"sourcesContent":["<script lang=\"ts\">\n /**\n * Subtract — Phosphor icon (canonical Micdrop icon family).\n * Outline by default; pass `weight=\"fill\"` for solid, or let a stateful parent\n * (NavItem / Tabs / BottomNav / status badge) drive it via icon-weight context.\n */\n import { useIconWeight, type IconWeight } from './iconWeight.js';\n\n interface Props {\n /** Pixel size (width + height). */\n size?: string;\n /** Icon color; defaults to `currentColor` (inherits text color). */\n color?: string;\n /** Extra classes. */\n class?: string;\n /** `regular` (outline) or `fill` (solid). Overrides ambient state weight. */\n weight?: IconWeight;\n }\n\n let { size = '24', color = 'currentColor', class: className = '', weight }: Props = $props();\n\n const ctx = useIconWeight();\n let resolved: IconWeight = $derived(weight ?? ctx?.weight ?? 'regular');\n</script>\n\n<svg\n class={className}\n aria-hidden=\"true\"\n width={size}\n height={size}\n viewBox=\"0 0 256 256\"\n fill=\"currentColor\"\n style:color={color === 'currentColor' ? undefined : color}\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n {#if resolved === 'fill'}<path d=\"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM184,136H72a8,8,0,0,1,0-16H184a8,8,0,0,1,0,16Z\"/>{:else}<line x1=\"40\" y1=\"128\" x2=\"216\" y2=\"128\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/>{/if}\n</svg>\n","\n export function goto(url, opts) {\n if (typeof window !== 'undefined' && window.location) {\n if (opts?.replaceState) {\n window.history.replaceState({}, '', url);\n } else {\n window.location.href = url;\n }\n }\n }\n export function beforeNavigate(callback) {\n // No-op for library builds\n }\n export function afterNavigate(callback) {\n // No-op for library builds\n }\n export function disable() {\n // No-op for library builds\n }\n export function enable() {\n // No-op for library builds\n }\n ","<script module>\r\n import { createDebouncedAnnouncer } from '@getmicdrop/svelte-components/a11y';\r\n\r\n // A scarce ticket's badge exists 3× at once on an Event surface — TicketCard's\r\n // two responsive-tree copies plus BookingWidget's own badge — and on `main`\r\n // each was an inline aria-live region inside a CSS-hidden subtree, so exactly\r\n // one spoke. Routing every copy through the singleton announce() region made a\r\n // single availability tick speak \"Only 3 left\" 3×. Same canonical fix as\r\n // TicketCard: the shared createDebouncedAnnouncer at MODULE scope collapses the\r\n // identical same-tick calls into one, keyed by message (via a plain\r\n // string-keyed cache — a module-scope lookup, not reactive state, so a Map/\r\n // SvelteMap would be the wrong tool) so two DIFFERENT tickets changing in the\r\n // window — whose messages differ — each still announce.\r\n const SCARCITY_ANNOUNCE_DEBOUNCE_MS = 200;\r\n const scarcityAnnouncers = Object.create(null);\r\n function announceScarcity(message) {\r\n const debounced = (scarcityAnnouncers[message] ??= createDebouncedAnnouncer(\r\n SCARCITY_ANNOUNCE_DEBOUNCE_MS\r\n ));\r\n debounced(message, { politeness: 'polite' });\r\n }\r\n</script>\r\n\r\n<script>\r\n import { defaultLabels } from '$lib/i18n/defaultLabels.js';\r\n import { Badge } from '@getmicdrop/svelte-components';\r\n import { WarningCircleIcon } from '@getmicdrop/svelte-components/primitives/Icons/phosphor/index.js';\r\n import { computeScarcityLevel } from '$lib/constants/scarcity';\r\n\r\n /**\r\n * ScarcityBadge - Shows urgency indicators based on ticket availability.\r\n *\r\n * Wraps SC <Badge> with venue-calendar's threshold logic. Renders to\r\n * the same primitive every other status badge uses (List, Gallery,\r\n * Calendar embed) so a \"Selling fast\" / \"Sold out\" pill is visually\r\n * identical wherever it appears.\r\n *\r\n * The tier itself comes from the ONE canonical computeScarcityLevel in\r\n * $lib/constants/scarcity — a sliding scale (base low <=20% remaining, urgent\r\n * <=10%, bent toward an absolute floor of 5 and cap of 30). TicketBlock.svelte\r\n * and the browse grid route through the same function, so the badge tier\r\n * matches the urgency copy everywhere. This component only maps the tier to\r\n * copy and decides whether to reveal the exact count (event/ticket) or stay\r\n * vague (browse).\r\n *\r\n * - sold-out tier: \"Sold out\" (red, no flame)\r\n * - urgent tier (event/ticket): \"Only X left\" with exact count (warning + flame)\r\n * - low/urgent tier (browse) or low tier (event/ticket): \"Selling fast\" (warning + flame)\r\n * - plenty tier: No badge\r\n *\r\n * @prop {\"browse\"|\"event\"|\"ticket\"} context - browse=vague only; event/ticket=exact at urgent\r\n * @prop {\"default\"|\"minimal\"} variant - default=SC Badge pill; minimal=transparent text+icon\r\n * @prop {boolean} isFree - Suppress scarcity badges for free events/tickets\r\n */\r\n let {\r\n remaining,\r\n total,\r\n context = 'browse',\r\n variant = 'default',\r\n isFree = false,\r\n labels = defaultLabels,\r\n } = $props();\r\n\r\n let level = $derived(computeScarcityLevel(remaining, total));\r\n\r\n let badgeInfo = $derived.by(() => {\r\n const soldOutText = labels.statusSoldOut || 'Sold out';\r\n const sellingFastText = labels.statusSellingFast || 'Selling fast';\r\n const onlyNLeftTemplate =\r\n labels.scarcityOnlyNLeft || 'Only {remaining} left';\r\n\r\n if (level === 'sold-out') {\r\n return { type: 'sold-out', text: soldOutText, showFlame: false };\r\n }\r\n if (isFree) return null;\r\n\r\n // Browse surfaces show only the vague badge — never an exact count — so the\r\n // urgent and low tiers collapse to the same \"Selling fast\" pill.\r\n if (context === 'browse') {\r\n if (level === 'urgent' || level === 'low') {\r\n return { type: 'scarcity', text: sellingFastText, showFlame: true };\r\n }\r\n return null;\r\n }\r\n\r\n // Event / ticket surfaces reveal the exact count at the urgent tier (the\r\n // canon already caps that to MAX_EXACT_COUNT), vague at low.\r\n if (level === 'urgent') {\r\n return {\r\n type: 'scarcity',\r\n text: onlyNLeftTemplate.replace('{remaining}', String(remaining)),\r\n showFlame: true,\r\n };\r\n }\r\n if (level === 'low') {\r\n return { type: 'scarcity', text: sellingFastText, showFlame: true };\r\n }\r\n return null;\r\n });\r\n\r\n let scVariant = $derived(\r\n /** @type {'error' | 'warning'} */ (\r\n badgeInfo?.type === 'sold-out' ? 'error' : 'warning'\r\n )\r\n );\r\n let ariaLabel = $derived(\r\n badgeInfo?.type === 'sold-out'\r\n ? labels.statusSoldOut || 'Sold out'\r\n : `${labels.scarcityLowAvailability || 'Low availability'}: ${badgeInfo?.text}`\r\n );\r\n\r\n // Announce scarcity to screen readers on CHANGE only — never on mount. An\r\n // aria-live region is silent on its first paint (it announces later mutations,\r\n // not initial content), and Event renders both the desktop and mobile ticket\r\n // trees at once (one CSS-hidden, both in the DOM) — so a mount-time announce\r\n // would double-announce a scarce ticket's status on page load, worse than the\r\n // pre-migration silence. Same change-only guard TicketCard uses for quantity.\r\n let scarcityAnnounceReady = false;\r\n $effect(() => {\r\n const text = badgeInfo?.text;\r\n if (!scarcityAnnounceReady) {\r\n scarcityAnnounceReady = true;\r\n return;\r\n }\r\n if (text) announceScarcity(text);\r\n });\r\n</script>\r\n\r\n{#if badgeInfo}\r\n {#if variant === 'minimal'}\r\n <span\r\n class=\"inline-flex items-center gap-1 type-caption {badgeInfo.type ===\r\n 'sold-out'\r\n ? 'text-status-error-text'\r\n : 'text-accent-warning'}\"\r\n aria-label={ariaLabel}\r\n >\r\n {#if badgeInfo.showFlame}\r\n <WarningCircleIcon size=\"16\" />\r\n {/if}\r\n {badgeInfo.text}\r\n </span>\r\n {:else}\r\n <Badge variant={scVariant} size=\"sm\">\r\n {#snippet leftIcon()}\r\n {#if badgeInfo.showFlame}\r\n <WarningCircleIcon size=\"16\" />\r\n {/if}\r\n {/snippet}\r\n {badgeInfo.text}\r\n </Badge>\r\n {/if}\r\n{/if}\r\n"],"names":["size","$","$$props","color","className","ctx","useIconWeight","resolved","svg","root_2","path","root","line","root_1","$$render","consequent","alternate","styles","goto","url","opts","SCARCITY_ANNOUNCE_DEBOUNCE_MS","scarcityAnnouncers","announceScarcity","message","createDebouncedAnnouncer","context","variant","isFree","labels","defaultLabels","level","computeScarcityLevel","badgeInfo","soldOutText","sellingFastText","onlyNLeftTemplate","scVariant","ariaLabel","scarcityAnnounceReady","text","span","WarningCircleIcon","$$anchor","text_1","Badge","consequent_2","text_2","consequent_1","consequent_3"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"ScarcityBadge-5RMumV4l.js","sources":["../node_modules/@getmicdrop/svelte-components/dist/primitives/Icons/phosphor/SubtractIcon.svelte","../__SKIP_NAVIGATION__","../src/components/ScarcityBadge.svelte"],"sourcesContent":["<script lang=\"ts\">\n /**\n * Subtract — Phosphor icon (canonical Micdrop icon family).\n * Outline by default; pass `weight=\"fill\"` for solid, or let a stateful parent\n * (NavItem / Tabs / BottomNav / status badge) drive it via icon-weight context.\n */\n import { useIconWeight, type IconWeight } from './iconWeight.js';\n\n interface Props {\n /** Pixel size (width + height). */\n size?: string;\n /** Icon color; defaults to `currentColor` (inherits text color). */\n color?: string;\n /** Extra classes. */\n class?: string;\n /** `regular` (outline) or `fill` (solid). Overrides ambient state weight. */\n weight?: IconWeight;\n }\n\n let { size = '24', color = 'currentColor', class: className = '', weight }: Props = $props();\n\n const ctx = useIconWeight();\n let resolved: IconWeight = $derived(weight ?? ctx?.weight ?? 'regular');\n</script>\n\n<svg\n class={className}\n aria-hidden=\"true\"\n width={size}\n height={size}\n viewBox=\"0 0 256 256\"\n fill=\"currentColor\"\n style:color={color === 'currentColor' ? undefined : color}\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n {#if resolved === 'fill'}<path d=\"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM184,136H72a8,8,0,0,1,0-16H184a8,8,0,0,1,0,16Z\"/>{:else}<line x1=\"40\" y1=\"128\" x2=\"216\" y2=\"128\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"16\"/>{/if}\n</svg>\n","\n export function goto(url, opts) {\n if (typeof window !== 'undefined' && window.location) {\n if (opts?.replaceState) {\n window.history.replaceState({}, '', url);\n } else {\n window.location.href = url;\n }\n }\n }\n export function beforeNavigate(callback) {\n // No-op for library builds\n }\n export function afterNavigate(callback) {\n // No-op for library builds\n }\n export function disable() {\n // No-op for library builds\n }\n export function enable() {\n // No-op for library builds\n }\n ","<script module>\r\n import { createDebouncedAnnouncer } from '@getmicdrop/svelte-components/a11y';\r\n\r\n // A scarce ticket's badge exists 3× at once on an Event surface — TicketCard's\r\n // two responsive-tree copies plus BookingWidget's own badge — and on `main`\r\n // each was an inline aria-live region inside a CSS-hidden subtree, so exactly\r\n // one spoke. Routing every copy through the singleton announce() region made a\r\n // single availability tick speak \"Only 3 left\" 3×. Same canonical fix as\r\n // TicketCard: the shared createDebouncedAnnouncer at MODULE scope collapses the\r\n // identical same-tick calls into one, keyed by message (via a plain\r\n // string-keyed cache — a module-scope lookup, not reactive state, so a Map/\r\n // SvelteMap would be the wrong tool) so two DIFFERENT tickets changing in the\r\n // window — whose messages differ — each still announce.\r\n const SCARCITY_ANNOUNCE_DEBOUNCE_MS = 200;\r\n const scarcityAnnouncers = Object.create(null);\r\n function announceScarcity(message) {\r\n const debounced = (scarcityAnnouncers[message] ??= createDebouncedAnnouncer(\r\n SCARCITY_ANNOUNCE_DEBOUNCE_MS\r\n ));\r\n debounced(message, { politeness: 'polite' });\r\n }\r\n</script>\r\n\r\n<script>\r\n import { defaultLabels } from '$lib/i18n/defaultLabels.js';\r\n import { Badge } from '@getmicdrop/svelte-components';\r\n import { WarningCircleIcon } from '@getmicdrop/svelte-components/primitives/Icons/phosphor/index.js';\r\n import { computeScarcityLevel } from '$lib/constants/scarcity';\r\n\r\n /**\r\n * ScarcityBadge - Shows urgency indicators based on ticket availability.\r\n *\r\n * Wraps SC <Badge> with venue-calendar's threshold logic. Renders to\r\n * the same primitive every other status badge uses (List, Gallery,\r\n * Calendar embed) so a \"Selling fast\" / \"Sold out\" pill is visually\r\n * identical wherever it appears.\r\n *\r\n * The tier itself comes from the ONE canonical computeScarcityLevel in\r\n * $lib/constants/scarcity — a sliding scale (base low <=20% remaining, urgent\r\n * <=10%, bent toward an absolute floor of 5 and cap of 30). TicketBlock.svelte\r\n * and the browse grid route through the same function, so the badge tier\r\n * matches the urgency copy everywhere. This component only maps the tier to\r\n * copy and decides whether to reveal the exact count (event/ticket) or stay\r\n * vague (browse).\r\n *\r\n * - sold-out tier: \"Sold out\" (red, no flame)\r\n * - urgent tier (event/ticket): \"Only X left\" with exact count (warning + flame)\r\n * - low/urgent tier (browse) or low tier (event/ticket): \"Selling fast\" (warning + flame)\r\n * - plenty tier: No badge\r\n *\r\n * @prop {\"browse\"|\"event\"|\"ticket\"} context - browse=vague only; event/ticket=exact at urgent\r\n * @prop {\"default\"|\"minimal\"} variant - default=SC Badge pill; minimal=transparent text+icon\r\n * @prop {boolean} isFree - Suppress scarcity badges for free events/tickets\r\n */\r\n let {\r\n remaining,\r\n total,\r\n context = 'browse',\r\n variant = 'default',\r\n isFree = false,\r\n labels = defaultLabels,\r\n } = $props();\r\n\r\n let level = $derived(computeScarcityLevel(remaining, total));\r\n\r\n let badgeInfo = $derived.by(() => {\r\n const soldOutText = labels.statusSoldOut || 'Sold out';\r\n const sellingFastText = labels.statusSellingFast || 'Selling fast';\r\n const onlyNLeftTemplate =\r\n labels.scarcityOnlyNLeft || 'Only {remaining} left';\r\n\r\n if (level === 'sold-out') {\r\n return { type: 'sold-out', text: soldOutText, showFlame: false };\r\n }\r\n if (isFree) return null;\r\n\r\n // Browse surfaces show only the vague badge — never an exact count — so the\r\n // urgent and low tiers collapse to the same \"Selling fast\" pill.\r\n if (context === 'browse') {\r\n if (level === 'urgent' || level === 'low') {\r\n return { type: 'scarcity', text: sellingFastText, showFlame: true };\r\n }\r\n return null;\r\n }\r\n\r\n // Event / ticket surfaces reveal the exact count at the urgent tier (the\r\n // canon already caps that to MAX_EXACT_COUNT), vague at low.\r\n if (level === 'urgent') {\r\n return {\r\n type: 'scarcity',\r\n text: onlyNLeftTemplate.replace('{remaining}', String(remaining)),\r\n showFlame: true,\r\n };\r\n }\r\n if (level === 'low') {\r\n return { type: 'scarcity', text: sellingFastText, showFlame: true };\r\n }\r\n return null;\r\n });\r\n\r\n let scVariant = $derived(\r\n /** @type {'error' | 'warning'} */ (\r\n badgeInfo?.type === 'sold-out' ? 'error' : 'warning'\r\n )\r\n );\r\n let ariaLabel = $derived(\r\n badgeInfo?.type === 'sold-out'\r\n ? labels.statusSoldOut || 'Sold out'\r\n : `${labels.scarcityLowAvailability || 'Low availability'}: ${badgeInfo?.text}`\r\n );\r\n\r\n // Announce scarcity to screen readers on CHANGE only — never on mount. An\r\n // aria-live region is silent on its first paint (it announces later mutations,\r\n // not initial content), and Event renders both the desktop and mobile ticket\r\n // trees at once (one CSS-hidden, both in the DOM) — so a mount-time announce\r\n // would double-announce a scarce ticket's status on page load, worse than the\r\n // pre-migration silence. Same change-only guard TicketCard uses for quantity.\r\n let scarcityAnnounceReady = false;\r\n $effect(() => {\r\n const text = badgeInfo?.text;\r\n if (!scarcityAnnounceReady) {\r\n scarcityAnnounceReady = true;\r\n return;\r\n }\r\n if (text) announceScarcity(text);\r\n });\r\n</script>\r\n\r\n{#if badgeInfo}\r\n {#if variant === 'minimal'}\r\n <span\r\n class=\"inline-flex items-center gap-1 type-caption {badgeInfo.type ===\r\n 'sold-out'\r\n ? 'text-status-error-text'\r\n : 'text-accent-warning'}\"\r\n aria-label={ariaLabel}\r\n >\r\n {#if badgeInfo.showFlame}\r\n <WarningCircleIcon size=\"16\" />\r\n {/if}\r\n {badgeInfo.text}\r\n </span>\r\n {:else}\r\n <Badge variant={scVariant} size=\"sm\">\r\n {#snippet leftIcon()}\r\n {#if badgeInfo.showFlame}\r\n <WarningCircleIcon size=\"16\" />\r\n {/if}\r\n {/snippet}\r\n {badgeInfo.text}\r\n </Badge>\r\n {/if}\r\n{/if}\r\n"],"names":["size","$","$$props","color","className","ctx","useIconWeight","resolved","svg","root_2","path","root","line","root_1","$$render","consequent","alternate","styles","goto","url","opts","SCARCITY_ANNOUNCE_DEBOUNCE_MS","scarcityAnnouncers","announceScarcity","message","createDebouncedAnnouncer","context","variant","isFree","labels","defaultLabels","level","computeScarcityLevel","badgeInfo","soldOutText","sellingFastText","onlyNLeftTemplate","scVariant","ariaLabel","scarcityAnnounceReady","text","span","WarningCircleIcon","$$anchor","text_1","Badge","consequent_2","text_2","consequent_1","consequent_3"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "svelte/internal/disclose-version";
|
|
2
2
|
import * as e from "svelte/internal/client";
|
|
3
|
-
import { g as f } from "./ScarcityBadge-
|
|
4
|
-
import { u as d, x as u } from "./VenueCalendar-
|
|
5
|
-
import { E as v } from "./Event-
|
|
6
|
-
import { a as p } from "./transform-
|
|
3
|
+
import { g as f } from "./ScarcityBadge-5RMumV4l.js";
|
|
4
|
+
import { u as d, x as u } from "./VenueCalendar-Ys8-209-.js";
|
|
5
|
+
import { E as v } from "./Event-DJusXK29.js";
|
|
6
|
+
import { a as p } from "./transform-DiYvD4iM.js";
|
|
7
7
|
function w(n, i) {
|
|
8
8
|
e.push(i, !0), d("SeriesPage");
|
|
9
9
|
let r = e.prop(i, "onNavigateToOccurrence", 3, void 0), s = e.prop(i, "locale", 3, void 0), a = e.derived(() => i.series ? p(i.series) : null);
|
|
@@ -33,4 +33,4 @@ function w(n, i) {
|
|
|
33
33
|
export {
|
|
34
34
|
w as default
|
|
35
35
|
};
|
|
36
|
-
//# sourceMappingURL=SeriesPage-
|
|
36
|
+
//# sourceMappingURL=SeriesPage-Dy28yKRV.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SeriesPage-
|
|
1
|
+
{"version":3,"file":"SeriesPage-Dy28yKRV.js","sources":["../src/components/Views/SeriesPage.svelte"],"sourcesContent":["<!-- @route-escape: widget-intentional. -->\r\n<script lang=\"ts\">\r\n import { goto } from '$app/navigation';\r\n import { resolve } from '$app/paths';\r\n import EventExperience from '$lib/public-calendar-flow/Event.svelte';\r\n import { createLogger } from '@getmicdrop/svelte-components';\r\n import { transformSeriesPageData } from '$lib/public-calendar-flow/transform';\r\n\r\n const _logger = createLogger('SeriesPage');\r\n\r\n // --- Props (matches old SeriesPage external interface) ---\r\n interface Props {\r\n series: any;\r\n onNavigateToOccurrence?: (\r\n _id: number,\r\n _slug: string,\r\n _name?: string\r\n ) => void;\r\n /** BCP-47 locale, threaded per-instance to EventExperience's date\r\n * formatters (vc#760). Undefined → en-US. */\r\n locale?: string;\r\n }\r\n\r\n let {\r\n series,\r\n onNavigateToOccurrence = undefined,\r\n locale = undefined,\r\n }: Props = $props();\r\n\r\n // Transform series data to EventData for EventExperience\r\n let eventData = $derived(series ? transformSeriesPageData(series) : null);\r\n\r\n // Handle occurrence click — delegate to callback or navigate directly\r\n function handleShowtimeClick(occurrence: { id: number; slug: string }): void {\r\n if (onNavigateToOccurrence) {\r\n onNavigateToOccurrence(occurrence.id, occurrence.slug);\r\n } else {\r\n // @url-builder-escape: widget-internal route; SC's url-builders cover /a admin paths, not embedded calendar navigation.\r\n goto(\r\n resolve('/[id]/[slug]', {\r\n id: String(occurrence.id),\r\n slug: String(occurrence.slug),\r\n })\r\n );\r\n }\r\n }\r\n</script>\r\n\r\n{#if eventData}\r\n <EventExperience\r\n event={eventData}\r\n isSeriesMaster\r\n onShowtimeClick={handleShowtimeClick}\r\n {locale}\r\n />\r\n{/if}\r\n"],"names":["createLogger","onNavigateToOccurrence","$","$$props","locale","eventData","transformSeriesPageData","handleShowtimeClick","occurrence","goto","resolve","EventExperience","$$anchor","$$render","consequent"],"mappings":";;;;;;iBACA;iBAOkBA,EAAa,YAAY;AAezC,MAEEC,IAAsBC,EAAA,KAAAC,GAAA,0BAAA,GAAG,MAAS,GAClCC,2BAAS,MAAS,GAIhBC,IAASH,EAAA,QAAA,MAAAC,EAAA,SAAqBG,EAAuBH,EAAA,MAAA,IAAW,IAAI;AAGxE,WAASI,EAAoBC,GAAgD;AAC3E,IAAIP,EAAsB,IACxBA,EAAsB,EAACO,EAAW,IAAIA,EAAW,IAAI,IAGrDC,EACEC,EAAQ,gBAAc,EACpB,IAAI,OAAOF,EAAW,EAAE,GACxB,MAAM,OAAOA,EAAW,IAAI,EAAA,CAAA,CAAA;AAAA,EAIpC;;;;AAICG,MAAAA,EAAeC,GAAA;AAAA;uBACPP,CAAS;AAAA;;yBAECE;AAAA;iBAChBH,EAAM;AAAA;;;;YALNC,CAAS,KAAAQ,EAAAC,CAAA;AAAA;;;AAFN;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "svelte/internal/disclose-version";
|
|
2
2
|
import * as e from "svelte/internal/client";
|
|
3
|
-
import { m as f, c5 as r, c6 as i } from "./VenueCalendar-
|
|
3
|
+
import { m as f, c5 as r, c6 as i } from "./VenueCalendar-Ys8-209-.js";
|
|
4
4
|
var h = e.from_html('<svg aria-hidden="true" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg" role="status"><path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"></path><path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"></path></svg> <span class="sr-only"> </span>', 1);
|
|
5
5
|
function x(o, t) {
|
|
6
6
|
e.push(t, !0);
|
|
@@ -14,4 +14,4 @@ function x(o, t) {
|
|
|
14
14
|
export {
|
|
15
15
|
x as S
|
|
16
16
|
};
|
|
17
|
-
//# sourceMappingURL=Spinner-
|
|
17
|
+
//# sourceMappingURL=Spinner-D-c4nFeN.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Spinner-
|
|
1
|
+
{"version":3,"file":"Spinner-D-c4nFeN.js","sources":["../node_modules/@getmicdrop/svelte-components/dist/primitives/Spinner/Spinner.svelte"],"sourcesContent":["<script lang=\"ts\">\n import { mergeLabels, type SCLabels } from '../../utils/labels.js';\n import {\n spinnerColorVariants,\n type SpinnerColorVariant,\n } from '../../tokens/variants.js';\n import { iconSizes, type IconSize } from '../../tokens/sizing.js';\n\n const defaultLabels = {\n loading: 'Loading...',\n };\n\n interface Props {\n size?: IconSize;\n color?: SpinnerColorVariant;\n class?: string;\n labels?: SCLabels<typeof defaultLabels>;\n }\n\n let {\n size = 'md',\n color = 'blue',\n class: className = '',\n labels: userLabels = {},\n }: Props = $props();\n\n let labels = $derived(mergeLabels(defaultLabels, userLabels));\n\n let sizeClass = $derived(iconSizes[size] || iconSizes.md);\n let colorClass = $derived(spinnerColorVariants[color] || spinnerColorVariants.blue);\n</script>\n\n<svg\n aria-hidden=\"true\"\n class=\"{sizeClass} tone-muted animate-spin {colorClass} {className}\"\n viewBox=\"0 0 100 101\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n role=\"status\"\n>\n <path\n d=\"M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z\"\n fill=\"currentFill\"\n />\n</svg>\n<span class=\"sr-only\">{labels.loading}</span>\n"],"names":["defaultLabels","size","$","$$props","color","className","userLabels","labels","mergeLabels","sizeClass","iconSizes","colorClass","spinnerColorVariants","svg","fragment","span","text"],"mappings":";;;;iBAAA;;AAQE,QAAMA,IAAa,EACjB,SAAS,aAAY;AAUvB,MACEC,IAAIC,EAAA,KAAAC,GAAA,QAAA,GAAG,IAAI,GACXC,0BAAQ,MAAM,GACPC,0BAAY,EAAE,GACbC,IAAUJ,EAAA,KAAAC,GAAA,UAAA,IAAA,OAAA,CAAA,EAAA,GAGhBI,IAAML,EAAA,QAAA,MAAYM,EAAYR,GAAeM,EAAU,CAAA,CAAA,GAEvDG,oBAAqBC,EAAUT,EAAI,CAAA,KAAKS,EAAU,EAAE,GACpDC,oBAAsBC,EAAqBR,EAAK,CAAA,KAAKQ,EAAqB,IAAI;eAGnFC,IAAEX,EAAA,YAAAY,CAAA,GAiBFC,cAjBAF,GAAE,CAAA,eAiBFE,GAAI,EAAA;UAAJA,CAAI;AAjBJ,IAAAb,EAAA,UAAAW,GAAE,GAAA,GAAAX,EAAA,IAEOO,CAAS,KAAA,EAAA,4BAAAP,EAAA,IAA2BS,CAAU,WAAGN,EAAS,KAAA,EAAA,EAAA,GAe7CH,EAAA,SAAAc,GAAAd,EAAA,IAAAK,CAAM,EAAC,OAAO;AAAA;AAnB7B;","x_google_ignoreList":[0]}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import "svelte/internal/disclose-version";
|
|
2
|
-
import { Z as Ne, _ as ke, $ as Ue, a0 as me, a1 as Le, a2 as Oe, a3 as Me, j as ie, a4 as Re, a5 as Fe, a6 as Q, g as Ge, a7 as je, a8 as Be, a9 as Ve, aa as qe, ab as He, X as We, u as Ye, x as fe } from "./VenueCalendar-
|
|
2
|
+
import { Z as Ne, _ as ke, $ as Ue, a0 as me, a1 as Le, a2 as Oe, a3 as Me, j as ie, a4 as Re, a5 as Fe, a6 as Q, g as Ge, a7 as je, a8 as Be, a9 as Ve, aa as qe, ab as He, X as We, u as Ye, x as fe } from "./VenueCalendar-Ys8-209-.js";
|
|
3
3
|
import { SvelteMap as Ze } from "svelte/reactivity";
|
|
4
4
|
import * as e from "svelte/internal/client";
|
|
5
5
|
import { onMount as ce, onDestroy as Ke } from "svelte";
|
|
6
|
-
import { a as pe, c as Xe, r as Je } from "./utm-
|
|
7
|
-
import { c as Qe, E as $e, t as et } from "./transform-
|
|
8
|
-
import { d as te, m as tt, a as rt, b as at, c as st, g as lt } from "./showcase-state-options-
|
|
9
|
-
import { O as nt, g as it, c as ot } from "./index-
|
|
6
|
+
import { a as pe, c as Xe, r as Je } from "./utm-TGZ2W8Ii.js";
|
|
7
|
+
import { c as Qe, E as $e, t as et } from "./transform-DiYvD4iM.js";
|
|
8
|
+
import { d as te, m as tt, a as rt, b as at, c as st, g as lt } from "./showcase-state-options-QYvDSYq0.js";
|
|
9
|
+
import { O as nt, g as it, c as ot } from "./index-B5pEXtmb.js";
|
|
10
10
|
import { d as we } from "./labels-BhvPsg7u.js";
|
|
11
|
-
import { C as Ce, H as ct } from "./Heading-
|
|
11
|
+
import { C as Ce, H as ct } from "./Heading-D81DQHoP.js";
|
|
12
12
|
import { T as $ } from "./Text-DacTw_9X.js";
|
|
13
|
-
import { M as dt, D as vt } from "./MailIcon-
|
|
14
|
-
import { I as ut } from "./Image-
|
|
15
|
-
import { C as he } from "./CalendarIcon-
|
|
16
|
-
import { L as gt } from "./copyToClipboard-
|
|
13
|
+
import { M as dt, D as vt } from "./MailIcon-3o_dDUzN.js";
|
|
14
|
+
import { I as ut } from "./Image-BktsxRho.js";
|
|
15
|
+
import { C as he } from "./CalendarIcon-BXHIKvAr.js";
|
|
16
|
+
import { L as gt } from "./copyToClipboard-Ct55SL-r.js";
|
|
17
17
|
var mt = e.from_svg('<path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,168a12,12,0,1,1,12-12A12,12,0,0,1,128,192Zm8-48.72V144a8,8,0,0,1-16,0v-8a8,8,0,0,1,8-8c13.23,0,24-9,24-20s-10.77-20-24-20-24,9-24,20v4a8,8,0,0,1-16,0v-4c0-19.85,17.94-36,40-36s40,16.15,40,36C168,125.38,154.24,139.93,136,143.28Z"></path>'), ft = e.from_svg('<circle cx="128" cy="180" r="12"></circle><path d="M128,144v-8c17.67,0,32-12.54,32-28s-14.33-28-32-28S96,92.54,96,108v4" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"></path><circle cx="128" cy="128" r="96" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"></circle>', 1), pt = e.from_svg('<svg aria-hidden="true" viewBox="0 0 256 256" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><!></svg>');
|
|
18
18
|
function ht(x, t) {
|
|
19
19
|
e.push(t, !0);
|
|
@@ -868,4 +868,4 @@ function Jt(x, t) {
|
|
|
868
868
|
export {
|
|
869
869
|
Jt as default
|
|
870
870
|
};
|
|
871
|
-
//# sourceMappingURL=Success-
|
|
871
|
+
//# sourceMappingURL=Success-Zx8HLwlN.js.map
|