tempest-react-sdk 0.54.0 → 0.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tempest-react-sdk.cjs +1 -1
- package/dist/tempest-react-sdk.d.ts +247 -0
- package/dist/tempest-react-sdk.js +31 -29
- package/dist/webrtc/mesh-quality.cjs +2 -0
- package/dist/webrtc/mesh-quality.cjs.map +1 -0
- package/dist/webrtc/mesh-quality.js +51 -0
- package/dist/webrtc/mesh-quality.js.map +1 -0
- package/dist/webrtc/peer-link.cjs +2 -0
- package/dist/webrtc/peer-link.cjs.map +1 -0
- package/dist/webrtc/peer-link.js +45 -0
- package/dist/webrtc/peer-link.js.map +1 -0
- package/dist/webrtc/peer-mesh.cjs +2 -0
- package/dist/webrtc/peer-mesh.cjs.map +1 -0
- package/dist/webrtc/peer-mesh.js +155 -0
- package/dist/webrtc/peer-mesh.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});/* empty css */const ee=require("./utils/cn.cjs"),te=require("./components/Accordion/Accordion.cjs"),ne=require("./components/Alert/Alert.cjs"),re=require("./components/AppBar/AppBar.cjs"),e=require("./hooks/use-breakpoint.cjs"),ie=require("./components/AppShell/AppShell.cjs"),ae=require("./components/AspectRatio/AspectRatio.cjs"),oe=require("./components/Avatar/Avatar.cjs"),se=require("./components/AvatarGroup/AvatarGroup.cjs"),ce=require("./components/Badge/Badge.cjs"),le=require("./components/Banner/Banner.cjs"),ue=require("./components/BottomNavigation/BottomNavigation.cjs"),de=require("./components/BottomSheet/BottomSheet.cjs"),fe=require("./components/Breadcrumbs/Breadcrumbs.cjs"),pe=require("./components/Button/Button.cjs"),me=require("./components/Card/Card.cjs"),he=require("./components/Center/Center.cjs"),ge=require("./components/Checkbox/Checkbox.cjs"),_e=require("./components/ChipInput/ChipInput.cjs"),ve=require("./components/Combobox/Combobox.cjs"),ye=require("./components/Modal/Modal.cjs"),be=require("./components/ConfirmDialog/ConfirmDialog.cjs"),xe=require("./components/Input/Input.cjs"),Se=require("./components/DatePicker/DatePicker.cjs"),Ce=require("./components/Divider/Divider.cjs"),we=require("./components/Drawer/Drawer.cjs"),Te=require("./components/DropdownMenu/DropdownMenu.cjs"),Ee=require("./components/Dropzone/Dropzone.cjs"),De=require("./components/EmptyState/EmptyState.cjs"),Oe=require("./components/ErrorState/ErrorState.cjs"),ke=require("./components/FileUpload/FileUpload.cjs"),t=require("./components/Form/Form.cjs"),n=require("./components/Layout/Layout.cjs"),Ae=require("./hooks/use-before-install-prompt.cjs"),je=require("./components/InstallBanner/InstallBanner.cjs"),Me=require("./components/InstallButton/InstallButton.cjs"),Ne=require("./hooks/use-debounce.cjs"),Pe=require("./hooks/use-pagination.cjs"),Fe=require("./hooks/use-client-filter.cjs"),Ie=require("./hooks/use-media-query.cjs"),Le=require("./hooks/use-latest-ref.cjs"),Re=require("./hooks/use-event-listener.cjs"),ze=require("./hooks/use-local-storage.cjs"),Be=require("./hooks/use-toggle.cjs"),Ve=require("./hooks/use-async.cjs"),He=require("./hooks/use-online.cjs"),Ue=require("./hooks/use-document-visibility.cjs"),We=require("./hooks/use-intersection-observer.cjs"),Ge=require("./hooks/use-resize-observer.cjs"),Ke=require("./hooks/use-clipboard.cjs"),qe=require("./hooks/use-keyboard-shortcut.cjs"),Je=require("./hooks/use-idle.cjs"),Ye=require("./hooks/use-fullscreen.cjs"),r=require("./hooks/use-push-to-talk.cjs"),Xe=require("./hooks/use-geolocation.cjs"),Ze=require("./hooks/use-scroll-lock.cjs"),Qe=require("./hooks/use-focus-trap.cjs"),i=require("./hooks/use-announce.cjs"),$e=require("./hooks/use-stable-callback.cjs"),et=require("./hooks/use-deep-memo.cjs"),tt=require("./hooks/use-previous.cjs"),nt=require("./hooks/use-interval.cjs"),rt=require("./hooks/use-timeout.cjs"),it=require("./hooks/use-throttle.cjs"),at=require("./hooks/use-window-size.cjs"),ot=require("./hooks/use-hover.cjs"),st=require("./hooks/use-long-press.cjs"),ct=require("./hooks/use-disclosure.cjs"),lt=require("./hooks/use-list-state.cjs"),ut=require("./hooks/use-counter.cjs"),dt=require("./hooks/use-countdown.cjs"),ft=require("./hooks/use-typewriter.cjs"),pt=require("./hooks/use-document-title.cjs"),mt=require("./hooks/use-favicon.cjs"),ht=require("./hooks/use-map.cjs"),gt=require("./hooks/use-set.cjs"),_t=require("./hooks/use-queue.cjs"),vt=require("./hooks/use-click-outside.cjs"),yt=require("./hooks/use-is-first-render.cjs"),bt=require("./hooks/use-object-url.cjs"),xt=require("./hooks/use-long-press-handlers.cjs"),a=require("./hooks/pwa-env.cjs"),St=require("./hooks/use-install-prompt.cjs"),o=require("./sw/register-service-worker.cjs"),Ct=require("./hooks/use-service-worker-update.cjs"),s=require("./hooks/use-storage-estimate.cjs"),c=require("./hooks/use-sortable.cjs"),wt=require("./hooks/use-scroll-overflow.cjs"),Tt=require("./hooks/use-media-permission.cjs"),Et=require("./hooks/use-media-devices.cjs"),Dt=require("./components/OfflineIndicator/OfflineIndicator.cjs"),Ot=require("./offline/use-offline-sync.cjs"),kt=require("./components/VisuallyHidden/VisuallyHidden.cjs"),At=require("./components/SyncStatusBadge/SyncStatusBadge.cjs"),jt=require("./components/UpdatePrompt/UpdatePrompt.cjs"),Mt=require("./components/Kanban/Kanban.cjs"),Nt=require("./components/Kbd/Kbd.cjs"),Pt=require("./components/ModalsManager/ModalsManager.cjs"),Ft=require("./components/Navbar/Navbar.cjs"),It=require("./components/NProgress/NProgress.cjs"),Lt=require("./components/Page/Page.cjs"),Rt=require("./components/Pagination/Pagination.cjs"),zt=require("./components/PasswordInput/PasswordInput.cjs"),Bt=require("./components/PinInput/PinInput.cjs"),Vt=require("./components/Popover/Popover.cjs"),Ht=require("./components/Progress/Progress.cjs"),Ut=require("./components/Radio/Radio.cjs"),Wt=require("./components/RangeSlider/RangeSlider.cjs"),Gt=require("./components/RatingStars/RatingStars.cjs"),Kt=require("./components/Responsive/Responsive.cjs"),qt=require("./components/SafeArea/SafeArea.cjs"),Jt=require("./components/SearchBar/SearchBar.cjs"),Yt=require("./components/SegmentedControl/SegmentedControl.cjs"),Xt=require("./components/Select/Select.cjs"),Zt=require("./components/Sidebar/Sidebar.cjs"),Qt=require("./components/Skeleton/Skeleton.cjs"),$t=require("./components/Spacer/Spacer.cjs"),en=require("./components/Spinner/Spinner.cjs"),tn=require("./components/Stat/Stat.cjs"),nn=require("./components/Stepper/Stepper.cjs"),l=require("./utils/numbers.cjs"),rn=require("./components/StepperInput/StepperInput.cjs"),an=require("./components/Switch/Switch.cjs"),on=require("./components/Tag/Tag.cjs"),sn=require("./components/Table/Table.cjs"),cn=require("./components/Tabs/Tabs.cjs"),ln=require("./components/Textarea/Textarea.cjs"),un=require("./components/Timeline/Timeline.cjs"),dn=require("./components/Tooltip/Tooltip.cjs"),fn=require("./components/Toast/ToastProvider.cjs"),pn=require("./components/ImageCropper/ImageCropper.cjs"),mn=require("./components/Sparkline/Sparkline.cjs"),hn=require("./components/Scheduler/Scheduler.cjs"),gn=require("./utils/relative-time.cjs"),_n=require("./components/NotificationCenter/NotificationCenter.cjs"),vn=require("./components/NotificationCenter/use-notification-inbox.cjs"),yn=require("./components/VirtualList/VirtualList.cjs"),bn=require("./utils/compare-values.cjs"),xn=require("./components/VirtualTable/VirtualTable.cjs"),u=require("./components/QRCode/qr-encode.cjs"),Sn=require("./components/QRCode/QRCode.cjs"),Cn=require("./components/CopyButton/CopyButton.cjs"),wn=require("./components/CodeBlock/CodeBlock.cjs"),Tn=require("./components/RelativeTime/RelativeTime.cjs"),En=require("./components/Money/Money.cjs"),Dn=require("./components/TreeView/TreeView.cjs"),On=require("./components/TruncateText/TruncateText.cjs"),kn=require("./components/Portal/Portal.cjs"),An=require("./components/ClickOutside/ClickOutside.cjs"),jn=require("./components/ConditionalWrapper/ConditionalWrapper.cjs"),Mn=require("./components/For/For.cjs"),Nn=require("./components/ErrorText/ErrorText.cjs"),Pn=require("./components/Image/Image.cjs"),Fn=require("./components/DataList/DataList.cjs"),In=require("./components/DescriptionList/DescriptionList.cjs"),Ln=require("./components/Toggle/Toggle.cjs"),Rn=require("./components/ToggleGroup/ToggleGroup.cjs"),zn=require("./components/Label/Label.cjs"),Bn=require("./components/Collapsible/Collapsible.cjs"),Vn=require("./components/ContextMenu/ContextMenu.cjs"),Hn=require("./components/HoverCard/HoverCard.cjs"),Un=require("./components/Command/Command.cjs"),Wn=require("./components/ScrollArea/ScrollArea.cjs"),Gn=require("./components/Resizable/Resizable.cjs"),Kn=require("./components/Calendar/Calendar.cjs"),qn=require("./components/Slider/Slider.cjs"),Jn=require("./components/MultiSelect/MultiSelect.cjs"),Yn=require("./components/DateRangePicker/DateRangePicker.cjs"),Xn=require("./components/NavigationMenu/NavigationMenu.cjs"),Zn=require("./components/Menubar/Menubar.cjs"),Qn=require("./components/Carousel/Carousel.cjs"),$n=require("./components/DataTable/DataTable.cjs"),er=require("./components/ListTile/ListTile.cjs"),tr=require("./components/FloatingActionButton/FloatingActionButton.cjs"),nr=require("./components/NavigationRail/NavigationRail.cjs"),rr=require("./components/TimePicker/TimePicker.cjs"),ir=require("./components/RefreshIndicator/RefreshIndicator.cjs"),ar=require("./components/Wizard/Wizard.cjs"),or=require("./components/Lightbox/Lightbox.cjs"),sr=require("./components/SignaturePad/SignaturePad.cjs"),cr=require("./components/Chat/ChatComposer.cjs"),lr=require("./components/Chat/Chat.cjs"),ur=require("./audio/audio-output.cjs"),dr=require("./components/AudioPlayer/AudioPlayer.cjs"),fr=require("./capture/media-recorder.cjs"),d=require("./audio/audio-recorder.cjs"),pr=require("./audio/level-meter.cjs"),mr=require("./audio/use-audio-recorder.cjs"),hr=require("./audio/media-access.cjs"),gr=require("./audio/use-microphone.cjs"),_r=require("./audio/wav.cjs"),vr=require("./components/AudioRecorder/AudioRecorder.cjs"),f=require("./capture/barcode.cjs"),yr=require("./capture/use-torch.cjs"),br=require("./capture/use-barcode-scanner.cjs"),xr=require("./components/BarcodeScanner/BarcodeScanner.cjs"),p=require("./components/AIChat/ai-chat-turns.cjs"),Sr=require("./components/AIChat/AIChatComposer.cjs"),Cr=require("./components/Markdown/Markdown.cjs"),wr=require("./components/AIChat/AIChatTurn.cjs"),Tr=require("./components/AIChat/AIChat.cjs"),Er=require("./components/Transfer/Transfer.cjs"),Dr=require("./components/Masonry/Masonry.cjs"),Or=require("./components/Tour/Tour.cjs"),kr=require("./components/BarList/bar-list-model.cjs"),Ar=require("./components/BarList/BarList.cjs"),m=require("./components/FilterBar/filter-model.cjs"),jr=require("./components/FilterBar/FilterBar.cjs"),h=require("./utils/format.cjs"),Mr=require("./components/FilterBar/filter-apply.cjs"),Nr=require("./components/FilterBar/filter-query.cjs"),Pr=require("./utils/storage.cjs"),g=require("./utils/compressed-storage.cjs"),_=require("./utils/strings.cjs"),v=require("./utils/arrays.cjs"),y=require("./utils/objects.cjs"),b=require("./utils/guards.cjs"),x=require("./utils/functions.cjs"),Fr=require("./utils/promises.cjs"),Ir=require("./utils/ids.cjs"),Lr=require("./utils/xlsx.cjs"),Rr=require("./share/share.cjs"),zr=require("./share/share-or-download.cjs"),Br=require("./utils/csv.cjs"),Vr=require("./http/build-url.cjs"),S=require("./http/errors.cjs"),Hr=require("./http/retry.cjs"),Ur=require("./http/api-client.cjs"),C=require("./http/describe-api-error.cjs"),Wr=require("./i18n/create-i18n.cjs"),w=require("./i18n/I18nProvider.cjs"),Gr=require("./http/use-describe-api-error.cjs"),Kr=require("./http/parse-response.cjs"),qr=require("./http/upload-with-progress.cjs"),Jr=require("./http/idempotency.cjs"),T=require("./http/resumable-upload.cjs"),Yr=require("./http/use-poll.cjs"),Xr=require("./auth/create-auth-store.cjs"),Zr=require("./auth/AuthGuard.cjs"),Qr=require("./auth/jwt.cjs"),$r=require("./auth/lazy-with-retry.cjs"),ei=require("./auth/refresh-queue.cjs"),E=require("./auth/passkey.cjs"),D=require("./auth/use-passkey.cjs"),ti=require("./auth/create-tempest-auth.cjs"),ni=require("./access/access-control-context.cjs"),ri=require("./access/use-can.cjs"),ii=require("./access/Can.cjs"),ai=require("./access/create-role-access-control.cjs"),oi=require("./access/permissions-from-token.cjs"),si=require("./oauth/GoogleSignIn.cjs"),ci=require("./oauth/use-oauth-callback.cjs"),O=require("./query/constants.cjs"),li=require("./query/create-query-keys.cjs"),ui=require("./query/retry-policy.cjs"),di=require("./query/QueryProvider.cjs"),k=require("./query/pagination.cjs"),fi=require("./query/use-paginated-query.cjs"),pi=require("./query/use-cursor-query.cjs"),mi=require("./query/use-offline-mutation.cjs"),A=require("./query/optimistic.cjs"),hi=require("./offline/create-offline-store.cjs"),gi=require("./query/offline-persistence.cjs"),_i=require("./data/create-data-provider.cjs"),j=require("./data/data-provider-context.cjs"),M=require("./data/use-resource.cjs"),vi=require("./router/RouteGuard.cjs"),N=require("./router/AppRouter.cjs"),yi=require("./store/create-store.cjs"),bi=require("./store/create-selectors.cjs"),P=require("./theme/ThemeProvider.cjs"),xi=require("./error-boundary/ErrorBoundary.cjs"),Si=require("./app/AppProviders.cjs"),Ci=require("./sse/create-event-stream.cjs"),wi=require("./sse/use-event-stream.cjs"),F=require("./push/utils.cjs"),I=require("./push/web-push-client.cjs"),Ti=require("./push/use-push-subscription.cjs"),L=require("./sw/create-push-handler.cjs"),R=require("./sw/cache.cjs"),Ei=require("./sw/background-sync.cjs"),Di=require("./sw/periodic-sync.cjs"),Oi=require("./sw/cache-inspect.cjs"),z=require("./audio/audio-player.cjs"),ki=require("./audio/use-audio.cjs"),Ai=require("./audio/sfx-pool.cjs"),ji=require("./audio/use-sfx-pool.cjs"),Mi=require("./audio/audio-bus.cjs"),Ni=require("./audio/use-audio-bus.cjs"),B=require("./audio/voice-chain.cjs"),Pi=require("./audio/noise-floor.cjs"),Fi=require("./audio/voice-activity.cjs"),V=require("./capture/video-recorder.cjs"),Ii=require("./capture/use-video-recorder.cjs"),Li=require("./capture/use-screen-capture.cjs"),Ri=require("./capture/use-speech-recognition.cjs"),zi=require("./offline/create-offline-database.cjs"),Bi=require("./offline/create-offline-sync.cjs"),Vi=require("./offline/conflict.cjs"),Hi=require("./error-boundary/use-error-handler.cjs"),Ui=require("./forms/FormField.cjs"),Wi=require("./forms/validate-form.cjs"),Gi=require("./forms/zod-resolver.cjs"),Ki=require("./forms/use-zod-form.cjs"),H=require("./forms/br-validators.cjs"),U=require("./forms/masked-inputs.cjs"),qi=require("./forms/use-viacep.cjs"),Ji=require("./ws/resilience.cjs"),Yi=require("./ws/create-web-socket.cjs"),Xi=require("./ws/use-web-socket.cjs"),Zi=require("./webrtc/opus-sdp.cjs"),Qi=require("./webrtc/sender-bitrate.cjs"),$i=require("./webrtc/link-stats.cjs"),ea=require("./webrtc/use-link-stats.cjs"),W=require("./geo/types.cjs"),G=require("./geo/distance.cjs"),K=require("./geo/estimate.cjs"),q=require("./geo/bounds.cjs"),J=require("./geo/projection.cjs"),ta=require("./geo/routing.cjs"),na=require("./geo/create-position-tracker.cjs"),ra=require("./geo/use-position-tracker.cjs"),ia=require("./geo/TrajectoryMap.cjs"),aa=require("./theme/apply-theme.cjs"),Y=require("./theme/color.cjs"),oa=require("./theme/create-theme.cjs"),sa=require("./theme/theme-presets.cjs"),ca=require("./theme/initial-theme.cjs"),la=require("./logger/logger.cjs"),ua=require("./telemetry/TelemetryProvider.cjs"),da=require("./telemetry/console-adapter.cjs"),fa=require("./telemetry/sentry-adapter.cjs"),pa=require("./telemetry/posthog-adapter.cjs"),X=require("./feature-flags/FeatureFlagsProvider.cjs"),ma=require("./feature-flags/in-memory-adapter.cjs"),ha=require("./feature-flags/growthbook-adapter.cjs"),ga=require("./feature-flags/launchdarkly-adapter.cjs"),Z=require("./charts/scales.cjs"),_a=require("./perf/cache-size.cjs"),va=require("./perf/device.cjs"),ya=require("./perf/format.cjs"),ba=require("./perf/profiler.cjs");let Q=require("react-router"),$=require("react-hook-form");exports.AIChat=Tr.AIChat,exports.AIChatComposer=Sr.AIChatComposer,exports.AIChatTurn=wr.AIChatTurn,exports.ALL_BARCODE_FORMATS=f.ALL_BARCODE_FORMATS,exports.API_ERROR_OFFLINE_KEY=C.API_ERROR_OFFLINE_KEY,exports.API_ERROR_VALIDATION_KEY=C.API_ERROR_VALIDATION_KEY,exports.AUDIO_MIME_CANDIDATES=d.AUDIO_MIME_CANDIDATES,exports.AccessControlProvider=ni.AccessControlProvider,exports.Accordion=te.Accordion,exports.Alert=ne.Alert,exports.AppBar=re.AppBar,exports.AppProviders=Si.AppProviders,exports.AppRouter=N.AppRouter,exports.AppShell=ie.AppShell,exports.AspectRatio=ae.AspectRatio,exports.AudioPlayer=dr.AudioPlayer,exports.AudioRecorder=vr.AudioRecorder,exports.AuthGuard=Zr.AuthGuard,exports.Avatar=oe.Avatar,exports.AvatarGroup=se.AvatarGroup,exports.BREAKPOINTS=e.BREAKPOINTS,exports.Badge=ce.Badge,exports.Banner=le.Banner,exports.BarList=Ar.BarList,exports.BarcodeScanner=xr.BarcodeScanner,exports.BottomNavigation=ue.BottomNavigation,exports.BottomSheet=de.BottomSheet,exports.Breadcrumbs=fe.Breadcrumbs,Object.defineProperty(exports,"BrowserRouter",{enumerable:!0,get:function(){return Q.BrowserRouter}}),exports.Button=pe.Button,exports.CACHE_TIME=O.CACHE_TIME,exports.CEPInput=U.CEPInput,exports.CNPJInput=U.CNPJInput,exports.CPFInput=U.CPFInput,exports.Calendar=Kn.Calendar,exports.Can=ii.Can,exports.Card=me.Card,exports.Carousel=Qn.Carousel,exports.Center=he.Center,exports.Chat=lr.Chat,exports.ChatComposer=cr.ChatComposer,exports.Checkbox=ge.Checkbox,exports.ChipInput=_e.ChipInput,exports.ClickOutside=An.ClickOutside,exports.CodeBlock=wn.CodeBlock,exports.Collapsible=Bn.Collapsible,exports.Combobox=ve.Combobox,exports.Command=Un.Command,exports.ConditionalWrapper=jn.ConditionalWrapper,exports.ConfirmDialog=be.ConfirmDialog,exports.Container=n.Container,exports.ContextMenu=Vn.ContextMenu,Object.defineProperty(exports,"Controller",{enumerable:!0,get:function(){return $.Controller}}),exports.CopyButton=Cn.CopyButton,exports.DEFAULT_API_ERROR_STRINGS=C.DEFAULT_API_ERROR_STRINGS,exports.DEFAULT_BARCODE_FORMATS=f.DEFAULT_BARCODE_FORMATS,exports.DEFAULT_CAR_SPEED_KMH=K.DEFAULT_CAR_SPEED_KMH,exports.DEFAULT_CHUNK_SIZE=T.DEFAULT_CHUNK_SIZE,exports.DEFAULT_CIRCUITY_FACTOR=K.DEFAULT_CIRCUITY_FACTOR,exports.DEFAULT_MAX_GAIN=Mi.DEFAULT_MAX_GAIN,exports.DEFAULT_MODE_DURATION_FACTORS=K.DEFAULT_MODE_DURATION_FACTORS,exports.DEFAULT_PUB_KEY_CRED_PARAMS=E.DEFAULT_PUB_KEY_CRED_PARAMS,exports.DEFAULT_PUSH_TO_TALK_KEY=r.DEFAULT_PUSH_TO_TALK_KEY,exports.DEFAULT_VOICE_CHAIN=B.DEFAULT_VOICE_CHAIN,exports.DIVERGING_STEP_COUNT=Z.DIVERGING_STEP_COUNT,exports.DataList=Fn.DataList,exports.DataTable=$n.DataTable,exports.DatePicker=Se.DatePicker,exports.DateRangePicker=Yn.DateRangePicker,exports.DescriptionList=In.DescriptionList,exports.Divider=Ce.Divider,exports.Drawer=we.Drawer,exports.DropdownMenu=Te.DropdownMenu,exports.Dropzone=Ee.Dropzone,exports.EARTH_RADIUS_KM=G.EARTH_RADIUS_KM,exports.EmptyState=De.EmptyState,exports.ErrorBoundary=xi.ErrorBoundary,exports.ErrorState=Oe.ErrorState,exports.ErrorText=Nn.ErrorText,exports.FeatureFlagsProvider=X.FeatureFlagsProvider,exports.FileUpload=ke.FileUpload,exports.FilterBar=jr.FilterBar,exports.FloatingActionButton=tr.FloatingActionButton,exports.For=Mn.For,exports.Form=t.Form,exports.FormActions=t.FormActions,exports.FormField=Ui.FormField,Object.defineProperty(exports,"FormProvider",{enumerable:!0,get:function(){return $.FormProvider}}),exports.FormRow=t.FormRow,exports.FormSection=t.FormSection,exports.GoogleSignIn=si.GoogleSignIn,exports.Grid=n.Grid,exports.HEARTBEAT_CLOSE_CODE=Ji.HEARTBEAT_CLOSE_CODE,Object.defineProperty(exports,"HashRouter",{enumerable:!0,get:function(){return Q.HashRouter}}),exports.Hide=Kt.Hide,exports.HoverCard=Hn.HoverCard,exports.I18nProvider=w.I18nProvider,exports.Image=Pn.Image,exports.ImageCropper=pn.ImageCropper,exports.Input=xe.Input,exports.InstallBanner=je.InstallBanner,exports.InstallButton=Me.InstallButton,exports.Kanban=Mt.Kanban,exports.Kbd=Nt.Kbd,exports.Label=zn.Label,exports.Lightbox=or.Lightbox,Object.defineProperty(exports,"Link",{enumerable:!0,get:function(){return Q.Link}}),exports.ListTile=er.ListTile,exports.Markdown=Cr.Markdown,exports.Masonry=Dr.Masonry,Object.defineProperty(exports,"MemoryRouter",{enumerable:!0,get:function(){return Q.MemoryRouter}}),exports.Menubar=Zn.Menubar,exports.Modal=ye.Modal,exports.ModalsProvider=Pt.ModalsProvider,exports.Money=En.Money,exports.MoneyInput=U.MoneyInput,exports.MultiSelect=Jn.MultiSelect,exports.NProgressBar=It.NProgressBar,Object.defineProperty(exports,"NavLink",{enumerable:!0,get:function(){return Q.NavLink}}),exports.Navbar=Ft.Navbar,Object.defineProperty(exports,"Navigate",{enumerable:!0,get:function(){return Q.Navigate}}),exports.NavigationMenu=Xn.NavigationMenu,exports.NavigationRail=nr.NavigationRail,exports.NotificationCenter=_n.NotificationCenter,exports.ORDINAL_START_STEP=Z.ORDINAL_START_STEP,exports.OfflineIndicator=Dt.OfflineIndicator,Object.defineProperty(exports,"Outlet",{enumerable:!0,get:function(){return Q.Outlet}}),exports.PUSH_TO_TALK_KEYS=r.PUSH_TO_TALK_KEYS,exports.Page=Lt.Page,exports.Pagination=Rt.Pagination,exports.PasskeyError=E.PasskeyError,exports.PasswordInput=zt.PasswordInput,exports.PhoneInput=U.PhoneInput,exports.PinInput=Bt.PinInput,exports.Popover=Vt.Popover,exports.Portal=kn.Portal,exports.Progress=Ht.Progress,exports.QRCapacityError=u.QRCapacityError,exports.QRCode=Sn.QRCode,exports.QueryProvider=di.QueryProvider,exports.REFETCH_TIME=O.REFETCH_TIME,exports.Radio=Ut.Radio,exports.RadioGroup=Ut.RadioGroup,exports.RangeSlider=Wt.RangeSlider,exports.RatingStars=Gt.RatingStars,exports.RefreshIndicator=ir.RefreshIndicator,exports.RelativeTime=Tn.RelativeTime,exports.Resizable=Gn.Resizable,Object.defineProperty(exports,"Route",{enumerable:!0,get:function(){return Q.Route}}),exports.RouteGuard=vi.RouteGuard,Object.defineProperty(exports,"Routes",{enumerable:!0,get:function(){return Q.Routes}}),exports.SEQUENTIAL_STEP_COUNT=Z.SEQUENTIAL_STEP_COUNT,exports.STALE_TIME=O.STALE_TIME,exports.SafeArea=qt.SafeArea,exports.Scheduler=hn.Scheduler,exports.ScrollArea=Wn.ScrollArea,exports.SearchBar=Jt.SearchBar,exports.SegmentedControl=Yt.SegmentedControl,exports.Select=Xt.Select,exports.Show=Kt.Show,exports.Sidebar=Zt.Sidebar,exports.SignaturePad=sr.SignaturePad,exports.Skeleton=Qt.Skeleton,exports.Slider=qn.Slider,exports.Spacer=$t.Spacer,exports.Sparkline=mn.Sparkline,exports.Spinner=en.Spinner,exports.Stack=n.Stack,exports.Stat=tn.Stat,exports.Stepper=nn.Stepper,exports.StepperInput=rn.StepperInput,exports.Switch=an.Switch,exports.SyncStatusBadge=At.SyncStatusBadge,exports.Table=sn.Table,exports.Tabs=cn.Tabs,exports.Tag=on.Tag,exports.TelemetryProvider=ua.TelemetryProvider,exports.TempestApiError=S.TempestApiError,exports.TempestDataProvider=j.TempestDataProvider,exports.Textarea=ln.Textarea,exports.ThemeProvider=P.ThemeProvider,exports.TimePicker=rr.TimePicker,exports.Timeline=un.Timeline,exports.ToastProvider=fn.ToastProvider,exports.Toggle=Ln.Toggle,exports.ToggleGroup=Rn.ToggleGroup,exports.ToggleGroupItem=Rn.ToggleGroupItem,exports.Tooltip=dn.Tooltip,exports.Tour=Or.Tour,exports.TrajectoryMap=ia.TrajectoryMap,exports.Transfer=Er.Transfer,exports.TreeView=Dn.TreeView,exports.TruncateText=On.TruncateText,exports.UpdatePrompt=jt.UpdatePrompt,exports.VirtualList=yn.VirtualList,exports.VirtualTable=xn.VirtualTable,exports.VisuallyHidden=kt.VisuallyHidden,exports.WebPushClient=I.WebPushClient,exports.WebPushPermissionDeniedError=I.WebPushPermissionDeniedError,exports.WebPushUnsupportedError=I.WebPushUnsupportedError,exports.Wizard=ar.Wizard,exports.aiChatStrings=p.aiChatStrings,exports.announce=i.announce,exports.applyFilters=Mr.applyFilters,exports.applyKanbanMove=Mt.applyKanbanMove,exports.applyTheme=aa.applyTheme,exports.assertNever=b.assertNever,exports.base64UrlToBytes=E.base64UrlToBytes,exports.bearingDeg=G.bearingDeg,exports.blobToWav=_r.blobToWav,exports.boundingBox=q.boundingBox,exports.boundsCenter=q.boundsCenter,exports.buildApiUrl=Vr.buildApiUrl,exports.buildBarListRows=kr.buildBarListRows,exports.buildOpenInChromeIntent=a.buildOpenInChromeIntent,exports.bytesToBase64Url=E.bytesToBase64Url,exports.cachedResponseBytes=_a.cachedResponseBytes,exports.camelCase=_.camelCase,exports.capitalize=_.capitalize,exports.chunk=v.chunk,exports.clamp=l.clamp,exports.clampLatitude=W.clampLatitude,exports.classifyPasskeyError=E.classifyPasskeyError,exports.clearAnnouncer=i.clearAnnouncer,exports.clearCaches=Oi.clearCaches,exports.cn=ee.cn,exports.compareValues=bn.compareValues,exports.compressToString=g.compressToString,exports.compressedStorage=g.compressedStorage,exports.compressedStorageCodec=g.compressedStorageCodec,exports.consoleSink=la.consoleSink,exports.consoleTelemetryAdapter=da.consoleTelemetryAdapter,exports.contrastRatio=Y.contrastRatio,exports.createApiClient=Ur.createApiClient,exports.createAudioBus=Mi.createAudioBus,exports.createAudioPlayer=z.createAudioPlayer,exports.createAudioRecorder=d.createAudioRecorder,exports.createAuthStore=Xr.createAuthStore,exports.createBarcodeDetector=f.createBarcodeDetector,exports.createColorScale=Y.createColorScale,exports.createDataProvider=_i.createDataProvider,exports.createEventStream=Ci.createEventStream,exports.createGrowthBookFeatureFlagsAdapter=ha.createGrowthBookFeatureFlagsAdapter,exports.createI18n=Wr.createI18n,exports.createInMemoryFlags=ma.createInMemoryFlags,exports.createInferenceProfiler=ba.createInferenceProfiler,exports.createJsonStorage=Pr.createJsonStorage,exports.createLaunchDarklyFeatureFlagsAdapter=ga.createLaunchDarklyFeatureFlagsAdapter,exports.createLevelMeter=pr.createLevelMeter,exports.createLinkStatsSampler=$i.createLinkStatsSampler,exports.createLocalUploadStorage=T.createLocalUploadStorage,exports.createLogger=la.createLogger,exports.createMediaRecorder=fr.createMediaRecorder,exports.createOSRMBackend=ta.createOSRMBackend,exports.createOfflineDatabase=zi.createOfflineDatabase,exports.createOfflineStore=hi.createOfflineStore,exports.createOfflineSync=Bi.createOfflineSync,exports.createPartialResponse=R.createPartialResponse,exports.createPasskeyClient=E.createPasskeyClient,exports.createPositionTracker=na.createPositionTracker,exports.createPostHogTelemetryAdapter=pa.createPostHogTelemetryAdapter,exports.createQueryKeys=li.createQueryKeys,exports.createRefreshQueue=ei.createRefreshQueue,exports.createResumableUpload=T.createResumableUpload,exports.createRoleAccessControl=ai.createRoleAccessControl,exports.createSelectors=bi.createSelectors,exports.createSentryTelemetryAdapter=fa.createSentryTelemetryAdapter,exports.createSfxPool=Ai.createSfxPool,exports.createStore=yi.createStore,exports.createTempestAuth=ti.createTempestAuth,exports.createTheme=oa.createTheme,exports.createVideoRecorder=V.createVideoRecorder,exports.createVoiceChain=B.createVoiceChain,exports.createWebSocket=Yi.createWebSocket,exports.debounce=x.debounce,exports.decodeJWT=Qr.decodeJWT,exports.decompressFromString=g.decompressFromString,exports.deepMerge=y.deepMerge,exports.defineRoutes=N.defineRoutes,exports.describeApiError=C.describeApiError,exports.describeFilter=m.describeFilter,exports.divergingScale=Z.divergingScale,exports.downloadCsv=Br.downloadCsv,exports.emptyOffsetPage=k.emptyOffsetPage,exports.encodeQR=u.encodeQR,exports.encodeWav=_r.encodeWav,exports.estimatePasswordStrength=zt.estimatePasswordStrength,exports.estimateStorage=s.estimateStorage,exports.estimateTravel=K.estimateTravel,exports.expandBounds=q.expandBounds,exports.filtersFromSearchParams=m.filtersFromSearchParams,exports.filtersToQueryParams=Nr.filtersToQueryParams,exports.filtersToSearchParams=m.filtersToSearchParams,exports.fitProjection=J.fitProjection,exports.formatBytes=l.formatBytes,exports.formatCEP=H.formatCEP,exports.formatCNPJ=H.formatCNPJ,exports.formatCPF=h.formatCPF,exports.formatCompactNumber=l.formatCompactNumber,exports.formatCurrency=h.formatCurrency,exports.formatDate=h.formatDate,exports.formatDateForInput=h.formatDateForInput,exports.formatDateTime=h.formatDateTime,exports.formatDateTimeForInput=h.formatDateTimeForInput,exports.formatDurationMs=ya.formatDurationMs,exports.formatPercent=h.formatPercent,exports.formatPhone=h.formatPhone,exports.generateIdempotencyKey=Jr.generateIdempotencyKey,exports.getInitialTheme=ca.getInitialTheme,exports.getSupportedBarcodeFormats=f.getSupportedBarcodeFormats,exports.getThemePreset=sa.getThemePreset,exports.groupBy=v.groupBy,exports.haversineKm=G.haversineKm,exports.hexToOklch=Y.hexToOklch,exports.hexToRgb=Y.hexToRgb,exports.hexToRgbaString=Y.hexToRgbaString,exports.higherVersionWins=Vi.higherVersionWins,exports.inspectCaches=Oi.inspectCaches,exports.installBackgroundSync=Ei.installBackgroundSync,exports.installNotificationClickHandler=L.installNotificationClickHandler,exports.installPrecache=R.installPrecache,exports.installPushHandler=L.installPushHandler,exports.installRuntimeCache=R.installRuntimeCache,exports.installSkipWaitingListener=L.installSkipWaitingListener,exports.isAndroid=a.isAndroid,exports.isAndroidWithoutPromptApi=a.isAndroidWithoutPromptApi,exports.isApiError=S.isApiError,exports.isAudioOutputSelectionSupported=ur.isAudioOutputSelectionSupported,exports.isAudioRecordingSupported=d.isAudioRecordingSupported,exports.isBarcodeDetectionSupported=f.isBarcodeDetectionSupported,exports.isConditionalMediationAvailable=E.isConditionalMediationAvailable,exports.isCoordinate=W.isCoordinate,exports.isCursorPage=k.isCursorPage,exports.isDefined=b.isDefined,exports.isEmpty=y.isEmpty,exports.isFullscreenSupported=Ye.isFullscreenSupported,exports.isGenerating=p.isGenerating,exports.isIOS=a.isIOS,exports.isJWTExpired=Qr.isJWTExpired,exports.isMediaCaptureSupported=hr.isMediaCaptureSupported,exports.isNumber=b.isNumber,exports.isOffsetPage=k.isOffsetPage,exports.isPasskeySupported=E.isPasskeySupported,exports.isPlainObject=b.isPlainObject,exports.isPlatformAuthenticatorAvailable=E.isPlatformAuthenticatorAvailable,exports.isPushSupported=F.isPushSupported,exports.isRejectionCloseCode=Ji.isRejectionCloseCode,exports.isRetriableStatus=S.isRetriableStatus,exports.isScreenCaptureSupported=Li.isScreenCaptureSupported,exports.isShareSupported=Rr.isShareSupported,exports.isSpeechRecognitionSupported=Ri.isSpeechRecognitionSupported,exports.isStandalone=a.isStandalone,exports.isString=b.isString,exports.isValidLatitude=W.isValidLatitude,exports.isValidLongitude=W.isValidLongitude,exports.isVideoRecordingSupported=V.isVideoRecordingSupported,exports.isVoiceChainIdle=B.isVoiceChainIdle,exports.kebabCase=_.kebabCase,exports.lastAssistantId=p.lastAssistantId,exports.lastWriteWins=Vi.lastWriteWins,exports.lazyWithRetry=$r.lazyWithRetry,exports.listQueryKey=M.listQueryKey,exports.matrixToPath=u.matrixToPath,exports.measureNoiseFloor=Pi.measureNoiseFloor,exports.memoizeOne=x.memoizeOne,exports.monitorVoiceActivity=Fi.monitorVoiceActivity,exports.monitorVoiceChain=B.monitorVoiceChain,exports.moveItem=c.moveItem,exports.normalizeBarcode=f.normalizeBarcode,exports.normalizeLongitude=W.normalizeLongitude,exports.nprogress=It.nprogress,exports.oklchToHex=Y.oklchToHex,exports.omit=y.omit,exports.once=x.once,exports.oneQueryKey=M.oneQueryKey,exports.operatorsFor=m.operatorsFor,exports.parseResponse=Kr.parseResponse,exports.pathLengthKm=G.pathLengthKm,exports.percentOf=l.percentOf,exports.permissionsFromToken=oi.permissionsFromToken,exports.persistQueryClientOffline=gi.persistQueryClientOffline,exports.pick=y.pick,exports.pickAudioMimeType=d.pickAudioMimeType,exports.pickVideoMimeType=V.pickVideoMimeType,exports.playAudio=z.playAudio,exports.pluralize=_.pluralize,exports.projectMercator=J.projectMercator,exports.pushToTalkKeyLabel=r.pushToTalkKeyLabel,exports.randomId=Ir.randomId,exports.range=v.range,exports.readDeviceProfile=va.readDeviceProfile,exports.readRoundTripMs=$i.readRoundTripMs,exports.readThemeToken=aa.readThemeToken,exports.readableForeground=Y.readableForeground,Object.defineProperty(exports,"redirect",{enumerable:!0,get:function(){return Q.redirect}}),exports.registerPeriodicSync=Di.registerPeriodicSync,exports.registerServiceWorker=o.registerServiceWorker,exports.relativeLuminance=Y.relativeLuminance,exports.relativeTime=gn.relativeTime,exports.removeById=A.removeById,exports.requestPersistentStorage=s.requestPersistentStorage,exports.retry=Hr.retry,exports.rgbToHex=Y.rgbToHex,exports.roleLabel=p.roleLabel,exports.scaleSteps=Z.scaleSteps,exports.sequentialScale=Z.sequentialScale,exports.setAudioOutput=ur.setAudioOutput,exports.setSenderBitrate=Qi.setSenderBitrate,exports.setTunedLocalDescription=Zi.setTunedLocalDescription,exports.share=Rr.share,exports.shareOrDownloadBlob=zr.shareOrDownloadBlob,exports.shouldRetryQuery=ui.shouldRetryQuery,exports.skipWaiting=o.skipWaiting,exports.sleep=Fr.sleep,exports.slugify=_.slugify,exports.stopAudio=z.stopAudio,exports.storage=Pr.storage,exports.suggestGateThreshold=Pi.suggestGateThreshold,exports.tailSignature=p.tailSignature,exports.themeContrast=oa.themeContrast,exports.themeInitScript=ca.themeInitScript,exports.themePresets=sa.themePresets,exports.throttle=x.throttle,exports.toCsv=Br.toCsv,exports.toRadians=G.toRadians,exports.truncate=_.truncate,exports.tuneOpus=Zi.tuneOpus,exports.turnTime=p.turnTime,exports.uniqueBy=v.uniqueBy,exports.unmask=H.unmask,exports.unprojectMercator=J.unprojectMercator,exports.unregisterAllServiceWorkers=o.unregisterAllServiceWorkers,exports.uploadFingerprint=T.uploadFingerprint,exports.uploadWithProgress=qr.uploadWithProgress,exports.upsertById=A.upsertById,exports.urlBase64ToUint8Array=F.urlBase64ToUint8Array,exports.useAccessControl=ni.useAccessControl,exports.useAnnounce=i.useAnnounce,exports.useAsync=Ve.useAsync,exports.useAudio=ki.useAudio,exports.useAudioBus=Ni.useAudioBus,exports.useAudioRecorder=mr.useAudioRecorder,exports.useBarcodeScanner=br.useBarcodeScanner,exports.useBeforeInstallPrompt=Ae.useBeforeInstallPrompt,exports.useBreakpoint=e.useBreakpoint,exports.useCan=ri.useCan,exports.useClickOutside=vt.useClickOutside,exports.useClientFilter=Fe.useClientFilter,exports.useClipboard=Ke.useClipboard,exports.useCountdown=dt.useCountdown,exports.useCounter=ut.useCounter,exports.useCreate=M.useCreate,exports.useCursorQuery=pi.useCursorQuery,exports.useDataProvider=j.useDataProvider,exports.useDebounce=Ne.useDebounce,exports.useDeepMemo=et.useDeepMemo,exports.useDelete=M.useDelete,exports.useDescribeApiError=Gr.useDescribeApiError,exports.useDisclosure=ct.useDisclosure,exports.useDocumentTitle=pt.useDocumentTitle,exports.useDocumentVisibility=Ue.useDocumentVisibility,exports.useErrorHandler=Hi.useErrorHandler,exports.useEventListener=Re.useEventListener,exports.useEventStream=wi.useEventStream,exports.useFavicon=mt.useFavicon,exports.useFeatureFlag=X.useFeatureFlag,Object.defineProperty(exports,"useFieldArray",{enumerable:!0,get:function(){return $.useFieldArray}}),exports.useFlagValue=X.useFlagValue,exports.useFocusTrap=Qe.useFocusTrap,Object.defineProperty(exports,"useForm",{enumerable:!0,get:function(){return $.useForm}}),Object.defineProperty(exports,"useFormContext",{enumerable:!0,get:function(){return $.useFormContext}}),Object.defineProperty(exports,"useFormState",{enumerable:!0,get:function(){return $.useFormState}}),exports.useFullscreen=Ye.useFullscreen,exports.useGeolocation=Xe.useGeolocation,exports.useHover=ot.useHover,exports.useI18n=w.useI18n,exports.useIdle=Je.useIdle,exports.useInstallPrompt=St.useInstallPrompt,exports.useIntersectionObserver=We.useIntersectionObserver,exports.useInterval=nt.useInterval,exports.useIsFirstRender=yt.useIsFirstRender,exports.useKeyboardShortcut=qe.useKeyboardShortcut,exports.useLatestRef=Le.useLatestRef,exports.useLinkStats=ea.useLinkStats,exports.useList=M.useList,exports.useListState=lt.useListState,exports.useLocalStorage=ze.useLocalStorage,Object.defineProperty(exports,"useLocation",{enumerable:!0,get:function(){return Q.useLocation}}),exports.useLongPress=st.useLongPress,exports.useLongPressHandlers=xt.useLongPressHandlers,exports.useMap=ht.useMap,Object.defineProperty(exports,"useMatch",{enumerable:!0,get:function(){return Q.useMatch}}),exports.useMediaDevices=Et.useMediaDevices,exports.useMediaPermission=Tt.useMediaPermission,exports.useMediaQuery=Ie.useMediaQuery,exports.useMicrophone=gr.useMicrophone,exports.useModals=Pt.useModals,Object.defineProperty(exports,"useNavigate",{enumerable:!0,get:function(){return Q.useNavigate}}),exports.useNotificationInbox=vn.useNotificationInbox,exports.useOAuthCallback=ci.useOAuthCallback,exports.useObjectUrl=bt.useObjectUrl,exports.useOfflineMutation=mi.useOfflineMutation,exports.useOfflineSync=Ot.useOfflineSync,exports.useOne=M.useOne,exports.useOnline=He.useOnline,exports.useOptionalI18n=w.useOptionalI18n,exports.usePaginatedQuery=fi.usePaginatedQuery,exports.usePagination=Pe.usePagination,Object.defineProperty(exports,"useParams",{enumerable:!0,get:function(){return Q.useParams}}),exports.usePasskeyCapabilities=D.usePasskeyCapabilities,exports.usePasskeyRegistration=D.usePasskeyRegistration,exports.usePasskeySignIn=D.usePasskeySignIn,exports.usePoll=Yr.usePoll,exports.usePositionTracker=ra.usePositionTracker,exports.usePrevious=tt.usePrevious,exports.usePushSubscription=Ti.usePushSubscription,exports.usePushToTalk=r.usePushToTalk,exports.useQueue=_t.useQueue,exports.useResizeObserver=Ge.useResizeObserver,Object.defineProperty(exports,"useRouteError",{enumerable:!0,get:function(){return Q.useRouteError}}),exports.useScreenCapture=Li.useScreenCapture,exports.useScrollLock=Ze.useScrollLock,exports.useScrollOverflow=wt.useScrollOverflow,Object.defineProperty(exports,"useSearchParams",{enumerable:!0,get:function(){return Q.useSearchParams}}),exports.useServiceWorkerUpdate=Ct.useServiceWorkerUpdate,exports.useSet=gt.useSet,exports.useSfxPool=ji.useSfxPool,exports.useSortable=c.useSortable,exports.useSpeechRecognition=Ri.useSpeechRecognition,exports.useStableCallback=$e.useStableCallback,exports.useStorageEstimate=s.useStorageEstimate,exports.useSyncStatus=Ot.useSyncStatus,exports.useTelemetry=ua.useTelemetry,exports.useTheme=P.useTheme,exports.useThrottle=it.useThrottle,exports.useTimeout=rt.useTimeout,exports.useToast=fn.useToast,exports.useToggle=Be.useToggle,exports.useTorch=yr.useTorch,exports.useTranslate=w.useTranslate,exports.useTypewriter=ft.useTypewriter,exports.useUpdate=M.useUpdate,exports.useViaCEP=qi.useViaCEP,exports.useVideoRecorder=Ii.useVideoRecorder,Object.defineProperty(exports,"useWatch",{enumerable:!0,get:function(){return $.useWatch}}),exports.useWebSocket=Xi.useWebSocket,exports.useWindowSize=at.useWindowSize,exports.useZodForm=Ki.useZodForm,exports.validateCNPJ=H.validateCNPJ,exports.validateCPF=H.validateCPF,exports.validateForm=Wi.validateForm,exports.visibleTurns=p.visibleTurns,exports.withTimeout=Fr.withTimeout,exports.writeXlsx=Lr.writeXlsx,exports.zodResolver=Gi.zodResolver;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});/* empty css */const ee=require("./utils/cn.cjs"),te=require("./components/Accordion/Accordion.cjs"),ne=require("./components/Alert/Alert.cjs"),re=require("./components/AppBar/AppBar.cjs"),ie=require("./hooks/use-breakpoint.cjs"),ae=require("./components/AppShell/AppShell.cjs"),oe=require("./components/AspectRatio/AspectRatio.cjs"),se=require("./components/Avatar/Avatar.cjs"),ce=require("./components/AvatarGroup/AvatarGroup.cjs"),le=require("./components/Badge/Badge.cjs"),ue=require("./components/Banner/Banner.cjs"),de=require("./components/BottomNavigation/BottomNavigation.cjs"),fe=require("./components/BottomSheet/BottomSheet.cjs"),pe=require("./components/Breadcrumbs/Breadcrumbs.cjs"),me=require("./components/Button/Button.cjs"),he=require("./components/Card/Card.cjs"),ge=require("./components/Center/Center.cjs"),_e=require("./components/Checkbox/Checkbox.cjs"),ve=require("./components/ChipInput/ChipInput.cjs"),ye=require("./components/Combobox/Combobox.cjs"),be=require("./components/Modal/Modal.cjs"),xe=require("./components/ConfirmDialog/ConfirmDialog.cjs"),Se=require("./components/Input/Input.cjs"),Ce=require("./components/DatePicker/DatePicker.cjs"),we=require("./components/Divider/Divider.cjs"),Te=require("./components/Drawer/Drawer.cjs"),Ee=require("./components/DropdownMenu/DropdownMenu.cjs"),De=require("./components/Dropzone/Dropzone.cjs"),Oe=require("./components/EmptyState/EmptyState.cjs"),ke=require("./components/ErrorState/ErrorState.cjs"),Ae=require("./components/FileUpload/FileUpload.cjs"),e=require("./components/Form/Form.cjs"),t=require("./components/Layout/Layout.cjs"),je=require("./hooks/use-before-install-prompt.cjs"),Me=require("./components/InstallBanner/InstallBanner.cjs"),Ne=require("./components/InstallButton/InstallButton.cjs"),Pe=require("./hooks/use-debounce.cjs"),Fe=require("./hooks/use-pagination.cjs"),Ie=require("./hooks/use-client-filter.cjs"),Le=require("./hooks/use-media-query.cjs"),Re=require("./hooks/use-latest-ref.cjs"),ze=require("./hooks/use-event-listener.cjs"),Be=require("./hooks/use-local-storage.cjs"),Ve=require("./hooks/use-toggle.cjs"),He=require("./hooks/use-async.cjs"),Ue=require("./hooks/use-online.cjs"),We=require("./hooks/use-document-visibility.cjs"),Ge=require("./hooks/use-intersection-observer.cjs"),Ke=require("./hooks/use-resize-observer.cjs"),qe=require("./hooks/use-clipboard.cjs"),Je=require("./hooks/use-keyboard-shortcut.cjs"),Ye=require("./hooks/use-idle.cjs"),Xe=require("./hooks/use-fullscreen.cjs"),n=require("./hooks/use-push-to-talk.cjs"),Ze=require("./hooks/use-geolocation.cjs"),Qe=require("./hooks/use-scroll-lock.cjs"),$e=require("./hooks/use-focus-trap.cjs"),r=require("./hooks/use-announce.cjs"),et=require("./hooks/use-stable-callback.cjs"),tt=require("./hooks/use-deep-memo.cjs"),nt=require("./hooks/use-previous.cjs"),rt=require("./hooks/use-interval.cjs"),it=require("./hooks/use-timeout.cjs"),at=require("./hooks/use-throttle.cjs"),ot=require("./hooks/use-window-size.cjs"),st=require("./hooks/use-hover.cjs"),ct=require("./hooks/use-long-press.cjs"),lt=require("./hooks/use-disclosure.cjs"),ut=require("./hooks/use-list-state.cjs"),dt=require("./hooks/use-counter.cjs"),ft=require("./hooks/use-countdown.cjs"),pt=require("./hooks/use-typewriter.cjs"),mt=require("./hooks/use-document-title.cjs"),ht=require("./hooks/use-favicon.cjs"),gt=require("./hooks/use-map.cjs"),_t=require("./hooks/use-set.cjs"),vt=require("./hooks/use-queue.cjs"),yt=require("./hooks/use-click-outside.cjs"),bt=require("./hooks/use-is-first-render.cjs"),xt=require("./hooks/use-object-url.cjs"),St=require("./hooks/use-long-press-handlers.cjs"),i=require("./hooks/pwa-env.cjs"),Ct=require("./hooks/use-install-prompt.cjs"),a=require("./sw/register-service-worker.cjs"),wt=require("./hooks/use-service-worker-update.cjs"),o=require("./hooks/use-storage-estimate.cjs"),Tt=require("./hooks/use-sortable.cjs"),Et=require("./hooks/use-scroll-overflow.cjs"),Dt=require("./hooks/use-media-permission.cjs"),Ot=require("./hooks/use-media-devices.cjs"),kt=require("./components/OfflineIndicator/OfflineIndicator.cjs"),At=require("./offline/use-offline-sync.cjs"),jt=require("./components/VisuallyHidden/VisuallyHidden.cjs"),Mt=require("./components/SyncStatusBadge/SyncStatusBadge.cjs"),Nt=require("./components/UpdatePrompt/UpdatePrompt.cjs"),Pt=require("./components/Kanban/Kanban.cjs"),Ft=require("./components/Kbd/Kbd.cjs"),It=require("./components/ModalsManager/ModalsManager.cjs"),Lt=require("./components/Navbar/Navbar.cjs"),Rt=require("./components/NProgress/NProgress.cjs"),zt=require("./components/Page/Page.cjs"),Bt=require("./components/Pagination/Pagination.cjs"),Vt=require("./components/PasswordInput/PasswordInput.cjs"),Ht=require("./components/PinInput/PinInput.cjs"),Ut=require("./components/Popover/Popover.cjs"),Wt=require("./components/Progress/Progress.cjs"),Gt=require("./components/Radio/Radio.cjs"),Kt=require("./components/RangeSlider/RangeSlider.cjs"),qt=require("./components/RatingStars/RatingStars.cjs"),Jt=require("./components/Responsive/Responsive.cjs"),Yt=require("./components/SafeArea/SafeArea.cjs"),Xt=require("./components/SearchBar/SearchBar.cjs"),Zt=require("./components/SegmentedControl/SegmentedControl.cjs"),Qt=require("./components/Select/Select.cjs"),$t=require("./components/Sidebar/Sidebar.cjs"),en=require("./components/Skeleton/Skeleton.cjs"),tn=require("./components/Spacer/Spacer.cjs"),nn=require("./components/Spinner/Spinner.cjs"),rn=require("./components/Stat/Stat.cjs"),an=require("./components/Stepper/Stepper.cjs"),s=require("./utils/numbers.cjs"),on=require("./components/StepperInput/StepperInput.cjs"),sn=require("./components/Switch/Switch.cjs"),cn=require("./components/Tag/Tag.cjs"),ln=require("./components/Table/Table.cjs"),un=require("./components/Tabs/Tabs.cjs"),dn=require("./components/Textarea/Textarea.cjs"),fn=require("./components/Timeline/Timeline.cjs"),pn=require("./components/Tooltip/Tooltip.cjs"),mn=require("./components/Toast/ToastProvider.cjs"),hn=require("./components/ImageCropper/ImageCropper.cjs"),gn=require("./components/Sparkline/Sparkline.cjs"),_n=require("./components/Scheduler/Scheduler.cjs"),vn=require("./utils/relative-time.cjs"),yn=require("./components/NotificationCenter/NotificationCenter.cjs"),bn=require("./components/NotificationCenter/use-notification-inbox.cjs"),xn=require("./components/VirtualList/VirtualList.cjs"),Sn=require("./utils/compare-values.cjs"),Cn=require("./components/VirtualTable/VirtualTable.cjs"),c=require("./components/QRCode/qr-encode.cjs"),wn=require("./components/QRCode/QRCode.cjs"),Tn=require("./components/CopyButton/CopyButton.cjs"),En=require("./components/CodeBlock/CodeBlock.cjs"),Dn=require("./components/RelativeTime/RelativeTime.cjs"),On=require("./components/Money/Money.cjs"),kn=require("./components/TreeView/TreeView.cjs"),An=require("./components/TruncateText/TruncateText.cjs"),jn=require("./components/Portal/Portal.cjs"),Mn=require("./components/ClickOutside/ClickOutside.cjs"),Nn=require("./components/ConditionalWrapper/ConditionalWrapper.cjs"),Pn=require("./components/For/For.cjs"),Fn=require("./components/ErrorText/ErrorText.cjs"),In=require("./components/Image/Image.cjs"),Ln=require("./components/DataList/DataList.cjs"),Rn=require("./components/DescriptionList/DescriptionList.cjs"),zn=require("./components/Toggle/Toggle.cjs"),Bn=require("./components/ToggleGroup/ToggleGroup.cjs"),Vn=require("./components/Label/Label.cjs"),Hn=require("./components/Collapsible/Collapsible.cjs"),Un=require("./components/ContextMenu/ContextMenu.cjs"),Wn=require("./components/HoverCard/HoverCard.cjs"),Gn=require("./components/Command/Command.cjs"),Kn=require("./components/ScrollArea/ScrollArea.cjs"),qn=require("./components/Resizable/Resizable.cjs"),Jn=require("./components/Calendar/Calendar.cjs"),Yn=require("./components/Slider/Slider.cjs"),Xn=require("./components/MultiSelect/MultiSelect.cjs"),Zn=require("./components/DateRangePicker/DateRangePicker.cjs"),Qn=require("./components/NavigationMenu/NavigationMenu.cjs"),$n=require("./components/Menubar/Menubar.cjs"),er=require("./components/Carousel/Carousel.cjs"),tr=require("./components/DataTable/DataTable.cjs"),nr=require("./components/ListTile/ListTile.cjs"),rr=require("./components/FloatingActionButton/FloatingActionButton.cjs"),ir=require("./components/NavigationRail/NavigationRail.cjs"),ar=require("./components/TimePicker/TimePicker.cjs"),or=require("./components/RefreshIndicator/RefreshIndicator.cjs"),sr=require("./components/Wizard/Wizard.cjs"),cr=require("./components/Lightbox/Lightbox.cjs"),lr=require("./components/SignaturePad/SignaturePad.cjs"),ur=require("./components/Chat/ChatComposer.cjs"),dr=require("./components/Chat/Chat.cjs"),l=require("./audio/audio-output.cjs"),fr=require("./components/AudioPlayer/AudioPlayer.cjs"),pr=require("./capture/media-recorder.cjs"),u=require("./audio/audio-recorder.cjs"),mr=require("./audio/level-meter.cjs"),hr=require("./audio/use-audio-recorder.cjs"),gr=require("./audio/media-access.cjs"),_r=require("./audio/use-microphone.cjs"),vr=require("./audio/wav.cjs"),yr=require("./components/AudioRecorder/AudioRecorder.cjs"),d=require("./capture/barcode.cjs"),br=require("./capture/use-torch.cjs"),xr=require("./capture/use-barcode-scanner.cjs"),Sr=require("./components/BarcodeScanner/BarcodeScanner.cjs"),f=require("./components/AIChat/ai-chat-turns.cjs"),Cr=require("./components/AIChat/AIChatComposer.cjs"),wr=require("./components/Markdown/Markdown.cjs"),Tr=require("./components/AIChat/AIChatTurn.cjs"),Er=require("./components/AIChat/AIChat.cjs"),Dr=require("./components/Transfer/Transfer.cjs"),Or=require("./components/Masonry/Masonry.cjs"),kr=require("./components/Tour/Tour.cjs"),Ar=require("./components/BarList/bar-list-model.cjs"),jr=require("./components/BarList/BarList.cjs"),p=require("./components/FilterBar/filter-model.cjs"),Mr=require("./components/FilterBar/FilterBar.cjs"),m=require("./utils/format.cjs"),Nr=require("./components/FilterBar/filter-apply.cjs"),Pr=require("./components/FilterBar/filter-query.cjs"),Fr=require("./utils/storage.cjs"),h=require("./utils/compressed-storage.cjs"),g=require("./utils/strings.cjs"),_=require("./utils/arrays.cjs"),v=require("./utils/objects.cjs"),y=require("./utils/guards.cjs"),b=require("./utils/functions.cjs"),Ir=require("./utils/promises.cjs"),Lr=require("./utils/ids.cjs"),Rr=require("./utils/xlsx.cjs"),zr=require("./share/share.cjs"),Br=require("./share/share-or-download.cjs"),Vr=require("./utils/csv.cjs"),Hr=require("./http/build-url.cjs"),x=require("./http/errors.cjs"),Ur=require("./http/retry.cjs"),Wr=require("./http/api-client.cjs"),S=require("./http/describe-api-error.cjs"),Gr=require("./i18n/create-i18n.cjs"),C=require("./i18n/I18nProvider.cjs"),Kr=require("./http/use-describe-api-error.cjs"),qr=require("./http/parse-response.cjs"),Jr=require("./http/upload-with-progress.cjs"),Yr=require("./http/idempotency.cjs"),w=require("./http/resumable-upload.cjs"),Xr=require("./http/use-poll.cjs"),Zr=require("./auth/create-auth-store.cjs"),Qr=require("./auth/AuthGuard.cjs"),$r=require("./auth/jwt.cjs"),ei=require("./auth/lazy-with-retry.cjs"),ti=require("./auth/refresh-queue.cjs"),T=require("./auth/passkey.cjs"),E=require("./auth/use-passkey.cjs"),ni=require("./auth/create-tempest-auth.cjs"),ri=require("./access/access-control-context.cjs"),ii=require("./access/use-can.cjs"),ai=require("./access/Can.cjs"),oi=require("./access/create-role-access-control.cjs"),si=require("./access/permissions-from-token.cjs"),ci=require("./oauth/GoogleSignIn.cjs"),li=require("./oauth/use-oauth-callback.cjs"),D=require("./query/constants.cjs"),ui=require("./query/create-query-keys.cjs"),di=require("./query/retry-policy.cjs"),fi=require("./query/QueryProvider.cjs"),O=require("./query/pagination.cjs"),pi=require("./query/use-paginated-query.cjs"),mi=require("./query/use-cursor-query.cjs"),hi=require("./query/use-offline-mutation.cjs"),k=require("./query/optimistic.cjs"),gi=require("./offline/create-offline-store.cjs"),_i=require("./query/offline-persistence.cjs"),vi=require("./data/create-data-provider.cjs"),A=require("./data/data-provider-context.cjs"),j=require("./data/use-resource.cjs"),yi=require("./router/RouteGuard.cjs"),M=require("./router/AppRouter.cjs"),bi=require("./store/create-store.cjs"),xi=require("./store/create-selectors.cjs"),N=require("./theme/ThemeProvider.cjs"),Si=require("./error-boundary/ErrorBoundary.cjs"),Ci=require("./app/AppProviders.cjs"),wi=require("./sse/create-event-stream.cjs"),Ti=require("./sse/use-event-stream.cjs"),P=require("./push/utils.cjs"),F=require("./push/web-push-client.cjs"),Ei=require("./push/use-push-subscription.cjs"),I=require("./sw/create-push-handler.cjs"),L=require("./sw/cache.cjs"),Di=require("./sw/background-sync.cjs"),Oi=require("./sw/periodic-sync.cjs"),ki=require("./sw/cache-inspect.cjs"),R=require("./audio/audio-player.cjs"),Ai=require("./audio/use-audio.cjs"),ji=require("./audio/sfx-pool.cjs"),Mi=require("./audio/use-sfx-pool.cjs"),Ni=require("./audio/audio-bus.cjs"),Pi=require("./audio/use-audio-bus.cjs"),z=require("./audio/voice-chain.cjs"),Fi=require("./audio/noise-floor.cjs"),Ii=require("./audio/voice-activity.cjs"),B=require("./capture/video-recorder.cjs"),Li=require("./capture/use-video-recorder.cjs"),Ri=require("./capture/use-screen-capture.cjs"),zi=require("./capture/use-speech-recognition.cjs"),Bi=require("./offline/create-offline-database.cjs"),Vi=require("./offline/create-offline-sync.cjs"),Hi=require("./offline/conflict.cjs"),Ui=require("./error-boundary/use-error-handler.cjs"),Wi=require("./forms/FormField.cjs"),Gi=require("./forms/validate-form.cjs"),Ki=require("./forms/zod-resolver.cjs"),qi=require("./forms/use-zod-form.cjs"),V=require("./forms/br-validators.cjs"),H=require("./forms/masked-inputs.cjs"),Ji=require("./forms/use-viacep.cjs"),Yi=require("./ws/resilience.cjs"),Xi=require("./ws/create-web-socket.cjs"),Zi=require("./ws/use-web-socket.cjs"),Qi=require("./webrtc/opus-sdp.cjs"),$i=require("./webrtc/sender-bitrate.cjs"),ea=require("./webrtc/link-stats.cjs"),ta=require("./webrtc/use-link-stats.cjs"),na=require("./webrtc/mesh-quality.cjs"),ra=require("./webrtc/peer-mesh.cjs"),U=require("./geo/types.cjs"),W=require("./geo/distance.cjs"),G=require("./geo/estimate.cjs"),K=require("./geo/bounds.cjs"),q=require("./geo/projection.cjs"),ia=require("./geo/routing.cjs"),aa=require("./geo/create-position-tracker.cjs"),oa=require("./geo/use-position-tracker.cjs"),sa=require("./geo/TrajectoryMap.cjs"),ca=require("./theme/apply-theme.cjs"),J=require("./theme/color.cjs"),la=require("./theme/create-theme.cjs"),Y=require("./theme/theme-presets.cjs"),ua=require("./theme/initial-theme.cjs"),da=require("./logger/logger.cjs"),fa=require("./telemetry/TelemetryProvider.cjs"),pa=require("./telemetry/console-adapter.cjs"),ma=require("./telemetry/sentry-adapter.cjs"),ha=require("./telemetry/posthog-adapter.cjs"),X=require("./feature-flags/FeatureFlagsProvider.cjs"),ga=require("./feature-flags/in-memory-adapter.cjs"),_a=require("./feature-flags/growthbook-adapter.cjs"),va=require("./feature-flags/launchdarkly-adapter.cjs"),Z=require("./charts/scales.cjs"),ya=require("./perf/cache-size.cjs"),ba=require("./perf/device.cjs"),xa=require("./perf/format.cjs"),Sa=require("./perf/profiler.cjs");let Q=require("react-router"),$=require("react-hook-form");exports.AIChat=Er.AIChat,exports.AIChatComposer=Cr.AIChatComposer,exports.AIChatTurn=Tr.AIChatTurn,exports.ALL_BARCODE_FORMATS=d.ALL_BARCODE_FORMATS,exports.API_ERROR_OFFLINE_KEY=S.API_ERROR_OFFLINE_KEY,exports.API_ERROR_VALIDATION_KEY=S.API_ERROR_VALIDATION_KEY,exports.AUDIO_MIME_CANDIDATES=u.AUDIO_MIME_CANDIDATES,exports.AccessControlProvider=ri.AccessControlProvider,exports.Accordion=te.Accordion,exports.Alert=ne.Alert,exports.AppBar=re.AppBar,exports.AppProviders=Ci.AppProviders,exports.AppRouter=M.AppRouter,exports.AppShell=ae.AppShell,exports.AspectRatio=oe.AspectRatio,exports.AudioPlayer=fr.AudioPlayer,exports.AudioRecorder=yr.AudioRecorder,exports.AuthGuard=Qr.AuthGuard,exports.Avatar=se.Avatar,exports.AvatarGroup=ce.AvatarGroup,exports.BREAKPOINTS=ie.BREAKPOINTS,exports.Badge=le.Badge,exports.Banner=ue.Banner,exports.BarList=jr.BarList,exports.BarcodeScanner=Sr.BarcodeScanner,exports.BottomNavigation=de.BottomNavigation,exports.BottomSheet=fe.BottomSheet,exports.Breadcrumbs=pe.Breadcrumbs,Object.defineProperty(exports,"BrowserRouter",{enumerable:!0,get:function(){return Q.BrowserRouter}}),exports.Button=me.Button,exports.CACHE_TIME=D.CACHE_TIME,exports.CEPInput=H.CEPInput,exports.CNPJInput=H.CNPJInput,exports.CPFInput=H.CPFInput,exports.Calendar=Jn.Calendar,exports.Can=ai.Can,exports.Card=he.Card,exports.Carousel=er.Carousel,exports.Center=ge.Center,exports.Chat=dr.Chat,exports.ChatComposer=ur.ChatComposer,exports.Checkbox=_e.Checkbox,exports.ChipInput=ve.ChipInput,exports.ClickOutside=Mn.ClickOutside,exports.CodeBlock=En.CodeBlock,exports.Collapsible=Hn.Collapsible,exports.Combobox=ye.Combobox,exports.Command=Gn.Command,exports.ConditionalWrapper=Nn.ConditionalWrapper,exports.ConfirmDialog=xe.ConfirmDialog,exports.Container=t.Container,exports.ContextMenu=Un.ContextMenu,Object.defineProperty(exports,"Controller",{enumerable:!0,get:function(){return $.Controller}}),exports.CopyButton=Tn.CopyButton,exports.DEFAULT_API_ERROR_STRINGS=S.DEFAULT_API_ERROR_STRINGS,exports.DEFAULT_BARCODE_FORMATS=d.DEFAULT_BARCODE_FORMATS,exports.DEFAULT_CAR_SPEED_KMH=G.DEFAULT_CAR_SPEED_KMH,exports.DEFAULT_CHUNK_SIZE=w.DEFAULT_CHUNK_SIZE,exports.DEFAULT_CIRCUITY_FACTOR=G.DEFAULT_CIRCUITY_FACTOR,exports.DEFAULT_MAX_GAIN=Ni.DEFAULT_MAX_GAIN,exports.DEFAULT_MODE_DURATION_FACTORS=G.DEFAULT_MODE_DURATION_FACTORS,exports.DEFAULT_PUB_KEY_CRED_PARAMS=T.DEFAULT_PUB_KEY_CRED_PARAMS,exports.DEFAULT_PUSH_TO_TALK_KEY=n.DEFAULT_PUSH_TO_TALK_KEY,exports.DEFAULT_VOICE_CHAIN=z.DEFAULT_VOICE_CHAIN,exports.DIVERGING_STEP_COUNT=Z.DIVERGING_STEP_COUNT,exports.DataList=Ln.DataList,exports.DataTable=tr.DataTable,exports.DatePicker=Ce.DatePicker,exports.DateRangePicker=Zn.DateRangePicker,exports.DescriptionList=Rn.DescriptionList,exports.Divider=we.Divider,exports.Drawer=Te.Drawer,exports.DropdownMenu=Ee.DropdownMenu,exports.Dropzone=De.Dropzone,exports.EARTH_RADIUS_KM=W.EARTH_RADIUS_KM,exports.EmptyState=Oe.EmptyState,exports.ErrorBoundary=Si.ErrorBoundary,exports.ErrorState=ke.ErrorState,exports.ErrorText=Fn.ErrorText,exports.FeatureFlagsProvider=X.FeatureFlagsProvider,exports.FileUpload=Ae.FileUpload,exports.FilterBar=Mr.FilterBar,exports.FloatingActionButton=rr.FloatingActionButton,exports.For=Pn.For,exports.Form=e.Form,exports.FormActions=e.FormActions,exports.FormField=Wi.FormField,Object.defineProperty(exports,"FormProvider",{enumerable:!0,get:function(){return $.FormProvider}}),exports.FormRow=e.FormRow,exports.FormSection=e.FormSection,exports.GoogleSignIn=ci.GoogleSignIn,exports.Grid=t.Grid,exports.HEARTBEAT_CLOSE_CODE=Yi.HEARTBEAT_CLOSE_CODE,Object.defineProperty(exports,"HashRouter",{enumerable:!0,get:function(){return Q.HashRouter}}),exports.Hide=Jt.Hide,exports.HoverCard=Wn.HoverCard,exports.I18nProvider=C.I18nProvider,exports.Image=In.Image,exports.ImageCropper=hn.ImageCropper,exports.Input=Se.Input,exports.InstallBanner=Me.InstallBanner,exports.InstallButton=Ne.InstallButton,exports.Kanban=Pt.Kanban,exports.Kbd=Ft.Kbd,exports.Label=Vn.Label,exports.Lightbox=cr.Lightbox,Object.defineProperty(exports,"Link",{enumerable:!0,get:function(){return Q.Link}}),exports.ListTile=nr.ListTile,exports.Markdown=wr.Markdown,exports.Masonry=Or.Masonry,Object.defineProperty(exports,"MemoryRouter",{enumerable:!0,get:function(){return Q.MemoryRouter}}),exports.Menubar=$n.Menubar,exports.Modal=be.Modal,exports.ModalsProvider=It.ModalsProvider,exports.Money=On.Money,exports.MoneyInput=H.MoneyInput,exports.MultiSelect=Xn.MultiSelect,exports.NProgressBar=Rt.NProgressBar,Object.defineProperty(exports,"NavLink",{enumerable:!0,get:function(){return Q.NavLink}}),exports.Navbar=Lt.Navbar,Object.defineProperty(exports,"Navigate",{enumerable:!0,get:function(){return Q.Navigate}}),exports.NavigationMenu=Qn.NavigationMenu,exports.NavigationRail=ir.NavigationRail,exports.NotificationCenter=yn.NotificationCenter,exports.ORDINAL_START_STEP=Z.ORDINAL_START_STEP,exports.OfflineIndicator=kt.OfflineIndicator,Object.defineProperty(exports,"Outlet",{enumerable:!0,get:function(){return Q.Outlet}}),exports.PUSH_TO_TALK_KEYS=n.PUSH_TO_TALK_KEYS,exports.Page=zt.Page,exports.Pagination=Bt.Pagination,exports.PasskeyError=T.PasskeyError,exports.PasswordInput=Vt.PasswordInput,exports.PhoneInput=H.PhoneInput,exports.PinInput=Ht.PinInput,exports.Popover=Ut.Popover,exports.Portal=jn.Portal,exports.Progress=Wt.Progress,exports.QRCapacityError=c.QRCapacityError,exports.QRCode=wn.QRCode,exports.QueryProvider=fi.QueryProvider,exports.REFETCH_TIME=D.REFETCH_TIME,exports.Radio=Gt.Radio,exports.RadioGroup=Gt.RadioGroup,exports.RangeSlider=Kt.RangeSlider,exports.RatingStars=qt.RatingStars,exports.RefreshIndicator=or.RefreshIndicator,exports.RelativeTime=Dn.RelativeTime,exports.Resizable=qn.Resizable,Object.defineProperty(exports,"Route",{enumerable:!0,get:function(){return Q.Route}}),exports.RouteGuard=yi.RouteGuard,Object.defineProperty(exports,"Routes",{enumerable:!0,get:function(){return Q.Routes}}),exports.SEQUENTIAL_STEP_COUNT=Z.SEQUENTIAL_STEP_COUNT,exports.STALE_TIME=D.STALE_TIME,exports.SafeArea=Yt.SafeArea,exports.Scheduler=_n.Scheduler,exports.ScrollArea=Kn.ScrollArea,exports.SearchBar=Xt.SearchBar,exports.SegmentedControl=Zt.SegmentedControl,exports.Select=Qt.Select,exports.Show=Jt.Show,exports.Sidebar=$t.Sidebar,exports.SignaturePad=lr.SignaturePad,exports.Skeleton=en.Skeleton,exports.Slider=Yn.Slider,exports.Spacer=tn.Spacer,exports.Sparkline=gn.Sparkline,exports.Spinner=nn.Spinner,exports.Stack=t.Stack,exports.Stat=rn.Stat,exports.Stepper=an.Stepper,exports.StepperInput=on.StepperInput,exports.Switch=sn.Switch,exports.SyncStatusBadge=Mt.SyncStatusBadge,exports.Table=ln.Table,exports.Tabs=un.Tabs,exports.Tag=cn.Tag,exports.TelemetryProvider=fa.TelemetryProvider,exports.TempestApiError=x.TempestApiError,exports.TempestDataProvider=A.TempestDataProvider,exports.Textarea=dn.Textarea,exports.ThemeProvider=N.ThemeProvider,exports.TimePicker=ar.TimePicker,exports.Timeline=fn.Timeline,exports.ToastProvider=mn.ToastProvider,exports.Toggle=zn.Toggle,exports.ToggleGroup=Bn.ToggleGroup,exports.ToggleGroupItem=Bn.ToggleGroupItem,exports.Tooltip=pn.Tooltip,exports.Tour=kr.Tour,exports.TrajectoryMap=sa.TrajectoryMap,exports.Transfer=Dr.Transfer,exports.TreeView=kn.TreeView,exports.TruncateText=An.TruncateText,exports.UpdatePrompt=Nt.UpdatePrompt,exports.VirtualList=xn.VirtualList,exports.VirtualTable=Cn.VirtualTable,exports.VisuallyHidden=jt.VisuallyHidden,exports.WebPushClient=F.WebPushClient,exports.WebPushPermissionDeniedError=F.WebPushPermissionDeniedError,exports.WebPushUnsupportedError=F.WebPushUnsupportedError,exports.Wizard=sr.Wizard,exports.aiChatStrings=f.aiChatStrings,exports.announce=r.announce,exports.applyFilters=Nr.applyFilters,exports.applyKanbanMove=Pt.applyKanbanMove,exports.applyTheme=ca.applyTheme,exports.assertNever=y.assertNever,exports.base64UrlToBytes=T.base64UrlToBytes,exports.bearingDeg=W.bearingDeg,exports.blobToWav=vr.blobToWav,exports.boundingBox=K.boundingBox,exports.boundsCenter=K.boundsCenter,exports.buildApiUrl=Hr.buildApiUrl,exports.buildBarListRows=Ar.buildBarListRows,exports.buildOpenInChromeIntent=i.buildOpenInChromeIntent,exports.bytesToBase64Url=T.bytesToBase64Url,exports.cachedResponseBytes=ya.cachedResponseBytes,exports.camelCase=g.camelCase,exports.capitalize=g.capitalize,exports.chunk=_.chunk,exports.clamp=s.clamp,exports.clampLatitude=U.clampLatitude,exports.classifyPasskeyError=T.classifyPasskeyError,exports.clearAnnouncer=r.clearAnnouncer,exports.clearCaches=ki.clearCaches,exports.cn=ee.cn,exports.compareValues=Sn.compareValues,exports.compressToString=h.compressToString,exports.compressedStorage=h.compressedStorage,exports.compressedStorageCodec=h.compressedStorageCodec,exports.consoleSink=da.consoleSink,exports.consoleTelemetryAdapter=pa.consoleTelemetryAdapter,exports.contrastRatio=J.contrastRatio,exports.createApiClient=Wr.createApiClient,exports.createAudioBus=Ni.createAudioBus,exports.createAudioPlayer=R.createAudioPlayer,exports.createAudioRecorder=u.createAudioRecorder,exports.createAuthStore=Zr.createAuthStore,exports.createBarcodeDetector=d.createBarcodeDetector,exports.createColorScale=J.createColorScale,exports.createDataProvider=vi.createDataProvider,exports.createEventStream=wi.createEventStream,exports.createGrowthBookFeatureFlagsAdapter=_a.createGrowthBookFeatureFlagsAdapter,exports.createI18n=Gr.createI18n,exports.createInMemoryFlags=ga.createInMemoryFlags,exports.createInferenceProfiler=Sa.createInferenceProfiler,exports.createJsonStorage=Fr.createJsonStorage,exports.createLaunchDarklyFeatureFlagsAdapter=va.createLaunchDarklyFeatureFlagsAdapter,exports.createLevelMeter=mr.createLevelMeter,exports.createLinkStatsSampler=ea.createLinkStatsSampler,exports.createLocalUploadStorage=w.createLocalUploadStorage,exports.createLogger=da.createLogger,exports.createMediaRecorder=pr.createMediaRecorder,exports.createOSRMBackend=ia.createOSRMBackend,exports.createOfflineDatabase=Bi.createOfflineDatabase,exports.createOfflineStore=gi.createOfflineStore,exports.createOfflineSync=Vi.createOfflineSync,exports.createPartialResponse=L.createPartialResponse,exports.createPasskeyClient=T.createPasskeyClient,exports.createPeerMesh=ra.createPeerMesh,exports.createPositionTracker=aa.createPositionTracker,exports.createPostHogTelemetryAdapter=ha.createPostHogTelemetryAdapter,exports.createQueryKeys=ui.createQueryKeys,exports.createRefreshQueue=ti.createRefreshQueue,exports.createResumableUpload=w.createResumableUpload,exports.createRoleAccessControl=oi.createRoleAccessControl,exports.createSelectors=xi.createSelectors,exports.createSentryTelemetryAdapter=ma.createSentryTelemetryAdapter,exports.createSfxPool=ji.createSfxPool,exports.createStore=bi.createStore,exports.createTempestAuth=ni.createTempestAuth,exports.createTheme=la.createTheme,exports.createVideoRecorder=B.createVideoRecorder,exports.createVoiceChain=z.createVoiceChain,exports.createWebSocket=Xi.createWebSocket,exports.debounce=b.debounce,exports.decodeJWT=$r.decodeJWT,exports.decompressFromString=h.decompressFromString,exports.deepMerge=v.deepMerge,exports.defineRoutes=M.defineRoutes,exports.describeApiError=S.describeApiError,exports.describeFilter=p.describeFilter,exports.divergingScale=Z.divergingScale,exports.downloadCsv=Vr.downloadCsv,exports.emptyOffsetPage=O.emptyOffsetPage,exports.encodeQR=c.encodeQR,exports.encodeWav=vr.encodeWav,exports.estimatePasswordStrength=Vt.estimatePasswordStrength,exports.estimateStorage=o.estimateStorage,exports.estimateTravel=G.estimateTravel,exports.expandBounds=K.expandBounds,exports.filtersFromSearchParams=p.filtersFromSearchParams,exports.filtersToQueryParams=Pr.filtersToQueryParams,exports.filtersToSearchParams=p.filtersToSearchParams,exports.fitProjection=q.fitProjection,exports.formatBytes=s.formatBytes,exports.formatCEP=V.formatCEP,exports.formatCNPJ=V.formatCNPJ,exports.formatCPF=m.formatCPF,exports.formatCompactNumber=s.formatCompactNumber,exports.formatCurrency=m.formatCurrency,exports.formatDate=m.formatDate,exports.formatDateForInput=m.formatDateForInput,exports.formatDateTime=m.formatDateTime,exports.formatDateTimeForInput=m.formatDateTimeForInput,exports.formatDurationMs=xa.formatDurationMs,exports.formatPercent=m.formatPercent,exports.formatPhone=m.formatPhone,exports.generateIdempotencyKey=Yr.generateIdempotencyKey,exports.getInitialTheme=ua.getInitialTheme,exports.getSupportedBarcodeFormats=d.getSupportedBarcodeFormats,exports.getThemePreset=Y.getThemePreset,exports.groupBy=_.groupBy,exports.haversineKm=W.haversineKm,exports.hexToOklch=J.hexToOklch,exports.hexToRgb=J.hexToRgb,exports.hexToRgbaString=J.hexToRgbaString,exports.higherVersionWins=Hi.higherVersionWins,exports.inspectCaches=ki.inspectCaches,exports.installBackgroundSync=Di.installBackgroundSync,exports.installNotificationClickHandler=I.installNotificationClickHandler,exports.installPrecache=L.installPrecache,exports.installPushHandler=I.installPushHandler,exports.installRuntimeCache=L.installRuntimeCache,exports.installSkipWaitingListener=I.installSkipWaitingListener,exports.isAndroid=i.isAndroid,exports.isAndroidWithoutPromptApi=i.isAndroidWithoutPromptApi,exports.isApiError=x.isApiError,exports.isAudioOutputSelectionSupported=l.isAudioOutputSelectionSupported,exports.isAudioRecordingSupported=u.isAudioRecordingSupported,exports.isBarcodeDetectionSupported=d.isBarcodeDetectionSupported,exports.isConditionalMediationAvailable=T.isConditionalMediationAvailable,exports.isCoordinate=U.isCoordinate,exports.isCursorPage=O.isCursorPage,exports.isDefined=y.isDefined,exports.isEmpty=v.isEmpty,exports.isFullscreenSupported=Xe.isFullscreenSupported,exports.isGenerating=f.isGenerating,exports.isIOS=i.isIOS,exports.isJWTExpired=$r.isJWTExpired,exports.isMediaCaptureSupported=gr.isMediaCaptureSupported,exports.isNumber=y.isNumber,exports.isOffsetPage=O.isOffsetPage,exports.isPasskeySupported=T.isPasskeySupported,exports.isPlainObject=y.isPlainObject,exports.isPlatformAuthenticatorAvailable=T.isPlatformAuthenticatorAvailable,exports.isPushSupported=P.isPushSupported,exports.isRejectionCloseCode=Yi.isRejectionCloseCode,exports.isRetriableStatus=x.isRetriableStatus,exports.isScreenCaptureSupported=Ri.isScreenCaptureSupported,exports.isShareSupported=zr.isShareSupported,exports.isSpeechRecognitionSupported=zi.isSpeechRecognitionSupported,exports.isStandalone=i.isStandalone,exports.isString=y.isString,exports.isValidLatitude=U.isValidLatitude,exports.isValidLongitude=U.isValidLongitude,exports.isVideoRecordingSupported=B.isVideoRecordingSupported,exports.isVoiceChainIdle=z.isVoiceChainIdle,exports.kebabCase=g.kebabCase,exports.lastAssistantId=f.lastAssistantId,exports.lastWriteWins=Hi.lastWriteWins,exports.lazyWithRetry=ei.lazyWithRetry,exports.listQueryKey=j.listQueryKey,exports.matrixToPath=c.matrixToPath,exports.measureNoiseFloor=Fi.measureNoiseFloor,exports.memoizeOne=b.memoizeOne,exports.monitorVoiceActivity=Ii.monitorVoiceActivity,exports.monitorVoiceChain=z.monitorVoiceChain,exports.moveItem=Tt.moveItem,exports.normalizeBarcode=d.normalizeBarcode,exports.normalizeLongitude=U.normalizeLongitude,exports.nprogress=Rt.nprogress,exports.oklchToHex=J.oklchToHex,exports.omit=v.omit,exports.once=b.once,exports.oneQueryKey=j.oneQueryKey,exports.operatorsFor=p.operatorsFor,exports.parseResponse=qr.parseResponse,exports.pathLengthKm=W.pathLengthKm,exports.percentOf=s.percentOf,exports.permissionsFromToken=si.permissionsFromToken,exports.persistQueryClientOffline=_i.persistQueryClientOffline,exports.pick=v.pick,exports.pickAudioMimeType=u.pickAudioMimeType,exports.pickVideoMimeType=B.pickVideoMimeType,exports.playAudio=R.playAudio,exports.pluralize=g.pluralize,exports.projectMercator=q.projectMercator,exports.pushToTalkKeyLabel=n.pushToTalkKeyLabel,exports.randomId=Lr.randomId,exports.range=_.range,exports.readDeviceProfile=ba.readDeviceProfile,exports.readRoundTripMs=ea.readRoundTripMs,exports.readThemeToken=ca.readThemeToken,exports.readableForeground=J.readableForeground,Object.defineProperty(exports,"redirect",{enumerable:!0,get:function(){return Q.redirect}}),exports.registerPeriodicSync=Oi.registerPeriodicSync,exports.registerServiceWorker=a.registerServiceWorker,exports.relativeLuminance=J.relativeLuminance,exports.relativeTime=vn.relativeTime,exports.removeById=k.removeById,exports.requestPersistentStorage=o.requestPersistentStorage,exports.resolveDegradation=na.resolveDegradation,exports.retry=Ur.retry,exports.rgbToHex=J.rgbToHex,exports.roleLabel=f.roleLabel,exports.scaleForRoom=na.scaleForRoom,exports.scaleSteps=Z.scaleSteps,exports.sequentialScale=Z.sequentialScale,exports.setAudioOutput=l.setAudioOutput,exports.setSenderBitrate=$i.setSenderBitrate,exports.setTunedLocalDescription=Qi.setTunedLocalDescription,exports.share=zr.share,exports.shareOrDownloadBlob=Br.shareOrDownloadBlob,exports.shouldRetryQuery=di.shouldRetryQuery,exports.skipWaiting=a.skipWaiting,exports.sleep=Ir.sleep,exports.slugify=g.slugify,exports.stopAudio=R.stopAudio,exports.storage=Fr.storage,exports.suggestGateThreshold=Fi.suggestGateThreshold,exports.tailSignature=f.tailSignature,exports.themeContrast=la.themeContrast,exports.themeInitScript=ua.themeInitScript,exports.themePresets=Y.themePresets,exports.throttle=b.throttle,exports.toCsv=Vr.toCsv,exports.toRadians=W.toRadians,exports.truncate=g.truncate,exports.tuneOpus=Qi.tuneOpus,exports.turnTime=f.turnTime,exports.uniqueBy=_.uniqueBy,exports.unmask=V.unmask,exports.unprojectMercator=q.unprojectMercator,exports.unregisterAllServiceWorkers=a.unregisterAllServiceWorkers,exports.uploadFingerprint=w.uploadFingerprint,exports.uploadWithProgress=Jr.uploadWithProgress,exports.upsertById=k.upsertById,exports.urlBase64ToUint8Array=P.urlBase64ToUint8Array,exports.useAccessControl=ri.useAccessControl,exports.useAnnounce=r.useAnnounce,exports.useAsync=He.useAsync,exports.useAudio=Ai.useAudio,exports.useAudioBus=Pi.useAudioBus,exports.useAudioRecorder=hr.useAudioRecorder,exports.useBarcodeScanner=xr.useBarcodeScanner,exports.useBeforeInstallPrompt=je.useBeforeInstallPrompt,exports.useBreakpoint=ie.useBreakpoint,exports.useCan=ii.useCan,exports.useClickOutside=yt.useClickOutside,exports.useClientFilter=Ie.useClientFilter,exports.useClipboard=qe.useClipboard,exports.useCountdown=ft.useCountdown,exports.useCounter=dt.useCounter,exports.useCreate=j.useCreate,exports.useCursorQuery=mi.useCursorQuery,exports.useDataProvider=A.useDataProvider,exports.useDebounce=Pe.useDebounce,exports.useDeepMemo=tt.useDeepMemo,exports.useDelete=j.useDelete,exports.useDescribeApiError=Kr.useDescribeApiError,exports.useDisclosure=lt.useDisclosure,exports.useDocumentTitle=mt.useDocumentTitle,exports.useDocumentVisibility=We.useDocumentVisibility,exports.useErrorHandler=Ui.useErrorHandler,exports.useEventListener=ze.useEventListener,exports.useEventStream=Ti.useEventStream,exports.useFavicon=ht.useFavicon,exports.useFeatureFlag=X.useFeatureFlag,Object.defineProperty(exports,"useFieldArray",{enumerable:!0,get:function(){return $.useFieldArray}}),exports.useFlagValue=X.useFlagValue,exports.useFocusTrap=$e.useFocusTrap,Object.defineProperty(exports,"useForm",{enumerable:!0,get:function(){return $.useForm}}),Object.defineProperty(exports,"useFormContext",{enumerable:!0,get:function(){return $.useFormContext}}),Object.defineProperty(exports,"useFormState",{enumerable:!0,get:function(){return $.useFormState}}),exports.useFullscreen=Xe.useFullscreen,exports.useGeolocation=Ze.useGeolocation,exports.useHover=st.useHover,exports.useI18n=C.useI18n,exports.useIdle=Ye.useIdle,exports.useInstallPrompt=Ct.useInstallPrompt,exports.useIntersectionObserver=Ge.useIntersectionObserver,exports.useInterval=rt.useInterval,exports.useIsFirstRender=bt.useIsFirstRender,exports.useKeyboardShortcut=Je.useKeyboardShortcut,exports.useLatestRef=Re.useLatestRef,exports.useLinkStats=ta.useLinkStats,exports.useList=j.useList,exports.useListState=ut.useListState,exports.useLocalStorage=Be.useLocalStorage,Object.defineProperty(exports,"useLocation",{enumerable:!0,get:function(){return Q.useLocation}}),exports.useLongPress=ct.useLongPress,exports.useLongPressHandlers=St.useLongPressHandlers,exports.useMap=gt.useMap,Object.defineProperty(exports,"useMatch",{enumerable:!0,get:function(){return Q.useMatch}}),exports.useMediaDevices=Ot.useMediaDevices,exports.useMediaPermission=Dt.useMediaPermission,exports.useMediaQuery=Le.useMediaQuery,exports.useMicrophone=_r.useMicrophone,exports.useModals=It.useModals,Object.defineProperty(exports,"useNavigate",{enumerable:!0,get:function(){return Q.useNavigate}}),exports.useNotificationInbox=bn.useNotificationInbox,exports.useOAuthCallback=li.useOAuthCallback,exports.useObjectUrl=xt.useObjectUrl,exports.useOfflineMutation=hi.useOfflineMutation,exports.useOfflineSync=At.useOfflineSync,exports.useOne=j.useOne,exports.useOnline=Ue.useOnline,exports.useOptionalI18n=C.useOptionalI18n,exports.usePaginatedQuery=pi.usePaginatedQuery,exports.usePagination=Fe.usePagination,Object.defineProperty(exports,"useParams",{enumerable:!0,get:function(){return Q.useParams}}),exports.usePasskeyCapabilities=E.usePasskeyCapabilities,exports.usePasskeyRegistration=E.usePasskeyRegistration,exports.usePasskeySignIn=E.usePasskeySignIn,exports.usePoll=Xr.usePoll,exports.usePositionTracker=oa.usePositionTracker,exports.usePrevious=nt.usePrevious,exports.usePushSubscription=Ei.usePushSubscription,exports.usePushToTalk=n.usePushToTalk,exports.useQueue=vt.useQueue,exports.useResizeObserver=Ke.useResizeObserver,Object.defineProperty(exports,"useRouteError",{enumerable:!0,get:function(){return Q.useRouteError}}),exports.useScreenCapture=Ri.useScreenCapture,exports.useScrollLock=Qe.useScrollLock,exports.useScrollOverflow=Et.useScrollOverflow,Object.defineProperty(exports,"useSearchParams",{enumerable:!0,get:function(){return Q.useSearchParams}}),exports.useServiceWorkerUpdate=wt.useServiceWorkerUpdate,exports.useSet=_t.useSet,exports.useSfxPool=Mi.useSfxPool,exports.useSortable=Tt.useSortable,exports.useSpeechRecognition=zi.useSpeechRecognition,exports.useStableCallback=et.useStableCallback,exports.useStorageEstimate=o.useStorageEstimate,exports.useSyncStatus=At.useSyncStatus,exports.useTelemetry=fa.useTelemetry,exports.useTheme=N.useTheme,exports.useThrottle=at.useThrottle,exports.useTimeout=it.useTimeout,exports.useToast=mn.useToast,exports.useToggle=Ve.useToggle,exports.useTorch=br.useTorch,exports.useTranslate=C.useTranslate,exports.useTypewriter=pt.useTypewriter,exports.useUpdate=j.useUpdate,exports.useViaCEP=Ji.useViaCEP,exports.useVideoRecorder=Li.useVideoRecorder,Object.defineProperty(exports,"useWatch",{enumerable:!0,get:function(){return $.useWatch}}),exports.useWebSocket=Zi.useWebSocket,exports.useWindowSize=ot.useWindowSize,exports.useZodForm=qi.useZodForm,exports.validateCNPJ=V.validateCNPJ,exports.validateCPF=V.validateCPF,exports.validateForm=Gi.validateForm,exports.visibleTurns=f.visibleTurns,exports.withTimeout=Ir.withTimeout,exports.writeXlsx=Rr.writeXlsx,exports.zodResolver=Ki.zodResolver;
|
|
@@ -3728,6 +3728,33 @@ export declare interface CreatePasskeyClientOptions {
|
|
|
3728
3728
|
credentials?: CredentialsContainerLike;
|
|
3729
3729
|
}
|
|
3730
3730
|
|
|
3731
|
+
/**
|
|
3732
|
+
* One `RTCPeerConnection` per peer, with the slots negotiated up front.
|
|
3733
|
+
*
|
|
3734
|
+
* The signalling protocol stays yours: this produces and accepts three message
|
|
3735
|
+
* shapes (`offer`, `answer`, `ice`) and leaves delivery, room membership and
|
|
3736
|
+
* identity to your server. What it owns is the part that is the same in every
|
|
3737
|
+
* mesh and wrong in most of them — see {@link PeerMesh} for the traps each
|
|
3738
|
+
* method exists to avoid.
|
|
3739
|
+
*
|
|
3740
|
+
* @param options - See {@link PeerMeshOptions}.
|
|
3741
|
+
* @returns The mesh.
|
|
3742
|
+
*
|
|
3743
|
+
* @example
|
|
3744
|
+
* const mesh = createPeerMesh({
|
|
3745
|
+
* slots: [
|
|
3746
|
+
* { name: "mic", kind: "audio" },
|
|
3747
|
+
* { name: "cam", kind: "video" },
|
|
3748
|
+
* ],
|
|
3749
|
+
* send: (message) => socket.send(message),
|
|
3750
|
+
* onPeers: setPeers,
|
|
3751
|
+
* });
|
|
3752
|
+
* socket.onMessage = (message) => void mesh.accept(message);
|
|
3753
|
+
* await mesh.addPeer("peer-2", { offerer: true });
|
|
3754
|
+
* await mesh.setLocalTrack("mic", micTrack);
|
|
3755
|
+
*/
|
|
3756
|
+
export declare function createPeerMesh(options: PeerMeshOptions): PeerMesh;
|
|
3757
|
+
|
|
3731
3758
|
/**
|
|
3732
3759
|
* Record a live GPS trajectory from `navigator.geolocation.watchPosition`.
|
|
3733
3760
|
* Framework-free — the {@link usePositionTracker} hook wraps this for React.
|
|
@@ -8363,6 +8390,109 @@ export declare interface MercatorPoint {
|
|
|
8363
8390
|
y: number;
|
|
8364
8391
|
}
|
|
8365
8392
|
|
|
8393
|
+
/** A message the mesh produces and accepts. The transport is the caller's. */
|
|
8394
|
+
export declare type MeshMessage = {
|
|
8395
|
+
type: "offer";
|
|
8396
|
+
to: string;
|
|
8397
|
+
from?: string;
|
|
8398
|
+
sdp: string;
|
|
8399
|
+
} | {
|
|
8400
|
+
type: "answer";
|
|
8401
|
+
to: string;
|
|
8402
|
+
from?: string;
|
|
8403
|
+
sdp: string;
|
|
8404
|
+
} | {
|
|
8405
|
+
type: "ice";
|
|
8406
|
+
to: string;
|
|
8407
|
+
from?: string;
|
|
8408
|
+
candidate: string | null;
|
|
8409
|
+
sdpMid: string | null;
|
|
8410
|
+
sdpMLineIndex: number | null;
|
|
8411
|
+
};
|
|
8412
|
+
|
|
8413
|
+
/** One remote participant, as the mesh currently sees it. */
|
|
8414
|
+
export declare interface MeshPeer {
|
|
8415
|
+
/** The id the caller registered this peer under. */
|
|
8416
|
+
peerId: string;
|
|
8417
|
+
/** The connection's own state, straight from `RTCPeerConnection`. */
|
|
8418
|
+
connection: RTCPeerConnectionState;
|
|
8419
|
+
/** Inbound stream per slot name, `null` for a slot the peer is not sending. */
|
|
8420
|
+
streams: Record<string, MediaStream | null>;
|
|
8421
|
+
}
|
|
8422
|
+
|
|
8423
|
+
/** Encoder limits, before the room divides them. */
|
|
8424
|
+
export declare interface MeshQuality {
|
|
8425
|
+
/**
|
|
8426
|
+
* Cap per video slot, in kbps. `null` leaves that slot uncapped.
|
|
8427
|
+
*
|
|
8428
|
+
* Divided by the size of the room — see {@link PeerMesh.applyQuality}.
|
|
8429
|
+
*/
|
|
8430
|
+
video?: Record<string, number | null>;
|
|
8431
|
+
/**
|
|
8432
|
+
* Cap per audio slot, in **bps**, matching `setSenderBitrate`.
|
|
8433
|
+
*
|
|
8434
|
+
* Never divided. Audio is an order of magnitude cheaper than video and is
|
|
8435
|
+
* the part of a call that has to survive: dividing it buys back a few
|
|
8436
|
+
* percent of the uplink in exchange for the only thing everyone needs.
|
|
8437
|
+
*/
|
|
8438
|
+
audio?: Record<string, number>;
|
|
8439
|
+
/** Frame ceiling written onto every video encoding. */
|
|
8440
|
+
maxFramerate?: number;
|
|
8441
|
+
/** What a video encoder gives up first. */
|
|
8442
|
+
degradationPreference?: RTCDegradationPreference;
|
|
8443
|
+
/**
|
|
8444
|
+
* Total uplink to divide among the peers, in kbps.
|
|
8445
|
+
*
|
|
8446
|
+
* A mesh sends one copy of everything **per participant**, so a cap that is
|
|
8447
|
+
* comfortable one-to-one saturates a home connection with four people.
|
|
8448
|
+
*/
|
|
8449
|
+
uplinkBudgetKbps?: number;
|
|
8450
|
+
/**
|
|
8451
|
+
* Floor each video slot keeps after the division, in kbps.
|
|
8452
|
+
*
|
|
8453
|
+
* Dividing without a floor eventually allocates tens of kbps per stream,
|
|
8454
|
+
* which buys a blur that updates once a second: everybody loses the picture
|
|
8455
|
+
* instead of the excess giving way.
|
|
8456
|
+
*/
|
|
8457
|
+
minVideoKbps?: number;
|
|
8458
|
+
/**
|
|
8459
|
+
* Budget below which `maintain-framerate` is overridden.
|
|
8460
|
+
*
|
|
8461
|
+
* Somebody who asked for fluidity wants a good picture in motion, not the
|
|
8462
|
+
* number 60. Once the share of the uplink is this small, holding the frame
|
|
8463
|
+
* rate halves what each frame gets and the result is worse than the lower
|
|
8464
|
+
* rate it replaced.
|
|
8465
|
+
*/
|
|
8466
|
+
fluidFloorKbps?: number;
|
|
8467
|
+
}
|
|
8468
|
+
|
|
8469
|
+
/**
|
|
8470
|
+
* One media lane, negotiated once and reused for the life of the link.
|
|
8471
|
+
*
|
|
8472
|
+
* The order of the slot list is the wire protocol: the offerer allocates one
|
|
8473
|
+
* m-line per slot in this order, so a slot's `mid` is its ordinal and both ends
|
|
8474
|
+
* read the same identity off it. Reorder the list and the two sides disagree
|
|
8475
|
+
* about which lane carries the camera.
|
|
8476
|
+
*/
|
|
8477
|
+
export declare interface MeshSlot {
|
|
8478
|
+
/** Stable name the caller uses in {@link PeerMesh.setLocalTrack}. */
|
|
8479
|
+
name: string;
|
|
8480
|
+
/** Whether the lane carries audio or video. */
|
|
8481
|
+
kind: MeshSlotKind;
|
|
8482
|
+
}
|
|
8483
|
+
|
|
8484
|
+
/** What a slot carries. */
|
|
8485
|
+
export declare type MeshSlotKind = "audio" | "video";
|
|
8486
|
+
|
|
8487
|
+
/**
|
|
8488
|
+
* The single state a call badge shows.
|
|
8489
|
+
*
|
|
8490
|
+
* `connected` covers being alone in the room: a mesh with no peers has nothing
|
|
8491
|
+
* to connect to and is not failing, which is the case a naive "any link
|
|
8492
|
+
* connected?" check reports as broken for as long as nobody else joins.
|
|
8493
|
+
*/
|
|
8494
|
+
export declare type MeshState = "connecting" | "connected" | "reconnecting" | "failed" | "closed";
|
|
8495
|
+
|
|
8366
8496
|
export declare type Messages = Record<string, string>;
|
|
8367
8497
|
|
|
8368
8498
|
/** Lifecycle of a microphone stream. */
|
|
@@ -9811,6 +9941,87 @@ export declare interface PcmAudio {
|
|
|
9811
9941
|
sampleRate: number;
|
|
9812
9942
|
}
|
|
9813
9943
|
|
|
9944
|
+
/** A running mesh. */
|
|
9945
|
+
export declare interface PeerMesh {
|
|
9946
|
+
/**
|
|
9947
|
+
* Open a link to a peer.
|
|
9948
|
+
*
|
|
9949
|
+
* `offerer` decides which side sends the offer, and exactly one side of each
|
|
9950
|
+
* link must say `true`. Drive it from the arrival order your server already
|
|
9951
|
+
* imposes — the peer that joined **later** offers, the one already in the
|
|
9952
|
+
* room answers. That avoids glare by construction, without the rollback
|
|
9953
|
+
* dance of perfect negotiation and without depending on a browser
|
|
9954
|
+
* implementing argument-less `setLocalDescription`.
|
|
9955
|
+
*/
|
|
9956
|
+
addPeer: (peerId: string, options: {
|
|
9957
|
+
offerer: boolean;
|
|
9958
|
+
}) => Promise<void>;
|
|
9959
|
+
/** Close one link and give its share of the uplink back to the others. */
|
|
9960
|
+
removePeer: (peerId: string) => void;
|
|
9961
|
+
/** Feed the mesh an `offer`, `answer` or `ice` message from `from`. */
|
|
9962
|
+
accept: (message: MeshMessage & {
|
|
9963
|
+
from: string;
|
|
9964
|
+
}) => Promise<void>;
|
|
9965
|
+
/**
|
|
9966
|
+
* Publish or retract one slot across every live link.
|
|
9967
|
+
*
|
|
9968
|
+
* `null` retracts: the sender keeps its negotiated transceiver and stops
|
|
9969
|
+
* producing, which is what mutes a microphone without disturbing the other
|
|
9970
|
+
* slots or the connection. Nothing renegotiates — the m-lines were allocated
|
|
9971
|
+
* before any track existed, which is what makes a mesh survive toggling: a
|
|
9972
|
+
* renegotiation per toggle is N-1 simultaneous offer/answer rounds every time
|
|
9973
|
+
* somebody unmutes.
|
|
9974
|
+
*/
|
|
9975
|
+
setLocalTrack: (slot: string, track: MediaStreamTrack | null) => Promise<void>;
|
|
9976
|
+
/** Apply encoder limits, divided by the current size of the room. */
|
|
9977
|
+
applyQuality: (quality: MeshQuality) => Promise<void>;
|
|
9978
|
+
/** Replace the ICE servers used for links opened from now on. */
|
|
9979
|
+
setIceServers: (servers: RTCIceServer[]) => void;
|
|
9980
|
+
/** Close every link and report `closed`. */
|
|
9981
|
+
stop: () => void;
|
|
9982
|
+
/** The peers as the mesh currently sees them. */
|
|
9983
|
+
readonly peers: MeshPeer[];
|
|
9984
|
+
}
|
|
9985
|
+
|
|
9986
|
+
/** Options for `createPeerMesh`. */
|
|
9987
|
+
export declare interface PeerMeshOptions {
|
|
9988
|
+
/** The lanes every link negotiates, in the order they are allocated. */
|
|
9989
|
+
slots: readonly MeshSlot[];
|
|
9990
|
+
/** Send one message to the peer named by `to`. The transport is yours. */
|
|
9991
|
+
send: (message: MeshMessage) => void;
|
|
9992
|
+
/** ICE servers for every connection this mesh opens. */
|
|
9993
|
+
iceServers?: RTCIceServer[];
|
|
9994
|
+
/** Called whenever the peer list or any peer's streams change. */
|
|
9995
|
+
onPeers?: (peers: MeshPeer[]) => void;
|
|
9996
|
+
/** Called when the aggregate state changes, with an optional detail. */
|
|
9997
|
+
onState?: (state: MeshState, detail?: string) => void;
|
|
9998
|
+
/** Called for a failure worth surfacing that is not fatal to the mesh. */
|
|
9999
|
+
onNotice?: (reason: string) => void;
|
|
10000
|
+
/** Initial encoder limits. */
|
|
10001
|
+
quality?: MeshQuality;
|
|
10002
|
+
/**
|
|
10003
|
+
* Applies a local description, so the SDP can be rewritten on the way out.
|
|
10004
|
+
*
|
|
10005
|
+
* Defaults to `connection.setLocalDescription(description)`. The reason it
|
|
10006
|
+
* is a seam is `setTunedLocalDescription`: the mesh is what creates every
|
|
10007
|
+
* offer and answer, so without a hook here there is nowhere left to put the
|
|
10008
|
+
* Opus rewrite, and a call that adopts the mesh silently loses the bitrate
|
|
10009
|
+
* and channel layout it had negotiated before.
|
|
10010
|
+
*
|
|
10011
|
+
* Profiles are keyed by **audio m-line position**, which is legitimate for
|
|
10012
|
+
* exactly the reason slot routing is: the slot list fixes the order, so the
|
|
10013
|
+
* first audio slot is always the first audio m-line.
|
|
10014
|
+
*
|
|
10015
|
+
* @example
|
|
10016
|
+
* setLocalDescription: (connection, description) =>
|
|
10017
|
+
* setTunedLocalDescription(connection, description, {
|
|
10018
|
+
* 0: MIC_PROFILE,
|
|
10019
|
+
* 1: SYSTEM_AUDIO_PROFILE,
|
|
10020
|
+
* }),
|
|
10021
|
+
*/
|
|
10022
|
+
setLocalDescription?: (connection: RTCPeerConnection, description: RTCSessionDescriptionInit) => Promise<unknown>;
|
|
10023
|
+
}
|
|
10024
|
+
|
|
9814
10025
|
/**
|
|
9815
10026
|
* What percentage of `total` is `part`, with an empty base yielding `0`.
|
|
9816
10027
|
*
|
|
@@ -10834,6 +11045,22 @@ export declare interface ResizableProps extends Omit<HTMLAttributes<HTMLDivEleme
|
|
|
10834
11045
|
children: [ReactNode, ReactNode];
|
|
10835
11046
|
}
|
|
10836
11047
|
|
|
11048
|
+
/**
|
|
11049
|
+
* Decide what the encoder gives up, letting physics override the preference.
|
|
11050
|
+
*
|
|
11051
|
+
* `maintain-framerate` is honoured while there are bits enough for the frames to
|
|
11052
|
+
* be worth keeping. Once the room's division has taken the budget below the
|
|
11053
|
+
* fluid floor, holding the rate halves what each frame receives and the picture
|
|
11054
|
+
* is worse than the lower rate it replaced — so below that line the preference
|
|
11055
|
+
* is overridden rather than obeyed.
|
|
11056
|
+
*
|
|
11057
|
+
* @param quality - What was asked for.
|
|
11058
|
+
* @param effective - What the room's share actually allows.
|
|
11059
|
+
* @returns The degradation preference to write onto the senders, or `undefined`
|
|
11060
|
+
* when the caller expressed no preference.
|
|
11061
|
+
*/
|
|
11062
|
+
export declare function resolveDegradation(quality: MeshQuality, effective: MeshQuality): RTCDegradationPreference | undefined;
|
|
11063
|
+
|
|
10837
11064
|
export declare type ResolvedTheme = "light" | "dark";
|
|
10838
11065
|
|
|
10839
11066
|
/**
|
|
@@ -11183,6 +11410,26 @@ export declare interface SafeAreaProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
11183
11410
|
children?: ReactNode;
|
|
11184
11411
|
}
|
|
11185
11412
|
|
|
11413
|
+
/**
|
|
11414
|
+
* Divide the video caps by the size of the room.
|
|
11415
|
+
*
|
|
11416
|
+
* A mesh sends one copy of everything per participant, so the uplink is the
|
|
11417
|
+
* shared resource and the caps are what compete for it. Nothing is divided while
|
|
11418
|
+
* the caller is alone with one peer — that is the case the largest sizes exist
|
|
11419
|
+
* for, and dividing a budget that is not being shared would make them
|
|
11420
|
+
* unreachable in the only call where they fit.
|
|
11421
|
+
*
|
|
11422
|
+
* The floor is what keeps the division honest: without it a busy room allocates
|
|
11423
|
+
* tens of kbps per stream, and everybody loses the picture instead of the excess
|
|
11424
|
+
* giving way.
|
|
11425
|
+
*
|
|
11426
|
+
* @param quality - The caps as asked for.
|
|
11427
|
+
* @param peers - How many links are live.
|
|
11428
|
+
* @returns The caps to actually apply. The input is never mutated, so a room
|
|
11429
|
+
* that empties out climbs back to what was asked for.
|
|
11430
|
+
*/
|
|
11431
|
+
export declare function scaleForRoom(quality: MeshQuality, peers: number): MeshQuality;
|
|
11432
|
+
|
|
11186
11433
|
/** The ten steps of a Tempest tint scale, lightest to darkest. */
|
|
11187
11434
|
export declare type ScaleStep = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
|
|
11188
11435
|
|
|
@@ -315,32 +315,34 @@ import { setTunedLocalDescription as tc, tuneOpus as nc } from "./webrtc/opus-sd
|
|
|
315
315
|
import { setSenderBitrate as rc } from "./webrtc/sender-bitrate.js";
|
|
316
316
|
import { createLinkStatsSampler as ic, readRoundTripMs as ac } from "./webrtc/link-stats.js";
|
|
317
317
|
import { useLinkStats as oc } from "./webrtc/use-link-stats.js";
|
|
318
|
-
import {
|
|
319
|
-
import {
|
|
320
|
-
import {
|
|
321
|
-
import {
|
|
322
|
-
import {
|
|
323
|
-
import {
|
|
324
|
-
import {
|
|
325
|
-
import {
|
|
326
|
-
import {
|
|
327
|
-
import {
|
|
328
|
-
import {
|
|
329
|
-
import {
|
|
330
|
-
import {
|
|
331
|
-
import {
|
|
332
|
-
import {
|
|
333
|
-
import {
|
|
334
|
-
import {
|
|
335
|
-
import {
|
|
336
|
-
import {
|
|
337
|
-
import {
|
|
338
|
-
import {
|
|
339
|
-
import {
|
|
340
|
-
import {
|
|
341
|
-
import {
|
|
342
|
-
import {
|
|
343
|
-
import {
|
|
344
|
-
import {
|
|
345
|
-
import {
|
|
346
|
-
export { Ir as AIChat, Nr as AIChatComposer, Fr as AIChatTurn, _r as ALL_BARCODE_FORMATS, qi as API_ERROR_OFFLINE_KEY, Ji as API_ERROR_VALIDATION_KEY, or as AUDIO_MIME_CANDIDATES, Aa as AccessControlProvider, t as Accordion, n as Alert, r as AppBar, Fo as AppProviders, fo as AppRouter, o as AppShell, s as AspectRatio, ir as AudioPlayer, gr as AudioRecorder, fa as AuthGuard, c as Avatar, l as AvatarGroup, i as BREAKPOINTS, u as Badge, d as Banner, Vr as BarList, Tr as BarcodeScanner, f as BottomNavigation, p as BottomSheet, m as Breadcrumbs, mo as BrowserRouter, h as Button, Ra as CACHE_TIME, Rs as CEPInput, zs as CNPJInput, Bs as CPFInput, Rn as Calendar, Na as Can, g as Card, Wn as Carousel, _ as Center, tr as Chat, er as ChatComposer, v as Checkbox, y as ChipInput, xn as ClickOutside, hn as CodeBlock, Mn as Collapsible, b as Combobox, Fn as Command, Sn as ConditionalWrapper, S as ConfirmDialog, I as Container, Nn as ContextMenu, Ws as Controller, mn as CopyButton, Yi as DEFAULT_API_ERROR_STRINGS, vr as DEFAULT_BARCODE_FORMATS, _c as DEFAULT_CAR_SPEED_KMH, oa as DEFAULT_CHUNK_SIZE, vc as DEFAULT_CIRCUITY_FACTOR, os as DEFAULT_MAX_GAIN, yc as DEFAULT_MODE_DURATION_FACTORS, _a as DEFAULT_PUB_KEY_CRED_PARAMS, oe as DEFAULT_PUSH_TO_TALK_KEY, ls as DEFAULT_VOICE_CHAIN, sl as DIVERGING_STEP_COUNT, En as DataList, Gn as DataTable, w as DatePicker, Vn as DateRangePicker, Dn as DescriptionList, T as Divider, E as Drawer, D as DropdownMenu, O as Dropzone, fc as EARTH_RADIUS_KM, k as EmptyState, Po as ErrorBoundary, A as ErrorState, wn as ErrorText, tl as FeatureFlagsProvider, j as FileUpload, Kr as FilterBar, qn as FloatingActionButton, Cn as For, M as Form, N as FormActions, ks as FormField, Gs as FormProvider, P as FormRow, F as FormSection, Ia as GoogleSignIn, L as Grid, Zs as HEARTBEAT_CLOSE_CODE, ho as HashRouter, Ot as Hide, Pn as HoverCard, Qi as I18nProvider, Tn as Image, en as ImageCropper, C as Input, B as InstallBanner, V as InstallButton, lt as Kanban, dt as Kbd, jn as Label, Qn as Lightbox, go as Link, Kn as ListTile, Pr as Markdown, Rr as Masonry, _o as MemoryRouter, Un as Menubar, x as Modal, ft as ModalsProvider, _n as Money, Vs as MoneyInput, Bn as MultiSelect, ht as NProgressBar, vo as NavLink, mt as Navbar, yo as Navigate, Hn as NavigationMenu, Jn as NavigationRail, an as NotificationCenter, cl as ORDINAL_START_STEP, rt as OfflineIndicator, bo as Outlet, se as PUSH_TO_TALK_KEYS, _t as Page, vt as Pagination, va as PasskeyError, yt as PasswordInput, Hs as PhoneInput, xt as PinInput, St as Popover, bn as Portal, Ct as Progress, un as QRCapacityError, pn as QRCode, Ua as QueryProvider, za as REFETCH_TIME, wt as Radio, Tt as RadioGroup, Et as RangeSlider, Dt as RatingStars, Xn as RefreshIndicator, gn as RelativeTime, Ln as Resizable, xo as Route, uo as RouteGuard, So as Routes, ll as SEQUENTIAL_STEP_COUNT, Ba as STALE_TIME, At as SafeArea, nn as Scheduler, In as ScrollArea, jt as SearchBar, Mt as SegmentedControl, Nt as Select, kt as Show, Pt as Sidebar, $n as SignaturePad, Ft as Skeleton, zn as Slider, It as Spacer, tn as Sparkline, Lt as Spinner, R as Stack, Rt as Stat, zt as Stepper, Wt as StepperInput, Gt as Switch, st as SyncStatusBadge, qt as Table, Jt as Tabs, Kt as Tag, Xc as TelemetryProvider, Hi as TempestApiError, to as TempestDataProvider, Yt as Textarea, Mo as ThemeProvider, Yn as TimePicker, Xt as Timeline, Qt as ToastProvider, On as Toggle, kn as ToggleGroup, An as ToggleGroupItem, Zt as Tooltip, zr as Tour, Ac as TrajectoryMap, Lr as Transfer, vn as TreeView, yn as TruncateText, ct as UpdatePrompt, sn as VirtualList, ln as VirtualTable, ot as VisuallyHidden, Bo as WebPushClient, Vo as WebPushPermissionDeniedError, Ho as WebPushUnsupportedError, Zn as Wizard, Er as aiChatStrings, pe as announce, ti as applyFilters, ut as applyKanbanMove, jc as applyTheme, Ci as assertNever, ya as base64UrlToBytes, pc as bearingDeg, mr as blobToWav, xc as boundingBox, Sc as boundsCenter, Vi as buildApiUrl, Br as buildBarListRows, ze as buildOpenInChromeIntent, ba as bytesToBase64Url, pl as cachedResponseBytes, li as camelCase, ui as capitalize, hi as chunk, Bt as clamp, sc as clampLatitude, xa as classifyPasskeyError, me as clearAnnouncer, Qo as clearCaches, e as cn, cn as compareValues, ai as compressToString, oi as compressedStorage, si as compressedStorageCodec, Jc as consoleSink, Qc as consoleTelemetryAdapter, Nc as contrastRatio, Ki as createApiClient, ss as createAudioBus, es as createAudioPlayer, sr as createAudioRecorder, da as createAuthStore, yr as createBarcodeDetector, Pc as createColorScale, eo as createDataProvider, Io as createEventStream, al as createGrowthBookFeatureFlagsAdapter, Zi as createI18n, il as createInMemoryFlags, gl as createInferenceProfiler, ri as createJsonStorage, ol as createLaunchDarklyFeatureFlagsAdapter, ur as createLevelMeter, ic as createLinkStatsSampler, sa as createLocalUploadStorage, Yc as createLogger, ar as createMediaRecorder, Dc as createOSRMBackend, ws as createOfflineDatabase, Qa as createOfflineStore, Ts as createOfflineSync, qo as createPartialResponse, Sa as createPasskeyClient, Oc as createPositionTracker, el as createPostHogTelemetryAdapter, Va as createQueryKeys, ga as createRefreshQueue, ca as createResumableUpload, Pa as createRoleAccessControl, jo as createSelectors, $c as createSentryTelemetryAdapter, is as createSfxPool, Ao as createStore, ka as createTempestAuth, Hc as createTheme, gs as createVideoRecorder, us as createVoiceChain, $s as createWebSocket, Oi as debounce, pa as decodeJWT, ci as decompressFromString, yi as deepMerge, po as defineRoutes, Xi as describeApiError, Hr as describeFilter, ul as divergingScale, zi as downloadCsv, Wa as emptyOffsetPage, dn as encodeQR, hr as encodeWav, bt as estimatePasswordStrength, Ye as estimateStorage, bc as estimateTravel, Cc as expandBounds, Ur as filtersFromSearchParams, ni as filtersToQueryParams, Wr as filtersToSearchParams, wc as fitProjection, Vt as formatBytes, Ns as formatCEP, Ps as formatCNPJ, qr as formatCPF, Ht as formatCompactNumber, Jr as formatCurrency, Yr as formatDate, Xr as formatDateForInput, Zr as formatDateTime, Qr as formatDateTimeForInput, hl as formatDurationMs, $r as formatPercent, ei as formatPhone, aa as generateIdempotencyKey, Kc as getInitialTheme, br as getSupportedBarcodeFormats, Wc as getThemePreset, gi as groupBy, mc as haversineKm, Fc as hexToOklch, Ic as hexToRgb, Lc as hexToRgbaString, Es as higherVersionWins, $o as inspectCaches, Xo as installBackgroundSync, Wo as installNotificationClickHandler, Jo as installPrecache, Go as installPushHandler, Yo as installRuntimeCache, Ko as installSkipWaitingListener, Be as isAndroid, Ve as isAndroidWithoutPromptApi, Ui as isApiError, nr as isAudioOutputSelectionSupported, cr as isAudioRecordingSupported, xr as isBarcodeDetectionSupported, Ca as isConditionalMediationAvailable, cc as isCoordinate, Ga as isCursorPage, wi as isDefined, bi as isEmpty, ie as isFullscreenSupported, Dr as isGenerating, He as isIOS, ma as isJWTExpired, fr as isMediaCaptureSupported, Ti as isNumber, Ka as isOffsetPage, wa as isPasskeySupported, Ei as isPlainObject, Ta as isPlatformAuthenticatorAvailable, Ro as isPushSupported, Qs as isRejectionCloseCode, Wi as isRetriableStatus, bs as isScreenCaptureSupported, Ii as isShareSupported, Ss as isSpeechRecognitionSupported, Ue as isStandalone, Di as isString, lc as isValidLatitude, uc as isValidLongitude, _s as isVideoRecordingSupported, ds as isVoiceChainIdle, di as kebabCase, Or as lastAssistantId, Ds as lastWriteWins, ha as lazyWithRetry, ro as listQueryKey, fn as matrixToPath, ps as measureNoiseFloor, ki as memoizeOne, hs as monitorVoiceActivity, fs as monitorVoiceChain, Qe as moveItem, Sr as normalizeBarcode, dc as normalizeLongitude, gt as nprogress, Rc as oklchToHex, xi as omit, Ai as once, io as oneQueryKey, Gr as operatorsFor, ra as parseResponse, hc as pathLengthKm, Ut as percentOf, Fa as permissionsFromToken, $a as persistQueryClientOffline, Si as pick, lr as pickAudioMimeType, vs as pickVideoMimeType, ts as playAudio, fi as pluralize, Tc as projectMercator, ce as pushToTalkKeyLabel, Pi as randomId, _i as range, ml as readDeviceProfile, ac as readRoundTripMs, Mc as readThemeToken, zc as readableForeground, Co as redirect, Zo as registerPeriodicSync, Ge as registerServiceWorker, Bc as relativeLuminance, rn as relativeTime, Xa as removeById, Xe as requestPersistentStorage, Gi as retry, Vc as rgbToHex, kr as roleLabel, dl as scaleSteps, fl as sequentialScale, rr as setAudioOutput, rc as setSenderBitrate, tc as setTunedLocalDescription, Li as share, Ri as shareOrDownloadBlob, Ha as shouldRetryQuery, Ke as skipWaiting, Mi as sleep, pi as slugify, ns as stopAudio, ii as storage, ms as suggestGateThreshold, Ar as tailSignature, Uc as themeContrast, qc as themeInitScript, Gc as themePresets, ji as throttle, Bi as toCsv, gc as toRadians, mi as truncate, nc as tuneOpus, jr as turnTime, vi as uniqueBy, Fs as unmask, Ec as unprojectMercator, qe as unregisterAllServiceWorkers, la as uploadFingerprint, ia as uploadWithProgress, Za as upsertById, zo as urlBase64ToUint8Array, ja as useAccessControl, he as useAnnounce, X as useAsync, rs as useAudio, cs as useAudioBus, dr as useAudioRecorder, wr as useBarcodeScanner, z as useBeforeInstallPrompt, a as useBreakpoint, Ma as useCan, Fe as useClickOutside, W as useClientFilter, te as useClipboard, Oe as useCountdown, De as useCounter, ao as useCreate, Ja as useCursorQuery, no as useDataProvider, H as useDebounce, _e as useDeepMemo, oo as useDelete, na as useDescribeApiError, Te as useDisclosure, Ae as useDocumentTitle, Q as useDocumentVisibility, Os as useErrorHandler, q as useEventListener, Lo as useEventStream, je as useFavicon, nl as useFeatureFlag, Ks as useFieldArray, rl as useFlagValue, fe as useFocusTrap, qs as useForm, Js as useFormContext, Ys as useFormState, ae as useFullscreen, ue as useGeolocation, Ce as useHover, $i as useI18n, re as useIdle, We as useInstallPrompt, $ as useIntersectionObserver, ye as useInterval, Ie as useIsFirstRender, ne as useKeyboardShortcut, K as useLatestRef, oc as useLinkStats, so as useList, Ee as useListState, J as useLocalStorage, wo as useLocation, we as useLongPress, Re as useLongPressHandlers, Me as useMap, To as useMatch, nt as useMediaDevices, tt as useMediaPermission, G as useMediaQuery, pr as useMicrophone, pt as useModals, Eo as useNavigate, on as useNotificationInbox, La as useOAuthCallback, Le as useObjectUrl, Ya as useOfflineMutation, it as useOfflineSync, co as useOne, Z as useOnline, ea as useOptionalI18n, qa as usePaginatedQuery, U as usePagination, Do as useParams, Ea as usePasskeyCapabilities, Da as usePasskeyRegistration, Oa as usePasskeySignIn, ua as usePoll, kc as usePositionTracker, ve as usePrevious, Uo as usePushSubscription, le as usePushToTalk, Pe as useQueue, ee as useResizeObserver, Oo as useRouteError, xs as useScreenCapture, de as useScrollLock, et as useScrollOverflow, ko as useSearchParams, Je as useServiceWorkerUpdate, Ne as useSet, as as useSfxPool, $e as useSortable, Cs as useSpeechRecognition, ge as useStableCallback, Ze as useStorageEstimate, at as useSyncStatus, Zc as useTelemetry, No as useTheme, xe as useThrottle, be as useTimeout, $t as useToast, Y as useToggle, Cr as useTorch, ta as useTranslate, ke as useTypewriter, lo as useUpdate, Us as useViaCEP, ys as useVideoRecorder, Xs as useWatch, ec as useWebSocket, Se as useWindowSize, Ms as useZodForm, Is as validateCNPJ, Ls as validateCPF, As as validateForm, Mr as visibleTurns, Ni as withTimeout, Fi as writeXlsx, js as zodResolver };
|
|
318
|
+
import { resolveDegradation as sc, scaleForRoom as cc } from "./webrtc/mesh-quality.js";
|
|
319
|
+
import { createPeerMesh as lc } from "./webrtc/peer-mesh.js";
|
|
320
|
+
import { clampLatitude as uc, isCoordinate as dc, isValidLatitude as fc, isValidLongitude as pc, normalizeLongitude as mc } from "./geo/types.js";
|
|
321
|
+
import { EARTH_RADIUS_KM as hc, bearingDeg as gc, haversineKm as _c, pathLengthKm as vc, toRadians as yc } from "./geo/distance.js";
|
|
322
|
+
import { DEFAULT_CAR_SPEED_KMH as bc, DEFAULT_CIRCUITY_FACTOR as xc, DEFAULT_MODE_DURATION_FACTORS as Sc, estimateTravel as Cc } from "./geo/estimate.js";
|
|
323
|
+
import { boundingBox as wc, boundsCenter as Tc, expandBounds as Ec } from "./geo/bounds.js";
|
|
324
|
+
import { fitProjection as Dc, projectMercator as Oc, unprojectMercator as kc } from "./geo/projection.js";
|
|
325
|
+
import { createOSRMBackend as Ac } from "./geo/routing.js";
|
|
326
|
+
import { createPositionTracker as jc } from "./geo/create-position-tracker.js";
|
|
327
|
+
import { usePositionTracker as Mc } from "./geo/use-position-tracker.js";
|
|
328
|
+
import { TrajectoryMap as Nc } from "./geo/TrajectoryMap.js";
|
|
329
|
+
import { applyTheme as Pc, readThemeToken as Fc } from "./theme/apply-theme.js";
|
|
330
|
+
import { contrastRatio as Ic, createColorScale as Lc, hexToOklch as Rc, hexToRgb as zc, hexToRgbaString as Bc, oklchToHex as Vc, readableForeground as Hc, relativeLuminance as Uc, rgbToHex as Wc } from "./theme/color.js";
|
|
331
|
+
import { createTheme as Gc, themeContrast as Kc } from "./theme/create-theme.js";
|
|
332
|
+
import { getThemePreset as qc, themePresets as Jc } from "./theme/theme-presets.js";
|
|
333
|
+
import { getInitialTheme as Yc, themeInitScript as Xc } from "./theme/initial-theme.js";
|
|
334
|
+
import { consoleSink as Zc, createLogger as Qc } from "./logger/logger.js";
|
|
335
|
+
import { TelemetryProvider as $c, useTelemetry as el } from "./telemetry/TelemetryProvider.js";
|
|
336
|
+
import { consoleTelemetryAdapter as tl } from "./telemetry/console-adapter.js";
|
|
337
|
+
import { createSentryTelemetryAdapter as nl } from "./telemetry/sentry-adapter.js";
|
|
338
|
+
import { createPostHogTelemetryAdapter as rl } from "./telemetry/posthog-adapter.js";
|
|
339
|
+
import { FeatureFlagsProvider as il, useFeatureFlag as al, useFlagValue as ol } from "./feature-flags/FeatureFlagsProvider.js";
|
|
340
|
+
import { createInMemoryFlags as sl } from "./feature-flags/in-memory-adapter.js";
|
|
341
|
+
import { createGrowthBookFeatureFlagsAdapter as cl } from "./feature-flags/growthbook-adapter.js";
|
|
342
|
+
import { createLaunchDarklyFeatureFlagsAdapter as ll } from "./feature-flags/launchdarkly-adapter.js";
|
|
343
|
+
import { DIVERGING_STEP_COUNT as ul, ORDINAL_START_STEP as dl, SEQUENTIAL_STEP_COUNT as fl, divergingScale as pl, scaleSteps as ml, sequentialScale as hl } from "./charts/scales.js";
|
|
344
|
+
import { cachedResponseBytes as gl } from "./perf/cache-size.js";
|
|
345
|
+
import { readDeviceProfile as _l } from "./perf/device.js";
|
|
346
|
+
import { formatDurationMs as vl } from "./perf/format.js";
|
|
347
|
+
import { createInferenceProfiler as yl } from "./perf/profiler.js";
|
|
348
|
+
export { Ir as AIChat, Nr as AIChatComposer, Fr as AIChatTurn, _r as ALL_BARCODE_FORMATS, qi as API_ERROR_OFFLINE_KEY, Ji as API_ERROR_VALIDATION_KEY, or as AUDIO_MIME_CANDIDATES, Aa as AccessControlProvider, t as Accordion, n as Alert, r as AppBar, Fo as AppProviders, fo as AppRouter, o as AppShell, s as AspectRatio, ir as AudioPlayer, gr as AudioRecorder, fa as AuthGuard, c as Avatar, l as AvatarGroup, i as BREAKPOINTS, u as Badge, d as Banner, Vr as BarList, Tr as BarcodeScanner, f as BottomNavigation, p as BottomSheet, m as Breadcrumbs, mo as BrowserRouter, h as Button, Ra as CACHE_TIME, Rs as CEPInput, zs as CNPJInput, Bs as CPFInput, Rn as Calendar, Na as Can, g as Card, Wn as Carousel, _ as Center, tr as Chat, er as ChatComposer, v as Checkbox, y as ChipInput, xn as ClickOutside, hn as CodeBlock, Mn as Collapsible, b as Combobox, Fn as Command, Sn as ConditionalWrapper, S as ConfirmDialog, I as Container, Nn as ContextMenu, Ws as Controller, mn as CopyButton, Yi as DEFAULT_API_ERROR_STRINGS, vr as DEFAULT_BARCODE_FORMATS, bc as DEFAULT_CAR_SPEED_KMH, oa as DEFAULT_CHUNK_SIZE, xc as DEFAULT_CIRCUITY_FACTOR, os as DEFAULT_MAX_GAIN, Sc as DEFAULT_MODE_DURATION_FACTORS, _a as DEFAULT_PUB_KEY_CRED_PARAMS, oe as DEFAULT_PUSH_TO_TALK_KEY, ls as DEFAULT_VOICE_CHAIN, ul as DIVERGING_STEP_COUNT, En as DataList, Gn as DataTable, w as DatePicker, Vn as DateRangePicker, Dn as DescriptionList, T as Divider, E as Drawer, D as DropdownMenu, O as Dropzone, hc as EARTH_RADIUS_KM, k as EmptyState, Po as ErrorBoundary, A as ErrorState, wn as ErrorText, il as FeatureFlagsProvider, j as FileUpload, Kr as FilterBar, qn as FloatingActionButton, Cn as For, M as Form, N as FormActions, ks as FormField, Gs as FormProvider, P as FormRow, F as FormSection, Ia as GoogleSignIn, L as Grid, Zs as HEARTBEAT_CLOSE_CODE, ho as HashRouter, Ot as Hide, Pn as HoverCard, Qi as I18nProvider, Tn as Image, en as ImageCropper, C as Input, B as InstallBanner, V as InstallButton, lt as Kanban, dt as Kbd, jn as Label, Qn as Lightbox, go as Link, Kn as ListTile, Pr as Markdown, Rr as Masonry, _o as MemoryRouter, Un as Menubar, x as Modal, ft as ModalsProvider, _n as Money, Vs as MoneyInput, Bn as MultiSelect, ht as NProgressBar, vo as NavLink, mt as Navbar, yo as Navigate, Hn as NavigationMenu, Jn as NavigationRail, an as NotificationCenter, dl as ORDINAL_START_STEP, rt as OfflineIndicator, bo as Outlet, se as PUSH_TO_TALK_KEYS, _t as Page, vt as Pagination, va as PasskeyError, yt as PasswordInput, Hs as PhoneInput, xt as PinInput, St as Popover, bn as Portal, Ct as Progress, un as QRCapacityError, pn as QRCode, Ua as QueryProvider, za as REFETCH_TIME, wt as Radio, Tt as RadioGroup, Et as RangeSlider, Dt as RatingStars, Xn as RefreshIndicator, gn as RelativeTime, Ln as Resizable, xo as Route, uo as RouteGuard, So as Routes, fl as SEQUENTIAL_STEP_COUNT, Ba as STALE_TIME, At as SafeArea, nn as Scheduler, In as ScrollArea, jt as SearchBar, Mt as SegmentedControl, Nt as Select, kt as Show, Pt as Sidebar, $n as SignaturePad, Ft as Skeleton, zn as Slider, It as Spacer, tn as Sparkline, Lt as Spinner, R as Stack, Rt as Stat, zt as Stepper, Wt as StepperInput, Gt as Switch, st as SyncStatusBadge, qt as Table, Jt as Tabs, Kt as Tag, $c as TelemetryProvider, Hi as TempestApiError, to as TempestDataProvider, Yt as Textarea, Mo as ThemeProvider, Yn as TimePicker, Xt as Timeline, Qt as ToastProvider, On as Toggle, kn as ToggleGroup, An as ToggleGroupItem, Zt as Tooltip, zr as Tour, Nc as TrajectoryMap, Lr as Transfer, vn as TreeView, yn as TruncateText, ct as UpdatePrompt, sn as VirtualList, ln as VirtualTable, ot as VisuallyHidden, Bo as WebPushClient, Vo as WebPushPermissionDeniedError, Ho as WebPushUnsupportedError, Zn as Wizard, Er as aiChatStrings, pe as announce, ti as applyFilters, ut as applyKanbanMove, Pc as applyTheme, Ci as assertNever, ya as base64UrlToBytes, gc as bearingDeg, mr as blobToWav, wc as boundingBox, Tc as boundsCenter, Vi as buildApiUrl, Br as buildBarListRows, ze as buildOpenInChromeIntent, ba as bytesToBase64Url, gl as cachedResponseBytes, li as camelCase, ui as capitalize, hi as chunk, Bt as clamp, uc as clampLatitude, xa as classifyPasskeyError, me as clearAnnouncer, Qo as clearCaches, e as cn, cn as compareValues, ai as compressToString, oi as compressedStorage, si as compressedStorageCodec, Zc as consoleSink, tl as consoleTelemetryAdapter, Ic as contrastRatio, Ki as createApiClient, ss as createAudioBus, es as createAudioPlayer, sr as createAudioRecorder, da as createAuthStore, yr as createBarcodeDetector, Lc as createColorScale, eo as createDataProvider, Io as createEventStream, cl as createGrowthBookFeatureFlagsAdapter, Zi as createI18n, sl as createInMemoryFlags, yl as createInferenceProfiler, ri as createJsonStorage, ll as createLaunchDarklyFeatureFlagsAdapter, ur as createLevelMeter, ic as createLinkStatsSampler, sa as createLocalUploadStorage, Qc as createLogger, ar as createMediaRecorder, Ac as createOSRMBackend, ws as createOfflineDatabase, Qa as createOfflineStore, Ts as createOfflineSync, qo as createPartialResponse, Sa as createPasskeyClient, lc as createPeerMesh, jc as createPositionTracker, rl as createPostHogTelemetryAdapter, Va as createQueryKeys, ga as createRefreshQueue, ca as createResumableUpload, Pa as createRoleAccessControl, jo as createSelectors, nl as createSentryTelemetryAdapter, is as createSfxPool, Ao as createStore, ka as createTempestAuth, Gc as createTheme, gs as createVideoRecorder, us as createVoiceChain, $s as createWebSocket, Oi as debounce, pa as decodeJWT, ci as decompressFromString, yi as deepMerge, po as defineRoutes, Xi as describeApiError, Hr as describeFilter, pl as divergingScale, zi as downloadCsv, Wa as emptyOffsetPage, dn as encodeQR, hr as encodeWav, bt as estimatePasswordStrength, Ye as estimateStorage, Cc as estimateTravel, Ec as expandBounds, Ur as filtersFromSearchParams, ni as filtersToQueryParams, Wr as filtersToSearchParams, Dc as fitProjection, Vt as formatBytes, Ns as formatCEP, Ps as formatCNPJ, qr as formatCPF, Ht as formatCompactNumber, Jr as formatCurrency, Yr as formatDate, Xr as formatDateForInput, Zr as formatDateTime, Qr as formatDateTimeForInput, vl as formatDurationMs, $r as formatPercent, ei as formatPhone, aa as generateIdempotencyKey, Yc as getInitialTheme, br as getSupportedBarcodeFormats, qc as getThemePreset, gi as groupBy, _c as haversineKm, Rc as hexToOklch, zc as hexToRgb, Bc as hexToRgbaString, Es as higherVersionWins, $o as inspectCaches, Xo as installBackgroundSync, Wo as installNotificationClickHandler, Jo as installPrecache, Go as installPushHandler, Yo as installRuntimeCache, Ko as installSkipWaitingListener, Be as isAndroid, Ve as isAndroidWithoutPromptApi, Ui as isApiError, nr as isAudioOutputSelectionSupported, cr as isAudioRecordingSupported, xr as isBarcodeDetectionSupported, Ca as isConditionalMediationAvailable, dc as isCoordinate, Ga as isCursorPage, wi as isDefined, bi as isEmpty, ie as isFullscreenSupported, Dr as isGenerating, He as isIOS, ma as isJWTExpired, fr as isMediaCaptureSupported, Ti as isNumber, Ka as isOffsetPage, wa as isPasskeySupported, Ei as isPlainObject, Ta as isPlatformAuthenticatorAvailable, Ro as isPushSupported, Qs as isRejectionCloseCode, Wi as isRetriableStatus, bs as isScreenCaptureSupported, Ii as isShareSupported, Ss as isSpeechRecognitionSupported, Ue as isStandalone, Di as isString, fc as isValidLatitude, pc as isValidLongitude, _s as isVideoRecordingSupported, ds as isVoiceChainIdle, di as kebabCase, Or as lastAssistantId, Ds as lastWriteWins, ha as lazyWithRetry, ro as listQueryKey, fn as matrixToPath, ps as measureNoiseFloor, ki as memoizeOne, hs as monitorVoiceActivity, fs as monitorVoiceChain, Qe as moveItem, Sr as normalizeBarcode, mc as normalizeLongitude, gt as nprogress, Vc as oklchToHex, xi as omit, Ai as once, io as oneQueryKey, Gr as operatorsFor, ra as parseResponse, vc as pathLengthKm, Ut as percentOf, Fa as permissionsFromToken, $a as persistQueryClientOffline, Si as pick, lr as pickAudioMimeType, vs as pickVideoMimeType, ts as playAudio, fi as pluralize, Oc as projectMercator, ce as pushToTalkKeyLabel, Pi as randomId, _i as range, _l as readDeviceProfile, ac as readRoundTripMs, Fc as readThemeToken, Hc as readableForeground, Co as redirect, Zo as registerPeriodicSync, Ge as registerServiceWorker, Uc as relativeLuminance, rn as relativeTime, Xa as removeById, Xe as requestPersistentStorage, sc as resolveDegradation, Gi as retry, Wc as rgbToHex, kr as roleLabel, cc as scaleForRoom, ml as scaleSteps, hl as sequentialScale, rr as setAudioOutput, rc as setSenderBitrate, tc as setTunedLocalDescription, Li as share, Ri as shareOrDownloadBlob, Ha as shouldRetryQuery, Ke as skipWaiting, Mi as sleep, pi as slugify, ns as stopAudio, ii as storage, ms as suggestGateThreshold, Ar as tailSignature, Kc as themeContrast, Xc as themeInitScript, Jc as themePresets, ji as throttle, Bi as toCsv, yc as toRadians, mi as truncate, nc as tuneOpus, jr as turnTime, vi as uniqueBy, Fs as unmask, kc as unprojectMercator, qe as unregisterAllServiceWorkers, la as uploadFingerprint, ia as uploadWithProgress, Za as upsertById, zo as urlBase64ToUint8Array, ja as useAccessControl, he as useAnnounce, X as useAsync, rs as useAudio, cs as useAudioBus, dr as useAudioRecorder, wr as useBarcodeScanner, z as useBeforeInstallPrompt, a as useBreakpoint, Ma as useCan, Fe as useClickOutside, W as useClientFilter, te as useClipboard, Oe as useCountdown, De as useCounter, ao as useCreate, Ja as useCursorQuery, no as useDataProvider, H as useDebounce, _e as useDeepMemo, oo as useDelete, na as useDescribeApiError, Te as useDisclosure, Ae as useDocumentTitle, Q as useDocumentVisibility, Os as useErrorHandler, q as useEventListener, Lo as useEventStream, je as useFavicon, al as useFeatureFlag, Ks as useFieldArray, ol as useFlagValue, fe as useFocusTrap, qs as useForm, Js as useFormContext, Ys as useFormState, ae as useFullscreen, ue as useGeolocation, Ce as useHover, $i as useI18n, re as useIdle, We as useInstallPrompt, $ as useIntersectionObserver, ye as useInterval, Ie as useIsFirstRender, ne as useKeyboardShortcut, K as useLatestRef, oc as useLinkStats, so as useList, Ee as useListState, J as useLocalStorage, wo as useLocation, we as useLongPress, Re as useLongPressHandlers, Me as useMap, To as useMatch, nt as useMediaDevices, tt as useMediaPermission, G as useMediaQuery, pr as useMicrophone, pt as useModals, Eo as useNavigate, on as useNotificationInbox, La as useOAuthCallback, Le as useObjectUrl, Ya as useOfflineMutation, it as useOfflineSync, co as useOne, Z as useOnline, ea as useOptionalI18n, qa as usePaginatedQuery, U as usePagination, Do as useParams, Ea as usePasskeyCapabilities, Da as usePasskeyRegistration, Oa as usePasskeySignIn, ua as usePoll, Mc as usePositionTracker, ve as usePrevious, Uo as usePushSubscription, le as usePushToTalk, Pe as useQueue, ee as useResizeObserver, Oo as useRouteError, xs as useScreenCapture, de as useScrollLock, et as useScrollOverflow, ko as useSearchParams, Je as useServiceWorkerUpdate, Ne as useSet, as as useSfxPool, $e as useSortable, Cs as useSpeechRecognition, ge as useStableCallback, Ze as useStorageEstimate, at as useSyncStatus, el as useTelemetry, No as useTheme, xe as useThrottle, be as useTimeout, $t as useToast, Y as useToggle, Cr as useTorch, ta as useTranslate, ke as useTypewriter, lo as useUpdate, Us as useViaCEP, ys as useVideoRecorder, Xs as useWatch, ec as useWebSocket, Se as useWindowSize, Ms as useZodForm, Is as validateCNPJ, Ls as validateCPF, As as validateForm, Mr as visibleTurns, Ni as withTimeout, Fi as writeXlsx, js as zodResolver };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./sender-bitrate.cjs");var t=6e3,n=300,r=900;function i(e,r){let i=e.video??{};if(r<=1)return e;let a=Object.values(i).reduce((e,t)=>e+(t??0),0);if(a===0)return e;let o=(e.uplinkBudgetKbps??t)/r;if(a<=o)return e;let s=e.minVideoKbps??n,c=o/a,l={};for(let[e,t]of Object.entries(i))l[e]=t===null?null:Math.max(s,Math.round(t*c));return{...e,video:l}}function a(e,t){let n=e.degradationPreference;if(n!==`maintain-framerate`)return n;let i=Object.values(t.video??{}).filter(e=>e!==null);return i.length===0?n:Math.max(...i)>=(e.fluidFloorKbps??r)?`maintain-framerate`:`maintain-resolution`}function o(e,t,n){let r=e.getParameters();if(t!==void 0&&(r.degradationPreference=t),n!==void 0)for(let e of r.encodings??[])e.maxFramerate=n;return r}async function s(t,n,r,i){for(let[a,s]of n.entries()){let n=t[a]?.sender;if(!n)continue;if(s.kind===`audio`){let t=r.audio?.[s.name];t!==void 0&&await e.setSenderBitrate(n,t);continue}let c=r.video?.[s.name];if(c!==void 0&&await e.setSenderBitrate(n,c===null?null:c*1e3),i!==void 0||r.maxFramerate!==void 0)try{await n.setParameters(o(n,i,r.maxFramerate))}catch{try{await n.setParameters(o(n,void 0,r.maxFramerate))}catch{}}}}exports.applyQualityToLink=s,exports.resolveDegradation=a,exports.scaleForRoom=i;
|
|
2
|
+
//# sourceMappingURL=mesh-quality.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mesh-quality.cjs","names":[],"sources":["../../src/webrtc/mesh-quality.ts"],"sourcesContent":["import { setSenderBitrate } from \"./sender-bitrate\";\nimport type { MeshQuality, MeshSlot } from \"./mesh-types\";\n\n/** Uplink assumed available when the caller names no budget, in kbps. */\nconst DEFAULT_UPLINK_BUDGET_KBPS = 6000;\n\n/** Floor a video slot keeps after the division, in kbps. */\nconst DEFAULT_MIN_VIDEO_KBPS = 300;\n\n/** Budget below which `maintain-framerate` stops being worth holding, in kbps. */\nconst DEFAULT_FLUID_FLOOR_KBPS = 900;\n\n/**\n * Divide the video caps by the size of the room.\n *\n * A mesh sends one copy of everything per participant, so the uplink is the\n * shared resource and the caps are what compete for it. Nothing is divided while\n * the caller is alone with one peer — that is the case the largest sizes exist\n * for, and dividing a budget that is not being shared would make them\n * unreachable in the only call where they fit.\n *\n * The floor is what keeps the division honest: without it a busy room allocates\n * tens of kbps per stream, and everybody loses the picture instead of the excess\n * giving way.\n *\n * @param quality - The caps as asked for.\n * @param peers - How many links are live.\n * @returns The caps to actually apply. The input is never mutated, so a room\n * that empties out climbs back to what was asked for.\n */\nexport function scaleForRoom(quality: MeshQuality, peers: number): MeshQuality {\n const video = quality.video ?? {};\n if (peers <= 1) return quality;\n\n const asked = Object.values(video).reduce<number>((sum, cap) => sum + (cap ?? 0), 0);\n if (asked === 0) return quality;\n\n const perPeer = (quality.uplinkBudgetKbps ?? DEFAULT_UPLINK_BUDGET_KBPS) / peers;\n if (asked <= perPeer) return quality;\n\n const floor = quality.minVideoKbps ?? DEFAULT_MIN_VIDEO_KBPS;\n const factor = perPeer / asked;\n const scaled: Record<string, number | null> = {};\n for (const [slot, cap] of Object.entries(video)) {\n scaled[slot] = cap === null ? null : Math.max(floor, Math.round(cap * factor));\n }\n return { ...quality, video: scaled };\n}\n\n/**\n * Decide what the encoder gives up, letting physics override the preference.\n *\n * `maintain-framerate` is honoured while there are bits enough for the frames to\n * be worth keeping. Once the room's division has taken the budget below the\n * fluid floor, holding the rate halves what each frame receives and the picture\n * is worse than the lower rate it replaced — so below that line the preference\n * is overridden rather than obeyed.\n *\n * @param quality - What was asked for.\n * @param effective - What the room's share actually allows.\n * @returns The degradation preference to write onto the senders, or `undefined`\n * when the caller expressed no preference.\n */\nexport function resolveDegradation(\n quality: MeshQuality,\n effective: MeshQuality,\n): RTCDegradationPreference | undefined {\n const asked = quality.degradationPreference;\n if (asked !== \"maintain-framerate\") return asked;\n\n const caps = Object.values(effective.video ?? {}).filter((cap): cap is number => cap !== null);\n if (caps.length === 0) return asked;\n\n const budget = Math.max(...caps);\n return budget >= (quality.fluidFloorKbps ?? DEFAULT_FLUID_FLOOR_KBPS)\n ? \"maintain-framerate\"\n : \"maintain-resolution\";\n}\n\n/**\n * Read a video sender's parameters back with the motion settings written on.\n *\n * Read fresh on every call because `setParameters` only accepts the object the\n * **same** sender's `getParameters` returned, so a rejected attempt cannot be\n * retried with the object that was rejected.\n *\n * @param sender - The video sender to read from.\n * @param degradation - What to give up first, or `undefined` to leave it alone.\n * @param fps - Frame ceiling, or `undefined` to leave it alone.\n * @returns Parameters ready to be written back to `sender`.\n */\nfunction videoParameters(\n sender: RTCRtpSender,\n degradation: RTCDegradationPreference | undefined,\n fps: number | undefined,\n): RTCRtpSendParameters {\n const params = sender.getParameters();\n if (degradation !== undefined) params.degradationPreference = degradation;\n if (fps !== undefined) {\n for (const encoding of params.encodings ?? []) encoding.maxFramerate = fps;\n }\n return params;\n}\n\n/**\n * Write the quality settings onto one link's senders.\n *\n * `degradationPreference` goes only on video: it describes trading resolution\n * against frame rate, which an audio sender has no analogue for, and some\n * browsers reject it outright there.\n *\n * The retry without `degradationPreference` is for Firefox, which rejects the\n * member entirely — sending both together would lose the frame-rate cap to an\n * objection about something else.\n *\n * @param transceivers - The link's transceivers, in slot order.\n * @param slots - The slot list those transceivers were allocated from.\n * @param effective - Caps after the room's division.\n * @param degradation - Already resolved against the fluid floor.\n */\nexport async function applyQualityToLink(\n transceivers: readonly RTCRtpTransceiver[],\n slots: readonly MeshSlot[],\n effective: MeshQuality,\n degradation: RTCDegradationPreference | undefined,\n): Promise<void> {\n for (const [index, slot] of slots.entries()) {\n const sender = transceivers[index]?.sender;\n if (!sender) continue;\n\n if (slot.kind === \"audio\") {\n const bps = effective.audio?.[slot.name];\n if (bps !== undefined) await setSenderBitrate(sender, bps);\n continue;\n }\n\n const kbps = effective.video?.[slot.name];\n if (kbps !== undefined) await setSenderBitrate(sender, kbps === null ? null : kbps * 1000);\n\n if (degradation === undefined && effective.maxFramerate === undefined) continue;\n try {\n await sender.setParameters(\n videoParameters(sender, degradation, effective.maxFramerate),\n );\n } catch {\n try {\n await sender.setParameters(\n videoParameters(sender, undefined, effective.maxFramerate),\n );\n } catch {\n /* the sender refused both; the bitrate cap above still applies */\n }\n }\n }\n}\n"],"mappings":"wCAIA,IAAM,EAA6B,IAG7B,EAAyB,IAGzB,EAA2B,IAoBjC,SAAgB,EAAa,EAAsB,EAA4B,CAC3E,IAAM,EAAQ,EAAQ,OAAS,CAAC,EAChC,GAAI,GAAS,EAAG,OAAO,EAEvB,IAAM,EAAQ,OAAO,OAAO,CAAK,CAAC,CAAC,QAAgB,EAAK,IAAQ,GAAO,GAAO,GAAI,CAAC,EACnF,GAAI,IAAU,EAAG,OAAO,EAExB,IAAM,GAAW,EAAQ,kBAAoB,GAA8B,EAC3E,GAAI,GAAS,EAAS,OAAO,EAE7B,IAAM,EAAQ,EAAQ,cAAgB,EAChC,EAAS,EAAU,EACnB,EAAwC,CAAC,EAC/C,IAAK,GAAM,CAAC,EAAM,KAAQ,OAAO,QAAQ,CAAK,EAC1C,EAAO,GAAQ,IAAQ,KAAO,KAAO,KAAK,IAAI,EAAO,KAAK,MAAM,EAAM,CAAM,CAAC,EAEjF,MAAO,CAAE,GAAG,EAAS,MAAO,CAAO,CACvC,CAgBA,SAAgB,EACZ,EACA,EACoC,CACpC,IAAM,EAAQ,EAAQ,sBACtB,GAAI,IAAU,qBAAsB,OAAO,EAE3C,IAAM,EAAO,OAAO,OAAO,EAAU,OAAS,CAAC,CAAC,CAAC,CAAC,OAAQ,GAAuB,IAAQ,IAAI,EAI7F,OAHI,EAAK,SAAW,EAAU,EAEf,KAAK,IAAI,GAAG,CACpB,IAAW,EAAQ,gBAAkB,GACtC,qBACA,qBACV,CAcA,SAAS,EACL,EACA,EACA,EACoB,CACpB,IAAM,EAAS,EAAO,cAAc,EAEpC,GADI,IAAgB,IAAA,KAAW,EAAO,sBAAwB,GAC1D,IAAQ,IAAA,GACR,IAAK,IAAM,KAAY,EAAO,WAAa,CAAC,EAAG,EAAS,aAAe,EAE3E,OAAO,CACX,CAkBA,eAAsB,EAClB,EACA,EACA,EACA,EACa,CACb,IAAK,GAAM,CAAC,EAAO,KAAS,EAAM,QAAQ,EAAG,CACzC,IAAM,EAAS,EAAa,EAAM,EAAE,OACpC,GAAI,CAAC,EAAQ,SAEb,GAAI,EAAK,OAAS,QAAS,CACvB,IAAM,EAAM,EAAU,QAAQ,EAAK,MAC/B,IAAQ,IAAA,IAAW,MAAM,EAAA,iBAAiB,EAAQ,CAAG,EACzD,QACJ,CAEA,IAAM,EAAO,EAAU,QAAQ,EAAK,MACpC,GAAI,IAAS,IAAA,IAAW,MAAM,EAAA,iBAAiB,EAAQ,IAAS,KAAO,KAAO,EAAO,GAAI,EAErF,IAAgB,IAAA,IAAa,EAAU,eAAiB,IAAA,GAC5D,GAAI,CACA,MAAM,EAAO,cACT,EAAgB,EAAQ,EAAa,EAAU,YAAY,CAC/D,CACJ,MAAQ,CACJ,GAAI,CACA,MAAM,EAAO,cACT,EAAgB,EAAQ,IAAA,GAAW,EAAU,YAAY,CAC7D,CACJ,MAAQ,CAER,CACJ,CACJ,CACJ"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { setSenderBitrate as e } from "./sender-bitrate.js";
|
|
2
|
+
//#region src/webrtc/mesh-quality.ts
|
|
3
|
+
var t = 6e3, n = 300, r = 900;
|
|
4
|
+
function i(e, r) {
|
|
5
|
+
let i = e.video ?? {};
|
|
6
|
+
if (r <= 1) return e;
|
|
7
|
+
let a = Object.values(i).reduce((e, t) => e + (t ?? 0), 0);
|
|
8
|
+
if (a === 0) return e;
|
|
9
|
+
let o = (e.uplinkBudgetKbps ?? t) / r;
|
|
10
|
+
if (a <= o) return e;
|
|
11
|
+
let s = e.minVideoKbps ?? n, c = o / a, l = {};
|
|
12
|
+
for (let [e, t] of Object.entries(i)) l[e] = t === null ? null : Math.max(s, Math.round(t * c));
|
|
13
|
+
return {
|
|
14
|
+
...e,
|
|
15
|
+
video: l
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function a(e, t) {
|
|
19
|
+
let n = e.degradationPreference;
|
|
20
|
+
if (n !== "maintain-framerate") return n;
|
|
21
|
+
let i = Object.values(t.video ?? {}).filter((e) => e !== null);
|
|
22
|
+
return i.length === 0 ? n : Math.max(...i) >= (e.fluidFloorKbps ?? r) ? "maintain-framerate" : "maintain-resolution";
|
|
23
|
+
}
|
|
24
|
+
function o(e, t, n) {
|
|
25
|
+
let r = e.getParameters();
|
|
26
|
+
if (t !== void 0 && (r.degradationPreference = t), n !== void 0) for (let e of r.encodings ?? []) e.maxFramerate = n;
|
|
27
|
+
return r;
|
|
28
|
+
}
|
|
29
|
+
async function s(t, n, r, i) {
|
|
30
|
+
for (let [a, s] of n.entries()) {
|
|
31
|
+
let n = t[a]?.sender;
|
|
32
|
+
if (!n) continue;
|
|
33
|
+
if (s.kind === "audio") {
|
|
34
|
+
let t = r.audio?.[s.name];
|
|
35
|
+
t !== void 0 && await e(n, t);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
let c = r.video?.[s.name];
|
|
39
|
+
if (c !== void 0 && await e(n, c === null ? null : c * 1e3), i !== void 0 || r.maxFramerate !== void 0) try {
|
|
40
|
+
await n.setParameters(o(n, i, r.maxFramerate));
|
|
41
|
+
} catch {
|
|
42
|
+
try {
|
|
43
|
+
await n.setParameters(o(n, void 0, r.maxFramerate));
|
|
44
|
+
} catch {}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { s as applyQualityToLink, a as resolveDegradation, i as scaleForRoom };
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=mesh-quality.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mesh-quality.js","names":[],"sources":["../../src/webrtc/mesh-quality.ts"],"sourcesContent":["import { setSenderBitrate } from \"./sender-bitrate\";\nimport type { MeshQuality, MeshSlot } from \"./mesh-types\";\n\n/** Uplink assumed available when the caller names no budget, in kbps. */\nconst DEFAULT_UPLINK_BUDGET_KBPS = 6000;\n\n/** Floor a video slot keeps after the division, in kbps. */\nconst DEFAULT_MIN_VIDEO_KBPS = 300;\n\n/** Budget below which `maintain-framerate` stops being worth holding, in kbps. */\nconst DEFAULT_FLUID_FLOOR_KBPS = 900;\n\n/**\n * Divide the video caps by the size of the room.\n *\n * A mesh sends one copy of everything per participant, so the uplink is the\n * shared resource and the caps are what compete for it. Nothing is divided while\n * the caller is alone with one peer — that is the case the largest sizes exist\n * for, and dividing a budget that is not being shared would make them\n * unreachable in the only call where they fit.\n *\n * The floor is what keeps the division honest: without it a busy room allocates\n * tens of kbps per stream, and everybody loses the picture instead of the excess\n * giving way.\n *\n * @param quality - The caps as asked for.\n * @param peers - How many links are live.\n * @returns The caps to actually apply. The input is never mutated, so a room\n * that empties out climbs back to what was asked for.\n */\nexport function scaleForRoom(quality: MeshQuality, peers: number): MeshQuality {\n const video = quality.video ?? {};\n if (peers <= 1) return quality;\n\n const asked = Object.values(video).reduce<number>((sum, cap) => sum + (cap ?? 0), 0);\n if (asked === 0) return quality;\n\n const perPeer = (quality.uplinkBudgetKbps ?? DEFAULT_UPLINK_BUDGET_KBPS) / peers;\n if (asked <= perPeer) return quality;\n\n const floor = quality.minVideoKbps ?? DEFAULT_MIN_VIDEO_KBPS;\n const factor = perPeer / asked;\n const scaled: Record<string, number | null> = {};\n for (const [slot, cap] of Object.entries(video)) {\n scaled[slot] = cap === null ? null : Math.max(floor, Math.round(cap * factor));\n }\n return { ...quality, video: scaled };\n}\n\n/**\n * Decide what the encoder gives up, letting physics override the preference.\n *\n * `maintain-framerate` is honoured while there are bits enough for the frames to\n * be worth keeping. Once the room's division has taken the budget below the\n * fluid floor, holding the rate halves what each frame receives and the picture\n * is worse than the lower rate it replaced — so below that line the preference\n * is overridden rather than obeyed.\n *\n * @param quality - What was asked for.\n * @param effective - What the room's share actually allows.\n * @returns The degradation preference to write onto the senders, or `undefined`\n * when the caller expressed no preference.\n */\nexport function resolveDegradation(\n quality: MeshQuality,\n effective: MeshQuality,\n): RTCDegradationPreference | undefined {\n const asked = quality.degradationPreference;\n if (asked !== \"maintain-framerate\") return asked;\n\n const caps = Object.values(effective.video ?? {}).filter((cap): cap is number => cap !== null);\n if (caps.length === 0) return asked;\n\n const budget = Math.max(...caps);\n return budget >= (quality.fluidFloorKbps ?? DEFAULT_FLUID_FLOOR_KBPS)\n ? \"maintain-framerate\"\n : \"maintain-resolution\";\n}\n\n/**\n * Read a video sender's parameters back with the motion settings written on.\n *\n * Read fresh on every call because `setParameters` only accepts the object the\n * **same** sender's `getParameters` returned, so a rejected attempt cannot be\n * retried with the object that was rejected.\n *\n * @param sender - The video sender to read from.\n * @param degradation - What to give up first, or `undefined` to leave it alone.\n * @param fps - Frame ceiling, or `undefined` to leave it alone.\n * @returns Parameters ready to be written back to `sender`.\n */\nfunction videoParameters(\n sender: RTCRtpSender,\n degradation: RTCDegradationPreference | undefined,\n fps: number | undefined,\n): RTCRtpSendParameters {\n const params = sender.getParameters();\n if (degradation !== undefined) params.degradationPreference = degradation;\n if (fps !== undefined) {\n for (const encoding of params.encodings ?? []) encoding.maxFramerate = fps;\n }\n return params;\n}\n\n/**\n * Write the quality settings onto one link's senders.\n *\n * `degradationPreference` goes only on video: it describes trading resolution\n * against frame rate, which an audio sender has no analogue for, and some\n * browsers reject it outright there.\n *\n * The retry without `degradationPreference` is for Firefox, which rejects the\n * member entirely — sending both together would lose the frame-rate cap to an\n * objection about something else.\n *\n * @param transceivers - The link's transceivers, in slot order.\n * @param slots - The slot list those transceivers were allocated from.\n * @param effective - Caps after the room's division.\n * @param degradation - Already resolved against the fluid floor.\n */\nexport async function applyQualityToLink(\n transceivers: readonly RTCRtpTransceiver[],\n slots: readonly MeshSlot[],\n effective: MeshQuality,\n degradation: RTCDegradationPreference | undefined,\n): Promise<void> {\n for (const [index, slot] of slots.entries()) {\n const sender = transceivers[index]?.sender;\n if (!sender) continue;\n\n if (slot.kind === \"audio\") {\n const bps = effective.audio?.[slot.name];\n if (bps !== undefined) await setSenderBitrate(sender, bps);\n continue;\n }\n\n const kbps = effective.video?.[slot.name];\n if (kbps !== undefined) await setSenderBitrate(sender, kbps === null ? null : kbps * 1000);\n\n if (degradation === undefined && effective.maxFramerate === undefined) continue;\n try {\n await sender.setParameters(\n videoParameters(sender, degradation, effective.maxFramerate),\n );\n } catch {\n try {\n await sender.setParameters(\n videoParameters(sender, undefined, effective.maxFramerate),\n );\n } catch {\n /* the sender refused both; the bitrate cap above still applies */\n }\n }\n }\n}\n"],"mappings":";;AAIA,IAAM,IAA6B,KAG7B,IAAyB,KAGzB,IAA2B;AAoBjC,SAAgB,EAAa,GAAsB,GAA4B;CAC3E,IAAM,IAAQ,EAAQ,SAAS,CAAC;CAChC,IAAI,KAAS,GAAG,OAAO;CAEvB,IAAM,IAAQ,OAAO,OAAO,CAAK,CAAC,CAAC,QAAgB,GAAK,MAAQ,KAAO,KAAO,IAAI,CAAC;CACnF,IAAI,MAAU,GAAG,OAAO;CAExB,IAAM,KAAW,EAAQ,oBAAoB,KAA8B;CAC3E,IAAI,KAAS,GAAS,OAAO;CAE7B,IAAM,IAAQ,EAAQ,gBAAgB,GAChC,IAAS,IAAU,GACnB,IAAwC,CAAC;CAC/C,KAAK,IAAM,CAAC,GAAM,MAAQ,OAAO,QAAQ,CAAK,GAC1C,EAAO,KAAQ,MAAQ,OAAO,OAAO,KAAK,IAAI,GAAO,KAAK,MAAM,IAAM,CAAM,CAAC;CAEjF,OAAO;EAAE,GAAG;EAAS,OAAO;CAAO;AACvC;AAgBA,SAAgB,EACZ,GACA,GACoC;CACpC,IAAM,IAAQ,EAAQ;CACtB,IAAI,MAAU,sBAAsB,OAAO;CAE3C,IAAM,IAAO,OAAO,OAAO,EAAU,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,MAAuB,MAAQ,IAAI;CAI7F,OAHI,EAAK,WAAW,IAAU,IAEf,KAAK,IAAI,GAAG,CACpB,MAAW,EAAQ,kBAAkB,KACtC,uBACA;AACV;AAcA,SAAS,EACL,GACA,GACA,GACoB;CACpB,IAAM,IAAS,EAAO,cAAc;CAEpC,IADI,MAAgB,KAAA,MAAW,EAAO,wBAAwB,IAC1D,MAAQ,KAAA,GACR,KAAK,IAAM,KAAY,EAAO,aAAa,CAAC,GAAG,EAAS,eAAe;CAE3E,OAAO;AACX;AAkBA,eAAsB,EAClB,GACA,GACA,GACA,GACa;CACb,KAAK,IAAM,CAAC,GAAO,MAAS,EAAM,QAAQ,GAAG;EACzC,IAAM,IAAS,EAAa,EAAM,EAAE;EACpC,IAAI,CAAC,GAAQ;EAEb,IAAI,EAAK,SAAS,SAAS;GACvB,IAAM,IAAM,EAAU,QAAQ,EAAK;GACnC,AAAI,MAAQ,KAAA,KAAW,MAAM,EAAiB,GAAQ,CAAG;GACzD;EACJ;EAEA,IAAM,IAAO,EAAU,QAAQ,EAAK;EACpC,IAAI,MAAS,KAAA,KAAW,MAAM,EAAiB,GAAQ,MAAS,OAAO,OAAO,IAAO,GAAI,GAErF,MAAgB,KAAA,KAAa,EAAU,iBAAiB,KAAA,GAC5D,IAAI;GACA,MAAM,EAAO,cACT,EAAgB,GAAQ,GAAa,EAAU,YAAY,CAC/D;EACJ,QAAQ;GACJ,IAAI;IACA,MAAM,EAAO,cACT,EAAgB,GAAQ,KAAA,GAAW,EAAU,YAAY,CAC7D;GACJ,QAAQ,CAER;EACJ;CACJ;AACJ"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function e(e){return new RTCPeerConnection({iceServers:e,bundlePolicy:`max-bundle`,rtcpMuxPolicy:`require`})}function t(e,t,n){let r=Number(e.mid);if(e.mid!==null&&Number.isInteger(r)&&n[r])return n[r];let i=t.transceivers.indexOf(e);return i>=0?n[i]??null:null}async function n(e){let t=e.pendingCandidates.splice(0,e.pendingCandidates.length);for(let n of t)try{await e.pc.addIceCandidate(n)}catch{}}async function r(e,t){if(!e.remoteReady){e.pendingCandidates.push(t);return}try{await e.pc.addIceCandidate(t)}catch{}}async function i(e,t,n){for(let[r,i]of t.entries()){let t=e.transceivers[r],a=n.get(i.name)??null;if(!(!t||!a))try{await t.sender.replaceTrack(a)}catch{}}}function a(e){e.transceivers=e.pc.getTransceivers().filter(e=>e.mid!==null).sort((e,t)=>Number(e.mid)-Number(t.mid));for(let t of e.transceivers)t.direction!==`sendrecv`&&(t.direction=`sendrecv`)}exports.acceptCandidate=r,exports.adoptTransceivers=a,exports.attachLocalTracks=i,exports.createPeerConnection=e,exports.drainCandidates=n,exports.slotOf=t;
|
|
2
|
+
//# sourceMappingURL=peer-link.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-link.cjs","names":[],"sources":["../../src/webrtc/peer-link.ts"],"sourcesContent":["import type { MeshSlot } from \"./mesh-types\";\n\n/** One remote peer's connection and everything the mesh tracks about it. */\nexport interface PeerLink {\n peerId: string;\n pc: RTCPeerConnection;\n /**\n * Transceivers in slot order.\n *\n * Held explicitly rather than re-read from `getTransceivers()` so slot\n * lookup stays O(1) and cannot drift if a browser reorders.\n */\n transceivers: RTCRtpTransceiver[];\n /** Candidates that arrived before the remote description they belong to. */\n pendingCandidates: RTCIceCandidateInit[];\n /** Whether `setRemoteDescription` has landed, which gates the queue. */\n remoteReady: boolean;\n /** Whether an offer is in flight, so a re-entrant call does not stack one. */\n makingOffer: boolean;\n /** Whether this side offers. Exactly one side of a link does. */\n isOfferer: boolean;\n}\n\n/** Open a connection with the policies a mesh needs. */\nexport function createPeerConnection(iceServers: RTCIceServer[]): RTCPeerConnection {\n return new RTCPeerConnection({\n iceServers,\n bundlePolicy: \"max-bundle\",\n rtcpMuxPolicy: \"require\",\n });\n}\n\n/**\n * Resolve which slot a transceiver carries.\n *\n * The offerer allocates the m-lines in slot order, so a transceiver's `mid` is\n * its ordinal and both ends read the same one. That makes `mid` the slot's wire\n * identity, and the **only** identifier correct on both sides of a link.\n *\n * Position in the link's own array is a fallback for a `mid` that is not a plain\n * ordinal, and never the primary: a browser answering an offer appends the\n * negotiated transceivers *after* any it already held, so positional lookup\n * silently resolves to the wrong slot — the camera arriving in the screen tile —\n * or to none at all, dropping the track.\n *\n * @param transceiver - The transceiver a track arrived on.\n * @param link - The link it belongs to.\n * @param slots - The mesh's slot list.\n * @returns The slot, or `null` when neither route names one.\n */\nexport function slotOf(\n transceiver: RTCRtpTransceiver,\n link: PeerLink,\n slots: readonly MeshSlot[],\n): MeshSlot | null {\n const ordinal = Number(transceiver.mid);\n if (transceiver.mid !== null && Number.isInteger(ordinal) && slots[ordinal]) {\n return slots[ordinal];\n }\n const index = link.transceivers.indexOf(transceiver);\n return index >= 0 ? (slots[index] ?? null) : null;\n}\n\n/**\n * Feed a link every candidate that arrived before its remote description.\n *\n * `addIceCandidate` throws while `remoteDescription` is `null`, and candidates\n * routinely beat the offer or answer they belong to. Without the queue the\n * connection loses them and sits in `checking` until it times out — a failure\n * with no error anywhere.\n *\n * @param link - The link whose queue is drained.\n */\nexport async function drainCandidates(link: PeerLink): Promise<void> {\n const queued = link.pendingCandidates.splice(0, link.pendingCandidates.length);\n for (const candidate of queued) {\n try {\n await link.pc.addIceCandidate(candidate);\n } catch {\n /* a candidate the browser rejects is not fatal to the connection */\n }\n }\n}\n\n/**\n * Hand a candidate to the connection, or park it until the description lands.\n *\n * @param link - The link the candidate belongs to.\n * @param init - The candidate, already in `RTCIceCandidateInit` shape.\n */\nexport async function acceptCandidate(link: PeerLink, init: RTCIceCandidateInit): Promise<void> {\n if (!link.remoteReady) {\n link.pendingCandidates.push(init);\n return;\n }\n try {\n await link.pc.addIceCandidate(init);\n } catch {\n /* a candidate the browser rejects is not fatal to the connection */\n }\n}\n\n/**\n * Publish every held local track onto a link's slots.\n *\n * Called once the transceivers exist — up front for the offerer, after the offer\n * lands for the answerer — so a microphone that was already live when the peer\n * joined starts flowing without waiting for a toggle.\n *\n * @param link - The link to publish onto.\n * @param slots - The mesh's slot list.\n * @param tracks - The current local track per slot name.\n */\nexport async function attachLocalTracks(\n link: PeerLink,\n slots: readonly MeshSlot[],\n tracks: Map<string, MediaStreamTrack | null>,\n): Promise<void> {\n for (const [index, slot] of slots.entries()) {\n const transceiver = link.transceivers[index];\n const track = tracks.get(slot.name) ?? null;\n if (!transceiver || !track) continue;\n try {\n await transceiver.sender.replaceTrack(track);\n } catch {\n /* the browser refused the track; the slot simply stays silent */\n }\n }\n}\n\n/**\n * Adopt the transceivers a remote offer created, in `mid` order.\n *\n * The answering side allocates **nothing** up front, and that is the whole\n * subtlety: applying a remote offer creates one transceiver per m-line, in\n * m-line order, and browsers do not reuse transceivers the answerer made\n * beforehand. Pre-allocating leaves dead, never-negotiated transceivers sitting\n * in front of the live ones, which is how slot lookup ends up pointing at the\n * wrong media or at nothing.\n *\n * Each adopted transceiver is switched to `sendrecv` so this side may publish on\n * it too; without that a peer that answered could hear but never be heard.\n *\n * @param link - The link that just applied a remote offer.\n */\nexport function adoptTransceivers(link: PeerLink): void {\n link.transceivers = link.pc\n .getTransceivers()\n .filter((transceiver) => transceiver.mid !== null)\n .sort((a, b) => Number(a.mid) - Number(b.mid));\n for (const transceiver of link.transceivers) {\n if (transceiver.direction !== \"sendrecv\") transceiver.direction = \"sendrecv\";\n }\n}\n"],"mappings":"AAwBA,SAAgB,EAAqB,EAA+C,CAChF,OAAO,IAAI,kBAAkB,CACzB,aACA,aAAc,aACd,cAAe,SACnB,CAAC,CACL,CAoBA,SAAgB,EACZ,EACA,EACA,EACe,CACf,IAAM,EAAU,OAAO,EAAY,GAAG,EACtC,GAAI,EAAY,MAAQ,MAAQ,OAAO,UAAU,CAAO,GAAK,EAAM,GAC/D,OAAO,EAAM,GAEjB,IAAM,EAAQ,EAAK,aAAa,QAAQ,CAAW,EACnD,OAAO,GAAS,EAAK,EAAM,IAAU,KAAQ,IACjD,CAYA,eAAsB,EAAgB,EAA+B,CACjE,IAAM,EAAS,EAAK,kBAAkB,OAAO,EAAG,EAAK,kBAAkB,MAAM,EAC7E,IAAK,IAAM,KAAa,EACpB,GAAI,CACA,MAAM,EAAK,GAAG,gBAAgB,CAAS,CAC3C,MAAQ,CAER,CAER,CAQA,eAAsB,EAAgB,EAAgB,EAA0C,CAC5F,GAAI,CAAC,EAAK,YAAa,CACnB,EAAK,kBAAkB,KAAK,CAAI,EAChC,MACJ,CACA,GAAI,CACA,MAAM,EAAK,GAAG,gBAAgB,CAAI,CACtC,MAAQ,CAER,CACJ,CAaA,eAAsB,EAClB,EACA,EACA,EACa,CACb,IAAK,GAAM,CAAC,EAAO,KAAS,EAAM,QAAQ,EAAG,CACzC,IAAM,EAAc,EAAK,aAAa,GAChC,EAAQ,EAAO,IAAI,EAAK,IAAI,GAAK,KACnC,MAAC,GAAe,CAAC,GACrB,GAAI,CACA,MAAM,EAAY,OAAO,aAAa,CAAK,CAC/C,MAAQ,CAER,CACJ,CACJ,CAiBA,SAAgB,EAAkB,EAAsB,CACpD,EAAK,aAAe,EAAK,GACpB,gBAAgB,CAAC,CACjB,OAAQ,GAAgB,EAAY,MAAQ,IAAI,CAAC,CACjD,MAAM,EAAG,IAAM,OAAO,EAAE,GAAG,EAAI,OAAO,EAAE,GAAG,CAAC,EACjD,IAAK,IAAM,KAAe,EAAK,aACvB,EAAY,YAAc,aAAY,EAAY,UAAY,WAE1E"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//#region src/webrtc/peer-link.ts
|
|
2
|
+
function e(e) {
|
|
3
|
+
return new RTCPeerConnection({
|
|
4
|
+
iceServers: e,
|
|
5
|
+
bundlePolicy: "max-bundle",
|
|
6
|
+
rtcpMuxPolicy: "require"
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
function t(e, t, n) {
|
|
10
|
+
let r = Number(e.mid);
|
|
11
|
+
if (e.mid !== null && Number.isInteger(r) && n[r]) return n[r];
|
|
12
|
+
let i = t.transceivers.indexOf(e);
|
|
13
|
+
return i >= 0 ? n[i] ?? null : null;
|
|
14
|
+
}
|
|
15
|
+
async function n(e) {
|
|
16
|
+
let t = e.pendingCandidates.splice(0, e.pendingCandidates.length);
|
|
17
|
+
for (let n of t) try {
|
|
18
|
+
await e.pc.addIceCandidate(n);
|
|
19
|
+
} catch {}
|
|
20
|
+
}
|
|
21
|
+
async function r(e, t) {
|
|
22
|
+
if (!e.remoteReady) {
|
|
23
|
+
e.pendingCandidates.push(t);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
await e.pc.addIceCandidate(t);
|
|
28
|
+
} catch {}
|
|
29
|
+
}
|
|
30
|
+
async function i(e, t, n) {
|
|
31
|
+
for (let [r, i] of t.entries()) {
|
|
32
|
+
let t = e.transceivers[r], a = n.get(i.name) ?? null;
|
|
33
|
+
if (!(!t || !a)) try {
|
|
34
|
+
await t.sender.replaceTrack(a);
|
|
35
|
+
} catch {}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function a(e) {
|
|
39
|
+
e.transceivers = e.pc.getTransceivers().filter((e) => e.mid !== null).sort((e, t) => Number(e.mid) - Number(t.mid));
|
|
40
|
+
for (let t of e.transceivers) t.direction !== "sendrecv" && (t.direction = "sendrecv");
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { r as acceptCandidate, a as adoptTransceivers, i as attachLocalTracks, e as createPeerConnection, n as drainCandidates, t as slotOf };
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=peer-link.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-link.js","names":[],"sources":["../../src/webrtc/peer-link.ts"],"sourcesContent":["import type { MeshSlot } from \"./mesh-types\";\n\n/** One remote peer's connection and everything the mesh tracks about it. */\nexport interface PeerLink {\n peerId: string;\n pc: RTCPeerConnection;\n /**\n * Transceivers in slot order.\n *\n * Held explicitly rather than re-read from `getTransceivers()` so slot\n * lookup stays O(1) and cannot drift if a browser reorders.\n */\n transceivers: RTCRtpTransceiver[];\n /** Candidates that arrived before the remote description they belong to. */\n pendingCandidates: RTCIceCandidateInit[];\n /** Whether `setRemoteDescription` has landed, which gates the queue. */\n remoteReady: boolean;\n /** Whether an offer is in flight, so a re-entrant call does not stack one. */\n makingOffer: boolean;\n /** Whether this side offers. Exactly one side of a link does. */\n isOfferer: boolean;\n}\n\n/** Open a connection with the policies a mesh needs. */\nexport function createPeerConnection(iceServers: RTCIceServer[]): RTCPeerConnection {\n return new RTCPeerConnection({\n iceServers,\n bundlePolicy: \"max-bundle\",\n rtcpMuxPolicy: \"require\",\n });\n}\n\n/**\n * Resolve which slot a transceiver carries.\n *\n * The offerer allocates the m-lines in slot order, so a transceiver's `mid` is\n * its ordinal and both ends read the same one. That makes `mid` the slot's wire\n * identity, and the **only** identifier correct on both sides of a link.\n *\n * Position in the link's own array is a fallback for a `mid` that is not a plain\n * ordinal, and never the primary: a browser answering an offer appends the\n * negotiated transceivers *after* any it already held, so positional lookup\n * silently resolves to the wrong slot — the camera arriving in the screen tile —\n * or to none at all, dropping the track.\n *\n * @param transceiver - The transceiver a track arrived on.\n * @param link - The link it belongs to.\n * @param slots - The mesh's slot list.\n * @returns The slot, or `null` when neither route names one.\n */\nexport function slotOf(\n transceiver: RTCRtpTransceiver,\n link: PeerLink,\n slots: readonly MeshSlot[],\n): MeshSlot | null {\n const ordinal = Number(transceiver.mid);\n if (transceiver.mid !== null && Number.isInteger(ordinal) && slots[ordinal]) {\n return slots[ordinal];\n }\n const index = link.transceivers.indexOf(transceiver);\n return index >= 0 ? (slots[index] ?? null) : null;\n}\n\n/**\n * Feed a link every candidate that arrived before its remote description.\n *\n * `addIceCandidate` throws while `remoteDescription` is `null`, and candidates\n * routinely beat the offer or answer they belong to. Without the queue the\n * connection loses them and sits in `checking` until it times out — a failure\n * with no error anywhere.\n *\n * @param link - The link whose queue is drained.\n */\nexport async function drainCandidates(link: PeerLink): Promise<void> {\n const queued = link.pendingCandidates.splice(0, link.pendingCandidates.length);\n for (const candidate of queued) {\n try {\n await link.pc.addIceCandidate(candidate);\n } catch {\n /* a candidate the browser rejects is not fatal to the connection */\n }\n }\n}\n\n/**\n * Hand a candidate to the connection, or park it until the description lands.\n *\n * @param link - The link the candidate belongs to.\n * @param init - The candidate, already in `RTCIceCandidateInit` shape.\n */\nexport async function acceptCandidate(link: PeerLink, init: RTCIceCandidateInit): Promise<void> {\n if (!link.remoteReady) {\n link.pendingCandidates.push(init);\n return;\n }\n try {\n await link.pc.addIceCandidate(init);\n } catch {\n /* a candidate the browser rejects is not fatal to the connection */\n }\n}\n\n/**\n * Publish every held local track onto a link's slots.\n *\n * Called once the transceivers exist — up front for the offerer, after the offer\n * lands for the answerer — so a microphone that was already live when the peer\n * joined starts flowing without waiting for a toggle.\n *\n * @param link - The link to publish onto.\n * @param slots - The mesh's slot list.\n * @param tracks - The current local track per slot name.\n */\nexport async function attachLocalTracks(\n link: PeerLink,\n slots: readonly MeshSlot[],\n tracks: Map<string, MediaStreamTrack | null>,\n): Promise<void> {\n for (const [index, slot] of slots.entries()) {\n const transceiver = link.transceivers[index];\n const track = tracks.get(slot.name) ?? null;\n if (!transceiver || !track) continue;\n try {\n await transceiver.sender.replaceTrack(track);\n } catch {\n /* the browser refused the track; the slot simply stays silent */\n }\n }\n}\n\n/**\n * Adopt the transceivers a remote offer created, in `mid` order.\n *\n * The answering side allocates **nothing** up front, and that is the whole\n * subtlety: applying a remote offer creates one transceiver per m-line, in\n * m-line order, and browsers do not reuse transceivers the answerer made\n * beforehand. Pre-allocating leaves dead, never-negotiated transceivers sitting\n * in front of the live ones, which is how slot lookup ends up pointing at the\n * wrong media or at nothing.\n *\n * Each adopted transceiver is switched to `sendrecv` so this side may publish on\n * it too; without that a peer that answered could hear but never be heard.\n *\n * @param link - The link that just applied a remote offer.\n */\nexport function adoptTransceivers(link: PeerLink): void {\n link.transceivers = link.pc\n .getTransceivers()\n .filter((transceiver) => transceiver.mid !== null)\n .sort((a, b) => Number(a.mid) - Number(b.mid));\n for (const transceiver of link.transceivers) {\n if (transceiver.direction !== \"sendrecv\") transceiver.direction = \"sendrecv\";\n }\n}\n"],"mappings":";AAwBA,SAAgB,EAAqB,GAA+C;CAChF,OAAO,IAAI,kBAAkB;EACzB;EACA,cAAc;EACd,eAAe;CACnB,CAAC;AACL;AAoBA,SAAgB,EACZ,GACA,GACA,GACe;CACf,IAAM,IAAU,OAAO,EAAY,GAAG;CACtC,IAAI,EAAY,QAAQ,QAAQ,OAAO,UAAU,CAAO,KAAK,EAAM,IAC/D,OAAO,EAAM;CAEjB,IAAM,IAAQ,EAAK,aAAa,QAAQ,CAAW;CACnD,OAAO,KAAS,IAAK,EAAM,MAAU,OAAQ;AACjD;AAYA,eAAsB,EAAgB,GAA+B;CACjE,IAAM,IAAS,EAAK,kBAAkB,OAAO,GAAG,EAAK,kBAAkB,MAAM;CAC7E,KAAK,IAAM,KAAa,GACpB,IAAI;EACA,MAAM,EAAK,GAAG,gBAAgB,CAAS;CAC3C,QAAQ,CAER;AAER;AAQA,eAAsB,EAAgB,GAAgB,GAA0C;CAC5F,IAAI,CAAC,EAAK,aAAa;EACnB,EAAK,kBAAkB,KAAK,CAAI;EAChC;CACJ;CACA,IAAI;EACA,MAAM,EAAK,GAAG,gBAAgB,CAAI;CACtC,QAAQ,CAER;AACJ;AAaA,eAAsB,EAClB,GACA,GACA,GACa;CACb,KAAK,IAAM,CAAC,GAAO,MAAS,EAAM,QAAQ,GAAG;EACzC,IAAM,IAAc,EAAK,aAAa,IAChC,IAAQ,EAAO,IAAI,EAAK,IAAI,KAAK;EACnC,OAAC,KAAe,CAAC,IACrB,IAAI;GACA,MAAM,EAAY,OAAO,aAAa,CAAK;EAC/C,QAAQ,CAER;CACJ;AACJ;AAiBA,SAAgB,EAAkB,GAAsB;CACpD,EAAK,eAAe,EAAK,GACpB,gBAAgB,CAAC,CACjB,QAAQ,MAAgB,EAAY,QAAQ,IAAI,CAAC,CACjD,MAAM,GAAG,MAAM,OAAO,EAAE,GAAG,IAAI,OAAO,EAAE,GAAG,CAAC;CACjD,KAAK,IAAM,KAAe,EAAK,cAC3B,AAAI,EAAY,cAAc,eAAY,EAAY,YAAY;AAE1E"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./mesh-quality.cjs"),t=require("./peer-link.cjs");function n(n){let{slots:r,send:i}=n,a=new Map,o=new Map,s=new Map,c=n.iceServers??[],l=n.setLocalDescription??((e,t)=>e.setLocalDescription(t)),u=n.quality??{},d=!1,f=()=>Object.fromEntries(r.map(e=>[e.name,null])),p=()=>{n.onPeers?.([...o.values()].map(e=>({...e})))},m=()=>{if(d)return;let e=[...a.values()].map(e=>e.pc.connectionState);e.some(e=>e===`connected`)?n.onState?.(`connected`):e.length>0?n.onState?.(`connecting`,`negotiating`):n.onState?.(`connected`,`alone`)},h=async t=>{u=t;let n=e.scaleForRoom(t,a.size),i=e.resolveDegradation(t,n);for(let t of a.values())await e.applyQualityToLink(t.transceivers,r,n,i)},g=async e=>{if(!e.makingOffer){e.makingOffer=!0;try{let t=await e.pc.createOffer();if(!t.sdp){n.onNotice?.(`empty_local_offer_sdp`);return}await l(e.pc,t),i({type:`offer`,to:e.peerId,sdp:e.pc.localDescription?.sdp??t.sdp})}catch{n.onNotice?.(`offer_failed`)}finally{e.makingOffer=!1}}},_=e=>e.streams?.[0]||(typeof MediaStream>`u`?null:new MediaStream([e.track])),v=(e,n)=>{let i=t.slotOf(n.transceiver,e,r),a=o.get(e.peerId);!i||!a||(a.streams={...a.streams,[i.name]:_(n)},n.track.onended=()=>{let t=o.get(e.peerId);t&&(t.streams={...t.streams,[i.name]:null},p())},p())},y=e=>{let t=a.get(e);t&&(t.pc.close(),a.delete(e)),o.delete(e),h(u),p(),m()},b=async(e,{offerer:n})=>{if(a.has(e))return;let l=t.createPeerConnection(c),u={peerId:e,pc:l,transceivers:[],pendingCandidates:[],remoteReady:!1,makingOffer:!1,isOfferer:n};a.set(e,u),o.set(e,{peerId:e,connection:l.connectionState,streams:o.get(e)?.streams??f()}),n&&(u.transceivers=r.map(e=>l.addTransceiver(e.kind,{direction:`sendrecv`})),await t.attachLocalTracks(u,r,s)),l.onicecandidate=t=>{i({type:`ice`,to:e,candidate:t.candidate?.candidate??null,sdpMid:t.candidate?.sdpMid??null,sdpMLineIndex:t.candidate?.sdpMLineIndex??null})},l.ontrack=e=>v(u,e),l.onconnectionstatechange=()=>{let t=o.get(e);if(t&&(t.connection=l.connectionState),l.connectionState===`failed`||l.connectionState===`closed`){y(e);return}p(),m()},l.onnegotiationneeded=()=>{u.isOfferer&&g(u)},p(),m(),n&&await g(u)},x=async(e,o)=>{a.has(e)||await b(e,{offerer:!1});let c=a.get(e);if(!c)return;await c.pc.setRemoteDescription({type:`offer`,sdp:o}),c.remoteReady=!0,await t.drainCandidates(c),c.isOfferer||(t.adoptTransceivers(c),await t.attachLocalTracks(c,r,s));let d=await c.pc.createAnswer();if(!d.sdp){n.onNotice?.(`empty_local_answer_sdp`);return}await l(c.pc,d),i({type:`answer`,to:e,sdp:c.pc.localDescription?.sdp??d.sdp}),await h(u)};return n.onState?.(`connecting`,`signaling`),{addPeer:b,removePeer:y,accept:async e=>{if(e.type===`offer`){await x(e.from,e.sdp);return}let n=a.get(e.from);if(n){if(e.type===`answer`){await n.pc.setRemoteDescription({type:`answer`,sdp:e.sdp}),n.remoteReady=!0,await t.drainCandidates(n),await h(u);return}e.candidate!==null&&await t.acceptCandidate(n,{candidate:e.candidate,sdpMid:e.sdpMid??void 0,sdpMLineIndex:e.sdpMLineIndex??void 0})}},setLocalTrack:async(e,t)=>{s.set(e,t);let n=r.findIndex(t=>t.name===e);if(!(n<0)){for(let e of a.values()){let r=e.transceivers[n];if(r)try{await r.sender.replaceTrack(t)}catch{}}await h(u)}},applyQuality:h,setIceServers:e=>{c=e},stop:()=>{for(let e of a.values())e.pc.close();a.clear(),o.clear(),d=!0,p(),n.onState?.(`closed`)},get peers(){return[...o.values()].map(e=>({...e}))}}}exports.createPeerMesh=n;
|
|
2
|
+
//# sourceMappingURL=peer-mesh.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-mesh.cjs","names":[],"sources":["../../src/webrtc/peer-mesh.ts"],"sourcesContent":["/**\n * @tempest-limits file-lines — the mesh is one object's lifetime: a link's\n * transceivers, the offer it owes, the tracks published on it and the share of\n * the uplink it costs all change together, and every method here reads or writes\n * the same two maps. The pieces that *could* stand alone already do —\n * `peer-link.ts` for the per-connection mechanics and `mesh-quality.ts` for the\n * division — and what is left is the coordination between them.\n */\nimport { applyQualityToLink, resolveDegradation, scaleForRoom } from \"./mesh-quality\";\nimport {\n acceptCandidate,\n adoptTransceivers,\n attachLocalTracks,\n createPeerConnection,\n drainCandidates,\n slotOf,\n type PeerLink,\n} from \"./peer-link\";\nimport type { MeshMessage, MeshPeer, MeshQuality, PeerMeshOptions } from \"./mesh-types\";\n\n/** A running mesh. */\nexport interface PeerMesh {\n /**\n * Open a link to a peer.\n *\n * `offerer` decides which side sends the offer, and exactly one side of each\n * link must say `true`. Drive it from the arrival order your server already\n * imposes — the peer that joined **later** offers, the one already in the\n * room answers. That avoids glare by construction, without the rollback\n * dance of perfect negotiation and without depending on a browser\n * implementing argument-less `setLocalDescription`.\n */\n addPeer: (peerId: string, options: { offerer: boolean }) => Promise<void>;\n /** Close one link and give its share of the uplink back to the others. */\n removePeer: (peerId: string) => void;\n /** Feed the mesh an `offer`, `answer` or `ice` message from `from`. */\n accept: (message: MeshMessage & { from: string }) => Promise<void>;\n /**\n * Publish or retract one slot across every live link.\n *\n * `null` retracts: the sender keeps its negotiated transceiver and stops\n * producing, which is what mutes a microphone without disturbing the other\n * slots or the connection. Nothing renegotiates — the m-lines were allocated\n * before any track existed, which is what makes a mesh survive toggling: a\n * renegotiation per toggle is N-1 simultaneous offer/answer rounds every time\n * somebody unmutes.\n */\n setLocalTrack: (slot: string, track: MediaStreamTrack | null) => Promise<void>;\n /** Apply encoder limits, divided by the current size of the room. */\n applyQuality: (quality: MeshQuality) => Promise<void>;\n /** Replace the ICE servers used for links opened from now on. */\n setIceServers: (servers: RTCIceServer[]) => void;\n /** Close every link and report `closed`. */\n stop: () => void;\n /** The peers as the mesh currently sees them. */\n readonly peers: MeshPeer[];\n}\n\n/**\n * One `RTCPeerConnection` per peer, with the slots negotiated up front.\n *\n * The signalling protocol stays yours: this produces and accepts three message\n * shapes (`offer`, `answer`, `ice`) and leaves delivery, room membership and\n * identity to your server. What it owns is the part that is the same in every\n * mesh and wrong in most of them — see {@link PeerMesh} for the traps each\n * method exists to avoid.\n *\n * @param options - See {@link PeerMeshOptions}.\n * @returns The mesh.\n *\n * @example\n * const mesh = createPeerMesh({\n * slots: [\n * { name: \"mic\", kind: \"audio\" },\n * { name: \"cam\", kind: \"video\" },\n * ],\n * send: (message) => socket.send(message),\n * onPeers: setPeers,\n * });\n * socket.onMessage = (message) => void mesh.accept(message);\n * await mesh.addPeer(\"peer-2\", { offerer: true });\n * await mesh.setLocalTrack(\"mic\", micTrack);\n */\nexport function createPeerMesh(options: PeerMeshOptions): PeerMesh {\n const { slots, send } = options;\n const links = new Map<string, PeerLink>();\n const peers = new Map<string, MeshPeer>();\n const localTracks = new Map<string, MediaStreamTrack | null>();\n let iceServers = options.iceServers ?? [];\n const describe =\n options.setLocalDescription ??\n ((connection: RTCPeerConnection, description: RTCSessionDescriptionInit) =>\n connection.setLocalDescription(description));\n let quality: MeshQuality = options.quality ?? {};\n let stopped = false;\n\n const emptyStreams = (): Record<string, MediaStream | null> =>\n Object.fromEntries(slots.map((slot) => [slot.name, null]));\n\n const emitPeers = (): void => {\n options.onPeers?.([...peers.values()].map((peer) => ({ ...peer })));\n };\n\n /**\n * Collapse the per-link states into the one badge a call shows.\n *\n * No links at all is `connected`, not a failure: it means nobody else is in\n * the room yet, which is a legitimate state a call sits in for as long as the\n * first person is early.\n */\n const refreshState = (): void => {\n if (stopped) return;\n const states = [...links.values()].map((link) => link.pc.connectionState);\n if (states.some((state) => state === \"connected\")) options.onState?.(\"connected\");\n else if (states.length > 0) options.onState?.(\"connecting\", \"negotiating\");\n else options.onState?.(\"connected\", \"alone\");\n };\n\n const applyQuality = async (next: MeshQuality): Promise<void> => {\n quality = next;\n const effective = scaleForRoom(next, links.size);\n const degradation = resolveDegradation(next, effective);\n for (const link of links.values()) {\n await applyQualityToLink(link.transceivers, slots, effective, degradation);\n }\n };\n\n const makeOffer = async (link: PeerLink): Promise<void> => {\n if (link.makingOffer) return;\n link.makingOffer = true;\n try {\n const offer = await link.pc.createOffer();\n if (!offer.sdp) {\n options.onNotice?.(\"empty_local_offer_sdp\");\n return;\n }\n await describe(link.pc, offer);\n send({\n type: \"offer\",\n to: link.peerId,\n sdp: link.pc.localDescription?.sdp ?? offer.sdp,\n });\n } catch {\n options.onNotice?.(\"offer_failed\");\n } finally {\n link.makingOffer = false;\n }\n };\n\n /**\n * Wrap an inbound track in the stream the caller renders.\n *\n * The event's own stream is preferred: it is the one the sending side\n * grouped the track into, so a caller that reads `stream.id` sees what the\n * peer published rather than a wrapper invented here. Browsers only fill it\n * when the offer named a stream, hence the fallback — and the guard after\n * that is for a runtime with no `MediaStream` at all, where routing still\n * has to not throw.\n */\n const streamFor = (event: RTCTrackEvent): MediaStream | null => {\n const provided = event.streams?.[0];\n if (provided) return provided;\n return typeof MediaStream === \"undefined\" ? null : new MediaStream([event.track]);\n };\n\n const attachRemoteTrack = (link: PeerLink, event: RTCTrackEvent): void => {\n const slot = slotOf(event.transceiver, link, slots);\n const peer = peers.get(link.peerId);\n if (!slot || !peer) return;\n\n peer.streams = { ...peer.streams, [slot.name]: streamFor(event) };\n event.track.onended = (): void => {\n const current = peers.get(link.peerId);\n if (!current) return;\n current.streams = { ...current.streams, [slot.name]: null };\n emitPeers();\n };\n emitPeers();\n };\n\n const removePeer = (peerId: string): void => {\n const link = links.get(peerId);\n if (link) {\n link.pc.close();\n links.delete(peerId);\n }\n peers.delete(peerId);\n void applyQuality(quality);\n emitPeers();\n refreshState();\n };\n\n const addPeer = async (peerId: string, { offerer }: { offerer: boolean }): Promise<void> => {\n if (links.has(peerId)) return;\n\n const pc = createPeerConnection(iceServers);\n const link: PeerLink = {\n peerId,\n pc,\n transceivers: [],\n pendingCandidates: [],\n remoteReady: false,\n makingOffer: false,\n isOfferer: offerer,\n };\n links.set(peerId, link);\n peers.set(peerId, {\n peerId,\n connection: pc.connectionState,\n streams: peers.get(peerId)?.streams ?? emptyStreams(),\n });\n\n if (offerer) {\n link.transceivers = slots.map((slot) =>\n pc.addTransceiver(slot.kind, { direction: \"sendrecv\" }),\n );\n await attachLocalTracks(link, slots, localTracks);\n }\n\n pc.onicecandidate = (event): void => {\n send({\n type: \"ice\",\n to: peerId,\n candidate: event.candidate?.candidate ?? null,\n sdpMid: event.candidate?.sdpMid ?? null,\n sdpMLineIndex: event.candidate?.sdpMLineIndex ?? null,\n });\n };\n\n pc.ontrack = (event): void => attachRemoteTrack(link, event);\n\n pc.onconnectionstatechange = (): void => {\n const peer = peers.get(peerId);\n if (peer) peer.connection = pc.connectionState;\n if (pc.connectionState === \"failed\" || pc.connectionState === \"closed\") {\n removePeer(peerId);\n return;\n }\n emitPeers();\n refreshState();\n };\n\n pc.onnegotiationneeded = (): void => {\n if (link.isOfferer) void makeOffer(link);\n };\n\n emitPeers();\n refreshState();\n if (offerer) await makeOffer(link);\n };\n\n const acceptOffer = async (from: string, sdp: string): Promise<void> => {\n if (!links.has(from)) await addPeer(from, { offerer: false });\n const link = links.get(from);\n if (!link) return;\n\n await link.pc.setRemoteDescription({ type: \"offer\", sdp });\n link.remoteReady = true;\n await drainCandidates(link);\n\n if (!link.isOfferer) {\n adoptTransceivers(link);\n await attachLocalTracks(link, slots, localTracks);\n }\n\n const answer = await link.pc.createAnswer();\n if (!answer.sdp) {\n options.onNotice?.(\"empty_local_answer_sdp\");\n return;\n }\n await describe(link.pc, answer);\n send({ type: \"answer\", to: from, sdp: link.pc.localDescription?.sdp ?? answer.sdp });\n await applyQuality(quality);\n };\n\n const accept = async (message: MeshMessage & { from: string }): Promise<void> => {\n if (message.type === \"offer\") {\n await acceptOffer(message.from, message.sdp);\n return;\n }\n\n const link = links.get(message.from);\n if (!link) return;\n\n if (message.type === \"answer\") {\n await link.pc.setRemoteDescription({ type: \"answer\", sdp: message.sdp });\n link.remoteReady = true;\n await drainCandidates(link);\n await applyQuality(quality);\n return;\n }\n\n if (message.candidate === null) return;\n await acceptCandidate(link, {\n candidate: message.candidate,\n sdpMid: message.sdpMid ?? undefined,\n sdpMLineIndex: message.sdpMLineIndex ?? undefined,\n });\n };\n\n const setLocalTrack = async (slot: string, track: MediaStreamTrack | null): Promise<void> => {\n localTracks.set(slot, track);\n const index = slots.findIndex((entry) => entry.name === slot);\n if (index < 0) return;\n\n for (const link of links.values()) {\n const transceiver = link.transceivers[index];\n if (!transceiver) continue;\n try {\n await transceiver.sender.replaceTrack(track);\n } catch {\n /* the link is tearing down; its state handler will remove it */\n }\n }\n await applyQuality(quality);\n };\n\n const stop = (): void => {\n for (const link of links.values()) link.pc.close();\n links.clear();\n peers.clear();\n stopped = true;\n emitPeers();\n options.onState?.(\"closed\");\n };\n\n options.onState?.(\"connecting\", \"signaling\");\n\n return {\n addPeer,\n removePeer,\n accept,\n setLocalTrack,\n applyQuality,\n setIceServers: (servers): void => {\n iceServers = servers;\n },\n stop,\n get peers(): MeshPeer[] {\n return [...peers.values()].map((peer) => ({ ...peer }));\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { applyQualityToLink as e, resolveDegradation as t, scaleForRoom as n } from "./mesh-quality.js";
|
|
2
|
+
import { acceptCandidate as r, adoptTransceivers as i, attachLocalTracks as a, createPeerConnection as o, drainCandidates as s, slotOf as c } from "./peer-link.js";
|
|
3
|
+
//#region src/webrtc/peer-mesh.ts
|
|
4
|
+
function l(l) {
|
|
5
|
+
let { slots: u, send: d } = l, f = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map(), m = /* @__PURE__ */ new Map(), h = l.iceServers ?? [], g = l.setLocalDescription ?? ((e, t) => e.setLocalDescription(t)), _ = l.quality ?? {}, v = !1, y = () => Object.fromEntries(u.map((e) => [e.name, null])), b = () => {
|
|
6
|
+
l.onPeers?.([...p.values()].map((e) => ({ ...e })));
|
|
7
|
+
}, x = () => {
|
|
8
|
+
if (v) return;
|
|
9
|
+
let e = [...f.values()].map((e) => e.pc.connectionState);
|
|
10
|
+
e.some((e) => e === "connected") ? l.onState?.("connected") : e.length > 0 ? l.onState?.("connecting", "negotiating") : l.onState?.("connected", "alone");
|
|
11
|
+
}, S = async (r) => {
|
|
12
|
+
_ = r;
|
|
13
|
+
let i = n(r, f.size), a = t(r, i);
|
|
14
|
+
for (let t of f.values()) await e(t.transceivers, u, i, a);
|
|
15
|
+
}, C = async (e) => {
|
|
16
|
+
if (!e.makingOffer) {
|
|
17
|
+
e.makingOffer = !0;
|
|
18
|
+
try {
|
|
19
|
+
let t = await e.pc.createOffer();
|
|
20
|
+
if (!t.sdp) {
|
|
21
|
+
l.onNotice?.("empty_local_offer_sdp");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
await g(e.pc, t), d({
|
|
25
|
+
type: "offer",
|
|
26
|
+
to: e.peerId,
|
|
27
|
+
sdp: e.pc.localDescription?.sdp ?? t.sdp
|
|
28
|
+
});
|
|
29
|
+
} catch {
|
|
30
|
+
l.onNotice?.("offer_failed");
|
|
31
|
+
} finally {
|
|
32
|
+
e.makingOffer = !1;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}, w = (e) => e.streams?.[0] || (typeof MediaStream > "u" ? null : new MediaStream([e.track])), T = (e, t) => {
|
|
36
|
+
let n = c(t.transceiver, e, u), r = p.get(e.peerId);
|
|
37
|
+
!n || !r || (r.streams = {
|
|
38
|
+
...r.streams,
|
|
39
|
+
[n.name]: w(t)
|
|
40
|
+
}, t.track.onended = () => {
|
|
41
|
+
let t = p.get(e.peerId);
|
|
42
|
+
t && (t.streams = {
|
|
43
|
+
...t.streams,
|
|
44
|
+
[n.name]: null
|
|
45
|
+
}, b());
|
|
46
|
+
}, b());
|
|
47
|
+
}, E = (e) => {
|
|
48
|
+
let t = f.get(e);
|
|
49
|
+
t && (t.pc.close(), f.delete(e)), p.delete(e), S(_), b(), x();
|
|
50
|
+
}, D = async (e, { offerer: t }) => {
|
|
51
|
+
if (f.has(e)) return;
|
|
52
|
+
let n = o(h), r = {
|
|
53
|
+
peerId: e,
|
|
54
|
+
pc: n,
|
|
55
|
+
transceivers: [],
|
|
56
|
+
pendingCandidates: [],
|
|
57
|
+
remoteReady: !1,
|
|
58
|
+
makingOffer: !1,
|
|
59
|
+
isOfferer: t
|
|
60
|
+
};
|
|
61
|
+
f.set(e, r), p.set(e, {
|
|
62
|
+
peerId: e,
|
|
63
|
+
connection: n.connectionState,
|
|
64
|
+
streams: p.get(e)?.streams ?? y()
|
|
65
|
+
}), t && (r.transceivers = u.map((e) => n.addTransceiver(e.kind, { direction: "sendrecv" })), await a(r, u, m)), n.onicecandidate = (t) => {
|
|
66
|
+
d({
|
|
67
|
+
type: "ice",
|
|
68
|
+
to: e,
|
|
69
|
+
candidate: t.candidate?.candidate ?? null,
|
|
70
|
+
sdpMid: t.candidate?.sdpMid ?? null,
|
|
71
|
+
sdpMLineIndex: t.candidate?.sdpMLineIndex ?? null
|
|
72
|
+
});
|
|
73
|
+
}, n.ontrack = (e) => T(r, e), n.onconnectionstatechange = () => {
|
|
74
|
+
let t = p.get(e);
|
|
75
|
+
if (t && (t.connection = n.connectionState), n.connectionState === "failed" || n.connectionState === "closed") {
|
|
76
|
+
E(e);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
b(), x();
|
|
80
|
+
}, n.onnegotiationneeded = () => {
|
|
81
|
+
r.isOfferer && C(r);
|
|
82
|
+
}, b(), x(), t && await C(r);
|
|
83
|
+
}, O = async (e, t) => {
|
|
84
|
+
f.has(e) || await D(e, { offerer: !1 });
|
|
85
|
+
let n = f.get(e);
|
|
86
|
+
if (!n) return;
|
|
87
|
+
await n.pc.setRemoteDescription({
|
|
88
|
+
type: "offer",
|
|
89
|
+
sdp: t
|
|
90
|
+
}), n.remoteReady = !0, await s(n), n.isOfferer || (i(n), await a(n, u, m));
|
|
91
|
+
let r = await n.pc.createAnswer();
|
|
92
|
+
if (!r.sdp) {
|
|
93
|
+
l.onNotice?.("empty_local_answer_sdp");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
await g(n.pc, r), d({
|
|
97
|
+
type: "answer",
|
|
98
|
+
to: e,
|
|
99
|
+
sdp: n.pc.localDescription?.sdp ?? r.sdp
|
|
100
|
+
}), await S(_);
|
|
101
|
+
};
|
|
102
|
+
return l.onState?.("connecting", "signaling"), {
|
|
103
|
+
addPeer: D,
|
|
104
|
+
removePeer: E,
|
|
105
|
+
accept: async (e) => {
|
|
106
|
+
if (e.type === "offer") {
|
|
107
|
+
await O(e.from, e.sdp);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
let t = f.get(e.from);
|
|
111
|
+
if (t) {
|
|
112
|
+
if (e.type === "answer") {
|
|
113
|
+
await t.pc.setRemoteDescription({
|
|
114
|
+
type: "answer",
|
|
115
|
+
sdp: e.sdp
|
|
116
|
+
}), t.remoteReady = !0, await s(t), await S(_);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
e.candidate !== null && await r(t, {
|
|
120
|
+
candidate: e.candidate,
|
|
121
|
+
sdpMid: e.sdpMid ?? void 0,
|
|
122
|
+
sdpMLineIndex: e.sdpMLineIndex ?? void 0
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
setLocalTrack: async (e, t) => {
|
|
127
|
+
m.set(e, t);
|
|
128
|
+
let n = u.findIndex((t) => t.name === e);
|
|
129
|
+
if (!(n < 0)) {
|
|
130
|
+
for (let e of f.values()) {
|
|
131
|
+
let r = e.transceivers[n];
|
|
132
|
+
if (r) try {
|
|
133
|
+
await r.sender.replaceTrack(t);
|
|
134
|
+
} catch {}
|
|
135
|
+
}
|
|
136
|
+
await S(_);
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
applyQuality: S,
|
|
140
|
+
setIceServers: (e) => {
|
|
141
|
+
h = e;
|
|
142
|
+
},
|
|
143
|
+
stop: () => {
|
|
144
|
+
for (let e of f.values()) e.pc.close();
|
|
145
|
+
f.clear(), p.clear(), v = !0, b(), l.onState?.("closed");
|
|
146
|
+
},
|
|
147
|
+
get peers() {
|
|
148
|
+
return [...p.values()].map((e) => ({ ...e }));
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
//#endregion
|
|
153
|
+
export { l as createPeerMesh };
|
|
154
|
+
|
|
155
|
+
//# sourceMappingURL=peer-mesh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-mesh.js","names":[],"sources":["../../src/webrtc/peer-mesh.ts"],"sourcesContent":["/**\n * @tempest-limits file-lines — the mesh is one object's lifetime: a link's\n * transceivers, the offer it owes, the tracks published on it and the share of\n * the uplink it costs all change together, and every method here reads or writes\n * the same two maps. The pieces that *could* stand alone already do —\n * `peer-link.ts` for the per-connection mechanics and `mesh-quality.ts` for the\n * division — and what is left is the coordination between them.\n */\nimport { applyQualityToLink, resolveDegradation, scaleForRoom } from \"./mesh-quality\";\nimport {\n acceptCandidate,\n adoptTransceivers,\n attachLocalTracks,\n createPeerConnection,\n drainCandidates,\n slotOf,\n type PeerLink,\n} from \"./peer-link\";\nimport type { MeshMessage, MeshPeer, MeshQuality, PeerMeshOptions } from \"./mesh-types\";\n\n/** A running mesh. */\nexport interface PeerMesh {\n /**\n * Open a link to a peer.\n *\n * `offerer` decides which side sends the offer, and exactly one side of each\n * link must say `true`. Drive it from the arrival order your server already\n * imposes — the peer that joined **later** offers, the one already in the\n * room answers. That avoids glare by construction, without the rollback\n * dance of perfect negotiation and without depending on a browser\n * implementing argument-less `setLocalDescription`.\n */\n addPeer: (peerId: string, options: { offerer: boolean }) => Promise<void>;\n /** Close one link and give its share of the uplink back to the others. */\n removePeer: (peerId: string) => void;\n /** Feed the mesh an `offer`, `answer` or `ice` message from `from`. */\n accept: (message: MeshMessage & { from: string }) => Promise<void>;\n /**\n * Publish or retract one slot across every live link.\n *\n * `null` retracts: the sender keeps its negotiated transceiver and stops\n * producing, which is what mutes a microphone without disturbing the other\n * slots or the connection. Nothing renegotiates — the m-lines were allocated\n * before any track existed, which is what makes a mesh survive toggling: a\n * renegotiation per toggle is N-1 simultaneous offer/answer rounds every time\n * somebody unmutes.\n */\n setLocalTrack: (slot: string, track: MediaStreamTrack | null) => Promise<void>;\n /** Apply encoder limits, divided by the current size of the room. */\n applyQuality: (quality: MeshQuality) => Promise<void>;\n /** Replace the ICE servers used for links opened from now on. */\n setIceServers: (servers: RTCIceServer[]) => void;\n /** Close every link and report `closed`. */\n stop: () => void;\n /** The peers as the mesh currently sees them. */\n readonly peers: MeshPeer[];\n}\n\n/**\n * One `RTCPeerConnection` per peer, with the slots negotiated up front.\n *\n * The signalling protocol stays yours: this produces and accepts three message\n * shapes (`offer`, `answer`, `ice`) and leaves delivery, room membership and\n * identity to your server. What it owns is the part that is the same in every\n * mesh and wrong in most of them — see {@link PeerMesh} for the traps each\n * method exists to avoid.\n *\n * @param options - See {@link PeerMeshOptions}.\n * @returns The mesh.\n *\n * @example\n * const mesh = createPeerMesh({\n * slots: [\n * { name: \"mic\", kind: \"audio\" },\n * { name: \"cam\", kind: \"video\" },\n * ],\n * send: (message) => socket.send(message),\n * onPeers: setPeers,\n * });\n * socket.onMessage = (message) => void mesh.accept(message);\n * await mesh.addPeer(\"peer-2\", { offerer: true });\n * await mesh.setLocalTrack(\"mic\", micTrack);\n */\nexport function createPeerMesh(options: PeerMeshOptions): PeerMesh {\n const { slots, send } = options;\n const links = new Map<string, PeerLink>();\n const peers = new Map<string, MeshPeer>();\n const localTracks = new Map<string, MediaStreamTrack | null>();\n let iceServers = options.iceServers ?? [];\n const describe =\n options.setLocalDescription ??\n ((connection: RTCPeerConnection, description: RTCSessionDescriptionInit) =>\n connection.setLocalDescription(description));\n let quality: MeshQuality = options.quality ?? {};\n let stopped = false;\n\n const emptyStreams = (): Record<string, MediaStream | null> =>\n Object.fromEntries(slots.map((slot) => [slot.name, null]));\n\n const emitPeers = (): void => {\n options.onPeers?.([...peers.values()].map((peer) => ({ ...peer })));\n };\n\n /**\n * Collapse the per-link states into the one badge a call shows.\n *\n * No links at all is `connected`, not a failure: it means nobody else is in\n * the room yet, which is a legitimate state a call sits in for as long as the\n * first person is early.\n */\n const refreshState = (): void => {\n if (stopped) return;\n const states = [...links.values()].map((link) => link.pc.connectionState);\n if (states.some((state) => state === \"connected\")) options.onState?.(\"connected\");\n else if (states.length > 0) options.onState?.(\"connecting\", \"negotiating\");\n else options.onState?.(\"connected\", \"alone\");\n };\n\n const applyQuality = async (next: MeshQuality): Promise<void> => {\n quality = next;\n const effective = scaleForRoom(next, links.size);\n const degradation = resolveDegradation(next, effective);\n for (const link of links.values()) {\n await applyQualityToLink(link.transceivers, slots, effective, degradation);\n }\n };\n\n const makeOffer = async (link: PeerLink): Promise<void> => {\n if (link.makingOffer) return;\n link.makingOffer = true;\n try {\n const offer = await link.pc.createOffer();\n if (!offer.sdp) {\n options.onNotice?.(\"empty_local_offer_sdp\");\n return;\n }\n await describe(link.pc, offer);\n send({\n type: \"offer\",\n to: link.peerId,\n sdp: link.pc.localDescription?.sdp ?? offer.sdp,\n });\n } catch {\n options.onNotice?.(\"offer_failed\");\n } finally {\n link.makingOffer = false;\n }\n };\n\n /**\n * Wrap an inbound track in the stream the caller renders.\n *\n * The event's own stream is preferred: it is the one the sending side\n * grouped the track into, so a caller that reads `stream.id` sees what the\n * peer published rather than a wrapper invented here. Browsers only fill it\n * when the offer named a stream, hence the fallback — and the guard after\n * that is for a runtime with no `MediaStream` at all, where routing still\n * has to not throw.\n */\n const streamFor = (event: RTCTrackEvent): MediaStream | null => {\n const provided = event.streams?.[0];\n if (provided) return provided;\n return typeof MediaStream === \"undefined\" ? null : new MediaStream([event.track]);\n };\n\n const attachRemoteTrack = (link: PeerLink, event: RTCTrackEvent): void => {\n const slot = slotOf(event.transceiver, link, slots);\n const peer = peers.get(link.peerId);\n if (!slot || !peer) return;\n\n peer.streams = { ...peer.streams, [slot.name]: streamFor(event) };\n event.track.onended = (): void => {\n const current = peers.get(link.peerId);\n if (!current) return;\n current.streams = { ...current.streams, [slot.name]: null };\n emitPeers();\n };\n emitPeers();\n };\n\n const removePeer = (peerId: string): void => {\n const link = links.get(peerId);\n if (link) {\n link.pc.close();\n links.delete(peerId);\n }\n peers.delete(peerId);\n void applyQuality(quality);\n emitPeers();\n refreshState();\n };\n\n const addPeer = async (peerId: string, { offerer }: { offerer: boolean }): Promise<void> => {\n if (links.has(peerId)) return;\n\n const pc = createPeerConnection(iceServers);\n const link: PeerLink = {\n peerId,\n pc,\n transceivers: [],\n pendingCandidates: [],\n remoteReady: false,\n makingOffer: false,\n isOfferer: offerer,\n };\n links.set(peerId, link);\n peers.set(peerId, {\n peerId,\n connection: pc.connectionState,\n streams: peers.get(peerId)?.streams ?? emptyStreams(),\n });\n\n if (offerer) {\n link.transceivers = slots.map((slot) =>\n pc.addTransceiver(slot.kind, { direction: \"sendrecv\" }),\n );\n await attachLocalTracks(link, slots, localTracks);\n }\n\n pc.onicecandidate = (event): void => {\n send({\n type: \"ice\",\n to: peerId,\n candidate: event.candidate?.candidate ?? null,\n sdpMid: event.candidate?.sdpMid ?? null,\n sdpMLineIndex: event.candidate?.sdpMLineIndex ?? null,\n });\n };\n\n pc.ontrack = (event): void => attachRemoteTrack(link, event);\n\n pc.onconnectionstatechange = (): void => {\n const peer = peers.get(peerId);\n if (peer) peer.connection = pc.connectionState;\n if (pc.connectionState === \"failed\" || pc.connectionState === \"closed\") {\n removePeer(peerId);\n return;\n }\n emitPeers();\n refreshState();\n };\n\n pc.onnegotiationneeded = (): void => {\n if (link.isOfferer) void makeOffer(link);\n };\n\n emitPeers();\n refreshState();\n if (offerer) await makeOffer(link);\n };\n\n const acceptOffer = async (from: string, sdp: string): Promise<void> => {\n if (!links.has(from)) await addPeer(from, { offerer: false });\n const link = links.get(from);\n if (!link) return;\n\n await link.pc.setRemoteDescription({ type: \"offer\", sdp });\n link.remoteReady = true;\n await drainCandidates(link);\n\n if (!link.isOfferer) {\n adoptTransceivers(link);\n await attachLocalTracks(link, slots, localTracks);\n }\n\n const answer = await link.pc.createAnswer();\n if (!answer.sdp) {\n options.onNotice?.(\"empty_local_answer_sdp\");\n return;\n }\n await describe(link.pc, answer);\n send({ type: \"answer\", to: from, sdp: link.pc.localDescription?.sdp ?? answer.sdp });\n await applyQuality(quality);\n };\n\n const accept = async (message: MeshMessage & { from: string }): Promise<void> => {\n if (message.type === \"offer\") {\n await acceptOffer(message.from, message.sdp);\n return;\n }\n\n const link = links.get(message.from);\n if (!link) return;\n\n if (message.type === \"answer\") {\n await link.pc.setRemoteDescription({ type: \"answer\", sdp: message.sdp });\n link.remoteReady = true;\n await drainCandidates(link);\n await applyQuality(quality);\n return;\n }\n\n if (message.candidate === null) return;\n await acceptCandidate(link, {\n candidate: message.candidate,\n sdpMid: message.sdpMid ?? undefined,\n sdpMLineIndex: message.sdpMLineIndex ?? undefined,\n });\n };\n\n const setLocalTrack = async (slot: string, track: MediaStreamTrack | null): Promise<void> => {\n localTracks.set(slot, track);\n const index = slots.findIndex((entry) => entry.name === slot);\n if (index < 0) return;\n\n for (const link of links.values()) {\n const transceiver = link.transceivers[index];\n if (!transceiver) continue;\n try {\n await transceiver.sender.replaceTrack(track);\n } catch {\n /* the link is tearing down; its state handler will remove it */\n }\n }\n await applyQuality(quality);\n };\n\n const stop = (): void => {\n for (const link of links.values()) link.pc.close();\n links.clear();\n peers.clear();\n stopped = true;\n emitPeers();\n options.onState?.(\"closed\");\n };\n\n options.onState?.(\"connecting\", \"signaling\");\n\n return {\n addPeer,\n removePeer,\n accept,\n setLocalTrack,\n applyQuality,\n setIceServers: (servers): void => {\n iceServers = servers;\n },\n stop,\n get peers(): MeshPeer[] {\n return [...peers.values()].map((peer) => ({ ...peer }));\n },\n };\n}\n"],"mappings":"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"}
|