@navigoo/map-components 1.0.2 → 1.0.3

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.
@@ -9,6 +9,7 @@ interface DashboardProps {
9
9
  setRoutes: (routes: Route[]) => void;
10
10
  setSelectedRouteIndex: (index: number) => void;
11
11
  isTracking: boolean;
12
+ className?: string;
12
13
  }
13
14
  declare const Dashboard: React.FC<DashboardProps>;
14
15
  export default Dashboard;
@@ -11,15 +11,9 @@ const RouteSearch_1 = __importDefault(require("./RouteSearch"));
11
11
  const DetourRouteSearch_1 = __importDefault(require("./DetourRouteSearch"));
12
12
  const TransportOptions_1 = __importDefault(require("./TransportOptions"));
13
13
  const TripType_1 = __importDefault(require("./TripType"));
14
- const styles_module_css_1 = __importDefault(require("./styles.module.css"));
15
- const lucide_react_1 = require("lucide-react");
16
- const Dashboard = ({ apiClient, setUserLocation, setSearchedPlace, setIsTracking, setRoutes, setSelectedRouteIndex, isTracking, }) => {
17
- const [activeSection, setActiveSection] = (0, react_1.useState)(null);
14
+ const Dashboard = ({ apiClient, setUserLocation, setSearchedPlace, setIsTracking, setRoutes, setSelectedRouteIndex, isTracking, className, }) => {
18
15
  const [geoLoading, setGeoLoading] = (0, react_1.useState)(false);
19
16
  const [geoError, setGeoError] = (0, react_1.useState)(null);
20
- const toggleSection = (section) => {
21
- setActiveSection(activeSection === section ? null : section);
22
- };
23
17
  const handleToggleTracking = () => {
24
18
  setIsTracking(!isTracking);
25
19
  if (isTracking) {
@@ -47,6 +41,6 @@ const Dashboard = ({ apiClient, setUserLocation, setSearchedPlace, setIsTracking
47
41
  setGeoLoading(false);
48
42
  }
49
43
  }, [geoLoading, isTracking, setUserLocation, setRoutes, setSelectedRouteIndex]);
50
- return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: styles_module_css_1.default.header, children: (0, jsx_runtime_1.jsxs)("h1", { className: styles_module_css_1.default.headerTitle, children: [(0, jsx_runtime_1.jsx)("span", { className: styles_module_css_1.default.titleAccent, children: "Navi" }), "goo"] }) }), (0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.mainContainer, children: [(0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.sidebar, children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => toggleSection('geolocation'), className: `${styles_module_css_1.default.sidebarButton} ${activeSection === 'geolocation' ? styles_module_css_1.default.active : ''}`, title: "G\u00E9olocalisation et suivi", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Footprints, { size: 24, color: "#000" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: () => toggleSection('search'), className: `${styles_module_css_1.default.sidebarButton} ${activeSection === 'search' ? styles_module_css_1.default.active : ''}`, title: "Recherche de lieu", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Search, { size: 24, color: "#000" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: () => toggleSection('route'), className: `${styles_module_css_1.default.sidebarButton} ${activeSection === 'route' ? styles_module_css_1.default.active : ''}`, title: "Trac\u00E9 d'itin\u00E9raire", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ArrowRight, { size: 24, color: "#000" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: () => toggleSection('routeWithDetour'), className: `${styles_module_css_1.default.sidebarButton} ${activeSection === 'routeWithDetour' ? styles_module_css_1.default.active : ''}`, title: "Trac\u00E9 d'itin\u00E9raire avec d\u00E9tour", children: (0, jsx_runtime_1.jsx)(lucide_react_1.RefreshCcw, { size: 24, color: "#000" }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: `${styles_module_css_1.default.contentPanel} ${activeSection ? styles_module_css_1.default.open : ''}`, children: [activeSection === 'geolocation' && ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.sectionContainer, children: [(0, jsx_runtime_1.jsxs)("h2", { className: styles_module_css_1.default.sectionTitle, children: [(0, jsx_runtime_1.jsx)("span", { className: styles_module_css_1.default.titleAccent, children: "G\u00E9o" }), "localisation"] }), (0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.toggleContainer, children: [(0, jsx_runtime_1.jsxs)("label", { className: styles_module_css_1.default.switch, children: [(0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: isTracking, onChange: handleToggleTracking }), (0, jsx_runtime_1.jsx)("span", { className: styles_module_css_1.default.slider })] }), (0, jsx_runtime_1.jsxs)("span", { className: styles_module_css_1.default.toggleLabel, children: ["Suivi: ", isTracking ? 'Activé' : 'Désactivé'] })] }), (0, jsx_runtime_1.jsx)("button", { onClick: handleGeolocation, className: styles_module_css_1.default.locationButton, disabled: geoLoading || isTracking, children: geoLoading ? ('Chargement...') : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(lucide_react_1.MapPin, { size: 18, color: "#000", style: { marginRight: '8px' } }), "Ma position"] })) }), geoError && (0, jsx_runtime_1.jsx)("div", { className: styles_module_css_1.default.error, children: geoError })] })), activeSection === 'search' && ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.sectionContainer, children: [(0, jsx_runtime_1.jsxs)("h2", { className: styles_module_css_1.default.sectionTitle, children: [(0, jsx_runtime_1.jsx)("span", { className: styles_module_css_1.default.titleAccent, children: "Re" }), "cherche"] }), (0, jsx_runtime_1.jsx)(SearchBar_1.default, { apiClient: apiClient, setUserLocation: setUserLocation, setSearchedPlace: setSearchedPlace })] })), activeSection === 'route' && ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.sectionContainer, children: [(0, jsx_runtime_1.jsxs)("h2", { className: styles_module_css_1.default.sectionTitle, children: [(0, jsx_runtime_1.jsx)("span", { className: styles_module_css_1.default.titleAccent, children: "Itin\u00E9" }), "raire"] }), (0, jsx_runtime_1.jsx)(RouteSearch_1.default, { apiClient: apiClient, setRoutes: setRoutes, setSelectedRouteIndex: setSelectedRouteIndex }), (0, jsx_runtime_1.jsx)(TransportOptions_1.default, {}), (0, jsx_runtime_1.jsx)(TripType_1.default, {})] })), activeSection === 'routeWithDetour' && ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.sectionContainer, children: [(0, jsx_runtime_1.jsxs)("h2", { className: styles_module_css_1.default.sectionTitle, children: [(0, jsx_runtime_1.jsx)("span", { className: styles_module_css_1.default.titleAccent, children: "Itin\u00E9" }), "raire avec d\u00E9tour"] }), (0, jsx_runtime_1.jsx)(DetourRouteSearch_1.default, { apiClient: apiClient, setRoutes: setRoutes, setSelectedRouteIndex: setSelectedRouteIndex }), (0, jsx_runtime_1.jsx)(TransportOptions_1.default, {}), (0, jsx_runtime_1.jsx)(TripType_1.default, {})] }))] })] })] }));
44
+ return ((0, jsx_runtime_1.jsxs)("div", { className: className, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsxs)("label", { children: [(0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: isTracking, onChange: handleToggleTracking }), "Suivi: ", isTracking ? 'Activé' : 'Désactivé'] }) }), (0, jsx_runtime_1.jsx)("button", { onClick: handleGeolocation, disabled: geoLoading || isTracking, children: geoLoading ? 'Chargement...' : 'Ma position' }), geoError && (0, jsx_runtime_1.jsx)("div", { children: geoError })] }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(SearchBar_1.default, { apiClient: apiClient, setUserLocation: setUserLocation, setSearchedPlace: setSearchedPlace }) }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(RouteSearch_1.default, { apiClient: apiClient, setRoutes: setRoutes, setSelectedRouteIndex: setSelectedRouteIndex }), (0, jsx_runtime_1.jsx)(TransportOptions_1.default, {}), (0, jsx_runtime_1.jsx)(TripType_1.default, {})] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(DetourRouteSearch_1.default, { apiClient: apiClient, setRoutes: setRoutes, setSelectedRouteIndex: setSelectedRouteIndex }), (0, jsx_runtime_1.jsx)(TransportOptions_1.default, {}), (0, jsx_runtime_1.jsx)(TripType_1.default, {})] })] }));
51
45
  };
