@fluid-app/portal-sdk 0.1.231 → 0.1.232
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/{AppDownloadScreen-BmYJ7Zgb.cjs → AppDownloadScreen-B0YwMqYM.cjs} +2 -2
- package/dist/{AppDownloadScreen-BmYJ7Zgb.cjs.map → AppDownloadScreen-B0YwMqYM.cjs.map} +1 -1
- package/dist/{AppDownloadScreen-zrhWlSE7.mjs → AppDownloadScreen-Dj5ZPsSb.mjs} +2 -2
- package/dist/{AppDownloadScreen-zrhWlSE7.mjs.map → AppDownloadScreen-Dj5ZPsSb.mjs.map} +1 -1
- package/dist/{AppNavigationContext-C1-hd9Rw.cjs → AppNavigationContext-BDs1cOuG.cjs} +1 -1
- package/dist/{AppNavigationContext-C1-hd9Rw.cjs.map → AppNavigationContext-BDs1cOuG.cjs.map} +1 -1
- package/dist/{AppNavigationContext-BcZZMtV6.mjs → AppNavigationContext-DNod9mf6.mjs} +1 -1
- package/dist/{AppNavigationContext-BcZZMtV6.mjs.map → AppNavigationContext-DNod9mf6.mjs.map} +1 -1
- package/dist/{ContactsScreen-BfS33bcq.cjs → ContactsScreen-9cZWC9PP.cjs} +6 -6
- package/dist/{ContactsScreen-DHHzJhO4.mjs → ContactsScreen-B4Ue9m5H.mjs} +9 -22
- package/dist/ContactsScreen-B4Ue9m5H.mjs.map +1 -0
- package/dist/{ContactsScreen-gq1fPZzb.cjs → ContactsScreen-BTQ_qfq3.cjs} +10 -23
- package/dist/ContactsScreen-BTQ_qfq3.cjs.map +1 -0
- package/dist/{CustomersScreen-D55HjYHC.mjs → CustomersScreen-CX3P2KpF.mjs} +1 -1
- package/dist/{CustomersScreen-D55HjYHC.mjs.map → CustomersScreen-CX3P2KpF.mjs.map} +1 -1
- package/dist/{CustomersScreen-DW3BuhBs.cjs → CustomersScreen-GROLIynQ.cjs} +1 -1
- package/dist/{CustomersScreen-DW3BuhBs.cjs.map → CustomersScreen-GROLIynQ.cjs.map} +1 -1
- package/dist/{FluidProvider-DWNo4QTC.cjs → FluidProvider-BNL_Apw2.cjs} +26 -6
- package/dist/{FluidProvider-DWNo4QTC.cjs.map → FluidProvider-BNL_Apw2.cjs.map} +1 -1
- package/dist/{FluidProvider-i69t4zBo.mjs → FluidProvider-Dg-eouRw.mjs} +26 -6
- package/dist/FluidProvider-Dg-eouRw.mjs.map +1 -0
- package/dist/{InfiniteScrollSentinel-bVdxImf8.mjs → InfiniteScrollSentinel-CQD9JPVe.mjs} +1 -1
- package/dist/{InfiniteScrollSentinel-bVdxImf8.mjs.map → InfiniteScrollSentinel-CQD9JPVe.mjs.map} +1 -1
- package/dist/{InfiniteScrollSentinel-LcHXpBw-.cjs → InfiniteScrollSentinel-V1ubmA8z.cjs} +1 -1
- package/dist/{InfiniteScrollSentinel-LcHXpBw-.cjs.map → InfiniteScrollSentinel-V1ubmA8z.cjs.map} +1 -1
- package/dist/{MessagingScreen-CDx6ryDj.cjs → MessagingScreen-BMoCh4MT.cjs} +6 -6
- package/dist/{MessagingScreen-Crp-Kl4c.cjs → MessagingScreen-CxpLlTW_.cjs} +5 -5
- package/dist/{MessagingScreen-Crp-Kl4c.cjs.map → MessagingScreen-CxpLlTW_.cjs.map} +1 -1
- package/dist/{MessagingScreen-BbIKoH2L.mjs → MessagingScreen-Q17pdhUz.mjs} +3 -3
- package/dist/{MessagingScreen-BbIKoH2L.mjs.map → MessagingScreen-Q17pdhUz.mjs.map} +1 -1
- package/dist/{MySiteScreen-DsR9VEwa.cjs → MySiteScreen-5-eNH2S6.cjs} +3 -3
- package/dist/{MySiteScreen-DwgWY0cl.cjs → MySiteScreen-B1yomsp6.cjs} +3 -3
- package/dist/{MySiteScreen-DwgWY0cl.cjs.map → MySiteScreen-B1yomsp6.cjs.map} +1 -1
- package/dist/{MySiteScreen-Q9xN2oxD.mjs → MySiteScreen-BBT8FN5s.mjs} +3 -3
- package/dist/{MySiteScreen-Q9xN2oxD.mjs.map → MySiteScreen-BBT8FN5s.mjs.map} +1 -1
- package/dist/OrdersScreen-Co2oatu4.cjs +9 -0
- package/dist/{OrdersScreen-DcC_-N8h.mjs → OrdersScreen-DkTGTQJZ.mjs} +5 -5
- package/dist/{OrdersScreen-DcC_-N8h.mjs.map → OrdersScreen-DkTGTQJZ.mjs.map} +1 -1
- package/dist/{OrdersScreen-DxQmihvZ.cjs → OrdersScreen-e5DdNpD-.cjs} +5 -5
- package/dist/{OrdersScreen-DxQmihvZ.cjs.map → OrdersScreen-e5DdNpD-.cjs.map} +1 -1
- package/dist/{PortalProductsApiProvider-CP1xk872.mjs → PortalProductsApiProvider-BIZg_c4Y.mjs} +2 -2
- package/dist/{PortalProductsApiProvider-CP1xk872.mjs.map → PortalProductsApiProvider-BIZg_c4Y.mjs.map} +1 -1
- package/dist/{PortalProductsApiProvider-jDoPfaPB.cjs → PortalProductsApiProvider-DL8nl7To.cjs} +2 -2
- package/dist/{PortalProductsApiProvider-jDoPfaPB.cjs.map → PortalProductsApiProvider-DL8nl7To.cjs.map} +1 -1
- package/dist/{ProfileScreen-B2JEvxsd.cjs → ProfileScreen-BSWw10cc.cjs} +6 -6
- package/dist/{ProfileScreen-ftzRbWgc.mjs → ProfileScreen-CHsIDbg8.mjs} +6 -6
- package/dist/{ProfileScreen-ftzRbWgc.mjs.map → ProfileScreen-CHsIDbg8.mjs.map} +1 -1
- package/dist/{ProfileScreen-BPdHZZXV.cjs → ProfileScreen-CVOS2By3.cjs} +6 -6
- package/dist/{ProfileScreen-BPdHZZXV.cjs.map → ProfileScreen-CVOS2By3.cjs.map} +1 -1
- package/dist/{ScreenHeaderContext-4WYXIqQ5.mjs → ScreenHeaderContext-Cemdo7bM.mjs} +1 -1
- package/dist/{ScreenHeaderContext-4WYXIqQ5.mjs.map → ScreenHeaderContext-Cemdo7bM.mjs.map} +1 -1
- package/dist/{ScreenHeaderContext-PbjwAMeB.cjs → ScreenHeaderContext-oIu5Bvhs.cjs} +1 -1
- package/dist/{ScreenHeaderContext-PbjwAMeB.cjs.map → ScreenHeaderContext-oIu5Bvhs.cjs.map} +1 -1
- package/dist/{SearchSort-BQ-nf9gJ.mjs → SearchSort-DN0gsmxk.mjs} +1 -1
- package/dist/{SearchSort-BQ-nf9gJ.mjs.map → SearchSort-DN0gsmxk.mjs.map} +1 -1
- package/dist/{SearchSort-Hwga1dIi.cjs → SearchSort-O89uV2dl.cjs} +1 -1
- package/dist/{SearchSort-Hwga1dIi.cjs.map → SearchSort-O89uV2dl.cjs.map} +1 -1
- package/dist/{ShareablesScreen-BjpwByeL.mjs → ShareablesScreen-DHKFnIOE.mjs} +11 -11
- package/dist/{ShareablesScreen-BjpwByeL.mjs.map → ShareablesScreen-DHKFnIOE.mjs.map} +1 -1
- package/dist/{ShareablesScreen-iXNQCKSx.cjs → ShareablesScreen-DQjgnn2x.cjs} +8 -8
- package/dist/{ShareablesScreen-BsICzJuf.cjs → ShareablesScreen-DfrTNnRw.cjs} +12 -12
- package/dist/{ShareablesScreen-BsICzJuf.cjs.map → ShareablesScreen-DfrTNnRw.cjs.map} +1 -1
- package/dist/{ShopScreen-recdiuo_.cjs → ShopScreen-CFR2O1jn.cjs} +7 -7
- package/dist/{ShopScreen-d6e2Bm0N.mjs → ShopScreen-CLN8FFiL.mjs} +7 -7
- package/dist/{ShopScreen-d6e2Bm0N.mjs.map → ShopScreen-CLN8FFiL.mjs.map} +1 -1
- package/dist/{ShopScreen-DBopix8F.cjs → ShopScreen-jk3Y3-x8.cjs} +7 -7
- package/dist/{ShopScreen-DBopix8F.cjs.map → ShopScreen-jk3Y3-x8.cjs.map} +1 -1
- package/dist/{SubscriptionsScreen-CcaqnqiQ.mjs → SubscriptionsScreen-CVPj6hhP.mjs} +10 -10
- package/dist/{SubscriptionsScreen-CcaqnqiQ.mjs.map → SubscriptionsScreen-CVPj6hhP.mjs.map} +1 -1
- package/dist/{SubscriptionsScreen-BI296E2y.cjs → SubscriptionsScreen-DOf7rlRP.cjs} +6 -6
- package/dist/{SubscriptionsScreen-DkiuXzRX.cjs → SubscriptionsScreen-r2_drNFg.cjs} +11 -11
- package/dist/{SubscriptionsScreen-DkiuXzRX.cjs.map → SubscriptionsScreen-r2_drNFg.cjs.map} +1 -1
- package/dist/ToDoWidget-BgyusdPn.cjs +8 -0
- package/dist/{ToDoWidget-CaDOZtAB.cjs → ToDoWidget-CQ_zTbhz.cjs} +114 -31
- package/dist/ToDoWidget-CQ_zTbhz.cjs.map +1 -0
- package/dist/{ToDoWidget-Bv258x8F.mjs → ToDoWidget-DYGt45vL.mjs} +116 -23
- package/dist/ToDoWidget-DYGt45vL.mjs.map +1 -0
- package/dist/{UpgradeScreen-4Z5_ALSr.cjs → UpgradeScreen-BJbdv9T9.cjs} +1 -1
- package/dist/{UpgradeScreen-CGiVn0KG.mjs → UpgradeScreen-DMxxZjj_.mjs} +1 -1
- package/dist/{UpgradeScreen-CGiVn0KG.mjs.map → UpgradeScreen-DMxxZjj_.mjs.map} +1 -1
- package/dist/{UpgradeScreen-BaclFXEh.cjs → UpgradeScreen-QhhBuHXE.cjs} +1 -1
- package/dist/{UpgradeScreen-BaclFXEh.cjs.map → UpgradeScreen-QhhBuHXE.cjs.map} +1 -1
- package/dist/{VideoWidget-BntlfHhP.cjs → VideoWidget-Bc6ZAAaA.cjs} +1 -1
- package/dist/{VideoWidget-BntlfHhP.cjs.map → VideoWidget-Bc6ZAAaA.cjs.map} +1 -1
- package/dist/{VideoWidget-DmHZ05vp.mjs → VideoWidget-lTyeZypJ.mjs} +1 -1
- package/dist/{VideoWidget-DmHZ05vp.mjs.map → VideoWidget-lTyeZypJ.mjs.map} +1 -1
- package/dist/{dist-FHf4OHgt.cjs → dist-BQZkLGL6.cjs} +1 -1
- package/dist/{dist-FHf4OHgt.cjs.map → dist-BQZkLGL6.cjs.map} +1 -1
- package/dist/{dist-BQCx-9SK.cjs → dist-DbRTQ2QF.cjs} +1 -1
- package/dist/{dist-BQCx-9SK.cjs.map → dist-DbRTQ2QF.cjs.map} +1 -1
- package/dist/{dist-q1wrtxfG.mjs → dist-PbA1vxAz.mjs} +1 -1
- package/dist/{dist-q1wrtxfG.mjs.map → dist-PbA1vxAz.mjs.map} +1 -1
- package/dist/{dist-5XPflEEG.cjs → dist-myuZC8sf.cjs} +2 -2
- package/dist/{dist-5XPflEEG.cjs.map → dist-myuZC8sf.cjs.map} +1 -1
- package/dist/{dist-CsNsoBdu.mjs → dist-o2cjwzIa.mjs} +2 -2
- package/dist/{dist-CsNsoBdu.mjs.map → dist-o2cjwzIa.mjs.map} +1 -1
- package/dist/{es-nxOxb57F.cjs → es-UfEBhcZD.cjs} +1 -1
- package/dist/{es-nxOxb57F.cjs.map → es-UfEBhcZD.cjs.map} +1 -1
- package/dist/{fluid-pay-api-adapter-COBmngde.cjs → fluid-pay-api-adapter-CLP8wfno.cjs} +1 -1
- package/dist/{fluid-pay-api-adapter-COBmngde.cjs.map → fluid-pay-api-adapter-CLP8wfno.cjs.map} +1 -1
- package/dist/{fluid-pay-api-adapter-Dv2K17WN.mjs → fluid-pay-api-adapter-Dfi0LtxL.mjs} +1 -1
- package/dist/{fluid-pay-api-adapter-Dv2K17WN.mjs.map → fluid-pay-api-adapter-Dfi0LtxL.mjs.map} +1 -1
- package/dist/{format-Dyb61f6F.cjs → format-CytB2M00.cjs} +1 -1
- package/dist/{format-Dyb61f6F.cjs.map → format-CytB2M00.cjs.map} +1 -1
- package/dist/index.cjs +49 -49
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +48 -48
- package/dist/{order-status-badge-CnQE7lFJ.mjs → order-status-badge-CL5XC2va.mjs} +3 -3
- package/dist/{order-status-badge-CnQE7lFJ.mjs.map → order-status-badge-CL5XC2va.mjs.map} +1 -1
- package/dist/{order-status-badge-NMygmn5d.cjs → order-status-badge-Cqkx76d8.cjs} +3 -3
- package/dist/{order-status-badge-NMygmn5d.cjs.map → order-status-badge-Cqkx76d8.cjs.map} +1 -1
- package/dist/parse-task-body-BxbA_DC6.cjs +29 -0
- package/dist/parse-task-body-BxbA_DC6.cjs.map +1 -0
- package/dist/parse-task-body-DEmYvdNM.mjs +24 -0
- package/dist/parse-task-body-DEmYvdNM.mjs.map +1 -0
- package/dist/{portal_tenant-CxChT6OB.cjs → portal_tenant-CNmiAf_A.cjs} +18 -1
- package/dist/{portal_tenant-CxChT6OB.cjs.map → portal_tenant-CNmiAf_A.cjs.map} +1 -1
- package/dist/{portal_tenant-f_Cs2YmO.mjs → portal_tenant-Q3x7ALaZ.mjs} +13 -2
- package/dist/{portal_tenant-f_Cs2YmO.mjs.map → portal_tenant-Q3x7ALaZ.mjs.map} +1 -1
- package/dist/{query-keys-CC2PXIfJ.cjs → query-keys-D3lK70Ea.cjs} +1 -1
- package/dist/{query-keys-BkMRwfNo.mjs.map → query-keys-D3lK70Ea.cjs.map} +1 -1
- package/dist/{query-keys-BkMRwfNo.mjs → query-keys-xJy_fapN.mjs} +1 -1
- package/dist/{query-keys-CC2PXIfJ.cjs.map → query-keys-xJy_fapN.mjs.map} +1 -1
- package/dist/{sortable.esm-BSpvRpWg.mjs → sortable.esm-C8G00cCP.mjs} +1 -1
- package/dist/{sortable.esm-BSpvRpWg.mjs.map → sortable.esm-C8G00cCP.mjs.map} +1 -1
- package/dist/{use-account-Ipii17ZX.mjs → use-account-CBMPhhs7.mjs} +2 -2
- package/dist/{use-account-Ipii17ZX.mjs.map → use-account-CBMPhhs7.mjs.map} +1 -1
- package/dist/{use-account-Bv_VAVxj.cjs → use-account-DcBCP06c.cjs} +2 -2
- package/dist/{use-account-Bv_VAVxj.cjs.map → use-account-DcBCP06c.cjs.map} +1 -1
- package/dist/{use-store-3holBUj4.mjs → use-store-By_7tzrN.mjs} +1 -1
- package/dist/{use-store-3holBUj4.mjs.map → use-store-By_7tzrN.mjs.map} +1 -1
- package/dist/{use-store-D2S1FywW.cjs → use-store-lOOUcpRT.cjs} +1 -1
- package/dist/{use-store-D2S1FywW.cjs.map → use-store-lOOUcpRT.cjs.map} +1 -1
- package/package.json +13 -13
- package/dist/ContactsScreen-DHHzJhO4.mjs.map +0 -1
- package/dist/ContactsScreen-gq1fPZzb.cjs.map +0 -1
- package/dist/FluidProvider-i69t4zBo.mjs.map +0 -1
- package/dist/OrdersScreen-CfnNy52h.cjs +0 -9
- package/dist/ToDoWidget-Bv258x8F.mjs.map +0 -1
- package/dist/ToDoWidget-CaDOZtAB.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoWidget-DmHZ05vp.mjs","names":[],"sources":["../../widgets/src/widgets/VideoWidget.tsx"],"sourcesContent":["import type { ComponentProps, CSSProperties, ReactNode } from \"react\";\nimport type React from \"react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n borderColorClasses,\n borderWidthClasses,\n getBorderColorField,\n getBorderRadiusField,\n getBorderWidthField,\n getColorField,\n getHeightField,\n type WidgetPropertySchema,\n} from \"@fluid-app/portal-core/registries\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n ShareableItem,\n} from \"@fluid-app/portal-core/types\";\nimport { MediaRenderer } from \"../components/MediaRenderer\";\n\ntype VideoWidgetProps = ComponentProps<\"div\"> & {\n // Content\n src?: string;\n poster?: string;\n resource?: ShareableItem;\n useCustomUrl?: boolean;\n\n // Display\n displayMode?: \"inline\" | \"card\";\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n verticalSizing?: \"auto\" | \"fixed\";\n fixedHeight?: string;\n displayFit?: \"cover\" | \"contain\";\n focusPoint?: string;\n\n // Native video behavior (inline mode)\n controls?: boolean;\n autoplay?: boolean;\n loop?: boolean;\n muted?: boolean;\n\n // Card mode — editorial frame + metadata\n editorialFrame?: boolean;\n frameColor?: ColorOptions;\n eyebrow?: string;\n tag?: string;\n title?: string;\n tagline?: string;\n duration?: string;\n author?: string;\n date?: string;\n showFullscreenPill?: boolean;\n\n // Card mode — modal CTAs\n primaryCtaText?: string;\n primaryCtaLink?: string;\n secondaryCtaText?: string;\n secondaryCtaLink?: string;\n};\n\nexport function VideoWidget({\n src = \"\",\n poster = \"\",\n resource,\n useCustomUrl,\n\n displayMode = \"inline\",\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n verticalSizing = \"auto\",\n fixedHeight = \"200px\",\n displayFit = \"cover\",\n focusPoint,\n\n controls = true,\n autoplay = false,\n loop = false,\n muted = true,\n\n editorialFrame = true,\n frameColor = \"foreground\",\n eyebrow,\n tag,\n title,\n tagline,\n duration,\n author,\n date,\n showFullscreenPill = true,\n\n primaryCtaText,\n primaryCtaLink,\n secondaryCtaText,\n secondaryCtaLink,\n}: VideoWidgetProps): React.JSX.Element {\n const effectiveSrc = useCustomUrl ? src : (resource?.videoUrl ?? src);\n const effectivePoster = useCustomUrl\n ? poster\n : (resource?.imageUrl ?? poster ?? undefined);\n\n if (displayMode === \"card\") {\n const resolvedTitle =\n typeof title === \"string\" && title.trim()\n ? title\n : (resource?.title ?? undefined);\n const resourceDescription =\n typeof resource?.description === \"string\"\n ? resource.description\n : undefined;\n const resolvedTagline =\n typeof tagline === \"string\" && tagline.trim()\n ? tagline\n : resourceDescription;\n\n return (\n <VideoCard\n src={effectiveSrc}\n poster={effectivePoster ?? undefined}\n borderRadius={borderRadius}\n editorialFrame={editorialFrame}\n frameColor={frameColor}\n eyebrow={eyebrow}\n tag={tag}\n title={resolvedTitle}\n tagline={resolvedTagline}\n duration={duration}\n author={author}\n date={date}\n showFullscreenPill={showFullscreenPill}\n primaryCtaText={primaryCtaText}\n primaryCtaLink={primaryCtaLink}\n secondaryCtaText={secondaryCtaText}\n secondaryCtaLink={secondaryCtaLink}\n />\n );\n }\n\n const isFixed = verticalSizing === \"fixed\";\n const borderWidthClass = borderWidthClasses[borderWidth];\n const borderColorClass =\n borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\";\n\n return (\n <div\n className={`relative w-full overflow-hidden rounded-${borderRadius} ${borderWidthClass} ${borderColorClass}`}\n style={isFixed ? { height: fixedHeight } : undefined}\n >\n <MediaRenderer\n mediaType=\"video\"\n src={effectiveSrc}\n poster={effectivePoster}\n objectFit={isFixed ? displayFit : undefined}\n focusPoint={isFixed ? focusPoint : undefined}\n controls={controls}\n autoplay={autoplay}\n loop={loop}\n muted={muted}\n />\n </div>\n );\n}\n\ntype VideoCardProps = {\n src: string | undefined;\n poster: string | undefined;\n borderRadius: BorderRadiusOptions;\n editorialFrame: boolean;\n frameColor: ColorOptions;\n eyebrow: string | undefined;\n tag: string | undefined;\n title: string | undefined;\n tagline: string | undefined;\n duration: string | undefined;\n author: string | undefined;\n date: string | undefined;\n showFullscreenPill: boolean;\n primaryCtaText: string | undefined;\n primaryCtaLink: string | undefined;\n secondaryCtaText: string | undefined;\n secondaryCtaLink: string | undefined;\n};\n\nfunction useVideoPosterFallback(\n poster: string | undefined,\n embed: ParsedVideoSource,\n) {\n const resolvedPoster = poster || embed.thumbnail || \"\";\n const [posterSrc, setPosterSrc] = useState(resolvedPoster);\n\n useEffect(() => {\n setPosterSrc(resolvedPoster);\n }, [resolvedPoster]);\n\n const handlePosterError = useCallback(() => {\n if (embed.thumbnailFallback && posterSrc !== embed.thumbnailFallback) {\n setPosterSrc(embed.thumbnailFallback);\n }\n }, [embed.thumbnailFallback, posterSrc]);\n\n return { posterSrc, handlePosterError };\n}\n\nfunction VideoCard({\n src,\n poster,\n borderRadius,\n editorialFrame,\n frameColor,\n eyebrow,\n tag,\n title,\n tagline,\n duration,\n author,\n date,\n showFullscreenPill,\n primaryCtaText,\n primaryCtaLink,\n secondaryCtaText,\n secondaryCtaLink,\n}: VideoCardProps) {\n const [modalOpen, setModalOpen] = useState(false);\n const handleClose = useCallback(() => setModalOpen(false), []);\n\n const embed = parseVideoSource(src);\n const { posterSrc, handlePosterError } = useVideoPosterFallback(\n poster,\n embed,\n );\n\n const frameVar = `var(--color-${frameColor})`;\n const frameShadow = editorialFrame\n ? \"shadow-[0_1px_2px_rgba(15,23,42,0.04),0_30px_60px_-30px_rgba(15,23,42,0.4)]\"\n : \"\";\n const frameBg = editorialFrame ? `bg-${frameColor}` : \"\";\n\n const gradientTop: CSSProperties = {\n background: `linear-gradient(to top, ${frameVar}, color-mix(in oklch, ${frameVar} 55%, transparent), color-mix(in oklch, ${frameVar} 8%, transparent))`,\n };\n const gradientLeft: CSSProperties = {\n background: `linear-gradient(to right, color-mix(in oklch, ${frameVar} 70%, transparent), transparent)`,\n };\n\n return (\n <>\n <button\n type=\"button\"\n onClick={() => setModalOpen(true)}\n aria-label={title ? `Play video: ${title}` : \"Play video\"}\n className={`group relative block w-full overflow-hidden rounded-${borderRadius} ${frameBg} ${frameShadow} focus-visible:ring-primary text-left focus:outline-none focus-visible:ring-2`}\n >\n <div className=\"relative aspect-[16/9] w-full\">\n {posterSrc ? (\n <img\n src={posterSrc}\n alt={title ?? \"Video thumbnail\"}\n className=\"absolute inset-0 h-full w-full object-cover transition-transform duration-[700ms] group-hover:scale-[1.03]\"\n onError={handlePosterError}\n />\n ) : (\n <div className=\"bg-muted/30 absolute inset-0 flex items-center justify-center\">\n <PlayIcon size={40} filled />\n </div>\n )}\n\n {editorialFrame && (\n <>\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={gradientTop}\n />\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={gradientLeft}\n />\n </>\n )}\n\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <span\n className={`bg-${frameColor === \"foreground\" ? \"background\" : \"foreground\"} flex size-16 items-center justify-center rounded-full shadow-[0_12px_32px_-8px_rgba(255,255,255,0.35)] transition-transform duration-300 group-hover:scale-[1.08] group-active:scale-95`}\n style={{\n animation: \"fluidVideoPopIn 400ms ease-out 120ms both\",\n }}\n >\n <PlayIcon size={22} filled color={frameVar} />\n </span>\n </div>\n\n {showFullscreenPill && (\n <div className=\"absolute top-1/2 right-6 -translate-y-1/2 opacity-0 transition-opacity duration-300 group-hover:opacity-100\">\n <div\n className=\"flex items-center gap-1.5 rounded-full px-3 py-1.5 text-[11px] font-bold shadow-lg\"\n style={{\n backgroundColor: \"rgba(255,255,255,0.95)\",\n color: frameVar,\n }}\n >\n <MaximizeIcon size={12} />\n Full screen\n </div>\n </div>\n )}\n\n <div className=\"absolute inset-x-0 top-0 z-10 flex items-center justify-between p-5 sm:p-6\">\n {(eyebrow || tag) && (\n <div className=\"flex items-center gap-2\">\n <span\n className=\"flex size-5 items-center justify-center rounded-full backdrop-blur-sm\"\n style={{\n backgroundColor: \"rgba(255,255,255,0.15)\",\n boxShadow: \"inset 0 0 0 1px rgba(255,255,255,0.2)\",\n }}\n >\n <PlayIcon size={10} filled color=\"#fff\" marginLeft={1} />\n </span>\n {tag && (\n <span\n className=\"rounded-full px-2.5 py-1 text-[10px] font-bold tracking-[0.24em] text-white uppercase backdrop-blur-sm\"\n style={{\n backgroundColor: \"rgba(255,255,255,0.15)\",\n boxShadow: \"inset 0 0 0 1px rgba(255,255,255,0.2)\",\n }}\n >\n {tag}\n </span>\n )}\n {eyebrow && (\n <span\n className=\"text-[10px] font-bold tracking-[0.24em] uppercase\"\n style={{ color: \"rgba(255,255,255,0.85)\" }}\n >\n {eyebrow}\n </span>\n )}\n </div>\n )}\n\n {duration && (\n <span\n className=\"flex items-center gap-1.5 rounded-full px-2.5 py-1 font-mono text-[10px] font-bold text-white tabular-nums backdrop-blur-sm\"\n style={{\n backgroundColor: \"rgba(255,255,255,0.1)\",\n boxShadow: \"inset 0 0 0 1px rgba(255,255,255,0.15)\",\n }}\n >\n <ClockIcon size={10} />\n {duration}\n </span>\n )}\n </div>\n\n {(title || tagline || author || date) && (\n <div className=\"absolute inset-x-0 bottom-0 z-10 flex flex-col p-5 sm:p-6\">\n {title && (\n <h3 className=\"text-[22px] leading-[1.18] font-bold tracking-[-0.015em] text-white sm:text-[24px]\">\n {title}\n </h3>\n )}\n {tagline && (\n <p\n className=\"mt-1.5 max-w-[520px] text-[12.5px] leading-[1.55]\"\n style={{ color: \"rgba(255,255,255,0.7)\" }}\n >\n {tagline}\n </p>\n )}\n {(author || date) && (\n <div\n className=\"mt-3 flex items-center gap-2 text-[10px] font-bold tracking-[0.16em] uppercase\"\n style={{ color: \"rgba(255,255,255,0.6)\" }}\n >\n {author && <span>{author}</span>}\n {author && date && (\n <span\n className=\"size-0.5 rounded-full\"\n style={{ backgroundColor: \"rgba(255,255,255,0.3)\" }}\n />\n )}\n {date && <span>{date}</span>}\n </div>\n )}\n </div>\n )}\n </div>\n </button>\n\n {modalOpen && (\n <VideoModal\n src={src}\n embed={embed}\n title={title}\n frameColor={frameColor}\n onClose={handleClose}\n primaryCtaText={primaryCtaText}\n primaryCtaLink={primaryCtaLink}\n secondaryCtaText={secondaryCtaText}\n secondaryCtaLink={secondaryCtaLink}\n />\n )}\n </>\n );\n}\n\ntype VideoModalProps = {\n src: string | undefined;\n embed: ParsedVideoSource;\n title: string | undefined;\n frameColor: ColorOptions;\n onClose: () => void;\n primaryCtaText: string | undefined;\n primaryCtaLink: string | undefined;\n secondaryCtaText: string | undefined;\n secondaryCtaLink: string | undefined;\n};\n\ntype VideoModalPlaybackState = {\n loading: boolean;\n loadFailed: boolean;\n mediaKey: number;\n reloadMedia: () => void;\n handleMediaLoaded: () => void;\n handleMediaError: () => void;\n};\n\nfunction useVideoModalPlaybackState({\n src,\n embedUrl,\n isMissingDirectVideo,\n}: {\n src: string | undefined;\n embedUrl: string | undefined;\n isMissingDirectVideo: boolean;\n}): VideoModalPlaybackState {\n const [loading, setLoading] = useState(!isMissingDirectVideo);\n const [loadFailed, setLoadFailed] = useState(isMissingDirectVideo);\n const [mediaKey, setMediaKey] = useState(0);\n\n const resetLoadState = useCallback(() => {\n setLoading(!isMissingDirectVideo);\n setLoadFailed(isMissingDirectVideo);\n }, [isMissingDirectVideo]);\n\n useEffect(() => {\n resetLoadState();\n }, [resetLoadState, src, embedUrl]);\n\n const reloadMedia = useCallback(() => {\n setMediaKey((key) => key + 1);\n resetLoadState();\n }, [resetLoadState]);\n\n const handleMediaLoaded = useCallback(() => {\n setLoading(false);\n }, []);\n\n const handleMediaError = useCallback(() => {\n setLoading(false);\n setLoadFailed(true);\n }, []);\n\n return {\n loading,\n loadFailed,\n mediaKey,\n reloadMedia,\n handleMediaLoaded,\n handleMediaError,\n };\n}\n\nfunction useVideoModalLifecycle(\n onClose: () => void,\n dialogRef: React.RefObject<HTMLDivElement | null>,\n): void {\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [onClose]);\n\n useEffect(() => {\n const { overflow } = document.body.style;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = overflow;\n };\n }, []);\n\n useEffect(() => {\n const previouslyFocused =\n document.activeElement instanceof HTMLElement\n ? document.activeElement\n : null;\n dialogRef.current?.focus();\n return () => {\n previouslyFocused?.focus();\n };\n }, [dialogRef]);\n}\n\nfunction VideoModal({\n src,\n embed,\n title,\n frameColor,\n onClose,\n primaryCtaText,\n primaryCtaLink,\n secondaryCtaText,\n secondaryCtaLink,\n}: VideoModalProps) {\n const directSrc = src?.trim();\n const isMissingDirectVideo = embed.source === \"direct\" && !directSrc;\n const dialogRef = useRef<HTMLDivElement>(null);\n const {\n loading,\n loadFailed,\n mediaKey,\n reloadMedia,\n handleMediaLoaded,\n handleMediaError,\n } = useVideoModalPlaybackState({\n src,\n embedUrl: embed.embedUrl,\n isMissingDirectVideo,\n });\n\n useVideoModalLifecycle(onClose, dialogRef);\n\n const frameVar = `var(--color-${frameColor})`;\n const backdropStyle: CSSProperties = {\n backgroundColor: `color-mix(in oklch, ${frameVar} 85%, transparent)`,\n backdropFilter: \"blur(12px)\",\n WebkitBackdropFilter: \"blur(12px)\",\n };\n\n const brandAccent = embed.accent ?? \"var(--color-primary)\";\n\n // Portal to document.body so the fixed-position dialog isn't clipped by\n // a transformed widget container on the live canvas (CSS transforms make\n // descendants the containing block for `position: fixed`).\n return createPortal(\n <div\n ref={dialogRef}\n tabIndex={-1}\n className=\"fixed inset-0 z-[9999] flex items-center justify-center p-4 focus:outline-none sm:p-8\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title ?? \"Video player\"}\n >\n <div\n className=\"absolute inset-0\"\n style={backdropStyle}\n onClick={onClose}\n aria-hidden=\"true\"\n />\n\n <div\n className={`bg-${frameColor} relative z-10 flex max-h-full w-full max-w-5xl flex-col overflow-hidden rounded-2xl shadow-[0_40px_80px_-20px_rgba(0,0,0,0.6)]`}\n >\n <div\n className=\"flex items-center justify-between gap-3 px-4 py-3\"\n style={{ borderBottom: \"1px solid rgba(255,255,255,0.1)\" }}\n >\n <div className=\"flex items-center gap-3\">\n {embed.source !== \"direct\" && (\n <span\n className=\"flex size-9 items-center justify-center rounded-full\"\n style={{\n background: embed.iconGradient ?? \"var(--color-primary)\",\n }}\n >\n <PlayIcon size={16} filled color=\"#fff\" marginLeft={2} />\n </span>\n )}\n {title && (\n <span className=\"line-clamp-1 text-[13px] font-bold text-white\">\n {title}\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-1\">\n <ToolbarButton label=\"Refresh\" onClick={reloadMedia}>\n <RefreshIcon size={14} />\n </ToolbarButton>\n {embed.watchUrl && (\n <ToolbarButton\n label=\"Open externally\"\n asLink\n href={embed.watchUrl}\n >\n <ExternalIcon size={14} />\n </ToolbarButton>\n )}\n <ToolbarButton label=\"Close\" onClick={onClose}>\n <CloseIcon size={14} />\n </ToolbarButton>\n </div>\n </div>\n\n <div className={`bg-${frameColor} relative w-full`}>\n <div className=\"relative aspect-video w-full\">\n {loading && (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <span\n className=\"size-8 animate-spin rounded-full border-2\"\n style={{\n borderColor: \"rgba(255,255,255,0.1)\",\n borderTopColor: brandAccent,\n }}\n />\n </div>\n )}\n\n {loadFailed ? (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <p\n className=\"text-sm\"\n style={{ color: \"rgba(255,255,255,0.7)\" }}\n >\n Unable to load video.\n </p>\n </div>\n ) : embed.source === \"direct\" ? (\n <video\n key={mediaKey}\n src={directSrc}\n controls\n autoPlay\n className=\"absolute inset-0 h-full w-full\"\n onLoadedData={handleMediaLoaded}\n onError={handleMediaError}\n >\n Your browser does not support the video tag.\n </video>\n ) : embed.embedUrl ? (\n <iframe\n key={mediaKey}\n src={embed.embedUrl}\n title={title ?? \"Video\"}\n className=\"absolute inset-0 h-full w-full border-0\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\"\n allowFullScreen\n onLoad={handleMediaLoaded}\n />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <p\n className=\"text-sm\"\n style={{ color: \"rgba(255,255,255,0.7)\" }}\n >\n Unable to load video.\n </p>\n </div>\n )}\n </div>\n </div>\n\n {((primaryCtaText && primaryCtaLink) ||\n (secondaryCtaText && secondaryCtaLink)) && (\n <div\n className=\"flex items-center justify-end gap-3 px-4 py-3\"\n style={{ borderTop: \"1px solid rgba(255,255,255,0.1)\" }}\n >\n {secondaryCtaText && secondaryCtaLink && (\n <a\n href={secondaryCtaLink}\n className=\"inline-flex items-center gap-1.5 rounded-full px-4 py-2 text-[12px] font-bold transition-colors\"\n style={{ color: \"rgba(255,255,255,0.75)\" }}\n >\n {secondaryCtaText}\n </a>\n )}\n {primaryCtaText && primaryCtaLink && (\n <a\n href={primaryCtaLink}\n className={`text-${frameColor} inline-flex items-center gap-1.5 rounded-full bg-white px-5 py-2 text-[13px] font-bold shadow-[0_8px_22px_-8px_rgba(255,255,255,0.4)] transition-transform hover:scale-[1.02]`}\n >\n {primaryCtaText}\n <span aria-hidden=\"true\">→</span>\n </a>\n )}\n </div>\n )}\n </div>\n </div>,\n document.body,\n );\n}\n\ntype ToolbarButtonProps = {\n label: string;\n onClick?: () => void;\n asLink?: boolean;\n href?: string;\n children: ReactNode;\n};\n\nfunction ToolbarButton({\n label,\n onClick,\n asLink,\n href,\n children,\n}: ToolbarButtonProps) {\n const className =\n \"flex size-9 items-center justify-center rounded-full transition-colors hover:text-white\";\n const style: CSSProperties = { color: \"rgba(255,255,255,0.7)\" };\n\n if (asLink && href) {\n return (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={label}\n className={className}\n style={style}\n >\n {children}\n </a>\n );\n }\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={label}\n className={className}\n style={style}\n >\n {children}\n </button>\n );\n}\n\ntype ParsedVideoSource = {\n source: \"youtube\" | \"vimeo\" | \"direct\";\n embedUrl?: string;\n watchUrl?: string;\n thumbnail?: string;\n thumbnailFallback?: string;\n accent?: string;\n iconGradient?: string;\n};\n\nfunction parseVideoSource(src: string | undefined): ParsedVideoSource {\n if (!src) return { source: \"direct\" };\n const url = src.trim();\n\n const youtubeId = extractYouTubeId(url);\n if (youtubeId) {\n // maxresdefault only exists for videos uploaded at >=720p; hqdefault\n // always exists. Try max first, fall back via the <img> onError handler.\n return {\n source: \"youtube\",\n embedUrl: `https://www.youtube.com/embed/${youtubeId}?autoplay=1&rel=0`,\n watchUrl: `https://www.youtube.com/watch?v=${youtubeId}`,\n thumbnail: `https://i.ytimg.com/vi/${youtubeId}/maxresdefault.jpg`,\n thumbnailFallback: `https://i.ytimg.com/vi/${youtubeId}/hqdefault.jpg`,\n accent: \"#FF0033\",\n iconGradient: \"linear-gradient(135deg, #FF0033 0%, #CC0022 100%)\",\n };\n }\n\n const vimeoId = extractVimeoId(url);\n if (vimeoId) {\n return {\n source: \"vimeo\",\n embedUrl: `https://player.vimeo.com/video/${vimeoId}?autoplay=1`,\n watchUrl: `https://vimeo.com/${vimeoId}`,\n accent: \"#1AB7EA\",\n iconGradient: \"linear-gradient(135deg, #1AB7EA 0%, #0D8BBA 100%)\",\n };\n }\n\n return { source: \"direct\" };\n}\n\nfunction extractYouTubeId(url: string): string | undefined {\n const normalizeId = (value: string | null | undefined) =>\n value && /^[a-zA-Z0-9_-]{11}$/.test(value) ? value : undefined;\n\n try {\n const parsed = new URL(url);\n const hostname = parsed.hostname.replace(/^www\\./, \"\").toLowerCase();\n const pathParts = parsed.pathname.split(\"/\").filter(Boolean);\n\n if (hostname === \"youtu.be\") {\n return normalizeId(pathParts[0]);\n }\n\n const isYouTubeHost =\n hostname === \"youtube.com\" ||\n hostname.endsWith(\".youtube.com\") ||\n hostname === \"youtube-nocookie.com\" ||\n hostname.endsWith(\".youtube-nocookie.com\");\n\n if (isYouTubeHost) {\n const watchId = normalizeId(parsed.searchParams.get(\"v\"));\n if (watchId) return watchId;\n\n if (\n (pathParts[0] === \"embed\" || pathParts[0] === \"shorts\") &&\n pathParts[1]\n ) {\n return normalizeId(pathParts[1]);\n }\n }\n } catch {\n // Fall back to regexes for protocol-less URLs and other loose input.\n }\n\n const patterns = [\n /youtube\\.com\\/watch.*[?&]v=([a-zA-Z0-9_-]{11})/,\n /youtu\\.be\\/([a-zA-Z0-9_-]{11})/,\n /youtube\\.com\\/embed\\/([a-zA-Z0-9_-]{11})/,\n /youtube\\.com\\/shorts\\/([a-zA-Z0-9_-]{11})/,\n ];\n for (const pattern of patterns) {\n const match = pattern.exec(url);\n const youtubeId = normalizeId(match?.[1]);\n if (youtubeId) return youtubeId;\n }\n return undefined;\n}\n\nfunction extractVimeoId(url: string): string | undefined {\n const patterns = [\n /vimeo\\.com\\/(?:video\\/)?(\\d{6,})/,\n /player\\.vimeo\\.com\\/video\\/(\\d{6,})/,\n ];\n for (const pattern of patterns) {\n const match = pattern.exec(url);\n if (match?.[1]) return match[1];\n }\n return undefined;\n}\n\ntype IconProps = {\n size: number;\n color?: string;\n filled?: boolean;\n marginLeft?: number;\n};\n\nfunction PlayIcon({ size, color, filled, marginLeft }: IconProps) {\n const style: CSSProperties = {};\n if (color) style.color = color;\n if (marginLeft) style.marginLeft = `${marginLeft}px`;\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill={filled ? \"currentColor\" : \"none\"}\n stroke=\"currentColor\"\n strokeWidth={filled ? 0 : 2.5}\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n style={style}\n >\n <path d=\"M8 5v14l11-7z\" />\n </svg>\n );\n}\n\nfunction ClockIcon({ size }: { size: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2.5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <polyline points=\"12 6 12 12 16 14\" />\n </svg>\n );\n}\n\nfunction MaximizeIcon({ size }: { size: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2.5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"15 3 21 3 21 9\" />\n <polyline points=\"9 21 3 21 3 15\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n );\n}\n\nfunction RefreshIcon({ size }: { size: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"23 4 23 10 17 10\" />\n <polyline points=\"1 20 1 14 7 14\" />\n <path d=\"M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15\" />\n </svg>\n );\n}\n\nfunction ExternalIcon({ size }: { size: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n <polyline points=\"15 3 21 3 21 9\" />\n <line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\n </svg>\n );\n}\n\nfunction CloseIcon({ size }: { size: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2.5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n );\n}\n\nexport const videoWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"VideoWidget\",\n displayName: \"Video\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"behavior\", label: \"Behavior\" },\n ],\n fields: [\n // Content group\n {\n key: \"resource\",\n label: \"Select Video\",\n type: \"resource\",\n description: \"Browse and select a video\",\n allowedTypes: [\"Medium\"],\n tab: \"styling\",\n group: \"Content\",\n },\n {\n key: \"useCustomUrl\",\n label: \"Use Custom URL\",\n type: \"boolean\",\n description: \"Enter a custom video URL instead of selecting media.\",\n defaultValue: false,\n tab: \"styling\",\n group: \"Content\",\n },\n {\n key: \"src\",\n label: \"Video URL\",\n type: \"text\",\n description:\n \"Direct video URL for inline mode. Card mode supports YouTube, Vimeo, and direct video URLs.\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Content\",\n requiresKeyToBeTrue: \"useCustomUrl\",\n },\n {\n key: \"poster\",\n label: \"Poster Image URL\",\n type: \"text\",\n description:\n \"Thumbnail shown before play. Card mode can auto-derive YouTube thumbnails; add a poster for Vimeo URLs.\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Content\",\n requiresKeyToBeTrue: \"useCustomUrl\",\n },\n\n // Display Mode group (new)\n {\n key: \"displayMode\",\n label: \"Display Mode\",\n type: \"buttonGroup\",\n description:\n \"Inline: native player embedded in the page. Card: premium thumbnail that opens a modal.\",\n options: [\n { label: \"Inline\", value: \"inline\" },\n { label: \"Card\", value: \"card\" },\n ],\n defaultValue: \"inline\",\n tab: \"styling\",\n group: \"Display Mode\",\n },\n\n // Card metadata group\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"Headline on the card thumbnail (card mode only).\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Card Content\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"tagline\",\n label: \"Tagline\",\n type: \"textarea\",\n description: \"Short body line under the title.\",\n defaultValue: \"\",\n rows: 2,\n tab: \"styling\",\n group: \"Card Content\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"eyebrow\",\n label: \"Eyebrow\",\n type: \"text\",\n description:\n \"Small label above the card (e.g. 'Training · Fluid Academy').\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Card Content\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"tag\",\n label: \"Tag\",\n type: \"text\",\n description: \"Optional pill label.\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Card Content\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"duration\",\n label: \"Duration\",\n type: \"text\",\n description: \"Runtime (e.g. '4:52' or '1:09:30'). Shown as a chip.\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Card Content\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"author\",\n label: \"Author / Instructor\",\n type: \"text\",\n description: \"Meta line author.\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Card Content\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"date\",\n label: \"Date\",\n type: \"text\",\n description: \"Meta line date (e.g. 'Apr 12').\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Card Content\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n\n // Card frame group\n {\n key: \"editorialFrame\",\n label: \"Editorial Frame\",\n type: \"boolean\",\n description:\n \"Premium dark canvas with layered shadow and dual gradient overlays.\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Card Frame\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n getColorField({\n defaultValue: \"foreground\",\n key: \"frameColor\",\n label: \"Frame Color\",\n description: \"Surface color for the card and modal.\",\n tab: \"styling\",\n group: \"Card Frame\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n }),\n {\n key: \"showFullscreenPill\",\n label: \"Show Fullscreen Pill\",\n type: \"boolean\",\n description: \"Show the 'Full screen' hover hint on the card.\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Card Frame\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n\n // Card modal CTAs group\n {\n key: \"primaryCtaText\",\n label: \"Primary CTA Text\",\n type: \"text\",\n description: \"Primary button in the modal footer (optional).\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Modal CTAs\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"primaryCtaLink\",\n label: \"Primary CTA Link\",\n type: \"text\",\n description: \"URL for the primary CTA.\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Modal CTAs\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"secondaryCtaText\",\n label: \"Secondary CTA Text\",\n type: \"text\",\n description: \"Secondary (ghost) button in the modal footer (optional).\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Modal CTAs\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"secondaryCtaLink\",\n label: \"Secondary CTA Link\",\n type: \"text\",\n description: \"URL for the secondary CTA.\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Modal CTAs\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n\n // Inline design group (existing)\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the video container\",\n defaultValue: \"md\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget\",\n defaultValue: \"none\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the widget\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"verticalSizing\",\n label: \"Vertical Sizing\",\n type: \"buttonGroup\",\n description: \"How the video height is determined (inline mode only)\",\n options: [\n { label: \"Auto\", value: \"auto\" },\n { label: \"Fixed\", value: \"fixed\" },\n ],\n defaultValue: \"auto\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyValue: { key: \"displayMode\", value: \"inline\" },\n },\n getHeightField({\n key: \"fixedHeight\",\n label: \"Height\",\n description: \"Fixed height of the video container\",\n defaultValue: \"200px\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyValue: { key: \"verticalSizing\", value: \"fixed\" },\n }),\n {\n key: \"displayFit\",\n label: \"Display Fit\",\n type: \"buttonGroup\",\n description: \"How the video fills its container\",\n options: [\n { label: \"Cover\", value: \"cover\" },\n { label: \"Contain\", value: \"contain\" },\n ],\n defaultValue: \"cover\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyValue: { key: \"verticalSizing\", value: \"fixed\" },\n },\n {\n key: \"focusPoint\",\n label: \"Focus Point\",\n type: \"contentPosition\",\n description: \"The focal point of the video within its container\",\n defaultValue: \"center\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyValue: { key: \"verticalSizing\", value: \"fixed\" },\n },\n\n // Behavior tab (inline only)\n {\n key: \"controls\",\n label: \"Show Controls\",\n type: \"boolean\",\n description:\n \"Display video playback controls (inline mode only — card mode always shows controls in the modal).\",\n defaultValue: true,\n tab: \"behavior\",\n group: \"Behavior\",\n requiresKeyValue: { key: \"displayMode\", value: \"inline\" },\n },\n {\n key: \"autoplay\",\n label: \"Autoplay\",\n type: \"boolean\",\n description: \"Automatically start playing the video\",\n defaultValue: false,\n tab: \"behavior\",\n group: \"Behavior\",\n requiresKeyValue: { key: \"displayMode\", value: \"inline\" },\n },\n {\n key: \"loop\",\n label: \"Loop\",\n type: \"boolean\",\n description: \"Repeat the video when it ends\",\n defaultValue: false,\n tab: \"behavior\",\n group: \"Behavior\",\n requiresKeyValue: { key: \"displayMode\", value: \"inline\" },\n },\n {\n key: \"muted\",\n label: \"Muted\",\n type: \"boolean\",\n description: \"Start with audio muted\",\n defaultValue: true,\n tab: \"behavior\",\n group: \"Behavior\",\n requiresKeyValue: { key: \"displayMode\", value: \"inline\" },\n },\n ],\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"VideoWidget-lTyeZypJ.mjs","names":[],"sources":["../../widgets/src/widgets/VideoWidget.tsx"],"sourcesContent":["import type { ComponentProps, CSSProperties, ReactNode } from \"react\";\nimport type React from \"react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n borderColorClasses,\n borderWidthClasses,\n getBorderColorField,\n getBorderRadiusField,\n getBorderWidthField,\n getColorField,\n getHeightField,\n type WidgetPropertySchema,\n} from \"@fluid-app/portal-core/registries\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n ShareableItem,\n} from \"@fluid-app/portal-core/types\";\nimport { MediaRenderer } from \"../components/MediaRenderer\";\n\ntype VideoWidgetProps = ComponentProps<\"div\"> & {\n // Content\n src?: string;\n poster?: string;\n resource?: ShareableItem;\n useCustomUrl?: boolean;\n\n // Display\n displayMode?: \"inline\" | \"card\";\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n verticalSizing?: \"auto\" | \"fixed\";\n fixedHeight?: string;\n displayFit?: \"cover\" | \"contain\";\n focusPoint?: string;\n\n // Native video behavior (inline mode)\n controls?: boolean;\n autoplay?: boolean;\n loop?: boolean;\n muted?: boolean;\n\n // Card mode — editorial frame + metadata\n editorialFrame?: boolean;\n frameColor?: ColorOptions;\n eyebrow?: string;\n tag?: string;\n title?: string;\n tagline?: string;\n duration?: string;\n author?: string;\n date?: string;\n showFullscreenPill?: boolean;\n\n // Card mode — modal CTAs\n primaryCtaText?: string;\n primaryCtaLink?: string;\n secondaryCtaText?: string;\n secondaryCtaLink?: string;\n};\n\nexport function VideoWidget({\n src = \"\",\n poster = \"\",\n resource,\n useCustomUrl,\n\n displayMode = \"inline\",\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n verticalSizing = \"auto\",\n fixedHeight = \"200px\",\n displayFit = \"cover\",\n focusPoint,\n\n controls = true,\n autoplay = false,\n loop = false,\n muted = true,\n\n editorialFrame = true,\n frameColor = \"foreground\",\n eyebrow,\n tag,\n title,\n tagline,\n duration,\n author,\n date,\n showFullscreenPill = true,\n\n primaryCtaText,\n primaryCtaLink,\n secondaryCtaText,\n secondaryCtaLink,\n}: VideoWidgetProps): React.JSX.Element {\n const effectiveSrc = useCustomUrl ? src : (resource?.videoUrl ?? src);\n const effectivePoster = useCustomUrl\n ? poster\n : (resource?.imageUrl ?? poster ?? undefined);\n\n if (displayMode === \"card\") {\n const resolvedTitle =\n typeof title === \"string\" && title.trim()\n ? title\n : (resource?.title ?? undefined);\n const resourceDescription =\n typeof resource?.description === \"string\"\n ? resource.description\n : undefined;\n const resolvedTagline =\n typeof tagline === \"string\" && tagline.trim()\n ? tagline\n : resourceDescription;\n\n return (\n <VideoCard\n src={effectiveSrc}\n poster={effectivePoster ?? undefined}\n borderRadius={borderRadius}\n editorialFrame={editorialFrame}\n frameColor={frameColor}\n eyebrow={eyebrow}\n tag={tag}\n title={resolvedTitle}\n tagline={resolvedTagline}\n duration={duration}\n author={author}\n date={date}\n showFullscreenPill={showFullscreenPill}\n primaryCtaText={primaryCtaText}\n primaryCtaLink={primaryCtaLink}\n secondaryCtaText={secondaryCtaText}\n secondaryCtaLink={secondaryCtaLink}\n />\n );\n }\n\n const isFixed = verticalSizing === \"fixed\";\n const borderWidthClass = borderWidthClasses[borderWidth];\n const borderColorClass =\n borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\";\n\n return (\n <div\n className={`relative w-full overflow-hidden rounded-${borderRadius} ${borderWidthClass} ${borderColorClass}`}\n style={isFixed ? { height: fixedHeight } : undefined}\n >\n <MediaRenderer\n mediaType=\"video\"\n src={effectiveSrc}\n poster={effectivePoster}\n objectFit={isFixed ? displayFit : undefined}\n focusPoint={isFixed ? focusPoint : undefined}\n controls={controls}\n autoplay={autoplay}\n loop={loop}\n muted={muted}\n />\n </div>\n );\n}\n\ntype VideoCardProps = {\n src: string | undefined;\n poster: string | undefined;\n borderRadius: BorderRadiusOptions;\n editorialFrame: boolean;\n frameColor: ColorOptions;\n eyebrow: string | undefined;\n tag: string | undefined;\n title: string | undefined;\n tagline: string | undefined;\n duration: string | undefined;\n author: string | undefined;\n date: string | undefined;\n showFullscreenPill: boolean;\n primaryCtaText: string | undefined;\n primaryCtaLink: string | undefined;\n secondaryCtaText: string | undefined;\n secondaryCtaLink: string | undefined;\n};\n\nfunction useVideoPosterFallback(\n poster: string | undefined,\n embed: ParsedVideoSource,\n) {\n const resolvedPoster = poster || embed.thumbnail || \"\";\n const [posterSrc, setPosterSrc] = useState(resolvedPoster);\n\n useEffect(() => {\n setPosterSrc(resolvedPoster);\n }, [resolvedPoster]);\n\n const handlePosterError = useCallback(() => {\n if (embed.thumbnailFallback && posterSrc !== embed.thumbnailFallback) {\n setPosterSrc(embed.thumbnailFallback);\n }\n }, [embed.thumbnailFallback, posterSrc]);\n\n return { posterSrc, handlePosterError };\n}\n\nfunction VideoCard({\n src,\n poster,\n borderRadius,\n editorialFrame,\n frameColor,\n eyebrow,\n tag,\n title,\n tagline,\n duration,\n author,\n date,\n showFullscreenPill,\n primaryCtaText,\n primaryCtaLink,\n secondaryCtaText,\n secondaryCtaLink,\n}: VideoCardProps) {\n const [modalOpen, setModalOpen] = useState(false);\n const handleClose = useCallback(() => setModalOpen(false), []);\n\n const embed = parseVideoSource(src);\n const { posterSrc, handlePosterError } = useVideoPosterFallback(\n poster,\n embed,\n );\n\n const frameVar = `var(--color-${frameColor})`;\n const frameShadow = editorialFrame\n ? \"shadow-[0_1px_2px_rgba(15,23,42,0.04),0_30px_60px_-30px_rgba(15,23,42,0.4)]\"\n : \"\";\n const frameBg = editorialFrame ? `bg-${frameColor}` : \"\";\n\n const gradientTop: CSSProperties = {\n background: `linear-gradient(to top, ${frameVar}, color-mix(in oklch, ${frameVar} 55%, transparent), color-mix(in oklch, ${frameVar} 8%, transparent))`,\n };\n const gradientLeft: CSSProperties = {\n background: `linear-gradient(to right, color-mix(in oklch, ${frameVar} 70%, transparent), transparent)`,\n };\n\n return (\n <>\n <button\n type=\"button\"\n onClick={() => setModalOpen(true)}\n aria-label={title ? `Play video: ${title}` : \"Play video\"}\n className={`group relative block w-full overflow-hidden rounded-${borderRadius} ${frameBg} ${frameShadow} focus-visible:ring-primary text-left focus:outline-none focus-visible:ring-2`}\n >\n <div className=\"relative aspect-[16/9] w-full\">\n {posterSrc ? (\n <img\n src={posterSrc}\n alt={title ?? \"Video thumbnail\"}\n className=\"absolute inset-0 h-full w-full object-cover transition-transform duration-[700ms] group-hover:scale-[1.03]\"\n onError={handlePosterError}\n />\n ) : (\n <div className=\"bg-muted/30 absolute inset-0 flex items-center justify-center\">\n <PlayIcon size={40} filled />\n </div>\n )}\n\n {editorialFrame && (\n <>\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={gradientTop}\n />\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={gradientLeft}\n />\n </>\n )}\n\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <span\n className={`bg-${frameColor === \"foreground\" ? \"background\" : \"foreground\"} flex size-16 items-center justify-center rounded-full shadow-[0_12px_32px_-8px_rgba(255,255,255,0.35)] transition-transform duration-300 group-hover:scale-[1.08] group-active:scale-95`}\n style={{\n animation: \"fluidVideoPopIn 400ms ease-out 120ms both\",\n }}\n >\n <PlayIcon size={22} filled color={frameVar} />\n </span>\n </div>\n\n {showFullscreenPill && (\n <div className=\"absolute top-1/2 right-6 -translate-y-1/2 opacity-0 transition-opacity duration-300 group-hover:opacity-100\">\n <div\n className=\"flex items-center gap-1.5 rounded-full px-3 py-1.5 text-[11px] font-bold shadow-lg\"\n style={{\n backgroundColor: \"rgba(255,255,255,0.95)\",\n color: frameVar,\n }}\n >\n <MaximizeIcon size={12} />\n Full screen\n </div>\n </div>\n )}\n\n <div className=\"absolute inset-x-0 top-0 z-10 flex items-center justify-between p-5 sm:p-6\">\n {(eyebrow || tag) && (\n <div className=\"flex items-center gap-2\">\n <span\n className=\"flex size-5 items-center justify-center rounded-full backdrop-blur-sm\"\n style={{\n backgroundColor: \"rgba(255,255,255,0.15)\",\n boxShadow: \"inset 0 0 0 1px rgba(255,255,255,0.2)\",\n }}\n >\n <PlayIcon size={10} filled color=\"#fff\" marginLeft={1} />\n </span>\n {tag && (\n <span\n className=\"rounded-full px-2.5 py-1 text-[10px] font-bold tracking-[0.24em] text-white uppercase backdrop-blur-sm\"\n style={{\n backgroundColor: \"rgba(255,255,255,0.15)\",\n boxShadow: \"inset 0 0 0 1px rgba(255,255,255,0.2)\",\n }}\n >\n {tag}\n </span>\n )}\n {eyebrow && (\n <span\n className=\"text-[10px] font-bold tracking-[0.24em] uppercase\"\n style={{ color: \"rgba(255,255,255,0.85)\" }}\n >\n {eyebrow}\n </span>\n )}\n </div>\n )}\n\n {duration && (\n <span\n className=\"flex items-center gap-1.5 rounded-full px-2.5 py-1 font-mono text-[10px] font-bold text-white tabular-nums backdrop-blur-sm\"\n style={{\n backgroundColor: \"rgba(255,255,255,0.1)\",\n boxShadow: \"inset 0 0 0 1px rgba(255,255,255,0.15)\",\n }}\n >\n <ClockIcon size={10} />\n {duration}\n </span>\n )}\n </div>\n\n {(title || tagline || author || date) && (\n <div className=\"absolute inset-x-0 bottom-0 z-10 flex flex-col p-5 sm:p-6\">\n {title && (\n <h3 className=\"text-[22px] leading-[1.18] font-bold tracking-[-0.015em] text-white sm:text-[24px]\">\n {title}\n </h3>\n )}\n {tagline && (\n <p\n className=\"mt-1.5 max-w-[520px] text-[12.5px] leading-[1.55]\"\n style={{ color: \"rgba(255,255,255,0.7)\" }}\n >\n {tagline}\n </p>\n )}\n {(author || date) && (\n <div\n className=\"mt-3 flex items-center gap-2 text-[10px] font-bold tracking-[0.16em] uppercase\"\n style={{ color: \"rgba(255,255,255,0.6)\" }}\n >\n {author && <span>{author}</span>}\n {author && date && (\n <span\n className=\"size-0.5 rounded-full\"\n style={{ backgroundColor: \"rgba(255,255,255,0.3)\" }}\n />\n )}\n {date && <span>{date}</span>}\n </div>\n )}\n </div>\n )}\n </div>\n </button>\n\n {modalOpen && (\n <VideoModal\n src={src}\n embed={embed}\n title={title}\n frameColor={frameColor}\n onClose={handleClose}\n primaryCtaText={primaryCtaText}\n primaryCtaLink={primaryCtaLink}\n secondaryCtaText={secondaryCtaText}\n secondaryCtaLink={secondaryCtaLink}\n />\n )}\n </>\n );\n}\n\ntype VideoModalProps = {\n src: string | undefined;\n embed: ParsedVideoSource;\n title: string | undefined;\n frameColor: ColorOptions;\n onClose: () => void;\n primaryCtaText: string | undefined;\n primaryCtaLink: string | undefined;\n secondaryCtaText: string | undefined;\n secondaryCtaLink: string | undefined;\n};\n\ntype VideoModalPlaybackState = {\n loading: boolean;\n loadFailed: boolean;\n mediaKey: number;\n reloadMedia: () => void;\n handleMediaLoaded: () => void;\n handleMediaError: () => void;\n};\n\nfunction useVideoModalPlaybackState({\n src,\n embedUrl,\n isMissingDirectVideo,\n}: {\n src: string | undefined;\n embedUrl: string | undefined;\n isMissingDirectVideo: boolean;\n}): VideoModalPlaybackState {\n const [loading, setLoading] = useState(!isMissingDirectVideo);\n const [loadFailed, setLoadFailed] = useState(isMissingDirectVideo);\n const [mediaKey, setMediaKey] = useState(0);\n\n const resetLoadState = useCallback(() => {\n setLoading(!isMissingDirectVideo);\n setLoadFailed(isMissingDirectVideo);\n }, [isMissingDirectVideo]);\n\n useEffect(() => {\n resetLoadState();\n }, [resetLoadState, src, embedUrl]);\n\n const reloadMedia = useCallback(() => {\n setMediaKey((key) => key + 1);\n resetLoadState();\n }, [resetLoadState]);\n\n const handleMediaLoaded = useCallback(() => {\n setLoading(false);\n }, []);\n\n const handleMediaError = useCallback(() => {\n setLoading(false);\n setLoadFailed(true);\n }, []);\n\n return {\n loading,\n loadFailed,\n mediaKey,\n reloadMedia,\n handleMediaLoaded,\n handleMediaError,\n };\n}\n\nfunction useVideoModalLifecycle(\n onClose: () => void,\n dialogRef: React.RefObject<HTMLDivElement | null>,\n): void {\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [onClose]);\n\n useEffect(() => {\n const { overflow } = document.body.style;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = overflow;\n };\n }, []);\n\n useEffect(() => {\n const previouslyFocused =\n document.activeElement instanceof HTMLElement\n ? document.activeElement\n : null;\n dialogRef.current?.focus();\n return () => {\n previouslyFocused?.focus();\n };\n }, [dialogRef]);\n}\n\nfunction VideoModal({\n src,\n embed,\n title,\n frameColor,\n onClose,\n primaryCtaText,\n primaryCtaLink,\n secondaryCtaText,\n secondaryCtaLink,\n}: VideoModalProps) {\n const directSrc = src?.trim();\n const isMissingDirectVideo = embed.source === \"direct\" && !directSrc;\n const dialogRef = useRef<HTMLDivElement>(null);\n const {\n loading,\n loadFailed,\n mediaKey,\n reloadMedia,\n handleMediaLoaded,\n handleMediaError,\n } = useVideoModalPlaybackState({\n src,\n embedUrl: embed.embedUrl,\n isMissingDirectVideo,\n });\n\n useVideoModalLifecycle(onClose, dialogRef);\n\n const frameVar = `var(--color-${frameColor})`;\n const backdropStyle: CSSProperties = {\n backgroundColor: `color-mix(in oklch, ${frameVar} 85%, transparent)`,\n backdropFilter: \"blur(12px)\",\n WebkitBackdropFilter: \"blur(12px)\",\n };\n\n const brandAccent = embed.accent ?? \"var(--color-primary)\";\n\n // Portal to document.body so the fixed-position dialog isn't clipped by\n // a transformed widget container on the live canvas (CSS transforms make\n // descendants the containing block for `position: fixed`).\n return createPortal(\n <div\n ref={dialogRef}\n tabIndex={-1}\n className=\"fixed inset-0 z-[9999] flex items-center justify-center p-4 focus:outline-none sm:p-8\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title ?? \"Video player\"}\n >\n <div\n className=\"absolute inset-0\"\n style={backdropStyle}\n onClick={onClose}\n aria-hidden=\"true\"\n />\n\n <div\n className={`bg-${frameColor} relative z-10 flex max-h-full w-full max-w-5xl flex-col overflow-hidden rounded-2xl shadow-[0_40px_80px_-20px_rgba(0,0,0,0.6)]`}\n >\n <div\n className=\"flex items-center justify-between gap-3 px-4 py-3\"\n style={{ borderBottom: \"1px solid rgba(255,255,255,0.1)\" }}\n >\n <div className=\"flex items-center gap-3\">\n {embed.source !== \"direct\" && (\n <span\n className=\"flex size-9 items-center justify-center rounded-full\"\n style={{\n background: embed.iconGradient ?? \"var(--color-primary)\",\n }}\n >\n <PlayIcon size={16} filled color=\"#fff\" marginLeft={2} />\n </span>\n )}\n {title && (\n <span className=\"line-clamp-1 text-[13px] font-bold text-white\">\n {title}\n </span>\n )}\n </div>\n <div className=\"flex items-center gap-1\">\n <ToolbarButton label=\"Refresh\" onClick={reloadMedia}>\n <RefreshIcon size={14} />\n </ToolbarButton>\n {embed.watchUrl && (\n <ToolbarButton\n label=\"Open externally\"\n asLink\n href={embed.watchUrl}\n >\n <ExternalIcon size={14} />\n </ToolbarButton>\n )}\n <ToolbarButton label=\"Close\" onClick={onClose}>\n <CloseIcon size={14} />\n </ToolbarButton>\n </div>\n </div>\n\n <div className={`bg-${frameColor} relative w-full`}>\n <div className=\"relative aspect-video w-full\">\n {loading && (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <span\n className=\"size-8 animate-spin rounded-full border-2\"\n style={{\n borderColor: \"rgba(255,255,255,0.1)\",\n borderTopColor: brandAccent,\n }}\n />\n </div>\n )}\n\n {loadFailed ? (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <p\n className=\"text-sm\"\n style={{ color: \"rgba(255,255,255,0.7)\" }}\n >\n Unable to load video.\n </p>\n </div>\n ) : embed.source === \"direct\" ? (\n <video\n key={mediaKey}\n src={directSrc}\n controls\n autoPlay\n className=\"absolute inset-0 h-full w-full\"\n onLoadedData={handleMediaLoaded}\n onError={handleMediaError}\n >\n Your browser does not support the video tag.\n </video>\n ) : embed.embedUrl ? (\n <iframe\n key={mediaKey}\n src={embed.embedUrl}\n title={title ?? \"Video\"}\n className=\"absolute inset-0 h-full w-full border-0\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\"\n allowFullScreen\n onLoad={handleMediaLoaded}\n />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <p\n className=\"text-sm\"\n style={{ color: \"rgba(255,255,255,0.7)\" }}\n >\n Unable to load video.\n </p>\n </div>\n )}\n </div>\n </div>\n\n {((primaryCtaText && primaryCtaLink) ||\n (secondaryCtaText && secondaryCtaLink)) && (\n <div\n className=\"flex items-center justify-end gap-3 px-4 py-3\"\n style={{ borderTop: \"1px solid rgba(255,255,255,0.1)\" }}\n >\n {secondaryCtaText && secondaryCtaLink && (\n <a\n href={secondaryCtaLink}\n className=\"inline-flex items-center gap-1.5 rounded-full px-4 py-2 text-[12px] font-bold transition-colors\"\n style={{ color: \"rgba(255,255,255,0.75)\" }}\n >\n {secondaryCtaText}\n </a>\n )}\n {primaryCtaText && primaryCtaLink && (\n <a\n href={primaryCtaLink}\n className={`text-${frameColor} inline-flex items-center gap-1.5 rounded-full bg-white px-5 py-2 text-[13px] font-bold shadow-[0_8px_22px_-8px_rgba(255,255,255,0.4)] transition-transform hover:scale-[1.02]`}\n >\n {primaryCtaText}\n <span aria-hidden=\"true\">→</span>\n </a>\n )}\n </div>\n )}\n </div>\n </div>,\n document.body,\n );\n}\n\ntype ToolbarButtonProps = {\n label: string;\n onClick?: () => void;\n asLink?: boolean;\n href?: string;\n children: ReactNode;\n};\n\nfunction ToolbarButton({\n label,\n onClick,\n asLink,\n href,\n children,\n}: ToolbarButtonProps) {\n const className =\n \"flex size-9 items-center justify-center rounded-full transition-colors hover:text-white\";\n const style: CSSProperties = { color: \"rgba(255,255,255,0.7)\" };\n\n if (asLink && href) {\n return (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={label}\n className={className}\n style={style}\n >\n {children}\n </a>\n );\n }\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={label}\n className={className}\n style={style}\n >\n {children}\n </button>\n );\n}\n\ntype ParsedVideoSource = {\n source: \"youtube\" | \"vimeo\" | \"direct\";\n embedUrl?: string;\n watchUrl?: string;\n thumbnail?: string;\n thumbnailFallback?: string;\n accent?: string;\n iconGradient?: string;\n};\n\nfunction parseVideoSource(src: string | undefined): ParsedVideoSource {\n if (!src) return { source: \"direct\" };\n const url = src.trim();\n\n const youtubeId = extractYouTubeId(url);\n if (youtubeId) {\n // maxresdefault only exists for videos uploaded at >=720p; hqdefault\n // always exists. Try max first, fall back via the <img> onError handler.\n return {\n source: \"youtube\",\n embedUrl: `https://www.youtube.com/embed/${youtubeId}?autoplay=1&rel=0`,\n watchUrl: `https://www.youtube.com/watch?v=${youtubeId}`,\n thumbnail: `https://i.ytimg.com/vi/${youtubeId}/maxresdefault.jpg`,\n thumbnailFallback: `https://i.ytimg.com/vi/${youtubeId}/hqdefault.jpg`,\n accent: \"#FF0033\",\n iconGradient: \"linear-gradient(135deg, #FF0033 0%, #CC0022 100%)\",\n };\n }\n\n const vimeoId = extractVimeoId(url);\n if (vimeoId) {\n return {\n source: \"vimeo\",\n embedUrl: `https://player.vimeo.com/video/${vimeoId}?autoplay=1`,\n watchUrl: `https://vimeo.com/${vimeoId}`,\n accent: \"#1AB7EA\",\n iconGradient: \"linear-gradient(135deg, #1AB7EA 0%, #0D8BBA 100%)\",\n };\n }\n\n return { source: \"direct\" };\n}\n\nfunction extractYouTubeId(url: string): string | undefined {\n const normalizeId = (value: string | null | undefined) =>\n value && /^[a-zA-Z0-9_-]{11}$/.test(value) ? value : undefined;\n\n try {\n const parsed = new URL(url);\n const hostname = parsed.hostname.replace(/^www\\./, \"\").toLowerCase();\n const pathParts = parsed.pathname.split(\"/\").filter(Boolean);\n\n if (hostname === \"youtu.be\") {\n return normalizeId(pathParts[0]);\n }\n\n const isYouTubeHost =\n hostname === \"youtube.com\" ||\n hostname.endsWith(\".youtube.com\") ||\n hostname === \"youtube-nocookie.com\" ||\n hostname.endsWith(\".youtube-nocookie.com\");\n\n if (isYouTubeHost) {\n const watchId = normalizeId(parsed.searchParams.get(\"v\"));\n if (watchId) return watchId;\n\n if (\n (pathParts[0] === \"embed\" || pathParts[0] === \"shorts\") &&\n pathParts[1]\n ) {\n return normalizeId(pathParts[1]);\n }\n }\n } catch {\n // Fall back to regexes for protocol-less URLs and other loose input.\n }\n\n const patterns = [\n /youtube\\.com\\/watch.*[?&]v=([a-zA-Z0-9_-]{11})/,\n /youtu\\.be\\/([a-zA-Z0-9_-]{11})/,\n /youtube\\.com\\/embed\\/([a-zA-Z0-9_-]{11})/,\n /youtube\\.com\\/shorts\\/([a-zA-Z0-9_-]{11})/,\n ];\n for (const pattern of patterns) {\n const match = pattern.exec(url);\n const youtubeId = normalizeId(match?.[1]);\n if (youtubeId) return youtubeId;\n }\n return undefined;\n}\n\nfunction extractVimeoId(url: string): string | undefined {\n const patterns = [\n /vimeo\\.com\\/(?:video\\/)?(\\d{6,})/,\n /player\\.vimeo\\.com\\/video\\/(\\d{6,})/,\n ];\n for (const pattern of patterns) {\n const match = pattern.exec(url);\n if (match?.[1]) return match[1];\n }\n return undefined;\n}\n\ntype IconProps = {\n size: number;\n color?: string;\n filled?: boolean;\n marginLeft?: number;\n};\n\nfunction PlayIcon({ size, color, filled, marginLeft }: IconProps) {\n const style: CSSProperties = {};\n if (color) style.color = color;\n if (marginLeft) style.marginLeft = `${marginLeft}px`;\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill={filled ? \"currentColor\" : \"none\"}\n stroke=\"currentColor\"\n strokeWidth={filled ? 0 : 2.5}\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n style={style}\n >\n <path d=\"M8 5v14l11-7z\" />\n </svg>\n );\n}\n\nfunction ClockIcon({ size }: { size: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2.5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <polyline points=\"12 6 12 12 16 14\" />\n </svg>\n );\n}\n\nfunction MaximizeIcon({ size }: { size: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2.5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"15 3 21 3 21 9\" />\n <polyline points=\"9 21 3 21 3 15\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n );\n}\n\nfunction RefreshIcon({ size }: { size: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"23 4 23 10 17 10\" />\n <polyline points=\"1 20 1 14 7 14\" />\n <path d=\"M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15\" />\n </svg>\n );\n}\n\nfunction ExternalIcon({ size }: { size: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n <polyline points=\"15 3 21 3 21 9\" />\n <line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\n </svg>\n );\n}\n\nfunction CloseIcon({ size }: { size: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2.5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n );\n}\n\nexport const videoWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"VideoWidget\",\n displayName: \"Video\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"behavior\", label: \"Behavior\" },\n ],\n fields: [\n // Content group\n {\n key: \"resource\",\n label: \"Select Video\",\n type: \"resource\",\n description: \"Browse and select a video\",\n allowedTypes: [\"Medium\"],\n tab: \"styling\",\n group: \"Content\",\n },\n {\n key: \"useCustomUrl\",\n label: \"Use Custom URL\",\n type: \"boolean\",\n description: \"Enter a custom video URL instead of selecting media.\",\n defaultValue: false,\n tab: \"styling\",\n group: \"Content\",\n },\n {\n key: \"src\",\n label: \"Video URL\",\n type: \"text\",\n description:\n \"Direct video URL for inline mode. Card mode supports YouTube, Vimeo, and direct video URLs.\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Content\",\n requiresKeyToBeTrue: \"useCustomUrl\",\n },\n {\n key: \"poster\",\n label: \"Poster Image URL\",\n type: \"text\",\n description:\n \"Thumbnail shown before play. Card mode can auto-derive YouTube thumbnails; add a poster for Vimeo URLs.\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Content\",\n requiresKeyToBeTrue: \"useCustomUrl\",\n },\n\n // Display Mode group (new)\n {\n key: \"displayMode\",\n label: \"Display Mode\",\n type: \"buttonGroup\",\n description:\n \"Inline: native player embedded in the page. Card: premium thumbnail that opens a modal.\",\n options: [\n { label: \"Inline\", value: \"inline\" },\n { label: \"Card\", value: \"card\" },\n ],\n defaultValue: \"inline\",\n tab: \"styling\",\n group: \"Display Mode\",\n },\n\n // Card metadata group\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"Headline on the card thumbnail (card mode only).\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Card Content\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"tagline\",\n label: \"Tagline\",\n type: \"textarea\",\n description: \"Short body line under the title.\",\n defaultValue: \"\",\n rows: 2,\n tab: \"styling\",\n group: \"Card Content\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"eyebrow\",\n label: \"Eyebrow\",\n type: \"text\",\n description:\n \"Small label above the card (e.g. 'Training · Fluid Academy').\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Card Content\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"tag\",\n label: \"Tag\",\n type: \"text\",\n description: \"Optional pill label.\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Card Content\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"duration\",\n label: \"Duration\",\n type: \"text\",\n description: \"Runtime (e.g. '4:52' or '1:09:30'). Shown as a chip.\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Card Content\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"author\",\n label: \"Author / Instructor\",\n type: \"text\",\n description: \"Meta line author.\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Card Content\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"date\",\n label: \"Date\",\n type: \"text\",\n description: \"Meta line date (e.g. 'Apr 12').\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Card Content\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n\n // Card frame group\n {\n key: \"editorialFrame\",\n label: \"Editorial Frame\",\n type: \"boolean\",\n description:\n \"Premium dark canvas with layered shadow and dual gradient overlays.\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Card Frame\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n getColorField({\n defaultValue: \"foreground\",\n key: \"frameColor\",\n label: \"Frame Color\",\n description: \"Surface color for the card and modal.\",\n tab: \"styling\",\n group: \"Card Frame\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n }),\n {\n key: \"showFullscreenPill\",\n label: \"Show Fullscreen Pill\",\n type: \"boolean\",\n description: \"Show the 'Full screen' hover hint on the card.\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Card Frame\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n\n // Card modal CTAs group\n {\n key: \"primaryCtaText\",\n label: \"Primary CTA Text\",\n type: \"text\",\n description: \"Primary button in the modal footer (optional).\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Modal CTAs\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"primaryCtaLink\",\n label: \"Primary CTA Link\",\n type: \"text\",\n description: \"URL for the primary CTA.\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Modal CTAs\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"secondaryCtaText\",\n label: \"Secondary CTA Text\",\n type: \"text\",\n description: \"Secondary (ghost) button in the modal footer (optional).\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Modal CTAs\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n {\n key: \"secondaryCtaLink\",\n label: \"Secondary CTA Link\",\n type: \"text\",\n description: \"URL for the secondary CTA.\",\n defaultValue: \"\",\n tab: \"styling\",\n group: \"Modal CTAs\",\n requiresKeyValue: { key: \"displayMode\", value: \"card\" },\n },\n\n // Inline design group (existing)\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the video container\",\n defaultValue: \"md\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget\",\n defaultValue: \"none\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the widget\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"verticalSizing\",\n label: \"Vertical Sizing\",\n type: \"buttonGroup\",\n description: \"How the video height is determined (inline mode only)\",\n options: [\n { label: \"Auto\", value: \"auto\" },\n { label: \"Fixed\", value: \"fixed\" },\n ],\n defaultValue: \"auto\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyValue: { key: \"displayMode\", value: \"inline\" },\n },\n getHeightField({\n key: \"fixedHeight\",\n label: \"Height\",\n description: \"Fixed height of the video container\",\n defaultValue: \"200px\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyValue: { key: \"verticalSizing\", value: \"fixed\" },\n }),\n {\n key: \"displayFit\",\n label: \"Display Fit\",\n type: \"buttonGroup\",\n description: \"How the video fills its container\",\n options: [\n { label: \"Cover\", value: \"cover\" },\n { label: \"Contain\", value: \"contain\" },\n ],\n defaultValue: \"cover\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyValue: { key: \"verticalSizing\", value: \"fixed\" },\n },\n {\n key: \"focusPoint\",\n label: \"Focus Point\",\n type: \"contentPosition\",\n description: \"The focal point of the video within its container\",\n defaultValue: \"center\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyValue: { key: \"verticalSizing\", value: \"fixed\" },\n },\n\n // Behavior tab (inline only)\n {\n key: \"controls\",\n label: \"Show Controls\",\n type: \"boolean\",\n description:\n \"Display video playback controls (inline mode only — card mode always shows controls in the modal).\",\n defaultValue: true,\n tab: \"behavior\",\n group: \"Behavior\",\n requiresKeyValue: { key: \"displayMode\", value: \"inline\" },\n },\n {\n key: \"autoplay\",\n label: \"Autoplay\",\n type: \"boolean\",\n description: \"Automatically start playing the video\",\n defaultValue: false,\n tab: \"behavior\",\n group: \"Behavior\",\n requiresKeyValue: { key: \"displayMode\", value: \"inline\" },\n },\n {\n key: \"loop\",\n label: \"Loop\",\n type: \"boolean\",\n description: \"Repeat the video when it ends\",\n defaultValue: false,\n tab: \"behavior\",\n group: \"Behavior\",\n requiresKeyValue: { key: \"displayMode\", value: \"inline\" },\n },\n {\n key: \"muted\",\n label: \"Muted\",\n type: \"boolean\",\n description: \"Start with audio muted\",\n defaultValue: true,\n tab: \"behavior\",\n group: \"Behavior\",\n requiresKeyValue: { key: \"displayMode\", value: \"inline\" },\n },\n ],\n};\n"],"mappings":";;;;;;;;;;;AAgEA,SAAgB,YAAY,EAC1B,MAAM,IACN,SAAS,IACT,UACA,cAEA,cAAc,UACd,eAAe,MACf,cAAc,QACd,cAAc,SACd,iBAAiB,QACjB,cAAc,SACd,aAAa,SACb,YAEA,WAAW,MACX,WAAW,OACX,OAAO,OACP,QAAQ,MAER,iBAAiB,MACjB,aAAa,cACb,SACA,KACA,OACA,SACA,UACA,QACA,MACA,qBAAqB,MAErB,gBACA,gBACA,kBACA,oBACsC;CACtC,MAAM,eAAe,eAAe,MAAO,UAAU,YAAY;CACjE,MAAM,kBAAkB,eACpB,SACC,UAAU,YAAY,UAAU,KAAA;AAErC,KAAI,gBAAgB,QAAQ;EAC1B,MAAM,gBACJ,OAAO,UAAU,YAAY,MAAM,MAAM,GACrC,QACC,UAAU,SAAS,KAAA;EAC1B,MAAM,sBACJ,OAAO,UAAU,gBAAgB,WAC7B,SAAS,cACT,KAAA;EACN,MAAM,kBACJ,OAAO,YAAY,YAAY,QAAQ,MAAM,GACzC,UACA;AAEN,SACE,oBAAC,WAAD;GACE,KAAK;GACL,QAAQ,mBAAmB,KAAA;GACb;GACE;GACJ;GACH;GACJ;GACL,OAAO;GACP,SAAS;GACC;GACF;GACF;GACc;GACJ;GACA;GACE;GACA;GAClB,CAAA;;CAIN,MAAM,UAAU,mBAAmB;CACnC,MAAM,mBAAmB,mBAAmB;AAI5C,QACE,oBAAC,OAAD;EACE,WAAW,2CAA2C,aAAa,GAAG,iBAAiB,GAJzF,gBAAgB,SAAS,mBAAmB,eAAe;EAKzD,OAAO,UAAU,EAAE,QAAQ,aAAa,GAAG,KAAA;YAE3C,oBAAC,eAAD;GACE,WAAU;GACV,KAAK;GACL,QAAQ;GACR,WAAW,UAAU,aAAa,KAAA;GAClC,YAAY,UAAU,aAAa,KAAA;GACzB;GACA;GACJ;GACC;GACP,CAAA;EACE,CAAA;;AAwBV,SAAS,uBACP,QACA,OACA;CACA,MAAM,iBAAiB,UAAU,MAAM,aAAa;CACpD,MAAM,CAAC,WAAW,gBAAgB,SAAS,eAAe;AAE1D,iBAAgB;AACd,eAAa,eAAe;IAC3B,CAAC,eAAe,CAAC;AAQpB,QAAO;EAAE;EAAW,mBANM,kBAAkB;AAC1C,OAAI,MAAM,qBAAqB,cAAc,MAAM,kBACjD,cAAa,MAAM,kBAAkB;KAEtC,CAAC,MAAM,mBAAmB,UAAU,CAAC;EAED;;AAGzC,SAAS,UAAU,EACjB,KACA,QACA,cACA,gBACA,YACA,SACA,KACA,OACA,SACA,UACA,QACA,MACA,oBACA,gBACA,gBACA,kBACA,oBACiB;CACjB,MAAM,CAAC,WAAW,gBAAgB,SAAS,MAAM;CACjD,MAAM,cAAc,kBAAkB,aAAa,MAAM,EAAE,EAAE,CAAC;CAE9D,MAAM,QAAQ,iBAAiB,IAAI;CACnC,MAAM,EAAE,WAAW,sBAAsB,uBACvC,QACA,MACD;CAED,MAAM,WAAW,eAAe,WAAW;CAC3C,MAAM,cAAc,iBAChB,gFACA;CACJ,MAAM,UAAU,iBAAiB,MAAM,eAAe;CAEtD,MAAM,cAA6B,EACjC,YAAY,2BAA2B,SAAS,wBAAwB,SAAS,0CAA0C,SAAS,qBACrI;CACD,MAAM,eAA8B,EAClC,YAAY,iDAAiD,SAAS,mCACvE;AAED,QACE,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,UAAD;EACE,MAAK;EACL,eAAe,aAAa,KAAK;EACjC,cAAY,QAAQ,eAAe,UAAU;EAC7C,WAAW,uDAAuD,aAAa,GAAG,QAAQ,GAAG,YAAY;YAEzG,qBAAC,OAAD;GAAK,WAAU;aAAf;IACG,YACC,oBAAC,OAAD;KACE,KAAK;KACL,KAAK,SAAS;KACd,WAAU;KACV,SAAS;KACT,CAAA,GAEF,oBAAC,OAAD;KAAK,WAAU;eACb,oBAAC,UAAD;MAAU,MAAM;MAAI,QAAA;MAAS,CAAA;KACzB,CAAA;IAGP,kBACC,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,OAAD;KACE,WAAU;KACV,OAAO;KACP,CAAA,EACF,oBAAC,OAAD;KACE,WAAU;KACV,OAAO;KACP,CAAA,CACD,EAAA,CAAA;IAGL,oBAAC,OAAD;KAAK,WAAU;eACb,oBAAC,QAAD;MACE,WAAW,MAAM,eAAe,eAAe,eAAe,aAAa;MAC3E,OAAO,EACL,WAAW,6CACZ;gBAED,oBAAC,UAAD;OAAU,MAAM;OAAI,QAAA;OAAO,OAAO;OAAY,CAAA;MACzC,CAAA;KACH,CAAA;IAEL,sBACC,oBAAC,OAAD;KAAK,WAAU;eACb,qBAAC,OAAD;MACE,WAAU;MACV,OAAO;OACL,iBAAiB;OACjB,OAAO;OACR;gBALH,CAOE,oBAAC,cAAD,EAAc,MAAM,IAAM,CAAA,EAAA,cAEtB;;KACF,CAAA;IAGR,qBAAC,OAAD;KAAK,WAAU;eAAf,EACI,WAAW,QACX,qBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,oBAAC,QAAD;QACE,WAAU;QACV,OAAO;SACL,iBAAiB;SACjB,WAAW;SACZ;kBAED,oBAAC,UAAD;SAAU,MAAM;SAAI,QAAA;SAAO,OAAM;SAAO,YAAY;SAAK,CAAA;QACpD,CAAA;OACN,OACC,oBAAC,QAAD;QACE,WAAU;QACV,OAAO;SACL,iBAAiB;SACjB,WAAW;SACZ;kBAEA;QACI,CAAA;OAER,WACC,oBAAC,QAAD;QACE,WAAU;QACV,OAAO,EAAE,OAAO,0BAA0B;kBAEzC;QACI,CAAA;OAEL;SAGP,YACC,qBAAC,QAAD;MACE,WAAU;MACV,OAAO;OACL,iBAAiB;OACjB,WAAW;OACZ;gBALH,CAOE,oBAAC,WAAD,EAAW,MAAM,IAAM,CAAA,EACtB,SACI;QAEL;;KAEJ,SAAS,WAAW,UAAU,SAC9B,qBAAC,OAAD;KAAK,WAAU;eAAf;MACG,SACC,oBAAC,MAAD;OAAI,WAAU;iBACX;OACE,CAAA;MAEN,WACC,oBAAC,KAAD;OACE,WAAU;OACV,OAAO,EAAE,OAAO,yBAAyB;iBAExC;OACC,CAAA;OAEJ,UAAU,SACV,qBAAC,OAAD;OACE,WAAU;OACV,OAAO,EAAE,OAAO,yBAAyB;iBAF3C;QAIG,UAAU,oBAAC,QAAD,EAAA,UAAO,QAAc,CAAA;QAC/B,UAAU,QACT,oBAAC,QAAD;SACE,WAAU;SACV,OAAO,EAAE,iBAAiB,yBAAyB;SACnD,CAAA;QAEH,QAAQ,oBAAC,QAAD,EAAA,UAAO,MAAY,CAAA;QACxB;;MAEJ;;IAEJ;;EACC,CAAA,EAER,aACC,oBAAC,YAAD;EACO;EACE;EACA;EACK;EACZ,SAAS;EACO;EACA;EACE;EACA;EAClB,CAAA,CAEH,EAAA,CAAA;;AAyBP,SAAS,2BAA2B,EAClC,KACA,UACA,wBAK0B;CAC1B,MAAM,CAAC,SAAS,cAAc,SAAS,CAAC,qBAAqB;CAC7D,MAAM,CAAC,YAAY,iBAAiB,SAAS,qBAAqB;CAClE,MAAM,CAAC,UAAU,eAAe,SAAS,EAAE;CAE3C,MAAM,iBAAiB,kBAAkB;AACvC,aAAW,CAAC,qBAAqB;AACjC,gBAAc,qBAAqB;IAClC,CAAC,qBAAqB,CAAC;AAE1B,iBAAgB;AACd,kBAAgB;IACf;EAAC;EAAgB;EAAK;EAAS,CAAC;AAgBnC,QAAO;EACL;EACA;EACA;EACA,aAlBkB,kBAAkB;AACpC,gBAAa,QAAQ,MAAM,EAAE;AAC7B,mBAAgB;KACf,CAAC,eAAe,CAAC;EAgBlB,mBAdwB,kBAAkB;AAC1C,cAAW,MAAM;KAChB,EAAE,CAAC;EAaJ,kBAXuB,kBAAkB;AACzC,cAAW,MAAM;AACjB,iBAAc,KAAK;KAClB,EAAE,CAAC;EASL;;AAGH,SAAS,uBACP,SACA,WACM;AACN,iBAAgB;EACd,MAAM,WAAW,MAAqB;AACpC,OAAI,EAAE,QAAQ,SAAU,UAAS;;AAEnC,SAAO,iBAAiB,WAAW,QAAQ;AAC3C,eAAa,OAAO,oBAAoB,WAAW,QAAQ;IAC1D,CAAC,QAAQ,CAAC;AAEb,iBAAgB;EACd,MAAM,EAAE,aAAa,SAAS,KAAK;AACnC,WAAS,KAAK,MAAM,WAAW;AAC/B,eAAa;AACX,YAAS,KAAK,MAAM,WAAW;;IAEhC,EAAE,CAAC;AAEN,iBAAgB;EACd,MAAM,oBACJ,SAAS,yBAAyB,cAC9B,SAAS,gBACT;AACN,YAAU,SAAS,OAAO;AAC1B,eAAa;AACX,sBAAmB,OAAO;;IAE3B,CAAC,UAAU,CAAC;;AAGjB,SAAS,WAAW,EAClB,KACA,OACA,OACA,YACA,SACA,gBACA,gBACA,kBACA,oBACkB;CAClB,MAAM,YAAY,KAAK,MAAM;CAC7B,MAAM,uBAAuB,MAAM,WAAW,YAAY,CAAC;CAC3D,MAAM,YAAY,OAAuB,KAAK;CAC9C,MAAM,EACJ,SACA,YACA,UACA,aACA,mBACA,qBACE,2BAA2B;EAC7B;EACA,UAAU,MAAM;EAChB;EACD,CAAC;AAEF,wBAAuB,SAAS,UAAU;CAG1C,MAAM,gBAA+B;EACnC,iBAAiB,uBAFF,eAAe,WAAW,GAEQ;EACjD,gBAAgB;EAChB,sBAAsB;EACvB;CAED,MAAM,cAAc,MAAM,UAAU;AAKpC,QAAO,aACL,qBAAC,OAAD;EACE,KAAK;EACL,UAAU;EACV,WAAU;EACV,MAAK;EACL,cAAW;EACX,cAAY,SAAS;YANvB,CAQE,oBAAC,OAAD;GACE,WAAU;GACV,OAAO;GACP,SAAS;GACT,eAAY;GACZ,CAAA,EAEF,qBAAC,OAAD;GACE,WAAW,MAAM,WAAW;aAD9B;IAGE,qBAAC,OAAD;KACE,WAAU;KACV,OAAO,EAAE,cAAc,mCAAmC;eAF5D,CAIE,qBAAC,OAAD;MAAK,WAAU;gBAAf,CACG,MAAM,WAAW,YAChB,oBAAC,QAAD;OACE,WAAU;OACV,OAAO,EACL,YAAY,MAAM,gBAAgB,wBACnC;iBAED,oBAAC,UAAD;QAAU,MAAM;QAAI,QAAA;QAAO,OAAM;QAAO,YAAY;QAAK,CAAA;OACpD,CAAA,EAER,SACC,oBAAC,QAAD;OAAM,WAAU;iBACb;OACI,CAAA,CAEL;SACN,qBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,oBAAC,eAAD;QAAe,OAAM;QAAU,SAAS;kBACtC,oBAAC,aAAD,EAAa,MAAM,IAAM,CAAA;QACX,CAAA;OACf,MAAM,YACL,oBAAC,eAAD;QACE,OAAM;QACN,QAAA;QACA,MAAM,MAAM;kBAEZ,oBAAC,cAAD,EAAc,MAAM,IAAM,CAAA;QACZ,CAAA;OAElB,oBAAC,eAAD;QAAe,OAAM;QAAQ,SAAS;kBACpC,oBAAC,WAAD,EAAW,MAAM,IAAM,CAAA;QACT,CAAA;OACZ;QACF;;IAEN,oBAAC,OAAD;KAAK,WAAW,MAAM,WAAW;eAC/B,qBAAC,OAAD;MAAK,WAAU;gBAAf,CACG,WACC,oBAAC,OAAD;OAAK,WAAU;iBACb,oBAAC,QAAD;QACE,WAAU;QACV,OAAO;SACL,aAAa;SACb,gBAAgB;SACjB;QACD,CAAA;OACE,CAAA,EAGP,aACC,oBAAC,OAAD;OAAK,WAAU;iBACb,oBAAC,KAAD;QACE,WAAU;QACV,OAAO,EAAE,OAAO,yBAAyB;kBAC1C;QAEG,CAAA;OACA,CAAA,GACJ,MAAM,WAAW,WACnB,oBAAC,SAAD;OAEE,KAAK;OACL,UAAA;OACA,UAAA;OACA,WAAU;OACV,cAAc;OACd,SAAS;iBACV;OAEO,EATD,SASC,GACN,MAAM,WACR,oBAAC,UAAD;OAEE,KAAK,MAAM;OACX,OAAO,SAAS;OAChB,WAAU;OACV,OAAM;OACN,iBAAA;OACA,QAAQ;OACR,EAPK,SAOL,GAEF,oBAAC,OAAD;OAAK,WAAU;iBACb,oBAAC,KAAD;QACE,WAAU;QACV,OAAO,EAAE,OAAO,yBAAyB;kBAC1C;QAEG,CAAA;OACA,CAAA,CAEJ;;KACF,CAAA;KAEH,kBAAkB,kBAClB,oBAAoB,qBACrB,qBAAC,OAAD;KACE,WAAU;KACV,OAAO,EAAE,WAAW,mCAAmC;eAFzD,CAIG,oBAAoB,oBACnB,oBAAC,KAAD;MACE,MAAM;MACN,WAAU;MACV,OAAO,EAAE,OAAO,0BAA0B;gBAEzC;MACC,CAAA,EAEL,kBAAkB,kBACjB,qBAAC,KAAD;MACE,MAAM;MACN,WAAW,QAAQ,WAAW;gBAFhC,CAIG,gBACD,oBAAC,QAAD;OAAM,eAAY;iBAAO;OAAQ,CAAA,CAC/B;QAEF;;IAEJ;KACF;KACN,SAAS,KACV;;AAWH,SAAS,cAAc,EACrB,OACA,SACA,QACA,MACA,YACqB;CACrB,MAAM,YACJ;CACF,MAAM,QAAuB,EAAE,OAAO,yBAAyB;AAE/D,KAAI,UAAU,KACZ,QACE,oBAAC,KAAD;EACQ;EACN,QAAO;EACP,KAAI;EACJ,cAAY;EACD;EACJ;EAEN;EACC,CAAA;AAIR,QACE,oBAAC,UAAD;EACE,MAAK;EACI;EACT,cAAY;EACD;EACJ;EAEN;EACM,CAAA;;AAcb,SAAS,iBAAiB,KAA4C;AACpE,KAAI,CAAC,IAAK,QAAO,EAAE,QAAQ,UAAU;CACrC,MAAM,MAAM,IAAI,MAAM;CAEtB,MAAM,YAAY,iBAAiB,IAAI;AACvC,KAAI,UAGF,QAAO;EACL,QAAQ;EACR,UAAU,iCAAiC,UAAU;EACrD,UAAU,mCAAmC;EAC7C,WAAW,0BAA0B,UAAU;EAC/C,mBAAmB,0BAA0B,UAAU;EACvD,QAAQ;EACR,cAAc;EACf;CAGH,MAAM,UAAU,eAAe,IAAI;AACnC,KAAI,QACF,QAAO;EACL,QAAQ;EACR,UAAU,kCAAkC,QAAQ;EACpD,UAAU,qBAAqB;EAC/B,QAAQ;EACR,cAAc;EACf;AAGH,QAAO,EAAE,QAAQ,UAAU;;AAG7B,SAAS,iBAAiB,KAAiC;CACzD,MAAM,eAAe,UACnB,SAAS,sBAAsB,KAAK,MAAM,GAAG,QAAQ,KAAA;AAEvD,KAAI;EACF,MAAM,SAAS,IAAI,IAAI,IAAI;EAC3B,MAAM,WAAW,OAAO,SAAS,QAAQ,UAAU,GAAG,CAAC,aAAa;EACpE,MAAM,YAAY,OAAO,SAAS,MAAM,IAAI,CAAC,OAAO,QAAQ;AAE5D,MAAI,aAAa,WACf,QAAO,YAAY,UAAU,GAAG;AASlC,MALE,aAAa,iBACb,SAAS,SAAS,eAAe,IACjC,aAAa,0BACb,SAAS,SAAS,wBAAwB,EAEzB;GACjB,MAAM,UAAU,YAAY,OAAO,aAAa,IAAI,IAAI,CAAC;AACzD,OAAI,QAAS,QAAO;AAEpB,QACG,UAAU,OAAO,WAAW,UAAU,OAAO,aAC9C,UAAU,GAEV,QAAO,YAAY,UAAU,GAAG;;SAG9B;AAUR,MAAK,MAAM,WANM;EACf;EACA;EACA;EACA;EACD,EAC+B;EAE9B,MAAM,YAAY,YADJ,QAAQ,KAAK,IAAI,GACO,GAAG;AACzC,MAAI,UAAW,QAAO;;;AAK1B,SAAS,eAAe,KAAiC;AAKvD,MAAK,MAAM,WAJM,CACf,oCACA,sCACD,EAC+B;EAC9B,MAAM,QAAQ,QAAQ,KAAK,IAAI;AAC/B,MAAI,QAAQ,GAAI,QAAO,MAAM;;;AAYjC,SAAS,SAAS,EAAE,MAAM,OAAO,QAAQ,cAAyB;CAChE,MAAM,QAAuB,EAAE;AAC/B,KAAI,MAAO,OAAM,QAAQ;AACzB,KAAI,WAAY,OAAM,aAAa,GAAG,WAAW;AACjD,QACE,oBAAC,OAAD;EACE,OAAO;EACP,QAAQ;EACR,SAAQ;EACR,MAAM,SAAS,iBAAiB;EAChC,QAAO;EACP,aAAa,SAAS,IAAI;EAC1B,gBAAe;EACf,eAAY;EACL;YAEP,oBAAC,QAAD,EAAM,GAAE,iBAAkB,CAAA;EACtB,CAAA;;AAIV,SAAS,UAAU,EAAE,QAA0B;AAC7C,QACE,qBAAC,OAAD;EACE,OAAO;EACP,QAAQ;EACR,SAAQ;EACR,MAAK;EACL,QAAO;EACP,aAAa;EACb,eAAc;EACd,gBAAe;EACf,eAAY;YATd,CAWE,oBAAC,UAAD;GAAQ,IAAG;GAAK,IAAG;GAAK,GAAE;GAAO,CAAA,EACjC,oBAAC,YAAD,EAAU,QAAO,oBAAqB,CAAA,CAClC;;;AAIV,SAAS,aAAa,EAAE,QAA0B;AAChD,QACE,qBAAC,OAAD;EACE,OAAO;EACP,QAAQ;EACR,SAAQ;EACR,MAAK;EACL,QAAO;EACP,aAAa;EACb,eAAc;EACd,gBAAe;EACf,eAAY;YATd;GAWE,oBAAC,YAAD,EAAU,QAAO,kBAAmB,CAAA;GACpC,oBAAC,YAAD,EAAU,QAAO,kBAAmB,CAAA;GACpC,oBAAC,QAAD;IAAM,IAAG;IAAK,IAAG;IAAI,IAAG;IAAK,IAAG;IAAO,CAAA;GACvC,oBAAC,QAAD;IAAM,IAAG;IAAI,IAAG;IAAK,IAAG;IAAK,IAAG;IAAO,CAAA;GACnC;;;AAIV,SAAS,YAAY,EAAE,QAA0B;AAC/C,QACE,qBAAC,OAAD;EACE,OAAO;EACP,QAAQ;EACR,SAAQ;EACR,MAAK;EACL,QAAO;EACP,aAAa;EACb,eAAc;EACd,gBAAe;EACf,eAAY;YATd;GAWE,oBAAC,YAAD,EAAU,QAAO,oBAAqB,CAAA;GACtC,oBAAC,YAAD,EAAU,QAAO,kBAAmB,CAAA;GACpC,oBAAC,QAAD,EAAM,GAAE,wEAAyE,CAAA;GAC7E;;;AAIV,SAAS,aAAa,EAAE,QAA0B;AAChD,QACE,qBAAC,OAAD;EACE,OAAO;EACP,QAAQ;EACR,SAAQ;EACR,MAAK;EACL,QAAO;EACP,aAAa;EACb,eAAc;EACd,gBAAe;EACf,eAAY;YATd;GAWE,oBAAC,QAAD,EAAM,GAAE,4DAA6D,CAAA;GACrE,oBAAC,YAAD,EAAU,QAAO,kBAAmB,CAAA;GACpC,oBAAC,QAAD;IAAM,IAAG;IAAK,IAAG;IAAK,IAAG;IAAK,IAAG;IAAM,CAAA;GACnC;;;AAIV,SAAS,UAAU,EAAE,QAA0B;AAC7C,QACE,qBAAC,OAAD;EACE,OAAO;EACP,QAAQ;EACR,SAAQ;EACR,MAAK;EACL,QAAO;EACP,aAAa;EACb,eAAc;EACd,gBAAe;EACf,eAAY;YATd,CAWE,oBAAC,QAAD;GAAM,IAAG;GAAK,IAAG;GAAI,IAAG;GAAI,IAAG;GAAO,CAAA,EACtC,oBAAC,QAAD;GAAM,IAAG;GAAI,IAAG;GAAI,IAAG;GAAK,IAAG;GAAO,CAAA,CAClC;;;AAIV,MAAa,4BAAkD;CAC7D,YAAY;CACZ,aAAa;CACb,YAAY,CACV;EAAE,IAAI;EAAW,OAAO;EAAW,EACnC;EAAE,IAAI;EAAY,OAAO;EAAY,CACtC;CACD,QAAQ;EAEN;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc,CAAC,SAAS;GACxB,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EAGD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,SAAS,CACP;IAAE,OAAO;IAAU,OAAO;IAAU,EACpC;IAAE,OAAO;IAAQ,OAAO;IAAQ,CACjC;GACD,cAAc;GACd,KAAK;GACL,OAAO;GACR;EAGD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAQ;GACxD;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAQ;GACxD;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAQ;GACxD;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAQ;GACxD;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAQ;GACxD;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAQ;GACxD;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAQ;GACxD;EAGD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAQ;GACxD;EACD,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAQ;GACxD,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAQ;GACxD;EAGD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAQ;GACxD;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAQ;GACxD;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAQ;GACxD;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAQ;GACxD;EAGD,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,SAAS,CACP;IAAE,OAAO;IAAQ,OAAO;IAAQ,EAChC;IAAE,OAAO;IAAS,OAAO;IAAS,CACnC;GACD,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAU;GAC1D;EACD,eAAe;GACb,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAkB,OAAO;IAAS;GAC5D,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,SAAS,CACP;IAAE,OAAO;IAAS,OAAO;IAAS,EAClC;IAAE,OAAO;IAAW,OAAO;IAAW,CACvC;GACD,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAkB,OAAO;IAAS;GAC5D;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAkB,OAAO;IAAS;GAC5D;EAGD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAU;GAC1D;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAU;GAC1D;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAU;GAC1D;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAe,OAAO;IAAU;GAC1D;EACF;CACF"}
|