@kendawson-online/vantl 2.0.4 → 2.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,14 @@
1
- # Vantl - Vanilla (JS) Timeline
1
+ # Vantl - Vanilla Timeline
2
2
 
3
- A lightweight, responsive timeline library created with vanilla Javascript for creating beautiful horizontal and vertical timelines with zero dependencies. Inspired by [timeline](https://github.com/squarechip/timeline) originally created by [squarechip](https://github.com/squarechip) in 2018.
3
+ Vantl is a lightweight, responsive timeline library created with vanilla Javascript for creating beautiful horizontal and vertical timelines with zero dependencies. Inspired by [timeline](https://github.com/squarechip/timeline) originally created by [squarechip](https://github.com/squarechip) in 2018.
4
4
 
5
+ <table align="center">
6
+ <tr>
7
+ <td><img src="demo/assets/img/horizontal-screenshot.png" width="650"></td>
8
+ </tr>
9
+ </table>
10
+
11
+ <br/>
5
12
 
6
13
  ## Features
7
14
 
@@ -15,128 +22,305 @@ A lightweight, responsive timeline library created with vanilla Javascript for c
15
22
  - 🚀 **Auto-init** - Just add a data attribute to load from JSON
16
23
  - 📏 **Small footprint** - Minified and tree-shakeable
17
24
 
18
- ## Quick Start
25
+ <br/><br/>
19
26
 
20
- ### Via CDN
27
+ # Getting Started:
21
28
 
22
- ```html
29
+ <br/>
30
+
31
+ Load stylesheet and Javascript functions to your document via CDN links:
32
+
33
+ ````html
23
34
  <!DOCTYPE html>
24
35
  <html>
25
36
  <head>
26
- <!-- timeline stylesheet -->
27
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@kendawson-online/vantl@2/src/css/timeline.css">
37
+ <!-- load stylesheet -->
38
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@kendawson-online/vantl@2/dist/timeline.min.css">
28
39
  </head>
29
40
  <body>
30
41
 
31
- <!-- your timeline code here -->
32
- <div id="timeline" class="timeline" data-json-config="/path/to/your/data.json"></div>
42
+ <!-- your timeline will go here -->
33
43
 
34
- <!-- timeline Javascript -->
44
+ <!-- load functions -->
35
45
  <script src="https://cdn.jsdelivr.net/npm/@kendawson-online/vantl@2/dist/timeline.min.js"></script>
36
46
  </body>
37
47
  </html>
38
- ```
48
+ ````
49
+ <br/>
39
50
 
40
- ### Via npm
51
+ ### 1️⃣ CREATE A TIMELINE USING BASIC HTML
41
52
 
42
- ```bash
43
- npm install @kendawson-online/vantl
44
- ```
53
+ <br/>
45
54
 
46
- ```javascript
47
- import { timeline } from '@kendawson-online/vantl';
48
- import '@kendawson-online/vantl/src/css/timeline.css';
55
+ Add some timeline node data in HTML. If you want your timeline to be oriented horizontally, set `data-mode="horizontal"` on the parent element (see code below). If you omit this setting, the timeline will be oriented vertically by default.
49
56
 
50
- timeline(document.querySelectorAll('.timeline'), {
51
- mode: 'vertical',
52
- nodeColor: '#2d6cdf'
53
- });
54
- ```
57
+ ````html
58
+ <!-- your timeline -->
59
+ <div class="timeline" data-mode="horizontal">
60
+ <div class="timeline__wrap">
61
+ <div class="timeline__items">
62
+ <div class="timeline__item">
63
+ <div class="timeline__content">
64
+ <h5>Jan. 1, 2000</h5>
65
+ <p>Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum.</p>
66
+ </div>
67
+ </div>
68
+ <div class="timeline__item">
69
+ <div class="timeline__content">
70
+ <h5>Dec. 31, 2000</h5>
71
+ <p>Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum.</p>
72
+ </div>
73
+ </div>
74
+ <div class="timeline__item">
75
+ <div class="timeline__content">
76
+ <h5>Jan. 1, 2001</h5>
77
+ <p>Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum.</p>
78
+ </div>
79
+ </div>
80
+ </div>
81
+ </div>
82
+ </div>
83
+ ````
84
+ <br/>
85
+
86
+ Add one line of code at the bottom to initialize your timeline. It goes after the CDN link but before the closing `</body>` tag and looks like this:
87
+
88
+ ````html
89
+ <!-- load functions -->
90
+ <script src="https://cdn.jsdelivr.net/npm/@kendawson-online/vantl@2/dist/timeline.min.js"></script>
91
+
92
+ <!-- initialize the timeline -->
93
+ <script>
94
+ timeline(document.querySelectorAll('.timeline'));
95
+ </script>
96
+
97
+ </body>
98
+ </html>
99
+ ````
100
+
101
+ <br/>
102
+
103
+ ### <a href="demo/basic-example.html" target="_blank">View A Basic HTML Example (With Source Code)</a> 👀
104
+
105
+ <br/><br/>
55
106
 
56
- ## Usage Examples
107
+ <a href="https://jquery.com" target="_blank"><img src="demo/assets/img/jquery.png" width="145" alt="jQuery" title="jQuery" /></a>
57
108
 
58
- ### 1. Auto-Init with JSON (Easiest)
109
+ Note: if you're using <a href="https://jquery.com" target="_blank">jQuery</a> in your document, you can initialize your timeline like this:
59
110
 
60
- The timeline auto-initializes when you add a `data-json-config` attribute:
111
+ ````html
112
+ <!-- load functions -->
113
+ <script src="https://cdn.jsdelivr.net/npm/@kendawson-online/vantl@2/dist/timeline.min.js"></script>
114
+
115
+ <!-- initialize timeline with jQuery -->
116
+ <script>
117
+ jQuery(function () {
118
+ $('.timeline').timeline({
119
+ mode: 'horizontal'
120
+ });
121
+ });
122
+ </script>
123
+
124
+ </body>
125
+ </html>
126
+ ````
127
+ For more info check the Advanced Usage section below
128
+
129
+ <br/>
130
+
131
+ ----
132
+
133
+ <br/>
134
+
135
+ ### 2️⃣ USE DATA ATTRIBUTES TO CUSTOMIZE YOUR TIMELINE
136
+
137
+ You can add data attributes to the timeline element to control how it looks and/or functions. For example, this is how you would set the orientation of the timeline to be horizontal instead of vertical (default):
61
138
 
62
139
  ```html
63
- <div class="timeline" data-json-config="/path/to/timeline.json"></div>
64
- ```
140
+ <div class="timeline" data-mode="horizontal">
141
+ ...
142
+ </div>
143
+ ````
144
+
145
+ If you don't pass an attribute, the app will simply use the default values.
146
+
147
+ Here are the available data attributes:
148
+
149
+ | Option | Type | Default | Description |
150
+ |--------|------|---------|-------------|
151
+ | `data-mode` | string | `'vertical'` | Layout mode: `'vertical'` or `'horizontal'` |
152
+ | `data-min-width` | number | `600` | Minimum viewport width (px) to maintain horizontal mode |
153
+ | `data-max-width` | number | `600` | Maximum viewport width (px) to maintain vertical mode |
154
+ | `data-visible-items` | number | `3` | Number of items in horizontal viewport |
155
+ | `data-move-items` | number | `1` | Items to scroll per navigation click (horizontal) |
156
+ | `data-start-index` | number | `0` | Initial item index (horizontal mode) |
157
+ | `data-horizontal-start-position` | string | `'top'` | First item alignment in horizontal layout: `'top'` or `'bottom'` |
158
+ | `data-vertical-start-position` | string | `'left'` | First item alignment in vertical layout: `'left'` or `'right'` |
159
+ | `data-vertical-trigger` | string | `'15%'` | Scroll trigger distance: percentage or px (e.g., `'20%'` or `'150px'`) |
160
+ | `data-rtl-mode` | boolean | `false` | Right to left mode: `true` or `false` (only works in horizontal mode and overrides `startIndex` setting) |
161
+ | `data-node-color` | string | — | Node circle color (hex/rgb/hsl) |
162
+ | `data-line-color` | string | — | Timeline line color (hex/rgb/hsl) |
163
+ | `data-nav-color` | string | — | Navigation button color (hex/rgb/hsl) |
164
+ | `data-json-config` | string | — | path to a JSON data file (e.g., /path/to/valid/file.json)|
165
+
166
+ <br/>
167
+
168
+ See the [API Documentation](API-Documentation.md) for a more detailed description of all options.
169
+
170
+ <br/>
171
+
172
+ ----
65
173
 
66
- **JSON Format:**
67
- ```json
174
+ <br/>
175
+
176
+ ### 3️⃣ USING A JSON FILE TO LOAD TIMELINE DATA
177
+
178
+ <br/>
179
+
180
+ A great way to use vanilla timeline is to store and load your data from an external [JSON](https://www.json.org) file. JSON stands for: "JavaScript Object Notation".
181
+
182
+ It's a lightweight text format stored in a file with a `.json` extension. It's easy for humans to read and write and for machines to parse and use in apps. JSON is based on a web standard so you have to follow the rules to produce "well-formed JSON" that is formatted a specific way. A simple JSON file might look something like this:
183
+
184
+ ````javascript
68
185
  {
69
- "timelineName": "My Timeline",
70
- "layoutMode": "vertical",
71
- "lastupdated": "2026-01-08T20:15:34.873Z",
72
- "nodes": [
73
- {
74
- "id": 1,
75
- "title": "Event Title",
76
- "content": "Event description...",
77
- "image": "/path/to/image.jpg"
78
- }
79
- ]
186
+ "timelineName": "Timeline Title",
187
+ "layoutMode": "horizontal",
188
+ "visibleItems": 5,
189
+ "minWidth": 700,
190
+ "maxWidth": "",
191
+ "nodeColor": "",
192
+ "lineColor": "",
193
+ "navColor": "",
80
194
  }
81
- ```
195
+ ````
82
196
 
83
- ### 2. Inline HTML with Data Attributes
197
+ <br/>
198
+
199
+ To use JSON, you add a data attribute called `data-json-config` to your HTML to tell the app which JSON file you want to load:
84
200
 
85
201
  ```html
86
- <div class="timeline" data-mode="horizontal">
87
- <div class="timeline__wrap">
202
+ <div class="timeline" data-json-config="/path/to/timeline.json"></div>
203
+ ```
204
+
205
+ <br/>
206
+
207
+ ⚠️ **Important:** if you set a `data-json-config` value, the app will prioritize JSON file settings and ignore any other data attribute values being passed inlne via HTML.
208
+
209
+ If you load your timeline data using the JSON method, you don't have to add the extra line of code at the bottom of the page (used to initialize the timeline). When a JSON file is loaded, the app is initialized automatically.
210
+
211
+ Here are some examples of JSON files you can use as templates to build your own timelines:
212
+
213
+ - [The most basic and simplified JSON file format possible](demo/assets/data/simple-data-array.json)
214
+
215
+ - [A Basic Horizontal Timeline Without Images](demo/assets/data/horiz-no-images.json)
216
+
217
+ - [A Basic Vertical Timeline Without Images](demo/assets/data/vert-no-images.json)
218
+
219
+ - [Advanced JSON template with Images and Colors](demo/assets/data/blank-template.json)
220
+
221
+ <br/>
222
+
223
+ 🗓️ **A NOTE ABOUT DATES IN JSON** 🗓️
224
+
225
+ If there are dates stored in these JSON files (e.g. the `lastupdated` field), they're stored in a special format named ISO 8601. The vanilla timeline app expects dates to be in this format.
226
+
227
+ There is a [demo page](demo/time.html) included which displays this date format for you. This page also teaches you how to generate the ISO 8601 timestamp in the developer console of your web browser. Open the [demo/time.html](demo/time.html) file in your browser to see a current ISO 8601 timestamp. You can copy/paste this date string directly into your JSON timelines.
228
+
229
+ ----
230
+
231
+ <br/>
232
+
233
+ # Deep Linking
234
+
235
+ Link to a specific timeline node using URL parameters:
236
+
237
+ ```
238
+ https://example.com/page.html?timeline=myTimelineId&id=3
239
+
240
+
241
+ https://[domain name]/[page name]?timeline=[timeline ID]&id=[node id]
242
+ ```
243
+ <br/>
244
+
245
+ 1) Add an `id` attribute and value to your timeline container:
246
+
247
+ ````html
248
+ <div id="myTimeline" class="timeline">
249
+ ...
250
+ </div>
251
+ ````
252
+ <br/>
253
+
254
+ 2) Add a `data-node-id` to each node you want to link to
255
+ ````html
88
256
  <div class="timeline__items">
257
+ <!-- node 1 -->
89
258
  <div class="timeline__item">
90
259
  <div class="timeline__content">
91
- <h5>2001</h5>
92
- <p>Lorem ipsum dolor sit amet, qui <a href="#">minim</a> labore adipisicing minim sint cillum sint consectetur cupidatat.</p>
260
+ <h5>Jan. 1, 2015</h5>
261
+ <p>Lorem ipsum dolor sit amet, qui minim labore.</p>
93
262
  </div>
94
263
  </div>
264
+ <!-- node 2 -->
95
265
  <div class="timeline__item">
96
266
  <div class="timeline__content">
97
- <h5>2002</h5>
98
- <p>Lorem ipsum <a href="#">dolor sit amet</a>, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.</p>
267
+ <h5>Dec. 31, 2016</h5>
268
+ <p>Lorem ipsum dolor sit amet, qui minim labore.</p>
99
269
  </div>
100
270
  </div>
101
- <div class="timeline__item">
102
- <div class="timeline__content">
103
- <h5>2003</h5>
104
- <p>Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.</p>
105
- </div>
106
- </div>
107
- </div>
108
- </div>
109
- </div>
271
+ </div>
272
+ ````
110
273
 
111
- <script>
112
- timeline(document.querySelectorAll('.timeline'));
113
- </script>
274
+ Deep linking works automatically with JSON-loaded timelines
275
+
276
+ <br/>
277
+
278
+ # Advanced Usage:
279
+
280
+ ### Installing with npm
281
+
282
+ ```bash
283
+ npm install @kendawson-online/vantl
114
284
  ```
115
285
 
116
- ### 3. JavaScript API
286
+ Importing timeline functions into your Javscript app:
117
287
 
118
288
  ```javascript
119
- // Vanilla JS
289
+ import { timeline } from '@kendawson-online/vantl';
290
+ import '@kendawson-online/vantl/dist/timeline.min.css';
291
+
292
+ timeline(document.querySelectorAll('.timeline'), {
293
+ mode: 'vertical',
294
+ nodeColor: '#2d6cdf'
295
+ });
296
+ ```
297
+
298
+ ### Setting options
299
+
300
+ ```javascript
301
+ // vanilla Javascript
120
302
  timeline(document.querySelectorAll('.timeline'), {
121
303
  mode: 'horizontal',
122
304
  visibleItems: 3,
123
305
  });
124
306
 
125
- // jQuery (if available)
307
+
308
+ // jQuery
126
309
  $('.timeline').timeline({
127
310
  mode: 'vertical',
128
311
  verticalTrigger: '20%'
129
312
  });
130
313
  ```
131
314
 
132
- ## API Options
315
+ ### Available API Options
133
316
 
134
- All options can be set via JavaScript API, data attributes, or JSON config.
317
+ All options can be set via JavaScript API, data attributes, or with JSON config.
135
318
 
136
319
  | Option | Type | Default | Description |
137
320
  |--------|------|---------|-------------|
138
321
  | `mode` | string | `'vertical'` | Layout mode: `'vertical'` or `'horizontal'` |
139
322
  | `minWidth` | number | `600` | Min viewport width (px) to maintain horizontal mode |
323
+ | `maxWidth` | number | `600` | Max viewport width (px) to maintain vertical mode |
140
324
  | `visibleItems` | number | `3` | Number of items in horizontal viewport |
141
325
  | `moveItems` | number | `1` | Items to scroll per navigation click (horizontal) |
142
326
  | `startIndex` | number | `0` | Initial item index (horizontal mode) |
@@ -148,36 +332,6 @@ All options can be set via JavaScript API, data attributes, or JSON config.
148
332
  | `lineColor` | string | — | Center line color (hex/rgb/hsl) |
149
333
  | `navColor` | string | — | Navigation button color (hex/rgb/hsl) |
150
334
 
151
- **Setting Options:**
152
-
153
- ```javascript
154
- // JavaScript
155
- timeline(el, { mode: 'horizontal', nodeColor: '#2d6cdf' });
156
- ```
157
-
158
- ```html
159
- <!-- Data attributes -->
160
- <div class="timeline" data-mode="horizontal" data-node-color="#2d6cdf">
161
- ```
162
-
163
- ```json
164
- // JSON
165
- { "layoutMode": "horizontal", "nodeColor": "#2d6cdf" }
166
- ```
167
-
168
- ## Deep Linking
169
-
170
- Link to a specific timeline node using URL parameters:
171
-
172
- ```
173
- https://example.com/page.html?timeline=myTimelineId&id=3
174
- ```
175
-
176
- - Add `id` attribute to timeline container
177
- - Add `data-node-id` to each item you want to link to
178
- - Works automatically with JSON-loaded timelines
179
-
180
- ## Advanced Features
181
335
 
182
336
  ### Custom Image Path
183
337
 
@@ -192,30 +346,14 @@ Override the auto-detected image path:
192
346
  <script src="dist/timeline.min.js"></script>
193
347
  ```
194
348
 
195
- ### Modal Content
196
-
197
- Each timeline item can display a modal popup on click:
198
-
199
- ```html
200
- <div class="timeline__item"
201
- data-modal-title="Full Title"
202
- data-modal-content="Extended description..."
203
- data-modal-image="/img/large.jpg"
204
- data-modal-html="<p>Custom HTML content</p>">
205
- ...
206
- </div>
207
- ```
208
-
209
- JSON items automatically support modals with the `title`, `content`, `image`, and `html` fields.
210
-
211
- ### Programmatic Control
349
+ ### Programmatic control
212
350
 
213
351
  ```javascript
214
352
  // Load from JSON programmatically
215
353
  loadDataFromJson('/data/timeline.json', '#myTimeline');
216
354
 
217
355
  // Clear cache
218
- clearTimelineCache(); // Clear all
356
+ clearTimelineCache(); // Clear all
219
357
  clearTimelineCache('timelineId'); // Clear specific
220
358
 
221
359
  // Navigate to node (horizontal mode)
@@ -228,6 +366,11 @@ openTimelineModal(itemElement);
228
366
  closeTimelineModal();
