@mim/histui 0.2.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Histui
2
2
 
3
- Histui is a reusable, framework-agnostic interactive history timeline package. It can render PastStruct datasets or already-normalized records into a zoomable, pannable, responsive timeline with LOD, clustering, a zoom navigator, hover-linked connectors, blueprint-style measurement indicators, axis placement controls, themes, Persian/English UI strings, and explode mode.
3
+ Histui is a reusable, framework-agnostic interactive history timeline package. It can render PastStruct datasets or already-normalized records into a zoomable, pannable, responsive timeline with LOD, clustering, a zoom navigator, hover-linked connectors, blueprint-style measurement indicators, axis placement controls, themes, broadcast display mode, Persian/English UI strings, and explode mode.
4
4
 
5
5
  ## Files
6
6
 
@@ -30,6 +30,7 @@ const histui = createHistuiTimeline({
30
30
  data: pastStructDataset,
31
31
  language: "en",
32
32
  themeId: "obsidian-lab",
33
+ displayMode: "standard",
33
34
  explodeEnabled: false,
34
35
  onSelect(record) {
35
36
  console.log("selected", record.id);
@@ -90,6 +91,7 @@ Common options:
90
91
  - `language`: default `"en"`.
91
92
  - `direction`: optional text direction override.
92
93
  - `themeId` or `theme`: built-in theme id or custom theme object.
94
+ - `displayMode`: `"standard"` or `"broadcast"`. Broadcast mode increases legibility and uses overlay-friendly timeline styling.
93
95
  - `controls`: render built-in timeline controls. Default `true`.
94
96
  - `replace`: clear the container before mounting. Default `true`.
95
97
  - `filters`: initial filter object.
@@ -120,6 +122,8 @@ Common options:
120
122
  - `setExplodeEnabled(enabled)`
121
123
  - `setMeasurementOptions(options)`
122
124
  - `setMeasurementEnabled(enabled)`
125
+ - `setDisplayMode("standard" | "broadcast")`
126
+ - `setBroadcastMode(enabled)`
123
127
  - `setLanguage(language, direction)`
124
128
  - `setTheme(themeOrId)`
125
129
  - `getState()`
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.2.1",
6
+ "version": "0.3.3",
7
7
  "description": "Reusable Histui interactive timeline package for PastStruct and normalized historical records.",
8
8
  "type": "module",
9
9
  "main": "./src/index.js",
@@ -4,6 +4,7 @@ export const DEFAULT_HISTUI_CONFIG = {
4
4
  defaultLanguage: "en",
5
5
  languages: ["en", "fa"],
6
6
  defaultTheme: "obsidian-lab",
7
+ displayMode: "standard",
7
8
  orientation: "auto",
8
9
  axisPlacement: {
9
10
  horizontal: "center",
package/src/i18n.js CHANGED
@@ -29,6 +29,18 @@ export const UI_STRINGS = {
29
29
  uncertainOnly: "Uncertain dates",
30
30
  lod: "Adaptive detail",
31
31
  explode: "Explode",
32
+ broadcast: "Broadcast",
33
+ broadcastMode: "Broadcast Mode",
34
+ broadcastSettings: "Broadcast settings",
35
+ exitBroadcast: "Exit broadcast",
36
+ preset: "Preset",
37
+ background: "Background",
38
+ showDetails: "Show selected details",
39
+ restoreOnLoad: "Restore on load",
40
+ copyUrl: "Copy viewer URL",
41
+ copied: "Copied",
42
+ settings: "Settings",
43
+ close: "Close",
32
44
  resetFilters: "Reset",
33
45
  zoomIn: "Zoom in",
34
46
  zoomOut: "Zoom out",
@@ -113,6 +125,18 @@ export const UI_STRINGS = {
113
125
  uncertainOnly: "تاریخ نامطمئن",
114
126
  lod: "جزئیات تطبیقی",
115
127
  explode: "نمای انفجاری",
128
+ broadcast: "پخش",
129
+ broadcastMode: "حالت پخش",
130
+ broadcastSettings: "تنظیمات پخش",
131
+ exitBroadcast: "خروج از پخش",
132
+ preset: "پیش تنظیم",
133
+ background: "پس زمینه",
134
+ showDetails: "نمایش جزئیات انتخاب",
135
+ restoreOnLoad: "بازیابی هنگام بارگذاری",
136
+ copyUrl: "کپی نشانی نما",
137
+ copied: "کپی شد",
138
+ settings: "تنظیمات",
139
+ close: "بستن",
116
140
  resetFilters: "بازنشانی",
117
141
  zoomIn: "بزرگ نمایی",
118
142
  zoomOut: "کوچک نمایی",
package/src/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export type HistuiOrientation = "auto" | "horizontal" | "vertical";
2
2
  export type HistuiAxisPlacement = "center" | "side-start" | "side-end";
3
+ export type HistuiDisplayMode = "standard" | "broadcast";
3
4
 
4
5
  export interface HistuiTheme {
5
6
  id: string;
@@ -31,6 +32,7 @@ export interface HistuiConfig {
31
32
  defaultLanguage?: string;
32
33
  languages?: string[];
33
34
  defaultTheme?: string;
35
+ displayMode?: HistuiDisplayMode;
34
36
  orientation?: HistuiOrientation;
35
37
  axisPlacement?: {
36
38
  horizontal?: HistuiAxisPlacement;
@@ -83,6 +85,7 @@ export interface HistuiTimelineOptions<RecordType = any> {
83
85
  theme?: HistuiTheme;
84
86
  title?: string;
85
87
  description?: string;
88
+ displayMode?: HistuiDisplayMode;
86
89
  controls?: boolean;
87
90
  replace?: boolean;
88
91
  selectInitial?: boolean;
@@ -116,6 +119,7 @@ export interface HistuiState<RecordType = any> {
116
119
  language: string;
117
120
  direction: string;
118
121
  themeId: string;
122
+ displayMode: HistuiDisplayMode;
119
123
  orientation: HistuiOrientation;
120
124
  axisPlacement: {
121
125
  horizontal: HistuiAxisPlacement;
@@ -142,6 +146,8 @@ export class HistuiTimeline<RecordType = any> {
142
146
  setExplodeEnabled(enabled: boolean): this;
143
147
  setMeasurementOptions(options: HistuiMeasurementConfig): this;
144
148
  setMeasurementEnabled(enabled: boolean): this;
149
+ setDisplayMode(displayMode: HistuiDisplayMode): this;
150
+ setBroadcastMode(enabled: boolean): this;
145
151
  setLanguage(language: string, direction?: "ltr" | "rtl"): this;
146
152
  setTheme(themeOrId: string | HistuiTheme): this;
147
153
  applyTheme(theme: HistuiTheme): void;
package/src/index.js CHANGED
@@ -43,6 +43,7 @@ export class HistuiTimeline {
43
43
  this.direction = options.direction || dirForLanguage(this.language);
44
44
  this.t = options.translator || makeTranslator(this.language);
45
45
  this.themeId = options.themeId || this.config.app.defaultTheme;
46
+ this.displayMode = normalizeDisplayMode(options.displayMode || this.config.app.displayMode);
46
47
  this.orientation = options.orientation || this.config.app.orientation || "auto";
47
48
  this.axisPlacement = {
48
49
  horizontal: options.axisPlacement?.horizontal || this.config.app.axisPlacement?.horizontal || "center",
@@ -77,6 +78,7 @@ export class HistuiTimeline {
77
78
  this.root.className = "histui-timeline";
78
79
  this.root.lang = this.language;
79
80
  this.root.dir = this.direction;
81
+ this.applyDisplayMode(this.displayMode);
80
82
  this.root.innerHTML = `
81
83
  <section class="histui-timeline-workbench">
82
84
  <header class="histui-timeline-head" data-histui-head></header>
@@ -269,6 +271,27 @@ export class HistuiTimeline {
269
271
  return this;
270
272
  }
271
273
 
274
+ setDisplayMode(displayMode) {
275
+ const nextMode = normalizeDisplayMode(displayMode);
276
+ if (nextMode === this.displayMode) return this;
277
+ this.displayMode = nextMode;
278
+ this.applyDisplayMode(nextMode);
279
+ this.timeline.render();
280
+ this.track("timeline_setting_change", { setting: "display-mode", value: nextMode });
281
+ return this;
282
+ }
283
+
284
+ setBroadcastMode(enabled) {
285
+ return this.setDisplayMode(enabled ? "broadcast" : "standard");
286
+ }
287
+
288
+ applyDisplayMode(displayMode) {
289
+ if (!this.root) return;
290
+ const mode = normalizeDisplayMode(displayMode);
291
+ this.root.dataset.displayMode = mode;
292
+ this.root.classList.toggle("is-broadcast-mode", mode === "broadcast");
293
+ }
294
+
272
295
  applyTheme(theme) {
273
296
  applyTheme(theme, this.root);
274
297
  }
@@ -285,6 +308,7 @@ export class HistuiTimeline {
285
308
  language: this.language,
286
309
  direction: this.direction,
287
310
  themeId: this.themeId,
311
+ displayMode: this.displayMode,
288
312
  orientation: this.orientation,
289
313
  axisPlacement: { ...this.axisPlacement },
290
314
  lodEnabled: this.lodEnabled,
@@ -459,6 +483,10 @@ function resolveContainer(container) {
459
483
  return element;
460
484
  }
461
485
 
486
+ function normalizeDisplayMode(displayMode) {
487
+ return displayMode === "broadcast" ? "broadcast" : "standard";
488
+ }
489
+
462
490
  function mergeConfig(base, override) {
463
491
  if (Array.isArray(base) || Array.isArray(override)) return override ?? base;
464
492
  if (!isPlainObject(base) || !isPlainObject(override)) return override ?? base;
package/src/styles.css CHANGED
@@ -66,6 +66,22 @@
66
66
  grid-template-rows: minmax(0, 1fr) auto;
67
67
  }
68
68
 
69
+ .histui-timeline.is-broadcast-mode {
70
+ background: transparent;
71
+ }
72
+
73
+ .histui-timeline.is-broadcast-mode .histui-timeline-workbench {
74
+ background:
75
+ linear-gradient(90deg, color-mix(in srgb, var(--grid) 18%, transparent) 1px, transparent 1px),
76
+ linear-gradient(0deg, color-mix(in srgb, var(--grid) 14%, transparent) 1px, transparent 1px),
77
+ color-mix(in srgb, var(--background) 58%, transparent);
78
+ background-size: 52px 52px;
79
+ }
80
+
81
+ .histui-timeline.is-broadcast-mode.has-hidden-controls .histui-timeline-workbench {
82
+ grid-template-rows: minmax(0, 1fr) auto;
83
+ }
84
+
69
85
  .histui-timeline-head {
70
86
  display: flex;
71
87
  align-items: center;
@@ -451,6 +467,35 @@
451
467
  padding: 1px 5px;
452
468
  }
453
469
 
470
+ .histui-timeline.is-broadcast-mode .event-card {
471
+ width: 320px;
472
+ max-width: min(320px, calc(100vw - 42px));
473
+ max-height: 214px;
474
+ border-color: color-mix(in srgb, var(--record-color) 68%, var(--text));
475
+ background:
476
+ linear-gradient(180deg, color-mix(in srgb, var(--surface-raised) 88%, var(--record-color) 12%), color-mix(in srgb, var(--surface) 92%, transparent));
477
+ box-shadow:
478
+ 0 22px 52px color-mix(in srgb, var(--shadow) 92%, transparent),
479
+ 0 0 0 1px color-mix(in srgb, var(--record-color) 24%, transparent);
480
+ }
481
+
482
+ .histui-timeline.is-broadcast-mode .event-card.mode-short {
483
+ width: 246px;
484
+ max-height: 146px;
485
+ }
486
+
487
+ .histui-timeline.is-broadcast-mode .event-card.mode-icon {
488
+ width: 188px;
489
+ }
490
+
491
+ .histui-timeline.is-broadcast-mode .card-title {
492
+ font-size: 15px;
493
+ }
494
+
495
+ .histui-timeline.is-broadcast-mode .event-card p {
496
+ font-size: 13px;
497
+ }
498
+
454
499
  .card-date {
455
500
  display: block;
456
501
  margin-bottom: 6px;
@@ -1595,7 +1595,8 @@ export class TimelineView {
1595
1595
  }
1596
1596
 
1597
1597
  if (metrics.placement === "center") {
1598
- return clamp(this.direction === "rtl" ? metrics.width - offset : offset, 18, metrics.width - 18);
1598
+ const side = this.direction === "rtl" ? -1 : 1;
1599
+ return clamp(metrics.axisCoordinate + side * offset, 18, metrics.width - 18);
1599
1600
  }
1600
1601
 
1601
1602
  const side = metrics.axisCoordinate < metrics.width / 2 ? 1 : -1;