52
46
  exports.default = Dashboard;
@@ -5,6 +5,15 @@ interface DetourRouteSearchProps {
5
5
  apiClient: ApiClient;
6
6
  setRoutes: (routes: Route[]) => void;
7
7
  setSelectedRouteIndex: (index: number) => void;
8
+ className?: string;
9
+ searchGroupClassName?: string;
10
+ labelClassName?: string;
11
+ inputClassName?: string;
12
+ resultsClassName?: string;
13
+ resultItemClassName?: string;
14
+ errorClassName?: string;
15
+ buttonClassName?: string;
16
+ disabledButtonClassName?: string;
8
17
  }
9
18
  declare const DetourRouteSearch: React.FC<DetourRouteSearchProps>;
10
19
  export default DetourRouteSearch;
@@ -1,12 +1,8 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  const jsx_runtime_1 = require("react/jsx-runtime");
7
4
  const react_1 = require("react");
8
- const styles_module_css_1 = __importDefault(require("./styles.module.css"));
9
- const DetourRouteSearch = ({ apiClient, setRoutes, setSelectedRouteIndex }) => {
5
+ const DetourRouteSearch = ({ apiClient, setRoutes, setSelectedRouteIndex, className, searchGroupClassName, labelClassName, inputClassName, resultsClassName, resultItemClassName, errorClassName, buttonClassName, disabledButtonClassName, }) => {
10
6
  const [startQuery, setStartQuery] = (0, react_1.useState)('');
11
7
  const [detourQuery, setDetourQuery] = (0, react_1.useState)('');
12
8
  const [endQuery, setEndQuery] = (0, react_1.useState)('');
@@ -105,15 +101,15 @@ const DetourRouteSearch = ({ apiClient, setRoutes, setSelectedRouteIndex }) => {
105
101
  setLoading(false);
106
102
  }
107
103
  };
108
- return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.routeSearchSection, children: [(0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.searchGroup, children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "start", className: styles_module_css_1.default.label, children: "D\u00E9part" }), (0, jsx_runtime_1.jsx)("input", { id: "start", type: "text", value: startQuery, onChange: (e) => {
104
+ return ((0, jsx_runtime_1.jsxs)("div", { className: className, children: [(0, jsx_runtime_1.jsxs)("div", { className: searchGroupClassName, children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "start", className: labelClassName, children: "D\u00E9part" }), (0, jsx_runtime_1.jsx)("input", { id: "start", type: "text", value: startQuery, onChange: (e) => {
109
105
  setStartQuery(e.target.value);
110
106
  handleSearch(e.target.value, setStartResults);
111
- }, placeholder: "Point de d\u00E9part", className: styles_module_css_1.default.searchInput }), startResults.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: styles_module_css_1.default.searchResults, children: startResults.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelectStart(place), className: styles_module_css_1.default.searchResultItem, children: place.name }, place.id))) }))] }), (0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.searchGroup, children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "detour", className: styles_module_css_1.default.label, children: "D\u00E9tour" }), (0, jsx_runtime_1.jsx)("input", { id: "detour", type: "text", value: detourQuery, onChange: (e) => {
107
+ }, placeholder: "Point de d\u00E9part", className: inputClassName }), startResults.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: resultsClassName, children: startResults.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelectStart(place), className: resultItemClassName, children: place.name }, place.id))) }))] }), (0, jsx_runtime_1.jsxs)("div", { className: searchGroupClassName, children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "detour", className: labelClassName, children: "D\u00E9tour" }), (0, jsx_runtime_1.jsx)("input", { id: "detour", type: "text", value: detourQuery, onChange: (e) => {
112
108
  setDetourQuery(e.target.value);
113
109
  handleSearch(e.target.value, setDetourResults);
114
- }, placeholder: "Point de d\u00E9tour", className: styles_module_css_1.default.searchInput }), detourResults.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: styles_module_css_1.default.searchResults, children: detourResults.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelectDetour(place), className: styles_module_css_1.default.searchResultItem, children: place.name }, place.id))) }))] }), (0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.searchGroup, children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "end", className: styles_module_css_1.default.label, children: "Destination" }), (0, jsx_runtime_1.jsx)("input", { id: "end", type: "text", value: endQuery, onChange: (e) => {
110
+ }, placeholder: "Point de d\u00E9tour", className: inputClassName }), detourResults.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: resultsClassName, children: detourResults.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelectDetour(place), className: resultItemClassName, children: place.name }, place.id))) }))] }), (0, jsx_runtime_1.jsxs)("div", { className: searchGroupClassName, children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "end", className: labelClassName, children: "Destination" }), (0, jsx_runtime_1.jsx)("input", { id: "end", type: "text", value: endQuery, onChange: (e) => {
115
111
  setEndQuery(e.target.value);
116
112
  handleSearch(e.target.value, setEndResults);
117
- }, placeholder: "Point d'arriv\u00E9e", className: styles_module_css_1.default.searchInput }), endResults.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: styles_module_css_1.default.searchResults, children: endResults.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelectEnd(place), className: styles_module_css_1.default.searchResultItem, children: place.name }, place.id))) }))] }), error && (0, jsx_runtime_1.jsx)("div", { className: styles_module_css_1.default.error, children: error }), (0, jsx_runtime_1.jsx)("button", { onClick: handleCalculateRoute, disabled: loading || !selectedStart || !selectedDetour || !selectedEnd, className: `${styles_module_css_1.default.searchButton} ${loading || !selectedStart || !selectedDetour || !selectedEnd ? styles_module_css_1.default.disabled : ''}`, children: loading ? 'Calcul...' : 'Calculer l\'itinéraire' })] }));
113
+ }, placeholder: "Point d'arriv\u00E9e", className: inputClassName }), endResults.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: resultsClassName, children: endResults.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelectEnd(place), className: resultItemClassName, children: place.name }, place.id))) }))] }), error && (0, jsx_runtime_1.jsx)("div", { className: errorClassName, children: error }), (0, jsx_runtime_1.jsx)("button", { onClick: handleCalculateRoute, disabled: loading || !selectedStart || !selectedDetour || !selectedEnd, className: loading || !selectedStart || !selectedDetour || !selectedEnd ? disabledButtonClassName : buttonClassName, children: loading ? 'Calcul...' : 'Calculer l\'itinéraire' })] }));
118
114
  };
119
115
  exports.default = DetourRouteSearch;
@@ -5,6 +5,15 @@ interface RouteSearchProps {
5
5
  apiClient: ApiClient;
6
6
  setRoutes: (routes: Route[]) => void;
7
7
  setSelectedRouteIndex: (index: number) => void;
8
+ className?: string;
9
+ searchGroupClassName?: string;
10
+ labelClassName?: string;
11
+ inputClassName?: string;
12
+ resultsClassName?: string;
13
+ resultItemClassName?: string;
14
+ errorClassName?: string;
15
+ buttonClassName?: string;
16
+ disabledButtonClassName?: string;
8
17
  }
9
18
  declare const RouteSearch: React.FC<RouteSearchProps>;
10
19
  export default RouteSearch;
@@ -1,12 +1,8 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  const jsx_runtime_1 = require("react/jsx-runtime");
7
4
  const react_1 = require("react");