229
367
  ```
230
368
 
369
+ ### More Information
370
+
371
+ - [API Documentation](API-Documentation.md)
372
+ - [Development Documentation](Development.md)
373
+
231
374
  ## Browser Support
232
375
 
233
376
  - Chrome/Edge (2018+)
@@ -237,11 +380,29 @@ closeTimelineModal();
237
380
 
238
381
  ## Contributing
239
382
 
240
- See [DEVELOPMENT.md](DEVELOPMENT.md) for build instructions and architecture overview.
383
+ See [Development.md](Development.md) for build instructions and an architectural overview.
384
+
385
+ See [API Documentation](API-Documentation.md) for details about how the API works.
386
+
387
+ You can report issues and open pull requests on GitHub:
388
+
389
+ - https://github.com/kendawson-online/vantl/issues
390
+
391
+ - https://github.com/kendawson-online/vantl/pulls
392
+
393
+ ## Links
394
+
395
+ **NPM Package:** [@kendawson-online/vantl](https://www.npmjs.com/package/@kendawson-online/vantl)
396
+
397
+ **Repository:** [github.com/kendawson-online/vantl](https://github.com/kendawson-online/vantl)
398
+
399
+ **CDN:** [cdn.jsdelivr.net/npm/@kendawson-online/vantl](https://cdn.jsdelivr.net/npm/@kendawson-online/vantl)
400
+
241
401
 
242
402
  ## License
243
403
 
244
- MIT License - see [LICENSE](LICENSE) file for details.
404
+ [MIT License](LICENSE)
405
+
245
406
 
246
407
  ## Credits
247
408
 
@@ -249,8 +410,3 @@ Originally inspired by [timeline](https://github.com/squarechip/timeline) by [Mi
249
410
 
250
411
  Refactored and maintained by [Ken Dawson](https://github.com/kendawson-online) (2026).
251
412
 
252
- ---
253
-
254
- **Package:** [@kendawson-online/vantl](https://www.npmjs.com/package/@kendawson-online/vantl)
255
- **Repository:** [github.com/kendawson-online/vantl](https://github.com/kendawson-online/vantl)
256
- **CDN:** [cdn.jsdelivr.net/npm/@kendawson-online/vantl](https://cdn.jsdelivr.net/npm/@kendawson-online/vantl)
@@ -0,0 +1,2 @@
1
+ .timeline{--timeline-line-color:#ddd;--timeline-node-color:#ddd;--timeline-node-bg:#fff;--timeline-nav-color:#fff;--timeline-nav-border:#ddd;box-sizing:border-box;overflow-x:hidden;position:relative}.timeline__heading{color:#333;font-size:2rem;font-weight:700;margin:0 0 60px;text-align:center}.timeline *,.timeline :after,.timeline :before{box-sizing:inherit}.timeline:not(.timeline--horizontal):before{background-color:var(--timeline-line-color);bottom:0;content:"";left:50%;margin-left:-2px;position:absolute;top:0;width:4px;z-index:1}.timeline__wrap{overflow:hidden;position:relative;z-index:2}.timeline--horizontal .timeline__wrap{overflow:visible}.timeline__item{font-size:1rem;padding:10px 40px 10px 0;position:relative;width:50%;z-index:2}.timeline:not(.timeline--horizontal):not(.timeline--mobile) .timeline__item .timeline__content{display:flex;flex-direction:column;max-height:200px}.timeline:not(.timeline--horizontal):not(.timeline--mobile) .timeline__item .timeline__image{flex-shrink:0}.timeline:not(.timeline--horizontal):not(.timeline--mobile) .timeline__item .timeline__content>div{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden}.timeline:not(.timeline--horizontal):not(.timeline--mobile) .timeline__item .timeline__content h3{flex-shrink:0;margin:0 0 6px;text-align:center}.timeline:not(.timeline--horizontal):not(.timeline--mobile) .timeline__item .timeline__content p{flex:1;margin-bottom:0;min-height:0;overflow:hidden}.timeline:not(.timeline--horizontal):not(.timeline--mobile) .timeline__item .timeline__image{height:auto;margin:0 auto 12px;max-height:100px;object-fit:cover;width:100px}.timeline__item:after{background-color:var(--timeline-node-bg);border:4px solid var(--timeline-node-color);border-radius:50%;content:"";height:20px;position:absolute;right:-10px;top:50%;transform:translateY(-50%);width:20px;z-index:1}.timeline__item.animated{animation-duration:1s;animation-fill-mode:both;opacity:0}.timeline__item.fadeIn{animation-name:fadeIn}.timeline__item--active .timeline__content{box-shadow:0 4px 12px rgba(0,0,0,.15);transform:scale(1.05)}.timeline__item--left{left:0}.timeline__item--right{left:50%;padding:10px 0 10px 40px}.timeline__item--right:after{left:-10px}.timeline__item--right .timeline__content:before{border:10px solid transparent;border-left:none;border-right:12px solid #ccc;left:-12px}.timeline__item--right .timeline__content:after{border:9px solid transparent;border-left:none;border-right:11px solid #fff;left:-10px}.timeline__content{background-color:#fff;border:1px solid #ccc;border-radius:10px;color:#333;display:block;padding:20px;position:relative}.timeline__image{border-radius:8px;display:block;height:auto;margin-bottom:12px;max-width:100%;width:100%}.timeline--horizontal .timeline__image{height:100px;margin:0 auto 8px;object-fit:cover;width:100px}.timeline__content:after,.timeline__content:before{content:"";height:0;position:absolute;top:50%;transform:translateY(-50%);width:0}.timeline__content:before{border-bottom:10px solid transparent;border-left:12px solid #ccc;border-top:10px solid transparent;right:-12px;z-index:1}.timeline__content:after{border-bottom:9px solid transparent;border-left:11px solid #fff;border-top:9px solid transparent;right:-10px;z-index:2}.timeline__content h2{font-size:20px;font-weight:700;margin:0 0 10px}.timeline__content h3{font-size:18px;font-weight:700;margin:0 0 10px}.timeline__content p{font-size:15px;line-height:1.5;margin-bottom:10px}.timeline--horizontal{font-size:0;overflow-x:hidden;overflow-y:visible;padding:0 60px;white-space:nowrap}.timeline--horizontal .timeline-divider{background-color:var(--timeline-line-color);display:block;height:4px;left:40px;position:absolute;right:40px;transform:translateY(-50%);z-index:1}.timeline--horizontal .timeline__items{transition:all .8s;will-change:transform}.timeline--horizontal .timeline__item{display:inline-block;left:0;padding:0 0 40px;position:relative;transition:none;vertical-align:top;white-space:normal;width:200px}.timeline--horizontal .timeline__item .timeline__content{min-height:180px;padding:12px}.timeline--horizontal .timeline__item .timeline__content h3{font-size:18px;font-weight:700;margin:0 0 8px}.timeline--horizontal .timeline__item .timeline__content p{font-size:11px;line-height:1.4;margin-bottom:0}.timeline--horizontal .timeline__item:after{left:50%;right:auto;top:100%;transform:translate(-50%,-50%)}.timeline--horizontal .timeline__item .timeline__item__inner{display:table;height:100%;width:100%}.timeline--horizontal .timeline__item .timeline__content__wrap{display:table-cell;margin:0;padding:0;vertical-align:bottom}.timeline--horizontal .timeline__item .timeline__content:before{border-left:12px solid transparent;border-right:12px solid transparent;border-top:12px solid #ccc;left:50%;right:auto;top:100%;transform:translateX(-50%)}.timeline--horizontal .timeline__item .timeline__content:after{border-left:10px solid transparent;border-right:10px solid transparent;border-top:10px solid #fff;left:50%;right:auto;top:100%;transform:translateX(-50%)}.timeline--horizontal .timeline__item--bottom{padding:40px 0 0}.timeline--horizontal .timeline__item--bottom:after{top:0}.timeline--horizontal .timeline__item--bottom .timeline__content__wrap{vertical-align:top}.timeline--horizontal .timeline__item--bottom .timeline__content:before{border:12px solid transparent;border-bottom:12px solid #ccc;border-top:none;bottom:100%;top:auto}.timeline--horizontal .timeline__item--bottom .timeline__content:after{border:10px solid transparent;border-bottom:10px solid #fff;border-top:none;bottom:100%;top:auto}.timeline-nav-button{background-color:var(--timeline-nav-color);border:3px solid var(--timeline-nav-border);border-radius:50px;box-shadow:0 2px 4px rgba(0,0,0,.1);box-sizing:border-box;cursor:pointer;display:block;height:40px;outline:none;position:absolute;text-indent:-9999px;top:50%;transform:translateY(-50%);transition:all .3s ease;width:40px;z-index:10}.timeline-nav-button:hover{box-shadow:0 4px 8px rgba(0,0,0,.15);transform:translateY(-50%) scale(1.15)}.timeline-nav-button:disabled{cursor:not-allowed;opacity:.5;pointer-events:none;user-select:none}.timeline-nav-button:before{display:none}.timeline-nav-button svg{left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}.timeline-nav-button--prev{left:10px}.timeline-nav-button--next{right:10px}.timeline--mobile{padding:0}.timeline--mobile:before{left:10px!important;margin:0!important}.timeline--mobile .timeline__item{left:0;margin-bottom:20px;padding-left:40px;padding-right:0;width:100%}.timeline--mobile .timeline__item .timeline__content{align-items:flex-start;display:flex;flex-direction:row;gap:6px;max-height:100px;padding:12px}.timeline--mobile .timeline__item .timeline__image{border-radius:6px;flex-shrink:0;height:80px;margin:0;object-fit:cover;width:80px}.timeline--mobile .timeline__item .timeline__content>div{flex:1;min-width:0}.timeline--mobile .timeline__item .timeline__content h3{font-size:16px;margin:0 0 6px}.timeline--mobile .timeline__item .timeline__content p{font-size:13px;line-height:1.4;margin:0;overflow:hidden;text-overflow:ellipsis}.timeline--mobile .timeline__item:after{left:2px;margin:0}.timeline--mobile .timeline__item .timeline__content:before{border:12px solid transparent;border-left:none;border-right-color:#ccc;left:-12px}.timeline--mobile .timeline__item .timeline__content:after{border:10px solid transparent;border-left:none;border-right-color:#fff;left:-10px}@keyframes fadeIn{0%{opacity:0;top:70px}to{opacity:1;top:0}}@keyframes liftUp{0%{top:0}to{top:-15px}}.timeline-modal-overlay{background-color:rgba(0,0,0,.85);height:100%;left:0;opacity:0;position:fixed;top:0;transition:opacity .3s ease,visibility .3s ease;visibility:hidden;width:100%;z-index:9998}.timeline-modal-overlay.timeline-modal-show{opacity:1;visibility:visible}.timeline-modal{background-color:#fff;border-radius:12px;box-shadow:0 10px 40px rgba(0,0,0,.3);left:50%;max-height:90vh;max-width:900px;opacity:0;overflow:hidden;position:fixed;top:50%;transform:translate(-50%,-50%) scale(.7);transition:opacity .3s ease,transform .3s ease,visibility .3s ease;visibility:hidden;width:90%;z-index:9999}.timeline-modal.timeline-modal-show{opacity:1;transform:translate(-50%,-50%) scale(1);visibility:visible}.timeline-modal__content{max-height:90vh;overflow-x:hidden;overflow-y:auto;padding:40px 40px 80px}.timeline-modal__content::-webkit-scrollbar{width:8px}.timeline-modal__content::-webkit-scrollbar-track{background:#f1f1f1;border-radius:0 12px 12px 0}.timeline-modal__content::-webkit-scrollbar-thumb{background:#888;border-radius:4px}.timeline-modal__content::-webkit-scrollbar-thumb:hover{background:#555}.timeline-modal__image{border-radius:8px;display:block;height:auto;margin:0 auto 20px;max-width:100%;width:auto}.timeline-modal__title{color:#333;font-size:28px;font-weight:700;margin:0 0 20px}.timeline-modal__text{color:#555;font-size:16px;line-height:1.6}.timeline-modal__text p{margin-bottom:15px}.timeline-modal__divider{border:0;border-top:1px solid #ddd;margin:30px 0}.timeline-modal__close-bottom{background-color:#333;border:none;border-radius:6px;color:#fff;cursor:pointer;display:block;font-size:16px;margin:30px auto 0;padding:12px 40px;transition:background-color .2s ease}.timeline-modal__close-bottom:hover{background-color:#555}.timeline-modal__close{align-items:center;background-color:rgba(0,0,0,.6);border:none;border-radius:50%;color:#fff;cursor:pointer;display:flex;font-size:24px;height:40px;justify-content:center;line-height:1;position:absolute;right:20px;top:20px;transition:background-color .2s ease,transform .2s ease;width:40px}.timeline-modal__close:hover{background-color:rgba(0,0,0,.8);transform:scale(1.1)}.timeline-modal__close:before{content:"×"}.timeline__item{cursor:pointer;transition:transform .2s ease}.timeline__item:hover .timeline__content{box-shadow:0 4px 12px rgba(0,0,0,.15);transform:translateY(-2px)}.timeline__loader-overlay{background-color:#fff;inset:0;position:fixed;z-index:10000}.timeline__loader,.timeline__loader-overlay{align-items:center;display:flex;justify-content:center}.timeline__loader{padding:20px}.timeline__loader-spinner{display:block;height:auto;max-width:100%;object-fit:contain;width:120px}.timeline__error{align-items:center;background-color:#f9f9f9;border:2px solid #e0e0e0;border-radius:12px;display:flex;flex-direction:column;justify-content:center;margin:20px auto;max-width:600px;min-height:300px;padding:60px 20px;text-align:center}.timeline__error-icon{height:auto;margin-bottom:24px;max-width:100%;opacity:.8;width:200px}.timeline__error-title{color:#d32f2f;font-size:24px;font-weight:700;margin:0 0 16px}.timeline__error-message{color:#555;font-size:16px;line-height:1.6;margin:0 0 16px}.timeline__error-solution{background-color:#fff3cd;border:1px solid #ffc107;border-radius:6px;color:#333;font-size:15px;line-height:1.6;margin:0 0 12px;padding:12px 16px}.timeline__error-solution strong{color:#856404}.timeline__error-details{background-color:#f5f5f5;border:1px solid #ddd;border-radius:4px;color:#666;font-family:Courier New,monospace;font-size:13px;line-height:1.5;margin:12px 0 0;max-width:100%;overflow-x:auto;padding:8px 12px}.timeline__error-details strong{color:#333}
2
+ /*# sourceMappingURL=timeline.min.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["timeline.css"],"names":[],"mappings":"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","file":"timeline.min.css","sourcesContent":[".timeline {\n box-sizing: border-box;\n position: relative;\n overflow-x: hidden;\n \n /* CSS Custom Properties for dynamic colors */\n --timeline-line-color: #DDD;\n --timeline-node-color: #DDD;\n --timeline-node-bg: #FFF;\n --timeline-nav-color: #FFF;\n --timeline-nav-border: #DDD;\n}\n\n/* Timeline heading */\n.timeline__heading {\n font-size: 2rem;\n font-weight: 700;\n margin: 0 0 60px;\n text-align: center;\n color: #333;\n}\n\n.timeline *,\n.timeline *::before,\n.timeline *::after {\n box-sizing: inherit;\n}\n\n.timeline:not(.timeline--horizontal)::before {\n background-color: var(--timeline-line-color);\n bottom: 0;\n content: '';\n left: 50%;\n margin-left: -2px;\n position: absolute;\n top: 0;\n width: 4px;\n z-index: 1;\n}\n\n.timeline__wrap {\n overflow: hidden;\n position: relative;\n z-index: 2;\n}\n\n.timeline--horizontal .timeline__wrap {\n overflow: visible;\n}\n\n.timeline__item {\n font-size: 1rem;\n padding: 10px 40px 10px 0;\n position: relative;\n width: 50%;\n z-index: 2;\n}\n\n/* Vertical timeline (not mobile) - side-by-side layout */\n.timeline:not(.timeline--horizontal):not(.timeline--mobile) .timeline__item .timeline__content {\n max-height: 200px;\n display: flex;\n flex-direction: column;\n}\n\n.timeline:not(.timeline--horizontal):not(.timeline--mobile) .timeline__item .timeline__image {\n flex-shrink: 0;\n}\n\n.timeline:not(.timeline--horizontal):not(.timeline--mobile) .timeline__item .timeline__content > div {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n.timeline:not(.timeline--horizontal):not(.timeline--mobile) .timeline__item .timeline__content h3 {\n text-align: center;\n margin: 0 0 6px;\n flex-shrink: 0;\n}\n\n.timeline:not(.timeline--horizontal):not(.timeline--mobile) .timeline__item .timeline__content p {\n margin-bottom: 0;\n overflow: hidden;\n flex: 1;\n min-height: 0;\n}\n\n.timeline:not(.timeline--horizontal):not(.timeline--mobile) .timeline__item .timeline__image {\n width: 100px;\n height: auto;\n max-height: 100px;\n object-fit: cover;\n margin: 0 auto 12px;\n}\n\n.timeline__item::after {\n background-color: var(--timeline-node-bg);\n border: 4px solid var(--timeline-node-color);\n border-radius: 50%;\n content: '';\n height: 20px;\n position: absolute;\n right: -10px;\n transform: translateY(-50%);\n top: 50%;\n width: 20px;\n z-index: 1;\n}\n\n.timeline__item.animated {\n animation-duration: 1s;\n animation-fill-mode: both;\n opacity: 0;\n}\n\n.timeline__item.fadeIn {\n animation-name: fadeIn;\n}\n\n/* Active state for deep linking */\n.timeline__item--active .timeline__content {\n transform: scale(1.05);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n}\n\n.timeline__item--left {\n left: 0;\n}\n\n.timeline__item--right {\n left: 50%;\n padding: 10px 0 10px 40px;\n}\n\n.timeline__item--right::after {\n left: -10px;\n}\n\n.timeline__item--right .timeline__content::before {\n border-bottom: 10px solid transparent;\n border-right: 12px solid #CCC;\n border-left: none;\n border-top: 10px solid transparent;\n left: -12px;\n}\n\n.timeline__item--right .timeline__content::after {\n border-bottom: 9px solid transparent;\n border-right: 11px solid #FFF;\n border-left: none;\n border-top: 9px solid transparent;\n left: -10px;\n}\n\n.timeline__content {\n background-color: #FFF;\n border: 1px solid #CCC;\n border-radius: 10px;\n color: #333;\n display: block;\n padding: 20px;\n position: relative;\n}\n\n/* Image styling - fluid to fit content box */\n.timeline__image {\n width: 100%;\n height: auto;\n max-width: 100%;\n border-radius: 8px;\n margin-bottom: 12px;\n display: block;\n}\n\n/* Horizontal timeline images - square thumbnails */\n.timeline--horizontal .timeline__image {\n width: 100px;\n height: 100px;\n object-fit: cover;\n margin: 0 auto 8px;\n}\n\n.timeline__content::before,\n.timeline__content::after {\n content: '';\n height: 0;\n position: absolute;\n transform: translateY(-50%);\n top: 50%;\n width: 0;\n}\n\n.timeline__content::before {\n border-bottom: 10px solid transparent;\n border-left: 12px solid #CCC;\n border-top: 10px solid transparent;\n right: -12px;\n z-index: 1;\n}\n\n.timeline__content::after {\n border-bottom: 9px solid transparent;\n border-left: 11px solid #FFF;\n border-top: 9px solid transparent;\n right: -10px;\n z-index: 2;\n}\n\n.timeline__content h2 {\n font-size: 20px;\n font-weight: 700;\n margin: 0 0 10px;\n}\n\n.timeline__content h3 {\n font-size: 18px;\n font-weight: 700;\n margin: 0 0 10px;\n}\n\n.timeline__content p {\n font-size: 15px;\n line-height: 1.5;\n margin-bottom: 10px;\n}\n\n.timeline--horizontal {\n font-size: 0;\n padding: 0 60px;\n overflow-x: hidden;\n overflow-y: visible;\n white-space: nowrap;\n}\n\n.timeline--horizontal .timeline-divider {\n background-color: var(--timeline-line-color);\n display: block;\n height: 4px;\n left: 40px;\n position: absolute;\n transform: translateY(-50%);\n right: 40px;\n z-index: 1;\n}\n\n.timeline--horizontal .timeline__items {\n transition: all 0.8s;\n will-change: transform;\n}\n\n.timeline--horizontal .timeline__item {\n display: inline-block;\n left: 0;\n padding: 0 0 40px;\n position: relative;\n transition: none;\n vertical-align: top;\n white-space: normal;\n width: 200px;\n}\n\n.timeline--horizontal .timeline__item .timeline__content {\n padding: 12px;\n min-height: 180px;\n}\n\n.timeline--horizontal .timeline__item .timeline__content h3 {\n font-size: 18px;\n font-weight: 700;\n margin: 0 0 8px;\n}\n\n.timeline--horizontal .timeline__item .timeline__content p {\n font-size: 11px;\n line-height: 1.4;\n margin-bottom: 0;\n}\n\n.timeline--horizontal .timeline__item::after {\n left: 50%;\n right: auto;\n transform: translate(-50%, -50%);\n top: 100%;\n}\n\n.timeline--horizontal .timeline__item .timeline__item__inner {\n display: table;\n height: 100%;\n width: 100%;\n}\n\n.timeline--horizontal .timeline__item .timeline__content__wrap {\n display: table-cell;\n margin: 0;\n padding: 0;\n vertical-align: bottom;\n}\n\n.timeline--horizontal .timeline__item .timeline__content::before {\n border-left: 12px solid transparent;\n border-right: 12px solid transparent;\n border-top: 12px solid #CCC;\n left: 50%;\n right: auto;\n transform: translateX(-50%);\n top: 100%;\n}\n\n.timeline--horizontal .timeline__item .timeline__content::after {\n border-left: 10px solid transparent;\n border-right: 10px solid transparent;\n border-top: 10px solid #FFF;\n left: 50%;\n right: auto;\n transform: translateX(-50%);\n top: 100%;\n}\n\n.timeline--horizontal .timeline__item--bottom {\n padding: 40px 0 0;\n}\n\n.timeline--horizontal .timeline__item--bottom::after {\n top: 0;\n}\n\n.timeline--horizontal .timeline__item--bottom .timeline__content__wrap {\n vertical-align: top;\n}\n\n.timeline--horizontal .timeline__item--bottom .timeline__content::before {\n border-bottom: 12px solid #CCC;\n border-left: 12px solid transparent;\n border-right: 12px solid transparent;\n border-top: none;\n bottom: 100%;\n top: auto;\n}\n\n.timeline--horizontal .timeline__item--bottom .timeline__content::after {\n border-bottom: 10px solid #FFF;\n border-left: 10px solid transparent;\n border-right: 10px solid transparent;\n border-top: none;\n bottom: 100%;\n top: auto;\n}\n\n.timeline-nav-button {\n background-color: var(--timeline-nav-color);\n border: 3px solid var(--timeline-nav-border);\n border-radius: 50px;\n box-sizing: border-box;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n cursor: pointer;\n display: block;\n height: 40px;\n outline: none;\n position: absolute;\n text-indent: -9999px;\n transform: translateY(-50%);\n top: 50%;\n width: 40px;\n z-index: 10;\n transition: all 0.3s ease;\n}\n\n.timeline-nav-button:hover {\n transform: translateY(-50%) scale(1.15);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);\n}\n\n.timeline-nav-button:disabled {\n opacity: .5;\n pointer-events: none;\n cursor: not-allowed;\n user-select: none;\n}\n\n.timeline-nav-button::before {\n display: none;\n}\n\n.timeline-nav-button svg {\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n}\n\n.timeline-nav-button--prev {\n left: 10px;\n}\n\n.timeline-nav-button--next {\n right: 10px;\n}\n\n.timeline--mobile {\n padding: 0;\n}\n\n.timeline--mobile::before {\n left: 10px !important;\n margin: 0 !important;\n}\n\n.timeline--mobile .timeline__item {\n left: 0;\n padding-left: 40px;\n padding-right: 0;\n width: 100%;\n margin-bottom: 20px;\n}\n\n.timeline--mobile .timeline__item .timeline__content {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n gap: 6px;\n padding: 12px;\n max-height: 100px;\n}\n\n.timeline--mobile .timeline__item .timeline__image {\n width: 80px;\n height: 80px;\n object-fit: cover;\n flex-shrink: 0;\n margin: 0;\n border-radius: 6px;\n}\n\n.timeline--mobile .timeline__item .timeline__content > div {\n flex: 1;\n min-width: 0;\n}\n\n.timeline--mobile .timeline__item .timeline__content h3 {\n font-size: 16px;\n margin: 0 0 6px;\n}\n\n.timeline--mobile .timeline__item .timeline__content p {\n font-size: 13px;\n line-height: 1.4;\n margin: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.timeline--mobile .timeline__item::after {\n left: 2px;\n margin: 0;\n}\n\n.timeline--mobile .timeline__item .timeline__content::before {\n left: -12px;\n border-bottom: 12px solid transparent;\n border-right: 12px solid #CCC;\n border-left: none;\n border-top: 12px solid transparent;\n}\n\n.timeline--mobile .timeline__item .timeline__content::after {\n left: -10px;\n border-bottom: 10px solid transparent;\n border-right: 10px solid #FFF;\n border-left: none;\n border-top: 10px solid transparent;\n}\n\n@keyframes fadeIn {\n 0% {\n opacity: 0;\n top: 70px;\n }\n 100% {\n opacity: 1;\n top: 0px;\n }\n}\n\n@keyframes liftUp {\n 0% {\n top: 0px;\n }\n 100% {\n top: -15px;\n }\n}\n\n/* Modal Styles */\n.timeline-modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.85);\n z-index: 9998;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.3s ease, visibility 0.3s ease;\n}\n\n.timeline-modal-overlay.timeline-modal-show {\n opacity: 1;\n visibility: visible;\n}\n\n.timeline-modal {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%) scale(0.7);\n width: 90%;\n max-width: 900px;\n max-height: 90vh;\n background-color: #FFF;\n border-radius: 12px;\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);\n z-index: 9999;\n opacity: 0;\n visibility: hidden;\n overflow: hidden;\n transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s ease;\n}\n\n.timeline-modal.timeline-modal-show {\n opacity: 1;\n visibility: visible;\n transform: translate(-50%, -50%) scale(1);\n}\n\n.timeline-modal__content {\n padding: 40px 40px 80px 40px;\n max-height: 90vh;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n/* Fix scrollbar overflow on rounded corners */\n.timeline-modal__content::-webkit-scrollbar {\n width: 8px;\n}\n\n.timeline-modal__content::-webkit-scrollbar-track {\n background: #f1f1f1;\n border-radius: 0 12px 12px 0;\n}\n\n.timeline-modal__content::-webkit-scrollbar-thumb {\n background: #888;\n border-radius: 4px;\n}\n\n.timeline-modal__content::-webkit-scrollbar-thumb:hover {\n background: #555;\n}\n\n.timeline-modal__image {\n width: auto;\n max-width: 100%;\n height: auto;\n border-radius: 8px;\n margin: 0 auto 20px;\n display: block;\n}\n\n.timeline-modal__title {\n font-size: 28px;\n font-weight: 700;\n margin: 0 0 20px;\n color: #333;\n}\n\n.timeline-modal__text {\n font-size: 16px;\n line-height: 1.6;\n color: #555;\n}\n\n.timeline-modal__text p {\n margin-bottom: 15px;\n}\n\n.timeline-modal__divider {\n border: 0;\n border-top: 1px solid #ddd;\n margin: 30px 0;\n}\n\n.timeline-modal__close-bottom {\n display: block;\n margin: 30px auto 0;\n padding: 12px 40px;\n background-color: #333;\n color: #fff;\n border: none;\n border-radius: 6px;\n font-size: 16px;\n cursor: pointer;\n transition: background-color 0.2s ease;\n}\n\n.timeline-modal__close-bottom:hover {\n background-color: #555;\n}\n\n.timeline-modal__close {\n position: absolute;\n top: 20px;\n right: 20px;\n width: 40px;\n height: 40px;\n background-color: rgba(0, 0, 0, 0.6);\n border: none;\n border-radius: 50%;\n color: #FFF;\n font-size: 24px;\n line-height: 1;\n cursor: pointer;\n transition: background-color 0.2s ease, transform 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.timeline-modal__close:hover {\n background-color: rgba(0, 0, 0, 0.8);\n transform: scale(1.1);\n}\n\n.timeline-modal__close::before {\n content: '×';\n}\n\n/* Make timeline items clickable */\n.timeline__item {\n cursor: pointer;\n transition: transform 0.2s ease;\n}\n\n.timeline__item:hover .timeline__content {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n}\n\n/* Loading spinner styles */\n.timeline__loader-overlay {\n position: fixed;\n inset: 0;\n background-color: #ffffff;\n z-index: 10000;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.timeline__loader {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n}\n\n.timeline__loader-spinner {\n width: 120px;\n max-width: 100%;\n height: auto;\n display: block;\n object-fit: contain;\n}\n\n/* Error display styles */\n.timeline__error {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 300px;\n padding: 60px 20px;\n text-align: center;\n background-color: #f9f9f9;\n border: 2px solid #e0e0e0;\n border-radius: 12px;\n margin: 20px auto;\n max-width: 600px;\n}\n\n.timeline__error-icon {\n width: 200px;\n max-width: 100%;\n height: auto;\n margin-bottom: 24px;\n opacity: 0.8;\n}\n\n.timeline__error-title {\n font-size: 24px;\n font-weight: 700;\n margin: 0 0 16px;\n color: #d32f2f;\n}\n\n.timeline__error-message {\n font-size: 16px;\n line-height: 1.6;\n margin: 0 0 16px;\n color: #555;\n}\n\n.timeline__error-solution {\n font-size: 15px;\n line-height: 1.6;\n margin: 0 0 12px;\n color: #333;\n background-color: #fff3cd;\n border: 1px solid #ffc107;\n border-radius: 6px;\n padding: 12px 16px;\n}\n\n.timeline__error-solution strong {\n color: #856404;\n}\n\n.timeline__error-details {\n font-size: 13px;\n line-height: 1.5;\n margin: 12px 0 0;\n color: #666;\n font-family: 'Courier New', monospace;\n background-color: #f5f5f5;\n border: 1px solid #ddd;\n border-radius: 4px;\n padding: 8px 12px;\n max-width: 100%;\n overflow-x: auto;\n}\n\n.timeline__error-details strong {\n color: #333;\n}\n"]}
@@ -1,2 +1,2 @@
1
- var Timeline=function(e){"use strict";const t={count:0,startTime:0,removeTimer:null,overlayEl:null},i={modal:null,overlay:null},n={};function o(){if(i.modal)return;i.overlay=document.createElement("div"),i.overlay.className="timeline-modal-overlay",i.overlay.addEventListener("click",a),i.modal=document.createElement("div"),i.modal.className="timeline-modal",i.modal.innerHTML='\n <button class="timeline-modal__close" aria-label="Close modal"></button>\n <div class="timeline-modal__content">\n <img class="timeline-modal__image" src="" alt="" style="display: none;">\n <h2 class="timeline-modal__title"></h2>\n <div class="timeline-modal__text"></div>\n <hr class="timeline-modal__divider">\n <button class="timeline-modal__close-bottom">Close</button>\n </div>\n ';const e=i.modal.querySelector(".timeline-modal__close"),t=i.modal.querySelector(".timeline-modal__close-bottom");e.addEventListener("click",a),t.addEventListener("click",a),i.modal.addEventListener("click",function(e){e.stopPropagation()}),document.body.appendChild(i.overlay),document.body.appendChild(i.modal),document.addEventListener("keydown",function(e){"Escape"===e.key&&i.modal.classList.contains("timeline-modal-show")&&a()})}function l(e){i.modal||o();const t=e.getAttribute("data-modal-title"),n=e.getAttribute("data-modal-content"),l=e.getAttribute("data-modal-image"),a=e.getAttribute("data-modal-html"),r=i.modal.querySelector(".timeline-modal__title"),s=i.modal.querySelector(".timeline-modal__text"),d=i.modal.querySelector(".timeline-modal__image");r.textContent=t||"",l?(d.src=l,d.alt=t||"",d.style.display="block"):d.style.display="none",s.innerHTML=a||(n?"<p>"+n.replace(/\n/g,"</p><p>")+"</p>":""),setTimeout(function(){i.modal.classList.add("timeline-modal-show"),i.overlay.classList.add("timeline-modal-show"),document.body.style.overflow="hidden"},10)}function a(){i.modal&&(i.modal.classList.remove("timeline-modal-show"),i.overlay.classList.remove("timeline-modal-show"),document.body.style.overflow="")}function r(e){const t=new URLSearchParams(window.location.search),i=t.get("timeline"),n=t.get("id");if(!n)return;let o;if(o=i?document.getElementById(i):document.querySelector(e),!o)return void console.warn("Timeline not found for deep linking:",i||e);o.scrollIntoView({behavior:"smooth",block:"start"});const l=o.querySelector('[data-node-id="'+n+'"]');l&&setTimeout(function(){l.classList.add("timeline__item--active");const e=Array.from(l.parentNode.children).indexOf(l);s(o,e)},500)}function s(e,t){if(!e)return;const i=e.id||e.getAttribute("data-timeline-id");if(!i)return void console.warn("Cannot navigate: timeline container has no ID");const o=n[i];o?e.classList.contains("timeline--horizontal")&&o.setCurrentIndex&&o.updatePosition&&(o.setCurrentIndex(t),o.updatePosition()):console.warn("Timeline not found in registry:",i)}const d=function(){if("undefined"!=typeof window&&window.TimelineConfig&&window.TimelineConfig.basePath)return window.TimelineConfig.basePath;const e=document.getElementsByTagName("script");for(let t=0;t<e.length;t++){const i=e[t].src||"";if(!i)continue;const n=i.substring(0,i.lastIndexOf("/"));if(-1!==i.indexOf("timeline.min.js"))return n.replace("/dist","/src/images");if(-1!==i.indexOf("timeline.js"))return n.replace("/js","/images")}return"../src/images"}();function m(){if(t.count+=1,1!==t.count)return;t.startTime=Date.now(),t.removeTimer&&(clearTimeout(t.removeTimer),t.removeTimer=null);const e=document.createElement("div");e.className="timeline__loader-overlay";const i=document.createElement("div");i.className="timeline__loader";const n=document.createElement("img");n.src=d+"/spinner.gif",n.alt="Loading...",n.title="Loading...",n.className="timeline__loader-spinner",i.appendChild(n),e.appendChild(i),document.body.appendChild(e),t.overlayEl=e}function c(){if(t.count<=0)return;if(t.count-=1,t.count>0)return;const e=Date.now()-t.startTime,i=Math.max(0,1300-e),n=function(){t.overlayEl&&(t.overlayEl.remove(),t.overlayEl=null),t.removeTimer=null};t.removeTimer&&(clearTimeout(t.removeTimer),t.removeTimer=null),i>0?t.removeTimer=setTimeout(n,i):n()}function u(e,t,i){if(!e)return;const n={"json-load":{title:"Timeline Data Could Not Be Loaded",message:"The timeline data failed to load. This could be due to a network error or an incorrect file path.",solution:"Please check that the data-json-config path is correct and the file is accessible."},"json-parse":{title:"Invalid Timeline Data",message:"The timeline data file exists but contains invalid JSON.",solution:"Please validate your JSON using a tool like jsonlint.com and ensure it follows the correct schema."},"missing-element":{title:"Timeline Element Not Found",message:"The required timeline container element could not be found on the page.",solution:'Ensure your HTML includes a container with the class "timeline" and the correct selector.'},"invalid-config":{title:"Invalid Configuration",message:"One or more timeline configuration options are invalid.",solution:"Check your data attributes or JavaScript options and ensure they match the expected format."}}[t]||{title:"Timeline Error",message:"An unexpected error occurred while initializing the timeline.",solution:"Please check the browser console for more details."};c(),e.innerHTML="";const o=document.createElement("div");o.className="timeline__error";const l=document.createElement("img");l.src=d+"/alert.svg",l.alt="Error",l.className="timeline__error-icon";const a=document.createElement("h2");a.className="timeline__error-title",a.textContent=n.title;const r=document.createElement("p");r.className="timeline__error-message",r.textContent=n.message;const s=document.createElement("p");if(s.className="timeline__error-solution",s.innerHTML="<strong>Solution:</strong> "+n.solution,i){const e=document.createElement("p");e.className="timeline__error-details",e.innerHTML="<strong>Details:</strong> "+i,o.appendChild(e)}o.appendChild(l),o.appendChild(a),o.appendChild(r),o.appendChild(s),e.appendChild(o),console.error("Timeline Error ["+t+"]:",n.message,i||"")}function h(e){let t;if(!e||"string"!=typeof e)return 128;if(e.startsWith("#")){let i=e.substring(1);3===i.length&&(i=i[0]+i[0]+i[1]+i[1]+i[2]+i[2]);t=[parseInt(i.substring(0,2),16),parseInt(i.substring(2,4),16),parseInt(i.substring(4,6),16)]}else{if(!e.startsWith("rgb"))return 128;{const i=e.match(/\d+/g);t=i?i.map(Number):[128,128,128]}}return(299*t[0]+587*t[1]+114*t[2])/1e3}function f(e,t){let i=t.nodeColor||null,n=t.lineColor||null;const o=t.navColor||null;if(i&&!n&&(n=i),n&&!i&&(i=n),i&&e.style.setProperty("--timeline-node-color",i),n&&e.style.setProperty("--timeline-line-color",n),o){e.style.setProperty("--timeline-nav-color",o),e.style.setProperty("--timeline-nav-border",h(o)>128?"rgba(0, 0, 0, 0.2)":"rgba(255, 255, 255, 0.3)");const t=h(o)>128?"#333":"#fff";e.style.setProperty("--timeline-arrow-color",t),e.setAttribute("data-arrow-color",t)}}function g(e,t){return"left"===e?'<svg xmlns="http://www.w3.org/2000/svg" width="7.8" height="14" style="display:block;margin:auto;"><path fill="none" stroke="'+t+'" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M6.8 1L1 7l5.8 6"/></svg>':'<svg xmlns="http://www.w3.org/2000/svg" width="7.8" height="14" style="display:block;margin:auto;"><path fill="none" stroke="'+t+'" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M1 1l5.8 6L1 13"/></svg>'}function v(e,t){const i=[],o="Timeline:";let a,r=window.innerWidth,s=0;m();let d=!0;const h={minWidth:{type:"integer",defaultValue:600},horizontalStartPosition:{type:"string",acceptedValues:["bottom","top"],defaultValue:"top"},mode:{type:"string",acceptedValues:["horizontal","vertical"],defaultValue:"vertical"},moveItems:{type:"integer",defaultValue:1},rtlMode:{type:"boolean",acceptedValues:[!0,!1],defaultValue:!1},startIndex:{type:"integer",defaultValue:0},verticalStartPosition:{type:"string",acceptedValues:["left","right"],defaultValue:"left"},verticalTrigger:{type:"string",defaultValue:"15%"},visibleItems:{type:"integer",defaultValue:3}};function v(e,t,i){t.classList.add(i),e.parentNode.insertBefore(t,e),t.appendChild(e)}function p(e,t){const i=e.getBoundingClientRect(),n=window.innerHeight||document.documentElement.clientHeight,o=h.verticalTrigger.defaultValue.match(/(\d*\.?\d*)(.*)/);let l=t.unit,a=t.value,r=n;return"px"===l&&a>=n&&(console.warn('The value entered for the setting "verticalTrigger" is larger than the window height. The default value will be used instead.'),[,a,l]=o),"px"===l?r=parseInt(r-a,10):"%"===l&&(r=parseInt(r*((100-a)/100),10)),i.top<=r&&i.left<=(window.innerWidth||document.documentElement.clientWidth)&&i.top+i.height>=0&&i.left+i.width>=0}function b(e,t){e.style.webkitTransform=t,e.style.msTransform=t,e.style.transform=t}function w(e){const t=`translate3d(-${e.items[s].offsetLeft}px, 0, 0)`;b(e.scroller,t)}function y(e){s=e.settings.rtlMode?e.items.length>e.settings.visibleItems?e.items.length-e.settings.visibleItems:0:e.settings.startIndex,e.timelineEl.classList.add("timeline--horizontal"),function(e){window.innerWidth>e.settings.minWidth&&(e.itemWidth=200,e.items.forEach(t=>{t.style.width=`${e.itemWidth}px`}),e.scrollerWidth=e.itemWidth*e.items.length,e.scroller.style.width=`${e.scrollerWidth}px`,function(){let t=0,i=0;e.items.forEach((e,n)=>{e.style.height="auto";const o=e.offsetHeight;n%2==0?i=o>i?o:i:t=o>t?o:t});const n=`translateY(${i}px)`;e.items.forEach((o,l)=>{l%2==0?(o.style.height=`${i}px`,"bottom"===e.settings.horizontalStartPosition?(o.classList.add("timeline__item--bottom"),b(o,n)):o.classList.add("timeline__item--top")):(o.style.height=`${t}px`,"bottom"!==e.settings.horizontalStartPosition?(o.classList.add("timeline__item--bottom"),b(o,n)):o.classList.add("timeline__item--top"))}),e.scroller.style.height=`${i+t}px`}())}(e),w(e),function(e){const t=e.wrap.offsetWidth,i=Math.floor(t/e.itemWidth);if(e.items.length>i){const t=document.createElement("button"),n=document.createElement("button"),o=e.items[0].offsetHeight;t.className="timeline-nav-button timeline-nav-button--prev",n.className="timeline-nav-button timeline-nav-button--next",t.textContent="Previous",n.textContent="Next",t.style.top=`${o}px`,n.style.top=`${o}px`;const l=e.timelineEl.getAttribute("data-arrow-color")||"#333";t.innerHTML=g("left",l),n.innerHTML=g("right",l);const a=Math.max(0,e.items.length-i);0===s?t.disabled=!0:s>=a&&(n.disabled=!0),e.timelineEl.appendChild(t),e.timelineEl.appendChild(n)}}(e),function(e){const t=e.timelineEl.querySelector(".timeline-divider");t&&e.timelineEl.removeChild(t);const i=e.items[0].offsetHeight,n=document.createElement("span");n.className="timeline-divider",n.style.top=`${i}px`,e.timelineEl.appendChild(n)}(e),function(e){const t=e.timelineEl.querySelectorAll(".timeline-nav-button"),i=e.timelineEl.querySelector(".timeline-nav-button--prev"),n=e.timelineEl.querySelector(".timeline-nav-button--next"),o=e.wrap.offsetWidth,l=Math.floor(o/e.itemWidth),a=Math.max(0,e.items.length-l),r=parseInt(e.settings.moveItems,10),d=function(t){t.preventDefault(),t.stopPropagation(),this.disabled||(s=this.classList.contains("timeline-nav-button--next")?s+=r:s-=r,0===s||s<0?(s=0,i.disabled=!0,n.disabled=!1):s===a||s>a?(s=a,i.disabled=!1,n.disabled=!0):(i.disabled=!1,n.disabled=!1),w(e))};Array.from(t).forEach(t=>{t.addEventListener("click",d),e.listeners.push({element:t,type:"click",handler:d})})}(e);const t=e.timelineEl.id||e.timelineEl.getAttribute("data-timeline-id");t&&(n[t]={setCurrentIndex:function(t){const i=e.wrap.offsetWidth,n=Math.floor(i/e.itemWidth),o=Math.max(0,e.items.length-n);s=Math.max(0,Math.min(t,o))},updatePosition:function(){w(e);const t=e.timelineEl.querySelector(".timeline-nav-button--prev"),i=e.timelineEl.querySelector(".timeline-nav-button--next");if(t&&i){const n=e.wrap.offsetWidth,o=Math.floor(n/e.itemWidth),l=Math.max(0,e.items.length-o);t.disabled=0===s,i.disabled=s>=l}}})}function E(){i.forEach(e=>{e.timelineEl.style.opacity=0,e.timelineEl.classList.contains("timeline--loaded")||e.items.forEach(e=>{v(e.querySelector(".timeline__content"),document.createElement("div"),"timeline__content__wrap"),v(e.querySelector(".timeline__content__wrap"),document.createElement("div"),"timeline__item__inner")}),function(e){e.listeners&&e.listeners.length>0&&(e.listeners.forEach(({element:e,type:t,handler:i})=>{e.removeEventListener(t,i)}),e.listeners=[]),e.observer&&(e.observer.disconnect(),e.observer=null),e.timelineEl.classList.remove("timeline--horizontal","timeline--mobile"),e.scroller.removeAttribute("style"),e.items.forEach(e=>{e.removeAttribute("style"),e.classList.remove("animated","fadeIn","timeline__item--left","timeline__item--right")});const t=e.timelineEl.querySelectorAll(".timeline-nav-button");Array.from(t).forEach(e=>{e.parentNode.removeChild(e)})}(e),window.innerWidth<=e.settings.minWidth&&e.timelineEl.classList.add("timeline--mobile"),"horizontal"===e.settings.mode&&window.innerWidth>e.settings.minWidth?y(e):function(e){let t=0;e.items.forEach((i,n)=>{i.classList.remove("animated","fadeIn"),!p(i,e.settings.verticalTrigger)&&n>0?i.classList.add("animated"):t=n,n%2==("left"===e.settings.verticalStartPosition?1:0)&&window.innerWidth>e.settings.minWidth?i.classList.add("timeline__item--right"):i.classList.add("timeline__item--left")});for(let i=0;i<t;i+=1)e.items[i].classList.remove("animated","fadeIn");if("IntersectionObserver"in window){const t={rootMargin:"%"===e.settings.verticalTrigger.unit?`${e.settings.verticalTrigger.value}%`:`${e.settings.verticalTrigger.value}px`,threshold:.01},i=new IntersectionObserver(e=>{e.forEach(e=>{e.isIntersecting&&e.target.classList.add("fadeIn")})},t);e.items.forEach(e=>{e.classList.contains("animated")&&i.observe(e)}),e.observer=i}else{const t=()=>{e.items.forEach(t=>{p(t,e.settings.verticalTrigger)&&t.classList.add("fadeIn")})};window.addEventListener("scroll",t),e.listeners.push({element:window,type:"scroll",handler:t})}}(e),e.timelineEl.classList.add("timeline--loaded")}),setTimeout(()=>{i.forEach(e=>{e.timelineEl.style.opacity=1})},500),d&&(c(),d=!1)}e.length&&Array.from(e).forEach(function(e){const n=e.id?`#${e.id}`:`.${e.className}`,a="could not be found as a direct descendant of",r=e.dataset;let s,d,m;const c={};try{if(s=e.querySelector(".timeline__wrap"),!s)throw new Error(`${o} .timeline__wrap ${a} ${n}`);if(d=s.querySelector(".timeline__items"),!d)throw new Error(`${o} .timeline__items ${a} .timeline__wrap`);m=[].slice.call(d.children,0)}catch(t){return console.warn(t.message),u(e,"missing-element",t.message),!1}Object.keys(h).forEach(e=>{if(c[e]=h[e].defaultValue,"minWidth"===e){let e;void 0!==r.minWidth&&(e=r.minWidth),void 0!==r.minwidth&&(e=r.minwidth),void 0!==r.forceVerticalMode&&(e=r.forceVerticalMode),void 0!==r.forceverticalmode&&(e=r.forceverticalmode),void 0===e&&t&&(void 0!==t.minWidth?e=t.minWidth:void 0!==t.forceVerticalMode&&(e=t.forceVerticalMode)),void 0!==e&&(c.minWidth=e)}else r[e]?c[e]=r[e]:t&&void 0!==t[e]&&(c[e]=t[e]);var i,n;"integer"===h[e].type?c[e]&&(n=e,"number"==typeof(i=c[e])||i%1==0||(console.warn(`${o} The value "${i}" entered for the setting "${n}" is not an integer.`),0))||(c[e]=h[e].defaultValue):"string"===h[e].type&&h[e].acceptedValues&&-1===h[e].acceptedValues.indexOf(c[e])&&(console.warn(`${o} The value "${c[e]}" entered for the setting "${e}" was not recognised.`),c[e]=h[e].defaultValue)}),function(){const i=e.dataset,n=function(e){return void 0!==i[e]?i[e]:void 0!==i[e&&e.toLowerCase()]?i[e.toLowerCase()]:void 0};let o=n("nodeColor"),l=n("lineColor"),a=n("navColor");t&&(void 0!==t.nodeColor&&(o=t.nodeColor),void 0!==t.lineColor&&(l=t.lineColor),void 0!==t.navColor&&(a=t.navColor)),(o||l||a)&&f(e,{nodeColor:o,lineColor:l,navColor:a})}();const g=h.verticalTrigger.defaultValue.match(/(\d*\.?\d*)(.*)/),v=c.verticalTrigger.match(/(\d*\.?\d*)(.*)/);let[,p,b]=v,w=!0;p||(console.warn(`${o} No numercial value entered for the 'verticalTrigger' setting.`),w=!1),"px"!==b&&"%"!==b&&(console.warn(`${o} The setting 'verticalTrigger' must be a percentage or pixel value.`),w=!1),"%"===b&&(p>100||p<0)?(console.warn(`${o} The 'verticalTrigger' setting value must be between 0 and 100 if using a percentage value.`),w=!1):"px"===b&&p<0&&(console.warn(`${o} The 'verticalTrigger' setting value must be above 0 if using a pixel value.`),w=!1),!1===w&&([,p,b]=g),c.verticalTrigger={unit:b,value:p},c.moveItems>c.visibleItems&&(console.warn(`${o} The value of "moveItems" (${c.moveItems}) is larger than the number of "visibleItems" (${c.visibleItems}). The value of "visibleItems" has been used instead.`),c.moveItems=c.visibleItems),c.startIndex>m.length-c.visibleItems&&m.length>c.visibleItems?(console.warn(`${o} The 'startIndex' setting must be between 0 and ${m.length-c.visibleItems} for this timeline. The value of ${m.length-c.visibleItems} has been used instead.`),c.startIndex=m.length-c.visibleItems):m.length<=c.visibleItems?(console.warn(`${o} The number of items in the timeline must exceed the number of visible items to use the 'startIndex' option.`),c.startIndex=0):c.startIndex<0&&(console.warn(`${o} The 'startIndex' setting must be between 0 and ${m.length-c.visibleItems} for this timeline. The value of 0 has been used instead.`),c.startIndex=0),function(e,t){t&&t.length&&t.forEach(function(e){"1"!==e.getAttribute("data-modal-bound")&&(function(e){if(!e)return;const t=e.querySelector(".timeline__content")||e;if(!e.hasAttribute("data-modal-title")){const i=t.querySelector("h1,h2,h3,h4,h5,h6");i&&i.textContent&&e.setAttribute("data-modal-title",i.textContent.trim())}if(!e.hasAttribute("data-modal-content")){const i=t.querySelector("p");i&&i.textContent&&e.setAttribute("data-modal-content",i.textContent.trim())}if(!e.hasAttribute("data-modal-image")){const i=t.querySelector("img");i&&i.getAttribute("src")&&e.setAttribute("data-modal-image",i.getAttribute("src"))}}(e),(e.hasAttribute("data-modal-title")||e.hasAttribute("data-modal-content")||e.hasAttribute("data-modal-image")||e.hasAttribute("data-modal-html"))&&(e.addEventListener("click",function(t){t.preventDefault(),l(e)}),e.setAttribute("data-modal-bound","1")))})}(0,m),e.id||e.setAttribute("data-timeline-id","timeline-"+Date.now()+"-"+Math.random().toString(36).substr(2,9)),i.push({timelineEl:e,wrap:s,scroller:d,items:m,settings:c,listeners:[]})}),E(),window.addEventListener("resize",()=>{clearTimeout(a),a=setTimeout(()=>{const e=window.innerWidth;e!==r&&(E(),r=e)},250)})}function p(e,t,i){const n=document.querySelector(e);if(!n)return;let o=n.querySelector(".timeline__items");if(o)o.innerHTML="";else{const e=document.createElement("div");e.className="timeline__wrap",o=document.createElement("div"),o.className="timeline__items",e.appendChild(o),n.appendChild(e)}if(i&&(function(e,t){t.layoutMode&&e.setAttribute("data-mode",t.layoutMode),void 0!==t.visibleItems&&e.setAttribute("data-visible-items",t.visibleItems),void 0!==t.minWidth&&(e.setAttribute("data-minwidth",t.minWidth),e.setAttribute("data-force-vertical-mode",t.minWidth)),void 0!==t.maxWidth&&e.setAttribute("data-maxwidth",t.maxWidth)}(n,i),f(n,i),i.timelineName&&""!==i.timelineName.trim())){const e=n.previousElementSibling;if(e&&e.classList.contains("timeline__heading"))e.textContent=i.timelineName;else{const e=document.createElement("h1");e.className="timeline__heading",e.textContent=i.timelineName,n.parentNode.insertBefore(e,n)}n.setAttribute("data-timeline-name",i.timelineName)}return t.forEach(function(e){o.appendChild(function(e){const t=document.createElement("div");t.className="timeline__item",e.id&&t.setAttribute("data-node-id",e.id),t.setAttribute("data-modal-title",e.title||""),t.setAttribute("data-modal-content",e.content||""),t.setAttribute("data-modal-image",e.image||""),e.html&&t.setAttribute("data-modal-html",e.html);const i=document.createElement("div");if(i.className="timeline__content",e.image){const t=document.createElement("img");t.src=e.image,t.className="timeline__image",t.alt=e.title||"",t.onerror=function(){console.error('Timeline: The image "'+e.image+'" could not be loaded. Please check the path.'),this.src=d+"/missing-image.svg",this.alt="Image not found",this.title="Original image: "+e.image},i.appendChild(t)}const n=document.createElement("div");if(e.title){const t=document.createElement("h3");t.textContent=e.title,n.appendChild(t)}if(e.content){const t=document.createElement("p");let i=e.content;i.length>105&&(i=i.substring(0,105)+"..."),t.innerHTML=i,n.appendChild(t)}if(e.html){const t=document.createElement("div");t.innerHTML=e.html,n.appendChild(t)}return i.appendChild(n),t.appendChild(i),t.addEventListener("click",function(e){e.preventDefault(),"function"==typeof window.openTimelineModal&&window.openTimelineModal(t)}),t.setAttribute("data-modal-bound","1"),t}(e))}),n}function b(e,t,i){const n=p(e,t,i);n&&v([n],i)}function w(e,t){const i=document.querySelector(t);if(!i)return void console.error("Timeline: Container not found:",t);m();const n=i?i.id:null,o=n?"vjs_"+n:null;if(o&&"undefined"!=typeof Storage)try{const i=localStorage.getItem(o);if(i){const l=JSON.parse(i);return void fetch(e).then(function(t){if(!t.ok)throw new Error("Failed to load "+e+" ("+t.status+")");return t.json()}).then(function(e){e.lastupdated&&l.lastupdated&&e.lastupdated===l.lastupdated?(console.log("Using cached timeline data for",n),y(l,t)):(console.log("Updating cached timeline data for",n),localStorage.setItem(o,JSON.stringify(e)),y(e,t))}).catch(function(e){console.warn("Failed to fetch fresh data, using cache:",e),y(l,t)})}}catch(e){console.warn("Error reading from localStorage:",e)}fetch(e).then(function(t){if(!t.ok)throw new Error("Failed to load "+e+" ("+t.status+")");return t.json()}).then(function(e){if(o&&"undefined"!=typeof Storage)try{localStorage.setItem(o,JSON.stringify(e)),console.log("Cached timeline data for",n)}catch(e){console.warn("Failed to cache timeline data:",e)}y(e,t)}).catch(function(e){console.error("Error loading timeline JSON:",e),u(i,"json-load",e.message)})}function y(e,t){const i=document.querySelector(t);if(!i)return void console.error("Timeline: Container not found:",t);let n=null,o=[];try{if(e.nodes&&Array.isArray(e.nodes))o=e.nodes,n={timelineName:e.timelineName,layoutMode:e.layoutMode,visibleItems:e.visibleItems,minWidth:e.minWidth,maxWidth:e.maxWidth,nodeColor:e.nodeColor,lineColor:e.lineColor,navColor:e.navColor,lastupdated:e.lastupdated};else{if(!Array.isArray(e))throw new Error('Invalid JSON format. Expected object with "nodes" array or simple array.');o=e}if(0===o.length)throw new Error("No timeline items found in data.");p(t,o,n);try{v(document.querySelectorAll(t)),r(t),c()}catch(e){console.error("Error initializing timeline:",e);const i=document.querySelector(t);i&&u(i,"invalid-config",e.message),c()}}catch(e){console.error("Error processing timeline data:",e),u(i,"json-parse",e.message),c()}}function E(e){if("undefined"!=typeof Storage)if(e){const t="vjs_"+e;localStorage.removeItem(t),console.log("Cleared cache for timeline:",e)}else{const e=Object.keys(localStorage);let t=0;e.forEach(function(e){e.startsWith("vjs_")&&(localStorage.removeItem(e),t++)}),console.log("Cleared",t,"timeline cache(s)")}else console.warn("localStorage not supported")}return"undefined"!=typeof window&&(window.timeline=v,window.timelineFromData=b,window.renderTimelineFromData=p,window.processTimelineData=y,window.loadDataFromJson=w,window.clearTimelineCache=E,window.createTimelineModal=o,window.openTimelineModal=l,window.closeTimelineModal=a,window.handleTimelineDeepLinking=r,window.navigateTimelineToNodeIndex=s),document.addEventListener("DOMContentLoaded",function(){document.querySelectorAll("[data-json-config]").forEach(function(e){const t=e.getAttribute("data-json-config");if(!t)return;const i=(e.className||"").split(" ")[0],n=e.id?"#"+e.id:i?"."+i:null;n&&w(t,n)})}),"undefined"!=typeof window&&window.jQuery&&(window.jQuery.fn.timeline=function(e){return v(this,e),this}),e.clearTimelineCache=E,e.closeTimelineModal=a,e.createTimelineModal=o,e.handleDeepLinking=r,e.loadDataFromJson=w,e.navigateToNodeIndex=s,e.openTimelineModal=l,e.processTimelineData=y,e.renderTimelineFromData=p,e.timeline=v,e.timelineFromData=b,e}({});
1
+ var Timeline=function(e){"use strict";const t={count:0,startTime:0,removeTimer:null,overlayEl:null},i={modal:null,overlay:null},n={};function o(){if(i.modal)return;i.overlay=document.createElement("div"),i.overlay.className="timeline-modal-overlay",i.overlay.addEventListener("click",a),i.modal=document.createElement("div"),i.modal.className="timeline-modal",i.modal.innerHTML='\n <button class="timeline-modal__close" aria-label="Close modal"></button>\n <div class="timeline-modal__content">\n <img class="timeline-modal__image" src="" alt="" style="display: none;">\n <h2 class="timeline-modal__title"></h2>\n <div class="timeline-modal__text"></div>\n <hr class="timeline-modal__divider">\n <button class="timeline-modal__close-bottom">Close</button>\n </div>\n ';const e=i.modal.querySelector(".timeline-modal__close"),t=i.modal.querySelector(".timeline-modal__close-bottom");e.addEventListener("click",a),t.addEventListener("click",a),i.modal.addEventListener("click",function(e){e.stopPropagation()}),document.body.appendChild(i.overlay),document.body.appendChild(i.modal),document.addEventListener("keydown",function(e){"Escape"===e.key&&i.modal.classList.contains("timeline-modal-show")&&a()})}function l(e){i.modal||o();const t=e.getAttribute("data-modal-title"),n=e.getAttribute("data-modal-content"),l=e.getAttribute("data-modal-image"),a=e.getAttribute("data-modal-html"),r=i.modal.querySelector(".timeline-modal__title"),s=i.modal.querySelector(".timeline-modal__text"),d=i.modal.querySelector(".timeline-modal__image");r.textContent=t||"",l?(d.src=l,d.alt=t||"",d.style.display="block"):d.style.display="none",s.innerHTML=a||(n?"<p>"+n.replace(/\n/g,"</p><p>")+"</p>":""),setTimeout(function(){i.modal.classList.add("timeline-modal-show"),i.overlay.classList.add("timeline-modal-show"),document.body.style.overflow="hidden"},10)}function a(){i.modal&&(i.modal.classList.remove("timeline-modal-show"),i.overlay.classList.remove("timeline-modal-show"),document.body.style.overflow="")}function r(e){const t=new URLSearchParams(window.location.search),i=t.get("timeline"),n=t.get("id");if(!n)return;let o;if(o=i?document.getElementById(i):document.querySelector(e),!o)return void console.warn("Timeline not found for deep linking:",i||e);o.scrollIntoView({behavior:"smooth",block:"start"});const l=o.querySelector('[data-node-id="'+n+'"]');l&&setTimeout(function(){l.classList.add("timeline__item--active");const e=Array.from(l.parentNode.children).indexOf(l);s(o,e)},500)}function s(e,t){if(!e)return;const i=e.id||e.getAttribute("data-timeline-id");if(!i)return void console.warn("Cannot navigate: timeline container has no ID");const o=n[i];o?e.classList.contains("timeline--horizontal")&&o.setCurrentIndex&&o.updatePosition&&(o.setCurrentIndex(t),o.updatePosition()):console.warn("Timeline not found in registry:",i)}const d=function(){if("undefined"!=typeof window&&window.TimelineConfig&&window.TimelineConfig.basePath)return window.TimelineConfig.basePath;const e=document.getElementsByTagName("script");for(let t=0;t<e.length;t++){const i=e[t].src||"";if(!i)continue;const n=i.substring(0,i.lastIndexOf("/"));if(-1!==i.indexOf("timeline.min.js"))return n.replace("/dist","/src/images");if(-1!==i.indexOf("timeline.js"))return n.replace("/js","/images")}return"../src/images"}();function m(){if(t.count+=1,1!==t.count)return;t.startTime=Date.now(),t.removeTimer&&(clearTimeout(t.removeTimer),t.removeTimer=null);const e=document.createElement("div");e.className="timeline__loader-overlay";const i=document.createElement("div");i.className="timeline__loader";const n=document.createElement("img");n.src=d+"/spinner.gif",n.alt="Loading...",n.title="Loading...",n.className="timeline__loader-spinner",n.width=120,n.style.height="auto",i.appendChild(n),e.appendChild(i),document.body.appendChild(e),t.overlayEl=e}function c(){if(t.count<=0)return;if(t.count-=1,t.count>0)return;const e=Date.now()-t.startTime,i=Math.max(0,1300-e),n=function(){t.overlayEl&&(t.overlayEl.remove(),t.overlayEl=null),t.removeTimer=null};t.removeTimer&&(clearTimeout(t.removeTimer),t.removeTimer=null),i>0?t.removeTimer=setTimeout(n,i):n()}function u(e,t,i){if(!e)return;const n={"json-load":{title:"Timeline Data Could Not Be Loaded",message:"The timeline data failed to load. This could be due to a network error or an incorrect file path.",solution:"Please check that the data-json-config path is correct and the file is accessible."},"json-parse":{title:"Invalid Timeline Data",message:"The timeline data file exists but contains invalid JSON.",solution:"Please validate your JSON using a tool like jsonlint.com and ensure it follows the correct schema."},"missing-element":{title:"Timeline Element Not Found",message:"The required timeline container element could not be found on the page.",solution:'Ensure your HTML includes a container with the class "timeline" and the correct selector.'},"invalid-config":{title:"Invalid Configuration",message:"One or more timeline configuration options are invalid.",solution:"Check your data attributes or JavaScript options and ensure they match the expected format."}}[t]||{title:"Timeline Error",message:"An unexpected error occurred while initializing the timeline.",solution:"Please check the browser console for more details."};c(),e.innerHTML="";const o=document.createElement("div");o.className="timeline__error";const l=document.createElement("img");l.src=d+"/alert.svg",l.alt="Error",l.className="timeline__error-icon",l.width=200,l.style.height="auto";const a=document.createElement("h2");a.className="timeline__error-title",a.textContent=n.title;const r=document.createElement("p");r.className="timeline__error-message",r.textContent=n.message;const s=document.createElement("p");if(s.className="timeline__error-solution",s.innerHTML="<strong>Solution:</strong> "+n.solution,i){const e=document.createElement("p");e.className="timeline__error-details",e.innerHTML="<strong>Details:</strong> "+i,o.appendChild(e)}o.appendChild(l),o.appendChild(a),o.appendChild(r),o.appendChild(s),e.appendChild(o),console.error("Timeline Error ["+t+"]:",n.message,i||"")}function h(e){let t;if(!e||"string"!=typeof e)return 128;if(e.startsWith("#")){let i=e.substring(1);3===i.length&&(i=i[0]+i[0]+i[1]+i[1]+i[2]+i[2]);t=[parseInt(i.substring(0,2),16),parseInt(i.substring(2,4),16),parseInt(i.substring(4,6),16)]}else{if(!e.startsWith("rgb"))return 128;{const i=e.match(/\d+/g);t=i?i.map(Number):[128,128,128]}}return(299*t[0]+587*t[1]+114*t[2])/1e3}function f(e,t){let i=t.nodeColor||null,n=t.lineColor||null;const o=t.navColor||null;if(i&&!n&&(n=i),n&&!i&&(i=n),i&&e.style.setProperty("--timeline-node-color",i),n&&e.style.setProperty("--timeline-line-color",n),o){e.style.setProperty("--timeline-nav-color",o),e.style.setProperty("--timeline-nav-border",h(o)>128?"rgba(0, 0, 0, 0.2)":"rgba(255, 255, 255, 0.3)");const t=h(o)>128?"#333":"#fff";e.style.setProperty("--timeline-arrow-color",t),e.setAttribute("data-arrow-color",t)}}function g(e,t){return"left"===e?'<svg xmlns="http://www.w3.org/2000/svg" width="7.8" height="14" style="display:block;margin:auto;"><path fill="none" stroke="'+t+'" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M6.8 1L1 7l5.8 6"/></svg>':'<svg xmlns="http://www.w3.org/2000/svg" width="7.8" height="14" style="display:block;margin:auto;"><path fill="none" stroke="'+t+'" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M1 1l5.8 6L1 13"/></svg>'}function v(e,t){const i=[],o="Timeline:";let a,r=window.innerWidth,s=0;m();let d=!0;const h={minWidth:{type:"integer",defaultValue:600},maxWidth:{type:"integer",defaultValue:600},horizontalStartPosition:{type:"string",acceptedValues:["bottom","top"],defaultValue:"top"},mode:{type:"string",acceptedValues:["horizontal","vertical"],defaultValue:"vertical"},moveItems:{type:"integer",defaultValue:1},rtlMode:{type:"boolean",acceptedValues:[!0,!1],defaultValue:!1},startIndex:{type:"integer",defaultValue:0},verticalStartPosition:{type:"string",acceptedValues:["left","right"],defaultValue:"left"},verticalTrigger:{type:"string",defaultValue:"15%"},visibleItems:{type:"integer",defaultValue:3}};function v(e,t,i){t.classList.add(i),e.parentNode.insertBefore(t,e),t.appendChild(e)}function p(e,t){const i=e.getBoundingClientRect(),n=window.innerHeight||document.documentElement.clientHeight,o=h.verticalTrigger.defaultValue.match(/(\d*\.?\d*)(.*)/);let l=t.unit,a=t.value,r=n;return"px"===l&&a>=n&&(console.warn('The value entered for the setting "verticalTrigger" is larger than the window height. The default value will be used instead.'),[,a,l]=o),"px"===l?r=parseInt(r-a,10):"%"===l&&(r=parseInt(r*((100-a)/100),10)),i.top<=r&&i.left<=(window.innerWidth||document.documentElement.clientWidth)&&i.top+i.height>=0&&i.left+i.width>=0}function w(e,t){e.style.webkitTransform=t,e.style.msTransform=t,e.style.transform=t}function b(e){const t=`translate3d(-${e.items[s].offsetLeft}px, 0, 0)`;w(e.scroller,t)}function y(e){s=e.settings.rtlMode?e.items.length>e.settings.visibleItems?e.items.length-e.settings.visibleItems:0:e.settings.startIndex,e.timelineEl.classList.add("timeline--horizontal"),function(e){window.innerWidth>e.settings.minWidth&&(e.itemWidth=200,e.items.forEach(t=>{t.style.width=`${e.itemWidth}px`}),e.scrollerWidth=e.itemWidth*e.items.length,e.scroller.style.width=`${e.scrollerWidth}px`,function(){let t=0,i=0;e.items.forEach((e,n)=>{e.style.height="auto";const o=e.offsetHeight;n%2==0?i=o>i?o:i:t=o>t?o:t});const n=`translateY(${i}px)`;e.items.forEach((o,l)=>{l%2==0?(o.style.height=`${i}px`,"bottom"===e.settings.horizontalStartPosition?(o.classList.add("timeline__item--bottom"),w(o,n)):o.classList.add("timeline__item--top")):(o.style.height=`${t}px`,"bottom"!==e.settings.horizontalStartPosition?(o.classList.add("timeline__item--bottom"),w(o,n)):o.classList.add("timeline__item--top"))}),e.scroller.style.height=`${i+t}px`}())}(e),b(e),function(e){const t=e.wrap.offsetWidth,i=Math.floor(t/e.itemWidth);if(e.items.length>i){const t=document.createElement("button"),n=document.createElement("button"),o=e.items[0].offsetHeight;t.className="timeline-nav-button timeline-nav-button--prev",n.className="timeline-nav-button timeline-nav-button--next",t.textContent="Previous",n.textContent="Next",t.style.top=`${o}px`,n.style.top=`${o}px`;const l=e.timelineEl.getAttribute("data-arrow-color")||"#333";t.innerHTML=g("left",l),n.innerHTML=g("right",l);const a=Math.max(0,e.items.length-i);0===s?t.disabled=!0:s>=a&&(n.disabled=!0),e.timelineEl.appendChild(t),e.timelineEl.appendChild(n)}}(e),function(e){const t=e.timelineEl.querySelector(".timeline-divider");t&&e.timelineEl.removeChild(t);const i=e.items[0].offsetHeight,n=document.createElement("span");n.className="timeline-divider",n.style.top=`${i}px`,e.timelineEl.appendChild(n)}(e),function(e){const t=e.timelineEl.querySelectorAll(".timeline-nav-button"),i=e.timelineEl.querySelector(".timeline-nav-button--prev"),n=e.timelineEl.querySelector(".timeline-nav-button--next"),o=e.wrap.offsetWidth,l=Math.floor(o/e.itemWidth),a=Math.max(0,e.items.length-l),r=parseInt(e.settings.moveItems,10),d=function(t){t.preventDefault(),t.stopPropagation(),this.disabled||(s=this.classList.contains("timeline-nav-button--next")?s+=r:s-=r,0===s||s<0?(s=0,i.disabled=!0,n.disabled=!1):s===a||s>a?(s=a,i.disabled=!1,n.disabled=!0):(i.disabled=!1,n.disabled=!1),b(e))};Array.from(t).forEach(t=>{t.addEventListener("click",d),e.listeners.push({element:t,type:"click",handler:d})})}(e);const t=e.timelineEl.id||e.timelineEl.getAttribute("data-timeline-id");t&&(n[t]={setCurrentIndex:function(t){const i=e.wrap.offsetWidth,n=Math.floor(i/e.itemWidth),o=Math.max(0,e.items.length-n);s=Math.max(0,Math.min(t,o))},updatePosition:function(){b(e);const t=e.timelineEl.querySelector(".timeline-nav-button--prev"),i=e.timelineEl.querySelector(".timeline-nav-button--next");if(t&&i){const n=e.wrap.offsetWidth,o=Math.floor(n/e.itemWidth),l=Math.max(0,e.items.length-o);t.disabled=0===s,i.disabled=s>=l}}})}function E(){i.forEach(e=>{e.timelineEl.style.opacity=0,e.timelineEl.classList.contains("timeline--loaded")||e.items.forEach(e=>{v(e.querySelector(".timeline__content"),document.createElement("div"),"timeline__content__wrap"),v(e.querySelector(".timeline__content__wrap"),document.createElement("div"),"timeline__item__inner")}),function(e){e.listeners&&e.listeners.length>0&&(e.listeners.forEach(({element:e,type:t,handler:i})=>{e.removeEventListener(t,i)}),e.listeners=[]),e.observer&&(e.observer.disconnect(),e.observer=null),e.timelineEl.classList.remove("timeline--horizontal","timeline--mobile"),e.scroller.removeAttribute("style"),e.items.forEach(e=>{e.removeAttribute("style"),e.classList.remove("animated","fadeIn","timeline__item--left","timeline__item--right")});const t=e.timelineEl.querySelectorAll(".timeline-nav-button");Array.from(t).forEach(e=>{e.parentNode.removeChild(e)})}(e),window.innerWidth<=e.settings.minWidth&&e.timelineEl.classList.add("timeline--mobile");let t=!1;("horizontal"===e.settings.mode&&window.innerWidth>e.settings.minWidth||"vertical"===e.settings.mode&&window.innerWidth>e.settings.maxWidth)&&(t=!0),t?y(e):function(e){let t=0;e.items.forEach((i,n)=>{i.classList.remove("animated","fadeIn"),!p(i,e.settings.verticalTrigger)&&n>0?i.classList.add("animated"):t=n,n%2==("left"===e.settings.verticalStartPosition?1:0)&&window.innerWidth>e.settings.minWidth?i.classList.add("timeline__item--right"):i.classList.add("timeline__item--left")});for(let i=0;i<t;i+=1)e.items[i].classList.remove("animated","fadeIn");if("IntersectionObserver"in window){const t={rootMargin:"%"===e.settings.verticalTrigger.unit?`${e.settings.verticalTrigger.value}%`:`${e.settings.verticalTrigger.value}px`,threshold:.01},i=new IntersectionObserver(e=>{e.forEach(e=>{e.isIntersecting&&e.target.classList.add("fadeIn")})},t);e.items.forEach(e=>{e.classList.contains("animated")&&i.observe(e)}),e.observer=i}else{const t=()=>{e.items.forEach(t=>{p(t,e.settings.verticalTrigger)&&t.classList.add("fadeIn")})};window.addEventListener("scroll",t),e.listeners.push({element:window,type:"scroll",handler:t})}}(e),e.timelineEl.classList.add("timeline--loaded")}),setTimeout(()=>{i.forEach(e=>{e.timelineEl.style.opacity=1})},500),d&&(c(),d=!1)}e.length&&Array.from(e).forEach(function(e){const n=e.id?`#${e.id}`:`.${e.className}`,a="could not be found as a direct descendant of",r=e.dataset;let s,d,m;const c={};try{if(s=e.querySelector(".timeline__wrap"),!s)throw new Error(`${o} .timeline__wrap ${a} ${n}`);if(d=s.querySelector(".timeline__items"),!d)throw new Error(`${o} .timeline__items ${a} .timeline__wrap`);m=[].slice.call(d.children,0)}catch(t){return console.warn(t.message),u(e,"missing-element",t.message),!1}Object.keys(h).forEach(e=>{if(c[e]=h[e].defaultValue,"minWidth"===e){let e;void 0!==r.minWidth&&(e=r.minWidth),void 0!==r.minwidth&&(e=r.minwidth),void 0!==r.forceVerticalMode&&(e=r.forceVerticalMode),void 0!==r.forceverticalmode&&(e=r.forceverticalmode),void 0===e&&t&&(void 0!==t.minWidth?e=t.minWidth:void 0!==t.forceVerticalMode&&(e=t.forceVerticalMode)),void 0!==e&&(c.minWidth=e)}else if("maxWidth"===e){let e;void 0!==r.maxWidth&&(e=r.maxWidth),void 0!==r.maxwidth&&(e=r.maxwidth),void 0===e&&t&&void 0!==t.maxWidth&&(e=t.maxWidth),void 0!==e&&(c.maxWidth=e)}else r[e]?c[e]=r[e]:t&&void 0!==t[e]&&(c[e]=t[e]);var i,n;"integer"===h[e].type?c[e]&&(n=e,"number"==typeof(i=c[e])||i%1==0||(console.warn(`${o} The value "${i}" entered for the setting "${n}" is not an integer.`),0))||(c[e]=h[e].defaultValue):"string"===h[e].type&&h[e].acceptedValues&&-1===h[e].acceptedValues.indexOf(c[e])&&(console.warn(`${o} The value "${c[e]}" entered for the setting "${e}" was not recognised.`),c[e]=h[e].defaultValue)}),function(){const i=e.dataset,n=function(e){return void 0!==i[e]?i[e]:void 0!==i[e&&e.toLowerCase()]?i[e.toLowerCase()]:void 0};let o=n("nodeColor"),l=n("lineColor"),a=n("navColor");t&&(void 0!==t.nodeColor&&(o=t.nodeColor),void 0!==t.lineColor&&(l=t.lineColor),void 0!==t.navColor&&(a=t.navColor)),(o||l||a)&&f(e,{nodeColor:o,lineColor:l,navColor:a})}();const g=h.verticalTrigger.defaultValue.match(/(\d*\.?\d*)(.*)/),v=c.verticalTrigger.match(/(\d*\.?\d*)(.*)/);let[,p,w]=v,b=!0;p||(console.warn(`${o} No numercial value entered for the 'verticalTrigger' setting.`),b=!1),"px"!==w&&"%"!==w&&(console.warn(`${o} The setting 'verticalTrigger' must be a percentage or pixel value.`),b=!1),"%"===w&&(p>100||p<0)?(console.warn(`${o} The 'verticalTrigger' setting value must be between 0 and 100 if using a percentage value.`),b=!1):"px"===w&&p<0&&(console.warn(`${o} The 'verticalTrigger' setting value must be above 0 if using a pixel value.`),b=!1),!1===b&&([,p,w]=g),c.verticalTrigger={unit:w,value:p},c.moveItems>c.visibleItems&&(console.warn(`${o} The value of "moveItems" (${c.moveItems}) is larger than the number of "visibleItems" (${c.visibleItems}). The value of "visibleItems" has been used instead.`),c.moveItems=c.visibleItems),c.startIndex>m.length-c.visibleItems&&m.length>c.visibleItems?(console.warn(`${o} The 'startIndex' setting must be between 0 and ${m.length-c.visibleItems} for this timeline. The value of ${m.length-c.visibleItems} has been used instead.`),c.startIndex=m.length-c.visibleItems):m.length<=c.visibleItems?(console.warn(`${o} The number of items in the timeline must exceed the number of visible items to use the 'startIndex' option.`),c.startIndex=0):c.startIndex<0&&(console.warn(`${o} The 'startIndex' setting must be between 0 and ${m.length-c.visibleItems} for this timeline. The value of 0 has been used instead.`),c.startIndex=0),function(e,t){t&&t.length&&t.forEach(function(e){"1"!==e.getAttribute("data-modal-bound")&&(function(e){if(!e)return;const t=e.querySelector(".timeline__content")||e;if(!e.hasAttribute("data-modal-title")){const i=t.querySelector("h1,h2,h3,h4,h5,h6");i&&i.textContent&&e.setAttribute("data-modal-title",i.textContent.trim())}if(!e.hasAttribute("data-modal-content")){const i=t.querySelector("p");i&&i.textContent&&e.setAttribute("data-modal-content",i.textContent.trim())}if(!e.hasAttribute("data-modal-image")){const i=t.querySelector("img");i&&i.getAttribute("src")&&e.setAttribute("data-modal-image",i.getAttribute("src"))}}(e),(e.hasAttribute("data-modal-title")||e.hasAttribute("data-modal-content")||e.hasAttribute("data-modal-image")||e.hasAttribute("data-modal-html"))&&(e.addEventListener("click",function(t){t.preventDefault(),l(e)}),e.setAttribute("data-modal-bound","1")))})}(0,m),e.id||e.setAttribute("data-timeline-id","timeline-"+Date.now()+"-"+Math.random().toString(36).substr(2,9)),i.push({timelineEl:e,wrap:s,scroller:d,items:m,settings:c,listeners:[]})}),E(),window.addEventListener("resize",()=>{clearTimeout(a),a=setTimeout(()=>{const e=window.innerWidth;e!==r&&(E(),r=e)},250)})}function p(e,t,i){const n=document.querySelector(e);if(!n)return;let o=n.querySelector(".timeline__items");if(o)o.innerHTML="";else{const e=document.createElement("div");e.className="timeline__wrap",o=document.createElement("div"),o.className="timeline__items",e.appendChild(o),n.appendChild(e)}if(i&&(function(e,t){t.layoutMode&&e.setAttribute("data-mode",t.layoutMode),void 0!==t.visibleItems&&e.setAttribute("data-visible-items",t.visibleItems),void 0!==t.minWidth&&(e.setAttribute("data-min-width",t.minWidth),e.setAttribute("data-force-vertical-mode",t.minWidth)),void 0!==t.maxWidth&&e.setAttribute("data-max-width",t.maxWidth)}(n,i),f(n,i),i.timelineName&&""!==i.timelineName.trim())){const e=n.previousElementSibling;if(e&&e.classList.contains("timeline__heading"))e.textContent=i.timelineName;else{const e=document.createElement("h1");e.className="timeline__heading",e.textContent=i.timelineName,n.parentNode.insertBefore(e,n)}n.setAttribute("data-timeline-name",i.timelineName)}return t.forEach(function(e){o.appendChild(function(e){const t=document.createElement("div");t.className="timeline__item",e.id&&t.setAttribute("data-node-id",e.id),t.setAttribute("data-modal-title",e.title||""),t.setAttribute("data-modal-content",e.content||""),t.setAttribute("data-modal-image",e.image||""),e.html&&t.setAttribute("data-modal-html",e.html);const i=document.createElement("div");if(i.className="timeline__content",e.image){const t=document.createElement("img");t.src=e.image,t.className="timeline__image",t.alt=e.title||"",t.onerror=function(){console.error('Timeline: The image "'+e.image+'" could not be loaded. Please check the path.'),this.src=d+"/missing-image.svg",this.alt="Image not found",this.title="Original image: "+e.image},i.appendChild(t)}const n=document.createElement("div");if(e.title){const t=document.createElement("h3");t.textContent=e.title,n.appendChild(t)}if(e.content){const t=document.createElement("p");let i=e.content;i.length>105&&(i=i.substring(0,105)+"..."),t.innerHTML=i,n.appendChild(t)}if(e.html){const t=document.createElement("div");t.innerHTML=e.html,n.appendChild(t)}return i.appendChild(n),t.appendChild(i),t.addEventListener("click",function(e){e.preventDefault(),"function"==typeof window.openTimelineModal&&window.openTimelineModal(t)}),t.setAttribute("data-modal-bound","1"),t}(e))}),n}function w(e,t,i){const n=p(e,t,i);n&&v([n],i)}function b(e,t){const i=document.querySelector(t);if(!i)return void console.error("Timeline: Container not found:",t);m();const n=i?i.id:null,o=n?"vjs_"+n:null;if(o&&"undefined"!=typeof Storage)try{const i=localStorage.getItem(o);if(i){const l=JSON.parse(i);return void fetch(e).then(function(t){if(!t.ok)throw new Error("Failed to load "+e+" ("+t.status+")");return t.json()}).then(function(e){e.lastupdated&&l.lastupdated&&e.lastupdated===l.lastupdated?(console.log("Using cached timeline data for",n),y(l,t)):(console.log("Updating cached timeline data for",n),localStorage.setItem(o,JSON.stringify(e)),y(e,t))}).catch(function(e){console.warn("Failed to fetch fresh data, using cache:",e),y(l,t)})}}catch(e){console.warn("Error reading from localStorage:",e)}fetch(e).then(function(t){if(!t.ok)throw new Error("Failed to load "+e+" ("+t.status+")");return t.json()}).then(function(e){if(o&&"undefined"!=typeof Storage)try{localStorage.setItem(o,JSON.stringify(e)),console.log("Cached timeline data for",n)}catch(e){console.warn("Failed to cache timeline data:",e)}y(e,t)}).catch(function(e){console.error("Error loading timeline JSON:",e),u(i,"json-load",e.message)})}function y(e,t){const i=document.querySelector(t);if(!i)return void console.error("Timeline: Container not found:",t);let n=null,o=[];try{if(e.nodes&&Array.isArray(e.nodes))o=e.nodes,n={timelineName:e.timelineName,layoutMode:e.layoutMode,visibleItems:e.visibleItems,minWidth:e.minWidth,maxWidth:e.maxWidth,nodeColor:e.nodeColor,lineColor:e.lineColor,navColor:e.navColor,lastupdated:e.lastupdated};else{if(!Array.isArray(e))throw new Error('Invalid JSON format. Expected object with "nodes" array or simple array.');o=e}if(0===o.length)throw new Error("No timeline items found in data.");p(t,o,n);try{v(document.querySelectorAll(t)),r(t),c()}catch(e){console.error("Error initializing timeline:",e);const i=document.querySelector(t);i&&u(i,"invalid-config",e.message),c()}}catch(e){console.error("Error processing timeline data:",e),u(i,"json-parse",e.message),c()}}function E(e){if("undefined"!=typeof Storage)if(e){const t="vjs_"+e;localStorage.removeItem(t),console.log("Cleared cache for timeline:",e)}else{const e=Object.keys(localStorage);let t=0;e.forEach(function(e){e.startsWith("vjs_")&&(localStorage.removeItem(e),t++)}),console.log("Cleared",t,"timeline cache(s)")}else console.warn("localStorage not supported")}return"undefined"!=typeof window&&(window.timeline=v,window.timelineFromData=w,window.renderTimelineFromData=p,window.processTimelineData=y,window.loadDataFromJson=b,window.clearTimelineCache=E,window.createTimelineModal=o,window.openTimelineModal=l,window.closeTimelineModal=a,window.handleTimelineDeepLinking=r,window.navigateTimelineToNodeIndex=s),document.addEventListener("DOMContentLoaded",function(){document.querySelectorAll("[data-json-config]").forEach(function(e){const t=e.getAttribute("data-json-config");if(!t)return;const i=(e.className||"").split(" ")[0],n=e.id?"#"+e.id:i?"."+i:null;n&&b(t,n)})}),"undefined"!=typeof window&&window.jQuery&&(window.jQuery.fn.timeline=function(e){return v(this,e),this}),e.clearTimelineCache=E,e.closeTimelineModal=a,e.createTimelineModal=o,e.handleDeepLinking=r,e.loadDataFromJson=b,e.navigateToNodeIndex=s,e.openTimelineModal=l,e.processTimelineData=y,e.renderTimelineFromData=p,e.timeline=v,e.timelineFromData=w,e}({});
2
2
  //# sourceMappingURL=timeline.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"timeline.min.js","sources":["../src/js/shared/state.js","../src/js/features/modals.js","../src/js/features/deep-linking.js","../src/js/shared/config.js","../src/js/features/loader-ui.js","../src/js/features/error-ui.js","../src/js/shared/utils.js","../src/js/features/colors.js","../src/js/core/timeline-engine.js","../src/js/features/data-loader.js","../src/js/timeline.js"],"sourcesContent":["// Shared state containers\nexport const loaderState = {\n count: 0,\n startTime: 0,\n removeTimer: null,\n overlayEl: null\n};\n\nexport const modalState = {\n modal: null,\n overlay: null\n};\n\n// Global registry to store timeline instances for programmatic navigation\nexport const timelineRegistry = {};\n","import { modalState } from '../shared/state.js';\n\nexport function createTimelineModal() {\n if (modalState.modal) return;\n\n modalState.overlay = document.createElement('div');\n modalState.overlay.className = 'timeline-modal-overlay';\n modalState.overlay.addEventListener('click', closeTimelineModal);\n\n modalState.modal = document.createElement('div');\n modalState.modal.className = 'timeline-modal';\n modalState.modal.innerHTML = `\n <button class=\"timeline-modal__close\" aria-label=\"Close modal\"></button>\n <div class=\"timeline-modal__content\">\n <img class=\"timeline-modal__image\" src=\"\" alt=\"\" style=\"display: none;\">\n <h2 class=\"timeline-modal__title\"></h2>\n <div class=\"timeline-modal__text\"></div>\n <hr class=\"timeline-modal__divider\">\n <button class=\"timeline-modal__close-bottom\">Close</button>\n </div>\n `;\n\n const closeBtn = modalState.modal.querySelector('.timeline-modal__close');\n const closeBottomBtn = modalState.modal.querySelector('.timeline-modal__close-bottom');\n closeBtn.addEventListener('click', closeTimelineModal);\n closeBottomBtn.addEventListener('click', closeTimelineModal);\n\n modalState.modal.addEventListener('click', function(e) {\n e.stopPropagation();\n });\n\n document.body.appendChild(modalState.overlay);\n document.body.appendChild(modalState.modal);\n\n document.addEventListener('keydown', function(e) {\n if (e.key === 'Escape' && modalState.modal.classList.contains('timeline-modal-show')) {\n closeTimelineModal();\n }\n });\n}\n\nexport function openTimelineModal(itemEl) {\n if (!modalState.modal) {\n createTimelineModal();\n }\n\n const title = itemEl.getAttribute('data-modal-title');\n const content = itemEl.getAttribute('data-modal-content');\n const image = itemEl.getAttribute('data-modal-image');\n const html = itemEl.getAttribute('data-modal-html');\n\n const modalTitle = modalState.modal.querySelector('.timeline-modal__title');\n const modalText = modalState.modal.querySelector('.timeline-modal__text');\n const modalImage = modalState.modal.querySelector('.timeline-modal__image');\n\n modalTitle.textContent = title || '';\n\n if (image) {\n modalImage.src = image;\n modalImage.alt = title || '';\n modalImage.style.display = 'block';\n } else {\n modalImage.style.display = 'none';\n }\n\n if (html) {\n modalText.innerHTML = html;\n } else if (content) {\n modalText.innerHTML = '<p>' + content.replace(/\\n/g, '</p><p>') + '</p>';\n } else {\n modalText.innerHTML = '';\n }\n\n setTimeout(function() {\n modalState.modal.classList.add('timeline-modal-show');\n modalState.overlay.classList.add('timeline-modal-show');\n document.body.style.overflow = 'hidden';\n }, 10);\n}\n\nexport function closeTimelineModal() {\n if (modalState.modal) {\n modalState.modal.classList.remove('timeline-modal-show');\n modalState.overlay.classList.remove('timeline-modal-show');\n document.body.style.overflow = '';\n }\n}\n","import { timelineRegistry } from '../shared/state.js';\n\nexport function handleDeepLinking(containerSelector) {\n const urlParams = new URLSearchParams(window.location.search);\n const timelineId = urlParams.get('timeline');\n const nodeId = urlParams.get('id');\n if (!nodeId) return;\n\n let targetContainer;\n if (timelineId) {\n targetContainer = document.getElementById(timelineId);\n } else {\n targetContainer = document.querySelector(containerSelector);\n }\n\n if (!targetContainer) {\n console.warn('Timeline not found for deep linking:', timelineId || containerSelector);\n return;\n }\n\n targetContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });\n\n const targetNode = targetContainer.querySelector('[data-node-id=\"' + nodeId + '\"]');\n if (targetNode) {\n setTimeout(function() {\n targetNode.classList.add('timeline__item--active');\n const itemIndex = Array.from(targetNode.parentNode.children).indexOf(targetNode);\n navigateToNodeIndex(targetContainer, itemIndex);\n }, 500);\n }\n}\n\nexport function navigateToNodeIndex(container, index) {\n if (!container) return;\n const timelineId = container.id || container.getAttribute('data-timeline-id');\n if (!timelineId) {\n console.warn('Cannot navigate: timeline container has no ID');\n return;\n }\n\n const tlData = timelineRegistry[timelineId];\n if (!tlData) {\n console.warn('Timeline not found in registry:', timelineId);\n return;\n }\n\n if (!container.classList.contains('timeline--horizontal')) {\n return;\n }\n\n if (tlData.setCurrentIndex && tlData.updatePosition) {\n tlData.setCurrentIndex(index);\n tlData.updatePosition();\n }\n}\n","// Shared configuration values\n// Auto-detect the timeline.js script location to build correct image paths\nexport const timelineBasePath = (function() {\n // Check for user override\n if (typeof window !== 'undefined' && \n window.TimelineConfig && \n window.TimelineConfig.basePath) {\n return window.TimelineConfig.basePath;\n }\n \n const scripts = document.getElementsByTagName('script');\n for (let i = 0; i < scripts.length; i++) {\n const src = scripts[i].src || '';\n if (!src) continue;\n const dir = src.substring(0, src.lastIndexOf('/'));\n if (src.indexOf('timeline.min.js') !== -1) {\n // When loading from dist, map to src/images\n return dir.replace('/dist', '/src/images');\n }\n if (src.indexOf('timeline.js') !== -1) {\n // When loading from src/js, map to src/images\n return dir.replace('/js', '/images');\n }\n }\n // Fallback relative to demo pages; most demos live under demo/**\n return '../src/images';\n})();\n\n// Minimum time (ms) to keep the loading spinner visible\nlet timelineLoaderMinMs = 1300;\nexport function getTimelineLoaderMinMs() {\n return timelineLoaderMinMs;\n}\nexport function setTimelineLoaderMinMs(value) {\n if (typeof value === 'number' && value >= 0) {\n timelineLoaderMinMs = value;\n }\n}\n","import { loaderState } from '../shared/state.js';\nimport { getTimelineLoaderMinMs, timelineBasePath } from '../shared/config.js';\n\nexport function showTimelineLoader() {\n loaderState.count += 1;\n if (loaderState.count !== 1) return;\n\n loaderState.startTime = Date.now();\n\n if (loaderState.removeTimer) {\n clearTimeout(loaderState.removeTimer);\n loaderState.removeTimer = null;\n }\n\n const overlay = document.createElement('div');\n overlay.className = 'timeline__loader-overlay';\n\n const loader = document.createElement('div');\n loader.className = 'timeline__loader';\n\n const spinner = document.createElement('img');\n spinner.src = timelineBasePath + '/spinner.gif';\n spinner.alt = 'Loading...';\n spinner.title = 'Loading...';\n spinner.className = 'timeline__loader-spinner';\n\n loader.appendChild(spinner);\n overlay.appendChild(loader);\n\n document.body.appendChild(overlay);\n loaderState.overlayEl = overlay;\n}\n\nexport function hideTimelineLoader() {\n if (loaderState.count <= 0) return;\n loaderState.count -= 1;\n if (loaderState.count > 0) return;\n\n const elapsed = Date.now() - loaderState.startTime;\n const minMs = getTimelineLoaderMinMs();\n const remaining = Math.max(0, minMs - elapsed);\n\n const removeOverlay = function() {\n if (loaderState.overlayEl) {\n loaderState.overlayEl.remove();\n loaderState.overlayEl = null;\n }\n loaderState.removeTimer = null;\n };\n\n if (loaderState.removeTimer) {\n clearTimeout(loaderState.removeTimer);\n loaderState.removeTimer = null;\n }\n\n if (remaining > 0) {\n loaderState.removeTimer = setTimeout(removeOverlay, remaining);\n } else {\n removeOverlay();\n }\n}\n","import { timelineBasePath } from '../shared/config.js';\nimport { hideTimelineLoader } from './loader-ui.js';\n\nexport function showTimelineError(container, errorType, details) {\n if (!container) return;\n\n const errorMessages = {\n 'json-load': {\n title: 'Timeline Data Could Not Be Loaded',\n message: 'The timeline data failed to load. This could be due to a network error or an incorrect file path.',\n solution: 'Please check that the data-json-config path is correct and the file is accessible.'\n },\n 'json-parse': {\n title: 'Invalid Timeline Data',\n message: 'The timeline data file exists but contains invalid JSON.',\n solution: 'Please validate your JSON using a tool like jsonlint.com and ensure it follows the correct schema.'\n },\n 'missing-element': {\n title: 'Timeline Element Not Found',\n message: 'The required timeline container element could not be found on the page.',\n solution: 'Ensure your HTML includes a container with the class \"timeline\" and the correct selector.'\n },\n 'invalid-config': {\n title: 'Invalid Configuration',\n message: 'One or more timeline configuration options are invalid.',\n solution: 'Check your data attributes or JavaScript options and ensure they match the expected format.'\n }\n };\n\n const errorInfo = errorMessages[errorType] || {\n title: 'Timeline Error',\n message: 'An unexpected error occurred while initializing the timeline.',\n solution: 'Please check the browser console for more details.'\n };\n\n hideTimelineLoader(container);\n container.innerHTML = '';\n\n const errorDiv = document.createElement('div');\n errorDiv.className = 'timeline__error';\n\n const errorIcon = document.createElement('img');\n errorIcon.src = timelineBasePath + '/alert.svg';\n errorIcon.alt = 'Error';\n errorIcon.className = 'timeline__error-icon';\n\n const errorTitle = document.createElement('h2');\n errorTitle.className = 'timeline__error-title';\n errorTitle.textContent = errorInfo.title;\n\n const errorMessage = document.createElement('p');\n errorMessage.className = 'timeline__error-message';\n errorMessage.textContent = errorInfo.message;\n\n const errorSolution = document.createElement('p');\n errorSolution.className = 'timeline__error-solution';\n errorSolution.innerHTML = '<strong>Solution:</strong> ' + errorInfo.solution;\n\n if (details) {\n const errorDetails = document.createElement('p');\n errorDetails.className = 'timeline__error-details';\n errorDetails.innerHTML = '<strong>Details:</strong> ' + details;\n errorDiv.appendChild(errorDetails);\n }\n\n errorDiv.appendChild(errorIcon);\n errorDiv.appendChild(errorTitle);\n errorDiv.appendChild(errorMessage);\n errorDiv.appendChild(errorSolution);\n\n container.appendChild(errorDiv);\n\n console.error('Timeline Error [' + errorType + ']:', errorInfo.message, details || '');\n}\n","// Utility helpers shared across modules\nexport function getContrastColor(bgColor) {\n const brightness = getColorBrightness(bgColor);\n return brightness > 128 ? 'rgba(0, 0, 0, 0.2)' : 'rgba(255, 255, 255, 0.3)';\n}\n\nexport function getColorBrightness(color) {\n let rgb;\n if (!color || typeof color !== 'string') return 128;\n\n if (color.startsWith('#')) {\n let hex = color.substring(1);\n if (hex.length === 3) {\n hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];\n }\n const r = parseInt(hex.substring(0, 2), 16);\n const g = parseInt(hex.substring(2, 4), 16);\n const b = parseInt(hex.substring(4, 6), 16);\n rgb = [r, g, b];\n } else if (color.startsWith('rgb')) {\n const matches = color.match(/\\d+/g);\n rgb = matches ? matches.map(Number) : [128, 128, 128];\n } else {\n return 128;\n }\n\n return (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000;\n}\n","import { getContrastColor, getColorBrightness } from '../shared/utils.js';\n\nexport function applyTimelineColors(container, config) {\n let nodeColor = config.nodeColor || null;\n let lineColor = config.lineColor || null;\n const navColor = config.navColor || null;\n\n if (nodeColor && !lineColor) lineColor = nodeColor;\n if (lineColor && !nodeColor) nodeColor = lineColor;\n\n if (nodeColor) {\n container.style.setProperty('--timeline-node-color', nodeColor);\n }\n if (lineColor) {\n container.style.setProperty('--timeline-line-color', lineColor);\n }\n if (navColor) {\n container.style.setProperty('--timeline-nav-color', navColor);\n container.style.setProperty('--timeline-nav-border', getContrastColor(navColor));\n const brightness = getColorBrightness(navColor);\n const arrowColor = brightness > 128 ? '#333' : '#fff';\n container.style.setProperty('--timeline-arrow-color', arrowColor);\n container.setAttribute('data-arrow-color', arrowColor);\n }\n}\n","import { showTimelineLoader, hideTimelineLoader } from '../features/loader-ui.js';\nimport { showTimelineError } from '../features/error-ui.js';\nimport { applyTimelineColors } from '../features/colors.js';\nimport { openTimelineModal } from '../features/modals.js';\nimport { timelineRegistry } from '../shared/state.js';\n\nfunction ensureInlineModalData(itemEl) {\n if (!itemEl) return;\n const content = itemEl.querySelector('.timeline__content') || itemEl;\n if (!itemEl.hasAttribute('data-modal-title')) {\n const heading = content.querySelector('h1,h2,h3,h4,h5,h6');\n if (heading && heading.textContent) {\n itemEl.setAttribute('data-modal-title', heading.textContent.trim());\n }\n }\n if (!itemEl.hasAttribute('data-modal-content')) {\n const firstP = content.querySelector('p');\n if (firstP && firstP.textContent) {\n itemEl.setAttribute('data-modal-content', firstP.textContent.trim());\n }\n }\n if (!itemEl.hasAttribute('data-modal-image')) {\n const img = content.querySelector('img');\n if (img && img.getAttribute('src')) {\n itemEl.setAttribute('data-modal-image', img.getAttribute('src'));\n }\n }\n}\n\nfunction enhanceInlineItems(timelineEl, items) {\n if (!items || !items.length) return;\n items.forEach(function(item){\n if (item.getAttribute('data-modal-bound') === '1') return;\n ensureInlineModalData(item);\n const hasModal = item.hasAttribute('data-modal-title') || item.hasAttribute('data-modal-content') || item.hasAttribute('data-modal-image') || item.hasAttribute('data-modal-html');\n if (hasModal) {\n item.addEventListener('click', function(e){\n e.preventDefault();\n openTimelineModal(item);\n });\n item.setAttribute('data-modal-bound', '1');\n }\n });\n}\n\nfunction createArrowSVG(direction, color) {\n if (direction === 'left') {\n return '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"7.8\" height=\"14\" style=\"display:block;margin:auto;\"><path fill=\"none\" stroke=\"' + color + '\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6.8 1L1 7l5.8 6\"/></svg>';\n }\n return '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"7.8\" height=\"14\" style=\"display:block;margin:auto;\"><path fill=\"none\" stroke=\"' + color + '\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M1 1l5.8 6L1 13\"/></svg>';\n}\n\nexport function timeline(collection, options) {\n const timelines = [];\n const warningLabel = 'Timeline:';\n let winWidth = window.innerWidth;\n let resizeTimer;\n let currentIndex = 0;\n const eventListeners = new Map(); // Track listeners for cleanup\n\n showTimelineLoader();\n let shouldHideLoader = true;\n\n const defaultSettings = {\n minWidth: { type: 'integer', defaultValue: 600 },\n horizontalStartPosition: { type: 'string', acceptedValues: ['bottom', 'top'], defaultValue: 'top' },\n mode: { type: 'string', acceptedValues: ['horizontal', 'vertical'], defaultValue: 'vertical' },\n moveItems: { type: 'integer', defaultValue: 1 },\n rtlMode: { type: 'boolean', acceptedValues: [true, false], defaultValue: false },\n startIndex: { type: 'integer', defaultValue: 0 },\n verticalStartPosition: { type: 'string', acceptedValues: ['left', 'right'], defaultValue: 'left' },\n verticalTrigger: { type: 'string', defaultValue: '15%' },\n visibleItems: { type: 'integer', defaultValue: 3 }\n };\n\n function testValues(value, settingName) {\n if (typeof value !== 'number' && value % 1 !== 0) {\n console.warn(`${warningLabel} The value \"${value}\" entered for the setting \"${settingName}\" is not an integer.`);\n return false;\n }\n return true;\n }\n\n function itemWrap(el, wrapper, classes) {\n wrapper.classList.add(classes);\n el.parentNode.insertBefore(wrapper, el);\n wrapper.appendChild(el);\n }\n\n function wrapElements(items) {\n items.forEach((item) => {\n itemWrap(item.querySelector('.timeline__content'), document.createElement('div'), 'timeline__content__wrap');\n itemWrap(item.querySelector('.timeline__content__wrap'), document.createElement('div'), 'timeline__item__inner');\n });\n }\n\n function isElementInViewport(el, triggerPosition) {\n const rect = el.getBoundingClientRect();\n const windowHeight = window.innerHeight || document.documentElement.clientHeight;\n const defaultTrigger = defaultSettings.verticalTrigger.defaultValue.match(/(\\d*\\.?\\d*)(.*)/);\n let triggerUnit = triggerPosition.unit;\n let triggerValue = triggerPosition.value;\n let trigger = windowHeight;\n if (triggerUnit === 'px' && triggerValue >= windowHeight) {\n console.warn('The value entered for the setting \"verticalTrigger\" is larger than the window height. The default value will be used instead.');\n [, triggerValue, triggerUnit] = defaultTrigger;\n }\n if (triggerUnit === 'px') {\n trigger = parseInt(trigger - triggerValue, 10);\n } else if (triggerUnit === '%') {\n trigger = parseInt(trigger * ((100 - triggerValue) / 100), 10);\n }\n return (\n rect.top <= trigger &&\n rect.left <= (window.innerWidth || document.documentElement.clientWidth) &&\n (rect.top + rect.height) >= 0 &&\n (rect.left + rect.width) >= 0\n );\n }\n\n function addTransforms(el, transform) {\n el.style.webkitTransform = transform;\n el.style.msTransform = transform;\n el.style.transform = transform;\n }\n\n function createTimelines(timelineEl) {\n const timelineName = timelineEl.id ? `#${timelineEl.id}` : `.${timelineEl.className}`;\n const errorPart = 'could not be found as a direct descendant of';\n const data = timelineEl.dataset;\n let wrap;\n let scroller;\n let items;\n const settings = {};\n\n try {\n wrap = timelineEl.querySelector('.timeline__wrap');\n if (!wrap) {\n throw new Error(`${warningLabel} .timeline__wrap ${errorPart} ${timelineName}`);\n } else {\n scroller = wrap.querySelector('.timeline__items');\n if (!scroller) {\n throw new Error(`${warningLabel} .timeline__items ${errorPart} .timeline__wrap`);\n } else {\n items = [].slice.call(scroller.children, 0);\n }\n }\n } catch (e) {\n console.warn(e.message);\n showTimelineError(timelineEl, 'missing-element', e.message);\n return false;\n }\n\n Object.keys(defaultSettings).forEach((key) => {\n settings[key] = defaultSettings[key].defaultValue;\n\n if (key === 'minWidth') {\n let candidate = undefined;\n if (data.minWidth !== undefined) candidate = data.minWidth;\n if (data.minwidth !== undefined) candidate = data.minwidth;\n if (data.forceVerticalMode !== undefined) candidate = data.forceVerticalMode;\n if (data.forceverticalmode !== undefined) candidate = data.forceverticalmode;\n if (candidate === undefined && options) {\n if (options.minWidth !== undefined) candidate = options.minWidth;\n else if (options.forceVerticalMode !== undefined) candidate = options.forceVerticalMode;\n }\n if (candidate !== undefined) settings.minWidth = candidate;\n } else {\n if (data[key]) {\n settings[key] = data[key];\n } else if (options && options[key] !== undefined) {\n settings[key] = options[key];\n }\n }\n\n if (defaultSettings[key].type === 'integer') {\n if (!settings[key] || !testValues(settings[key], key)) {\n settings[key] = defaultSettings[key].defaultValue;\n }\n } else if (defaultSettings[key].type === 'string') {\n if (defaultSettings[key].acceptedValues && defaultSettings[key].acceptedValues.indexOf(settings[key]) === -1) {\n console.warn(`${warningLabel} The value \"${settings[key]}\" entered for the setting \"${key}\" was not recognised.`);\n settings[key] = defaultSettings[key].defaultValue;\n }\n }\n });\n\n (function applyColorParity(){\n const data = timelineEl.dataset;\n const getData = function(k){\n return data[k] !== undefined ? data[k] : (data[k && k.toLowerCase()] !== undefined ? data[k.toLowerCase()] : undefined);\n };\n let nodeColor = getData('nodeColor');\n let lineColor = getData('lineColor');\n let navColor = getData('navColor');\n if (options) {\n if (options.nodeColor !== undefined) nodeColor = options.nodeColor;\n if (options.lineColor !== undefined) lineColor = options.lineColor;\n if (options.navColor !== undefined) navColor = options.navColor;\n }\n if (nodeColor || lineColor || navColor) {\n applyTimelineColors(timelineEl, { nodeColor, lineColor, navColor });\n }\n })();\n\n const defaultTrigger = defaultSettings.verticalTrigger.defaultValue.match(/(\\d*\\.?\\d*)(.*)/);\n const triggerArray = settings.verticalTrigger.match(/(\\d*\\.?\\d*)(.*)/);\n let [, triggerValue, triggerUnit] = triggerArray;\n let triggerValid = true;\n if (!triggerValue) {\n console.warn(`${warningLabel} No numercial value entered for the 'verticalTrigger' setting.`);\n triggerValid = false;\n }\n if (triggerUnit !== 'px' && triggerUnit !== '%') {\n console.warn(`${warningLabel} The setting 'verticalTrigger' must be a percentage or pixel value.`);\n triggerValid = false;\n }\n if (triggerUnit === '%' && (triggerValue > 100 || triggerValue < 0)) {\n console.warn(`${warningLabel} The 'verticalTrigger' setting value must be between 0 and 100 if using a percentage value.`);\n triggerValid = false;\n } else if (triggerUnit === 'px' && triggerValue < 0) {\n console.warn(`${warningLabel} The 'verticalTrigger' setting value must be above 0 if using a pixel value.`);\n triggerValid = false;\n }\n\n if (triggerValid === false) {\n [, triggerValue, triggerUnit] = defaultTrigger;\n }\n\n settings.verticalTrigger = {\n unit: triggerUnit,\n value: triggerValue\n };\n\n if (settings.moveItems > settings.visibleItems) {\n console.warn(`${warningLabel} The value of \"moveItems\" (${settings.moveItems}) is larger than the number of \"visibleItems\" (${settings.visibleItems}). The value of \"visibleItems\" has been used instead.`);\n settings.moveItems = settings.visibleItems;\n }\n\n if (settings.startIndex > (items.length - settings.visibleItems) && items.length > settings.visibleItems) {\n console.warn(`${warningLabel} The 'startIndex' setting must be between 0 and ${items.length - settings.visibleItems} for this timeline. The value of ${items.length - settings.visibleItems} has been used instead.`);\n settings.startIndex = items.length - settings.visibleItems;\n } else if (items.length <= settings.visibleItems) {\n console.warn(`${warningLabel} The number of items in the timeline must exceed the number of visible items to use the 'startIndex' option.`);\n settings.startIndex = 0;\n } else if (settings.startIndex < 0) {\n console.warn(`${warningLabel} The 'startIndex' setting must be between 0 and ${items.length - settings.visibleItems} for this timeline. The value of 0 has been used instead.`);\n settings.startIndex = 0;\n }\n\n enhanceInlineItems(timelineEl, items);\n\n if (!timelineEl.id) {\n timelineEl.setAttribute('data-timeline-id', 'timeline-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9));\n }\n\n timelines.push({\n timelineEl,\n wrap,\n scroller,\n items,\n settings,\n listeners: [] // Store listeners for cleanup\n });\n }\n\n if (collection.length) {\n Array.from(collection).forEach(createTimelines);\n }\n\n function setHeightandWidths(tl) {\n function setWidths() {\n tl.itemWidth = 200;\n tl.items.forEach((item) => {\n item.style.width = `${tl.itemWidth}px`;\n });\n tl.scrollerWidth = tl.itemWidth * tl.items.length;\n tl.scroller.style.width = `${tl.scrollerWidth}px`;\n }\n\n function setHeights() {\n let oddIndexTallest = 0;\n let evenIndexTallest = 0;\n tl.items.forEach((item, i) => {\n item.style.height = 'auto';\n const height = item.offsetHeight;\n if (i % 2 === 0) {\n evenIndexTallest = height > evenIndexTallest ? height : evenIndexTallest;\n } else {\n oddIndexTallest = height > oddIndexTallest ? height : oddIndexTallest;\n }\n });\n\n const transformString = `translateY(${evenIndexTallest}px)`;\n tl.items.forEach((item, i) => {\n if (i % 2 === 0) {\n item.style.height = `${evenIndexTallest}px`;\n if (tl.settings.horizontalStartPosition === 'bottom') {\n item.classList.add('timeline__item--bottom');\n addTransforms(item, transformString);\n } else {\n item.classList.add('timeline__item--top');\n }\n } else {\n item.style.height = `${oddIndexTallest}px`;\n if (tl.settings.horizontalStartPosition !== 'bottom') {\n item.classList.add('timeline__item--bottom');\n addTransforms(item, transformString);\n } else {\n item.classList.add('timeline__item--top');\n }\n }\n });\n tl.scroller.style.height = `${evenIndexTallest + oddIndexTallest}px`;\n }\n\n if (window.innerWidth > tl.settings.minWidth) {\n setWidths();\n setHeights();\n }\n }\n\n function addNavigation(tl) {\n const viewportWidth = tl.wrap.offsetWidth;\n const itemsVisible = Math.floor(viewportWidth / tl.itemWidth);\n\n if (tl.items.length > itemsVisible) {\n const prevArrow = document.createElement('button');\n const nextArrow = document.createElement('button');\n const topPosition = tl.items[0].offsetHeight;\n prevArrow.className = 'timeline-nav-button timeline-nav-button--prev';\n nextArrow.className = 'timeline-nav-button timeline-nav-button--next';\n prevArrow.textContent = 'Previous';\n nextArrow.textContent = 'Next';\n prevArrow.style.top = `${topPosition}px`;\n nextArrow.style.top = `${topPosition}px`;\n\n const arrowColor = tl.timelineEl.getAttribute('data-arrow-color') || '#333';\n prevArrow.innerHTML = createArrowSVG('left', arrowColor);\n nextArrow.innerHTML = createArrowSVG('right', arrowColor);\n\n const maxIndex = Math.max(0, tl.items.length - itemsVisible);\n if (currentIndex === 0) {\n prevArrow.disabled = true;\n } else if (currentIndex >= maxIndex) {\n nextArrow.disabled = true;\n }\n tl.timelineEl.appendChild(prevArrow);\n tl.timelineEl.appendChild(nextArrow);\n }\n }\n\n function addHorizontalDivider(tl) {\n const divider = tl.timelineEl.querySelector('.timeline-divider');\n if (divider) {\n tl.timelineEl.removeChild(divider);\n }\n const topPosition = tl.items[0].offsetHeight;\n const horizontalDivider = document.createElement('span');\n horizontalDivider.className = 'timeline-divider';\n horizontalDivider.style.top = `${topPosition}px`;\n tl.timelineEl.appendChild(horizontalDivider);\n }\n\n function timelinePosition(tl) {\n const position = tl.items[currentIndex].offsetLeft;\n const str = `translate3d(-${position}px, 0, 0)`;\n addTransforms(tl.scroller, str);\n }\n\n function slideTimeline(tl) {\n const navArrows = tl.timelineEl.querySelectorAll('.timeline-nav-button');\n const arrowPrev = tl.timelineEl.querySelector('.timeline-nav-button--prev');\n const arrowNext = tl.timelineEl.querySelector('.timeline-nav-button--next');\n\n const viewportWidth = tl.wrap.offsetWidth;\n const itemsVisible = Math.floor(viewportWidth / tl.itemWidth);\n const maxIndex = Math.max(0, tl.items.length - itemsVisible);\n\n const moveItems = parseInt(tl.settings.moveItems, 10);\n \n const handleArrowClick = function(e) {\n e.preventDefault();\n e.stopPropagation();\n\n if (this.disabled) {\n return;\n }\n\n currentIndex = this.classList.contains('timeline-nav-button--next') ? (currentIndex += moveItems) : (currentIndex -= moveItems);\n if (currentIndex === 0 || currentIndex < 0) {\n currentIndex = 0;\n arrowPrev.disabled = true;\n arrowNext.disabled = false;\n } else if (currentIndex === maxIndex || currentIndex > maxIndex) {\n currentIndex = maxIndex;\n arrowPrev.disabled = false;\n arrowNext.disabled = true;\n } else {\n arrowPrev.disabled = false;\n arrowNext.disabled = false;\n }\n timelinePosition(tl);\n };\n \n Array.from(navArrows).forEach((arrow) => {\n arrow.addEventListener('click', handleArrowClick);\n tl.listeners.push({ element: arrow, type: 'click', handler: handleArrowClick });\n });\n }\n\n function setUpHorinzontalTimeline(tl) {\n if (tl.settings.rtlMode) {\n currentIndex = tl.items.length > tl.settings.visibleItems ? tl.items.length - tl.settings.visibleItems : 0;\n } else {\n currentIndex = tl.settings.startIndex;\n }\n tl.timelineEl.classList.add('timeline--horizontal');\n setHeightandWidths(tl);\n timelinePosition(tl);\n addNavigation(tl);\n addHorizontalDivider(tl);\n slideTimeline(tl);\n\n const timelineId = tl.timelineEl.id || tl.timelineEl.getAttribute('data-timeline-id');\n if (timelineId) {\n timelineRegistry[timelineId] = {\n setCurrentIndex: function(index) {\n const viewportWidth = tl.wrap.offsetWidth;\n const itemsVisible = Math.floor(viewportWidth / tl.itemWidth);\n const maxIndex = Math.max(0, tl.items.length - itemsVisible);\n currentIndex = Math.max(0, Math.min(index, maxIndex));\n },\n updatePosition: function() {\n timelinePosition(tl);\n const arrowPrev = tl.timelineEl.querySelector('.timeline-nav-button--prev');\n const arrowNext = tl.timelineEl.querySelector('.timeline-nav-button--next');\n if (arrowPrev && arrowNext) {\n const viewportWidth = tl.wrap.offsetWidth;\n const itemsVisible = Math.floor(viewportWidth / tl.itemWidth);\n const maxIndex = Math.max(0, tl.items.length - itemsVisible);\n arrowPrev.disabled = currentIndex === 0;\n arrowNext.disabled = currentIndex >= maxIndex;\n }\n }\n };\n }\n }\n\n function setUpVerticalTimeline(tl) {\n let lastVisibleIndex = 0;\n tl.items.forEach((item, i) => {\n item.classList.remove('animated', 'fadeIn');\n if (!isElementInViewport(item, tl.settings.verticalTrigger) && i > 0) {\n item.classList.add('animated');\n } else {\n lastVisibleIndex = i;\n }\n const divider = tl.settings.verticalStartPosition === 'left' ? 1 : 0;\n if (i % 2 === divider && window.innerWidth > tl.settings.minWidth) {\n item.classList.add('timeline__item--right');\n } else {\n item.classList.add('timeline__item--left');\n }\n });\n for (let i = 0; i < lastVisibleIndex; i += 1) {\n tl.items[i].classList.remove('animated', 'fadeIn');\n }\n \n // Use IntersectionObserver instead of scroll listener for better performance\n if ('IntersectionObserver' in window) {\n const observerOptions = {\n rootMargin: tl.settings.verticalTrigger.unit === '%' \n ? `${tl.settings.verticalTrigger.value}%` \n : `${tl.settings.verticalTrigger.value}px`,\n threshold: 0.01\n };\n \n const observer = new IntersectionObserver((entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting) {\n entry.target.classList.add('fadeIn');\n }\n });\n }, observerOptions);\n \n tl.items.forEach((item) => {\n if (item.classList.contains('animated')) {\n observer.observe(item);\n }\n });\n \n // Store observer for cleanup\n tl.observer = observer;\n } else {\n // Fallback for older browsers (though we're targeting 2018+)\n const scrollHandler = () => {\n tl.items.forEach((item) => {\n if (isElementInViewport(item, tl.settings.verticalTrigger)) {\n item.classList.add('fadeIn');\n }\n });\n };\n window.addEventListener('scroll', scrollHandler);\n tl.listeners.push({ element: window, type: 'scroll', handler: scrollHandler });\n }\n }\n\n function resetTimelines(tl) {\n // Clean up event listeners\n if (tl.listeners && tl.listeners.length > 0) {\n tl.listeners.forEach(({ element, type, handler }) => {\n element.removeEventListener(type, handler);\n });\n tl.listeners = [];\n }\n \n // Clean up IntersectionObserver\n if (tl.observer) {\n tl.observer.disconnect();\n tl.observer = null;\n }\n \n tl.timelineEl.classList.remove('timeline--horizontal', 'timeline--mobile');\n tl.scroller.removeAttribute('style');\n tl.items.forEach((item) => {\n item.removeAttribute('style');\n item.classList.remove('animated', 'fadeIn', 'timeline__item--left', 'timeline__item--right');\n });\n const navArrows = tl.timelineEl.querySelectorAll('.timeline-nav-button');\n Array.from(navArrows).forEach((arrow) => {\n arrow.parentNode.removeChild(arrow);\n });\n }\n\n function setUpTimelines() {\n timelines.forEach((tl) => {\n tl.timelineEl.style.opacity = 0;\n if (!tl.timelineEl.classList.contains('timeline--loaded')) {\n wrapElements(tl.items);\n }\n resetTimelines(tl);\n if (window.innerWidth <= tl.settings.minWidth) {\n tl.timelineEl.classList.add('timeline--mobile');\n }\n if (tl.settings.mode === 'horizontal' && window.innerWidth > tl.settings.minWidth) {\n setUpHorinzontalTimeline(tl);\n } else {\n setUpVerticalTimeline(tl);\n }\n tl.timelineEl.classList.add('timeline--loaded');\n });\n\n setTimeout(() => {\n timelines.forEach((tl) => {\n tl.timelineEl.style.opacity = 1;\n });\n }, 500);\n\n if (shouldHideLoader) {\n hideTimelineLoader();\n shouldHideLoader = false;\n }\n }\n\n setUpTimelines();\n\n window.addEventListener('resize', () => {\n clearTimeout(resizeTimer);\n resizeTimer = setTimeout(() => {\n const newWinWidth = window.innerWidth;\n if (newWinWidth !== winWidth) {\n setUpTimelines();\n winWidth = newWinWidth;\n }\n }, 250);\n });\n}","import { timelineBasePath } from '../shared/config.js';\nimport { showTimelineLoader, hideTimelineLoader } from './loader-ui.js';\nimport { showTimelineError } from './error-ui.js';\nimport { applyTimelineColors } from './colors.js';\nimport { handleDeepLinking } from './deep-linking.js';\nimport { timeline } from '../core/timeline-engine.js';\n\nfunction createItemNode(item) {\n const itemEl = document.createElement('div');\n itemEl.className = 'timeline__item';\n\n if (item.id) {\n itemEl.setAttribute('data-node-id', item.id);\n }\n\n itemEl.setAttribute('data-modal-title', item.title || '');\n itemEl.setAttribute('data-modal-content', item.content || '');\n itemEl.setAttribute('data-modal-image', item.image || '');\n if (item.html) {\n itemEl.setAttribute('data-modal-html', item.html);\n }\n\n const content = document.createElement('div');\n content.className = 'timeline__content';\n\n if (item.image) {\n const img = document.createElement('img');\n img.src = item.image;\n img.className = 'timeline__image';\n img.alt = item.title || '';\n img.onerror = function() {\n console.error('Timeline: The image \"' + item.image + '\" could not be loaded. Please check the path.');\n this.src = timelineBasePath + '/missing-image.svg';\n this.alt = 'Image not found';\n this.title = 'Original image: ' + item.image;\n };\n content.appendChild(img);\n }\n\n const textWrapper = document.createElement('div');\n if (item.title) {\n const title = document.createElement('h3');\n title.textContent = item.title;\n textWrapper.appendChild(title);\n }\n\n if (item.content) {\n const para = document.createElement('p');\n let displayText = item.content;\n if (displayText.length > 105) {\n displayText = displayText.substring(0, 105) + '...';\n }\n para.innerHTML = displayText;\n textWrapper.appendChild(para);\n }\n\n if (item.html) {\n const wrapper = document.createElement('div');\n wrapper.innerHTML = item.html;\n textWrapper.appendChild(wrapper);\n }\n\n content.appendChild(textWrapper);\n itemEl.appendChild(content);\n\n itemEl.addEventListener('click', function(e) {\n e.preventDefault();\n if (typeof window.openTimelineModal === 'function') {\n window.openTimelineModal(itemEl);\n }\n });\n itemEl.setAttribute('data-modal-bound', '1');\n\n return itemEl;\n}\n\nfunction applyDataAttributes(container, config) {\n if (config.layoutMode) {\n container.setAttribute('data-mode', config.layoutMode);\n }\n if (config.visibleItems !== undefined) {\n container.setAttribute('data-visible-items', config.visibleItems);\n }\n if (config.minWidth !== undefined) {\n container.setAttribute('data-minwidth', config.minWidth);\n container.setAttribute('data-force-vertical-mode', config.minWidth);\n }\n if (config.maxWidth !== undefined) {\n container.setAttribute('data-maxwidth', config.maxWidth);\n }\n}\n\nexport function renderTimelineFromData(containerSelector, data, config) {\n const container = document.querySelector(containerSelector);\n if (!container) return;\n\n let itemsWrap = container.querySelector('.timeline__items');\n if (!itemsWrap) {\n const wrap = document.createElement('div');\n wrap.className = 'timeline__wrap';\n itemsWrap = document.createElement('div');\n itemsWrap.className = 'timeline__items';\n wrap.appendChild(itemsWrap);\n container.appendChild(wrap);\n } else {\n itemsWrap.innerHTML = '';\n }\n\n if (config) {\n applyDataAttributes(container, config);\n applyTimelineColors(container, config);\n\n if (config.timelineName && config.timelineName.trim() !== '') {\n const existingHeading = container.previousElementSibling;\n if (existingHeading && existingHeading.classList.contains('timeline__heading')) {\n existingHeading.textContent = config.timelineName;\n } else {\n const heading = document.createElement('h1');\n heading.className = 'timeline__heading';\n heading.textContent = config.timelineName;\n container.parentNode.insertBefore(heading, container);\n }\n container.setAttribute('data-timeline-name', config.timelineName);\n }\n }\n\n data.forEach(function (it) {\n itemsWrap.appendChild(createItemNode(it));\n });\n\n return container;\n}\n\nexport function timelineFromData(containerSelector, data, options) {\n const container = renderTimelineFromData(containerSelector, data, options);\n if (!container) return;\n timeline([container], options);\n}\n\nexport function loadDataFromJson(url, containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) {\n console.error('Timeline: Container not found:', containerSelector);\n return;\n }\n\n showTimelineLoader();\n\n const timelineId = container ? container.id : null;\n const cacheKey = timelineId ? 'vjs_' + timelineId : null;\n\n if (cacheKey && typeof(Storage) !== 'undefined') {\n try {\n const cached = localStorage.getItem(cacheKey);\n if (cached) {\n const cachedData = JSON.parse(cached);\n fetch(url).then(function(res) {\n if (!res.ok) throw new Error('Failed to load ' + url + ' (' + res.status + ')');\n return res.json();\n }).then(function(json) {\n if (json.lastupdated && cachedData.lastupdated && json.lastupdated === cachedData.lastupdated) {\n console.log('Using cached timeline data for', timelineId);\n processTimelineData(cachedData, containerSelector);\n } else {\n console.log('Updating cached timeline data for', timelineId);\n localStorage.setItem(cacheKey, JSON.stringify(json));\n processTimelineData(json, containerSelector);\n }\n }).catch(function(err) {\n console.warn('Failed to fetch fresh data, using cache:', err);\n processTimelineData(cachedData, containerSelector);\n });\n return;\n }\n } catch (e) {\n console.warn('Error reading from localStorage:', e);\n }\n }\n\n fetch(url).then(function (res) {\n if (!res.ok) throw new Error('Failed to load ' + url + ' (' + res.status + ')');\n return res.json();\n }).then(function (json) {\n if (cacheKey && typeof(Storage) !== 'undefined') {\n try {\n localStorage.setItem(cacheKey, JSON.stringify(json));\n console.log('Cached timeline data for', timelineId);\n } catch (e) {\n console.warn('Failed to cache timeline data:', e);\n }\n }\n processTimelineData(json, containerSelector);\n }).catch(function (err) {\n console.error('Error loading timeline JSON:', err);\n showTimelineError(container, 'json-load', err.message);\n });\n}\n\nexport function processTimelineData(json, containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) {\n console.error('Timeline: Container not found:', containerSelector);\n return;\n }\n\n let config = null;\n let nodes = [];\n\n try {\n if (json.nodes && Array.isArray(json.nodes)) {\n nodes = json.nodes;\n config = {\n timelineName: json.timelineName,\n layoutMode: json.layoutMode,\n visibleItems: json.visibleItems,\n minWidth: json.minWidth,\n maxWidth: json.maxWidth,\n nodeColor: json.nodeColor,\n lineColor: json.lineColor,\n navColor: json.navColor,\n lastupdated: json.lastupdated\n };\n } else if (Array.isArray(json)) {\n nodes = json;\n } else {\n throw new Error('Invalid JSON format. Expected object with \"nodes\" array or simple array.');\n }\n\n if (nodes.length === 0) {\n throw new Error('No timeline items found in data.');\n }\n\n renderTimelineFromData(containerSelector, nodes, config);\n\n try {\n timeline(document.querySelectorAll(containerSelector));\n handleDeepLinking(containerSelector);\n hideTimelineLoader();\n } catch (e) {\n console.error('Error initializing timeline:', e);\n const container = document.querySelector(containerSelector);\n if (container) {\n showTimelineError(container, 'invalid-config', e.message);\n }\n hideTimelineLoader();\n }\n\n } catch (e) {\n console.error('Error processing timeline data:', e);\n showTimelineError(container, 'json-parse', e.message);\n hideTimelineLoader();\n }\n}\n\nexport function clearTimelineCache(timelineId) {\n if (typeof(Storage) === 'undefined') {\n console.warn('localStorage not supported');\n return;\n }\n\n if (timelineId) {\n const key = 'vjs_' + timelineId;\n localStorage.removeItem(key);\n console.log('Cleared cache for timeline:', timelineId);\n } else {\n const keys = Object.keys(localStorage);\n let cleared = 0;\n keys.forEach(function(key) {\n if (key.startsWith('vjs_')) {\n localStorage.removeItem(key);\n cleared++;\n }\n });\n console.log('Cleared', cleared, 'timeline cache(s)');\n }\n}\n","// --------------------------------------------------------------------------\r\n// timeline.js - a vanilla JS app to display timelines\r\n// \r\n// Created in 2018 by Mike Collins (https://github.com/squarechip/timeline)\r\n// Modified in 2026 by Ken Dawson (https://github.com/kendawson-online)\r\n// Last updated: 01/08/26\r\n//\r\n// --------------------------------------------------------------------------\r\n\r\nimport { createTimelineModal, openTimelineModal, closeTimelineModal } from './features/modals.js';\r\nimport { handleDeepLinking, navigateToNodeIndex } from './features/deep-linking.js';\r\nimport { renderTimelineFromData, timelineFromData, loadDataFromJson, processTimelineData, clearTimelineCache } from './features/data-loader.js';\r\nimport { timeline } from './core/timeline-engine.js';\r\n\r\nfunction autoInitJsonTimelines() {\r\n const timelinesWithJson = document.querySelectorAll('[data-json-config]');\r\n timelinesWithJson.forEach(function(timelineEl) {\r\n const jsonUrl = timelineEl.getAttribute('data-json-config');\r\n if (!jsonUrl) return;\r\n const className = (timelineEl.className || '').split(' ')[0];\r\n const selector = timelineEl.id ? '#' + timelineEl.id : (className ? '.' + className : null);\r\n if (selector) {\r\n loadDataFromJson(jsonUrl, selector);\r\n }\r\n });\r\n}\r\n\r\nfunction exposeGlobals() {\r\n if (typeof window === 'undefined') return;\r\n window.timeline = timeline;\r\n window.timelineFromData = timelineFromData;\r\n window.renderTimelineFromData = renderTimelineFromData;\r\n window.processTimelineData = processTimelineData;\r\n window.loadDataFromJson = loadDataFromJson;\r\n window.clearTimelineCache = clearTimelineCache;\r\n window.createTimelineModal = createTimelineModal;\r\n window.openTimelineModal = openTimelineModal;\r\n window.closeTimelineModal = closeTimelineModal;\r\n window.handleTimelineDeepLinking = handleDeepLinking;\r\n window.navigateTimelineToNodeIndex = navigateToNodeIndex;\r\n}\r\n\r\nexposeGlobals();\r\n\r\ndocument.addEventListener('DOMContentLoaded', function() {\r\n autoInitJsonTimelines();\r\n});\r\n\r\nif (typeof window !== 'undefined' && window.jQuery) {\r\n (( $) => {\r\n $.fn.timeline = function(opts) {\r\n timeline(this, opts);\r\n return this;\r\n };\r\n })(window.jQuery);\r\n}\r\n\r\nexport {\r\n timeline,\r\n timelineFromData,\r\n renderTimelineFromData,\r\n loadDataFromJson,\r\n processTimelineData,\r\n clearTimelineCache,\r\n createTimelineModal,\r\n openTimelineModal,\r\n closeTimelineModal,\r\n handleDeepLinking,\r\n navigateToNodeIndex\r\n};"],"names":["loaderState","count","startTime","removeTimer","overlayEl","modalState","modal","overlay","timelineRegistry","createTimelineModal","document","createElement","className","addEventListener","closeTimelineModal","innerHTML","closeBtn","querySelector","closeBottomBtn","e","stopPropagation","body","appendChild","key","classList","contains","openTimelineModal","itemEl","title","getAttribute","content","image","html","modalTitle","modalText","modalImage","textContent","src","alt","style","display","replace","setTimeout","add","overflow","remove","handleDeepLinking","containerSelector","urlParams","URLSearchParams","window","location","search","timelineId","get","nodeId","targetContainer","getElementById","console","warn","scrollIntoView","behavior","block","targetNode","itemIndex","Array","from","parentNode","children","indexOf","navigateToNodeIndex","container","index","id","tlData","setCurrentIndex","updatePosition","timelineBasePath","TimelineConfig","basePath","scripts","getElementsByTagName","i","length","dir","substring","lastIndexOf","showTimelineLoader","Date","now","clearTimeout","loader","spinner","hideTimelineLoader","elapsed","remaining","Math","max","removeOverlay","showTimelineError","errorType","details","errorInfo","message","solution","errorDiv","errorIcon","errorTitle","errorMessage","errorSolution","errorDetails","error","getColorBrightness","color","rgb","startsWith","hex","parseInt","matches","match","map","Number","applyTimelineColors","config","nodeColor","lineColor","navColor","setProperty","arrowColor","setAttribute","createArrowSVG","direction","timeline","collection","options","timelines","warningLabel","resizeTimer","winWidth","innerWidth","currentIndex","shouldHideLoader","defaultSettings","minWidth","type","defaultValue","horizontalStartPosition","acceptedValues","mode","moveItems","rtlMode","startIndex","verticalStartPosition","verticalTrigger","visibleItems","itemWrap","el","wrapper","classes","insertBefore","isElementInViewport","triggerPosition","rect","getBoundingClientRect","windowHeight","innerHeight","documentElement","clientHeight","defaultTrigger","triggerUnit","unit","triggerValue","value","trigger","top","left","clientWidth","height","width","addTransforms","transform","webkitTransform","msTransform","timelinePosition","tl","str","items","offsetLeft","scroller","setUpHorinzontalTimeline","settings","timelineEl","itemWidth","forEach","item","scrollerWidth","oddIndexTallest","evenIndexTallest","offsetHeight","transformString","setHeights","setHeightandWidths","viewportWidth","wrap","offsetWidth","itemsVisible","floor","prevArrow","nextArrow","topPosition","maxIndex","disabled","addNavigation","divider","removeChild","horizontalDivider","addHorizontalDivider","navArrows","querySelectorAll","arrowPrev","arrowNext","handleArrowClick","preventDefault","this","arrow","listeners","push","element","handler","slideTimeline","min","setUpTimelines","opacity","removeEventListener","observer","disconnect","removeAttribute","resetTimelines","lastVisibleIndex","observerOptions","rootMargin","threshold","IntersectionObserver","entries","entry","isIntersecting","target","observe","scrollHandler","setUpVerticalTimeline","timelineName","errorPart","data","dataset","Error","slice","call","Object","keys","candidate","undefined","minwidth","forceVerticalMode","forceverticalmode","settingName","getData","k","toLowerCase","triggerArray","triggerValid","hasAttribute","heading","trim","firstP","img","ensureInlineModalData","enhanceInlineItems","random","toString","substr","newWinWidth","renderTimelineFromData","itemsWrap","layoutMode","maxWidth","applyDataAttributes","existingHeading","previousElementSibling","it","onerror","textWrapper","para","displayText","createItemNode","timelineFromData","loadDataFromJson","url","cacheKey","cached","localStorage","getItem","cachedData","JSON","parse","fetch","then","res","ok","status","json","lastupdated","log","processTimelineData","setItem","stringify","catch","err","nodes","isArray","clearTimelineCache","removeItem","cleared","handleTimelineDeepLinking","navigateTimelineToNodeIndex","jsonUrl","split","selector","jQuery","fn","opts"],"mappings":"sCACO,MAAMA,EAAc,CACzBC,MAAO,EACPC,UAAW,EACXC,YAAa,KACbC,UAAW,MAGAC,EAAa,CACxBC,MAAO,KACPC,QAAS,MAIEC,EAAmB,CAAA,ECZzB,SAASC,IACd,GAAIJ,EAAWC,MAAO,OAEtBD,EAAWE,QAAUG,SAASC,cAAc,OAC5CN,EAAWE,QAAQK,UAAY,yBAC/BP,EAAWE,QAAQM,iBAAiB,QAASC,GAE7CT,EAAWC,MAAQI,SAASC,cAAc,OAC1CN,EAAWC,MAAMM,UAAY,iBAC7BP,EAAWC,MAAMS,UAAY,0aAW7B,MAAMC,EAAWX,EAAWC,MAAMW,cAAc,0BAC1CC,EAAiBb,EAAWC,MAAMW,cAAc,iCACtDD,EAASH,iBAAiB,QAASC,GACnCI,EAAeL,iBAAiB,QAASC,GAEzCT,EAAWC,MAAMO,iBAAiB,QAAS,SAASM,GAClDA,EAAEC,iBACJ,GAEAV,SAASW,KAAKC,YAAYjB,EAAWE,SACrCG,SAASW,KAAKC,YAAYjB,EAAWC,OAErCI,SAASG,iBAAiB,UAAW,SAASM,GAC9B,WAAVA,EAAEI,KAAoBlB,EAAWC,MAAMkB,UAAUC,SAAS,wBAC5DX,GAEJ,EACF,CAEO,SAASY,EAAkBC,GAC3BtB,EAAWC,OACdG,IAGF,MAAMmB,EAAQD,EAAOE,aAAa,oBAC5BC,EAAUH,EAAOE,aAAa,sBAC9BE,EAAQJ,EAAOE,aAAa,oBAC5BG,EAAOL,EAAOE,aAAa,mBAE3BI,EAAa5B,EAAWC,MAAMW,cAAc,0BAC5CiB,EAAY7B,EAAWC,MAAMW,cAAc,yBAC3CkB,EAAa9B,EAAWC,MAAMW,cAAc,0BAElDgB,EAAWG,YAAcR,GAAS,GAE9BG,GACFI,EAAWE,IAAMN,EACjBI,EAAWG,IAAMV,GAAS,GAC1BO,EAAWI,MAAMC,QAAU,SAE3BL,EAAWI,MAAMC,QAAU,OAI3BN,EAAUnB,UADRiB,IAEOF,EACa,MAAQA,EAAQW,QAAQ,MAAO,WAAa,OAE5C,IAGxBC,WAAW,WACTrC,EAAWC,MAAMkB,UAAUmB,IAAI,uBAC/BtC,EAAWE,QAAQiB,UAAUmB,IAAI,uBACjCjC,SAASW,KAAKkB,MAAMK,SAAW,QACjC,EAAG,GACL,CAEO,SAAS9B,IACVT,EAAWC,QACbD,EAAWC,MAAMkB,UAAUqB,OAAO,uBAClCxC,EAAWE,QAAQiB,UAAUqB,OAAO,uBACpCnC,SAASW,KAAKkB,MAAMK,SAAW,GAEnC,CCpFO,SAASE,EAAkBC,GAChC,MAAMC,EAAY,IAAIC,gBAAgBC,OAAOC,SAASC,QAChDC,EAAaL,EAAUM,IAAI,YAC3BC,EAASP,EAAUM,IAAI,MAC7B,IAAKC,EAAQ,OAEb,IAAIC,EAOJ,GALEA,EADEH,EACgB3C,SAAS+C,eAAeJ,GAExB3C,SAASO,cAAc8B,IAGtCS,EAEH,YADAE,QAAQC,KAAK,uCAAwCN,GAAcN,GAIrES,EAAgBI,eAAe,CAAEC,SAAU,SAAUC,MAAO,UAE5D,MAAMC,EAAaP,EAAgBvC,cAAc,kBAAoBsC,EAAS,MAC1EQ,GACFrB,WAAW,WACTqB,EAAWvC,UAAUmB,IAAI,0BACzB,MAAMqB,EAAYC,MAAMC,KAAKH,EAAWI,WAAWC,UAAUC,QAAQN,GACrEO,EAAoBd,EAAiBQ,EACvC,EAAG,IAEP,CAEO,SAASM,EAAoBC,EAAWC,GAC7C,IAAKD,EAAW,OAChB,MAAMlB,EAAakB,EAAUE,IAAMF,EAAU1C,aAAa,oBAC1D,IAAKwB,EAEH,YADAK,QAAQC,KAAK,iDAIf,MAAMe,EAASlE,EAAiB6C,GAC3BqB,EAKAH,EAAU/C,UAAUC,SAAS,yBAI9BiD,EAAOC,iBAAmBD,EAAOE,iBACnCF,EAAOC,gBAAgBH,GACvBE,EAAOE,kBAVPlB,QAAQC,KAAK,kCAAmCN,EAYpD,CCpDO,MAAMwB,EAAmB,WAE9B,GAAsB,oBAAX3B,QACPA,OAAO4B,gBACP5B,OAAO4B,eAAeC,SACxB,OAAO7B,OAAO4B,eAAeC,SAG/B,MAAMC,EAAUtE,SAASuE,qBAAqB,UAC9C,IAAK,IAAIC,EAAI,EAAGA,EAAIF,EAAQG,OAAQD,IAAK,CACvC,MAAM7C,EAAM2C,EAAQE,GAAG7C,KAAO,GAC9B,IAAKA,EAAK,SACV,MAAM+C,EAAM/C,EAAIgD,UAAU,EAAGhD,EAAIiD,YAAY,MAC7C,IAAuC,IAAnCjD,EAAIgC,QAAQ,mBAEd,OAAOe,EAAI3C,QAAQ,QAAS,eAE9B,IAAmC,IAA/BJ,EAAIgC,QAAQ,eAEd,OAAOe,EAAI3C,QAAQ,MAAO,UAE9B,CAEA,MAAO,eACR,CAxB+B,GCCzB,SAAS8C,IAEd,GADAvF,EAAYC,OAAS,EACK,IAAtBD,EAAYC,MAAa,OAE7BD,EAAYE,UAAYsF,KAAKC,MAEzBzF,EAAYG,cACduF,aAAa1F,EAAYG,aACzBH,EAAYG,YAAc,MAG5B,MAAMI,EAAUG,SAASC,cAAc,OACvCJ,EAAQK,UAAY,2BAEpB,MAAM+E,EAASjF,SAASC,cAAc,OACtCgF,EAAO/E,UAAY,mBAEnB,MAAMgF,EAAUlF,SAASC,cAAc,OACvCiF,EAAQvD,IAAMwC,EAAmB,eACjCe,EAAQtD,IAAM,aACdsD,EAAQhE,MAAQ,aAChBgE,EAAQhF,UAAY,2BAEpB+E,EAAOrE,YAAYsE,GACnBrF,EAAQe,YAAYqE,GAEpBjF,SAASW,KAAKC,YAAYf,GAC1BP,EAAYI,UAAYG,CAC1B,CAEO,SAASsF,IACd,GAAI7F,EAAYC,OAAS,EAAG,OAE5B,GADAD,EAAYC,OAAS,EACjBD,EAAYC,MAAQ,EAAG,OAE3B,MAAM6F,EAAUN,KAAKC,MAAQzF,EAAYE,UAEnC6F,EAAYC,KAAKC,IAAI,EDXH,KCWcH,GAEhCI,EAAgB,WAChBlG,EAAYI,YACdJ,EAAYI,UAAUyC,SACtB7C,EAAYI,UAAY,MAE1BJ,EAAYG,YAAc,IAC5B,EAEIH,EAAYG,cACduF,aAAa1F,EAAYG,aACzBH,EAAYG,YAAc,MAGxB4F,EAAY,EACd/F,EAAYG,YAAcuC,WAAWwD,EAAeH,GAEpDG,GAEJ,CCzDO,SAASC,EAAkB5B,EAAW6B,EAAWC,GACtD,IAAK9B,EAAW,OAEhB,MAuBM+B,EAvBgB,CACpB,YAAa,CACX1E,MAAO,oCACP2E,QAAS,oGACTC,SAAU,sFAEZ,aAAc,CACZ5E,MAAO,wBACP2E,QAAS,2DACTC,SAAU,sGAEZ,kBAAmB,CACjB5E,MAAO,6BACP2E,QAAS,0EACTC,SAAU,6FAEZ,iBAAkB,CAChB5E,MAAO,wBACP2E,QAAS,0DACTC,SAAU,gGAIkBJ,IAAc,CAC5CxE,MAAO,iBACP2E,QAAS,gEACTC,SAAU,sDAGZX,IACAtB,EAAUxD,UAAY,GAEtB,MAAM0F,EAAW/F,SAASC,cAAc,OACxC8F,EAAS7F,UAAY,kBAErB,MAAM8F,EAAYhG,SAASC,cAAc,OACzC+F,EAAUrE,IAAMwC,EAAmB,aACnC6B,EAAUpE,IAAM,QAChBoE,EAAU9F,UAAY,uBAEtB,MAAM+F,EAAajG,SAASC,cAAc,MAC1CgG,EAAW/F,UAAY,wBACvB+F,EAAWvE,YAAckE,EAAU1E,MAEnC,MAAMgF,EAAelG,SAASC,cAAc,KAC5CiG,EAAahG,UAAY,0BACzBgG,EAAaxE,YAAckE,EAAUC,QAErC,MAAMM,EAAgBnG,SAASC,cAAc,KAI7C,GAHAkG,EAAcjG,UAAY,2BAC1BiG,EAAc9F,UAAY,8BAAgCuF,EAAUE,SAEhEH,EAAS,CACX,MAAMS,EAAepG,SAASC,cAAc,KAC5CmG,EAAalG,UAAY,0BACzBkG,EAAa/F,UAAY,6BAA+BsF,EACxDI,EAASnF,YAAYwF,EACvB,CAEAL,EAASnF,YAAYoF,GACrBD,EAASnF,YAAYqF,GACrBF,EAASnF,YAAYsF,GACrBH,EAASnF,YAAYuF,GAErBtC,EAAUjD,YAAYmF,GAEtB/C,QAAQqD,MAAM,mBAAqBX,EAAY,KAAME,EAAUC,QAASF,GAAW,GACrF,CCnEO,SAASW,EAAmBC,GACjC,IAAIC,EACJ,IAAKD,GAA0B,iBAAVA,EAAoB,OAAO,IAEhD,GAAIA,EAAME,WAAW,KAAM,CACzB,IAAIC,EAAMH,EAAM5B,UAAU,GACP,IAAf+B,EAAIjC,SACNiC,EAAMA,EAAI,GAAKA,EAAI,GAAKA,EAAI,GAAKA,EAAI,GAAKA,EAAI,GAAKA,EAAI,IAKzDF,EAAM,CAHIG,SAASD,EAAI/B,UAAU,EAAG,GAAI,IAC9BgC,SAASD,EAAI/B,UAAU,EAAG,GAAI,IAC9BgC,SAASD,EAAI/B,UAAU,EAAG,GAAI,IAE1C,KAAO,KAAI4B,EAAME,WAAW,OAI1B,OAAO,IAJ2B,CAClC,MAAMG,EAAUL,EAAMM,MAAM,QAC5BL,EAAMI,EAAUA,EAAQE,IAAIC,QAAU,CAAC,IAAK,IAAK,IACnD,CAEA,CAEA,OAAiB,IAATP,EAAI,GAAoB,IAATA,EAAI,GAAoB,IAATA,EAAI,IAAY,GACxD,CCzBO,SAASQ,EAAoBnD,EAAWoD,GAC7C,IAAIC,EAAYD,EAAOC,WAAa,KAChCC,EAAYF,EAAOE,WAAa,KACpC,MAAMC,EAAWH,EAAOG,UAAY,KAWpC,GATIF,IAAcC,IAAWA,EAAYD,GACrCC,IAAcD,IAAWA,EAAYC,GAErCD,GACFrD,EAAUhC,MAAMwF,YAAY,wBAAyBH,GAEnDC,GACFtD,EAAUhC,MAAMwF,YAAY,wBAAyBF,GAEnDC,EAAU,CACZvD,EAAUhC,MAAMwF,YAAY,uBAAwBD,GACpDvD,EAAUhC,MAAMwF,YAAY,wBDhBXf,ECgBqDc,GDfpD,IAAM,qBAAuB,4BCgB/C,MACME,EADahB,EAAmBc,GACN,IAAM,OAAS,OAC/CvD,EAAUhC,MAAMwF,YAAY,yBAA0BC,GACtDzD,EAAU0D,aAAa,mBAAoBD,EAC7C,CACF,CCqBA,SAASE,EAAeC,EAAWlB,GACjC,MAAkB,SAAdkB,EACK,gIAAkIlB,EAAQ,iGAE5I,gIAAkIA,EAAQ,+FACnJ,CAEO,SAASmB,EAASC,EAAYC,GACnC,MAAMC,EAAY,GACZC,EAAe,YACrB,IACIC,EADAC,EAAWxF,OAAOyF,WAElBC,EAAe,EAGnBrD,IACA,IAAIsD,GAAmB,EAEvB,MAAMC,EAAkB,CACtBC,SAAU,CAAEC,KAAM,UAAWC,aAAc,KAC3CC,wBAAyB,CAAEF,KAAM,SAAUG,eAAgB,CAAC,SAAU,OAAQF,aAAc,OAC5FG,KAAM,CAAEJ,KAAM,SAAUG,eAAgB,CAAC,aAAc,YAAaF,aAAc,YAClFI,UAAW,CAAEL,KAAM,UAAWC,aAAc,GAC5CK,QAAS,CAAEN,KAAM,UAAWG,eAAgB,EAAC,GAAM,GAAQF,cAAc,GACzEM,WAAY,CAAEP,KAAM,UAAWC,aAAc,GAC7CO,sBAAuB,CAAER,KAAM,SAAUG,eAAgB,CAAC,OAAQ,SAAUF,aAAc,QAC1FQ,gBAAiB,CAAET,KAAM,SAAUC,aAAc,OACjDS,aAAc,CAAEV,KAAM,UAAWC,aAAc,IAWjD,SAASU,EAASC,EAAIC,EAASC,GAC7BD,EAAQrI,UAAUmB,IAAImH,GACtBF,EAAGzF,WAAW4F,aAAaF,EAASD,GACpCC,EAAQvI,YAAYsI,EACtB,CASA,SAASI,EAAoBJ,EAAIK,GAC/B,MAAMC,EAAON,EAAGO,wBACVC,EAAelH,OAAOmH,aAAe3J,SAAS4J,gBAAgBC,aAC9DC,EAAiB1B,EAAgBW,gBAAgBR,aAAa1B,MAAM,mBAC1E,IAAIkD,EAAcR,EAAgBS,KAC9BC,EAAeV,EAAgBW,MAC/BC,EAAUT,EAUd,MAToB,OAAhBK,GAAwBE,GAAgBP,IAC1C1G,QAAQC,KAAK,mIACVgH,EAAcF,GAAeD,GAEd,OAAhBC,EACFI,EAAUxD,SAASwD,EAAUF,EAAc,IAClB,MAAhBF,IACTI,EAAUxD,SAASwD,IAAY,IAAMF,GAAgB,KAAM,KAG3DT,EAAKY,KAAOD,GACZX,EAAKa,OAAS7H,OAAOyF,YAAcjI,SAAS4J,gBAAgBU,cAC3Dd,EAAKY,IAAMZ,EAAKe,QAAW,GAC3Bf,EAAKa,KAAOb,EAAKgB,OAAU,CAEhC,CAEA,SAASC,EAAcvB,EAAIwB,GACzBxB,EAAGrH,MAAM8I,gBAAkBD,EAC3BxB,EAAGrH,MAAM+I,YAAcF,EACvBxB,EAAGrH,MAAM6I,UAAYA,CACvB,CAgPA,SAASG,EAAiBC,GACxB,MACMC,EAAM,gBADKD,EAAGE,MAAM9C,GAAc+C,sBAExCR,EAAcK,EAAGI,SAAUH,EAC7B,CA2CA,SAASI,EAAyBL,GAE9B5C,EADE4C,EAAGM,SAASxC,QACCkC,EAAGE,MAAMvG,OAASqG,EAAGM,SAASpC,aAAe8B,EAAGE,MAAMvG,OAASqG,EAAGM,SAASpC,aAAe,EAE1F8B,EAAGM,SAASvC,WAE7BiC,EAAGO,WAAWvK,UAAUmB,IAAI,wBAnJ9B,SAA4B6I,GA8CtBtI,OAAOyF,WAAa6C,EAAGM,SAAS/C,WA5ClCyC,EAAGQ,UAAY,IACfR,EAAGE,MAAMO,QAASC,IAChBA,EAAK3J,MAAM2I,MAAQ,GAAGM,EAAGQ,gBAE3BR,EAAGW,cAAgBX,EAAGQ,UAAYR,EAAGE,MAAMvG,OAC3CqG,EAAGI,SAASrJ,MAAM2I,MAAQ,GAAGM,EAAGW,kBAGlC,WACE,IAAIC,EAAkB,EAClBC,EAAmB,EACvBb,EAAGE,MAAMO,QAAQ,CAACC,EAAMhH,KACtBgH,EAAK3J,MAAM0I,OAAS,OACpB,MAAMA,EAASiB,EAAKI,aAChBpH,EAAI,GAAM,EACZmH,EAAmBpB,EAASoB,EAAmBpB,EAASoB,EAExDD,EAAkBnB,EAASmB,EAAkBnB,EAASmB,IAI1D,MAAMG,EAAkB,cAAcF,OACtCb,EAAGE,MAAMO,QAAQ,CAACC,EAAMhH,KAClBA,EAAI,GAAM,GACZgH,EAAK3J,MAAM0I,OAAS,GAAGoB,MACqB,WAAxCb,EAAGM,SAAS5C,yBACdgD,EAAK1K,UAAUmB,IAAI,0BACnBwI,EAAce,EAAMK,IAEpBL,EAAK1K,UAAUmB,IAAI,yBAGrBuJ,EAAK3J,MAAM0I,OAAS,GAAGmB,MACqB,WAAxCZ,EAAGM,SAAS5C,yBACdgD,EAAK1K,UAAUmB,IAAI,0BACnBwI,EAAce,EAAMK,IAEpBL,EAAK1K,UAAUmB,IAAI,0BAIzB6I,EAAGI,SAASrJ,MAAM0I,OAAS,GAAGoB,EAAmBD,KACnD,CAIEI,GAEJ,CAkGEC,CAAmBjB,GACnBD,EAAiBC,GAjGnB,SAAuBA,GACrB,MAAMkB,EAAgBlB,EAAGmB,KAAKC,YACxBC,EAAe7G,KAAK8G,MAAMJ,EAAgBlB,EAAGQ,WAEnD,GAAIR,EAAGE,MAAMvG,OAAS0H,EAAc,CAClC,MAAME,EAAYrM,SAASC,cAAc,UACnCqM,EAAYtM,SAASC,cAAc,UACnCsM,EAAczB,EAAGE,MAAM,GAAGY,aAChCS,EAAUnM,UAAY,gDACtBoM,EAAUpM,UAAY,gDACtBmM,EAAU3K,YAAc,WACxB4K,EAAU5K,YAAc,OACxB2K,EAAUxK,MAAMuI,IAAM,GAAGmC,MACzBD,EAAUzK,MAAMuI,IAAM,GAAGmC,MAEzB,MAAMjF,EAAawD,EAAGO,WAAWlK,aAAa,qBAAuB,OACrEkL,EAAUhM,UAAYmH,EAAe,OAAQF,GAC7CgF,EAAUjM,UAAYmH,EAAe,QAASF,GAE9C,MAAMkF,EAAWlH,KAAKC,IAAI,EAAGuF,EAAGE,MAAMvG,OAAS0H,GAC1B,IAAjBjE,EACFmE,EAAUI,UAAW,EACZvE,GAAgBsE,IACzBF,EAAUG,UAAW,GAEvB3B,EAAGO,WAAWzK,YAAYyL,GAC1BvB,EAAGO,WAAWzK,YAAY0L,EAC5B,CACF,CAsEEI,CAAc5B,GApEhB,SAA8BA,GAC5B,MAAM6B,EAAU7B,EAAGO,WAAW9K,cAAc,qBACxCoM,GACF7B,EAAGO,WAAWuB,YAAYD,GAE5B,MAAMJ,EAAczB,EAAGE,MAAM,GAAGY,aAC1BiB,EAAoB7M,SAASC,cAAc,QACjD4M,EAAkB3M,UAAY,mBAC9B2M,EAAkBhL,MAAMuI,IAAM,GAAGmC,MACjCzB,EAAGO,WAAWzK,YAAYiM,EAC5B,CA2DEC,CAAqBhC,GAnDvB,SAAuBA,GACrB,MAAMiC,EAAYjC,EAAGO,WAAW2B,iBAAiB,wBAC3CC,EAAYnC,EAAGO,WAAW9K,cAAc,8BACxC2M,EAAYpC,EAAGO,WAAW9K,cAAc,8BAExCyL,EAAgBlB,EAAGmB,KAAKC,YACxBC,EAAe7G,KAAK8G,MAAMJ,EAAgBlB,EAAGQ,WAC7CkB,EAAWlH,KAAKC,IAAI,EAAGuF,EAAGE,MAAMvG,OAAS0H,GAEzCxD,EAAYhC,SAASmE,EAAGM,SAASzC,UAAW,IAE5CwE,EAAmB,SAAS1M,GAChCA,EAAE2M,iBACF3M,EAAEC,kBAEE2M,KAAKZ,WAITvE,EAAemF,KAAKvM,UAAUC,SAAS,6BAAgCmH,GAAgBS,EAAcT,GAAgBS,EAChG,IAAjBT,GAAsBA,EAAe,GACvCA,EAAe,EACf+E,EAAUR,UAAW,EACrBS,EAAUT,UAAW,GACZvE,IAAiBsE,GAAYtE,EAAesE,GACrDtE,EAAesE,EACfS,EAAUR,UAAW,EACrBS,EAAUT,UAAW,IAErBQ,EAAUR,UAAW,EACrBS,EAAUT,UAAW,GAEvB5B,EAAiBC,GACnB,EAEAvH,MAAMC,KAAKuJ,GAAWxB,QAAS+B,IAC7BA,EAAMnN,iBAAiB,QAASgN,GAChCrC,EAAGyC,UAAUC,KAAK,CAAEC,QAASH,EAAOhF,KAAM,QAASoF,QAASP,KAEhE,CAaEQ,CAAc7C,GAEd,MAAMnI,EAAamI,EAAGO,WAAWtH,IAAM+G,EAAGO,WAAWlK,aAAa,oBAC9DwB,IACF7C,EAAiB6C,GAAc,CAC7BsB,gBAAiB,SAASH,GACxB,MAAMkI,EAAgBlB,EAAGmB,KAAKC,YACxBC,EAAe7G,KAAK8G,MAAMJ,EAAgBlB,EAAGQ,WAC7CkB,EAAWlH,KAAKC,IAAI,EAAGuF,EAAGE,MAAMvG,OAAS0H,GAC/CjE,EAAe5C,KAAKC,IAAI,EAAGD,KAAKsI,IAAI9J,EAAO0I,GAC7C,EACAtI,eAAgB,WACd2G,EAAiBC,GACjB,MAAMmC,EAAYnC,EAAGO,WAAW9K,cAAc,8BACxC2M,EAAYpC,EAAGO,WAAW9K,cAAc,8BAC9C,GAAI0M,GAAaC,EAAW,CAC1B,MAAMlB,EAAgBlB,EAAGmB,KAAKC,YACxBC,EAAe7G,KAAK8G,MAAMJ,EAAgBlB,EAAGQ,WAC7CkB,EAAWlH,KAAKC,IAAI,EAAGuF,EAAGE,MAAMvG,OAAS0H,GAC/Cc,EAAUR,SAA4B,IAAjBvE,EACrBgF,EAAUT,SAAWvE,GAAgBsE,CACvC,CACF,GAGN,CAwFA,SAASqB,IACPhG,EAAU0D,QAAST,IACjBA,EAAGO,WAAWxJ,MAAMiM,QAAU,EACzBhD,EAAGO,WAAWvK,UAAUC,SAAS,qBACvB+J,EAAGE,MAjcdO,QAASC,IACbvC,EAASuC,EAAKjL,cAAc,sBAAuBP,SAASC,cAAc,OAAQ,2BAClFgJ,EAASuC,EAAKjL,cAAc,4BAA6BP,SAASC,cAAc,OAAQ,2BAga5F,SAAwB6K,GAElBA,EAAGyC,WAAazC,EAAGyC,UAAU9I,OAAS,IACxCqG,EAAGyC,UAAUhC,QAAQ,EAAGkC,UAASnF,OAAMoF,cACrCD,EAAQM,oBAAoBzF,EAAMoF,KAEpC5C,EAAGyC,UAAY,IAIbzC,EAAGkD,WACLlD,EAAGkD,SAASC,aACZnD,EAAGkD,SAAW,MAGhBlD,EAAGO,WAAWvK,UAAUqB,OAAO,uBAAwB,oBACvD2I,EAAGI,SAASgD,gBAAgB,SAC5BpD,EAAGE,MAAMO,QAASC,IAChBA,EAAK0C,gBAAgB,SACrB1C,EAAK1K,UAAUqB,OAAO,WAAY,SAAU,uBAAwB,2BAEtE,MAAM4K,EAAYjC,EAAGO,WAAW2B,iBAAiB,wBACjDzJ,MAAMC,KAAKuJ,GAAWxB,QAAS+B,IAC7BA,EAAM7J,WAAWmJ,YAAYU,IAEjC,CAQIa,CAAerD,GACXtI,OAAOyF,YAAc6C,EAAGM,SAAS/C,UACnCyC,EAAGO,WAAWvK,UAAUmB,IAAI,oBAEL,eAArB6I,EAAGM,SAAS1C,MAAyBlG,OAAOyF,WAAa6C,EAAGM,SAAS/C,SACvE8C,EAAyBL,GAjG/B,SAA+BA,GAC7B,IAAIsD,EAAmB,EACvBtD,EAAGE,MAAMO,QAAQ,CAACC,EAAMhH,KACtBgH,EAAK1K,UAAUqB,OAAO,WAAY,WAC7BmH,EAAoBkC,EAAMV,EAAGM,SAASrC,kBAAoBvE,EAAI,EACjEgH,EAAK1K,UAAUmB,IAAI,YAEnBmM,EAAmB5J,EAGjBA,EAAI,IAD8C,SAAtCsG,EAAGM,SAAStC,sBAAmC,EAAI,IAC1CtG,OAAOyF,WAAa6C,EAAGM,SAAS/C,SACvDmD,EAAK1K,UAAUmB,IAAI,yBAEnBuJ,EAAK1K,UAAUmB,IAAI,0BAGvB,IAAK,IAAIuC,EAAI,EAAGA,EAAI4J,EAAkB5J,GAAK,EACzCsG,EAAGE,MAAMxG,GAAG1D,UAAUqB,OAAO,WAAY,UAI3C,GAAI,yBAA0BK,OAAQ,CACpC,MAAM6L,EAAkB,CACtBC,WAAiD,MAArCxD,EAAGM,SAASrC,gBAAgBiB,KACpC,GAAGc,EAAGM,SAASrC,gBAAgBmB,SAC/B,GAAGY,EAAGM,SAASrC,gBAAgBmB,UACnCqE,UAAW,KAGPP,EAAW,IAAIQ,qBAAsBC,IACzCA,EAAQlD,QAASmD,IACXA,EAAMC,gBACRD,EAAME,OAAO9N,UAAUmB,IAAI,aAG9BoM,GAEHvD,EAAGE,MAAMO,QAASC,IACZA,EAAK1K,UAAUC,SAAS,aAC1BiN,EAASa,QAAQrD,KAKrBV,EAAGkD,SAAWA,CAChB,KAAO,CAEL,MAAMc,EAAgB,KACpBhE,EAAGE,MAAMO,QAASC,IACZlC,EAAoBkC,EAAMV,EAAGM,SAASrC,kBACxCyC,EAAK1K,UAAUmB,IAAI,aAIzBO,OAAOrC,iBAAiB,SAAU2O,GAClChE,EAAGyC,UAAUC,KAAK,CAAEC,QAASjL,OAAQ8F,KAAM,SAAUoF,QAASoB,GAChE,CACF,CA0CMC,CAAsBjE,GAExBA,EAAGO,WAAWvK,UAAUmB,IAAI,sBAG9BD,WAAW,KACT6F,EAAU0D,QAAST,IACjBA,EAAGO,WAAWxJ,MAAMiM,QAAU,KAE/B,KAEC3F,IACFhD,IACAgD,GAAmB,EAEvB,CAzSIR,EAAWlD,QACblB,MAAMC,KAAKmE,GAAY4D,QA7IzB,SAAyBF,GACvB,MAAM2D,EAAe3D,EAAWtH,GAAK,IAAIsH,EAAWtH,KAAO,IAAIsH,EAAWnL,YACpE+O,EAAY,+CACZC,EAAO7D,EAAW8D,QACxB,IAAIlD,EACAf,EACAF,EACJ,MAAMI,EAAW,CAAA,EAEjB,IAEE,GADAa,EAAOZ,EAAW9K,cAAc,oBAC3B0L,EACH,MAAM,IAAImD,MAAM,GAAGtH,qBAAgCmH,KAAaD,KAGhE,GADA9D,EAAWe,EAAK1L,cAAc,qBACzB2K,EACH,MAAM,IAAIkE,MAAM,GAAGtH,sBAAiCmH,qBAEpDjE,EAAQ,GAAGqE,MAAMC,KAAKpE,EAASxH,SAAU,EAG/C,CAAE,MAAOjD,GAGP,OAFAuC,QAAQC,KAAKxC,EAAEoF,SACfJ,EAAkB4F,EAAY,kBAAmB5K,EAAEoF,UAC5C,CACT,CAEA0J,OAAOC,KAAKpH,GAAiBmD,QAAS1K,IAGpC,GAFAuK,EAASvK,GAAOuH,EAAgBvH,GAAK0H,aAEzB,aAAR1H,EAAoB,CACtB,IAAI4O,OACkBC,IAAlBR,EAAK7G,WAAwBoH,EAAYP,EAAK7G,eAC5BqH,IAAlBR,EAAKS,WAAwBF,EAAYP,EAAKS,eACnBD,IAA3BR,EAAKU,oBAAiCH,EAAYP,EAAKU,wBAC5BF,IAA3BR,EAAKW,oBAAiCJ,EAAYP,EAAKW,wBACzCH,IAAdD,GAA2B7H,SACJ8H,IAArB9H,EAAQS,SAAwBoH,EAAY7H,EAAQS,cACjBqH,IAA9B9H,EAAQgI,oBAAiCH,EAAY7H,EAAQgI,yBAEtDF,IAAdD,IAAyBrE,EAAS/C,SAAWoH,EACnD,MACMP,EAAKrO,GACPuK,EAASvK,GAAOqO,EAAKrO,GACZ+G,QAA4B8H,IAAjB9H,EAAQ/G,KAC5BuK,EAASvK,GAAO+G,EAAQ/G,IAhGhC,IAAoBqJ,EAAO4F,EAoGW,YAA9B1H,EAAgBvH,GAAKyH,KAClB8C,EAASvK,KArGOiP,EAqG4BjP,EApGhC,iBADHqJ,EAqGoBkB,EAASvK,KApGdqJ,EAAQ,GAAM,IAC7ClH,QAAQC,KAAK,GAAG6E,gBAA2BoC,+BAAmC4F,yBACvE,MAmGH1E,EAASvK,GAAOuH,EAAgBvH,GAAK0H,cAEA,WAA9BH,EAAgBvH,GAAKyH,MAC1BF,EAAgBvH,GAAK4H,iBAAiF,IAA/DL,EAAgBvH,GAAK4H,eAAe9E,QAAQyH,EAASvK,MAC9FmC,QAAQC,KAAK,GAAG6E,gBAA2BsD,EAASvK,gCAAkCA,0BACtFuK,EAASvK,GAAOuH,EAAgBvH,GAAK0H,gBAK3C,WACE,MAAM2G,EAAO7D,EAAW8D,QAClBY,EAAU,SAASC,GACvB,YAAmBN,IAAZR,EAAKc,GAAmBd,EAAKc,QAAqCN,IAA/BR,EAAKc,GAAKA,EAAEC,eAA+Bf,EAAKc,EAAEC,oBAAiBP,CAC/G,EACA,IAAIxI,EAAY6I,EAAQ,aACpB5I,EAAY4I,EAAQ,aACpB3I,EAAW2I,EAAQ,YACnBnI,SACwB8H,IAAtB9H,EAAQV,YAAyBA,EAAYU,EAAQV,gBAC/BwI,IAAtB9H,EAAQT,YAAyBA,EAAYS,EAAQT,gBAChCuI,IAArB9H,EAAQR,WAAwBA,EAAWQ,EAAQR,YAErDF,GAAaC,GAAaC,IAC5BJ,EAAoBqE,EAAY,CAAEnE,YAAWC,YAAWC,YAE3D,CAhBD,GAkBA,MAAM0C,EAAiB1B,EAAgBW,gBAAgBR,aAAa1B,MAAM,mBACpEqJ,EAAe9E,EAASrC,gBAAgBlC,MAAM,mBACpD,IAAI,CAAGoD,EAAcF,GAAemG,EAChCC,GAAe,EACdlG,IACHjH,QAAQC,KAAK,GAAG6E,mEAChBqI,GAAe,GAEG,OAAhBpG,GAAwC,MAAhBA,IAC1B/G,QAAQC,KAAK,GAAG6E,wEAChBqI,GAAe,GAEG,MAAhBpG,IAAwBE,EAAe,KAAOA,EAAe,IAC/DjH,QAAQC,KAAK,GAAG6E,gGAChBqI,GAAe,GACU,OAAhBpG,GAAwBE,EAAe,IAChDjH,QAAQC,KAAK,GAAG6E,iFAChBqI,GAAe,IAGI,IAAjBA,MACClG,EAAcF,GAAeD,GAGlCsB,EAASrC,gBAAkB,CACzBiB,KAAMD,EACNG,MAAOD,GAGLmB,EAASzC,UAAYyC,EAASpC,eAChChG,QAAQC,KAAK,GAAG6E,+BAA0CsD,EAASzC,2DAA2DyC,EAASpC,qEACvIoC,EAASzC,UAAYyC,EAASpC,cAG5BoC,EAASvC,WAAcmC,EAAMvG,OAAS2G,EAASpC,cAAiBgC,EAAMvG,OAAS2G,EAASpC,cAC1FhG,QAAQC,KAAK,GAAG6E,oDAA+DkD,EAAMvG,OAAS2G,EAASpC,gDAAgDgC,EAAMvG,OAAS2G,EAASpC,uCAC/KoC,EAASvC,WAAamC,EAAMvG,OAAS2G,EAASpC,cACrCgC,EAAMvG,QAAU2G,EAASpC,cAClChG,QAAQC,KAAK,GAAG6E,iHAChBsD,EAASvC,WAAa,GACbuC,EAASvC,WAAa,IAC/B7F,QAAQC,KAAK,GAAG6E,oDAA+DkD,EAAMvG,OAAS2G,EAASpC,yEACvGoC,EAASvC,WAAa,GA1N5B,SAA4BwC,EAAYL,GACjCA,GAAUA,EAAMvG,QACrBuG,EAAMO,QAAQ,SAASC,GACyB,MAA1CA,EAAKrK,aAAa,sBA1B1B,SAA+BF,GAC7B,IAAKA,EAAQ,OACb,MAAMG,EAAUH,EAAOV,cAAc,uBAAyBU,EAC9D,IAAKA,EAAOmP,aAAa,oBAAqB,CAC5C,MAAMC,EAAUjP,EAAQb,cAAc,qBAClC8P,GAAWA,EAAQ3O,aACrBT,EAAOsG,aAAa,mBAAoB8I,EAAQ3O,YAAY4O,OAEhE,CACA,IAAKrP,EAAOmP,aAAa,sBAAuB,CAC9C,MAAMG,EAASnP,EAAQb,cAAc,KACjCgQ,GAAUA,EAAO7O,aACnBT,EAAOsG,aAAa,qBAAsBgJ,EAAO7O,YAAY4O,OAEjE,CACA,IAAKrP,EAAOmP,aAAa,oBAAqB,CAC5C,MAAMI,EAAMpP,EAAQb,cAAc,OAC9BiQ,GAAOA,EAAIrP,aAAa,QAC1BF,EAAOsG,aAAa,mBAAoBiJ,EAAIrP,aAAa,OAE7D,CACF,CAMIsP,CAAsBjF,IACLA,EAAK4E,aAAa,qBAAuB5E,EAAK4E,aAAa,uBAAyB5E,EAAK4E,aAAa,qBAAuB5E,EAAK4E,aAAa,sBAE9J5E,EAAKrL,iBAAiB,QAAS,SAASM,GACtCA,EAAE2M,iBACFpM,EAAkBwK,EACpB,GACAA,EAAKjE,aAAa,mBAAoB,MAE1C,EACF,CA+MImJ,CAAmBrF,EAAYL,GAE1BK,EAAWtH,IACdsH,EAAW9D,aAAa,mBAAoB,YAAczC,KAAKC,MAAQ,IAAMO,KAAKqL,SAASC,SAAS,IAAIC,OAAO,EAAG,IAGpHhJ,EAAU2F,KAAK,CACbnC,aACAY,OACAf,WACAF,QACAI,WACAmC,UAAW,IAEf,GA6SAM,IAEArL,OAAOrC,iBAAiB,SAAU,KAChC6E,aAAa+C,GACbA,EAAc/F,WAAW,KACvB,MAAM8O,EAActO,OAAOyF,WACvB6I,IAAgB9I,IAClB6F,IACA7F,EAAW8I,IAEZ,MAEP,CCreO,SAASC,EAAuB1O,EAAmB6M,EAAMjI,GAC9D,MAAMpD,EAAY7D,SAASO,cAAc8B,GACzC,IAAKwB,EAAW,OAEhB,IAAImN,EAAYnN,EAAUtD,cAAc,oBACxC,GAAKyQ,EAQHA,EAAU3Q,UAAY,OARR,CACd,MAAM4L,EAAOjM,SAASC,cAAc,OACpCgM,EAAK/L,UAAY,iBACjB8Q,EAAYhR,SAASC,cAAc,OACnC+Q,EAAU9Q,UAAY,kBACtB+L,EAAKrL,YAAYoQ,GACjBnN,EAAUjD,YAAYqL,EACxB,CAIA,GAAIhF,IAhCN,SAA6BpD,EAAWoD,GAClCA,EAAOgK,YACTpN,EAAU0D,aAAa,YAAaN,EAAOgK,iBAEjBvB,IAAxBzI,EAAO+B,cACTnF,EAAU0D,aAAa,qBAAsBN,EAAO+B,mBAE9B0G,IAApBzI,EAAOoB,WACTxE,EAAU0D,aAAa,gBAAiBN,EAAOoB,UAC/CxE,EAAU0D,aAAa,2BAA4BN,EAAOoB,gBAEpCqH,IAApBzI,EAAOiK,UACTrN,EAAU0D,aAAa,gBAAiBN,EAAOiK,SAEnD,CAmBIC,CAAoBtN,EAAWoD,GAC/BD,EAAoBnD,EAAWoD,GAE3BA,EAAO+H,cAA+C,KAA/B/H,EAAO+H,aAAasB,QAAe,CAC5D,MAAMc,EAAkBvN,EAAUwN,uBAClC,GAAID,GAAmBA,EAAgBtQ,UAAUC,SAAS,qBACxDqQ,EAAgB1P,YAAcuF,EAAO+H,iBAChC,CACL,MAAMqB,EAAUrQ,SAASC,cAAc,MACvCoQ,EAAQnQ,UAAY,oBACpBmQ,EAAQ3O,YAAcuF,EAAO+H,aAC7BnL,EAAUJ,WAAW4F,aAAagH,EAASxM,EAC7C,CACAA,EAAU0D,aAAa,qBAAsBN,EAAO+H,aACtD,CAOF,OAJAE,EAAK3D,QAAQ,SAAU+F,GACrBN,EAAUpQ,YAxHd,SAAwB4K,GACtB,MAAMvK,EAASjB,SAASC,cAAc,OACtCgB,EAAOf,UAAY,iBAEfsL,EAAKzH,IACP9C,EAAOsG,aAAa,eAAgBiE,EAAKzH,IAG3C9C,EAAOsG,aAAa,mBAAoBiE,EAAKtK,OAAS,IACtDD,EAAOsG,aAAa,qBAAsBiE,EAAKpK,SAAW,IAC1DH,EAAOsG,aAAa,mBAAoBiE,EAAKnK,OAAS,IAClDmK,EAAKlK,MACPL,EAAOsG,aAAa,kBAAmBiE,EAAKlK,MAG9C,MAAMF,EAAUpB,SAASC,cAAc,OAGvC,GAFAmB,EAAQlB,UAAY,oBAEhBsL,EAAKnK,MAAO,CACd,MAAMmP,EAAMxQ,SAASC,cAAc,OACnCuQ,EAAI7O,IAAM6J,EAAKnK,MACfmP,EAAItQ,UAAY,kBAChBsQ,EAAI5O,IAAM4J,EAAKtK,OAAS,GACxBsP,EAAIe,QAAU,WACZvO,QAAQqD,MAAM,wBAA0BmF,EAAKnK,MAAQ,iDACrDgM,KAAK1L,IAAMwC,EAAmB,qBAC9BkJ,KAAKzL,IAAM,kBACXyL,KAAKnM,MAAQ,mBAAqBsK,EAAKnK,KACzC,EACAD,EAAQR,YAAY4P,EACtB,CAEA,MAAMgB,EAAcxR,SAASC,cAAc,OAC3C,GAAIuL,EAAKtK,MAAO,CACd,MAAMA,EAAQlB,SAASC,cAAc,MACrCiB,EAAMQ,YAAc8J,EAAKtK,MACzBsQ,EAAY5Q,YAAYM,EAC1B,CAEA,GAAIsK,EAAKpK,QAAS,CAChB,MAAMqQ,EAAOzR,SAASC,cAAc,KACpC,IAAIyR,EAAclG,EAAKpK,QACnBsQ,EAAYjN,OAAS,MACvBiN,EAAcA,EAAY/M,UAAU,EAAG,KAAO,OAEhD8M,EAAKpR,UAAYqR,EACjBF,EAAY5Q,YAAY6Q,EAC1B,CAEA,GAAIjG,EAAKlK,KAAM,CACb,MAAM6H,EAAUnJ,SAASC,cAAc,OACvCkJ,EAAQ9I,UAAYmL,EAAKlK,KACzBkQ,EAAY5Q,YAAYuI,EAC1B,CAaA,OAXA/H,EAAQR,YAAY4Q,GACpBvQ,EAAOL,YAAYQ,GAEnBH,EAAOd,iBAAiB,QAAS,SAASM,GACxCA,EAAE2M,iBACsC,mBAA7B5K,OAAOxB,mBAChBwB,OAAOxB,kBAAkBC,EAE7B,GACAA,EAAOsG,aAAa,mBAAoB,KAEjCtG,CACT,CAqD0B0Q,CAAeL,GACvC,GAEOzN,CACT,CAEO,SAAS+N,EAAiBvP,EAAmB6M,EAAMtH,GACxD,MAAM/D,EAAYkN,EAAuB1O,EAAmB6M,EAAMtH,GAC7D/D,GACL6D,EAAS,CAAC7D,GAAY+D,EACxB,CAEO,SAASiK,EAAiBC,EAAKzP,GACpC,MAAMwB,EAAY7D,SAASO,cAAc8B,GACzC,IAAKwB,EAEH,YADAb,QAAQqD,MAAM,iCAAkChE,GAIlDwC,IAEA,MAAMlC,EAAakB,EAAYA,EAAUE,GAAK,KACxCgO,EAAWpP,EAAa,OAASA,EAAa,KAEpD,GAAIoP,GAAgC,oBAApB,QACd,IACE,MAAMC,EAASC,aAAaC,QAAQH,GACpC,GAAIC,EAAQ,CACV,MAAMG,EAAaC,KAAKC,MAAML,GAiB9B,YAhBAM,MAAMR,GAAKS,KAAK,SAASC,GACvB,IAAKA,EAAIC,GAAI,MAAM,IAAIrD,MAAM,kBAAoB0C,EAAM,KAAOU,EAAIE,OAAS,KAC3E,OAAOF,EAAIG,MACb,GAAGJ,KAAK,SAASI,GACXA,EAAKC,aAAeT,EAAWS,aAAeD,EAAKC,cAAgBT,EAAWS,aAChF5P,QAAQ6P,IAAI,iCAAkClQ,GAC9CmQ,EAAoBX,EAAY9P,KAEhCW,QAAQ6P,IAAI,oCAAqClQ,GACjDsP,aAAac,QAAQhB,EAAUK,KAAKY,UAAUL,IAC9CG,EAAoBH,EAAMtQ,GAE9B,GAAG4Q,MAAM,SAASC,GAChBlQ,QAAQC,KAAK,2CAA4CiQ,GACzDJ,EAAoBX,EAAY9P,EAClC,EAEF,CACF,CAAE,MAAO5B,GACPuC,QAAQC,KAAK,mCAAoCxC,EACnD,CAGF6R,MAAMR,GAAKS,KAAK,SAAUC,GACxB,IAAKA,EAAIC,GAAI,MAAM,IAAIrD,MAAM,kBAAoB0C,EAAM,KAAOU,EAAIE,OAAS,KAC3E,OAAOF,EAAIG,MACb,GAAGJ,KAAK,SAAUI,GAChB,GAAIZ,GAAgC,oBAApB,QACd,IACEE,aAAac,QAAQhB,EAAUK,KAAKY,UAAUL,IAC9C3P,QAAQ6P,IAAI,2BAA4BlQ,EAC1C,CAAE,MAAOlC,GACPuC,QAAQC,KAAK,iCAAkCxC,EACjD,CAEFqS,EAAoBH,EAAMtQ,EAC5B,GAAG4Q,MAAM,SAAUC,GACjBlQ,QAAQqD,MAAM,+BAAgC6M,GAC9CzN,EAAkB5B,EAAW,YAAaqP,EAAIrN,QAChD,EACF,CAEO,SAASiN,EAAoBH,EAAMtQ,GACxC,MAAMwB,EAAY7D,SAASO,cAAc8B,GACzC,IAAKwB,EAEH,YADAb,QAAQqD,MAAM,iCAAkChE,GAIlD,IAAI4E,EAAS,KACTkM,EAAQ,GAEZ,IACE,GAAIR,EAAKQ,OAAS5P,MAAM6P,QAAQT,EAAKQ,OACnCA,EAAQR,EAAKQ,MACblM,EAAS,CACP+H,aAAc2D,EAAK3D,aACnBiC,WAAY0B,EAAK1B,WACjBjI,aAAc2J,EAAK3J,aACnBX,SAAUsK,EAAKtK,SACf6I,SAAUyB,EAAKzB,SACfhK,UAAWyL,EAAKzL,UAChBC,UAAWwL,EAAKxL,UAChBC,SAAUuL,EAAKvL,SACfwL,YAAaD,EAAKC,iBAEf,KAAIrP,MAAM6P,QAAQT,GAGvB,MAAM,IAAIvD,MAAM,4EAFhB+D,EAAQR,CAGV,CAEA,GAAqB,IAAjBQ,EAAM1O,OACR,MAAM,IAAI2K,MAAM,oCAGlB2B,EAAuB1O,EAAmB8Q,EAAOlM,GAEjD,IACES,EAAS1H,SAASgN,iBAAiB3K,IACnCD,EAAkBC,GAClB8C,GACF,CAAE,MAAO1E,GACPuC,QAAQqD,MAAM,+BAAgC5F,GAC9C,MAAMoD,EAAY7D,SAASO,cAAc8B,GACrCwB,GACF4B,EAAkB5B,EAAW,iBAAkBpD,EAAEoF,SAEnDV,GACF,CAEF,CAAE,MAAO1E,GACPuC,QAAQqD,MAAM,kCAAmC5F,GACjDgF,EAAkB5B,EAAW,aAAcpD,EAAEoF,SAC7CV,GACF,CACF,CAEO,SAASkO,EAAmB1Q,GACjC,GAAwB,oBAApB,QAKJ,GAAIA,EAAY,CACd,MAAM9B,EAAM,OAAS8B,EACrBsP,aAAaqB,WAAWzS,GACxBmC,QAAQ6P,IAAI,8BAA+BlQ,EAC7C,KAAO,CACL,MAAM6M,EAAOD,OAAOC,KAAKyC,cACzB,IAAIsB,EAAU,EACd/D,EAAKjE,QAAQ,SAAS1K,GAChBA,EAAI4F,WAAW,UACjBwL,aAAaqB,WAAWzS,GACxB0S,IAEJ,GACAvQ,QAAQ6P,IAAI,UAAWU,EAAS,oBAClC,MAlBEvQ,QAAQC,KAAK,6BAmBjB,OCvPwB,oBAAXT,SACXA,OAAOkF,SAAWA,EAClBlF,OAAOoP,iBAAmBA,EAC1BpP,OAAOuO,uBAAyBA,EAChCvO,OAAOsQ,oBAAsBA,EAC7BtQ,OAAOqP,iBAAmBA,EAC1BrP,OAAO6Q,mBAAqBA,EAC5B7Q,OAAOzC,oBAAsBA,EAC7ByC,OAAOxB,kBAAoBA,EAC3BwB,OAAOpC,mBAAqBA,EAC5BoC,OAAOgR,0BAA4BpR,EACnCI,OAAOiR,4BAA8B7P,GAKvC5D,SAASG,iBAAiB,mBAAoB,WA7BlBH,SAASgN,iBAAiB,sBAClCzB,QAAQ,SAASF,GACjC,MAAMqI,EAAUrI,EAAWlK,aAAa,oBACxC,IAAKuS,EAAS,OACd,MAAMxT,GAAamL,EAAWnL,WAAa,IAAIyT,MAAM,KAAK,GACpDC,EAAWvI,EAAWtH,GAAK,IAAMsH,EAAWtH,GAAM7D,EAAY,IAAMA,EAAY,KAClF0T,GACF/B,EAAiB6B,EAASE,EAE9B,EAsBF,GAEsB,oBAAXpR,QAA0BA,OAAOqR,SAMvCrR,OAAOqR,OAJNC,GAAGpM,SAAW,SAASqM,GAEvB,OADArM,EAAS2F,KAAM0G,GACR1G,IACT"}
