@nowline/layout 0.2.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/LICENSE +190 -0
- package/README.md +103 -0
- package/dist/band-scale.d.ts +56 -0
- package/dist/band-scale.d.ts.map +1 -0
- package/dist/band-scale.js +86 -0
- package/dist/band-scale.js.map +1 -0
- package/dist/calendar.d.ts +79 -0
- package/dist/calendar.d.ts.map +1 -0
- package/dist/calendar.js +210 -0
- package/dist/calendar.js.map +1 -0
- package/dist/capacity.d.ts +72 -0
- package/dist/capacity.d.ts.map +1 -0
- package/dist/capacity.js +163 -0
- package/dist/capacity.js.map +1 -0
- package/dist/dsl-utils.d.ts +5 -0
- package/dist/dsl-utils.d.ts.map +1 -0
- package/dist/dsl-utils.js +28 -0
- package/dist/dsl-utils.js.map +1 -0
- package/dist/edge-routing.d.ts +89 -0
- package/dist/edge-routing.d.ts.map +1 -0
- package/dist/edge-routing.js +435 -0
- package/dist/edge-routing.js.map +1 -0
- package/dist/frame-tab-geometry.d.ts +78 -0
- package/dist/frame-tab-geometry.d.ts.map +1 -0
- package/dist/frame-tab-geometry.js +115 -0
- package/dist/frame-tab-geometry.js.map +1 -0
- package/dist/header-card-geometry.d.ts +29 -0
- package/dist/header-card-geometry.d.ts.map +1 -0
- package/dist/header-card-geometry.js +41 -0
- package/dist/header-card-geometry.js.map +1 -0
- package/dist/i18n.d.ts +48 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +114 -0
- package/dist/i18n.js.map +1 -0
- package/dist/include-chrome-geometry.d.ts +86 -0
- package/dist/include-chrome-geometry.d.ts.map +1 -0
- package/dist/include-chrome-geometry.js +104 -0
- package/dist/include-chrome-geometry.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/item-bar-geometry.d.ts +127 -0
- package/dist/item-bar-geometry.d.ts.map +1 -0
- package/dist/item-bar-geometry.js +173 -0
- package/dist/item-bar-geometry.js.map +1 -0
- package/dist/lane-utilization.d.ts +90 -0
- package/dist/lane-utilization.d.ts.map +1 -0
- package/dist/lane-utilization.js +206 -0
- package/dist/lane-utilization.js.map +1 -0
- package/dist/layout-context.d.ts +143 -0
- package/dist/layout-context.d.ts.map +1 -0
- package/dist/layout-context.js +8 -0
- package/dist/layout-context.js.map +1 -0
- package/dist/layout.d.ts +18 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +1213 -0
- package/dist/layout.js.map +1 -0
- package/dist/nodes/anchor-node.d.ts +16 -0
- package/dist/nodes/anchor-node.d.ts.map +1 -0
- package/dist/nodes/anchor-node.js +68 -0
- package/dist/nodes/anchor-node.js.map +1 -0
- package/dist/nodes/footnote-node.d.ts +10 -0
- package/dist/nodes/footnote-node.d.ts.map +1 -0
- package/dist/nodes/footnote-node.js +41 -0
- package/dist/nodes/footnote-node.js.map +1 -0
- package/dist/nodes/group-node.d.ts +29 -0
- package/dist/nodes/group-node.d.ts.map +1 -0
- package/dist/nodes/group-node.js +187 -0
- package/dist/nodes/group-node.js.map +1 -0
- package/dist/nodes/include-node.d.ts +16 -0
- package/dist/nodes/include-node.d.ts.map +1 -0
- package/dist/nodes/include-node.js +117 -0
- package/dist/nodes/include-node.js.map +1 -0
- package/dist/nodes/item-node.d.ts +51 -0
- package/dist/nodes/item-node.d.ts.map +1 -0
- package/dist/nodes/item-node.js +108 -0
- package/dist/nodes/item-node.js.map +1 -0
- package/dist/nodes/marker-geometry.d.ts +22 -0
- package/dist/nodes/marker-geometry.d.ts.map +1 -0
- package/dist/nodes/marker-geometry.js +38 -0
- package/dist/nodes/marker-geometry.js.map +1 -0
- package/dist/nodes/milestone-node.d.ts +48 -0
- package/dist/nodes/milestone-node.d.ts.map +1 -0
- package/dist/nodes/milestone-node.js +210 -0
- package/dist/nodes/milestone-node.js.map +1 -0
- package/dist/nodes/parallel-node.d.ts +21 -0
- package/dist/nodes/parallel-node.d.ts.map +1 -0
- package/dist/nodes/parallel-node.js +80 -0
- package/dist/nodes/parallel-node.js.map +1 -0
- package/dist/nodes/roadmap-node.d.ts +76 -0
- package/dist/nodes/roadmap-node.d.ts.map +1 -0
- package/dist/nodes/roadmap-node.js +788 -0
- package/dist/nodes/roadmap-node.js.map +1 -0
- package/dist/nodes/swimlane-node.d.ts +38 -0
- package/dist/nodes/swimlane-node.d.ts.map +1 -0
- package/dist/nodes/swimlane-node.js +308 -0
- package/dist/nodes/swimlane-node.js.map +1 -0
- package/dist/renderable.d.ts +44 -0
- package/dist/renderable.d.ts.map +1 -0
- package/dist/renderable.js +21 -0
- package/dist/renderable.js.map +1 -0
- package/dist/row-packer.d.ts +125 -0
- package/dist/row-packer.d.ts.map +1 -0
- package/dist/row-packer.js +169 -0
- package/dist/row-packer.js.map +1 -0
- package/dist/style-resolution.d.ts +14 -0
- package/dist/style-resolution.d.ts.map +1 -0
- package/dist/style-resolution.js +191 -0
- package/dist/style-resolution.js.map +1 -0
- package/dist/themes/dark.d.ts +4 -0
- package/dist/themes/dark.d.ts.map +1 -0
- package/dist/themes/dark.js +241 -0
- package/dist/themes/dark.js.map +1 -0
- package/dist/themes/index.d.ts +15 -0
- package/dist/themes/index.d.ts.map +1 -0
- package/dist/themes/index.js +30 -0
- package/dist/themes/index.js.map +1 -0
- package/dist/themes/light.d.ts +4 -0
- package/dist/themes/light.d.ts.map +1 -0
- package/dist/themes/light.js +248 -0
- package/dist/themes/light.js.map +1 -0
- package/dist/themes/shape.d.ts +194 -0
- package/dist/themes/shape.d.ts.map +1 -0
- package/dist/themes/shape.js +6 -0
- package/dist/themes/shape.js.map +1 -0
- package/dist/themes/shared.d.ts +145 -0
- package/dist/themes/shared.d.ts.map +1 -0
- package/dist/themes/shared.js +310 -0
- package/dist/themes/shared.js.map +1 -0
- package/dist/time-scale.d.ts +39 -0
- package/dist/time-scale.d.ts.map +1 -0
- package/dist/time-scale.js +62 -0
- package/dist/time-scale.js.map +1 -0
- package/dist/types.d.ts +483 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/view-preset.d.ts +23 -0
- package/dist/view-preset.d.ts.map +1 -0
- package/dist/view-preset.js +146 -0
- package/dist/view-preset.js.map +1 -0
- package/dist/working-calendar.d.ts +14 -0
- package/dist/working-calendar.d.ts.map +1 -0
- package/dist/working-calendar.js +74 -0
- package/dist/working-calendar.js.map +1 -0
- package/package.json +37 -0
- package/src/band-scale.ts +115 -0
- package/src/calendar.ts +244 -0
- package/src/capacity.ts +191 -0
- package/src/dsl-utils.ts +30 -0
- package/src/edge-routing.ts +550 -0
- package/src/frame-tab-geometry.ts +165 -0
- package/src/header-card-geometry.ts +48 -0
- package/src/i18n.ts +124 -0
- package/src/include-chrome-geometry.ts +156 -0
- package/src/index.ts +116 -0
- package/src/item-bar-geometry.ts +222 -0
- package/src/lane-utilization.ts +259 -0
- package/src/layout-context.ts +182 -0
- package/src/layout.ts +1446 -0
- package/src/nodes/anchor-node.ts +77 -0
- package/src/nodes/footnote-node.ts +60 -0
- package/src/nodes/group-node.ts +252 -0
- package/src/nodes/include-node.ts +168 -0
- package/src/nodes/item-node.ts +171 -0
- package/src/nodes/marker-geometry.ts +43 -0
- package/src/nodes/milestone-node.ts +263 -0
- package/src/nodes/parallel-node.ts +101 -0
- package/src/nodes/roadmap-node.ts +957 -0
- package/src/nodes/swimlane-node.ts +423 -0
- package/src/renderable.ts +68 -0
- package/src/row-packer.ts +271 -0
- package/src/style-resolution.ts +243 -0
- package/src/themes/dark.ts +244 -0
- package/src/themes/index.ts +36 -0
- package/src/themes/light.ts +251 -0
- package/src/themes/shape.ts +230 -0
- package/src/themes/shared.ts +369 -0
- package/src/time-scale.ts +78 -0
- package/src/types.ts +607 -0
- package/src/view-preset.ts +180 -0
- package/src/working-calendar.ts +91 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// ViewPreset — declarative configuration for the timeline header
|
|
2
|
+
// (tick stride, label thinning, label format). Replaces the
|
|
3
|
+
// imperative `for` loop and `formatTickLabel` switch in the legacy
|
|
4
|
+
// `timeline.ts`.
|
|
5
|
+
//
|
|
6
|
+
// `resolveScale` parses the DSL `scale:` property (and any nested
|
|
7
|
+
// `scale` block) into a `ViewPreset`. `buildHeaderTicks` produces
|
|
8
|
+
// the `PositionedTick[]` byte-stable with the legacy generator: same
|
|
9
|
+
// x positions, same labelX positions, same major/minor flags, same
|
|
10
|
+
// label text.
|
|
11
|
+
|
|
12
|
+
import type { NowlineFile, ScaleBlock } from '@nowline/core';
|
|
13
|
+
import { addDays } from './calendar.js';
|
|
14
|
+
import { DEFAULT_LOCALE, localeStrings } from './i18n.js';
|
|
15
|
+
import { DEFAULT_PIXELS_PER_DAY, LABEL_THINNING } from './themes/shared.js';
|
|
16
|
+
import type { TimeScale } from './time-scale.js';
|
|
17
|
+
import type { PositionedTick } from './types.js';
|
|
18
|
+
import type { WorkingCalendar } from './working-calendar.js';
|
|
19
|
+
|
|
20
|
+
export type ScaleUnit = 'days' | 'weeks' | 'months' | 'quarters' | 'years';
|
|
21
|
+
|
|
22
|
+
export interface ViewPreset {
|
|
23
|
+
/** Tick stride unit (each tick is one `unit` apart). */
|
|
24
|
+
unit: ScaleUnit;
|
|
25
|
+
/** Show a label every N ticks (1 = every tick gets a label). */
|
|
26
|
+
labelEvery: number;
|
|
27
|
+
/** Pixels per `1 unit` worth of working days. */
|
|
28
|
+
pixelsPerUnit: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// `ScaleConfig` is kept as an alias for source-compat with the few
|
|
32
|
+
// callers that still spell the old name; new code should use
|
|
33
|
+
// `ViewPreset`.
|
|
34
|
+
export type ScaleConfig = ViewPreset;
|
|
35
|
+
|
|
36
|
+
function stripColon(key: string): string {
|
|
37
|
+
return key.endsWith(':') ? key.slice(0, -1) : key;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function resolveScale(file: NowlineFile, scaleBlock: ScaleBlock | undefined): ViewPreset {
|
|
41
|
+
const scaleProp = file.roadmapDecl?.properties.find((p) => stripColon(p.key) === 'scale');
|
|
42
|
+
// `scale:` accepts a unit name (`days`/`weeks`/`months`/`quarters`/`years`)
|
|
43
|
+
// OR a duration literal (`1w`, `2w`, `1m`, `1q`, `1y`). The literal form
|
|
44
|
+
// is the documented default in the DSL spec; it picks the unit and uses
|
|
45
|
+
// the literal's count to size the pixels-per-unit budget.
|
|
46
|
+
const rawScale = scaleProp?.value;
|
|
47
|
+
let unit: ScaleUnit = 'weeks';
|
|
48
|
+
let pixelsPerUnitOverride: number | undefined;
|
|
49
|
+
let labelEveryOverride: number | undefined;
|
|
50
|
+
if (rawScale) {
|
|
51
|
+
if (
|
|
52
|
+
rawScale === 'days' ||
|
|
53
|
+
rawScale === 'weeks' ||
|
|
54
|
+
rawScale === 'months' ||
|
|
55
|
+
rawScale === 'quarters' ||
|
|
56
|
+
rawScale === 'years'
|
|
57
|
+
) {
|
|
58
|
+
unit = rawScale;
|
|
59
|
+
} else {
|
|
60
|
+
const dur = /^(\d+)([dwmqy])$/.exec(rawScale);
|
|
61
|
+
if (dur) {
|
|
62
|
+
const n = Math.max(1, parseInt(dur[1], 10));
|
|
63
|
+
switch (dur[2]) {
|
|
64
|
+
case 'd':
|
|
65
|
+
unit = 'days';
|
|
66
|
+
break;
|
|
67
|
+
case 'w':
|
|
68
|
+
unit = 'weeks';
|
|
69
|
+
break;
|
|
70
|
+
case 'm':
|
|
71
|
+
unit = 'months';
|
|
72
|
+
break;
|
|
73
|
+
case 'q':
|
|
74
|
+
unit = 'quarters';
|
|
75
|
+
break;
|
|
76
|
+
case 'y':
|
|
77
|
+
unit = 'years';
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
pixelsPerUnitOverride = unitPx(unit) * n;
|
|
81
|
+
// A literal scale like `1w` says "I want exactly one label per
|
|
82
|
+
// unit." Override the default thinning so every tick is named.
|
|
83
|
+
labelEveryOverride = 1;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const defaultLabelEvery = labelEveryOverride ?? LABEL_THINNING[unit] ?? 4;
|
|
88
|
+
|
|
89
|
+
if (scaleBlock) {
|
|
90
|
+
const unitProp = scaleBlock.properties.find((p) => stripColon(p.key) === 'unit');
|
|
91
|
+
const resolvedUnit: ScaleUnit = (unitProp?.value as ScaleUnit) ?? unit;
|
|
92
|
+
const labelProp = scaleBlock.properties.find((p) => stripColon(p.key) === 'label-every');
|
|
93
|
+
const pxProp = scaleBlock.properties.find((p) => stripColon(p.key) === 'pixels-per-unit');
|
|
94
|
+
const labelEvery = labelProp
|
|
95
|
+
? Math.max(1, parseInt(labelProp.value, 10) || defaultLabelEvery)
|
|
96
|
+
: defaultLabelEvery;
|
|
97
|
+
const pixelsPerUnit = pxProp
|
|
98
|
+
? Math.max(1, parseInt(pxProp.value, 10) || unitPx(resolvedUnit))
|
|
99
|
+
: (pixelsPerUnitOverride ?? unitPx(resolvedUnit));
|
|
100
|
+
return { unit: resolvedUnit, labelEvery, pixelsPerUnit };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
unit,
|
|
105
|
+
labelEvery: defaultLabelEvery,
|
|
106
|
+
pixelsPerUnit: pixelsPerUnitOverride ?? unitPx(unit),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function unitPx(unit: ScaleUnit): number {
|
|
111
|
+
// Baseline pixel widths per one unit, tuned so ~6 month roadmaps fit
|
|
112
|
+
// comfortably in a 1200 px wide chart area.
|
|
113
|
+
switch (unit) {
|
|
114
|
+
case 'days':
|
|
115
|
+
return DEFAULT_PIXELS_PER_DAY;
|
|
116
|
+
case 'weeks':
|
|
117
|
+
return 40;
|
|
118
|
+
case 'months':
|
|
119
|
+
return 80;
|
|
120
|
+
case 'quarters':
|
|
121
|
+
return 160;
|
|
122
|
+
case 'years':
|
|
123
|
+
return 320;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Build header ticks for the chart. The ith tick sits at
|
|
129
|
+
* `originX + i * stridePx`. The last tick is rendered (so the chart
|
|
130
|
+
* has a closing edge) but its label is suppressed because there's no
|
|
131
|
+
* following column.
|
|
132
|
+
*/
|
|
133
|
+
export function buildHeaderTicks(
|
|
134
|
+
scale: TimeScale,
|
|
135
|
+
preset: ViewPreset,
|
|
136
|
+
calendar: WorkingCalendar,
|
|
137
|
+
locale: string = DEFAULT_LOCALE,
|
|
138
|
+
): PositionedTick[] {
|
|
139
|
+
const dayPerTick = calendar.daysPerUnit(preset.unit);
|
|
140
|
+
const stridePx = dayPerTick * scale.pixelsPerDay;
|
|
141
|
+
const totalDays = Math.max(1, Math.round(scale.widthPx / scale.pixelsPerDay));
|
|
142
|
+
const tickCount = Math.floor(totalDays / dayPerTick) + 1;
|
|
143
|
+
const ticks: PositionedTick[] = [];
|
|
144
|
+
for (let i = 0; i < tickCount; i++) {
|
|
145
|
+
const days = i * dayPerTick;
|
|
146
|
+
const x = scale.originX + days * scale.pixelsPerDay;
|
|
147
|
+
const isMajor = i % preset.labelEvery === 0;
|
|
148
|
+
const isLast = i === tickCount - 1;
|
|
149
|
+
ticks.push({
|
|
150
|
+
x,
|
|
151
|
+
labelX: isLast ? undefined : x + stridePx / 2,
|
|
152
|
+
major: isMajor,
|
|
153
|
+
label:
|
|
154
|
+
isMajor && !isLast
|
|
155
|
+
? formatTickLabel(preset.unit, addDays(scale.domain[0], days), i, locale)
|
|
156
|
+
: undefined,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
return ticks;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function formatTickLabel(unit: ScaleUnit, date: Date, _index: number, locale: string): string {
|
|
163
|
+
switch (unit) {
|
|
164
|
+
case 'days':
|
|
165
|
+
return `${date.getUTCMonth() + 1}/${date.getUTCDate()}`;
|
|
166
|
+
case 'weeks': {
|
|
167
|
+
const month = date.toLocaleString(locale, { month: 'short', timeZone: 'UTC' });
|
|
168
|
+
const day = date.getUTCDate().toString().padStart(2, '0');
|
|
169
|
+
return `${month} ${day}`;
|
|
170
|
+
}
|
|
171
|
+
case 'months':
|
|
172
|
+
return date.toLocaleString(locale, { month: 'short', timeZone: 'UTC' });
|
|
173
|
+
case 'quarters': {
|
|
174
|
+
const q = Math.floor(date.getUTCMonth() / 3) + 1;
|
|
175
|
+
return `${localeStrings(locale).quarterPrefix}${q} ${date.getUTCFullYear()}`;
|
|
176
|
+
}
|
|
177
|
+
case 'years':
|
|
178
|
+
return `${date.getUTCFullYear()}`;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// WorkingCalendar primitive — strategy interface for non-continuous
|
|
2
|
+
// time models (skip weekends, holidays, custom shutdowns). Today the
|
|
3
|
+
// rendering pipeline treats time as continuous; the existing
|
|
4
|
+
// `CalendarConfig` only changes how `1w` literals expand into days,
|
|
5
|
+
// not whether ticks skip weekends. WorkingCalendar establishes the
|
|
6
|
+
// API surface for the future weekend/holiday work without making
|
|
7
|
+
// `TimeScale` and `ViewPreset` aware of `CalendarConfig` directly.
|
|
8
|
+
//
|
|
9
|
+
// The default factories `continuousCalendar()` and
|
|
10
|
+
// `fromCalendarConfig(cal)` are pass-through: every calendar day is a
|
|
11
|
+
// working day, units expand using `CalendarConfig.daysPer*`. Future
|
|
12
|
+
// non-continuous calendars override `nextWorkingDay` and `addUnits`
|
|
13
|
+
// without changing the consumer surface.
|
|
14
|
+
|
|
15
|
+
import type { CalendarConfig } from './calendar.js';
|
|
16
|
+
import { addDays as addCalendarDays } from './calendar.js';
|
|
17
|
+
import type { ScaleUnit } from './view-preset.js';
|
|
18
|
+
|
|
19
|
+
export interface WorkingCalendar {
|
|
20
|
+
/** Days per `1<unit>` literal (e.g. `1w` → 5 for business). */
|
|
21
|
+
daysPerUnit(unit: ScaleUnit): number;
|
|
22
|
+
/** Move forward by N units (e.g. `addUnits(d, 2, 'weeks')`). */
|
|
23
|
+
addUnits(date: Date, count: number, unit: ScaleUnit): Date;
|
|
24
|
+
/** True when the given date is a working day in this calendar. */
|
|
25
|
+
isWorkingDay(date: Date): boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function fromCalendarConfig(cal: CalendarConfig): WorkingCalendar {
|
|
29
|
+
return {
|
|
30
|
+
daysPerUnit: (unit) => daysPerUnitForCalendar(unit, cal),
|
|
31
|
+
addUnits: (date, count, unit) =>
|
|
32
|
+
addCalendarDays(date, count * daysPerUnitForCalendar(unit, cal)),
|
|
33
|
+
// The continuous model used today treats every calendar day as a
|
|
34
|
+
// working day; non-continuous calendars will override this to
|
|
35
|
+
// implement weekend/holiday skipping when the work lands.
|
|
36
|
+
isWorkingDay: () => true,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function continuousCalendar(): WorkingCalendar {
|
|
41
|
+
return {
|
|
42
|
+
daysPerUnit: (unit) => {
|
|
43
|
+
switch (unit) {
|
|
44
|
+
case 'days':
|
|
45
|
+
return 1;
|
|
46
|
+
case 'weeks':
|
|
47
|
+
return 7;
|
|
48
|
+
case 'months':
|
|
49
|
+
return 30;
|
|
50
|
+
case 'quarters':
|
|
51
|
+
return 91;
|
|
52
|
+
case 'years':
|
|
53
|
+
return 365;
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
addUnits: (date, count, unit) => {
|
|
57
|
+
const days =
|
|
58
|
+
count *
|
|
59
|
+
(unit === 'days'
|
|
60
|
+
? 1
|
|
61
|
+
: unit === 'weeks'
|
|
62
|
+
? 7
|
|
63
|
+
: unit === 'months'
|
|
64
|
+
? 30
|
|
65
|
+
: unit === 'quarters'
|
|
66
|
+
? 91
|
|
67
|
+
: 365);
|
|
68
|
+
return addCalendarDays(date, days);
|
|
69
|
+
},
|
|
70
|
+
isWorkingDay: () => true,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function daysPerUnit(unit: ScaleUnit, cal: CalendarConfig): number {
|
|
75
|
+
return daysPerUnitForCalendar(unit, cal);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function daysPerUnitForCalendar(unit: ScaleUnit, cal: CalendarConfig): number {
|
|
79
|
+
switch (unit) {
|
|
80
|
+
case 'days':
|
|
81
|
+
return 1;
|
|
82
|
+
case 'weeks':
|
|
83
|
+
return cal.daysPerWeek;
|
|
84
|
+
case 'months':
|
|
85
|
+
return cal.daysPerMonth;
|
|
86
|
+
case 'quarters':
|
|
87
|
+
return cal.daysPerQuarter;
|
|
88
|
+
case 'years':
|
|
89
|
+
return cal.daysPerYear;
|
|
90
|
+
}
|
|
91
|
+
}
|