8
- const styles_module_css_1 = __importDefault(require("./styles.module.css"));
9
- const RouteSearch = ({ apiClient, setRoutes, setSelectedRouteIndex }) => {
5
+ const RouteSearch = ({ apiClient, setRoutes, setSelectedRouteIndex, className, searchGroupClassName, labelClassName, inputClassName, resultsClassName, resultItemClassName, errorClassName, buttonClassName, disabledButtonClassName, }) => {
10
6
  const [startQuery, setStartQuery] = (0, react_1.useState)('');
11
7
  const [endQuery, setEndQuery] = (0, react_1.useState)('');
12
8
  const [startResults, setStartResults] = (0, react_1.useState)([]);
@@ -84,12 +80,12 @@ const RouteSearch = ({ apiClient, setRoutes, setSelectedRouteIndex }) => {
84
80
  setLoading(false);
85
81
  }
86
82
  };
87
- return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.routeSearchSection, children: [(0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.searchGroup, children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "start", className: styles_module_css_1.default.label, children: "D\u00E9part" }), (0, jsx_runtime_1.jsx)("input", { id: "start", type: "text", value: startQuery, onChange: (e) => {
83
+ return ((0, jsx_runtime_1.jsxs)("div", { className: className, children: [(0, jsx_runtime_1.jsxs)("div", { className: searchGroupClassName, children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "start", className: labelClassName, children: "D\u00E9part" }), (0, jsx_runtime_1.jsx)("input", { id: "start", type: "text", value: startQuery, onChange: (e) => {
88
84
  setStartQuery(e.target.value);
89
85
  handleSearch(e.target.value, setStartResults);
90
- }, placeholder: "Point de d\u00E9part", className: styles_module_css_1.default.searchInput }), startResults.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: styles_module_css_1.default.searchResults, children: startResults.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelectStart(place), className: styles_module_css_1.default.searchResultItem, children: place.name }, place.id))) }))] }), (0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.searchGroup, children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "end", className: styles_module_css_1.default.label, children: "Destination" }), (0, jsx_runtime_1.jsx)("input", { id: "end", type: "text", value: endQuery, onChange: (e) => {
86
+ }, placeholder: "Point de d\u00E9part", className: inputClassName }), startResults.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: resultsClassName, children: startResults.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelectStart(place), className: resultItemClassName, children: place.name }, place.id))) }))] }), (0, jsx_runtime_1.jsxs)("div", { className: searchGroupClassName, children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "end", className: labelClassName, children: "Destination" }), (0, jsx_runtime_1.jsx)("input", { id: "end", type: "text", value: endQuery, onChange: (e) => {
91
87
  setEndQuery(e.target.value);
92
88
  handleSearch(e.target.value, setEndResults);
93
- }, placeholder: "Point d'arriv\u00E9e", className: styles_module_css_1.default.searchInput }), endResults.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: styles_module_css_1.default.searchResults, children: endResults.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelectEnd(place), className: styles_module_css_1.default.searchResultItem, children: place.name }, place.id))) }))] }), error && (0, jsx_runtime_1.jsx)("div", { className: styles_module_css_1.default.error, children: error }), (0, jsx_runtime_1.jsx)("button", { onClick: handleCalculateRoute, disabled: loading || !selectedStart || !selectedEnd, className: `${styles_module_css_1.default.searchButton} ${loading || !selectedStart || !selectedEnd ? styles_module_css_1.default.disabled : ''}`, children: loading ? 'Calcul...' : 'Calculer l\'itinéraire' })] }));
89
+ }, placeholder: "Point d'arriv\u00E9e", className: inputClassName }), endResults.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: resultsClassName, children: endResults.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelectEnd(place), className: resultItemClassName, children: place.name }, place.id))) }))] }), error && (0, jsx_runtime_1.jsx)("div", { className: errorClassName, children: error }), (0, jsx_runtime_1.jsx)("button", { onClick: handleCalculateRoute, disabled: loading || !selectedStart || !selectedEnd, className: loading || !selectedStart || !selectedEnd ? disabledButtonClassName : buttonClassName, children: loading ? 'Calcul...' : 'Calculer l\'itinéraire' })] }));
94
90
  };
95
91
  exports.default = RouteSearch;
@@ -5,6 +5,12 @@ interface SearchBarProps {
5
5
  apiClient: ApiClient;
6
6
  setUserLocation: (location: GeolocationResult | null) => void;
7
7
  setSearchedPlace: (place: Place | null) => void;
8
+ className?: string;
9
+ inputClassName?: string;
10
+ buttonClassName?: string;
11
+ errorClassName?: string;
12
+ resultsClassName?: string;
13
+ resultItemClassName?: string;
8
14
  }
9
15
  declare const SearchBar: React.FC<SearchBarProps>;
10
16
  export default SearchBar;
@@ -1,12 +1,8 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  const jsx_runtime_1 = require("react/jsx-runtime");
7
4
  const react_1 = require("react");
8
- const styles_module_css_1 = __importDefault(require("./styles.module.css"));
9
- const SearchBar = ({ apiClient, setUserLocation, setSearchedPlace }) => {
5
+ const SearchBar = ({ apiClient, setUserLocation, setSearchedPlace, className, inputClassName, buttonClassName, errorClassName, resultsClassName, resultItemClassName, }) => {
10
6
  const [query, setQuery] = (0, react_1.useState)('');
11
7
  const [loading, setLoading] = (0, react_1.useState)(false);
12
8
  const [results, setResults] = (0, react_1.useState)([]);
@@ -43,6 +39,6 @@ const SearchBar = ({ apiClient, setUserLocation, setSearchedPlace }) => {
43
39
  }
44
40
  setResults([]);
45
41
  };
46
- return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.searchSection, children: [(0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.searchGroup, children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "search", className: styles_module_css_1.default.label, children: "Nom du lieu" }), (0, jsx_runtime_1.jsx)("input", { id: "search", type: "text", value: query, onChange: (e) => setQuery(e.target.value), placeholder: "Rechercher un lieu", className: styles_module_css_1.default.searchInput })] }), error && (0, jsx_runtime_1.jsx)("div", { className: styles_module_css_1.default.error, children: error }), results.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: styles_module_css_1.default.searchResults, children: results.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelect(place), className: styles_module_css_1.default.searchResultItem, children: place.name }, place.id))) })), (0, jsx_runtime_1.jsx)("button", { onClick: handleSearch, disabled: loading || !query, className: `${styles_module_css_1.default.searchButton} ${loading || !query ? styles_module_css_1.default.disabled : ''}`, children: loading ? 'Recherche...' : 'Rechercher' })] }));
42
+ return ((0, jsx_runtime_1.jsxs)("div", { className: className, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: "search", children: "Nom du lieu" }), (0, jsx_runtime_1.jsx)("input", { id: "search", type: "text", value: query, onChange: (e) => setQuery(e.target.value), placeholder: "Rechercher un lieu", className: inputClassName })] }), error && (0, jsx_runtime_1.jsx)("div", { className: errorClassName, children: error }), results.length > 0 && ((0, jsx_runtime_1.jsx)("ul", { className: resultsClassName, children: results.map((place) => ((0, jsx_runtime_1.jsx)("li", { onClick: () => handleSelect(place), className: resultItemClassName, children: place.name }, place.id))) })), (0, jsx_runtime_1.jsx)("button", { onClick: handleSearch, disabled: loading || !query, className: buttonClassName, children: loading ? 'Recherche...' : 'Rechercher' })] }));
47
43
  };
48
44
  exports.default = SearchBar;
@@ -1,3 +1,14 @@
1
1
  import React from 'react';
2
- declare const TransportOptions: React.FC;
2
+ interface TransportOptionsProps {
3
+ className?: string;
4
+ headerClassName?: string;
5
+ titleClassName?: string;
6
+ toggleButtonClassName?: string;
7
+ optionsClassName?: string;
8
+ optionClassName?: string;
9
+ selectedOptionClassName?: string;
10
+ iconClassName?: string;
11
+ nameClassName?: string;
12
+ }
13
+ declare const TransportOptions: React.FC<TransportOptionsProps>;
3
14
  export default TransportOptions;
@@ -1,12 +1,8 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  const jsx_runtime_1 = require("react/jsx-runtime");
7
4
  const react_1 = require("react");
