lifecycle-timeline 1.2.7 → 1.2.9
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 +1 -1
- package/dist/timeline.d.ts +267 -0
- package/dist/timeline.js +130 -92
- package/dist/timeline.umd.cjs +3 -3
- package/package.json +8 -9
- package/src/index.d.ts +0 -104
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;height:36px;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:80px;min-width:80px;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}.lt-version-label.lt-version-major{font-weight:800;border:2px solid var(--border-color)}.lt-version-label:hover{background-color:var(--bg-track);transform:scale(1.05);box-shadow:0 4px 12px #0000001a}.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-track-container{flex-grow:1;position:relative;height:100%;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-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}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a Lifecycle Timeline component.
|
|
3
|
+
*/
|
|
4
|
+
declare class Timeline {
|
|
5
|
+
root: HTMLElement | null;
|
|
6
|
+
options: TimelineOptions;
|
|
7
|
+
visibleCount: number;
|
|
8
|
+
showTable: boolean;
|
|
9
|
+
showThemeToggle: boolean;
|
|
10
|
+
showLegend: boolean;
|
|
11
|
+
filterVersions: boolean;
|
|
12
|
+
splitSupport: boolean;
|
|
13
|
+
compactMode: boolean;
|
|
14
|
+
showMajorFilter: boolean;
|
|
15
|
+
isExpanded: boolean;
|
|
16
|
+
theme: 'light' | 'dark';
|
|
17
|
+
filterText: string;
|
|
18
|
+
majorFilterEnabled: boolean;
|
|
19
|
+
activeHighlight: string | null;
|
|
20
|
+
translations: Record<string, Record<string, string>>;
|
|
21
|
+
locale: string;
|
|
22
|
+
data: TimelineVersion[];
|
|
23
|
+
minYear: number;
|
|
24
|
+
maxYear: number;
|
|
25
|
+
currentDate: Date;
|
|
26
|
+
tableContainer: HTMLElement;
|
|
27
|
+
wrapper: HTMLElement;
|
|
28
|
+
axis: HTMLElement;
|
|
29
|
+
tracks: HTMLElement;
|
|
30
|
+
legendContainer: HTMLElement;
|
|
31
|
+
tableBody: HTMLElement;
|
|
32
|
+
tableRows: {
|
|
33
|
+
el: HTMLElement;
|
|
34
|
+
version: string;
|
|
35
|
+
versionOriginal: string;
|
|
36
|
+
}[];
|
|
37
|
+
tableToggleContainer: HTMLElement;
|
|
38
|
+
grid: HTMLElement;
|
|
39
|
+
indicators: HTMLElement;
|
|
40
|
+
rows: {
|
|
41
|
+
el: HTMLElement;
|
|
42
|
+
version: string;
|
|
43
|
+
versionOriginal: string;
|
|
44
|
+
isMajor?: boolean;
|
|
45
|
+
}[];
|
|
46
|
+
toggleContainer: HTMLElement;
|
|
47
|
+
tooltip: HTMLElement;
|
|
48
|
+
/**
|
|
49
|
+
* Creates an instance of Timeline.
|
|
50
|
+
* @param elementId - The ID of the root element.
|
|
51
|
+
* @param data - The data array containing version details.
|
|
52
|
+
* @param options - Configuration options.
|
|
53
|
+
*/
|
|
54
|
+
constructor(elementId: string, data: TimelineVersion[], options?: TimelineOptions);
|
|
55
|
+
/**
|
|
56
|
+
* Detects the browser language.
|
|
57
|
+
* @returns The detected language code or 'en'.
|
|
58
|
+
*/
|
|
59
|
+
detectLanguage(): string;
|
|
60
|
+
/**
|
|
61
|
+
* Translates a key based on the current locale.
|
|
62
|
+
* @param key - The translation key.
|
|
63
|
+
* @param params - Parameters to replace in the translation string.
|
|
64
|
+
* @returns The translated string.
|
|
65
|
+
*/
|
|
66
|
+
t(key: string, params?: Record<string, any>): string;
|
|
67
|
+
/**
|
|
68
|
+
* Sets up the initial layout of the timeline.
|
|
69
|
+
*/
|
|
70
|
+
setupBaseLayout(): void;
|
|
71
|
+
/**
|
|
72
|
+
* Updates the timeline data and re-renders.
|
|
73
|
+
* @param newData - The new data array.
|
|
74
|
+
*/
|
|
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
|
+
validateData(data: TimelineVersion[]): TimelineVersion[];
|
|
82
|
+
/**
|
|
83
|
+
* Calculates the min and max years based on the data.
|
|
84
|
+
*/
|
|
85
|
+
calculateTimeRange(): void;
|
|
86
|
+
/**
|
|
87
|
+
* Renders the data table.
|
|
88
|
+
*/
|
|
89
|
+
renderTable(): void;
|
|
90
|
+
/**
|
|
91
|
+
* Creates a row for the data table.
|
|
92
|
+
* @param item - Version data.
|
|
93
|
+
*/
|
|
94
|
+
createTableRow(item: TimelineVersion): {
|
|
95
|
+
el: HTMLElement;
|
|
96
|
+
version: string;
|
|
97
|
+
versionOriginal: string;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Updates table visibility based on filter and visibleCount.
|
|
101
|
+
*/
|
|
102
|
+
updateTableVisibility(): void;
|
|
103
|
+
/**
|
|
104
|
+
* Renders the entire timeline.
|
|
105
|
+
*/
|
|
106
|
+
render(): void;
|
|
107
|
+
/**
|
|
108
|
+
* Sets up the tooltip overlay.
|
|
109
|
+
*/
|
|
110
|
+
setupTooltip(): void;
|
|
111
|
+
/**
|
|
112
|
+
* Shows the tooltip with provided content.
|
|
113
|
+
* @param e - The mouse event or position object.
|
|
114
|
+
* @param content - The HTML content for the tooltip.
|
|
115
|
+
*/
|
|
116
|
+
showTooltip(e: MouseEvent | {
|
|
117
|
+
pageX: number;
|
|
118
|
+
pageY: number;
|
|
119
|
+
}, content: string): void;
|
|
120
|
+
/**
|
|
121
|
+
* Updates tooltip position relative to mouse.
|
|
122
|
+
* @param e - The mouse event or position object.
|
|
123
|
+
*/
|
|
124
|
+
updateTooltipPos(e: MouseEvent | {
|
|
125
|
+
pageX: number;
|
|
126
|
+
pageY: number;
|
|
127
|
+
clientX?: number;
|
|
128
|
+
clientY?: number;
|
|
129
|
+
}): void;
|
|
130
|
+
/**
|
|
131
|
+
* Hides the tooltip.
|
|
132
|
+
*/
|
|
133
|
+
hideTooltip(): void;
|
|
134
|
+
/**
|
|
135
|
+
* Highlights the search term in a given text.
|
|
136
|
+
* @param text - The text to process.
|
|
137
|
+
* @returns The HTML with highlighted segments.
|
|
138
|
+
*/
|
|
139
|
+
highlight(text: string): string;
|
|
140
|
+
/**
|
|
141
|
+
* Helper to create DOM elements with styles and classes.
|
|
142
|
+
* @param tag - HTML tag.
|
|
143
|
+
* @param className - CSS class name.
|
|
144
|
+
* @param parent - Parent element.
|
|
145
|
+
* @param styles - Inline styles.
|
|
146
|
+
* @returns The created element.
|
|
147
|
+
*/
|
|
148
|
+
el(tag: string, className: string, parent?: HTMLElement, styles?: Record<string, string>): HTMLElement;
|
|
149
|
+
/**
|
|
150
|
+
* Renders the toolbar with the filter input.
|
|
151
|
+
*/
|
|
152
|
+
renderToolbar(): void;
|
|
153
|
+
/**
|
|
154
|
+
* Renders the theme toggle button.
|
|
155
|
+
*/
|
|
156
|
+
renderThemeToggle(): void;
|
|
157
|
+
/**
|
|
158
|
+
* Renders the legend section.
|
|
159
|
+
*/
|
|
160
|
+
renderLegend(): void;
|
|
161
|
+
/**
|
|
162
|
+
* Toggles highlighting for a specific segment type.
|
|
163
|
+
* @param type - 'oss', 'ent', or 'eol'.
|
|
164
|
+
*/
|
|
165
|
+
highlightSegment(type: string): void;
|
|
166
|
+
/**
|
|
167
|
+
* Renders the year axis.
|
|
168
|
+
*/
|
|
169
|
+
renderAxis(): void;
|
|
170
|
+
/**
|
|
171
|
+
* Renders the vertical grid lines for years.
|
|
172
|
+
*/
|
|
173
|
+
renderGrid(): void;
|
|
174
|
+
/**
|
|
175
|
+
* Creates a row for a specific version.
|
|
176
|
+
* @param item - The version data item.
|
|
177
|
+
* @returns Metadata about the created row.
|
|
178
|
+
*/
|
|
179
|
+
createRow(item: TimelineVersion, index: number): {
|
|
180
|
+
el: HTMLElement;
|
|
181
|
+
version: string;
|
|
182
|
+
versionOriginal: string;
|
|
183
|
+
isMajor?: boolean;
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* Creates a colored bar segment for the timeline.
|
|
187
|
+
* @param item - The version item.
|
|
188
|
+
* @param startStr - Start date string.
|
|
189
|
+
* @param endStr - End date string.
|
|
190
|
+
* @param className - CSS class.
|
|
191
|
+
* @param label - Support type label for tooltip.
|
|
192
|
+
* @returns The created bar element.
|
|
193
|
+
*/
|
|
194
|
+
createBar(item: TimelineVersion, startStr: string, endStr: string, className: string, label: string): HTMLElement;
|
|
195
|
+
/**
|
|
196
|
+
* Updates visibility of rows based on filtering and expansion state.
|
|
197
|
+
*/
|
|
198
|
+
updateVisibility(): void;
|
|
199
|
+
/**
|
|
200
|
+
* Renders the vertical line indicating current date.
|
|
201
|
+
*/
|
|
202
|
+
renderCurrentDateLine(): void;
|
|
203
|
+
}
|
|
204
|
+
export default Timeline;
|
|
205
|
+
|
|
206
|
+
declare interface TimelineOptions {
|
|
207
|
+
/**
|
|
208
|
+
* Number of versions to show before "Show more" button appears.
|
|
209
|
+
* @default 3
|
|
210
|
+
*/
|
|
211
|
+
visibleCount?: number;
|
|
212
|
+
/**
|
|
213
|
+
* Preferred locale for translations ('en' or 'fr').
|
|
214
|
+
* Defaults to browser language.
|
|
215
|
+
*/
|
|
216
|
+
locale?: 'en' | 'fr' | string;
|
|
217
|
+
/**
|
|
218
|
+
* Custom translations to merge or override.
|
|
219
|
+
*/
|
|
220
|
+
i18n?: Record<string, Record<string, string>>;
|
|
221
|
+
/**
|
|
222
|
+
* Whether to show the data table between filter and timeline.
|
|
223
|
+
* @default true
|
|
224
|
+
*/
|
|
225
|
+
showTable?: boolean;
|
|
226
|
+
/**
|
|
227
|
+
* Whether to show the legend below the timeline.
|
|
228
|
+
* @default true
|
|
229
|
+
*/
|
|
230
|
+
showLegend?: boolean;
|
|
231
|
+
/**
|
|
232
|
+
* Whether to show the version filter input.
|
|
233
|
+
* @default true
|
|
234
|
+
*/
|
|
235
|
+
filterVersions?: boolean;
|
|
236
|
+
/**
|
|
237
|
+
* Whether to show the enterprise bar normally (false) or split after OSS (true).
|
|
238
|
+
* @default false
|
|
239
|
+
*/
|
|
240
|
+
splitSupport?: boolean;
|
|
241
|
+
/**
|
|
242
|
+
* Whether to use compact mode (reduced height).
|
|
243
|
+
* @default false
|
|
244
|
+
*/
|
|
245
|
+
compactMode?: boolean;
|
|
246
|
+
/**
|
|
247
|
+
* Whether to show the major version filter checkbox.
|
|
248
|
+
* @default false
|
|
249
|
+
*/
|
|
250
|
+
showMajorFilter?: boolean;
|
|
251
|
+
/**
|
|
252
|
+
* Whether the major version filter runs by default.
|
|
253
|
+
* @default false
|
|
254
|
+
*/
|
|
255
|
+
majorFilterDefault?: boolean;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
declare interface TimelineVersion {
|
|
259
|
+
version: string;
|
|
260
|
+
ossStart: string;
|
|
261
|
+
ossEnd: string;
|
|
262
|
+
enterpriseEnd?: string;
|
|
263
|
+
releaseNotesUrl?: string;
|
|
264
|
+
isMajor?: boolean;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export { }
|
package/dist/timeline.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const p = {
|
|
2
2
|
en: {
|
|
3
3
|
filter: "Filter versions...",
|
|
4
4
|
oss: "OSS Support",
|
|
@@ -38,22 +38,57 @@ const u = {
|
|
|
38
38
|
majorOnly: "Versions majeures uniquement"
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
|
-
class
|
|
41
|
+
class f {
|
|
42
|
+
root;
|
|
43
|
+
options;
|
|
44
|
+
visibleCount;
|
|
45
|
+
showTable;
|
|
46
|
+
showThemeToggle;
|
|
47
|
+
showLegend;
|
|
48
|
+
filterVersions;
|
|
49
|
+
splitSupport;
|
|
50
|
+
compactMode;
|
|
51
|
+
showMajorFilter;
|
|
52
|
+
isExpanded;
|
|
53
|
+
theme;
|
|
54
|
+
filterText;
|
|
55
|
+
majorFilterEnabled;
|
|
56
|
+
activeHighlight;
|
|
57
|
+
translations;
|
|
58
|
+
locale;
|
|
59
|
+
data = [];
|
|
60
|
+
minYear = 0;
|
|
61
|
+
maxYear = 0;
|
|
62
|
+
currentDate = /* @__PURE__ */ new Date();
|
|
63
|
+
tableContainer;
|
|
64
|
+
wrapper;
|
|
65
|
+
axis;
|
|
66
|
+
tracks;
|
|
67
|
+
legendContainer;
|
|
68
|
+
tableBody;
|
|
69
|
+
tableRows = [];
|
|
70
|
+
tableToggleContainer;
|
|
71
|
+
grid;
|
|
72
|
+
indicators;
|
|
73
|
+
rows = [];
|
|
74
|
+
toggleContainer;
|
|
75
|
+
tooltip;
|
|
42
76
|
/**
|
|
43
77
|
* Creates an instance of Timeline.
|
|
44
|
-
* @param
|
|
45
|
-
* @param
|
|
46
|
-
* @param
|
|
47
|
-
* @param {number} [options.visibleCount=3] - Number of versions to show initially.
|
|
48
|
-
* @param {string} [options.locale] - Language code (e.g., 'en', 'fr').
|
|
49
|
-
* @param {Object} [options.i18n] - Custom translations to merge or override.
|
|
78
|
+
* @param elementId - The ID of the root element.
|
|
79
|
+
* @param data - The data array containing version details.
|
|
80
|
+
* @param options - Configuration options.
|
|
50
81
|
*/
|
|
51
82
|
constructor(t, e, i = {}) {
|
|
52
|
-
this.root = document.getElementById(t),
|
|
83
|
+
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";
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
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);
|
|
53
88
|
}
|
|
54
89
|
/**
|
|
55
90
|
* Detects the browser language.
|
|
56
|
-
* @returns
|
|
91
|
+
* @returns The detected language code or 'en'.
|
|
57
92
|
*/
|
|
58
93
|
detectLanguage() {
|
|
59
94
|
const t = (navigator.language || "en").split("-")[0];
|
|
@@ -61,9 +96,9 @@ class v {
|
|
|
61
96
|
}
|
|
62
97
|
/**
|
|
63
98
|
* Translates a key based on the current locale.
|
|
64
|
-
* @param
|
|
65
|
-
* @param
|
|
66
|
-
* @returns
|
|
99
|
+
* @param key - The translation key.
|
|
100
|
+
* @param params - Parameters to replace in the translation string.
|
|
101
|
+
* @returns The translated string.
|
|
67
102
|
*/
|
|
68
103
|
t(t, e = {}) {
|
|
69
104
|
let i = (this.translations[this.locale] || this.translations.en)[t] || t;
|
|
@@ -73,26 +108,26 @@ class v {
|
|
|
73
108
|
* Sets up the initial layout of the timeline.
|
|
74
109
|
*/
|
|
75
110
|
setupBaseLayout() {
|
|
76
|
-
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));
|
|
111
|
+
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)));
|
|
77
112
|
}
|
|
78
113
|
/**
|
|
79
114
|
* Updates the timeline data and re-renders.
|
|
80
|
-
* @param
|
|
115
|
+
* @param newData - The new data array.
|
|
81
116
|
*/
|
|
82
117
|
updateData(t) {
|
|
83
118
|
this.data = this.validateData(t || []), this.calculateTimeRange(), this.render();
|
|
84
119
|
}
|
|
85
120
|
/**
|
|
86
121
|
* Validates the input data.
|
|
87
|
-
* @param
|
|
88
|
-
* @returns
|
|
122
|
+
* @param data - The data array to validate.
|
|
123
|
+
* @returns The validated and filtered data array.
|
|
89
124
|
*/
|
|
90
125
|
validateData(t) {
|
|
91
126
|
return t.filter((e, i) => {
|
|
92
|
-
const
|
|
93
|
-
if (
|
|
94
|
-
return console.warn(`[Timeline] Missing fields for item at index ${i}: ${
|
|
95
|
-
const a = ["ossStart", "ossEnd", "enterpriseEnd"].filter((
|
|
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()));
|
|
96
131
|
return a.length > 0 ? (console.warn(`[Timeline] Invalid date format for item "${e.version}": ${a.join(", ")}`), !1) : !0;
|
|
97
132
|
});
|
|
98
133
|
}
|
|
@@ -105,8 +140,8 @@ class v {
|
|
|
105
140
|
return;
|
|
106
141
|
}
|
|
107
142
|
const t = this.data.flatMap((e) => [
|
|
108
|
-
new Date(e.ossStart),
|
|
109
|
-
new Date(e.enterpriseEnd || e.ossEnd)
|
|
143
|
+
new Date(e.ossStart).getTime(),
|
|
144
|
+
new Date(e.enterpriseEnd || e.ossEnd).getTime()
|
|
110
145
|
]);
|
|
111
146
|
this.minYear = new Date(Math.min(...t)).getFullYear(), this.maxYear = new Date(Math.max(...t)).getFullYear();
|
|
112
147
|
}
|
|
@@ -123,18 +158,18 @@ class v {
|
|
|
123
158
|
}
|
|
124
159
|
/**
|
|
125
160
|
* Creates a row for the data table.
|
|
126
|
-
* @param
|
|
161
|
+
* @param item - Version data.
|
|
127
162
|
*/
|
|
128
163
|
createTableRow(t) {
|
|
129
|
-
const e = this.el("tr", "", this.tableBody), i = Date.now(), s = new Date(t.ossStart).getTime(),
|
|
130
|
-
let h = `<span class="lt-table-badge ${a}">${t.
|
|
131
|
-
t.releaseNotesUrl ?
|
|
132
|
-
const
|
|
133
|
-
|
|
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");
|
|
134
169
|
const g = this.el("td", "", e);
|
|
135
|
-
g.textContent = t.ossEnd, i >
|
|
170
|
+
g.textContent = t.ossEnd, i > o && (g.className = "lt-past-date");
|
|
136
171
|
const c = this.el("td", "", e);
|
|
137
|
-
return c.textContent = t.enterpriseEnd || t.ossEnd, i >
|
|
172
|
+
return c.textContent = t.enterpriseEnd || t.ossEnd, i > n && (c.className = "lt-past-date"), { el: e, version: t.version.toLowerCase(), versionOriginal: t.version };
|
|
138
173
|
}
|
|
139
174
|
/**
|
|
140
175
|
* Updates table visibility based on filter and visibleCount.
|
|
@@ -142,15 +177,15 @@ class v {
|
|
|
142
177
|
updateTableVisibility() {
|
|
143
178
|
const t = this.tableRows.filter((s) => s.version.includes(this.filterText));
|
|
144
179
|
this.tableRows.forEach((s) => {
|
|
145
|
-
const
|
|
146
|
-
|
|
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");
|
|
147
182
|
});
|
|
148
183
|
const e = this.filterText === "" && t.length > this.visibleCount;
|
|
149
184
|
if ((e && !this.isExpanded ? t.slice(0, this.visibleCount) : t).forEach((s) => {
|
|
150
185
|
s.el.classList.remove("lt-row-hidden"), s.el.classList.add("lt-row-visible");
|
|
151
186
|
}), this.tableToggleContainer.innerHTML = "", e) {
|
|
152
|
-
const s = this.el("button", "lt-toggle-btn lt-table-toggle", this.tableToggleContainer),
|
|
153
|
-
s.innerHTML = this.isExpanded ? `${this.t("less")} ${
|
|
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 = () => {
|
|
154
189
|
this.isExpanded = !this.isExpanded, this.updateVisibility();
|
|
155
190
|
};
|
|
156
191
|
}
|
|
@@ -175,21 +210,22 @@ class v {
|
|
|
175
210
|
}
|
|
176
211
|
/**
|
|
177
212
|
* Shows the tooltip with provided content.
|
|
178
|
-
* @param
|
|
179
|
-
* @param
|
|
213
|
+
* @param e - The mouse event or position object.
|
|
214
|
+
* @param content - The HTML content for the tooltip.
|
|
180
215
|
*/
|
|
181
216
|
showTooltip(t, e) {
|
|
182
217
|
this.tooltip.innerHTML = e, this.tooltip.style.display = "block", this.updateTooltipPos(t);
|
|
183
218
|
}
|
|
184
219
|
/**
|
|
185
220
|
* Updates tooltip position relative to mouse.
|
|
186
|
-
* @param
|
|
221
|
+
* @param e - The mouse event or position object.
|
|
187
222
|
*/
|
|
188
223
|
updateTooltipPos(t) {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
224
|
+
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`;
|
|
193
229
|
}
|
|
194
230
|
/**
|
|
195
231
|
* Hides the tooltip.
|
|
@@ -199,8 +235,8 @@ class v {
|
|
|
199
235
|
}
|
|
200
236
|
/**
|
|
201
237
|
* Highlights the search term in a given text.
|
|
202
|
-
* @param
|
|
203
|
-
* @returns
|
|
238
|
+
* @param text - The text to process.
|
|
239
|
+
* @returns The HTML with highlighted segments.
|
|
204
240
|
*/
|
|
205
241
|
highlight(t) {
|
|
206
242
|
if (!this.filterText) return t;
|
|
@@ -213,20 +249,21 @@ class v {
|
|
|
213
249
|
}
|
|
214
250
|
/**
|
|
215
251
|
* Helper to create DOM elements with styles and classes.
|
|
216
|
-
* @param
|
|
217
|
-
* @param
|
|
218
|
-
* @param
|
|
219
|
-
* @param
|
|
220
|
-
* @returns
|
|
252
|
+
* @param tag - HTML tag.
|
|
253
|
+
* @param className - CSS class name.
|
|
254
|
+
* @param parent - Parent element.
|
|
255
|
+
* @param styles - Inline styles.
|
|
256
|
+
* @returns The created element.
|
|
221
257
|
*/
|
|
222
258
|
el(t, e, i, s = {}) {
|
|
223
|
-
const
|
|
224
|
-
return e && (
|
|
259
|
+
const o = document.createElement(t);
|
|
260
|
+
return e && (o.className = e), Object.assign(o.style, s), i && i.appendChild(o), o;
|
|
225
261
|
}
|
|
226
262
|
/**
|
|
227
263
|
* Renders the toolbar with the filter input.
|
|
228
264
|
*/
|
|
229
265
|
renderToolbar() {
|
|
266
|
+
if (!this.root) return;
|
|
230
267
|
const t = this.el("div", "lt-toolbar", this.root);
|
|
231
268
|
if (this.filterVersions) {
|
|
232
269
|
const e = this.el("div", "lt-filter-container", t);
|
|
@@ -238,8 +275,8 @@ class v {
|
|
|
238
275
|
}
|
|
239
276
|
if (this.showMajorFilter) {
|
|
240
277
|
const e = this.el("label", "lt-checkbox-label", t), i = this.el("input", "", e);
|
|
241
|
-
i.type = "checkbox", i.checked = this.majorFilterEnabled, i.onchange = (
|
|
242
|
-
this.majorFilterEnabled =
|
|
278
|
+
i.type = "checkbox", i.checked = this.majorFilterEnabled, i.onchange = (o) => {
|
|
279
|
+
this.majorFilterEnabled = o.target.checked, this.updateVisibility();
|
|
243
280
|
};
|
|
244
281
|
const s = this.el("span", "", e);
|
|
245
282
|
s.textContent = this.t("majorOnly");
|
|
@@ -249,6 +286,7 @@ class v {
|
|
|
249
286
|
* Renders the theme toggle button.
|
|
250
287
|
*/
|
|
251
288
|
renderThemeToggle() {
|
|
289
|
+
if (!this.root) return;
|
|
252
290
|
const t = this.el("button", "lt-theme-toggle-btn", this.root);
|
|
253
291
|
t.title = this.t("dark"), t.setAttribute("aria-label", this.t("dark"));
|
|
254
292
|
const e = {
|
|
@@ -256,7 +294,7 @@ class v {
|
|
|
256
294
|
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>'
|
|
257
295
|
};
|
|
258
296
|
t.innerHTML = this.theme === "dark" ? e.sun : e.moon, t.onclick = () => {
|
|
259
|
-
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");
|
|
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());
|
|
260
298
|
};
|
|
261
299
|
}
|
|
262
300
|
/**
|
|
@@ -275,19 +313,19 @@ class v {
|
|
|
275
313
|
}
|
|
276
314
|
/**
|
|
277
315
|
* Toggles highlighting for a specific segment type.
|
|
278
|
-
* @param
|
|
316
|
+
* @param type - 'oss', 'ent', or 'eol'.
|
|
279
317
|
*/
|
|
280
318
|
highlightSegment(t) {
|
|
281
|
-
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();
|
|
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());
|
|
282
320
|
}
|
|
283
321
|
/**
|
|
284
322
|
* Renders the year axis.
|
|
285
323
|
*/
|
|
286
324
|
renderAxis() {
|
|
287
|
-
this.el("div", "", this.axis, { width: "
|
|
325
|
+
this.el("div", "", this.axis, { width: "106px", flexShrink: "0" }).setAttribute("role", "presentation");
|
|
288
326
|
for (let e = this.minYear; e <= this.maxYear; e++) {
|
|
289
327
|
const i = this.el("div", "lt-year", this.axis);
|
|
290
|
-
i.textContent = e, i.setAttribute("role", "columnheader");
|
|
328
|
+
i.textContent = e.toString(), i.setAttribute("role", "columnheader");
|
|
291
329
|
}
|
|
292
330
|
}
|
|
293
331
|
/**
|
|
@@ -302,65 +340,65 @@ class v {
|
|
|
302
340
|
}
|
|
303
341
|
/**
|
|
304
342
|
* Creates a row for a specific version.
|
|
305
|
-
* @param
|
|
306
|
-
* @returns
|
|
343
|
+
* @param item - The version data item.
|
|
344
|
+
* @returns Metadata about the created row.
|
|
307
345
|
*/
|
|
308
346
|
createRow(t, e) {
|
|
309
347
|
const i = this.el("div", "lt-row row-entrance", this.tracks);
|
|
310
348
|
i.setAttribute("role", "row"), i.style.transitionDelay = `${e * 0.05}s`;
|
|
311
349
|
const s = this.el("div", "lt-version-label", i);
|
|
312
350
|
s.setAttribute("role", "rowheader");
|
|
313
|
-
const
|
|
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" : "";
|
|
314
352
|
if (h && s.classList.add(h), t.isMajor && s.classList.add("lt-version-major"), t.releaseNotesUrl) {
|
|
315
|
-
const
|
|
316
|
-
|
|
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 }));
|
|
317
355
|
} else
|
|
318
|
-
s.innerHTML = this.highlight(t.version);
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
const g = this.splitSupport ? t.ossEnd : t.ossStart, c = t.enterpriseEnd || t.ossEnd,
|
|
322
|
-
return
|
|
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 };
|
|
323
361
|
}
|
|
324
362
|
/**
|
|
325
363
|
* Creates a colored bar segment for the timeline.
|
|
326
|
-
* @param
|
|
327
|
-
* @param
|
|
328
|
-
* @param
|
|
329
|
-
* @param
|
|
330
|
-
* @param
|
|
331
|
-
* @returns
|
|
364
|
+
* @param item - The version item.
|
|
365
|
+
* @param startStr - Start date string.
|
|
366
|
+
* @param endStr - End date string.
|
|
367
|
+
* @param className - CSS class.
|
|
368
|
+
* @param label - Support type label for tooltip.
|
|
369
|
+
* @returns The created bar element.
|
|
332
370
|
*/
|
|
333
|
-
createBar(t, e, i, s,
|
|
334
|
-
const
|
|
335
|
-
|
|
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;
|
|
336
374
|
const c = `
|
|
337
|
-
<div class="lt-tooltip-header">${
|
|
375
|
+
<div class="lt-tooltip-header">${o} - ${t.version}</div>
|
|
338
376
|
<div class="lt-tooltip-date"><strong>Du:</strong> ${e}</div>
|
|
339
377
|
<div class="lt-tooltip-date"><strong>Au:</strong> ${i}</div>
|
|
340
378
|
`;
|
|
341
|
-
return
|
|
342
|
-
const d =
|
|
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();
|
|
343
381
|
this.showTooltip({ pageX: d.left + window.scrollX, pageY: d.top + window.scrollY - 40 }, c);
|
|
344
|
-
},
|
|
382
|
+
}, r.onblur = () => this.hideTooltip(), r;
|
|
345
383
|
}
|
|
346
384
|
/**
|
|
347
385
|
* Updates visibility of rows based on filtering and expansion state.
|
|
348
386
|
*/
|
|
349
387
|
updateVisibility() {
|
|
350
388
|
const t = this.rows.filter((s) => {
|
|
351
|
-
const
|
|
352
|
-
return
|
|
389
|
+
const o = s.version.includes(this.filterText), n = this.majorFilterEnabled ? s.isMajor : !0;
|
|
390
|
+
return o && n;
|
|
353
391
|
});
|
|
354
392
|
this.rows.forEach((s) => {
|
|
355
|
-
const
|
|
356
|
-
|
|
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");
|
|
357
395
|
});
|
|
358
396
|
const e = this.filterText === "" && t.length > this.visibleCount;
|
|
359
397
|
if ((e && !this.isExpanded ? t.slice(0, this.visibleCount) : t).forEach((s) => {
|
|
360
398
|
s.el.classList.remove("lt-row-hidden"), s.el.classList.add("lt-row-visible");
|
|
361
399
|
}), this.showTable && this.updateTableVisibility(), this.toggleContainer.innerHTML = "", e) {
|
|
362
|
-
const s = this.el("button", "lt-toggle-btn", this.toggleContainer),
|
|
363
|
-
s.innerHTML = this.isExpanded ? `${this.t("less")} ${
|
|
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 = () => {
|
|
364
402
|
this.isExpanded = !this.isExpanded, this.updateVisibility();
|
|
365
403
|
};
|
|
366
404
|
}
|
|
@@ -371,12 +409,12 @@ class v {
|
|
|
371
409
|
renderCurrentDateLine() {
|
|
372
410
|
const t = new Date(this.minYear, 0, 1).getTime(), e = new Date(this.maxYear, 11, 31).getTime() - t, i = Date.now() - t;
|
|
373
411
|
if (i < 0 || i > e) return;
|
|
374
|
-
const s = (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
|
|
375
|
-
|
|
376
|
-
const
|
|
377
|
-
|
|
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");
|
|
378
416
|
}
|
|
379
417
|
}
|
|
380
418
|
export {
|
|
381
|
-
|
|
419
|
+
f as default
|
|
382
420
|
};
|
package/dist/timeline.umd.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
(function(u,b){typeof exports=="object"&&typeof module<"u"?module.exports=b():typeof define=="function"&&define.amd?define(b):(u=typeof globalThis<"u"?globalThis:u||self,u.Timeline=b())})(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 b{constructor(t,e,i={}){this.root=document.getElementById(t),this.root&&(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=!1,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.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(r=>!e[r]);if(n.length>0)return console.warn(`[Timeline] Missing fields for item at index ${i}: ${n.join(", ")}`),!1;const a=["ossStart","ossEnd","enterpriseEnd"].filter(r=>e[r]).filter(r=>isNaN(new Date(e[r]).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),new Date(e.enterpriseEnd||e.ossEnd)]);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(),l=t.enterpriseEnd?new Date(t.enterpriseEnd).getTime():n,a=i>=s&&i<=n?"lt-status-oss":i>n&&i<=l?"lt-status-ent":i>l?"lt-status-expired":"",r=this.el("td","",e);let h=`<span class="lt-table-badge ${a}">${t.versionOriginal||t.version}</span>`;t.releaseNotesUrl?r.innerHTML=`<a href="${t.releaseNotesUrl}" target="_blank" class="lt-table-version-link">${h}</a>`:r.innerHTML=h;const o=this.el("td","",e);o.textContent=t.ossStart,i>s&&(o.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>l&&(c.className="lt-past-date"),{el:e,version:t.version.toLowerCase(),versionOriginal:t.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.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){const e=this.root.getBoundingClientRect(),i=12;let s=t.clientX-e.left+i,n=t.clientY-e.top+i;const l=this.tooltip.offsetWidth,a=this.tooltip.offsetHeight;s+l>this.root.offsetWidth&&(s=t.clientX-e.left-l-i),n+a>this.root.offsetHeight&&(n=t.clientY-e.top-a-i),this.tooltip.style.left=`${s}px`,this.tooltip.style.top=`${n}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(){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(){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")}}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(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=`
|
|
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.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:"
|
|
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
5
|
<div class="lt-tooltip-header">${n} - ${t.version}</div>
|
|
6
6
|
<div class="lt-tooltip-date"><strong>Du:</strong> ${e}</div>
|
|
7
7
|
<div class="lt-tooltip-date"><strong>Au:</strong> ${i}</div>
|
|
8
|
-
`;return
|
|
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}));
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lifecycle-timeline",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.9",
|
|
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",
|
|
7
7
|
"module": "./dist/timeline.js",
|
|
8
|
-
"types": "./
|
|
8
|
+
"types": "./dist/timeline.d.ts",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
|
-
"types": "./
|
|
11
|
+
"types": "./dist/timeline.d.ts",
|
|
12
12
|
"import": "./dist/timeline.js",
|
|
13
13
|
"require": "./dist/timeline.umd.cjs"
|
|
14
14
|
},
|
|
@@ -16,8 +16,7 @@
|
|
|
16
16
|
"./dist/timeline.css": "./dist/timeline.css"
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
|
-
"dist"
|
|
20
|
-
"src/index.d.ts"
|
|
19
|
+
"dist"
|
|
21
20
|
],
|
|
22
21
|
"scripts": {
|
|
23
22
|
"dev": "vite",
|
|
@@ -25,7 +24,6 @@
|
|
|
25
24
|
"build:demo": "vite build --config vite.config.demo.js",
|
|
26
25
|
"preview": "vite preview",
|
|
27
26
|
"test": "vitest run",
|
|
28
|
-
"prepublishOnly": "npm run build",
|
|
29
27
|
"release": "npm run build && npm publish"
|
|
30
28
|
},
|
|
31
29
|
"keywords": [
|
|
@@ -61,10 +59,11 @@
|
|
|
61
59
|
"devDependencies": {
|
|
62
60
|
"@testing-library/dom": "^10.4.1",
|
|
63
61
|
"jsdom": "^24.1.3",
|
|
62
|
+
"typescript": "^5.0.0",
|
|
63
|
+
"vite-plugin-dts": "^4.0.0",
|
|
64
|
+
"@types/node": "^20.0.0",
|
|
64
65
|
"vite": "^7.3.0",
|
|
65
66
|
"vitest": "^4.0.16"
|
|
66
67
|
},
|
|
67
|
-
"dependencies": {
|
|
68
|
-
"html-to-image": "^1.11.13"
|
|
69
|
-
}
|
|
68
|
+
"dependencies": {}
|
|
70
69
|
}
|
package/src/index.d.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
export interface TimelineVersion {
|
|
2
|
-
version: string;
|
|
3
|
-
ossStart: string;
|
|
4
|
-
ossEnd: string;
|
|
5
|
-
enterpriseEnd: string;
|
|
6
|
-
releaseNotesUrl?: string;
|
|
7
|
-
isMajor?: boolean;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface TimelineOptions {
|
|
11
|
-
/**
|
|
12
|
-
* Number of versions to show before "Show more" button appears.
|
|
13
|
-
* @default 3
|
|
14
|
-
*/
|
|
15
|
-
visibleCount?: number;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Preferred locale for translations ('en' or 'fr').
|
|
19
|
-
* Defaults to browser language.
|
|
20
|
-
*/
|
|
21
|
-
locale?: 'en' | 'fr' | string;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Custom translations to merge or override.
|
|
25
|
-
*/
|
|
26
|
-
i18n?: Record<string, Record<string, string>>;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Whether to show the data table between filter and timeline.
|
|
30
|
-
* @default true
|
|
31
|
-
*/
|
|
32
|
-
showTable?: boolean;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Whether to show the legend below the timeline.
|
|
36
|
-
* @default true
|
|
37
|
-
*/
|
|
38
|
-
showLegend?: boolean;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Whether to show the version filter input.
|
|
42
|
-
* @default true
|
|
43
|
-
*/
|
|
44
|
-
filterVersions?: boolean;
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Whether to show the enterprise bar normally (false) or split after OSS (true).
|
|
48
|
-
* @default false
|
|
49
|
-
*/
|
|
50
|
-
splitSupport?: boolean;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Whether to use compact mode (reduced height).
|
|
54
|
-
* @default false
|
|
55
|
-
*/
|
|
56
|
-
compactMode?: boolean;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Whether to show the major version filter checkbox.
|
|
60
|
-
* @default false
|
|
61
|
-
*/
|
|
62
|
-
showMajorFilter?: boolean;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export default class Timeline {
|
|
66
|
-
/**
|
|
67
|
-
* Creates a new Lifecycle Timeline.
|
|
68
|
-
* @param elementId The ID of the container element.
|
|
69
|
-
* @param data Array of version data.
|
|
70
|
-
* @param options Configuration options.
|
|
71
|
-
*/
|
|
72
|
-
constructor(elementId: string, data: TimelineVersion[], options?: TimelineOptions);
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Sets up the initial layout.
|
|
76
|
-
*/
|
|
77
|
-
setupBaseLayout(): void;
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Updates the timeline data and re-renders.
|
|
81
|
-
* @param newData Array of version data.
|
|
82
|
-
*/
|
|
83
|
-
updateData(newData: TimelineVersion[]): void;
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Renders the entire timeline.
|
|
87
|
-
*/
|
|
88
|
-
render(): void;
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Renders the toolbar (search/filter).
|
|
92
|
-
*/
|
|
93
|
-
renderToolbar(): void;
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Renders the theme toggle button.
|
|
97
|
-
*/
|
|
98
|
-
renderThemeToggle(): void;
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Updates the visibility of rows based on filtering and expansion state.
|
|
102
|
-
*/
|
|
103
|
-
updateVisibility(): void;
|
|
104
|
-
}
|