1
+ {"version":3,"file":"timeline.min.js","sources":["../src/js/shared/state.js","../src/js/features/modals.js","../src/js/features/deep-linking.js","../src/js/shared/config.js","../src/js/features/loader-ui.js","../src/js/features/error-ui.js","../src/js/shared/utils.js","../src/js/features/colors.js","../src/js/core/timeline-engine.js","../src/js/features/data-loader.js","../src/js/timeline.js"],"sourcesContent":["// Shared state containers\nexport const loaderState = {\n count: 0,\n startTime: 0,\n removeTimer: null,\n overlayEl: null\n};\n\nexport const modalState = {\n modal: null,\n overlay: null\n};\n\n// Global registry to store timeline instances for programmatic navigation\nexport const timelineRegistry = {};\n","import { modalState } from '../shared/state.js';\n\nexport function createTimelineModal() {\n if (modalState.modal) return;\n\n modalState.overlay = document.createElement('div');\n modalState.overlay.className = 'timeline-modal-overlay';\n modalState.overlay.addEventListener('click', closeTimelineModal);\n\n modalState.modal = document.createElement('div');\n modalState.modal.className = 'timeline-modal';\n modalState.modal.innerHTML = `\n <button class=\"timeline-modal__close\" aria-label=\"Close modal\"></button>\n <div class=\"timeline-modal__content\">\n <img class=\"timeline-modal__image\" src=\"\" alt=\"\" style=\"display: none;\">\n <h2 class=\"timeline-modal__title\"></h2>\n <div class=\"timeline-modal__text\"></div>\n <hr class=\"timeline-modal__divider\">\n <button class=\"timeline-modal__close-bottom\">Close</button>\n </div>\n `;\n\n const closeBtn = modalState.modal.querySelector('.timeline-modal__close');\n const closeBottomBtn = modalState.modal.querySelector('.timeline-modal__close-bottom');\n closeBtn.addEventListener('click', closeTimelineModal);\n closeBottomBtn.addEventListener('click', closeTimelineModal);\n\n modalState.modal.addEventListener('click', function(e) {\n e.stopPropagation();\n });\n\n document.body.appendChild(modalState.overlay);\n document.body.appendChild(modalState.modal);\n\n document.addEventListener('keydown', function(e) {\n if (e.key === 'Escape' && modalState.modal.classList.contains('timeline-modal-show')) {\n closeTimelineModal();\n }\n });\n}\n\nexport function openTimelineModal(itemEl) {\n if (!modalState.modal) {\n createTimelineModal();\n }\n\n const title = itemEl.getAttribute('data-modal-title');\n const content = itemEl.getAttribute('data-modal-content');\n const image = itemEl.getAttribute('data-modal-image');\n const html = itemEl.getAttribute('data-modal-html');\n\n const modalTitle = modalState.modal.querySelector('.timeline-modal__title');\n const modalText = modalState.modal.querySelector('.timeline-modal__text');\n const modalImage = modalState.modal.querySelector('.timeline-modal__image');\n\n modalTitle.textContent = title || '';\n\n if (image) {\n modalImage.src = image;\n modalImage.alt = title || '';\n modalImage.style.display = 'block';\n } else {\n modalImage.style.display = 'none';\n }\n\n if (html) {\n modalText.innerHTML = html;\n } else if (content) {\n modalText.innerHTML = '<p>' + content.replace(/\\n/g, '</p><p>') + '</p>';\n } else {\n modalText.innerHTML = '';\n }\n\n setTimeout(function() {\n modalState.modal.classList.add('timeline-modal-show');\n modalState.overlay.classList.add('timeline-modal-show');\n document.body.style.overflow = 'hidden';\n }, 10);\n}\n\nexport function closeTimelineModal() {\n if (modalState.modal) {\n modalState.modal.classList.remove('timeline-modal-show');\n modalState.overlay.classList.remove('timeline-modal-show');\n document.body.style.overflow = '';\n }\n}\n","import { timelineRegistry } from '../shared/state.js';\n\nexport function handleDeepLinking(containerSelector) {\n const urlParams = new URLSearchParams(window.location.search);\n const timelineId = urlParams.get('timeline');\n const nodeId = urlParams.get('id');\n if (!nodeId) return;\n\n let targetContainer;\n if (timelineId) {\n targetContainer = document.getElementById(timelineId);\n } else {\n targetContainer = document.querySelector(containerSelector);\n }\n\n if (!targetContainer) {\n console.warn('Timeline not found for deep linking:', timelineId || containerSelector);\n return;\n }\n\n targetContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });\n\n const targetNode = targetContainer.querySelector('[data-node-id=\"' + nodeId + '\"]');\n if (targetNode) {\n setTimeout(function() {\n targetNode.classList.add('timeline__item--active');\n const itemIndex = Array.from(targetNode.parentNode.children).indexOf(targetNode);\n navigateToNodeIndex(targetContainer, itemIndex);\n }, 500);\n }\n}\n\nexport function navigateToNodeIndex(container, index) {\n if (!container) return;\n const timelineId = container.id || container.getAttribute('data-timeline-id');\n if (!timelineId) {\n console.warn('Cannot navigate: timeline container has no ID');\n return;\n }\n\n const tlData = timelineRegistry[timelineId];\n if (!tlData) {\n console.warn('Timeline not found in registry:', timelineId);\n return;\n }\n\n if (!container.classList.contains('timeline--horizontal')) {\n return;\n }\n\n if (tlData.setCurrentIndex && tlData.updatePosition) {\n tlData.setCurrentIndex(index);\n tlData.updatePosition();\n }\n}\n","// Shared configuration values\n// Auto-detect the timeline.js script location to build correct image paths\nexport const timelineBasePath = (function() {\n // Check for user override\n if (typeof window !== 'undefined' && \n window.TimelineConfig && \n window.TimelineConfig.basePath) {\n return window.TimelineConfig.basePath;\n }\n \n const scripts = document.getElementsByTagName('script');\n for (let i = 0; i < scripts.length; i++) {\n const src = scripts[i].src || '';\n if (!src) continue;\n const dir = src.substring(0, src.lastIndexOf('/'));\n if (src.indexOf('timeline.min.js') !== -1) {\n // When loading from dist, map to src/images\n return dir.replace('/dist', '/src/images');\n }\n if (src.indexOf('timeline.js') !== -1) {\n // When loading from src/js, map to src/images\n return dir.replace('/js', '/images');\n }\n }\n // Fallback relative to demo pages; most demos live under demo/**\n return '../src/images';\n})();\n\n// Minimum time (ms) to keep the loading spinner visible\nlet timelineLoaderMinMs = 1300;\nexport function getTimelineLoaderMinMs() {\n return timelineLoaderMinMs;\n}\nexport function setTimelineLoaderMinMs(value) {\n if (typeof value === 'number' && value >= 0) {\n timelineLoaderMinMs = value;\n }\n}\n","import { loaderState } from '../shared/state.js';\nimport { getTimelineLoaderMinMs, timelineBasePath } from '../shared/config.js';\n\nexport function showTimelineLoader() {\n loaderState.count += 1;\n if (loaderState.count !== 1) return;\n\n loaderState.startTime = Date.now();\n\n if (loaderState.removeTimer) {\n clearTimeout(loaderState.removeTimer);\n loaderState.removeTimer = null;\n }\n\n const overlay = document.createElement('div');\n overlay.className = 'timeline__loader-overlay';\n\n const loader = document.createElement('div');\n loader.className = 'timeline__loader';\n\n const spinner = document.createElement('img');\n spinner.src = timelineBasePath + '/spinner.gif';\n spinner.alt = 'Loading...';\n spinner.title = 'Loading...';\n spinner.className = 'timeline__loader-spinner';\n // Default to a compact spinner if page CSS is missing\n spinner.width = 120;\n spinner.style.height = 'auto';\n\n loader.appendChild(spinner);\n overlay.appendChild(loader);\n\n document.body.appendChild(overlay);\n loaderState.overlayEl = overlay;\n}\n\nexport function hideTimelineLoader() {\n if (loaderState.count <= 0) return;\n loaderState.count -= 1;\n if (loaderState.count > 0) return;\n\n const elapsed = Date.now() - loaderState.startTime;\n const minMs = getTimelineLoaderMinMs();\n const remaining = Math.max(0, minMs - elapsed);\n\n const removeOverlay = function() {\n if (loaderState.overlayEl) {\n loaderState.overlayEl.remove();\n loaderState.overlayEl = null;\n }\n loaderState.removeTimer = null;\n };\n\n if (loaderState.removeTimer) {\n clearTimeout(loaderState.removeTimer);\n loaderState.removeTimer = null;\n }\n\n if (remaining > 0) {\n loaderState.removeTimer = setTimeout(removeOverlay, remaining);\n } else {\n removeOverlay();\n }\n}\n","import { timelineBasePath } from '../shared/config.js';\nimport { hideTimelineLoader } from './loader-ui.js';\n\nexport function showTimelineError(container, errorType, details) {\n if (!container) return;\n\n const errorMessages = {\n 'json-load': {\n title: 'Timeline Data Could Not Be Loaded',\n message: 'The timeline data failed to load. This could be due to a network error or an incorrect file path.',\n solution: 'Please check that the data-json-config path is correct and the file is accessible.'\n },\n 'json-parse': {\n title: 'Invalid Timeline Data',\n message: 'The timeline data file exists but contains invalid JSON.',\n solution: 'Please validate your JSON using a tool like jsonlint.com and ensure it follows the correct schema.'\n },\n 'missing-element': {\n title: 'Timeline Element Not Found',\n message: 'The required timeline container element could not be found on the page.',\n solution: 'Ensure your HTML includes a container with the class \"timeline\" and the correct selector.'\n },\n 'invalid-config': {\n title: 'Invalid Configuration',\n message: 'One or more timeline configuration options are invalid.',\n solution: 'Check your data attributes or JavaScript options and ensure they match the expected format.'\n }\n };\n\n const errorInfo = errorMessages[errorType] || {\n title: 'Timeline Error',\n message: 'An unexpected error occurred while initializing the timeline.',\n solution: 'Please check the browser console for more details.'\n };\n\n hideTimelineLoader(container);\n container.innerHTML = '';\n\n const errorDiv = document.createElement('div');\n errorDiv.className = 'timeline__error';\n\n const errorIcon = document.createElement('img');\n errorIcon.src = timelineBasePath + '/alert.svg';\n errorIcon.alt = 'Error';\n errorIcon.className = 'timeline__error-icon';\n // Ensure a reasonable default size even if CSS isn't loaded\n // This makes the error icon usable when a consumer forgets to include CSS.\n errorIcon.width = 200;\n errorIcon.style.height = 'auto';\n\n const errorTitle = document.createElement('h2');\n errorTitle.className = 'timeline__error-title';\n errorTitle.textContent = errorInfo.title;\n\n const errorMessage = document.createElement('p');\n errorMessage.className = 'timeline__error-message';\n errorMessage.textContent = errorInfo.message;\n\n const errorSolution = document.createElement('p');\n errorSolution.className = 'timeline__error-solution';\n errorSolution.innerHTML = '<strong>Solution:</strong> ' + errorInfo.solution;\n\n if (details) {\n const errorDetails = document.createElement('p');\n errorDetails.className = 'timeline__error-details';\n errorDetails.innerHTML = '<strong>Details:</strong> ' + details;\n errorDiv.appendChild(errorDetails);\n }\n\n errorDiv.appendChild(errorIcon);\n errorDiv.appendChild(errorTitle);\n errorDiv.appendChild(errorMessage);\n errorDiv.appendChild(errorSolution);\n\n container.appendChild(errorDiv);\n\n console.error('Timeline Error [' + errorType + ']:', errorInfo.message, details || '');\n}\n","// Utility helpers shared across modules\nexport function getContrastColor(bgColor) {\n const brightness = getColorBrightness(bgColor);\n return brightness > 128 ? 'rgba(0, 0, 0, 0.2)' : 'rgba(255, 255, 255, 0.3)';\n}\n\nexport function getColorBrightness(color) {\n let rgb;\n if (!color || typeof color !== 'string') return 128;\n\n if (color.startsWith('#')) {\n let hex = color.substring(1);\n if (hex.length === 3) {\n hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];\n }\n const r = parseInt(hex.substring(0, 2), 16);\n const g = parseInt(hex.substring(2, 4), 16);\n const b = parseInt(hex.substring(4, 6), 16);\n rgb = [r, g, b];\n } else if (color.startsWith('rgb')) {\n const matches = color.match(/\\d+/g);\n rgb = matches ? matches.map(Number) : [128, 128, 128];\n } else {\n return 128;\n }\n\n return (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000;\n}\n","import { getContrastColor, getColorBrightness } from '../shared/utils.js';\n\nexport function applyTimelineColors(container, config) {\n let nodeColor = config.nodeColor || null;\n let lineColor = config.lineColor || null;\n const navColor = config.navColor || null;\n\n if (nodeColor && !lineColor) lineColor = nodeColor;\n if (lineColor && !nodeColor) nodeColor = lineColor;\n\n if (nodeColor) {\n container.style.setProperty('--timeline-node-color', nodeColor);\n }\n if (lineColor) {\n container.style.setProperty('--timeline-line-color', lineColor);\n }\n if (navColor) {\n container.style.setProperty('--timeline-nav-color', navColor);\n container.style.setProperty('--timeline-nav-border', getContrastColor(navColor));\n const brightness = getColorBrightness(navColor);\n const arrowColor = brightness > 128 ? '#333' : '#fff';\n container.style.setProperty('--timeline-arrow-color', arrowColor);\n container.setAttribute('data-arrow-color', arrowColor);\n }\n}\n","import { showTimelineLoader, hideTimelineLoader } from '../features/loader-ui.js';\nimport { showTimelineError } from '../features/error-ui.js';\nimport { applyTimelineColors } from '../features/colors.js';\nimport { openTimelineModal } from '../features/modals.js';\nimport { timelineRegistry } from '../shared/state.js';\n\nfunction ensureInlineModalData(itemEl) {\n if (!itemEl) return;\n const content = itemEl.querySelector('.timeline__content') || itemEl;\n if (!itemEl.hasAttribute('data-modal-title')) {\n const heading = content.querySelector('h1,h2,h3,h4,h5,h6');\n if (heading && heading.textContent) {\n itemEl.setAttribute('data-modal-title', heading.textContent.trim());\n }\n }\n if (!itemEl.hasAttribute('data-modal-content')) {\n const firstP = content.querySelector('p');\n if (firstP && firstP.textContent) {\n itemEl.setAttribute('data-modal-content', firstP.textContent.trim());\n }\n }\n if (!itemEl.hasAttribute('data-modal-image')) {\n const img = content.querySelector('img');\n if (img && img.getAttribute('src')) {\n itemEl.setAttribute('data-modal-image', img.getAttribute('src'));\n }\n }\n}\n\nfunction enhanceInlineItems(timelineEl, items) {\n if (!items || !items.length) return;\n items.forEach(function(item){\n if (item.getAttribute('data-modal-bound') === '1') return;\n ensureInlineModalData(item);\n const hasModal = item.hasAttribute('data-modal-title') || item.hasAttribute('data-modal-content') || item.hasAttribute('data-modal-image') || item.hasAttribute('data-modal-html');\n if (hasModal) {\n item.addEventListener('click', function(e){\n e.preventDefault();\n openTimelineModal(item);\n });\n item.setAttribute('data-modal-bound', '1');\n }\n });\n}\n\nfunction createArrowSVG(direction, color) {\n if (direction === 'left') {\n return '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"7.8\" height=\"14\" style=\"display:block;margin:auto;\"><path fill=\"none\" stroke=\"' + color + '\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6.8 1L1 7l5.8 6\"/></svg>';\n }\n return '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"7.8\" height=\"14\" style=\"display:block;margin:auto;\"><path fill=\"none\" stroke=\"' + color + '\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M1 1l5.8 6L1 13\"/></svg>';\n}\n\nexport function timeline(collection, options) {\n const timelines = [];\n const warningLabel = 'Timeline:';\n let winWidth = window.innerWidth;\n let resizeTimer;\n let currentIndex = 0;\n const eventListeners = new Map(); // Track listeners for cleanup\n\n showTimelineLoader();\n let shouldHideLoader = true;\n\n const defaultSettings = {\n minWidth: { type: 'integer', defaultValue: 600 },\n maxWidth: { type: 'integer', defaultValue: 600 },\n horizontalStartPosition: { type: 'string', acceptedValues: ['bottom', 'top'], defaultValue: 'top' },\n mode: { type: 'string', acceptedValues: ['horizontal', 'vertical'], defaultValue: 'vertical' },\n moveItems: { type: 'integer', defaultValue: 1 },\n rtlMode: { type: 'boolean', acceptedValues: [true, false], defaultValue: false },\n startIndex: { type: 'integer', defaultValue: 0 },\n verticalStartPosition: { type: 'string', acceptedValues: ['left', 'right'], defaultValue: 'left' },\n verticalTrigger: { type: 'string', defaultValue: '15%' },\n visibleItems: { type: 'integer', defaultValue: 3 }\n };\n\n function testValues(value, settingName) {\n if (typeof value !== 'number' && value % 1 !== 0) {\n console.warn(`${warningLabel} The value \"${value}\" entered for the setting \"${settingName}\" is not an integer.`);\n return false;\n }\n return true;\n }\n\n function itemWrap(el, wrapper, classes) {\n wrapper.classList.add(classes);\n el.parentNode.insertBefore(wrapper, el);\n wrapper.appendChild(el);\n }\n\n function wrapElements(items) {\n items.forEach((item) => {\n itemWrap(item.querySelector('.timeline__content'), document.createElement('div'), 'timeline__content__wrap');\n itemWrap(item.querySelector('.timeline__content__wrap'), document.createElement('div'), 'timeline__item__inner');\n });\n }\n\n function isElementInViewport(el, triggerPosition) {\n const rect = el.getBoundingClientRect();\n const windowHeight = window.innerHeight || document.documentElement.clientHeight;\n const defaultTrigger = defaultSettings.verticalTrigger.defaultValue.match(/(\\d*\\.?\\d*)(.*)/);\n let triggerUnit = triggerPosition.unit;\n let triggerValue = triggerPosition.value;\n let trigger = windowHeight;\n if (triggerUnit === 'px' && triggerValue >= windowHeight) {\n console.warn('The value entered for the setting \"verticalTrigger\" is larger than the window height. The default value will be used instead.');\n [, triggerValue, triggerUnit] = defaultTrigger;\n }\n if (triggerUnit === 'px') {\n trigger = parseInt(trigger - triggerValue, 10);\n } else if (triggerUnit === '%') {\n trigger = parseInt(trigger * ((100 - triggerValue) / 100), 10);\n }\n return (\n rect.top <= trigger &&\n rect.left <= (window.innerWidth || document.documentElement.clientWidth) &&\n (rect.top + rect.height) >= 0 &&\n (rect.left + rect.width) >= 0\n );\n }\n\n function addTransforms(el, transform) {\n el.style.webkitTransform = transform;\n el.style.msTransform = transform;\n el.style.transform = transform;\n }\n\n function createTimelines(timelineEl) {\n const timelineName = timelineEl.id ? `#${timelineEl.id}` : `.${timelineEl.className}`;\n const errorPart = 'could not be found as a direct descendant of';\n const data = timelineEl.dataset;\n let wrap;\n let scroller;\n let items;\n const settings = {};\n\n try {\n wrap = timelineEl.querySelector('.timeline__wrap');\n if (!wrap) {\n throw new Error(`${warningLabel} .timeline__wrap ${errorPart} ${timelineName}`);\n } else {\n scroller = wrap.querySelector('.timeline__items');\n if (!scroller) {\n throw new Error(`${warningLabel} .timeline__items ${errorPart} .timeline__wrap`);\n } else {\n items = [].slice.call(scroller.children, 0);\n }\n }\n } catch (e) {\n console.warn(e.message);\n showTimelineError(timelineEl, 'missing-element', e.message);\n return false;\n }\n\n Object.keys(defaultSettings).forEach((key) => {\n settings[key] = defaultSettings[key].defaultValue;\n\n if (key === 'minWidth') {\n let candidate = undefined;\n if (data.minWidth !== undefined) candidate = data.minWidth;\n if (data.minwidth !== undefined) candidate = data.minwidth;\n if (data.forceVerticalMode !== undefined) candidate = data.forceVerticalMode;\n if (data.forceverticalmode !== undefined) candidate = data.forceverticalmode;\n if (candidate === undefined && options) {\n if (options.minWidth !== undefined) candidate = options.minWidth;\n else if (options.forceVerticalMode !== undefined) candidate = options.forceVerticalMode;\n }\n if (candidate !== undefined) settings.minWidth = candidate;\n } else if (key === 'maxWidth') {\n let candidate = undefined;\n if (data.maxWidth !== undefined) candidate = data.maxWidth;\n if (data.maxwidth !== undefined) candidate = data.maxwidth;\n if (candidate === undefined && options) {\n if (options.maxWidth !== undefined) candidate = options.maxWidth;\n }\n if (candidate !== undefined) settings.maxWidth = candidate;\n } else {\n if (data[key]) {\n settings[key] = data[key];\n } else if (options && options[key] !== undefined) {\n settings[key] = options[key];\n }\n }\n\n if (defaultSettings[key].type === 'integer') {\n if (!settings[key] || !testValues(settings[key], key)) {\n settings[key] = defaultSettings[key].defaultValue;\n }\n } else if (defaultSettings[key].type === 'string') {\n if (defaultSettings[key].acceptedValues && defaultSettings[key].acceptedValues.indexOf(settings[key]) === -1) {\n console.warn(`${warningLabel} The value \"${settings[key]}\" entered for the setting \"${key}\" was not recognised.`);\n settings[key] = defaultSettings[key].defaultValue;\n }\n }\n });\n\n (function applyColorParity(){\n const data = timelineEl.dataset;\n const getData = function(k){\n return data[k] !== undefined ? data[k] : (data[k && k.toLowerCase()] !== undefined ? data[k.toLowerCase()] : undefined);\n };\n let nodeColor = getData('nodeColor');\n let lineColor = getData('lineColor');\n let navColor = getData('navColor');\n if (options) {\n if (options.nodeColor !== undefined) nodeColor = options.nodeColor;\n if (options.lineColor !== undefined) lineColor = options.lineColor;\n if (options.navColor !== undefined) navColor = options.navColor;\n }\n if (nodeColor || lineColor || navColor) {\n applyTimelineColors(timelineEl, { nodeColor, lineColor, navColor });\n }\n })();\n\n const defaultTrigger = defaultSettings.verticalTrigger.defaultValue.match(/(\\d*\\.?\\d*)(.*)/);\n const triggerArray = settings.verticalTrigger.match(/(\\d*\\.?\\d*)(.*)/);\n let [, triggerValue, triggerUnit] = triggerArray;\n let triggerValid = true;\n if (!triggerValue) {\n console.warn(`${warningLabel} No numercial value entered for the 'verticalTrigger' setting.`);\n triggerValid = false;\n }\n if (triggerUnit !== 'px' && triggerUnit !== '%') {\n console.warn(`${warningLabel} The setting 'verticalTrigger' must be a percentage or pixel value.`);\n triggerValid = false;\n }\n if (triggerUnit === '%' && (triggerValue > 100 || triggerValue < 0)) {\n console.warn(`${warningLabel} The 'verticalTrigger' setting value must be between 0 and 100 if using a percentage value.`);\n triggerValid = false;\n } else if (triggerUnit === 'px' && triggerValue < 0) {\n console.warn(`${warningLabel} The 'verticalTrigger' setting value must be above 0 if using a pixel value.`);\n triggerValid = false;\n }\n\n if (triggerValid === false) {\n [, triggerValue, triggerUnit] = defaultTrigger;\n }\n\n settings.verticalTrigger = {\n unit: triggerUnit,\n value: triggerValue\n };\n\n if (settings.moveItems > settings.visibleItems) {\n console.warn(`${warningLabel} The value of \"moveItems\" (${settings.moveItems}) is larger than the number of \"visibleItems\" (${settings.visibleItems}). The value of \"visibleItems\" has been used instead.`);\n settings.moveItems = settings.visibleItems;\n }\n\n if (settings.startIndex > (items.length - settings.visibleItems) && items.length > settings.visibleItems) {\n console.warn(`${warningLabel} The 'startIndex' setting must be between 0 and ${items.length - settings.visibleItems} for this timeline. The value of ${items.length - settings.visibleItems} has been used instead.`);\n settings.startIndex = items.length - settings.visibleItems;\n } else if (items.length <= settings.visibleItems) {\n console.warn(`${warningLabel} The number of items in the timeline must exceed the number of visible items to use the 'startIndex' option.`);\n settings.startIndex = 0;\n } else if (settings.startIndex < 0) {\n console.warn(`${warningLabel} The 'startIndex' setting must be between 0 and ${items.length - settings.visibleItems} for this timeline. The value of 0 has been used instead.`);\n settings.startIndex = 0;\n }\n\n enhanceInlineItems(timelineEl, items);\n\n if (!timelineEl.id) {\n timelineEl.setAttribute('data-timeline-id', 'timeline-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9));\n }\n\n timelines.push({\n timelineEl,\n wrap,\n scroller,\n items,\n settings,\n listeners: [] // Store listeners for cleanup\n });\n }\n\n if (collection.length) {\n Array.from(collection).forEach(createTimelines);\n }\n\n function setHeightandWidths(tl) {\n function setWidths() {\n tl.itemWidth = 200;\n tl.items.forEach((item) => {\n item.style.width = `${tl.itemWidth}px`;\n });\n tl.scrollerWidth = tl.itemWidth * tl.items.length;\n tl.scroller.style.width = `${tl.scrollerWidth}px`;\n }\n\n function setHeights() {\n let oddIndexTallest = 0;\n let evenIndexTallest = 0;\n tl.items.forEach((item, i) => {\n item.style.height = 'auto';\n const height = item.offsetHeight;\n if (i % 2 === 0) {\n evenIndexTallest = height > evenIndexTallest ? height : evenIndexTallest;\n } else {\n oddIndexTallest = height > oddIndexTallest ? height : oddIndexTallest;\n }\n });\n\n const transformString = `translateY(${evenIndexTallest}px)`;\n tl.items.forEach((item, i) => {\n if (i % 2 === 0) {\n item.style.height = `${evenIndexTallest}px`;\n if (tl.settings.horizontalStartPosition === 'bottom') {\n item.classList.add('timeline__item--bottom');\n addTransforms(item, transformString);\n } else {\n item.classList.add('timeline__item--top');\n }\n } else {\n item.style.height = `${oddIndexTallest}px`;\n if (tl.settings.horizontalStartPosition !== 'bottom') {\n item.classList.add('timeline__item--bottom');\n addTransforms(item, transformString);\n } else {\n item.classList.add('timeline__item--top');\n }\n }\n });\n tl.scroller.style.height = `${evenIndexTallest + oddIndexTallest}px`;\n }\n\n if (window.innerWidth > tl.settings.minWidth) {\n setWidths();\n setHeights();\n }\n }\n\n function addNavigation(tl) {\n const viewportWidth = tl.wrap.offsetWidth;\n const itemsVisible = Math.floor(viewportWidth / tl.itemWidth);\n\n if (tl.items.length > itemsVisible) {\n const prevArrow = document.createElement('button');\n const nextArrow = document.createElement('button');\n const topPosition = tl.items[0].offsetHeight;\n prevArrow.className = 'timeline-nav-button timeline-nav-button--prev';\n nextArrow.className = 'timeline-nav-button timeline-nav-button--next';\n prevArrow.textContent = 'Previous';\n nextArrow.textContent = 'Next';\n prevArrow.style.top = `${topPosition}px`;\n nextArrow.style.top = `${topPosition}px`;\n\n const arrowColor = tl.timelineEl.getAttribute('data-arrow-color') || '#333';\n prevArrow.innerHTML = createArrowSVG('left', arrowColor);\n nextArrow.innerHTML = createArrowSVG('right', arrowColor);\n\n const maxIndex = Math.max(0, tl.items.length - itemsVisible);\n if (currentIndex === 0) {\n prevArrow.disabled = true;\n } else if (currentIndex >= maxIndex) {\n nextArrow.disabled = true;\n }\n tl.timelineEl.appendChild(prevArrow);\n tl.timelineEl.appendChild(nextArrow);\n }\n }\n\n function addHorizontalDivider(tl) {\n const divider = tl.timelineEl.querySelector('.timeline-divider');\n if (divider) {\n tl.timelineEl.removeChild(divider);\n }\n const topPosition = tl.items[0].offsetHeight;\n const horizontalDivider = document.createElement('span');\n horizontalDivider.className = 'timeline-divider';\n horizontalDivider.style.top = `${topPosition}px`;\n tl.timelineEl.appendChild(horizontalDivider);\n }\n\n function timelinePosition(tl) {\n const position = tl.items[currentIndex].offsetLeft;\n const str = `translate3d(-${position}px, 0, 0)`;\n addTransforms(tl.scroller, str);\n }\n\n function slideTimeline(tl) {\n const navArrows = tl.timelineEl.querySelectorAll('.timeline-nav-button');\n const arrowPrev = tl.timelineEl.querySelector('.timeline-nav-button--prev');\n const arrowNext = tl.timelineEl.querySelector('.timeline-nav-button--next');\n\n const viewportWidth = tl.wrap.offsetWidth;\n const itemsVisible = Math.floor(viewportWidth / tl.itemWidth);\n const maxIndex = Math.max(0, tl.items.length - itemsVisible);\n\n const moveItems = parseInt(tl.settings.moveItems, 10);\n \n const handleArrowClick = function(e) {\n e.preventDefault();\n e.stopPropagation();\n\n if (this.disabled) {\n return;\n }\n\n currentIndex = this.classList.contains('timeline-nav-button--next') ? (currentIndex += moveItems) : (currentIndex -= moveItems);\n if (currentIndex === 0 || currentIndex < 0) {\n currentIndex = 0;\n arrowPrev.disabled = true;\n arrowNext.disabled = false;\n } else if (currentIndex === maxIndex || currentIndex > maxIndex) {\n currentIndex = maxIndex;\n arrowPrev.disabled = false;\n arrowNext.disabled = true;\n } else {\n arrowPrev.disabled = false;\n arrowNext.disabled = false;\n }\n timelinePosition(tl);\n };\n \n Array.from(navArrows).forEach((arrow) => {\n arrow.addEventListener('click', handleArrowClick);\n tl.listeners.push({ element: arrow, type: 'click', handler: handleArrowClick });\n });\n }\n\n function setUpHorinzontalTimeline(tl) {\n if (tl.settings.rtlMode) {\n currentIndex = tl.items.length > tl.settings.visibleItems ? tl.items.length - tl.settings.visibleItems : 0;\n } else {\n currentIndex = tl.settings.startIndex;\n }\n tl.timelineEl.classList.add('timeline--horizontal');\n setHeightandWidths(tl);\n timelinePosition(tl);\n addNavigation(tl);\n addHorizontalDivider(tl);\n slideTimeline(tl);\n\n const timelineId = tl.timelineEl.id || tl.timelineEl.getAttribute('data-timeline-id');\n if (timelineId) {\n timelineRegistry[timelineId] = {\n setCurrentIndex: function(index) {\n const viewportWidth = tl.wrap.offsetWidth;\n const itemsVisible = Math.floor(viewportWidth / tl.itemWidth);\n const maxIndex = Math.max(0, tl.items.length - itemsVisible);\n currentIndex = Math.max(0, Math.min(index, maxIndex));\n },\n updatePosition: function() {\n timelinePosition(tl);\n const arrowPrev = tl.timelineEl.querySelector('.timeline-nav-button--prev');\n const arrowNext = tl.timelineEl.querySelector('.timeline-nav-button--next');\n if (arrowPrev && arrowNext) {\n const viewportWidth = tl.wrap.offsetWidth;\n const itemsVisible = Math.floor(viewportWidth / tl.itemWidth);\n const maxIndex = Math.max(0, tl.items.length - itemsVisible);\n arrowPrev.disabled = currentIndex === 0;\n arrowNext.disabled = currentIndex >= maxIndex;\n }\n }\n };\n }\n }\n\n function setUpVerticalTimeline(tl) {\n let lastVisibleIndex = 0;\n tl.items.forEach((item, i) => {\n item.classList.remove('animated', 'fadeIn');\n if (!isElementInViewport(item, tl.settings.verticalTrigger) && i > 0) {\n item.classList.add('animated');\n } else {\n lastVisibleIndex = i;\n }\n const divider = tl.settings.verticalStartPosition === 'left' ? 1 : 0;\n if (i % 2 === divider && window.innerWidth > tl.settings.minWidth) {\n item.classList.add('timeline__item--right');\n } else {\n item.classList.add('timeline__item--left');\n }\n });\n for (let i = 0; i < lastVisibleIndex; i += 1) {\n tl.items[i].classList.remove('animated', 'fadeIn');\n }\n \n // Use IntersectionObserver instead of scroll listener for better performance\n if ('IntersectionObserver' in window) {\n const observerOptions = {\n rootMargin: tl.settings.verticalTrigger.unit === '%' \n ? `${tl.settings.verticalTrigger.value}%` \n : `${tl.settings.verticalTrigger.value}px`,\n threshold: 0.01\n };\n \n const observer = new IntersectionObserver((entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting) {\n entry.target.classList.add('fadeIn');\n }\n });\n }, observerOptions);\n \n tl.items.forEach((item) => {\n if (item.classList.contains('animated')) {\n observer.observe(item);\n }\n });\n \n // Store observer for cleanup\n tl.observer = observer;\n } else {\n // Fallback for older browsers (though we're targeting 2018+)\n const scrollHandler = () => {\n tl.items.forEach((item) => {\n if (isElementInViewport(item, tl.settings.verticalTrigger)) {\n item.classList.add('fadeIn');\n }\n });\n };\n window.addEventListener('scroll', scrollHandler);\n tl.listeners.push({ element: window, type: 'scroll', handler: scrollHandler });\n }\n }\n\n function resetTimelines(tl) {\n // Clean up event listeners\n if (tl.listeners && tl.listeners.length > 0) {\n tl.listeners.forEach(({ element, type, handler }) => {\n element.removeEventListener(type, handler);\n });\n tl.listeners = [];\n }\n \n // Clean up IntersectionObserver\n if (tl.observer) {\n tl.observer.disconnect();\n tl.observer = null;\n }\n \n tl.timelineEl.classList.remove('timeline--horizontal', 'timeline--mobile');\n tl.scroller.removeAttribute('style');\n tl.items.forEach((item) => {\n item.removeAttribute('style');\n item.classList.remove('animated', 'fadeIn', 'timeline__item--left', 'timeline__item--right');\n });\n const navArrows = tl.timelineEl.querySelectorAll('.timeline-nav-button');\n Array.from(navArrows).forEach((arrow) => {\n arrow.parentNode.removeChild(arrow);\n });\n }\n\n function setUpTimelines() {\n timelines.forEach((tl) => {\n tl.timelineEl.style.opacity = 0;\n if (!tl.timelineEl.classList.contains('timeline--loaded')) {\n wrapElements(tl.items);\n }\n resetTimelines(tl);\n if (window.innerWidth <= tl.settings.minWidth) {\n tl.timelineEl.classList.add('timeline--mobile');\n }\n \n // Determine which mode to use based on settings and viewport width\n let useHorizontalMode = false;\n if (tl.settings.mode === 'horizontal' && window.innerWidth > tl.settings.minWidth) {\n useHorizontalMode = true;\n } else if (tl.settings.mode === 'vertical' && window.innerWidth > tl.settings.maxWidth) {\n useHorizontalMode = true;\n }\n \n if (useHorizontalMode) {\n setUpHorinzontalTimeline(tl);\n } else {\n setUpVerticalTimeline(tl);\n }\n tl.timelineEl.classList.add('timeline--loaded');\n });\n\n setTimeout(() => {\n timelines.forEach((tl) => {\n tl.timelineEl.style.opacity = 1;\n });\n }, 500);\n\n if (shouldHideLoader) {\n hideTimelineLoader();\n shouldHideLoader = false;\n }\n }\n\n setUpTimelines();\n\n window.addEventListener('resize', () => {\n clearTimeout(resizeTimer);\n resizeTimer = setTimeout(() => {\n const newWinWidth = window.innerWidth;\n if (newWinWidth !== winWidth) {\n setUpTimelines();\n winWidth = newWinWidth;\n }\n }, 250);\n });\n}","import { timelineBasePath } from '../shared/config.js';\nimport { showTimelineLoader, hideTimelineLoader } from './loader-ui.js';\nimport { showTimelineError } from './error-ui.js';\nimport { applyTimelineColors } from './colors.js';\nimport { handleDeepLinking } from './deep-linking.js';\nimport { timeline } from '../core/timeline-engine.js';\n\nfunction createItemNode(item) {\n const itemEl = document.createElement('div');\n itemEl.className = 'timeline__item';\n\n if (item.id) {\n itemEl.setAttribute('data-node-id', item.id);\n }\n\n itemEl.setAttribute('data-modal-title', item.title || '');\n itemEl.setAttribute('data-modal-content', item.content || '');\n itemEl.setAttribute('data-modal-image', item.image || '');\n if (item.html) {\n itemEl.setAttribute('data-modal-html', item.html);\n }\n\n const content = document.createElement('div');\n content.className = 'timeline__content';\n\n if (item.image) {\n const img = document.createElement('img');\n img.src = item.image;\n img.className = 'timeline__image';\n img.alt = item.title || '';\n img.onerror = function() {\n console.error('Timeline: The image \"' + item.image + '\" could not be loaded. Please check the path.');\n this.src = timelineBasePath + '/missing-image.svg';\n this.alt = 'Image not found';\n this.title = 'Original image: ' + item.image;\n };\n content.appendChild(img);\n }\n\n const textWrapper = document.createElement('div');\n if (item.title) {\n const title = document.createElement('h3');\n title.textContent = item.title;\n textWrapper.appendChild(title);\n }\n\n if (item.content) {\n const para = document.createElement('p');\n let displayText = item.content;\n if (displayText.length > 105) {\n displayText = displayText.substring(0, 105) + '...';\n }\n para.innerHTML = displayText;\n textWrapper.appendChild(para);\n }\n\n if (item.html) {\n const wrapper = document.createElement('div');\n wrapper.innerHTML = item.html;\n textWrapper.appendChild(wrapper);\n }\n\n content.appendChild(textWrapper);\n itemEl.appendChild(content);\n\n itemEl.addEventListener('click', function(e) {\n e.preventDefault();\n if (typeof window.openTimelineModal === 'function') {\n window.openTimelineModal(itemEl);\n }\n });\n itemEl.setAttribute('data-modal-bound', '1');\n\n return itemEl;\n}\n\nfunction applyDataAttributes(container, config) {\n if (config.layoutMode) {\n container.setAttribute('data-mode', config.layoutMode);\n }\n if (config.visibleItems !== undefined) {\n container.setAttribute('data-visible-items', config.visibleItems);\n }\n if (config.minWidth !== undefined) {\n container.setAttribute('data-min-width', config.minWidth);\n container.setAttribute('data-force-vertical-mode', config.minWidth);\n }\n if (config.maxWidth !== undefined) {\n container.setAttribute('data-max-width', config.maxWidth);\n }\n}\n\nexport function renderTimelineFromData(containerSelector, data, config) {\n const container = document.querySelector(containerSelector);\n if (!container) return;\n\n let itemsWrap = container.querySelector('.timeline__items');\n if (!itemsWrap) {\n const wrap = document.createElement('div');\n wrap.className = 'timeline__wrap';\n itemsWrap = document.createElement('div');\n itemsWrap.className = 'timeline__items';\n wrap.appendChild(itemsWrap);\n container.appendChild(wrap);\n } else {\n itemsWrap.innerHTML = '';\n }\n\n if (config) {\n applyDataAttributes(container, config);\n applyTimelineColors(container, config);\n\n if (config.timelineName && config.timelineName.trim() !== '') {\n const existingHeading = container.previousElementSibling;\n if (existingHeading && existingHeading.classList.contains('timeline__heading')) {\n existingHeading.textContent = config.timelineName;\n } else {\n const heading = document.createElement('h1');\n heading.className = 'timeline__heading';\n heading.textContent = config.timelineName;\n container.parentNode.insertBefore(heading, container);\n }\n container.setAttribute('data-timeline-name', config.timelineName);\n }\n }\n\n data.forEach(function (it) {\n itemsWrap.appendChild(createItemNode(it));\n });\n\n return container;\n}\n\nexport function timelineFromData(containerSelector, data, options) {\n const container = renderTimelineFromData(containerSelector, data, options);\n if (!container) return;\n timeline([container], options);\n}\n\nexport function loadDataFromJson(url, containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) {\n console.error('Timeline: Container not found:', containerSelector);\n return;\n }\n\n showTimelineLoader();\n\n const timelineId = container ? container.id : null;\n const cacheKey = timelineId ? 'vjs_' + timelineId : null;\n\n if (cacheKey && typeof(Storage) !== 'undefined') {\n try {\n const cached = localStorage.getItem(cacheKey);\n if (cached) {\n const cachedData = JSON.parse(cached);\n fetch(url).then(function(res) {\n if (!res.ok) throw new Error('Failed to load ' + url + ' (' + res.status + ')');\n return res.json();\n }).then(function(json) {\n if (json.lastupdated && cachedData.lastupdated && json.lastupdated === cachedData.lastupdated) {\n console.log('Using cached timeline data for', timelineId);\n processTimelineData(cachedData, containerSelector);\n } else {\n console.log('Updating cached timeline data for', timelineId);\n localStorage.setItem(cacheKey, JSON.stringify(json));\n processTimelineData(json, containerSelector);\n }\n }).catch(function(err) {\n console.warn('Failed to fetch fresh data, using cache:', err);\n processTimelineData(cachedData, containerSelector);\n });\n return;\n }\n } catch (e) {\n console.warn('Error reading from localStorage:', e);\n }\n }\n\n fetch(url).then(function (res) {\n if (!res.ok) throw new Error('Failed to load ' + url + ' (' + res.status + ')');\n return res.json();\n }).then(function (json) {\n if (cacheKey && typeof(Storage) !== 'undefined') {\n try {\n localStorage.setItem(cacheKey, JSON.stringify(json));\n console.log('Cached timeline data for', timelineId);\n } catch (e) {\n console.warn('Failed to cache timeline data:', e);\n }\n }\n processTimelineData(json, containerSelector);\n }).catch(function (err) {\n console.error('Error loading timeline JSON:', err);\n showTimelineError(container, 'json-load', err.message);\n });\n}\n\nexport function processTimelineData(json, containerSelector) {\n const container = document.querySelector(containerSelector);\n if (!container) {\n console.error('Timeline: Container not found:', containerSelector);\n return;\n }\n\n let config = null;\n let nodes = [];\n\n try {\n if (json.nodes && Array.isArray(json.nodes)) {\n nodes = json.nodes;\n config = {\n timelineName: json.timelineName,\n layoutMode: json.layoutMode,\n visibleItems: json.visibleItems,\n minWidth: json.minWidth,\n maxWidth: json.maxWidth,\n nodeColor: json.nodeColor,\n lineColor: json.lineColor,\n navColor: json.navColor,\n lastupdated: json.lastupdated\n };\n } else if (Array.isArray(json)) {\n nodes = json;\n } else {\n throw new Error('Invalid JSON format. Expected object with \"nodes\" array or simple array.');\n }\n\n if (nodes.length === 0) {\n throw new Error('No timeline items found in data.');\n }\n\n renderTimelineFromData(containerSelector, nodes, config);\n\n try {\n timeline(document.querySelectorAll(containerSelector));\n handleDeepLinking(containerSelector);\n hideTimelineLoader();\n } catch (e) {\n console.error('Error initializing timeline:', e);\n const container = document.querySelector(containerSelector);\n if (container) {\n showTimelineError(container, 'invalid-config', e.message);\n }\n hideTimelineLoader();\n }\n\n } catch (e) {\n console.error('Error processing timeline data:', e);\n showTimelineError(container, 'json-parse', e.message);\n hideTimelineLoader();\n }\n}\n\nexport function clearTimelineCache(timelineId) {\n if (typeof(Storage) === 'undefined') {\n console.warn('localStorage not supported');\n return;\n }\n\n if (timelineId) {\n const key = 'vjs_' + timelineId;\n localStorage.removeItem(key);\n console.log('Cleared cache for timeline:', timelineId);\n } else {\n const keys = Object.keys(localStorage);\n let cleared = 0;\n keys.forEach(function(key) {\n if (key.startsWith('vjs_')) {\n localStorage.removeItem(key);\n cleared++;\n }\n });\n console.log('Cleared', cleared, 'timeline cache(s)');\n }\n}\n","// --------------------------------------------------------------------------\r\n// timeline.js - a vanilla JS app to display timelines\r\n// \r\n// Created in 2018 by Mike Collins (https://github.com/squarechip/timeline)\r\n// Modified in 2026 by Ken Dawson (https://github.com/kendawson-online)\r\n// Last updated: 01/08/26\r\n//\r\n// --------------------------------------------------------------------------\r\n\r\nimport { createTimelineModal, openTimelineModal, closeTimelineModal } from './features/modals.js';\r\nimport { handleDeepLinking, navigateToNodeIndex } from './features/deep-linking.js';\r\nimport { renderTimelineFromData, timelineFromData, loadDataFromJson, processTimelineData, clearTimelineCache } from './features/data-loader.js';\r\nimport { timeline } from './core/timeline-engine.js';\r\nimport '../css/timeline.css';\r\n\r\nfunction autoInitJsonTimelines() {\r\n const timelinesWithJson = document.querySelectorAll('[data-json-config]');\r\n timelinesWithJson.forEach(function(timelineEl) {\r\n const jsonUrl = timelineEl.getAttribute('data-json-config');\r\n if (!jsonUrl) return;\r\n const className = (timelineEl.className || '').split(' ')[0];\r\n const selector = timelineEl.id ? '#' + timelineEl.id : (className ? '.' + className : null);\r\n if (selector) {\r\n loadDataFromJson(jsonUrl, selector);\r\n }\r\n });\r\n}\r\n\r\nfunction exposeGlobals() {\r\n if (typeof window === 'undefined') return;\r\n window.timeline = timeline;\r\n window.timelineFromData = timelineFromData;\r\n window.renderTimelineFromData = renderTimelineFromData;\r\n window.processTimelineData = processTimelineData;\r\n window.loadDataFromJson = loadDataFromJson;\r\n window.clearTimelineCache = clearTimelineCache;\r\n window.createTimelineModal = createTimelineModal;\r\n window.openTimelineModal = openTimelineModal;\r\n window.closeTimelineModal = closeTimelineModal;\r\n window.handleTimelineDeepLinking = handleDeepLinking;\r\n window.navigateTimelineToNodeIndex = navigateToNodeIndex;\r\n}\r\n\r\nexposeGlobals();\r\n\r\ndocument.addEventListener('DOMContentLoaded', function() {\r\n autoInitJsonTimelines();\r\n});\r\n\r\nif (typeof window !== 'undefined' && window.jQuery) {\r\n (( $) => {\r\n $.fn.timeline = function(opts) {\r\n timeline(this, opts);\r\n return this;\r\n };\r\n })(window.jQuery);\r\n}\r\n\r\nexport {\r\n timeline,\r\n timelineFromData,\r\n renderTimelineFromData,\r\n loadDataFromJson,\r\n processTimelineData,\r\n clearTimelineCache,\r\n createTimelineModal,\r\n openTimelineModal,\r\n closeTimelineModal,\r\n handleDeepLinking,\r\n navigateToNodeIndex\r\n};"],"names":["loaderState","count","startTime","removeTimer","overlayEl","modalState","modal","overlay","timelineRegistry","createTimelineModal","document","createElement","className","addEventListener","closeTimelineModal","innerHTML","closeBtn","querySelector","closeBottomBtn","e","stopPropagation","body","appendChild","key","classList","contains","openTimelineModal","itemEl","title","getAttribute","content","image","html","modalTitle","modalText","modalImage","textContent","src","alt","style","display","replace","setTimeout","add","overflow","remove","handleDeepLinking","containerSelector","urlParams","URLSearchParams","window","location","search","timelineId","get","nodeId","targetContainer","getElementById","console","warn","scrollIntoView","behavior","block","targetNode","itemIndex","Array","from","parentNode","children","indexOf","navigateToNodeIndex","container","index","id","tlData","setCurrentIndex","updatePosition","timelineBasePath","TimelineConfig","basePath","scripts","getElementsByTagName","i","length","dir","substring","lastIndexOf","showTimelineLoader","Date","now","clearTimeout","loader","spinner","width","height","hideTimelineLoader","elapsed","remaining","Math","max","removeOverlay","showTimelineError","errorType","details","errorInfo","message","solution","errorDiv","errorIcon","errorTitle","errorMessage","errorSolution","errorDetails","error","getColorBrightness","color","rgb","startsWith","hex","parseInt","matches","match","map","Number","applyTimelineColors","config","nodeColor","lineColor","navColor","setProperty","arrowColor","setAttribute","createArrowSVG","direction","timeline","collection","options","timelines","warningLabel","resizeTimer","winWidth","innerWidth","currentIndex","shouldHideLoader","defaultSettings","minWidth","type","defaultValue","maxWidth","horizontalStartPosition","acceptedValues","mode","moveItems","rtlMode","startIndex","verticalStartPosition","verticalTrigger","visibleItems","itemWrap","el","wrapper","classes","insertBefore","isElementInViewport","triggerPosition","rect","getBoundingClientRect","windowHeight","innerHeight","documentElement","clientHeight","defaultTrigger","triggerUnit","unit","triggerValue","value","trigger","top","left","clientWidth","addTransforms","transform","webkitTransform","msTransform","timelinePosition","tl","str","items","offsetLeft","scroller","setUpHorinzontalTimeline","settings","timelineEl","itemWidth","forEach","item","scrollerWidth","oddIndexTallest","evenIndexTallest","offsetHeight","transformString","setHeights","setHeightandWidths","viewportWidth","wrap","offsetWidth","itemsVisible","floor","prevArrow","nextArrow","topPosition","maxIndex","disabled","addNavigation","divider","removeChild","horizontalDivider","addHorizontalDivider","navArrows","querySelectorAll","arrowPrev","arrowNext","handleArrowClick","preventDefault","this","arrow","listeners","push","element","handler","slideTimeline","min","setUpTimelines","opacity","removeEventListener","observer","disconnect","removeAttribute","resetTimelines","useHorizontalMode","lastVisibleIndex","observerOptions","rootMargin","threshold","IntersectionObserver","entries","entry","isIntersecting","target","observe","scrollHandler","setUpVerticalTimeline","timelineName","errorPart","data","dataset","Error","slice","call","Object","keys","candidate","undefined","minwidth","forceVerticalMode","forceverticalmode","maxwidth","settingName","getData","k","toLowerCase","triggerArray","triggerValid","hasAttribute","heading","trim","firstP","img","ensureInlineModalData","enhanceInlineItems","random","toString","substr","newWinWidth","renderTimelineFromData","itemsWrap","layoutMode","applyDataAttributes","existingHeading","previousElementSibling","it","onerror","textWrapper","para","displayText","createItemNode","timelineFromData","loadDataFromJson","url","cacheKey","cached","localStorage","getItem","cachedData","JSON","parse","fetch","then","res","ok","status","json","lastupdated","log","processTimelineData","setItem","stringify","catch","err","nodes","isArray","clearTimelineCache","removeItem","cleared","handleTimelineDeepLinking","navigateTimelineToNodeIndex","jsonUrl","split","selector","jQuery","fn","opts"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kendawson-online/vantl",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "description": "A vanilla JavaScript library that creates responsive timelines for both horizontal and vertical layouts",
5
5
  "main": "dist/timeline.min.js",
6
6
  "scripts": {
@@ -9,7 +9,10 @@
9
9
  },
10
10
  "devDependencies": {
11
11
  "@rollup/plugin-terser": "^0.4.4",
12
- "rollup": "^4.55.1"
12
+ "cssnano": "^7.1.2",
13
+ "postcss": "^8.5.6",
14
+ "rollup": "^4.55.1",
15
+ "rollup-plugin-postcss": "^4.0.2"
13
16
  },
14
17
  "keywords": [
15
18
  "timeline",
@@ -33,5 +36,7 @@
33
36
  "src/images"
34
37
  ],
35
38
  "prepare": "npm run build",
36
- "publishConfig": { "access": "public" }
39
+ "publishConfig": {
40
+ "access": "public"
41
+ }
37
42
  }
@@ -669,8 +669,9 @@
669
669
  }
670
670
 
671
671
  .timeline__loader-spinner {
672
- width: 498px;
673
- height: 328px;
672
+ width: 120px;
673
+ max-width: 100%;
674
+ height: auto;
674
675
  display: block;
675
676
  object-fit: contain;
676
677
  }
@@ -693,7 +694,8 @@
693
694
 
694
695
  .timeline__error-icon {
695
696
  width: 200px;
696
- height: 200px;
697
+ max-width: 100%;
698
+ height: auto;
697
699
  margin-bottom: 24px;
698
700
  opacity: 0.8;
699
701
  }
File without changes
File without changes
File without changes