8
- const styles_module_css_1 = __importDefault(require("./styles.module.css"));
9
- const TransportOptions = () => {
5
+ const TransportOptions = ({ className, headerClassName, titleClassName, toggleButtonClassName, optionsClassName, optionClassName, selectedOptionClassName, iconClassName, nameClassName, }) => {
10
6
  const [showOptions, setShowOptions] = (0, react_1.useState)(false);
11
7
  const [selectedTransport, setSelectedTransport] = (0, react_1.useState)('taxi');
12
8
  const transportOptions = [
@@ -17,8 +13,8 @@ const TransportOptions = () => {
17
13
  (0, react_1.useEffect)(() => {
18
14
  window.dispatchEvent(new CustomEvent('transportChange', { detail: selectedTransport }));
19
15
  }, [selectedTransport]);
20
- return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.optionsSection, children: [(0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.optionsHeader, children: [(0, jsx_runtime_1.jsx)("h3", { className: styles_module_css_1.default.optionsTitle, children: "Moyen de transport" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => setShowOptions(!showOptions), className: styles_module_css_1.default.toggleButton, children: showOptions ? 'Réduire' : 'Options' })] }), showOptions && ((0, jsx_runtime_1.jsx)("div", { className: styles_module_css_1.default.transportOptions, children: transportOptions.map((option) => ((0, jsx_runtime_1.jsxs)("button", { onClick: () => setSelectedTransport(option.id), className: `${styles_module_css_1.default.transportOption} ${selectedTransport === option.id ? styles_module_css_1.default.selected : ''}`, style: {
16
+ return ((0, jsx_runtime_1.jsxs)("div", { className: className, children: [(0, jsx_runtime_1.jsxs)("div", { className: headerClassName, children: [(0, jsx_runtime_1.jsx)("h3", { className: titleClassName, children: "Moyen de transport" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => setShowOptions(!showOptions), className: toggleButtonClassName, children: showOptions ? 'Réduire' : 'Options' })] }), showOptions && ((0, jsx_runtime_1.jsx)("div", { className: optionsClassName, children: transportOptions.map((option) => ((0, jsx_runtime_1.jsxs)("button", { onClick: () => setSelectedTransport(option.id), className: `${optionClassName} ${selectedTransport === option.id ? selectedOptionClassName : ''}`, style: {
21
17
  backgroundColor: selectedTransport === option.id ? option.color : undefined,
22
- }, children: [(0, jsx_runtime_1.jsx)("span", { className: styles_module_css_1.default.transportIcon, children: option.icon }), (0, jsx_runtime_1.jsx)("span", { className: styles_module_css_1.default.transportName, children: option.name })] }, option.id))) }))] }));
18
+ }, children: [(0, jsx_runtime_1.jsx)("span", { className: iconClassName, children: option.icon }), (0, jsx_runtime_1.jsx)("span", { className: nameClassName, children: option.name })] }, option.id))) }))] }));
23
19
  };
24
20
  exports.default = TransportOptions;
@@ -1,3 +1,14 @@
1
1
  import React from 'react';
2
- declare const TripType: React.FC;
2
+ interface TripTypeProps {
3
+ className?: string;
4
+ headerClassName?: string;
5
+ titleClassName?: string;
6
+ toggleButtonClassName?: string;
7
+ optionsClassName?: string;
8
+ optionClassName?: string;
9
+ selectedOptionClassName?: string;
10
+ iconClassName?: string;
11
+ nameClassName?: string;
12
+ }
13
+ declare const TripType: React.FC<TripTypeProps>;
3
14
  export default TripType;
@@ -1,20 +1,16 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  const jsx_runtime_1 = require("react/jsx-runtime");
7
4
  const react_1 = require("react");
8
- const styles_module_css_1 = __importDefault(require("./styles.module.css"));
9
- const TripType = () => {
5
+ const TripType = ({ className, headerClassName, titleClassName, toggleButtonClassName, optionsClassName, optionClassName, selectedOptionClassName, iconClassName, nameClassName, }) => {
10
6
  const [showOptions, setShowOptions] = (0, react_1.useState)(false);
11
7
  const [selectedTripType, setSelectedTripType] = (0, react_1.useState)('individuel');
12
8
  const tripTypeOptions = [
13
9
  { id: 'individuel', name: 'Individuel', icon: '👤', color: '#3498db' },
14
10
  { id: 'ramassage', name: 'Ramassage', icon: '👥', color: '#9b59b6' },
15
11
  ];
16
- return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.optionsSection, children: [(0, jsx_runtime_1.jsxs)("div", { className: styles_module_css_1.default.optionsHeader, children: [(0, jsx_runtime_1.jsx)("h3", { className: styles_module_css_1.default.optionsTitle, children: "Type de trajet" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => setShowOptions(!showOptions), className: styles_module_css_1.default.toggleButton, children: showOptions ? 'Réduire' : 'Options' })] }), showOptions && ((0, jsx_runtime_1.jsx)("div", { className: styles_module_css_1.default.transportOptions, children: tripTypeOptions.map((option) => ((0, jsx_runtime_1.jsxs)("button", { onClick: () => setSelectedTripType(option.id), className: `${styles_module_css_1.default.transportOption} ${selectedTripType === option.id ? styles_module_css_1.default.selected : ''}`, style: {
12
+ return ((0, jsx_runtime_1.jsxs)("div", { className: className, children: [(0, jsx_runtime_1.jsxs)("div", { className: headerClassName, children: [(0, jsx_runtime_1.jsx)("h3", { className: titleClassName, children: "Type de trajet" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => setShowOptions(!showOptions), className: toggleButtonClassName, children: showOptions ? 'Réduire' : 'Options' })] }), showOptions && ((0, jsx_runtime_1.jsx)("div", { className: optionsClassName, children: tripTypeOptions.map((option) => ((0, jsx_runtime_1.jsxs)("button", { onClick: () => setSelectedTripType(option.id), className: `${optionClassName} ${selectedTripType === option.id ? selectedOptionClassName : ''}`, style: {
17
13
  backgroundColor: selectedTripType === option.id ? option.color : undefined,
18
- }, children: [(0, jsx_runtime_1.jsx)("span", { className: styles_module_css_1.default.transportIcon, children: option.icon }), (0, jsx_runtime_1.jsx)("span", { className: styles_module_css_1.default.transportName, children: option.name })] }, option.id))) }))] }));
14
+ }, children: [(0, jsx_runtime_1.jsx)("span", { className: iconClassName, children: option.icon }), (0, jsx_runtime_1.jsx)("span", { className: nameClassName, children: option.name })] }, option.id))) }))] }));
19
15
  };
20
16
  exports.default = TripType;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@navigoo/map-components",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Reusable React components for mapping and routing in Yaoundé",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -6,8 +6,6 @@ import RouteSearch from './RouteSearch';
6
6
  import DetourRouteSearch from './DetourRouteSearch';
7
7
  import TransportOptions from './TransportOptions';
8
8
  import TripType from './TripType';
9
- import styles from './styles.module.css';
10
- import { Footprints, Search, ArrowRight, RefreshCcw, MapPin } from 'lucide-react';
11
9
  import { ApiClient } from '../lib/api';
12
10
 
