tempest-react-sdk 0.77.0 → 0.79.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/README.md +6 -6
- package/bin/lib/alias/collect.mjs +20 -3
- package/bin/lib/alias/index.mjs +12 -1
- package/bin/lib/alias/index.test.mjs +24 -0
- package/bin/lib/css/analyze.test.mjs +21 -1
- package/bin/lib/css/collect.mjs +14 -0
- package/bin/lib/css/extract.mjs +63 -5
- package/bin/lib/css/extract.test.mjs +110 -1
- package/bin/lib/css/fix.e2e.test.mjs +50 -0
- package/bin/lib/css/index.mjs +6 -1
- package/bin/lib/fs/contain.mjs +50 -0
- package/bin/lib/icons/generate.mjs +28 -3
- package/bin/lib/icons/generate.test.mjs +57 -1
- package/bin/lib/openapi/escape.mjs +20 -6
- package/bin/lib/openapi/generate.encode.test.mjs +120 -0
- package/bin/lib/openapi/generate.hostile.test.mjs +38 -9
- package/bin/lib/openapi/generate.mjs +203 -64
- package/bin/lib/openapi/generate.pagination.test.mjs +3 -2
- package/bin/lib/openapi/generate.test.mjs +270 -3
- package/bin/lib/openapi/schema-to-zod.mjs +5 -3
- package/bin/tempest-gen.test.mjs +188 -0
- package/bin/tempest.mjs +120 -44
- package/dist/access/Can.cjs.map +1 -1
- package/dist/access/Can.js.map +1 -1
- package/dist/access/access-control-context.cjs.map +1 -1
- package/dist/access/access-control-context.js.map +1 -1
- package/dist/access/create-role-access-control.cjs.map +1 -1
- package/dist/access/create-role-access-control.js.map +1 -1
- package/dist/access/permissions-from-token.cjs.map +1 -1
- package/dist/access/permissions-from-token.js.map +1 -1
- package/dist/access/use-can.cjs.map +1 -1
- package/dist/access/use-can.js.map +1 -1
- package/dist/app/AppProviders.cjs.map +1 -1
- package/dist/app/AppProviders.js.map +1 -1
- package/dist/audio/audio-bus.cjs.map +1 -1
- package/dist/audio/audio-bus.js.map +1 -1
- package/dist/audio/audio-output.cjs.map +1 -1
- package/dist/audio/audio-output.js.map +1 -1
- package/dist/audio/audio-player.cjs.map +1 -1
- package/dist/audio/audio-player.js.map +1 -1
- package/dist/audio/audio-recorder.cjs.map +1 -1
- package/dist/audio/audio-recorder.js.map +1 -1
- package/dist/audio/duration.cjs.map +1 -1
- package/dist/audio/duration.js.map +1 -1
- package/dist/audio/level-meter.cjs.map +1 -1
- package/dist/audio/level-meter.js.map +1 -1
- package/dist/audio/media-access.cjs.map +1 -1
- package/dist/audio/media-access.js.map +1 -1
- package/dist/audio/noise-floor.cjs.map +1 -1
- package/dist/audio/noise-floor.js.map +1 -1
- package/dist/audio/sfx-pool.cjs.map +1 -1
- package/dist/audio/sfx-pool.js.map +1 -1
- package/dist/audio/use-audio-bus.cjs.map +1 -1
- package/dist/audio/use-audio-bus.js.map +1 -1
- package/dist/audio/use-audio-recorder.cjs.map +1 -1
- package/dist/audio/use-audio-recorder.js.map +1 -1
- package/dist/audio/use-audio.cjs.map +1 -1
- package/dist/audio/use-audio.js.map +1 -1
- package/dist/audio/use-microphone.cjs +1 -1
- package/dist/audio/use-microphone.cjs.map +1 -1
- package/dist/audio/use-microphone.js +1 -5
- package/dist/audio/use-microphone.js.map +1 -1
- package/dist/audio/use-sfx-pool.cjs.map +1 -1
- package/dist/audio/use-sfx-pool.js.map +1 -1
- package/dist/audio/voice-activity.cjs.map +1 -1
- package/dist/audio/voice-activity.js.map +1 -1
- package/dist/audio/voice-chain-stages.cjs.map +1 -1
- package/dist/audio/voice-chain-stages.js.map +1 -1
- package/dist/audio/voice-chain.cjs.map +1 -1
- package/dist/audio/voice-chain.js.map +1 -1
- package/dist/audio/wav.cjs.map +1 -1
- package/dist/audio/wav.js.map +1 -1
- package/dist/auth/AuthGuard.cjs.map +1 -1
- package/dist/auth/AuthGuard.js.map +1 -1
- package/dist/auth/create-auth-store.cjs.map +1 -1
- package/dist/auth/create-auth-store.js.map +1 -1
- package/dist/auth/create-tempest-auth.cjs +1 -1
- package/dist/auth/create-tempest-auth.cjs.map +1 -1
- package/dist/auth/create-tempest-auth.js +185 -114
- package/dist/auth/create-tempest-auth.js.map +1 -1
- package/dist/auth/jwt.cjs.map +1 -1
- package/dist/auth/jwt.js.map +1 -1
- package/dist/auth/lazy-with-retry.cjs.map +1 -1
- package/dist/auth/lazy-with-retry.js.map +1 -1
- package/dist/auth/passkey.cjs.map +1 -1
- package/dist/auth/passkey.js.map +1 -1
- package/dist/auth/refresh-queue.cjs.map +1 -1
- package/dist/auth/refresh-queue.js.map +1 -1
- package/dist/auth/use-passkey.cjs +1 -1
- package/dist/auth/use-passkey.cjs.map +1 -1
- package/dist/auth/use-passkey.js +1 -1
- package/dist/auth/use-passkey.js.map +1 -1
- package/dist/br/BrazilMap.cjs.map +1 -1
- package/dist/br/BrazilMap.js.map +1 -1
- package/dist/br/BrazilMap.module.cjs.map +1 -1
- package/dist/br/BrazilMap.module.js.map +1 -1
- package/dist/br/BrazilStateCitySelect.cjs.map +1 -1
- package/dist/br/BrazilStateCitySelect.js.map +1 -1
- package/dist/br/BrazilStateMap.cjs.map +1 -1
- package/dist/br/BrazilStateMap.js.map +1 -1
- package/dist/br/MapLegend.cjs.map +1 -1
- package/dist/br/MapLegend.js.map +1 -1
- package/dist/br/MapLegend.module.cjs.map +1 -1
- package/dist/br/MapLegend.module.js.map +1 -1
- package/dist/br/MapMarkers.cjs.map +1 -1
- package/dist/br/MapMarkers.js.map +1 -1
- package/dist/br/MapTooltip.cjs.map +1 -1
- package/dist/br/MapTooltip.js.map +1 -1
- package/dist/br/MunicipalitySearch.cjs +1 -1
- package/dist/br/MunicipalitySearch.cjs.map +1 -1
- package/dist/br/MunicipalitySearch.js +2 -5
- package/dist/br/MunicipalitySearch.js.map +1 -1
- package/dist/br/MunicipalitySearch.module.cjs.map +1 -1
- package/dist/br/MunicipalitySearch.module.js.map +1 -1
- package/dist/br/PixQRCode.cjs.map +1 -1
- package/dist/br/PixQRCode.js.map +1 -1
- package/dist/br/PixQRCode.module.cjs.map +1 -1
- package/dist/br/PixQRCode.module.js.map +1 -1
- package/dist/br/boleto.cjs.map +1 -1
- package/dist/br/boleto.js.map +1 -1
- package/dist/br/br-geo.cjs.map +1 -1
- package/dist/br/br-geo.js.map +1 -1
- package/dist/br/data/br-centroids.cjs.map +1 -1
- package/dist/br/data/br-centroids.js.map +1 -1
- package/dist/br/data/br-locations.cjs.map +1 -1
- package/dist/br/data/br-locations.js.map +1 -1
- package/dist/br/data/br-uf-geo.cjs.map +1 -1
- package/dist/br/data/br-uf-geo.js.map +1 -1
- package/dist/br/data/mun/AC.cjs.map +1 -1
- package/dist/br/data/mun/AC.js.map +1 -1
- package/dist/br/data/mun/AL.cjs.map +1 -1
- package/dist/br/data/mun/AL.js.map +1 -1
- package/dist/br/data/mun/AM.cjs.map +1 -1
- package/dist/br/data/mun/AM.js.map +1 -1
- package/dist/br/data/mun/AP.cjs.map +1 -1
- package/dist/br/data/mun/AP.js.map +1 -1
- package/dist/br/data/mun/BA.cjs.map +1 -1
- package/dist/br/data/mun/BA.js.map +1 -1
- package/dist/br/data/mun/CE.cjs.map +1 -1
- package/dist/br/data/mun/CE.js.map +1 -1
- package/dist/br/data/mun/DF.cjs.map +1 -1
- package/dist/br/data/mun/DF.js.map +1 -1
- package/dist/br/data/mun/ES.cjs.map +1 -1
- package/dist/br/data/mun/ES.js.map +1 -1
- package/dist/br/data/mun/GO.cjs.map +1 -1
- package/dist/br/data/mun/GO.js.map +1 -1
- package/dist/br/data/mun/MA.cjs.map +1 -1
- package/dist/br/data/mun/MA.js.map +1 -1
- package/dist/br/data/mun/MG.cjs.map +1 -1
- package/dist/br/data/mun/MG.js.map +1 -1
- package/dist/br/data/mun/MS.cjs.map +1 -1
- package/dist/br/data/mun/MS.js.map +1 -1
- package/dist/br/data/mun/MT.cjs.map +1 -1
- package/dist/br/data/mun/MT.js.map +1 -1
- package/dist/br/data/mun/PA.cjs.map +1 -1
- package/dist/br/data/mun/PA.js.map +1 -1
- package/dist/br/data/mun/PB.cjs.map +1 -1
- package/dist/br/data/mun/PB.js.map +1 -1
- package/dist/br/data/mun/PE.cjs.map +1 -1
- package/dist/br/data/mun/PE.js.map +1 -1
- package/dist/br/data/mun/PI.cjs.map +1 -1
- package/dist/br/data/mun/PI.js.map +1 -1
- package/dist/br/data/mun/PR.cjs.map +1 -1
- package/dist/br/data/mun/PR.js.map +1 -1
- package/dist/br/data/mun/RJ.cjs.map +1 -1
- package/dist/br/data/mun/RJ.js.map +1 -1
- package/dist/br/data/mun/RN.cjs.map +1 -1
- package/dist/br/data/mun/RN.js.map +1 -1
- package/dist/br/data/mun/RO.cjs.map +1 -1
- package/dist/br/data/mun/RO.js.map +1 -1
- package/dist/br/data/mun/RR.cjs.map +1 -1
- package/dist/br/data/mun/RR.js.map +1 -1
- package/dist/br/data/mun/RS.cjs.map +1 -1
- package/dist/br/data/mun/RS.js.map +1 -1
- package/dist/br/data/mun/SC.cjs.map +1 -1
- package/dist/br/data/mun/SC.js.map +1 -1
- package/dist/br/data/mun/SE.cjs.map +1 -1
- package/dist/br/data/mun/SE.js.map +1 -1
- package/dist/br/data/mun/SP.cjs.map +1 -1
- package/dist/br/data/mun/SP.js.map +1 -1
- package/dist/br/data/mun/TO.cjs.map +1 -1
- package/dist/br/data/mun/TO.js.map +1 -1
- package/dist/br/geocode.cjs.map +1 -1
- package/dist/br/geocode.js.map +1 -1
- package/dist/br/holidays.cjs.map +1 -1
- package/dist/br/holidays.js.map +1 -1
- package/dist/br/locations.cjs.map +1 -1
- package/dist/br/locations.js.map +1 -1
- package/dist/br/nfe.cjs.map +1 -1
- package/dist/br/nfe.js.map +1 -1
- package/dist/br/pix.cjs +1 -1
- package/dist/br/pix.cjs.map +1 -1
- package/dist/br/pix.js +108 -71
- package/dist/br/pix.js.map +1 -1
- package/dist/br/regions.cjs.map +1 -1
- package/dist/br/regions.js.map +1 -1
- package/dist/br/scales.cjs.map +1 -1
- package/dist/br/scales.js.map +1 -1
- package/dist/br/state-geo.cjs.map +1 -1
- package/dist/br/state-geo.js.map +1 -1
- package/dist/br/svg-utils.cjs.map +1 -1
- package/dist/br/svg-utils.js.map +1 -1
- package/dist/br/use-map-hover.cjs.map +1 -1
- package/dist/br/use-map-hover.js.map +1 -1
- package/dist/br/use-map-zoom.cjs.map +1 -1
- package/dist/br/use-map-zoom.js.map +1 -1
- package/dist/br/whatsapp.cjs.map +1 -1
- package/dist/br/whatsapp.js.map +1 -1
- package/dist/br.cjs.map +1 -1
- package/dist/br.d.ts +16 -5
- package/dist/br.js.map +1 -1
- package/dist/capture/barcode.cjs.map +1 -1
- package/dist/capture/barcode.js.map +1 -1
- package/dist/capture/media-recorder.cjs.map +1 -1
- package/dist/capture/media-recorder.js.map +1 -1
- package/dist/capture/use-barcode-scanner.cjs.map +1 -1
- package/dist/capture/use-barcode-scanner.js.map +1 -1
- package/dist/capture/use-screen-capture.cjs +1 -1
- package/dist/capture/use-screen-capture.cjs.map +1 -1
- package/dist/capture/use-screen-capture.js +1 -7
- package/dist/capture/use-screen-capture.js.map +1 -1
- package/dist/capture/use-speech-recognition.cjs +1 -1
- package/dist/capture/use-speech-recognition.cjs.map +1 -1
- package/dist/capture/use-speech-recognition.js +35 -36
- package/dist/capture/use-speech-recognition.js.map +1 -1
- package/dist/capture/use-torch.cjs.map +1 -1
- package/dist/capture/use-torch.js.map +1 -1
- package/dist/capture/use-video-recorder.cjs.map +1 -1
- package/dist/capture/use-video-recorder.js.map +1 -1
- package/dist/capture/video-recorder.cjs.map +1 -1
- package/dist/capture/video-recorder.js.map +1 -1
- package/dist/charts/AreaChart.cjs.map +1 -1
- package/dist/charts/AreaChart.js.map +1 -1
- package/dist/charts/BarChart.cjs.map +1 -1
- package/dist/charts/BarChart.js.map +1 -1
- package/dist/charts/LineChart.cjs.map +1 -1
- package/dist/charts/LineChart.js.map +1 -1
- package/dist/charts/PieChart.cjs.map +1 -1
- package/dist/charts/PieChart.js.map +1 -1
- package/dist/charts/RadarChart.cjs.map +1 -1
- package/dist/charts/RadarChart.js.map +1 -1
- package/dist/charts/palette.cjs.map +1 -1
- package/dist/charts/palette.js.map +1 -1
- package/dist/charts/scales.cjs.map +1 -1
- package/dist/charts/scales.js.map +1 -1
- package/dist/charts/types.cjs.map +1 -1
- package/dist/charts/types.js.map +1 -1
- package/dist/charts/use-chart-colors.cjs.map +1 -1
- package/dist/charts/use-chart-colors.js.map +1 -1
- package/dist/components/AIChat/AIChat.cjs +1 -1
- package/dist/components/AIChat/AIChat.cjs.map +1 -1
- package/dist/components/AIChat/AIChat.js +1 -5
- package/dist/components/AIChat/AIChat.js.map +1 -1
- package/dist/components/AIChat/AIChat.module.cjs.map +1 -1
- package/dist/components/AIChat/AIChat.module.js.map +1 -1
- package/dist/components/AIChat/AIChatComposer.cjs +1 -1
- package/dist/components/AIChat/AIChatComposer.cjs.map +1 -1
- package/dist/components/AIChat/AIChatComposer.js +1 -7
- package/dist/components/AIChat/AIChatComposer.js.map +1 -1
- package/dist/components/AIChat/AIChatTurn.cjs.map +1 -1
- package/dist/components/AIChat/AIChatTurn.js.map +1 -1
- package/dist/components/AIChat/ai-chat-turns.cjs.map +1 -1
- package/dist/components/AIChat/ai-chat-turns.js.map +1 -1
- package/dist/components/Accordion/Accordion.cjs.map +1 -1
- package/dist/components/Accordion/Accordion.js.map +1 -1
- package/dist/components/Accordion/Accordion.module.cjs.map +1 -1
- package/dist/components/Accordion/Accordion.module.js.map +1 -1
- package/dist/components/Alert/Alert.cjs.map +1 -1
- package/dist/components/Alert/Alert.js.map +1 -1
- package/dist/components/Alert/Alert.module.cjs.map +1 -1
- package/dist/components/Alert/Alert.module.js.map +1 -1
- package/dist/components/AppBar/AppBar.cjs.map +1 -1
- package/dist/components/AppBar/AppBar.js.map +1 -1
- package/dist/components/AppBar/AppBar.module.cjs.map +1 -1
- package/dist/components/AppBar/AppBar.module.js.map +1 -1
- package/dist/components/AppBar/use-sticky-body-warning.cjs +1 -1
- package/dist/components/AppBar/use-sticky-body-warning.cjs.map +1 -1
- package/dist/components/AppBar/use-sticky-body-warning.js +1 -1
- package/dist/components/AppBar/use-sticky-body-warning.js.map +1 -1
- package/dist/components/AppShell/AppShell.cjs.map +1 -1
- package/dist/components/AppShell/AppShell.js.map +1 -1
- package/dist/components/AppShell/AppShell.module.cjs.map +1 -1
- package/dist/components/AppShell/AppShell.module.js.map +1 -1
- package/dist/components/AspectRatio/AspectRatio.cjs.map +1 -1
- package/dist/components/AspectRatio/AspectRatio.js.map +1 -1
- package/dist/components/AspectRatio/AspectRatio.module.cjs.map +1 -1
- package/dist/components/AspectRatio/AspectRatio.module.js.map +1 -1
- package/dist/components/AudioPlayer/AudioPlayer.cjs +1 -1
- package/dist/components/AudioPlayer/AudioPlayer.cjs.map +1 -1
- package/dist/components/AudioPlayer/AudioPlayer.js +1 -7
- package/dist/components/AudioPlayer/AudioPlayer.js.map +1 -1
- package/dist/components/AudioPlayer/AudioPlayer.module.cjs.map +1 -1
- package/dist/components/AudioPlayer/AudioPlayer.module.js.map +1 -1
- package/dist/components/AudioRecorder/AudioRecorder.cjs +1 -1
- package/dist/components/AudioRecorder/AudioRecorder.cjs.map +1 -1
- package/dist/components/AudioRecorder/AudioRecorder.js +16 -21
- package/dist/components/AudioRecorder/AudioRecorder.js.map +1 -1
- package/dist/components/AudioRecorder/AudioRecorder.module.cjs.map +1 -1
- package/dist/components/AudioRecorder/AudioRecorder.module.js.map +1 -1
- package/dist/components/Avatar/Avatar.cjs.map +1 -1
- package/dist/components/Avatar/Avatar.js.map +1 -1
- package/dist/components/Avatar/Avatar.module.cjs.map +1 -1
- package/dist/components/Avatar/Avatar.module.js.map +1 -1
- package/dist/components/AvatarGroup/AvatarGroup.cjs.map +1 -1
- package/dist/components/AvatarGroup/AvatarGroup.js.map +1 -1
- package/dist/components/AvatarGroup/AvatarGroup.module.cjs.map +1 -1
- package/dist/components/AvatarGroup/AvatarGroup.module.js.map +1 -1
- package/dist/components/Badge/Badge.cjs.map +1 -1
- package/dist/components/Badge/Badge.js.map +1 -1
- package/dist/components/Badge/Badge.module.cjs.map +1 -1
- package/dist/components/Badge/Badge.module.js.map +1 -1
- package/dist/components/Banner/Banner.cjs.map +1 -1
- package/dist/components/Banner/Banner.js.map +1 -1
- package/dist/components/Banner/Banner.module.cjs.map +1 -1
- package/dist/components/Banner/Banner.module.js.map +1 -1
- package/dist/components/BarList/BarList.cjs.map +1 -1
- package/dist/components/BarList/BarList.js.map +1 -1
- package/dist/components/BarList/BarList.module.cjs.map +1 -1
- package/dist/components/BarList/BarList.module.js.map +1 -1
- package/dist/components/BarList/bar-list-model.cjs.map +1 -1
- package/dist/components/BarList/bar-list-model.js.map +1 -1
- package/dist/components/BarcodeScanner/BarcodeScanner.cjs.map +1 -1
- package/dist/components/BarcodeScanner/BarcodeScanner.js.map +1 -1
- package/dist/components/BarcodeScanner/BarcodeScanner.module.cjs.map +1 -1
- package/dist/components/BarcodeScanner/BarcodeScanner.module.js.map +1 -1
- package/dist/components/BottomNavigation/BottomNavigation.cjs.map +1 -1
- package/dist/components/BottomNavigation/BottomNavigation.js.map +1 -1
- package/dist/components/BottomNavigation/BottomNavigation.module.cjs.map +1 -1
- package/dist/components/BottomNavigation/BottomNavigation.module.js.map +1 -1
- package/dist/components/BottomSheet/BottomSheet.cjs.map +1 -1
- package/dist/components/BottomSheet/BottomSheet.js.map +1 -1
- package/dist/components/BottomSheet/BottomSheet.module.cjs.map +1 -1
- package/dist/components/BottomSheet/BottomSheet.module.js.map +1 -1
- package/dist/components/Breadcrumbs/Breadcrumbs.cjs.map +1 -1
- package/dist/components/Breadcrumbs/Breadcrumbs.js.map +1 -1
- package/dist/components/Breadcrumbs/Breadcrumbs.module.cjs.map +1 -1
- package/dist/components/Breadcrumbs/Breadcrumbs.module.js.map +1 -1
- package/dist/components/Button/Button.cjs.map +1 -1
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Button/Button.module.cjs.map +1 -1
- package/dist/components/Button/Button.module.js.map +1 -1
- package/dist/components/Button/ButtonContent.cjs.map +1 -1
- package/dist/components/Button/ButtonContent.js.map +1 -1
- package/dist/components/Button/ButtonSlot.cjs.map +1 -1
- package/dist/components/Button/ButtonSlot.js.map +1 -1
- package/dist/components/Button/button-class.cjs.map +1 -1
- package/dist/components/Button/button-class.js.map +1 -1
- package/dist/components/Button/link-rel.cjs.map +1 -1
- package/dist/components/Button/link-rel.js.map +1 -1
- package/dist/components/Button/slot.cjs.map +1 -1
- package/dist/components/Button/slot.js.map +1 -1
- package/dist/components/Calendar/Calendar.cjs.map +1 -1
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Calendar/Calendar.module.cjs.map +1 -1
- package/dist/components/Calendar/Calendar.module.js.map +1 -1
- package/dist/components/Card/Card.cjs.map +1 -1
- package/dist/components/Card/Card.js.map +1 -1
- package/dist/components/Card/Card.module.cjs.map +1 -1
- package/dist/components/Card/Card.module.js.map +1 -1
- package/dist/components/Carousel/Carousel.cjs.map +1 -1
- package/dist/components/Carousel/Carousel.js.map +1 -1
- package/dist/components/Carousel/Carousel.module.cjs.map +1 -1
- package/dist/components/Carousel/Carousel.module.js.map +1 -1
- package/dist/components/Center/Center.cjs.map +1 -1
- package/dist/components/Center/Center.js.map +1 -1
- package/dist/components/Center/Center.module.cjs.map +1 -1
- package/dist/components/Center/Center.module.js.map +1 -1
- package/dist/components/Chat/Chat.cjs.map +1 -1
- package/dist/components/Chat/Chat.js.map +1 -1
- package/dist/components/Chat/Chat.module.cjs.map +1 -1
- package/dist/components/Chat/Chat.module.js.map +1 -1
- package/dist/components/Chat/ChatActionsMenu.cjs.map +1 -1
- package/dist/components/Chat/ChatActionsMenu.js.map +1 -1
- package/dist/components/Chat/ChatAttachments.cjs.map +1 -1
- package/dist/components/Chat/ChatAttachments.js.map +1 -1
- package/dist/components/Chat/ChatBubble.cjs.map +1 -1
- package/dist/components/Chat/ChatBubble.js.map +1 -1
- package/dist/components/Chat/ChatComposer.cjs.map +1 -1
- package/dist/components/Chat/ChatComposer.js.map +1 -1
- package/dist/components/Chat/chat-groups.cjs +1 -1
- package/dist/components/Chat/chat-groups.cjs.map +1 -1
- package/dist/components/Chat/chat-groups.js +2 -6
- package/dist/components/Chat/chat-groups.js.map +1 -1
- package/dist/components/Chat/chat-receipt.cjs.map +1 -1
- package/dist/components/Chat/chat-receipt.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.cjs.map +1 -1
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.module.cjs.map +1 -1
- package/dist/components/Checkbox/Checkbox.module.js.map +1 -1
- package/dist/components/ChipInput/ChipInput.cjs +1 -1
- package/dist/components/ChipInput/ChipInput.cjs.map +1 -1
- package/dist/components/ChipInput/ChipInput.js +2 -12
- package/dist/components/ChipInput/ChipInput.js.map +1 -1
- package/dist/components/ChipInput/ChipInput.module.cjs.map +1 -1
- package/dist/components/ChipInput/ChipInput.module.js.map +1 -1
- package/dist/components/ClickOutside/ClickOutside.cjs.map +1 -1
- package/dist/components/ClickOutside/ClickOutside.js.map +1 -1
- package/dist/components/CodeBlock/CodeBlock.cjs +1 -1
- package/dist/components/CodeBlock/CodeBlock.cjs.map +1 -1
- package/dist/components/CodeBlock/CodeBlock.js +1 -1
- package/dist/components/CodeBlock/CodeBlock.js.map +1 -1
- package/dist/components/CodeBlock/CodeBlock.module.cjs.map +1 -1
- package/dist/components/CodeBlock/CodeBlock.module.js.map +1 -1
- package/dist/components/CodeBlock/tokenize.cjs +1 -1
- package/dist/components/CodeBlock/tokenize.cjs.map +1 -1
- package/dist/components/CodeBlock/tokenize.js +54 -25
- package/dist/components/CodeBlock/tokenize.js.map +1 -1
- package/dist/components/Collapsible/Collapsible.cjs.map +1 -1
- package/dist/components/Collapsible/Collapsible.js.map +1 -1
- package/dist/components/Collapsible/Collapsible.module.cjs.map +1 -1
- package/dist/components/Collapsible/Collapsible.module.js.map +1 -1
- package/dist/components/Combobox/Combobox.cjs.map +1 -1
- package/dist/components/Combobox/Combobox.js.map +1 -1
- package/dist/components/Combobox/Combobox.module.cjs.map +1 -1
- package/dist/components/Combobox/Combobox.module.js.map +1 -1
- package/dist/components/Combobox/use-listbox-dismiss.cjs.map +1 -1
- package/dist/components/Combobox/use-listbox-dismiss.js.map +1 -1
- package/dist/components/Command/Command.cjs +1 -1
- package/dist/components/Command/Command.cjs.map +1 -1
- package/dist/components/Command/Command.js +4 -11
- package/dist/components/Command/Command.js.map +1 -1
- package/dist/components/Command/Command.module.cjs.map +1 -1
- package/dist/components/Command/Command.module.js.map +1 -1
- package/dist/components/ConditionalWrapper/ConditionalWrapper.cjs.map +1 -1
- package/dist/components/ConditionalWrapper/ConditionalWrapper.js.map +1 -1
- package/dist/components/ConfirmDialog/ConfirmDialog.cjs.map +1 -1
- package/dist/components/ConfirmDialog/ConfirmDialog.js.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.cjs +1 -1
- package/dist/components/ContextMenu/ContextMenu.cjs.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.js +1 -1
- package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.module.cjs.map +1 -1
- package/dist/components/ContextMenu/ContextMenu.module.js.map +1 -1
- package/dist/components/CopyButton/CopyButton.cjs.map +1 -1
- package/dist/components/CopyButton/CopyButton.js.map +1 -1
- package/dist/components/CopyButton/CopyButton.module.cjs.map +1 -1
- package/dist/components/CopyButton/CopyButton.module.js.map +1 -1
- package/dist/components/DataList/DataList.cjs.map +1 -1
- package/dist/components/DataList/DataList.js.map +1 -1
- package/dist/components/DataList/DataList.module.cjs.map +1 -1
- package/dist/components/DataList/DataList.module.js.map +1 -1
- package/dist/components/DataTable/DataTable.cjs +1 -1
- package/dist/components/DataTable/DataTable.cjs.map +1 -1
- package/dist/components/DataTable/DataTable.js +6 -14
- package/dist/components/DataTable/DataTable.js.map +1 -1
- package/dist/components/DataTable/DataTable.module.cjs.map +1 -1
- package/dist/components/DataTable/DataTable.module.js.map +1 -1
- package/dist/components/DataTable/EditableCell.cjs +1 -1
- package/dist/components/DataTable/EditableCell.cjs.map +1 -1
- package/dist/components/DataTable/EditableCell.js +1 -9
- package/dist/components/DataTable/EditableCell.js.map +1 -1
- package/dist/components/DataTable/LoadingRows.cjs.map +1 -1
- package/dist/components/DataTable/LoadingRows.js.map +1 -1
- package/dist/components/DataTable/edit-labels.cjs.map +1 -1
- package/dist/components/DataTable/edit-labels.js.map +1 -1
- package/dist/components/DataTable/use-dev-warnings.cjs.map +1 -1
- package/dist/components/DataTable/use-dev-warnings.js.map +1 -1
- package/dist/components/DatePicker/DatePicker.cjs.map +1 -1
- package/dist/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.cjs.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.js.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.module.cjs.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.module.js.map +1 -1
- package/dist/components/DescriptionList/DescriptionList.cjs.map +1 -1
- package/dist/components/DescriptionList/DescriptionList.js.map +1 -1
- package/dist/components/DescriptionList/DescriptionList.module.cjs.map +1 -1
- package/dist/components/DescriptionList/DescriptionList.module.js.map +1 -1
- package/dist/components/Divider/Divider.cjs.map +1 -1
- package/dist/components/Divider/Divider.js.map +1 -1
- package/dist/components/Divider/Divider.module.cjs.map +1 -1
- package/dist/components/Divider/Divider.module.js.map +1 -1
- package/dist/components/Drawer/Drawer.cjs.map +1 -1
- package/dist/components/Drawer/Drawer.js.map +1 -1
- package/dist/components/Drawer/Drawer.module.cjs.map +1 -1
- package/dist/components/Drawer/Drawer.module.js.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.cjs +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.cjs.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.js +2 -14
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.module.cjs.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.module.js.map +1 -1
- package/dist/components/Dropzone/Dropzone.cjs.map +1 -1
- package/dist/components/Dropzone/Dropzone.js.map +1 -1
- package/dist/components/Dropzone/Dropzone.module.cjs.map +1 -1
- package/dist/components/Dropzone/Dropzone.module.js.map +1 -1
- package/dist/components/EmptyState/EmptyState.cjs.map +1 -1
- package/dist/components/EmptyState/EmptyState.js.map +1 -1
- package/dist/components/EmptyState/EmptyState.module.cjs.map +1 -1
- package/dist/components/EmptyState/EmptyState.module.js.map +1 -1
- package/dist/components/ErrorState/ErrorState.cjs.map +1 -1
- package/dist/components/ErrorState/ErrorState.js.map +1 -1
- package/dist/components/ErrorState/ErrorState.module.cjs.map +1 -1
- package/dist/components/ErrorState/ErrorState.module.js.map +1 -1
- package/dist/components/ErrorText/ErrorText.cjs.map +1 -1
- package/dist/components/ErrorText/ErrorText.js.map +1 -1
- package/dist/components/ErrorText/ErrorText.module.cjs.map +1 -1
- package/dist/components/ErrorText/ErrorText.module.js.map +1 -1
- package/dist/components/FileUpload/FileUpload.cjs +1 -1
- package/dist/components/FileUpload/FileUpload.cjs.map +1 -1
- package/dist/components/FileUpload/FileUpload.js +7 -17
- package/dist/components/FileUpload/FileUpload.js.map +1 -1
- package/dist/components/FileUpload/FileUpload.module.cjs.map +1 -1
- package/dist/components/FileUpload/FileUpload.module.js.map +1 -1
- package/dist/components/FilterBar/FilterBar.cjs.map +1 -1
- package/dist/components/FilterBar/FilterBar.js.map +1 -1
- package/dist/components/FilterBar/FilterBar.module.cjs.map +1 -1
- package/dist/components/FilterBar/FilterBar.module.js.map +1 -1
- package/dist/components/FilterBar/filter-apply.cjs.map +1 -1
- package/dist/components/FilterBar/filter-apply.js.map +1 -1
- package/dist/components/FilterBar/filter-model.cjs.map +1 -1
- package/dist/components/FilterBar/filter-model.js.map +1 -1
- package/dist/components/FilterBar/filter-query.cjs +1 -1
- package/dist/components/FilterBar/filter-query.cjs.map +1 -1
- package/dist/components/FilterBar/filter-query.js +2 -5
- package/dist/components/FilterBar/filter-query.js.map +1 -1
- package/dist/components/FilterPanel/FilterPanel.cjs.map +1 -1
- package/dist/components/FilterPanel/FilterPanel.js.map +1 -1
- package/dist/components/FilterPanel/FilterPanel.module.cjs.map +1 -1
- package/dist/components/FilterPanel/FilterPanel.module.js.map +1 -1
- package/dist/components/FloatingActionButton/FloatingActionButton.cjs.map +1 -1
- package/dist/components/FloatingActionButton/FloatingActionButton.js.map +1 -1
- package/dist/components/FloatingActionButton/FloatingActionButton.module.cjs.map +1 -1
- package/dist/components/FloatingActionButton/FloatingActionButton.module.js.map +1 -1
- package/dist/components/For/For.cjs.map +1 -1
- package/dist/components/For/For.js.map +1 -1
- package/dist/components/Form/Form.cjs.map +1 -1
- package/dist/components/Form/Form.js.map +1 -1
- package/dist/components/Form/Form.module.cjs.map +1 -1
- package/dist/components/Form/Form.module.js.map +1 -1
- package/dist/components/HoverCard/HoverCard.cjs.map +1 -1
- package/dist/components/HoverCard/HoverCard.js.map +1 -1
- package/dist/components/HoverCard/HoverCard.module.cjs.map +1 -1
- package/dist/components/HoverCard/HoverCard.module.js.map +1 -1
- package/dist/components/Image/Image.cjs.map +1 -1
- package/dist/components/Image/Image.js.map +1 -1
- package/dist/components/Image/Image.module.cjs.map +1 -1
- package/dist/components/Image/Image.module.js.map +1 -1
- package/dist/components/ImageCropper/ImageCropper.cjs +1 -1
- package/dist/components/ImageCropper/ImageCropper.cjs.map +1 -1
- package/dist/components/ImageCropper/ImageCropper.js +4 -8
- package/dist/components/ImageCropper/ImageCropper.js.map +1 -1
- package/dist/components/ImageCropper/ImageCropper.module.cjs.map +1 -1
- package/dist/components/ImageCropper/ImageCropper.module.js.map +1 -1
- package/dist/components/ImageCropper/crop-geometry.cjs.map +1 -1
- package/dist/components/ImageCropper/crop-geometry.js.map +1 -1
- package/dist/components/Input/Input.cjs.map +1 -1
- package/dist/components/Input/Input.js.map +1 -1
- package/dist/components/Input/Input.module.cjs.map +1 -1
- package/dist/components/Input/Input.module.js.map +1 -1
- package/dist/components/InstallBanner/InstallBanner.cjs.map +1 -1
- package/dist/components/InstallBanner/InstallBanner.js.map +1 -1
- package/dist/components/InstallBanner/InstallBanner.module.cjs.map +1 -1
- package/dist/components/InstallBanner/InstallBanner.module.js.map +1 -1
- package/dist/components/InstallButton/InstallButton.cjs.map +1 -1
- package/dist/components/InstallButton/InstallButton.js.map +1 -1
- package/dist/components/InstallButton/InstallButton.module.cjs.map +1 -1
- package/dist/components/InstallButton/InstallButton.module.js.map +1 -1
- package/dist/components/InstallButton/install-hints.cjs.map +1 -1
- package/dist/components/InstallButton/install-hints.js.map +1 -1
- package/dist/components/Kanban/Kanban.cjs.map +1 -1
- package/dist/components/Kanban/Kanban.js.map +1 -1
- package/dist/components/Kanban/Kanban.module.cjs.map +1 -1
- package/dist/components/Kanban/Kanban.module.js.map +1 -1
- package/dist/components/Kbd/Kbd.cjs.map +1 -1
- package/dist/components/Kbd/Kbd.js.map +1 -1
- package/dist/components/Kbd/Kbd.module.cjs.map +1 -1
- package/dist/components/Kbd/Kbd.module.js.map +1 -1
- package/dist/components/Label/Label.cjs.map +1 -1
- package/dist/components/Label/Label.js.map +1 -1
- package/dist/components/Label/Label.module.cjs.map +1 -1
- package/dist/components/Label/Label.module.js.map +1 -1
- package/dist/components/Layout/Layout.cjs.map +1 -1
- package/dist/components/Layout/Layout.js.map +1 -1
- package/dist/components/Layout/Layout.module.cjs.map +1 -1
- package/dist/components/Layout/Layout.module.js.map +1 -1
- package/dist/components/Lightbox/Lightbox.cjs +1 -1
- package/dist/components/Lightbox/Lightbox.cjs.map +1 -1
- package/dist/components/Lightbox/Lightbox.js +1 -1
- package/dist/components/Lightbox/Lightbox.js.map +1 -1
- package/dist/components/Lightbox/Lightbox.module.cjs.map +1 -1
- package/dist/components/Lightbox/Lightbox.module.js.map +1 -1
- package/dist/components/ListTile/ListTile.cjs.map +1 -1
- package/dist/components/ListTile/ListTile.js.map +1 -1
- package/dist/components/ListTile/ListTile.module.cjs.map +1 -1
- package/dist/components/ListTile/ListTile.module.js.map +1 -1
- package/dist/components/Markdown/Markdown.cjs.map +1 -1
- package/dist/components/Markdown/Markdown.js.map +1 -1
- package/dist/components/Markdown/Markdown.module.cjs.map +1 -1
- package/dist/components/Markdown/Markdown.module.js.map +1 -1
- package/dist/components/Markdown/markdown-parse.cjs +6 -6
- package/dist/components/Markdown/markdown-parse.cjs.map +1 -1
- package/dist/components/Markdown/markdown-parse.js +94 -96
- package/dist/components/Markdown/markdown-parse.js.map +1 -1
- package/dist/components/Masonry/Masonry.cjs.map +1 -1
- package/dist/components/Masonry/Masonry.js.map +1 -1
- package/dist/components/Masonry/Masonry.module.cjs.map +1 -1
- package/dist/components/Masonry/Masonry.module.js.map +1 -1
- package/dist/components/Masonry/masonry-layout.cjs.map +1 -1
- package/dist/components/Masonry/masonry-layout.js.map +1 -1
- package/dist/components/Menubar/Menubar.cjs.map +1 -1
- package/dist/components/Menubar/Menubar.js.map +1 -1
- package/dist/components/Menubar/Menubar.module.cjs.map +1 -1
- package/dist/components/Menubar/Menubar.module.js.map +1 -1
- package/dist/components/Modal/Modal.cjs.map +1 -1
- package/dist/components/Modal/Modal.js.map +1 -1
- package/dist/components/Modal/Modal.module.cjs.map +1 -1
- package/dist/components/Modal/Modal.module.js.map +1 -1
- package/dist/components/ModalsManager/ModalsManager.cjs.map +1 -1
- package/dist/components/ModalsManager/ModalsManager.js.map +1 -1
- package/dist/components/ModalsManager/ModalsManager.module.cjs.map +1 -1
- package/dist/components/ModalsManager/ModalsManager.module.js.map +1 -1
- package/dist/components/Money/Money.cjs.map +1 -1
- package/dist/components/Money/Money.js.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.cjs.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.module.cjs.map +1 -1
- package/dist/components/MultiSelect/MultiSelect.module.js.map +1 -1
- package/dist/components/NProgress/NProgress.cjs.map +1 -1
- package/dist/components/NProgress/NProgress.js.map +1 -1
- package/dist/components/NProgress/NProgress.module.cjs.map +1 -1
- package/dist/components/NProgress/NProgress.module.js.map +1 -1
- package/dist/components/Navbar/Navbar.cjs.map +1 -1
- package/dist/components/Navbar/Navbar.js.map +1 -1
- package/dist/components/Navbar/Navbar.module.cjs.map +1 -1
- package/dist/components/Navbar/Navbar.module.js.map +1 -1
- package/dist/components/NavigationMenu/NavigationMenu.cjs.map +1 -1
- package/dist/components/NavigationMenu/NavigationMenu.js.map +1 -1
- package/dist/components/NavigationMenu/NavigationMenu.module.cjs.map +1 -1
- package/dist/components/NavigationMenu/NavigationMenu.module.js.map +1 -1
- package/dist/components/NavigationRail/NavigationRail.cjs.map +1 -1
- package/dist/components/NavigationRail/NavigationRail.js.map +1 -1
- package/dist/components/NavigationRail/NavigationRail.module.cjs.map +1 -1
- package/dist/components/NavigationRail/NavigationRail.module.js.map +1 -1
- package/dist/components/NotificationCenter/NotificationCenter.cjs.map +1 -1
- package/dist/components/NotificationCenter/NotificationCenter.js.map +1 -1
- package/dist/components/NotificationCenter/NotificationCenter.module.cjs.map +1 -1
- package/dist/components/NotificationCenter/NotificationCenter.module.js.map +1 -1
- package/dist/components/NotificationCenter/use-notification-inbox.cjs.map +1 -1
- package/dist/components/NotificationCenter/use-notification-inbox.js.map +1 -1
- package/dist/components/OfflineIndicator/OfflineIndicator.cjs.map +1 -1
- package/dist/components/OfflineIndicator/OfflineIndicator.js.map +1 -1
- package/dist/components/OfflineIndicator/OfflineIndicator.module.cjs.map +1 -1
- package/dist/components/OfflineIndicator/OfflineIndicator.module.js.map +1 -1
- package/dist/components/Page/Page.cjs.map +1 -1
- package/dist/components/Page/Page.js.map +1 -1
- package/dist/components/Page/Page.module.cjs.map +1 -1
- package/dist/components/Page/Page.module.js.map +1 -1
- package/dist/components/Pagination/Pagination.cjs.map +1 -1
- package/dist/components/Pagination/Pagination.js.map +1 -1
- package/dist/components/Pagination/Pagination.module.cjs.map +1 -1
- package/dist/components/Pagination/Pagination.module.js.map +1 -1
- package/dist/components/PasswordInput/PasswordInput.cjs.map +1 -1
- package/dist/components/PasswordInput/PasswordInput.js.map +1 -1
- package/dist/components/PasswordInput/PasswordInput.module.cjs.map +1 -1
- package/dist/components/PasswordInput/PasswordInput.module.js.map +1 -1
- package/dist/components/PinInput/PinInput.cjs.map +1 -1
- package/dist/components/PinInput/PinInput.js.map +1 -1
- package/dist/components/PinInput/PinInput.module.cjs.map +1 -1
- package/dist/components/PinInput/PinInput.module.js.map +1 -1
- package/dist/components/Popover/Popover.cjs.map +1 -1
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/Popover/Popover.module.cjs.map +1 -1
- package/dist/components/Popover/Popover.module.js.map +1 -1
- package/dist/components/Portal/Portal.cjs.map +1 -1
- package/dist/components/Portal/Portal.js.map +1 -1
- package/dist/components/Portal/anchor-position.cjs.map +1 -1
- package/dist/components/Portal/anchor-position.js.map +1 -1
- package/dist/components/Portal/escape-layer.cjs.map +1 -1
- package/dist/components/Portal/escape-layer.js.map +1 -1
- package/dist/components/Portal/portal-host.cjs.map +1 -1
- package/dist/components/Portal/portal-host.js.map +1 -1
- package/dist/components/Portal/tab-bridge.cjs +1 -1
- package/dist/components/Portal/tab-bridge.cjs.map +1 -1
- package/dist/components/Portal/tab-bridge.js +1 -5
- package/dist/components/Portal/tab-bridge.js.map +1 -1
- package/dist/components/Progress/Progress.cjs.map +1 -1
- package/dist/components/Progress/Progress.js.map +1 -1
- package/dist/components/Progress/Progress.module.cjs.map +1 -1
- package/dist/components/Progress/Progress.module.js.map +1 -1
- package/dist/components/QRCode/QRCode.cjs.map +1 -1
- package/dist/components/QRCode/QRCode.js.map +1 -1
- package/dist/components/QRCode/QRCode.module.cjs.map +1 -1
- package/dist/components/QRCode/QRCode.module.js.map +1 -1
- package/dist/components/QRCode/qr-encode.cjs +1 -1
- package/dist/components/QRCode/qr-encode.cjs.map +1 -1
- package/dist/components/QRCode/qr-encode.js +7 -13
- package/dist/components/QRCode/qr-encode.js.map +1 -1
- package/dist/components/QRCode/qr-tables.cjs.map +1 -1
- package/dist/components/QRCode/qr-tables.js.map +1 -1
- package/dist/components/Radio/Radio.cjs.map +1 -1
- package/dist/components/Radio/Radio.js.map +1 -1
- package/dist/components/Radio/Radio.module.cjs.map +1 -1
- package/dist/components/Radio/Radio.module.js.map +1 -1
- package/dist/components/RangeSlider/RangeSlider.cjs.map +1 -1
- package/dist/components/RangeSlider/RangeSlider.js.map +1 -1
- package/dist/components/RangeSlider/RangeSlider.module.cjs.map +1 -1
- package/dist/components/RangeSlider/RangeSlider.module.js.map +1 -1
- package/dist/components/RatingStars/RatingStars.cjs.map +1 -1
- package/dist/components/RatingStars/RatingStars.js.map +1 -1
- package/dist/components/RatingStars/RatingStars.module.cjs.map +1 -1
- package/dist/components/RatingStars/RatingStars.module.js.map +1 -1
- package/dist/components/RefreshIndicator/RefreshIndicator.cjs +1 -1
- package/dist/components/RefreshIndicator/RefreshIndicator.cjs.map +1 -1
- package/dist/components/RefreshIndicator/RefreshIndicator.js +10 -18
- package/dist/components/RefreshIndicator/RefreshIndicator.js.map +1 -1
- package/dist/components/RefreshIndicator/RefreshIndicator.module.cjs.map +1 -1
- package/dist/components/RefreshIndicator/RefreshIndicator.module.js.map +1 -1
- package/dist/components/RelativeTime/RelativeTime.cjs.map +1 -1
- package/dist/components/RelativeTime/RelativeTime.js.map +1 -1
- package/dist/components/Resizable/Resizable.cjs +1 -1
- package/dist/components/Resizable/Resizable.cjs.map +1 -1
- package/dist/components/Resizable/Resizable.js +1 -9
- package/dist/components/Resizable/Resizable.js.map +1 -1
- package/dist/components/Resizable/Resizable.module.cjs.map +1 -1
- package/dist/components/Resizable/Resizable.module.js.map +1 -1
- package/dist/components/Responsive/Responsive.cjs.map +1 -1
- package/dist/components/Responsive/Responsive.js.map +1 -1
- package/dist/components/Reveal/Reveal.cjs.map +1 -1
- package/dist/components/Reveal/Reveal.js.map +1 -1
- package/dist/components/Reveal/Reveal.module.cjs.map +1 -1
- package/dist/components/Reveal/Reveal.module.js.map +1 -1
- package/dist/components/Reveal/reveal-threshold.cjs.map +1 -1
- package/dist/components/Reveal/reveal-threshold.js.map +1 -1
- package/dist/components/SafeArea/SafeArea.cjs.map +1 -1
- package/dist/components/SafeArea/SafeArea.js.map +1 -1
- package/dist/components/SafeArea/SafeArea.module.cjs.map +1 -1
- package/dist/components/SafeArea/SafeArea.module.js.map +1 -1
- package/dist/components/Scheduler/Scheduler.cjs.map +1 -1
- package/dist/components/Scheduler/Scheduler.js.map +1 -1
- package/dist/components/Scheduler/Scheduler.module.cjs.map +1 -1
- package/dist/components/Scheduler/Scheduler.module.js.map +1 -1
- package/dist/components/Scheduler/scheduler-layout.cjs.map +1 -1
- package/dist/components/Scheduler/scheduler-layout.js.map +1 -1
- package/dist/components/ScrollArea/ScrollArea.cjs.map +1 -1
- package/dist/components/ScrollArea/ScrollArea.js.map +1 -1
- package/dist/components/ScrollArea/ScrollArea.module.cjs.map +1 -1
- package/dist/components/ScrollArea/ScrollArea.module.js.map +1 -1
- package/dist/components/SearchBar/SearchBar.cjs.map +1 -1
- package/dist/components/SearchBar/SearchBar.js.map +1 -1
- package/dist/components/SearchBar/SearchBar.module.cjs.map +1 -1
- package/dist/components/SearchBar/SearchBar.module.js.map +1 -1
- package/dist/components/SectionHeader/SectionHeader.cjs.map +1 -1
- package/dist/components/SectionHeader/SectionHeader.js.map +1 -1
- package/dist/components/SectionHeader/SectionHeader.module.cjs.map +1 -1
- package/dist/components/SectionHeader/SectionHeader.module.js.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.cjs.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.module.cjs.map +1 -1
- package/dist/components/SegmentedControl/SegmentedControl.module.js.map +1 -1
- package/dist/components/Select/CaretIcon.cjs.map +1 -1
- package/dist/components/Select/CaretIcon.js.map +1 -1
- package/dist/components/Select/Select.cjs.map +1 -1
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Select/Select.module.cjs.map +1 -1
- package/dist/components/Select/Select.module.js.map +1 -1
- package/dist/components/Select/options.cjs.map +1 -1
- package/dist/components/Select/options.js.map +1 -1
- package/dist/components/Sidebar/Sidebar.cjs +1 -1
- package/dist/components/Sidebar/Sidebar.cjs.map +1 -1
- package/dist/components/Sidebar/Sidebar.js +13 -23
- package/dist/components/Sidebar/Sidebar.js.map +1 -1
- package/dist/components/Sidebar/Sidebar.module.cjs.map +1 -1
- package/dist/components/Sidebar/Sidebar.module.js.map +1 -1
- package/dist/components/Sidebar/SidebarEntry.cjs.map +1 -1
- package/dist/components/Sidebar/SidebarEntry.js.map +1 -1
- package/dist/components/Sidebar/active-nav-key.cjs.map +1 -1
- package/dist/components/Sidebar/active-nav-key.js.map +1 -1
- package/dist/components/SignaturePad/SignaturePad.cjs +1 -1
- package/dist/components/SignaturePad/SignaturePad.cjs.map +1 -1
- package/dist/components/SignaturePad/SignaturePad.js +1 -5
- package/dist/components/SignaturePad/SignaturePad.js.map +1 -1
- package/dist/components/SignaturePad/SignaturePad.module.cjs.map +1 -1
- package/dist/components/SignaturePad/SignaturePad.module.js.map +1 -1
- package/dist/components/Skeleton/Skeleton.cjs.map +1 -1
- package/dist/components/Skeleton/Skeleton.js.map +1 -1
- package/dist/components/Skeleton/Skeleton.module.cjs.map +1 -1
- package/dist/components/Skeleton/Skeleton.module.js.map +1 -1
- package/dist/components/Slider/Slider.cjs.map +1 -1
- package/dist/components/Slider/Slider.js.map +1 -1
- package/dist/components/Slider/Slider.module.cjs.map +1 -1
- package/dist/components/Slider/Slider.module.js.map +1 -1
- package/dist/components/Spacer/Spacer.cjs.map +1 -1
- package/dist/components/Spacer/Spacer.js.map +1 -1
- package/dist/components/Spacer/Spacer.module.cjs.map +1 -1
- package/dist/components/Spacer/Spacer.module.js.map +1 -1
- package/dist/components/Sparkline/Sparkline.cjs.map +1 -1
- package/dist/components/Sparkline/Sparkline.js.map +1 -1
- package/dist/components/Sparkline/Sparkline.module.cjs.map +1 -1
- package/dist/components/Sparkline/Sparkline.module.js.map +1 -1
- package/dist/components/Sparkline/sparkline-geometry.cjs.map +1 -1
- package/dist/components/Sparkline/sparkline-geometry.js.map +1 -1
- package/dist/components/Spinner/Spinner.cjs.map +1 -1
- package/dist/components/Spinner/Spinner.js.map +1 -1
- package/dist/components/Spinner/Spinner.module.cjs.map +1 -1
- package/dist/components/Spinner/Spinner.module.js.map +1 -1
- package/dist/components/Stat/Stat.cjs.map +1 -1
- package/dist/components/Stat/Stat.js.map +1 -1
- package/dist/components/Stat/Stat.module.cjs.map +1 -1
- package/dist/components/Stat/Stat.module.js.map +1 -1
- package/dist/components/Stepper/Stepper.cjs.map +1 -1
- package/dist/components/Stepper/Stepper.js.map +1 -1
- package/dist/components/Stepper/Stepper.module.cjs.map +1 -1
- package/dist/components/Stepper/Stepper.module.js.map +1 -1
- package/dist/components/StepperInput/StepperInput.cjs.map +1 -1
- package/dist/components/StepperInput/StepperInput.js.map +1 -1
- package/dist/components/StepperInput/StepperInput.module.cjs.map +1 -1
- package/dist/components/StepperInput/StepperInput.module.js.map +1 -1
- package/dist/components/Switch/Switch.cjs.map +1 -1
- package/dist/components/Switch/Switch.js.map +1 -1
- package/dist/components/Switch/Switch.module.cjs.map +1 -1
- package/dist/components/Switch/Switch.module.js.map +1 -1
- package/dist/components/SyncStatusBadge/SyncStatusBadge.cjs.map +1 -1
- package/dist/components/SyncStatusBadge/SyncStatusBadge.js.map +1 -1
- package/dist/components/SyncStatusBadge/SyncStatusBadge.module.cjs.map +1 -1
- package/dist/components/SyncStatusBadge/SyncStatusBadge.module.js.map +1 -1
- package/dist/components/Table/Table.cjs.map +1 -1
- package/dist/components/Table/Table.js.map +1 -1
- package/dist/components/Table/Table.module.cjs.map +1 -1
- package/dist/components/Table/Table.module.js.map +1 -1
- package/dist/components/Tabs/Tabs.cjs.map +1 -1
- package/dist/components/Tabs/Tabs.js.map +1 -1
- package/dist/components/Tabs/Tabs.module.cjs.map +1 -1
- package/dist/components/Tabs/Tabs.module.js.map +1 -1
- package/dist/components/Tag/Tag.cjs.map +1 -1
- package/dist/components/Tag/Tag.js.map +1 -1
- package/dist/components/Tag/Tag.module.cjs.map +1 -1
- package/dist/components/Tag/Tag.module.js.map +1 -1
- package/dist/components/Textarea/Textarea.cjs.map +1 -1
- package/dist/components/Textarea/Textarea.js.map +1 -1
- package/dist/components/Textarea/Textarea.module.cjs.map +1 -1
- package/dist/components/Textarea/Textarea.module.js.map +1 -1
- package/dist/components/TimePicker/TimePicker.cjs.map +1 -1
- package/dist/components/TimePicker/TimePicker.js.map +1 -1
- package/dist/components/TimePicker/TimePicker.module.cjs.map +1 -1
- package/dist/components/TimePicker/TimePicker.module.js.map +1 -1
- package/dist/components/Timeline/Timeline.cjs.map +1 -1
- package/dist/components/Timeline/Timeline.js.map +1 -1
- package/dist/components/Timeline/Timeline.module.cjs.map +1 -1
- package/dist/components/Timeline/Timeline.module.js.map +1 -1
- package/dist/components/Toast/Toast.module.cjs.map +1 -1
- package/dist/components/Toast/Toast.module.js.map +1 -1
- package/dist/components/Toast/ToastProvider.cjs.map +1 -1
- package/dist/components/Toast/ToastProvider.js.map +1 -1
- package/dist/components/Toggle/Toggle.cjs.map +1 -1
- package/dist/components/Toggle/Toggle.js.map +1 -1
- package/dist/components/Toggle/Toggle.module.cjs.map +1 -1
- package/dist/components/Toggle/Toggle.module.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.cjs.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.module.cjs.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.module.js.map +1 -1
- package/dist/components/Tooltip/Tooltip.cjs.map +1 -1
- package/dist/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/components/Tooltip/Tooltip.module.cjs.map +1 -1
- package/dist/components/Tooltip/Tooltip.module.js.map +1 -1
- package/dist/components/Tour/Tour.cjs +1 -1
- package/dist/components/Tour/Tour.cjs.map +1 -1
- package/dist/components/Tour/Tour.js +1 -5
- package/dist/components/Tour/Tour.js.map +1 -1
- package/dist/components/Tour/Tour.module.cjs.map +1 -1
- package/dist/components/Tour/Tour.module.js.map +1 -1
- package/dist/components/Tour/tour-position.cjs.map +1 -1
- package/dist/components/Tour/tour-position.js.map +1 -1
- package/dist/components/Transfer/Transfer.cjs.map +1 -1
- package/dist/components/Transfer/Transfer.js.map +1 -1
- package/dist/components/Transfer/Transfer.module.cjs.map +1 -1
- package/dist/components/Transfer/Transfer.module.js.map +1 -1
- package/dist/components/Transfer/transfer-state.cjs.map +1 -1
- package/dist/components/Transfer/transfer-state.js.map +1 -1
- package/dist/components/TreeView/TreeView.cjs.map +1 -1
- package/dist/components/TreeView/TreeView.js.map +1 -1
- package/dist/components/TreeView/TreeView.module.cjs.map +1 -1
- package/dist/components/TreeView/TreeView.module.js.map +1 -1
- package/dist/components/TruncateText/TruncateText.cjs.map +1 -1
- package/dist/components/TruncateText/TruncateText.js.map +1 -1
- package/dist/components/TruncateText/TruncateText.module.cjs.map +1 -1
- package/dist/components/TruncateText/TruncateText.module.js.map +1 -1
- package/dist/components/UpdatePrompt/UpdatePrompt.cjs.map +1 -1
- package/dist/components/UpdatePrompt/UpdatePrompt.js.map +1 -1
- package/dist/components/UpdatePrompt/UpdatePrompt.module.cjs.map +1 -1
- package/dist/components/UpdatePrompt/UpdatePrompt.module.js.map +1 -1
- package/dist/components/VideoPlayer/VideoPlayer.cjs +1 -1
- package/dist/components/VideoPlayer/VideoPlayer.cjs.map +1 -1
- package/dist/components/VideoPlayer/VideoPlayer.js +1 -7
- package/dist/components/VideoPlayer/VideoPlayer.js.map +1 -1
- package/dist/components/VideoPlayer/VideoPlayer.module.cjs.map +1 -1
- package/dist/components/VideoPlayer/VideoPlayer.module.js.map +1 -1
- package/dist/components/VideoPlayer/playback-rates.cjs.map +1 -1
- package/dist/components/VideoPlayer/playback-rates.js.map +1 -1
- package/dist/components/VirtualList/VirtualList.cjs.map +1 -1
- package/dist/components/VirtualList/VirtualList.js.map +1 -1
- package/dist/components/VirtualList/VirtualList.module.cjs.map +1 -1
- package/dist/components/VirtualList/VirtualList.module.js.map +1 -1
- package/dist/components/VirtualTable/VirtualTable.cjs.map +1 -1
- package/dist/components/VirtualTable/VirtualTable.js.map +1 -1
- package/dist/components/VirtualTable/VirtualTable.module.cjs.map +1 -1
- package/dist/components/VirtualTable/VirtualTable.module.js.map +1 -1
- package/dist/components/VisuallyHidden/VisuallyHidden.cjs.map +1 -1
- package/dist/components/VisuallyHidden/VisuallyHidden.js.map +1 -1
- package/dist/components/VisuallyHidden/VisuallyHidden.module.cjs.map +1 -1
- package/dist/components/VisuallyHidden/VisuallyHidden.module.js.map +1 -1
- package/dist/components/Wizard/Wizard.cjs +1 -1
- package/dist/components/Wizard/Wizard.cjs.map +1 -1
- package/dist/components/Wizard/Wizard.js +4 -11
- package/dist/components/Wizard/Wizard.js.map +1 -1
- package/dist/components/Wizard/Wizard.module.cjs.map +1 -1
- package/dist/components/Wizard/Wizard.module.js.map +1 -1
- package/dist/data/create-data-provider.cjs.map +1 -1
- package/dist/data/create-data-provider.js.map +1 -1
- package/dist/data/data-provider-context.cjs.map +1 -1
- package/dist/data/data-provider-context.js.map +1 -1
- package/dist/data/use-resource.cjs.map +1 -1
- package/dist/data/use-resource.js.map +1 -1
- package/dist/editor/RichTextEditor.cjs.map +1 -1
- package/dist/editor/RichTextEditor.js.map +1 -1
- package/dist/editor/RichTextEditor.module.cjs.map +1 -1
- package/dist/editor/RichTextEditor.module.js.map +1 -1
- package/dist/editor.js +1 -2
- package/dist/error-boundary/ErrorBoundary.cjs.map +1 -1
- package/dist/error-boundary/ErrorBoundary.js.map +1 -1
- package/dist/error-boundary/use-error-handler.cjs.map +1 -1
- package/dist/error-boundary/use-error-handler.js.map +1 -1
- package/dist/feature-flags/FeatureFlagsProvider.cjs.map +1 -1
- package/dist/feature-flags/FeatureFlagsProvider.js.map +1 -1
- package/dist/feature-flags/growthbook-adapter.cjs.map +1 -1
- package/dist/feature-flags/growthbook-adapter.js.map +1 -1
- package/dist/feature-flags/in-memory-adapter.cjs.map +1 -1
- package/dist/feature-flags/in-memory-adapter.js.map +1 -1
- package/dist/feature-flags/launchdarkly-adapter.cjs.map +1 -1
- package/dist/feature-flags/launchdarkly-adapter.js.map +1 -1
- package/dist/forms/FormField.cjs.map +1 -1
- package/dist/forms/FormField.js.map +1 -1
- package/dist/forms/br-validators.cjs.map +1 -1
- package/dist/forms/br-validators.js.map +1 -1
- package/dist/forms/masked-inputs.cjs.map +1 -1
- package/dist/forms/masked-inputs.js.map +1 -1
- package/dist/forms/use-viacep.cjs.map +1 -1
- package/dist/forms/use-viacep.js.map +1 -1
- package/dist/forms/use-zod-form.cjs.map +1 -1
- package/dist/forms/use-zod-form.js.map +1 -1
- package/dist/forms/validate-form.cjs.map +1 -1
- package/dist/forms/validate-form.js.map +1 -1
- package/dist/forms/zod-resolver.cjs.map +1 -1
- package/dist/forms/zod-resolver.js.map +1 -1
- package/dist/geo/TrajectoryMap.cjs.map +1 -1
- package/dist/geo/TrajectoryMap.js.map +1 -1
- package/dist/geo/TrajectoryMap.module.cjs.map +1 -1
- package/dist/geo/TrajectoryMap.module.js.map +1 -1
- package/dist/geo/bounds.cjs.map +1 -1
- package/dist/geo/bounds.js.map +1 -1
- package/dist/geo/create-position-tracker.cjs +1 -1
- package/dist/geo/create-position-tracker.cjs.map +1 -1
- package/dist/geo/create-position-tracker.js +1 -7
- package/dist/geo/create-position-tracker.js.map +1 -1
- package/dist/geo/distance.cjs.map +1 -1
- package/dist/geo/distance.js.map +1 -1
- package/dist/geo/estimate.cjs.map +1 -1
- package/dist/geo/estimate.js.map +1 -1
- package/dist/geo/leaflet-map.cjs.map +1 -1
- package/dist/geo/leaflet-map.js.map +1 -1
- package/dist/geo/projection.cjs.map +1 -1
- package/dist/geo/projection.js.map +1 -1
- package/dist/geo/routing.cjs.map +1 -1
- package/dist/geo/routing.js.map +1 -1
- package/dist/geo/types.cjs.map +1 -1
- package/dist/geo/types.js.map +1 -1
- package/dist/geo/use-position-tracker.cjs.map +1 -1
- package/dist/geo/use-position-tracker.js.map +1 -1
- package/dist/hooks/pwa-env.cjs.map +1 -1
- package/dist/hooks/pwa-env.js.map +1 -1
- package/dist/hooks/tab-sequence.cjs.map +1 -1
- package/dist/hooks/tab-sequence.js.map +1 -1
- package/dist/hooks/use-announce.cjs +1 -1
- package/dist/hooks/use-announce.cjs.map +1 -1
- package/dist/hooks/use-announce.js +2 -2
- package/dist/hooks/use-announce.js.map +1 -1
- package/dist/hooks/use-async.cjs.map +1 -1
- package/dist/hooks/use-async.js.map +1 -1
- package/dist/hooks/use-before-install-prompt.cjs.map +1 -1
- package/dist/hooks/use-before-install-prompt.js.map +1 -1
- package/dist/hooks/use-breakpoint.cjs.map +1 -1
- package/dist/hooks/use-breakpoint.js.map +1 -1
- package/dist/hooks/use-click-outside.cjs.map +1 -1
- package/dist/hooks/use-click-outside.js.map +1 -1
- package/dist/hooks/use-client-filter.cjs.map +1 -1
- package/dist/hooks/use-client-filter.js.map +1 -1
- package/dist/hooks/use-clipboard.cjs.map +1 -1
- package/dist/hooks/use-clipboard.js.map +1 -1
- package/dist/hooks/use-countdown.cjs.map +1 -1
- package/dist/hooks/use-countdown.js.map +1 -1
- package/dist/hooks/use-counter.cjs.map +1 -1
- package/dist/hooks/use-counter.js.map +1 -1
- package/dist/hooks/use-debounce.cjs.map +1 -1
- package/dist/hooks/use-debounce.js.map +1 -1
- package/dist/hooks/use-deep-memo.cjs.map +1 -1
- package/dist/hooks/use-deep-memo.js.map +1 -1
- package/dist/hooks/use-disclosure.cjs.map +1 -1
- package/dist/hooks/use-disclosure.js.map +1 -1
- package/dist/hooks/use-document-title.cjs.map +1 -1
- package/dist/hooks/use-document-title.js.map +1 -1
- package/dist/hooks/use-document-visibility.cjs.map +1 -1
- package/dist/hooks/use-document-visibility.js.map +1 -1
- package/dist/hooks/use-draft-filters.cjs.map +1 -1
- package/dist/hooks/use-draft-filters.js.map +1 -1
- package/dist/hooks/use-event-listener.cjs.map +1 -1
- package/dist/hooks/use-event-listener.js.map +1 -1
- package/dist/hooks/use-favicon.cjs.map +1 -1
- package/dist/hooks/use-favicon.js.map +1 -1
- package/dist/hooks/use-focus-trap.cjs.map +1 -1
- package/dist/hooks/use-focus-trap.js.map +1 -1
- package/dist/hooks/use-fullscreen-element.cjs.map +1 -1
- package/dist/hooks/use-fullscreen-element.js.map +1 -1
- package/dist/hooks/use-fullscreen.cjs +1 -1
- package/dist/hooks/use-fullscreen.cjs.map +1 -1
- package/dist/hooks/use-fullscreen.js +7 -23
- package/dist/hooks/use-fullscreen.js.map +1 -1
- package/dist/hooks/use-geolocation.cjs.map +1 -1
- package/dist/hooks/use-geolocation.js.map +1 -1
- package/dist/hooks/use-hover.cjs.map +1 -1
- package/dist/hooks/use-hover.js.map +1 -1
- package/dist/hooks/use-idle.cjs.map +1 -1
- package/dist/hooks/use-idle.js.map +1 -1
- package/dist/hooks/use-install-prompt.cjs +1 -1
- package/dist/hooks/use-install-prompt.cjs.map +1 -1
- package/dist/hooks/use-install-prompt.js +1 -1
- package/dist/hooks/use-install-prompt.js.map +1 -1
- package/dist/hooks/use-intersection-observer.cjs.map +1 -1
- package/dist/hooks/use-intersection-observer.js.map +1 -1
- package/dist/hooks/use-interval.cjs.map +1 -1
- package/dist/hooks/use-interval.js.map +1 -1
- package/dist/hooks/use-is-first-render.cjs.map +1 -1
- package/dist/hooks/use-is-first-render.js.map +1 -1
- package/dist/hooks/use-keyboard-shortcut.cjs.map +1 -1
- package/dist/hooks/use-keyboard-shortcut.js.map +1 -1
- package/dist/hooks/use-latest-ref.cjs.map +1 -1
- package/dist/hooks/use-latest-ref.js.map +1 -1
- package/dist/hooks/use-list-state.cjs.map +1 -1
- package/dist/hooks/use-list-state.js.map +1 -1
- package/dist/hooks/use-local-storage.cjs +1 -1
- package/dist/hooks/use-local-storage.cjs.map +1 -1
- package/dist/hooks/use-local-storage.js +2 -5
- package/dist/hooks/use-local-storage.js.map +1 -1
- package/dist/hooks/use-long-press-handlers.cjs.map +1 -1
- package/dist/hooks/use-long-press-handlers.js.map +1 -1
- package/dist/hooks/use-long-press.cjs.map +1 -1
- package/dist/hooks/use-long-press.js.map +1 -1
- package/dist/hooks/use-map.cjs.map +1 -1
- package/dist/hooks/use-map.js.map +1 -1
- package/dist/hooks/use-media-devices.cjs.map +1 -1
- package/dist/hooks/use-media-devices.js.map +1 -1
- package/dist/hooks/use-media-permission.cjs +1 -1
- package/dist/hooks/use-media-permission.cjs.map +1 -1
- package/dist/hooks/use-media-permission.js +2 -5
- package/dist/hooks/use-media-permission.js.map +1 -1
- package/dist/hooks/use-media-query.cjs.map +1 -1
- package/dist/hooks/use-media-query.js.map +1 -1
- package/dist/hooks/use-object-url.cjs.map +1 -1
- package/dist/hooks/use-object-url.js.map +1 -1
- package/dist/hooks/use-online.cjs.map +1 -1
- package/dist/hooks/use-online.js.map +1 -1
- package/dist/hooks/use-pagination.cjs.map +1 -1
- package/dist/hooks/use-pagination.js.map +1 -1
- package/dist/hooks/use-previous.cjs.map +1 -1
- package/dist/hooks/use-previous.js.map +1 -1
- package/dist/hooks/use-push-to-talk.cjs.map +1 -1
- package/dist/hooks/use-push-to-talk.js.map +1 -1
- package/dist/hooks/use-queue.cjs.map +1 -1
- package/dist/hooks/use-queue.js.map +1 -1
- package/dist/hooks/use-resize-observer.cjs.map +1 -1
- package/dist/hooks/use-resize-observer.js.map +1 -1
- package/dist/hooks/use-scroll-lock.cjs.map +1 -1
- package/dist/hooks/use-scroll-lock.js.map +1 -1
- package/dist/hooks/use-scroll-overflow.cjs.map +1 -1
- package/dist/hooks/use-scroll-overflow.js.map +1 -1
- package/dist/hooks/use-service-worker-update.cjs.map +1 -1
- package/dist/hooks/use-service-worker-update.js.map +1 -1
- package/dist/hooks/use-set.cjs.map +1 -1
- package/dist/hooks/use-set.js.map +1 -1
- package/dist/hooks/use-sortable.cjs.map +1 -1
- package/dist/hooks/use-sortable.js.map +1 -1
- package/dist/hooks/use-stable-callback.cjs.map +1 -1
- package/dist/hooks/use-stable-callback.js.map +1 -1
- package/dist/hooks/use-storage-estimate.cjs.map +1 -1
- package/dist/hooks/use-storage-estimate.js.map +1 -1
- package/dist/hooks/use-throttle.cjs.map +1 -1
- package/dist/hooks/use-throttle.js.map +1 -1
- package/dist/hooks/use-timeout.cjs.map +1 -1
- package/dist/hooks/use-timeout.js.map +1 -1
- package/dist/hooks/use-toggle.cjs.map +1 -1
- package/dist/hooks/use-toggle.js.map +1 -1
- package/dist/hooks/use-typewriter.cjs.map +1 -1
- package/dist/hooks/use-typewriter.js.map +1 -1
- package/dist/hooks/use-window-size.cjs.map +1 -1
- package/dist/hooks/use-window-size.js.map +1 -1
- package/dist/http/api-client.cjs.map +1 -1
- package/dist/http/api-client.js.map +1 -1
- package/dist/http/build-url.cjs.map +1 -1
- package/dist/http/build-url.js.map +1 -1
- package/dist/http/credential-scope.cjs.map +1 -1
- package/dist/http/credential-scope.js.map +1 -1
- package/dist/http/csrf.cjs.map +1 -1
- package/dist/http/csrf.js.map +1 -1
- package/dist/http/decode-response.cjs.map +1 -1
- package/dist/http/decode-response.js.map +1 -1
- package/dist/http/describe-api-error.cjs.map +1 -1
- package/dist/http/describe-api-error.js.map +1 -1
- package/dist/http/errors.cjs.map +1 -1
- package/dist/http/errors.js.map +1 -1
- package/dist/http/idempotency.cjs.map +1 -1
- package/dist/http/idempotency.js.map +1 -1
- package/dist/http/parse-response.cjs.map +1 -1
- package/dist/http/parse-response.js.map +1 -1
- package/dist/http/resumable-upload.cjs +1 -1
- package/dist/http/resumable-upload.cjs.map +1 -1
- package/dist/http/resumable-upload.js +141 -105
- package/dist/http/resumable-upload.js.map +1 -1
- package/dist/http/retry.cjs +1 -1
- package/dist/http/retry.cjs.map +1 -1
- package/dist/http/retry.js +5 -6
- package/dist/http/retry.js.map +1 -1
- package/dist/http/timeout.cjs.map +1 -1
- package/dist/http/timeout.js.map +1 -1
- package/dist/http/upload-with-progress.cjs +1 -1
- package/dist/http/upload-with-progress.cjs.map +1 -1
- package/dist/http/upload-with-progress.js +2 -7
- package/dist/http/upload-with-progress.js.map +1 -1
- package/dist/http/use-describe-api-error.cjs.map +1 -1
- package/dist/http/use-describe-api-error.js.map +1 -1
- package/dist/http/use-poll.cjs +1 -1
- package/dist/http/use-poll.cjs.map +1 -1
- package/dist/http/use-poll.js +2 -5
- package/dist/http/use-poll.js.map +1 -1
- package/dist/i18n/I18nProvider.cjs.map +1 -1
- package/dist/i18n/I18nProvider.js.map +1 -1
- package/dist/i18n/create-i18n.cjs.map +1 -1
- package/dist/i18n/create-i18n.js.map +1 -1
- package/dist/icons/Icon.cjs.map +1 -1
- package/dist/icons/Icon.js.map +1 -1
- package/dist/icons/IconPicker.cjs.map +1 -1
- package/dist/icons/IconPicker.js.map +1 -1
- package/dist/icons/IconPicker.module.cjs.map +1 -1
- package/dist/icons/IconPicker.module.js.map +1 -1
- package/dist/icons/IconProvider.cjs.map +1 -1
- package/dist/icons/IconProvider.js.map +1 -1
- package/dist/icons/alias.cjs.map +1 -1
- package/dist/icons/alias.js.map +1 -1
- package/dist/icons/generated/aliases.cjs.map +1 -1
- package/dist/icons/generated/aliases.js.map +1 -1
- package/dist/icons/generated/icon-names.cjs.map +1 -1
- package/dist/icons/generated/icon-names.js.map +1 -1
- package/dist/icons/generated/loaders.cjs.map +1 -1
- package/dist/icons/generated/loaders.js.map +1 -1
- package/dist/icons/generated/shard-00.cjs.map +1 -1
- package/dist/icons/generated/shard-00.js.map +1 -1
- package/dist/icons/generated/shard-01.cjs.map +1 -1
- package/dist/icons/generated/shard-01.js.map +1 -1
- package/dist/icons/generated/shard-02.cjs.map +1 -1
- package/dist/icons/generated/shard-02.js.map +1 -1
- package/dist/icons/generated/shard-03.cjs.map +1 -1
- package/dist/icons/generated/shard-03.js.map +1 -1
- package/dist/icons/generated/shard-04.cjs.map +1 -1
- package/dist/icons/generated/shard-04.js.map +1 -1
- package/dist/icons/generated/shard-05.cjs.map +1 -1
- package/dist/icons/generated/shard-05.js.map +1 -1
- package/dist/icons/generated/shard-06.cjs.map +1 -1
- package/dist/icons/generated/shard-06.js.map +1 -1
- package/dist/icons/generated/shard-07.cjs.map +1 -1
- package/dist/icons/generated/shard-07.js.map +1 -1
- package/dist/icons/generated/shard-08.cjs.map +1 -1
- package/dist/icons/generated/shard-08.js.map +1 -1
- package/dist/icons/generated/shard-09.cjs.map +1 -1
- package/dist/icons/generated/shard-09.js.map +1 -1
- package/dist/icons/generated/shard-10.cjs.map +1 -1
- package/dist/icons/generated/shard-10.js.map +1 -1
- package/dist/icons/generated/shard-11.cjs.map +1 -1
- package/dist/icons/generated/shard-11.js.map +1 -1
- package/dist/icons/generated/shard-12.cjs.map +1 -1
- package/dist/icons/generated/shard-12.js.map +1 -1
- package/dist/icons/generated/shard-13.cjs.map +1 -1
- package/dist/icons/generated/shard-13.js.map +1 -1
- package/dist/icons/generated/shard-14.cjs.map +1 -1
- package/dist/icons/generated/shard-14.js.map +1 -1
- package/dist/icons/generated/shard-15.cjs.map +1 -1
- package/dist/icons/generated/shard-15.js.map +1 -1
- package/dist/icons/generated/shard-16.cjs.map +1 -1
- package/dist/icons/generated/shard-16.js.map +1 -1
- package/dist/icons/generated/shard-17.cjs.map +1 -1
- package/dist/icons/generated/shard-17.js.map +1 -1
- package/dist/icons/generated/shard-18.cjs.map +1 -1
- package/dist/icons/generated/shard-18.js.map +1 -1
- package/dist/icons/generated/shard-19.cjs.map +1 -1
- package/dist/icons/generated/shard-19.js.map +1 -1
- package/dist/icons/generated/shard-20.cjs.map +1 -1
- package/dist/icons/generated/shard-20.js.map +1 -1
- package/dist/icons/generated/shard-21.cjs.map +1 -1
- package/dist/icons/generated/shard-21.js.map +1 -1
- package/dist/icons/generated/shard-22.cjs.map +1 -1
- package/dist/icons/generated/shard-22.js.map +1 -1
- package/dist/icons/generated/shard-23.cjs.map +1 -1
- package/dist/icons/generated/shard-23.js.map +1 -1
- package/dist/icons/generated/shard-24.cjs.map +1 -1
- package/dist/icons/generated/shard-24.js.map +1 -1
- package/dist/icons/generated/shard-25.cjs.map +1 -1
- package/dist/icons/generated/shard-25.js.map +1 -1
- package/dist/icons/generated/shard-26.cjs.map +1 -1
- package/dist/icons/generated/shard-26.js.map +1 -1
- package/dist/icons/generated/shard-27.cjs.map +1 -1
- package/dist/icons/generated/shard-27.js.map +1 -1
- package/dist/icons/generated/shard-28.cjs.map +1 -1
- package/dist/icons/generated/shard-28.js.map +1 -1
- package/dist/icons/generated/shard-29.cjs.map +1 -1
- package/dist/icons/generated/shard-29.js.map +1 -1
- package/dist/icons/generated/shard-30.cjs.map +1 -1
- package/dist/icons/generated/shard-30.js.map +1 -1
- package/dist/icons/generated/shard-31.cjs.map +1 -1
- package/dist/icons/generated/shard-31.js.map +1 -1
- package/dist/icons/generated/shard-32.cjs.map +1 -1
- package/dist/icons/generated/shard-32.js.map +1 -1
- package/dist/icons/generated/shard-33.cjs.map +1 -1
- package/dist/icons/generated/shard-33.js.map +1 -1
- package/dist/icons/generated/shard-34.cjs.map +1 -1
- package/dist/icons/generated/shard-34.js.map +1 -1
- package/dist/icons/generated/shard-35.cjs.map +1 -1
- package/dist/icons/generated/shard-35.js.map +1 -1
- package/dist/icons/generated/shard-36.cjs.map +1 -1
- package/dist/icons/generated/shard-36.js.map +1 -1
- package/dist/icons/generated/shard-37.cjs.map +1 -1
- package/dist/icons/generated/shard-37.js.map +1 -1
- package/dist/icons/generated/shard-38.cjs.map +1 -1
- package/dist/icons/generated/shard-38.js.map +1 -1
- package/dist/icons/generated/shard-39.cjs.map +1 -1
- package/dist/icons/generated/shard-39.js.map +1 -1
- package/dist/icons/generated/shard-40.cjs.map +1 -1
- package/dist/icons/generated/shard-40.js.map +1 -1
- package/dist/icons/generated/shard-41.cjs.map +1 -1
- package/dist/icons/generated/shard-41.js.map +1 -1
- package/dist/icons/generated/shard-42.cjs.map +1 -1
- package/dist/icons/generated/shard-42.js.map +1 -1
- package/dist/icons/generated/shard-43.cjs.map +1 -1
- package/dist/icons/generated/shard-43.js.map +1 -1
- package/dist/icons/generated/shard-44.cjs.map +1 -1
- package/dist/icons/generated/shard-44.js.map +1 -1
- package/dist/icons/generated/shard-45.cjs.map +1 -1
- package/dist/icons/generated/shard-45.js.map +1 -1
- package/dist/icons/icon-context.cjs.map +1 -1
- package/dist/icons/icon-context.js.map +1 -1
- package/dist/icons/is-icon-name.cjs.map +1 -1
- package/dist/icons/is-icon-name.js.map +1 -1
- package/dist/icons/material-symbols.cjs.map +1 -1
- package/dist/icons/material-symbols.js.map +1 -1
- package/dist/icons/normalize-icon-name.cjs.map +1 -1
- package/dist/icons/normalize-icon-name.js.map +1 -1
- package/dist/icons/shard-cache.cjs +1 -1
- package/dist/icons/shard-cache.cjs.map +1 -1
- package/dist/icons/shard-cache.js +2 -5
- package/dist/icons/shard-cache.js.map +1 -1
- package/dist/icons/use-icon.cjs.map +1 -1
- package/dist/icons/use-icon.js.map +1 -1
- package/dist/icons/validate-icon-name.cjs.map +1 -1
- package/dist/icons/validate-icon-name.js.map +1 -1
- package/dist/icons-virtual.cjs.map +1 -1
- package/dist/icons-virtual.js.map +1 -1
- package/dist/imaging/canvas.cjs.map +1 -1
- package/dist/imaging/canvas.js.map +1 -1
- package/dist/imaging/compress.cjs.map +1 -1
- package/dist/imaging/compress.js.map +1 -1
- package/dist/imaging/decode.cjs.map +1 -1
- package/dist/imaging/decode.js.map +1 -1
- package/dist/imaging/encode.cjs.map +1 -1
- package/dist/imaging/encode.js.map +1 -1
- package/dist/imaging/exceptions.cjs.map +1 -1
- package/dist/imaging/exceptions.js.map +1 -1
- package/dist/imaging/frame.cjs.map +1 -1
- package/dist/imaging/frame.js.map +1 -1
- package/dist/imaging/thumbnails.cjs.map +1 -1
- package/dist/imaging/thumbnails.js.map +1 -1
- package/dist/imaging/transform.cjs.map +1 -1
- package/dist/imaging/transform.js.map +1 -1
- package/dist/imaging/use-image-processing.cjs.map +1 -1
- package/dist/imaging/use-image-processing.js.map +1 -1
- package/dist/logger/logger.cjs.map +1 -1
- package/dist/logger/logger.js.map +1 -1
- package/dist/neural.cjs.map +1 -1
- package/dist/neural.js.map +1 -1
- package/dist/oauth/GoogleSignIn.cjs +1 -1
- package/dist/oauth/GoogleSignIn.cjs.map +1 -1
- package/dist/oauth/GoogleSignIn.js +6 -9
- package/dist/oauth/GoogleSignIn.js.map +1 -1
- package/dist/oauth/callback.cjs.map +1 -1
- package/dist/oauth/callback.js.map +1 -1
- package/dist/oauth/use-oauth-callback.cjs.map +1 -1
- package/dist/oauth/use-oauth-callback.js.map +1 -1
- package/dist/offline/conflict.cjs.map +1 -1
- package/dist/offline/conflict.js.map +1 -1
- package/dist/offline/create-offline-database.cjs.map +1 -1
- package/dist/offline/create-offline-database.js.map +1 -1
- package/dist/offline/create-offline-store.cjs +1 -1
- package/dist/offline/create-offline-store.cjs.map +1 -1
- package/dist/offline/create-offline-store.js +1 -5
- package/dist/offline/create-offline-store.js.map +1 -1
- package/dist/offline/create-offline-sync.cjs +1 -1
- package/dist/offline/create-offline-sync.cjs.map +1 -1
- package/dist/offline/create-offline-sync.js +9 -14
- package/dist/offline/create-offline-sync.js.map +1 -1
- package/dist/offline/use-offline-sync.cjs.map +1 -1
- package/dist/offline/use-offline-sync.js.map +1 -1
- package/dist/perf/cache-size.cjs.map +1 -1
- package/dist/perf/cache-size.js.map +1 -1
- package/dist/perf/device.cjs.map +1 -1
- package/dist/perf/device.js.map +1 -1
- package/dist/perf/format.cjs.map +1 -1
- package/dist/perf/format.js.map +1 -1
- package/dist/perf/profiler.cjs.map +1 -1
- package/dist/perf/profiler.js.map +1 -1
- package/dist/push/use-push-subscription.cjs.map +1 -1
- package/dist/push/use-push-subscription.js.map +1 -1
- package/dist/push/utils.cjs.map +1 -1
- package/dist/push/utils.js.map +1 -1
- package/dist/push/web-push-client.cjs.map +1 -1
- package/dist/push/web-push-client.js.map +1 -1
- package/dist/query/QueryProvider.cjs.map +1 -1
- package/dist/query/QueryProvider.js.map +1 -1
- package/dist/query/constants.cjs.map +1 -1
- package/dist/query/constants.js.map +1 -1
- package/dist/query/create-query-keys.cjs.map +1 -1
- package/dist/query/create-query-keys.js.map +1 -1
- package/dist/query/foreign-client-warning.cjs.map +1 -1
- package/dist/query/foreign-client-warning.js.map +1 -1
- package/dist/query/offline-persistence.cjs +1 -1
- package/dist/query/offline-persistence.cjs.map +1 -1
- package/dist/query/offline-persistence.js +2 -10
- package/dist/query/offline-persistence.js.map +1 -1
- package/dist/query/optimistic.cjs.map +1 -1
- package/dist/query/optimistic.js.map +1 -1
- package/dist/query/pagination.cjs.map +1 -1
- package/dist/query/pagination.js.map +1 -1
- package/dist/query/retry-policy.cjs.map +1 -1
- package/dist/query/retry-policy.js.map +1 -1
- package/dist/query/use-cursor-query.cjs.map +1 -1
- package/dist/query/use-cursor-query.js.map +1 -1
- package/dist/query/use-offline-mutation.cjs.map +1 -1
- package/dist/query/use-offline-mutation.js.map +1 -1
- package/dist/query/use-paginated-query.cjs.map +1 -1
- package/dist/query/use-paginated-query.js.map +1 -1
- package/dist/router/AppRouter.cjs.map +1 -1
- package/dist/router/AppRouter.js.map +1 -1
- package/dist/router/RouteGuard.cjs.map +1 -1
- package/dist/router/RouteGuard.js.map +1 -1
- package/dist/router/index.js +2 -2
- package/dist/share/share-or-download.cjs.map +1 -1
- package/dist/share/share-or-download.js.map +1 -1
- package/dist/share/share.cjs.map +1 -1
- package/dist/share/share.js.map +1 -1
- package/dist/sse/create-event-stream.cjs.map +1 -1
- package/dist/sse/create-event-stream.js.map +1 -1
- package/dist/sse/use-event-stream.cjs.map +1 -1
- package/dist/sse/use-event-stream.js.map +1 -1
- package/dist/store/create-selectors.cjs.map +1 -1
- package/dist/store/create-selectors.js.map +1 -1
- package/dist/store/create-store.cjs.map +1 -1
- package/dist/store/create-store.js.map +1 -1
- package/dist/sw/background-sync.cjs +1 -1
- package/dist/sw/background-sync.cjs.map +1 -1
- package/dist/sw/background-sync.js +32 -31
- package/dist/sw/background-sync.js.map +1 -1
- package/dist/sw/cache-inspect.cjs.map +1 -1
- package/dist/sw/cache-inspect.js.map +1 -1
- package/dist/sw/cache.cjs +1 -1
- package/dist/sw/cache.cjs.map +1 -1
- package/dist/sw/cache.js +2 -6
- package/dist/sw/cache.js.map +1 -1
- package/dist/sw/create-push-handler.cjs.map +1 -1
- package/dist/sw/create-push-handler.js.map +1 -1
- package/dist/sw/credential-headers.cjs.map +1 -1
- package/dist/sw/credential-headers.js.map +1 -1
- package/dist/sw/periodic-sync.cjs.map +1 -1
- package/dist/sw/periodic-sync.js.map +1 -1
- package/dist/sw/register-service-worker.cjs.map +1 -1
- package/dist/sw/register-service-worker.js.map +1 -1
- package/dist/sw/session-data.cjs.map +1 -1
- package/dist/sw/session-data.js.map +1 -1
- package/dist/sw.d.ts +46 -8
- package/dist/tabular/assets.cjs.map +1 -1
- package/dist/tabular/assets.js.map +1 -1
- package/dist/tabular/cache.cjs.map +1 -1
- package/dist/tabular/cache.js.map +1 -1
- package/dist/tabular/compact.cjs.map +1 -1
- package/dist/tabular/compact.js.map +1 -1
- package/dist/tabular/exceptions.cjs.map +1 -1
- package/dist/tabular/exceptions.js.map +1 -1
- package/dist/tabular/manifest.cjs.map +1 -1
- package/dist/tabular/manifest.js.map +1 -1
- package/dist/tabular/predictor.cjs.map +1 -1
- package/dist/tabular/predictor.js.map +1 -1
- package/dist/tabular/use-tabular-predictor.cjs.map +1 -1
- package/dist/tabular/use-tabular-predictor.js.map +1 -1
- package/dist/telemetry/TelemetryProvider.cjs.map +1 -1
- package/dist/telemetry/TelemetryProvider.js.map +1 -1
- package/dist/telemetry/app-error-adapter.cjs.map +1 -1
- package/dist/telemetry/app-error-adapter.js.map +1 -1
- package/dist/telemetry/app-error-queue.cjs.map +1 -1
- package/dist/telemetry/app-error-queue.js.map +1 -1
- package/dist/telemetry/app-error-reporter.cjs +1 -1
- package/dist/telemetry/app-error-reporter.cjs.map +1 -1
- package/dist/telemetry/app-error-reporter.js +1 -1
- package/dist/telemetry/app-error-reporter.js.map +1 -1
- package/dist/telemetry/app-error-schema.cjs.map +1 -1
- package/dist/telemetry/app-error-schema.js.map +1 -1
- package/dist/telemetry/app-error-transport.cjs.map +1 -1
- package/dist/telemetry/app-error-transport.js.map +1 -1
- package/dist/telemetry/console-adapter.cjs.map +1 -1
- package/dist/telemetry/console-adapter.js.map +1 -1
- package/dist/telemetry/describe-app-error.cjs.map +1 -1
- package/dist/telemetry/describe-app-error.js.map +1 -1
- package/dist/telemetry/posthog-adapter.cjs +1 -1
- package/dist/telemetry/posthog-adapter.cjs.map +1 -1
- package/dist/telemetry/posthog-adapter.js +1 -5
- package/dist/telemetry/posthog-adapter.js.map +1 -1
- package/dist/telemetry/sentry-adapter.cjs.map +1 -1
- package/dist/telemetry/sentry-adapter.js.map +1 -1
- package/dist/tempest-react-sdk.cjs +1 -1
- package/dist/tempest-react-sdk.d.ts +448 -15
- package/dist/tempest-react-sdk.js +119 -119
- package/dist/testing/create-mock-handlers.cjs.map +1 -1
- package/dist/testing/create-mock-handlers.js.map +1 -1
- package/dist/testing.js +1 -2
- package/dist/theme/ThemeProvider.cjs.map +1 -1
- package/dist/theme/ThemeProvider.js.map +1 -1
- package/dist/theme/apply-theme.cjs.map +1 -1
- package/dist/theme/apply-theme.js.map +1 -1
- package/dist/theme/color.cjs.map +1 -1
- package/dist/theme/color.js.map +1 -1
- package/dist/theme/create-theme.cjs.map +1 -1
- package/dist/theme/create-theme.js.map +1 -1
- package/dist/theme/data-viz-ramps.cjs.map +1 -1
- package/dist/theme/data-viz-ramps.js.map +1 -1
- package/dist/theme/initial-theme.cjs.map +1 -1
- package/dist/theme/initial-theme.js.map +1 -1
- package/dist/theme/inverse-render.cjs.map +1 -1
- package/dist/theme/inverse-render.js.map +1 -1
- package/dist/theme/inverse-restore.cjs.map +1 -1
- package/dist/theme/inverse-restore.js.map +1 -1
- package/dist/theme/inverse-surface.cjs.map +1 -1
- package/dist/theme/inverse-surface.js.map +1 -1
- package/dist/theme/status-tokens.cjs.map +1 -1
- package/dist/theme/status-tokens.js.map +1 -1
- package/dist/theme/theme-presets.cjs.map +1 -1
- package/dist/theme/theme-presets.js.map +1 -1
- package/dist/utils/absent.cjs.map +1 -1
- package/dist/utils/absent.js.map +1 -1
- package/dist/utils/arrays.cjs.map +1 -1
- package/dist/utils/arrays.js.map +1 -1
- package/dist/utils/base64.cjs.map +1 -1
- package/dist/utils/base64.js.map +1 -1
- package/dist/utils/cn.cjs.map +1 -1
- package/dist/utils/cn.js.map +1 -1
- package/dist/utils/compare-values.cjs.map +1 -1
- package/dist/utils/compare-values.js.map +1 -1
- package/dist/utils/compressed-storage.cjs.map +1 -1
- package/dist/utils/compressed-storage.js.map +1 -1
- package/dist/utils/csv.cjs +3 -3
- package/dist/utils/csv.cjs.map +1 -1
- package/dist/utils/csv.js +11 -10
- package/dist/utils/csv.js.map +1 -1
- package/dist/utils/dev-mode.cjs.map +1 -1
- package/dist/utils/dev-mode.js.map +1 -1
- package/dist/utils/duplicate-instance.cjs.map +1 -1
- package/dist/utils/duplicate-instance.js.map +1 -1
- package/dist/utils/format.cjs.map +1 -1
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/functions.cjs +1 -1
- package/dist/utils/functions.cjs.map +1 -1
- package/dist/utils/functions.js +1 -1
- package/dist/utils/functions.js.map +1 -1
- package/dist/utils/guards.cjs.map +1 -1
- package/dist/utils/guards.js.map +1 -1
- package/dist/utils/ids.cjs.map +1 -1
- package/dist/utils/ids.js.map +1 -1
- package/dist/utils/intl-cache.cjs.map +1 -1
- package/dist/utils/intl-cache.js.map +1 -1
- package/dist/utils/json-frame.cjs.map +1 -1
- package/dist/utils/json-frame.js.map +1 -1
- package/dist/utils/numbers.cjs.map +1 -1
- package/dist/utils/numbers.js.map +1 -1
- package/dist/utils/objects.cjs.map +1 -1
- package/dist/utils/objects.js.map +1 -1
- package/dist/{telemetry/app-error-owner.cjs → utils/owner-fingerprint.cjs} +2 -2
- package/dist/utils/owner-fingerprint.cjs.map +1 -0
- package/dist/{telemetry/app-error-owner.js → utils/owner-fingerprint.js} +3 -3
- package/dist/utils/owner-fingerprint.js.map +1 -0
- package/dist/utils/promises.cjs.map +1 -1
- package/dist/utils/promises.js.map +1 -1
- package/dist/utils/relative-time.cjs.map +1 -1
- package/dist/utils/relative-time.js.map +1 -1
- package/dist/utils/safe-url.cjs.map +1 -1
- package/dist/utils/safe-url.js.map +1 -1
- package/dist/utils/schema-like.cjs.map +1 -1
- package/dist/utils/schema-like.js.map +1 -1
- package/dist/utils/storage.cjs +1 -1
- package/dist/utils/storage.cjs.map +1 -1
- package/dist/utils/storage.js +2 -2
- package/dist/utils/storage.js.map +1 -1
- package/dist/utils/strings.cjs.map +1 -1
- package/dist/utils/strings.js.map +1 -1
- package/dist/utils/xlsx.cjs.map +1 -1
- package/dist/utils/xlsx.js.map +1 -1
- package/dist/vision/core/canvas.cjs.map +1 -1
- package/dist/vision/core/canvas.js.map +1 -1
- package/dist/vision/core/dtypes.cjs.map +1 -1
- package/dist/vision/core/dtypes.js.map +1 -1
- package/dist/vision/core/exceptions.cjs.map +1 -1
- package/dist/vision/core/exceptions.js.map +1 -1
- package/dist/vision/core/graph.cjs.map +1 -1
- package/dist/vision/core/graph.js.map +1 -1
- package/dist/vision/core/metadata.cjs +1 -1
- package/dist/vision/core/metadata.cjs.map +1 -1
- package/dist/vision/core/metadata.js +9 -26
- package/dist/vision/core/metadata.js.map +1 -1
- package/dist/vision/core/providers.cjs.map +1 -1
- package/dist/vision/core/providers.js.map +1 -1
- package/dist/vision/core/session.cjs.map +1 -1
- package/dist/vision/core/session.js.map +1 -1
- package/dist/vision/core/timing.cjs.map +1 -1
- package/dist/vision/core/timing.js.map +1 -1
- package/dist/vision/fusion.cjs.map +1 -1
- package/dist/vision/fusion.js.map +1 -1
- package/dist/vision/index.cjs.map +1 -1
- package/dist/vision/index.js.map +1 -1
- package/dist/vision/io/image.cjs.map +1 -1
- package/dist/vision/io/image.js.map +1 -1
- package/dist/vision/labels.cjs.map +1 -1
- package/dist/vision/labels.js.map +1 -1
- package/dist/vision/luminance.cjs.map +1 -1
- package/dist/vision/luminance.js.map +1 -1
- package/dist/vision/normalization.cjs.map +1 -1
- package/dist/vision/normalization.js.map +1 -1
- package/dist/vision/postprocess/classification.cjs.map +1 -1
- package/dist/vision/postprocess/classification.js.map +1 -1
- package/dist/vision/postprocess/detection.cjs.map +1 -1
- package/dist/vision/postprocess/detection.js.map +1 -1
- package/dist/vision/postprocess/segmentation.cjs.map +1 -1
- package/dist/vision/postprocess/segmentation.js.map +1 -1
- package/dist/vision/preprocess/image.cjs.map +1 -1
- package/dist/vision/preprocess/image.js.map +1 -1
- package/dist/vision/preprocess/pipeline.cjs.map +1 -1
- package/dist/vision/preprocess/pipeline.js.map +1 -1
- package/dist/vision/results.cjs.map +1 -1
- package/dist/vision/results.js.map +1 -1
- package/dist/vision/tasks/base.cjs.map +1 -1
- package/dist/vision/tasks/base.js.map +1 -1
- package/dist/vision/tasks/classifier.cjs.map +1 -1
- package/dist/vision/tasks/classifier.js.map +1 -1
- package/dist/vision/tasks/detectClassify.cjs.map +1 -1
- package/dist/vision/tasks/detectClassify.js.map +1 -1
- package/dist/vision/tasks/detector.cjs.map +1 -1
- package/dist/vision/tasks/detector.js.map +1 -1
- package/dist/vision/tasks/segmenter.cjs.map +1 -1
- package/dist/vision/tasks/segmenter.js.map +1 -1
- package/dist/vision/types.cjs.map +1 -1
- package/dist/vision/types.js.map +1 -1
- package/dist/vision/use-camera-stream.cjs +1 -1
- package/dist/vision/use-camera-stream.cjs.map +1 -1
- package/dist/vision/use-camera-stream.js +3 -9
- package/dist/vision/use-camera-stream.js.map +1 -1
- package/dist/vision/use-live-luminance.cjs +1 -1
- package/dist/vision/use-live-luminance.cjs.map +1 -1
- package/dist/vision/use-live-luminance.js +1 -5
- package/dist/vision/use-live-luminance.js.map +1 -1
- package/dist/vite/base-url.cjs.map +1 -1
- package/dist/vite/base-url.js.map +1 -1
- package/dist/vite/create-vite-config.cjs.map +1 -1
- package/dist/vite/create-vite-config.js.map +1 -1
- package/dist/vite/narrow-tokens.cjs.map +1 -1
- package/dist/vite/narrow-tokens.js.map +1 -1
- package/dist/vite/tempest-csp.cjs +2 -2
- package/dist/vite/tempest-csp.cjs.map +1 -1
- package/dist/vite/tempest-csp.js +69 -66
- package/dist/vite/tempest-csp.js.map +1 -1
- package/dist/vite/tempest-icons.cjs.map +1 -1
- package/dist/vite/tempest-icons.js.map +1 -1
- package/dist/vite/tempest-pwa-dev-sw.cjs +1 -1
- package/dist/vite/tempest-pwa-dev-sw.cjs.map +1 -1
- package/dist/vite/tempest-pwa-dev-sw.js +9 -16
- package/dist/vite/tempest-pwa-dev-sw.js.map +1 -1
- package/dist/vite/tempest-pwa-icons.cjs.map +1 -1
- package/dist/vite/tempest-pwa-icons.js.map +1 -1
- package/dist/vite/tempest-pwa-manifest.cjs.map +1 -1
- package/dist/vite/tempest-pwa-manifest.js.map +1 -1
- package/dist/vite/tempest-styles.cjs.map +1 -1
- package/dist/vite/tempest-styles.js.map +1 -1
- package/dist/vite/tempest-vitest.cjs.map +1 -1
- package/dist/vite/tempest-vitest.js.map +1 -1
- package/dist/vite.d.ts +5 -3
- package/dist/webrtc/link-stats.cjs.map +1 -1
- package/dist/webrtc/link-stats.js.map +1 -1
- package/dist/webrtc/mesh-quality.cjs.map +1 -1
- package/dist/webrtc/mesh-quality.js.map +1 -1
- package/dist/webrtc/opus-sdp.cjs.map +1 -1
- package/dist/webrtc/opus-sdp.js.map +1 -1
- package/dist/webrtc/peer-link.cjs +1 -1
- package/dist/webrtc/peer-link.cjs.map +1 -1
- package/dist/webrtc/peer-link.js +2 -5
- package/dist/webrtc/peer-link.js.map +1 -1
- package/dist/webrtc/peer-mesh.cjs +1 -1
- package/dist/webrtc/peer-mesh.cjs.map +1 -1
- package/dist/webrtc/peer-mesh.js +8 -24
- package/dist/webrtc/peer-mesh.js.map +1 -1
- package/dist/webrtc/sender-bitrate.cjs.map +1 -1
- package/dist/webrtc/sender-bitrate.js.map +1 -1
- package/dist/webrtc/use-link-stats.cjs.map +1 -1
- package/dist/webrtc/use-link-stats.js.map +1 -1
- package/dist/ws/create-web-socket.cjs +1 -1
- package/dist/ws/create-web-socket.cjs.map +1 -1
- package/dist/ws/create-web-socket.js +4 -22
- package/dist/ws/create-web-socket.js.map +1 -1
- package/dist/ws/resilience.cjs.map +1 -1
- package/dist/ws/resilience.js.map +1 -1
- package/dist/ws/use-web-socket.cjs.map +1 -1
- package/dist/ws/use-web-socket.js.map +1 -1
- package/package.json +9 -6
- package/template/package.json +1 -1
- package/dist/telemetry/app-error-owner.cjs.map +0 -1
- package/dist/telemetry/app-error-owner.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageCropper.js","names":[],"sources":["../../../src/components/ImageCropper/ImageCropper.tsx"],"sourcesContent":["/**\n * @tempest-limits file-lines, props-count, function-lines — pointer drag, wheel\n * zoom, aspect clamping and canvas export share one piece of geometry state, and the\n * props are the two halves of that: the frame (aspect, shape, maxZoom, label) and\n * the export (maxSize, outputType, outputQuality, onCropChange, ref). Threading the\n * geometry through props would duplicate the clamp maths.\n */\nimport {\n type HTMLAttributes,\n type KeyboardEvent,\n type PointerEvent as ReactPointerEvent,\n useCallback,\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport {\n clampOffset,\n computeCropRect,\n coverScale,\n type Offset,\n outputSize,\n type Size,\n} from \"./crop-geometry\";\nimport styles from \"./ImageCropper.module.css\";\n\n/** Imperative handle for exporting the current crop. */\nexport interface ImageCropperHandle {\n /**\n * Render the current crop and resolve with it.\n *\n * Resolves `null` when the image has not loaded yet or the browser refuses to\n * encode — never throws, so a submit handler does not need a try/catch.\n */\n crop: () => Promise<Blob | null>;\n /** Recentre at zoom 1. */\n reset: () => void;\n}\n\nexport interface ImageCropperProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** The image to crop: a `File`/`Blob` from an input, or a URL. */\n src: File | Blob | string;\n /** Crop aspect ratio as `width / height`. Default `1` (square). */\n aspect?: number;\n /** Maximum zoom over the cover scale. Default `4`. */\n maxZoom?: number;\n /**\n * Cap on the longest edge of the exported image, in px.\n *\n * Without it the export keeps the source resolution, which is right for a\n * document scan and wasteful for an avatar.\n */\n maxSize?: number;\n /** Output MIME type. Default `\"image/png\"`. */\n outputType?: string;\n /** Output quality for lossy types, `0`–`1`. Default `0.92`. */\n outputQuality?: number;\n /** Overlay shape. `\"circle\"` for an avatar, `\"rect\"` for a document. Default `\"rect\"`. */\n shape?: \"rect\" | \"circle\";\n /** Called whenever the crop changes, e.g. to enable a submit button. */\n onCropChange?: (state: { zoom: number; offset: Offset }) => void;\n /** Accessible name for the crop area. */\n label?: string;\n ref?: React.Ref<ImageCropperHandle>;\n}\n\n/** Pixels moved per arrow-key press. */\nconst KEY_STEP = 12;\n\n/** Zoom added or removed per `+`/`-` press, and per wheel notch. */\nconst ZOOM_STEP = 0.15;\n\n/**\n * Crop an image to a fixed aspect ratio.\n *\n * The frame stays put and the image pans and zooms behind it — the model an avatar\n * or document-photo flow wants, where the output shape is decided by the app and\n * the user only chooses what lands inside it. (A free-form draggable rectangle is a\n * different component; this one cannot produce an off-ratio crop by construction.)\n *\n * The export reads the *natural* pixels through a canvas, so a 4000 px photo is not\n * silently downsampled to whatever the on-screen preview measured. The image is\n * also always clamped to cover the frame, so an export can never contain the empty\n * bands you get from panning past an edge.\n *\n * Works by pointer, wheel and keyboard: arrows pan, `+`/`-` zoom, `0` resets.\n *\n * @example\n * const cropper = useRef<ImageCropperHandle>(null);\n *\n * <ImageCropper ref={cropper} src={file} aspect={1} shape=\"circle\" maxSize={512} />\n * <Button onClick={async () => upload(await cropper.current?.crop())}>Salvar</Button>\n */\nexport function ImageCropper({\n src,\n aspect = 1,\n maxZoom = 4,\n maxSize,\n outputType = \"image/png\",\n outputQuality = 0.92,\n shape = \"rect\",\n onCropChange,\n label = \"Área de recorte\",\n className,\n ref,\n ...rest\n}: ImageCropperProps) {\n /**\n * Id for the shortcut hint.\n *\n * Generated rather than derived from `label`: a label with spaces would produce\n * an id with spaces, and `aria-describedby` splits on whitespace — so the\n * description would silently never associate with the frame.\n */\n const hintId = `${useId()}-hint`;\n\n const frameRef = useRef<HTMLDivElement>(null);\n const imageRef = useRef<HTMLImageElement | null>(null);\n const dragRef = useRef<{\n pointerId: number;\n startX: number;\n startY: number;\n from: Offset;\n } | null>(null);\n\n const [url, setUrl] = useState<string | null>(null);\n const [natural, setNatural] = useState<Size | null>(null);\n const [frame, setFrame] = useState<Size>({ width: 0, height: 0 });\n const [zoom, setZoom] = useState(1);\n const [offset, setOffset] = useState<Offset>({ x: 0, y: 0 });\n\n /**\n * Resolve `src` to a displayable URL.\n *\n * A `File`/`Blob` needs `createObjectURL`, and the URL must be revoked when the\n * source changes or the component unmounts — otherwise every re-pick of a photo\n * leaks the previous one for the lifetime of the document.\n */\n useEffect(() => {\n if (typeof src === \"string\") {\n setUrl(src);\n return;\n }\n const objectUrl = URL.createObjectURL(src);\n setUrl(objectUrl);\n return () => URL.revokeObjectURL(objectUrl);\n }, [src]);\n\n // A new source invalidates the previous framing.\n useEffect(() => {\n setNatural(null);\n setZoom(1);\n setOffset({ x: 0, y: 0 });\n }, [url]);\n\n /** Track the frame's rendered size — the crop math is all relative to it. */\n useEffect(() => {\n const element = frameRef.current;\n if (!element) return;\n const measure = () =>\n setFrame({ width: element.clientWidth, height: element.clientHeight });\n measure();\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n return () => observer.disconnect();\n }, []);\n\n const scale = natural ? coverScale(natural, frame) * zoom : 0;\n\n /**\n * On-screen image size.\n *\n * Memoized because the pan callback depends on it: a fresh object every render\n * would rebuild that callback every render, and the pointer handlers close over\n * it during a drag.\n */\n const displayed = useMemo<Size>(\n () =>\n natural\n ? { width: natural.width * scale, height: natural.height * scale }\n : { width: 0, height: 0 },\n [natural, scale],\n );\n\n /** Apply a pan, clamped so the frame stays covered. */\n const pan = useCallback(\n (next: Offset) => {\n setOffset((current) => {\n const clamped = clampOffset(next, displayed, frame);\n if (clamped.x === current.x && clamped.y === current.y) return current;\n onCropChange?.({ zoom, offset: clamped });\n return clamped;\n });\n },\n [displayed, frame, onCropChange, zoom],\n );\n\n /**\n * Apply a zoom, then re-clamp the offset.\n *\n * Re-clamping is not optional: zooming *out* shrinks the image, so an offset\n * that was legal a moment ago can now expose background.\n */\n const applyZoom = useCallback(\n (next: number) => {\n const clampedZoom = Math.min(maxZoom, Math.max(1, next));\n setZoom(clampedZoom);\n if (!natural) return;\n const nextScale = coverScale(natural, frame) * clampedZoom;\n const nextDisplayed = {\n width: natural.width * nextScale,\n height: natural.height * nextScale,\n };\n setOffset((current) => {\n const clamped = clampOffset(current, nextDisplayed, frame);\n onCropChange?.({ zoom: clampedZoom, offset: clamped });\n return clamped;\n });\n },\n [frame, maxZoom, natural, onCropChange],\n );\n\n const reset = useCallback(() => {\n setZoom(1);\n setOffset({ x: 0, y: 0 });\n onCropChange?.({ zoom: 1, offset: { x: 0, y: 0 } });\n }, [onCropChange]);\n\n /**\n * Draw the current crop and encode it.\n *\n * Returns `null` rather than throwing on the paths a caller cannot do anything\n * about: no image yet, no 2D context, or an encoder that declined.\n */\n const crop = useCallback(async (): Promise<Blob | null> => {\n const image = imageRef.current;\n if (!image || !natural) return null;\n\n const rect = computeCropRect({ image: natural, frame, zoom, offset });\n if (rect.sWidth <= 0 || rect.sHeight <= 0) return null;\n\n const out = outputSize(rect, maxSize);\n const canvas = document.createElement(\"canvas\");\n canvas.width = out.width;\n canvas.height = out.height;\n const context = canvas.getContext(\"2d\");\n if (!context) return null;\n\n context.drawImage(\n image,\n rect.sx,\n rect.sy,\n rect.sWidth,\n rect.sHeight,\n 0,\n 0,\n out.width,\n out.height,\n );\n\n return new Promise((resolve) => {\n canvas.toBlob((blob) => resolve(blob), outputType, outputQuality);\n });\n }, [frame, maxSize, natural, offset, outputQuality, outputType, zoom]);\n\n useImperativeHandle(ref, () => ({ crop, reset }), [crop, reset]);\n\n const onPointerDown = (event: ReactPointerEvent<HTMLDivElement>): void => {\n if (!natural) return;\n dragRef.current = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n from: offset,\n };\n event.currentTarget.setPointerCapture?.(event.pointerId);\n };\n\n const onPointerMove = (event: ReactPointerEvent<HTMLDivElement>): void => {\n const drag = dragRef.current;\n if (!drag || drag.pointerId !== event.pointerId) return;\n pan({\n x: drag.from.x + (event.clientX - drag.startX),\n y: drag.from.y + (event.clientY - drag.startY),\n });\n };\n\n const endDrag = (event: ReactPointerEvent<HTMLDivElement>): void => {\n if (dragRef.current?.pointerId !== event.pointerId) return;\n dragRef.current = null;\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {\n const step = event.shiftKey ? KEY_STEP * 4 : KEY_STEP;\n const moves: Record<string, Offset> = {\n ArrowLeft: { x: -step, y: 0 },\n ArrowRight: { x: step, y: 0 },\n ArrowUp: { x: 0, y: -step },\n ArrowDown: { x: 0, y: step },\n };\n const move = moves[event.key];\n if (move) {\n event.preventDefault();\n pan({ x: offset.x + move.x, y: offset.y + move.y });\n return;\n }\n if (event.key === \"+\" || event.key === \"=\") {\n event.preventDefault();\n applyZoom(zoom + ZOOM_STEP);\n } else if (event.key === \"-\" || event.key === \"_\") {\n event.preventDefault();\n applyZoom(zoom - ZOOM_STEP);\n } else if (event.key === \"0\") {\n event.preventDefault();\n reset();\n }\n };\n\n return (\n <div className={cn(styles.wrapper, className)} {...rest}>\n <div\n ref={frameRef}\n className={cn(styles.frame, shape === \"circle\" && styles.circle)}\n style={{ aspectRatio: String(aspect) }}\n role=\"group\"\n aria-label={label}\n aria-describedby={hintId}\n tabIndex={0}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={endDrag}\n onPointerCancel={endDrag}\n onKeyDown={onKeyDown}\n onWheel={(event) => {\n event.preventDefault();\n applyZoom(zoom + (event.deltaY < 0 ? ZOOM_STEP : -ZOOM_STEP));\n }}\n >\n {url && (\n <img\n ref={imageRef}\n src={url}\n alt=\"\"\n draggable={false}\n className={styles.image}\n style={{\n width: displayed.width || undefined,\n height: displayed.height || undefined,\n transform: `translate(${offset.x}px, ${offset.y}px)`,\n }}\n onLoad={(event) => {\n const element = event.currentTarget;\n // A decode can succeed and still report no intrinsic size —\n // an SVG without a viewBox is the common case. Accepting\n // that would enable the controls over an image the crop\n // maths can do nothing with.\n if (element.naturalWidth > 0 && element.naturalHeight > 0) {\n setNatural({\n width: element.naturalWidth,\n height: element.naturalHeight,\n });\n }\n }}\n />\n )}\n </div>\n\n <div className={styles.controls}>\n <input\n type=\"range\"\n className={styles.zoom}\n min={1}\n max={maxZoom}\n step={0.01}\n value={zoom}\n onChange={(event) => applyZoom(Number(event.target.value))}\n aria-label=\"Zoom\"\n disabled={!natural}\n />\n <button type=\"button\" className={styles.reset} onClick={reset} disabled={!natural}>\n Centralizar\n </button>\n </div>\n\n <p id={hintId} className={styles.hint}>\n Arraste para reposicionar. Setas movem, <kbd>+</kbd> e <kbd>−</kbd> dão zoom,{\" \"}\n <kbd>0</kbd> centraliza.\n </p>\n </div>\n );\n}\n"],"mappings":";;;;;;AAyEA,IAAM,IAAW,IAGX,IAAY;AAuBlB,SAAgB,EAAa,EACzB,QACA,YAAS,GACT,aAAU,GACV,YACA,gBAAa,aACb,mBAAgB,KAChB,WAAQ,QACR,iBACA,WAAQ,mBACR,cACA,QACA,GAAG,KACe;CAQlB,IAAM,IAAS,GAAG,EAAM,EAAE,QAEpB,IAAW,EAAuB,IAAI,GACtC,IAAW,EAAgC,IAAI,GAC/C,IAAU,EAKN,IAAI,GAER,CAAC,GAAK,KAAU,EAAwB,IAAI,GAC5C,CAAC,GAAS,KAAc,EAAsB,IAAI,GAClD,CAAC,GAAO,KAAY,EAAe;EAAE,OAAO;EAAG,QAAQ;CAAE,CAAC,GAC1D,CAAC,GAAM,KAAW,EAAS,CAAC,GAC5B,CAAC,GAAQ,KAAa,EAAiB;EAAE,GAAG;EAAG,GAAG;CAAE,CAAC;CA2B3D,AAlBA,QAAgB;EACZ,IAAI,OAAO,KAAQ,UAAU;GACzB,EAAO,CAAG;GACV;EACJ;EACA,IAAM,IAAY,IAAI,gBAAgB,CAAG;EAEzC,OADA,EAAO,CAAS,SACH,IAAI,gBAAgB,CAAS;CAC9C,GAAG,CAAC,CAAG,CAAC,GAGR,QAAgB;EAGZ,AAFA,EAAW,IAAI,GACf,EAAQ,CAAC,GACT,EAAU;GAAE,GAAG;GAAG,GAAG;EAAE,CAAC;CAC5B,GAAG,CAAC,CAAG,CAAC,GAGR,QAAgB;EACZ,IAAM,IAAU,EAAS;EACzB,IAAI,CAAC,GAAS;EACd,IAAM,UACF,EAAS;GAAE,OAAO,EAAQ;GAAa,QAAQ,EAAQ;EAAa,CAAC;EAEzE,IADA,EAAQ,GACJ,OAAO,iBAAmB,KAAa;EAC3C,IAAM,IAAW,IAAI,eAAe,CAAO;EAE3C,OADA,EAAS,QAAQ,CAAO,SACX,EAAS,WAAW;CACrC,GAAG,CAAC,CAAC;CAEL,IAAM,IAAQ,IAAU,EAAW,GAAS,CAAK,IAAI,IAAO,GAStD,IAAY,QAEV,IACM;EAAE,OAAO,EAAQ,QAAQ;EAAO,QAAQ,EAAQ,SAAS;CAAM,IAC/D;EAAE,OAAO;EAAG,QAAQ;CAAE,GAChC,CAAC,GAAS,CAAK,CACnB,GAGM,IAAM,GACP,MAAiB;EACd,GAAW,MAAY;GACnB,IAAM,IAAU,EAAY,GAAM,GAAW,CAAK;GAGlD,OAFI,EAAQ,MAAM,EAAQ,KAAK,EAAQ,MAAM,EAAQ,IAAU,KAC/D,IAAe;IAAE;IAAM,QAAQ;GAAQ,CAAC,GACjC;EACX,CAAC;CACL,GACA;EAAC;EAAW;EAAO;EAAc;CAAI,CACzC,GAQM,IAAY,GACb,MAAiB;EACd,IAAM,IAAc,KAAK,IAAI,GAAS,KAAK,IAAI,GAAG,CAAI,CAAC;EAEvD,IADA,EAAQ,CAAW,GACf,CAAC,GAAS;EACd,IAAM,IAAY,EAAW,GAAS,CAAK,IAAI,GACzC,IAAgB;GAClB,OAAO,EAAQ,QAAQ;GACvB,QAAQ,EAAQ,SAAS;EAC7B;EACA,GAAW,MAAY;GACnB,IAAM,IAAU,EAAY,GAAS,GAAe,CAAK;GAEzD,OADA,IAAe;IAAE,MAAM;IAAa,QAAQ;GAAQ,CAAC,GAC9C;EACX,CAAC;CACL,GACA;EAAC;EAAO;EAAS;EAAS;CAAY,CAC1C,GAEM,IAAQ,QAAkB;EAG5B,AAFA,EAAQ,CAAC,GACT,EAAU;GAAE,GAAG;GAAG,GAAG;EAAE,CAAC,GACxB,IAAe;GAAE,MAAM;GAAG,QAAQ;IAAE,GAAG;IAAG,GAAG;GAAE;EAAE,CAAC;CACtD,GAAG,CAAC,CAAY,CAAC,GAQX,IAAO,EAAY,YAAkC;EACvD,IAAM,IAAQ,EAAS;EACvB,IAAI,CAAC,KAAS,CAAC,GAAS,OAAO;EAE/B,IAAM,IAAO,EAAgB;GAAE,OAAO;GAAS;GAAO;GAAM;EAAO,CAAC;EACpE,IAAI,EAAK,UAAU,KAAK,EAAK,WAAW,GAAG,OAAO;EAElD,IAAM,IAAM,EAAW,GAAM,CAAO,GAC9B,IAAS,SAAS,cAAc,QAAQ;EAE9C,AADA,EAAO,QAAQ,EAAI,OACnB,EAAO,SAAS,EAAI;EACpB,IAAM,IAAU,EAAO,WAAW,IAAI;EAetC,OAdK,KAEL,EAAQ,UACJ,GACA,EAAK,IACL,EAAK,IACL,EAAK,QACL,EAAK,SACL,GACA,GACA,EAAI,OACJ,EAAI,MACR,GAEO,IAAI,SAAS,MAAY;GAC5B,EAAO,QAAQ,MAAS,EAAQ,CAAI,GAAG,GAAY,CAAa;EACpE,CAAC,KAhBoB;CAiBzB,GAAG;EAAC;EAAO;EAAS;EAAS;EAAQ;EAAe;EAAY;CAAI,CAAC;CAErE,EAAoB,UAAY;EAAE;EAAM;CAAM,IAAI,CAAC,GAAM,CAAK,CAAC;CAE/D,IAAM,KAAiB,MAAmD;EACjE,MACL,EAAQ,UAAU;GACd,WAAW,EAAM;GACjB,QAAQ,EAAM;GACd,QAAQ,EAAM;GACd,MAAM;EACV,GACA,EAAM,cAAc,oBAAoB,EAAM,SAAS;CAC3D,GAEM,KAAiB,MAAmD;EACtE,IAAM,IAAO,EAAQ;EACjB,AAAC,KAAQ,EAAK,cAAc,EAAM,aACtC,EAAI;GACA,GAAG,EAAK,KAAK,KAAK,EAAM,UAAU,EAAK;GACvC,GAAG,EAAK,KAAK,KAAK,EAAM,UAAU,EAAK;EAC3C,CAAC;CACL,GAEM,KAAW,MAAmD;EAC5D,EAAQ,SAAS,cAAc,EAAM,cACzC,EAAQ,UAAU;CACtB,GAEM,KAAa,MAA+C;EAC9D,IAAM,IAAO,EAAM,WAAW,KAAe,GAOvC,IAAO;GALT,WAAW;IAAE,GAAG,CAAC;IAAM,GAAG;GAAE;GAC5B,YAAY;IAAE,GAAG;IAAM,GAAG;GAAE;GAC5B,SAAS;IAAE,GAAG;IAAG,GAAG,CAAC;GAAK;GAC1B,WAAW;IAAE,GAAG;IAAG,GAAG;GAAK;EAElB,EAAM,EAAM;EACzB,IAAI,GAAM;GAEN,AADA,EAAM,eAAe,GACrB,EAAI;IAAE,GAAG,EAAO,IAAI,EAAK;IAAG,GAAG,EAAO,IAAI,EAAK;GAAE,CAAC;GAClD;EACJ;EACA,AAAI,EAAM,QAAQ,OAAO,EAAM,QAAQ,OACnC,EAAM,eAAe,GACrB,EAAU,IAAO,CAAS,KACnB,EAAM,QAAQ,OAAO,EAAM,QAAQ,OAC1C,EAAM,eAAe,GACrB,EAAU,IAAO,CAAS,KACnB,EAAM,QAAQ,QACrB,EAAM,eAAe,GACrB,EAAM;CAEd;CAEA,OACI,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,SAAS,CAAS;EAAG,GAAI;EAAnD,UAAA;GACI,kBAAC,OAAD;IACI,KAAK;IACL,WAAW,EAAG,EAAO,OAAO,MAAU,YAAY,EAAO,MAAM;IAC/D,OAAO,EAAE,aAAa,OAAO,CAAM,EAAE;IACrC,MAAK;IACL,cAAY;IACZ,oBAAkB;IAClB,UAAU;IACK;IACA;IACf,aAAa;IACb,iBAAiB;IACN;IACX,UAAU,MAAU;KAEhB,AADA,EAAM,eAAe,GACrB,EAAU,KAAQ,EAAM,SAAS,IAAI,IAAY,KAAW;IAChE;IAEC,UAAA,KACG,kBAAC,OAAD;KACI,KAAK;KACL,KAAK;KACL,KAAI;KACJ,WAAW;KACX,WAAW,EAAO;KAClB,OAAO;MACH,OAAO,EAAU,SAAS,KAAA;MAC1B,QAAQ,EAAU,UAAU,KAAA;MAC5B,WAAW,aAAa,EAAO,EAAE,MAAM,EAAO,EAAE;KACpD;KACA,SAAS,MAAU;MACf,IAAM,IAAU,EAAM;MAKtB,AAAI,EAAQ,eAAe,KAAK,EAAQ,gBAAgB,KACpD,EAAW;OACP,OAAO,EAAQ;OACf,QAAQ,EAAQ;MACpB,CAAC;KAET;IACH,CAAA;GAEJ,CAAA;GAEL,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAvB,UAAA,CACI,kBAAC,SAAD;KACI,MAAK;KACL,WAAW,EAAO;KAClB,KAAK;KACL,KAAK;KACL,MAAM;KACN,OAAO;KACP,WAAW,MAAU,EAAU,OAAO,EAAM,OAAO,KAAK,CAAC;KACzD,cAAW;KACX,UAAU,CAAC;IACd,CAAA,GACD,kBAAC,UAAD;KAAQ,MAAK;KAAS,WAAW,EAAO;KAAO,SAAS;KAAO,UAAU,CAAC;KAAS,UAAA;IAE3E,CAAA,CACP;;GAEL,kBAAC,KAAD;IAAG,IAAI;IAAQ,WAAW,EAAO;IAAjC,UAAA;KAAuC;KACK,kBAAC,OAAD,EAAA,UAAK,IAAM,CAAA;KAAC;KAAG,kBAAC,OAAD,EAAA,UAAK,IAAM,CAAA;KAAC;KAAW;KAC9E,kBAAC,OAAD,EAAA,UAAK,IAAM,CAAA;KAAC;IACb;;EACF;;AAEb"}
|
|
1
|
+
{"version":3,"file":"ImageCropper.js","names":["styles","ImageCropper_module_default","KEY_STEP","ZOOM_STEP","ImageCropper","rest","hintId","useId","frameRef","useRef","imageRef","dragRef","url","setUrl","useState","natural","setNatural","frame","setFrame","zoom","setZoom","offset","setOffset","useEffect","src","objectUrl","element","measure","observer","scale","coverScale","displayed","useMemo","pan","useCallback","clamped","clampOffset","next","current","onCropChange","applyZoom","clampedZoom","maxZoom","nextScale","nextDisplayed","reset","crop","image","rect","computeCropRect","out","outputSize","maxSize","canvas","context","resolve","blob","outputType","outputQuality","ref","onPointerDown","event","onPointerMove","drag","endDrag","onKeyDown","step","move","cn","className","shape","aspect","label"],"sources":["../../../src/components/ImageCropper/ImageCropper.tsx"],"sourcesContent":["/**\n * @tempest-limits file-lines, props-count, function-lines — pointer drag, wheel\n * zoom, aspect clamping and canvas export share one piece of geometry state, and the\n * props are the two halves of that: the frame (aspect, shape, maxZoom, label) and\n * the export (maxSize, outputType, outputQuality, onCropChange, ref). Threading the\n * geometry through props would duplicate the clamp maths.\n */\nimport {\n type HTMLAttributes,\n type KeyboardEvent,\n type PointerEvent as ReactPointerEvent,\n useCallback,\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport {\n clampOffset,\n computeCropRect,\n coverScale,\n type Offset,\n outputSize,\n type Size,\n} from \"./crop-geometry\";\nimport styles from \"./ImageCropper.module.css\";\n\n/** Imperative handle for exporting the current crop. */\nexport interface ImageCropperHandle {\n /**\n * Render the current crop and resolve with it.\n *\n * Resolves `null` when the image has not loaded yet or the browser refuses to\n * encode — never throws, so a submit handler does not need a try/catch.\n */\n crop: () => Promise<Blob | null>;\n /** Recentre at zoom 1. */\n reset: () => void;\n}\n\nexport interface ImageCropperProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** The image to crop: a `File`/`Blob` from an input, or a URL. */\n src: File | Blob | string;\n /** Crop aspect ratio as `width / height`. Default `1` (square). */\n aspect?: number;\n /** Maximum zoom over the cover scale. Default `4`. */\n maxZoom?: number;\n /**\n * Cap on the longest edge of the exported image, in px.\n *\n * Without it the export keeps the source resolution, which is right for a\n * document scan and wasteful for an avatar.\n */\n maxSize?: number;\n /** Output MIME type. Default `\"image/png\"`. */\n outputType?: string;\n /** Output quality for lossy types, `0`–`1`. Default `0.92`. */\n outputQuality?: number;\n /** Overlay shape. `\"circle\"` for an avatar, `\"rect\"` for a document. Default `\"rect\"`. */\n shape?: \"rect\" | \"circle\";\n /** Called whenever the crop changes, e.g. to enable a submit button. */\n onCropChange?: (state: { zoom: number; offset: Offset }) => void;\n /** Accessible name for the crop area. */\n label?: string;\n ref?: React.Ref<ImageCropperHandle>;\n}\n\n/** Pixels moved per arrow-key press. */\nconst KEY_STEP = 12;\n\n/** Zoom added or removed per `+`/`-` press, and per wheel notch. */\nconst ZOOM_STEP = 0.15;\n\n/**\n * Crop an image to a fixed aspect ratio.\n *\n * The frame stays put and the image pans and zooms behind it — the model an avatar\n * or document-photo flow wants, where the output shape is decided by the app and\n * the user only chooses what lands inside it. (A free-form draggable rectangle is a\n * different component; this one cannot produce an off-ratio crop by construction.)\n *\n * The export reads the *natural* pixels through a canvas, so a 4000 px photo is not\n * silently downsampled to whatever the on-screen preview measured. The image is\n * also always clamped to cover the frame, so an export can never contain the empty\n * bands you get from panning past an edge.\n *\n * Works by pointer, wheel and keyboard: arrows pan, `+`/`-` zoom, `0` resets.\n *\n * @example\n * const cropper = useRef<ImageCropperHandle>(null);\n *\n * <ImageCropper ref={cropper} src={file} aspect={1} shape=\"circle\" maxSize={512} />\n * <Button onClick={async () => upload(await cropper.current?.crop())}>Salvar</Button>\n */\nexport function ImageCropper({\n src,\n aspect = 1,\n maxZoom = 4,\n maxSize,\n outputType = \"image/png\",\n outputQuality = 0.92,\n shape = \"rect\",\n onCropChange,\n label = \"Área de recorte\",\n className,\n ref,\n ...rest\n}: ImageCropperProps) {\n /**\n * Id for the shortcut hint.\n *\n * Generated rather than derived from `label`: a label with spaces would produce\n * an id with spaces, and `aria-describedby` splits on whitespace — so the\n * description would silently never associate with the frame.\n */\n const hintId = `${useId()}-hint`;\n\n const frameRef = useRef<HTMLDivElement>(null);\n const imageRef = useRef<HTMLImageElement | null>(null);\n const dragRef = useRef<{\n pointerId: number;\n startX: number;\n startY: number;\n from: Offset;\n } | null>(null);\n\n const [url, setUrl] = useState<string | null>(null);\n const [natural, setNatural] = useState<Size | null>(null);\n const [frame, setFrame] = useState<Size>({ width: 0, height: 0 });\n const [zoom, setZoom] = useState(1);\n const [offset, setOffset] = useState<Offset>({ x: 0, y: 0 });\n\n /**\n * Resolve `src` to a displayable URL.\n *\n * A `File`/`Blob` needs `createObjectURL`, and the URL must be revoked when the\n * source changes or the component unmounts — otherwise every re-pick of a photo\n * leaks the previous one for the lifetime of the document.\n */\n useEffect(() => {\n if (typeof src === \"string\") {\n setUrl(src);\n return;\n }\n const objectUrl = URL.createObjectURL(src);\n setUrl(objectUrl);\n return () => URL.revokeObjectURL(objectUrl);\n }, [src]);\n\n // A new source invalidates the previous framing.\n useEffect(() => {\n setNatural(null);\n setZoom(1);\n setOffset({ x: 0, y: 0 });\n }, [url]);\n\n /** Track the frame's rendered size — the crop math is all relative to it. */\n useEffect(() => {\n const element = frameRef.current;\n if (!element) return;\n const measure = () =>\n setFrame({ width: element.clientWidth, height: element.clientHeight });\n measure();\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n return () => observer.disconnect();\n }, []);\n\n const scale = natural ? coverScale(natural, frame) * zoom : 0;\n\n /**\n * On-screen image size.\n *\n * Memoized because the pan callback depends on it: a fresh object every render\n * would rebuild that callback every render, and the pointer handlers close over\n * it during a drag.\n */\n const displayed = useMemo<Size>(\n () =>\n natural\n ? { width: natural.width * scale, height: natural.height * scale }\n : { width: 0, height: 0 },\n [natural, scale],\n );\n\n /** Apply a pan, clamped so the frame stays covered. */\n const pan = useCallback(\n (next: Offset) => {\n setOffset((current) => {\n const clamped = clampOffset(next, displayed, frame);\n if (clamped.x === current.x && clamped.y === current.y) return current;\n onCropChange?.({ zoom, offset: clamped });\n return clamped;\n });\n },\n [displayed, frame, onCropChange, zoom],\n );\n\n /**\n * Apply a zoom, then re-clamp the offset.\n *\n * Re-clamping is not optional: zooming *out* shrinks the image, so an offset\n * that was legal a moment ago can now expose background.\n */\n const applyZoom = useCallback(\n (next: number) => {\n const clampedZoom = Math.min(maxZoom, Math.max(1, next));\n setZoom(clampedZoom);\n if (!natural) return;\n const nextScale = coverScale(natural, frame) * clampedZoom;\n const nextDisplayed = {\n width: natural.width * nextScale,\n height: natural.height * nextScale,\n };\n setOffset((current) => {\n const clamped = clampOffset(current, nextDisplayed, frame);\n onCropChange?.({ zoom: clampedZoom, offset: clamped });\n return clamped;\n });\n },\n [frame, maxZoom, natural, onCropChange],\n );\n\n const reset = useCallback(() => {\n setZoom(1);\n setOffset({ x: 0, y: 0 });\n onCropChange?.({ zoom: 1, offset: { x: 0, y: 0 } });\n }, [onCropChange]);\n\n /**\n * Draw the current crop and encode it.\n *\n * Returns `null` rather than throwing on the paths a caller cannot do anything\n * about: no image yet, no 2D context, or an encoder that declined.\n */\n const crop = useCallback(async (): Promise<Blob | null> => {\n const image = imageRef.current;\n if (!image || !natural) return null;\n\n const rect = computeCropRect({ image: natural, frame, zoom, offset });\n if (rect.sWidth <= 0 || rect.sHeight <= 0) return null;\n\n const out = outputSize(rect, maxSize);\n const canvas = document.createElement(\"canvas\");\n canvas.width = out.width;\n canvas.height = out.height;\n const context = canvas.getContext(\"2d\");\n if (!context) return null;\n\n context.drawImage(\n image,\n rect.sx,\n rect.sy,\n rect.sWidth,\n rect.sHeight,\n 0,\n 0,\n out.width,\n out.height,\n );\n\n return new Promise((resolve) => {\n canvas.toBlob((blob) => resolve(blob), outputType, outputQuality);\n });\n }, [frame, maxSize, natural, offset, outputQuality, outputType, zoom]);\n\n useImperativeHandle(ref, () => ({ crop, reset }), [crop, reset]);\n\n const onPointerDown = (event: ReactPointerEvent<HTMLDivElement>): void => {\n if (!natural) return;\n dragRef.current = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n from: offset,\n };\n event.currentTarget.setPointerCapture?.(event.pointerId);\n };\n\n const onPointerMove = (event: ReactPointerEvent<HTMLDivElement>): void => {\n const drag = dragRef.current;\n if (!drag || drag.pointerId !== event.pointerId) return;\n pan({\n x: drag.from.x + (event.clientX - drag.startX),\n y: drag.from.y + (event.clientY - drag.startY),\n });\n };\n\n const endDrag = (event: ReactPointerEvent<HTMLDivElement>): void => {\n if (dragRef.current?.pointerId !== event.pointerId) return;\n dragRef.current = null;\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {\n const step = event.shiftKey ? KEY_STEP * 4 : KEY_STEP;\n const moves: Record<string, Offset> = {\n ArrowLeft: { x: -step, y: 0 },\n ArrowRight: { x: step, y: 0 },\n ArrowUp: { x: 0, y: -step },\n ArrowDown: { x: 0, y: step },\n };\n const move = moves[event.key];\n if (move) {\n event.preventDefault();\n pan({ x: offset.x + move.x, y: offset.y + move.y });\n return;\n }\n if (event.key === \"+\" || event.key === \"=\") {\n event.preventDefault();\n applyZoom(zoom + ZOOM_STEP);\n } else if (event.key === \"-\" || event.key === \"_\") {\n event.preventDefault();\n applyZoom(zoom - ZOOM_STEP);\n } else if (event.key === \"0\") {\n event.preventDefault();\n reset();\n }\n };\n\n return (\n <div className={cn(styles.wrapper, className)} {...rest}>\n <div\n ref={frameRef}\n className={cn(styles.frame, shape === \"circle\" && styles.circle)}\n style={{ aspectRatio: String(aspect) }}\n role=\"group\"\n aria-label={label}\n aria-describedby={hintId}\n tabIndex={0}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={endDrag}\n onPointerCancel={endDrag}\n onKeyDown={onKeyDown}\n onWheel={(event) => {\n event.preventDefault();\n applyZoom(zoom + (event.deltaY < 0 ? ZOOM_STEP : -ZOOM_STEP));\n }}\n >\n {url && (\n <img\n ref={imageRef}\n src={url}\n alt=\"\"\n draggable={false}\n className={styles.image}\n style={{\n width: displayed.width || undefined,\n height: displayed.height || undefined,\n transform: `translate(${offset.x}px, ${offset.y}px)`,\n }}\n onLoad={(event) => {\n const element = event.currentTarget;\n // A decode can succeed and still report no intrinsic size —\n // an SVG without a viewBox is the common case. Accepting\n // that would enable the controls over an image the crop\n // maths can do nothing with.\n if (element.naturalWidth > 0 && element.naturalHeight > 0) {\n setNatural({\n width: element.naturalWidth,\n height: element.naturalHeight,\n });\n }\n }}\n />\n )}\n </div>\n\n <div className={styles.controls}>\n <input\n type=\"range\"\n className={styles.zoom}\n min={1}\n max={maxZoom}\n step={0.01}\n value={zoom}\n onChange={(event) => applyZoom(Number(event.target.value))}\n aria-label=\"Zoom\"\n disabled={!natural}\n />\n <button type=\"button\" className={styles.reset} onClick={reset} disabled={!natural}>\n Centralizar\n </button>\n </div>\n\n <p id={hintId} className={styles.hint}>\n Arraste para reposicionar. Setas movem, <kbd>+</kbd> e <kbd>−</kbd> dão zoom,{\" \"}\n <kbd>0</kbd> centraliza.\n </p>\n </div>\n );\n}\n"],"mappings":";;;;;;AAyEA,IAAME,IAAW,IAGXC,IAAY;AAuBlB,SAAgBC,EAAa,EACzB,QACA,YAAS,GACT,aAAU,GACV,YACA,gBAAa,aACb,mBAAgB,KAChB,WAAQ,QACR,iBACA,WAAQ,mBACR,cACA,QACA,GAAGC,KACe;CAQlB,IAAMC,IAAS,GAAGC,EAAM,EAAE,QAEpBC,IAAWC,EAAuB,IAAI,GACtCC,IAAWD,EAAgC,IAAI,GAC/CE,IAAUF,EAKN,IAAI,GAER,CAACG,GAAKC,KAAUC,EAAwB,IAAI,GAC5C,CAACC,GAASC,KAAcF,EAAsB,IAAI,GAClD,CAACG,GAAOC,KAAYJ,EAAe;EAAE,OAAO;EAAG,QAAQ;CAAE,CAAC,GAC1D,CAACK,GAAMC,KAAWN,EAAS,CAAC,GAC5B,CAACO,GAAQC,KAAaR,EAAiB;EAAE,GAAG;EAAG,GAAG;CAAE,CAAC;CA2B3D,AAlBAS,QAAgB;EACZ,IAAI,OAAOC,KAAQ,UAAU;GACzB,EAAOA,CAAG;GACV;EACJ;EACA,IAAMC,IAAY,IAAI,gBAAgBD,CAAG;EAEzC,OADAX,EAAOY,CAAS,SACH,IAAI,gBAAgBA,CAAS;CAC9C,GAAG,CAACD,CAAG,CAAC,GAGRD,QAAgB;EAGZ,AAFAP,EAAW,IAAI,GACfI,EAAQ,CAAC,GACTE,EAAU;GAAE,GAAG;GAAG,GAAG;EAAE,CAAC;CAC5B,GAAG,CAACV,CAAG,CAAC,GAGRW,QAAgB;EACZ,IAAMG,IAAUlB,EAAS;EACzB,IAAI,CAACkB,GAAS;EACd,IAAMC,UACFT,EAAS;GAAE,OAAOQ,EAAQ;GAAa,QAAQA,EAAQ;EAAa,CAAC;EAEzE,IADAC,EAAQ,GACJ,OAAO,iBAAmB,KAAa;EAC3C,IAAMC,IAAW,IAAI,eAAeD,CAAO;EAE3C,OADAC,EAAS,QAAQF,CAAO,SACXE,EAAS,WAAW;CACrC,GAAG,CAAC,CAAC;CAEL,IAAMC,IAAQd,IAAUe,EAAWf,GAASE,CAAK,IAAIE,IAAO,GAStDY,IAAYC,QAEVjB,IACM;EAAE,OAAOA,EAAQ,QAAQc;EAAO,QAAQd,EAAQ,SAASc;CAAM,IAC/D;EAAE,OAAO;EAAG,QAAQ;CAAE,GAChC,CAACd,GAASc,CAAK,CACnB,GAGMI,IAAMC,GACP,MAAiB;EACd,GAAW,MAAY;GACnB,IAAMC,IAAUC,EAAYC,GAAMN,GAAWd,CAAK;GAGlD,OAFIkB,EAAQ,MAAMG,EAAQ,KAAKH,EAAQ,MAAMG,EAAQ,IAAUA,KAC/DC,IAAe;IAAE;IAAM,QAAQJ;GAAQ,CAAC,GACjCA;EACX,CAAC;CACL,GACA;EAACJ;EAAWd;EAAOsB;EAAcpB;CAAI,CACzC,GAQMqB,IAAYN,GACb,MAAiB;EACd,IAAMO,IAAc,KAAK,IAAIC,GAAS,KAAK,IAAI,GAAGL,CAAI,CAAC;EAEvD,IADAjB,EAAQqB,CAAW,GACf,CAAC1B,GAAS;EACd,IAAM4B,IAAYb,EAAWf,GAASE,CAAK,IAAIwB,GACzCG,IAAgB;GAClB,OAAO7B,EAAQ,QAAQ4B;GACvB,QAAQ5B,EAAQ,SAAS4B;EAC7B;EACA,GAAW,MAAY;GACnB,IAAMR,IAAUC,EAAYE,GAASM,GAAe3B,CAAK;GAEzD,OADAsB,IAAe;IAAE,MAAME;IAAa,QAAQN;GAAQ,CAAC,GAC9CA;EACX,CAAC;CACL,GACA;EAAClB;EAAOyB;EAAS3B;EAASwB;CAAY,CAC1C,GAEMM,IAAQX,QAAkB;EAG5B,AAFAd,EAAQ,CAAC,GACTE,EAAU;GAAE,GAAG;GAAG,GAAG;EAAE,CAAC,GACxBiB,IAAe;GAAE,MAAM;GAAG,QAAQ;IAAE,GAAG;IAAG,GAAG;GAAE;EAAE,CAAC;CACtD,GAAG,CAACA,CAAY,CAAC,GAQXO,IAAOZ,EAAY,YAAkC;EACvD,IAAMa,IAAQrC,EAAS;EACvB,IAAI,CAACqC,KAAS,CAAChC,GAAS,OAAO;EAE/B,IAAMiC,IAAOC,EAAgB;GAAE,OAAOlC;GAAS;GAAO;GAAM;EAAO,CAAC;EACpE,IAAIiC,EAAK,UAAU,KAAKA,EAAK,WAAW,GAAG,OAAO;EAElD,IAAME,IAAMC,EAAWH,GAAMI,CAAO,GAC9BC,IAAS,SAAS,cAAc,QAAQ;EAE9C,AADA,EAAO,QAAQH,EAAI,OACnB,EAAO,SAASA,EAAI;EACpB,IAAMI,IAAUD,EAAO,WAAW,IAAI;EAetC,OAdKC,KAELA,EAAQ,UACJP,GACAC,EAAK,IACLA,EAAK,IACLA,EAAK,QACLA,EAAK,SACL,GACA,GACAE,EAAI,OACJA,EAAI,MACR,GAEO,IAAI,SAAS,MAAY;GAC5B,EAAO,QAAQ,MAASK,EAAQC,CAAI,GAAGC,GAAYC,CAAa;EACpE,CAAC,KAhBoB;CAiBzB,GAAG;EAACzC;EAAOmC;EAASrC;EAASM;EAAQqC;EAAeD;EAAYtC;CAAI,CAAC;CAErE,EAAoBwC,UAAY;EAAE;EAAM;CAAM,IAAI,CAACb,GAAMD,CAAK,CAAC;CAE/D,IAAMe,KAAiB,MAAmD;EACtE,AAAK7C,MACL,EAAQ,UAAU;GACd,WAAW8C,EAAM;GACjB,QAAQA,EAAM;GACd,QAAQA,EAAM;GACd,MAAMxC;EACV,GACAwC,EAAM,cAAc,oBAAoBA,EAAM,SAAS;CAC3D,GAEMC,KAAiB,MAAmD;EACtE,IAAMC,IAAOpD,EAAQ;EACrB,AAAKoD,KAAQA,EAAK,cAAcF,EAAM,aACtC5B,EAAI;GACA,GAAG8B,EAAK,KAAK,KAAKF,EAAM,UAAUE,EAAK;GACvC,GAAGA,EAAK,KAAK,KAAKF,EAAM,UAAUE,EAAK;EAC3C,CAAC;CACL,GAEMC,KAAW,MAAmD;EAChE,AAAIrD,EAAQ,SAAS,cAAckD,EAAM,cACzC,EAAQ,UAAU;CACtB,GAEMI,KAAa,MAA+C;EAC9D,IAAMC,IAAOL,EAAM,WAAW,KAAe3D,GAOvCiE,IAAO;GALT,WAAW;IAAE,GAAG,CAACD;IAAM,GAAG;GAAE;GAC5B,YAAY;IAAE,GAAGA;IAAM,GAAG;GAAE;GAC5B,SAAS;IAAE,GAAG;IAAG,GAAG,CAACA;GAAK;GAC1B,WAAW;IAAE,GAAG;IAAG,GAAGA;GAAK;EAElB,EAAML,EAAM;EACzB,AAAIM,KACAN,EAAM,eAAe,GACrB5B,EAAI;GAAE,GAAGZ,EAAO,IAAI8C,EAAK;GAAG,GAAG9C,EAAO,IAAI8C,EAAK;EAAE,CAAC,KAGlDN,EAAM,QAAQ,OAAOA,EAAM,QAAQ,OACnCA,EAAM,eAAe,GACrBrB,EAAUrB,IAAOhB,CAAS,KACnB0D,EAAM,QAAQ,OAAOA,EAAM,QAAQ,OAC1CA,EAAM,eAAe,GACrBrB,EAAUrB,IAAOhB,CAAS,KACnB0D,EAAM,QAAQ,QACrBA,EAAM,eAAe,GACrBhB,EAAM;CAEd;CAEA,OACI,kBAAC,OAAD;EAAK,WAAWuB,EAAGpE,EAAO,SAASqE,CAAS;EAAG,GAAIhE;EAAnD,UAAA;GACI,kBAAC,OAAD;IACI,KAAKG;IACL,WAAW4D,EAAGpE,EAAO,OAAOsE,MAAU,YAAYtE,EAAO,MAAM;IAC/D,OAAO,EAAE,aAAa,OAAOuE,CAAM,EAAE;IACrC,MAAK;IACL,cAAYC;IACZ,oBAAkBlE;IAClB,UAAU;IACK;IACA;IACf,aAAa0D;IACb,iBAAiBA;IACN;IACX,UAAU,MAAU;KAEhB,AADAH,EAAM,eAAe,GACrBrB,EAAUrB,KAAQ0C,EAAM,SAAS,IAAI1D,IAAY,KAAW;IAChE;IAEC,UAAAS,KACG,kBAAC,OAAD;KACI,KAAKF;KACL,KAAKE;KACL,KAAI;KACJ,WAAW;KACX,WAAWZ,EAAO;KAClB,OAAO;MACH,OAAO+B,EAAU,SAAS,KAAA;MAC1B,QAAQA,EAAU,UAAU,KAAA;MAC5B,WAAW,aAAaV,EAAO,EAAE,MAAMA,EAAO,EAAE;KACpD;KACA,SAAS,MAAU;MACf,IAAMK,IAAUmC,EAAM;MAKtB,AAAInC,EAAQ,eAAe,KAAKA,EAAQ,gBAAgB,KACpDV,EAAW;OACP,OAAOU,EAAQ;OACf,QAAQA,EAAQ;MACpB,CAAC;KAET;IACH,CAAA;GAEJ,CAAA;GAEL,kBAAC,OAAD;IAAK,WAAW1B,EAAO;IAAvB,UAAA,CACI,kBAAC,SAAD;KACI,MAAK;KACL,WAAWA,EAAO;KAClB,KAAK;KACL,KAAK0C;KACL,MAAM;KACN,OAAOvB;KACP,WAAW,MAAUqB,EAAU,OAAOqB,EAAM,OAAO,KAAK,CAAC;KACzD,cAAW;KACX,UAAU,CAAC9C;IACd,CAAA,GACD,kBAAC,UAAD;KAAQ,MAAK;KAAS,WAAWf,EAAO;KAAO,SAAS6C;KAAO,UAAU,CAAC9B;KAAS,UAAA;IAE3E,CAAA,CACP;;GAEL,kBAAC,KAAD;IAAG,IAAIT;IAAQ,WAAWN,EAAO;IAAjC,UAAA;KAAuC;KACK,kBAAC,OAAD,EAAA,UAAK,IAAM,CAAA;KAAC;KAAG,kBAAC,OAAD,EAAA,UAAK,IAAM,CAAA;KAAC;KAAW;KAC9E,kBAAC,OAAD,EAAA,UAAK,IAAM,CAAA;KAAC;IACb;;EACF;;AAEb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageCropper.module.cjs","names":[],"sources":["../../../src/components/ImageCropper/ImageCropper.module.css"],"sourcesContent":[".wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--tempest-space-3);\n max-width: 100%;\n font-family: var(--tempest-font-sans);\n}\n\n.frame {\n position: relative;\n width: 100%;\n overflow: hidden;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-lg);\n background-color: var(--tempest-surface);\n /*\n * `grab` rather than `move`: nothing is being moved to a destination, the\n * image is being dragged under a fixed frame.\n */\n cursor: grab;\n /*\n * The frame owns dragging on touch, so the browser must not also scroll the\n * page from the same gesture.\n */\n touch-action: none;\n user-select: none;\n}\n\n.frame:active {\n cursor: grabbing;\n}\n\n.frame:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: var(--tempest-focus-ring-offset);\n}\n\n.circle {\n border-radius: var(--tempest-radius-full);\n}\n\n.image {\n position: absolute;\n top: 50%;\n left: 50%;\n /*\n * Both `max-*`, not just the width. The size is set inline from the zoom, so\n * either cap silently overrides it — and an app reset carrying\n * `img { max-height: 100% }` is enough, since a 0-0-1 element rule meets no\n * competition here. The failure is worse than it looks: `crop()` builds its\n * rectangle from `computeCropRect({ image: natural, ... })` and never reads the\n * rendered element, so the export stays correct while the preview is squashed\n * on one axis. The user drags against a distorted image and gets a framing they\n * never saw. A component that sizes itself inline owns neutralising both caps.\n */\n max-width: none;\n max-height: none;\n pointer-events: none;\n /*\n * Centring lives in `translate` and the pan in the inline `transform`, which\n * are separate CSS properties applied in that order. Keeping them apart means\n * a pan is just `transform: translate(x, y)` — it never has to re-derive the\n * `-50% -50%` centring, and the two cannot overwrite each other.\n */\n translate: -50% -50%;\n}\n\n.controls {\n display: flex;\n /*\n * Wraps rather than squeezing. The zoom slider is the flexible item, so on a\n * narrow row it is the one that gives — and a range input has no useful floor\n * of its own, so it gave all the way to `width: 0`, leaving the thumb alone and\n * no visible focus ring while the button beside it kept both. Measured at 390px\n * with a crowded row. Wrapping moves the slider to its own line instead.\n */\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-3);\n}\n\n.zoom {\n /*\n * `min-width: 0` is what let it collapse to nothing: it exists to let a flex\n * item shrink past its min-content size, which for a range input is the whole\n * control. A real floor keeps the slider draggable and its focus ring visible;\n * the wrap on `.controls` is what absorbs the width this refuses to give up.\n */\n flex: 1 1 6rem;\n min-width: 6rem;\n accent-color: var(--tempest-primary);\n}\n\n.zoom:disabled {\n opacity: 0.5;\n}\n\n.reset {\n padding: var(--tempest-space-1) var(--tempest-space-3);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background-color: var(--tempest-bg);\n color: var(--tempest-text);\n font: inherit;\n font-size: var(--tempest-text-sm);\n cursor: pointer;\n}\n\n@media (hover: hover) and (pointer: fine) {\n .reset:hover:not(:disabled) {\n background-color: var(--tempest-surface);\n }\n}\n\n.reset:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: var(--tempest-focus-ring-offset);\n}\n\n.reset:disabled {\n opacity: 0.5;\n cursor: default;\n}\n\n.hint {\n margin: 0;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-xs);\n}\n\n.hint kbd {\n padding: 0 var(--tempest-space-1);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-sm);\n background-color: var(--tempest-surface);\n font-family: var(--tempest-font-mono, monospace);\n font-size: inherit;\n}\n"],"mappings":";"}
|
|
1
|
+
{"version":3,"file":"ImageCropper.module.cjs","names":["wrapper","frame","circle","image","controls","zoom","reset","hint","ImageCropper_module_default"],"sources":["../../../src/components/ImageCropper/ImageCropper.module.css"],"sourcesContent":[".wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--tempest-space-3);\n max-width: 100%;\n font-family: var(--tempest-font-sans);\n}\n\n.frame {\n position: relative;\n width: 100%;\n overflow: hidden;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-lg);\n background-color: var(--tempest-surface);\n /*\n * `grab` rather than `move`: nothing is being moved to a destination, the\n * image is being dragged under a fixed frame.\n */\n cursor: grab;\n /*\n * The frame owns dragging on touch, so the browser must not also scroll the\n * page from the same gesture.\n */\n touch-action: none;\n user-select: none;\n}\n\n.frame:active {\n cursor: grabbing;\n}\n\n.frame:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: var(--tempest-focus-ring-offset);\n}\n\n.circle {\n border-radius: var(--tempest-radius-full);\n}\n\n.image {\n position: absolute;\n top: 50%;\n left: 50%;\n /*\n * Both `max-*`, not just the width. The size is set inline from the zoom, so\n * either cap silently overrides it — and an app reset carrying\n * `img { max-height: 100% }` is enough, since a 0-0-1 element rule meets no\n * competition here. The failure is worse than it looks: `crop()` builds its\n * rectangle from `computeCropRect({ image: natural, ... })` and never reads the\n * rendered element, so the export stays correct while the preview is squashed\n * on one axis. The user drags against a distorted image and gets a framing they\n * never saw. A component that sizes itself inline owns neutralising both caps.\n */\n max-width: none;\n max-height: none;\n pointer-events: none;\n /*\n * Centring lives in `translate` and the pan in the inline `transform`, which\n * are separate CSS properties applied in that order. Keeping them apart means\n * a pan is just `transform: translate(x, y)` — it never has to re-derive the\n * `-50% -50%` centring, and the two cannot overwrite each other.\n */\n translate: -50% -50%;\n}\n\n.controls {\n display: flex;\n /*\n * Wraps rather than squeezing. The zoom slider is the flexible item, so on a\n * narrow row it is the one that gives — and a range input has no useful floor\n * of its own, so it gave all the way to `width: 0`, leaving the thumb alone and\n * no visible focus ring while the button beside it kept both. Measured at 390px\n * with a crowded row. Wrapping moves the slider to its own line instead.\n */\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-3);\n}\n\n.zoom {\n /*\n * `min-width: 0` is what let it collapse to nothing: it exists to let a flex\n * item shrink past its min-content size, which for a range input is the whole\n * control. A real floor keeps the slider draggable and its focus ring visible;\n * the wrap on `.controls` is what absorbs the width this refuses to give up.\n */\n flex: 1 1 6rem;\n min-width: 6rem;\n accent-color: var(--tempest-primary);\n}\n\n.zoom:disabled {\n opacity: 0.5;\n}\n\n.reset {\n padding: var(--tempest-space-1) var(--tempest-space-3);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background-color: var(--tempest-bg);\n color: var(--tempest-text);\n font: inherit;\n font-size: var(--tempest-text-sm);\n cursor: pointer;\n}\n\n@media (hover: hover) and (pointer: fine) {\n .reset:hover:not(:disabled) {\n background-color: var(--tempest-surface);\n }\n}\n\n.reset:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: var(--tempest-focus-ring-offset);\n}\n\n.reset:disabled {\n opacity: 0.5;\n cursor: default;\n}\n\n.hint {\n margin: 0;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-xs);\n}\n\n.hint kbd {\n padding: 0 var(--tempest-space-1);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-sm);\n background-color: var(--tempest-surface);\n font-family: var(--tempest-font-mono, monospace);\n font-size: inherit;\n}\n"],"mappings":";"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageCropper.module.js","names":[],"sources":["../../../src/components/ImageCropper/ImageCropper.module.css"],"sourcesContent":[".wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--tempest-space-3);\n max-width: 100%;\n font-family: var(--tempest-font-sans);\n}\n\n.frame {\n position: relative;\n width: 100%;\n overflow: hidden;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-lg);\n background-color: var(--tempest-surface);\n /*\n * `grab` rather than `move`: nothing is being moved to a destination, the\n * image is being dragged under a fixed frame.\n */\n cursor: grab;\n /*\n * The frame owns dragging on touch, so the browser must not also scroll the\n * page from the same gesture.\n */\n touch-action: none;\n user-select: none;\n}\n\n.frame:active {\n cursor: grabbing;\n}\n\n.frame:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: var(--tempest-focus-ring-offset);\n}\n\n.circle {\n border-radius: var(--tempest-radius-full);\n}\n\n.image {\n position: absolute;\n top: 50%;\n left: 50%;\n /*\n * Both `max-*`, not just the width. The size is set inline from the zoom, so\n * either cap silently overrides it — and an app reset carrying\n * `img { max-height: 100% }` is enough, since a 0-0-1 element rule meets no\n * competition here. The failure is worse than it looks: `crop()` builds its\n * rectangle from `computeCropRect({ image: natural, ... })` and never reads the\n * rendered element, so the export stays correct while the preview is squashed\n * on one axis. The user drags against a distorted image and gets a framing they\n * never saw. A component that sizes itself inline owns neutralising both caps.\n */\n max-width: none;\n max-height: none;\n pointer-events: none;\n /*\n * Centring lives in `translate` and the pan in the inline `transform`, which\n * are separate CSS properties applied in that order. Keeping them apart means\n * a pan is just `transform: translate(x, y)` — it never has to re-derive the\n * `-50% -50%` centring, and the two cannot overwrite each other.\n */\n translate: -50% -50%;\n}\n\n.controls {\n display: flex;\n /*\n * Wraps rather than squeezing. The zoom slider is the flexible item, so on a\n * narrow row it is the one that gives — and a range input has no useful floor\n * of its own, so it gave all the way to `width: 0`, leaving the thumb alone and\n * no visible focus ring while the button beside it kept both. Measured at 390px\n * with a crowded row. Wrapping moves the slider to its own line instead.\n */\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-3);\n}\n\n.zoom {\n /*\n * `min-width: 0` is what let it collapse to nothing: it exists to let a flex\n * item shrink past its min-content size, which for a range input is the whole\n * control. A real floor keeps the slider draggable and its focus ring visible;\n * the wrap on `.controls` is what absorbs the width this refuses to give up.\n */\n flex: 1 1 6rem;\n min-width: 6rem;\n accent-color: var(--tempest-primary);\n}\n\n.zoom:disabled {\n opacity: 0.5;\n}\n\n.reset {\n padding: var(--tempest-space-1) var(--tempest-space-3);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background-color: var(--tempest-bg);\n color: var(--tempest-text);\n font: inherit;\n font-size: var(--tempest-text-sm);\n cursor: pointer;\n}\n\n@media (hover: hover) and (pointer: fine) {\n .reset:hover:not(:disabled) {\n background-color: var(--tempest-surface);\n }\n}\n\n.reset:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: var(--tempest-focus-ring-offset);\n}\n\n.reset:disabled {\n opacity: 0.5;\n cursor: default;\n}\n\n.hint {\n margin: 0;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-xs);\n}\n\n.hint kbd {\n padding: 0 var(--tempest-space-1);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-sm);\n background-color: var(--tempest-surface);\n font-family: var(--tempest-font-mono, monospace);\n font-size: inherit;\n}\n"],"mappings":";"}
|
|
1
|
+
{"version":3,"file":"ImageCropper.module.js","names":["wrapper","frame","circle","image","controls","zoom","reset","hint","ImageCropper_module_default"],"sources":["../../../src/components/ImageCropper/ImageCropper.module.css"],"sourcesContent":[".wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--tempest-space-3);\n max-width: 100%;\n font-family: var(--tempest-font-sans);\n}\n\n.frame {\n position: relative;\n width: 100%;\n overflow: hidden;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-lg);\n background-color: var(--tempest-surface);\n /*\n * `grab` rather than `move`: nothing is being moved to a destination, the\n * image is being dragged under a fixed frame.\n */\n cursor: grab;\n /*\n * The frame owns dragging on touch, so the browser must not also scroll the\n * page from the same gesture.\n */\n touch-action: none;\n user-select: none;\n}\n\n.frame:active {\n cursor: grabbing;\n}\n\n.frame:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: var(--tempest-focus-ring-offset);\n}\n\n.circle {\n border-radius: var(--tempest-radius-full);\n}\n\n.image {\n position: absolute;\n top: 50%;\n left: 50%;\n /*\n * Both `max-*`, not just the width. The size is set inline from the zoom, so\n * either cap silently overrides it — and an app reset carrying\n * `img { max-height: 100% }` is enough, since a 0-0-1 element rule meets no\n * competition here. The failure is worse than it looks: `crop()` builds its\n * rectangle from `computeCropRect({ image: natural, ... })` and never reads the\n * rendered element, so the export stays correct while the preview is squashed\n * on one axis. The user drags against a distorted image and gets a framing they\n * never saw. A component that sizes itself inline owns neutralising both caps.\n */\n max-width: none;\n max-height: none;\n pointer-events: none;\n /*\n * Centring lives in `translate` and the pan in the inline `transform`, which\n * are separate CSS properties applied in that order. Keeping them apart means\n * a pan is just `transform: translate(x, y)` — it never has to re-derive the\n * `-50% -50%` centring, and the two cannot overwrite each other.\n */\n translate: -50% -50%;\n}\n\n.controls {\n display: flex;\n /*\n * Wraps rather than squeezing. The zoom slider is the flexible item, so on a\n * narrow row it is the one that gives — and a range input has no useful floor\n * of its own, so it gave all the way to `width: 0`, leaving the thumb alone and\n * no visible focus ring while the button beside it kept both. Measured at 390px\n * with a crowded row. Wrapping moves the slider to its own line instead.\n */\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-3);\n}\n\n.zoom {\n /*\n * `min-width: 0` is what let it collapse to nothing: it exists to let a flex\n * item shrink past its min-content size, which for a range input is the whole\n * control. A real floor keeps the slider draggable and its focus ring visible;\n * the wrap on `.controls` is what absorbs the width this refuses to give up.\n */\n flex: 1 1 6rem;\n min-width: 6rem;\n accent-color: var(--tempest-primary);\n}\n\n.zoom:disabled {\n opacity: 0.5;\n}\n\n.reset {\n padding: var(--tempest-space-1) var(--tempest-space-3);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background-color: var(--tempest-bg);\n color: var(--tempest-text);\n font: inherit;\n font-size: var(--tempest-text-sm);\n cursor: pointer;\n}\n\n@media (hover: hover) and (pointer: fine) {\n .reset:hover:not(:disabled) {\n background-color: var(--tempest-surface);\n }\n}\n\n.reset:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: var(--tempest-focus-ring-offset);\n}\n\n.reset:disabled {\n opacity: 0.5;\n cursor: default;\n}\n\n.hint {\n margin: 0;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-xs);\n}\n\n.hint kbd {\n padding: 0 var(--tempest-space-1);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-sm);\n background-color: var(--tempest-surface);\n font-family: var(--tempest-font-mono, monospace);\n font-size: inherit;\n}\n"],"mappings":";"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crop-geometry.cjs","names":[],"sources":["../../../src/components/ImageCropper/crop-geometry.ts"],"sourcesContent":["/** A width/height pair in pixels. */\nexport interface Size {\n width: number;\n height: number;\n}\n\n/** A pan offset in frame pixels, measured from the centered position. */\nexport interface Offset {\n x: number;\n y: number;\n}\n\n/** The source rectangle to read out of the natural-size image. */\nexport interface CropRect {\n sx: number;\n sy: number;\n sWidth: number;\n sHeight: number;\n}\n\n/**\n * Scale that makes `image` exactly cover `frame` with no empty space.\n *\n * `max` rather than `min`: a crop frame must never show background, so the\n * constraining axis is the one that would leave a gap.\n *\n * @param image - Natural image size.\n * @param frame - Crop frame size.\n * @returns The cover scale, or `0` when either dimension is unusable.\n */\nexport function coverScale(image: Size, frame: Size): number {\n if (image.width <= 0 || image.height <= 0 || frame.width <= 0 || frame.height <= 0) return 0;\n return Math.max(frame.width / image.width, frame.height / image.height);\n}\n\n/**\n * The largest pan offset that keeps the image covering the frame.\n *\n * Zero on an axis means the image is exactly as wide (or tall) as the frame\n * there, so panning along it would expose background.\n *\n * @param displayed - On-screen image size, after scale and zoom.\n * @param frame - Crop frame size.\n * @returns Maximum absolute offset per axis.\n */\nexport function maxOffset(displayed: Size, frame: Size): Offset {\n return {\n x: Math.max(0, (displayed.width - frame.width) / 2),\n y: Math.max(0, (displayed.height - frame.height) / 2),\n };\n}\n\n/**\n * Clamp a pan offset so the frame stays fully covered.\n *\n * This is what stops the single most common defect in a cropper: dragging or\n * zooming until the frame shows empty space, which then bakes transparent or\n * black bands into the exported image.\n *\n * @param offset - Desired offset.\n * @param displayed - On-screen image size, after scale and zoom.\n * @param frame - Crop frame size.\n * @returns The offset, clamped per axis.\n */\nexport function clampOffset(offset: Offset, displayed: Size, frame: Size): Offset {\n const max = maxOffset(displayed, frame);\n return {\n x: normalizeZero(Math.min(max.x, Math.max(-max.x, offset.x))),\n y: normalizeZero(Math.min(max.y, Math.max(-max.y, offset.y))),\n };\n}\n\n/**\n * Turn `-0` into `0`.\n *\n * Clamping a negative offset against a zero maximum yields `-0`, which compares\n * equal to `0` under `===` but not under `Object.is`. Left alone it leaks into\n * state comparisons and into the `translate()` string, so it is normalized once\n * here rather than guarded at every call site.\n */\nfunction normalizeZero(value: number): number {\n return value === 0 ? 0 : value;\n}\n\n/**\n * Map the crop frame back onto the natural-size image.\n *\n * The frame is what the user sees; the export has to read the corresponding\n * region of the *original* pixels, so every on-screen quantity is divided back\n * out by the effective scale. Working in natural pixels — instead of exporting\n * whatever the preview happens to be sized at — is what keeps a 4000 px photo\n * from being downsampled to the width of a 320 px preview.\n *\n * @param params.image - Natural image size.\n * @param params.frame - Crop frame size.\n * @param params.zoom - Zoom multiplier over the cover scale (`1` = cover).\n * @param params.offset - Pan offset in frame pixels.\n * @returns The source rectangle, clamped to the image bounds.\n */\nexport function computeCropRect({\n image,\n frame,\n zoom,\n offset,\n}: {\n image: Size;\n frame: Size;\n zoom: number;\n offset: Offset;\n}): CropRect {\n const scale = coverScale(image, frame) * zoom;\n if (scale <= 0) return { sx: 0, sy: 0, sWidth: 0, sHeight: 0 };\n\n const sWidth = frame.width / scale;\n const sHeight = frame.height / scale;\n\n // A positive offset moves the image right/down on screen, which means the\n // visible region moves left/up within the source — hence the subtraction.\n const centerX = image.width / 2 - offset.x / scale;\n const centerY = image.height / 2 - offset.y / scale;\n\n const sx = Math.max(0, Math.min(image.width - sWidth, centerX - sWidth / 2));\n const sy = Math.max(0, Math.min(image.height - sHeight, centerY - sHeight / 2));\n\n return { sx, sy, sWidth, sHeight };\n}\n\n/**\n * Output size for a crop, honoring an optional cap on the long edge.\n *\n * Exporting at the frame's own size would tie file size to whatever the preview\n * happened to measure. Exporting at full source resolution is right by default,\n * but a 12 MP phone photo cropped for a 96 px avatar is megabytes of waste — so\n * `maxSize` caps the long edge while preserving the aspect ratio.\n *\n * @param crop - The source rectangle being exported.\n * @param maxSize - Cap on the longest output edge, if any.\n * @returns Integer output dimensions, at least 1 px per axis.\n */\nexport function outputSize(crop: CropRect, maxSize?: number): Size {\n const width = crop.sWidth;\n const height = crop.sHeight;\n if (!maxSize || maxSize <= 0 || (width <= maxSize && height <= maxSize)) {\n return { width: Math.max(1, Math.round(width)), height: Math.max(1, Math.round(height)) };\n }\n const ratio = maxSize / Math.max(width, height);\n return {\n width: Math.max(1, Math.round(width * ratio)),\n height: Math.max(1, Math.round(height * ratio)),\n };\n}\n"],"mappings":"AA8BA,
|
|
1
|
+
{"version":3,"file":"crop-geometry.cjs","names":["coverScale","image","frame","maxOffset","displayed","clampOffset","max","normalizeZero","offset","value","computeCropRect","scale","zoom","sWidth","sHeight","centerX","centerY","outputSize","width","crop","height","maxSize","ratio"],"sources":["../../../src/components/ImageCropper/crop-geometry.ts"],"sourcesContent":["/** A width/height pair in pixels. */\nexport interface Size {\n width: number;\n height: number;\n}\n\n/** A pan offset in frame pixels, measured from the centered position. */\nexport interface Offset {\n x: number;\n y: number;\n}\n\n/** The source rectangle to read out of the natural-size image. */\nexport interface CropRect {\n sx: number;\n sy: number;\n sWidth: number;\n sHeight: number;\n}\n\n/**\n * Scale that makes `image` exactly cover `frame` with no empty space.\n *\n * `max` rather than `min`: a crop frame must never show background, so the\n * constraining axis is the one that would leave a gap.\n *\n * @param image - Natural image size.\n * @param frame - Crop frame size.\n * @returns The cover scale, or `0` when either dimension is unusable.\n */\nexport function coverScale(image: Size, frame: Size): number {\n if (image.width <= 0 || image.height <= 0 || frame.width <= 0 || frame.height <= 0) return 0;\n return Math.max(frame.width / image.width, frame.height / image.height);\n}\n\n/**\n * The largest pan offset that keeps the image covering the frame.\n *\n * Zero on an axis means the image is exactly as wide (or tall) as the frame\n * there, so panning along it would expose background.\n *\n * @param displayed - On-screen image size, after scale and zoom.\n * @param frame - Crop frame size.\n * @returns Maximum absolute offset per axis.\n */\nexport function maxOffset(displayed: Size, frame: Size): Offset {\n return {\n x: Math.max(0, (displayed.width - frame.width) / 2),\n y: Math.max(0, (displayed.height - frame.height) / 2),\n };\n}\n\n/**\n * Clamp a pan offset so the frame stays fully covered.\n *\n * This is what stops the single most common defect in a cropper: dragging or\n * zooming until the frame shows empty space, which then bakes transparent or\n * black bands into the exported image.\n *\n * @param offset - Desired offset.\n * @param displayed - On-screen image size, after scale and zoom.\n * @param frame - Crop frame size.\n * @returns The offset, clamped per axis.\n */\nexport function clampOffset(offset: Offset, displayed: Size, frame: Size): Offset {\n const max = maxOffset(displayed, frame);\n return {\n x: normalizeZero(Math.min(max.x, Math.max(-max.x, offset.x))),\n y: normalizeZero(Math.min(max.y, Math.max(-max.y, offset.y))),\n };\n}\n\n/**\n * Turn `-0` into `0`.\n *\n * Clamping a negative offset against a zero maximum yields `-0`, which compares\n * equal to `0` under `===` but not under `Object.is`. Left alone it leaks into\n * state comparisons and into the `translate()` string, so it is normalized once\n * here rather than guarded at every call site.\n */\nfunction normalizeZero(value: number): number {\n return value === 0 ? 0 : value;\n}\n\n/**\n * Map the crop frame back onto the natural-size image.\n *\n * The frame is what the user sees; the export has to read the corresponding\n * region of the *original* pixels, so every on-screen quantity is divided back\n * out by the effective scale. Working in natural pixels — instead of exporting\n * whatever the preview happens to be sized at — is what keeps a 4000 px photo\n * from being downsampled to the width of a 320 px preview.\n *\n * @param params.image - Natural image size.\n * @param params.frame - Crop frame size.\n * @param params.zoom - Zoom multiplier over the cover scale (`1` = cover).\n * @param params.offset - Pan offset in frame pixels.\n * @returns The source rectangle, clamped to the image bounds.\n */\nexport function computeCropRect({\n image,\n frame,\n zoom,\n offset,\n}: {\n image: Size;\n frame: Size;\n zoom: number;\n offset: Offset;\n}): CropRect {\n const scale = coverScale(image, frame) * zoom;\n if (scale <= 0) return { sx: 0, sy: 0, sWidth: 0, sHeight: 0 };\n\n const sWidth = frame.width / scale;\n const sHeight = frame.height / scale;\n\n // A positive offset moves the image right/down on screen, which means the\n // visible region moves left/up within the source — hence the subtraction.\n const centerX = image.width / 2 - offset.x / scale;\n const centerY = image.height / 2 - offset.y / scale;\n\n const sx = Math.max(0, Math.min(image.width - sWidth, centerX - sWidth / 2));\n const sy = Math.max(0, Math.min(image.height - sHeight, centerY - sHeight / 2));\n\n return { sx, sy, sWidth, sHeight };\n}\n\n/**\n * Output size for a crop, honoring an optional cap on the long edge.\n *\n * Exporting at the frame's own size would tie file size to whatever the preview\n * happened to measure. Exporting at full source resolution is right by default,\n * but a 12 MP phone photo cropped for a 96 px avatar is megabytes of waste — so\n * `maxSize` caps the long edge while preserving the aspect ratio.\n *\n * @param crop - The source rectangle being exported.\n * @param maxSize - Cap on the longest output edge, if any.\n * @returns Integer output dimensions, at least 1 px per axis.\n */\nexport function outputSize(crop: CropRect, maxSize?: number): Size {\n const width = crop.sWidth;\n const height = crop.sHeight;\n if (!maxSize || maxSize <= 0 || (width <= maxSize && height <= maxSize)) {\n return { width: Math.max(1, Math.round(width)), height: Math.max(1, Math.round(height)) };\n }\n const ratio = maxSize / Math.max(width, height);\n return {\n width: Math.max(1, Math.round(width * ratio)),\n height: Math.max(1, Math.round(height * ratio)),\n };\n}\n"],"mappings":"AA8BA,SAAgBA,EAAW,EAAa,EAAqB,CAEzD,OADIC,EAAM,OAAS,GAAKA,EAAM,QAAU,GAAKC,EAAM,OAAS,GAAKA,EAAM,QAAU,EAAU,EACpF,KAAK,IAAIA,EAAM,MAAQD,EAAM,MAAOC,EAAM,OAASD,EAAM,MAAM,CAC1E,CAYA,SAAgBE,EAAU,EAAiB,EAAqB,CAC5D,MAAO,CACH,EAAG,KAAK,IAAI,GAAIC,EAAU,MAAQF,EAAM,OAAS,CAAC,EAClD,EAAG,KAAK,IAAI,GAAIE,EAAU,OAASF,EAAM,QAAU,CAAC,CACxD,CACJ,CAcA,SAAgBG,EAAY,EAAgB,EAAiB,EAAqB,CAC9E,IAAMC,EAAMH,EAAUC,EAAWF,CAAK,EACtC,MAAO,CACH,EAAGK,EAAc,KAAK,IAAID,EAAI,EAAG,KAAK,IAAI,CAACA,EAAI,EAAGE,EAAO,CAAC,CAAC,CAAC,EAC5D,EAAGD,EAAc,KAAK,IAAID,EAAI,EAAG,KAAK,IAAI,CAACA,EAAI,EAAGE,EAAO,CAAC,CAAC,CAAC,CAChE,CACJ,CAUA,SAASD,EAAc,EAAuB,CAC1C,OAAOE,IAAU,EAAI,EAAIA,CAC7B,CAiBA,SAAgBC,EAAgB,CAC5B,QACA,QACA,OACA,UAMS,CACT,IAAMC,EAAQX,EAAWC,EAAOC,CAAK,EAAIU,EACzC,GAAID,GAAS,EAAG,MAAO,CAAE,GAAI,EAAG,GAAI,EAAG,OAAQ,EAAG,QAAS,CAAE,EAE7D,IAAME,EAASX,EAAM,MAAQS,EACvBG,EAAUZ,EAAM,OAASS,EAIzBI,EAAUd,EAAM,MAAQ,EAAIO,EAAO,EAAIG,EACvCK,EAAUf,EAAM,OAAS,EAAIO,EAAO,EAAIG,EAK9C,MAAO,CAAE,GAHE,KAAK,IAAI,EAAG,KAAK,IAAIV,EAAM,MAAQY,EAAQE,EAAUF,EAAS,CAAC,CAGjE,EAAI,GAFF,KAAK,IAAI,EAAG,KAAK,IAAIZ,EAAM,OAASa,EAASE,EAAUF,EAAU,CAAC,CAEhE,EAAI,SAAQ,SAAQ,CACrC,CAcA,SAAgBG,EAAW,EAAgB,EAAwB,CAC/D,IAAMC,EAAQC,EAAK,OACbC,EAASD,EAAK,QACpB,GAAI,CAACE,GAAWA,GAAW,GAAMH,GAASG,GAAWD,GAAUC,EAC3D,MAAO,CAAE,MAAO,KAAK,IAAI,EAAG,KAAK,MAAMH,CAAK,CAAC,EAAG,OAAQ,KAAK,IAAI,EAAG,KAAK,MAAME,CAAM,CAAC,CAAE,EAE5F,IAAME,EAAQD,EAAU,KAAK,IAAIH,EAAOE,CAAM,EAC9C,MAAO,CACH,MAAO,KAAK,IAAI,EAAG,KAAK,MAAMF,EAAQI,CAAK,CAAC,EAC5C,OAAQ,KAAK,IAAI,EAAG,KAAK,MAAMF,EAASE,CAAK,CAAC,CAClD,CACJ,C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crop-geometry.js","names":[],"sources":["../../../src/components/ImageCropper/crop-geometry.ts"],"sourcesContent":["/** A width/height pair in pixels. */\nexport interface Size {\n width: number;\n height: number;\n}\n\n/** A pan offset in frame pixels, measured from the centered position. */\nexport interface Offset {\n x: number;\n y: number;\n}\n\n/** The source rectangle to read out of the natural-size image. */\nexport interface CropRect {\n sx: number;\n sy: number;\n sWidth: number;\n sHeight: number;\n}\n\n/**\n * Scale that makes `image` exactly cover `frame` with no empty space.\n *\n * `max` rather than `min`: a crop frame must never show background, so the\n * constraining axis is the one that would leave a gap.\n *\n * @param image - Natural image size.\n * @param frame - Crop frame size.\n * @returns The cover scale, or `0` when either dimension is unusable.\n */\nexport function coverScale(image: Size, frame: Size): number {\n if (image.width <= 0 || image.height <= 0 || frame.width <= 0 || frame.height <= 0) return 0;\n return Math.max(frame.width / image.width, frame.height / image.height);\n}\n\n/**\n * The largest pan offset that keeps the image covering the frame.\n *\n * Zero on an axis means the image is exactly as wide (or tall) as the frame\n * there, so panning along it would expose background.\n *\n * @param displayed - On-screen image size, after scale and zoom.\n * @param frame - Crop frame size.\n * @returns Maximum absolute offset per axis.\n */\nexport function maxOffset(displayed: Size, frame: Size): Offset {\n return {\n x: Math.max(0, (displayed.width - frame.width) / 2),\n y: Math.max(0, (displayed.height - frame.height) / 2),\n };\n}\n\n/**\n * Clamp a pan offset so the frame stays fully covered.\n *\n * This is what stops the single most common defect in a cropper: dragging or\n * zooming until the frame shows empty space, which then bakes transparent or\n * black bands into the exported image.\n *\n * @param offset - Desired offset.\n * @param displayed - On-screen image size, after scale and zoom.\n * @param frame - Crop frame size.\n * @returns The offset, clamped per axis.\n */\nexport function clampOffset(offset: Offset, displayed: Size, frame: Size): Offset {\n const max = maxOffset(displayed, frame);\n return {\n x: normalizeZero(Math.min(max.x, Math.max(-max.x, offset.x))),\n y: normalizeZero(Math.min(max.y, Math.max(-max.y, offset.y))),\n };\n}\n\n/**\n * Turn `-0` into `0`.\n *\n * Clamping a negative offset against a zero maximum yields `-0`, which compares\n * equal to `0` under `===` but not under `Object.is`. Left alone it leaks into\n * state comparisons and into the `translate()` string, so it is normalized once\n * here rather than guarded at every call site.\n */\nfunction normalizeZero(value: number): number {\n return value === 0 ? 0 : value;\n}\n\n/**\n * Map the crop frame back onto the natural-size image.\n *\n * The frame is what the user sees; the export has to read the corresponding\n * region of the *original* pixels, so every on-screen quantity is divided back\n * out by the effective scale. Working in natural pixels — instead of exporting\n * whatever the preview happens to be sized at — is what keeps a 4000 px photo\n * from being downsampled to the width of a 320 px preview.\n *\n * @param params.image - Natural image size.\n * @param params.frame - Crop frame size.\n * @param params.zoom - Zoom multiplier over the cover scale (`1` = cover).\n * @param params.offset - Pan offset in frame pixels.\n * @returns The source rectangle, clamped to the image bounds.\n */\nexport function computeCropRect({\n image,\n frame,\n zoom,\n offset,\n}: {\n image: Size;\n frame: Size;\n zoom: number;\n offset: Offset;\n}): CropRect {\n const scale = coverScale(image, frame) * zoom;\n if (scale <= 0) return { sx: 0, sy: 0, sWidth: 0, sHeight: 0 };\n\n const sWidth = frame.width / scale;\n const sHeight = frame.height / scale;\n\n // A positive offset moves the image right/down on screen, which means the\n // visible region moves left/up within the source — hence the subtraction.\n const centerX = image.width / 2 - offset.x / scale;\n const centerY = image.height / 2 - offset.y / scale;\n\n const sx = Math.max(0, Math.min(image.width - sWidth, centerX - sWidth / 2));\n const sy = Math.max(0, Math.min(image.height - sHeight, centerY - sHeight / 2));\n\n return { sx, sy, sWidth, sHeight };\n}\n\n/**\n * Output size for a crop, honoring an optional cap on the long edge.\n *\n * Exporting at the frame's own size would tie file size to whatever the preview\n * happened to measure. Exporting at full source resolution is right by default,\n * but a 12 MP phone photo cropped for a 96 px avatar is megabytes of waste — so\n * `maxSize` caps the long edge while preserving the aspect ratio.\n *\n * @param crop - The source rectangle being exported.\n * @param maxSize - Cap on the longest output edge, if any.\n * @returns Integer output dimensions, at least 1 px per axis.\n */\nexport function outputSize(crop: CropRect, maxSize?: number): Size {\n const width = crop.sWidth;\n const height = crop.sHeight;\n if (!maxSize || maxSize <= 0 || (width <= maxSize && height <= maxSize)) {\n return { width: Math.max(1, Math.round(width)), height: Math.max(1, Math.round(height)) };\n }\n const ratio = maxSize / Math.max(width, height);\n return {\n width: Math.max(1, Math.round(width * ratio)),\n height: Math.max(1, Math.round(height * ratio)),\n };\n}\n"],"mappings":";AA8BA,
|
|
1
|
+
{"version":3,"file":"crop-geometry.js","names":["coverScale","image","frame","maxOffset","displayed","clampOffset","max","normalizeZero","offset","value","computeCropRect","scale","zoom","sWidth","sHeight","centerX","centerY","outputSize","width","crop","height","maxSize","ratio"],"sources":["../../../src/components/ImageCropper/crop-geometry.ts"],"sourcesContent":["/** A width/height pair in pixels. */\nexport interface Size {\n width: number;\n height: number;\n}\n\n/** A pan offset in frame pixels, measured from the centered position. */\nexport interface Offset {\n x: number;\n y: number;\n}\n\n/** The source rectangle to read out of the natural-size image. */\nexport interface CropRect {\n sx: number;\n sy: number;\n sWidth: number;\n sHeight: number;\n}\n\n/**\n * Scale that makes `image` exactly cover `frame` with no empty space.\n *\n * `max` rather than `min`: a crop frame must never show background, so the\n * constraining axis is the one that would leave a gap.\n *\n * @param image - Natural image size.\n * @param frame - Crop frame size.\n * @returns The cover scale, or `0` when either dimension is unusable.\n */\nexport function coverScale(image: Size, frame: Size): number {\n if (image.width <= 0 || image.height <= 0 || frame.width <= 0 || frame.height <= 0) return 0;\n return Math.max(frame.width / image.width, frame.height / image.height);\n}\n\n/**\n * The largest pan offset that keeps the image covering the frame.\n *\n * Zero on an axis means the image is exactly as wide (or tall) as the frame\n * there, so panning along it would expose background.\n *\n * @param displayed - On-screen image size, after scale and zoom.\n * @param frame - Crop frame size.\n * @returns Maximum absolute offset per axis.\n */\nexport function maxOffset(displayed: Size, frame: Size): Offset {\n return {\n x: Math.max(0, (displayed.width - frame.width) / 2),\n y: Math.max(0, (displayed.height - frame.height) / 2),\n };\n}\n\n/**\n * Clamp a pan offset so the frame stays fully covered.\n *\n * This is what stops the single most common defect in a cropper: dragging or\n * zooming until the frame shows empty space, which then bakes transparent or\n * black bands into the exported image.\n *\n * @param offset - Desired offset.\n * @param displayed - On-screen image size, after scale and zoom.\n * @param frame - Crop frame size.\n * @returns The offset, clamped per axis.\n */\nexport function clampOffset(offset: Offset, displayed: Size, frame: Size): Offset {\n const max = maxOffset(displayed, frame);\n return {\n x: normalizeZero(Math.min(max.x, Math.max(-max.x, offset.x))),\n y: normalizeZero(Math.min(max.y, Math.max(-max.y, offset.y))),\n };\n}\n\n/**\n * Turn `-0` into `0`.\n *\n * Clamping a negative offset against a zero maximum yields `-0`, which compares\n * equal to `0` under `===` but not under `Object.is`. Left alone it leaks into\n * state comparisons and into the `translate()` string, so it is normalized once\n * here rather than guarded at every call site.\n */\nfunction normalizeZero(value: number): number {\n return value === 0 ? 0 : value;\n}\n\n/**\n * Map the crop frame back onto the natural-size image.\n *\n * The frame is what the user sees; the export has to read the corresponding\n * region of the *original* pixels, so every on-screen quantity is divided back\n * out by the effective scale. Working in natural pixels — instead of exporting\n * whatever the preview happens to be sized at — is what keeps a 4000 px photo\n * from being downsampled to the width of a 320 px preview.\n *\n * @param params.image - Natural image size.\n * @param params.frame - Crop frame size.\n * @param params.zoom - Zoom multiplier over the cover scale (`1` = cover).\n * @param params.offset - Pan offset in frame pixels.\n * @returns The source rectangle, clamped to the image bounds.\n */\nexport function computeCropRect({\n image,\n frame,\n zoom,\n offset,\n}: {\n image: Size;\n frame: Size;\n zoom: number;\n offset: Offset;\n}): CropRect {\n const scale = coverScale(image, frame) * zoom;\n if (scale <= 0) return { sx: 0, sy: 0, sWidth: 0, sHeight: 0 };\n\n const sWidth = frame.width / scale;\n const sHeight = frame.height / scale;\n\n // A positive offset moves the image right/down on screen, which means the\n // visible region moves left/up within the source — hence the subtraction.\n const centerX = image.width / 2 - offset.x / scale;\n const centerY = image.height / 2 - offset.y / scale;\n\n const sx = Math.max(0, Math.min(image.width - sWidth, centerX - sWidth / 2));\n const sy = Math.max(0, Math.min(image.height - sHeight, centerY - sHeight / 2));\n\n return { sx, sy, sWidth, sHeight };\n}\n\n/**\n * Output size for a crop, honoring an optional cap on the long edge.\n *\n * Exporting at the frame's own size would tie file size to whatever the preview\n * happened to measure. Exporting at full source resolution is right by default,\n * but a 12 MP phone photo cropped for a 96 px avatar is megabytes of waste — so\n * `maxSize` caps the long edge while preserving the aspect ratio.\n *\n * @param crop - The source rectangle being exported.\n * @param maxSize - Cap on the longest output edge, if any.\n * @returns Integer output dimensions, at least 1 px per axis.\n */\nexport function outputSize(crop: CropRect, maxSize?: number): Size {\n const width = crop.sWidth;\n const height = crop.sHeight;\n if (!maxSize || maxSize <= 0 || (width <= maxSize && height <= maxSize)) {\n return { width: Math.max(1, Math.round(width)), height: Math.max(1, Math.round(height)) };\n }\n const ratio = maxSize / Math.max(width, height);\n return {\n width: Math.max(1, Math.round(width * ratio)),\n height: Math.max(1, Math.round(height * ratio)),\n };\n}\n"],"mappings":";AA8BA,SAAgBA,EAAW,GAAa,GAAqB;CAEzD,OADIC,EAAM,SAAS,KAAKA,EAAM,UAAU,KAAKC,EAAM,SAAS,KAAKA,EAAM,UAAU,IAAU,IACpF,KAAK,IAAIA,EAAM,QAAQD,EAAM,OAAOC,EAAM,SAASD,EAAM,MAAM;AAC1E;AAYA,SAAgBE,EAAU,GAAiB,GAAqB;CAC5D,OAAO;EACH,GAAG,KAAK,IAAI,IAAIC,EAAU,QAAQF,EAAM,SAAS,CAAC;EAClD,GAAG,KAAK,IAAI,IAAIE,EAAU,SAASF,EAAM,UAAU,CAAC;CACxD;AACJ;AAcA,SAAgBG,EAAY,GAAgB,GAAiB,GAAqB;CAC9E,IAAMC,IAAMH,EAAUC,GAAWF,CAAK;CACtC,OAAO;EACH,GAAGK,EAAc,KAAK,IAAID,EAAI,GAAG,KAAK,IAAI,CAACA,EAAI,GAAGE,EAAO,CAAC,CAAC,CAAC;EAC5D,GAAGD,EAAc,KAAK,IAAID,EAAI,GAAG,KAAK,IAAI,CAACA,EAAI,GAAGE,EAAO,CAAC,CAAC,CAAC;CAChE;AACJ;AAUA,SAASD,EAAc,GAAuB;CAC1C,OAAOE,MAAU,IAAI,IAAIA;AAC7B;AAiBA,SAAgBC,EAAgB,EAC5B,UACA,UACA,SACA,aAMS;CACT,IAAMC,IAAQX,EAAWC,GAAOC,CAAK,IAAIU;CACzC,IAAID,KAAS,GAAG,OAAO;EAAE,IAAI;EAAG,IAAI;EAAG,QAAQ;EAAG,SAAS;CAAE;CAE7D,IAAME,IAASX,EAAM,QAAQS,GACvBG,IAAUZ,EAAM,SAASS,GAIzBI,IAAUd,EAAM,QAAQ,IAAIO,EAAO,IAAIG,GACvCK,IAAUf,EAAM,SAAS,IAAIO,EAAO,IAAIG;CAK9C,OAAO;EAAE,IAHE,KAAK,IAAI,GAAG,KAAK,IAAIV,EAAM,QAAQY,GAAQE,IAAUF,IAAS,CAAC,CAGjE;EAAI,IAFF,KAAK,IAAI,GAAG,KAAK,IAAIZ,EAAM,SAASa,GAASE,IAAUF,IAAU,CAAC,CAEhE;EAAI;EAAQ;CAAQ;AACrC;AAcA,SAAgBG,EAAW,GAAgB,GAAwB;CAC/D,IAAMC,IAAQC,EAAK,QACbC,IAASD,EAAK;CACpB,IAAI,CAACE,KAAWA,KAAW,KAAMH,KAASG,KAAWD,KAAUC,GAC3D,OAAO;EAAE,OAAO,KAAK,IAAI,GAAG,KAAK,MAAMH,CAAK,CAAC;EAAG,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAME,CAAM,CAAC;CAAE;CAE5F,IAAME,IAAQD,IAAU,KAAK,IAAIH,GAAOE,CAAM;CAC9C,OAAO;EACH,OAAO,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAQI,CAAK,CAAC;EAC5C,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAMF,IAASE,CAAK,CAAC;CAClD;AACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.cjs","names":[],"sources":["../../../src/components/Input/Input.tsx"],"sourcesContent":["import { forwardRef, useId } from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Input.module.css\";\n\nexport type InputSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"size\"> {\n label?: string;\n helperText?: string;\n error?: string;\n leftIcon?: ReactNode;\n rightIcon?: ReactNode;\n wrapperClassName?: string;\n /** Visual size — drives height, padding and font via density-aware tokens. */\n size?: InputSize;\n}\n\n/**\n * Labelled text input with helper/error slots and optional adornment icons.\n * Forwards refs to the underlying `<input>` for integration with form libraries.\n */\nexport const Input = forwardRef<HTMLInputElement, InputProps>(function Input(\n {\n label,\n helperText,\n error,\n leftIcon,\n rightIcon,\n wrapperClassName,\n className,\n id,\n required,\n size = \"md\",\n ...props\n },\n ref,\n) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const describedById = error ? `${inputId}-error` : helperText ? `${inputId}-helper` : undefined;\n const sizeClass = size === \"sm\" ? styles.sizeSm : size === \"lg\" ? styles.sizeLg : styles.sizeMd;\n\n return (\n <div className={cn(styles.wrapper, error && styles.error, wrapperClassName)}>\n {label && (\n <label htmlFor={inputId} className={styles.label}>\n {label}\n {required && <span className={styles.required}>*</span>}\n </label>\n )}\n <div className={styles.field}>\n {leftIcon && <span className={styles.iconLeft}>{leftIcon}</span>}\n <input\n ref={ref}\n id={inputId}\n aria-invalid={!!error}\n aria-describedby={describedById}\n required={required}\n className={cn(\n styles.input,\n sizeClass,\n leftIcon && styles.hasLeftIcon,\n rightIcon && styles.hasRightIcon,\n className,\n )}\n {...props}\n />\n {rightIcon && <span className={styles.iconRight}>{rightIcon}</span>}\n </div>\n {error ? (\n <span id={`${inputId}-error`} className={styles.errorText}>\n {error}\n </span>\n ) : helperText ? (\n <span id={`${inputId}-helper`} className={styles.helper}>\n {helperText}\n </span>\n ) : null}\n </div>\n );\n});\n"],"mappings":"4HAsBA,
|
|
1
|
+
{"version":3,"file":"Input.cjs","names":["forwardRef","useId","styles","cn","require_cn","require_Input_module","react","react_jsx_runtime","Input","props","generatedId","inputId","id","describedById","error","helperText","sizeClass","size","wrapperClassName","label","required","leftIcon","rightIcon","className"],"sources":["../../../src/components/Input/Input.tsx"],"sourcesContent":["import { forwardRef, useId } from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Input.module.css\";\n\nexport type InputSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"size\"> {\n label?: string;\n helperText?: string;\n error?: string;\n leftIcon?: ReactNode;\n rightIcon?: ReactNode;\n wrapperClassName?: string;\n /** Visual size — drives height, padding and font via density-aware tokens. */\n size?: InputSize;\n}\n\n/**\n * Labelled text input with helper/error slots and optional adornment icons.\n * Forwards refs to the underlying `<input>` for integration with form libraries.\n */\nexport const Input = forwardRef<HTMLInputElement, InputProps>(function Input(\n {\n label,\n helperText,\n error,\n leftIcon,\n rightIcon,\n wrapperClassName,\n className,\n id,\n required,\n size = \"md\",\n ...props\n },\n ref,\n) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const describedById = error ? `${inputId}-error` : helperText ? `${inputId}-helper` : undefined;\n const sizeClass = size === \"sm\" ? styles.sizeSm : size === \"lg\" ? styles.sizeLg : styles.sizeMd;\n\n return (\n <div className={cn(styles.wrapper, error && styles.error, wrapperClassName)}>\n {label && (\n <label htmlFor={inputId} className={styles.label}>\n {label}\n {required && <span className={styles.required}>*</span>}\n </label>\n )}\n <div className={styles.field}>\n {leftIcon && <span className={styles.iconLeft}>{leftIcon}</span>}\n <input\n ref={ref}\n id={inputId}\n aria-invalid={!!error}\n aria-describedby={describedById}\n required={required}\n className={cn(\n styles.input,\n sizeClass,\n leftIcon && styles.hasLeftIcon,\n rightIcon && styles.hasRightIcon,\n className,\n )}\n {...props}\n />\n {rightIcon && <span className={styles.iconRight}>{rightIcon}</span>}\n </div>\n {error ? (\n <span id={`${inputId}-error`} className={styles.errorText}>\n {error}\n </span>\n ) : helperText ? (\n <span id={`${inputId}-helper`} className={styles.helper}>\n {helperText}\n </span>\n ) : null}\n </div>\n );\n});\n"],"mappings":"A,4HAsBA,IAAaQ,GAAA,EAAQR,EAAAA,WAAAA,CAAyC,SAC1D,CACI,QACA,aACA,QACA,WACA,YACA,mBACA,YACA,KACA,WACA,OAAO,KACP,GAAGS,GAEP,EACF,CACE,IAAMC,GAAA,EAAcT,EAAAA,MAAAA,CAAM,EACpBU,EAAUC,GAAMF,EAChBG,EAAgBC,EAAQ,GAAGH,EAAQ,QAAUI,EAAa,GAAGJ,EAAQ,SAAW,IAAA,GAChFK,EAAYC,IAAS,KAAOf,EAAAA,QAAO,OAASe,IAAS,KAAOf,EAAAA,QAAO,OAASA,EAAAA,QAAO,OAEzF,OACI,EAAAK,EAAA,KAAA,CAAC,MAAD,CAAK,UAAWJ,EAAAA,GAAGD,EAAAA,QAAO,QAASY,GAASZ,EAAAA,QAAO,MAAOgB,CAAgB,EAA1E,SAAA,CACKC,IACG,EAAAZ,EAAA,KAAA,CAAC,QAAD,CAAO,QAASI,EAAS,UAAWT,EAAAA,QAAO,MAA3C,SAAA,CACKiB,EACAC,IAAY,EAAAb,EAAA,IAAA,CAAC,OAAD,CAAM,UAAWL,EAAAA,QAAO,SAAU,SAAA,GAAO,CAAA,CACnD,C,IAEX,EAAAK,EAAA,KAAA,CAAC,MAAD,CAAK,UAAWL,EAAAA,QAAO,MAAvB,SAAA,CACKmB,IAAY,EAAAd,EAAA,IAAA,CAAC,OAAD,CAAM,UAAWL,EAAAA,QAAO,SAAW,SAAAmB,CAAe,CAAA,GAC/D,EAAAd,EAAA,IAAA,CAAC,QAAD,CACS,MACL,GAAII,EACJ,eAAc,CAAC,CAACG,EAChB,mBAAkBD,EACR,WACV,UAAWV,EAAAA,GACPD,EAAAA,QAAO,MACPc,EACAK,GAAYnB,EAAAA,QAAO,YACnBoB,GAAapB,EAAAA,QAAO,aACpBqB,CACJ,EACA,GAAId,CACP,CAAA,EACAa,IAAa,EAAAf,EAAA,IAAA,CAAC,OAAD,CAAM,UAAWL,EAAAA,QAAO,UAAY,SAAAoB,CAAgB,CAAA,CACjE,C,GACJR,GACG,EAAAP,EAAA,IAAA,CAAC,OAAD,CAAM,GAAI,GAAGI,EAAQ,QAAS,UAAWT,EAAAA,QAAO,UAC3C,SAAAY,CACC,CAAA,EACNC,GACA,EAAAR,EAAA,IAAA,CAAC,OAAD,CAAM,GAAI,GAAGI,EAAQ,SAAU,UAAWT,EAAAA,QAAO,OAC5C,SAAAa,CACC,CAAA,EACN,IACH,C,EAEb,CAAC,E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.js","names":[],"sources":["../../../src/components/Input/Input.tsx"],"sourcesContent":["import { forwardRef, useId } from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Input.module.css\";\n\nexport type InputSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"size\"> {\n label?: string;\n helperText?: string;\n error?: string;\n leftIcon?: ReactNode;\n rightIcon?: ReactNode;\n wrapperClassName?: string;\n /** Visual size — drives height, padding and font via density-aware tokens. */\n size?: InputSize;\n}\n\n/**\n * Labelled text input with helper/error slots and optional adornment icons.\n * Forwards refs to the underlying `<input>` for integration with form libraries.\n */\nexport const Input = forwardRef<HTMLInputElement, InputProps>(function Input(\n {\n label,\n helperText,\n error,\n leftIcon,\n rightIcon,\n wrapperClassName,\n className,\n id,\n required,\n size = \"md\",\n ...props\n },\n ref,\n) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const describedById = error ? `${inputId}-error` : helperText ? `${inputId}-helper` : undefined;\n const sizeClass = size === \"sm\" ? styles.sizeSm : size === \"lg\" ? styles.sizeLg : styles.sizeMd;\n\n return (\n <div className={cn(styles.wrapper, error && styles.error, wrapperClassName)}>\n {label && (\n <label htmlFor={inputId} className={styles.label}>\n {label}\n {required && <span className={styles.required}>*</span>}\n </label>\n )}\n <div className={styles.field}>\n {leftIcon && <span className={styles.iconLeft}>{leftIcon}</span>}\n <input\n ref={ref}\n id={inputId}\n aria-invalid={!!error}\n aria-describedby={describedById}\n required={required}\n className={cn(\n styles.input,\n sizeClass,\n leftIcon && styles.hasLeftIcon,\n rightIcon && styles.hasRightIcon,\n className,\n )}\n {...props}\n />\n {rightIcon && <span className={styles.iconRight}>{rightIcon}</span>}\n </div>\n {error ? (\n <span id={`${inputId}-error`} className={styles.errorText}>\n {error}\n </span>\n ) : helperText ? (\n <span id={`${inputId}-helper`} className={styles.helper}>\n {helperText}\n </span>\n ) : null}\n </div>\n );\n});\n"],"mappings":";;;;;AAsBA,
|
|
1
|
+
{"version":3,"file":"Input.js","names":["styles","Input_module_default","Input","forwardRef","props","generatedId","useId","inputId","id","describedById","error","helperText","sizeClass","size","cn","wrapperClassName","label","required","leftIcon","rightIcon","className"],"sources":["../../../src/components/Input/Input.tsx"],"sourcesContent":["import { forwardRef, useId } from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Input.module.css\";\n\nexport type InputSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"size\"> {\n label?: string;\n helperText?: string;\n error?: string;\n leftIcon?: ReactNode;\n rightIcon?: ReactNode;\n wrapperClassName?: string;\n /** Visual size — drives height, padding and font via density-aware tokens. */\n size?: InputSize;\n}\n\n/**\n * Labelled text input with helper/error slots and optional adornment icons.\n * Forwards refs to the underlying `<input>` for integration with form libraries.\n */\nexport const Input = forwardRef<HTMLInputElement, InputProps>(function Input(\n {\n label,\n helperText,\n error,\n leftIcon,\n rightIcon,\n wrapperClassName,\n className,\n id,\n required,\n size = \"md\",\n ...props\n },\n ref,\n) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const describedById = error ? `${inputId}-error` : helperText ? `${inputId}-helper` : undefined;\n const sizeClass = size === \"sm\" ? styles.sizeSm : size === \"lg\" ? styles.sizeLg : styles.sizeMd;\n\n return (\n <div className={cn(styles.wrapper, error && styles.error, wrapperClassName)}>\n {label && (\n <label htmlFor={inputId} className={styles.label}>\n {label}\n {required && <span className={styles.required}>*</span>}\n </label>\n )}\n <div className={styles.field}>\n {leftIcon && <span className={styles.iconLeft}>{leftIcon}</span>}\n <input\n ref={ref}\n id={inputId}\n aria-invalid={!!error}\n aria-describedby={describedById}\n required={required}\n className={cn(\n styles.input,\n sizeClass,\n leftIcon && styles.hasLeftIcon,\n rightIcon && styles.hasRightIcon,\n className,\n )}\n {...props}\n />\n {rightIcon && <span className={styles.iconRight}>{rightIcon}</span>}\n </div>\n {error ? (\n <span id={`${inputId}-error`} className={styles.errorText}>\n {error}\n </span>\n ) : helperText ? (\n <span id={`${inputId}-helper`} className={styles.helper}>\n {helperText}\n </span>\n ) : null}\n </div>\n );\n});\n"],"mappings":";;;;;AAsBA,IAAaE,IAAQC,EAAyC,SAC1D,EACI,UACA,eACA,UACA,aACA,cACA,qBACA,cACA,OACA,aACA,UAAO,MACP,GAAGC,KAEP,GACF;CACE,IAAMC,IAAcC,EAAM,GACpBC,IAAUC,KAAMH,GAChBI,IAAgBC,IAAQ,GAAGH,EAAQ,UAAUI,IAAa,GAAGJ,EAAQ,WAAW,KAAA,GAChFK,IAAYC,MAAS,OAAOb,EAAO,SAASa,MAAS,OAAOb,EAAO,SAASA,EAAO;CAEzF,OACI,kBAAC,OAAD;EAAK,WAAWc,EAAGd,EAAO,SAASU,KAASV,EAAO,OAAOe,CAAgB;EAA1E,UAAA;GACKC,KACG,kBAAC,SAAD;IAAO,SAAST;IAAS,WAAWP,EAAO;IAA3C,UAAA,CACKgB,GACAC,KAAY,kBAAC,QAAD;KAAM,WAAWjB,EAAO;KAAU,UAAA;IAAO,CAAA,CACnD;;GAEX,kBAAC,OAAD;IAAK,WAAWA,EAAO;IAAvB,UAAA;KACKkB,KAAY,kBAAC,QAAD;MAAM,WAAWlB,EAAO;MAAW,UAAAkB;KAAe,CAAA;KAC/D,kBAAC,SAAD;MACS;MACL,IAAIX;MACJ,gBAAc,CAAC,CAACG;MAChB,oBAAkBD;MACR;MACV,WAAWK,EACPd,EAAO,OACPY,GACAM,KAAYlB,EAAO,aACnBmB,KAAanB,EAAO,cACpBoB,CACJ;MACA,GAAIhB;KACP,CAAA;KACAe,KAAa,kBAAC,QAAD;MAAM,WAAWnB,EAAO;MAAY,UAAAmB;KAAgB,CAAA;IACjE;;GACJT,IACG,kBAAC,QAAD;IAAM,IAAI,GAAGH,EAAQ;IAAS,WAAWP,EAAO;IAC3C,UAAAU;GACC,CAAA,IACNC,IACA,kBAAC,QAAD;IAAM,IAAI,GAAGJ,EAAQ;IAAU,WAAWP,EAAO;IAC5C,UAAAW;GACC,CAAA,IACN;EACH;;AAEb,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.module.cjs","names":[],"sources":["../../../src/components/Input/Input.module.css"],"sourcesContent":[".wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--tempest-space-1);\n width: 100%;\n}\n\n.label {\n font-size: var(--tempest-text-sm);\n font-weight: var(--tempest-weight-semibold);\n color: var(--tempest-text);\n line-height: var(--tempest-leading-snug);\n}\n\n.required {\n color: var(--tempest-danger);\n margin-left: 2px;\n}\n\n.field {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.input {\n width: 100%;\n height: var(--tempest-control-height-md);\n padding: 0 var(--tempest-control-padding-md);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-control-radius);\n background-color: var(--tempest-bg);\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-control-font-md);\n line-height: var(--tempest-leading-snug);\n box-shadow: var(--tempest-shadow-xs);\n transition: var(--tempest-transition-color), var(--tempest-transition-shadow);\n}\n\n.input::placeholder {\n color: var(--tempest-text-subtle);\n}\n\n.input:hover:not(:disabled):not(:focus) {\n border-color: var(--tempest-border-strong);\n}\n\n.input:focus {\n outline: none;\n border-color: var(--tempest-primary);\n box-shadow: 0 0 0 var(--tempest-focus-ring-width) var(--tempest-focus-ring-color);\n}\n\n.input:disabled {\n background-color: var(--tempest-surface);\n cursor: not-allowed;\n color: var(--tempest-text-muted);\n box-shadow: none;\n}\n\n.input:read-only {\n background-color: var(--tempest-surface);\n}\n\n/* Sizes — density-aware. Applied directly on the <input>. */\n.sizeSm {\n height: var(--tempest-control-height-sm);\n padding: 0 var(--tempest-control-padding-sm);\n font-size: var(--tempest-control-font-sm);\n}\n.sizeMd {\n height: var(--tempest-control-height-md);\n padding: 0 var(--tempest-control-padding-md);\n font-size: var(--tempest-control-font-md);\n}\n.sizeLg {\n height: var(--tempest-control-height-lg);\n padding: 0 var(--tempest-control-padding-lg);\n font-size: var(--tempest-control-font-lg);\n}\n\n.hasLeftIcon {\n padding-left: 36px;\n}\n\n.hasRightIcon {\n padding-right: 36px;\n}\n\n.iconLeft,\n.iconRight {\n position: absolute;\n display: flex;\n align-items: center;\n color: var(--tempest-text-muted);\n pointer-events: none;\n}\n\n/*\n * Decorative icons let clicks fall through to the input, but interactive\n * adornments (a clear/reveal/save button passed as leftIcon/rightIcon) must\n * stay clickable — re-enable pointer events on the slot's children.\n */\n.iconLeft > *,\n.iconRight > * {\n pointer-events: auto;\n}\n\n.iconLeft {\n left: 12px;\n}\n\n.iconRight {\n right: 12px;\n}\n\n.error .input {\n border-color: var(--tempest-danger);\n}\n\n.error .input:focus {\n box-shadow: 0 0 0 var(--tempest-focus-ring-width)\n color-mix(in srgb, var(--tempest-danger) 25%, transparent);\n}\n\n.helper {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-text-muted);\n line-height: var(--tempest-leading-snug);\n}\n\n.errorText {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-danger);\n line-height: var(--tempest-leading-snug);\n}\n"],"mappings":";"}
|
|
1
|
+
{"version":3,"file":"Input.module.cjs","names":["wrapper","label","required","field","input","sizeSm","sizeMd","sizeLg","hasLeftIcon","hasRightIcon","iconLeft","iconRight","error","helper","errorText","Input_module_default"],"sources":["../../../src/components/Input/Input.module.css"],"sourcesContent":[".wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--tempest-space-1);\n width: 100%;\n}\n\n.label {\n font-size: var(--tempest-text-sm);\n font-weight: var(--tempest-weight-semibold);\n color: var(--tempest-text);\n line-height: var(--tempest-leading-snug);\n}\n\n.required {\n color: var(--tempest-danger);\n margin-left: 2px;\n}\n\n.field {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.input {\n width: 100%;\n height: var(--tempest-control-height-md);\n padding: 0 var(--tempest-control-padding-md);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-control-radius);\n background-color: var(--tempest-bg);\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-control-font-md);\n line-height: var(--tempest-leading-snug);\n box-shadow: var(--tempest-shadow-xs);\n transition: var(--tempest-transition-color), var(--tempest-transition-shadow);\n}\n\n.input::placeholder {\n color: var(--tempest-text-subtle);\n}\n\n.input:hover:not(:disabled):not(:focus) {\n border-color: var(--tempest-border-strong);\n}\n\n.input:focus {\n outline: none;\n border-color: var(--tempest-primary);\n box-shadow: 0 0 0 var(--tempest-focus-ring-width) var(--tempest-focus-ring-color);\n}\n\n.input:disabled {\n background-color: var(--tempest-surface);\n cursor: not-allowed;\n color: var(--tempest-text-muted);\n box-shadow: none;\n}\n\n.input:read-only {\n background-color: var(--tempest-surface);\n}\n\n/* Sizes — density-aware. Applied directly on the <input>. */\n.sizeSm {\n height: var(--tempest-control-height-sm);\n padding: 0 var(--tempest-control-padding-sm);\n font-size: var(--tempest-control-font-sm);\n}\n.sizeMd {\n height: var(--tempest-control-height-md);\n padding: 0 var(--tempest-control-padding-md);\n font-size: var(--tempest-control-font-md);\n}\n.sizeLg {\n height: var(--tempest-control-height-lg);\n padding: 0 var(--tempest-control-padding-lg);\n font-size: var(--tempest-control-font-lg);\n}\n\n.hasLeftIcon {\n padding-left: 36px;\n}\n\n.hasRightIcon {\n padding-right: 36px;\n}\n\n.iconLeft,\n.iconRight {\n position: absolute;\n display: flex;\n align-items: center;\n color: var(--tempest-text-muted);\n pointer-events: none;\n}\n\n/*\n * Decorative icons let clicks fall through to the input, but interactive\n * adornments (a clear/reveal/save button passed as leftIcon/rightIcon) must\n * stay clickable — re-enable pointer events on the slot's children.\n */\n.iconLeft > *,\n.iconRight > * {\n pointer-events: auto;\n}\n\n.iconLeft {\n left: 12px;\n}\n\n.iconRight {\n right: 12px;\n}\n\n.error .input {\n border-color: var(--tempest-danger);\n}\n\n.error .input:focus {\n box-shadow: 0 0 0 var(--tempest-focus-ring-width)\n color-mix(in srgb, var(--tempest-danger) 25%, transparent);\n}\n\n.helper {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-text-muted);\n line-height: var(--tempest-leading-snug);\n}\n\n.errorText {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-danger);\n line-height: var(--tempest-leading-snug);\n}\n"],"mappings":";"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.module.js","names":[],"sources":["../../../src/components/Input/Input.module.css"],"sourcesContent":[".wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--tempest-space-1);\n width: 100%;\n}\n\n.label {\n font-size: var(--tempest-text-sm);\n font-weight: var(--tempest-weight-semibold);\n color: var(--tempest-text);\n line-height: var(--tempest-leading-snug);\n}\n\n.required {\n color: var(--tempest-danger);\n margin-left: 2px;\n}\n\n.field {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.input {\n width: 100%;\n height: var(--tempest-control-height-md);\n padding: 0 var(--tempest-control-padding-md);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-control-radius);\n background-color: var(--tempest-bg);\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-control-font-md);\n line-height: var(--tempest-leading-snug);\n box-shadow: var(--tempest-shadow-xs);\n transition: var(--tempest-transition-color), var(--tempest-transition-shadow);\n}\n\n.input::placeholder {\n color: var(--tempest-text-subtle);\n}\n\n.input:hover:not(:disabled):not(:focus) {\n border-color: var(--tempest-border-strong);\n}\n\n.input:focus {\n outline: none;\n border-color: var(--tempest-primary);\n box-shadow: 0 0 0 var(--tempest-focus-ring-width) var(--tempest-focus-ring-color);\n}\n\n.input:disabled {\n background-color: var(--tempest-surface);\n cursor: not-allowed;\n color: var(--tempest-text-muted);\n box-shadow: none;\n}\n\n.input:read-only {\n background-color: var(--tempest-surface);\n}\n\n/* Sizes — density-aware. Applied directly on the <input>. */\n.sizeSm {\n height: var(--tempest-control-height-sm);\n padding: 0 var(--tempest-control-padding-sm);\n font-size: var(--tempest-control-font-sm);\n}\n.sizeMd {\n height: var(--tempest-control-height-md);\n padding: 0 var(--tempest-control-padding-md);\n font-size: var(--tempest-control-font-md);\n}\n.sizeLg {\n height: var(--tempest-control-height-lg);\n padding: 0 var(--tempest-control-padding-lg);\n font-size: var(--tempest-control-font-lg);\n}\n\n.hasLeftIcon {\n padding-left: 36px;\n}\n\n.hasRightIcon {\n padding-right: 36px;\n}\n\n.iconLeft,\n.iconRight {\n position: absolute;\n display: flex;\n align-items: center;\n color: var(--tempest-text-muted);\n pointer-events: none;\n}\n\n/*\n * Decorative icons let clicks fall through to the input, but interactive\n * adornments (a clear/reveal/save button passed as leftIcon/rightIcon) must\n * stay clickable — re-enable pointer events on the slot's children.\n */\n.iconLeft > *,\n.iconRight > * {\n pointer-events: auto;\n}\n\n.iconLeft {\n left: 12px;\n}\n\n.iconRight {\n right: 12px;\n}\n\n.error .input {\n border-color: var(--tempest-danger);\n}\n\n.error .input:focus {\n box-shadow: 0 0 0 var(--tempest-focus-ring-width)\n color-mix(in srgb, var(--tempest-danger) 25%, transparent);\n}\n\n.helper {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-text-muted);\n line-height: var(--tempest-leading-snug);\n}\n\n.errorText {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-danger);\n line-height: var(--tempest-leading-snug);\n}\n"],"mappings":";"}
|
|
1
|
+
{"version":3,"file":"Input.module.js","names":["wrapper","label","required","field","input","sizeSm","sizeMd","sizeLg","hasLeftIcon","hasRightIcon","iconLeft","iconRight","error","helper","errorText","Input_module_default"],"sources":["../../../src/components/Input/Input.module.css"],"sourcesContent":[".wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--tempest-space-1);\n width: 100%;\n}\n\n.label {\n font-size: var(--tempest-text-sm);\n font-weight: var(--tempest-weight-semibold);\n color: var(--tempest-text);\n line-height: var(--tempest-leading-snug);\n}\n\n.required {\n color: var(--tempest-danger);\n margin-left: 2px;\n}\n\n.field {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.input {\n width: 100%;\n height: var(--tempest-control-height-md);\n padding: 0 var(--tempest-control-padding-md);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-control-radius);\n background-color: var(--tempest-bg);\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-control-font-md);\n line-height: var(--tempest-leading-snug);\n box-shadow: var(--tempest-shadow-xs);\n transition: var(--tempest-transition-color), var(--tempest-transition-shadow);\n}\n\n.input::placeholder {\n color: var(--tempest-text-subtle);\n}\n\n.input:hover:not(:disabled):not(:focus) {\n border-color: var(--tempest-border-strong);\n}\n\n.input:focus {\n outline: none;\n border-color: var(--tempest-primary);\n box-shadow: 0 0 0 var(--tempest-focus-ring-width) var(--tempest-focus-ring-color);\n}\n\n.input:disabled {\n background-color: var(--tempest-surface);\n cursor: not-allowed;\n color: var(--tempest-text-muted);\n box-shadow: none;\n}\n\n.input:read-only {\n background-color: var(--tempest-surface);\n}\n\n/* Sizes — density-aware. Applied directly on the <input>. */\n.sizeSm {\n height: var(--tempest-control-height-sm);\n padding: 0 var(--tempest-control-padding-sm);\n font-size: var(--tempest-control-font-sm);\n}\n.sizeMd {\n height: var(--tempest-control-height-md);\n padding: 0 var(--tempest-control-padding-md);\n font-size: var(--tempest-control-font-md);\n}\n.sizeLg {\n height: var(--tempest-control-height-lg);\n padding: 0 var(--tempest-control-padding-lg);\n font-size: var(--tempest-control-font-lg);\n}\n\n.hasLeftIcon {\n padding-left: 36px;\n}\n\n.hasRightIcon {\n padding-right: 36px;\n}\n\n.iconLeft,\n.iconRight {\n position: absolute;\n display: flex;\n align-items: center;\n color: var(--tempest-text-muted);\n pointer-events: none;\n}\n\n/*\n * Decorative icons let clicks fall through to the input, but interactive\n * adornments (a clear/reveal/save button passed as leftIcon/rightIcon) must\n * stay clickable — re-enable pointer events on the slot's children.\n */\n.iconLeft > *,\n.iconRight > * {\n pointer-events: auto;\n}\n\n.iconLeft {\n left: 12px;\n}\n\n.iconRight {\n right: 12px;\n}\n\n.error .input {\n border-color: var(--tempest-danger);\n}\n\n.error .input:focus {\n box-shadow: 0 0 0 var(--tempest-focus-ring-width)\n color-mix(in srgb, var(--tempest-danger) 25%, transparent);\n}\n\n.helper {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-text-muted);\n line-height: var(--tempest-leading-snug);\n}\n\n.errorText {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-danger);\n line-height: var(--tempest-leading-snug);\n}\n"],"mappings":";"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstallBanner.cjs","names":[],"sources":["../../../src/components/InstallBanner/InstallBanner.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — title, description, installLabel and dismissLabel\n * are four strings the app has to write, icon and className the look, storageKey the\n * dismissal memory and onResult the outcome. An install prompt with SDK-authored\n * copy is the one thing nobody ships.\n */\nimport { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"@/utils/cn\";\nimport { Button } from \"@/components/Button\";\nimport { useInstallPrompt } from \"@/hooks/use-install-prompt\";\nimport { defaultInstallHint } from \"@/components/InstallButton/install-hints\";\nimport type { RenderInstallHint } from \"@/components/InstallButton/install-hints\";\nimport type { InstallOutcome } from \"@/components/InstallButton\";\nimport styles from \"./InstallBanner.module.css\";\n\nexport interface InstallBannerProps {\n /** Headline. Default `\"Instale o app\"`. */\n title?: ReactNode;\n /** Supporting copy under the title. */\n description?: ReactNode;\n /** Install button label. Default `\"Instalar\"`. */\n installLabel?: string;\n /** Accessible label for the dismiss button. Default `\"Dispensar\"`. */\n dismissLabel?: string;\n /** Optional leading icon. */\n icon?: ReactNode;\n /**\n * `localStorage` key used to remember dismissal across reloads. Omit to\n * make dismissal last only for the current session (component state).\n */\n storageKey?: string;\n /**\n * How long, in ms, a dismissal lasts before the banner may return.\n *\n * Omitted, a dismissal written to `storageKey` is permanent, which is what\n * the component always did and what a stored `\"1\"` keeps meaning. With a\n * cooldown the dismissal is stored as a timestamp instead, so the banner\n * comes back after the window — the same shape `useInstallPrompt` uses for\n * its own decline.\n */\n declineCooldownMs?: number;\n /**\n * Install button label used when the browser cannot be prompted and the\n * banner shows the manual instruction. Default `\"Como instalar\"`.\n */\n hintLabel?: string;\n /**\n * Replaces the instruction shown for the `\"ios\"` and `\"manual\"` methods.\n *\n * The default copy is in PT-BR and names the real menu entries.\n */\n renderHint?: RenderInstallHint;\n /**\n * How long, in ms, to wait for `beforeinstallprompt` before falling back to\n * the manual instruction. Forwarded to {@link useInstallPrompt}; defaults to\n * 3000 there.\n */\n manualFallbackDelayMs?: number;\n /** Called with the user's choice after the install prompt resolves. */\n onResult?: (outcome: InstallOutcome) => void;\n className?: string;\n}\n\n/**\n * Whether the user already dismissed this banner.\n *\n * Two stored shapes, and both have to keep working: `\"1\"` is the permanent\n * dismissal the component has always written, and a timestamp is what a banner\n * with `declineCooldownMs` writes. A `\"1\"` found while a cooldown is configured\n * still counts as dismissed forever — it was written under the old contract, and\n * reviving a banner the user turned off is worse than keeping it off.\n *\n * @param storageKey - The key holding the dismissal, if any.\n * @param declineCooldownMs - How long a timestamped dismissal lasts.\n * @returns Whether the banner should stay hidden.\n */\nfunction readDismissed(storageKey?: string, declineCooldownMs?: number): boolean {\n if (!storageKey || typeof window === \"undefined\") return false;\n try {\n const raw = window.localStorage.getItem(storageKey);\n if (!raw) return false;\n if (raw === \"1\") return true;\n const dismissedAt = Number(raw);\n if (!Number.isFinite(dismissedAt)) return false;\n if (declineCooldownMs === undefined) return true;\n return Date.now() - dismissedAt < declineCooldownMs;\n } catch {\n return false;\n }\n}\n\n/**\n * Dismissible bottom banner that invites the user to install the PWA, wired to\n * {@link useInstallPrompt}.\n *\n * Where the browser fires `beforeinstallprompt`, the button installs. Where it\n * does not — iOS Safari, and the Android Chromium forks that strip the API — the\n * banner shows that platform's instruction instead of disappearing. It used to\n * disappear: built on `useBeforeInstallPrompt`, it rendered `null` exactly where\n * the user has no other way to find the install entry, which is why every app\n * kept a local copy of this component just to add the two missing paths.\n *\n * @tempest-limits empty-catch — persisting the dismissal is a courtesy, not the\n * feature. When `localStorage` refuses the write (quota, private mode) the banner\n * still hides for this session; the worst case is that it comes back next visit,\n * which beats an error thrown out of a click handler that only closed a banner.\n *\n * @example\n * <InstallBanner\n * title=\"Instale o FAMACHApp\"\n * description=\"Acesso offline e atalho na tela inicial.\"\n * storageKey=\"famacha:install-dismissed\"\n * />\n */\nexport function InstallBanner({\n title = \"Instale o app\",\n description,\n installLabel = \"Instalar\",\n hintLabel = \"Como instalar\",\n dismissLabel = \"Dispensar\",\n icon,\n storageKey,\n declineCooldownMs,\n renderHint = defaultInstallHint,\n manualFallbackDelayMs,\n onResult,\n className,\n}: InstallBannerProps) {\n const { method, openInChromeIntent, install } = useInstallPrompt({ manualFallbackDelayMs });\n const [dismissed, setDismissed] = useState<boolean>(() =>\n readDismissed(storageKey, declineCooldownMs),\n );\n const [hintOpen, setHintOpen] = useState(false);\n const hintId = useId();\n\n if (method === \"none\" || dismissed) return null;\n\n const dismiss = (): void => {\n setDismissed(true);\n if (storageKey && typeof window !== \"undefined\") {\n try {\n window.localStorage.setItem(\n storageKey,\n declineCooldownMs === undefined ? \"1\" : String(Date.now()),\n );\n } catch {\n /* empty */\n }\n }\n };\n\n const hint = method === \"native\" ? null : renderHint({ method, openInChromeIntent });\n\n return (\n <div className={cn(styles.banner, className)} role=\"region\" aria-label={String(title)}>\n {icon && <span className={styles.icon}>{icon}</span>}\n <div className={styles.body}>\n <p className={styles.title}>{title}</p>\n {description && <p className={styles.description}>{description}</p>}\n {hintOpen && hint ? (\n <p className={styles.hint} id={hintId}>\n {hint}\n </p>\n ) : null}\n </div>\n {method === \"native\" ? (\n <Button\n size=\"sm\"\n onClick={async () => {\n const accepted = await install();\n onResult?.(accepted ? \"accepted\" : \"dismissed\");\n }}\n >\n {installLabel}\n </Button>\n ) : (\n <Button\n size=\"sm\"\n aria-expanded={hintOpen}\n aria-controls={hintOpen && hint ? hintId : undefined}\n onClick={() => setHintOpen((open) => !open)}\n >\n {hintLabel}\n </Button>\n )}\n <button\n type=\"button\"\n className={styles.close}\n aria-label={dismissLabel}\n onClick={dismiss}\n >\n <X size={18} aria-hidden />\n </button>\n </div>\n );\n}\n"],"mappings":"gSA8EA,SAAS,EAAc,EAAqB,EAAqC,CAC7E,GAAI,CAAC,GAAc,OAAO,OAAW,IAAa,MAAO,GACzD,GAAI,CACA,IAAM,EAAM,OAAO,aAAa,QAAQ,CAAU,EAClD,GAAI,CAAC,EAAK,MAAO,GACjB,GAAI,IAAQ,IAAK,MAAO,GACxB,IAAM,EAAc,OAAO,CAAG,EAG9B,OAFK,OAAO,SAAS,CAAW,EAC5B,IAAsB,IAAA,IACnB,KAAK,IAAI,EAAI,EAAc,EAFQ,EAG9C,MAAQ,CACJ,MAAO,EACX,CACJ,CAyBA,SAAgB,EAAc,CAC1B,QAAQ,gBACR,cACA,eAAe,WACf,YAAY,gBACZ,eAAe,YACf,OACA,aACA,oBACA,aAAa,EAAA,mBACb,wBACA,WACA,aACmB,CACnB,GAAM,CAAE,SAAQ,qBAAoB,WAAY,EAAA,iBAAiB,CAAE,uBAAsB,CAAC,EACpF,CAAC,EAAW,IAAA,EAAgB,EAAA,SAAA,KAC9B,EAAc,EAAY,CAAiB,CAC/C,EACM,CAAC,EAAU,IAAA,EAAe,EAAA,SAAA,CAAS,EAAK,EACxC,GAAA,EAAS,EAAA,MAAA,CAAM,EAErB,GAAI,IAAW,QAAU,EAAW,OAAO,KAE3C,IAAM,MAAsB,CAExB,GADA,EAAa,EAAI,EACb,GAAc,OAAO,OAAW,IAChC,GAAI,CACA,OAAO,aAAa,QAChB,EACA,IAAsB,IAAA,GAAY,IAAM,OAAO,KAAK,IAAI,CAAC,CAC7D,CACJ,MAAQ,CAER,CAER,EAEM,EAAO,IAAW,SAAW,KAAO,EAAW,CAAE,SAAQ,oBAAmB,CAAC,EAEnF,OACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,OAAQ,CAAS,EAAG,KAAK,SAAS,aAAY,OAAO,CAAK,EAApF,SAAA,CACK,IAAQ,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,KAAO,SAAA,CAAW,CAAA,GACnD,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,KAAvB,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAW,EAAA,QAAO,MAAQ,SAAA,CAAS,CAAA,EACrC,IAAe,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAW,EAAA,QAAO,YAAc,SAAA,CAAe,CAAA,EACjE,GAAY,GACT,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAW,EAAA,QAAO,KAAM,GAAI,EAC1B,SAAA,CACF,CAAA,EACH,IACH,IACJ,IAAW,UACR,EAAA,EAAA,IAAA,CAAC,EAAA,OAAD,CACI,KAAK,KACL,QAAS,SAAY,CACjB,IAAM,EAAW,MAAM,EAAQ,EAC/B,IAAW,EAAW,WAAa,WAAW,CAClD,EAEC,SAAA,CACG,CAAA,GAER,EAAA,EAAA,IAAA,CAAC,EAAA,OAAD,CACI,KAAK,KACL,gBAAe,EACf,gBAAe,GAAY,EAAO,EAAS,IAAA,GAC3C,YAAe,EAAa,GAAS,CAAC,CAAI,EAEzC,SAAA,CACG,CAAA,GAEZ,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,KAAK,SACL,UAAW,EAAA,QAAO,MAClB,aAAY,EACZ,QAAS,EAET,UAAA,EAAA,EAAA,IAAA,CAAC,EAAA,EAAD,CAAG,KAAM,GAAI,cAAA,EAAa,CAAA,CACtB,CAAA,CACP,GAEb"}
|
|
1
|
+
{"version":3,"file":"InstallBanner.cjs","names":["defaultInstallHint","useInstallPrompt","useState","useId","cn","styles","Button","X","require_cn","require_Button","require_use_install_prompt","require_install_hints","require_InstallBanner_module","react","react_jsx_runtime","lucide_react","readDismissed","storageKey","raw","dismissedAt","declineCooldownMs","InstallBanner","dismissed","setDismissed","hintOpen","setHintOpen","hintId","method","dismiss","hint","renderHint","className","title","icon","description","accepted","install","onResult","installLabel","open","hintLabel","dismissLabel"],"sources":["../../../src/components/InstallBanner/InstallBanner.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — title, description, installLabel and dismissLabel\n * are four strings the app has to write, icon and className the look, storageKey the\n * dismissal memory and onResult the outcome. An install prompt with SDK-authored\n * copy is the one thing nobody ships.\n */\nimport { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"@/utils/cn\";\nimport { Button } from \"@/components/Button\";\nimport { useInstallPrompt } from \"@/hooks/use-install-prompt\";\nimport { defaultInstallHint } from \"@/components/InstallButton/install-hints\";\nimport type { RenderInstallHint } from \"@/components/InstallButton/install-hints\";\nimport type { InstallOutcome } from \"@/components/InstallButton\";\nimport styles from \"./InstallBanner.module.css\";\n\nexport interface InstallBannerProps {\n /** Headline. Default `\"Instale o app\"`. */\n title?: ReactNode;\n /** Supporting copy under the title. */\n description?: ReactNode;\n /** Install button label. Default `\"Instalar\"`. */\n installLabel?: string;\n /** Accessible label for the dismiss button. Default `\"Dispensar\"`. */\n dismissLabel?: string;\n /** Optional leading icon. */\n icon?: ReactNode;\n /**\n * `localStorage` key used to remember dismissal across reloads. Omit to\n * make dismissal last only for the current session (component state).\n */\n storageKey?: string;\n /**\n * How long, in ms, a dismissal lasts before the banner may return.\n *\n * Omitted, a dismissal written to `storageKey` is permanent, which is what\n * the component always did and what a stored `\"1\"` keeps meaning. With a\n * cooldown the dismissal is stored as a timestamp instead, so the banner\n * comes back after the window — the same shape `useInstallPrompt` uses for\n * its own decline.\n */\n declineCooldownMs?: number;\n /**\n * Install button label used when the browser cannot be prompted and the\n * banner shows the manual instruction. Default `\"Como instalar\"`.\n */\n hintLabel?: string;\n /**\n * Replaces the instruction shown for the `\"ios\"` and `\"manual\"` methods.\n *\n * The default copy is in PT-BR and names the real menu entries.\n */\n renderHint?: RenderInstallHint;\n /**\n * How long, in ms, to wait for `beforeinstallprompt` before falling back to\n * the manual instruction. Forwarded to {@link useInstallPrompt}; defaults to\n * 3000 there.\n */\n manualFallbackDelayMs?: number;\n /** Called with the user's choice after the install prompt resolves. */\n onResult?: (outcome: InstallOutcome) => void;\n className?: string;\n}\n\n/**\n * Whether the user already dismissed this banner.\n *\n * Two stored shapes, and both have to keep working: `\"1\"` is the permanent\n * dismissal the component has always written, and a timestamp is what a banner\n * with `declineCooldownMs` writes. A `\"1\"` found while a cooldown is configured\n * still counts as dismissed forever — it was written under the old contract, and\n * reviving a banner the user turned off is worse than keeping it off.\n *\n * @param storageKey - The key holding the dismissal, if any.\n * @param declineCooldownMs - How long a timestamped dismissal lasts.\n * @returns Whether the banner should stay hidden.\n */\nfunction readDismissed(storageKey?: string, declineCooldownMs?: number): boolean {\n if (!storageKey || typeof window === \"undefined\") return false;\n try {\n const raw = window.localStorage.getItem(storageKey);\n if (!raw) return false;\n if (raw === \"1\") return true;\n const dismissedAt = Number(raw);\n if (!Number.isFinite(dismissedAt)) return false;\n if (declineCooldownMs === undefined) return true;\n return Date.now() - dismissedAt < declineCooldownMs;\n } catch {\n return false;\n }\n}\n\n/**\n * Dismissible bottom banner that invites the user to install the PWA, wired to\n * {@link useInstallPrompt}.\n *\n * Where the browser fires `beforeinstallprompt`, the button installs. Where it\n * does not — iOS Safari, and the Android Chromium forks that strip the API — the\n * banner shows that platform's instruction instead of disappearing. It used to\n * disappear: built on `useBeforeInstallPrompt`, it rendered `null` exactly where\n * the user has no other way to find the install entry, which is why every app\n * kept a local copy of this component just to add the two missing paths.\n *\n * @tempest-limits empty-catch — persisting the dismissal is a courtesy, not the\n * feature. When `localStorage` refuses the write (quota, private mode) the banner\n * still hides for this session; the worst case is that it comes back next visit,\n * which beats an error thrown out of a click handler that only closed a banner.\n *\n * @example\n * <InstallBanner\n * title=\"Instale o FAMACHApp\"\n * description=\"Acesso offline e atalho na tela inicial.\"\n * storageKey=\"famacha:install-dismissed\"\n * />\n */\nexport function InstallBanner({\n title = \"Instale o app\",\n description,\n installLabel = \"Instalar\",\n hintLabel = \"Como instalar\",\n dismissLabel = \"Dispensar\",\n icon,\n storageKey,\n declineCooldownMs,\n renderHint = defaultInstallHint,\n manualFallbackDelayMs,\n onResult,\n className,\n}: InstallBannerProps) {\n const { method, openInChromeIntent, install } = useInstallPrompt({ manualFallbackDelayMs });\n const [dismissed, setDismissed] = useState<boolean>(() =>\n readDismissed(storageKey, declineCooldownMs),\n );\n const [hintOpen, setHintOpen] = useState(false);\n const hintId = useId();\n\n if (method === \"none\" || dismissed) return null;\n\n const dismiss = (): void => {\n setDismissed(true);\n if (storageKey && typeof window !== \"undefined\") {\n try {\n window.localStorage.setItem(\n storageKey,\n declineCooldownMs === undefined ? \"1\" : String(Date.now()),\n );\n } catch {\n /* empty */\n }\n }\n };\n\n const hint = method === \"native\" ? null : renderHint({ method, openInChromeIntent });\n\n return (\n <div className={cn(styles.banner, className)} role=\"region\" aria-label={String(title)}>\n {icon && <span className={styles.icon}>{icon}</span>}\n <div className={styles.body}>\n <p className={styles.title}>{title}</p>\n {description && <p className={styles.description}>{description}</p>}\n {hintOpen && hint ? (\n <p className={styles.hint} id={hintId}>\n {hint}\n </p>\n ) : null}\n </div>\n {method === \"native\" ? (\n <Button\n size=\"sm\"\n onClick={async () => {\n const accepted = await install();\n onResult?.(accepted ? \"accepted\" : \"dismissed\");\n }}\n >\n {installLabel}\n </Button>\n ) : (\n <Button\n size=\"sm\"\n aria-expanded={hintOpen}\n aria-controls={hintOpen && hint ? hintId : undefined}\n onClick={() => setHintOpen((open) => !open)}\n >\n {hintLabel}\n </Button>\n )}\n <button\n type=\"button\"\n className={styles.close}\n aria-label={dismissLabel}\n onClick={dismiss}\n >\n <X size={18} aria-hidden />\n </button>\n </div>\n );\n}\n"],"mappings":"A,gSA8EA,SAASgB,EAAc,EAAqB,EAAqC,CAC7E,GAAI,CAACC,GAAc,OAAO,OAAW,IAAa,MAAO,GACzD,GAAI,CACA,IAAMC,EAAM,OAAO,aAAa,QAAQD,CAAU,EAClD,GAAI,CAACC,EAAK,MAAO,GACjB,GAAIA,IAAQ,IAAK,MAAO,GACxB,IAAMC,EAAc,OAAOD,CAAG,EAG9B,OAFK,OAAO,SAASC,CAAW,EAC5BC,IAAsB,IAAA,IACnB,KAAK,IAAI,EAAID,EAAcC,EAFQ,EAG9C,MAAQ,CACJ,MAAO,EACX,CACJ,CAyBA,SAAgBC,EAAc,CAC1B,QAAQ,gBACR,cACA,eAAe,WACf,YAAY,gBACZ,eAAe,YACf,OACA,aACA,oBACA,aAAarB,EAAAA,mBACb,wBACA,WACA,aACmB,CACnB,GAAM,CAAE,SAAQ,qBAAoB,WAAYC,EAAAA,iBAAiB,CAAE,uBAAsB,CAAC,EACpF,CAACqB,EAAWC,IAAA,EAAgBrB,EAAAA,SAAAA,KAC9Bc,EAAcC,EAAYG,CAAiB,CAC/C,EACM,CAACI,EAAUC,IAAA,EAAevB,EAAAA,SAAAA,CAAS,EAAK,EACxCwB,GAAA,EAASvB,EAAAA,MAAAA,CAAM,EAErB,GAAIwB,IAAW,QAAUL,EAAW,OAAO,KAE3C,IAAMM,MAAsB,CAExB,GADAL,EAAa,EAAI,EACbN,GAAc,OAAO,OAAW,IAChC,GAAI,CACA,OAAO,aAAa,QAChBA,EACAG,IAAsB,IAAA,GAAY,IAAM,OAAO,KAAK,IAAI,CAAC,CAC7D,CACJ,MAAQ,CAER,CAER,EAEMS,EAAOF,IAAW,SAAW,KAAOG,EAAW,CAAE,SAAQ,oBAAmB,CAAC,EAEnF,OACI,EAAAhB,EAAA,KAAA,CAAC,MAAD,CAAK,UAAWV,EAAAA,GAAGC,EAAAA,QAAO,OAAQ0B,CAAS,EAAG,KAAK,SAAS,aAAY,OAAOC,CAAK,EAApF,SAAA,CACKC,IAAQ,EAAAnB,EAAA,IAAA,CAAC,OAAD,CAAM,UAAWT,EAAAA,QAAO,KAAO,SAAA4B,CAAW,CAAA,GACnD,EAAAnB,EAAA,KAAA,CAAC,MAAD,CAAK,UAAWT,EAAAA,QAAO,KAAvB,SAAA,EACI,EAAAS,EAAA,IAAA,CAAC,IAAD,CAAG,UAAWT,EAAAA,QAAO,MAAQ,SAAA2B,CAAS,CAAA,EACrCE,IAAe,EAAApB,EAAA,IAAA,CAAC,IAAD,CAAG,UAAWT,EAAAA,QAAO,YAAc,SAAA6B,CAAe,CAAA,EACjEV,GAAYK,GACT,EAAAf,EAAA,IAAA,CAAC,IAAD,CAAG,UAAWT,EAAAA,QAAO,KAAM,GAAIqB,EAC1B,SAAAG,CACF,CAAA,EACH,IACH,C,GACJF,IAAW,UACR,EAAAb,EAAA,IAAA,CAACR,EAAAA,OAAD,CACI,KAAK,KACL,QAAS,SAAY,CACjB,IAAM6B,EAAW,MAAMC,EAAQ,EAC/BC,IAAWF,EAAW,WAAa,WAAW,CAClD,EAEC,SAAAG,CACG,CAAA,GAER,EAAAxB,EAAA,IAAA,CAACR,EAAAA,OAAD,CACI,KAAK,KACL,gBAAekB,EACf,gBAAeA,GAAYK,EAAOH,EAAS,IAAA,GAC3C,YAAeD,EAAa,GAAS,CAACc,CAAI,EAEzC,SAAAC,CACG,CAAA,GAEZ,EAAA1B,EAAA,IAAA,CAAC,SAAD,CACI,KAAK,SACL,UAAWT,EAAAA,QAAO,MAClB,aAAYoC,EACZ,QAASb,EAET,UAAA,EAAAd,EAAA,IAAA,CAACP,EAAAA,EAAD,CAAG,KAAM,GAAI,cAAA,EAAa,CAAA,CACtB,CAAA,CACP,C,EAEb,C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstallBanner.js","names":[],"sources":["../../../src/components/InstallBanner/InstallBanner.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — title, description, installLabel and dismissLabel\n * are four strings the app has to write, icon and className the look, storageKey the\n * dismissal memory and onResult the outcome. An install prompt with SDK-authored\n * copy is the one thing nobody ships.\n */\nimport { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"@/utils/cn\";\nimport { Button } from \"@/components/Button\";\nimport { useInstallPrompt } from \"@/hooks/use-install-prompt\";\nimport { defaultInstallHint } from \"@/components/InstallButton/install-hints\";\nimport type { RenderInstallHint } from \"@/components/InstallButton/install-hints\";\nimport type { InstallOutcome } from \"@/components/InstallButton\";\nimport styles from \"./InstallBanner.module.css\";\n\nexport interface InstallBannerProps {\n /** Headline. Default `\"Instale o app\"`. */\n title?: ReactNode;\n /** Supporting copy under the title. */\n description?: ReactNode;\n /** Install button label. Default `\"Instalar\"`. */\n installLabel?: string;\n /** Accessible label for the dismiss button. Default `\"Dispensar\"`. */\n dismissLabel?: string;\n /** Optional leading icon. */\n icon?: ReactNode;\n /**\n * `localStorage` key used to remember dismissal across reloads. Omit to\n * make dismissal last only for the current session (component state).\n */\n storageKey?: string;\n /**\n * How long, in ms, a dismissal lasts before the banner may return.\n *\n * Omitted, a dismissal written to `storageKey` is permanent, which is what\n * the component always did and what a stored `\"1\"` keeps meaning. With a\n * cooldown the dismissal is stored as a timestamp instead, so the banner\n * comes back after the window — the same shape `useInstallPrompt` uses for\n * its own decline.\n */\n declineCooldownMs?: number;\n /**\n * Install button label used when the browser cannot be prompted and the\n * banner shows the manual instruction. Default `\"Como instalar\"`.\n */\n hintLabel?: string;\n /**\n * Replaces the instruction shown for the `\"ios\"` and `\"manual\"` methods.\n *\n * The default copy is in PT-BR and names the real menu entries.\n */\n renderHint?: RenderInstallHint;\n /**\n * How long, in ms, to wait for `beforeinstallprompt` before falling back to\n * the manual instruction. Forwarded to {@link useInstallPrompt}; defaults to\n * 3000 there.\n */\n manualFallbackDelayMs?: number;\n /** Called with the user's choice after the install prompt resolves. */\n onResult?: (outcome: InstallOutcome) => void;\n className?: string;\n}\n\n/**\n * Whether the user already dismissed this banner.\n *\n * Two stored shapes, and both have to keep working: `\"1\"` is the permanent\n * dismissal the component has always written, and a timestamp is what a banner\n * with `declineCooldownMs` writes. A `\"1\"` found while a cooldown is configured\n * still counts as dismissed forever — it was written under the old contract, and\n * reviving a banner the user turned off is worse than keeping it off.\n *\n * @param storageKey - The key holding the dismissal, if any.\n * @param declineCooldownMs - How long a timestamped dismissal lasts.\n * @returns Whether the banner should stay hidden.\n */\nfunction readDismissed(storageKey?: string, declineCooldownMs?: number): boolean {\n if (!storageKey || typeof window === \"undefined\") return false;\n try {\n const raw = window.localStorage.getItem(storageKey);\n if (!raw) return false;\n if (raw === \"1\") return true;\n const dismissedAt = Number(raw);\n if (!Number.isFinite(dismissedAt)) return false;\n if (declineCooldownMs === undefined) return true;\n return Date.now() - dismissedAt < declineCooldownMs;\n } catch {\n return false;\n }\n}\n\n/**\n * Dismissible bottom banner that invites the user to install the PWA, wired to\n * {@link useInstallPrompt}.\n *\n * Where the browser fires `beforeinstallprompt`, the button installs. Where it\n * does not — iOS Safari, and the Android Chromium forks that strip the API — the\n * banner shows that platform's instruction instead of disappearing. It used to\n * disappear: built on `useBeforeInstallPrompt`, it rendered `null` exactly where\n * the user has no other way to find the install entry, which is why every app\n * kept a local copy of this component just to add the two missing paths.\n *\n * @tempest-limits empty-catch — persisting the dismissal is a courtesy, not the\n * feature. When `localStorage` refuses the write (quota, private mode) the banner\n * still hides for this session; the worst case is that it comes back next visit,\n * which beats an error thrown out of a click handler that only closed a banner.\n *\n * @example\n * <InstallBanner\n * title=\"Instale o FAMACHApp\"\n * description=\"Acesso offline e atalho na tela inicial.\"\n * storageKey=\"famacha:install-dismissed\"\n * />\n */\nexport function InstallBanner({\n title = \"Instale o app\",\n description,\n installLabel = \"Instalar\",\n hintLabel = \"Como instalar\",\n dismissLabel = \"Dispensar\",\n icon,\n storageKey,\n declineCooldownMs,\n renderHint = defaultInstallHint,\n manualFallbackDelayMs,\n onResult,\n className,\n}: InstallBannerProps) {\n const { method, openInChromeIntent, install } = useInstallPrompt({ manualFallbackDelayMs });\n const [dismissed, setDismissed] = useState<boolean>(() =>\n readDismissed(storageKey, declineCooldownMs),\n );\n const [hintOpen, setHintOpen] = useState(false);\n const hintId = useId();\n\n if (method === \"none\" || dismissed) return null;\n\n const dismiss = (): void => {\n setDismissed(true);\n if (storageKey && typeof window !== \"undefined\") {\n try {\n window.localStorage.setItem(\n storageKey,\n declineCooldownMs === undefined ? \"1\" : String(Date.now()),\n );\n } catch {\n /* empty */\n }\n }\n };\n\n const hint = method === \"native\" ? null : renderHint({ method, openInChromeIntent });\n\n return (\n <div className={cn(styles.banner, className)} role=\"region\" aria-label={String(title)}>\n {icon && <span className={styles.icon}>{icon}</span>}\n <div className={styles.body}>\n <p className={styles.title}>{title}</p>\n {description && <p className={styles.description}>{description}</p>}\n {hintOpen && hint ? (\n <p className={styles.hint} id={hintId}>\n {hint}\n </p>\n ) : null}\n </div>\n {method === \"native\" ? (\n <Button\n size=\"sm\"\n onClick={async () => {\n const accepted = await install();\n onResult?.(accepted ? \"accepted\" : \"dismissed\");\n }}\n >\n {installLabel}\n </Button>\n ) : (\n <Button\n size=\"sm\"\n aria-expanded={hintOpen}\n aria-controls={hintOpen && hint ? hintId : undefined}\n onClick={() => setHintOpen((open) => !open)}\n >\n {hintLabel}\n </Button>\n )}\n <button\n type=\"button\"\n className={styles.close}\n aria-label={dismissLabel}\n onClick={dismiss}\n >\n <X size={18} aria-hidden />\n </button>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AA8EA,SAAS,EAAc,GAAqB,GAAqC;CAC7E,IAAI,CAAC,KAAc,OAAO,SAAW,KAAa,OAAO;CACzD,IAAI;EACA,IAAM,IAAM,OAAO,aAAa,QAAQ,CAAU;EAClD,IAAI,CAAC,GAAK,OAAO;EACjB,IAAI,MAAQ,KAAK,OAAO;EACxB,IAAM,IAAc,OAAO,CAAG;EAG9B,OAFK,OAAO,SAAS,CAAW,IAC5B,MAAsB,KAAA,KACnB,KAAK,IAAI,IAAI,IAAc,IAFQ;CAG9C,QAAQ;EACJ,OAAO;CACX;AACJ;AAyBA,SAAgB,EAAc,EAC1B,WAAQ,iBACR,gBACA,kBAAe,YACf,eAAY,iBACZ,kBAAe,aACf,SACA,eACA,sBACA,gBAAa,GACb,0BACA,aACA,gBACmB;CACnB,IAAM,EAAE,WAAQ,uBAAoB,eAAY,EAAiB,EAAE,yBAAsB,CAAC,GACpF,CAAC,GAAW,KAAgB,QAC9B,EAAc,GAAY,CAAiB,CAC/C,GACM,CAAC,GAAU,KAAe,EAAS,EAAK,GACxC,IAAS,EAAM;CAErB,IAAI,MAAW,UAAU,GAAW,OAAO;CAE3C,IAAM,UAAsB;EAExB,IADA,EAAa,EAAI,GACb,KAAc,OAAO,SAAW,KAChC,IAAI;GACA,OAAO,aAAa,QAChB,GACA,MAAsB,KAAA,IAAY,MAAM,OAAO,KAAK,IAAI,CAAC,CAC7D;EACJ,QAAQ,CAER;CAER,GAEM,IAAO,MAAW,WAAW,OAAO,EAAW;EAAE;EAAQ;CAAmB,CAAC;CAEnF,OACI,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,QAAQ,CAAS;EAAG,MAAK;EAAS,cAAY,OAAO,CAAK;EAApF,UAAA;GACK,KAAQ,kBAAC,QAAD;IAAM,WAAW,EAAO;IAAO,UAAA;GAAW,CAAA;GACnD,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAvB,UAAA;KACI,kBAAC,KAAD;MAAG,WAAW,EAAO;MAAQ,UAAA;KAAS,CAAA;KACrC,KAAe,kBAAC,KAAD;MAAG,WAAW,EAAO;MAAc,UAAA;KAAe,CAAA;KACjE,KAAY,IACT,kBAAC,KAAD;MAAG,WAAW,EAAO;MAAM,IAAI;MAC1B,UAAA;KACF,CAAA,IACH;IACH;;GACJ,MAAW,WACR,kBAAC,GAAD;IACI,MAAK;IACL,SAAS,YAAY;KACjB,IAAM,IAAW,MAAM,EAAQ;KAC/B,IAAW,IAAW,aAAa,WAAW;IAClD;IAEC,UAAA;GACG,CAAA,IAER,kBAAC,GAAD;IACI,MAAK;IACL,iBAAe;IACf,iBAAe,KAAY,IAAO,IAAS,KAAA;IAC3C,eAAe,GAAa,MAAS,CAAC,CAAI;IAEzC,UAAA;GACG,CAAA;GAEZ,kBAAC,UAAD;IACI,MAAK;IACL,WAAW,EAAO;IAClB,cAAY;IACZ,SAAS;IAET,UAAA,kBAAC,GAAD;KAAG,MAAM;KAAI,eAAA;IAAa,CAAA;GACtB,CAAA;EACP;;AAEb"}
|
|
1
|
+
{"version":3,"file":"InstallBanner.js","names":["styles","InstallBanner_module_default","readDismissed","storageKey","raw","dismissedAt","declineCooldownMs","InstallBanner","defaultInstallHint","useInstallPrompt","dismissed","setDismissed","useState","hintOpen","setHintOpen","hintId","useId","method","dismiss","hint","renderHint","cn","className","title","icon","description","Button","accepted","install","installLabel","open","hintLabel","dismissLabel","X"],"sources":["../../../src/components/InstallBanner/InstallBanner.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — title, description, installLabel and dismissLabel\n * are four strings the app has to write, icon and className the look, storageKey the\n * dismissal memory and onResult the outcome. An install prompt with SDK-authored\n * copy is the one thing nobody ships.\n */\nimport { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"@/utils/cn\";\nimport { Button } from \"@/components/Button\";\nimport { useInstallPrompt } from \"@/hooks/use-install-prompt\";\nimport { defaultInstallHint } from \"@/components/InstallButton/install-hints\";\nimport type { RenderInstallHint } from \"@/components/InstallButton/install-hints\";\nimport type { InstallOutcome } from \"@/components/InstallButton\";\nimport styles from \"./InstallBanner.module.css\";\n\nexport interface InstallBannerProps {\n /** Headline. Default `\"Instale o app\"`. */\n title?: ReactNode;\n /** Supporting copy under the title. */\n description?: ReactNode;\n /** Install button label. Default `\"Instalar\"`. */\n installLabel?: string;\n /** Accessible label for the dismiss button. Default `\"Dispensar\"`. */\n dismissLabel?: string;\n /** Optional leading icon. */\n icon?: ReactNode;\n /**\n * `localStorage` key used to remember dismissal across reloads. Omit to\n * make dismissal last only for the current session (component state).\n */\n storageKey?: string;\n /**\n * How long, in ms, a dismissal lasts before the banner may return.\n *\n * Omitted, a dismissal written to `storageKey` is permanent, which is what\n * the component always did and what a stored `\"1\"` keeps meaning. With a\n * cooldown the dismissal is stored as a timestamp instead, so the banner\n * comes back after the window — the same shape `useInstallPrompt` uses for\n * its own decline.\n */\n declineCooldownMs?: number;\n /**\n * Install button label used when the browser cannot be prompted and the\n * banner shows the manual instruction. Default `\"Como instalar\"`.\n */\n hintLabel?: string;\n /**\n * Replaces the instruction shown for the `\"ios\"` and `\"manual\"` methods.\n *\n * The default copy is in PT-BR and names the real menu entries.\n */\n renderHint?: RenderInstallHint;\n /**\n * How long, in ms, to wait for `beforeinstallprompt` before falling back to\n * the manual instruction. Forwarded to {@link useInstallPrompt}; defaults to\n * 3000 there.\n */\n manualFallbackDelayMs?: number;\n /** Called with the user's choice after the install prompt resolves. */\n onResult?: (outcome: InstallOutcome) => void;\n className?: string;\n}\n\n/**\n * Whether the user already dismissed this banner.\n *\n * Two stored shapes, and both have to keep working: `\"1\"` is the permanent\n * dismissal the component has always written, and a timestamp is what a banner\n * with `declineCooldownMs` writes. A `\"1\"` found while a cooldown is configured\n * still counts as dismissed forever — it was written under the old contract, and\n * reviving a banner the user turned off is worse than keeping it off.\n *\n * @param storageKey - The key holding the dismissal, if any.\n * @param declineCooldownMs - How long a timestamped dismissal lasts.\n * @returns Whether the banner should stay hidden.\n */\nfunction readDismissed(storageKey?: string, declineCooldownMs?: number): boolean {\n if (!storageKey || typeof window === \"undefined\") return false;\n try {\n const raw = window.localStorage.getItem(storageKey);\n if (!raw) return false;\n if (raw === \"1\") return true;\n const dismissedAt = Number(raw);\n if (!Number.isFinite(dismissedAt)) return false;\n if (declineCooldownMs === undefined) return true;\n return Date.now() - dismissedAt < declineCooldownMs;\n } catch {\n return false;\n }\n}\n\n/**\n * Dismissible bottom banner that invites the user to install the PWA, wired to\n * {@link useInstallPrompt}.\n *\n * Where the browser fires `beforeinstallprompt`, the button installs. Where it\n * does not — iOS Safari, and the Android Chromium forks that strip the API — the\n * banner shows that platform's instruction instead of disappearing. It used to\n * disappear: built on `useBeforeInstallPrompt`, it rendered `null` exactly where\n * the user has no other way to find the install entry, which is why every app\n * kept a local copy of this component just to add the two missing paths.\n *\n * @tempest-limits empty-catch — persisting the dismissal is a courtesy, not the\n * feature. When `localStorage` refuses the write (quota, private mode) the banner\n * still hides for this session; the worst case is that it comes back next visit,\n * which beats an error thrown out of a click handler that only closed a banner.\n *\n * @example\n * <InstallBanner\n * title=\"Instale o FAMACHApp\"\n * description=\"Acesso offline e atalho na tela inicial.\"\n * storageKey=\"famacha:install-dismissed\"\n * />\n */\nexport function InstallBanner({\n title = \"Instale o app\",\n description,\n installLabel = \"Instalar\",\n hintLabel = \"Como instalar\",\n dismissLabel = \"Dispensar\",\n icon,\n storageKey,\n declineCooldownMs,\n renderHint = defaultInstallHint,\n manualFallbackDelayMs,\n onResult,\n className,\n}: InstallBannerProps) {\n const { method, openInChromeIntent, install } = useInstallPrompt({ manualFallbackDelayMs });\n const [dismissed, setDismissed] = useState<boolean>(() =>\n readDismissed(storageKey, declineCooldownMs),\n );\n const [hintOpen, setHintOpen] = useState(false);\n const hintId = useId();\n\n if (method === \"none\" || dismissed) return null;\n\n const dismiss = (): void => {\n setDismissed(true);\n if (storageKey && typeof window !== \"undefined\") {\n try {\n window.localStorage.setItem(\n storageKey,\n declineCooldownMs === undefined ? \"1\" : String(Date.now()),\n );\n } catch {\n /* empty */\n }\n }\n };\n\n const hint = method === \"native\" ? null : renderHint({ method, openInChromeIntent });\n\n return (\n <div className={cn(styles.banner, className)} role=\"region\" aria-label={String(title)}>\n {icon && <span className={styles.icon}>{icon}</span>}\n <div className={styles.body}>\n <p className={styles.title}>{title}</p>\n {description && <p className={styles.description}>{description}</p>}\n {hintOpen && hint ? (\n <p className={styles.hint} id={hintId}>\n {hint}\n </p>\n ) : null}\n </div>\n {method === \"native\" ? (\n <Button\n size=\"sm\"\n onClick={async () => {\n const accepted = await install();\n onResult?.(accepted ? \"accepted\" : \"dismissed\");\n }}\n >\n {installLabel}\n </Button>\n ) : (\n <Button\n size=\"sm\"\n aria-expanded={hintOpen}\n aria-controls={hintOpen && hint ? hintId : undefined}\n onClick={() => setHintOpen((open) => !open)}\n >\n {hintLabel}\n </Button>\n )}\n <button\n type=\"button\"\n className={styles.close}\n aria-label={dismissLabel}\n onClick={dismiss}\n >\n <X size={18} aria-hidden />\n </button>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AA8EA,SAASE,EAAc,GAAqB,GAAqC;CAC7E,IAAI,CAACC,KAAc,OAAO,SAAW,KAAa,OAAO;CACzD,IAAI;EACA,IAAMC,IAAM,OAAO,aAAa,QAAQD,CAAU;EAClD,IAAI,CAACC,GAAK,OAAO;EACjB,IAAIA,MAAQ,KAAK,OAAO;EACxB,IAAMC,IAAc,OAAOD,CAAG;EAG9B,OAFK,OAAO,SAASC,CAAW,IAC5BC,MAAsB,KAAA,KACnB,KAAK,IAAI,IAAID,IAAcC,IAFQ;CAG9C,QAAQ;EACJ,OAAO;CACX;AACJ;AAyBA,SAAgBC,EAAc,EAC1B,WAAQ,iBACR,gBACA,kBAAe,YACf,eAAY,iBACZ,kBAAe,aACf,SACA,eACA,sBACA,gBAAaC,GACb,0BACA,aACA,gBACmB;CACnB,IAAM,EAAE,WAAQ,uBAAoB,eAAYC,EAAiB,EAAE,yBAAsB,CAAC,GACpF,CAACC,GAAWC,KAAgBC,QAC9BV,EAAcC,GAAYG,CAAiB,CAC/C,GACM,CAACO,GAAUC,KAAeF,EAAS,EAAK,GACxCG,IAASC,EAAM;CAErB,IAAIC,MAAW,UAAUP,GAAW,OAAO;CAE3C,IAAMQ,UAAsB;EAExB,IADAP,EAAa,EAAI,GACbR,KAAc,OAAO,SAAW,KAChC,IAAI;GACA,OAAO,aAAa,QAChBA,GACAG,MAAsB,KAAA,IAAY,MAAM,OAAO,KAAK,IAAI,CAAC,CAC7D;EACJ,QAAQ,CAER;CAER,GAEMa,IAAOF,MAAW,WAAW,OAAOG,EAAW;EAAE;EAAQ;CAAmB,CAAC;CAEnF,OACI,kBAAC,OAAD;EAAK,WAAWC,EAAGrB,EAAO,QAAQsB,CAAS;EAAG,MAAK;EAAS,cAAY,OAAOC,CAAK;EAApF,UAAA;GACKC,KAAQ,kBAAC,QAAD;IAAM,WAAWxB,EAAO;IAAO,UAAAwB;GAAW,CAAA;GACnD,kBAAC,OAAD;IAAK,WAAWxB,EAAO;IAAvB,UAAA;KACI,kBAAC,KAAD;MAAG,WAAWA,EAAO;MAAQ,UAAAuB;KAAS,CAAA;KACrCE,KAAe,kBAAC,KAAD;MAAG,WAAWzB,EAAO;MAAc,UAAAyB;KAAe,CAAA;KACjEZ,KAAYM,IACT,kBAAC,KAAD;MAAG,WAAWnB,EAAO;MAAM,IAAIe;MAC1B,UAAAI;KACF,CAAA,IACH;IACH;;GACJF,MAAW,WACR,kBAACS,GAAD;IACI,MAAK;IACL,SAAS,YAAY;KACjB,IAAMC,IAAW,MAAMC,EAAQ;KAC/B,IAAWD,IAAW,aAAa,WAAW;IAClD;IAEC,UAAAE;GACG,CAAA,IAER,kBAACH,GAAD;IACI,MAAK;IACL,iBAAeb;IACf,iBAAeA,KAAYM,IAAOJ,IAAS,KAAA;IAC3C,eAAeD,GAAa,MAAS,CAACgB,CAAI;IAEzC,UAAAC;GACG,CAAA;GAEZ,kBAAC,UAAD;IACI,MAAK;IACL,WAAW/B,EAAO;IAClB,cAAYgC;IACZ,SAASd;IAET,UAAA,kBAACe,GAAD;KAAG,MAAM;KAAI,eAAA;IAAa,CAAA;GACtB,CAAA;EACP;;AAEb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstallBanner.module.cjs","names":[],"sources":["../../../src/components/InstallBanner/InstallBanner.module.css"],"sourcesContent":[".banner {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-3);\n padding: var(--tempest-space-3) var(--tempest-space-4);\n border-radius: var(--tempest-radius-lg);\n border: 1px solid var(--tempest-border);\n background: var(--tempest-surface);\n color: var(--tempest-text);\n box-shadow: var(--tempest-shadow-lg);\n width: 100%;\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-sm);\n line-height: var(--tempest-leading-snug);\n}\n\n.icon {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n line-height: 1;\n color: var(--tempest-primary);\n}\n\n.body {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.title {\n margin: 0;\n font-weight: var(--tempest-weight-semibold);\n color: var(--tempest-text);\n}\n\n.description {\n margin: var(--tempest-space-1) 0 0;\n color: var(--tempest-text-muted);\n}\n\n.close {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: 0;\n color: var(--tempest-text-muted);\n cursor: pointer;\n padding: 0;\n width: 28px;\n height: 28px;\n border-radius: var(--tempest-radius-sm);\n}\n\n.close:hover {\n background: color-mix(in srgb, currentColor 10%, transparent);\n}\n\n.hint {\n margin: var(--tempest-space-2) 0 0;\n color: var(--tempest-text-muted);\n}\n\n.hint a {\n color: var(--tempest-primary);\n}\n"],"mappings":";"}
|
|
1
|
+
{"version":3,"file":"InstallBanner.module.cjs","names":["banner","icon","body","title","description","close","hint","InstallBanner_module_default"],"sources":["../../../src/components/InstallBanner/InstallBanner.module.css"],"sourcesContent":[".banner {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-3);\n padding: var(--tempest-space-3) var(--tempest-space-4);\n border-radius: var(--tempest-radius-lg);\n border: 1px solid var(--tempest-border);\n background: var(--tempest-surface);\n color: var(--tempest-text);\n box-shadow: var(--tempest-shadow-lg);\n width: 100%;\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-sm);\n line-height: var(--tempest-leading-snug);\n}\n\n.icon {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n line-height: 1;\n color: var(--tempest-primary);\n}\n\n.body {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.title {\n margin: 0;\n font-weight: var(--tempest-weight-semibold);\n color: var(--tempest-text);\n}\n\n.description {\n margin: var(--tempest-space-1) 0 0;\n color: var(--tempest-text-muted);\n}\n\n.close {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: 0;\n color: var(--tempest-text-muted);\n cursor: pointer;\n padding: 0;\n width: 28px;\n height: 28px;\n border-radius: var(--tempest-radius-sm);\n}\n\n.close:hover {\n background: color-mix(in srgb, currentColor 10%, transparent);\n}\n\n.hint {\n margin: var(--tempest-space-2) 0 0;\n color: var(--tempest-text-muted);\n}\n\n.hint a {\n color: var(--tempest-primary);\n}\n"],"mappings":";"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstallBanner.module.js","names":[],"sources":["../../../src/components/InstallBanner/InstallBanner.module.css"],"sourcesContent":[".banner {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-3);\n padding: var(--tempest-space-3) var(--tempest-space-4);\n border-radius: var(--tempest-radius-lg);\n border: 1px solid var(--tempest-border);\n background: var(--tempest-surface);\n color: var(--tempest-text);\n box-shadow: var(--tempest-shadow-lg);\n width: 100%;\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-sm);\n line-height: var(--tempest-leading-snug);\n}\n\n.icon {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n line-height: 1;\n color: var(--tempest-primary);\n}\n\n.body {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.title {\n margin: 0;\n font-weight: var(--tempest-weight-semibold);\n color: var(--tempest-text);\n}\n\n.description {\n margin: var(--tempest-space-1) 0 0;\n color: var(--tempest-text-muted);\n}\n\n.close {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: 0;\n color: var(--tempest-text-muted);\n cursor: pointer;\n padding: 0;\n width: 28px;\n height: 28px;\n border-radius: var(--tempest-radius-sm);\n}\n\n.close:hover {\n background: color-mix(in srgb, currentColor 10%, transparent);\n}\n\n.hint {\n margin: var(--tempest-space-2) 0 0;\n color: var(--tempest-text-muted);\n}\n\n.hint a {\n color: var(--tempest-primary);\n}\n"],"mappings":";"}
|
|
1
|
+
{"version":3,"file":"InstallBanner.module.js","names":["banner","icon","body","title","description","close","hint","InstallBanner_module_default"],"sources":["../../../src/components/InstallBanner/InstallBanner.module.css"],"sourcesContent":[".banner {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-3);\n padding: var(--tempest-space-3) var(--tempest-space-4);\n border-radius: var(--tempest-radius-lg);\n border: 1px solid var(--tempest-border);\n background: var(--tempest-surface);\n color: var(--tempest-text);\n box-shadow: var(--tempest-shadow-lg);\n width: 100%;\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-sm);\n line-height: var(--tempest-leading-snug);\n}\n\n.icon {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n line-height: 1;\n color: var(--tempest-primary);\n}\n\n.body {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.title {\n margin: 0;\n font-weight: var(--tempest-weight-semibold);\n color: var(--tempest-text);\n}\n\n.description {\n margin: var(--tempest-space-1) 0 0;\n color: var(--tempest-text-muted);\n}\n\n.close {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: 0;\n color: var(--tempest-text-muted);\n cursor: pointer;\n padding: 0;\n width: 28px;\n height: 28px;\n border-radius: var(--tempest-radius-sm);\n}\n\n.close:hover {\n background: color-mix(in srgb, currentColor 10%, transparent);\n}\n\n.hint {\n margin: var(--tempest-space-2) 0 0;\n color: var(--tempest-text-muted);\n}\n\n.hint a {\n color: var(--tempest-primary);\n}\n"],"mappings":";"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstallButton.cjs","names":[],"sources":["../../../src/components/InstallButton/InstallButton.tsx"],"sourcesContent":["import { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Button, type ButtonAsButtonProps } from \"@/components/Button\";\nimport { useInstallPrompt } from \"@/hooks/use-install-prompt\";\nimport { cn } from \"@/utils/cn\";\nimport { defaultInstallHint, type RenderInstallHint } from \"./install-hints\";\nimport styles from \"./InstallButton.module.css\";\n\nexport type InstallOutcome = \"accepted\" | \"dismissed\" | \"unsupported\";\n\nexport interface InstallButtonProps extends Omit<ButtonAsButtonProps, \"onClick\" | \"children\"> {\n /** Button label. Default `\"Instalar app\"`. */\n label?: ReactNode;\n /**\n * Label used when the browser cannot be prompted and the button reveals the\n * manual instruction instead. Default `\"Como instalar\"`.\n */\n hintLabel?: ReactNode;\n /** Called with the user's choice after the install prompt resolves. */\n onResult?: (outcome: InstallOutcome) => void;\n /**\n * Replaces the instruction shown for the `\"ios\"` and `\"manual\"` methods.\n *\n * The default copy is in PT-BR and names the real menu entries. Pass this to\n * translate it, to shorten it, or to point at a screenshot of your own.\n */\n renderHint?: RenderInstallHint;\n /**\n * How long, in ms, to wait for `beforeinstallprompt` before falling back to\n * the manual instruction. Forwarded to {@link useInstallPrompt}; defaults to\n * 3000 there.\n */\n manualFallbackDelayMs?: number;\n /** Class applied to the wrapper that holds the button and the instruction. */\n wrapperClassName?: string;\n}\n\n/**\n * Button wired to PWA installation, through {@link useInstallPrompt}.\n *\n * Where the browser fires `beforeinstallprompt`, the click installs. Where it\n * does not — iOS Safari, and the Android Chromium forks (Mi Browser, UC, Opera\n * Mini, Huawei) that strip the API — the click reveals the instruction for that\n * platform instead of the button disappearing.\n *\n * That disappearance was the defect: the component was built on\n * `useBeforeInstallPrompt`, so it rendered `null` exactly where the user needs\n * the most help, and every app re-implemented the iOS and manual paths locally.\n * Nothing renders only when there is genuinely nothing to offer — already\n * installed, running standalone, or inside the decline cooldown.\n *\n * Inherits every {@link Button} prop of the `<button>` mode (`variant`, `size`,\n * `leftIcon`, …) but not `href`: its click opens the install prompt\n * or toggles the instruction, which is an action, not a navigation.\n *\n * @example\n * <InstallButton variant=\"primary\" leftIcon={<Download />} />\n *\n * @example\n * <InstallButton renderHint={({ method }) => (method === \"ios\" ? <IOSSteps /> : <MenuSteps />)} />\n */\nexport function InstallButton({\n label = \"Instalar app\",\n hintLabel = \"Como instalar\",\n onResult,\n renderHint = defaultInstallHint,\n manualFallbackDelayMs,\n wrapperClassName,\n ...props\n}: InstallButtonProps) {\n const { method, openInChromeIntent, install } = useInstallPrompt({ manualFallbackDelayMs });\n const [hintOpen, setHintOpen] = useState(false);\n const hintId = useId();\n\n if (method === \"none\") return null;\n\n if (method === \"native\") {\n return (\n <Button\n onClick={async () => {\n const accepted = await install();\n onResult?.(accepted ? \"accepted\" : \"dismissed\");\n }}\n {...props}\n >\n {label}\n </Button>\n );\n }\n\n const hint = renderHint({ method, openInChromeIntent });\n\n return (\n <div className={cn(styles.wrapper, wrapperClassName)}>\n <Button\n aria-expanded={hintOpen}\n aria-controls={hintOpen && hint ? hintId : undefined}\n onClick={() => setHintOpen((open) => !open)}\n {...props}\n >\n {hintLabel}\n </Button>\n {hintOpen && hint ? (\n <p className={styles.hint} id={hintId}>\n {hint}\n </p>\n ) : null}\n </div>\n );\n}\n"],"mappings":"uPA6DA,
|
|
1
|
+
{"version":3,"file":"InstallButton.cjs","names":["defaultInstallHint","useInstallPrompt","useState","useId","Button","cn","styles","require_cn","require_Button","require_use_install_prompt","require_install_hints","require_InstallButton_module","react","react_jsx_runtime","InstallButton","props","hintOpen","setHintOpen","hintId","method","accepted","install","onResult","label","hint","renderHint","wrapperClassName","open","hintLabel"],"sources":["../../../src/components/InstallButton/InstallButton.tsx"],"sourcesContent":["import { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Button, type ButtonAsButtonProps } from \"@/components/Button\";\nimport { useInstallPrompt } from \"@/hooks/use-install-prompt\";\nimport { cn } from \"@/utils/cn\";\nimport { defaultInstallHint, type RenderInstallHint } from \"./install-hints\";\nimport styles from \"./InstallButton.module.css\";\n\nexport type InstallOutcome = \"accepted\" | \"dismissed\" | \"unsupported\";\n\nexport interface InstallButtonProps extends Omit<ButtonAsButtonProps, \"onClick\" | \"children\"> {\n /** Button label. Default `\"Instalar app\"`. */\n label?: ReactNode;\n /**\n * Label used when the browser cannot be prompted and the button reveals the\n * manual instruction instead. Default `\"Como instalar\"`.\n */\n hintLabel?: ReactNode;\n /** Called with the user's choice after the install prompt resolves. */\n onResult?: (outcome: InstallOutcome) => void;\n /**\n * Replaces the instruction shown for the `\"ios\"` and `\"manual\"` methods.\n *\n * The default copy is in PT-BR and names the real menu entries. Pass this to\n * translate it, to shorten it, or to point at a screenshot of your own.\n */\n renderHint?: RenderInstallHint;\n /**\n * How long, in ms, to wait for `beforeinstallprompt` before falling back to\n * the manual instruction. Forwarded to {@link useInstallPrompt}; defaults to\n * 3000 there.\n */\n manualFallbackDelayMs?: number;\n /** Class applied to the wrapper that holds the button and the instruction. */\n wrapperClassName?: string;\n}\n\n/**\n * Button wired to PWA installation, through {@link useInstallPrompt}.\n *\n * Where the browser fires `beforeinstallprompt`, the click installs. Where it\n * does not — iOS Safari, and the Android Chromium forks (Mi Browser, UC, Opera\n * Mini, Huawei) that strip the API — the click reveals the instruction for that\n * platform instead of the button disappearing.\n *\n * That disappearance was the defect: the component was built on\n * `useBeforeInstallPrompt`, so it rendered `null` exactly where the user needs\n * the most help, and every app re-implemented the iOS and manual paths locally.\n * Nothing renders only when there is genuinely nothing to offer — already\n * installed, running standalone, or inside the decline cooldown.\n *\n * Inherits every {@link Button} prop of the `<button>` mode (`variant`, `size`,\n * `leftIcon`, …) but not `href`: its click opens the install prompt\n * or toggles the instruction, which is an action, not a navigation.\n *\n * @example\n * <InstallButton variant=\"primary\" leftIcon={<Download />} />\n *\n * @example\n * <InstallButton renderHint={({ method }) => (method === \"ios\" ? <IOSSteps /> : <MenuSteps />)} />\n */\nexport function InstallButton({\n label = \"Instalar app\",\n hintLabel = \"Como instalar\",\n onResult,\n renderHint = defaultInstallHint,\n manualFallbackDelayMs,\n wrapperClassName,\n ...props\n}: InstallButtonProps) {\n const { method, openInChromeIntent, install } = useInstallPrompt({ manualFallbackDelayMs });\n const [hintOpen, setHintOpen] = useState(false);\n const hintId = useId();\n\n if (method === \"none\") return null;\n\n if (method === \"native\") {\n return (\n <Button\n onClick={async () => {\n const accepted = await install();\n onResult?.(accepted ? \"accepted\" : \"dismissed\");\n }}\n {...props}\n >\n {label}\n </Button>\n );\n }\n\n const hint = renderHint({ method, openInChromeIntent });\n\n return (\n <div className={cn(styles.wrapper, wrapperClassName)}>\n <Button\n aria-expanded={hintOpen}\n aria-controls={hintOpen && hint ? hintId : undefined}\n onClick={() => setHintOpen((open) => !open)}\n {...props}\n >\n {hintLabel}\n </Button>\n {hintOpen && hint ? (\n <p className={styles.hint} id={hintId}>\n {hint}\n </p>\n ) : null}\n </div>\n );\n}\n"],"mappings":"A,uPA6DA,SAAgBc,EAAc,CAC1B,QAAQ,eACR,YAAY,gBACZ,WACA,aAAad,EAAAA,mBACb,wBACA,mBACA,GAAGe,GACgB,CACnB,GAAM,CAAE,SAAQ,qBAAoB,WAAYd,EAAAA,iBAAiB,CAAE,uBAAsB,CAAC,EACpF,CAACe,EAAUC,IAAA,EAAef,EAAAA,SAAAA,CAAS,EAAK,EACxCgB,GAAA,EAASf,EAAAA,MAAAA,CAAM,EAErB,GAAIgB,IAAW,OAAQ,OAAO,KAE9B,GAAIA,IAAW,SACX,OACI,EAAAN,EAAA,IAAA,CAACT,EAAAA,OAAD,CACI,QAAS,SAAY,CACjB,IAAMgB,EAAW,MAAMC,EAAQ,EAC/BC,IAAWF,EAAW,WAAa,WAAW,CAClD,EACA,GAAIL,EAEH,SAAAQ,CACG,CAAA,EAIhB,IAAMC,EAAOC,EAAW,CAAE,SAAQ,oBAAmB,CAAC,EAEtD,OACI,EAAAZ,EAAA,KAAA,CAAC,MAAD,CAAK,UAAWR,EAAAA,GAAGC,EAAAA,QAAO,QAASoB,CAAgB,EAAnD,SAAA,EACI,EAAAb,EAAA,IAAA,CAACT,EAAAA,OAAD,CACI,gBAAeY,EACf,gBAAeA,GAAYQ,EAAON,EAAS,IAAA,GAC3C,YAAeD,EAAa,GAAS,CAACU,CAAI,EAC1C,GAAIZ,EAEH,SAAAa,CACG,CAAA,EACPZ,GAAYQ,GACT,EAAAX,EAAA,IAAA,CAAC,IAAD,CAAG,UAAWP,EAAAA,QAAO,KAAM,GAAIY,EAC1B,SAAAM,CACF,CAAA,EACH,IACH,C,EAEb,C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstallButton.js","names":[],"sources":["../../../src/components/InstallButton/InstallButton.tsx"],"sourcesContent":["import { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Button, type ButtonAsButtonProps } from \"@/components/Button\";\nimport { useInstallPrompt } from \"@/hooks/use-install-prompt\";\nimport { cn } from \"@/utils/cn\";\nimport { defaultInstallHint, type RenderInstallHint } from \"./install-hints\";\nimport styles from \"./InstallButton.module.css\";\n\nexport type InstallOutcome = \"accepted\" | \"dismissed\" | \"unsupported\";\n\nexport interface InstallButtonProps extends Omit<ButtonAsButtonProps, \"onClick\" | \"children\"> {\n /** Button label. Default `\"Instalar app\"`. */\n label?: ReactNode;\n /**\n * Label used when the browser cannot be prompted and the button reveals the\n * manual instruction instead. Default `\"Como instalar\"`.\n */\n hintLabel?: ReactNode;\n /** Called with the user's choice after the install prompt resolves. */\n onResult?: (outcome: InstallOutcome) => void;\n /**\n * Replaces the instruction shown for the `\"ios\"` and `\"manual\"` methods.\n *\n * The default copy is in PT-BR and names the real menu entries. Pass this to\n * translate it, to shorten it, or to point at a screenshot of your own.\n */\n renderHint?: RenderInstallHint;\n /**\n * How long, in ms, to wait for `beforeinstallprompt` before falling back to\n * the manual instruction. Forwarded to {@link useInstallPrompt}; defaults to\n * 3000 there.\n */\n manualFallbackDelayMs?: number;\n /** Class applied to the wrapper that holds the button and the instruction. */\n wrapperClassName?: string;\n}\n\n/**\n * Button wired to PWA installation, through {@link useInstallPrompt}.\n *\n * Where the browser fires `beforeinstallprompt`, the click installs. Where it\n * does not — iOS Safari, and the Android Chromium forks (Mi Browser, UC, Opera\n * Mini, Huawei) that strip the API — the click reveals the instruction for that\n * platform instead of the button disappearing.\n *\n * That disappearance was the defect: the component was built on\n * `useBeforeInstallPrompt`, so it rendered `null` exactly where the user needs\n * the most help, and every app re-implemented the iOS and manual paths locally.\n * Nothing renders only when there is genuinely nothing to offer — already\n * installed, running standalone, or inside the decline cooldown.\n *\n * Inherits every {@link Button} prop of the `<button>` mode (`variant`, `size`,\n * `leftIcon`, …) but not `href`: its click opens the install prompt\n * or toggles the instruction, which is an action, not a navigation.\n *\n * @example\n * <InstallButton variant=\"primary\" leftIcon={<Download />} />\n *\n * @example\n * <InstallButton renderHint={({ method }) => (method === \"ios\" ? <IOSSteps /> : <MenuSteps />)} />\n */\nexport function InstallButton({\n label = \"Instalar app\",\n hintLabel = \"Como instalar\",\n onResult,\n renderHint = defaultInstallHint,\n manualFallbackDelayMs,\n wrapperClassName,\n ...props\n}: InstallButtonProps) {\n const { method, openInChromeIntent, install } = useInstallPrompt({ manualFallbackDelayMs });\n const [hintOpen, setHintOpen] = useState(false);\n const hintId = useId();\n\n if (method === \"none\") return null;\n\n if (method === \"native\") {\n return (\n <Button\n onClick={async () => {\n const accepted = await install();\n onResult?.(accepted ? \"accepted\" : \"dismissed\");\n }}\n {...props}\n >\n {label}\n </Button>\n );\n }\n\n const hint = renderHint({ method, openInChromeIntent });\n\n return (\n <div className={cn(styles.wrapper, wrapperClassName)}>\n <Button\n aria-expanded={hintOpen}\n aria-controls={hintOpen && hint ? hintId : undefined}\n onClick={() => setHintOpen((open) => !open)}\n {...props}\n >\n {hintLabel}\n </Button>\n {hintOpen && hint ? (\n <p className={styles.hint} id={hintId}>\n {hint}\n </p>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;;;;;;AA6DA,
|
|
1
|
+
{"version":3,"file":"InstallButton.js","names":["styles","InstallButton_module_default","InstallButton","defaultInstallHint","props","useInstallPrompt","hintOpen","setHintOpen","useState","hintId","useId","method","Button","accepted","install","label","hint","renderHint","cn","wrapperClassName","open","hintLabel"],"sources":["../../../src/components/InstallButton/InstallButton.tsx"],"sourcesContent":["import { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Button, type ButtonAsButtonProps } from \"@/components/Button\";\nimport { useInstallPrompt } from \"@/hooks/use-install-prompt\";\nimport { cn } from \"@/utils/cn\";\nimport { defaultInstallHint, type RenderInstallHint } from \"./install-hints\";\nimport styles from \"./InstallButton.module.css\";\n\nexport type InstallOutcome = \"accepted\" | \"dismissed\" | \"unsupported\";\n\nexport interface InstallButtonProps extends Omit<ButtonAsButtonProps, \"onClick\" | \"children\"> {\n /** Button label. Default `\"Instalar app\"`. */\n label?: ReactNode;\n /**\n * Label used when the browser cannot be prompted and the button reveals the\n * manual instruction instead. Default `\"Como instalar\"`.\n */\n hintLabel?: ReactNode;\n /** Called with the user's choice after the install prompt resolves. */\n onResult?: (outcome: InstallOutcome) => void;\n /**\n * Replaces the instruction shown for the `\"ios\"` and `\"manual\"` methods.\n *\n * The default copy is in PT-BR and names the real menu entries. Pass this to\n * translate it, to shorten it, or to point at a screenshot of your own.\n */\n renderHint?: RenderInstallHint;\n /**\n * How long, in ms, to wait for `beforeinstallprompt` before falling back to\n * the manual instruction. Forwarded to {@link useInstallPrompt}; defaults to\n * 3000 there.\n */\n manualFallbackDelayMs?: number;\n /** Class applied to the wrapper that holds the button and the instruction. */\n wrapperClassName?: string;\n}\n\n/**\n * Button wired to PWA installation, through {@link useInstallPrompt}.\n *\n * Where the browser fires `beforeinstallprompt`, the click installs. Where it\n * does not — iOS Safari, and the Android Chromium forks (Mi Browser, UC, Opera\n * Mini, Huawei) that strip the API — the click reveals the instruction for that\n * platform instead of the button disappearing.\n *\n * That disappearance was the defect: the component was built on\n * `useBeforeInstallPrompt`, so it rendered `null` exactly where the user needs\n * the most help, and every app re-implemented the iOS and manual paths locally.\n * Nothing renders only when there is genuinely nothing to offer — already\n * installed, running standalone, or inside the decline cooldown.\n *\n * Inherits every {@link Button} prop of the `<button>` mode (`variant`, `size`,\n * `leftIcon`, …) but not `href`: its click opens the install prompt\n * or toggles the instruction, which is an action, not a navigation.\n *\n * @example\n * <InstallButton variant=\"primary\" leftIcon={<Download />} />\n *\n * @example\n * <InstallButton renderHint={({ method }) => (method === \"ios\" ? <IOSSteps /> : <MenuSteps />)} />\n */\nexport function InstallButton({\n label = \"Instalar app\",\n hintLabel = \"Como instalar\",\n onResult,\n renderHint = defaultInstallHint,\n manualFallbackDelayMs,\n wrapperClassName,\n ...props\n}: InstallButtonProps) {\n const { method, openInChromeIntent, install } = useInstallPrompt({ manualFallbackDelayMs });\n const [hintOpen, setHintOpen] = useState(false);\n const hintId = useId();\n\n if (method === \"none\") return null;\n\n if (method === \"native\") {\n return (\n <Button\n onClick={async () => {\n const accepted = await install();\n onResult?.(accepted ? \"accepted\" : \"dismissed\");\n }}\n {...props}\n >\n {label}\n </Button>\n );\n }\n\n const hint = renderHint({ method, openInChromeIntent });\n\n return (\n <div className={cn(styles.wrapper, wrapperClassName)}>\n <Button\n aria-expanded={hintOpen}\n aria-controls={hintOpen && hint ? hintId : undefined}\n onClick={() => setHintOpen((open) => !open)}\n {...props}\n >\n {hintLabel}\n </Button>\n {hintOpen && hint ? (\n <p className={styles.hint} id={hintId}>\n {hint}\n </p>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;;;;;;AA6DA,SAAgBE,EAAc,EAC1B,WAAQ,gBACR,eAAY,iBACZ,aACA,gBAAaC,GACb,0BACA,qBACA,GAAGC,KACgB;CACnB,IAAM,EAAE,WAAQ,uBAAoB,eAAYC,EAAiB,EAAE,yBAAsB,CAAC,GACpF,CAACC,GAAUC,KAAeC,EAAS,EAAK,GACxCC,IAASC,EAAM;CAErB,IAAIC,MAAW,QAAQ,OAAO;CAE9B,IAAIA,MAAW,UACX,OACI,kBAACC,GAAD;EACI,SAAS,YAAY;GACjB,IAAMC,IAAW,MAAMC,EAAQ;GAC/B,IAAWD,IAAW,aAAa,WAAW;EAClD;EACA,GAAIT;EAEH,UAAAW;CACG,CAAA;CAIhB,IAAMC,IAAOC,EAAW;EAAE;EAAQ;CAAmB,CAAC;CAEtD,OACI,kBAAC,OAAD;EAAK,WAAWC,EAAGlB,EAAO,SAASmB,CAAgB;EAAnD,UAAA,CACI,kBAACP,GAAD;GACI,iBAAeN;GACf,iBAAeA,KAAYU,IAAOP,IAAS,KAAA;GAC3C,eAAeF,GAAa,MAAS,CAACa,CAAI;GAC1C,GAAIhB;GAEH,UAAAiB;EACG,CAAA,GACPf,KAAYU,IACT,kBAAC,KAAD;GAAG,WAAWhB,EAAO;GAAM,IAAIS;GAC1B,UAAAO;EACF,CAAA,IACH,IACH;;AAEb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstallButton.module.cjs","names":[],"sources":["../../../src/components/InstallButton/InstallButton.module.css"],"sourcesContent":[".wrapper {\n display: inline-flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--tempest-space-2);\n font-family: var(--tempest-font-sans);\n}\n\n.hint {\n margin: 0;\n max-width: 36ch;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-sm);\n line-height: var(--tempest-leading-snug);\n}\n\n.hint a {\n color: var(--tempest-primary);\n}\n"],"mappings":";"}
|
|
1
|
+
{"version":3,"file":"InstallButton.module.cjs","names":["wrapper","hint","InstallButton_module_default"],"sources":["../../../src/components/InstallButton/InstallButton.module.css"],"sourcesContent":[".wrapper {\n display: inline-flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--tempest-space-2);\n font-family: var(--tempest-font-sans);\n}\n\n.hint {\n margin: 0;\n max-width: 36ch;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-sm);\n line-height: var(--tempest-leading-snug);\n}\n\n.hint a {\n color: var(--tempest-primary);\n}\n"],"mappings":";"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstallButton.module.js","names":[],"sources":["../../../src/components/InstallButton/InstallButton.module.css"],"sourcesContent":[".wrapper {\n display: inline-flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--tempest-space-2);\n font-family: var(--tempest-font-sans);\n}\n\n.hint {\n margin: 0;\n max-width: 36ch;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-sm);\n line-height: var(--tempest-leading-snug);\n}\n\n.hint a {\n color: var(--tempest-primary);\n}\n"],"mappings":";"}
|
|
1
|
+
{"version":3,"file":"InstallButton.module.js","names":["wrapper","hint","InstallButton_module_default"],"sources":["../../../src/components/InstallButton/InstallButton.module.css"],"sourcesContent":[".wrapper {\n display: inline-flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--tempest-space-2);\n font-family: var(--tempest-font-sans);\n}\n\n.hint {\n margin: 0;\n max-width: 36ch;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-sm);\n line-height: var(--tempest-leading-snug);\n}\n\n.hint a {\n color: var(--tempest-primary);\n}\n"],"mappings":";"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install-hints.cjs","names":[],"sources":["../../../src/components/InstallButton/install-hints.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\n\nimport type { InstallMethod } from \"@/hooks/use-install-prompt\";\n\n/** What an install affordance needs to render the instruction for a method. */\nexport interface InstallHintInput {\n /** The strategy `useInstallPrompt` resolved. */\n method: InstallMethod;\n /** An `intent://` URL that re-opens the page in Chrome on Android, if any. */\n openInChromeIntent: string | null;\n}\n\n/** Renders the instruction shown when the browser has no install prompt. */\nexport type RenderInstallHint = (input: InstallHintInput) => ReactNode;\n\n/**\n * The default instruction for a browser that cannot be prompted.\n *\n * Written out rather than left to the app because every app wrote the same two\n * sentences, and getting them wrong is invisible: an iOS user who is told to\n * look for an \"Install\" menu never finds one, because Safari puts it behind the\n * Share sheet.\n *\n * On an Android fork the copy also offers the `intent://` link the SDK already\n * builds — reopening the page in Chrome is the only path that reaches a real\n * install on a browser whose menu has no install entry at all.\n *\n * @param input - The resolved method and the optional Chrome intent.\n * @returns The instruction, or `null` when the method needs none.\n */\nexport function defaultInstallHint({ method, openInChromeIntent }: InstallHintInput): ReactNode {\n if (method === \"ios\") {\n return (\n <>\n Toque em <strong>Compartilhar</strong> e escolha{\" \"}\n <strong>Adicionar à Tela de Início</strong>.\n </>\n );\n }\n if (method === \"manual\") {\n return (\n <>\n Abra o menu do navegador (<strong>⋮</strong>) e escolha{\" \"}\n <strong>Instalar app</strong>.\n {openInChromeIntent ? (\n <>\n {\" \"}\n Se não houver essa opção, <a href={openInChromeIntent}>abra no Chrome</a>.\n </>\n ) : null}\n </>\n );\n }\n return null;\n}\n"],"mappings":"mCA8BA,
|
|
1
|
+
{"version":3,"file":"install-hints.cjs","names":["_Fragment","react_jsx_runtime","defaultInstallHint","method","openInChromeIntent"],"sources":["../../../src/components/InstallButton/install-hints.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\n\nimport type { InstallMethod } from \"@/hooks/use-install-prompt\";\n\n/** What an install affordance needs to render the instruction for a method. */\nexport interface InstallHintInput {\n /** The strategy `useInstallPrompt` resolved. */\n method: InstallMethod;\n /** An `intent://` URL that re-opens the page in Chrome on Android, if any. */\n openInChromeIntent: string | null;\n}\n\n/** Renders the instruction shown when the browser has no install prompt. */\nexport type RenderInstallHint = (input: InstallHintInput) => ReactNode;\n\n/**\n * The default instruction for a browser that cannot be prompted.\n *\n * Written out rather than left to the app because every app wrote the same two\n * sentences, and getting them wrong is invisible: an iOS user who is told to\n * look for an \"Install\" menu never finds one, because Safari puts it behind the\n * Share sheet.\n *\n * On an Android fork the copy also offers the `intent://` link the SDK already\n * builds — reopening the page in Chrome is the only path that reaches a real\n * install on a browser whose menu has no install entry at all.\n *\n * @param input - The resolved method and the optional Chrome intent.\n * @returns The instruction, or `null` when the method needs none.\n */\nexport function defaultInstallHint({ method, openInChromeIntent }: InstallHintInput): ReactNode {\n if (method === \"ios\") {\n return (\n <>\n Toque em <strong>Compartilhar</strong> e escolha{\" \"}\n <strong>Adicionar à Tela de Início</strong>.\n </>\n );\n }\n if (method === \"manual\") {\n return (\n <>\n Abra o menu do navegador (<strong>⋮</strong>) e escolha{\" \"}\n <strong>Instalar app</strong>.\n {openInChromeIntent ? (\n <>\n {\" \"}\n Se não houver essa opção, <a href={openInChromeIntent}>abra no Chrome</a>.\n </>\n ) : null}\n </>\n );\n }\n return null;\n}\n"],"mappings":"A,mCA8BA,SAAgBE,EAAmB,CAAE,SAAQ,sBAAmD,CAuB5F,OAtBIC,IAAW,OAEP,EAAAF,EAAA,KAAA,CAAAD,EAAAA,SAAA,CAAA,SAAA,CAAE,aACW,EAAAC,EAAA,IAAA,CAAC,SAAD,CAAA,SAAQ,cAAoB,CAAA,EAAC,aAAW,KACjD,EAAAA,EAAA,IAAA,CAAC,SAAD,CAAA,SAAQ,4BAAkC,CAAA,EAAC,GAC7C,CAAA,CAAA,EAGNE,IAAW,UAEP,EAAAF,EAAA,KAAA,CAAAD,EAAAA,SAAA,CAAA,SAAA,CAAE,8BAC4B,EAAAC,EAAA,IAAA,CAAC,SAAD,CAAA,SAAQ,GAAS,CAAA,EAAC,cAAY,KACxD,EAAAA,EAAA,IAAA,CAAC,SAAD,CAAA,SAAQ,cAAoB,CAAA,EAAC,IAC5BG,GACG,EAAAH,EAAA,KAAA,CAAAD,EAAAA,SAAA,CAAA,SAAA,CACK,IAAI,8BACqB,EAAAC,EAAA,IAAA,CAAC,IAAD,CAAG,KAAMG,EAAoB,SAAA,gBAAiB,CAAA,EAAC,GAC3E,CAAA,CAAA,EACF,IACN,CAAA,CAAA,EAGH,IACX,C"}
|