@unabridged/midwest 0.24.3 → 0.25.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.
Files changed (28) hide show
  1. package/app/assets/javascript/midwest/index.ts +8 -0
  2. package/app/assets/javascript/midwest/map_providers.ts +61 -0
  3. package/app/assets/javascript/midwest.js +1009 -9
  4. package/app/assets/javascript/midwest.js.map +1 -1
  5. package/app/assets/stylesheets/midwest.css +1 -1
  6. package/app/assets/stylesheets/midwest.tailwind.css +13 -1
  7. package/dist/css/midwest.css +1 -1
  8. package/dist/javascript/collection/app/assets/javascript/midwest/index.js +8 -0
  9. package/dist/javascript/collection/app/assets/javascript/midwest/index.js.map +1 -1
  10. package/dist/javascript/collection/app/assets/javascript/midwest/map_providers.js +56 -0
  11. package/dist/javascript/collection/app/assets/javascript/midwest/map_providers.js.map +1 -0
  12. package/dist/javascript/collection/app/components/midwest/form/address_component/address_component_controller.js +441 -0
  13. package/dist/javascript/collection/app/components/midwest/form/address_component/address_component_controller.js.map +1 -0
  14. package/dist/javascript/collection/app/components/midwest/form/form_controller.js +37 -3
  15. package/dist/javascript/collection/app/components/midwest/form/form_controller.js.map +1 -1
  16. package/dist/javascript/collection/app/components/midwest/form/live_summary_component/live_summary_component_controller.js +55 -1
  17. package/dist/javascript/collection/app/components/midwest/form/live_summary_component/live_summary_component_controller.js.map +1 -1
  18. package/dist/javascript/collection/app/components/midwest/map_component/map_component_controller.js +297 -0
  19. package/dist/javascript/collection/app/components/midwest/map_component/map_component_controller.js.map +1 -0
  20. package/dist/javascript/collection/app/components/midwest/onboarding_component/onboarding_component_controller.js +34 -5
  21. package/dist/javascript/collection/app/components/midwest/onboarding_component/onboarding_component_controller.js.map +1 -1
  22. package/dist/javascript/collection/app/components/midwest/page_transition_component/page_transition_component_controller.js +38 -0
  23. package/dist/javascript/collection/app/components/midwest/page_transition_component/page_transition_component_controller.js.map +1 -0
  24. package/dist/javascript/collection/app/components/midwest/popover_component/popover_component_controller.js +67 -0
  25. package/dist/javascript/collection/app/components/midwest/popover_component/popover_component_controller.js.map +1 -0
  26. package/dist/javascript/midwest.js +1009 -9
  27. package/dist/javascript/midwest.js.map +1 -1
  28. package/package.json +1 -1