13
11
  interface DashboardProps {
@@ -18,6 +16,7 @@ interface DashboardProps {
18
16
  setRoutes: (routes: Route[]) => void;
19
17
  setSelectedRouteIndex: (index: number) => void;
20
18
  isTracking: boolean;
19
+ className?: string; // Allow custom styling
21
20
  }
22
21
 
23
22
  const Dashboard: React.FC<DashboardProps> = ({
@@ -28,15 +27,11 @@ const Dashboard: React.FC<DashboardProps> = ({
28
27
  setRoutes,
29
28
  setSelectedRouteIndex,
30
29
  isTracking,
30
+ className,
31
31
  }) => {
32
- const [activeSection, setActiveSection] = useState<string | null>(null);
33
32
  const [geoLoading, setGeoLoading] = useState(false);
34
33
  const [geoError, setGeoError] = useState<string | null>(null);
35
34
 
36
- const toggleSection = (section: string) => {
37
- setActiveSection(activeSection === section ? null : section);
38
- };
39
-
40
35
  const handleToggleTracking = () => {
41
36
  setIsTracking(!isTracking);
42
37
  if (isTracking) {
@@ -65,116 +60,57 @@ const Dashboard: React.FC<DashboardProps> = ({
65
60
  }, [geoLoading, isTracking, setUserLocation, setRoutes, setSelectedRouteIndex]);
66
61
 
67
62
  return (
68
- <div>
69
- <div className={styles.header}>
70
- <h1 className={styles.headerTitle}>
71
- <span className={styles.titleAccent}>Navi</span>goo
72
- </h1>
73
- </div>
74
- <div className={styles.mainContainer}>
75
- <div className={styles.sidebar}>
76
- <button
77
- onClick={() => toggleSection('geolocation')}
78
- className={`${styles.sidebarButton} ${activeSection === 'geolocation' ? styles.active : ''}`}
79
- title="Géolocalisation et suivi"
80
- >
81
- <Footprints size={24} color="#000" />
82
- </button>
83
- <button
84
- onClick={() => toggleSection('search')}
85
- className={`${styles.sidebarButton} ${activeSection === 'search' ? styles.active : ''}`}
86
- title="Recherche de lieu"
87
- >
88
- <Search size={24} color="#000" />
89
- </button>
90
- <button
91
- onClick={() => toggleSection('route')}
92
- className={`${styles.sidebarButton} ${activeSection === 'route' ? styles.active : ''}`}
93
- title="Tracé d'itinéraire"
94
- >
95
- <ArrowRight size={24} color="#000" />
96
- </button>
97
- <button
98
- onClick={() => toggleSection('routeWithDetour')}
99
- className={`${styles.sidebarButton} ${activeSection === 'routeWithDetour' ? styles.active : ''}`}
100
- title="Tracé d'itinéraire avec détour"
101
- >
102
- <RefreshCcw size={24} color="#000" />
103
- </button>
104
- </div>
105
- <div className={`${styles.contentPanel} ${activeSection ? styles.open : ''}`}>
106
- {activeSection === 'geolocation' && (
107
- <div className={styles.sectionContainer}>
108
- <h2 className={styles.sectionTitle}>
109
- <span className={styles.titleAccent}>Géo</span>localisation
110
- </h2>
111
- <div className={styles.toggleContainer}>
112
- <label className={styles.switch}>
113
- <input type="checkbox" checked={isTracking} onChange={handleToggleTracking} />
114
- <span className={styles.slider}></span>
115
- </label>
116
- <span className={styles.toggleLabel}>
117
- Suivi: {isTracking ? 'Activé' : 'Désactivé'}
118
- </span>
119
- </div>
120
- <button
121
- onClick={handleGeolocation}
122
- className={styles.locationButton}
123
- disabled={geoLoading || isTracking}
124
- >
125
- {geoLoading ? (
126
- 'Chargement...'
127
- ) : (
128
- <>
129
- <MapPin size={18} color="#000" style={{ marginRight: '8px' }} />
130
- Ma position
131
- </>
132
- )}
133
- </button>
134
- {geoError && <div className={styles.error}>{geoError}</div>}
135
- </div>
136
- )}
137
- {activeSection === 'search' && (
138
- <div className={styles.sectionContainer}>
139
- <h2 className={styles.sectionTitle}>
140
- <span className={styles.titleAccent}>Re</span>cherche
141
- </h2>
142
- <SearchBar
143
- apiClient={apiClient}
144
- setUserLocation={setUserLocation}
145
- setSearchedPlace={setSearchedPlace}
146
- />
147
- </div>
148
- )}
149
- {activeSection === 'route' && (
150
- <div className={styles.sectionContainer}>
151
- <h2 className={styles.sectionTitle}>
152
- <span className={styles.titleAccent}>Itiné</span>raire
153
- </h2>
154
- <RouteSearch
155
- apiClient={apiClient}
156
- setRoutes={setRoutes}
157
- setSelectedRouteIndex={setSelectedRouteIndex}
158
- />
159
- <TransportOptions />
160
- <TripType />
161
- </div>
162
- )}
163
- {activeSection === 'routeWithDetour' && (
164
- <div className={styles.sectionContainer}>
165
- <h2 className={styles.sectionTitle}>
166
- <span className={styles.titleAccent}>Itiné</span>raire avec détour
167
- </h2>
168
- <DetourRouteSearch
169
- apiClient={apiClient}
170
- setRoutes={setRoutes}
171
- setSelectedRouteIndex={setSelectedRouteIndex}
172
- />
173
- <TransportOptions />
174
- <TripType />
175
- </div>
176
- )}
63
+ <div className={className}>
64
+ {/* Geolocation Section */}
65
+ <div>
66
+ <div>
67
+ <label>
68
+ <input
69
+ type="checkbox"
70
+ checked={isTracking}
71
+ onChange={handleToggleTracking}
72
+ />
73
+ Suivi: {isTracking ? 'Activé' : 'Désactivé'}
74
+ </label>
177
75
  </div>
76
+ <button
77
+ onClick={handleGeolocation}
78
+ disabled={geoLoading || isTracking}
79
+ >
80
+ {geoLoading ? 'Chargement...' : 'Ma position'}
81
+ </button>
82
+ {geoError && <div>{geoError}</div>}
83
+ </div>
84
+
85
+ {/* Search Section */}
86
+ <div>
87
+ <SearchBar
88
+ apiClient={apiClient}
89
+ setUserLocation={setUserLocation}
90
+ setSearchedPlace={setSearchedPlace}
91
+ />
92
+ </div>
93
+
94
+ {/* Route Search Section */}
95
+ <div>
96
+ <RouteSearch
97
+ apiClient={apiClient}
98
+ setRoutes={setRoutes}
99
+ setSelectedRouteIndex={setSelectedRouteIndex}
100
+ />
101
+ <TransportOptions />
102
+ <TripType />
103
+ </div>
104
+
105
+ {/* Detour Route Search Section */}
106
+ <div>
107
+ <DetourRouteSearch
108
+ apiClient={apiClient}
109
+ setRoutes={setRoutes}
110
+ setSelectedRouteIndex={setSelectedRouteIndex}
111
+ />
112
+ <TransportOptions />
113
+ <TripType />
178
114
  </div>
179
115
  </div>
180
116
  );
@@ -1,15 +1,36 @@
1
- import React, { useState, useEffect } from 'react';
1
+ import React, { useState, useEffect, ReactNode } from 'react';
2
2
  import { Place, Route } from '../lib/type';
3
3
  import { ApiClient } from '../lib/api';
4
- import styles from './styles.module.css';
5
4
 
6
5
  interface DetourRouteSearchProps {
7
6
  apiClient: ApiClient;
8
7
  setRoutes: (routes: Route[]) => void;
9
8
  setSelectedRouteIndex: (index: number) => void;
9
+ className?: string;
10
+ searchGroupClassName?: string;
11
+ labelClassName?: string;
12
+ inputClassName?: string;
13
+ resultsClassName?: string;
14
+ resultItemClassName?: string;
15
+ errorClassName?: string;
16
+ buttonClassName?: string;
17
+ disabledButtonClassName?: string;
10
18
  }
11
19
 
12
- const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({ apiClient, setRoutes, setSelectedRouteIndex }) => {
20
+ const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({
21
+ apiClient,
22
+ setRoutes,
23
+ setSelectedRouteIndex,
24
+ className,
25
+ searchGroupClassName,
26
+ labelClassName,
27
+ inputClassName,
28
+ resultsClassName,
29
+ resultItemClassName,
30
+ errorClassName,
31
+ buttonClassName,
32
+ disabledButtonClassName,
33
+ }) => {
13
34
  const [startQuery, setStartQuery] = useState('');
14
35
  const [detourQuery, setDetourQuery] = useState('');
15
36
  const [endQuery, setEndQuery] = useState('');
@@ -120,9 +141,9 @@ const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({ apiClient, setRou
120
141
  };
121
142
 
122
143
  return (
123
- <div className={styles.routeSearchSection}>
124
- <div className={styles.searchGroup}>
125
- <label htmlFor="start" className={styles.label}>Départ</label>
144
+ <div className={className}>
145
+ <div className={searchGroupClassName}>
146
+ <label htmlFor="start" className={labelClassName}>Départ</label>
126
147
  <input
127
148
  id="start"
128
149
  type="text"
@@ -132,15 +153,15 @@ const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({ apiClient, setRou
132
153
  handleSearch(e.target.value, setStartResults);
133
154
  }}
134
155
  placeholder="Point de départ"
135
- className={styles.searchInput}
156
+ className={inputClassName}
136
157
  />
137
158
  {startResults.length > 0 && (
138
- <ul className={styles.searchResults}>
159
+ <ul className={resultsClassName}>
139
160
  {startResults.map((place) => (
140
161
  <li
141
162
  key={place.id}
142
163
  onClick={() => handleSelectStart(place)}
143
- className={styles.searchResultItem}
164
+ className={resultItemClassName}
144
165
  >
145
166
  {place.name}
146
167
  </li>
@@ -148,8 +169,8 @@ const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({ apiClient, setRou
148
169
  </ul>
149
170
  )}
150
171
  </div>
151
- <div className={styles.searchGroup}>
152
- <label htmlFor="detour" className={styles.label}>Détour</label>
172
+ <div className={searchGroupClassName}>
173
+ <label htmlFor="detour" className={labelClassName}>Détour</label>
153
174
  <input
154
175
  id="detour"
155
176
  type="text"
@@ -159,15 +180,15 @@ const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({ apiClient, setRou
159
180
  handleSearch(e.target.value, setDetourResults);
160
181
  }}
161
182
  placeholder="Point de détour"
162
- className={styles.searchInput}
183
+ className={inputClassName}
163
184
  />
164
185
  {detourResults.length > 0 && (
165
- <ul className={styles.searchResults}>
186
+ <ul className={resultsClassName}>
166
187
  {detourResults.map((place) => (
167
188
  <li
168
189
  key={place.id}
169
190
  onClick={() => handleSelectDetour(place)}
170
- className={styles.searchResultItem}
191
+ className={resultItemClassName}
171
192
  >
172
193
  {place.name}
173
194
  </li>
@@ -175,8 +196,8 @@ const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({ apiClient, setRou
175
196
  </ul>
176
197
  )}
177
198
  </div>
178
- <div className={styles.searchGroup}>
179
- <label htmlFor="end" className={styles.label}>Destination</label>
199
+ <div className={searchGroupClassName}>
200
+ <label htmlFor="end" className={labelClassName}>Destination</label>
180
201
  <input
181
202
  id="end"
182
203
  type="text"
@@ -186,15 +207,15 @@ const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({ apiClient, setRou
186
207
  handleSearch(e.target.value, setEndResults);
187
208
  }}
188
209
  placeholder="Point d'arrivée"
189
- className={styles.searchInput}
210
+ className={inputClassName}
190
211
  />
191
212
  {endResults.length > 0 && (
192
- <ul className={styles.searchResults}>
213
+ <ul className={resultsClassName}>
193
214
  {endResults.map((place) => (
194
215
  <li
195
216
  key={place.id}
196
217
  onClick={() => handleSelectEnd(place)}
197
- className={styles.searchResultItem}
218
+ className={resultItemClassName}
198
219
  >
199
220
  {place.name}
200
221
  </li>
@@ -202,11 +223,11 @@ const DetourRouteSearch: React.FC<DetourRouteSearchProps> = ({ apiClient, setRou
202
223
  </ul>
203
224
  )}
204
225
  </div>
205
- {error && <div className={styles.error}>{error}</div>}
226
+ {error && <div className={errorClassName}>{error}</div>}
206
227
  <button
207
228
  onClick={handleCalculateRoute}
208
229
  disabled={loading || !selectedStart || !selectedDetour || !selectedEnd}
209
- className={`${styles.searchButton} ${loading || !selectedStart || !selectedDetour || !selectedEnd ? styles.disabled : ''}`}
230
+ className={loading || !selectedStart || !selectedDetour || !selectedEnd ? disabledButtonClassName : buttonClassName}
210
231
  >
211
232
  {loading ? 'Calcul...' : 'Calculer l\'itinéraire'}
212
233
  </button>
@@ -1,15 +1,36 @@
1
1
  import React, { useState, useEffect } from 'react';
2
- import { Place, Route, GeolocationResult } from '../lib/type';
2
+ import { Place, Route } from '../lib/type';
3
3
  import { ApiClient } from '../lib/api';
4
- import styles from './styles.module.css';
5
4
 
6
5
  interface RouteSearchProps {
7
6
  apiClient: ApiClient;
8
7
  setRoutes: (routes: Route[]) => void;
9
8
  setSelectedRouteIndex: (index: number) => void;
9
+ className?: string;
10
+ searchGroupClassName?: string;
11
+ labelClassName?: string;
12
+ inputClassName?: string;
13
+ resultsClassName?: string;
14
+ resultItemClassName?: string;
15
+ errorClassName?: string;
16
+ buttonClassName?: string;
17
+ disabledButtonClassName?: string;
10
18
  }
11
19
 
12
- const RouteSearch: React.FC<RouteSearchProps> = ({ apiClient, setRoutes, setSelectedRouteIndex }) => {
20
+ const RouteSearch: React.FC<RouteSearchProps> = ({
21
+ apiClient,
22
+ setRoutes,
23
+ setSelectedRouteIndex,
24
+ className,
25
+ searchGroupClassName,
26
+ labelClassName,
27
+ inputClassName,
28
+ resultsClassName,
29
+ resultItemClassName,
30
+ errorClassName,
31
+ buttonClassName,
32
+ disabledButtonClassName,
33
+ }) => {
13
34
  const [startQuery, setStartQuery] = useState('');
14
35
  const [endQuery, setEndQuery] = useState('');
15
36
  const [startResults, setStartResults] = useState<Place[]>([]);
@@ -93,9 +114,9 @@ const RouteSearch: React.FC<RouteSearchProps> = ({ apiClient, setRoutes, setSele
93
114
  };
94
115
 
95
116
  return (
96
- <div className={styles.routeSearchSection}>
97
- <div className={styles.searchGroup}>
98
- <label htmlFor="start" className={styles.label}>Départ</label>
117
+ <div className={className}>
118
+ <div className={searchGroupClassName}>
119
+ <label htmlFor="start" className={labelClassName}>Départ</label>
99
120
  <input
100
121
  id="start"
101
122
  type="text"
@@ -105,15 +126,15 @@ const RouteSearch: React.FC<RouteSearchProps> = ({ apiClient, setRoutes, setSele
105
126
  handleSearch(e.target.value, setStartResults);
106
127
  }}
107
128
  placeholder="Point de départ"
108
- className={styles.searchInput}
129
+ className={inputClassName}
109
130
  />
110
131
  {startResults.length > 0 && (
111
- <ul className={styles.searchResults}>
132
+ <ul className={resultsClassName}>
112
133
  {startResults.map((place) => (
113
134
  <li
114
135
  key={place.id}
115
136
  onClick={() => handleSelectStart(place)}
116
- className={styles.searchResultItem}
137
+ className={resultItemClassName}
117
138
  >
118
139
  {place.name}
119
140
  </li>
@@ -121,8 +142,8 @@ const RouteSearch: React.FC<RouteSearchProps> = ({ apiClient, setRoutes, setSele
121
142
  </ul>
122
143
  )}
123
144
  </div>
124
- <div className={styles.searchGroup}>
125
- <label htmlFor="end" className={styles.label}>Destination</label>
145
+ <div className={searchGroupClassName}>
146
+ <label htmlFor="end" className={labelClassName}>Destination</label>
126
147
  <input
127
148
  id="end"
128
149
  type="text"
@@ -132,15 +153,15 @@ const RouteSearch: React.FC<RouteSearchProps> = ({ apiClient, setRoutes, setSele
132
153
  handleSearch(e.target.value, setEndResults);
133
154
  }}
134
155
  placeholder="Point d'arrivée"
135
- className={styles.searchInput}
156
+ className={inputClassName}
136
157
  />
137
158
  {endResults.length > 0 && (
138
- <ul className={styles.searchResults}>
159
+ <ul className={resultsClassName}>
139
160
  {endResults.map((place) => (
140
161
  <li
141
162
  key={place.id}
142
163
  onClick={() => handleSelectEnd(place)}
143
- className={styles.searchResultItem}
164
+ className={resultItemClassName}
144
165
  >
145
166
  {place.name}
146
167
  </li>
@@ -148,11 +169,11 @@ const RouteSearch: React.FC<RouteSearchProps> = ({ apiClient, setRoutes, setSele
148
169
  </ul>
149
170
  )}
150
171
  </div>
151
- {error && <div className={styles.error}>{error}</div>}
172
+ {error && <div className={errorClassName}>{error}</div>}
152
173
  <button
153
174
  onClick={handleCalculateRoute}
154
175
  disabled={loading || !selectedStart || !selectedEnd}
155
- className={`${styles.searchButton} ${loading || !selectedStart || !selectedEnd ? styles.disabled : ''}`}
176
+ className={loading || !selectedStart || !selectedEnd ? disabledButtonClassName : buttonClassName}
156
177
  >
157
178
  {loading ? 'Calcul...' : 'Calculer l\'itinéraire'}
158
179
  </button>
@@ -1,15 +1,30 @@
1
1
  import React, { useState } from 'react';
2
2
  import { Place, GeolocationResult } from '../lib/type';
3
3
  import { ApiClient } from '../lib/api';
4
- import styles from './styles.module.css';
5
4
 
6
5
  interface SearchBarProps {
7
6
  apiClient: ApiClient;
8
7
  setUserLocation: (location: GeolocationResult | null) => void;
9
8
  setSearchedPlace: (place: Place | null) => void;
9
+ className?: string;
10
+ inputClassName?: string;
11
+ buttonClassName?: string;
12
+ errorClassName?: string;
13
+ resultsClassName?: string;
14
+ resultItemClassName?: string;
10
15
  }
11
16
 
12
- const SearchBar: React.FC<SearchBarProps> = ({ apiClient, setUserLocation, setSearchedPlace }) => {
17
+ const SearchBar: React.FC<SearchBarProps> = ({
18
+ apiClient,
19
+ setUserLocation,
20
+ setSearchedPlace,
21
+ className,
22
+ inputClassName,
23
+ buttonClassName,
24
+ errorClassName,
25
+ resultsClassName,
26
+ resultItemClassName,
27
+ }) => {
13
28
  const [query, setQuery] = useState('');
14
29
  const [loading, setLoading] = useState(false);
15
30
  const [results, setResults] = useState<Place[]>([]);
@@ -47,26 +62,26 @@ const SearchBar: React.FC<SearchBarProps> = ({ apiClient, setUserLocation, setSe
47
62
  };
48
63
 
49
64
  return (
50
- <div className={styles.searchSection}>
51
- <div className={styles.searchGroup}>
52
- <label htmlFor="search" className={styles.label}>Nom du lieu</label>
65
+ <div className={className}>
66
+ <div>
67
+ <label htmlFor="search">Nom du lieu</label>
53
68
  <input
54
69
  id="search"
55
70
  type="text"
56
71
  value={query}
57
72
  onChange={(e) => setQuery(e.target.value)}
58
73
  placeholder="Rechercher un lieu"
59
- className={styles.searchInput}
74
+ className={inputClassName}
60
75
  />
61
76
  </div>
62
- {error && <div className={styles.error}>{error}</div>}
77
+ {error && <div className={errorClassName}>{error}</div>}
63
78
  {results.length > 0 && (
64
- <ul className={styles.searchResults}>
79
+ <ul className={resultsClassName}>
65
80
  {results.map((place) => (
66
81
  <li
67
82
  key={place.id}
68
83
  onClick={() => handleSelect(place)}
69
- className={styles.searchResultItem}
84
+ className={resultItemClassName}
70
85
  >
71
86
  {place.name}
72
87
  </li>
@@ -76,7 +91,7 @@ const SearchBar: React.FC<SearchBarProps> = ({ apiClient, setUserLocation, setSe
76
91
  <button
77
92
  onClick={handleSearch}
78
93
  disabled={loading || !query}
79
- className={`${styles.searchButton} ${loading || !query ? styles.disabled : ''}`}
94
+ className={buttonClassName}
80
95
  >
81
96
  {loading ? 'Recherche...' : 'Rechercher'}
82
97
  </button>
@@ -1,7 +1,28 @@
1
1
  import React, { useState, useEffect } from 'react';
2
- import styles from './styles.module.css';
3
2
 
4
- const TransportOptions: React.FC = () => {
3
+ interface TransportOptionsProps {
4
+ className?: string;
5
+ headerClassName?: string;
6
+ titleClassName?: string;
7
+ toggleButtonClassName?: string;
8
+ optionsClassName?: string;
9
+ optionClassName?: string;
10
+ selectedOptionClassName?: string;
11
+ iconClassName?: string;
12
+ nameClassName?: string;
13
+ }
14
+
15
+ const TransportOptions: React.FC<TransportOptionsProps> = ({
16
+ className,
17
+ headerClassName,
18
+ titleClassName,
19
+ toggleButtonClassName,
20
+ optionsClassName,
21
+ optionClassName,
22
+ selectedOptionClassName,
23
+ iconClassName,
24
+ nameClassName,
25
+ }) => {
5
26
  const [showOptions, setShowOptions] = useState(false);
6
27
  const [selectedTransport, setSelectedTransport] = useState('taxi');
7
28
 
@@ -16,37 +37,34 @@ const TransportOptions: React.FC = () => {
16
37
  }, [selectedTransport]);
17
38
 
18
39
  return (
19
- <div className={styles.optionsSection}>
20
- <div className={styles.optionsHeader}>
21
- <h3 className={styles.optionsTitle}>Moyen de transport</h3>
40
+ <div className={className}>
41
+ <div className={headerClassName}>
42
+ <h3 className={titleClassName}>Moyen de transport</h3>
22
43
  <button
23
44
  onClick={() => setShowOptions(!showOptions)}
24
- className={styles.toggleButton}
45
+ className={toggleButtonClassName}
25
46
  >
26
47
  {showOptions ? 'Réduire' : 'Options'}
27
48
  </button>
28
49
  </div>
29
50
  {showOptions && (
30
- <div className={styles.transportOptions}>
51
+ <div className={optionsClassName}>
31
52
  {transportOptions.map((option) => (
32
53
  <button
33
54
  key={option.id}
34
55
  onClick={() => setSelectedTransport(option.id)}
35
- className={`${styles.transportOption} ${
36
- selectedTransport === option.id ? styles.selected : ''
37
- }`}
56
+ className={`${optionClassName} ${selectedTransport === option.id ? selectedOptionClassName : ''}`}
38
57
  style={{
39
58
  backgroundColor: selectedTransport === option.id ? option.color : undefined,
40
59
  }}
41
60
  >
42
- <span className={styles.transportIcon}>{option.icon}</span>
43
- <span className={styles.transportName}>{option.name}</span>
61
+ <span className={iconClassName}>{option.icon}</span>
62
+ <span className={nameClassName}>{option.name}</span>
44
63
  </button>
45
64
  ))}
46
65
  </div>
47
66
  )}
48
67
  </div>
49
-
50
68
  );
51
69
  };
52
70
 
@@ -1,7 +1,28 @@
1
1
  import React, { useState } from 'react';
2
- import styles from './styles.module.css';
3
2
 
4
- const TripType: React.FC = () => {
3
+ interface TripTypeProps {
4
+ className?: string;
5
+ headerClassName?: string;
6
+ titleClassName?: string;
7
+ toggleButtonClassName?: string;
8
+ optionsClassName?: string;
9
+ optionClassName?: string;
10
+ selectedOptionClassName?: string;
11
+ iconClassName?: string;
12
+ nameClassName?: string;
13
+ }
14
+
15
+ const TripType: React.FC<TripTypeProps> = ({
16
+ className,
17
+ headerClassName,
18
+ titleClassName,
19
+ toggleButtonClassName,
20
+ optionsClassName,
21
+ optionClassName,
22
+ selectedOptionClassName,
23
+ iconClassName,
24
+ nameClassName,
25
+ }) => {
5
26
  const [showOptions, setShowOptions] = useState(false);
6
27
  const [selectedTripType, setSelectedTripType] = useState('individuel');
7
28
 
@@ -11,31 +32,29 @@ const TripType: React.FC = () => {
11
32
  ];
12
33
 
13
34
  return (
14
- <div className={styles.optionsSection}>
15
- <div className={styles.optionsHeader}>
16
- <h3 className={styles.optionsTitle}>Type de trajet</h3>
35
+ <div className={className}>
36
+ <div className={headerClassName}>
37
+ <h3 className={titleClassName}>Type de trajet</h3>
17
38
  <button
18
39
  onClick={() => setShowOptions(!showOptions)}
19
- className={styles.toggleButton}
40
+ className={toggleButtonClassName}
20
41
  >
21
42
  {showOptions ? 'Réduire' : 'Options'}
22
43
  </button>
23
44
  </div>
24
45
  {showOptions && (
25
- <div className={styles.transportOptions}>
46
+ <div className={optionsClassName}>
26
47
  {tripTypeOptions.map((option) => (
27
48
  <button
28
49
  key={option.id}
29
50
  onClick={() => setSelectedTripType(option.id)}
30
- className={`${styles.transportOption} ${
31
- selectedTripType === option.id ? styles.selected : ''
32
- }`}
51
+ className={`${optionClassName} ${selectedTripType === option.id ? selectedOptionClassName : ''}`}
33
52
  style={{
34
53
  backgroundColor: selectedTripType === option.id ? option.color : undefined,
35
54
  }}
36
55
  >
37
- <span className={styles.transportIcon}>{option.icon}</span>
38
- <span className={styles.transportName}>{option.name}</span>
56
+ <span className={iconClassName}>{option.icon}</span>
57
+ <span className={nameClassName}>{option.name}</span>
39
58
  </button>
40
59
  ))}
41
60
  </div>
@@ -1,207 +0,0 @@
1
- .header {
2
- background-color: #fff;
3
- padding: 10px 20px;
4
- border-bottom: 1px solid #ddd;
5
- }
6
- .headerTitle {
7
- font-size: 24px;
8
- font-weight: bold;
9
- }
10
- .titleAccent {
11
- color: #007bff;
12
- }
13
- .mainContainer {
14
- display: flex;
15
- }
16
- .sidebar {
17
- width: 60px;
18
- background-color: #f4f4f4;
19
- display: flex;
20
- flex-direction: column;
21
- align-items: center;
22
- padding-top: 20px;
23
- }
24
- .sidebarButton {
25
- background: none;
26
- border: none;
27
- padding: 10px;
28
- cursor: pointer;
29
- margin-bottom: 20px;
30
- }
31
- .sidebarButton.active {
32
- background-color: #007bff;
33
- border-radius: 5px;
34
- }
35
- .contentPanel {
36
- flex: 1;
37
- padding: 20px;
38
- transition: all 0.3s;
39
- }
40
- .contentPanel.open {
41
- transform: translateX(0);
42
- }
43
- .sectionContainer {
44
- background-color: #fff;
45
- padding: 20px;
46
- border-radius: 8px;
47
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
48
- }
49
- .sectionTitle {
50
- font-size: 20px;
51
- margin-bottom: 20px;
52
- }
53
- .toggleContainer {
54
- display: flex;
55
- align-items: center;
56
- margin-bottom: 20px;
57
- }
58
- .switch {
59
- position: relative;
60
- display: inline-block;
61
- width: 40px;
62
- height: 20px;
63
- }
64
- .switch input {
65
- opacity: 0;
66
- width: 0;
67
- height: 0;
68
- }
69
- .slider {
70
- position: absolute;
71
- cursor: pointer;
72
- top: 0;
73
- left: 0;
74
- right: 0;
75
- bottom: 0;
76
- background-color: #ccc;
77
- border-radius: 20px;
78
- transition: 0.4s;
79
- }
80
- .slider:before {
81
- position: absolute;
82
- content: '';
83
- height: 16px;
84
- width: 16px;
85
- left: 2px;
86
- bottom: 2px;
87
- background-color: white;
88
- border-radius: 50%;
89
- transition: 0.4s;
90
- }
91
- .switch input:checked + .slider {
92
- background-color: #007bff;
93
- }
94
- .switch input:checked + .slider:before {
95
- transform: translateX(20px);
96
- }
97
- .toggleLabel {
98
- margin-left: 10px;
99
- }
100
- .locationButton {
101
- display: flex;
102
- align-items: center;
103
- padding: 10px 20px;
104
- background-color: #007bff;
105
- color: white;
106
- border: none;
107
- border-radius: 4px;
108
- cursor: pointer;
109
- }
110
- .locationButton:disabled {
111
- background-color: #ccc;
112
- cursor: not-allowed;
113
- }
114
- .error {
115
- color: red;
116
- margin: 10px 0;
117
- }
118
- .searchSection {
119
- padding: 20px;
120
- }
121
- .searchGroup {
122
- margin-bottom: 15px;
123
- }
124
- .label {
125
- display: block;
126
- font-weight: bold;
127
- margin-bottom: 5px;
128
- }
129
- .searchInput {
130
- width: 100%;
131
- padding: 8px;
132
- border: 1px solid #ccc;
133
- border-radius: 4px;
134
- }
135
- .searchResults {
136
- list-style: none;
137
- padding: 0;
138
- margin: 5px 0;
139
- border: 1px solid #ccc;
140
- max-height: 200px;
141
- overflow-y: auto;
142
- }
143
- .routeSearchSection {
144
- padding: 20px;
145
- }
146
- .route-search {
147
- margin-bottom: 20px;
148
- }
149
- .searchResultItem {
150
- padding: 8px;
151
- cursor: pointer;
152
- }
153
- .searchResultItem:hover {
154
- background-color: #f0f0f0;
155
- }
156
- .searchButton {
157
- padding: 10px 20px;
158
- background-color: #007bff;
159
- color: white;
160
- border: none;
161
- border-radius: 4px;
162
- cursor: pointer;
163
- }
164
- .searchButton.disabled {
165
- background-color: #ccc;
166
- cursor: not-allowed;
167
- }
168
- .optionsSection {
169
- margin-top: 20px;
170
- }
171
- .optionsHeader {
172
- display: flex;
173
- justify-content: space-between;
174
- align-items: center;
175
- }
176
- .optionsTitle {
177
- font-size: 16px;
178
- font-weight: bold;
179
- }
180
- .toggleButton {
181
- background: none;
182
- border: none;
183
- color: #007bff;
184
- cursor: pointer;
185
- }
186
- .transportOptions {
187
- display: flex;
188
- gap: 10px;
189
- margin-top: 10px;
190
- }
191
- .transportOption {
192
- display: flex;
193
- align-items: center;
194
- padding: 8px 16px;
195
- border: 1px solid #ccc;
196
- border-radius: 4px;
197
- cursor: pointer;
198
- }
199
- .transportOption.selected {
200
- border-color: #007bff;
201
- }
202
- .transportIcon {
203
- margin-right: 8px;
204
- }
205
- .transportName {
206
- font-size: 14px;
207
- }