@sinequa/atomic-angular 1.16.0 → 2.0.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/README.md +23 -18
- package/components/navbar-tabs/i18n/de.json +4 -2
- package/components/navbar-tabs/i18n/en.json +4 -2
- package/components/navbar-tabs/i18n/fr.json +5 -3
- package/components/preview/i18n/de.json +12 -0
- package/components/preview/i18n/en.json +12 -0
- package/components/preview/i18n/fr.json +12 -0
- package/components/sort-selector/i18n/de.json +1 -0
- package/components/sort-selector/i18n/en.json +1 -0
- package/components/sort-selector/i18n/fr.json +1 -0
- package/components/sponsored-results/i18n/de.json +3 -0
- package/components/sponsored-results/i18n/en.json +3 -0
- package/components/sponsored-results/i18n/fr.json +3 -0
- package/document-workspaces/i18n/de.json +6 -2
- package/document-workspaces/i18n/en.json +6 -2
- package/document-workspaces/i18n/fr.json +6 -2
- package/document-workspaces/i18n/ja.json +6 -2
- package/features/{drawer → advanced-search}/i18n/de.json +12 -1
- package/features/{drawer → advanced-search}/i18n/en.json +12 -1
- package/features/{drawer → advanced-search}/i18n/fr.json +13 -2
- package/features/alerts/i18n/de.json +7 -1
- package/features/alerts/i18n/en.json +7 -1
- package/features/alerts/i18n/fr.json +7 -1
- package/features/auth/i18n/de.json +6 -0
- package/features/auth/i18n/en.json +6 -0
- package/features/auth/i18n/fr.json +6 -1
- package/features/collections/i18n/de.json +4 -1
- package/features/collections/i18n/en.json +4 -1
- package/features/collections/i18n/fr.json +4 -1
- package/features/dialogs/i18n/de.json +11 -1
- package/features/dialogs/i18n/en.json +11 -1
- package/features/dialogs/i18n/fr.json +11 -1
- package/features/export/i18n/de.json +5 -1
- package/features/export/i18n/en.json +5 -1
- package/features/export/i18n/fr.json +5 -1
- package/features/feedback/i18n/de.json +2 -1
- package/features/feedback/i18n/en.json +2 -1
- package/features/feedback/i18n/fr.json +2 -1
- package/features/filters/i18n/de.json +10 -3
- package/features/filters/i18n/en.json +10 -3
- package/features/filters/i18n/fr.json +11 -4
- package/features/labels/i18n/de.json +5 -1
- package/features/labels/i18n/en.json +5 -1
- package/features/labels/i18n/fr.json +5 -1
- package/features/list-panel/i18n/de.json +4 -0
- package/features/list-panel/i18n/en.json +4 -0
- package/features/list-panel/i18n/fr.json +4 -0
- package/features/searches/i18n/de.json +2 -1
- package/features/searches/i18n/en.json +2 -1
- package/features/searches/i18n/fr.json +3 -2
- package/features/sheet/i18n/de.json +3 -0
- package/features/sheet/i18n/en.json +3 -0
- package/features/sheet/i18n/fr.json +3 -0
- package/features/user-profile/i18n/de.json +22 -1
- package/features/user-profile/i18n/en.json +22 -1
- package/features/user-profile/i18n/fr.json +22 -1
- package/fesm2022/sinequa-atomic-angular-charts-heatmap.mjs +294 -0
- package/fesm2022/sinequa-atomic-angular-charts-heatmap.mjs.map +1 -0
- package/fesm2022/sinequa-atomic-angular-charts.mjs +969 -0
- package/fesm2022/sinequa-atomic-angular-charts.mjs.map +1 -0
- package/fesm2022/sinequa-atomic-angular-document-workspaces.mjs +11188 -7846
- package/fesm2022/sinequa-atomic-angular-document-workspaces.mjs.map +1 -1
- package/fesm2022/sinequa-atomic-angular-workspace-elements.mjs +85 -152
- package/fesm2022/sinequa-atomic-angular-workspace-elements.mjs.map +1 -1
- package/fesm2022/sinequa-atomic-angular.mjs +30683 -17302
- package/fesm2022/sinequa-atomic-angular.mjs.map +1 -1
- package/package.json +60 -23
- package/styles/calendar.css +88 -0
- package/types/sinequa-atomic-angular-charts-heatmap.d.ts +154 -0
- package/types/sinequa-atomic-angular-charts.d.ts +462 -0
- package/types/sinequa-atomic-angular-document-workspaces.d.ts +2527 -0
- package/types/sinequa-atomic-angular-workspace-elements.d.ts +49 -0
- package/types/sinequa-atomic-angular.d.ts +19918 -0
- package/workspace-elements/styles/lexiq-workspaces.css +7310 -4010
- package/document-workspaces/index.d.ts +0 -2116
- package/elements/index.d.ts +0 -346
- package/fesm2022/sinequa-atomic-angular-elements.mjs +0 -7526
- package/fesm2022/sinequa-atomic-angular-elements.mjs.map +0 -1
- package/index.d.ts +0 -16119
- package/workspace-elements/index.d.ts +0 -37
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sinequa-atomic-angular-charts.mjs","names":[],"sources":["../../../projects/atomic-angular/charts/core/chart-setup.ts","../../../projects/atomic-angular/charts/core/chart-theme.ts","../../../projects/atomic-angular/charts/core/chart-canvas.ts","../../../projects/atomic-angular/charts/core/timeline-brush.plugin.ts","../../../projects/atomic-angular/charts/core/axis-click.plugin.ts","../../../projects/atomic-angular/charts/data/timeline-data.ts","../../../projects/atomic-angular/charts/aggregation-chart.ts","../../../projects/atomic-angular/charts/aggregation-timeline.ts"],"sourcesContent":["import { Chart, registerables } from \"chart.js\";\n\nimport { galactikSemantic } from \"@sinequa/atomic-angular\";\n\nlet registered = false;\n\n/**\n * Registers the Chart.js controllers, scales and elements the charts need.\n *\n * Chart.js 4 ships nothing by default. This is idempotent on purpose: it is called from the\n * constructor of every `<ChartCanvas>`, so it must be safe to call many times. Registering from a\n * component rather than from application bootstrap keeps the entry point self-contained — an\n * application that never imports `@sinequa/atomic-angular/charts` never runs this, and never needs\n * `chart.js` installed.\n */\nexport function setupCharts(): void {\n if (registered) return;\n Chart.register(...registerables);\n registered = true;\n}\n\n/**\n * Applies theme-dependent defaults: axis and legend text colour, and grid line colour.\n *\n * These read *semantic* galactik tokens, not primitive ramps — semantic tokens are exactly the ones\n * `galactik-tokens-dark.css` reassigns under `:root.dark`, so the chart chrome follows the theme\n * while series colours (built from primitives) keep their identity.\n *\n * Chart.js reads `Chart.defaults` when an instance is CONSTRUCTED, never afterwards. Calling\n * `chart.update()` after a theme switch therefore leaves the axes in the previous colour — the\n * instance has to be destroyed and rebuilt. `<ChartCanvas>` does exactly that.\n */\nexport function applyChartTheme(): void {\n Chart.defaults.color = galactikSemantic(\"font-neutral-muted\");\n Chart.defaults.borderColor = galactikSemantic(\"stroke-neutral-muted\");\n}\n","import { DestroyRef, inject, Service, signal, type Signal } from \"@angular/core\";\n\n/**\n * Dark mode, exposed as a signal.\n *\n * galactik switches theme through a `dark` class on the document root (`:root.dark`), so this\n * observes the DOM rather than depending on a particular store. That keeps the charts usable in any\n * host application, whatever drives its theme.\n *\n * A canvas cannot react to a CSS class on its own: `<ChartCanvas>` reads this signal and rebuilds\n * its Chart.js instance when it flips. See `applyChartTheme`.\n */\n@Service()\nexport class ChartThemeService {\n private readonly dark = signal(hasDarkClass());\n\n /** `true` when the document root carries the `dark` class. Updates on its own. */\n readonly isDark: Signal<boolean> = this.dark.asReadonly();\n\n constructor() {\n // MutationObserver fires outside Angular, which is fine in a zoneless application: writing to a\n // signal is what schedules the update, not a zone.\n const observer = new MutationObserver(() => this.dark.set(hasDarkClass()));\n observer.observe(document.documentElement, { attributes: true, attributeFilter: [\"class\"] });\n inject(DestroyRef).onDestroy(() => observer.disconnect());\n }\n}\n\nfunction hasDarkClass(): boolean {\n return document.documentElement.classList.contains(\"dark\");\n}\n","import { afterNextRender, Component, DestroyRef, effect, ElementRef, inject, input, viewChild, type InputSignal } from \"@angular/core\";\nimport { Chart, type ChartConfiguration, type Plugin } from \"chart.js\";\n\nimport { cn } from \"cn\";\n\nimport { applyChartTheme, setupCharts } from \"./chart-setup\";\nimport { ChartThemeService } from \"./chart-theme\";\n\n/**\n * The Chart.js canvas, and the whole of its lifecycle.\n *\n * Every chart in this entry point is built on this one component. Chart.js has no Angular binding,\n * so the integration work is entirely the canvas lifecycle — and that is where every bug lives.\n * Four rules, all of them enforced here so no caller has to think about them:\n *\n * 1. **Create after the first render.** A canvas created during construction has no layout and\n * Chart.js measures it as 0x0. `afterNextRender` is the zoneless-safe hook.\n * 2. **Always destroy.** Chart.js attaches a `ResizeObserver` and global listeners; leaking an\n * instance leaks both.\n * 3. **Rebuild when `type` changes.** Chart.js cannot swap controller on a live instance.\n * 4. **Rebuild when the theme changes.** `Chart.defaults` is read at construction time only, so\n * `update()` would leave the axes in the previous colour.\n *\n * Rules 3 and 4 are why this component owns an `effect()` — the only one in the entry point.\n * Everything else is `computed()`.\n *\n * Named `ChartCanvas` rather than `Chart` deliberately: this file imports `Chart` from `chart.js`.\n *\n * **The host must have a resolved height.** The canvas fills its host and Chart.js sizes itself from\n * the canvas' parent box, so put it in a container with a height (`class=\"h-80\"`). A blank chart is\n * nearly always this.\n */\n@Component({\n selector: \"ChartCanvas, chart-canvas, chartcanvas\",\n template: `<canvas #canvas class=\"block size-full\"></canvas>`,\n host: {\n \"[class]\": 'cn(\"block h-full w-full\", class())'\n }\n})\nexport class ChartCanvasComponent {\n cn = cn;\n\n /**\n * Extra classes for the host element.\n * @default \"\"\n */\n readonly class = input(\"\");\n\n /**\n * The Chart.js configuration. Rebuilt automatically when its `type` changes.\n *\n * Explicitly annotated, like `plugins` below, and for a second reason on top of portability: an\n * inferred type is emitted into the .d.ts with the default type arguments already expanded, which\n * freezes the union of known chart types at the moment THIS entry point was compiled. A caller in\n * another entry point that augments `chart.js` — `/charts/heatmap` registers the `matrix`\n * controller — would then be handing over a `ChartConfiguration` that no longer matches. Keeping\n * the annotation keeps the name in the .d.ts, so it re-resolves in the caller's own context.\n */\n readonly config: InputSignal<ChartConfiguration> = input.required<ChartConfiguration>();\n\n /**\n * Local plugins, kept separate from `config.plugins` for readability. Build them once, outside any\n * `computed()`: a plugin holding drag state would lose it on every recompute.\n * @default []\n */\n // Explicitly annotated: the library emits .d.ts, and the inferred type would have to name\n // an internal chart.js type (`AnyObject`) by path, which is not portable.\n readonly plugins: InputSignal<Plugin[]> = input<Plugin[]>([]);\n\n private readonly canvas = viewChild.required<ElementRef<HTMLCanvasElement>>(\"canvas\");\n private readonly destroyRef = inject(DestroyRef);\n private readonly theme = inject(ChartThemeService);\n\n private chart?: Chart;\n private currentType?: ChartConfiguration[\"type\"];\n private currentDark?: boolean;\n\n constructor() {\n setupCharts();\n\n afterNextRender(() => {\n const dark = this.theme.isDark();\n applyChartTheme();\n this.chart = new Chart(this.canvas().nativeElement, this.withDefaults(this.config(), this.plugins()));\n this.currentType = this.config().type;\n this.currentDark = dark;\n });\n\n effect(() => {\n const config = this.config();\n const dark = this.theme.isDark();\n if (!this.chart) return; // first render has not happened yet; afterNextRender will build it\n\n if (this.currentType !== config.type || this.currentDark !== dark) {\n applyChartTheme();\n this.chart.destroy();\n this.chart = new Chart(this.canvas().nativeElement, this.withDefaults(config, this.plugins()));\n this.currentType = config.type;\n this.currentDark = dark;\n return;\n }\n\n // Same type, same theme: a cheap in-place update is enough.\n this.chart.data = config.data;\n this.chart.options = { ...this.chart.options, ...(config.options ?? {}) };\n this.chart.update();\n });\n\n this.destroyRef.onDestroy(() => this.chart?.destroy());\n }\n\n /**\n * `responsive` and `maintainAspectRatio: false` are forced here: together they make the chart\n * follow its container instead of a fixed 2:1 ratio, and no caller should have to remember them.\n */\n private withDefaults(config: ChartConfiguration, plugins: Plugin[]): ChartConfiguration {\n return {\n ...config,\n plugins: [...(config.plugins ?? []), ...plugins],\n options: {\n responsive: true,\n maintainAspectRatio: false,\n ...(config.options ?? {})\n }\n };\n }\n}\n","// Range selection (\"brush\") for the timeline, as a plain Chart.js plugin.\n//\n// This replaces d3.brushX. It is ~60 lines and needs no dependency: Chart.js exposes the canvas\n// context in `afterDraw` and raw pointer events in `afterEvent`, which is everything a brush needs.\n//\n// TWO NON-OBVIOUS RULES, both of which fail silently if you get them wrong:\n//\n// 1. The chart MUST declare `options.events` explicitly and include \"mousedown\"/\"mouseup\".\n// Chart.js' default event list is [\"mousemove\", \"mouseout\", \"click\", \"touchstart\", \"touchmove\"],\n// so without this the plugin never sees a drag begin or end. No error, just an inert brush.\n// See aggregation-timeline.ts.\n//\n// 2. `createTimelineBrushPlugin()` must be called ONCE and the result kept (a class field).\n// Building it inside a `computed()` would hand Chart.js a brand new object on every recompute,\n// resetting `startX`/`currentX` mid-drag.\n\nimport type { Chart, Plugin } from \"chart.js\";\n\nimport { galactikPrimitive, withAlpha } from \"@sinequa/atomic-angular\";\n\nconst clamp = (value: number, min: number, max: number): number => Math.min(Math.max(value, min), max);\n\n/** Ignore drags shorter than this, so a plain click does not select a one-bucket range. */\nconst MIN_DRAG_PX = 4;\n\n/**\n * Creates the brush plugin.\n *\n * @param onSelect called on mouse release with the first and last category LABELS covered by the\n * drag. Labels (not pixels, not dates) because the timeline uses a `category` axis:\n * what the caller gets back is exactly what it put into `data.labels`.\n */\nexport function createTimelineBrushPlugin(onSelect: (from: string, to: string) => void): Plugin {\n let startX: number | null = null;\n let currentX: number | null = null;\n\n return {\n id: \"timeline-brush\",\n\n afterEvent(chart: Chart, args) {\n const event = args.event;\n const area = chart.chartArea;\n const x = event.x ?? 0;\n\n switch (event.type) {\n case \"mousedown\":\n if (x >= area.left && x <= area.right) {\n startX = x;\n currentX = x;\n }\n break;\n\n case \"mousemove\":\n if (startX !== null) {\n currentX = clamp(x, area.left, area.right);\n // Tells Chart.js the plugin changed something and a redraw is needed -- this is what\n // makes the selection rectangle follow the cursor.\n args.changed = true;\n }\n break;\n\n case \"mouseup\":\n case \"mouseout\":\n if (startX !== null && currentX !== null && Math.abs(currentX - startX) > MIN_DRAG_PX) {\n // `chart.scales[\"x\"]`, not `chart.scales.x`: Mint compiles with\n // `noPropertyAccessFromIndexSignature`, and `scales` is a Record.\n const xScale = chart.scales[\"x\"];\n const labels = (chart.data.labels as string[] | undefined) ?? [];\n if (xScale && labels.length > 0) {\n const i1 = clamp(Math.round(xScale.getValueForPixel(Math.min(startX, currentX)) ?? 0), 0, labels.length - 1);\n const i2 = clamp(Math.round(xScale.getValueForPixel(Math.max(startX, currentX)) ?? 0), 0, labels.length - 1);\n const from = labels[i1];\n const to = labels[i2];\n if (from != null && to != null) onSelect(String(from), String(to));\n }\n }\n startX = null;\n currentX = null;\n args.changed = true;\n break;\n\n default:\n break;\n }\n },\n\n afterDraw(chart: Chart) {\n if (startX === null || currentX === null) return;\n const { ctx, chartArea: area } = chart;\n const left = Math.min(startX, currentX);\n const right = Math.max(startX, currentX);\n ctx.save();\n // Galactik blue, the same primitive ramp the primary timeline series uses.\n ctx.fillStyle = withAlpha(galactikPrimitive(\"blue-500\"), 0.15);\n ctx.strokeStyle = withAlpha(galactikPrimitive(\"blue-500\"), 0.5);\n ctx.fillRect(left, area.top, right - left, area.bottom - area.top);\n ctx.strokeRect(left, area.top, right - left, area.bottom - area.top);\n ctx.restore();\n }\n };\n}\n","import type { Chart, Plugin, Scale } from \"chart.js\";\n\n/** A click on an axis label: which axis, which category index, and the label as it was drawn. */\nexport interface AxisLabelHit {\n readonly axis: \"x\" | \"y\";\n /** Index of the category on that axis, i.e. its position in the scale's labels. */\n readonly index: number;\n readonly label: string;\n}\n\n/**\n * Makes axis labels clickable — SBA v2's `axisClicked`, on a canvas.\n *\n * On a DOM chart (`<Heatmap>`) an axis label is a `<button>` and this is free. On a canvas it is\n * painted pixels, so the hit test has to be written. Three things make it work, and each of them is\n * a failure mode of the naive version:\n *\n * 1. **`options.onClick` cannot do this.** Chart.js only calls it when the pointer is inside\n * `chartArea` (`Chart#_handleEvent`), and axis labels are outside it by construction. A\n * plugin's `afterEvent` sees every event on the canvas, in or out of the area.\n * 2. **No `options.events` change is needed**, unlike the timeline brush: `click`, `mousemove`\n * and `mouseout` are already in the Chart.js default list — only `mousedown`/`mouseup` are not.\n * 3. **Hit-test the scale's own box** (`scale.left/top/right/bottom`), not a band derived from\n * `chartArea`. It is exactly the strip Chart.js reserved for that axis, the two axis boxes\n * never overlap, and the corner between them — which belongs to neither — is excluded for free.\n *\n * Generic: any chart with a category axis can use it, not just the heatmap.\n *\n * @param onSelect called on a click over an axis label.\n * @param axes which axes react. Defaults to both.\n */\nexport function createAxisClickPlugin(onSelect: (hit: AxisLabelHit) => void, axes: ReadonlyArray<\"x\" | \"y\"> = [\"x\", \"y\"]): Plugin {\n // Remembered so the cursor is written only when it changes: `afterEvent` fires on every mousemove,\n // and assigning `style.cursor` on each one is a needless style recalculation.\n let hovering = false;\n\n const setCursor = (chart: Chart, hover: boolean): void => {\n if (hover === hovering) return;\n hovering = hover;\n // \"\" restores the stylesheet value rather than forcing \"default\": nothing else competes for the\n // cursor, Chart.js does not manage it.\n chart.canvas.style.cursor = hover ? \"pointer\" : \"\";\n };\n\n return {\n id: \"axis-click\",\n\n afterEvent(chart, args) {\n const event = args.event;\n const x = event.x ?? 0;\n const y = event.y ?? 0;\n\n switch (event.type) {\n case \"click\": {\n const hit = hitTest(chart, axes, x, y);\n if (hit) onSelect(hit);\n break;\n }\n\n case \"mousemove\":\n setCursor(chart, hitTest(chart, axes, x, y) !== null);\n break;\n\n case \"mouseout\":\n setCursor(chart, false);\n break;\n\n default:\n break;\n }\n },\n\n // The canvas outlives `chart.destroy()` — `<ChartCanvas>` owns it and rebuilds an instance on a\n // theme or type change — so a \"pointer\" left behind would strand on the next chart.\n afterDestroy(chart) {\n if (hovering) {\n hovering = false;\n chart.canvas.style.cursor = \"\";\n }\n }\n };\n}\n\nfunction hitTest(chart: Chart, axes: ReadonlyArray<\"x\" | \"y\">, x: number, y: number): AxisLabelHit | null {\n for (const axis of axes) {\n const scale = chart.scales[axis];\n if (!scale || !isInsideScaleBox(scale, x, y)) continue;\n\n const tick = nearestTick(scale, scale.isHorizontal() ? x : y);\n if (tick) return { axis, index: tick.index, label: tick.label };\n }\n return null;\n}\n\nfunction isInsideScaleBox(scale: Scale, x: number, y: number): boolean {\n return x >= scale.left && x <= scale.right && y >= scale.top && y <= scale.bottom;\n}\n\n/**\n * Finds the tick whose drawn position is closest to the click.\n *\n * `getPixelForTick()` rather than `getValueForPixel()`: the latter assumes uniform spacing from the\n * scale bounds, which stops holding as soon as `offset` (every heatmap axis) or `autoSkip` is\n * involved. Walking the ticks that were actually drawn is exact in every case, and an axis holds a\n * few dozen of them — the loop is free.\n */\nfunction nearestTick(scale: Scale, position: number): { index: number; label: string } | null {\n const ticks = scale.ticks;\n if (ticks.length === 0) return null;\n\n let best = 0;\n let bestDistance = Number.POSITIVE_INFINITY;\n for (let i = 0; i < ticks.length; i++) {\n const distance = Math.abs(scale.getPixelForTick(i) - position);\n if (distance < bestDistance) {\n bestDistance = distance;\n best = i;\n }\n }\n\n // Reject a click that landed nowhere near a label. Without this, clicking the empty margin at the\n // end of a short axis would filter on whichever category happens to be last — the kind of silent\n // mis-click that gets reported as \"the heatmap filters on the wrong value\".\n const span = scale.isHorizontal() ? scale.width : scale.height;\n if (bestDistance > span / ticks.length / 2 + 2) return null;\n\n // `tick.value`, not `best`: on a category scale the value IS the category index, and the two only\n // coincide while `autoSkip` is off. Reporting the category index keeps the caller independent of\n // how many ticks Chart.js decided to draw.\n const value = ticks[best]?.value ?? best;\n return { index: value, label: scale.getLabelForValue(value) };\n}\n","// Everything the timeline knows about TIME, as pure functions.\n//\n// Everything the timeline needs to know about TIME lives here, as pure functions.\n//\n// This is the single most important design decision of the timeline example. In SBA v2 the same\n// logic was spread across the 811 lines of sq-timeline, entangled with d3 scales and SVG. Pulling\n// it out has two consequences worth stating plainly:\n//\n// - the component becomes trivial (build a config, hand it to <chart>);\n// - the hard part -- bucket parsing, gap filling, resolution picking -- becomes testable without\n// a DOM, a canvas, or a Sinequa server.\n//\n// It is also what makes a `category` axis sufficient. Chart.js can do a real `time` axis, but only\n// with a date adapter (chartjs-adapter-date-fns), which Mint does not ship. Rather than add a\n// dependency, we resolve the time axis HERE and hand Chart.js a list of ready-made string labels.\n// The chart never sees a Date.\n//\n// WARNING: setting scales.x.type = \"time\" without an adapter compiles perfectly and then fails at\n// runtime with \"This method is not implemented: Check that a complete date adapter is provided\".\n// The compiler cannot help you with that one.\n\nimport type { AggregationItemLike, AggregationLike } from \"@sinequa/atomic-angular\";\n\n/**\n * The date masks Sinequa uses for time aggregations. The mask is configured server-side on the\n * aggregation and tells you the width of one bucket.\n */\nexport type TimelineMask = \"YYYY\" | \"YYYY-MM\" | \"YYYY-WW\" | \"YYYY-MM-DD\" | \"YYYY-MM-DD-hh\" | \"YYYY-MM-DD-hh-mm\";\n\ntype BucketUnit = \"minute\" | \"hour\" | \"day\" | \"week\" | \"month\" | \"year\";\n\n/** Bucket width implied by each Sinequa mask. */\nconst MASK_UNIT: Record<TimelineMask, BucketUnit> = {\n \"YYYY-MM-DD-hh-mm\": \"minute\",\n \"YYYY-MM-DD-hh\": \"hour\",\n \"YYYY-MM-DD\": \"day\",\n \"YYYY-WW\": \"week\",\n \"YYYY-MM\": \"month\",\n YYYY: \"year\"\n};\n\n/** One input series, before the shared axis is built. */\nexport interface TimelineSeriesInput {\n readonly label: string;\n /** Only primary series determine the extent of the axis; secondary ones are just plotted on it. */\n readonly primary?: boolean;\n /** Aggregation whose items are date buckets: `value` is the bucket key, `count` the measure. */\n readonly aggregation: AggregationLike | undefined;\n /** Read this operator result instead of `count` (e.g. \"avg\" for a response-time curve). */\n readonly weightField?: string;\n}\n\n/** One output series, aligned on the shared axis: `values[i]` belongs to `labels[i]`. */\nexport interface TimelineSeries {\n readonly label: string;\n readonly primary: boolean;\n readonly values: Array<number | null>;\n}\n\nexport interface TimelineData {\n readonly labels: string[];\n readonly series: TimelineSeries[];\n}\n\nexport interface TimelineOptions {\n /** Bucket width. Without it, no gap filling happens: the axis is just the keys that exist. */\n readonly mask?: TimelineMask;\n /** Safety valve for generated buckets. A one-minute mask over a year would produce ~525 600. */\n readonly maxBuckets?: number;\n}\n\n/**\n * Builds a shared category axis and aligns every series onto it.\n *\n * The gap filling is the point. Without it, three days with no activity are not drawn as a flat\n * line at zero -- they simply do not exist, and the line jumps straight from one populated day to\n * the next, silently misrepresenting the data. SBA v2 did this in createDatapoints(); the comment\n * there drew it as:\n *\n * aggregation: [ # # # # # # # # # # # ]\n * series: [ 0 # # 0 0 # # # 0 # 0 0 # # 0 0 # # # 0 ]\n */\nexport function buildTimeline(inputs: readonly TimelineSeriesInput[], options: TimelineOptions = {}): TimelineData {\n const parsed = inputs.map(input => ({\n label: input.label,\n primary: input.primary ?? false,\n points: toPointMap(input.aggregation, input.weightField)\n }));\n\n const axis = buildAxis(parsed, options);\n\n const series: TimelineSeries[] = parsed.map(entry => {\n // The range this series actually reported on. Everything inside it is real data — a bucket with\n // no events genuinely means zero. Everything outside it is absence of coverage.\n const range = timestampRange(entry.points);\n\n return {\n label: entry.label,\n primary: entry.primary,\n values: axis.timestamps.map(ts => {\n const value = entry.points.get(ts);\n if (value !== undefined) return value;\n // Inside the series' own range: the bucket exists and carried no events. Zero, drawn flat —\n // this is the whole point of building a complete axis.\n if (range && ts >= range.first && ts <= range.last) return 0;\n // Outside it: this series does not cover that period at all. null, bridged by `spanGaps`,\n // rather than a misleading drop to zero.\n return null;\n })\n };\n });\n\n return { labels: axis.labels, series };\n}\n\ninterface Axis {\n readonly labels: string[];\n readonly timestamps: number[];\n}\n\ninterface ParsedSeries {\n readonly label: string;\n readonly primary: boolean;\n readonly points: Map<number, number>;\n}\n\n/**\n * Builds the complete axis: every bucket between the first and the last, at the mask's step,\n * including the empty ones.\n */\nfunction buildAxis(series: readonly ParsedSeries[], options: TimelineOptions): Axis {\n // Only primary series set the extent, when any is marked primary.\n const extentSources = series.some(s => s.primary) ? series.filter(s => s.primary) : series;\n\n const tsToKey = new Map<number, string>();\n for (const entry of extentSources) {\n for (const ts of entry.points.keys()) {\n if (!tsToKey.has(ts)) tsToKey.set(ts, formatFallback(ts));\n }\n }\n // Secondary series still contribute their labels where they overlap.\n for (const entry of series) {\n for (const ts of entry.points.keys()) {\n if (!tsToKey.has(ts) && extentSources === series) tsToKey.set(ts, formatFallback(ts));\n }\n }\n\n const sorted = [...tsToKey.keys()].sort((a, b) => a - b);\n const unit = options.mask ? MASK_UNIT[options.mask] : undefined;\n\n // No mask, or too few points to interpolate: use the keys as they are.\n if (!unit || sorted.length < 2) {\n return { labels: sorted.map(ts => formatKey(ts, options.mask)), timestamps: sorted };\n }\n\n const maxBuckets = options.maxBuckets ?? 5000;\n const last = sorted[sorted.length - 1] ?? 0;\n const labels: string[] = [];\n const timestamps: number[] = [];\n\n let cursor = new Date(sorted[0] ?? 0);\n for (let i = 0; i < maxBuckets && cursor.getTime() <= last; i++) {\n const ts = cursor.getTime();\n timestamps.push(ts);\n labels.push(formatKey(ts, options.mask));\n cursor = stepDate(cursor, unit);\n }\n\n return { labels, timestamps };\n}\n\n/** First and last timestamp a series reported, or `undefined` when it reported nothing. */\nfunction timestampRange(points: Map<number, number>): { first: number; last: number } | undefined {\n let first: number | undefined;\n let last: number | undefined;\n // A loop rather than Math.min(...keys): a long time series would blow the argument limit.\n for (const ts of points.keys()) {\n if (first === undefined || ts < first) first = ts;\n if (last === undefined || ts > last) last = ts;\n }\n return first === undefined || last === undefined ? undefined : { first, last };\n}\n\nfunction toPointMap(aggregation: AggregationLike | undefined, weightField?: string): Map<number, number> {\n const points = new Map<number, number>();\n if (!aggregation) return points;\n\n for (const item of aggregation.items) {\n const date = parseBucketDate(String(item.value ?? \"\"));\n if (!date) continue;\n points.set(date.getTime(), readValue(item, weightField));\n }\n return points;\n}\n\nfunction readValue(item: AggregationItemLike, weightField?: string): number {\n if (weightField) {\n const raw = item.operatorResults?.[weightField];\n if (raw instanceof Date) return raw.getTime();\n return Number(raw ?? 0);\n }\n return Number(item.count ?? 0);\n}\n\n/**\n * Parses a Sinequa bucket key: \"2026\", \"2026-01\", \"2026-01-13\", \"2026-01-13 14:00:00\", ...\n *\n * Everything is read in LOCAL time, including date-only keys. This is deliberate: `new Date(\"2026-01-13\")`\n * is parsed as UTC by the specification, while `new Date(2026, 0, 13)` is local. Mixing the two puts\n * the generated buckets half a day out of step with the parsed ones near a DST boundary.\n */\nexport function parseBucketDate(key: string): Date | null {\n const s = key.trim();\n if (s.length === 0) return null;\n\n if (/^\\d{4}$/.test(s)) return new Date(Number(s), 0, 1);\n\n const ym = /^(\\d{4})-(\\d{2})$/.exec(s);\n if (ym) return new Date(Number(ym[1]), Number(ym[2]) - 1, 1);\n\n const ymd = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(s);\n if (ymd) return new Date(Number(ymd[1]), Number(ymd[2]) - 1, Number(ymd[3]));\n\n const parsed = new Date(s.replace(\" \", \"T\"));\n return Number.isNaN(parsed.getTime()) ? null : parsed;\n}\n\n/** Advances one bucket. Calendar-aware for month and year, so February keeps its own length. */\nfunction stepDate(date: Date, unit: BucketUnit): Date {\n const d = new Date(date.getTime());\n switch (unit) {\n case \"minute\":\n d.setMinutes(d.getMinutes() + 1);\n break;\n case \"hour\":\n d.setHours(d.getHours() + 1);\n break;\n case \"day\":\n d.setDate(d.getDate() + 1);\n break;\n case \"week\":\n d.setDate(d.getDate() + 7);\n break;\n case \"month\":\n d.setMonth(d.getMonth() + 1);\n break;\n case \"year\":\n d.setFullYear(d.getFullYear() + 1);\n break;\n default:\n break;\n }\n return d;\n}\n\nconst pad = (n: number): string => String(n).padStart(2, \"0\");\n\n/** Renders a timestamp back into a label matching the mask's granularity. */\nfunction formatKey(timestamp: number, mask?: TimelineMask): string {\n const d = new Date(timestamp);\n switch (mask) {\n case \"YYYY\":\n return String(d.getFullYear());\n case \"YYYY-MM\":\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}`;\n case \"YYYY-WW\":\n case \"YYYY-MM-DD\":\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;\n case \"YYYY-MM-DD-hh\":\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:00`;\n case \"YYYY-MM-DD-hh-mm\":\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;\n default:\n return formatFallback(timestamp);\n }\n}\n\nfunction formatFallback(timestamp: number): string {\n const d = new Date(timestamp);\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;\n}\n\n/** A candidate aggregation for adaptive resolution. */\nexport interface ResolutionCandidate<T> {\n readonly mask: TimelineMask;\n /**\n * Widest range, in months, this candidate should serve. Use -1 for \"no limit\".\n * Mirrors SBA v2's maxNMonths.\n */\n readonly maxMonths: number;\n readonly value: T;\n}\n\n/**\n * Picks the finest resolution that still covers the requested range.\n *\n * This is what keeps a timeline usable across scales: a daily aggregation over twenty years is\n * 7 300 points, unreadable and slow, while a yearly aggregation over one month is a single dot.\n * SBA v2 called this \"combined aggregations\". Feed it the range currently displayed (after a brush\n * selection, say) and re-fetch with the aggregation it returns.\n */\nexport function pickResolution<T>(candidates: readonly ResolutionCandidate<T>[], rangeMonths: number): ResolutionCandidate<T> | undefined {\n if (candidates.length === 0) return undefined;\n\n let best: ResolutionCandidate<T> | undefined;\n for (const candidate of candidates) {\n const unlimited = candidate.maxMonths === -1;\n if (!unlimited && candidate.maxMonths < rangeMonths) continue;\n if (!best) {\n best = candidate;\n continue;\n }\n // Prefer the tightest bound that still fits: it is the finest granularity available.\n const bestUnlimited = best.maxMonths === -1;\n if (bestUnlimited && !unlimited) best = candidate;\n else if (!bestUnlimited && !unlimited && candidate.maxMonths < best.maxMonths) best = candidate;\n }\n return best ?? candidates[candidates.length - 1];\n}\n\n/** Whole months between two dates, for feeding pickResolution(). */\nexport function monthsBetween(from: Date, to: Date): number {\n return (to.getFullYear() - from.getFullYear()) * 12 + (to.getMonth() - from.getMonth());\n}\n","import { afterNextRender, Component, computed, input, output, signal } from \"@angular/core\";\nimport type { ChartConfiguration, ChartType } from \"chart.js\";\n\nimport { cn } from \"cn\";\n\nimport { paletteColor, seriesPalette, toPercentages, toSeries, type AggregationLike } from \"@sinequa/atomic-angular\";\n\nimport { ChartCanvasComponent } from \"./core/chart-canvas\";\n\n/** The chart types this component supports. A narrow union keeps `strictTemplates` useful. */\nexport type AggregationChartType = \"bar\" | \"pie\" | \"doughnut\";\n\n/**\n * A Sinequa aggregation rendered as a bar, pie or doughnut chart.\n *\n * Note what this component does **not** do:\n *\n * - **it does not fetch.** It takes an `Aggregation` as an input, like `<Aggregation>` in\n * controlled mode. Feed it from `AggregationsStore`, from `QueryService.search()` or from\n * `fetchQuery()` — the component does not care, and stays testable without a server.\n * - **it does not transform.** `toSeries()` does that, as a pure function.\n * - **it does not touch the canvas.** `<ChartCanvas>` owns the Chart.js lifecycle.\n *\n * What is left is one `computed()` building a `ChartConfiguration`. That is the whole component.\n */\n@Component({\n selector: \"AggregationChart, aggregation-chart, aggregationchart\",\n imports: [ChartCanvasComponent],\n template: `\n @if (isEmpty()) {\n <p class=\"flex h-full items-center justify-center text-sm text-(--font-neutral-muted)\">{{ emptyLabel() }}</p>\n } @else {\n <ChartCanvas [config]=\"config()\" />\n }\n `,\n host: {\n \"[class]\": 'cn(\"block h-full w-full\", class())'\n }\n})\nexport class AggregationChartComponent {\n cn = cn;\n\n /**\n * Extra classes for the host element.\n * @default \"\"\n */\n readonly class = input(\"\");\n\n /**\n * The aggregation to render.\n * @default undefined\n */\n readonly aggregation = input<AggregationLike | undefined>(undefined);\n\n /**\n * Chart type.\n * @default \"bar\"\n */\n readonly type = input<AggregationChartType>(\"bar\");\n\n /**\n * Dataset label, shown in the legend and the tooltip.\n * @default \"\"\n */\n readonly label = input(\"\");\n\n /**\n * Number of items kept, largest first. Charts stop being readable long before the data runs out.\n * @default 10\n */\n readonly limit = input(10);\n\n /**\n * Plot each item as a share of the total instead of a raw count.\n * @default false\n */\n readonly asPercentage = input(false);\n\n /**\n * Read `operatorResults[weightField]` instead of `count` — for an average response time, say.\n * @default undefined\n */\n readonly weightField = input<string | undefined>(undefined);\n\n /**\n * Text shown when there is nothing to display.\n * @default \"No data\"\n */\n readonly emptyLabel = input(\"No data\");\n\n /**\n * Emitted with the label of the clicked slice. Wire it to `AggregationsService.toFilter()` and\n * `QueryParamsStore.updateFilter()` to turn this chart into a facet.\n */\n readonly itemSelected = output<string>();\n\n /** Resolved after the first render: `getComputedStyle` is useless before styles have applied. */\n private readonly palette = signal<string[]>(seriesPalette());\n\n constructor() {\n afterNextRender(() => this.palette.set(seriesPalette()));\n }\n\n private readonly series = computed(() => toSeries(this.aggregation(), { limit: this.limit(), weightField: this.weightField() }));\n\n protected readonly isEmpty = computed(() => this.series().labels.length === 0);\n\n protected readonly config = computed<ChartConfiguration>(() => {\n const series = this.series();\n const type = this.type();\n const circular = type === \"pie\" || type === \"doughnut\";\n const percentages = toPercentages(series.values);\n const plotted = this.asPercentage() ? percentages : series.values;\n const palette = this.palette();\n\n return {\n // `as ChartType` because the input is a narrow union while ChartConfiguration wants the full\n // type. Safe: every member of the union is a registered controller.\n type: type as ChartType,\n data: {\n labels: series.labels,\n datasets: [\n {\n label: this.label(),\n data: plotted,\n // A pie needs one colour per slice. A bar chart of a single measure reads better in one\n // colour, so the eye compares lengths rather than hues.\n backgroundColor: circular ? [...palette] : paletteColor(palette, 0)\n }\n ]\n },\n options: {\n plugins: {\n // A legend is redundant on a bar chart — the axis already labels every bar — but essential\n // on a pie, where slice labels have nowhere else to go.\n legend: { display: circular, position: \"right\" },\n tooltip: {\n callbacks: {\n // Always show both the share and the raw count: a percentage on its own hides the\n // difference between 3 documents out of 6 and 3000 out of 6000.\n label: ctx => {\n const index = ctx.dataIndex;\n const count = series.values[index] ?? 0;\n const share = percentages[index] ?? 0;\n return ` ${share.toFixed(1)}% (${count})`;\n }\n }\n }\n },\n scales: circular\n ? {}\n : {\n y: {\n beginAtZero: true,\n ticks: this.asPercentage() ? { callback: value => `${value}%` } : {}\n }\n },\n onClick: (_event, elements) => {\n const first = elements[0];\n if (!first) return;\n const label = series.labels[first.index];\n if (label != null) this.itemSelected.emit(label);\n }\n }\n };\n });\n}\n","import { afterNextRender, Component, computed, input, output, signal, type Signal } from \"@angular/core\";\nimport type { ChartConfiguration, Plugin } from \"chart.js\";\n\nimport { cn } from \"cn\";\n\nimport { paletteColor, timelinePalette, withAlpha } from \"@sinequa/atomic-angular\";\n\nimport { ChartCanvasComponent } from \"./core/chart-canvas\";\nimport { createTimelineBrushPlugin } from \"./core/timeline-brush.plugin\";\nimport { buildTimeline, type TimelineMask, type TimelineSeriesInput } from \"./data/timeline-data\";\n\n/** A brushed range, expressed with the same bucket labels the caller supplied. */\nexport interface TimelineRange {\n readonly from: string;\n readonly to: string;\n}\n\n/**\n * A time series with drag-to-select range selection, on Chart.js, with no d3.\n *\n * The d3 timeline this replaces was ~800 lines. The mapping:\n *\n * | d3 | here |\n * |---|---|\n * | `d3.curveStep` | `stepped: \"middle\"` |\n * | `d3.area()` | `fill: true` + `withAlpha(colour, 0.18)` |\n * | `d3.scaleUtc` + axis | a `category` axis over labels resolved in `timeline-data.ts` |\n * | `d3.brushX` | `createTimelineBrushPlugin()`, ~60 lines |\n * | `d3.bisector` tooltip | `interaction: { mode: \"index\", intersect: false }` |\n * | gap filling, resolution picking | pure functions in `timeline-data.ts` |\n *\n * The real gain is not the removed dependency: it is that all the time-axis logic became pure and\n * testable instead of being welded to the rendering.\n *\n * **A `category` axis, never `time`.** Chart.js can do a real time axis, but only with a date\n * adapter, which this library does not ship. Setting `scales.x.type = \"time\"` without one compiles\n * perfectly and then throws at runtime.\n *\n * **`(rangeSelected)` only reports.** If the host does nothing with it, you drag, the rectangle\n * appears, it vanishes, and nothing moves — the component is fine, the loop is simply not closed.\n * Keep a stack of ranges: a drag pushes one (zoom in), a control pops it (zoom out).\n */\n@Component({\n selector: \"AggregationTimeline, aggregation-timeline, aggregationtimeline\",\n imports: [ChartCanvasComponent],\n template: `\n @if (isEmpty()) {\n <p class=\"flex h-full items-center justify-center text-sm text-(--font-neutral-muted)\">{{ emptyLabel() }}</p>\n } @else {\n <ChartCanvas [config]=\"config()\" [plugins]=\"plugins()\" />\n }\n `,\n host: {\n \"[class]\": 'cn(\"block h-full w-full\", class())'\n }\n})\nexport class AggregationTimelineComponent {\n cn = cn;\n\n /**\n * Extra classes for the host element.\n * @default \"\"\n */\n readonly class = input(\"\");\n\n /**\n * The series to plot. Each carries an aggregation whose items are date buckets.\n * @default []\n */\n readonly series = input<readonly TimelineSeriesInput[]>([]);\n\n /**\n * Bucket width. Without it there is no gap filling: empty buckets are skipped rather than drawn\n * flat at zero, which silently misrepresents the data.\n * @default \"YYYY-MM-DD\"\n */\n readonly mask = input<TimelineMask | undefined>(\"YYYY-MM-DD\");\n\n /**\n * Enable the drag-to-select brush.\n * @default true\n */\n readonly enableSelection = input(true);\n\n /**\n * Render every second series dashed — the \"previous period\" convention.\n * @default false\n */\n readonly dashSecondary = input(false);\n\n /**\n * Text shown when there is nothing to display.\n * @default \"No data\"\n */\n readonly emptyLabel = input(\"No data\");\n\n /** Emitted on mouse release with the first and last bucket labels covered by the drag. */\n readonly rangeSelected = output<TimelineRange>();\n\n /**\n * Built ONCE, as a field, never inside a `computed()`.\n *\n * The brush keeps its drag state in a closure. Rebuilding it mid-drag would hand Chart.js a fresh\n * object with empty state and cancel the selection — producing a brush that \"sometimes does not\n * work\", which is worse than one that never does.\n */\n private readonly brush: Plugin = createTimelineBrushPlugin((from, to) => this.rangeSelected.emit({ from, to }));\n\n /** Resolved after the first render: `getComputedStyle` is useless before styles have applied. */\n private readonly palette = signal<string[]>(timelinePalette());\n\n constructor() {\n afterNextRender(() => this.palette.set(timelinePalette()));\n }\n\n // Annotated for the same reason as `ChartCanvas.plugins`: emitted declarations must not have to\n // name a chart.js internal type by path.\n protected readonly plugins: Signal<Plugin[]> = computed<Plugin[]>(() => (this.enableSelection() ? [this.brush] : []));\n\n private readonly timeline = computed(() => buildTimeline(this.series(), { mask: this.mask() }));\n\n protected readonly isEmpty = computed(() => this.timeline().labels.length === 0);\n\n protected readonly config = computed<ChartConfiguration>(() => {\n const { labels, series } = this.timeline();\n // A single series reads better as a filled area; several would hide each other.\n const filled = series.length === 1;\n const dashSecondary = this.dashSecondary();\n const palette = this.palette();\n\n const datasets = series.map((entry, index) => {\n // Dashed series share the colour of the series they compare against, so the pairing is\n // obvious without doubling the number of hues.\n const color = paletteColor(palette, dashSecondary ? Math.floor(index / 2) : index);\n const secondary = dashSecondary && index % 2 === 1;\n\n return {\n label: entry.label,\n data: entry.values,\n borderColor: color,\n backgroundColor: filled ? withAlpha(color, 0.18) : color,\n borderWidth: 1.5,\n borderDash: secondary ? [4, 4] : undefined,\n // \"middle\" reproduces d3.curveStep: the value holds for the whole bucket and changes at its\n // boundary. A smooth curve would imply data between buckets that does not exist.\n stepped: \"middle\" as const,\n fill: filled && !secondary,\n // Bridge nulls (buckets outside this series' range). Buckets that exist with no events are\n // 0, not null, and are drawn flat — which is the point of the gap filling.\n spanGaps: true,\n // Hide points at rest, reveal on hover: one point per day over a month is 30 dots of noise.\n pointRadius: 0,\n pointHoverRadius: 4\n };\n });\n\n return {\n type: \"line\",\n data: { labels, datasets },\n options: {\n // MANDATORY for the brush. Chart.js' default event list is\n // [\"mousemove\", \"mouseout\", \"click\", \"touchstart\", \"touchmove\"] — no mousedown, no mouseup.\n // Omit this and the plugin never sees a drag start or end: no error, just an inert brush.\n events: [\"mousedown\", \"mousemove\", \"mouseup\", \"mouseout\", \"click\", \"touchstart\", \"touchmove\", \"touchend\"],\n // Replaces d3.bisector: hovering anywhere in a column highlights every series at that\n // bucket, which is what makes comparing two curves possible.\n interaction: { mode: \"index\", intersect: false },\n scales: {\n x: { type: \"category\", grid: { display: false } },\n y: { beginAtZero: true }\n },\n plugins: {\n legend: { display: datasets.length > 1, position: \"bottom\" }\n }\n }\n };\n });\n}\n"],"mappings":"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"}
|