@@ -0,0 +1,297 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ import { loadMapKitScript, loadGoogleMapsScript, loadLeafletScript } from '../../../assets/javascript/midwest/map_providers.js';
3
+
4
+ const LEAFLET_TILES = {
5
+ MutedStandard: {
6
+ url: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png",
7
+ attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>'
8
+ },
9
+ Standard: {
10
+ url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
11
+ attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
12
+ maxZoom: 19
13
+ },
14
+ Hybrid: {
15
+ url: "https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png",
16
+ attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>'
17
+ },
18
+ Satellite: {
19
+ url: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
20
+ attribution: "Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community",
21
+ maxZoom: 18
22
+ },
23
+ Dark: {
24
+ url: "https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png",
25
+ attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>'
26
+ }
27
+ };
28
+ const GOOGLE_MUTED_STYLES = [
29
+ { elementType: "geometry", stylers: [{ color: "#f5f5f5" }] },
30
+ { elementType: "labels.icon", stylers: [{ visibility: "off" }] },
31
+ { elementType: "labels.text.fill", stylers: [{ color: "#616161" }] },
32
+ { elementType: "labels.text.stroke", stylers: [{ color: "#f5f5f5" }] },
33
+ { featureType: "administrative.land_parcel", elementType: "labels", stylers: [{ visibility: "off" }] },
34
+ { featureType: "poi", elementType: "geometry", stylers: [{ color: "#eeeeee" }] },
35
+ { featureType: "poi.park", elementType: "geometry", stylers: [{ color: "#e5e5e5" }] },
36
+ { featureType: "road", elementType: "geometry", stylers: [{ color: "#ffffff" }] },
37
+ { featureType: "road.highway", elementType: "geometry", stylers: [{ color: "#dadada" }] },
38
+ { featureType: "water", elementType: "geometry", stylers: [{ color: "#c9c9c9" }] }
39
+ ];
40
+ const GOOGLE_DARK_STYLES = [
41
+ { elementType: "geometry", stylers: [{ color: "#242f3e" }] },
42
+ { elementType: "labels.text.stroke", stylers: [{ color: "#242f3e" }] },
43
+ { elementType: "labels.text.fill", stylers: [{ color: "#746855" }] },
44
+ { featureType: "administrative.locality", elementType: "labels.text.fill", stylers: [{ color: "#d59563" }] },
45
+ { featureType: "poi", elementType: "labels.text.fill", stylers: [{ color: "#d59563" }] },
46
+ { featureType: "poi.park", elementType: "geometry", stylers: [{ color: "#263c3f" }] },
47
+ { featureType: "poi.park", elementType: "labels.text.fill", stylers: [{ color: "#6b9a76" }] },
48
+ { featureType: "road", elementType: "geometry", stylers: [{ color: "#38414e" }] },
49
+ { featureType: "road", elementType: "geometry.stroke", stylers: [{ color: "#212a37" }] },
50
+ { featureType: "road", elementType: "labels.text.fill", stylers: [{ color: "#9ca5b3" }] },
51
+ { featureType: "road.highway", elementType: "geometry", stylers: [{ color: "#746855" }] },
52
+ { featureType: "road.highway", elementType: "geometry.stroke", stylers: [{ color: "#1f2835" }] },
53
+ { featureType: "road.highway", elementType: "labels.text.fill", stylers: [{ color: "#f3d19c" }] },
54
+ { featureType: "transit", elementType: "geometry", stylers: [{ color: "#2f3948" }] },
55
+ { featureType: "transit.station", elementType: "labels.text.fill", stylers: [{ color: "#d59563" }] },
56
+ { featureType: "water", elementType: "geometry", stylers: [{ color: "#17263c" }] },
57
+ { featureType: "water", elementType: "labels.text.fill", stylers: [{ color: "#515c6d" }] },
58
+ { featureType: "water", elementType: "labels.text.stroke", stylers: [{ color: "#17263c" }] }
59
+ ];
60
+ class Map extends Controller {
61
+ static values = {
62
+ latitude: { type: Number, default: 37.334886 },
63
+ longitude: { type: Number, default: -122.008988 },
64
+ span: { type: Number, default: 0.1 },
65
+ mapType: { type: String, default: "MutedStandard" },
66
+ colorScheme: { type: String, default: "Auto" },
67
+ provider: { type: String, default: "" },
68
+ token: { type: String, default: "" },
69
+ tokenUrl: { type: String, default: "" },
70
+ apiKey: { type: String, default: "" },
71
+ zoom: { type: Number, default: -1 },
72
+ markers: { type: Array, default: [] },
73
+ showsUserLocation: { type: Boolean, default: false },
74
+ showsMapTypeControl: { type: Boolean, default: false },
75
+ showsZoomControl: { type: Boolean, default: true },
76
+ showsCompass: { type: String, default: "Adaptive" },
77
+ rotation: { type: Number, default: 0 }
78
+ };
79
+ mapInstance = null;
80
+ async connect() {
81
+ const provider = this.providerValue;
82
+ if (!provider)
83
+ return;
84
+ try {
85
+ if (provider === "mapkit") {
86
+ await loadMapKitScript();
87
+ this.initMapKit();
88
+ this.initMapKitMap();
89
+ } else if (provider === "google") {
90
+ await loadGoogleMapsScript(this.apiKeyValue);
91
+ this.initGoogleMap();
92
+ } else if (provider === "leaflet") {
93
+ await loadLeafletScript();
94
+ this.initLeafletMap();
95
+ }
96
+ } catch (err) {
97
+ console.error(`[midwest-map] Failed to initialise ${provider} map:`, err);
98
+ }
99
+ }
100
+ disconnect() {
101
+ if (this.mapInstance) {
102
+ if (this.providerValue === "mapkit")
103
+ this.mapInstance.destroy();
104
+ if (this.providerValue === "leaflet")
105
+ this.mapInstance.remove();
106
+ this.mapInstance = null;
107
+ }
108
+ }
109
+ tokenValueChanged() {
110
+ if (this.mapInstance && this.providerValue === "mapkit")
111
+ this.initMapKit();
112
+ }
113
+ // --- MapKit ---
114
+ initMapKit() {
115
+ const mk = window.mapkit;
116
+ const token = this.tokenValue;
117
+ const tokenUrl = this.tokenUrlValue;
118
+ mk.init({
119
+ authorizationCallback: (done) => {
120
+ if (token) {
121
+ done(token);
122
+ } else if (tokenUrl) {
123
+ fetch(tokenUrl).then((r) => r.text()).then(done).catch((err) => console.error("[midwest-map] Token fetch failed:", err));
124
+ }
125
+ },
126
+ language: document.documentElement.lang || "en"
127
+ });
128
+ }
129
+ initMapKitMap() {
130
+ const mk = window.mapkit;
131
+ const region = new mk.CoordinateRegion(
132
+ new mk.Coordinate(this.latitudeValue, this.longitudeValue),
133
+ new mk.CoordinateSpan(this.spanValue, this.spanValue)
134
+ );
135
+ const colorScheme = this.colorSchemeValue === "Auto" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? mk.Map.ColorSchemes.Dark : mk.Map.ColorSchemes.Light : mk.Map.ColorSchemes[this.colorSchemeValue];
136
+ this.mapInstance = new mk.Map(this.element, {
137
+ region,
138
+ mapType: mk.Map.MapTypes[this.mapTypeValue],
139
+ colorScheme,
140
+ showsUserLocation: this.showsUserLocationValue,
141
+ showsMapTypeControl: this.showsMapTypeControlValue,
142
+ showsZoomControl: this.showsZoomControlValue,
143
+ showsCompass: mk.FeatureVisibility[this.showsCompassValue],
144
+ rotation: this.rotationValue
145
+ });
146
+ this.addMapKitMarkers();
147
+ this.element.dataset.mapLoaded = "true";
148
+ }
149
+ addMapKitMarkers() {
150
+ const mk = window.mapkit;
151
+ if (!this.markersValue.length)
152
+ return;
153
+ const annotations = this.markersValue.map((m) => {
154
+ const opts = {};
155
+ if (m.title)
156
+ opts.title = m.title;
157
+ if (m.subtitle)
158
+ opts.subtitle = m.subtitle;
159
+ if (m.color)
160
+ opts.color = m.color;
161
+ if (m.glyphText)
162
+ opts.glyphText = m.glyphText;
163
+ return new mk.MarkerAnnotation(
164
+ new mk.Coordinate(m.latitude, m.longitude),
165
+ opts
166
+ );
167
+ });
168
+ this.mapInstance.addAnnotations(annotations);
169
+ const openIndex = this.markersValue.findIndex((m) => m.open);
170
+ if (openIndex >= 0) {
171
+ this.mapInstance.selectedAnnotation = annotations[openIndex];
172
+ }
173
+ }
174
+ // --- Google Maps ---
175
+ initGoogleMap() {
176
+ const g = window.google;
177
+ const zoom = this.zoomValue > 0 ? this.zoomValue : this.spanToZoom(this.spanValue);
178
+ const isDark = this.colorSchemeValue === "Dark" || this.colorSchemeValue === "Auto" && window.matchMedia("(prefers-color-scheme: dark)").matches;
179
+ const mapTypeId = this.googleMapTypeId();
180
+ const opts = {
181
+ center: { lat: this.latitudeValue, lng: this.longitudeValue },
182
+ zoom,
183
+ mapTypeId,
184
+ disableDefaultUI: true,
185
+ zoomControl: this.showsZoomControlValue,
186
+ mapTypeControl: this.showsMapTypeControlValue,
187
+ fullscreenControl: false,
188
+ streetViewControl: false
189
+ };
190
+ const styles = this.googleMapStyles(isDark, mapTypeId);
191
+ if (styles)
192
+ opts.styles = styles;
193
+ this.mapInstance = new g.maps.Map(this.element, opts);
194
+ this.addGoogleMarkers();
195
+ this.element.dataset.mapLoaded = "true";
196
+ }
197
+ googleMapTypeId() {
198
+ const types = {
199
+ Standard: "roadmap",
200
+ Hybrid: "hybrid",
201
+ Satellite: "satellite",
202
+ MutedStandard: "roadmap"
203
+ };
204
+ return types[this.mapTypeValue] ?? "roadmap";
205
+ }
206
+ googleMapStyles(isDark, mapTypeId) {
207
+ if (mapTypeId !== "roadmap")
208
+ return null;
209
+ if (isDark)
210
+ return GOOGLE_DARK_STYLES;
211
+ if (this.mapTypeValue === "MutedStandard")
212
+ return GOOGLE_MUTED_STYLES;
213
+ return null;
214
+ }
215
+ addGoogleMarkers() {
216
+ const g = window.google;
217
+ if (!this.markersValue.length)
218
+ return;
219
+ this.markersValue.forEach((m) => {
220
+ const marker = new g.maps.Marker({
221
+ map: this.mapInstance,
222
+ position: { lat: m.latitude, lng: m.longitude },
223
+ title: m.title ?? ""
224
+ });
225
+ if (m.open && m.title) {
226
+ const content = m.subtitle ? `<strong>${m.title}</strong><br><span style="color:#777">${m.subtitle}</span>` : `<strong>${m.title}</strong>`;
227
+ const infoWindow = new g.maps.InfoWindow({ content });
228
+ infoWindow.open(this.mapInstance, marker);
229
+ }
230
+ });
231
+ }
232
+ // --- Leaflet ---
233
+ initLeafletMap() {
234
+ const L = window.L;
235
+ const zoom = this.zoomValue > 0 ? this.zoomValue : this.spanToZoom(this.spanValue);
236
+ const isDark = this.colorSchemeValue === "Dark" || this.colorSchemeValue === "Auto" && window.matchMedia("(prefers-color-scheme: dark)").matches;
237
+ const tileKey = isDark ? "Dark" : this.mapTypeValue;
238
+ const tile = LEAFLET_TILES[tileKey] ?? LEAFLET_TILES.MutedStandard;
239
+ this.mapInstance = L.map(this.element, {
240
+ center: [this.latitudeValue, this.longitudeValue],
241
+ zoom,
242
+ zoomControl: this.showsZoomControlValue,
243
+ attributionControl: true
244
+ });
245
+ L.tileLayer(tile.url, {
246
+ attribution: tile.attribution,
247
+ maxZoom: tile.maxZoom ?? 19
248
+ }).addTo(this.mapInstance);
249
+ this.addLeafletMarkers();
250
+ this.element.dataset.mapLoaded = "true";
251
+ }
252
+ addLeafletMarkers() {
253
+ const L = window.L;
254
+ if (!this.markersValue.length)
255
+ return;
256
+ this.markersValue.forEach((m) => {
257
+ const icon = this.leafletMarkerIcon(m.color, m.glyphText);
258
+ const marker = L.marker([m.latitude, m.longitude], { icon }).addTo(this.mapInstance);
259
+ if (m.title) {
260
+ const content = m.subtitle ? `<strong>${m.title}</strong><br><span style="color:#777">${m.subtitle}</span>` : `<strong>${m.title}</strong>`;
261
+ marker.bindPopup(content);
262
+ if (m.open)
263
+ marker.openPopup();
264
+ }
265
+ });
266
+ }
267
+ // Returns a Leaflet icon — default blue when no color/glyph, otherwise a
268
+ // custom SVG pin rendered via divIcon.
269
+ leafletMarkerIcon(color, glyphText) {
270
+ const L = window.L;
271
+ if (!color && !glyphText)
272
+ return new L.Icon.Default();
273
+ const fill = color ?? "#2563eb";
274
+ const inner = glyphText ? `<text x="12" y="16" text-anchor="middle" font-size="9" font-family="system-ui,sans-serif" fill="white">${glyphText}</text>` : `<circle cx="12" cy="12" r="4" fill="rgba(255,255,255,0.9)"/>`;
275
+ const svg = [
276
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 36" width="24" height="36">',
277
+ ` <path d="M12 0C5.373 0 0 5.373 0 12c0 9 12 24 12 24s12-15 12-24C24 5.373 18.627 0 12 0z" fill="${fill}"/>`,
278
+ ` ${inner}`,
279
+ "</svg>"
280
+ ].join("");
281
+ return L.divIcon({
282
+ html: svg,
283
+ className: "",
284
+ iconSize: [24, 36],
285
+ iconAnchor: [12, 36],
286
+ popupAnchor: [0, -36]
287
+ });
288
+ }
289
+ // Approximate MapKit coordinate span to a Web Mercator zoom level.
290
+ // CoordinateSpan 360° = zoom 0; halving span adds 1 zoom level.
291
+ spanToZoom(span) {
292
+ return Math.round(Math.log2(360 / span));
293
+ }
294
+ }
295
+
296
+ export { Map as default };
297
+ //# sourceMappingURL=map_component_controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map_component_controller.js","sources":["../../../../../../../app/components/midwest/map_component/map_component_controller.ts"],"sourcesContent":["import { Controller } from '@hotwired/stimulus'\nimport { loadMapKitScript, loadGoogleMapsScript, loadLeafletScript } from '../../../assets/javascript/midwest/map_providers'\n\n// Leaflet tile layers keyed by Midwest map type (MapKit-style strings) and a\n// special 'Dark' entry for dark color schemes. CartoDB and ESRI tiles are free\n// for open-source / low-traffic use; no API key required.\nconst LEAFLET_TILES: Record<string, { url: string; attribution: string; maxZoom?: number }> = {\n MutedStandard: {\n url: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png',\n attribution: '&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors &copy; <a href=\"https://carto.com/attributions\">CARTO</a>'\n },\n Standard: {\n url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',\n attribution: '&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors',\n maxZoom: 19\n },\n Hybrid: {\n url: 'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png',\n attribution: '&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors &copy; <a href=\"https://carto.com/attributions\">CARTO</a>'\n },\n Satellite: {\n url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',\n attribution: 'Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community',\n maxZoom: 18\n },\n Dark: {\n url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png',\n attribution: '&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors &copy; <a href=\"https://carto.com/attributions\">CARTO</a>'\n }\n}\n\n// Muted (light) style for Google Maps — mirrors MapKit's MutedStandard.\nconst GOOGLE_MUTED_STYLES = [\n { elementType: 'geometry', stylers: [{ color: '#f5f5f5' }] },\n { elementType: 'labels.icon', stylers: [{ visibility: 'off' }] },\n { elementType: 'labels.text.fill', stylers: [{ color: '#616161' }] },\n { elementType: 'labels.text.stroke', stylers: [{ color: '#f5f5f5' }] },\n { featureType: 'administrative.land_parcel', elementType: 'labels', stylers: [{ visibility: 'off' }] },\n { featureType: 'poi', elementType: 'geometry', stylers: [{ color: '#eeeeee' }] },\n { featureType: 'poi.park', elementType: 'geometry', stylers: [{ color: '#e5e5e5' }] },\n { featureType: 'road', elementType: 'geometry', stylers: [{ color: '#ffffff' }] },\n { featureType: 'road.highway', elementType: 'geometry', stylers: [{ color: '#dadada' }] },\n { featureType: 'water', elementType: 'geometry', stylers: [{ color: '#c9c9c9' }] }\n]\n\n// Google's standard dark theme.\nconst GOOGLE_DARK_STYLES = [\n { elementType: 'geometry', stylers: [{ color: '#242f3e' }] },\n { elementType: 'labels.text.stroke', stylers: [{ color: '#242f3e' }] },\n { elementType: 'labels.text.fill', stylers: [{ color: '#746855' }] },\n { featureType: 'administrative.locality', elementType: 'labels.text.fill', stylers: [{ color: '#d59563' }] },\n { featureType: 'poi', elementType: 'labels.text.fill', stylers: [{ color: '#d59563' }] },\n { featureType: 'poi.park', elementType: 'geometry', stylers: [{ color: '#263c3f' }] },\n { featureType: 'poi.park', elementType: 'labels.text.fill', stylers: [{ color: '#6b9a76' }] },\n { featureType: 'road', elementType: 'geometry', stylers: [{ color: '#38414e' }] },\n { featureType: 'road', elementType: 'geometry.stroke', stylers: [{ color: '#212a37' }] },\n { featureType: 'road', elementType: 'labels.text.fill', stylers: [{ color: '#9ca5b3' }] },\n { featureType: 'road.highway', elementType: 'geometry', stylers: [{ color: '#746855' }] },\n { featureType: 'road.highway', elementType: 'geometry.stroke', stylers: [{ color: '#1f2835' }] },\n { featureType: 'road.highway', elementType: 'labels.text.fill', stylers: [{ color: '#f3d19c' }] },\n { featureType: 'transit', elementType: 'geometry', stylers: [{ color: '#2f3948' }] },\n { featureType: 'transit.station', elementType: 'labels.text.fill', stylers: [{ color: '#d59563' }] },\n { featureType: 'water', elementType: 'geometry', stylers: [{ color: '#17263c' }] },\n { featureType: 'water', elementType: 'labels.text.fill', stylers: [{ color: '#515c6d' }] },\n { featureType: 'water', elementType: 'labels.text.stroke', stylers: [{ color: '#17263c' }] }\n]\n\n\nexport default class Map extends Controller<HTMLElement> {\n static values = {\n latitude: { type: Number, default: 37.334886 },\n longitude: { type: Number, default: -122.008988 },\n span: { type: Number, default: 0.1 },\n mapType: { type: String, default: 'MutedStandard' },\n colorScheme: { type: String, default: 'Auto' },\n provider: { type: String, default: '' },\n token: { type: String, default: '' },\n tokenUrl: { type: String, default: '' },\n apiKey: { type: String, default: '' },\n zoom: { type: Number, default: -1 },\n markers: { type: Array, default: [] },\n showsUserLocation: { type: Boolean, default: false },\n showsMapTypeControl: { type: Boolean, default: false },\n showsZoomControl: { type: Boolean, default: true },\n showsCompass: { type: String, default: 'Adaptive' },\n rotation: { type: Number, default: 0 }\n }\n\n declare latitudeValue: number\n declare longitudeValue: number\n declare spanValue: number\n declare mapTypeValue: string\n declare colorSchemeValue: string\n declare providerValue: string\n declare tokenValue: string\n declare tokenUrlValue: string\n declare apiKeyValue: string\n declare zoomValue: number\n declare markersValue: {\n latitude: number\n longitude: number\n title?: string\n subtitle?: string\n color?: string\n glyphText?: string\n /** When true, the callout / info window is shown on first load. */\n open?: boolean\n }[]\n\n declare showsUserLocationValue: boolean\n declare showsMapTypeControlValue: boolean\n declare showsZoomControlValue: boolean\n declare showsCompassValue: string\n declare rotationValue: number\n\n private mapInstance: any = null\n\n async connect (): Promise<void> {\n const provider = this.providerValue\n if (!provider) return\n\n try {\n if (provider === 'mapkit') {\n await loadMapKitScript()\n this.initMapKit()\n this.initMapKitMap()\n } else if (provider === 'google') {\n await loadGoogleMapsScript(this.apiKeyValue)\n this.initGoogleMap()\n } else if (provider === 'leaflet') {\n await loadLeafletScript()\n this.initLeafletMap()\n }\n } catch (err) {\n console.error(`[midwest-map] Failed to initialise ${provider} map:`, err)\n }\n }\n\n disconnect (): void {\n if (this.mapInstance) {\n if (this.providerValue === 'mapkit') this.mapInstance.destroy()\n if (this.providerValue === 'leaflet') this.mapInstance.remove()\n this.mapInstance = null\n }\n }\n\n tokenValueChanged (): void {\n if (this.mapInstance && this.providerValue === 'mapkit') this.initMapKit()\n }\n\n // --- MapKit ---\n\n private initMapKit (): void {\n const mk = (window as any).mapkit\n const token = this.tokenValue\n const tokenUrl = this.tokenUrlValue\n\n mk.init({\n authorizationCallback: (done: (t: string) => void) => {\n if (token) {\n done(token)\n } else if (tokenUrl) {\n fetch(tokenUrl)\n .then(r => r.text())\n .then(done)\n .catch(err => console.error('[midwest-map] Token fetch failed:', err))\n }\n },\n language: document.documentElement.lang || 'en'\n })\n }\n\n private initMapKitMap (): void {\n const mk = (window as any).mapkit\n\n const region = new mk.CoordinateRegion(\n new mk.Coordinate(this.latitudeValue, this.longitudeValue),\n new mk.CoordinateSpan(this.spanValue, this.spanValue)\n )\n\n const colorScheme = this.colorSchemeValue === 'Auto'\n ? (window.matchMedia('(prefers-color-scheme: dark)').matches\n ? mk.Map.ColorSchemes.Dark\n : mk.Map.ColorSchemes.Light)\n : mk.Map.ColorSchemes[this.colorSchemeValue]\n\n this.mapInstance = new mk.Map(this.element, {\n region,\n mapType: mk.Map.MapTypes[this.mapTypeValue],\n colorScheme,\n showsUserLocation: this.showsUserLocationValue,\n showsMapTypeControl: this.showsMapTypeControlValue,\n showsZoomControl: this.showsZoomControlValue,\n showsCompass: mk.FeatureVisibility[this.showsCompassValue],\n rotation: this.rotationValue\n })\n\n this.addMapKitMarkers()\n this.element.dataset.mapLoaded = 'true'\n }\n\n private addMapKitMarkers (): void {\n const mk = (window as any).mapkit\n if (!this.markersValue.length) return\n\n const annotations = this.markersValue.map(m => {\n const opts: Record<string, any> = {}\n if (m.title) opts.title = m.title\n if (m.subtitle) opts.subtitle = m.subtitle\n if (m.color) opts.color = m.color\n if (m.glyphText) opts.glyphText = m.glyphText\n\n return new mk.MarkerAnnotation(\n new mk.Coordinate(m.latitude, m.longitude),\n opts\n )\n })\n\n this.mapInstance.addAnnotations(annotations)\n\n // Select the first marker flagged as open so its callout shows on load.\n const openIndex = this.markersValue.findIndex(m => m.open)\n if (openIndex >= 0) {\n this.mapInstance.selectedAnnotation = annotations[openIndex]\n }\n }\n\n // --- Google Maps ---\n\n private initGoogleMap (): void {\n const g = (window as any).google\n const zoom = this.zoomValue > 0 ? this.zoomValue : this.spanToZoom(this.spanValue)\n\n const isDark = this.colorSchemeValue === 'Dark' ||\n (this.colorSchemeValue === 'Auto' && window.matchMedia('(prefers-color-scheme: dark)').matches)\n\n const mapTypeId = this.googleMapTypeId()\n\n const opts: Record<string, any> = {\n center: { lat: this.latitudeValue, lng: this.longitudeValue },\n zoom,\n mapTypeId,\n disableDefaultUI: true,\n zoomControl: this.showsZoomControlValue,\n mapTypeControl: this.showsMapTypeControlValue,\n fullscreenControl: false,\n streetViewControl: false\n }\n\n const styles = this.googleMapStyles(isDark, mapTypeId)\n if (styles) opts.styles = styles\n\n this.mapInstance = new g.maps.Map(this.element, opts)\n this.addGoogleMarkers()\n this.element.dataset.mapLoaded = 'true'\n }\n\n private googleMapTypeId (): string {\n const types: Record<string, string> = {\n Standard: 'roadmap',\n Hybrid: 'hybrid',\n Satellite: 'satellite',\n MutedStandard: 'roadmap'\n }\n return types[this.mapTypeValue] ?? 'roadmap'\n }\n\n private googleMapStyles (isDark: boolean, mapTypeId: string): object[] | null {\n if (mapTypeId !== 'roadmap') return null\n if (isDark) return GOOGLE_DARK_STYLES\n if (this.mapTypeValue === 'MutedStandard') return GOOGLE_MUTED_STYLES\n return null\n }\n\n private addGoogleMarkers (): void {\n const g = (window as any).google\n if (!this.markersValue.length) return\n\n this.markersValue.forEach(m => {\n const marker = new g.maps.Marker({\n map: this.mapInstance,\n position: { lat: m.latitude, lng: m.longitude },\n title: m.title ?? ''\n })\n\n if (m.open && m.title) {\n const content = m.subtitle\n ? `<strong>${m.title}</strong><br><span style=\"color:#777\">${m.subtitle}</span>`\n : `<strong>${m.title}</strong>`\n const infoWindow = new g.maps.InfoWindow({ content })\n infoWindow.open(this.mapInstance, marker)\n }\n })\n }\n\n // --- Leaflet ---\n\n private initLeafletMap (): void {\n const L = (window as any).L\n const zoom = this.zoomValue > 0 ? this.zoomValue : this.spanToZoom(this.spanValue)\n\n const isDark = this.colorSchemeValue === 'Dark' ||\n (this.colorSchemeValue === 'Auto' && window.matchMedia('(prefers-color-scheme: dark)').matches)\n\n const tileKey = isDark ? 'Dark' : this.mapTypeValue\n const tile = LEAFLET_TILES[tileKey] ?? LEAFLET_TILES.MutedStandard\n\n this.mapInstance = L.map(this.element, {\n center: [this.latitudeValue, this.longitudeValue],\n zoom,\n zoomControl: this.showsZoomControlValue,\n attributionControl: true\n })\n\n L.tileLayer(tile.url, {\n attribution: tile.attribution,\n maxZoom: tile.maxZoom ?? 19\n }).addTo(this.mapInstance)\n\n this.addLeafletMarkers()\n this.element.dataset.mapLoaded = 'true'\n }\n\n private addLeafletMarkers (): void {\n const L = (window as any).L\n if (!this.markersValue.length) return\n\n this.markersValue.forEach(m => {\n const icon = this.leafletMarkerIcon(m.color, m.glyphText)\n const marker = L.marker([m.latitude, m.longitude], { icon })\n .addTo(this.mapInstance)\n\n if (m.title) {\n const content = m.subtitle\n ? `<strong>${m.title}</strong><br><span style=\"color:#777\">${m.subtitle}</span>`\n : `<strong>${m.title}</strong>`\n marker.bindPopup(content)\n if (m.open) marker.openPopup()\n }\n })\n }\n\n // Returns a Leaflet icon — default blue when no color/glyph, otherwise a\n // custom SVG pin rendered via divIcon.\n private leafletMarkerIcon (color?: string, glyphText?: string): any {\n const L = (window as any).L\n if (!color && !glyphText) return new L.Icon.Default()\n\n const fill = color ?? '#2563eb'\n const inner = glyphText\n ? `<text x=\"12\" y=\"16\" text-anchor=\"middle\" font-size=\"9\" font-family=\"system-ui,sans-serif\" fill=\"white\">${glyphText}</text>`\n : `<circle cx=\"12\" cy=\"12\" r=\"4\" fill=\"rgba(255,255,255,0.9)\"/>`\n\n const svg = [\n '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 36\" width=\"24\" height=\"36\">',\n ` <path d=\"M12 0C5.373 0 0 5.373 0 12c0 9 12 24 12 24s12-15 12-24C24 5.373 18.627 0 12 0z\" fill=\"${fill}\"/>`,\n ` ${inner}`,\n '</svg>'\n ].join('')\n\n return L.divIcon({\n html: svg,\n className: '',\n iconSize: [24, 36] as [number, number],\n iconAnchor: [12, 36] as [number, number],\n popupAnchor: [0, -36] as [number, number]\n })\n }\n\n // Approximate MapKit coordinate span to a Web Mercator zoom level.\n // CoordinateSpan 360° = zoom 0; halving span adds 1 zoom level.\n private spanToZoom (span: number): number {\n return Math.round(Math.log2(360 / span))\n }\n}\n"],"names":[],"mappings":"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"}
@@ -10,14 +10,14 @@ const FOCUSABLE = [
10
10
  ].join(", ");
