@wasto/cms-components 1.5.10 → 1.5.11

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.
Files changed (98) hide show
  1. package/README.md +47 -47
  2. package/dist/index.d.mts +103 -2
  3. package/dist/index.d.ts +103 -2
  4. package/dist/index.js +2861 -2442
  5. package/dist/index.mjs +3651 -3227
  6. package/package.json +2 -2
  7. package/src/components/announcement-modal/AnnouncementModal.tsx +183 -183
  8. package/src/components/article/Article.tsx +21 -21
  9. package/src/components/article/ArticleCard.tsx +81 -81
  10. package/src/components/article/ArticleExcerpts.tsx +80 -80
  11. package/src/components/article/ArticleList.tsx +114 -114
  12. package/src/components/article/ArticleMarkdown.tsx +170 -170
  13. package/src/components/article/ArticleReaderModal.tsx +93 -93
  14. package/src/components/article/ArticleSingle.tsx +57 -57
  15. package/src/components/bottom-tab/BottomTab.tsx +392 -392
  16. package/src/components/button/Button.tsx +154 -154
  17. package/src/components/challenge/Badges.tsx +84 -84
  18. package/src/components/challenge/BadgesModal.tsx +166 -166
  19. package/src/components/challenge/Challenge.tsx +380 -380
  20. package/src/components/challenge/ChallengeModal.tsx +231 -231
  21. package/src/components/challenge/ChallengeVignette.tsx +249 -249
  22. package/src/components/challenge/ChallengesModal.tsx +243 -243
  23. package/src/components/challenge/QuizModal.tsx +381 -381
  24. package/src/components/challenge/ResultModal.tsx +144 -144
  25. package/src/components/chat/Chat.tsx +928 -928
  26. package/src/components/collection-calendar/CollectionCalendar.tsx +274 -274
  27. package/src/components/columns/Columns.tsx +33 -33
  28. package/src/components/consignes-modal/ConsignesModal.tsx +267 -267
  29. package/src/components/content-inset/ContentInset.tsx +33 -33
  30. package/src/components/header/Header.tsx +391 -391
  31. package/src/components/image/Image.tsx +15 -15
  32. package/src/components/image/ImageFrame.tsx +102 -102
  33. package/src/components/image/ImageMedia.tsx +31 -31
  34. package/src/components/image/ImageUrl.tsx +30 -30
  35. package/src/components/locations-map/LocationSheet.tsx +417 -417
  36. package/src/components/locations-map/LocationsMap.native.tsx +260 -260
  37. package/src/components/locations-map/LocationsMap.tsx +13 -13
  38. package/src/components/locations-map/LocationsMap.web.tsx +10 -10
  39. package/src/components/locations-map/LocationsMapShell.tsx +527 -527
  40. package/src/components/locations-map/LocationsMapView.tsx +108 -108
  41. package/src/components/locations-map/LocationsMapView.web.tsx +331 -331
  42. package/src/components/nav-button/NavButton.tsx +59 -59
  43. package/src/components/next-collection/NextCollection.tsx +636 -621
  44. package/src/components/notifications/NotificationsScreen.tsx +247 -247
  45. package/src/components/page/Page.tsx +102 -64
  46. package/src/components/parapraph/Paragraph.tsx +67 -67
  47. package/src/components/profile/ProfileScreen.tsx +236 -236
  48. package/src/components/recycling-info/RecyclingInfo.tsx +189 -189
  49. package/src/components/safe-area/OptionalSafeAreaProvider.tsx +17 -17
  50. package/src/components/search/Search.tsx +320 -320
  51. package/src/components/select-street-modal/SelectStreetModal.tsx +475 -475
  52. package/src/components/title/Title.tsx +100 -100
  53. package/src/components/vision/Vision.tsx +447 -447
  54. package/src/components/vision/VisionActionCard.tsx +117 -117
  55. package/src/components/vision/VisionCapture.tsx +30 -30
  56. package/src/components/vision/VisionTapOverlay.tsx +122 -122
  57. package/src/contexts/AnnouncementsContext.tsx +171 -171
  58. package/src/contexts/AppDataContext.tsx +458 -0
  59. package/src/contexts/ChallengesContext.tsx +182 -182
  60. package/src/contexts/LocalContext.tsx +227 -227
  61. package/src/contexts/ThemeContext.tsx +37 -37
  62. package/src/contexts/WastoContext.tsx +130 -127
  63. package/src/helpers/blogPost.ts +72 -72
  64. package/src/helpers/generateQuizQuestions.ts +247 -247
  65. package/src/helpers/getContrastColor.ts +18 -18
  66. package/src/helpers/haptics.ts +20 -20
  67. package/src/helpers/hoursSchedule.ts +230 -230
  68. package/src/helpers/htmlContentToMarkdown.ts +114 -114
  69. package/src/helpers/layout.ts +54 -54
  70. package/src/helpers/loadLinearGradient.ts +22 -22
  71. package/src/helpers/mapLocations.ts +170 -0
  72. package/src/helpers/maquetteTheme.ts +76 -76
  73. package/src/helpers/markdownUnderlinePlugin.ts +32 -32
  74. package/src/helpers/nextCollection.ts +122 -0
  75. package/src/helpers/normalizeWasteTypeRecyclingInfo.ts +80 -80
  76. package/src/helpers/publicMediaUrl.ts +8 -8
  77. package/src/helpers/resolveApiAssetUrl.ts +21 -21
  78. package/src/helpers/systemRoutes.ts +7 -7
  79. package/src/helpers/themeStyles.ts +114 -114
  80. package/src/helpers/ttlCache.ts +41 -0
  81. package/src/helpers/useSafeAreaPadding.ts +14 -14
  82. package/src/hooks/useBadges.ts +100 -100
  83. package/src/hooks/useBlogPosts.ts +109 -105
  84. package/src/hooks/useChallenges.ts +110 -110
  85. package/src/hooks/useCities.ts +56 -56
  86. package/src/hooks/useCityAnnouncements.ts +118 -118
  87. package/src/hooks/useCollectionCalendar.ts +421 -421
  88. package/src/hooks/useColumns.ts +19 -19
  89. package/src/hooks/useConsignes.ts +62 -62
  90. package/src/hooks/useLocations.ts +120 -248
  91. package/src/hooks/useNextCollection.ts +163 -238
  92. package/src/hooks/useRecyclingInfo.ts +90 -90
  93. package/src/hooks/useWastoClient.ts +16 -16
  94. package/src/index.ts +149 -142
  95. package/src/navigation/NavigationContext.tsx +56 -56
  96. package/src/sentry/initSentry.ts +120 -120
  97. package/src/types/Theme.ts +72 -72
  98. package/src/types/css-modules.d.ts +1 -1
