@pisell/materials 6.11.65 → 6.11.66
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/build/lowcode/assets-daily.json +11 -11
- package/build/lowcode/assets-dev.json +2 -2
- package/build/lowcode/assets-prod.json +11 -11
- package/build/lowcode/meta.js +1 -1
- package/build/lowcode/render/default/view.js +2 -2
- package/build/lowcode/view.js +2 -2
- package/es/components/pisellReservationScheduleBand/PisellReservationScheduleBand.d.ts +10 -0
- package/es/components/pisellReservationScheduleBand/PisellReservationScheduleBand.stories.d.ts +16 -0
- package/es/components/pisellReservationScheduleBand/index.d.ts +2 -0
- package/es/components/pisellReservationScheduleBand/types.d.ts +61 -0
- package/es/components/pisellTimeNavigator/PisellTimeNavigator.d.ts +10 -0
- package/es/components/pisellTimeNavigator/PisellTimeNavigator.js +11 -3
- package/es/components/pisellTimeNavigator/PisellTimeNavigator.stories.d.ts +79 -0
- package/es/components/pisellTimeNavigator/components/ScaleLayer.d.ts +40 -0
- package/es/components/pisellTimeNavigator/components/ScaleLayer.js +37 -6
- package/es/components/pisellTimeNavigator/components/index.d.ts +5 -0
- package/es/components/pisellTimeNavigator/hooks/index.d.ts +5 -0
- package/es/components/pisellTimeNavigator/hooks/useTimeAxis.d.ts +37 -0
- package/es/components/pisellTimeNavigator/hooks/useTimeAxis.js +49 -25
- package/es/components/pisellTimeNavigator/index.d.ts +5 -0
- package/es/components/pisellTimeNavigator/utils/index.d.ts +65 -0
- package/es/components/pisellTimeNavigator/utils/index.js +66 -6
- package/lib/components/pisellReservationScheduleBand/PisellReservationScheduleBand.d.ts +10 -0
- package/lib/components/pisellReservationScheduleBand/PisellReservationScheduleBand.stories.d.ts +16 -0
- package/lib/components/pisellReservationScheduleBand/index.d.ts +2 -0
- package/lib/components/pisellReservationScheduleBand/types.d.ts +61 -0
- package/lib/components/pisellTimeNavigator/PisellTimeNavigator.d.ts +10 -0
- package/lib/components/pisellTimeNavigator/PisellTimeNavigator.js +6 -2
- package/lib/components/pisellTimeNavigator/PisellTimeNavigator.stories.d.ts +79 -0
- package/lib/components/pisellTimeNavigator/components/ScaleLayer.d.ts +40 -0
- package/lib/components/pisellTimeNavigator/components/ScaleLayer.js +32 -4
- package/lib/components/pisellTimeNavigator/components/index.d.ts +5 -0
- package/lib/components/pisellTimeNavigator/hooks/index.d.ts +5 -0
- package/lib/components/pisellTimeNavigator/hooks/useTimeAxis.d.ts +37 -0
- package/lib/components/pisellTimeNavigator/hooks/useTimeAxis.js +27 -15
- package/lib/components/pisellTimeNavigator/index.d.ts +5 -0
- package/lib/components/pisellTimeNavigator/utils/index.d.ts +65 -0
- package/lib/components/pisellTimeNavigator/utils/index.js +32 -4
- package/package.json +1 -1
- package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.d.ts +0 -13
- package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.stories.d.ts +0 -59
- package/es/components/pisellFloorMapLayout/appearance/floorMapAppearance.d.ts +0 -15
- package/es/components/pisellFloorMapLayout/components/ViewControls.d.ts +0 -57
- package/es/components/pisellFloorMapLayout/components/ViewControlsWithZoom.d.ts +0 -26
- package/es/components/pisellFloorMapLayout/context/mergeFloorMapLayoutContext.d.ts +0 -5
- package/es/components/pisellFloorMapLayout/types.d.ts +0 -666
- package/es/components/pisellRecordBoard/index.d.ts +0 -51
- package/es/components/pisellRecordBoard/shellFrame/Calendar/bookingCalendarInternalTypes.d.ts +0 -43
- package/es/components/pisellRecordBoard/shellFrame/Calendar/const/bookingCalendarConstants.d.ts +0 -73
- package/es/components/pisellRecordBoard/shellFrame/Calendar/hooks/useBookingCalendarDayOverlayLayout.d.ts +0 -18
- package/es/components/pisellRecordBoard/shellFrame/Calendar/modal/BookingCalendarBlockPanel.d.ts +0 -26
- package/es/components/pisellRecordBoard/shellFrame/Calendar/modal/BookingCalendarOverflowListLayer.d.ts +0 -14
- package/es/components/pisellRecordBoard/shellFrame/Calendar/utils/bookingCalendarSelectionUtils.d.ts +0 -7
- package/es/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarDaySelectionBar.d.ts +0 -21
- package/es/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarDayView.d.ts +0 -49
- package/es/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarResourceView.d.ts +0 -57
- package/es/components/pisellRecordBoard/shellFrame/Calendar/view/day/useBookingCalendarDayHourRemaining.d.ts +0 -10
- package/es/components/pisellRecordBoard/shellFrame/Calendar/view/day/useBookingCalendarDaySelection.d.ts +0 -11
- package/es/components/pisellRecordBoard/shellFrame/Calendar/view/resource/useBookingCalendarResourceCellToggle.d.ts +0 -3
- package/es/components/pisellRecordBoard/shellFrame/Calendar/view/resource/useBookingCalendarResourceDayHeaderRemaining.d.ts +0 -8
- package/es/components/pisellRecordBoard/shellFrame/Calendar/view/useBookingCalendarGoToDayFromCell.d.ts +0 -3
- package/es/components/pisellRecordBoard/types.d.ts +0 -835
- package/es/components/pisellReservationSchedule/PisellReservationSchedule.d.ts +0 -10
- package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.d.ts +0 -13
- package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.stories.d.ts +0 -59
- package/lib/components/pisellFloorMapLayout/appearance/floorMapAppearance.d.ts +0 -15
- package/lib/components/pisellFloorMapLayout/components/ViewControls.d.ts +0 -57
- package/lib/components/pisellFloorMapLayout/components/ViewControlsWithZoom.d.ts +0 -26
- package/lib/components/pisellFloorMapLayout/context/mergeFloorMapLayoutContext.d.ts +0 -5
- package/lib/components/pisellFloorMapLayout/types.d.ts +0 -666
- package/lib/components/pisellRecordBoard/index.d.ts +0 -51
- package/lib/components/pisellRecordBoard/shellFrame/Calendar/bookingCalendarInternalTypes.d.ts +0 -43
- package/lib/components/pisellRecordBoard/shellFrame/Calendar/const/bookingCalendarConstants.d.ts +0 -73
- package/lib/components/pisellRecordBoard/shellFrame/Calendar/hooks/useBookingCalendarDayOverlayLayout.d.ts +0 -18
- package/lib/components/pisellRecordBoard/shellFrame/Calendar/modal/BookingCalendarBlockPanel.d.ts +0 -26
- package/lib/components/pisellRecordBoard/shellFrame/Calendar/modal/BookingCalendarOverflowListLayer.d.ts +0 -14
- package/lib/components/pisellRecordBoard/shellFrame/Calendar/utils/bookingCalendarSelectionUtils.d.ts +0 -7
- package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarDaySelectionBar.d.ts +0 -21
- package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarDayView.d.ts +0 -49
- package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarResourceView.d.ts +0 -57
- package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/day/useBookingCalendarDayHourRemaining.d.ts +0 -10
- package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/day/useBookingCalendarDaySelection.d.ts +0 -11
- package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/resource/useBookingCalendarResourceCellToggle.d.ts +0 -3
- package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/resource/useBookingCalendarResourceDayHeaderRemaining.d.ts +0 -8
- package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/useBookingCalendarGoToDayFromCell.d.ts +0 -3
- package/lib/components/pisellRecordBoard/types.d.ts +0 -835
- package/lib/components/pisellReservationSchedule/PisellReservationSchedule.d.ts +0 -10
|
@@ -123,7 +123,9 @@ export function isInDisabledRanges(t, disabledRanges) {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
/**
|
|
126
|
-
* 在 [rangeStart, rangeEnd] 内按 stepMinutes
|
|
126
|
+
* 在 [rangeStart, rangeEnd] 内按 stepMinutes 生成等步刻度时间列表(Dayjs)。
|
|
127
|
+
*
|
|
128
|
+
* @deprecated 仅用于不需要「头/尾 partial 格」的场景;时间轴渲染请用 {@link getAxisCells}。
|
|
127
129
|
*/
|
|
128
130
|
export function getTicks(rangeStart, rangeEnd, stepMinutes) {
|
|
129
131
|
var out = [];
|
|
@@ -136,15 +138,73 @@ export function getTicks(rangeStart, rangeEnd, stepMinutes) {
|
|
|
136
138
|
}
|
|
137
139
|
|
|
138
140
|
/**
|
|
139
|
-
*
|
|
141
|
+
* 时间轴上一格的描述:起始时间 + 跨度(分钟)。
|
|
142
|
+
* - 中间格:跨度 = `stepMinutes`,起点对齐到 step 网格(如 15 分钟一格时落在 `:00/:15/:30/:45`);
|
|
143
|
+
* - head 格:当 `rangeStart` 不在网格上时存在,起点 = `rangeStart`,跨度 < step;
|
|
144
|
+
* - tail 格:当 `rangeEnd` 不在网格上时存在,起点 = 最后一个对齐点,跨度 < step。
|
|
145
|
+
*/
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* 把 [`rangeStart`, `rangeEnd`] 切成「对齐到 step 网格」的格子序列:
|
|
149
|
+
*
|
|
150
|
+
* 1. 找到第一个 ≥ `rangeStart` 且分钟为 `stepMinutes` 整数倍的对齐点;
|
|
151
|
+
* 2. 若对齐点严格大于 `rangeStart`,先放一格 head(`rangeStart` → 对齐点),跨度 < step;
|
|
152
|
+
* 3. 中间按 step 步进,每格起点都落在网格上;
|
|
153
|
+
* 4. 若 `rangeEnd` 落在两个对齐点之间,最后多出一格 tail(最后对齐点 → `rangeEnd`),跨度 < step。
|
|
154
|
+
*
|
|
155
|
+
* `rangeStart` / `rangeEnd` 都恰落在网格上时退化为完全等步格。
|
|
156
|
+
*/
|
|
157
|
+
export function getAxisCells(rangeStart, rangeEnd, stepMinutes) {
|
|
158
|
+
var out = [];
|
|
159
|
+
if (!rangeEnd.isAfter(rangeStart) || stepMinutes <= 0) return out;
|
|
160
|
+
var startMin = rangeStart.minute();
|
|
161
|
+
var remainder = (startMin % stepMinutes + stepMinutes) % stepMinutes;
|
|
162
|
+
var isStartAligned = remainder === 0 && rangeStart.second() === 0 && rangeStart.millisecond() === 0;
|
|
163
|
+
var firstAligned = isStartAligned ? rangeStart : rangeStart.startOf('hour').minute(startMin - remainder + stepMinutes).second(0).millisecond(0);
|
|
164
|
+
if (firstAligned.isAfter(rangeStart)) {
|
|
165
|
+
var headMin = firstAligned.diff(rangeStart, 'minute', true);
|
|
166
|
+
if (headMin > 0) {
|
|
167
|
+
out.push({
|
|
168
|
+
start: rangeStart,
|
|
169
|
+
widthMinutes: headMin
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
var cur = firstAligned;
|
|
174
|
+
/**
|
|
175
|
+
* 防御:超大 / 非法 range 时(如 1 年)直接挂死。这里限制最多 2 天 + 1 步的格数,
|
|
176
|
+
* 与 useTimeAxis 的 `totalLengthPx` 上限呼应。
|
|
177
|
+
*/
|
|
178
|
+
var safetyLimit = 2 * 24 * 60 / stepMinutes + 4;
|
|
179
|
+
while (cur.isBefore(rangeEnd) && out.length < safetyLimit) {
|
|
180
|
+
var next = cur.add(stepMinutes, 'minute');
|
|
181
|
+
if (next.isAfter(rangeEnd)) {
|
|
182
|
+
var tailMin = rangeEnd.diff(cur, 'minute', true);
|
|
183
|
+
if (tailMin > 0) {
|
|
184
|
+
out.push({
|
|
185
|
+
start: cur,
|
|
186
|
+
widthMinutes: tailMin
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
out.push({
|
|
192
|
+
start: cur,
|
|
193
|
+
widthMinutes: stepMinutes
|
|
194
|
+
});
|
|
195
|
+
cur = next;
|
|
196
|
+
}
|
|
197
|
+
return out;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* 横向时间轴「格」数量,与 useTimeAxis 中 cells 算法一致。
|
|
202
|
+
* 用于 cursor-moves 模式下计算压缩后的每格像素宽度。
|
|
140
203
|
*/
|
|
141
204
|
export function getHorizontalAxisSlotCount(range, referenceDate, stepMinutes) {
|
|
142
205
|
var _getRangeBounds5 = getRangeBounds(range, referenceDate),
|
|
143
206
|
_getRangeBounds6 = _slicedToArray(_getRangeBounds5, 2),
|
|
144
207
|
rangeStart = _getRangeBounds6[0],
|
|
145
208
|
rangeEnd = _getRangeBounds6[1];
|
|
146
|
-
|
|
147
|
-
var lastTick = ticks.length > 0 ? ticks[ticks.length - 1] : null;
|
|
148
|
-
var needTailCell = lastTick != null && rangeEnd.isAfter(lastTick);
|
|
149
|
-
return ticks.length + (needTailCell ? 1 : 0);
|
|
209
|
+
return getAxisCells(rangeStart, rangeEnd, stepMinutes).length;
|
|
150
210
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { PisellReservationScheduleBandProps } from './types';
|
|
3
|
+
import './PisellReservationScheduleBand.less';
|
|
4
|
+
/**
|
|
5
|
+
* 预约顶栏组合:营业日切换 + 锚定到选中日的时间导航轴
|
|
6
|
+
*/
|
|
7
|
+
export declare function PisellReservationScheduleBand(props: PisellReservationScheduleBandProps): React.JSX.Element;
|
|
8
|
+
export declare namespace PisellReservationScheduleBand {
|
|
9
|
+
var displayName: string;
|
|
10
|
+
}
|
package/lib/components/pisellReservationScheduleBand/PisellReservationScheduleBand.stories.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { PisellReservationScheduleBand } from './PisellReservationScheduleBand';
|
|
3
|
+
/**
|
|
4
|
+
* PisellReservationScheduleBand:营业日条 + 横向时间轴顶栏组合,统一 value `{ date, at }`。
|
|
5
|
+
* 详见组件目录下 docs/PisellReservationScheduleBand.md。
|
|
6
|
+
*/
|
|
7
|
+
declare const meta: Meta<typeof PisellReservationScheduleBand>;
|
|
8
|
+
export default meta;
|
|
9
|
+
declare type Story = StoryObj<typeof PisellReservationScheduleBand>;
|
|
10
|
+
export declare const Default: Story;
|
|
11
|
+
export declare const CustomTimeNavigator: Story;
|
|
12
|
+
export declare const ScheduleMinMax: Story;
|
|
13
|
+
export declare const Controlled: Story;
|
|
14
|
+
export declare const InitialPastDay: Story;
|
|
15
|
+
/** 日程行左右插槽:左标题 + 中间 PisellReservationSchedule + 右操作区(整条顶栏暗色背景需在业务外层自行包一层,避免压住下方时间轴) */
|
|
16
|
+
export declare const WithScheduleSlots: Story;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from 'react';
|
|
2
|
+
import type { Dayjs } from 'dayjs';
|
|
3
|
+
import type { PisellTimeNavigatorProps } from '../pisellTimeNavigator/types';
|
|
4
|
+
import type { PisellReservationScheduleProps } from '../pisellReservationSchedule/types';
|
|
5
|
+
/** 组合值:日历日 + 该日上的时刻(与 PisellTimeNavigator 对齐) */
|
|
6
|
+
export interface ReservationScheduleBandValue {
|
|
7
|
+
date: Dayjs;
|
|
8
|
+
at: Dayjs;
|
|
9
|
+
}
|
|
10
|
+
export declare type TimeNavigatorPassthroughProps = Omit<PisellTimeNavigatorProps, 'value' | 'onChange' | 'defaultValue'>;
|
|
11
|
+
/**
|
|
12
|
+
* PisellReservationScheduleBand:营业日条 + 横向时间轴
|
|
13
|
+
*/
|
|
14
|
+
export interface PisellReservationScheduleBandProps {
|
|
15
|
+
/**
|
|
16
|
+
* 受控:选中日 + 轴上时刻
|
|
17
|
+
*/
|
|
18
|
+
value?: ReservationScheduleBandValue;
|
|
19
|
+
/**
|
|
20
|
+
* 日历日或时刻任一变化时触发
|
|
21
|
+
*/
|
|
22
|
+
onChange?: (next: ReservationScheduleBandValue) => void;
|
|
23
|
+
/**
|
|
24
|
+
* 非受控初始值(可只传部分字段)
|
|
25
|
+
*/
|
|
26
|
+
defaultValue?: Partial<ReservationScheduleBandValue>;
|
|
27
|
+
/**
|
|
28
|
+
* 透传给 PisellReservationSchedule(如 minDate / maxDate)
|
|
29
|
+
*/
|
|
30
|
+
scheduleProps?: Omit<PisellReservationScheduleProps, 'value' | 'onChange' | 'defaultValue'>;
|
|
31
|
+
/**
|
|
32
|
+
* 透传给 PisellTimeNavigator(不含 value/onChange/referenceDate)
|
|
33
|
+
*/
|
|
34
|
+
timeNavigatorProps?: TimeNavigatorPassthroughProps;
|
|
35
|
+
/**
|
|
36
|
+
* 顶栏日程行:PisellReservationSchedule 左侧自定义内容(如标题)
|
|
37
|
+
*/
|
|
38
|
+
scheduleStartSlot?: ReactNode;
|
|
39
|
+
/**
|
|
40
|
+
* 顶栏日程行:PisellReservationSchedule 右侧自定义内容(如状态、主按钮)
|
|
41
|
+
*/
|
|
42
|
+
scheduleEndSlot?: ReactNode;
|
|
43
|
+
/**
|
|
44
|
+
* 顶栏日程行:紧挨在选日组件之后(如「跟随当前」),与中间列同一 flex 区
|
|
45
|
+
*/
|
|
46
|
+
scheduleAfterDateSlot?: ReactNode;
|
|
47
|
+
/**
|
|
48
|
+
* 为 true 时隐藏下方时间导航轴(如日历视图仅需要选日/选周/选月)
|
|
49
|
+
*/
|
|
50
|
+
hideTimeNavigator?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* 为 true 时在整个日程带上叠加载层(如切换营业日后拉预约列表期间)
|
|
53
|
+
*/
|
|
54
|
+
dataLoading?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* 加载层内文案,由业务侧 {@link locales.getText} 等注入
|
|
57
|
+
*/
|
|
58
|
+
dataLoadingTip?: ReactNode;
|
|
59
|
+
className?: string;
|
|
60
|
+
style?: CSSProperties;
|
|
61
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { PisellTimeNavigatorProps } from './types';
|
|
3
|
+
import './PisellTimeNavigator.less';
|
|
4
|
+
/**
|
|
5
|
+
* PisellTimeNavigator:可拖动的时间导航轴,时间范围内浏览、选择、控制
|
|
6
|
+
*/
|
|
7
|
+
export declare function PisellTimeNavigator(props: PisellTimeNavigatorProps): React.JSX.Element;
|
|
8
|
+
export declare namespace PisellTimeNavigator {
|
|
9
|
+
var displayName: string;
|
|
10
|
+
}
|
|
@@ -186,7 +186,7 @@ function PisellTimeNavigator(props) {
|
|
|
186
186
|
const span = Math.max(1, maxV - minV);
|
|
187
187
|
const h = import_timeNavigatorConstants.DENSITY_LAYER_HEIGHT;
|
|
188
188
|
const points = slice.map((v, i) => {
|
|
189
|
-
const x = i
|
|
189
|
+
const x = axis.timeToOffset(axis.ticks[i]);
|
|
190
190
|
const t = (v - minV) / span;
|
|
191
191
|
const y = h - 1 - t * (h - 3);
|
|
192
192
|
return { x, y };
|
|
@@ -214,6 +214,7 @@ function PisellTimeNavigator(props) {
|
|
|
214
214
|
isHorizontal,
|
|
215
215
|
resolvedDensity,
|
|
216
216
|
axis.ticks,
|
|
217
|
+
axis.timeToOffset,
|
|
217
218
|
axis.totalLengthPx,
|
|
218
219
|
cellSizePx
|
|
219
220
|
]);
|
|
@@ -867,7 +868,10 @@ function PisellTimeNavigator(props) {
|
|
|
867
868
|
timeFormat,
|
|
868
869
|
locale,
|
|
869
870
|
style: scaleStyle,
|
|
870
|
-
horizontalCellSizePx: isHorizontal ? cellSizePx : void 0
|
|
871
|
+
horizontalCellSizePx: isHorizontal ? cellSizePx : void 0,
|
|
872
|
+
cellWidthsPx: isHorizontal ? axis.cellWidthsPx : void 0,
|
|
873
|
+
leadingPaddingPx: isHorizontal ? dotOffsetPx : void 0,
|
|
874
|
+
trailingPaddingPx: isHorizontal ? dotOffsetPx : void 0
|
|
871
875
|
}
|
|
872
876
|
),
|
|
873
877
|
isHorizontal && currentTimeOffsetPx != null && currentTimeOffsetPx >= 0 && /* @__PURE__ */ import_react.default.createElement(
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { PisellTimeNavigator } from './PisellTimeNavigator';
|
|
3
|
+
/**
|
|
4
|
+
* PisellTimeNavigator 组件 Storybook
|
|
5
|
+
* 时间导航轴:时间范围内浏览、选择、控制
|
|
6
|
+
*/
|
|
7
|
+
declare const meta: Meta<typeof PisellTimeNavigator>;
|
|
8
|
+
export default meta;
|
|
9
|
+
declare type Story = StoryObj<typeof PisellTimeNavigator>;
|
|
10
|
+
/**
|
|
11
|
+
* 默认:横向、轴动、显示 Now
|
|
12
|
+
*/
|
|
13
|
+
export declare const Default: Story;
|
|
14
|
+
/** 默认 - 竖向 */
|
|
15
|
+
export declare const DefaultVertical: Story;
|
|
16
|
+
/**
|
|
17
|
+
* 受控 + 默认 12:00
|
|
18
|
+
*/
|
|
19
|
+
export declare const Controlled: Story;
|
|
20
|
+
/** 受控 - 竖向 */
|
|
21
|
+
export declare const ControlledVertical: Story;
|
|
22
|
+
/**
|
|
23
|
+
* 非受控 + 默认 14:30
|
|
24
|
+
*/
|
|
25
|
+
export declare const Uncontrolled: Story;
|
|
26
|
+
/** 非受控 - 竖向 */
|
|
27
|
+
export declare const UncontrolledVertical: Story;
|
|
28
|
+
/**
|
|
29
|
+
* 竖向
|
|
30
|
+
*/
|
|
31
|
+
export declare const Vertical: Story;
|
|
32
|
+
/**
|
|
33
|
+
* 指针动模式(cursor-moves)
|
|
34
|
+
*/
|
|
35
|
+
export declare const CursorMoves: Story;
|
|
36
|
+
/** 指针动模式 - 竖向 */
|
|
37
|
+
export declare const CursorMovesVertical: Story;
|
|
38
|
+
/**
|
|
39
|
+
* 营业时间高亮 10:00–22:00
|
|
40
|
+
*/
|
|
41
|
+
export declare const BusinessHours: Story;
|
|
42
|
+
/** 营业时间高亮 - 竖向 */
|
|
43
|
+
export declare const BusinessHoursVertical: Story;
|
|
44
|
+
/**
|
|
45
|
+
* 自定义时间范围 08:00–20:00
|
|
46
|
+
*/
|
|
47
|
+
export declare const CustomRange: Story;
|
|
48
|
+
/** 自定义时间范围 - 竖向 */
|
|
49
|
+
export declare const CustomRangeVertical: Story;
|
|
50
|
+
/**
|
|
51
|
+
* 步长 30 分钟
|
|
52
|
+
*/
|
|
53
|
+
export declare const Step30: Story;
|
|
54
|
+
/** 步长 30 分钟 - 竖向 */
|
|
55
|
+
export declare const Step30Vertical: Story;
|
|
56
|
+
/**
|
|
57
|
+
* 惯性滚动开启
|
|
58
|
+
*/
|
|
59
|
+
export declare const Inertia: Story;
|
|
60
|
+
/** 惯性滚动 - 竖向 */
|
|
61
|
+
export declare const InertiaVertical: Story;
|
|
62
|
+
/**
|
|
63
|
+
* 吸附到整点(松手后自动吸附到 0/15/30/45 分刻度)
|
|
64
|
+
*/
|
|
65
|
+
export declare const SnapToStep: Story;
|
|
66
|
+
/** 吸附到整点 - 竖向 */
|
|
67
|
+
export declare const SnapToStepVertical: Story;
|
|
68
|
+
/**
|
|
69
|
+
* 隐藏 Now 按钮
|
|
70
|
+
*/
|
|
71
|
+
export declare const NoNowButton: Story;
|
|
72
|
+
/** 隐藏 Now 按钮 - 竖向 */
|
|
73
|
+
export declare const NoNowButtonVertical: Story;
|
|
74
|
+
/**
|
|
75
|
+
* 实时模式(仅演示,实际会跟随系统时间)
|
|
76
|
+
*/
|
|
77
|
+
export declare const Realtime: Story;
|
|
78
|
+
/** 实时模式 - 竖向 */
|
|
79
|
+
export declare const RealtimeVertical: Story;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Dayjs } from 'dayjs';
|
|
3
|
+
export interface ScaleLayerProps {
|
|
4
|
+
orientation: 'horizontal' | 'vertical';
|
|
5
|
+
ticks: Dayjs[];
|
|
6
|
+
stepMinutes: number;
|
|
7
|
+
majorStepMinutes: number;
|
|
8
|
+
timeFormat: string;
|
|
9
|
+
locale?: string;
|
|
10
|
+
style?: React.CSSProperties;
|
|
11
|
+
className?: string;
|
|
12
|
+
/**
|
|
13
|
+
* 横向每格宽度(px),须与 useTimeAxis 的 cellSizePx 一致;
|
|
14
|
+
* 不传时样式表默认 82(axis-moves);cursor-moves 压缩比例时必传
|
|
15
|
+
*/
|
|
16
|
+
horizontalCellSizePx?: number;
|
|
17
|
+
/**
|
|
18
|
+
* 每个 tick 对应「格」的实际宽度(px)。范围起止不在 step 网格上时,首尾会出现宽度
|
|
19
|
+
* 小于 `horizontalCellSizePx` 的 head/tail 格;中间仍保持整步宽。
|
|
20
|
+
* 不传时退化为「全部按 horizontalCellSizePx 等宽」。
|
|
21
|
+
*/
|
|
22
|
+
cellWidthsPx?: number[];
|
|
23
|
+
/**
|
|
24
|
+
* 横向时,整体两端各留出 `cellSize/2` 的居中留白(与 `useTimeAxis.dotOffsetPx` 一致),
|
|
25
|
+
* 使 rangeStart / rangeEnd 的实际像素位置落在头格 / 尾格的左 / 右边沿,
|
|
26
|
+
* 与拖拽光标的 `timeToOffset` 像素对齐。
|
|
27
|
+
*/
|
|
28
|
+
leadingPaddingPx?: number;
|
|
29
|
+
trailingPaddingPx?: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 刻度层:渲染时间刻度与标签
|
|
33
|
+
* - 横向:整点数字 + 小圆点;当 range 起止不在 step 网格上时,首尾两个格按时间比例**变窄**
|
|
34
|
+
* (宽度 = `widthMinutes / step × cellSize`),中间格保持整步宽并落在整点 / 半点等对齐位置上。
|
|
35
|
+
* - 竖向:整点数字 + 分割线。
|
|
36
|
+
*
|
|
37
|
+
* 标签仅在「整点」(`tick.minute() === 0` 且秒为 0)时显示数字;非整点格只渲染圆点 / 分割线,
|
|
38
|
+
* 配合变窄的 head/tail 让起止时刻在视觉上自然衔接到第一个 / 最后一个整点。
|
|
39
|
+
*/
|
|
40
|
+
export declare function ScaleLayer({ orientation, ticks, stepMinutes, majorStepMinutes, timeFormat, locale, style, className, horizontalCellSizePx, cellWidthsPx, leadingPaddingPx, trailingPaddingPx, }: ScaleLayerProps): React.JSX.Element;
|
|
@@ -43,7 +43,10 @@ function ScaleLayer({
|
|
|
43
43
|
locale,
|
|
44
44
|
style,
|
|
45
45
|
className,
|
|
46
|
-
horizontalCellSizePx
|
|
46
|
+
horizontalCellSizePx,
|
|
47
|
+
cellWidthsPx,
|
|
48
|
+
leadingPaddingPx,
|
|
49
|
+
trailingPaddingPx
|
|
47
50
|
}) {
|
|
48
51
|
const isHorizontal = orientation === "horizontal";
|
|
49
52
|
return /* @__PURE__ */ import_react.default.createElement(
|
|
@@ -56,11 +59,24 @@ function ScaleLayer({
|
|
|
56
59
|
),
|
|
57
60
|
style
|
|
58
61
|
},
|
|
62
|
+
isHorizontal && leadingPaddingPx != null && leadingPaddingPx > 0 && /* @__PURE__ */ import_react.default.createElement(
|
|
63
|
+
"div",
|
|
64
|
+
{
|
|
65
|
+
"aria-hidden": true,
|
|
66
|
+
style: {
|
|
67
|
+
width: leadingPaddingPx,
|
|
68
|
+
minWidth: leadingPaddingPx,
|
|
69
|
+
maxWidth: leadingPaddingPx,
|
|
70
|
+
flex: "0 0 auto"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
),
|
|
59
74
|
ticks.map((tick, i) => {
|
|
60
|
-
const isMajor = tick.minute()
|
|
75
|
+
const isMajor = tick.minute() === 0 && tick.second() === 0;
|
|
61
76
|
const label = isHorizontal && isMajor ? locale ? tick.locale(locale).format("H") : tick.format("H") : locale ? tick.locale(locale).format(timeFormat) : tick.format(timeFormat);
|
|
62
77
|
if (isHorizontal) {
|
|
63
|
-
const
|
|
78
|
+
const baseCw = horizontalCellSizePx != null && horizontalCellSizePx > 0 ? horizontalCellSizePx : void 0;
|
|
79
|
+
const cw = cellWidthsPx != null && cellWidthsPx[i] != null ? cellWidthsPx[i] : baseCw;
|
|
64
80
|
const compactPad = cw != null ? cw < 36 ? 2 : cw < 52 ? 6 : 10 : void 0;
|
|
65
81
|
return /* @__PURE__ */ import_react.default.createElement(
|
|
66
82
|
"div",
|
|
@@ -107,7 +123,19 @@ function ScaleLayer({
|
|
|
107
123
|
/* @__PURE__ */ import_react.default.createElement("span", { className: "pisell-time-navigator-scale-divider", "aria-hidden": true }),
|
|
108
124
|
isMajor && /* @__PURE__ */ import_react.default.createElement("span", { className: "pisell-time-navigator-scale-label" }, label)
|
|
109
125
|
);
|
|
110
|
-
})
|
|
126
|
+
}),
|
|
127
|
+
isHorizontal && trailingPaddingPx != null && trailingPaddingPx > 0 && /* @__PURE__ */ import_react.default.createElement(
|
|
128
|
+
"div",
|
|
129
|
+
{
|
|
130
|
+
"aria-hidden": true,
|
|
131
|
+
style: {
|
|
132
|
+
width: trailingPaddingPx,
|
|
133
|
+
minWidth: trailingPaddingPx,
|
|
134
|
+
maxWidth: trailingPaddingPx,
|
|
135
|
+
flex: "0 0 auto"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
)
|
|
111
139
|
);
|
|
112
140
|
}
|
|
113
141
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { useTimeAxis } from './useTimeAxis';
|
|
2
|
+
export type { UseTimeAxisOptions, TimeAxisState } from './useTimeAxis';
|
|
3
|
+
export { useRealtime } from './useRealtime';
|
|
4
|
+
export { useDragInertia } from './useDragInertia';
|
|
5
|
+
export type { UseDragInertiaOptions } from './useDragInertia';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Dayjs } from 'dayjs';
|
|
2
|
+
import type { TimeRangeOption } from '../types';
|
|
3
|
+
export interface UseTimeAxisOptions {
|
|
4
|
+
range?: TimeRangeOption;
|
|
5
|
+
stepMinutes: number;
|
|
6
|
+
referenceDate: Dayjs;
|
|
7
|
+
orientation: 'horizontal' | 'vertical';
|
|
8
|
+
/** 横向时每格宽度(px),竖向时每格高度(px) */
|
|
9
|
+
cellSizePx: number;
|
|
10
|
+
}
|
|
11
|
+
export interface TimeAxisState {
|
|
12
|
+
rangeStart: Dayjs;
|
|
13
|
+
rangeEnd: Dayjs;
|
|
14
|
+
/** 每格起点时间序列(含 head / tail,对齐到 step 网格) */
|
|
15
|
+
ticks: Dayjs[];
|
|
16
|
+
/** 与 `ticks` 一一对应的格宽(px);head / tail 可 < cellSizePx,中间格 = cellSizePx */
|
|
17
|
+
cellWidthsPx: number[];
|
|
18
|
+
/** 时间转主轴偏移(px) */
|
|
19
|
+
timeToOffset: (t: Dayjs) => number;
|
|
20
|
+
/** 主轴偏移(px)转时间(最近刻度,用于刻度对齐) */
|
|
21
|
+
offsetToTime: (offset: number) => Dayjs | null;
|
|
22
|
+
/** 主轴偏移(px)转时间(连续插值,用于拖动时按分钟步长显示) */
|
|
23
|
+
offsetToTimeContinuous: (offset: number) => Dayjs | null;
|
|
24
|
+
/** 主轴总长度(px) */
|
|
25
|
+
totalLengthPx: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 时间轴刻度与时间↔像素换算。
|
|
29
|
+
*
|
|
30
|
+
* 格子拆分策略见 {@link getAxisCells}:当 `range.start` / `range.end` 不在 `stepMinutes` 网格上时,
|
|
31
|
+
* 首尾出现宽度按时间比例缩小的 head/tail 格,中间格保持 step 整步并落在网格整点上。
|
|
32
|
+
*
|
|
33
|
+
* 时间→像素仍是线性映射 `dotOffsetPx + (t - rangeStart) / step × cellSize`,与 head/tail 是否存在无关:
|
|
34
|
+
* `dotOffsetPx`(横向 = `cellSize/2`,竖向 = 0)为 rangeStart 在轴内的像素位置;轴两端各保留 `dotOffsetPx`
|
|
35
|
+
* 留白以居中 rangeStart / rangeEnd。
|
|
36
|
+
*/
|
|
37
|
+
export declare function useTimeAxis(options: UseTimeAxisOptions): TimeAxisState;
|
|
@@ -34,31 +34,42 @@ function useTimeAxis(options) {
|
|
|
34
34
|
} = options;
|
|
35
35
|
return (0, import_react.useMemo)(() => {
|
|
36
36
|
const [rangeStart, rangeEnd] = (0, import_utils.getRangeBounds)(range, referenceDate);
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const
|
|
37
|
+
const safeStep = Math.max(1, stepMinutes);
|
|
38
|
+
const cells = (0, import_utils.getAxisCells)(rangeStart, rangeEnd, safeStep);
|
|
39
|
+
const ticks = cells.map((c) => c.start);
|
|
40
|
+
const cellWidthsPx = cells.map(
|
|
41
|
+
(c) => c.widthMinutes / safeStep * cellSizePx
|
|
42
|
+
);
|
|
43
|
+
const cellsTotalPx = cellWidthsPx.reduce((s, w) => s + w, 0);
|
|
44
44
|
const dotOffsetPx = orientation === "vertical" ? 0 : cellSizePx / 2;
|
|
45
|
-
const
|
|
45
|
+
const rawTotalPx = orientation === "horizontal" ? cellsTotalPx + cellSizePx : cellsTotalPx;
|
|
46
|
+
const totalLengthPx = Math.min(rawTotalPx, 5e5);
|
|
47
|
+
const maxOffsetPx = orientation === "vertical" ? cellsTotalPx : dotOffsetPx + cellsTotalPx;
|
|
46
48
|
const timeToOffset = (t) => {
|
|
47
49
|
const diffMs = t.diff(rangeStart);
|
|
48
50
|
const diffMin = diffMs / (60 * 1e3);
|
|
49
|
-
const index = diffMin /
|
|
51
|
+
const index = diffMin / safeStep;
|
|
50
52
|
const px = dotOffsetPx + index * cellSizePx;
|
|
51
53
|
return Math.max(dotOffsetPx, Math.min(px, maxOffsetPx));
|
|
52
54
|
};
|
|
53
55
|
const offsetToTime = (offset) => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
if (ticks.length === 0) return null;
|
|
57
|
+
let bestIdx = 0;
|
|
58
|
+
let bestDist = Infinity;
|
|
59
|
+
for (let i = 0; i < ticks.length; i += 1) {
|
|
60
|
+
const px = timeToOffset(ticks[i]);
|
|
61
|
+
const d = Math.abs(px - offset);
|
|
62
|
+
if (d < bestDist) {
|
|
63
|
+
bestDist = d;
|
|
64
|
+
bestIdx = i;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return ticks[bestIdx];
|
|
57
68
|
};
|
|
58
69
|
const offsetToTimeContinuous = (offset) => {
|
|
59
70
|
const index = (offset - dotOffsetPx) / cellSizePx;
|
|
60
|
-
const minutesFromStart = index *
|
|
61
|
-
|
|
71
|
+
const minutesFromStart = index * safeStep;
|
|
72
|
+
const t = rangeStart.add(minutesFromStart, "minute");
|
|
62
73
|
if (t.isBefore(rangeStart)) return rangeStart;
|
|
63
74
|
if (t.isAfter(rangeEnd)) return rangeEnd;
|
|
64
75
|
return t;
|
|
@@ -66,7 +77,8 @@ function useTimeAxis(options) {
|
|
|
66
77
|
return {
|
|
67
78
|
rangeStart,
|
|
68
79
|
rangeEnd,
|
|
69
|
-
ticks
|
|
80
|
+
ticks,
|
|
81
|
+
cellWidthsPx,
|
|
70
82
|
timeToOffset,
|
|
71
83
|
offsetToTime,
|
|
72
84
|
offsetToTimeContinuous,
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { PisellTimeNavigator } from './PisellTimeNavigator';
|
|
2
|
+
export { getHorizontalAxisSlotCount, getRangeBounds, buildCalendarHourSlotsFromRange, buildCalendarTimelineSlotStartsFromRange, DEFAULT_CALENDAR_SLOT_STEP_MINUTES, } from './utils';
|
|
3
|
+
export type { PisellTimeNavigatorProps, TimeNavigatorValue, TimeRangeOption, CursorMode, TimeNavigatorOrientation, } from './types';
|
|
4
|
+
/** 多语言文案(en / zh-CN / zh-HK / ja / pt),使用前请在应用内通过 locales.init(pisellTimeNavigatorLocales, lang) 合并 */
|
|
5
|
+
export { default as pisellTimeNavigatorLocales } from './locales';
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { type Dayjs } from 'dayjs';
|
|
2
|
+
import type { TimeNavigatorValue, TimeRangeOption } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* 解析 value 为 Dayjs,无效则返回 null。
|
|
5
|
+
* 支持 dayjs 可解析的日期时间;纯时间字符串(如 '12:00'、'14:30')会基于 reference 的日期解析。
|
|
6
|
+
*/
|
|
7
|
+
export declare function parseValue(value: TimeNavigatorValue, reference?: Dayjs): Dayjs | null;
|
|
8
|
+
/** 日历时间轴默认步长(分钟),与历史「整点列」一致 */
|
|
9
|
+
export declare const DEFAULT_CALENDAR_SLOT_STEP_MINUTES = 60;
|
|
10
|
+
/**
|
|
11
|
+
* 按营业日 {@link TimeRangeOption} 在锚定自然日零点展开,生成日视图时间轴「列左边界」:
|
|
12
|
+
* 值为相对 `reference.startOf('day')` 的**浮点小时**(可 ≥24,表示次日时刻),步长为 `slotStepMinutes`。
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildCalendarTimelineSlotStartsFromRange(range: TimeRangeOption | undefined, anchorDate: Date | Dayjs, slotStepMinutes?: number): number[];
|
|
15
|
+
/**
|
|
16
|
+
* @deprecated 语义上等价于 {@link buildCalendarTimelineSlotStartsFromRange}(..., 60);保留兼容导出。
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildCalendarHourSlotsFromRange(range: TimeRangeOption | undefined, anchorDate: Date | Dayjs): number[];
|
|
19
|
+
/**
|
|
20
|
+
* 将 range 转为 [startDayjs, endDayjs](reference 为营业锚定日的 0 点)
|
|
21
|
+
* - 同日内:如 08:00–22:00
|
|
22
|
+
* - 跨日营业:结束钟面早于或等于开始(如 02:01–次日 02:00)时,end 解析为 reference 的次日同一时刻
|
|
23
|
+
*/
|
|
24
|
+
export declare function getRangeBounds(range: TimeRangeOption | undefined, reference: Dayjs): [Dayjs, Dayjs];
|
|
25
|
+
/**
|
|
26
|
+
* 将时间吸附到 step 分钟刻度(0、15、30、45 等):四舍五入到最近刻度。
|
|
27
|
+
*/
|
|
28
|
+
export declare function snapToStepMinutes(t: Dayjs, stepMinutes: number): Dayjs;
|
|
29
|
+
/**
|
|
30
|
+
* 判断时间是否落在任一禁用区间内(按绝对时间与区间 [start,end) 比较)
|
|
31
|
+
* 注:与主时间轴同 reference 的跨日 range 一致时需传入同一营业锚定日解析出的区间。
|
|
32
|
+
*/
|
|
33
|
+
export declare function isInDisabledRanges(t: Dayjs, disabledRanges: TimeRangeOption[] | undefined): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* 在 [rangeStart, rangeEnd] 内按 stepMinutes 生成等步刻度时间列表(Dayjs)。
|
|
36
|
+
*
|
|
37
|
+
* @deprecated 仅用于不需要「头/尾 partial 格」的场景;时间轴渲染请用 {@link getAxisCells}。
|
|
38
|
+
*/
|
|
39
|
+
export declare function getTicks(rangeStart: Dayjs, rangeEnd: Dayjs, stepMinutes: number): Dayjs[];
|
|
40
|
+
/**
|
|
41
|
+
* 时间轴上一格的描述:起始时间 + 跨度(分钟)。
|
|
42
|
+
* - 中间格:跨度 = `stepMinutes`,起点对齐到 step 网格(如 15 分钟一格时落在 `:00/:15/:30/:45`);
|
|
43
|
+
* - head 格:当 `rangeStart` 不在网格上时存在,起点 = `rangeStart`,跨度 < step;
|
|
44
|
+
* - tail 格:当 `rangeEnd` 不在网格上时存在,起点 = 最后一个对齐点,跨度 < step。
|
|
45
|
+
*/
|
|
46
|
+
export interface AxisCell {
|
|
47
|
+
start: Dayjs;
|
|
48
|
+
widthMinutes: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 把 [`rangeStart`, `rangeEnd`] 切成「对齐到 step 网格」的格子序列:
|
|
52
|
+
*
|
|
53
|
+
* 1. 找到第一个 ≥ `rangeStart` 且分钟为 `stepMinutes` 整数倍的对齐点;
|
|
54
|
+
* 2. 若对齐点严格大于 `rangeStart`,先放一格 head(`rangeStart` → 对齐点),跨度 < step;
|
|
55
|
+
* 3. 中间按 step 步进,每格起点都落在网格上;
|
|
56
|
+
* 4. 若 `rangeEnd` 落在两个对齐点之间,最后多出一格 tail(最后对齐点 → `rangeEnd`),跨度 < step。
|
|
57
|
+
*
|
|
58
|
+
* `rangeStart` / `rangeEnd` 都恰落在网格上时退化为完全等步格。
|
|
59
|
+
*/
|
|
60
|
+
export declare function getAxisCells(rangeStart: Dayjs, rangeEnd: Dayjs, stepMinutes: number): AxisCell[];
|
|
61
|
+
/**
|
|
62
|
+
* 横向时间轴「格」数量,与 useTimeAxis 中 cells 算法一致。
|
|
63
|
+
* 用于 cursor-moves 模式下计算压缩后的每格像素宽度。
|
|
64
|
+
*/
|
|
65
|
+
export declare function getHorizontalAxisSlotCount(range: TimeRangeOption | undefined, referenceDate: Dayjs, stepMinutes: number): number;
|
|
@@ -32,6 +32,7 @@ __export(utils_exports, {
|
|
|
32
32
|
DEFAULT_CALENDAR_SLOT_STEP_MINUTES: () => DEFAULT_CALENDAR_SLOT_STEP_MINUTES,
|
|
33
33
|
buildCalendarHourSlotsFromRange: () => buildCalendarHourSlotsFromRange,
|
|
34
34
|
buildCalendarTimelineSlotStartsFromRange: () => buildCalendarTimelineSlotStartsFromRange,
|
|
35
|
+
getAxisCells: () => getAxisCells,
|
|
35
36
|
getHorizontalAxisSlotCount: () => getHorizontalAxisSlotCount,
|
|
36
37
|
getRangeBounds: () => getRangeBounds,
|
|
37
38
|
getTicks: () => getTicks,
|
|
@@ -118,18 +119,45 @@ function getTicks(rangeStart, rangeEnd, stepMinutes) {
|
|
|
118
119
|
}
|
|
119
120
|
return out;
|
|
120
121
|
}
|
|
122
|
+
function getAxisCells(rangeStart, rangeEnd, stepMinutes) {
|
|
123
|
+
const out = [];
|
|
124
|
+
if (!rangeEnd.isAfter(rangeStart) || stepMinutes <= 0) return out;
|
|
125
|
+
const startMin = rangeStart.minute();
|
|
126
|
+
const remainder = (startMin % stepMinutes + stepMinutes) % stepMinutes;
|
|
127
|
+
const isStartAligned = remainder === 0 && rangeStart.second() === 0 && rangeStart.millisecond() === 0;
|
|
128
|
+
const firstAligned = isStartAligned ? rangeStart : rangeStart.startOf("hour").minute(startMin - remainder + stepMinutes).second(0).millisecond(0);
|
|
129
|
+
if (firstAligned.isAfter(rangeStart)) {
|
|
130
|
+
const headMin = firstAligned.diff(rangeStart, "minute", true);
|
|
131
|
+
if (headMin > 0) {
|
|
132
|
+
out.push({ start: rangeStart, widthMinutes: headMin });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
let cur = firstAligned;
|
|
136
|
+
const safetyLimit = 2 * 24 * 60 / stepMinutes + 4;
|
|
137
|
+
while (cur.isBefore(rangeEnd) && out.length < safetyLimit) {
|
|
138
|
+
const next = cur.add(stepMinutes, "minute");
|
|
139
|
+
if (next.isAfter(rangeEnd)) {
|
|
140
|
+
const tailMin = rangeEnd.diff(cur, "minute", true);
|
|
141
|
+
if (tailMin > 0) {
|
|
142
|
+
out.push({ start: cur, widthMinutes: tailMin });
|
|
143
|
+
}
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
out.push({ start: cur, widthMinutes: stepMinutes });
|
|
147
|
+
cur = next;
|
|
148
|
+
}
|
|
149
|
+
return out;
|
|
150
|
+
}
|
|
121
151
|
function getHorizontalAxisSlotCount(range, referenceDate, stepMinutes) {
|
|
122
152
|
const [rangeStart, rangeEnd] = getRangeBounds(range, referenceDate);
|
|
123
|
-
|
|
124
|
-
const lastTick = ticks.length > 0 ? ticks[ticks.length - 1] : null;
|
|
125
|
-
const needTailCell = lastTick != null && rangeEnd.isAfter(lastTick);
|
|
126
|
-
return ticks.length + (needTailCell ? 1 : 0);
|
|
153
|
+
return getAxisCells(rangeStart, rangeEnd, stepMinutes).length;
|
|
127
154
|
}
|
|
128
155
|
// Annotate the CommonJS export names for ESM import in node:
|
|
129
156
|
0 && (module.exports = {
|
|
130
157
|
DEFAULT_CALENDAR_SLOT_STEP_MINUTES,
|
|
131
158
|
buildCalendarHourSlotsFromRange,
|
|
132
159
|
buildCalendarTimelineSlotStartsFromRange,
|
|
160
|
+
getAxisCells,
|
|
133
161
|
getHorizontalAxisSlotCount,
|
|
134
162
|
getRangeBounds,
|
|
135
163
|
getTicks,
|