lifecycle-timeline 1.2.9 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/timeline.css CHANGED
@@ -1 +1 @@
1
- .lt-root{--bg-page: #f9fafb;--bg-card: #ffffff;--bg-track: #e5e7eb;--text-primary: #1f2937;--text-secondary: #6b7280;--text-inverse: #ffffff;--border-color: #e5e7eb;--line-color: #e5e7eb;--grid-line: #9ca3af;--accent-oss: #99e67d;--accent-ent: #ffe88e;--current-date: #086dc3;--accent-eol: #ef4444;--font-family: "Inter", system-ui, -apple-system, sans-serif;--tooltip-bg: #ffffff;--tooltip-shadow: rgba(0, 0, 0, .1);transition:background-color .3s ease,color .3s ease;background-color:var(--bg-card);color:var(--text-primary);font-family:var(--font-family);padding:24px;border-radius:16px;overflow:hidden;border:1px solid var(--border-color)}.lt-root[data-theme=dark]{--bg-page: #111827;--bg-card: #1f2937;--bg-track: #374151;--text-primary: #f9fafb;--text-secondary: #9ca3af;--border-color: #374151;--line-color: #374151;--grid-line: #6b7280;--tooltip-bg: #1f2937;--tooltip-shadow: rgba(0, 0, 0, .5);--accent-oss: #78bd5d;--accent-ent: #e3c456;--accent-eol: #f87171}.lt-wrapper{position:relative;padding-top:40px;padding-bottom:60px;overflow-x:auto;scrollbar-width:thin}.lt-header{display:flex;position:sticky;left:0;margin-bottom:20px}.lt-tracks{position:relative;padding-top:20px}.lt-axis{display:flex;border-bottom:1px solid var(--border-color);margin-bottom:10px;padding-bottom:8px;position:relative}.lt-year{flex:1;font-size:.875rem;font-weight:600;color:var(--text-secondary);border-left:1px dashed var(--border-color);padding-left:0;text-align:center;box-sizing:border-box}.lt-year:first-child{border-left:none}.lt-row{display:flex;align-items:center;margin-bottom:1.5rem;position:relative;min-height:36px;height:auto;z-index:1;opacity:0;transform:translateY(10px);transition:opacity .4s ease,transform .4s ease}.lt-row.lt-row-visible{opacity:1;transform:translateY(0)}.lt-version-label{width:90px;min-width:90px;box-sizing:border-box;padding:4px;border-radius:12px;flex-shrink:0;font-weight:600;font-size:.85rem;color:var(--text-primary);margin-right:16px;text-align:center;background-color:transparent;cursor:pointer;transition:all .3s ease;position:sticky;left:0;z-index:10;white-space:normal;word-wrap:break-word;overflow:visible;display:flex;align-items:center;justify-content:center;line-height:1.2}.lt-version-label.lt-version-major{font-weight:800;border:2px solid var(--border-color)}.lt-version-label:hover{transform:scale(1.05);box-shadow:0 4px 12px #0000001a;filter:brightness(.95)}.lt-version-label a.lt-version-link{text-decoration:none;color:inherit;display:block;width:100%;height:100%}.lt-version-label a.lt-version-link:hover{text-decoration:underline;opacity:.8}.lt-status-oss{background-color:var(--accent-oss);color:#000}.lt-status-ent{background-color:var(--accent-ent);color:#000}.lt-status-expired{background-color:var(--accent-eol);color:#fff}.lt-status-future{background-color:var(--bg-track);color:var(--text-secondary);border:1px solid var(--border-color)}.lt-track-container{flex-grow:1;position:relative;height:36px;background:var(--bg-track);border-radius:0;overflow:hidden;transition:background-color .3s ease}.lt-bar-segment{position:absolute;height:100%;top:0;transition:opacity .3s ease;display:flex;align-items:center;justify-content:center;color:#fff;font-size:.75rem;font-weight:500;overflow:hidden;white-space:nowrap;box-shadow:0 1px 2px #0000001a}.lt-bar-oss{background:linear-gradient(to bottom,#dcfce7 0%,var(--accent-oss) 100%);z-index:2;border-radius:0;height:100%;top:auto;bottom:0}[data-theme=dark] .lt-bar-oss{background:linear-gradient(to bottom,#a7f3d0 0%,var(--accent-oss) 100%)}.lt-bar-ent{background:linear-gradient(to bottom,#fef9c3 0%,var(--accent-ent) 100%);z-index:1;border-radius:0;opacity:.9;height:100%}.lt-bar-eol{background:linear-gradient(to bottom,#fee2e2 0%,var(--accent-eol) 100%);z-index:0;border-radius:0;opacity:.8}.lt-grid-lines-container{position:absolute;inset:0 0 0 96px;pointer-events:none;z-index:5}.lt-indicators-container{position:absolute;inset:0 0 0 96px;pointer-events:none;z-index:20}.lt-current-date-indicator{position:absolute;top:-30px;bottom:0;width:3px;background-image:linear-gradient(to bottom,var(--current-date) 60%,transparent 60%);background-size:3px 20px;background-repeat:repeat-y;border-left:none;z-index:20;pointer-events:none}@keyframes pulse-blue{0%{box-shadow:0 0 #086dc3b3}70%{box-shadow:0 0 0 6px #086dc300}to{box-shadow:0 0 #086dc300}}.lt-current-date-badge{position:absolute;top:100%;margin-top:8px;left:50%;transform:translate(-50%);background-color:var(--current-date);color:#fff;padding:4px 12px;border-radius:12px;font-size:.75rem;font-weight:600;white-space:nowrap;box-shadow:0 2px 4px #086dc333;z-index:25;animation:pulse-blue 2s infinite}.lt-year-grid-line{position:absolute;top:0;bottom:0;border-left:2px solid var(--grid-line);opacity:1;z-index:5;pointer-events:none}.lt-tooltip{position:absolute;background:var(--tooltip-bg);color:var(--text-primary);padding:10px 14px;border-radius:8px;font-size:.85rem;box-shadow:0 10px 15px -3px var(--tooltip-shadow),0 4px 6px -4px var(--tooltip-shadow);border:1px solid var(--border-color);pointer-events:none;z-index:10000;transition:opacity .15s ease-out;line-height:1.4}.lt-tooltip-header{font-weight:700;margin-bottom:4px;color:var(--current-date);text-transform:uppercase;font-size:.75rem;letter-spacing:.05em}.lt-tooltip-date strong{color:var(--text-secondary)}.lt-row{transition:opacity .3s ease,transform .3s ease,height .3s ease}.lt-row[style*="display: none"]{opacity:0;transform:translateY(10px)}.lt-bar-segment{transition:transform .2s ease,box-shadow .2s ease}.lt-bar-segment:hover{box-shadow:0 4px 12px #0000001a}.lt-bar-segment:focus-visible{outline:2px solid var(--text-primary);outline-offset:-2px;z-index:100}.lt-track-container{transition:background-color .3s ease}.lt-legend{margin:40px auto 0;padding:24px;background-color:var(--bg-card);border:1px solid var(--border-color);border-radius:12px;display:flex;flex-direction:column;gap:16px;max-width:800px}.lt-legend-block{display:flex;align-items:flex-start;gap:12px}.lt-legend-icon{width:20px;height:20px;border-radius:4px;flex-shrink:0;margin-top:2px}.lt-legend-block h3{margin:0 0 4px;font-size:1rem;font-weight:700;color:var(--text-primary)}.lt-legend-block p{margin:0;font-size:.9rem;color:var(--text-secondary);line-height:1.5}.lt-legend-block.oss .lt-legend-icon{background-color:var(--accent-oss)}.lt-legend-block.commercial .lt-legend-icon{background-color:var(--accent-ent)}.lt-legend-block.eol .lt-legend-icon{background-color:var(--accent-eol)}.lt-toolbar{display:flex;justify-content:flex-start;align-items:center;margin-bottom:24px;gap:16px}.lt-filter-container{display:flex;align-items:center;gap:12px;background:var(--bg-card);border:1px solid var(--border-color);padding:8px 16px;border-radius:24px;max-width:400px;flex-grow:1;transition:all .3s ease;box-shadow:0 2px 4px #0000000d}.lt-filter-container:focus-within{border-color:var(--current-date);box-shadow:0 8px 20px #086dc31a}.lt-filter-input{border:none;outline:none;font-size:.95rem;color:var(--text-primary);background:transparent;width:100%}.lt-checkbox-label{display:flex;align-items:center;gap:8px;font-size:.85rem;color:var(--text-primary);cursor:pointer;-webkit-user-select:none;user-select:none}.lt-checkbox-label input{width:16px;height:16px;cursor:pointer}.lt-highlight-match{background-color:#fde68a;color:#92400e;padding:0 2px;border-radius:2px;font-weight:700}.lt-legend{display:flex;flex-wrap:wrap;gap:1.5rem;margin-top:2rem;padding-top:1.5rem;border-top:1px solid var(--border-color)}.lt-legend-item-reactive{cursor:pointer;transition:all .2s ease;padding:8px;border-radius:8px;border:1px solid transparent}.lt-legend-item-reactive:hover{background-color:var(--bg-track);transform:translateY(-2px)}.lt-legend-item-reactive.lt-active-highlight{background-color:var(--bg-track);border-color:var(--grid-line);box-shadow:0 2px 4px #0000001a}.lt-bar-segment,.lt-version-label{transition:opacity .3s ease,filter .3s ease}.lt-mode-compact .lt-row{margin-bottom:.85rem;height:24px}.lt-mode-compact .lt-version-label{font-size:.75rem;padding:2px 4px}.lt-mode-compact .lt-bar-segment{font-size:.7rem}[class*=lt-highlight-oss] .lt-bar-segment:not(.lt-segment-oss),[class*=lt-highlight-oss] .lt-version-label:not(.lt-status-oss){opacity:.3;filter:grayscale(.5)}[class*=lt-highlight-ent] .lt-bar-segment:not(.lt-segment-ent),[class*=lt-highlight-ent] .lt-version-label:not(.lt-status-ent){opacity:.3;filter:grayscale(.5)}[class*=lt-highlight-eol] .lt-bar-segment,[class*=lt-highlight-eol] .lt-version-label:not(.lt-status-expired){opacity:.3;filter:grayscale(.5)}.lt-toggle-btn{display:flex;align-items:center;gap:8px;background:var(--bg-card);border:1px solid var(--border-color);padding:8px 16px;border-radius:20px;cursor:pointer;font-size:.875rem;font-weight:500;color:var(--text-primary);box-shadow:0 1px 2px #0000000d;transition:all .2s ease}.lt-toggle-btn:hover{background:var(--bg-page);border-color:var(--text-secondary);transform:translateY(-1px)}.lt-toggle-btn:focus-visible{outline:2px solid var(--current-date);outline-offset:2px}.lt-theme-toggle-btn{position:absolute;top:24px;right:24px;background:var(--bg-card);border:1px solid var(--border-color);color:var(--text-primary);width:40px;height:40px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;z-index:1000;box-shadow:0 4px 6px -1px #0000001a}.lt-theme-toggle-btn:focus-visible{outline:2px solid var(--current-date);outline-offset:2px}.lt-root{position:relative}.lt-theme-toggle-btn:hover{background-color:var(--bg-track);transform:scale(1.1)}@media(max-width:1024px){.lt-wrapper{padding-left:0}}@media(max-width:768px){.page-container{padding:1rem}.lt-toolbar{flex-direction:column;align-items:stretch}.lt-filter-container{max-width:none}}.lt-row,.lt-table tr{transition:opacity .4s ease,transform .4s cubic-bezier(.4,0,.2,1)}.lt-row-hidden{display:none!important;opacity:0;transform:translateY(-10px)}.lt-row-visible{display:flex!important;opacity:1;transform:translateY(0)}.lt-table tr.lt-row-visible{display:table-row!important}.lt-tracks,.lt-table tbody{transition:max-height .5s ease-in-out}.lt-table-container{margin-top:1rem;margin-bottom:2rem;overflow-x:auto;border-radius:12px;border:1px solid var(--border-color);background-color:var(--bg-card);transition:all .3s ease}.lt-table{width:100%;border-collapse:collapse;font-size:.85rem;text-align:left}.lt-table th{background-color:var(--bg-page);color:var(--text-secondary);font-weight:700;padding:14px 16px;border-bottom:1px solid var(--border-color);text-transform:uppercase;font-size:.75rem;letter-spacing:.05em}.lt-table td{padding:12px 16px;border-bottom:1px solid var(--border-color);color:var(--text-primary);vertical-align:middle}.lt-table tr:hover td{background-color:var(--bg-page)}.lt-table tr:last-child td{border-bottom:none}.lt-table-badge{display:inline-block;padding:4px 12px;border-radius:12px;font-size:.85rem;font-weight:600;font-family:var(--font-family);text-align:center;min-width:64px;transition:all .3s ease}.lt-table-version-link{text-decoration:none;color:inherit;display:inline-block}.lt-table-version-link:hover .lt-table-badge{transform:translateY(-1px);box-shadow:0 4px 8px #0000001a}.lt-table-badge.status-oss{background-color:var(--accent-oss);color:#000}.lt-table-badge.status-ent{background-color:var(--accent-ent);color:#000}.lt-table-badge.status-expired{background-color:var(--accent-eol);color:#fff}.lt-past-date{color:var(--text-secondary);opacity:.7;font-style:italic}.lt-table-toggle{display:flex;justify-content:center;padding:10px;background-color:var(--bg-card);border-top:1px solid var(--border-color);border-bottom-left-radius:12px;margin-top:40px}.risk-high{color:#ef4444}.risk-medium{color:#f59e0b}.risk-low{color:#10b981}[data-theme=dark] .details-header{background-color:#0f172a}
1
+ .lt-root{--bg-page: #f9fafb;--bg-card: #ffffff;--bg-track: #e5e7eb;--text-primary: #1f2937;--text-secondary: #6b7280;--text-inverse: #ffffff;--border-color: #e5e7eb;--line-color: #e5e7eb;--grid-line: #9ca3af;--accent-oss: #99e67d;--accent-ent: #ffe88e;--current-date: #086dc3;--accent-eol: #ef4444;--font-family: "Inter", system-ui, -apple-system, sans-serif;--tooltip-bg: #ffffff;--tooltip-shadow: rgba(0, 0, 0, .1);transition:background-color .3s ease,color .3s ease;background-color:var(--bg-card);color:var(--text-primary);font-family:var(--font-family);padding:24px;border-radius:16px;overflow:hidden;border:1px solid var(--border-color)}.lt-root[data-theme=dark]{--bg-page: #111827;--bg-card: #1f2937;--bg-track: #374151;--text-primary: #f9fafb;--text-secondary: #9ca3af;--border-color: #374151;--line-color: #374151;--grid-line: #6b7280;--tooltip-bg: #1f2937;--tooltip-shadow: rgba(0, 0, 0, .5);--accent-oss: #78bd5d;--accent-ent: #e3c456;--accent-eol: #f87171}.lt-wrapper{position:relative;padding-top:40px;padding-bottom:60px;overflow-x:auto;scrollbar-width:thin}.lt-header{display:flex;position:sticky;left:0;margin-bottom:20px}.lt-tracks{position:relative;padding-top:20px}.lt-axis{display:flex;border-bottom:1px solid var(--border-color);margin-bottom:10px;padding-bottom:8px;position:relative}.lt-year{flex:1;font-size:.875rem;font-weight:600;color:var(--text-secondary);border-left:1px dashed var(--border-color);padding-left:0;text-align:center;box-sizing:border-box}.lt-year:first-child{border-left:none}.lt-row{display:flex;align-items:center;margin-bottom:1.5rem;position:relative;min-height:36px;height:auto;z-index:1;opacity:0;transform:translateY(10px);transition:opacity .4s ease,transform .4s ease}.lt-row.lt-row-visible{opacity:1;transform:translateY(0)}.lt-version-label{width:90px;min-width:90px;box-sizing:border-box;padding:4px;border-radius:12px;flex-shrink:0;font-weight:600;font-size:.85rem;color:var(--text-primary);margin-right:16px;text-align:center;background-color:transparent;cursor:pointer;transition:all .3s ease;position:sticky;left:0;z-index:10;white-space:normal;word-wrap:break-word;overflow:visible;display:flex;align-items:center;justify-content:center;line-height:1.2}.lt-version-label.lt-version-major{font-weight:800;border:2px solid var(--border-color)}.lt-version-label:hover{transform:scale(1.05);box-shadow:0 4px 12px #0000001a;filter:brightness(.95)}.lt-version-label a.lt-version-link{text-decoration:none;color:inherit;display:block;width:100%;height:100%}.lt-version-label a.lt-version-link:hover{text-decoration:underline;opacity:.8}.lt-status-oss{background-color:var(--accent-oss);color:#000}.lt-status-ent{background-color:var(--accent-ent);color:#000}.lt-status-expired{background-color:var(--accent-eol);color:#fff}.lt-status-future{background-color:var(--bg-track);color:var(--text-secondary);border:1px solid var(--border-color)}.lt-status-is-future{background-color:var(--current-date);color:#fff}.lt-status-fictive{background-color:#94a3b8;color:#fff;opacity:.8}.lt-track-container{flex-grow:1;position:relative;height:36px;background:var(--bg-track);border-radius:0;overflow:hidden;transition:background-color .3s ease}.lt-bar-segment{position:absolute;height:100%;top:0;transition:opacity .3s ease;display:flex;align-items:center;justify-content:center;color:#fff;font-size:.75rem;font-weight:500;overflow:hidden;white-space:nowrap;box-shadow:0 1px 2px #0000001a}.lt-bar-oss{background:linear-gradient(to bottom,#dcfce7 0%,var(--accent-oss) 100%);z-index:2;border-radius:0;height:100%;top:auto;bottom:0}[data-theme=dark] .lt-bar-oss{background:linear-gradient(to bottom,#a7f3d0 0%,var(--accent-oss) 100%)}.lt-bar-oss.lt-is-future-oss{background:linear-gradient(to bottom,#7dd3fc 0%,var(--current-date) 100%)}.lt-bar-ent{background:linear-gradient(to bottom,#fef9c3 0%,var(--accent-ent) 100%);z-index:1;border-radius:0;opacity:.9;height:100%}.lt-bar-eol{background:linear-gradient(to bottom,#fee2e2 0%,var(--accent-eol) 100%);z-index:0;border-radius:0;opacity:.8}.lt-is-fictive-bar{filter:desaturate(1) opacity(.4);background:#94a3b8!important}.lt-grid-lines-container{position:absolute;inset:0 0 0 106px;pointer-events:none;z-index:5}.lt-indicators-container{position:absolute;inset:0 0 0 106px;pointer-events:none;z-index:20}.lt-current-date-indicator{position:absolute;top:-30px;bottom:0;width:3px;background-image:linear-gradient(to bottom,var(--current-date) 60%,transparent 60%);background-size:3px 20px;background-repeat:repeat-y;border-left:none;z-index:20;pointer-events:none}@keyframes pulse-blue{0%{box-shadow:0 0 #086dc3b3}70%{box-shadow:0 0 0 6px #086dc300}to{box-shadow:0 0 #086dc300}}.lt-current-date-badge{position:absolute;top:100%;margin-top:8px;left:50%;transform:translate(-50%);background-color:var(--current-date);color:#fff;padding:4px 12px;border-radius:12px;font-size:.75rem;font-weight:600;white-space:nowrap;box-shadow:0 2px 4px #086dc333;z-index:25;animation:pulse-blue 2s infinite}.lt-year-grid-line{position:absolute;top:0;bottom:0;border-left:2px solid var(--grid-line);opacity:1;z-index:5;pointer-events:none}.lt-tooltip{position:absolute;background:var(--tooltip-bg);color:var(--text-primary);padding:10px 14px;border-radius:8px;font-size:.85rem;box-shadow:0 10px 15px -3px var(--tooltip-shadow),0 4px 6px -4px var(--tooltip-shadow);border:1px solid var(--border-color);pointer-events:none;z-index:10000;transition:opacity .15s ease-out;line-height:1.4}.lt-tooltip-header{font-weight:700;margin-bottom:4px;color:var(--current-date);text-transform:uppercase;font-size:.75rem;letter-spacing:.05em}.lt-tooltip-date strong{color:var(--text-secondary)}.lt-row{transition:opacity .3s ease,transform .3s ease,height .3s ease}.lt-row[style*="display: none"]{opacity:0;transform:translateY(10px)}.lt-bar-segment{transition:transform .2s ease,box-shadow .2s ease}.lt-bar-segment:hover{box-shadow:0 4px 12px #0000001a}.lt-bar-segment:focus-visible{outline:2px solid var(--text-primary);outline-offset:-2px;z-index:100}.lt-track-container{transition:background-color .3s ease}.lt-legend{margin:40px auto 0;padding:24px;background-color:var(--bg-card);border:1px solid var(--border-color);border-radius:12px;display:flex;flex-direction:column;gap:16px;max-width:800px}.lt-legend-block{display:flex;align-items:flex-start;gap:12px}.lt-legend-icon{width:20px;height:20px;border-radius:4px;flex-shrink:0;margin-top:2px}.lt-legend-block h3{margin:0 0 4px;font-size:1rem;font-weight:700;color:var(--text-primary)}.lt-legend-block p{margin:0;font-size:.9rem;color:var(--text-secondary);line-height:1.5}.lt-legend-block.oss .lt-legend-icon{background-color:var(--accent-oss)}.lt-legend-block.commercial .lt-legend-icon{background-color:var(--accent-ent)}.lt-legend-block.eol .lt-legend-icon{background-color:var(--accent-eol)}.lt-legend-block.future .lt-legend-icon{background-color:var(--current-date)}.lt-legend-block.fictive .lt-legend-icon{background-color:#94a3b8}.lt-toolbar{display:flex;justify-content:flex-start;align-items:center;margin-bottom:24px;gap:16px}.lt-filter-container{display:flex;align-items:center;gap:12px;background:var(--bg-card);border:1px solid var(--border-color);padding:8px 16px;border-radius:24px;max-width:400px;flex-grow:1;transition:all .3s ease;box-shadow:0 2px 4px #0000000d}.lt-filter-container:focus-within{border-color:var(--current-date);box-shadow:0 8px 20px #086dc31a}.lt-filter-input{border:none;outline:none;font-size:.95rem;color:var(--text-primary);background:transparent;width:100%}.lt-checkbox-label{display:flex;align-items:center;gap:8px;font-size:.85rem;color:var(--text-primary);cursor:pointer;-webkit-user-select:none;user-select:none}.lt-checkbox-label input{width:16px;height:16px;cursor:pointer}.lt-highlight-match{background-color:#fde68a;color:#92400e;padding:0 2px;border-radius:2px;font-weight:700}.lt-legend{display:flex;flex-wrap:wrap;gap:1.5rem;margin-top:2rem;padding-top:1.5rem;border-top:1px solid var(--border-color)}.lt-legend-item-reactive{cursor:pointer;transition:all .2s ease;padding:8px;border-radius:8px;border:1px solid transparent}.lt-legend-item-reactive:hover{background-color:var(--bg-track);transform:translateY(-2px)}.lt-legend-item-reactive.lt-active-highlight{background-color:var(--bg-track);border-color:var(--grid-line);box-shadow:0 2px 4px #0000001a}.lt-bar-segment,.lt-version-label{transition:opacity .3s ease,filter .3s ease}.lt-mode-compact .lt-row{margin-bottom:.85rem;height:24px}.lt-mode-compact .lt-version-label{font-size:.75rem;padding:2px 4px}.lt-mode-compact .lt-bar-segment{font-size:.7rem}[class*=lt-highlight-oss] .lt-bar-segment:not(.lt-segment-oss),[class*=lt-highlight-oss] .lt-version-label:not(.lt-status-oss){opacity:.3;filter:grayscale(.5)}[class*=lt-highlight-ent] .lt-bar-segment:not(.lt-segment-ent),[class*=lt-highlight-ent] .lt-version-label:not(.lt-status-ent){opacity:.3;filter:grayscale(.5)}[class*=lt-highlight-eol] .lt-bar-segment,[class*=lt-highlight-eol] .lt-version-label:not(.lt-status-expired){opacity:.3;filter:grayscale(.5)}[class*=lt-highlight-future] .lt-bar-segment:not(.lt-is-future-oss),[class*=lt-highlight-future] .lt-version-label:not(.lt-status-is-future){opacity:.3;filter:grayscale(.5)}[class*=lt-highlight-fictive] .lt-bar-segment:not(.lt-is-fictive-bar),[class*=lt-highlight-fictive] .lt-version-label:not(.lt-status-fictive){opacity:.3;filter:grayscale(.5)}.lt-toggle-btn{display:flex;align-items:center;gap:8px;background:var(--bg-card);border:1px solid var(--border-color);padding:8px 16px;border-radius:20px;cursor:pointer;font-size:.875rem;font-weight:500;color:var(--text-primary);box-shadow:0 1px 2px #0000000d;transition:all .2s ease}.lt-toggle-btn:hover{background:var(--bg-page);border-color:var(--text-secondary);transform:translateY(-1px)}.lt-toggle-btn:focus-visible{outline:2px solid var(--current-date);outline-offset:2px}.lt-theme-toggle-btn{position:absolute;top:24px;right:24px;background:var(--bg-card);border:1px solid var(--border-color);color:var(--text-primary);width:40px;height:40px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;z-index:1000;box-shadow:0 4px 6px -1px #0000001a}.lt-theme-toggle-btn:focus-visible{outline:2px solid var(--current-date);outline-offset:2px}.lt-root{position:relative}.lt-theme-toggle-btn:hover{background-color:var(--bg-track);transform:scale(1.1)}@media(max-width:1024px){.lt-wrapper{padding-left:0}}@media(max-width:768px){.page-container{padding:1rem}.lt-toolbar{flex-direction:column;align-items:stretch}.lt-filter-container{max-width:none}}.lt-row,.lt-table tr{transition:opacity .4s ease,transform .4s cubic-bezier(.4,0,.2,1)}.lt-row-hidden{display:none!important;opacity:0;transform:translateY(-10px)}.lt-row-visible{display:flex!important;opacity:1;transform:translateY(0)}.lt-table tr.lt-row-visible{display:table-row!important}.lt-tracks,.lt-table tbody{transition:max-height .5s ease-in-out}.lt-table-container{margin-top:1rem;margin-bottom:2rem;overflow-x:auto;border-radius:12px;border:1px solid var(--border-color);background-color:var(--bg-card);transition:all .3s ease}.lt-table{width:100%;border-collapse:collapse;font-size:.85rem;text-align:left}.lt-table th{background-color:var(--bg-page);color:var(--text-secondary);font-weight:700;padding:14px 16px;border-bottom:1px solid var(--border-color);text-transform:uppercase;font-size:.75rem;letter-spacing:.05em}.lt-table td{padding:12px 16px;border-bottom:1px solid var(--border-color);color:var(--text-primary);vertical-align:middle}.lt-table tr:hover td{background-color:var(--bg-page)}.lt-table tr:last-child td{border-bottom:none}.lt-table-badge{display:inline-block;padding:4px 12px;border-radius:12px;font-size:.85rem;font-weight:600;font-family:var(--font-family);text-align:center;min-width:64px;transition:all .3s ease}.lt-table-version-link{text-decoration:none;color:inherit;display:inline-block}.lt-table-version-link:hover .lt-table-badge{transform:translateY(-1px);box-shadow:0 4px 8px #0000001a}.lt-table-badge.lt-status-oss{background-color:var(--accent-oss);color:#000}.lt-table-badge.lt-status-ent{background-color:var(--accent-ent);color:#000}.lt-table-badge.lt-status-expired{background-color:var(--accent-eol);color:#fff}.lt-table-badge.lt-status-is-future{background-color:var(--current-date);color:#fff}.lt-table-badge.lt-status-fictive{background-color:#94a3b8;color:#fff;opacity:.8}.lt-past-date{color:var(--text-secondary);opacity:.7;font-style:italic}.lt-table-toggle{display:flex;justify-content:center;padding:10px;background-color:var(--bg-card);border-top:1px solid var(--border-color);border-bottom-left-radius:12px;margin-top:40px}.risk-high{color:#ef4444}.risk-medium{color:#f59e0b}.risk-low{color:#10b981}[data-theme=dark] .details-header{background-color:#0f172a}
@@ -73,11 +73,6 @@ declare class Timeline {
73
73
  * @param newData - The new data array.
74
74
  */
75
75
  updateData(newData: TimelineVersion[]): void;
76
- /**
77
- * Validates the input data.
78
- * @param data - The data array to validate.
79
- * @returns The validated and filtered data array.
80
- */
81
76
  validateData(data: TimelineVersion[]): TimelineVersion[];
82
77
  /**
83
78
  * Calculates the min and max years based on the data.
@@ -257,11 +252,13 @@ declare interface TimelineOptions {
257
252
 
258
253
  declare interface TimelineVersion {
259
254
  version: string;
260
- ossStart: string;
261
- ossEnd: string;
255
+ ossStart?: string;
256
+ ossEnd?: string;
262
257
  enterpriseEnd?: string;
263
258
  releaseNotesUrl?: string;
264
259
  isMajor?: boolean;
260
+ isFuture?: boolean;
261
+ isFictive?: boolean;
265
262
  }
266
263
 
267
264
  export { }
package/dist/timeline.js CHANGED
@@ -1,4 +1,4 @@
1
- const p = {
1
+ const T = {
2
2
  en: {
3
3
  filter: "Filter versions...",
4
4
  oss: "OSS Support",
@@ -16,7 +16,11 @@ const p = {
16
16
  initial: "Initial Release",
17
17
  ossEnd: "End OSS",
18
18
  entEnd: "End Enterprise *",
19
- majorOnly: "Major versions only"
19
+ majorOnly: "Major versions only",
20
+ future: "Future Version",
21
+ futureDesc: "Planned version not yet released.",
22
+ fictive: "Fictive Version",
23
+ fictiveDesc: "Disabled or representative version."
20
24
  },
21
25
  fr: {
22
26
  filter: "Filtrer les versions...",
@@ -35,10 +39,14 @@ const p = {
35
39
  initial: "Sortie initiale",
36
40
  ossEnd: "Fin OSS",
37
41
  entEnd: "Fin Entreprise *",
38
- majorOnly: "Versions majeures uniquement"
42
+ majorOnly: "Versions majeures uniquement",
43
+ future: "Version future",
44
+ futureDesc: "Version prévue non encore sortie.",
45
+ fictive: "Version fictive",
46
+ fictiveDesc: "Version désactivée ou indicative."
39
47
  }
40
48
  };
41
- class f {
49
+ class E {
42
50
  root;
43
51
  options;
44
52
  visibleCount;
@@ -79,12 +87,17 @@ class f {
79
87
  * @param data - The data array containing version details.
80
88
  * @param options - Configuration options.
81
89
  */
82
- constructor(t, e, i = {}) {
90
+ constructor(t, s, e = {}) {
83
91
  if (this.root = document.getElementById(t), !this.root) {
84
- this.options = i, this.visibleCount = 3, this.showTable = !0, this.showThemeToggle = !0, this.showLegend = !0, this.filterVersions = !0, this.splitSupport = !1, this.compactMode = !1, this.showMajorFilter = !1, this.isExpanded = !1, this.theme = "light", this.filterText = "", this.majorFilterEnabled = !1, this.activeHighlight = null, this.translations = {}, this.locale = "en";
92
+ this.options = e, this.visibleCount = 3, this.showTable = !0, this.showThemeToggle = !0, this.showLegend = !0, this.filterVersions = !0, this.splitSupport = !1, this.compactMode = !1, this.showMajorFilter = !1, this.isExpanded = !1, this.theme = "light", this.filterText = "", this.majorFilterEnabled = !1, this.activeHighlight = null, this.translations = {}, this.locale = "en";
85
93
  return;
86
94
  }
87
- this.options = i, this.visibleCount = i.visibleCount || 3, this.showTable = i.showTable !== !1, this.showThemeToggle = i.showThemeToggle !== !1, this.showLegend = i.showLegend !== !1, this.filterVersions = i.filterVersions !== !1, this.splitSupport = i.splitSupport === !0, this.compactMode = i.compactMode === !0, this.showMajorFilter = i.showMajorFilter === !0, this.isExpanded = !1, this.theme = "light", this.filterText = "", this.majorFilterEnabled = i.majorFilterDefault === !0, this.activeHighlight = null, this.root.classList.add("lt-root"), this.root.classList.toggle("lt-mode-split", this.splitSupport), this.root.classList.toggle("lt-mode-overlay", !this.splitSupport), this.root.classList.toggle("lt-mode-compact", this.compactMode), this.root.setAttribute("data-theme", this.theme), this.translations = { ...p, ...i.i18n || {} }, this.locale = i.locale || this.detectLanguage(), this.setupBaseLayout(), this.updateData(e);
95
+ this.options = e, this.visibleCount = e.visibleCount || 3, this.showTable = e.showTable !== !1, this.showThemeToggle = e.showThemeToggle !== !1, this.showLegend = e.showLegend !== !1, this.filterVersions = e.filterVersions !== !1, this.splitSupport = e.splitSupport === !0, this.compactMode = e.compactMode === !0, this.showMajorFilter = e.showMajorFilter === !0, this.isExpanded = !1, this.theme = "light", this.filterText = "", this.majorFilterEnabled = e.majorFilterDefault === !0, this.activeHighlight = null, this.root.classList.add("lt-root"), this.root.classList.toggle("lt-mode-split", this.splitSupport), this.root.classList.toggle("lt-mode-overlay", !this.splitSupport), this.root.classList.toggle("lt-mode-compact", this.compactMode), this.root.setAttribute("data-theme", this.theme), this.translations = { ...T }, e.i18n && Object.keys(e.i18n).forEach((i) => {
96
+ this.translations[i] = {
97
+ ...this.translations[i] || this.translations.en || {},
98
+ ...e.i18n[i] || {}
99
+ };
100
+ }), this.locale = e.locale || this.detectLanguage(), this.setupBaseLayout(), this.updateData(s);
88
101
  }
89
102
  /**
90
103
  * Detects the browser language.
@@ -100,9 +113,9 @@ class f {
100
113
  * @param params - Parameters to replace in the translation string.
101
114
  * @returns The translated string.
102
115
  */
103
- t(t, e = {}) {
104
- let i = (this.translations[this.locale] || this.translations.en)[t] || t;
105
- return Object.keys(e).forEach((s) => i = i.replace(`{${s}}`, e[s])), i;
116
+ t(t, s = {}) {
117
+ let e = (this.translations[this.locale] || this.translations.en)[t] || t;
118
+ return Object.keys(s).forEach((i) => e = e.replace(`{${i}}`, s[i])), e;
106
119
  }
107
120
  /**
108
121
  * Sets up the initial layout of the timeline.
@@ -117,18 +130,12 @@ class f {
117
130
  updateData(t) {
118
131
  this.data = this.validateData(t || []), this.calculateTimeRange(), this.render();
119
132
  }
120
- /**
121
- * Validates the input data.
122
- * @param data - The data array to validate.
123
- * @returns The validated and filtered data array.
124
- */
125
133
  validateData(t) {
126
- return t.filter((e, i) => {
127
- const o = ["version", "ossStart", "ossEnd"].filter((l) => !e[l]);
128
- if (o.length > 0)
129
- return console.warn(`[Timeline] Missing fields for item at index ${i}: ${o.join(", ")}`), !1;
130
- const a = ["ossStart", "ossEnd", "enterpriseEnd"].filter((l) => e[l]).filter((l) => isNaN(new Date(e[l]).getTime()));
131
- return a.length > 0 ? (console.warn(`[Timeline] Invalid date format for item "${e.version}": ${a.join(", ")}`), !1) : !0;
134
+ return t.filter((s) => {
135
+ if (!s.ossStart || !s.ossEnd)
136
+ return s.isFictive = !0, !0;
137
+ const i = ["ossStart", "ossEnd", "enterpriseEnd"].filter((r) => s[r]).filter((r) => isNaN(new Date(s[r]).getTime()));
138
+ return i.length > 0 ? (console.warn(`[Timeline] Invalid date format for item "${s.version}": ${i.join(", ")}`), !1) : !0;
132
139
  });
133
140
  }
134
141
  /**
@@ -139,10 +146,14 @@ class f {
139
146
  this.minYear = this.currentDate.getFullYear() - 1, this.maxYear = this.currentDate.getFullYear() + 3;
140
147
  return;
141
148
  }
142
- const t = this.data.flatMap((e) => [
143
- new Date(e.ossStart).getTime(),
144
- new Date(e.enterpriseEnd || e.ossEnd).getTime()
149
+ const t = this.data.filter((s) => s.ossStart && s.ossEnd).flatMap((s) => [
150
+ new Date(s.ossStart).getTime(),
151
+ new Date(s.enterpriseEnd || s.ossEnd).getTime()
145
152
  ]);
153
+ if (t.length === 0) {
154
+ this.minYear = this.currentDate.getFullYear() - 1, this.maxYear = this.currentDate.getFullYear() + 3;
155
+ return;
156
+ }
146
157
  this.minYear = new Date(Math.min(...t)).getFullYear(), this.maxYear = new Date(Math.max(...t)).getFullYear();
147
158
  }
148
159
  /**
@@ -151,41 +162,41 @@ class f {
151
162
  renderTable() {
152
163
  const t = this.el("table", "lt-table", this.tableContainer);
153
164
  t.setAttribute("aria-label", "Project support");
154
- const e = this.el("thead", "", t), i = this.el("tr", "", e);
155
- [this.t("branch"), this.t("initial"), this.t("ossEnd"), this.t("entEnd")].forEach((s) => {
156
- this.el("th", "", i).textContent = s;
157
- }), this.tableBody = this.el("tbody", "", t), this.tableRows = this.data.map((s) => this.createTableRow(s)), this.tableToggleContainer = this.el("div", "lt-table-toggle", this.tableContainer), this.updateTableVisibility();
165
+ const s = this.el("thead", "", t), e = this.el("tr", "", s);
166
+ [this.t("branch"), this.t("initial"), this.t("ossEnd"), this.t("entEnd")].forEach((i) => {
167
+ this.el("th", "", e).textContent = i;
168
+ }), this.tableBody = this.el("tbody", "", t), this.tableRows = this.data.map((i) => this.createTableRow(i)), this.tableToggleContainer = this.el("div", "lt-table-toggle", this.tableContainer), this.updateTableVisibility();
158
169
  }
159
170
  /**
160
171
  * Creates a row for the data table.
161
172
  * @param item - Version data.
162
173
  */
163
174
  createTableRow(t) {
164
- const e = this.el("tr", "", this.tableBody), i = Date.now(), s = new Date(t.ossStart).getTime(), o = new Date(t.ossEnd).getTime(), n = t.enterpriseEnd ? new Date(t.enterpriseEnd).getTime() : o, a = i >= s && i <= o ? "lt-status-oss" : i > o && i <= n ? "lt-status-ent" : i > n ? "lt-status-expired" : "", l = this.el("td", "", e);
165
- let h = `<span class="lt-table-badge ${a}">${t.version}</span>`;
166
- t.releaseNotesUrl ? l.innerHTML = `<a href="${t.releaseNotesUrl}" target="_blank" class="lt-table-version-link">${h}</a>` : l.innerHTML = h;
167
- const r = this.el("td", "", e);
168
- r.textContent = t.ossStart, i > s && (r.className = "lt-past-date");
169
- const g = this.el("td", "", e);
170
- g.textContent = t.ossEnd, i > o && (g.className = "lt-past-date");
171
- const c = this.el("td", "", e);
172
- return c.textContent = t.enterpriseEnd || t.ossEnd, i > n && (c.className = "lt-past-date"), { el: e, version: t.version.toLowerCase(), versionOriginal: t.version };
175
+ const s = this.el("tr", "", this.tableBody), e = Date.now(), i = t.ossStart ? new Date(t.ossStart).getTime() : 0, r = t.ossEnd ? new Date(t.ossEnd).getTime() : 0, o = t.enterpriseEnd ? new Date(t.enterpriseEnd).getTime() : r, h = t.isFictive || !t.ossStart || !t.ossEnd ? "lt-status-fictive" : t.isFuture ? "lt-status-is-future" : e >= i && e <= r ? "lt-status-oss" : e > r && e <= o ? "lt-status-ent" : e > o ? "lt-status-expired" : "", d = this.el("td", "", s);
176
+ let n = `<span class="lt-table-badge ${h}">${t.version}</span>`;
177
+ t.releaseNotesUrl ? d.innerHTML = `<a href="${t.releaseNotesUrl}" target="_blank" class="lt-table-version-link">${n}</a>` : d.innerHTML = n;
178
+ const c = this.el("td", "", s);
179
+ c.textContent = t.ossStart || "-", t.ossStart && e > i && (c.className = "lt-past-date");
180
+ const u = this.el("td", "", s);
181
+ u.textContent = t.ossEnd || "-", t.ossEnd && e > r && (u.className = "lt-past-date");
182
+ const l = this.el("td", "", s);
183
+ return l.textContent = t.enterpriseEnd || t.ossEnd || "-", (t.enterpriseEnd || t.ossEnd) && e > o && (l.className = "lt-past-date"), { el: s, version: t.version.toLowerCase(), versionOriginal: t.version };
173
184
  }
174
185
  /**
175
186
  * Updates table visibility based on filter and visibleCount.
176
187
  */
177
188
  updateTableVisibility() {
178
- const t = this.tableRows.filter((s) => s.version.includes(this.filterText));
179
- this.tableRows.forEach((s) => {
180
- const o = s.el.querySelector(".lt-table-badge");
181
- o && (o.innerHTML = this.highlight(s.versionOriginal || s.version)), s.el.classList.remove("lt-row-visible"), s.el.classList.add("lt-row-hidden");
189
+ const t = this.tableRows.filter((i) => i.version.includes(this.filterText));
190
+ this.tableRows.forEach((i) => {
191
+ const r = i.el.querySelector(".lt-table-badge");
192
+ r && (r.innerHTML = this.highlight(i.versionOriginal || i.version)), i.el.classList.remove("lt-row-visible"), i.el.classList.add("lt-row-hidden");
182
193
  });
183
- const e = this.filterText === "" && t.length > this.visibleCount;
184
- if ((e && !this.isExpanded ? t.slice(0, this.visibleCount) : t).forEach((s) => {
185
- s.el.classList.remove("lt-row-hidden"), s.el.classList.add("lt-row-visible");
186
- }), this.tableToggleContainer.innerHTML = "", e) {
187
- const s = this.el("button", "lt-toggle-btn lt-table-toggle", this.tableToggleContainer), o = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="${this.isExpanded ? "18 15 12 9 6 15" : "6 9 12 15 18 9"}"></polyline></svg>`;
188
- s.innerHTML = this.isExpanded ? `${this.t("less")} ${o}` : `${this.t("more", { n: t.length - this.visibleCount })} ${o}`, s.onclick = () => {
194
+ const s = this.filterText === "" && t.length > this.visibleCount;
195
+ if ((s && !this.isExpanded ? t.slice(0, this.visibleCount) : t).forEach((i) => {
196
+ i.el.classList.remove("lt-row-hidden"), i.el.classList.add("lt-row-visible");
197
+ }), this.tableToggleContainer.innerHTML = "", s) {
198
+ const i = this.el("button", "lt-toggle-btn lt-table-toggle", this.tableToggleContainer), r = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="${this.isExpanded ? "18 15 12 9 6 15" : "6 9 12 15 18 9"}"></polyline></svg>`;
199
+ i.innerHTML = this.isExpanded ? `${this.t("less")} ${r}` : `${this.t("more", { n: t.length - this.visibleCount })} ${r}`, i.onclick = () => {
189
200
  this.isExpanded = !this.isExpanded, this.updateVisibility();
190
201
  };
191
202
  }
@@ -194,7 +205,7 @@ class f {
194
205
  * Renders the entire timeline.
195
206
  */
196
207
  render() {
197
- this.showTable && (this.tableContainer.innerHTML = ""), this.axis.innerHTML = "", this.tracks.innerHTML = "", this.showLegend && (this.legendContainer.innerHTML = ""), this.showTable && this.renderTable(), this.renderAxis(), this.grid = this.el("div", "lt-grid-lines-container", this.tracks), this.indicators = this.el("div", "lt-indicators-container", this.tracks), this.renderGrid(), this.renderCurrentDateLine(), this.rows = this.data.map((t, e) => this.createRow(t, e)), this.toggleContainer = this.el("div", "lt-more-toggle", this.tracks, {
208
+ this.showTable && (this.tableContainer.innerHTML = ""), this.axis.innerHTML = "", this.tracks.innerHTML = "", this.showLegend && (this.legendContainer.innerHTML = ""), this.showTable && this.renderTable(), this.renderAxis(), this.grid = this.el("div", "lt-grid-lines-container", this.tracks), this.indicators = this.el("div", "lt-indicators-container", this.tracks), this.renderGrid(), this.renderCurrentDateLine(), this.rows = this.data.map((t, s) => this.createRow(t, s)), this.toggleContainer = this.el("div", "lt-more-toggle", this.tracks, {
198
209
  paddingTop: "10px",
199
210
  display: "flex",
200
211
  justifyContent: "center",
@@ -213,8 +224,8 @@ class f {
213
224
  * @param e - The mouse event or position object.
214
225
  * @param content - The HTML content for the tooltip.
215
226
  */
216
- showTooltip(t, e) {
217
- this.tooltip.innerHTML = e, this.tooltip.style.display = "block", this.updateTooltipPos(t);
227
+ showTooltip(t, s) {
228
+ this.tooltip.innerHTML = s, this.tooltip.style.display = "block", this.updateTooltipPos(t);
218
229
  }
219
230
  /**
220
231
  * Updates tooltip position relative to mouse.
@@ -222,10 +233,10 @@ class f {
222
233
  */
223
234
  updateTooltipPos(t) {
224
235
  if (!this.root) return;
225
- const e = this.root.getBoundingClientRect(), i = 12, s = "clientX" in t ? t.clientX : t.pageX - window.scrollX, o = "clientY" in t ? t.clientY : t.pageY - window.scrollY;
226
- let n = (s || 0) - e.left + i, a = (o || 0) - e.top + i;
227
- const l = this.tooltip.offsetWidth, h = this.tooltip.offsetHeight;
228
- n + l > this.root.offsetWidth && (n = (s || 0) - e.left - l - i), a + h > this.root.offsetHeight && (a = (o || 0) - e.top - h - i), this.tooltip.style.left = `${n}px`, this.tooltip.style.top = `${a}px`;
236
+ const s = this.root.getBoundingClientRect(), e = 12, i = "clientX" in t ? t.clientX : t.pageX - window.scrollX, r = "clientY" in t ? t.clientY : t.pageY - window.scrollY;
237
+ let o = (i || 0) - s.left + e, a = (r || 0) - s.top + e;
238
+ const h = this.tooltip.offsetWidth, d = this.tooltip.offsetHeight;
239
+ o + h > this.root.offsetWidth && (o = (i || 0) - s.left - h - e), a + d > this.root.offsetHeight && (a = (r || 0) - s.top - d - e), this.tooltip.style.left = `${o}px`, this.tooltip.style.top = `${a}px`;
229
240
  }
230
241
  /**
231
242
  * Hides the tooltip.
@@ -241,8 +252,8 @@ class f {
241
252
  highlight(t) {
242
253
  if (!this.filterText) return t;
243
254
  try {
244
- const e = new RegExp(`(${this.filterText})`, "gi");
245
- return t.replace(e, '<mark class="lt-highlight-match">$1</mark>');
255
+ const s = new RegExp(`(${this.filterText})`, "gi");
256
+ return t.replace(s, '<mark class="lt-highlight-match">$1</mark>');
246
257
  } catch {
247
258
  return t;
248
259
  }
@@ -255,9 +266,9 @@ class f {
255
266
  * @param styles - Inline styles.
256
267
  * @returns The created element.
257
268
  */
258
- el(t, e, i, s = {}) {
259
- const o = document.createElement(t);
260
- return e && (o.className = e), Object.assign(o.style, s), i && i.appendChild(o), o;
269
+ el(t, s, e, i = {}) {
270
+ const r = document.createElement(t);
271
+ return s && (r.className = s), Object.assign(r.style, i), e && e.appendChild(r), r;
261
272
  }
262
273
  /**
263
274
  * Renders the toolbar with the filter input.
@@ -266,20 +277,20 @@ class f {
266
277
  if (!this.root) return;
267
278
  const t = this.el("div", "lt-toolbar", this.root);
268
279
  if (this.filterVersions) {
269
- const e = this.el("div", "lt-filter-container", t);
270
- e.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>';
271
- const i = this.el("input", "lt-filter-input", e);
272
- i.placeholder = this.t("filter"), i.value = this.filterText, i.setAttribute("aria-label", this.t("filter")), i.oninput = (s) => {
273
- this.filterText = s.target.value.toLowerCase().trim(), this.updateVisibility();
280
+ const s = this.el("div", "lt-filter-container", t);
281
+ s.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>';
282
+ const e = this.el("input", "lt-filter-input", s);
283
+ e.placeholder = this.t("filter"), e.value = this.filterText, e.setAttribute("aria-label", this.t("filter")), e.oninput = (i) => {
284
+ this.filterText = i.target.value.toLowerCase().trim(), this.updateVisibility();
274
285
  };
275
286
  }
276
287
  if (this.showMajorFilter) {
277
- const e = this.el("label", "lt-checkbox-label", t), i = this.el("input", "", e);
278
- i.type = "checkbox", i.checked = this.majorFilterEnabled, i.onchange = (o) => {
279
- this.majorFilterEnabled = o.target.checked, this.updateVisibility();
288
+ const s = this.el("label", "lt-checkbox-label", t), e = this.el("input", "", s);
289
+ e.type = "checkbox", e.checked = this.majorFilterEnabled, e.onchange = (r) => {
290
+ this.majorFilterEnabled = r.target.checked, this.updateVisibility();
280
291
  };
281
- const s = this.el("span", "", e);
282
- s.textContent = this.t("majorOnly");
292
+ const i = this.el("span", "", s);
293
+ i.textContent = this.t("majorOnly");
283
294
  }
284
295
  }
285
296
  /**
@@ -289,12 +300,12 @@ class f {
289
300
  if (!this.root) return;
290
301
  const t = this.el("button", "lt-theme-toggle-btn", this.root);
291
302
  t.title = this.t("dark"), t.setAttribute("aria-label", this.t("dark"));
292
- const e = {
303
+ const s = {
293
304
  moon: '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>',
294
305
  sun: '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>'
295
306
  };
296
- t.innerHTML = this.theme === "dark" ? e.sun : e.moon, t.onclick = () => {
297
- this.theme = this.theme === "light" ? "dark" : "light", this.root.setAttribute("data-theme", this.theme), t.innerHTML = this.theme === "dark" ? e.sun : e.moon, t.setAttribute("aria-pressed", (this.theme === "dark").toString());
307
+ t.innerHTML = this.theme === "dark" ? s.sun : s.moon, t.onclick = () => {
308
+ this.theme = this.theme === "light" ? "dark" : "light", this.root.setAttribute("data-theme", this.theme), t.innerHTML = this.theme === "dark" ? s.sun : s.moon, t.setAttribute("aria-pressed", (this.theme === "dark").toString());
298
309
  };
299
310
  }
300
311
  /**
@@ -303,7 +314,7 @@ class f {
303
314
  renderLegend() {
304
315
  this.legendContainer.innerHTML = "";
305
316
  const t = this.el("div", "lt-legend", this.legendContainer);
306
- t.setAttribute("role", "complementary"), t.setAttribute("aria-label", "Support Legend"), ["oss", "ent", "eol"].forEach((e) => {
317
+ t.setAttribute("role", "complementary"), t.setAttribute("aria-label", "Support Legend"), ["oss", "ent", "eol", "future", "fictive"].forEach((e) => {
307
318
  const i = this.el("div", `lt-legend-block ${e === "ent" ? "commercial" : e}`, t);
308
319
  i.classList.add("lt-legend-item-reactive"), this.activeHighlight === e && i.classList.add("lt-active-highlight"), i.innerHTML = `
309
320
  <div class="lt-legend-icon" aria-hidden="true"></div>
@@ -316,26 +327,26 @@ class f {
316
327
  * @param type - 'oss', 'ent', or 'eol'.
317
328
  */
318
329
  highlightSegment(t) {
319
- this.root && (this.activeHighlight = this.activeHighlight === t ? null : t, this.root.classList.remove("lt-highlight-oss", "lt-highlight-ent", "lt-highlight-eol"), this.activeHighlight && this.root.classList.add(`lt-highlight-${this.activeHighlight}`), this.renderLegend());
330
+ this.root && (this.activeHighlight = this.activeHighlight === t ? null : t, this.root.classList.remove("lt-highlight-oss", "lt-highlight-ent", "lt-highlight-eol", "lt-highlight-future", "lt-highlight-fictive"), this.activeHighlight && this.root.classList.add(`lt-highlight-${this.activeHighlight}`), this.renderLegend());
320
331
  }
321
332
  /**
322
333
  * Renders the year axis.
323
334
  */
324
335
  renderAxis() {
325
336
  this.el("div", "", this.axis, { width: "106px", flexShrink: "0" }).setAttribute("role", "presentation");
326
- for (let e = this.minYear; e <= this.maxYear; e++) {
327
- const i = this.el("div", "lt-year", this.axis);
328
- i.textContent = e.toString(), i.setAttribute("role", "columnheader");
337
+ for (let s = this.minYear; s <= this.maxYear; s++) {
338
+ const e = this.el("div", "lt-year", this.axis);
339
+ e.textContent = s.toString(), e.setAttribute("role", "columnheader");
329
340
  }
330
341
  }
331
342
  /**
332
343
  * Renders the vertical grid lines for years.
333
344
  */
334
345
  renderGrid() {
335
- const t = new Date(this.minYear, 0, 1).getTime(), e = new Date(this.maxYear, 11, 31).getTime() - t;
336
- for (let i = this.minYear; i <= this.maxYear; i++) {
337
- const s = this.el("div", "lt-year-grid-line", this.grid);
338
- s.style.left = `${(new Date(i, 0, 1).getTime() - t) / e * 100}%`, s.setAttribute("role", "presentation");
346
+ const t = new Date(this.minYear, 0, 1).getTime(), s = new Date(this.maxYear, 11, 31).getTime() - t;
347
+ for (let e = this.minYear; e <= this.maxYear; e++) {
348
+ const i = this.el("div", "lt-year-grid-line", this.grid);
349
+ i.style.left = `${(new Date(e, 0, 1).getTime() - t) / s * 100}%`, i.setAttribute("role", "presentation");
339
350
  }
340
351
  }
341
352
  /**
@@ -343,21 +354,22 @@ class f {
343
354
  * @param item - The version data item.
344
355
  * @returns Metadata about the created row.
345
356
  */
346
- createRow(t, e) {
347
- const i = this.el("div", "lt-row row-entrance", this.tracks);
348
- i.setAttribute("role", "row"), i.style.transitionDelay = `${e * 0.05}s`;
349
- const s = this.el("div", "lt-version-label", i);
350
- s.setAttribute("role", "rowheader");
351
- const o = Date.now(), n = new Date(t.ossStart).getTime(), a = new Date(t.ossEnd).getTime(), l = t.enterpriseEnd ? new Date(t.enterpriseEnd).getTime() : a, h = o < n ? "lt-status-future" : o >= n && o <= a ? "lt-status-oss" : o > a && o <= l ? "lt-status-ent" : o > l ? "lt-status-expired" : "";
352
- if (h && s.classList.add(h), t.isMajor && s.classList.add("lt-version-major"), t.releaseNotesUrl) {
353
- const u = this.el("a", "lt-version-link", s);
354
- u.href = t.releaseNotesUrl, u.target = "_blank", u.innerHTML = this.highlight(t.version), u.title = this.t("notes", { v: t.version }), u.setAttribute("aria-label", this.t("notes", { v: t.version }));
357
+ createRow(t, s) {
358
+ const e = this.el("div", "lt-row row-entrance", this.tracks);
359
+ e.setAttribute("role", "row"), e.style.transitionDelay = `${s * 0.05}s`;
360
+ const i = this.el("div", "lt-version-label", e);
361
+ i.setAttribute("role", "rowheader");
362
+ const r = Date.now(), o = t.ossStart ? new Date(t.ossStart).getTime() : 0, a = t.ossEnd ? new Date(t.ossEnd).getTime() : 0, h = t.enterpriseEnd ? new Date(t.enterpriseEnd).getTime() : a, n = t.isFictive || !t.ossStart || !t.ossEnd ? "lt-status-fictive" : t.isFuture ? "lt-status-is-future" : r < o ? "lt-status-future" : r >= o && r <= a ? "lt-status-oss" : r > a && r <= h ? "lt-status-ent" : r > h ? "lt-status-expired" : "";
363
+ if (n && i.classList.add(n), t.isMajor && i.classList.add("lt-version-major"), t.releaseNotesUrl) {
364
+ const g = this.el("a", "lt-version-link", i);
365
+ g.href = t.releaseNotesUrl, g.target = "_blank", g.innerHTML = this.highlight(t.version), g.title = this.t("notes", { v: t.version }), g.setAttribute("aria-label", this.t("notes", { v: t.version }));
355
366
  } else
356
- s.innerHTML = this.highlight(t.version), s.title = t.version;
357
- const r = this.el("div", "lt-track-container", i);
358
- r.setAttribute("role", "gridcell");
359
- const g = this.splitSupport ? t.ossEnd : t.ossStart, c = t.enterpriseEnd || t.ossEnd, d = new Date(this.maxYear, 11, 31).toISOString().split("T")[0];
360
- return r.appendChild(this.createBar(t, c, d, "lt-bar-eol", this.t("eol"))), r.appendChild(this.createBar(t, g, t.enterpriseEnd || t.ossEnd, "lt-bar-ent", this.t("ent"))), r.appendChild(this.createBar(t, t.ossStart, t.ossEnd, "lt-bar-oss", this.t("oss"))), { el: i, version: t.version.toLowerCase(), versionOriginal: t.version, isMajor: t.isMajor };
367
+ i.innerHTML = this.highlight(t.version), i.title = t.version;
368
+ const c = this.el("div", "lt-track-container", e);
369
+ if (c.setAttribute("role", "gridcell"), !t.ossStart || !t.ossEnd)
370
+ return { el: e, version: t.version.toLowerCase(), versionOriginal: t.version, isMajor: t.isMajor };
371
+ const l = this.splitSupport ? t.ossEnd : t.ossStart, b = t.enterpriseEnd || t.ossEnd, w = new Date(this.maxYear, 11, 31).toISOString().split("T")[0], v = this.createBar(t, b, w, "lt-bar-eol", this.t("eol")), f = this.createBar(t, l, t.enterpriseEnd || t.ossEnd, "lt-bar-ent", this.t("ent")), p = this.createBar(t, t.ossStart, t.ossEnd, "lt-bar-oss", this.t("oss"));
372
+ return t.isFictive ? (v.classList.add("lt-is-fictive-bar"), f.classList.add("lt-is-fictive-bar"), p.classList.add("lt-is-fictive-bar")) : t.isFuture && p.classList.add("lt-is-future-oss"), c.appendChild(v), c.appendChild(f), c.appendChild(p), { el: e, version: t.version.toLowerCase(), versionOriginal: t.version, isMajor: t.isMajor };
361
373
  }
362
374
  /**
363
375
  * Creates a colored bar segment for the timeline.
@@ -368,37 +380,37 @@ class f {
368
380
  * @param label - Support type label for tooltip.
369
381
  * @returns The created bar element.
370
382
  */
371
- createBar(t, e, i, s, o) {
372
- const n = new Date(e).getTime(), a = new Date(i).getTime(), l = new Date(this.minYear, 0, 1).getTime(), h = new Date(this.maxYear, 11, 31).getTime() - l, r = this.el("div", `lt-bar-segment ${s}`), g = s === "lt-bar-oss" ? "lt-segment-oss" : s === "lt-bar-ent" ? "lt-segment-ent" : "lt-segment-eol";
373
- r.classList.add(g), r.style.left = `${(n - l) / h * 100}%`, r.style.width = `${(a - n) / h * 100}%`, r.setAttribute("role", "img"), r.setAttribute("aria-label", `${o}: ${t.version} (${e} to ${i})`), r.tabIndex = 0;
374
- const c = `
375
- <div class="lt-tooltip-header">${o} - ${t.version}</div>
376
- <div class="lt-tooltip-date"><strong>Du:</strong> ${e}</div>
377
- <div class="lt-tooltip-date"><strong>Au:</strong> ${i}</div>
383
+ createBar(t, s, e, i, r) {
384
+ const o = new Date(s).getTime(), a = new Date(e).getTime(), h = new Date(this.minYear, 0, 1).getTime(), d = new Date(this.maxYear, 11, 31).getTime() - h, n = this.el("div", `lt-bar-segment ${i}`), c = i === "lt-bar-oss" ? "lt-segment-oss" : i === "lt-bar-ent" ? "lt-segment-ent" : "lt-segment-eol";
385
+ n.classList.add(c), n.style.left = `${(o - h) / d * 100}%`, n.style.width = `${(a - o) / d * 100}%`, n.setAttribute("role", "img"), n.setAttribute("aria-label", `${r}: ${t.version} (${s} to ${e})`), n.tabIndex = 0;
386
+ const u = `
387
+ <div class="lt-tooltip-header">${r} - ${t.version}</div>
388
+ <div class="lt-tooltip-date"><strong>Du:</strong> ${s}</div>
389
+ <div class="lt-tooltip-date"><strong>Au:</strong> ${e}</div>
378
390
  `;
379
- return r.onmouseenter = (d) => this.showTooltip(d, c), r.onmousemove = (d) => this.updateTooltipPos(d), r.onmouseleave = () => this.hideTooltip(), r.onfocus = () => {
380
- const d = r.getBoundingClientRect();
381
- this.showTooltip({ pageX: d.left + window.scrollX, pageY: d.top + window.scrollY - 40 }, c);
382
- }, r.onblur = () => this.hideTooltip(), r;
391
+ return n.onmouseenter = (l) => this.showTooltip(l, u), n.onmousemove = (l) => this.updateTooltipPos(l), n.onmouseleave = () => this.hideTooltip(), n.onfocus = () => {
392
+ const l = n.getBoundingClientRect();
393
+ this.showTooltip({ pageX: l.left + window.scrollX, pageY: l.top + window.scrollY - 40 }, u);
394
+ }, n.onblur = () => this.hideTooltip(), n;
383
395
  }
384
396
  /**
385
397
  * Updates visibility of rows based on filtering and expansion state.
386
398
  */
387
399
  updateVisibility() {
388
- const t = this.rows.filter((s) => {
389
- const o = s.version.includes(this.filterText), n = this.majorFilterEnabled ? s.isMajor : !0;
390
- return o && n;
400
+ const t = this.rows.filter((i) => {
401
+ const r = i.version.includes(this.filterText), o = this.majorFilterEnabled ? i.isMajor : !0;
402
+ return r && o;
391
403
  });
392
- this.rows.forEach((s) => {
393
- const o = s.el.querySelector(".lt-version-label"), n = o.querySelector(".lt-version-link");
394
- n ? n.innerHTML = this.highlight(s.versionOriginal || s.version) : o.innerHTML = this.highlight(s.versionOriginal || s.version), s.el.classList.remove("lt-row-visible"), s.el.classList.add("lt-row-hidden");
404
+ this.rows.forEach((i) => {
405
+ const r = i.el.querySelector(".lt-version-label"), o = r.querySelector(".lt-version-link");
406
+ o ? o.innerHTML = this.highlight(i.versionOriginal || i.version) : r.innerHTML = this.highlight(i.versionOriginal || i.version), i.el.classList.remove("lt-row-visible"), i.el.classList.add("lt-row-hidden");
395
407
  });
396
- const e = this.filterText === "" && t.length > this.visibleCount;
397
- if ((e && !this.isExpanded ? t.slice(0, this.visibleCount) : t).forEach((s) => {
398
- s.el.classList.remove("lt-row-hidden"), s.el.classList.add("lt-row-visible");
399
- }), this.showTable && this.updateTableVisibility(), this.toggleContainer.innerHTML = "", e) {
400
- const s = this.el("button", "lt-toggle-btn", this.toggleContainer), o = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="${this.isExpanded ? "18 15 12 9 6 15" : "6 9 12 15 18 9"}"></polyline></svg>`;
401
- s.innerHTML = this.isExpanded ? `${this.t("less")} ${o}` : `${this.t("more", { n: t.length - this.visibleCount })} ${o}`, s.setAttribute("aria-expanded", this.isExpanded.toString()), s.onclick = () => {
408
+ const s = this.filterText === "" && t.length > this.visibleCount;
409
+ if ((s && !this.isExpanded ? t.slice(0, this.visibleCount) : t).forEach((i) => {
410
+ i.el.classList.remove("lt-row-hidden"), i.el.classList.add("lt-row-visible");
411
+ }), this.showTable && this.updateTableVisibility(), this.toggleContainer.innerHTML = "", s) {
412
+ const i = this.el("button", "lt-toggle-btn", this.toggleContainer), r = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="${this.isExpanded ? "18 15 12 9 6 15" : "6 9 12 15 18 9"}"></polyline></svg>`;
413
+ i.innerHTML = this.isExpanded ? `${this.t("less")} ${r}` : `${this.t("more", { n: t.length - this.visibleCount })} ${r}`, i.setAttribute("aria-expanded", this.isExpanded.toString()), i.onclick = () => {
402
414
  this.isExpanded = !this.isExpanded, this.updateVisibility();
403
415
  };
404
416
  }
@@ -407,14 +419,14 @@ class f {
407
419
  * Renders the vertical line indicating current date.
408
420
  */
409
421
  renderCurrentDateLine() {
410
- const t = new Date(this.minYear, 0, 1).getTime(), e = new Date(this.maxYear, 11, 31).getTime() - t, i = Date.now() - t;
411
- if (i < 0 || i > e) return;
412
- const s = (/* @__PURE__ */ new Date()).toISOString().split("T")[0], o = this.el("div", "lt-current-date-indicator", this.indicators);
413
- o.style.left = `${i / e * 100}%`, o.setAttribute("role", "separator"), o.setAttribute("aria-label", this.t("today", { date: s }));
414
- const n = this.el("div", "lt-current-date-badge", o);
415
- n.textContent = s, n.setAttribute("aria-hidden", "true");
422
+ const t = new Date(this.minYear, 0, 1).getTime(), s = new Date(this.maxYear, 11, 31).getTime() - t, e = Date.now() - t;
423
+ if (e < 0 || e > s) return;
424
+ const i = (/* @__PURE__ */ new Date()).toISOString().split("T")[0], r = this.el("div", "lt-current-date-indicator", this.indicators);
425
+ r.style.left = `${e / s * 100}%`, r.setAttribute("role", "separator"), r.setAttribute("aria-label", this.t("today", { date: i }));
426
+ const o = this.el("div", "lt-current-date-badge", r);
427
+ o.textContent = i, o.setAttribute("aria-hidden", "true");
416
428
  }
417
429
  }
418
430
  export {
419
- f as default
431
+ E as default
420
432
  };
@@ -1,8 +1,8 @@
1
- (function(u,p){typeof exports=="object"&&typeof module<"u"?module.exports=p():typeof define=="function"&&define.amd?define(p):(u=typeof globalThis<"u"?globalThis:u||self,u.Timeline=p())})(this,(function(){"use strict";const u={en:{filter:"Filter versions...",oss:"OSS Support",ent:"Enterprise Support",eol:"Out of Support",less:"Show Less",more:"Show {n} more versions",notes:"View Release Notes for {v}",dark:"Toggle Dark Mode",ossDesc:"Free security updates and bugfixes.",entDesc:"Expert support during OSS plus extended support after EOL.",eolDesc:"End of life. No further updates are provided.",today:"Today's date: {date}",branch:"Branch",initial:"Initial Release",ossEnd:"End OSS",entEnd:"End Enterprise *",majorOnly:"Major versions only"},fr:{filter:"Filtrer les versions...",oss:"Support OSS",ent:"Support Entreprise",eol:"Fin de support",less:"Voir moins",more:"Voir {n} versions supplémentaires",notes:"Voir les notes de version pour {v}",dark:"Changer le mode sombre",ossDesc:"Mises à jour de sécurité et corrections de bugs gratuites.",entDesc:"Support pendant la période OSS plus support étendu après.",eolDesc:"Version en fin de vie. Plus de mises à jour.",today:"Date du jour : {date}",branch:"Version",initial:"Sortie initiale",ossEnd:"Fin OSS",entEnd:"Fin Entreprise *",majorOnly:"Versions majeures uniquement"}};class p{root;options;visibleCount;showTable;showThemeToggle;showLegend;filterVersions;splitSupport;compactMode;showMajorFilter;isExpanded;theme;filterText;majorFilterEnabled;activeHighlight;translations;locale;data=[];minYear=0;maxYear=0;currentDate=new Date;tableContainer;wrapper;axis;tracks;legendContainer;tableBody;tableRows=[];tableToggleContainer;grid;indicators;rows=[];toggleContainer;tooltip;constructor(t,e,i={}){if(this.root=document.getElementById(t),!this.root){this.options=i,this.visibleCount=3,this.showTable=!0,this.showThemeToggle=!0,this.showLegend=!0,this.filterVersions=!0,this.splitSupport=!1,this.compactMode=!1,this.showMajorFilter=!1,this.isExpanded=!1,this.theme="light",this.filterText="",this.majorFilterEnabled=!1,this.activeHighlight=null,this.translations={},this.locale="en";return}this.options=i,this.visibleCount=i.visibleCount||3,this.showTable=i.showTable!==!1,this.showThemeToggle=i.showThemeToggle!==!1,this.showLegend=i.showLegend!==!1,this.filterVersions=i.filterVersions!==!1,this.splitSupport=i.splitSupport===!0,this.compactMode=i.compactMode===!0,this.showMajorFilter=i.showMajorFilter===!0,this.isExpanded=!1,this.theme="light",this.filterText="",this.majorFilterEnabled=i.majorFilterDefault===!0,this.activeHighlight=null,this.root.classList.add("lt-root"),this.root.classList.toggle("lt-mode-split",this.splitSupport),this.root.classList.toggle("lt-mode-overlay",!this.splitSupport),this.root.classList.toggle("lt-mode-compact",this.compactMode),this.root.setAttribute("data-theme",this.theme),this.translations={...u,...i.i18n||{}},this.locale=i.locale||this.detectLanguage(),this.setupBaseLayout(),this.updateData(e)}detectLanguage(){const t=(navigator.language||"en").split("-")[0];return this.translations[t]?t:"en"}t(t,e={}){let i=(this.translations[this.locale]||this.translations.en)[t]||t;return Object.keys(e).forEach(s=>i=i.replace(`{${s}}`,e[s])),i}setupBaseLayout(){this.root&&(this.root.innerHTML="",this.root.setAttribute("role","application"),this.root.setAttribute("aria-label","Product Lifecycle Timeline"),this.renderToolbar(),this.showThemeToggle&&this.renderThemeToggle(),this.showTable&&(this.tableContainer=this.el("div","lt-table-container",this.root)),this.wrapper=this.el("div","lt-wrapper",this.root),this.wrapper.setAttribute("role","grid"),this.wrapper.setAttribute("aria-readonly","true"),this.axis=this.el("div","lt-axis",this.wrapper),this.axis.setAttribute("role","row"),this.tracks=this.el("div","lt-tracks",this.wrapper),this.showLegend&&(this.legendContainer=this.el("div","lt-legend-container",this.wrapper)))}updateData(t){this.data=this.validateData(t||[]),this.calculateTimeRange(),this.render()}validateData(t){return t.filter((e,i)=>{const n=["version","ossStart","ossEnd"].filter(l=>!e[l]);if(n.length>0)return console.warn(`[Timeline] Missing fields for item at index ${i}: ${n.join(", ")}`),!1;const a=["ossStart","ossEnd","enterpriseEnd"].filter(l=>e[l]).filter(l=>isNaN(new Date(e[l]).getTime()));return a.length>0?(console.warn(`[Timeline] Invalid date format for item "${e.version}": ${a.join(", ")}`),!1):!0})}calculateTimeRange(){if(this.currentDate=new Date,!this.data.length){this.minYear=this.currentDate.getFullYear()-1,this.maxYear=this.currentDate.getFullYear()+3;return}const t=this.data.flatMap(e=>[new Date(e.ossStart).getTime(),new Date(e.enterpriseEnd||e.ossEnd).getTime()]);this.minYear=new Date(Math.min(...t)).getFullYear(),this.maxYear=new Date(Math.max(...t)).getFullYear()}renderTable(){const t=this.el("table","lt-table",this.tableContainer);t.setAttribute("aria-label","Project support");const e=this.el("thead","",t),i=this.el("tr","",e);[this.t("branch"),this.t("initial"),this.t("ossEnd"),this.t("entEnd")].forEach(s=>{this.el("th","",i).textContent=s}),this.tableBody=this.el("tbody","",t),this.tableRows=this.data.map(s=>this.createTableRow(s)),this.tableToggleContainer=this.el("div","lt-table-toggle",this.tableContainer),this.updateTableVisibility()}createTableRow(t){const e=this.el("tr","",this.tableBody),i=Date.now(),s=new Date(t.ossStart).getTime(),n=new Date(t.ossEnd).getTime(),o=t.enterpriseEnd?new Date(t.enterpriseEnd).getTime():n,a=i>=s&&i<=n?"lt-status-oss":i>n&&i<=o?"lt-status-ent":i>o?"lt-status-expired":"",l=this.el("td","",e);let h=`<span class="lt-table-badge ${a}">${t.version}</span>`;t.releaseNotesUrl?l.innerHTML=`<a href="${t.releaseNotesUrl}" target="_blank" class="lt-table-version-link">${h}</a>`:l.innerHTML=h;const r=this.el("td","",e);r.textContent=t.ossStart,i>s&&(r.className="lt-past-date");const g=this.el("td","",e);g.textContent=t.ossEnd,i>n&&(g.className="lt-past-date");const c=this.el("td","",e);return c.textContent=t.enterpriseEnd||t.ossEnd,i>o&&(c.className="lt-past-date"),{el:e,version:t.version.toLowerCase(),versionOriginal:t.version}}updateTableVisibility(){const t=this.tableRows.filter(s=>s.version.includes(this.filterText));this.tableRows.forEach(s=>{const n=s.el.querySelector(".lt-table-badge");n&&(n.innerHTML=this.highlight(s.versionOriginal||s.version)),s.el.classList.remove("lt-row-visible"),s.el.classList.add("lt-row-hidden")});const e=this.filterText===""&&t.length>this.visibleCount;if((e&&!this.isExpanded?t.slice(0,this.visibleCount):t).forEach(s=>{s.el.classList.remove("lt-row-hidden"),s.el.classList.add("lt-row-visible")}),this.tableToggleContainer.innerHTML="",e){const s=this.el("button","lt-toggle-btn lt-table-toggle",this.tableToggleContainer),n=`<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="${this.isExpanded?"18 15 12 9 6 15":"6 9 12 15 18 9"}"></polyline></svg>`;s.innerHTML=this.isExpanded?`${this.t("less")} ${n}`:`${this.t("more",{n:t.length-this.visibleCount})} ${n}`,s.onclick=()=>{this.isExpanded=!this.isExpanded,this.updateVisibility()}}}render(){this.showTable&&(this.tableContainer.innerHTML=""),this.axis.innerHTML="",this.tracks.innerHTML="",this.showLegend&&(this.legendContainer.innerHTML=""),this.showTable&&this.renderTable(),this.renderAxis(),this.grid=this.el("div","lt-grid-lines-container",this.tracks),this.indicators=this.el("div","lt-indicators-container",this.tracks),this.renderGrid(),this.renderCurrentDateLine(),this.rows=this.data.map((t,e)=>this.createRow(t,e)),this.toggleContainer=this.el("div","lt-more-toggle",this.tracks,{paddingTop:"10px",display:"flex",justifyContent:"center",position:"relative",zIndex:"10"}),this.updateVisibility(),this.showLegend&&this.renderLegend(),this.setupTooltip()}setupTooltip(){this.tooltip&&this.tooltip.remove(),this.tooltip=this.el("div","lt-tooltip",this.root),this.tooltip.style.display="none",this.tooltip.setAttribute("role","tooltip")}showTooltip(t,e){this.tooltip.innerHTML=e,this.tooltip.style.display="block",this.updateTooltipPos(t)}updateTooltipPos(t){if(!this.root)return;const e=this.root.getBoundingClientRect(),i=12,s="clientX"in t?t.clientX:t.pageX-window.scrollX,n="clientY"in t?t.clientY:t.pageY-window.scrollY;let o=(s||0)-e.left+i,a=(n||0)-e.top+i;const l=this.tooltip.offsetWidth,h=this.tooltip.offsetHeight;o+l>this.root.offsetWidth&&(o=(s||0)-e.left-l-i),a+h>this.root.offsetHeight&&(a=(n||0)-e.top-h-i),this.tooltip.style.left=`${o}px`,this.tooltip.style.top=`${a}px`}hideTooltip(){this.tooltip&&(this.tooltip.style.display="none")}highlight(t){if(!this.filterText)return t;try{const e=new RegExp(`(${this.filterText})`,"gi");return t.replace(e,'<mark class="lt-highlight-match">$1</mark>')}catch{return t}}el(t,e,i,s={}){const n=document.createElement(t);return e&&(n.className=e),Object.assign(n.style,s),i&&i.appendChild(n),n}renderToolbar(){if(!this.root)return;const t=this.el("div","lt-toolbar",this.root);if(this.filterVersions){const e=this.el("div","lt-filter-container",t);e.innerHTML='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>';const i=this.el("input","lt-filter-input",e);i.placeholder=this.t("filter"),i.value=this.filterText,i.setAttribute("aria-label",this.t("filter")),i.oninput=s=>{this.filterText=s.target.value.toLowerCase().trim(),this.updateVisibility()}}if(this.showMajorFilter){const e=this.el("label","lt-checkbox-label",t),i=this.el("input","",e);i.type="checkbox",i.checked=this.majorFilterEnabled,i.onchange=n=>{this.majorFilterEnabled=n.target.checked,this.updateVisibility()};const s=this.el("span","",e);s.textContent=this.t("majorOnly")}}renderThemeToggle(){if(!this.root)return;const t=this.el("button","lt-theme-toggle-btn",this.root);t.title=this.t("dark"),t.setAttribute("aria-label",this.t("dark"));const e={moon:'<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>',sun:'<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>'};t.innerHTML=this.theme==="dark"?e.sun:e.moon,t.onclick=()=>{this.theme=this.theme==="light"?"dark":"light",this.root.setAttribute("data-theme",this.theme),t.innerHTML=this.theme==="dark"?e.sun:e.moon,t.setAttribute("aria-pressed",(this.theme==="dark").toString())}}renderLegend(){this.legendContainer.innerHTML="";const t=this.el("div","lt-legend",this.legendContainer);t.setAttribute("role","complementary"),t.setAttribute("aria-label","Support Legend"),["oss","ent","eol"].forEach(e=>{const i=this.el("div",`lt-legend-block ${e==="ent"?"commercial":e}`,t);i.classList.add("lt-legend-item-reactive"),this.activeHighlight===e&&i.classList.add("lt-active-highlight"),i.innerHTML=`
1
+ (function(g,p){typeof exports=="object"&&typeof module<"u"?module.exports=p():typeof define=="function"&&define.amd?define(p):(g=typeof globalThis<"u"?globalThis:g||self,g.Timeline=p())})(this,(function(){"use strict";const g={en:{filter:"Filter versions...",oss:"OSS Support",ent:"Enterprise Support",eol:"Out of Support",less:"Show Less",more:"Show {n} more versions",notes:"View Release Notes for {v}",dark:"Toggle Dark Mode",ossDesc:"Free security updates and bugfixes.",entDesc:"Expert support during OSS plus extended support after EOL.",eolDesc:"End of life. No further updates are provided.",today:"Today's date: {date}",branch:"Branch",initial:"Initial Release",ossEnd:"End OSS",entEnd:"End Enterprise *",majorOnly:"Major versions only",future:"Future Version",futureDesc:"Planned version not yet released.",fictive:"Fictive Version",fictiveDesc:"Disabled or representative version."},fr:{filter:"Filtrer les versions...",oss:"Support OSS",ent:"Support Entreprise",eol:"Fin de support",less:"Voir moins",more:"Voir {n} versions supplémentaires",notes:"Voir les notes de version pour {v}",dark:"Changer le mode sombre",ossDesc:"Mises à jour de sécurité et corrections de bugs gratuites.",entDesc:"Support pendant la période OSS plus support étendu après.",eolDesc:"Version en fin de vie. Plus de mises à jour.",today:"Date du jour : {date}",branch:"Version",initial:"Sortie initiale",ossEnd:"Fin OSS",entEnd:"Fin Entreprise *",majorOnly:"Versions majeures uniquement",future:"Version future",futureDesc:"Version prévue non encore sortie.",fictive:"Version fictive",fictiveDesc:"Version désactivée ou indicative."}};class p{root;options;visibleCount;showTable;showThemeToggle;showLegend;filterVersions;splitSupport;compactMode;showMajorFilter;isExpanded;theme;filterText;majorFilterEnabled;activeHighlight;translations;locale;data=[];minYear=0;maxYear=0;currentDate=new Date;tableContainer;wrapper;axis;tracks;legendContainer;tableBody;tableRows=[];tableToggleContainer;grid;indicators;rows=[];toggleContainer;tooltip;constructor(t,s,e={}){if(this.root=document.getElementById(t),!this.root){this.options=e,this.visibleCount=3,this.showTable=!0,this.showThemeToggle=!0,this.showLegend=!0,this.filterVersions=!0,this.splitSupport=!1,this.compactMode=!1,this.showMajorFilter=!1,this.isExpanded=!1,this.theme="light",this.filterText="",this.majorFilterEnabled=!1,this.activeHighlight=null,this.translations={},this.locale="en";return}this.options=e,this.visibleCount=e.visibleCount||3,this.showTable=e.showTable!==!1,this.showThemeToggle=e.showThemeToggle!==!1,this.showLegend=e.showLegend!==!1,this.filterVersions=e.filterVersions!==!1,this.splitSupport=e.splitSupport===!0,this.compactMode=e.compactMode===!0,this.showMajorFilter=e.showMajorFilter===!0,this.isExpanded=!1,this.theme="light",this.filterText="",this.majorFilterEnabled=e.majorFilterDefault===!0,this.activeHighlight=null,this.root.classList.add("lt-root"),this.root.classList.toggle("lt-mode-split",this.splitSupport),this.root.classList.toggle("lt-mode-overlay",!this.splitSupport),this.root.classList.toggle("lt-mode-compact",this.compactMode),this.root.setAttribute("data-theme",this.theme),this.translations={...g},e.i18n&&Object.keys(e.i18n).forEach(i=>{this.translations[i]={...this.translations[i]||this.translations.en||{},...e.i18n[i]||{}}}),this.locale=e.locale||this.detectLanguage(),this.setupBaseLayout(),this.updateData(s)}detectLanguage(){const t=(navigator.language||"en").split("-")[0];return this.translations[t]?t:"en"}t(t,s={}){let e=(this.translations[this.locale]||this.translations.en)[t]||t;return Object.keys(s).forEach(i=>e=e.replace(`{${i}}`,s[i])),e}setupBaseLayout(){this.root&&(this.root.innerHTML="",this.root.setAttribute("role","application"),this.root.setAttribute("aria-label","Product Lifecycle Timeline"),this.renderToolbar(),this.showThemeToggle&&this.renderThemeToggle(),this.showTable&&(this.tableContainer=this.el("div","lt-table-container",this.root)),this.wrapper=this.el("div","lt-wrapper",this.root),this.wrapper.setAttribute("role","grid"),this.wrapper.setAttribute("aria-readonly","true"),this.axis=this.el("div","lt-axis",this.wrapper),this.axis.setAttribute("role","row"),this.tracks=this.el("div","lt-tracks",this.wrapper),this.showLegend&&(this.legendContainer=this.el("div","lt-legend-container",this.wrapper)))}updateData(t){this.data=this.validateData(t||[]),this.calculateTimeRange(),this.render()}validateData(t){return t.filter(s=>{if(!s.ossStart||!s.ossEnd)return s.isFictive=!0,!0;const i=["ossStart","ossEnd","enterpriseEnd"].filter(r=>s[r]).filter(r=>isNaN(new Date(s[r]).getTime()));return i.length>0?(console.warn(`[Timeline] Invalid date format for item "${s.version}": ${i.join(", ")}`),!1):!0})}calculateTimeRange(){if(this.currentDate=new Date,!this.data.length){this.minYear=this.currentDate.getFullYear()-1,this.maxYear=this.currentDate.getFullYear()+3;return}const t=this.data.filter(s=>s.ossStart&&s.ossEnd).flatMap(s=>[new Date(s.ossStart).getTime(),new Date(s.enterpriseEnd||s.ossEnd).getTime()]);if(t.length===0){this.minYear=this.currentDate.getFullYear()-1,this.maxYear=this.currentDate.getFullYear()+3;return}this.minYear=new Date(Math.min(...t)).getFullYear(),this.maxYear=new Date(Math.max(...t)).getFullYear()}renderTable(){const t=this.el("table","lt-table",this.tableContainer);t.setAttribute("aria-label","Project support");const s=this.el("thead","",t),e=this.el("tr","",s);[this.t("branch"),this.t("initial"),this.t("ossEnd"),this.t("entEnd")].forEach(i=>{this.el("th","",e).textContent=i}),this.tableBody=this.el("tbody","",t),this.tableRows=this.data.map(i=>this.createTableRow(i)),this.tableToggleContainer=this.el("div","lt-table-toggle",this.tableContainer),this.updateTableVisibility()}createTableRow(t){const s=this.el("tr","",this.tableBody),e=Date.now(),i=t.ossStart?new Date(t.ossStart).getTime():0,r=t.ossEnd?new Date(t.ossEnd).getTime():0,n=t.enterpriseEnd?new Date(t.enterpriseEnd).getTime():r,h=t.isFictive||!t.ossStart||!t.ossEnd?"lt-status-fictive":t.isFuture?"lt-status-is-future":e>=i&&e<=r?"lt-status-oss":e>r&&e<=n?"lt-status-ent":e>n?"lt-status-expired":"",d=this.el("td","",s);let o=`<span class="lt-table-badge ${h}">${t.version}</span>`;t.releaseNotesUrl?d.innerHTML=`<a href="${t.releaseNotesUrl}" target="_blank" class="lt-table-version-link">${o}</a>`:d.innerHTML=o;const c=this.el("td","",s);c.textContent=t.ossStart||"-",t.ossStart&&e>i&&(c.className="lt-past-date");const u=this.el("td","",s);u.textContent=t.ossEnd||"-",t.ossEnd&&e>r&&(u.className="lt-past-date");const l=this.el("td","",s);return l.textContent=t.enterpriseEnd||t.ossEnd||"-",(t.enterpriseEnd||t.ossEnd)&&e>n&&(l.className="lt-past-date"),{el:s,version:t.version.toLowerCase(),versionOriginal:t.version}}updateTableVisibility(){const t=this.tableRows.filter(i=>i.version.includes(this.filterText));this.tableRows.forEach(i=>{const r=i.el.querySelector(".lt-table-badge");r&&(r.innerHTML=this.highlight(i.versionOriginal||i.version)),i.el.classList.remove("lt-row-visible"),i.el.classList.add("lt-row-hidden")});const s=this.filterText===""&&t.length>this.visibleCount;if((s&&!this.isExpanded?t.slice(0,this.visibleCount):t).forEach(i=>{i.el.classList.remove("lt-row-hidden"),i.el.classList.add("lt-row-visible")}),this.tableToggleContainer.innerHTML="",s){const i=this.el("button","lt-toggle-btn lt-table-toggle",this.tableToggleContainer),r=`<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="${this.isExpanded?"18 15 12 9 6 15":"6 9 12 15 18 9"}"></polyline></svg>`;i.innerHTML=this.isExpanded?`${this.t("less")} ${r}`:`${this.t("more",{n:t.length-this.visibleCount})} ${r}`,i.onclick=()=>{this.isExpanded=!this.isExpanded,this.updateVisibility()}}}render(){this.showTable&&(this.tableContainer.innerHTML=""),this.axis.innerHTML="",this.tracks.innerHTML="",this.showLegend&&(this.legendContainer.innerHTML=""),this.showTable&&this.renderTable(),this.renderAxis(),this.grid=this.el("div","lt-grid-lines-container",this.tracks),this.indicators=this.el("div","lt-indicators-container",this.tracks),this.renderGrid(),this.renderCurrentDateLine(),this.rows=this.data.map((t,s)=>this.createRow(t,s)),this.toggleContainer=this.el("div","lt-more-toggle",this.tracks,{paddingTop:"10px",display:"flex",justifyContent:"center",position:"relative",zIndex:"10"}),this.updateVisibility(),this.showLegend&&this.renderLegend(),this.setupTooltip()}setupTooltip(){this.tooltip&&this.tooltip.remove(),this.tooltip=this.el("div","lt-tooltip",this.root),this.tooltip.style.display="none",this.tooltip.setAttribute("role","tooltip")}showTooltip(t,s){this.tooltip.innerHTML=s,this.tooltip.style.display="block",this.updateTooltipPos(t)}updateTooltipPos(t){if(!this.root)return;const s=this.root.getBoundingClientRect(),e=12,i="clientX"in t?t.clientX:t.pageX-window.scrollX,r="clientY"in t?t.clientY:t.pageY-window.scrollY;let n=(i||0)-s.left+e,a=(r||0)-s.top+e;const h=this.tooltip.offsetWidth,d=this.tooltip.offsetHeight;n+h>this.root.offsetWidth&&(n=(i||0)-s.left-h-e),a+d>this.root.offsetHeight&&(a=(r||0)-s.top-d-e),this.tooltip.style.left=`${n}px`,this.tooltip.style.top=`${a}px`}hideTooltip(){this.tooltip&&(this.tooltip.style.display="none")}highlight(t){if(!this.filterText)return t;try{const s=new RegExp(`(${this.filterText})`,"gi");return t.replace(s,'<mark class="lt-highlight-match">$1</mark>')}catch{return t}}el(t,s,e,i={}){const r=document.createElement(t);return s&&(r.className=s),Object.assign(r.style,i),e&&e.appendChild(r),r}renderToolbar(){if(!this.root)return;const t=this.el("div","lt-toolbar",this.root);if(this.filterVersions){const s=this.el("div","lt-filter-container",t);s.innerHTML='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>';const e=this.el("input","lt-filter-input",s);e.placeholder=this.t("filter"),e.value=this.filterText,e.setAttribute("aria-label",this.t("filter")),e.oninput=i=>{this.filterText=i.target.value.toLowerCase().trim(),this.updateVisibility()}}if(this.showMajorFilter){const s=this.el("label","lt-checkbox-label",t),e=this.el("input","",s);e.type="checkbox",e.checked=this.majorFilterEnabled,e.onchange=r=>{this.majorFilterEnabled=r.target.checked,this.updateVisibility()};const i=this.el("span","",s);i.textContent=this.t("majorOnly")}}renderThemeToggle(){if(!this.root)return;const t=this.el("button","lt-theme-toggle-btn",this.root);t.title=this.t("dark"),t.setAttribute("aria-label",this.t("dark"));const s={moon:'<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>',sun:'<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>'};t.innerHTML=this.theme==="dark"?s.sun:s.moon,t.onclick=()=>{this.theme=this.theme==="light"?"dark":"light",this.root.setAttribute("data-theme",this.theme),t.innerHTML=this.theme==="dark"?s.sun:s.moon,t.setAttribute("aria-pressed",(this.theme==="dark").toString())}}renderLegend(){this.legendContainer.innerHTML="";const t=this.el("div","lt-legend",this.legendContainer);t.setAttribute("role","complementary"),t.setAttribute("aria-label","Support Legend"),["oss","ent","eol","future","fictive"].forEach(e=>{const i=this.el("div",`lt-legend-block ${e==="ent"?"commercial":e}`,t);i.classList.add("lt-legend-item-reactive"),this.activeHighlight===e&&i.classList.add("lt-active-highlight"),i.innerHTML=`
2
2
  <div class="lt-legend-icon" aria-hidden="true"></div>
3
3
  <div><h3>${this.t(e)}</h3><p>${this.t(e+"Desc")}</p></div>
4
- `,i.onclick=()=>this.highlightSegment(e)})}highlightSegment(t){this.root&&(this.activeHighlight=this.activeHighlight===t?null:t,this.root.classList.remove("lt-highlight-oss","lt-highlight-ent","lt-highlight-eol"),this.activeHighlight&&this.root.classList.add(`lt-highlight-${this.activeHighlight}`),this.renderLegend())}renderAxis(){this.el("div","",this.axis,{width:"106px",flexShrink:"0"}).setAttribute("role","presentation");for(let e=this.minYear;e<=this.maxYear;e++){const i=this.el("div","lt-year",this.axis);i.textContent=e.toString(),i.setAttribute("role","columnheader")}}renderGrid(){const t=new Date(this.minYear,0,1).getTime(),e=new Date(this.maxYear,11,31).getTime()-t;for(let i=this.minYear;i<=this.maxYear;i++){const s=this.el("div","lt-year-grid-line",this.grid);s.style.left=`${(new Date(i,0,1).getTime()-t)/e*100}%`,s.setAttribute("role","presentation")}}createRow(t,e){const i=this.el("div","lt-row row-entrance",this.tracks);i.setAttribute("role","row"),i.style.transitionDelay=`${e*.05}s`;const s=this.el("div","lt-version-label",i);s.setAttribute("role","rowheader");const n=Date.now(),o=new Date(t.ossStart).getTime(),a=new Date(t.ossEnd).getTime(),l=t.enterpriseEnd?new Date(t.enterpriseEnd).getTime():a,h=n<o?"lt-status-future":n>=o&&n<=a?"lt-status-oss":n>a&&n<=l?"lt-status-ent":n>l?"lt-status-expired":"";if(h&&s.classList.add(h),t.isMajor&&s.classList.add("lt-version-major"),t.releaseNotesUrl){const b=this.el("a","lt-version-link",s);b.href=t.releaseNotesUrl,b.target="_blank",b.innerHTML=this.highlight(t.version),b.title=this.t("notes",{v:t.version}),b.setAttribute("aria-label",this.t("notes",{v:t.version}))}else s.innerHTML=this.highlight(t.version),s.title=t.version;const r=this.el("div","lt-track-container",i);r.setAttribute("role","gridcell");const g=this.splitSupport?t.ossEnd:t.ossStart,c=t.enterpriseEnd||t.ossEnd,d=new Date(this.maxYear,11,31).toISOString().split("T")[0];return r.appendChild(this.createBar(t,c,d,"lt-bar-eol",this.t("eol"))),r.appendChild(this.createBar(t,g,t.enterpriseEnd||t.ossEnd,"lt-bar-ent",this.t("ent"))),r.appendChild(this.createBar(t,t.ossStart,t.ossEnd,"lt-bar-oss",this.t("oss"))),{el:i,version:t.version.toLowerCase(),versionOriginal:t.version,isMajor:t.isMajor}}createBar(t,e,i,s,n){const o=new Date(e).getTime(),a=new Date(i).getTime(),l=new Date(this.minYear,0,1).getTime(),h=new Date(this.maxYear,11,31).getTime()-l,r=this.el("div",`lt-bar-segment ${s}`),g=s==="lt-bar-oss"?"lt-segment-oss":s==="lt-bar-ent"?"lt-segment-ent":"lt-segment-eol";r.classList.add(g),r.style.left=`${(o-l)/h*100}%`,r.style.width=`${(a-o)/h*100}%`,r.setAttribute("role","img"),r.setAttribute("aria-label",`${n}: ${t.version} (${e} to ${i})`),r.tabIndex=0;const c=`
5
- <div class="lt-tooltip-header">${n} - ${t.version}</div>
6
- <div class="lt-tooltip-date"><strong>Du:</strong> ${e}</div>
7
- <div class="lt-tooltip-date"><strong>Au:</strong> ${i}</div>
8
- `;return r.onmouseenter=d=>this.showTooltip(d,c),r.onmousemove=d=>this.updateTooltipPos(d),r.onmouseleave=()=>this.hideTooltip(),r.onfocus=()=>{const d=r.getBoundingClientRect();this.showTooltip({pageX:d.left+window.scrollX,pageY:d.top+window.scrollY-40},c)},r.onblur=()=>this.hideTooltip(),r}updateVisibility(){const t=this.rows.filter(s=>{const n=s.version.includes(this.filterText),o=this.majorFilterEnabled?s.isMajor:!0;return n&&o});this.rows.forEach(s=>{const n=s.el.querySelector(".lt-version-label"),o=n.querySelector(".lt-version-link");o?o.innerHTML=this.highlight(s.versionOriginal||s.version):n.innerHTML=this.highlight(s.versionOriginal||s.version),s.el.classList.remove("lt-row-visible"),s.el.classList.add("lt-row-hidden")});const e=this.filterText===""&&t.length>this.visibleCount;if((e&&!this.isExpanded?t.slice(0,this.visibleCount):t).forEach(s=>{s.el.classList.remove("lt-row-hidden"),s.el.classList.add("lt-row-visible")}),this.showTable&&this.updateTableVisibility(),this.toggleContainer.innerHTML="",e){const s=this.el("button","lt-toggle-btn",this.toggleContainer),n=`<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="${this.isExpanded?"18 15 12 9 6 15":"6 9 12 15 18 9"}"></polyline></svg>`;s.innerHTML=this.isExpanded?`${this.t("less")} ${n}`:`${this.t("more",{n:t.length-this.visibleCount})} ${n}`,s.setAttribute("aria-expanded",this.isExpanded.toString()),s.onclick=()=>{this.isExpanded=!this.isExpanded,this.updateVisibility()}}}renderCurrentDateLine(){const t=new Date(this.minYear,0,1).getTime(),e=new Date(this.maxYear,11,31).getTime()-t,i=Date.now()-t;if(i<0||i>e)return;const s=new Date().toISOString().split("T")[0],n=this.el("div","lt-current-date-indicator",this.indicators);n.style.left=`${i/e*100}%`,n.setAttribute("role","separator"),n.setAttribute("aria-label",this.t("today",{date:s}));const o=this.el("div","lt-current-date-badge",n);o.textContent=s,o.setAttribute("aria-hidden","true")}}return p}));
4
+ `,i.onclick=()=>this.highlightSegment(e)})}highlightSegment(t){this.root&&(this.activeHighlight=this.activeHighlight===t?null:t,this.root.classList.remove("lt-highlight-oss","lt-highlight-ent","lt-highlight-eol","lt-highlight-future","lt-highlight-fictive"),this.activeHighlight&&this.root.classList.add(`lt-highlight-${this.activeHighlight}`),this.renderLegend())}renderAxis(){this.el("div","",this.axis,{width:"106px",flexShrink:"0"}).setAttribute("role","presentation");for(let s=this.minYear;s<=this.maxYear;s++){const e=this.el("div","lt-year",this.axis);e.textContent=s.toString(),e.setAttribute("role","columnheader")}}renderGrid(){const t=new Date(this.minYear,0,1).getTime(),s=new Date(this.maxYear,11,31).getTime()-t;for(let e=this.minYear;e<=this.maxYear;e++){const i=this.el("div","lt-year-grid-line",this.grid);i.style.left=`${(new Date(e,0,1).getTime()-t)/s*100}%`,i.setAttribute("role","presentation")}}createRow(t,s){const e=this.el("div","lt-row row-entrance",this.tracks);e.setAttribute("role","row"),e.style.transitionDelay=`${s*.05}s`;const i=this.el("div","lt-version-label",e);i.setAttribute("role","rowheader");const r=Date.now(),n=t.ossStart?new Date(t.ossStart).getTime():0,a=t.ossEnd?new Date(t.ossEnd).getTime():0,h=t.enterpriseEnd?new Date(t.enterpriseEnd).getTime():a,o=t.isFictive||!t.ossStart||!t.ossEnd?"lt-status-fictive":t.isFuture?"lt-status-is-future":r<n?"lt-status-future":r>=n&&r<=a?"lt-status-oss":r>a&&r<=h?"lt-status-ent":r>h?"lt-status-expired":"";if(o&&i.classList.add(o),t.isMajor&&i.classList.add("lt-version-major"),t.releaseNotesUrl){const f=this.el("a","lt-version-link",i);f.href=t.releaseNotesUrl,f.target="_blank",f.innerHTML=this.highlight(t.version),f.title=this.t("notes",{v:t.version}),f.setAttribute("aria-label",this.t("notes",{v:t.version}))}else i.innerHTML=this.highlight(t.version),i.title=t.version;const c=this.el("div","lt-track-container",e);if(c.setAttribute("role","gridcell"),!t.ossStart||!t.ossEnd)return{el:e,version:t.version.toLowerCase(),versionOriginal:t.version,isMajor:t.isMajor};const l=this.splitSupport?t.ossEnd:t.ossStart,T=t.enterpriseEnd||t.ossEnd,x=new Date(this.maxYear,11,31).toISOString().split("T")[0],b=this.createBar(t,T,x,"lt-bar-eol",this.t("eol")),w=this.createBar(t,l,t.enterpriseEnd||t.ossEnd,"lt-bar-ent",this.t("ent")),v=this.createBar(t,t.ossStart,t.ossEnd,"lt-bar-oss",this.t("oss"));return t.isFictive?(b.classList.add("lt-is-fictive-bar"),w.classList.add("lt-is-fictive-bar"),v.classList.add("lt-is-fictive-bar")):t.isFuture&&v.classList.add("lt-is-future-oss"),c.appendChild(b),c.appendChild(w),c.appendChild(v),{el:e,version:t.version.toLowerCase(),versionOriginal:t.version,isMajor:t.isMajor}}createBar(t,s,e,i,r){const n=new Date(s).getTime(),a=new Date(e).getTime(),h=new Date(this.minYear,0,1).getTime(),d=new Date(this.maxYear,11,31).getTime()-h,o=this.el("div",`lt-bar-segment ${i}`),c=i==="lt-bar-oss"?"lt-segment-oss":i==="lt-bar-ent"?"lt-segment-ent":"lt-segment-eol";o.classList.add(c),o.style.left=`${(n-h)/d*100}%`,o.style.width=`${(a-n)/d*100}%`,o.setAttribute("role","img"),o.setAttribute("aria-label",`${r}: ${t.version} (${s} to ${e})`),o.tabIndex=0;const u=`
5
+ <div class="lt-tooltip-header">${r} - ${t.version}</div>
6
+ <div class="lt-tooltip-date"><strong>Du:</strong> ${s}</div>
7
+ <div class="lt-tooltip-date"><strong>Au:</strong> ${e}</div>
8
+ `;return o.onmouseenter=l=>this.showTooltip(l,u),o.onmousemove=l=>this.updateTooltipPos(l),o.onmouseleave=()=>this.hideTooltip(),o.onfocus=()=>{const l=o.getBoundingClientRect();this.showTooltip({pageX:l.left+window.scrollX,pageY:l.top+window.scrollY-40},u)},o.onblur=()=>this.hideTooltip(),o}updateVisibility(){const t=this.rows.filter(i=>{const r=i.version.includes(this.filterText),n=this.majorFilterEnabled?i.isMajor:!0;return r&&n});this.rows.forEach(i=>{const r=i.el.querySelector(".lt-version-label"),n=r.querySelector(".lt-version-link");n?n.innerHTML=this.highlight(i.versionOriginal||i.version):r.innerHTML=this.highlight(i.versionOriginal||i.version),i.el.classList.remove("lt-row-visible"),i.el.classList.add("lt-row-hidden")});const s=this.filterText===""&&t.length>this.visibleCount;if((s&&!this.isExpanded?t.slice(0,this.visibleCount):t).forEach(i=>{i.el.classList.remove("lt-row-hidden"),i.el.classList.add("lt-row-visible")}),this.showTable&&this.updateTableVisibility(),this.toggleContainer.innerHTML="",s){const i=this.el("button","lt-toggle-btn",this.toggleContainer),r=`<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="${this.isExpanded?"18 15 12 9 6 15":"6 9 12 15 18 9"}"></polyline></svg>`;i.innerHTML=this.isExpanded?`${this.t("less")} ${r}`:`${this.t("more",{n:t.length-this.visibleCount})} ${r}`,i.setAttribute("aria-expanded",this.isExpanded.toString()),i.onclick=()=>{this.isExpanded=!this.isExpanded,this.updateVisibility()}}}renderCurrentDateLine(){const t=new Date(this.minYear,0,1).getTime(),s=new Date(this.maxYear,11,31).getTime()-t,e=Date.now()-t;if(e<0||e>s)return;const i=new Date().toISOString().split("T")[0],r=this.el("div","lt-current-date-indicator",this.indicators);r.style.left=`${e/s*100}%`,r.setAttribute("role","separator"),r.setAttribute("aria-label",this.t("today",{date:i}));const n=this.el("div","lt-current-date-badge",r);n.textContent=i,n.setAttribute("aria-hidden","true")}}return p}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lifecycle-timeline",
3
- "version": "1.2.9",
3
+ "version": "1.3.0",
4
4
  "description": "A beautiful, premium JS timeline component for visualizing product lifecycles, OSS support, and enterprise support dates.",
5
5
  "type": "module",
6
6
  "main": "./dist/timeline.umd.cjs",