@k2b/ui 0.33.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base.css +14 -1
- package/dist/browser/actions/ContextMenu.js +13 -0
- package/dist/browser/actions/ContextMenu.js.map +1 -1
- package/dist/browser/actions/Dropdown.js +16 -4
- package/dist/browser/actions/Dropdown.js.map +1 -1
- package/dist/browser/actions/SelectionToolbar.js +129 -0
- package/dist/browser/actions/SelectionToolbar.js.map +1 -0
- package/dist/browser/actions/index.js +1 -0
- package/dist/browser/actions/index.js.map +1 -1
- package/dist/browser/charts.js +6 -0
- package/dist/browser/charts.js.map +1 -0
- package/dist/browser/chat/ChatComposer.js +525 -407
- package/dist/browser/chat/ChatComposer.js.map +1 -1
- package/dist/browser/chat/chat-messages.js +4 -0
- package/dist/browser/chat/chat-messages.js.map +1 -1
- package/dist/browser/chat/composer-document.js +19 -0
- package/dist/browser/chat/composer-document.js.map +1 -1
- package/dist/browser/chat/index.js.map +1 -1
- package/dist/browser/content/Chart.js +8 -0
- package/dist/browser/content/Chart.js.map +1 -1
- package/dist/browser/content/FileGrid.js +231 -9
- package/dist/browser/content/FileGrid.js.map +1 -1
- package/dist/browser/content/FileTypeIcon.js +15 -0
- package/dist/browser/content/FileTypeIcon.js.map +1 -1
- package/dist/browser/content/FileView.js +11 -4
- package/dist/browser/content/FileView.js.map +1 -1
- package/dist/browser/content/MatchText.js +61 -0
- package/dist/browser/content/MatchText.js.map +1 -0
- package/dist/browser/content/MessageRow.js +73 -53
- package/dist/browser/content/MessageRow.js.map +1 -1
- package/dist/browser/content/ReactionBar.js +3 -1
- package/dist/browser/content/ReactionBar.js.map +1 -1
- package/dist/browser/content/calendar-day-scroll.js +4 -3
- package/dist/browser/content/calendar-day-scroll.js.map +1 -1
- package/dist/browser/content/chart-bar.js +476 -0
- package/dist/browser/content/chart-bar.js.map +1 -0
- package/dist/browser/content/file-list-messages.js +52 -0
- package/dist/browser/content/file-list-messages.js.map +1 -0
- package/dist/browser/content/index.js +2 -1
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/feedback/Tooltip.js +31 -14
- package/dist/browser/feedback/Tooltip.js.map +1 -1
- package/dist/browser/inputs/ChoiceList.js +178 -0
- package/dist/browser/inputs/ChoiceList.js.map +1 -0
- package/dist/browser/inputs/ChoiceSlider.js +314 -0
- package/dist/browser/inputs/ChoiceSlider.js.map +1 -0
- package/dist/browser/inputs/ChoiceTiles.js +135 -0
- package/dist/browser/inputs/ChoiceTiles.js.map +1 -0
- package/dist/browser/inputs/ColorChoices.js +120 -0
- package/dist/browser/inputs/ColorChoices.js.map +1 -0
- package/dist/browser/inputs/QrScanner.js +95 -13
- package/dist/browser/inputs/QrScanner.js.map +1 -1
- package/dist/browser/inputs/TextInput.js +15 -13
- package/dist/browser/inputs/TextInput.js.map +1 -1
- package/dist/browser/inputs/index.js +4 -0
- package/dist/browser/inputs/index.js.map +1 -1
- package/dist/browser/inputs/qr-messages.js +2 -0
- package/dist/browser/inputs/qr-messages.js.map +1 -1
- package/dist/browser/internal/radio-keys.js +13 -0
- package/dist/browser/internal/radio-keys.js.map +1 -0
- package/dist/browser/layout/AnchoredPopover.js +180 -0
- package/dist/browser/layout/AnchoredPopover.js.map +1 -0
- package/dist/browser/layout/AppWorkspace.js +155 -20
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/DetailPanel.js +443 -333
- package/dist/browser/layout/DetailPanel.js.map +1 -1
- package/dist/browser/layout/MobileShell.js +21 -7
- package/dist/browser/layout/MobileShell.js.map +1 -1
- package/dist/browser/layout/Settings.js +283 -175
- package/dist/browser/layout/Settings.js.map +1 -1
- package/dist/browser/layout/SidebarRailHint.js +79 -0
- package/dist/browser/layout/SidebarRailHint.js.map +1 -0
- package/dist/browser/layout/SidebarSwitcher.js +79 -66
- package/dist/browser/layout/SidebarSwitcher.js.map +1 -1
- package/dist/browser/layout/TabBar.js +18 -4
- package/dist/browser/layout/TabBar.js.map +1 -1
- package/dist/browser/layout/app-workspace-controller.js +11 -4
- package/dist/browser/layout/app-workspace-controller.js.map +1 -1
- package/dist/browser/layout/detail-panel-messages.js +4 -2
- package/dist/browser/layout/detail-panel-messages.js.map +1 -1
- package/dist/browser/layout/index.js +2 -1
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/browser/layout/settings-messages.js +26 -2
- package/dist/browser/layout/settings-messages.js.map +1 -1
- package/dist/browser/surfaces/Avatar.js +2 -14
- package/dist/browser/surfaces/Avatar.js.map +1 -1
- package/dist/browser/surfaces/DotStrip.js +70 -0
- package/dist/browser/surfaces/DotStrip.js.map +1 -0
- package/dist/browser/surfaces/ProgressRing.js +3 -0
- package/dist/browser/surfaces/ProgressRing.js.map +1 -1
- package/dist/browser/surfaces/ResourceCard.js +125 -68
- package/dist/browser/surfaces/ResourceCard.js.map +1 -1
- package/dist/browser/surfaces/index.js +2 -0
- package/dist/browser/surfaces/index.js.map +1 -1
- package/dist/browser/surfaces/person-color.js +18 -0
- package/dist/browser/surfaces/person-color.js.map +1 -0
- package/dist/browser/surfaces/resource-messages.js +6 -2
- package/dist/browser/surfaces/resource-messages.js.map +1 -1
- package/dist/browser/text-editor/TextEditor.js +1358 -0
- package/dist/browser/text-editor/TextEditor.js.map +1 -0
- package/dist/browser/text-editor/clipboard-html.js +152 -0
- package/dist/browser/text-editor/clipboard-html.js.map +1 -0
- package/dist/browser/text-editor/clipboard-loading.js +68 -0
- package/dist/browser/text-editor/clipboard-loading.js.map +1 -0
- package/dist/browser/text-editor/clipboard.js +51 -0
- package/dist/browser/text-editor/clipboard.js.map +1 -0
- package/dist/browser/text-editor/engine.js +125 -0
- package/dist/browser/text-editor/engine.js.map +1 -0
- package/dist/browser/text-editor/format.js +218 -0
- package/dist/browser/text-editor/format.js.map +1 -0
- package/dist/browser/text-editor/formatted.js +164 -0
- package/dist/browser/text-editor/formatted.js.map +1 -0
- package/dist/browser/text-editor/language.js +19 -0
- package/dist/browser/text-editor/language.js.map +1 -0
- package/dist/browser/text-editor/markdown-table.js +563 -0
- package/dist/browser/text-editor/markdown-table.js.map +1 -0
- package/dist/browser/text-editor/messages.js +233 -0
- package/dist/browser/text-editor/messages.js.map +1 -0
- package/dist/browser/text-editor/paste.js +115 -0
- package/dist/browser/text-editor/paste.js.map +1 -0
- package/dist/browser/text-editor/table.js +1760 -0
- package/dist/browser/text-editor/table.js.map +1 -0
- package/dist/browser/text-editor.js +5 -0
- package/dist/browser/text-editor.js.map +1 -0
- package/dist/browser/widgets/Widget.js +3 -2
- package/dist/browser/widgets/Widget.js.map +1 -1
- package/dist/ssr/actions/ContextMenu.js +9 -0
- package/dist/ssr/actions/ContextMenu.js.map +1 -1
- package/dist/ssr/actions/Dropdown.js +15 -4
- package/dist/ssr/actions/Dropdown.js.map +1 -1
- package/dist/ssr/actions/SelectionToolbar.js +104 -0
- package/dist/ssr/actions/SelectionToolbar.js.map +1 -0
- package/dist/ssr/actions/index.js +1 -0
- package/dist/ssr/actions/index.js.map +1 -1
- package/dist/ssr/charts.js +6 -0
- package/dist/ssr/charts.js.map +1 -0
- package/dist/ssr/chat/ChatComposer.js +132 -53
- package/dist/ssr/chat/ChatComposer.js.map +1 -1
- package/dist/ssr/chat/chat-messages.js +4 -0
- package/dist/ssr/chat/chat-messages.js.map +1 -1
- package/dist/ssr/chat/composer-document.js +19 -0
- package/dist/ssr/chat/composer-document.js.map +1 -1
- package/dist/ssr/chat/index.js.map +1 -1
- package/dist/ssr/content/Chart.js +8 -0
- package/dist/ssr/content/Chart.js.map +1 -1
- package/dist/ssr/content/FileGrid.js +132 -5
- package/dist/ssr/content/FileGrid.js.map +1 -1
- package/dist/ssr/content/FileTypeIcon.js +15 -0
- package/dist/ssr/content/FileTypeIcon.js.map +1 -1
- package/dist/ssr/content/FileView.js +11 -4
- package/dist/ssr/content/FileView.js.map +1 -1
- package/dist/ssr/content/MatchText.js +56 -0
- package/dist/ssr/content/MatchText.js.map +1 -0
- package/dist/ssr/content/MessageRow.js +16 -6
- package/dist/ssr/content/MessageRow.js.map +1 -1
- package/dist/ssr/content/ReactionBar.js +3 -1
- package/dist/ssr/content/ReactionBar.js.map +1 -1
- package/dist/ssr/content/calendar-day-scroll.js +4 -3
- package/dist/ssr/content/calendar-day-scroll.js.map +1 -1
- package/dist/ssr/content/chart-bar.js +476 -0
- package/dist/ssr/content/chart-bar.js.map +1 -0
- package/dist/ssr/content/file-list-messages.js +52 -0
- package/dist/ssr/content/file-list-messages.js.map +1 -0
- package/dist/ssr/content/index.js +2 -1
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/feedback/Tooltip.js +31 -14
- package/dist/ssr/feedback/Tooltip.js.map +1 -1
- package/dist/ssr/inputs/ChoiceList.js +95 -0
- package/dist/ssr/inputs/ChoiceList.js.map +1 -0
- package/dist/ssr/inputs/ChoiceSlider.js +191 -0
- package/dist/ssr/inputs/ChoiceSlider.js.map +1 -0
- package/dist/ssr/inputs/ChoiceTiles.js +61 -0
- package/dist/ssr/inputs/ChoiceTiles.js.map +1 -0
- package/dist/ssr/inputs/ColorChoices.js +60 -0
- package/dist/ssr/inputs/ColorChoices.js.map +1 -0
- package/dist/ssr/inputs/QrScanner.js +89 -10
- package/dist/ssr/inputs/QrScanner.js.map +1 -1
- package/dist/ssr/inputs/TextInput.js +13 -1
- package/dist/ssr/inputs/TextInput.js.map +1 -1
- package/dist/ssr/inputs/index.js +4 -0
- package/dist/ssr/inputs/index.js.map +1 -1
- package/dist/ssr/inputs/qr-messages.js +2 -0
- package/dist/ssr/inputs/qr-messages.js.map +1 -1
- package/dist/ssr/internal/radio-keys.js +13 -0
- package/dist/ssr/internal/radio-keys.js.map +1 -0
- package/dist/ssr/layout/AnchoredPopover.js +142 -0
- package/dist/ssr/layout/AnchoredPopover.js.map +1 -0
- package/dist/ssr/layout/AppWorkspace.js +154 -20
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/DetailPanel.js +181 -108
- package/dist/ssr/layout/DetailPanel.js.map +1 -1
- package/dist/ssr/layout/MobileShell.js +20 -6
- package/dist/ssr/layout/MobileShell.js.map +1 -1
- package/dist/ssr/layout/Settings.js +122 -45
- package/dist/ssr/layout/Settings.js.map +1 -1
- package/dist/ssr/layout/SidebarRailHint.js +79 -0
- package/dist/ssr/layout/SidebarRailHint.js.map +1 -0
- package/dist/ssr/layout/SidebarSwitcher.js +13 -3
- package/dist/ssr/layout/SidebarSwitcher.js.map +1 -1
- package/dist/ssr/layout/TabBar.js +11 -3
- package/dist/ssr/layout/TabBar.js.map +1 -1
- package/dist/ssr/layout/app-workspace-controller.js +11 -4
- package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
- package/dist/ssr/layout/detail-panel-messages.js +4 -2
- package/dist/ssr/layout/detail-panel-messages.js.map +1 -1
- package/dist/ssr/layout/index.js +2 -1
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/ssr/layout/settings-messages.js +26 -2
- package/dist/ssr/layout/settings-messages.js.map +1 -1
- package/dist/ssr/surfaces/Avatar.js +2 -14
- package/dist/ssr/surfaces/Avatar.js.map +1 -1
- package/dist/ssr/surfaces/DotStrip.js +31 -0
- package/dist/ssr/surfaces/DotStrip.js.map +1 -0
- package/dist/ssr/surfaces/ProgressRing.js +3 -0
- package/dist/ssr/surfaces/ProgressRing.js.map +1 -1
- package/dist/ssr/surfaces/ResourceCard.js +40 -15
- package/dist/ssr/surfaces/ResourceCard.js.map +1 -1
- package/dist/ssr/surfaces/index.js +2 -0
- package/dist/ssr/surfaces/index.js.map +1 -1
- package/dist/ssr/surfaces/person-color.js +18 -0
- package/dist/ssr/surfaces/person-color.js.map +1 -0
- package/dist/ssr/surfaces/resource-messages.js +6 -2
- package/dist/ssr/surfaces/resource-messages.js.map +1 -1
- package/dist/ssr/text-editor/TextEditor.js +1155 -0
- package/dist/ssr/text-editor/TextEditor.js.map +1 -0
- package/dist/ssr/text-editor/clipboard-html.js +152 -0
- package/dist/ssr/text-editor/clipboard-html.js.map +1 -0
- package/dist/ssr/text-editor/clipboard-loading.js +68 -0
- package/dist/ssr/text-editor/clipboard-loading.js.map +1 -0
- package/dist/ssr/text-editor/clipboard.js +51 -0
- package/dist/ssr/text-editor/clipboard.js.map +1 -0
- package/dist/ssr/text-editor/engine.js +125 -0
- package/dist/ssr/text-editor/engine.js.map +1 -0
- package/dist/ssr/text-editor/format.js +218 -0
- package/dist/ssr/text-editor/format.js.map +1 -0
- package/dist/ssr/text-editor/formatted.js +164 -0
- package/dist/ssr/text-editor/formatted.js.map +1 -0
- package/dist/ssr/text-editor/language.js +19 -0
- package/dist/ssr/text-editor/language.js.map +1 -0
- package/dist/ssr/text-editor/markdown-table.js +563 -0
- package/dist/ssr/text-editor/markdown-table.js.map +1 -0
- package/dist/ssr/text-editor/messages.js +233 -0
- package/dist/ssr/text-editor/messages.js.map +1 -0
- package/dist/ssr/text-editor/paste.js +115 -0
- package/dist/ssr/text-editor/paste.js.map +1 -0
- package/dist/ssr/text-editor/table.js +1760 -0
- package/dist/ssr/text-editor/table.js.map +1 -0
- package/dist/ssr/text-editor.js +5 -0
- package/dist/ssr/text-editor.js.map +1 -0
- package/dist/ssr/widgets/Widget.js +3 -2
- package/dist/ssr/widgets/Widget.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/actions/ContextMenu.d.ts +5 -0
- package/dist/types/actions/Dropdown.d.ts +7 -0
- package/dist/types/actions/SelectionToolbar.d.ts +38 -0
- package/dist/types/actions/index.d.ts +2 -0
- package/dist/types/charts.d.ts +5 -0
- package/dist/types/chat/ChatComposer.d.ts +15 -0
- package/dist/types/chat/chat-messages.d.ts +2 -0
- package/dist/types/chat/composer-document.d.ts +5 -0
- package/dist/types/chat/index.d.ts +1 -1
- package/dist/types/content/Chart.d.ts +2 -1
- package/dist/types/content/FileGrid.d.ts +43 -3
- package/dist/types/content/FileTypeIcon.d.ts +10 -0
- package/dist/types/content/FileView.d.ts +5 -1
- package/dist/types/content/MatchText.d.ts +21 -0
- package/dist/types/content/MessageRow.d.ts +2 -0
- package/dist/types/content/calendar-day-scroll.d.ts +2 -1
- package/dist/types/content/chart-bar.d.ts +60 -0
- package/dist/types/content/file-list-messages.d.ts +24 -0
- package/dist/types/content/index.d.ts +3 -2
- package/dist/types/feedback/Tooltip.d.ts +8 -2
- package/dist/types/inputs/ChoiceList.d.ts +28 -0
- package/dist/types/inputs/ChoiceSlider.d.ts +36 -0
- package/dist/types/inputs/ChoiceTiles.d.ts +25 -0
- package/dist/types/inputs/ColorChoices.d.ts +19 -0
- package/dist/types/inputs/index.d.ts +8 -0
- package/dist/types/inputs/qr-messages.d.ts +1 -0
- package/dist/types/internal/radio-keys.d.ts +5 -0
- package/dist/types/layout/AnchoredPopover.d.ts +31 -0
- package/dist/types/layout/AppWorkspace.d.ts +10 -0
- package/dist/types/layout/DetailPanel.d.ts +17 -0
- package/dist/types/layout/MobileShell.d.ts +5 -2
- package/dist/types/layout/Settings.d.ts +22 -0
- package/dist/types/layout/SidebarRailHint.d.ts +26 -0
- package/dist/types/layout/TabBar.d.ts +5 -0
- package/dist/types/layout/detail-panel-messages.d.ts +1 -0
- package/dist/types/layout/index.d.ts +3 -2
- package/dist/types/layout/settings-messages.d.ts +12 -0
- package/dist/types/surfaces/DotStrip.d.ts +22 -0
- package/dist/types/surfaces/ProgressRing.d.ts +2 -1
- package/dist/types/surfaces/ResourceCard.d.ts +9 -0
- package/dist/types/surfaces/index.d.ts +4 -1
- package/dist/types/surfaces/person-color.d.ts +10 -0
- package/dist/types/surfaces/resource-messages.d.ts +2 -0
- package/dist/types/text-editor/TextEditor.d.ts +69 -0
- package/dist/types/text-editor/clipboard-html.d.ts +9 -0
- package/dist/types/text-editor/clipboard-loading.d.ts +8 -0
- package/dist/types/text-editor/clipboard.d.ts +20 -0
- package/dist/types/text-editor/engine.d.ts +34 -0
- package/dist/types/text-editor/format.d.ts +34 -0
- package/dist/types/text-editor/formatted.d.ts +1 -0
- package/dist/types/text-editor/language.d.ts +8 -0
- package/dist/types/text-editor/markdown-table.d.ts +105 -0
- package/dist/types/text-editor/messages.d.ts +113 -0
- package/dist/types/text-editor/paste.d.ts +6 -0
- package/dist/types/text-editor/table.d.ts +81 -0
- package/dist/types/text-editor.d.ts +4 -0
- package/dist/types/widgets/Widget.d.ts +3 -2
- package/package.json +28 -3
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
import { chartDatumSvg, computeDomain, escapeXml, extendDomainToNice, mapLog, mapRange, niceLogTicks, niceStep, svgRoot } from "@k2b/stdlib";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Bar chart options: stdlib's `charts.bar` options plus a title for the category axis and a separate value format.
|
|
5
|
+
* The wrapper owns size and inspection.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Text keeps its pixel size while the drawing stretches to its box, and the drawing is never measured. Labels are
|
|
10
|
+
* laid out for the narrowest chart, a 320px phone column, so they fit in every wider one.
|
|
11
|
+
*/
|
|
12
|
+
const NARROW_PX = 296;
|
|
13
|
+
/** Tick, category and value labels are 11px (see the `.k2b-chart` rules). */
|
|
14
|
+
const FONT_PX = 11;
|
|
15
|
+
/** A label column takes at most this share of the narrowest chart; longer labels wrap to a second line. */
|
|
16
|
+
const LABEL_SHARE = 0.4;
|
|
17
|
+
const ROW_MIN = 22;
|
|
18
|
+
const ROW_TWO_LINES = 32;
|
|
19
|
+
const ROW_MAX = 36;
|
|
20
|
+
/** Rows aim for the height of the other Cartesian charts before they grow. */
|
|
21
|
+
const ROWS_TARGET_HEIGHT = 280;
|
|
22
|
+
const BAR_MAX = 20;
|
|
23
|
+
const COLUMN_MAX = 40;
|
|
24
|
+
const GAP_PX = 6;
|
|
25
|
+
const LEGEND_ROW = 20;
|
|
26
|
+
/** Rows keep at least this share of the narrowest chart for their bars; wider values go to the tooltip and table. */
|
|
27
|
+
const MIN_PLOT_SHARE = 0.3;
|
|
28
|
+
const narrow = opts => opts.displayWidth ?? NARROW_PX;
|
|
29
|
+
const fmt = value => Number.isFinite(value) ? `${Math.round(value * 100) / 100}` : "0";
|
|
30
|
+
|
|
31
|
+
/** Estimated width of `text` at `size` pixels in the UI sans font with tabular figures; a little wide on purpose. */
|
|
32
|
+
export const chartTextWidth = (text, size = FONT_PX) => {
|
|
33
|
+
let em = 0;
|
|
34
|
+
for (const char of text) {
|
|
35
|
+
if (/[\s.,:;!|'’ilIjft()[\]-]/.test(char)) em += 0.34;else if (/[MWmw@%]/.test(char)) em += 0.86;else if (/[A-Z0-9#$€&]/.test(char)) em += 0.66;else if (char.codePointAt(0) > 0x2e80) em += 1;else em += 0.56;
|
|
36
|
+
}
|
|
37
|
+
return em * size;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/** Split a label into at most `lines` lines of `maxPx`; the last line ends with an ellipsis when the label is longer. */
|
|
41
|
+
const wrapLabel = (label, maxPx, lines) => {
|
|
42
|
+
const words = label.trim().split(/\s+/);
|
|
43
|
+
const result = [];
|
|
44
|
+
let current = "";
|
|
45
|
+
const breakWord = word => {
|
|
46
|
+
// A word wider than a line breaks inside the word.
|
|
47
|
+
let part = "";
|
|
48
|
+
for (const char of word) {
|
|
49
|
+
if (part && chartTextWidth(part + char) > maxPx) {
|
|
50
|
+
result.push(part);
|
|
51
|
+
part = "";
|
|
52
|
+
}
|
|
53
|
+
part += char;
|
|
54
|
+
}
|
|
55
|
+
return part;
|
|
56
|
+
};
|
|
57
|
+
for (const word of words) {
|
|
58
|
+
const candidate = current ? `${current} ${word}` : word;
|
|
59
|
+
if (chartTextWidth(candidate) <= maxPx) current = candidate;else {
|
|
60
|
+
if (current) result.push(current);
|
|
61
|
+
current = chartTextWidth(word) > maxPx ? breakWord(word) : word;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (current) result.push(current);
|
|
65
|
+
if (result.length <= lines) return {
|
|
66
|
+
lines: result,
|
|
67
|
+
truncated: false
|
|
68
|
+
};
|
|
69
|
+
let last = result[lines - 1];
|
|
70
|
+
while (last && chartTextWidth(`${last}…`) > maxPx) last = last.slice(0, -1).trimEnd();
|
|
71
|
+
return {
|
|
72
|
+
lines: [...result.slice(0, lines - 1), `${last}…`],
|
|
73
|
+
truncated: true
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
/** The value scale of stdlib's bar chart: nice linear ticks including zero, or decades on a log axis. */
|
|
77
|
+
const valueScale = (values, axis, nice) => {
|
|
78
|
+
const log = axis?.scale === "log";
|
|
79
|
+
if (axis?.domain) {
|
|
80
|
+
const [lo, hi] = axis.domain;
|
|
81
|
+
if (!Number.isFinite(lo) || !Number.isFinite(hi) || lo >= hi || log && lo <= 0) throw new RangeError("Chart axis domain must have finite increasing bounds (positive for log scales)");
|
|
82
|
+
// Bars rest on zero, so a linear domain must contain it like every value.
|
|
83
|
+
if ((log ? values : [...values, 0]).some(value => (!log || value > 0) && (value < lo || value > hi))) throw new RangeError("Chart axis domain must contain all plotted values and bounds");
|
|
84
|
+
if (log) return {
|
|
85
|
+
domain: [lo, hi],
|
|
86
|
+
ticks: niceLogTicks(lo, hi).ticks.filter(tick => tick >= lo && tick <= hi),
|
|
87
|
+
log
|
|
88
|
+
};
|
|
89
|
+
const step = niceStep(hi - lo, axis.ticks ?? 5);
|
|
90
|
+
const ticks = [lo];
|
|
91
|
+
if (step > 0 && Number.isFinite(step)) for (let value = Math.ceil(lo / step) * step; value < hi;) {
|
|
92
|
+
if (value > lo) ticks.push(value);
|
|
93
|
+
const next = value + step;
|
|
94
|
+
if (next <= value) break;
|
|
95
|
+
value = next;
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
domain: [lo, hi],
|
|
99
|
+
ticks: [...ticks, hi],
|
|
100
|
+
log
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (log) {
|
|
104
|
+
const positive = values.filter(value => value > 0);
|
|
105
|
+
if (!positive.length) return {
|
|
106
|
+
domain: [1, 10],
|
|
107
|
+
ticks: [1, 10],
|
|
108
|
+
log
|
|
109
|
+
};
|
|
110
|
+
return {
|
|
111
|
+
...niceLogTicks(Math.min(...positive), Math.max(...positive)),
|
|
112
|
+
log
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
const [min, max] = computeDomain([...values, 0]);
|
|
116
|
+
if (!nice) return {
|
|
117
|
+
domain: [min, max],
|
|
118
|
+
ticks: [],
|
|
119
|
+
log
|
|
120
|
+
};
|
|
121
|
+
return {
|
|
122
|
+
...extendDomainToNice(min, max, niceStep(max - min, axis?.ticks ?? 5)),
|
|
123
|
+
log
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
const project = (scale, value, range) => (scale.log ? mapLog : mapRange)(value, scale.domain, range);
|
|
127
|
+
const finiteItems = data => data.flatMap((item, index) => Number.isFinite(item.value) ? [{
|
|
128
|
+
item,
|
|
129
|
+
index
|
|
130
|
+
}] : []);
|
|
131
|
+
const headerHeight = opts => opts.title || opts.subtitle ? (opts.title ? 14 : 0) + (opts.subtitle ? 6 : 0) + 16 : 0;
|
|
132
|
+
const valueFormat = opts => opts.valueFormat ?? opts.yAxis?.format ?? (value => String(value));
|
|
133
|
+
const tickFormat = opts => opts.yAxis?.format ?? (value => String(value));
|
|
134
|
+
|
|
135
|
+
/** Columns, when every category label fits below its column on the narrowest chart; rows otherwise. */
|
|
136
|
+
const columnsFit = (opts, finite, width) => {
|
|
137
|
+
const units = width / narrow(opts);
|
|
138
|
+
const columns = columnGeometry(opts, finite, width, 280);
|
|
139
|
+
const slotPx = (columns.x1 - columns.x0) / finite.length / units;
|
|
140
|
+
if (finite.some(({
|
|
141
|
+
item
|
|
142
|
+
}) => chartTextWidth(item.label) + GAP_PX > slotPx)) return false;
|
|
143
|
+
// Asked-for values must stay readable too; rows always have room for them.
|
|
144
|
+
return opts.showValues !== true || columns.valuesFit;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/** The renderer's plan for a chart: its layout and logical height at `width`, derived from the data alone. */
|
|
148
|
+
const barChartPlan = (opts, width = 480) => {
|
|
149
|
+
const finite = finiteItems(opts.data);
|
|
150
|
+
const header = headerHeight(opts);
|
|
151
|
+
if (!finite.length) return {
|
|
152
|
+
layout: "columns",
|
|
153
|
+
height: 280,
|
|
154
|
+
finite,
|
|
155
|
+
header
|
|
156
|
+
};
|
|
157
|
+
if (opts.xAxis?.ordered || columnsFit(opts, finite, width)) return {
|
|
158
|
+
layout: "columns",
|
|
159
|
+
height: 280,
|
|
160
|
+
finite,
|
|
161
|
+
header
|
|
162
|
+
};
|
|
163
|
+
const rows = rowGeometry(opts, finite, width, header);
|
|
164
|
+
return {
|
|
165
|
+
layout: "rows",
|
|
166
|
+
height: rows.height,
|
|
167
|
+
finite,
|
|
168
|
+
header
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/** The layout a bar chart takes and its logical height, so server and browser reserve the same box. */
|
|
173
|
+
export const barChartLayout = (opts, width = 480) => {
|
|
174
|
+
const {
|
|
175
|
+
layout,
|
|
176
|
+
height
|
|
177
|
+
} = barChartPlan(opts, width);
|
|
178
|
+
return {
|
|
179
|
+
layout,
|
|
180
|
+
height
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
const columnGeometry = (opts, finite, width, height) => {
|
|
184
|
+
const units = width / narrow(opts);
|
|
185
|
+
const given = typeof opts.padding === "number" ? {
|
|
186
|
+
top: opts.padding,
|
|
187
|
+
right: opts.padding,
|
|
188
|
+
bottom: opts.padding,
|
|
189
|
+
left: opts.padding
|
|
190
|
+
} : opts.padding;
|
|
191
|
+
const values = finite.map(({
|
|
192
|
+
item
|
|
193
|
+
}) => item.value);
|
|
194
|
+
const scale = valueScale(values, opts.yAxis, true);
|
|
195
|
+
const ticks = tickFormat(opts);
|
|
196
|
+
const longestTick = Math.max(0, ...scale.ticks.map(tick => chartTextWidth(ticks(tick))));
|
|
197
|
+
const legendRows = opts.colorByBar && opts.legend ? legendLayout(opts, finite, width).rows : 0;
|
|
198
|
+
const header = headerHeight(opts);
|
|
199
|
+
const x0 = given?.left ?? Math.max(40, Math.ceil((longestTick + GAP_PX + 2) * units));
|
|
200
|
+
const x1 = width - (given?.right ?? 16);
|
|
201
|
+
const y0 = header + (given?.top ?? 16) + (opts.yAxis?.label ? 16 : 0);
|
|
202
|
+
const y1 = height - (given?.bottom ?? 22) - (opts.xAxis?.label ? 16 : 0) - legendRows * LEGEND_ROW;
|
|
203
|
+
const slotPx = (x1 - x0) / Math.max(1, finite.length) / units;
|
|
204
|
+
const format = valueFormat(opts);
|
|
205
|
+
const valuesFit = finite.every(({
|
|
206
|
+
item
|
|
207
|
+
}) => chartTextWidth(format(item.value)) + 2 <= slotPx);
|
|
208
|
+
const printValues = opts.showValues ?? valuesFit;
|
|
209
|
+
// A printed negative value hangs below its bar: the plot ends a line above the category labels.
|
|
210
|
+
const plotBottom = y1 - (printValues && values.some(value => value < 0) ? 14 : 0);
|
|
211
|
+
return {
|
|
212
|
+
x0,
|
|
213
|
+
x1,
|
|
214
|
+
y0,
|
|
215
|
+
y1,
|
|
216
|
+
plotBottom,
|
|
217
|
+
scale,
|
|
218
|
+
valuesFit,
|
|
219
|
+
printValues,
|
|
220
|
+
legendRows
|
|
221
|
+
};
|
|
222
|
+
};
|
|
223
|
+
const rowGeometry = (opts, finite, width, header) => {
|
|
224
|
+
const printed = rowGeometryWith(opts, finite, width, header, opts.showValues !== false);
|
|
225
|
+
// Values too wide to leave the bars room stay in the tooltip and table; a value axis replaces them.
|
|
226
|
+
if (printed.showValues && (printed.x1 - printed.x0) / (width / narrow(opts)) < narrow(opts) * MIN_PLOT_SHARE) return rowGeometryWith(opts, finite, width, header, false);
|
|
227
|
+
return printed;
|
|
228
|
+
};
|
|
229
|
+
const rowGeometryWith = (opts, finite, width, header, showValues) => {
|
|
230
|
+
const units = width / narrow(opts);
|
|
231
|
+
const maxLabelPx = narrow(opts) * LABEL_SHARE;
|
|
232
|
+
const labels = finite.map(({
|
|
233
|
+
item
|
|
234
|
+
}) => wrapLabel(item.label, maxLabelPx, 2));
|
|
235
|
+
const twoLines = labels.some(label => label.lines.length > 1);
|
|
236
|
+
const labelPx = Math.min(maxLabelPx, Math.max(0, ...labels.flatMap(label => label.lines.map(line => chartTextWidth(line)))));
|
|
237
|
+
const format = valueFormat(opts);
|
|
238
|
+
const positivePx = showValues ? Math.max(0, ...finite.filter(({
|
|
239
|
+
item
|
|
240
|
+
}) => item.value >= 0).map(({
|
|
241
|
+
item
|
|
242
|
+
}) => chartTextWidth(format(item.value)))) : 0;
|
|
243
|
+
const negativePx = showValues ? Math.max(0, ...finite.filter(({
|
|
244
|
+
item
|
|
245
|
+
}) => item.value < 0).map(({
|
|
246
|
+
item
|
|
247
|
+
}) => chartTextWidth(format(item.value)))) : 0;
|
|
248
|
+
const refLabels = (opts.references ?? []).some(ref => (ref.axis ?? "y") === "y" && ref.label);
|
|
249
|
+
const titled = !!(opts.xAxis?.label || opts.yAxis?.label || refLabels);
|
|
250
|
+
const top = header + (titled ? 20 : 4);
|
|
251
|
+
const bottom = showValues ? 4 : 24;
|
|
252
|
+
const minimum = twoLines ? ROW_TWO_LINES : ROW_MIN;
|
|
253
|
+
const pitch = Math.min(ROW_MAX, Math.max(minimum, (ROWS_TARGET_HEIGHT - top - bottom) / finite.length));
|
|
254
|
+
const labelEnd = Math.ceil(labelPx * units);
|
|
255
|
+
const x0 = labelEnd + GAP_PX * units + (negativePx ? (negativePx + GAP_PX) * units : 0);
|
|
256
|
+
const x1 = width - (positivePx ? (positivePx + GAP_PX) * units : 8 * units);
|
|
257
|
+
return {
|
|
258
|
+
labels,
|
|
259
|
+
labelEnd,
|
|
260
|
+
x0,
|
|
261
|
+
x1,
|
|
262
|
+
top,
|
|
263
|
+
pitch,
|
|
264
|
+
twoLines,
|
|
265
|
+
showValues,
|
|
266
|
+
height: Math.ceil(top + pitch * finite.length + bottom)
|
|
267
|
+
};
|
|
268
|
+
};
|
|
269
|
+
const legendLayout = (opts, finite, width) => {
|
|
270
|
+
const units = width / narrow(opts);
|
|
271
|
+
const rows = [[]];
|
|
272
|
+
let cursor = 0;
|
|
273
|
+
finite.forEach(({
|
|
274
|
+
item
|
|
275
|
+
}, index) => {
|
|
276
|
+
const itemWidth = (8 + 4 + chartTextWidth(item.label)) * units;
|
|
277
|
+
if (cursor > 0 && cursor + 12 * units + itemWidth > width) {
|
|
278
|
+
rows.push([]);
|
|
279
|
+
cursor = 0;
|
|
280
|
+
}
|
|
281
|
+
const x = cursor ? cursor + 12 * units : 0;
|
|
282
|
+
rows.at(-1).push({
|
|
283
|
+
label: item.label,
|
|
284
|
+
color: colorIndex(item, index),
|
|
285
|
+
x
|
|
286
|
+
});
|
|
287
|
+
cursor = x + itemWidth;
|
|
288
|
+
});
|
|
289
|
+
return {
|
|
290
|
+
rows: rows.length,
|
|
291
|
+
items: rows
|
|
292
|
+
};
|
|
293
|
+
};
|
|
294
|
+
const colorIndex = (item, fallback) => {
|
|
295
|
+
const index = item.colorIndex ?? fallback;
|
|
296
|
+
if (!Number.isInteger(index) || index < 0) throw new RangeError("Chart colorIndex must be a nonnegative integer");
|
|
297
|
+
return index % 8;
|
|
298
|
+
};
|
|
299
|
+
const renderHeader = (opts, width) => {
|
|
300
|
+
const parts = [];
|
|
301
|
+
let y = 16;
|
|
302
|
+
if (opts.title) {
|
|
303
|
+
parts.push(`<text class="stdlib-chart-title" x="${fmt(width / 2)}" y="${y}" text-anchor="middle">${escapeXml(opts.title)}</text>`);
|
|
304
|
+
y += 14;
|
|
305
|
+
}
|
|
306
|
+
if (opts.subtitle) parts.push(`<text class="stdlib-chart-subtitle" x="${fmt(width / 2)}" y="${y}" text-anchor="middle">${escapeXml(opts.subtitle)}</text>`);
|
|
307
|
+
return parts.join("");
|
|
308
|
+
};
|
|
309
|
+
const datum = (item, index, anchor, format) => ({
|
|
310
|
+
index,
|
|
311
|
+
role: "item",
|
|
312
|
+
label: item.label,
|
|
313
|
+
anchor,
|
|
314
|
+
values: [{
|
|
315
|
+
key: "value",
|
|
316
|
+
value: item.value,
|
|
317
|
+
formatted: format(item.value)
|
|
318
|
+
}]
|
|
319
|
+
});
|
|
320
|
+
const renderColumns = (opts, plan, width, height, inspect) => {
|
|
321
|
+
const {
|
|
322
|
+
finite
|
|
323
|
+
} = plan;
|
|
324
|
+
const units = width / narrow(opts);
|
|
325
|
+
const g = columnGeometry(opts, finite, width, height);
|
|
326
|
+
const ticks = tickFormat(opts);
|
|
327
|
+
const format = valueFormat(opts);
|
|
328
|
+
const showValues = g.printValues;
|
|
329
|
+
const parts = [renderHeader(opts, width)];
|
|
330
|
+
const y = value => project(g.scale, value, [g.plotBottom, g.y0]);
|
|
331
|
+
if (opts.yAxis?.label) parts.push(`<text class="stdlib-chart-axis-label" x="0" y="${fmt(g.y0 - 8)}" text-anchor="start">${escapeXml(opts.yAxis.label)}</text>`);
|
|
332
|
+
for (const tick of g.scale.ticks) {
|
|
333
|
+
const ty = y(tick);
|
|
334
|
+
parts.push(`<line class="stdlib-chart-grid" x1="${fmt(g.x0)}" y1="${fmt(ty)}" x2="${fmt(g.x1)}" y2="${fmt(ty)}"/>`);
|
|
335
|
+
parts.push(`<text class="stdlib-chart-tick-label" x="${fmt(g.x0 - GAP_PX * units)}" y="${fmt(ty)}" dy="4" text-anchor="end">${escapeXml(ticks(tick))}</text>`);
|
|
336
|
+
}
|
|
337
|
+
if (opts.yAxis?.minorTicks && !g.scale.log) g.scale.ticks.slice(1).forEach((tick, index) => {
|
|
338
|
+
const previous = g.scale.ticks[index];
|
|
339
|
+
for (let step = 1; step < 5; step++) {
|
|
340
|
+
const ty = y(previous + (tick - previous) * step / 5);
|
|
341
|
+
parts.push(`<line class="stdlib-chart-minor-tick" x1="${fmt(g.x0 - 3)}" y1="${fmt(ty)}" x2="${fmt(g.x0)}" y2="${fmt(ty)}"/>`);
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
const baseline = g.scale.log ? g.plotBottom : y(0);
|
|
345
|
+
parts.push(`<line class="stdlib-chart-axis" x1="${fmt(g.x0)}" y1="${fmt(baseline)}" x2="${fmt(g.x1)}" y2="${fmt(baseline)}"/>`);
|
|
346
|
+
const slot = (g.x1 - g.x0) / finite.length;
|
|
347
|
+
const barWidth = Math.min(slot * 0.8, COLUMN_MAX);
|
|
348
|
+
// Text keeps its pixel size around its x/y anchor (`.k2b-chart` CSS), and so does a `dy` offset: labels anchored on
|
|
349
|
+
// the plot's bottom edge stay clear of the axis in a box shorter than the drawing.
|
|
350
|
+
const labelY = g.y1;
|
|
351
|
+
// Unordered columns fit every label (see columnsFit); ordered ones label every n-th column that leaves room, from
|
|
352
|
+
// the first column whose label stays inside the drawing.
|
|
353
|
+
const labelPx = Math.max(...finite.map(({
|
|
354
|
+
item
|
|
355
|
+
}) => chartTextWidth(item.label))) + GAP_PX;
|
|
356
|
+
const labelStep = Math.max(1, Math.ceil(labelPx / (slot / units)));
|
|
357
|
+
const inside = position => {
|
|
358
|
+
const half = chartTextWidth(finite[position].item.label) / 2 * units;
|
|
359
|
+
const center = g.x0 + slot * (position + 0.5);
|
|
360
|
+
return center - half >= 0 && center + half <= width;
|
|
361
|
+
};
|
|
362
|
+
const firstLabel = Math.max(0, finite.findIndex((_, position) => inside(position)));
|
|
363
|
+
finite.forEach(({
|
|
364
|
+
item,
|
|
365
|
+
index
|
|
366
|
+
}, position) => {
|
|
367
|
+
const center = g.x0 + slot * (position + 0.5);
|
|
368
|
+
if (position >= firstLabel && (position - firstLabel) % labelStep === 0 && inside(position)) parts.push(`<text class="stdlib-chart-tick-label stdlib-chart-category-label" x="${fmt(center)}" y="${fmt(labelY)}" dy="16" text-anchor="middle">${escapeXml(item.label)}</text>`);
|
|
369
|
+
if (g.scale.log && item.value <= 0) return;
|
|
370
|
+
const valueY = y(item.value);
|
|
371
|
+
const top = Math.min(valueY, baseline);
|
|
372
|
+
const barHeight = Math.abs(valueY - baseline);
|
|
373
|
+
const x = center - barWidth / 2;
|
|
374
|
+
const series = opts.colorByBar ? colorIndex(item, position) : 0;
|
|
375
|
+
parts.push(chartDatumSvg(`<rect class="stdlib-chart-bar stdlib-chart-series-${series}" x="${fmt(x)}" y="${fmt(top)}" width="${fmt(barWidth)}" height="${fmt(barHeight)}"/>`, datum(item, index, [center, top + barHeight / 2], format), inspect));
|
|
376
|
+
if (showValues) parts.push(`<text class="stdlib-chart-bar-value" x="${fmt(center)}" y="${fmt(item.value < 0 ? top + barHeight + 13 : top - 4)}" text-anchor="middle">${escapeXml(format(item.value))}</text>`);
|
|
377
|
+
});
|
|
378
|
+
for (const ref of opts.references ?? []) {
|
|
379
|
+
if ((ref.axis ?? "y") !== "y" || !Number.isFinite(ref.value) || ref.value < g.scale.domain[0] || ref.value > g.scale.domain[1]) continue;
|
|
380
|
+
const ry = y(ref.value);
|
|
381
|
+
parts.push(`<line class="stdlib-chart-reference" x1="${fmt(g.x0)}" y1="${fmt(ry)}" x2="${fmt(g.x1)}" y2="${fmt(ry)}"/>`);
|
|
382
|
+
if (ref.label) parts.push(`<text class="stdlib-chart-reference-label" x="${fmt(g.x1 - 4)}" y="${fmt(ry - 4)}" text-anchor="end">${escapeXml(ref.label)}</text>`);
|
|
383
|
+
}
|
|
384
|
+
if (opts.xAxis?.label) parts.push(`<text class="stdlib-chart-axis-label" x="${fmt((g.x0 + g.x1) / 2)}" y="${fmt(labelY)}" dy="34" text-anchor="middle">${escapeXml(opts.xAxis.label)}</text>`);
|
|
385
|
+
if (g.legendRows) {
|
|
386
|
+
const legend = legendLayout(opts, finite, width);
|
|
387
|
+
const top = height - g.legendRows * LEGEND_ROW;
|
|
388
|
+
parts.push('<g class="stdlib-chart-legend">');
|
|
389
|
+
legend.items.forEach((row, rowIndex) => {
|
|
390
|
+
const middle = top + rowIndex * LEGEND_ROW + LEGEND_ROW / 2;
|
|
391
|
+
for (const entry of row) parts.push(`<g class="stdlib-chart-legend-item stdlib-chart-series-${entry.color}"><rect class="stdlib-chart-legend-swatch" x="${fmt(entry.x)}" y="${fmt(middle - 4)}" width="${fmt(8 * units)}" height="8" rx="1"/><text class="stdlib-chart-legend-label" x="${fmt(entry.x + 12 * units)}" y="${fmt(middle + 4)}">${escapeXml(entry.label)}</text></g>`);
|
|
392
|
+
});
|
|
393
|
+
parts.push("</g>");
|
|
394
|
+
}
|
|
395
|
+
return parts.join("");
|
|
396
|
+
};
|
|
397
|
+
const renderRows = (opts, plan, width, inspect) => {
|
|
398
|
+
const {
|
|
399
|
+
finite,
|
|
400
|
+
header
|
|
401
|
+
} = plan;
|
|
402
|
+
const units = width / narrow(opts);
|
|
403
|
+
const g = rowGeometry(opts, finite, width, header);
|
|
404
|
+
const format = valueFormat(opts);
|
|
405
|
+
const scale = valueScale(finite.map(({
|
|
406
|
+
item
|
|
407
|
+
}) => item.value), opts.yAxis, !g.showValues);
|
|
408
|
+
const x = value => project(scale, value, [g.x0, g.x1]);
|
|
409
|
+
const baseline = scale.log ? g.x0 : x(0);
|
|
410
|
+
const plotBottom = g.top + g.pitch * finite.length;
|
|
411
|
+
const thickness = Math.min(BAR_MAX, g.pitch - (g.twoLines ? 14 : 8));
|
|
412
|
+
const parts = [renderHeader(opts, width)];
|
|
413
|
+
if (opts.xAxis?.label) parts.push(`<text class="stdlib-chart-axis-label" x="0" y="${fmt(g.top - 8)}" text-anchor="start">${escapeXml(opts.xAxis.label)}</text>`);
|
|
414
|
+
if (opts.yAxis?.label) parts.push(`<text class="stdlib-chart-axis-label" x="${width}" y="${fmt(g.top - 8)}" text-anchor="end">${escapeXml(opts.yAxis.label)}</text>`);
|
|
415
|
+
if (!g.showValues) {
|
|
416
|
+
const ticks = tickFormat(opts);
|
|
417
|
+
for (const tick of scale.ticks) {
|
|
418
|
+
const tx = x(tick);
|
|
419
|
+
parts.push(`<line class="stdlib-chart-grid" x1="${fmt(tx)}" y1="${fmt(g.top)}" x2="${fmt(tx)}" y2="${fmt(plotBottom)}"/>`);
|
|
420
|
+
parts.push(`<text class="stdlib-chart-tick-label" x="${fmt(tx)}" y="${fmt(plotBottom + 16)}" text-anchor="middle">${escapeXml(ticks(tick))}</text>`);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
finite.forEach(({
|
|
424
|
+
item,
|
|
425
|
+
index
|
|
426
|
+
}, position) => {
|
|
427
|
+
const rowTop = g.top + g.pitch * position;
|
|
428
|
+
const middle = rowTop + g.pitch / 2;
|
|
429
|
+
const label = g.labels[position];
|
|
430
|
+
const title = label.truncated ? `<title>${escapeXml(item.label)}</title>` : "";
|
|
431
|
+
label.lines.forEach((line, lineIndex) => {
|
|
432
|
+
const lineY = middle + 4 + (label.lines.length > 1 ? lineIndex === 0 ? -6.5 : 6.5 : 0);
|
|
433
|
+
parts.push(`<text class="stdlib-chart-tick-label stdlib-chart-category-label" x="${fmt(g.labelEnd)}" y="${fmt(lineY)}" text-anchor="end">${title}${escapeXml(line)}</text>`);
|
|
434
|
+
});
|
|
435
|
+
if (scale.log && item.value <= 0) return;
|
|
436
|
+
const valueX = x(item.value);
|
|
437
|
+
const left = Math.min(valueX, baseline);
|
|
438
|
+
const barWidth = Math.abs(valueX - baseline);
|
|
439
|
+
const series = opts.colorByBar ? colorIndex(item, position) : 0;
|
|
440
|
+
parts.push(chartDatumSvg(`<rect class="stdlib-chart-bar stdlib-chart-series-${series}" x="${fmt(left)}" y="${fmt(middle - thickness / 2)}" width="${fmt(barWidth)}" height="${fmt(thickness)}"/>`, datum(item, index, [left + barWidth / 2, middle], format), inspect));
|
|
441
|
+
if (g.showValues) {
|
|
442
|
+
const negative = item.value < 0;
|
|
443
|
+
parts.push(`<text class="stdlib-chart-bar-value" x="${fmt(valueX + (negative ? -GAP_PX : GAP_PX) * units)}" y="${fmt(middle + 4)}" text-anchor="${negative ? "end" : "start"}">${escapeXml(format(item.value))}</text>`);
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
parts.push(`<line class="stdlib-chart-axis" x1="${fmt(baseline)}" y1="${fmt(g.top)}" x2="${fmt(baseline)}" y2="${fmt(plotBottom)}"/>`);
|
|
447
|
+
for (const ref of opts.references ?? []) {
|
|
448
|
+
if ((ref.axis ?? "y") !== "y" || !Number.isFinite(ref.value) || ref.value < scale.domain[0] || ref.value > scale.domain[1]) continue;
|
|
449
|
+
const rx = x(ref.value);
|
|
450
|
+
parts.push(`<line class="stdlib-chart-reference" x1="${fmt(rx)}" y1="${fmt(g.top)}" x2="${fmt(rx)}" y2="${fmt(plotBottom)}"/>`);
|
|
451
|
+
if (ref.label) parts.push(`<text class="stdlib-chart-reference-label" x="${fmt(rx)}" y="${fmt(g.top - 8)}" text-anchor="middle">${escapeXml(ref.label)}</text>`);
|
|
452
|
+
}
|
|
453
|
+
return parts.join("");
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Render a bar chart in which every category has its label. Few short labels stand below vertical columns; otherwise
|
|
458
|
+
* each category becomes a horizontal row with its label left of the bar and its value at the bar's end. Rows grow the
|
|
459
|
+
* drawing instead of dropping labels: use {@link barChartLayout} for its logical height.
|
|
460
|
+
*/
|
|
461
|
+
export const renderBarChartSvg = opts => {
|
|
462
|
+
const plan = barChartPlan(opts, opts.width);
|
|
463
|
+
// The empty drawing of stdlib's bar chart, written here so bundles leave out stdlib's whole bar renderer.
|
|
464
|
+
if (!plan.finite.length) return svgRoot({
|
|
465
|
+
width: opts.width,
|
|
466
|
+
height: opts.height,
|
|
467
|
+
className: opts.className
|
|
468
|
+
}, `<text class="stdlib-chart-empty-text" x="${fmt(opts.width / 2)}" y="${fmt(opts.height / 2)}" text-anchor="middle" dominant-baseline="middle">no data</text>`);
|
|
469
|
+
const body = plan.layout === "rows" ? renderRows(opts, plan, opts.width, opts.inspect ?? false) : renderColumns(opts, plan, opts.width, opts.height, opts.inspect ?? false);
|
|
470
|
+
return svgRoot({
|
|
471
|
+
width: opts.width,
|
|
472
|
+
height: opts.height,
|
|
473
|
+
className: opts.className
|
|
474
|
+
}, body).replace("<svg ", `<svg data-bar-layout="${plan.layout}" `);
|
|
475
|
+
};
|
|
476
|
+
//# sourceMappingURL=chart-bar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["content/chart-bar.ts"],"sourcesContent":["import {\n type AxisOptions,\n type BarItem,\n chartDatumSvg,\n computeDomain,\n escapeXml,\n extendDomainToNice,\n mapLog,\n mapRange,\n niceLogTicks,\n niceStep,\n type ReferenceLine,\n svgRoot,\n} from \"@k2b/stdlib\";\n\n/**\n * Bar chart options: stdlib's `charts.bar` options plus a title for the category axis and a separate value format.\n * The wrapper owns size and inspection.\n */\nexport type BarChartOptions = {\n data: BarItem[];\n /** Value axis. `label` titles it, `format` writes its ticks and, without `valueFormat`, the printed values. */\n yAxis?: AxisOptions;\n /**\n * Category axis. `label` titles it. `ordered` marks categories that follow each other, such as days or steps: they\n * stay columns, and only every n-th label shows when they would not fit, as on a time axis. Unordered categories each\n * keep their label and turn into rows instead.\n */\n xAxis?: { label?: string; ordered?: boolean };\n /** Writes printed values and tooltip values. Defaults to `yAxis.format`. */\n valueFormat?: (value: number) => string;\n colorByBar?: boolean;\n references?: ReferenceLine[];\n /** Print every value at its bar. Default: whenever the values stay readable; rows always print them. */\n showValues?: boolean;\n /** A legend of the bar colors; used only with `colorByBar` in columns, where labels sit below the plot. */\n legend?: boolean;\n className?: string;\n title?: string;\n subtitle?: string;\n /**\n * The narrowest width in CSS pixels at which the drawing is shown; labels are laid out to fit it. Defaults to a\n * 320px phone column. A host that draws at its measured width passes that width.\n */\n displayWidth?: number;\n /** Logical insets of the column layout. Rows place their labels and values themselves. */\n padding?: number | { top?: number; right?: number; bottom?: number; left?: number };\n};\n\nexport type BarChartLayout = \"columns\" | \"rows\";\n\n/**\n * Text keeps its pixel size while the drawing stretches to its box, and the drawing is never measured. Labels are\n * laid out for the narrowest chart, a 320px phone column, so they fit in every wider one.\n */\nconst NARROW_PX = 296;\n/** Tick, category and value labels are 11px (see the `.k2b-chart` rules). */\nconst FONT_PX = 11;\n/** A label column takes at most this share of the narrowest chart; longer labels wrap to a second line. */\nconst LABEL_SHARE = 0.4;\nconst ROW_MIN = 22;\nconst ROW_TWO_LINES = 32;\nconst ROW_MAX = 36;\n/** Rows aim for the height of the other Cartesian charts before they grow. */\nconst ROWS_TARGET_HEIGHT = 280;\nconst BAR_MAX = 20;\nconst COLUMN_MAX = 40;\nconst GAP_PX = 6;\nconst LEGEND_ROW = 20;\n/** Rows keep at least this share of the narrowest chart for their bars; wider values go to the tooltip and table. */\nconst MIN_PLOT_SHARE = 0.3;\n\nconst narrow = (opts: BarChartOptions) => opts.displayWidth ?? NARROW_PX;\nconst fmt = (value: number) => (Number.isFinite(value) ? `${Math.round(value * 100) / 100}` : \"0\");\n\n/** Estimated width of `text` at `size` pixels in the UI sans font with tabular figures; a little wide on purpose. */\nexport const chartTextWidth = (text: string, size = FONT_PX): number => {\n let em = 0;\n for (const char of text) {\n if (/[\\s.,:;!|'’ilIjft()[\\]-]/.test(char)) em += 0.34;\n else if (/[MWmw@%]/.test(char)) em += 0.86;\n else if (/[A-Z0-9#$€&]/.test(char)) em += 0.66;\n else if (char.codePointAt(0)! > 0x2e80) em += 1;\n else em += 0.56;\n }\n return em * size;\n};\n\n/** Split a label into at most `lines` lines of `maxPx`; the last line ends with an ellipsis when the label is longer. */\nconst wrapLabel = (label: string, maxPx: number, lines: number): { lines: string[]; truncated: boolean } => {\n const words = label.trim().split(/\\s+/);\n const result: string[] = [];\n let current = \"\";\n const breakWord = (word: string) => {\n // A word wider than a line breaks inside the word.\n let part = \"\";\n for (const char of word) {\n if (part && chartTextWidth(part + char) > maxPx) {\n result.push(part);\n part = \"\";\n }\n part += char;\n }\n return part;\n };\n for (const word of words) {\n const candidate = current ? `${current} ${word}` : word;\n if (chartTextWidth(candidate) <= maxPx) current = candidate;\n else {\n if (current) result.push(current);\n current = chartTextWidth(word) > maxPx ? breakWord(word) : word;\n }\n }\n if (current) result.push(current);\n if (result.length <= lines) return { lines: result, truncated: false };\n let last = result[lines - 1]!;\n while (last && chartTextWidth(`${last}…`) > maxPx) last = last.slice(0, -1).trimEnd();\n return { lines: [...result.slice(0, lines - 1), `${last}…`], truncated: true };\n};\n\ntype Scale = { domain: [number, number]; ticks: number[]; log: boolean };\n\n/** The value scale of stdlib's bar chart: nice linear ticks including zero, or decades on a log axis. */\nconst valueScale = (values: number[], axis: AxisOptions | undefined, nice: boolean): Scale => {\n const log = axis?.scale === \"log\";\n if (axis?.domain) {\n const [lo, hi] = axis.domain;\n if (!Number.isFinite(lo) || !Number.isFinite(hi) || lo >= hi || (log && lo <= 0))\n throw new RangeError(\"Chart axis domain must have finite increasing bounds (positive for log scales)\");\n // Bars rest on zero, so a linear domain must contain it like every value.\n if ((log ? values : [...values, 0]).some((value) => (!log || value > 0) && (value < lo || value > hi)))\n throw new RangeError(\"Chart axis domain must contain all plotted values and bounds\");\n if (log) return { domain: [lo, hi], ticks: niceLogTicks(lo, hi).ticks.filter((tick) => tick >= lo && tick <= hi), log };\n const step = niceStep(hi - lo, axis.ticks ?? 5);\n const ticks = [lo];\n if (step > 0 && Number.isFinite(step))\n for (let value = Math.ceil(lo / step) * step; value < hi; ) {\n if (value > lo) ticks.push(value);\n const next = value + step;\n if (next <= value) break;\n value = next;\n }\n return { domain: [lo, hi], ticks: [...ticks, hi], log };\n }\n if (log) {\n const positive = values.filter((value) => value > 0);\n if (!positive.length) return { domain: [1, 10], ticks: [1, 10], log };\n return { ...niceLogTicks(Math.min(...positive), Math.max(...positive)), log };\n }\n const [min, max] = computeDomain([...values, 0]);\n if (!nice) return { domain: [min, max], ticks: [], log };\n return { ...extendDomainToNice(min, max, niceStep(max - min, axis?.ticks ?? 5)), log };\n};\n\nconst project = (scale: Scale, value: number, range: [number, number]) => (scale.log ? mapLog : mapRange)(value, scale.domain, range);\n\ntype Plan = {\n layout: BarChartLayout;\n height: number;\n finite: { item: BarItem; index: number }[];\n header: number;\n};\n\nconst finiteItems = (data: BarItem[]) => data.flatMap((item, index) => (Number.isFinite(item.value) ? [{ item, index }] : []));\nconst headerHeight = (opts: BarChartOptions) => (opts.title || opts.subtitle ? (opts.title ? 14 : 0) + (opts.subtitle ? 6 : 0) + 16 : 0);\nconst valueFormat = (opts: BarChartOptions) => opts.valueFormat ?? opts.yAxis?.format ?? ((value: number) => String(value));\nconst tickFormat = (opts: BarChartOptions) => opts.yAxis?.format ?? ((value: number) => String(value));\n\n/** Columns, when every category label fits below its column on the narrowest chart; rows otherwise. */\nconst columnsFit = (opts: BarChartOptions, finite: Plan[\"finite\"], width: number) => {\n const units = width / narrow(opts);\n const columns = columnGeometry(opts, finite, width, 280);\n const slotPx = (columns.x1 - columns.x0) / finite.length / units;\n if (finite.some(({ item }) => chartTextWidth(item.label) + GAP_PX > slotPx)) return false;\n // Asked-for values must stay readable too; rows always have room for them.\n return opts.showValues !== true || columns.valuesFit;\n};\n\n/** The renderer's plan for a chart: its layout and logical height at `width`, derived from the data alone. */\nconst barChartPlan = (opts: BarChartOptions, width = 480): Plan => {\n const finite = finiteItems(opts.data);\n const header = headerHeight(opts);\n if (!finite.length) return { layout: \"columns\", height: 280, finite, header };\n if (opts.xAxis?.ordered || columnsFit(opts, finite, width)) return { layout: \"columns\", height: 280, finite, header };\n const rows = rowGeometry(opts, finite, width, header);\n return { layout: \"rows\", height: rows.height, finite, header };\n};\n\n/** The layout a bar chart takes and its logical height, so server and browser reserve the same box. */\nexport const barChartLayout = (opts: BarChartOptions, width = 480): { layout: BarChartLayout; height: number } => {\n const { layout, height } = barChartPlan(opts, width);\n return { layout, height };\n};\n\nconst columnGeometry = (opts: BarChartOptions, finite: Plan[\"finite\"], width: number, height: number) => {\n const units = width / narrow(opts);\n const given =\n typeof opts.padding === \"number\" ? { top: opts.padding, right: opts.padding, bottom: opts.padding, left: opts.padding } : opts.padding;\n const values = finite.map(({ item }) => item.value);\n const scale = valueScale(values, opts.yAxis, true);\n const ticks = tickFormat(opts);\n const longestTick = Math.max(0, ...scale.ticks.map((tick) => chartTextWidth(ticks(tick))));\n const legendRows = opts.colorByBar && opts.legend ? legendLayout(opts, finite, width).rows : 0;\n const header = headerHeight(opts);\n const x0 = given?.left ?? Math.max(40, Math.ceil((longestTick + GAP_PX + 2) * units));\n const x1 = width - (given?.right ?? 16);\n const y0 = header + (given?.top ?? 16) + (opts.yAxis?.label ? 16 : 0);\n const y1 = height - (given?.bottom ?? 22) - (opts.xAxis?.label ? 16 : 0) - legendRows * LEGEND_ROW;\n const slotPx = (x1 - x0) / Math.max(1, finite.length) / units;\n const format = valueFormat(opts);\n const valuesFit = finite.every(({ item }) => chartTextWidth(format(item.value)) + 2 <= slotPx);\n const printValues = opts.showValues ?? valuesFit;\n // A printed negative value hangs below its bar: the plot ends a line above the category labels.\n const plotBottom = y1 - (printValues && values.some((value) => value < 0) ? 14 : 0);\n return { x0, x1, y0, y1, plotBottom, scale, valuesFit, printValues, legendRows };\n};\n\nconst rowGeometry = (opts: BarChartOptions, finite: Plan[\"finite\"], width: number, header: number) => {\n const printed = rowGeometryWith(opts, finite, width, header, opts.showValues !== false);\n // Values too wide to leave the bars room stay in the tooltip and table; a value axis replaces them.\n if (printed.showValues && (printed.x1 - printed.x0) / (width / narrow(opts)) < narrow(opts) * MIN_PLOT_SHARE)\n return rowGeometryWith(opts, finite, width, header, false);\n return printed;\n};\n\nconst rowGeometryWith = (opts: BarChartOptions, finite: Plan[\"finite\"], width: number, header: number, showValues: boolean) => {\n const units = width / narrow(opts);\n const maxLabelPx = narrow(opts) * LABEL_SHARE;\n const labels = finite.map(({ item }) => wrapLabel(item.label, maxLabelPx, 2));\n const twoLines = labels.some((label) => label.lines.length > 1);\n const labelPx = Math.min(maxLabelPx, Math.max(0, ...labels.flatMap((label) => label.lines.map((line) => chartTextWidth(line)))));\n const format = valueFormat(opts);\n const positivePx = showValues\n ? Math.max(0, ...finite.filter(({ item }) => item.value >= 0).map(({ item }) => chartTextWidth(format(item.value))))\n : 0;\n const negativePx = showValues\n ? Math.max(0, ...finite.filter(({ item }) => item.value < 0).map(({ item }) => chartTextWidth(format(item.value))))\n : 0;\n const refLabels = (opts.references ?? []).some((ref) => (ref.axis ?? \"y\") === \"y\" && ref.label);\n const titled = !!(opts.xAxis?.label || opts.yAxis?.label || refLabels);\n const top = header + (titled ? 20 : 4);\n const bottom = showValues ? 4 : 24;\n const minimum = twoLines ? ROW_TWO_LINES : ROW_MIN;\n const pitch = Math.min(ROW_MAX, Math.max(minimum, (ROWS_TARGET_HEIGHT - top - bottom) / finite.length));\n const labelEnd = Math.ceil(labelPx * units);\n const x0 = labelEnd + GAP_PX * units + (negativePx ? (negativePx + GAP_PX) * units : 0);\n const x1 = width - (positivePx ? (positivePx + GAP_PX) * units : 8 * units);\n return { labels, labelEnd, x0, x1, top, pitch, twoLines, showValues, height: Math.ceil(top + pitch * finite.length + bottom) };\n};\n\nconst legendLayout = (opts: BarChartOptions, finite: Plan[\"finite\"], width: number) => {\n const units = width / narrow(opts);\n const rows: { label: string; color: number; x: number }[][] = [[]];\n let cursor = 0;\n finite.forEach(({ item }, index) => {\n const itemWidth = (8 + 4 + chartTextWidth(item.label)) * units;\n if (cursor > 0 && cursor + 12 * units + itemWidth > width) {\n rows.push([]);\n cursor = 0;\n }\n const x = cursor ? cursor + 12 * units : 0;\n rows.at(-1)!.push({ label: item.label, color: colorIndex(item, index), x });\n cursor = x + itemWidth;\n });\n return { rows: rows.length, items: rows };\n};\n\nconst colorIndex = (item: BarItem, fallback: number) => {\n const index = item.colorIndex ?? fallback;\n if (!Number.isInteger(index) || index < 0) throw new RangeError(\"Chart colorIndex must be a nonnegative integer\");\n return index % 8;\n};\n\nconst renderHeader = (opts: BarChartOptions, width: number) => {\n const parts: string[] = [];\n let y = 16;\n if (opts.title) {\n parts.push(`<text class=\"stdlib-chart-title\" x=\"${fmt(width / 2)}\" y=\"${y}\" text-anchor=\"middle\">${escapeXml(opts.title)}</text>`);\n y += 14;\n }\n if (opts.subtitle)\n parts.push(\n `<text class=\"stdlib-chart-subtitle\" x=\"${fmt(width / 2)}\" y=\"${y}\" text-anchor=\"middle\">${escapeXml(opts.subtitle)}</text>`,\n );\n return parts.join(\"\");\n};\n\nconst datum = (item: BarItem, index: number, anchor: [number, number], format: (value: number) => string) => ({\n index,\n role: \"item\" as const,\n label: item.label,\n anchor,\n values: [{ key: \"value\", value: item.value, formatted: format(item.value) }],\n});\n\nconst renderColumns = (opts: BarChartOptions, plan: Plan, width: number, height: number, inspect: boolean) => {\n const { finite } = plan;\n const units = width / narrow(opts);\n const g = columnGeometry(opts, finite, width, height);\n const ticks = tickFormat(opts);\n const format = valueFormat(opts);\n const showValues = g.printValues;\n const parts: string[] = [renderHeader(opts, width)];\n const y = (value: number) => project(g.scale, value, [g.plotBottom, g.y0]);\n if (opts.yAxis?.label)\n parts.push(\n `<text class=\"stdlib-chart-axis-label\" x=\"0\" y=\"${fmt(g.y0 - 8)}\" text-anchor=\"start\">${escapeXml(opts.yAxis.label)}</text>`,\n );\n for (const tick of g.scale.ticks) {\n const ty = y(tick);\n parts.push(`<line class=\"stdlib-chart-grid\" x1=\"${fmt(g.x0)}\" y1=\"${fmt(ty)}\" x2=\"${fmt(g.x1)}\" y2=\"${fmt(ty)}\"/>`);\n parts.push(\n `<text class=\"stdlib-chart-tick-label\" x=\"${fmt(g.x0 - GAP_PX * units)}\" y=\"${fmt(ty)}\" dy=\"4\" text-anchor=\"end\">${escapeXml(ticks(tick))}</text>`,\n );\n }\n if (opts.yAxis?.minorTicks && !g.scale.log)\n g.scale.ticks.slice(1).forEach((tick, index) => {\n const previous = g.scale.ticks[index]!;\n for (let step = 1; step < 5; step++) {\n const ty = y(previous + ((tick - previous) * step) / 5);\n parts.push(`<line class=\"stdlib-chart-minor-tick\" x1=\"${fmt(g.x0 - 3)}\" y1=\"${fmt(ty)}\" x2=\"${fmt(g.x0)}\" y2=\"${fmt(ty)}\"/>`);\n }\n });\n const baseline = g.scale.log ? g.plotBottom : y(0);\n parts.push(`<line class=\"stdlib-chart-axis\" x1=\"${fmt(g.x0)}\" y1=\"${fmt(baseline)}\" x2=\"${fmt(g.x1)}\" y2=\"${fmt(baseline)}\"/>`);\n const slot = (g.x1 - g.x0) / finite.length;\n const barWidth = Math.min(slot * 0.8, COLUMN_MAX);\n // Text keeps its pixel size around its x/y anchor (`.k2b-chart` CSS), and so does a `dy` offset: labels anchored on\n // the plot's bottom edge stay clear of the axis in a box shorter than the drawing.\n const labelY = g.y1;\n // Unordered columns fit every label (see columnsFit); ordered ones label every n-th column that leaves room, from\n // the first column whose label stays inside the drawing.\n const labelPx = Math.max(...finite.map(({ item }) => chartTextWidth(item.label))) + GAP_PX;\n const labelStep = Math.max(1, Math.ceil(labelPx / (slot / units)));\n const inside = (position: number) => {\n const half = (chartTextWidth(finite[position]!.item.label) / 2) * units;\n const center = g.x0 + slot * (position + 0.5);\n return center - half >= 0 && center + half <= width;\n };\n const firstLabel = Math.max(\n 0,\n finite.findIndex((_, position) => inside(position)),\n );\n finite.forEach(({ item, index }, position) => {\n const center = g.x0 + slot * (position + 0.5);\n if (position >= firstLabel && (position - firstLabel) % labelStep === 0 && inside(position))\n parts.push(\n `<text class=\"stdlib-chart-tick-label stdlib-chart-category-label\" x=\"${fmt(center)}\" y=\"${fmt(labelY)}\" dy=\"16\" text-anchor=\"middle\">${escapeXml(item.label)}</text>`,\n );\n if (g.scale.log && item.value <= 0) return;\n const valueY = y(item.value);\n const top = Math.min(valueY, baseline);\n const barHeight = Math.abs(valueY - baseline);\n const x = center - barWidth / 2;\n const series = opts.colorByBar ? colorIndex(item, position) : 0;\n parts.push(\n chartDatumSvg(\n `<rect class=\"stdlib-chart-bar stdlib-chart-series-${series}\" x=\"${fmt(x)}\" y=\"${fmt(top)}\" width=\"${fmt(barWidth)}\" height=\"${fmt(barHeight)}\"/>`,\n datum(item, index, [center, top + barHeight / 2], format),\n inspect,\n ),\n );\n if (showValues)\n parts.push(\n `<text class=\"stdlib-chart-bar-value\" x=\"${fmt(center)}\" y=\"${fmt(item.value < 0 ? top + barHeight + 13 : top - 4)}\" text-anchor=\"middle\">${escapeXml(format(item.value))}</text>`,\n );\n });\n for (const ref of opts.references ?? []) {\n if ((ref.axis ?? \"y\") !== \"y\" || !Number.isFinite(ref.value) || ref.value < g.scale.domain[0] || ref.value > g.scale.domain[1])\n continue;\n const ry = y(ref.value);\n parts.push(`<line class=\"stdlib-chart-reference\" x1=\"${fmt(g.x0)}\" y1=\"${fmt(ry)}\" x2=\"${fmt(g.x1)}\" y2=\"${fmt(ry)}\"/>`);\n if (ref.label)\n parts.push(\n `<text class=\"stdlib-chart-reference-label\" x=\"${fmt(g.x1 - 4)}\" y=\"${fmt(ry - 4)}\" text-anchor=\"end\">${escapeXml(ref.label)}</text>`,\n );\n }\n if (opts.xAxis?.label)\n parts.push(\n `<text class=\"stdlib-chart-axis-label\" x=\"${fmt((g.x0 + g.x1) / 2)}\" y=\"${fmt(labelY)}\" dy=\"34\" text-anchor=\"middle\">${escapeXml(opts.xAxis.label)}</text>`,\n );\n if (g.legendRows) {\n const legend = legendLayout(opts, finite, width);\n const top = height - g.legendRows * LEGEND_ROW;\n parts.push('<g class=\"stdlib-chart-legend\">');\n legend.items.forEach((row, rowIndex) => {\n const middle = top + rowIndex * LEGEND_ROW + LEGEND_ROW / 2;\n for (const entry of row)\n parts.push(\n `<g class=\"stdlib-chart-legend-item stdlib-chart-series-${entry.color}\"><rect class=\"stdlib-chart-legend-swatch\" x=\"${fmt(entry.x)}\" y=\"${fmt(middle - 4)}\" width=\"${fmt(8 * units)}\" height=\"8\" rx=\"1\"/><text class=\"stdlib-chart-legend-label\" x=\"${fmt(entry.x + 12 * units)}\" y=\"${fmt(middle + 4)}\">${escapeXml(entry.label)}</text></g>`,\n );\n });\n parts.push(\"</g>\");\n }\n return parts.join(\"\");\n};\n\nconst renderRows = (opts: BarChartOptions, plan: Plan, width: number, inspect: boolean) => {\n const { finite, header } = plan;\n const units = width / narrow(opts);\n const g = rowGeometry(opts, finite, width, header);\n const format = valueFormat(opts);\n const scale = valueScale(\n finite.map(({ item }) => item.value),\n opts.yAxis,\n !g.showValues,\n );\n const x = (value: number) => project(scale, value, [g.x0, g.x1]);\n const baseline = scale.log ? g.x0 : x(0);\n const plotBottom = g.top + g.pitch * finite.length;\n const thickness = Math.min(BAR_MAX, g.pitch - (g.twoLines ? 14 : 8));\n const parts: string[] = [renderHeader(opts, width)];\n if (opts.xAxis?.label)\n parts.push(\n `<text class=\"stdlib-chart-axis-label\" x=\"0\" y=\"${fmt(g.top - 8)}\" text-anchor=\"start\">${escapeXml(opts.xAxis.label)}</text>`,\n );\n if (opts.yAxis?.label)\n parts.push(\n `<text class=\"stdlib-chart-axis-label\" x=\"${width}\" y=\"${fmt(g.top - 8)}\" text-anchor=\"end\">${escapeXml(opts.yAxis.label)}</text>`,\n );\n if (!g.showValues) {\n const ticks = tickFormat(opts);\n for (const tick of scale.ticks) {\n const tx = x(tick);\n parts.push(`<line class=\"stdlib-chart-grid\" x1=\"${fmt(tx)}\" y1=\"${fmt(g.top)}\" x2=\"${fmt(tx)}\" y2=\"${fmt(plotBottom)}\"/>`);\n parts.push(\n `<text class=\"stdlib-chart-tick-label\" x=\"${fmt(tx)}\" y=\"${fmt(plotBottom + 16)}\" text-anchor=\"middle\">${escapeXml(ticks(tick))}</text>`,\n );\n }\n }\n finite.forEach(({ item, index }, position) => {\n const rowTop = g.top + g.pitch * position;\n const middle = rowTop + g.pitch / 2;\n const label = g.labels[position]!;\n const title = label.truncated ? `<title>${escapeXml(item.label)}</title>` : \"\";\n label.lines.forEach((line, lineIndex) => {\n const lineY = middle + 4 + (label.lines.length > 1 ? (lineIndex === 0 ? -6.5 : 6.5) : 0);\n parts.push(\n `<text class=\"stdlib-chart-tick-label stdlib-chart-category-label\" x=\"${fmt(g.labelEnd)}\" y=\"${fmt(lineY)}\" text-anchor=\"end\">${title}${escapeXml(line)}</text>`,\n );\n });\n if (scale.log && item.value <= 0) return;\n const valueX = x(item.value);\n const left = Math.min(valueX, baseline);\n const barWidth = Math.abs(valueX - baseline);\n const series = opts.colorByBar ? colorIndex(item, position) : 0;\n parts.push(\n chartDatumSvg(\n `<rect class=\"stdlib-chart-bar stdlib-chart-series-${series}\" x=\"${fmt(left)}\" y=\"${fmt(middle - thickness / 2)}\" width=\"${fmt(barWidth)}\" height=\"${fmt(thickness)}\"/>`,\n datum(item, index, [left + barWidth / 2, middle], format),\n inspect,\n ),\n );\n if (g.showValues) {\n const negative = item.value < 0;\n parts.push(\n `<text class=\"stdlib-chart-bar-value\" x=\"${fmt(valueX + (negative ? -GAP_PX : GAP_PX) * units)}\" y=\"${fmt(middle + 4)}\" text-anchor=\"${negative ? \"end\" : \"start\"}\">${escapeXml(format(item.value))}</text>`,\n );\n }\n });\n parts.push(`<line class=\"stdlib-chart-axis\" x1=\"${fmt(baseline)}\" y1=\"${fmt(g.top)}\" x2=\"${fmt(baseline)}\" y2=\"${fmt(plotBottom)}\"/>`);\n for (const ref of opts.references ?? []) {\n if ((ref.axis ?? \"y\") !== \"y\" || !Number.isFinite(ref.value) || ref.value < scale.domain[0] || ref.value > scale.domain[1]) continue;\n const rx = x(ref.value);\n parts.push(`<line class=\"stdlib-chart-reference\" x1=\"${fmt(rx)}\" y1=\"${fmt(g.top)}\" x2=\"${fmt(rx)}\" y2=\"${fmt(plotBottom)}\"/>`);\n if (ref.label)\n parts.push(\n `<text class=\"stdlib-chart-reference-label\" x=\"${fmt(rx)}\" y=\"${fmt(g.top - 8)}\" text-anchor=\"middle\">${escapeXml(ref.label)}</text>`,\n );\n }\n return parts.join(\"\");\n};\n\n/**\n * Render a bar chart in which every category has its label. Few short labels stand below vertical columns; otherwise\n * each category becomes a horizontal row with its label left of the bar and its value at the bar's end. Rows grow the\n * drawing instead of dropping labels: use {@link barChartLayout} for its logical height.\n */\nexport const renderBarChartSvg = (opts: BarChartOptions & { width: number; height: number; inspect?: boolean }): string => {\n const plan = barChartPlan(opts, opts.width);\n // The empty drawing of stdlib's bar chart, written here so bundles leave out stdlib's whole bar renderer.\n if (!plan.finite.length)\n return svgRoot(\n { width: opts.width, height: opts.height, className: opts.className },\n `<text class=\"stdlib-chart-empty-text\" x=\"${fmt(opts.width / 2)}\" y=\"${fmt(opts.height / 2)}\" text-anchor=\"middle\" dominant-baseline=\"middle\">no data</text>`,\n );\n const body =\n plan.layout === \"rows\"\n ? renderRows(opts, plan, opts.width, opts.inspect ?? false)\n : renderColumns(opts, plan, opts.width, opts.height, opts.inspect ?? false);\n return svgRoot({ width: opts.width, height: opts.height, className: opts.className }, body).replace(\n \"<svg \",\n `<svg data-bar-layout=\"${plan.layout}\" `,\n );\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { i18n } from "@k2b/stdlib";
|
|
2
|
+
import { useLocale } from "../intl/locale";
|
|
3
|
+
|
|
4
|
+
/** File kinds and list folding shared by `FileGrid` and `fileKindLabel`. */
|
|
5
|
+
const fileListMessages = i18n.define({
|
|
6
|
+
baseLocale: "en",
|
|
7
|
+
messages: {
|
|
8
|
+
en: {
|
|
9
|
+
folder: "Folder",
|
|
10
|
+
pdf: "PDF",
|
|
11
|
+
image: "Image",
|
|
12
|
+
sheet: "Spreadsheet",
|
|
13
|
+
document: "Document",
|
|
14
|
+
slides: "Presentation",
|
|
15
|
+
video: "Video",
|
|
16
|
+
audio: "Audio",
|
|
17
|
+
archive: "Archive",
|
|
18
|
+
file: "File",
|
|
19
|
+
files: "Files",
|
|
20
|
+
images: "Images",
|
|
21
|
+
showAll: ({
|
|
22
|
+
count
|
|
23
|
+
}) => `Show all ${count}`,
|
|
24
|
+
showLess: "Show less"
|
|
25
|
+
},
|
|
26
|
+
de: {
|
|
27
|
+
folder: "Ordner",
|
|
28
|
+
pdf: "PDF",
|
|
29
|
+
image: "Bild",
|
|
30
|
+
sheet: "Tabelle",
|
|
31
|
+
document: "Dokument",
|
|
32
|
+
slides: "Präsentation",
|
|
33
|
+
video: "Video",
|
|
34
|
+
audio: "Audio",
|
|
35
|
+
archive: "Archiv",
|
|
36
|
+
file: "Datei",
|
|
37
|
+
files: "Dateien",
|
|
38
|
+
images: "Bilder",
|
|
39
|
+
showAll: ({
|
|
40
|
+
count
|
|
41
|
+
}) => `Alle ${count} anzeigen`,
|
|
42
|
+
showLess: "Weniger anzeigen"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
export const resolveFileListMessages = locale => fileListMessages.resolve([locale]).t;
|
|
47
|
+
export const useFileListMessages = () => {
|
|
48
|
+
const locale = useLocale();
|
|
49
|
+
return () => resolveFileListMessages(locale());
|
|
50
|
+
};
|
|
51
|
+
export const checkFileListMessages = () => fileListMessages.check();
|
|
52
|
+
//# sourceMappingURL=file-list-messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["content/file-list-messages.ts"],"sourcesContent":["import { i18n } from \"@k2b/stdlib\";\nimport { useLocale } from \"../intl/locale\";\n\n/** File kinds and list folding shared by `FileGrid` and `fileKindLabel`. */\nconst fileListMessages = i18n.define({\n baseLocale: \"en\",\n messages: {\n en: {\n folder: \"Folder\",\n pdf: \"PDF\",\n image: \"Image\",\n sheet: \"Spreadsheet\",\n document: \"Document\",\n slides: \"Presentation\",\n video: \"Video\",\n audio: \"Audio\",\n archive: \"Archive\",\n file: \"File\",\n files: \"Files\",\n images: \"Images\",\n showAll: ({ count }: { count: number }) => `Show all ${count}`,\n showLess: \"Show less\",\n },\n de: {\n folder: \"Ordner\",\n pdf: \"PDF\",\n image: \"Bild\",\n sheet: \"Tabelle\",\n document: \"Dokument\",\n slides: \"Präsentation\",\n video: \"Video\",\n audio: \"Audio\",\n archive: \"Archiv\",\n file: \"Datei\",\n files: \"Dateien\",\n images: \"Bilder\",\n showAll: ({ count }) => `Alle ${count} anzeigen`,\n showLess: \"Weniger anzeigen\",\n },\n },\n});\n\nexport type FileListMessages = ReturnType<(typeof fileListMessages)[\"resolve\"]>[\"t\"];\n\nexport const resolveFileListMessages = (locale: string): FileListMessages => fileListMessages.resolve([locale]).t;\n\nexport const useFileListMessages = (): (() => FileListMessages) => {\n const locale = useLocale();\n return () => resolveFileListMessages(locale());\n};\n\nexport const checkFileListMessages = () => fileListMessages.check();\n"],"mappings":"AAAA,SAAS,IAAI,QAAQ,aAAa;AAClC,SAAS,SAAS,QAAQ,gBAAgB;;AAE1C;AACA,MAAM,gBAAgB,GAAG,IAAI,CAAC,MAAM,CAAC;EACnC,UAAU,EAAE,IAAI;EAChB,QAAQ,EAAE;IACR,EAAE,EAAE;MACF,MAAM,EAAE,QAAQ;MAChB,GAAG,EAAE,KAAK;MACV,KAAK,EAAE,OAAO;MACd,KAAK,EAAE,aAAa;MACpB,QAAQ,EAAE,UAAU;MACpB,MAAM,EAAE,cAAc;MACtB,KAAK,EAAE,OAAO;MACd,KAAK,EAAE,OAAO;MACd,OAAO,EAAE,SAAS;MAClB,IAAI,EAAE,MAAM;MACZ,KAAK,EAAE,OAAO;MACd,MAAM,EAAE,QAAQ;MAChB,OAAO,EAAE,CAAC;QAAE;MAAyB,CAAC,KAAK,YAAY,KAAK,EAAE;MAC9D,QAAQ,EAAE;IACZ,CAAC;IACD,EAAE,EAAE;MACF,MAAM,EAAE,QAAQ;MAChB,GAAG,EAAE,KAAK;MACV,KAAK,EAAE,MAAM;MACb,KAAK,EAAE,SAAS;MAChB,QAAQ,EAAE,UAAU;MACpB,MAAM,EAAE,cAAc;MACtB,KAAK,EAAE,OAAO;MACd,KAAK,EAAE,OAAO;MACd,OAAO,EAAE,QAAQ;MACjB,IAAI,EAAE,OAAO;MACb,KAAK,EAAE,SAAS;MAChB,MAAM,EAAE,QAAQ;MAChB,OAAO,EAAE,CAAC;QAAE;MAAM,CAAC,KAAK,QAAQ,KAAK,WAAW;MAChD,QAAQ,EAAE;IACZ;EACF;AACF,CAAC,CAAC;AAIF,OAAO,MAAM,uBAAuB,GAAI,MAAc,IAAuB,gBAAgB,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAEjH,OAAO,MAAM,mBAAmB,GAAG,MAAgC;EACjE,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC;EAC1B,OAAO,MAAM,uBAAuB,CAAC,MAAM,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,OAAO,MAAM,qBAAqB,GAAG,MAAM,gBAAgB,CAAC,KAAK,CAAC,CAAC","ignoreList":[]}
|