11
11
  const GAP = 12;
12
12
  class Onboarding extends Controller {
13
- static targets = ["step", "overlay", "card", "title", "body", "back", "next", "done", "arrow"];
13
+ static targets = ["step", "overlay", "card", "title", "body", "back", "next", "done", "arrow", "motion"];
14
14
  static values = {
15
- autoOpen: { type: Boolean, default: false },
16
- confirm: { type: String, default: "" }
15
+ autoOpen: { type: Boolean, default: false }
17
16
  };
18
17
  steps = [];
19
18
  index = 0;
20
19
  active = false;
20
+ justOpened = false;
21
21
  previousFocus = null;
22
22
  highlighted = null;
23
23
  connect() {
@@ -47,6 +47,7 @@ class Onboarding extends Controller {
47
47
  this.previousFocus = document.activeElement;
48
48
  this.overlayTarget.hidden = false;
49
49
  this.cardTarget.hidden = false;
50
+ this.justOpened = true;
50
51
  document.addEventListener("keydown", this.handleKeydown, true);
51
52
  window.addEventListener("resize", this.reposition);
52
53
  window.addEventListener("scroll", this.reposition, true);
@@ -81,14 +82,14 @@ class Onboarding extends Controller {
81
82
  cancel() {
82
83
  if (!this.active)
83
84
  return;
84
- if (this.confirmValue && !window.confirm(this.confirmValue))
85
- return;
86
85
  this.teardown();
87
86
  this.dispatch("cancel", { bubbles: true });
88
87
  }
89
88
  render(index) {
90
89
  this.index = index;
91
90
  const step = this.steps[index];
91
+ const replay = !this.justOpened;
92
+ this.justOpened = false;
92
93
  this.clearHighlight();
93
94
  this.titleTarget.textContent = step.title;
94
95
  this.renderBody(step);
@@ -100,6 +101,9 @@ class Onboarding extends Controller {
100
101
  } else {
101
102
  this.center();
102
103
  }
104
+ if (replay && this.hasMotionTarget) {
105
+ this.replayMotion(this.cardTarget.dataset.placement ?? "center");
106
+ }
103
107
  this.dispatch("show", { detail: { index, name: step.name }, bubbles: true });
104
108
  this.focusCard();
105
109
  }
@@ -201,9 +205,34 @@ class Onboarding extends Controller {
201
205
  this.cardTarget.focus();
202
206
  });
203
207
  }
208
+ // Re-triggers the midwest_motion @starting-style entry on step transitions.
209
+ // The initial show is handled by @starting-style firing when the card's
210
+ // `hidden` is removed; subsequent steps need an explicit re-trigger since the
211
+ // card stays in the DOM. Toggling `hidden` on the motion element triggers
212
+ // @starting-style again; the rAF ensures both DOM writes land in the same
213
+ // paint so there is no blank-card flash.
214
+ replayMotion(placement) {
215
+ const el = this.motionTarget;
216
+ const dir = { bottom: "up", top: "down", right: "left", left: "right" };
217
+ el.classList.remove("from-up", "from-down", "from-left", "from-right");
218
+ const from = dir[placement];
219
+ if (from)
220
+ el.classList.add(`from-${from}`);
221
+ el.hidden = true;
222
+ requestAnimationFrame(() => {
223
+ if (this.active)
224
+ el.hidden = false;
225
+ });
226
+ }
204
227
  teardown() {
205
228
  this.active = false;
206
229
  this.clearHighlight();
230
+ this.element.querySelectorAll("[popover]").forEach((el) => {
231
+ try {
232
+ el.hidePopover();
233
+ } catch {
234
+ }
235
+ });
207
236
  this.overlayTarget.hidden = true;
208
237
  this.cardTarget.hidden = true;
209
238
  document.removeEventListener("keydown", this.handleKeydown, true);
@@ -1 +1 @@
1
- {"version":3,"file":"onboarding_component_controller.js","sources":["../../../../../../../app/components/midwest/onboarding_component/onboarding_component_controller.ts"],"sourcesContent":["import { Controller } from '@hotwired/stimulus'\n\nconst FOCUSABLE = [\n 'a[href]',\n 'button:not([disabled])',\n 'textarea:not([disabled])',\n 'input:not([disabled])',\n 'select:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])'\n].join(', ')\n\nconst GAP = 12 // px between the target and the card\n\ninterface StepConfig {\n el: HTMLElement\n name: string\n selector: string\n position: string\n title: string\n nextText: string\n backText: string\n completeText: string\n canClickTarget: boolean\n}\n\n// Native, dependency-free guided-tour engine. Reads the nested step config\n// carriers, then walks the user through them with a dimmed overlay, a card\n// positioned against each step's target element, and Back/Next/Done buttons.\nexport default class Onboarding extends Controller<HTMLElement> {\n static targets = ['step', 'overlay', 'card', 'title', 'body', 'back', 'next', 'done', 'arrow']\n\n static values = {\n autoOpen: { type: Boolean, default: false },\n confirm: { type: String, default: '' }\n }\n\n declare readonly stepTargets: HTMLElement[]\n declare readonly overlayTarget: HTMLElement\n declare readonly cardTarget: HTMLElement\n declare readonly titleTarget: HTMLElement\n declare readonly bodyTarget: HTMLElement\n declare readonly backTarget: HTMLButtonElement\n declare readonly nextTarget: HTMLButtonElement\n declare readonly doneTarget: HTMLButtonElement\n declare readonly arrowTarget: HTMLElement\n declare autoOpenValue: boolean\n declare confirmValue: string\n\n private steps: StepConfig[] = []\n private index = 0\n private active = false\n private previousFocus: HTMLElement | null = null\n private highlighted: HTMLElement | null = null\n\n connect () {\n this.steps = this.stepTargets.map((el) => ({\n el,\n name: el.dataset.name ?? '',\n selector: el.dataset.selector ?? '',\n position: el.dataset.position ?? 'auto',\n title: el.dataset.title ?? '',\n nextText: el.dataset.nextText ?? 'Next',\n backText: el.dataset.backText ?? 'Back',\n completeText: el.dataset.completeText ?? 'Done',\n canClickTarget: el.dataset.canClickTarget === 'true'\n }))\n\n window.addEventListener('midwest-onboarding:open', this.handleOpen)\n\n if (this.autoOpenValue) this.start()\n }\n\n disconnect () {\n window.removeEventListener('midwest-onboarding:open', this.handleOpen)\n this.teardown()\n }\n\n start () {\n if (this.active || this.steps.length === 0) return\n this.active = true\n this.previousFocus = document.activeElement as HTMLElement | null\n this.overlayTarget.hidden = false\n this.cardTarget.hidden = false\n document.addEventListener('keydown', this.handleKeydown, true)\n window.addEventListener('resize', this.reposition)\n window.addEventListener('scroll', this.reposition, true)\n this.dispatch('start', { bubbles: true })\n this.render(0)\n }\n\n next () {\n if (this.index < this.steps.length - 1) this.render(this.index + 1)\n else this.complete()\n }\n\n back () {\n if (this.index > 0) this.render(this.index - 1)\n }\n\n // Jump to a step by its `name`.\n show (name: string) {\n const target = this.steps.findIndex((step) => step.name === name)\n if (target >= 0) {\n if (!this.active) this.start()\n this.render(target)\n }\n }\n\n complete () {\n if (!this.active) return\n this.teardown()\n this.dispatch('complete', { bubbles: true })\n }\n\n cancel () {\n if (!this.active) return\n if (this.confirmValue && !window.confirm(this.confirmValue)) return\n this.teardown()\n this.dispatch('cancel', { bubbles: true })\n }\n\n private render (index: number) {\n this.index = index\n const step = this.steps[index]\n\n this.clearHighlight()\n\n this.titleTarget.textContent = step.title\n this.renderBody(step)\n this.renderButtons(step, index)\n\n const target = step.selector\n ? document.querySelector<HTMLElement>(step.selector)\n : null\n\n if (target) {\n this.highlight(target, step.canClickTarget)\n this.position(target, step.position)\n } else {\n this.center()\n }\n\n this.dispatch('show', { detail: { index, name: step.name }, bubbles: true })\n this.focusCard()\n }\n\n private renderBody (step: StepConfig) {\n this.bodyTarget.replaceChildren()\n const template = step.el.querySelector('template')\n if (template) this.bodyTarget.appendChild(template.content.cloneNode(true))\n }\n\n private renderButtons (step: StepConfig, index: number) {\n const isFirst = index === 0\n const isLast = index === this.steps.length - 1\n\n // Back keeps its layout box (visibility) so the forward button never shifts;\n // Next and Done are mutually exclusive, so exactly one fills the right slot.\n this.backTarget.textContent = step.backText\n this.backTarget.style.visibility = isFirst ? 'hidden' : ''\n\n // Inline display beats the button's own `display: inline-flex` rule.\n this.nextTarget.textContent = step.nextText\n this.nextTarget.style.display = isLast ? 'none' : ''\n\n this.doneTarget.textContent = step.completeText\n this.doneTarget.style.display = isLast ? '' : 'none'\n }\n\n private highlight (target: HTMLElement, canClickTarget: boolean) {\n target.classList.add('midwest-onboarding-highlight')\n target.classList.toggle('is-locked', !canClickTarget)\n this.highlighted = target\n target.scrollIntoView({ behavior: 'smooth', block: 'center' })\n }\n\n private clearHighlight () {\n this.highlighted?.classList.remove('midwest-onboarding-highlight', 'is-locked')\n this.highlighted = null\n }\n\n // Places the card against the target, choosing a side when `position` is auto.\n private position (target: HTMLElement, position: string) {\n const rect = target.getBoundingClientRect()\n const card = this.cardTarget.getBoundingClientRect()\n const vw = window.innerWidth\n const vh = window.innerHeight\n\n let placement = position\n if (placement === 'auto') {\n if (rect.bottom + card.height + GAP <= vh) placement = 'bottom'\n else if (rect.top - card.height - GAP >= 0) placement = 'top'\n else if (rect.right + card.width + GAP <= vw) placement = 'right'\n else placement = 'left'\n }\n\n let top: number\n let left: number\n\n switch (placement) {\n case 'top':\n top = rect.top - card.height - GAP\n left = rect.left + rect.width / 2 - card.width / 2\n break\n case 'left':\n top = rect.top + rect.height / 2 - card.height / 2\n left = rect.left - card.width - GAP\n break\n case 'right':\n top = rect.top + rect.height / 2 - card.height / 2\n left = rect.right + GAP\n break\n default: // bottom\n top = rect.bottom + GAP\n left = rect.left + rect.width / 2 - card.width / 2\n break\n }\n\n // Keep the card fully on screen.\n left = Math.max(8, Math.min(left, vw - card.width - 8))\n top = Math.max(8, Math.min(top, vh - card.height - 8))\n\n this.cardTarget.style.top = `${top}px`\n this.cardTarget.style.left = `${left}px`\n this.cardTarget.dataset.placement = placement\n\n this.positionArrow(placement, rect, top, left)\n }\n\n // Nudges the arrow so it points at the target's center, not the card's.\n private positionArrow (placement: string, rect: DOMRect, top: number, left: number) {\n const card = this.cardTarget.getBoundingClientRect()\n const arrow = this.arrowTarget.style\n\n if (placement === 'top' || placement === 'bottom') {\n const targetCenter = rect.left + rect.width / 2\n const offset = Math.max(12, Math.min(targetCenter - left, card.width - 12))\n arrow.left = `${offset}px`\n arrow.top = ''\n } else {\n const targetCenter = rect.top + rect.height / 2\n const offset = Math.max(12, Math.min(targetCenter - top, card.height - 12))\n arrow.top = `${offset}px`\n arrow.left = ''\n }\n }\n\n private center () {\n const card = this.cardTarget.getBoundingClientRect()\n this.cardTarget.style.top = `${Math.max(8, window.innerHeight / 2 - card.height / 2)}px`\n this.cardTarget.style.left = `${Math.max(8, window.innerWidth / 2 - card.width / 2)}px`\n this.cardTarget.dataset.placement = 'center'\n }\n\n private focusCard () {\n requestAnimationFrame(() => {\n if (this.active) this.cardTarget.focus()\n })\n }\n\n private teardown () {\n this.active = false\n this.clearHighlight()\n this.overlayTarget.hidden = true\n this.cardTarget.hidden = true\n document.removeEventListener('keydown', this.handleKeydown, true)\n window.removeEventListener('resize', this.reposition)\n window.removeEventListener('scroll', this.reposition, true)\n this.previousFocus?.focus()\n this.previousFocus = null\n }\n\n private handleOpen = (event: Event) => {\n const detail = (event as CustomEvent).detail ?? {}\n const id = String(detail.id ?? '').replace('#', '')\n if (id === this.element.id) this.start()\n }\n\n private reposition = () => {\n if (!this.active) return\n const step = this.steps[this.index]\n const target = step.selector ? document.querySelector<HTMLElement>(step.selector) : null\n if (target) this.position(target, step.position)\n else this.center()\n }\n\n private handleKeydown = (event: KeyboardEvent) => {\n if (!this.active) return\n\n switch (event.key) {\n case 'Escape':\n event.preventDefault()\n this.cancel()\n break\n case 'ArrowRight':\n event.preventDefault()\n this.next()\n break\n case 'ArrowLeft':\n event.preventDefault()\n this.back()\n break\n case 'Tab':\n this.trapTab(event)\n break\n }\n }\n\n // Keep Tab focus within the card while the tour is active.\n private trapTab (event: KeyboardEvent) {\n const focusable = Array.from(this.cardTarget.querySelectorAll<HTMLElement>(FOCUSABLE))\n .filter((el) => !el.hidden && el.offsetParent !== null && getComputedStyle(el).visibility !== 'hidden')\n if (focusable.length === 0) return\n\n const first = focusable[0]\n const last = focusable[focusable.length - 1]\n const active = document.activeElement\n\n if (event.shiftKey) {\n if (active === first || active === this.cardTarget || !this.cardTarget.contains(active)) {\n event.preventDefault()\n last.focus()\n }\n } else if (active === last || !this.cardTarget.contains(active)) {\n event.preventDefault()\n first.focus()\n }\n }\n}\n"],"names":[],"mappings":";;AAEA,MAAM,SAAY,GAAA;AAAA,EAChB,SAAA;AAAA,EACA,wBAAA;AAAA,EACA,0BAAA;AAAA,EACA,uBAAA;AAAA,EACA,wBAAA;AAAA,EACA,iCAAA;AACF,CAAA,CAAE,KAAK,IAAI,CAAA,CAAA;AAEX,MAAM,GAAM,GAAA,EAAA,CAAA;AAiBZ,MAAqB,mBAAmB,UAAwB,CAAA;AAAA,EAC9D,OAAO,OAAU,GAAA,CAAC,MAAQ,EAAA,SAAA,EAAW,MAAQ,EAAA,OAAA,EAAS,MAAQ,EAAA,MAAA,EAAQ,MAAQ,EAAA,MAAA,EAAQ,OAAO,CAAA,CAAA;AAAA,EAE7F,OAAO,MAAS,GAAA;AAAA,IACd,QAAU,EAAA,EAAE,IAAM,EAAA,OAAA,EAAS,SAAS,KAAM,EAAA;AAAA,IAC1C,OAAS,EAAA,EAAE,IAAM,EAAA,MAAA,EAAQ,SAAS,EAAG,EAAA;AAAA,GACvC,CAAA;AAAA,EAcQ,QAAsB,EAAC,CAAA;AAAA,EACvB,KAAQ,GAAA,CAAA,CAAA;AAAA,EACR,MAAS,GAAA,KAAA,CAAA;AAAA,EACT,aAAoC,GAAA,IAAA,CAAA;AAAA,EACpC,WAAkC,GAAA,IAAA,CAAA;AAAA,EAE1C,OAAW,GAAA;AACT,IAAA,IAAA,CAAK,KAAQ,GAAA,IAAA,CAAK,WAAY,CAAA,GAAA,CAAI,CAAC,EAAQ,MAAA;AAAA,MACzC,EAAA;AAAA,MACA,IAAA,EAAM,EAAG,CAAA,OAAA,CAAQ,IAAQ,IAAA,EAAA;AAAA,MACzB,QAAA,EAAU,EAAG,CAAA,OAAA,CAAQ,QAAY,IAAA,EAAA;AAAA,MACjC,QAAA,EAAU,EAAG,CAAA,OAAA,CAAQ,QAAY,IAAA,MAAA;AAAA,MACjC,KAAA,EAAO,EAAG,CAAA,OAAA,CAAQ,KAAS,IAAA,EAAA;AAAA,MAC3B,QAAA,EAAU,EAAG,CAAA,OAAA,CAAQ,QAAY,IAAA,MAAA;AAAA,MACjC,QAAA,EAAU,EAAG,CAAA,OAAA,CAAQ,QAAY,IAAA,MAAA;AAAA,MACjC,YAAA,EAAc,EAAG,CAAA,OAAA,CAAQ,YAAgB,IAAA,MAAA;AAAA,MACzC,cAAA,EAAgB,EAAG,CAAA,OAAA,CAAQ,cAAmB,KAAA,MAAA;AAAA,KAC9C,CAAA,CAAA,CAAA;AAEF,IAAO,MAAA,CAAA,gBAAA,CAAiB,yBAA2B,EAAA,IAAA,CAAK,UAAU,CAAA,CAAA;AAElE,IAAA,IAAI,IAAK,CAAA,aAAA;AAAe,MAAA,IAAA,CAAK,KAAM,EAAA,CAAA;AAAA,GACrC;AAAA,EAEA,UAAc,GAAA;AACZ,IAAO,MAAA,CAAA,mBAAA,CAAoB,yBAA2B,EAAA,IAAA,CAAK,UAAU,CAAA,CAAA;AACrE,IAAA,IAAA,CAAK,QAAS,EAAA,CAAA;AAAA,GAChB;AAAA,EAEA,KAAS,GAAA;AACP,IAAA,IAAI,IAAK,CAAA,MAAA,IAAU,IAAK,CAAA,KAAA,CAAM,MAAW,KAAA,CAAA;AAAG,MAAA,OAAA;AAC5C,IAAA,IAAA,CAAK,MAAS,GAAA,IAAA,CAAA;AACd,IAAA,IAAA,CAAK,gBAAgB,QAAS,CAAA,aAAA,CAAA;AAC9B,IAAA,IAAA,CAAK,cAAc,MAAS,GAAA,KAAA,CAAA;AAC5B,IAAA,IAAA,CAAK,WAAW,MAAS,GAAA,KAAA,CAAA;AACzB,IAAA,QAAA,CAAS,gBAAiB,CAAA,SAAA,EAAW,IAAK,CAAA,aAAA,EAAe,IAAI,CAAA,CAAA;AAC7D,IAAO,MAAA,CAAA,gBAAA,CAAiB,QAAU,EAAA,IAAA,CAAK,UAAU,CAAA,CAAA;AACjD,IAAA,MAAA,CAAO,gBAAiB,CAAA,QAAA,EAAU,IAAK,CAAA,UAAA,EAAY,IAAI,CAAA,CAAA;AACvD,IAAA,IAAA,CAAK,QAAS,CAAA,OAAA,EAAS,EAAE,OAAA,EAAS,MAAM,CAAA,CAAA;AACxC,IAAA,IAAA,CAAK,OAAO,CAAC,CAAA,CAAA;AAAA,GACf;AAAA,EAEA,IAAQ,GAAA;AACN,IAAA,IAAI,IAAK,CAAA,KAAA,GAAQ,IAAK,CAAA,KAAA,CAAM,MAAS,GAAA,CAAA;AAAG,MAAK,IAAA,CAAA,MAAA,CAAO,IAAK,CAAA,KAAA,GAAQ,CAAC,CAAA,CAAA;AAAA;AAC7D,MAAA,IAAA,CAAK,QAAS,EAAA,CAAA;AAAA,GACrB;AAAA,EAEA,IAAQ,GAAA;AACN,IAAA,IAAI,KAAK,KAAQ,GAAA,CAAA;AAAG,MAAK,IAAA,CAAA,MAAA,CAAO,IAAK,CAAA,KAAA,GAAQ,CAAC,CAAA,CAAA;AAAA,GAChD;AAAA;AAAA,EAGA,KAAM,IAAc,EAAA;AAClB,IAAM,MAAA,MAAA,GAAS,KAAK,KAAM,CAAA,SAAA,CAAU,CAAC,IAAS,KAAA,IAAA,CAAK,SAAS,IAAI,CAAA,CAAA;AAChE,IAAA,IAAI,UAAU,CAAG,EAAA;AACf,MAAA,IAAI,CAAC,IAAK,CAAA,MAAA;AAAQ,QAAA,IAAA,CAAK,KAAM,EAAA,CAAA;AAC7B,MAAA,IAAA,CAAK,OAAO,MAAM,CAAA,CAAA;AAAA,KACpB;AAAA,GACF;AAAA,EAEA,QAAY,GAAA;AACV,IAAA,IAAI,CAAC,IAAK,CAAA,MAAA;AAAQ,MAAA,OAAA;AAClB,IAAA,IAAA,CAAK,QAAS,EAAA,CAAA;AACd,IAAA,IAAA,CAAK,QAAS,CAAA,UAAA,EAAY,EAAE,OAAA,EAAS,MAAM,CAAA,CAAA;AAAA,GAC7C;AAAA,EAEA,MAAU,GAAA;AACR,IAAA,IAAI,CAAC,IAAK,CAAA,MAAA;AAAQ,MAAA,OAAA;AAClB,IAAA,IAAI,KAAK,YAAgB,IAAA,CAAC,MAAO,CAAA,OAAA,CAAQ,KAAK,YAAY,CAAA;AAAG,MAAA,OAAA;AAC7D,IAAA,IAAA,CAAK,QAAS,EAAA,CAAA;AACd,IAAA,IAAA,CAAK,QAAS,CAAA,QAAA,EAAU,EAAE,OAAA,EAAS,MAAM,CAAA,CAAA;AAAA,GAC3C;AAAA,EAEQ,OAAQ,KAAe,EAAA;AAC7B,IAAA,IAAA,CAAK,KAAQ,GAAA,KAAA,CAAA;AACb,IAAM,MAAA,IAAA,GAAO,IAAK,CAAA,KAAA,CAAM,KAAK,CAAA,CAAA;AAE7B,IAAA,IAAA,CAAK,cAAe,EAAA,CAAA;AAEpB,IAAK,IAAA,CAAA,WAAA,CAAY,cAAc,IAAK,CAAA,KAAA,CAAA;AACpC,IAAA,IAAA,CAAK,WAAW,IAAI,CAAA,CAAA;AACpB,IAAK,IAAA,CAAA,aAAA,CAAc,MAAM,KAAK,CAAA,CAAA;AAE9B,IAAA,MAAM,SAAS,IAAK,CAAA,QAAA,GAChB,SAAS,aAA2B,CAAA,IAAA,CAAK,QAAQ,CACjD,GAAA,IAAA,CAAA;AAEJ,IAAA,IAAI,MAAQ,EAAA;AACV,MAAK,IAAA,CAAA,SAAA,CAAU,MAAQ,EAAA,IAAA,CAAK,cAAc,CAAA,CAAA;AAC1C,MAAK,IAAA,CAAA,QAAA,CAAS,MAAQ,EAAA,IAAA,CAAK,QAAQ,CAAA,CAAA;AAAA,KAC9B,MAAA;AACL,MAAA,IAAA,CAAK,MAAO,EAAA,CAAA;AAAA,KACd;AAEA,IAAA,IAAA,CAAK,QAAS,CAAA,MAAA,EAAQ,EAAE,MAAA,EAAQ,EAAE,KAAA,EAAO,IAAM,EAAA,IAAA,CAAK,IAAK,EAAA,EAAG,OAAS,EAAA,IAAA,EAAM,CAAA,CAAA;AAC3E,IAAA,IAAA,CAAK,SAAU,EAAA,CAAA;AAAA,GACjB;AAAA,EAEQ,WAAY,IAAkB,EAAA;AACpC,IAAA,IAAA,CAAK,WAAW,eAAgB,EAAA,CAAA;AAChC,IAAA,MAAM,QAAW,GAAA,IAAA,CAAK,EAAG,CAAA,aAAA,CAAc,UAAU,CAAA,CAAA;AACjD,IAAI,IAAA,QAAA;AAAU,MAAA,IAAA,CAAK,WAAW,WAAY,CAAA,QAAA,CAAS,OAAQ,CAAA,SAAA,CAAU,IAAI,CAAC,CAAA,CAAA;AAAA,GAC5E;AAAA,EAEQ,aAAA,CAAe,MAAkB,KAAe,EAAA;AACtD,IAAA,MAAM,UAAU,KAAU,KAAA,CAAA,CAAA;AAC1B,IAAA,MAAM,MAAS,GAAA,KAAA,KAAU,IAAK,CAAA,KAAA,CAAM,MAAS,GAAA,CAAA,CAAA;AAI7C,IAAK,IAAA,CAAA,UAAA,CAAW,cAAc,IAAK,CAAA,QAAA,CAAA;AACnC,IAAA,IAAA,CAAK,UAAW,CAAA,KAAA,CAAM,UAAa,GAAA,OAAA,GAAU,QAAW,GAAA,EAAA,CAAA;AAGxD,IAAK,IAAA,CAAA,UAAA,CAAW,cAAc,IAAK,CAAA,QAAA,CAAA;AACnC,IAAA,IAAA,CAAK,UAAW,CAAA,KAAA,CAAM,OAAU,GAAA,MAAA,GAAS,MAAS,GAAA,EAAA,CAAA;AAElD,IAAK,IAAA,CAAA,UAAA,CAAW,cAAc,IAAK,CAAA,YAAA,CAAA;AACnC,IAAA,IAAA,CAAK,UAAW,CAAA,KAAA,CAAM,OAAU,GAAA,MAAA,GAAS,EAAK,GAAA,MAAA,CAAA;AAAA,GAChD;AAAA,EAEQ,SAAA,CAAW,QAAqB,cAAyB,EAAA;AAC/D,IAAO,MAAA,CAAA,SAAA,CAAU,IAAI,8BAA8B,CAAA,CAAA;AACnD,IAAA,MAAA,CAAO,SAAU,CAAA,MAAA,CAAO,WAAa,EAAA,CAAC,cAAc,CAAA,CAAA;AACpD,IAAA,IAAA,CAAK,WAAc,GAAA,MAAA,CAAA;AACnB,IAAA,MAAA,CAAO,eAAe,EAAE,QAAA,EAAU,QAAU,EAAA,KAAA,EAAO,UAAU,CAAA,CAAA;AAAA,GAC/D;AAAA,EAEQ,cAAkB,GAAA;AACxB,IAAA,IAAA,CAAK,WAAa,EAAA,SAAA,CAAU,MAAO,CAAA,8BAAA,EAAgC,WAAW,CAAA,CAAA;AAC9E,IAAA,IAAA,CAAK,WAAc,GAAA,IAAA,CAAA;AAAA,GACrB;AAAA;AAAA,EAGQ,QAAA,CAAU,QAAqB,QAAkB,EAAA;AACvD,IAAM,MAAA,IAAA,GAAO,OAAO,qBAAsB,EAAA,CAAA;AAC1C,IAAM,MAAA,IAAA,GAAO,IAAK,CAAA,UAAA,CAAW,qBAAsB,EAAA,CAAA;AACnD,IAAA,MAAM,KAAK,MAAO,CAAA,UAAA,CAAA;AAClB,IAAA,MAAM,KAAK,MAAO,CAAA,WAAA,CAAA;AAElB,IAAA,IAAI,SAAY,GAAA,QAAA,CAAA;AAChB,IAAA,IAAI,cAAc,MAAQ,EAAA;AACxB,MAAA,IAAI,IAAK,CAAA,MAAA,GAAS,IAAK,CAAA,MAAA,GAAS,GAAO,IAAA,EAAA;AAAI,QAAY,SAAA,GAAA,QAAA,CAAA;AAAA,WAAA,IAC9C,IAAK,CAAA,GAAA,GAAM,IAAK,CAAA,MAAA,GAAS,GAAO,IAAA,CAAA;AAAG,QAAY,SAAA,GAAA,KAAA,CAAA;AAAA,WAAA,IAC/C,IAAK,CAAA,KAAA,GAAQ,IAAK,CAAA,KAAA,GAAQ,GAAO,IAAA,EAAA;AAAI,QAAY,SAAA,GAAA,OAAA,CAAA;AAAA;AACrD,QAAY,SAAA,GAAA,MAAA,CAAA;AAAA,KACnB;AAEA,IAAI,IAAA,GAAA,CAAA;AACJ,IAAI,IAAA,IAAA,CAAA;AAEJ,IAAA,QAAQ,SAAW;AAAA,MACjB,KAAK,KAAA;AACH,QAAM,GAAA,GAAA,IAAA,CAAK,GAAM,GAAA,IAAA,CAAK,MAAS,GAAA,GAAA,CAAA;AAC/B,QAAA,IAAA,GAAO,KAAK,IAAO,GAAA,IAAA,CAAK,KAAQ,GAAA,CAAA,GAAI,KAAK,KAAQ,GAAA,CAAA,CAAA;AACjD,QAAA,MAAA;AAAA,MACF,KAAK,MAAA;AACH,QAAA,GAAA,GAAM,KAAK,GAAM,GAAA,IAAA,CAAK,MAAS,GAAA,CAAA,GAAI,KAAK,MAAS,GAAA,CAAA,CAAA;AACjD,QAAO,IAAA,GAAA,IAAA,CAAK,IAAO,GAAA,IAAA,CAAK,KAAQ,GAAA,GAAA,CAAA;AAChC,QAAA,MAAA;AAAA,MACF,KAAK,OAAA;AACH,QAAA,GAAA,GAAM,KAAK,GAAM,GAAA,IAAA,CAAK,MAAS,GAAA,CAAA,GAAI,KAAK,MAAS,GAAA,CAAA,CAAA;AACjD,QAAA,IAAA,GAAO,KAAK,KAAQ,GAAA,GAAA,CAAA;AACpB,QAAA,MAAA;AAAA,MACF;AACE,QAAA,GAAA,GAAM,KAAK,MAAS,GAAA,GAAA,CAAA;AACpB,QAAA,IAAA,GAAO,KAAK,IAAO,GAAA,IAAA,CAAK,KAAQ,GAAA,CAAA,GAAI,KAAK,KAAQ,GAAA,CAAA,CAAA;AACjD,QAAA,MAAA;AAAA,KACJ;AAGA,IAAO,IAAA,GAAA,IAAA,CAAK,GAAI,CAAA,CAAA,EAAG,IAAK,CAAA,GAAA,CAAI,MAAM,EAAK,GAAA,IAAA,CAAK,KAAQ,GAAA,CAAC,CAAC,CAAA,CAAA;AACtD,IAAM,GAAA,GAAA,IAAA,CAAK,GAAI,CAAA,CAAA,EAAG,IAAK,CAAA,GAAA,CAAI,KAAK,EAAK,GAAA,IAAA,CAAK,MAAS,GAAA,CAAC,CAAC,CAAA,CAAA;AAErD,IAAK,IAAA,CAAA,UAAA,CAAW,KAAM,CAAA,GAAA,GAAM,CAAG,EAAA,GAAA,CAAA,EAAA,CAAA,CAAA;AAC/B,IAAK,IAAA,CAAA,UAAA,CAAW,KAAM,CAAA,IAAA,GAAO,CAAG,EAAA,IAAA,CAAA,EAAA,CAAA,CAAA;AAChC,IAAK,IAAA,CAAA,UAAA,CAAW,QAAQ,SAAY,GAAA,SAAA,CAAA;AAEpC,IAAA,IAAA,CAAK,aAAc,CAAA,SAAA,EAAW,IAAM,EAAA,GAAA,EAAK,IAAI,CAAA,CAAA;AAAA,GAC/C;AAAA;AAAA,EAGQ,aAAe,CAAA,SAAA,EAAmB,IAAe,EAAA,GAAA,EAAa,IAAc,EAAA;AAClF,IAAM,MAAA,IAAA,GAAO,IAAK,CAAA,UAAA,CAAW,qBAAsB,EAAA,CAAA;AACnD,IAAM,MAAA,KAAA,GAAQ,KAAK,WAAY,CAAA,KAAA,CAAA;AAE/B,IAAI,IAAA,SAAA,KAAc,KAAS,IAAA,SAAA,KAAc,QAAU,EAAA;AACjD,MAAA,MAAM,YAAe,GAAA,IAAA,CAAK,IAAO,GAAA,IAAA,CAAK,KAAQ,GAAA,CAAA,CAAA;AAC9C,MAAM,MAAA,MAAA,GAAS,IAAK,CAAA,GAAA,CAAI,EAAI,EAAA,IAAA,CAAK,GAAI,CAAA,YAAA,GAAe,IAAM,EAAA,IAAA,CAAK,KAAQ,GAAA,EAAE,CAAC,CAAA,CAAA;AAC1E,MAAA,KAAA,CAAM,OAAO,CAAG,EAAA,MAAA,CAAA,EAAA,CAAA,CAAA;AAChB,MAAA,KAAA,CAAM,GAAM,GAAA,EAAA,CAAA;AAAA,KACP,MAAA;AACL,MAAA,MAAM,YAAe,GAAA,IAAA,CAAK,GAAM,GAAA,IAAA,CAAK,MAAS,GAAA,CAAA,CAAA;AAC9C,MAAM,MAAA,MAAA,GAAS,IAAK,CAAA,GAAA,CAAI,EAAI,EAAA,IAAA,CAAK,GAAI,CAAA,YAAA,GAAe,GAAK,EAAA,IAAA,CAAK,MAAS,GAAA,EAAE,CAAC,CAAA,CAAA;AAC1E,MAAA,KAAA,CAAM,MAAM,CAAG,EAAA,MAAA,CAAA,EAAA,CAAA,CAAA;AACf,MAAA,KAAA,CAAM,IAAO,GAAA,EAAA,CAAA;AAAA,KACf;AAAA,GACF;AAAA,EAEQ,MAAU,GAAA;AAChB,IAAM,MAAA,IAAA,GAAO,IAAK,CAAA,UAAA,CAAW,qBAAsB,EAAA,CAAA;AACnD,IAAA,IAAA,CAAK,UAAW,CAAA,KAAA,CAAM,GAAM,GAAA,CAAA,EAAG,IAAK,CAAA,GAAA,CAAI,CAAG,EAAA,MAAA,CAAO,WAAc,GAAA,CAAA,GAAI,IAAK,CAAA,MAAA,GAAS,CAAC,CAAA,CAAA,EAAA,CAAA,CAAA;AACnF,IAAA,IAAA,CAAK,UAAW,CAAA,KAAA,CAAM,IAAO,GAAA,CAAA,EAAG,IAAK,CAAA,GAAA,CAAI,CAAG,EAAA,MAAA,CAAO,UAAa,GAAA,CAAA,GAAI,IAAK,CAAA,KAAA,GAAQ,CAAC,CAAA,CAAA,EAAA,CAAA,CAAA;AAClF,IAAK,IAAA,CAAA,UAAA,CAAW,QAAQ,SAAY,GAAA,QAAA,CAAA;AAAA,GACtC;AAAA,EAEQ,SAAa,GAAA;AACnB,IAAA,qBAAA,CAAsB,MAAM;AAC1B,MAAA,IAAI,IAAK,CAAA,MAAA;AAAQ,QAAA,IAAA,CAAK,WAAW,KAAM,EAAA,CAAA;AAAA,KACxC,CAAA,CAAA;AAAA,GACH;AAAA,EAEQ,QAAY,GAAA;AAClB,IAAA,IAAA,CAAK,MAAS,GAAA,KAAA,CAAA;AACd,IAAA,IAAA,CAAK,cAAe,EAAA,CAAA;AACpB,IAAA,IAAA,CAAK,cAAc,MAAS,GAAA,IAAA,CAAA;AAC5B,IAAA,IAAA,CAAK,WAAW,MAAS,GAAA,IAAA,CAAA;AACzB,IAAA,QAAA,CAAS,mBAAoB,CAAA,SAAA,EAAW,IAAK,CAAA,aAAA,EAAe,IAAI,CAAA,CAAA;AAChE,IAAO,MAAA,CAAA,mBAAA,CAAoB,QAAU,EAAA,IAAA,CAAK,UAAU,CAAA,CAAA;AACpD,IAAA,MAAA,CAAO,mBAAoB,CAAA,QAAA,EAAU,IAAK,CAAA,UAAA,EAAY,IAAI,CAAA,CAAA;AAC1D,IAAA,IAAA,CAAK,eAAe,KAAM,EAAA,CAAA;AAC1B,IAAA,IAAA,CAAK,aAAgB,GAAA,IAAA,CAAA;AAAA,GACvB;AAAA,EAEQ,UAAA,GAAa,CAAC,KAAiB,KAAA;AACrC,IAAM,MAAA,MAAA,GAAU,KAAsB,CAAA,MAAA,IAAU,EAAC,CAAA;AACjD,IAAM,MAAA,EAAA,GAAK,OAAO,MAAO,CAAA,EAAA,IAAM,EAAE,CAAE,CAAA,OAAA,CAAQ,KAAK,EAAE,CAAA,CAAA;AAClD,IAAI,IAAA,EAAA,KAAO,KAAK,OAAQ,CAAA,EAAA;AAAI,MAAA,IAAA,CAAK,KAAM,EAAA,CAAA;AAAA,GACzC,CAAA;AAAA,EAEQ,aAAa,MAAM;AACzB,IAAA,IAAI,CAAC,IAAK,CAAA,MAAA;AAAQ,MAAA,OAAA;AAClB,IAAA,MAAM,IAAO,GAAA,IAAA,CAAK,KAAM,CAAA,IAAA,CAAK,KAAK,CAAA,CAAA;AAClC,IAAA,MAAM,SAAS,IAAK,CAAA,QAAA,GAAW,SAAS,aAA2B,CAAA,IAAA,CAAK,QAAQ,CAAI,GAAA,IAAA,CAAA;AACpF,IAAI,IAAA,MAAA;AAAQ,MAAK,IAAA,CAAA,QAAA,CAAS,MAAQ,EAAA,IAAA,CAAK,QAAQ,CAAA,CAAA;AAAA;AAC1C,MAAA,IAAA,CAAK,MAAO,EAAA,CAAA;AAAA,GACnB,CAAA;AAAA,EAEQ,aAAA,GAAgB,CAAC,KAAyB,KAAA;AAChD,IAAA,IAAI,CAAC,IAAK,CAAA,MAAA;AAAQ,MAAA,OAAA;AAElB,IAAA,QAAQ,MAAM,GAAK;AAAA,MACjB,KAAK,QAAA;AACH,QAAA,KAAA,CAAM,cAAe,EAAA,CAAA;AACrB,QAAA,IAAA,CAAK,MAAO,EAAA,CAAA;AACZ,QAAA,MAAA;AAAA,MACF,KAAK,YAAA;AACH,QAAA,KAAA,CAAM,cAAe,EAAA,CAAA;AACrB,QAAA,IAAA,CAAK,IAAK,EAAA,CAAA;AACV,QAAA,MAAA;AAAA,MACF,KAAK,WAAA;AACH,QAAA,KAAA,CAAM,cAAe,EAAA,CAAA;AACrB,QAAA,IAAA,CAAK,IAAK,EAAA,CAAA;AACV,QAAA,MAAA;AAAA,MACF,KAAK,KAAA;AACH,QAAA,IAAA,CAAK,QAAQ,KAAK,CAAA,CAAA;AAClB,QAAA,MAAA;AAAA,KACJ;AAAA,GACF,CAAA;AAAA;AAAA,EAGQ,QAAS,KAAsB,EAAA;AACrC,IAAM,MAAA,SAAA,GAAY,MAAM,IAAK,CAAA,IAAA,CAAK,WAAW,gBAA8B,CAAA,SAAS,CAAC,CAAA,CAClF,MAAO,CAAA,CAAC,OAAO,CAAC,EAAA,CAAG,UAAU,EAAG,CAAA,YAAA,KAAiB,QAAQ,gBAAiB,CAAA,EAAE,CAAE,CAAA,UAAA,KAAe,QAAQ,CAAA,CAAA;AACxG,IAAA,IAAI,UAAU,MAAW,KAAA,CAAA;AAAG,MAAA,OAAA;AAE5B,IAAM,MAAA,KAAA,GAAQ,UAAU,CAAC,CAAA,CAAA;AACzB,IAAA,MAAM,IAAO,GAAA,SAAA,CAAU,SAAU,CAAA,MAAA,GAAS,CAAC,CAAA,CAAA;AAC3C,IAAA,MAAM,SAAS,QAAS,CAAA,aAAA,CAAA;AAExB,IAAA,IAAI,MAAM,QAAU,EAAA;AAClB,MAAI,IAAA,MAAA,KAAW,KAAS,IAAA,MAAA,KAAW,IAAK,CAAA,UAAA,IAAc,CAAC,IAAK,CAAA,UAAA,CAAW,QAAS,CAAA,MAAM,CAAG,EAAA;AACvF,QAAA,KAAA,CAAM,cAAe,EAAA,CAAA;AACrB,QAAA,IAAA,CAAK,KAAM,EAAA,CAAA;AAAA,OACb;AAAA,KACF,MAAA,IAAW,WAAW,IAAQ,IAAA,CAAC,KAAK,UAAW,CAAA,QAAA,CAAS,MAAM,CAAG,EAAA;AAC/D,MAAA,KAAA,CAAM,cAAe,EAAA,CAAA;AACrB,MAAA,KAAA,CAAM,KAAM,EAAA,CAAA;AAAA,KACd;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"onboarding_component_controller.js","sources":["../../../../../../../app/components/midwest/onboarding_component/onboarding_component_controller.ts"],"sourcesContent":["import { Controller } from '@hotwired/stimulus'\n\nconst FOCUSABLE = [\n 'a[href]',\n 'button:not([disabled])',\n 'textarea:not([disabled])',\n 'input:not([disabled])',\n 'select:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])'\n].join(', ')\n\nconst GAP = 12 // px between the target and the card\n\ninterface StepConfig {\n el: HTMLElement\n name: string\n selector: string\n position: string\n title: string\n nextText: string\n backText: string\n completeText: string\n canClickTarget: boolean\n}\n\n// Native, dependency-free guided-tour engine. Reads the nested step config\n// carriers, then walks the user through them with a dimmed overlay, a card\n// positioned against each step's target element, and Back/Next/Done buttons.\nexport default class Onboarding extends Controller<HTMLElement> {\n static targets = ['step', 'overlay', 'card', 'title', 'body', 'back', 'next', 'done', 'arrow', 'motion']\n\n static values = {\n autoOpen: { type: Boolean, default: false }\n }\n\n declare readonly stepTargets: HTMLElement[]\n declare readonly overlayTarget: HTMLElement\n declare readonly cardTarget: HTMLElement\n declare readonly titleTarget: HTMLElement\n declare readonly bodyTarget: HTMLElement\n declare readonly backTarget: HTMLButtonElement\n declare readonly nextTarget: HTMLButtonElement\n declare readonly doneTarget: HTMLButtonElement\n declare readonly arrowTarget: HTMLElement\n declare readonly motionTarget: HTMLElement\n declare readonly hasMotionTarget: boolean\n declare autoOpenValue: boolean\n\n private steps: StepConfig[] = []\n private index = 0\n private active = false\n private justOpened = false\n private previousFocus: HTMLElement | null = null\n private highlighted: HTMLElement | null = null\n\n connect () {\n this.steps = this.stepTargets.map((el) => ({\n el,\n name: el.dataset.name ?? '',\n selector: el.dataset.selector ?? '',\n position: el.dataset.position ?? 'auto',\n title: el.dataset.title ?? '',\n nextText: el.dataset.nextText ?? 'Next',\n backText: el.dataset.backText ?? 'Back',\n completeText: el.dataset.completeText ?? 'Done',\n canClickTarget: el.dataset.canClickTarget === 'true'\n }))\n\n window.addEventListener('midwest-onboarding:open', this.handleOpen)\n\n if (this.autoOpenValue) this.start()\n }\n\n disconnect () {\n window.removeEventListener('midwest-onboarding:open', this.handleOpen)\n this.teardown()\n }\n\n start () {\n if (this.active || this.steps.length === 0) return\n this.active = true\n this.previousFocus = document.activeElement as HTMLElement | null\n this.overlayTarget.hidden = false\n this.cardTarget.hidden = false\n this.justOpened = true\n document.addEventListener('keydown', this.handleKeydown, true)\n window.addEventListener('resize', this.reposition)\n window.addEventListener('scroll', this.reposition, true)\n this.dispatch('start', { bubbles: true })\n this.render(0)\n }\n\n next () {\n if (this.index < this.steps.length - 1) this.render(this.index + 1)\n else this.complete()\n }\n\n back () {\n if (this.index > 0) this.render(this.index - 1)\n }\n\n // Jump to a step by its `name`.\n show (name: string) {\n const target = this.steps.findIndex((step) => step.name === name)\n if (target >= 0) {\n if (!this.active) this.start()\n this.render(target)\n }\n }\n\n complete () {\n if (!this.active) return\n this.teardown()\n this.dispatch('complete', { bubbles: true })\n }\n\n cancel () {\n if (!this.active) return\n this.teardown()\n this.dispatch('cancel', { bubbles: true })\n }\n\n private render (index: number) {\n this.index = index\n const step = this.steps[index]\n const replay = !this.justOpened\n this.justOpened = false\n\n this.clearHighlight()\n\n this.titleTarget.textContent = step.title\n this.renderBody(step)\n this.renderButtons(step, index)\n\n const target = step.selector\n ? document.querySelector<HTMLElement>(step.selector)\n : null\n\n if (target) {\n this.highlight(target, step.canClickTarget)\n this.position(target, step.position)\n } else {\n this.center()\n }\n\n if (replay && this.hasMotionTarget) {\n this.replayMotion(this.cardTarget.dataset.placement ?? 'center')\n }\n\n this.dispatch('show', { detail: { index, name: step.name }, bubbles: true })\n this.focusCard()\n }\n\n private renderBody (step: StepConfig) {\n this.bodyTarget.replaceChildren()\n const template = step.el.querySelector('template')\n if (template) this.bodyTarget.appendChild(template.content.cloneNode(true))\n }\n\n private renderButtons (step: StepConfig, index: number) {\n const isFirst = index === 0\n const isLast = index === this.steps.length - 1\n\n // Back keeps its layout box (visibility) so the forward button never shifts;\n // Next and Done are mutually exclusive, so exactly one fills the right slot.\n this.backTarget.textContent = step.backText\n this.backTarget.style.visibility = isFirst ? 'hidden' : ''\n\n // Inline display beats the button's own `display: inline-flex` rule.\n this.nextTarget.textContent = step.nextText\n this.nextTarget.style.display = isLast ? 'none' : ''\n\n this.doneTarget.textContent = step.completeText\n this.doneTarget.style.display = isLast ? '' : 'none'\n }\n\n private highlight (target: HTMLElement, canClickTarget: boolean) {\n target.classList.add('midwest-onboarding-highlight')\n target.classList.toggle('is-locked', !canClickTarget)\n this.highlighted = target\n target.scrollIntoView({ behavior: 'smooth', block: 'center' })\n }\n\n private clearHighlight () {\n this.highlighted?.classList.remove('midwest-onboarding-highlight', 'is-locked')\n this.highlighted = null\n }\n\n // Places the card against the target, choosing a side when `position` is auto.\n private position (target: HTMLElement, position: string) {\n const rect = target.getBoundingClientRect()\n const card = this.cardTarget.getBoundingClientRect()\n const vw = window.innerWidth\n const vh = window.innerHeight\n\n let placement = position\n if (placement === 'auto') {\n if (rect.bottom + card.height + GAP <= vh) placement = 'bottom'\n else if (rect.top - card.height - GAP >= 0) placement = 'top'\n else if (rect.right + card.width + GAP <= vw) placement = 'right'\n else placement = 'left'\n }\n\n let top: number\n let left: number\n\n switch (placement) {\n case 'top':\n top = rect.top - card.height - GAP\n left = rect.left + rect.width / 2 - card.width / 2\n break\n case 'left':\n top = rect.top + rect.height / 2 - card.height / 2\n left = rect.left - card.width - GAP\n break\n case 'right':\n top = rect.top + rect.height / 2 - card.height / 2\n left = rect.right + GAP\n break\n default: // bottom\n top = rect.bottom + GAP\n left = rect.left + rect.width / 2 - card.width / 2\n break\n }\n\n // Keep the card fully on screen.\n left = Math.max(8, Math.min(left, vw - card.width - 8))\n top = Math.max(8, Math.min(top, vh - card.height - 8))\n\n this.cardTarget.style.top = `${top}px`\n this.cardTarget.style.left = `${left}px`\n this.cardTarget.dataset.placement = placement\n\n this.positionArrow(placement, rect, top, left)\n }\n\n // Nudges the arrow so it points at the target's center, not the card's.\n private positionArrow (placement: string, rect: DOMRect, top: number, left: number) {\n const card = this.cardTarget.getBoundingClientRect()\n const arrow = this.arrowTarget.style\n\n if (placement === 'top' || placement === 'bottom') {\n const targetCenter = rect.left + rect.width / 2\n const offset = Math.max(12, Math.min(targetCenter - left, card.width - 12))\n arrow.left = `${offset}px`\n arrow.top = ''\n } else {\n const targetCenter = rect.top + rect.height / 2\n const offset = Math.max(12, Math.min(targetCenter - top, card.height - 12))\n arrow.top = `${offset}px`\n arrow.left = ''\n }\n }\n\n private center () {\n const card = this.cardTarget.getBoundingClientRect()\n this.cardTarget.style.top = `${Math.max(8, window.innerHeight / 2 - card.height / 2)}px`\n this.cardTarget.style.left = `${Math.max(8, window.innerWidth / 2 - card.width / 2)}px`\n this.cardTarget.dataset.placement = 'center'\n }\n\n private focusCard () {\n requestAnimationFrame(() => {\n if (this.active) this.cardTarget.focus()\n })\n }\n\n // Re-triggers the midwest_motion @starting-style entry on step transitions.\n // The initial show is handled by @starting-style firing when the card's\n // `hidden` is removed; subsequent steps need an explicit re-trigger since the\n // card stays in the DOM. Toggling `hidden` on the motion element triggers\n // @starting-style again; the rAF ensures both DOM writes land in the same\n // paint so there is no blank-card flash.\n private replayMotion (placement: string) {\n const el = this.motionTarget\n const dir: Record<string, string> = { bottom: 'up', top: 'down', right: 'left', left: 'right' }\n\n el.classList.remove('from-up', 'from-down', 'from-left', 'from-right')\n const from = dir[placement]\n if (from) el.classList.add(`from-${from}`)\n\n el.hidden = true\n requestAnimationFrame(() => { if (this.active) el.hidden = false })\n }\n\n private teardown () {\n this.active = false\n this.clearHighlight()\n // Close any open confirmation popovers before hiding the card.\n this.element.querySelectorAll<HTMLElement>('[popover]').forEach((el) => {\n try { el.hidePopover() } catch { /* already hidden */ }\n })\n this.overlayTarget.hidden = true\n this.cardTarget.hidden = true\n document.removeEventListener('keydown', this.handleKeydown, true)\n window.removeEventListener('resize', this.reposition)\n window.removeEventListener('scroll', this.reposition, true)\n this.previousFocus?.focus()\n this.previousFocus = null\n }\n\n private handleOpen = (event: Event) => {\n const detail = (event as CustomEvent).detail ?? {}\n const id = String(detail.id ?? '').replace('#', '')\n if (id === this.element.id) this.start()\n }\n\n private reposition = () => {\n if (!this.active) return\n const step = this.steps[this.index]\n const target = step.selector ? document.querySelector<HTMLElement>(step.selector) : null\n if (target) this.position(target, step.position)\n else this.center()\n }\n\n private handleKeydown = (event: KeyboardEvent) => {\n if (!this.active) return\n\n switch (event.key) {\n case 'Escape':\n event.preventDefault()\n this.cancel()\n break\n case 'ArrowRight':\n event.preventDefault()\n this.next()\n break\n case 'ArrowLeft':\n event.preventDefault()\n this.back()\n break\n case 'Tab':\n this.trapTab(event)\n break\n }\n }\n\n // Keep Tab focus within the card while the tour is active.\n private trapTab (event: KeyboardEvent) {\n const focusable = Array.from(this.cardTarget.querySelectorAll<HTMLElement>(FOCUSABLE))\n .filter((el) => !el.hidden && el.offsetParent !== null && getComputedStyle(el).visibility !== 'hidden')\n if (focusable.length === 0) return\n\n const first = focusable[0]\n const last = focusable[focusable.length - 1]\n const active = document.activeElement\n\n if (event.shiftKey) {\n if (active === first || active === this.cardTarget || !this.cardTarget.contains(active)) {\n event.preventDefault()\n last.focus()\n }\n } else if (active === last || !this.cardTarget.contains(active)) {\n event.preventDefault()\n first.focus()\n }\n }\n}\n"],"names":[],"mappings":";;AAEA,MAAM,SAAY,GAAA;AAAA,EAChB,SAAA;AAAA,EACA,wBAAA;AAAA,EACA,0BAAA;AAAA,EACA,uBAAA;AAAA,EACA,wBAAA;AAAA,EACA,iCAAA;AACF,CAAA,CAAE,KAAK,IAAI,CAAA,CAAA;AAEX,MAAM,GAAM,GAAA,EAAA,CAAA;AAiBZ,MAAqB,mBAAmB,UAAwB,CAAA;AAAA,EAC9D,OAAO,OAAA,GAAU,CAAC,MAAA,EAAQ,SAAW,EAAA,MAAA,EAAQ,OAAS,EAAA,MAAA,EAAQ,MAAQ,EAAA,MAAA,EAAQ,MAAQ,EAAA,OAAA,EAAS,QAAQ,CAAA,CAAA;AAAA,EAEvG,OAAO,MAAS,GAAA;AAAA,IACd,QAAU,EAAA,EAAE,IAAM,EAAA,OAAA,EAAS,SAAS,KAAM,EAAA;AAAA,GAC5C,CAAA;AAAA,EAeQ,QAAsB,EAAC,CAAA;AAAA,EACvB,KAAQ,GAAA,CAAA,CAAA;AAAA,EACR,MAAS,GAAA,KAAA,CAAA;AAAA,EACT,UAAa,GAAA,KAAA,CAAA;AAAA,EACb,aAAoC,GAAA,IAAA,CAAA;AAAA,EACpC,WAAkC,GAAA,IAAA,CAAA;AAAA,EAE1C,OAAW,GAAA;AACT,IAAA,IAAA,CAAK,KAAQ,GAAA,IAAA,CAAK,WAAY,CAAA,GAAA,CAAI,CAAC,EAAQ,MAAA;AAAA,MACzC,EAAA;AAAA,MACA,IAAA,EAAM,EAAG,CAAA,OAAA,CAAQ,IAAQ,IAAA,EAAA;AAAA,MACzB,QAAA,EAAU,EAAG,CAAA,OAAA,CAAQ,QAAY,IAAA,EAAA;AAAA,MACjC,QAAA,EAAU,EAAG,CAAA,OAAA,CAAQ,QAAY,IAAA,MAAA;AAAA,MACjC,KAAA,EAAO,EAAG,CAAA,OAAA,CAAQ,KAAS,IAAA,EAAA;AAAA,MAC3B,QAAA,EAAU,EAAG,CAAA,OAAA,CAAQ,QAAY,IAAA,MAAA;AAAA,MACjC,QAAA,EAAU,EAAG,CAAA,OAAA,CAAQ,QAAY,IAAA,MAAA;AAAA,MACjC,YAAA,EAAc,EAAG,CAAA,OAAA,CAAQ,YAAgB,IAAA,MAAA;AAAA,MACzC,cAAA,EAAgB,EAAG,CAAA,OAAA,CAAQ,cAAmB,KAAA,MAAA;AAAA,KAC9C,CAAA,CAAA,CAAA;AAEF,IAAO,MAAA,CAAA,gBAAA,CAAiB,yBAA2B,EAAA,IAAA,CAAK,UAAU,CAAA,CAAA;AAElE,IAAA,IAAI,IAAK,CAAA,aAAA;AAAe,MAAA,IAAA,CAAK,KAAM,EAAA,CAAA;AAAA,GACrC;AAAA,EAEA,UAAc,GAAA;AACZ,IAAO,MAAA,CAAA,mBAAA,CAAoB,yBAA2B,EAAA,IAAA,CAAK,UAAU,CAAA,CAAA;AACrE,IAAA,IAAA,CAAK,QAAS,EAAA,CAAA;AAAA,GAChB;AAAA,EAEA,KAAS,GAAA;AACP,IAAA,IAAI,IAAK,CAAA,MAAA,IAAU,IAAK,CAAA,KAAA,CAAM,MAAW,KAAA,CAAA;AAAG,MAAA,OAAA;AAC5C,IAAA,IAAA,CAAK,MAAS,GAAA,IAAA,CAAA;AACd,IAAA,IAAA,CAAK,gBAAgB,QAAS,CAAA,aAAA,CAAA;AAC9B,IAAA,IAAA,CAAK,cAAc,MAAS,GAAA,KAAA,CAAA;AAC5B,IAAA,IAAA,CAAK,WAAW,MAAS,GAAA,KAAA,CAAA;AACzB,IAAA,IAAA,CAAK,UAAa,GAAA,IAAA,CAAA;AAClB,IAAA,QAAA,CAAS,gBAAiB,CAAA,SAAA,EAAW,IAAK,CAAA,aAAA,EAAe,IAAI,CAAA,CAAA;AAC7D,IAAO,MAAA,CAAA,gBAAA,CAAiB,QAAU,EAAA,IAAA,CAAK,UAAU,CAAA,CAAA;AACjD,IAAA,MAAA,CAAO,gBAAiB,CAAA,QAAA,EAAU,IAAK,CAAA,UAAA,EAAY,IAAI,CAAA,CAAA;AACvD,IAAA,IAAA,CAAK,QAAS,CAAA,OAAA,EAAS,EAAE,OAAA,EAAS,MAAM,CAAA,CAAA;AACxC,IAAA,IAAA,CAAK,OAAO,CAAC,CAAA,CAAA;AAAA,GACf;AAAA,EAEA,IAAQ,GAAA;AACN,IAAA,IAAI,IAAK,CAAA,KAAA,GAAQ,IAAK,CAAA,KAAA,CAAM,MAAS,GAAA,CAAA;AAAG,MAAK,IAAA,CAAA,MAAA,CAAO,IAAK,CAAA,KAAA,GAAQ,CAAC,CAAA,CAAA;AAAA;AAC7D,MAAA,IAAA,CAAK,QAAS,EAAA,CAAA;AAAA,GACrB;AAAA,EAEA,IAAQ,GAAA;AACN,IAAA,IAAI,KAAK,KAAQ,GAAA,CAAA;AAAG,MAAK,IAAA,CAAA,MAAA,CAAO,IAAK,CAAA,KAAA,GAAQ,CAAC,CAAA,CAAA;AAAA,GAChD;AAAA;AAAA,EAGA,KAAM,IAAc,EAAA;AAClB,IAAM,MAAA,MAAA,GAAS,KAAK,KAAM,CAAA,SAAA,CAAU,CAAC,IAAS,KAAA,IAAA,CAAK,SAAS,IAAI,CAAA,CAAA;AAChE,IAAA,IAAI,UAAU,CAAG,EAAA;AACf,MAAA,IAAI,CAAC,IAAK,CAAA,MAAA;AAAQ,QAAA,IAAA,CAAK,KAAM,EAAA,CAAA;AAC7B,MAAA,IAAA,CAAK,OAAO,MAAM,CAAA,CAAA;AAAA,KACpB;AAAA,GACF;AAAA,EAEA,QAAY,GAAA;AACV,IAAA,IAAI,CAAC,IAAK,CAAA,MAAA;AAAQ,MAAA,OAAA;AAClB,IAAA,IAAA,CAAK,QAAS,EAAA,CAAA;AACd,IAAA,IAAA,CAAK,QAAS,CAAA,UAAA,EAAY,EAAE,OAAA,EAAS,MAAM,CAAA,CAAA;AAAA,GAC7C;AAAA,EAEA,MAAU,GAAA;AACR,IAAA,IAAI,CAAC,IAAK,CAAA,MAAA;AAAQ,MAAA,OAAA;AAClB,IAAA,IAAA,CAAK,QAAS,EAAA,CAAA;AACd,IAAA,IAAA,CAAK,QAAS,CAAA,QAAA,EAAU,EAAE,OAAA,EAAS,MAAM,CAAA,CAAA;AAAA,GAC3C;AAAA,EAEQ,OAAQ,KAAe,EAAA;AAC7B,IAAA,IAAA,CAAK,KAAQ,GAAA,KAAA,CAAA;AACb,IAAM,MAAA,IAAA,GAAO,IAAK,CAAA,KAAA,CAAM,KAAK,CAAA,CAAA;AAC7B,IAAM,MAAA,MAAA,GAAS,CAAC,IAAK,CAAA,UAAA,CAAA;AACrB,IAAA,IAAA,CAAK,UAAa,GAAA,KAAA,CAAA;AAElB,IAAA,IAAA,CAAK,cAAe,EAAA,CAAA;AAEpB,IAAK,IAAA,CAAA,WAAA,CAAY,cAAc,IAAK,CAAA,KAAA,CAAA;AACpC,IAAA,IAAA,CAAK,WAAW,IAAI,CAAA,CAAA;AACpB,IAAK,IAAA,CAAA,aAAA,CAAc,MAAM,KAAK,CAAA,CAAA;AAE9B,IAAA,MAAM,SAAS,IAAK,CAAA,QAAA,GAChB,SAAS,aAA2B,CAAA,IAAA,CAAK,QAAQ,CACjD,GAAA,IAAA,CAAA;AAEJ,IAAA,IAAI,MAAQ,EAAA;AACV,MAAK,IAAA,CAAA,SAAA,CAAU,MAAQ,EAAA,IAAA,CAAK,cAAc,CAAA,CAAA;AAC1C,MAAK,IAAA,CAAA,QAAA,CAAS,MAAQ,EAAA,IAAA,CAAK,QAAQ,CAAA,CAAA;AAAA,KAC9B,MAAA;AACL,MAAA,IAAA,CAAK,MAAO,EAAA,CAAA;AAAA,KACd;AAEA,IAAI,IAAA,MAAA,IAAU,KAAK,eAAiB,EAAA;AAClC,MAAA,IAAA,CAAK,YAAa,CAAA,IAAA,CAAK,UAAW,CAAA,OAAA,CAAQ,aAAa,QAAQ,CAAA,CAAA;AAAA,KACjE;AAEA,IAAA,IAAA,CAAK,QAAS,CAAA,MAAA,EAAQ,EAAE,MAAA,EAAQ,EAAE,KAAA,EAAO,IAAM,EAAA,IAAA,CAAK,IAAK,EAAA,EAAG,OAAS,EAAA,IAAA,EAAM,CAAA,CAAA;AAC3E,IAAA,IAAA,CAAK,SAAU,EAAA,CAAA;AAAA,GACjB;AAAA,EAEQ,WAAY,IAAkB,EAAA;AACpC,IAAA,IAAA,CAAK,WAAW,eAAgB,EAAA,CAAA;AAChC,IAAA,MAAM,QAAW,GAAA,IAAA,CAAK,EAAG,CAAA,aAAA,CAAc,UAAU,CAAA,CAAA;AACjD,IAAI,IAAA,QAAA;AAAU,MAAA,IAAA,CAAK,WAAW,WAAY,CAAA,QAAA,CAAS,OAAQ,CAAA,SAAA,CAAU,IAAI,CAAC,CAAA,CAAA;AAAA,GAC5E;AAAA,EAEQ,aAAA,CAAe,MAAkB,KAAe,EAAA;AACtD,IAAA,MAAM,UAAU,KAAU,KAAA,CAAA,CAAA;AAC1B,IAAA,MAAM,MAAS,GAAA,KAAA,KAAU,IAAK,CAAA,KAAA,CAAM,MAAS,GAAA,CAAA,CAAA;AAI7C,IAAK,IAAA,CAAA,UAAA,CAAW,cAAc,IAAK,CAAA,QAAA,CAAA;AACnC,IAAA,IAAA,CAAK,UAAW,CAAA,KAAA,CAAM,UAAa,GAAA,OAAA,GAAU,QAAW,GAAA,EAAA,CAAA;AAGxD,IAAK,IAAA,CAAA,UAAA,CAAW,cAAc,IAAK,CAAA,QAAA,CAAA;AACnC,IAAA,IAAA,CAAK,UAAW,CAAA,KAAA,CAAM,OAAU,GAAA,MAAA,GAAS,MAAS,GAAA,EAAA,CAAA;AAElD,IAAK,IAAA,CAAA,UAAA,CAAW,cAAc,IAAK,CAAA,YAAA,CAAA;AACnC,IAAA,IAAA,CAAK,UAAW,CAAA,KAAA,CAAM,OAAU,GAAA,MAAA,GAAS,EAAK,GAAA,MAAA,CAAA;AAAA,GAChD;AAAA,EAEQ,SAAA,CAAW,QAAqB,cAAyB,EAAA;AAC/D,IAAO,MAAA,CAAA,SAAA,CAAU,IAAI,8BAA8B,CAAA,CAAA;AACnD,IAAA,MAAA,CAAO,SAAU,CAAA,MAAA,CAAO,WAAa,EAAA,CAAC,cAAc,CAAA,CAAA;AACpD,IAAA,IAAA,CAAK,WAAc,GAAA,MAAA,CAAA;AACnB,IAAA,MAAA,CAAO,eAAe,EAAE,QAAA,EAAU,QAAU,EAAA,KAAA,EAAO,UAAU,CAAA,CAAA;AAAA,GAC/D;AAAA,EAEQ,cAAkB,GAAA;AACxB,IAAA,IAAA,CAAK,WAAa,EAAA,SAAA,CAAU,MAAO,CAAA,8BAAA,EAAgC,WAAW,CAAA,CAAA;AAC9E,IAAA,IAAA,CAAK,WAAc,GAAA,IAAA,CAAA;AAAA,GACrB;AAAA;AAAA,EAGQ,QAAA,CAAU,QAAqB,QAAkB,EAAA;AACvD,IAAM,MAAA,IAAA,GAAO,OAAO,qBAAsB,EAAA,CAAA;AAC1C,IAAM,MAAA,IAAA,GAAO,IAAK,CAAA,UAAA,CAAW,qBAAsB,EAAA,CAAA;AACnD,IAAA,MAAM,KAAK,MAAO,CAAA,UAAA,CAAA;AAClB,IAAA,MAAM,KAAK,MAAO,CAAA,WAAA,CAAA;AAElB,IAAA,IAAI,SAAY,GAAA,QAAA,CAAA;AAChB,IAAA,IAAI,cAAc,MAAQ,EAAA;AACxB,MAAA,IAAI,IAAK,CAAA,MAAA,GAAS,IAAK,CAAA,MAAA,GAAS,GAAO,IAAA,EAAA;AAAI,QAAY,SAAA,GAAA,QAAA,CAAA;AAAA,WAAA,IAC9C,IAAK,CAAA,GAAA,GAAM,IAAK,CAAA,MAAA,GAAS,GAAO,IAAA,CAAA;AAAG,QAAY,SAAA,GAAA,KAAA,CAAA;AAAA,WAAA,IAC/C,IAAK,CAAA,KAAA,GAAQ,IAAK,CAAA,KAAA,GAAQ,GAAO,IAAA,EAAA;AAAI,QAAY,SAAA,GAAA,OAAA,CAAA;AAAA;AACrD,QAAY,SAAA,GAAA,MAAA,CAAA;AAAA,KACnB;AAEA,IAAI,IAAA,GAAA,CAAA;AACJ,IAAI,IAAA,IAAA,CAAA;AAEJ,IAAA,QAAQ,SAAW;AAAA,MACjB,KAAK,KAAA;AACH,QAAM,GAAA,GAAA,IAAA,CAAK,GAAM,GAAA,IAAA,CAAK,MAAS,GAAA,GAAA,CAAA;AAC/B,QAAA,IAAA,GAAO,KAAK,IAAO,GAAA,IAAA,CAAK,KAAQ,GAAA,CAAA,GAAI,KAAK,KAAQ,GAAA,CAAA,CAAA;AACjD,QAAA,MAAA;AAAA,MACF,KAAK,MAAA;AACH,QAAA,GAAA,GAAM,KAAK,GAAM,GAAA,IAAA,CAAK,MAAS,GAAA,CAAA,GAAI,KAAK,MAAS,GAAA,CAAA,CAAA;AACjD,QAAO,IAAA,GAAA,IAAA,CAAK,IAAO,GAAA,IAAA,CAAK,KAAQ,GAAA,GAAA,CAAA;AAChC,QAAA,MAAA;AAAA,MACF,KAAK,OAAA;AACH,QAAA,GAAA,GAAM,KAAK,GAAM,GAAA,IAAA,CAAK,MAAS,GAAA,CAAA,GAAI,KAAK,MAAS,GAAA,CAAA,CAAA;AACjD,QAAA,IAAA,GAAO,KAAK,KAAQ,GAAA,GAAA,CAAA;AACpB,QAAA,MAAA;AAAA,MACF;AACE,QAAA,GAAA,GAAM,KAAK,MAAS,GAAA,GAAA,CAAA;AACpB,QAAA,IAAA,GAAO,KAAK,IAAO,GAAA,IAAA,CAAK,KAAQ,GAAA,CAAA,GAAI,KAAK,KAAQ,GAAA,CAAA,CAAA;AACjD,QAAA,MAAA;AAAA,KACJ;AAGA,IAAO,IAAA,GAAA,IAAA,CAAK,GAAI,CAAA,CAAA,EAAG,IAAK,CAAA,GAAA,CAAI,MAAM,EAAK,GAAA,IAAA,CAAK,KAAQ,GAAA,CAAC,CAAC,CAAA,CAAA;AACtD,IAAM,GAAA,GAAA,IAAA,CAAK,GAAI,CAAA,CAAA,EAAG,IAAK,CAAA,GAAA,CAAI,KAAK,EAAK,GAAA,IAAA,CAAK,MAAS,GAAA,CAAC,CAAC,CAAA,CAAA;AAErD,IAAK,IAAA,CAAA,UAAA,CAAW,KAAM,CAAA,GAAA,GAAM,CAAG,EAAA,GAAA,CAAA,EAAA,CAAA,CAAA;AAC/B,IAAK,IAAA,CAAA,UAAA,CAAW,KAAM,CAAA,IAAA,GAAO,CAAG,EAAA,IAAA,CAAA,EAAA,CAAA,CAAA;AAChC,IAAK,IAAA,CAAA,UAAA,CAAW,QAAQ,SAAY,GAAA,SAAA,CAAA;AAEpC,IAAA,IAAA,CAAK,aAAc,CAAA,SAAA,EAAW,IAAM,EAAA,GAAA,EAAK,IAAI,CAAA,CAAA;AAAA,GAC/C;AAAA;AAAA,EAGQ,aAAe,CAAA,SAAA,EAAmB,IAAe,EAAA,GAAA,EAAa,IAAc,EAAA;AAClF,IAAM,MAAA,IAAA,GAAO,IAAK,CAAA,UAAA,CAAW,qBAAsB,EAAA,CAAA;AACnD,IAAM,MAAA,KAAA,GAAQ,KAAK,WAAY,CAAA,KAAA,CAAA;AAE/B,IAAI,IAAA,SAAA,KAAc,KAAS,IAAA,SAAA,KAAc,QAAU,EAAA;AACjD,MAAA,MAAM,YAAe,GAAA,IAAA,CAAK,IAAO,GAAA,IAAA,CAAK,KAAQ,GAAA,CAAA,CAAA;AAC9C,MAAM,MAAA,MAAA,GAAS,IAAK,CAAA,GAAA,CAAI,EAAI,EAAA,IAAA,CAAK,GAAI,CAAA,YAAA,GAAe,IAAM,EAAA,IAAA,CAAK,KAAQ,GAAA,EAAE,CAAC,CAAA,CAAA;AAC1E,MAAA,KAAA,CAAM,OAAO,CAAG,EAAA,MAAA,CAAA,EAAA,CAAA,CAAA;AAChB,MAAA,KAAA,CAAM,GAAM,GAAA,EAAA,CAAA;AAAA,KACP,MAAA;AACL,MAAA,MAAM,YAAe,GAAA,IAAA,CAAK,GAAM,GAAA,IAAA,CAAK,MAAS,GAAA,CAAA,CAAA;AAC9C,MAAM,MAAA,MAAA,GAAS,IAAK,CAAA,GAAA,CAAI,EAAI,EAAA,IAAA,CAAK,GAAI,CAAA,YAAA,GAAe,GAAK,EAAA,IAAA,CAAK,MAAS,GAAA,EAAE,CAAC,CAAA,CAAA;AAC1E,MAAA,KAAA,CAAM,MAAM,CAAG,EAAA,MAAA,CAAA,EAAA,CAAA,CAAA;AACf,MAAA,KAAA,CAAM,IAAO,GAAA,EAAA,CAAA;AAAA,KACf;AAAA,GACF;AAAA,EAEQ,MAAU,GAAA;AAChB,IAAM,MAAA,IAAA,GAAO,IAAK,CAAA,UAAA,CAAW,qBAAsB,EAAA,CAAA;AACnD,IAAA,IAAA,CAAK,UAAW,CAAA,KAAA,CAAM,GAAM,GAAA,CAAA,EAAG,IAAK,CAAA,GAAA,CAAI,CAAG,EAAA,MAAA,CAAO,WAAc,GAAA,CAAA,GAAI,IAAK,CAAA,MAAA,GAAS,CAAC,CAAA,CAAA,EAAA,CAAA,CAAA;AACnF,IAAA,IAAA,CAAK,UAAW,CAAA,KAAA,CAAM,IAAO,GAAA,CAAA,EAAG,IAAK,CAAA,GAAA,CAAI,CAAG,EAAA,MAAA,CAAO,UAAa,GAAA,CAAA,GAAI,IAAK,CAAA,KAAA,GAAQ,CAAC,CAAA,CAAA,EAAA,CAAA,CAAA;AAClF,IAAK,IAAA,CAAA,UAAA,CAAW,QAAQ,SAAY,GAAA,QAAA,CAAA;AAAA,GACtC;AAAA,EAEQ,SAAa,GAAA;AACnB,IAAA,qBAAA,CAAsB,MAAM;AAC1B,MAAA,IAAI,IAAK,CAAA,MAAA;AAAQ,QAAA,IAAA,CAAK,WAAW,KAAM,EAAA,CAAA;AAAA,KACxC,CAAA,CAAA;AAAA,GACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,aAAc,SAAmB,EAAA;AACvC,IAAA,MAAM,KAAK,IAAK,CAAA,YAAA,CAAA;AAChB,IAAM,MAAA,GAAA,GAA8B,EAAE,MAAQ,EAAA,IAAA,EAAM,KAAK,MAAQ,EAAA,KAAA,EAAO,MAAQ,EAAA,IAAA,EAAM,OAAQ,EAAA,CAAA;AAE9F,IAAA,EAAA,CAAG,SAAU,CAAA,MAAA,CAAO,SAAW,EAAA,WAAA,EAAa,aAAa,YAAY,CAAA,CAAA;AACrE,IAAM,MAAA,IAAA,GAAO,IAAI,SAAS,CAAA,CAAA;AAC1B,IAAI,IAAA,IAAA;AAAM,MAAG,EAAA,CAAA,SAAA,CAAU,GAAI,CAAA,CAAA,KAAA,EAAQ,IAAM,CAAA,CAAA,CAAA,CAAA;AAEzC,IAAA,EAAA,CAAG,MAAS,GAAA,IAAA,CAAA;AACZ,IAAA,qBAAA,CAAsB,MAAM;AAAE,MAAA,IAAI,IAAK,CAAA,MAAA;AAAQ,QAAA,EAAA,CAAG,MAAS,GAAA,KAAA,CAAA;AAAA,KAAO,CAAA,CAAA;AAAA,GACpE;AAAA,EAEQ,QAAY,GAAA;AAClB,IAAA,IAAA,CAAK,MAAS,GAAA,KAAA,CAAA;AACd,IAAA,IAAA,CAAK,cAAe,EAAA,CAAA;AAEpB,IAAA,IAAA,CAAK,QAAQ,gBAA8B,CAAA,WAAW,CAAE,CAAA,OAAA,CAAQ,CAAC,EAAO,KAAA;AACtE,MAAI,IAAA;AAAE,QAAA,EAAA,CAAG,WAAY,EAAA,CAAA;AAAA,OAAI,CAAA,MAAA;AAAA,OAA6B;AAAA,KACvD,CAAA,CAAA;AACD,IAAA,IAAA,CAAK,cAAc,MAAS,GAAA,IAAA,CAAA;AAC5B,IAAA,IAAA,CAAK,WAAW,MAAS,GAAA,IAAA,CAAA;AACzB,IAAA,QAAA,CAAS,mBAAoB,CAAA,SAAA,EAAW,IAAK,CAAA,aAAA,EAAe,IAAI,CAAA,CAAA;AAChE,IAAO,MAAA,CAAA,mBAAA,CAAoB,QAAU,EAAA,IAAA,CAAK,UAAU,CAAA,CAAA;AACpD,IAAA,MAAA,CAAO,mBAAoB,CAAA,QAAA,EAAU,IAAK,CAAA,UAAA,EAAY,IAAI,CAAA,CAAA;AAC1D,IAAA,IAAA,CAAK,eAAe,KAAM,EAAA,CAAA;AAC1B,IAAA,IAAA,CAAK,aAAgB,GAAA,IAAA,CAAA;AAAA,GACvB;AAAA,EAEQ,UAAA,GAAa,CAAC,KAAiB,KAAA;AACrC,IAAM,MAAA,MAAA,GAAU,KAAsB,CAAA,MAAA,IAAU,EAAC,CAAA;AACjD,IAAM,MAAA,EAAA,GAAK,OAAO,MAAO,CAAA,EAAA,IAAM,EAAE,CAAE,CAAA,OAAA,CAAQ,KAAK,EAAE,CAAA,CAAA;AAClD,IAAI,IAAA,EAAA,KAAO,KAAK,OAAQ,CAAA,EAAA;AAAI,MAAA,IAAA,CAAK,KAAM,EAAA,CAAA;AAAA,GACzC,CAAA;AAAA,EAEQ,aAAa,MAAM;AACzB,IAAA,IAAI,CAAC,IAAK,CAAA,MAAA;AAAQ,MAAA,OAAA;AAClB,IAAA,MAAM,IAAO,GAAA,IAAA,CAAK,KAAM,CAAA,IAAA,CAAK,KAAK,CAAA,CAAA;AAClC,IAAA,MAAM,SAAS,IAAK,CAAA,QAAA,GAAW,SAAS,aAA2B,CAAA,IAAA,CAAK,QAAQ,CAAI,GAAA,IAAA,CAAA;AACpF,IAAI,IAAA,MAAA;AAAQ,MAAK,IAAA,CAAA,QAAA,CAAS,MAAQ,EAAA,IAAA,CAAK,QAAQ,CAAA,CAAA;AAAA;AAC1C,MAAA,IAAA,CAAK,MAAO,EAAA,CAAA;AAAA,GACnB,CAAA;AAAA,EAEQ,aAAA,GAAgB,CAAC,KAAyB,KAAA;AAChD,IAAA,IAAI,CAAC,IAAK,CAAA,MAAA;AAAQ,MAAA,OAAA;AAElB,IAAA,QAAQ,MAAM,GAAK;AAAA,MACjB,KAAK,QAAA;AACH,QAAA,KAAA,CAAM,cAAe,EAAA,CAAA;AACrB,QAAA,IAAA,CAAK,MAAO,EAAA,CAAA;AACZ,QAAA,MAAA;AAAA,MACF,KAAK,YAAA;AACH,QAAA,KAAA,CAAM,cAAe,EAAA,CAAA;AACrB,QAAA,IAAA,CAAK,IAAK,EAAA,CAAA;AACV,QAAA,MAAA;AAAA,MACF,KAAK,WAAA;AACH,QAAA,KAAA,CAAM,cAAe,EAAA,CAAA;AACrB,QAAA,IAAA,CAAK,IAAK,EAAA,CAAA;AACV,QAAA,MAAA;AAAA,MACF,KAAK,KAAA;AACH,QAAA,IAAA,CAAK,QAAQ,KAAK,CAAA,CAAA;AAClB,QAAA,MAAA;AAAA,KACJ;AAAA,GACF,CAAA;AAAA;AAAA,EAGQ,QAAS,KAAsB,EAAA;AACrC,IAAM,MAAA,SAAA,GAAY,MAAM,IAAK,CAAA,IAAA,CAAK,WAAW,gBAA8B,CAAA,SAAS,CAAC,CAAA,CAClF,MAAO,CAAA,CAAC,OAAO,CAAC,EAAA,CAAG,UAAU,EAAG,CAAA,YAAA,KAAiB,QAAQ,gBAAiB,CAAA,EAAE,CAAE,CAAA,UAAA,KAAe,QAAQ,CAAA,CAAA;AACxG,IAAA,IAAI,UAAU,MAAW,KAAA,CAAA;AAAG,MAAA,OAAA;AAE5B,IAAM,MAAA,KAAA,GAAQ,UAAU,CAAC,CAAA,CAAA;AACzB,IAAA,MAAM,IAAO,GAAA,SAAA,CAAU,SAAU,CAAA,MAAA,GAAS,CAAC,CAAA,CAAA;AAC3C,IAAA,MAAM,SAAS,QAAS,CAAA,aAAA,CAAA;AAExB,IAAA,IAAI,MAAM,QAAU,EAAA;AAClB,MAAI,IAAA,MAAA,KAAW,KAAS,IAAA,MAAA,KAAW,IAAK,CAAA,UAAA,IAAc,CAAC,IAAK,CAAA,UAAA,CAAW,QAAS,CAAA,MAAM,CAAG,EAAA;AACvF,QAAA,KAAA,CAAM,cAAe,EAAA,CAAA;AACrB,QAAA,IAAA,CAAK,KAAM,EAAA,CAAA;AAAA,OACb;AAAA,KACF,MAAA,IAAW,WAAW,IAAQ,IAAA,CAAC,KAAK,UAAW,CAAA,QAAA,CAAS,MAAM,CAAG,EAAA;AAC/D,MAAA,KAAA,CAAM,cAAe,EAAA,CAAA;AACrB,MAAA,KAAA,CAAM,KAAM,EAAA,CAAA;AAAA,KACd;AAAA,GACF;AACF;;;;"}
@@ -0,0 +1,38 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+
3
+ class PageTransition extends Controller {
4
+ static values = {
5
+ style: { type: String, default: "fade" },
6
+ duration: { type: String, default: "" },
7
+ easing: { type: String, default: "" }
8
+ };
9
+ injectedMeta = null;
10
+ connect() {
11
+ if (this.styleValue === "none")
12
+ return;
13
+ if (!document.querySelector('meta[name="view-transition"]')) {
14
+ const meta = document.createElement("meta");
15
+ meta.name = "view-transition";
16
+ meta.content = "same-origin";
17
+ document.head.appendChild(meta);
18
+ this.injectedMeta = meta;
19
+ }
20
+ document.documentElement.dataset.midwestPageTransition = this.styleValue;
21
+ if (this.durationValue) {
22
+ document.documentElement.style.setProperty("--page-transition-duration", this.durationValue);
23
+ }
24
+ if (this.easingValue) {
25
+ document.documentElement.style.setProperty("--page-transition-easing", this.easingValue);
26
+ }
27
+ }
28
+ disconnect() {
29
+ this.injectedMeta?.remove();
30
+ this.injectedMeta = null;
31
+ delete document.documentElement.dataset.midwestPageTransition;
32
+ document.documentElement.style.removeProperty("--page-transition-duration");
33
+ document.documentElement.style.removeProperty("--page-transition-easing");
34
+ }
35
+ }
36
+
37
+ export { PageTransition as default };
38
+ //# sourceMappingURL=page_transition_component_controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page_transition_component_controller.js","sources":["../../../../../../../app/components/midwest/page_transition_component/page_transition_component_controller.ts"],"sourcesContent":["import { Controller } from '@hotwired/stimulus'\n\n// Enables Turbo View Transitions by injecting the <meta name=\"view-transition\">\n// tag that Turbo 8 requires to wrap navigations in document.startViewTransition(),\n// and by writing `data-midwest-page-transition` onto <html> so the CSS keyframe\n// rules scope to the chosen style. Custom duration/easing are pushed as CSS custom\n// properties on <html> so they win over the layer defaults without !important.\n//\n// Values\n// style — transition key, one of:\n// \"fade\" | \"slide-left\" | \"slide-right\" | \"slide-up\" |\n// \"slide-down\" | \"scale\" | \"none\"\n// duration — optional resolved CSS value (e.g. \"var(--duration-fast)\", \"200ms\")\n// easing — optional resolved CSS value (e.g. \"var(--ease-emphasized)\")\nexport default class PageTransition extends Controller<HTMLElement> {\n static values = {\n style: { type: String, default: 'fade' },\n duration: { type: String, default: '' },\n easing: { type: String, default: '' }\n }\n\n declare styleValue: string\n declare durationValue: string\n declare easingValue: string\n\n private injectedMeta: HTMLMetaElement | null = null\n\n connect () {\n // `style: :none` means \"install no transitions at all.\"\n if (this.styleValue === 'none') return\n\n // Inject the Turbo View Transitions meta tag if not already present. We\n // track what we injected so we can remove it precisely on disconnect.\n if (!document.querySelector('meta[name=\"view-transition\"]')) {\n const meta = document.createElement('meta')\n meta.name = 'view-transition'\n meta.content = 'same-origin'\n document.head.appendChild(meta)\n this.injectedMeta = meta\n }\n\n // The CSS uses this attribute to scope ::view-transition-* animations.\n document.documentElement.dataset.midwestPageTransition = this.styleValue\n\n // Per-call timing overrides — win over the layer defaults without !important.\n if (this.durationValue) {\n document.documentElement.style.setProperty('--page-transition-duration', this.durationValue)\n }\n if (this.easingValue) {\n document.documentElement.style.setProperty('--page-transition-easing', this.easingValue)\n }\n }\n\n disconnect () {\n this.injectedMeta?.remove()\n this.injectedMeta = null\n delete document.documentElement.dataset.midwestPageTransition\n document.documentElement.style.removeProperty('--page-transition-duration')\n document.documentElement.style.removeProperty('--page-transition-easing')\n }\n}\n"],"names":[],"mappings":";;AAcA,MAAqB,uBAAuB,UAAwB,CAAA;AAAA,EAClE,OAAO,MAAS,GAAA;AAAA,IACd,KAAO,EAAA,EAAE,IAAM,EAAA,MAAA,EAAQ,SAAS,MAAO,EAAA;AAAA,IACvC,QAAU,EAAA,EAAE,IAAM,EAAA,MAAA,EAAQ,SAAS,EAAG,EAAA;AAAA,IACtC,MAAQ,EAAA,EAAE,IAAM,EAAA,MAAA,EAAQ,SAAS,EAAG,EAAA;AAAA,GACtC,CAAA;AAAA,EAMQ,YAAuC,GAAA,IAAA,CAAA;AAAA,EAE/C,OAAW,GAAA;AAET,IAAA,IAAI,KAAK,UAAe,KAAA,MAAA;AAAQ,MAAA,OAAA;AAIhC,IAAA,IAAI,CAAC,QAAA,CAAS,aAAc,CAAA,8BAA8B,CAAG,EAAA;AAC3D,MAAM,MAAA,IAAA,GAAO,QAAS,CAAA,aAAA,CAAc,MAAM,CAAA,CAAA;AAC1C,MAAA,IAAA,CAAK,IAAO,GAAA,iBAAA,CAAA;AACZ,MAAA,IAAA,CAAK,OAAU,GAAA,aAAA,CAAA;AACf,MAAS,QAAA,CAAA,IAAA,CAAK,YAAY,IAAI,CAAA,CAAA;AAC9B,MAAA,IAAA,CAAK,YAAe,GAAA,IAAA,CAAA;AAAA,KACtB;AAGA,IAAS,QAAA,CAAA,eAAA,CAAgB,OAAQ,CAAA,qBAAA,GAAwB,IAAK,CAAA,UAAA,CAAA;AAG9D,IAAA,IAAI,KAAK,aAAe,EAAA;AACtB,MAAA,QAAA,CAAS,eAAgB,CAAA,KAAA,CAAM,WAAY,CAAA,4BAAA,EAA8B,KAAK,aAAa,CAAA,CAAA;AAAA,KAC7F;AACA,IAAA,IAAI,KAAK,WAAa,EAAA;AACpB,MAAA,QAAA,CAAS,eAAgB,CAAA,KAAA,CAAM,WAAY,CAAA,0BAAA,EAA4B,KAAK,WAAW,CAAA,CAAA;AAAA,KACzF;AAAA,GACF;AAAA,EAEA,UAAc,GAAA;AACZ,IAAA,IAAA,CAAK,cAAc,MAAO,EAAA,CAAA;AAC1B,IAAA,IAAA,CAAK,YAAe,GAAA,IAAA,CAAA;AACpB,IAAO,OAAA,QAAA,CAAS,gBAAgB,OAAQ,CAAA,qBAAA,CAAA;AACxC,IAAS,QAAA,CAAA,eAAA,CAAgB,KAAM,CAAA,cAAA,CAAe,4BAA4B,CAAA,CAAA;AAC1E,IAAS,QAAA,CAAA,eAAA,CAAgB,KAAM,CAAA,cAAA,CAAe,0BAA0B,CAAA,CAAA;AAAA,GAC1E;AACF;;;;"}