histropediajs 1.4.0 → 1.5.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/index.d.ts CHANGED
@@ -67,19 +67,22 @@ export interface CardLayoutIconBox extends CanvasPosition {
67
67
  // Date and precision
68
68
  // ------------------------------------------------------------------------------------
69
69
 
70
- /** Numeric precision constants (public). */
71
- export const PRECISION_DAY: 11;
72
- export const PRECISION_MONTH: 10;
73
- export const PRECISION_YEAR: 9;
74
- export const PRECISION_DECADE: 8;
75
- export const PRECISION_CENTURY: 7;
76
- export const PRECISION_MILLENNIUM: 6;
77
- export const PRECISION_MILLION_YEARS: 3;
78
- export const PRECISION_BILLION_YEARS: 1;
70
+ /** Date precision constants (public). */
71
+ export const PRECISION_DAY: 'day';
72
+ export const PRECISION_MONTH: 'month';
73
+ export const PRECISION_YEAR: 'year';
74
+ export const PRECISION_DECADE: 'decade';
75
+ export const PRECISION_CENTURY: 'century';
76
+ export const PRECISION_MILLENNIUM: 'millennium';
77
+ export const PRECISION_MILLION_YEARS: 'million-years';
78
+ export const PRECISION_BILLION_YEARS: 'billion-years';
79
+
80
+ /** @deprecated Use the equivalent string precision instead. */
81
+ export type LegacyPrecision = 11 | 10 | 9 | 8 | 7 | 6 | 3 | 1;
79
82
 
80
83
  /**
81
84
  * Date precision used by Article/TimeBand ranges.
82
- * Matches the numeric constants exported above.
85
+ * Legacy numeric precision values remain supported for backwards compatibility.
83
86
  */
84
87
  export type Precision =
85
88
  | typeof PRECISION_DAY
@@ -89,7 +92,8 @@ export type Precision =
89
92
  | typeof PRECISION_CENTURY
90
93
  | typeof PRECISION_MILLENNIUM
91
94
  | typeof PRECISION_MILLION_YEARS
92
- | typeof PRECISION_BILLION_YEARS;
95
+ | typeof PRECISION_BILLION_YEARS
96
+ | LegacyPrecision;
93
97
 
94
98
  /** Plain YMD date parts (no precision). */
95
99
  export type DateParts = {
@@ -161,19 +165,24 @@ export const Dmy: DmyConstructor;
161
165
  // Public constants (used in options)
162
166
  // ------------------------------------------------------------------------------------
163
167
 
164
- export const DENSITY_ALL: 0;
165
- export const DENSITY_LOW: 1;
166
- export const DENSITY_MEDIUM: 2;
167
- export const DENSITY_HIGH: 3;
168
+ export const DENSITY_ALL: 'all';
169
+ export const DENSITY_LOW: 'low';
170
+ export const DENSITY_MEDIUM: 'medium';
171
+ export const DENSITY_HIGH: 'high';
172
+ /** @deprecated Use the equivalent string density instead. */
173
+ export type LegacyDensity = 0 | 1 | 2 | 3;
168
174
  export type Density =
169
175
  | typeof DENSITY_ALL
170
176
  | typeof DENSITY_LOW
171
177
  | typeof DENSITY_MEDIUM
172
- | typeof DENSITY_HIGH;
178
+ | typeof DENSITY_HIGH
179
+ | LegacyDensity;
173
180
 
174
- export const RANGE_ALL: 0;
175
- export const RANGE_SCREEN: 1;
176
- export type AutoStackRange = typeof RANGE_ALL | typeof RANGE_SCREEN;
181
+ export const RANGE_ALL: 'all';
182
+ export const RANGE_SCREEN: 'screen';
183
+ /** @deprecated Use the equivalent string auto-stacking range instead. */
184
+ export type LegacyAutoStackRange = 0 | 1;
185
+ export type AutoStackRange = typeof RANGE_ALL | typeof RANGE_SCREEN | LegacyAutoStackRange;
177
186
 
178
187
  export const MINOR_MARKER: 0;
179
188
  export const MAJOR_MARKER: 1;
@@ -471,6 +480,139 @@ export interface TimeBandData {
471
480
  style?: TimeBandStyle;
472
481
  }
473
482
 
483
+ export type ChartType = 'line' | 'area';
484
+ export type ChartScaleSource = 'data' | 'viewport';
485
+ export type ChartScaleTickMode = 'round' | 'exact';
486
+ export type ChartAreaStackingInterpolation = 'linear' | 'step' | 'none';
487
+
488
+ export interface ChartPointData {
489
+ date: DateInput;
490
+ value: number | null;
491
+ }
492
+
493
+ export interface ChartSeriesStyle {
494
+ color?: string;
495
+ lineWidth?: number;
496
+ lineDash?: number[];
497
+ area?: {
498
+ fillColor?: string | null;
499
+ opacity?: number;
500
+ };
501
+ point?: {
502
+ visible?: boolean;
503
+ radius?: number;
504
+ fillColor?: string | null;
505
+ strokeColor?: string | null;
506
+ lineWidth?: number;
507
+ };
508
+ }
509
+
510
+ export interface ChartGridLineStyle {
511
+ visible?: boolean;
512
+ color?: string;
513
+ /** Stroke thickness in canvas pixels. */
514
+ thickness?: number;
515
+ }
516
+
517
+ export interface ChartMinorGridLineStyle extends ChartGridLineStyle {
518
+ /** Hide minor grid lines while the timeline minor unit size is below this many pixels. @defaultValue 40 */
519
+ minimumSpacing?: number;
520
+ }
521
+
522
+ export interface ChartGridLineOptions {
523
+ x?: {
524
+ major?: ChartGridLineStyle;
525
+ minor?: ChartMinorGridLineStyle;
526
+ };
527
+ y?: {
528
+ major?: ChartGridLineStyle;
529
+ };
530
+ }
531
+
532
+ export interface ChartStyle {
533
+ padding?: {
534
+ top?: number;
535
+ right?: number;
536
+ bottom?: number;
537
+ left?: number;
538
+ };
539
+ backgroundColor?: string;
540
+ gridLine?: ChartGridLineOptions;
541
+ axis?: {
542
+ visible?: boolean;
543
+ color?: string;
544
+ lineWidth?: number;
545
+ };
546
+ yAxis?: {
547
+ visible?: boolean;
548
+ font?: string;
549
+ color?: string;
550
+ margin?: number;
551
+ /** Thousands separator for numeric y-axis labels. Set to null or an empty string to disable. @defaultValue ',' */
552
+ thousandsSeparator?: string | null;
553
+ formatter?: ((value: number) => string) | null;
554
+ };
555
+ legend?: {
556
+ visible?: boolean | 'auto';
557
+ position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
558
+ font?: string;
559
+ color?: string;
560
+ markerSize?: number;
561
+ markerGap?: number;
562
+ itemGap?: number;
563
+ inset?: { x?: number; y?: number };
564
+ };
565
+ series?: ChartSeriesStyle;
566
+ }
567
+
568
+ export interface ChartScaleOptions {
569
+ /** Use all loaded values or only values inside the current viewport. @defaultValue 'data' */
570
+ source?: ChartScaleSource;
571
+ /** Include 0 in the computed domain before padding/fixed bounds. @defaultValue false */
572
+ includeZero?: boolean;
573
+ /** Fractional padding applied to auto domains. @defaultValue 0.05 */
574
+ padding?: number;
575
+ /** Fixed minimum y value. */
576
+ min?: number;
577
+ /** Fixed maximum y value. */
578
+ max?: number;
579
+ /** Controls how y-axis tick values are generated. @defaultValue 'round' */
580
+ tickMode?: ChartScaleTickMode;
581
+ /** Preferred number of y-axis ticks. Rounded ticks may vary slightly. @defaultValue 5 */
582
+ tickTarget?: number;
583
+ }
584
+
585
+ export interface ChartTypeOptions {
586
+ area?: {
587
+ stacking?: {
588
+ /** Enable stacked area rendering. When false, area series fill independently from zero. @defaultValue true */
589
+ active?: boolean;
590
+ /** How missing series values are resolved across the shared area x-domain. @defaultValue 'linear' */
591
+ interpolation?: ChartAreaStackingInterpolation;
592
+ };
593
+ };
594
+ }
595
+
596
+ export interface ChartSeriesData {
597
+ id?: string | number;
598
+ title?: string;
599
+ points?: ChartPointData[];
600
+ style?: ChartSeriesStyle;
601
+ }
602
+
603
+ export interface ChartData {
604
+ id: string | number;
605
+ type?: ChartType;
606
+ title?: string;
607
+ lane?: string | number;
608
+ visibility?: VisibilityState | ((chart: Chart) => VisibilityState);
609
+ series?: ChartSeriesData[];
610
+ scale?: ChartScaleOptions;
611
+ typeOptions?: ChartTypeOptions;
612
+ area?: { up?: AreaValue; down?: AreaValue };
613
+ style?: ChartStyle;
614
+ }
615
+
474
616
  export interface LaneLayout {
475
617
  height?: number;
476
618
  /**
@@ -652,6 +794,11 @@ export interface TimelinePanOptions {
652
794
  momentum?: PanMomentumOptions;
653
795
  }
654
796
 
797
+ export interface TimelineDebugOverlayOptions {
798
+ /** Draw vertical guides at article-density region boundaries. @defaultValue false */
799
+ densityRegions?: boolean;
800
+ }
801
+
655
802
  export interface ArticleOptions {
656
803
  /** Density filter for visible articles. @defaultValue DENSITY_ALL */
657
804
  density?: Density;
@@ -748,6 +895,21 @@ export interface TimeBandOptions {
748
895
  data?: TimeBandData[];
749
896
  }
750
897
 
898
+ export interface ChartOptions {
899
+ /** Enable drawing of loaded charts. @defaultValue true */
900
+ visible?: boolean;
901
+ /** Main-view chart area relative to the shared axis. Lane-scoped charts use lane body geometry. */
902
+ area?: { up?: AreaValue; down?: AreaValue };
903
+ /** Global chart grid-line defaults merged into each chart style. */
904
+ gridLine?: ChartGridLineOptions;
905
+ /** Default data merged into every loaded chart. */
906
+ defaultData?: Partial<ChartData>;
907
+ /** Global default chart style merged into each chart. */
908
+ defaultStyle?: ChartStyle;
909
+ /** Charts to load initially. */
910
+ data?: ChartData[];
911
+ }
912
+
751
913
  export interface LaneOptions {
752
914
  /**
753
915
  * Enable lane DOM chrome. Article layout still remains lane-aware when lane data is present.
@@ -846,6 +1008,20 @@ export interface ImageOptions {
846
1008
  decodeMode?: ImageDecodeMode;
847
1009
  }
848
1010
 
1011
+ export interface TimelineDateBoundsOptions {
1012
+ /** Earliest allowed visible viewport edge. @defaultValue null */
1013
+ minDate?: DateParts | null;
1014
+ /** Latest allowed visible viewport edge. @defaultValue null */
1015
+ maxDate?: DateParts | null;
1016
+ /**
1017
+ * Boundary behaviour during active user interaction.
1018
+ * - 'elastic': allow resisted temporary overflow and settle back when interaction ends.
1019
+ * - 'clamp': prevent overflow immediately.
1020
+ * @defaultValue 'elastic'
1021
+ */
1022
+ overflow?: 'elastic' | 'clamp';
1023
+ }
1024
+
849
1025
  export interface TimelineOptions {
850
1026
  /** Canvas width in px. @defaultValue 1000 */
851
1027
  width?: number;
@@ -865,6 +1041,8 @@ export interface TimelineOptions {
865
1041
  dprMode?: 'stable' | 'native';
866
1042
  /** Maximum DPR to apply for performance. @defaultValue 3 */ maxDpr?: number;
867
1043
  };
1044
+ /** Per-timeline visual diagnostics. Independent from global debug logging. */
1045
+ debugOverlays?: TimelineDebugOverlayOptions;
868
1046
  /** Vertical offset of the main line in px. @defaultValue 40 */
869
1047
  verticalOffset?: number;
870
1048
  /** Enable user interactions (wheel/drag/pinch). @defaultValue true */
@@ -875,6 +1053,11 @@ export interface TimelineOptions {
875
1053
  zoom?: TimelineZoomOptions;
876
1054
  /** Initial date (top-left when position not offset). @defaultValue {year:1990,month:1,day:1} */
877
1055
  initialDate?: DateParts;
1056
+ /**
1057
+ * Optional visible viewport date bounds. Bounds constrain viewport edges, not only the centre date.
1058
+ * With both dates set, the settled viewport stays within `[minDate, maxDate]`.
1059
+ */
1060
+ bounds?: TimelineDateBoundsOptions;
878
1061
  /** Shift BCE input dates by +1 so 1BCE = year 0 internally. @defaultValue false */
879
1062
  shiftBceDates?: boolean;
880
1063
  /** Hide the built-in Histropedia branding/footer links. Defaults to false when omitted. */
@@ -897,6 +1080,8 @@ export interface TimelineOptions {
897
1080
  style?: TimelineStyleOptions;
898
1081
  /** Time band configuration. */
899
1082
  timeBand?: TimeBandOptions;
1083
+ /** Chart layer configuration. */
1084
+ chart?: ChartOptions;
900
1085
  /** Lane configuration. */
901
1086
  lane?: LaneOptions;
902
1087
  /** Article configuration. */
@@ -1082,6 +1267,13 @@ export interface FitDateRangeOptions {
1082
1267
  animation?: FitDateRangeAnimationOptions;
1083
1268
  }
1084
1269
 
1270
+ export interface SetStartDateOptions {
1271
+ /** Left padding in px for the supplied start date. This only affects the left side. @defaultValue 0 */
1272
+ padding?: number;
1273
+ /** Optional animation settings matching `fitDateRange(..., { animation })`. */
1274
+ animation?: FitDateRangeAnimationOptions;
1275
+ }
1276
+
1085
1277
  export interface FitArticleRangeOptions {
1086
1278
  /** Edge padding in px, or per-side padding for asymmetric fits. @defaultValue 0 */
1087
1279
  padding?: FitDateRangePadding;
@@ -1119,6 +1311,7 @@ export class Timeline {
1119
1311
  readonly articles: Article[];
1120
1312
  readonly lanes: Lane[];
1121
1313
  readonly timeBands: TimeBand[];
1314
+ readonly charts: Chart[];
1122
1315
 
1123
1316
  /** Register a reusable card layout globally for all timelines. */
1124
1317
  static registerCardLayout(definition: CardLayoutDefinition): void;
@@ -1132,6 +1325,14 @@ export class Timeline {
1132
1325
  loadLanes(lanes: LaneData[]): void;
1133
1326
  /** Load time bands and redraw. */
1134
1327
  loadTimeBands(bands: TimeBandData[]): void;
1328
+ /** Load new charts and redraw; duplicate ids are skipped with a warning. */
1329
+ loadCharts(charts: ChartData[]): void;
1330
+ /** Remove a chart by id and redraw when found. */
1331
+ removeChart(id: string | number): boolean;
1332
+ /** Remove all loaded charts and redraw. */
1333
+ clearCharts(): void;
1334
+ /** Stamp a lane id onto a batch of charts, load them, and redraw. */
1335
+ loadLaneCharts(laneId: string | number, charts: ChartData[]): void;
1135
1336
  /** Stamp a lane id onto a batch of articles, load them, and redraw. */
1136
1337
  loadLaneArticles(laneId: string | number, articles: ArticleData[]): void;
1137
1338
 
@@ -1139,6 +1340,7 @@ export class Timeline {
1139
1340
  getArticleById(id: string | number): Article | undefined;
1140
1341
  getActiveArticle(): Article | null;
1141
1342
  getLaneById(id: string | number): Lane | undefined;
1343
+ getChartById(id: string | number): Chart | undefined;
1142
1344
  hasArticle(id: string | number): boolean;
1143
1345
 
1144
1346
  // Selection and ordering
@@ -1161,7 +1363,9 @@ export class Timeline {
1161
1363
  setTitle(title: string): void;
1162
1364
 
1163
1365
  // Navigation & view
1164
- /** Set start date (left edge). String input accepted in "-YYYY-MM-DD" style. */
1366
+ /** Set start date (left edge). Accepts Dmy-compatible objects or strings in "-YYYY-MM-DD" style. */
1367
+ setStartDate(date: Dmy | string, options?: SetStartDateOptions): void;
1368
+ /** @deprecated Use `setStartDate(date, { padding })` instead. */
1165
1369
  setStartDate(date: Dmy | string, pixelOffset?: number): void;
1166
1370
  /** Set centre date using startDate + offset computation. */
1167
1371
  setCentreDate(date: Dmy | string, pixelOffset?: number): void;
@@ -1171,7 +1375,7 @@ export class Timeline {
1171
1375
  setZoom(zoom: number, pivotPixel?: number, offsetX?: number): void;
1172
1376
  /** Smooth pan by pixels (negative = right). */
1173
1377
  goToPixelAnim(pixels: number, options?: AnimOptions): void;
1174
- /** Smoothly scroll so that the given date is centred/positioned. */
1378
+ /** @deprecated Use `setStartDate(dmy, { padding, animation: { active: true, ... } })` instead. */
1175
1379
  goToDateAnim(dmy: Dmy, options?: AnimOptions): void;
1176
1380
  /** Fit a date range into the viewport with optional edge padding. Dates may be passed in either order; year-only and month-only inputs are treated as full periods. */
1177
1381
  fitDateRange(
@@ -1336,6 +1540,55 @@ export class TimeBand {
1336
1540
  setStyle(path: string): unknown;
1337
1541
  }
1338
1542
 
1543
+ export class Chart {
1544
+ id: string | number;
1545
+ owner: Timeline;
1546
+ data: ChartData;
1547
+ type: ChartType;
1548
+ title: string;
1549
+ laneId: string | number | null;
1550
+ area: { up?: AreaValue; down?: AreaValue } | null;
1551
+ scale: ChartScaleOptions;
1552
+ typeOptions: ChartTypeOptions;
1553
+ style: ChartStyle;
1554
+ series: Array<{
1555
+ id: string | number;
1556
+ title: string;
1557
+ style: ChartSeriesStyle;
1558
+ points: Array<{ date: DmyInstance; value: number | null }>;
1559
+ }>;
1560
+ visibility: VisibilityState;
1561
+
1562
+ /** Add one series to this chart and redraw. */
1563
+ addSeries(series: ChartSeriesData): void;
1564
+
1565
+ /** Remove one series by id and redraw when found. */
1566
+ removeSeriesById(id: string | number): boolean;
1567
+
1568
+ /** Return the normalized runtime series with this id. */
1569
+ getSeriesById(id: string | number):
1570
+ | {
1571
+ id: string | number;
1572
+ title: string;
1573
+ style: ChartSeriesStyle;
1574
+ points: Array<{ date: DmyInstance; value: number | null }>;
1575
+ }
1576
+ | undefined;
1577
+
1578
+ /** Update chart data at runtime (dot-path or object). */
1579
+ setOption(path: string, value: unknown): void;
1580
+ setOption(patch: Partial<Omit<ChartData, 'id'>>): void;
1581
+ setOption(path: string): unknown;
1582
+
1583
+ /** Update chart style (dot-path or object). */
1584
+ setStyle(path: string, value: unknown): void;
1585
+ setStyle(style: Partial<ChartStyle>): void;
1586
+ setStyle(path: string): unknown;
1587
+
1588
+ /** Resolve the active y-domain for the chart. */
1589
+ getScaleDomain(drawCycleContext?: RedrawCycleContext): { min: number; max: number };
1590
+ }
1591
+
1339
1592
  export class Lane {
1340
1593
  id: string | number;
1341
1594
  owner: Timeline;
@@ -1400,6 +1653,7 @@ export const ARTICLE_POSITION_SORTER: ArticleSorter;
1400
1653
  export interface HistropediaApi {
1401
1654
  Timeline: typeof Timeline;
1402
1655
  Article: typeof Article;
1656
+ Chart: typeof Chart;
1403
1657
  Lane: typeof Lane;
1404
1658
  TimeBand: typeof TimeBand;
1405
1659
  Dmy: DmyConstructor;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "histropediajs",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "JavaScript library for rendering interactive zoomable timelines in HTML5 canvas.",
5
5
  "main": "./dist/histropedia.esm.js",
6
6
  "module": "./dist/histropedia.esm.js",