package/README.md CHANGED
@@ -1,47 +1,47 @@
1
- # @wasto/cms-components
2
-
3
- Composants CMS pour apps Expo / React Native (New Architecture, Bridgeless).
4
-
5
- Metro doit charger le **source** (`src/`, champ `"react-native"`), pas seulement `dist/`. Ne pas forcer `react-native-safe-area-context/lib/commonjs` dans `metro.config.js` : ça casse le codegen Fabric (`RNCSafeArea*`).
6
-
7
- ## Peers
8
-
9
- | Package | Obligatoire | Notes |
10
- |--------|-------------|--------|
11
- | `react`, `react-native` | oui | RN 0.81+ / Expo 54+ |
12
- | `react-native-safe-area-context` | oui | `~5.6.0` — une seule copie, hoisted |
13
- | `@react-navigation/bottom-tabs` | oui | Types `BottomTab` (tabBar) |
14
- | `expo-image`, `lucide-react-native`, `@react-native-async-storage/async-storage`, `@wasto/sdk` | oui | |
15
- | `expo-router` | **optionnel** | Apps Expo Router : fournir `NavigationProvider` qui délègue à `router` |
16
- | `@maplibre/maplibre-react-native` | **optionnel** | Requis sur iOS/Android pour afficher la carte |
17
- | `maplibre-gl` | **optionnel** | Requis sur **web** (PWA / playground) pour la carte tuiles |
18
-
19
- ### Navigation
20
-
21
- `Header` / `NextCollection` n’importent plus `expo-router`. L’hôte enveloppe l’app avec `NavigationProvider` :
22
-
23
- ```tsx
24
- import { NavigationProvider } from "@wasto/cms-components";
25
- import { router } from "expo-router"; // ou React Navigation
26
-
27
- <NavigationProvider
28
- value={{
29
- push: (href) => router.push(href as never),
30
- canGoBack: () => router.canGoBack(),
31
- goBack: () => router.back(),
32
- }}
33
- >
34
- …
35
- </NavigationProvider>
36
- ```
37
-
38
- ## Carte (`LocationsMap`)
39
-
40
- ```ts
41
- import { LocationsMap } from "@wasto/cms-components"
42
- ```
43
-
44
- - **iOS / Android** : Metro charge `LocationsMap.native.tsx` (MapLibre React Native).
45
- - **Web** : Metro charge `LocationsMapView.web.tsx` (MapLibre GL JS, style OpenFreeMap) si `maplibre-gl` est installé ; sinon fallback pins (`LocationsMapView.tsx`).
46
-
47
- Sur native : dépendance + plugin Expo `@maplibre/maplibre-react-native`, puis rebuild (`expo run:ios`). pnpm : le module doit être résolvable depuis la racine (`shamefully-hoist` ou `extraNodeModules`).
1
+ # @wasto/cms-components
2
+
3
+ Composants CMS pour apps Expo / React Native (New Architecture, Bridgeless).
4
+
5
+ Metro doit charger le **source** (`src/`, champ `"react-native"`), pas seulement `dist/`. Ne pas forcer `react-native-safe-area-context/lib/commonjs` dans `metro.config.js` : ça casse le codegen Fabric (`RNCSafeArea*`).
6
+
7
+ ## Peers
8
+
9
+ | Package | Obligatoire | Notes |
10
+ |--------|-------------|--------|
11
+ | `react`, `react-native` | oui | RN 0.81+ / Expo 54+ |
12
+ | `react-native-safe-area-context` | oui | `~5.6.0` — une seule copie, hoisted |
13
+ | `@react-navigation/bottom-tabs` | oui | Types `BottomTab` (tabBar) |
14
+ | `expo-image`, `lucide-react-native`, `@react-native-async-storage/async-storage`, `@wasto/sdk` | oui | |
15
+ | `expo-router` | **optionnel** | Apps Expo Router : fournir `NavigationProvider` qui délègue à `router` |
16
+ | `@maplibre/maplibre-react-native` | **optionnel** | Requis sur iOS/Android pour afficher la carte |
17
+ | `maplibre-gl` | **optionnel** | Requis sur **web** (PWA / playground) pour la carte tuiles |
18
+
19
+ ### Navigation
20
+
21
+ `Header` / `NextCollection` n’importent plus `expo-router`. L’hôte enveloppe l’app avec `NavigationProvider` :
22
+
23
+ ```tsx
24
+ import { NavigationProvider } from "@wasto/cms-components";
25
+ import { router } from "expo-router"; // ou React Navigation
26
+
27
+ <NavigationProvider
28
+ value={{
29
+ push: (href) => router.push(href as never),
30
+ canGoBack: () => router.canGoBack(),
31
+ goBack: () => router.back(),
32
+ }}
33
+ >
34
+ …
35
+ </NavigationProvider>
36
+ ```
37
+
38
+ ## Carte (`LocationsMap`)
39
+
40
+ ```ts
41
+ import { LocationsMap } from "@wasto/cms-components"
42
+ ```
43
+
44
+ - **iOS / Android** : Metro charge `LocationsMap.native.tsx` (MapLibre React Native).
45
+ - **Web** : Metro charge `LocationsMapView.web.tsx` (MapLibre GL JS, style OpenFreeMap) si `maplibre-gl` est installé ; sinon fallback pins (`LocationsMapView.tsx`).
46
+
47
+ Sur native : dépendance + plugin Expo `@maplibre/maplibre-react-native`, puis rebuild (`expo run:ios`). pnpm : le module doit être résolvable depuis la racine (`shamefully-hoist` ou `extraNodeModules`).
package/dist/index.d.mts CHANGED
@@ -65,6 +65,31 @@ type ImageUrlProps = {
65
65
  type ImageProps = ImageUrlProps | ImageMediaProps;
66
66
  declare function Image(props: ImageProps): ReactNode;
67
67
 
68
+ type HoursDayRow = {
69
+ label: string;
70
+ hours: string;
71
+ closed: boolean;
72
+ };
73
+ type HoursStatus = {
74
+ open: boolean;
75
+ text: string;
76
+ };
77
+
78
+ type LocationCategory = "recycling" | "decheterie" | "collection_place" | "sorting_center";
79
+ type MapLocation = {
80
+ id: string;
81
+ name: string;
82
+ category: LocationCategory;
83
+ address?: string;
84
+ phone?: string;
85
+ hoursDisplay?: string;
86
+ hoursRows?: HoursDayRow[];
87
+ hoursStatus?: HoursStatus | null;
88
+ lat: number;
89
+ lon: number;
90
+ badges?: string[];
91
+ };
92
+
68
93
  type LocationsMapProps = {
69
94
  fullScreen?: boolean;
70
95
  showFilters?: boolean;
@@ -94,13 +119,18 @@ declare function NextCollection({ calendarHref, showCalendarCta, dayOffset, }: N
94
119
  type PageProps = PropsWithChildren & {
95
120
  /** When false, content fills the screen without scrolling (e.g. fullScreen map). Default true. */
96
121
  scroll?: boolean;
122
+ /**
123
+ * Pull-to-refresh : force refresh du cache tri + carte (TTL 1 semaine).
124
+ * Default true when scrollable.
125
+ */
126
+ pullToRefresh?: boolean;
97
127
  };
98
128
  /**
99
129
  * Page shell: top safe area + optional vertical scroll.
100
130
  * No global horizontal padding — each block uses ContentInset or is full-bleed
101
131
  * (map, calendar grid). Bottom inset is handled by BottomTab when using tabs.
102
132
  */
103
- declare function Page({ children, scroll }: PageProps): ReactNode;
133
+ declare function Page({ children, scroll, pullToRefresh, }: PageProps): ReactNode;
104
134
 
105
135
  type ContentInsetProps = PropsWithChildren & {
106
136
  /** Use 12px horizontal instead of 16px */
@@ -360,6 +390,77 @@ type WastoProviderProps = PropsWithChildren & {
360
390
  declare function WastoProvider(props: WastoProviderProps): ReactNode;
361
391
  declare function useWasto(): WastoContextType;
362
392
 
393
+ type City = {
394
+ id: string;
395
+ name: string;
396
+ status?: "NON_ACTIF" | "INCOMPLET" | "ACTIF" | "MAINTENANCE";
397
+ [key: string]: unknown;
398
+ };
399
+ type WasteType = {
400
+ id: string;
401
+ name?: string;
402
+ icon?: string;
403
+ imageUrl?: string | null;
404
+ color?: string;
405
+ [key: string]: unknown;
406
+ };
407
+ type WasteCollectionPlace = {
408
+ id: string;
409
+ name?: string;
410
+ collectionDays?: Array<{
411
+ /** Ex: "Lundi", "Mardi", ... (mapping lundi=0 … dimanche=6) */
412
+ name: string;
413
+ wasteTypeId: string;
414
+ biweekly?: boolean;
415
+ startDate?: string;
416
+ }>;
417
+ /** Périodes d’exception (pas de collecte) */
418
+ exceptions?: Array<{
419
+ dateFrom: string;
420
+ dateTo: string;
421
+ }>;
422
+ [key: string]: unknown;
423
+ };
424
+ type CollectionForDay = {
425
+ id: string;
426
+ name: string;
427
+ icon?: string;
428
+ imageUrl?: string | null;
429
+ color?: string;
430
+ contrastColor?: "#000000" | "#FFFFFF";
431
+ };
432
+
433
+ /** Fenêtre préchargée pour le carrousel « prochaines collectes ». */
434
+ declare const NEXT_EVENTS_DAY_RADIUS = 3;
435
+ type AppDataContextType = {
436
+ /** True tant que events ±3j + mois calendrier ne sont pas prêts (loader post-splash). */
437
+ isBootstrapping: boolean;
438
+ city: City | null;
439
+ wasteTypes: WasteType[];
440
+ wasteCollectionPlaces: WasteCollectionPlace[];
441
+ /** Collectes précalculées pour offsets -3 … +3. */
442
+ nextEventsByOffset: Record<number, CollectionForDay[]>;
443
+ locations: MapLocation[];
444
+ mapCenter: {
445
+ lat: number;
446
+ lon: number;
447
+ };
448
+ isMapLoading: boolean;
449
+ isRecyclingLoading: boolean;
450
+ scheduleError: string | null;
451
+ mapError: string | null;
452
+ /**
453
+ * Force-refresh tri + carte (invalide le TTL).
454
+ * Utilisé par le pull-to-refresh.
455
+ */
456
+ refreshCachedData: () => Promise<void>;
457
+ /** Recharge events + calendrier (critique). */
458
+ refreshSchedule: () => Promise<void>;
459
+ };
460
+ declare function useAppData(): AppDataContextType;
461
+ /** Safe variant for hooks that may run outside (preview / tests). */
462
+ declare function useOptionalAppData(): AppDataContextType | null;
463
+
363
464
  /** Shared Wasto HTTP client wired with optional API error reporting. */
364
465
  declare function useWastoClient(): WastoClient;
365
466
 
@@ -462,4 +563,4 @@ declare function useAppNavigation(): NavigationApi;
462
563
  /** Soft read — returns null when no provider (e.g. isolated component tests). */
463
564
  declare function useOptionalAppNavigation(): NavigationApi | null;
464
565
 
465
- export { type AppHeaderActionElement, type AppHeaderConfig, type AppHeaderElement, type AppHeaderLogoElement, type AppHeaderSlot, type AppHeaderTitleElement, Article, type ArticleDisplayMode, type ArticleProps, BottomTab, type BottomTabProps, Challenge, type ChallengeProps, ChallengeVignette, type ChallengeVignetteProps, Chat, type ChatProps, CollectionCalendar, type CollectionCalendarProps, Columns, type ColumnsColumnCount, type ColumnsProps, ContentInset, type ContentInsetProps, Header, type HeaderProps, Image, type ImageProps, LocationsMap, type LocationsMapProps, MAQUETTE_COLORS, MAQUETTE_RADII, type NavigationApi, NavigationProvider, type NavigationProviderProps, NextCollection, type NextCollectionProps, NotificationsScreen, Page, type PageProps, Paragraph, type PararaphProps, ProfileScreen, RecyclingInfo, type RecyclingInfoProps, type ResolvedTheme, SPACE, SYSTEM_ROUTES, Search, type SearchProps, type SystemRouteKey, type Theme, type ThemeShadowStyle, Title, type TitleLevel, type TitleProps, Vision, type VisionActionCardProps, type VisionCaptureResult, type VisionProps, type VisionSuggestion, type WastoContextType, type WastoErrorContext, WastoProvider, type WastoProviderProps, type WastoSentryConfig, cardStyle, coloredShadow, createMaquetteTheme, groupedSectionStyle, initWastoSentry, isWastoSentryActive, reportError, resolveTheme, softCardStyle, useAppNavigation, useOptionalAppNavigation, useWasto, useWastoClient, wrapWithSentry };
566
+ export { type AppDataContextType, type AppHeaderActionElement, type AppHeaderConfig, type AppHeaderElement, type AppHeaderLogoElement, type AppHeaderSlot, type AppHeaderTitleElement, Article, type ArticleDisplayMode, type ArticleProps, BottomTab, type BottomTabProps, Challenge, type ChallengeProps, ChallengeVignette, type ChallengeVignetteProps, Chat, type ChatProps, CollectionCalendar, type CollectionCalendarProps, Columns, type ColumnsColumnCount, type ColumnsProps, ContentInset, type ContentInsetProps, Header, type HeaderProps, Image, type ImageProps, LocationsMap, type LocationsMapProps, MAQUETTE_COLORS, MAQUETTE_RADII, NEXT_EVENTS_DAY_RADIUS, type NavigationApi, NavigationProvider, type NavigationProviderProps, NextCollection, type NextCollectionProps, NotificationsScreen, Page, type PageProps, Paragraph, type PararaphProps, ProfileScreen, RecyclingInfo, type RecyclingInfoProps, type ResolvedTheme, SPACE, SYSTEM_ROUTES, Search, type SearchProps, type SystemRouteKey, type Theme, type ThemeShadowStyle, Title, type TitleLevel, type TitleProps, Vision, type VisionActionCardProps, type VisionCaptureResult, type VisionProps, type VisionSuggestion, type WastoContextType, type WastoErrorContext, WastoProvider, type WastoProviderProps, type WastoSentryConfig, cardStyle, coloredShadow, createMaquetteTheme, groupedSectionStyle, initWastoSentry, isWastoSentryActive, reportError, resolveTheme, softCardStyle, useAppData, useAppNavigation, useOptionalAppData, useOptionalAppNavigation, useWasto, useWastoClient, wrapWithSentry };
package/dist/index.d.ts CHANGED
@@ -65,6 +65,31 @@ type ImageUrlProps = {
65
65
  type ImageProps = ImageUrlProps | ImageMediaProps;
66
66
  declare function Image(props: ImageProps): ReactNode;
67
67
 
68
+ type HoursDayRow = {
69
+ label: string;
70
+ hours: string;
71
+ closed: boolean;
72
+ };
73
+ type HoursStatus = {
74
+ open: boolean;
75
+ text: string;
76
+ };
77
+
78
+ type LocationCategory = "recycling" | "decheterie" | "collection_place" | "sorting_center";
79
+ type MapLocation = {
80
+ id: string;
81
+ name: string;
82
+ category: LocationCategory;
83
+ address?: string;
84
+ phone?: string;
85
+ hoursDisplay?: string;
86
+ hoursRows?: HoursDayRow[];
87
+ hoursStatus?: HoursStatus | null;
88
+ lat: number;
89
+ lon: number;
90
+ badges?: string[];
91
+ };
92
+
68
93
  type LocationsMapProps = {
69
94
  fullScreen?: boolean;
70
95
  showFilters?: boolean;
@@ -94,13 +119,18 @@ declare function NextCollection({ calendarHref, showCalendarCta, dayOffset, }: N
94
119
  type PageProps = PropsWithChildren & {
95
120
  /** When false, content fills the screen without scrolling (e.g. fullScreen map). Default true. */
96
121
  scroll?: boolean;
122
+ /**
123
+ * Pull-to-refresh : force refresh du cache tri + carte (TTL 1 semaine).
124
+ * Default true when scrollable.
125
+ */
126
+ pullToRefresh?: boolean;
97
127
  };
98
128
  /**
99
129
  * Page shell: top safe area + optional vertical scroll.
100
130
  * No global horizontal padding — each block uses ContentInset or is full-bleed
101
131
  * (map, calendar grid). Bottom inset is handled by BottomTab when using tabs.
102
132
  */
103
- declare function Page({ children, scroll }: PageProps): ReactNode;
133
+ declare function Page({ children, scroll, pullToRefresh, }: PageProps): ReactNode;
104
134
 
105
135
  type ContentInsetProps = PropsWithChildren & {
106
136
  /** Use 12px horizontal instead of 16px */
@@ -360,6 +390,77 @@ type WastoProviderProps = PropsWithChildren & {
360
390
  declare function WastoProvider(props: WastoProviderProps): ReactNode;
361
391
  declare function useWasto(): WastoContextType;
362
392
 
393
+ type City = {
394
+ id: string;
395
+ name: string;
396
+ status?: "NON_ACTIF" | "INCOMPLET" | "ACTIF" | "MAINTENANCE";
397
+ [key: string]: unknown;
398
+ };
399
+ type WasteType = {
400
+ id: string;
401
+ name?: string;
402
+ icon?: string;
403
+ imageUrl?: string | null;
404
+ color?: string;
405
+ [key: string]: unknown;
406
+ };
407
+ type WasteCollectionPlace = {
408
+ id: string;
409
+ name?: string;
410
+ collectionDays?: Array<{
411
+ /** Ex: "Lundi", "Mardi", ... (mapping lundi=0 … dimanche=6) */
412
+ name: string;
413
+ wasteTypeId: string;
414
+ biweekly?: boolean;
415
+ startDate?: string;
416
+ }>;
417
+ /** Périodes d’exception (pas de collecte) */
418
+ exceptions?: Array<{
419
+ dateFrom: string;
420
+ dateTo: string;
421
+ }>;
422
+ [key: string]: unknown;
423
+ };
424
+ type CollectionForDay = {
425
+ id: string;
426
+ name: string;
427
+ icon?: string;
428
+ imageUrl?: string | null;
429
+ color?: string;
430
+ contrastColor?: "#000000" | "#FFFFFF";
431
+ };
432
+
433
+ /** Fenêtre préchargée pour le carrousel « prochaines collectes ». */
434
+ declare const NEXT_EVENTS_DAY_RADIUS = 3;
435
+ type AppDataContextType = {
436
+ /** True tant que events ±3j + mois calendrier ne sont pas prêts (loader post-splash). */
437
+ isBootstrapping: boolean;
438
+ city: City | null;
439
+ wasteTypes: WasteType[];
440
+ wasteCollectionPlaces: WasteCollectionPlace[];
441
+ /** Collectes précalculées pour offsets -3 … +3. */
442
+ nextEventsByOffset: Record<number, CollectionForDay[]>;
443
+ locations: MapLocation[];
444
+ mapCenter: {
445
+ lat: number;
446
+ lon: number;
447
+ };
448
+ isMapLoading: boolean;
449
+ isRecyclingLoading: boolean;
450
+ scheduleError: string | null;
451
+ mapError: string | null;
452
+ /**
453
+ * Force-refresh tri + carte (invalide le TTL).
454
+ * Utilisé par le pull-to-refresh.
455
+ */
456
+ refreshCachedData: () => Promise<void>;
457
+ /** Recharge events + calendrier (critique). */
458
+ refreshSchedule: () => Promise<void>;
459
+ };
460
+ declare function useAppData(): AppDataContextType;
461
+ /** Safe variant for hooks that may run outside (preview / tests). */
462
+ declare function useOptionalAppData(): AppDataContextType | null;
463
+
363
464
  /** Shared Wasto HTTP client wired with optional API error reporting. */
364
465
  declare function useWastoClient(): WastoClient;
365
466
 
@@ -462,4 +563,4 @@ declare function useAppNavigation(): NavigationApi;
462
563
  /** Soft read — returns null when no provider (e.g. isolated component tests). */
463
564
  declare function useOptionalAppNavigation(): NavigationApi | null;
464
565
 
465
- export { type AppHeaderActionElement, type AppHeaderConfig, type AppHeaderElement, type AppHeaderLogoElement, type AppHeaderSlot, type AppHeaderTitleElement, Article, type ArticleDisplayMode, type ArticleProps, BottomTab, type BottomTabProps, Challenge, type ChallengeProps, ChallengeVignette, type ChallengeVignetteProps, Chat, type ChatProps, CollectionCalendar, type CollectionCalendarProps, Columns, type ColumnsColumnCount, type ColumnsProps, ContentInset, type ContentInsetProps, Header, type HeaderProps, Image, type ImageProps, LocationsMap, type LocationsMapProps, MAQUETTE_COLORS, MAQUETTE_RADII, type NavigationApi, NavigationProvider, type NavigationProviderProps, NextCollection, type NextCollectionProps, NotificationsScreen, Page, type PageProps, Paragraph, type PararaphProps, ProfileScreen, RecyclingInfo, type RecyclingInfoProps, type ResolvedTheme, SPACE, SYSTEM_ROUTES, Search, type SearchProps, type SystemRouteKey, type Theme, type ThemeShadowStyle, Title, type TitleLevel, type TitleProps, Vision, type VisionActionCardProps, type VisionCaptureResult, type VisionProps, type VisionSuggestion, type WastoContextType, type WastoErrorContext, WastoProvider, type WastoProviderProps, type WastoSentryConfig, cardStyle, coloredShadow, createMaquetteTheme, groupedSectionStyle, initWastoSentry, isWastoSentryActive, reportError, resolveTheme, softCardStyle, useAppNavigation, useOptionalAppNavigation, useWasto, useWastoClient, wrapWithSentry };
566
+ export { type AppDataContextType, type AppHeaderActionElement, type AppHeaderConfig, type AppHeaderElement, type AppHeaderLogoElement, type AppHeaderSlot, type AppHeaderTitleElement, Article, type ArticleDisplayMode, type ArticleProps, BottomTab, type BottomTabProps, Challenge, type ChallengeProps, ChallengeVignette, type ChallengeVignetteProps, Chat, type ChatProps, CollectionCalendar, type CollectionCalendarProps, Columns, type ColumnsColumnCount, type ColumnsProps, ContentInset, type ContentInsetProps, Header, type HeaderProps, Image, type ImageProps, LocationsMap, type LocationsMapProps, MAQUETTE_COLORS, MAQUETTE_RADII, NEXT_EVENTS_DAY_RADIUS, type NavigationApi, NavigationProvider, type NavigationProviderProps, NextCollection, type NextCollectionProps, NotificationsScreen, Page, type PageProps, Paragraph, type PararaphProps, ProfileScreen, RecyclingInfo, type RecyclingInfoProps, type ResolvedTheme, SPACE, SYSTEM_ROUTES, Search, type SearchProps, type SystemRouteKey, type Theme, type ThemeShadowStyle, Title, type TitleLevel, type TitleProps, Vision, type VisionActionCardProps, type VisionCaptureResult, type VisionProps, type VisionSuggestion, type WastoContextType, type WastoErrorContext, WastoProvider, type WastoProviderProps, type WastoSentryConfig, cardStyle, coloredShadow, createMaquetteTheme, groupedSectionStyle, initWastoSentry, isWastoSentryActive, reportError, resolveTheme, softCardStyle, useAppData, useAppNavigation, useOptionalAppData, useOptionalAppNavigation, useWasto, useWastoClient, wrapWithSentry };