@camstack/ui-library 1.1.23 → 1.1.24

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.
@@ -12,11 +12,13 @@ interface TimelineControlsProps {
12
12
  readonly onViewChange: (w: DayWindow) => void;
13
13
  }
14
14
  /**
15
- * Date selector + zoom-in / zoom-out buttons for the recording timeline.
16
- * Zoom cycles through ZOOM_LEVELS (widest → narrowest), anchored on the view's
17
- * RIGHT edge — so on today's timeline "now" stays pinned to the right instead
18
- * of drifting to a midday range. Horizontal pan (wheel) then moves the window
19
- * back/forward in time. Pan is wired via wheel events in RecordingTimeline.
15
+ * Date selector + prev/next pan + zoom-in / zoom-out buttons for the recording
16
+ * timeline. Zoom cycles through ZOOM_LEVELS (widest → narrowest), anchored on
17
+ * the view's RIGHT edge — so on today's timeline "now" stays pinned to the right
18
+ * instead of drifting to a midday range. The / buttons step the visible
19
+ * window earlier/later within the day (the discoverable equivalent of the
20
+ * horizontal wheel-pan wired in RecordingTimeline), so a zoomed-in day can be
21
+ * navigated back and forth without a mouse wheel.
20
22
  */
21
23
  export declare function TimelineControls({ day, onDayChange, view, dayBounds, onViewChange, }: TimelineControlsProps): import("react").JSX.Element;
22
24
  export {};
package/dist/index.cjs CHANGED
@@ -34197,11 +34197,13 @@ function parseDateInput(value) {
34197
34197
  return new Date(y, m - 1, d);
34198
34198
  }
34199
34199
  /**
34200
- * Date selector + zoom-in / zoom-out buttons for the recording timeline.
34201
- * Zoom cycles through ZOOM_LEVELS (widest → narrowest), anchored on the view's
34202
- * RIGHT edge — so on today's timeline "now" stays pinned to the right instead
34203
- * of drifting to a midday range. Horizontal pan (wheel) then moves the window
34204
- * back/forward in time. Pan is wired via wheel events in RecordingTimeline.
34200
+ * Date selector + prev/next pan + zoom-in / zoom-out buttons for the recording
34201
+ * timeline. Zoom cycles through ZOOM_LEVELS (widest → narrowest), anchored on
34202
+ * the view's RIGHT edge — so on today's timeline "now" stays pinned to the right
34203
+ * instead of drifting to a midday range. The / buttons step the visible
34204
+ * window earlier/later within the day (the discoverable equivalent of the
34205
+ * horizontal wheel-pan wired in RecordingTimeline), so a zoomed-in day can be
34206
+ * navigated back and forth without a mouse wheel.
34205
34207
  */
34206
34208
  function TimelineControls({ day, onDayChange, view, dayBounds, onViewChange }) {
34207
34209
  const handleDateChange = (e) => {
@@ -34236,6 +34238,15 @@ function TimelineControls({ day, onDayChange, view, dayBounds, onViewChange }) {
34236
34238
  };
34237
34239
  const canZoomIn = currentLevelIdx < ZOOM_LEVELS.length - 1;
34238
34240
  const canZoomOut = currentLevelIdx > 0;
34241
+ const panStepMs = Math.max(1, Math.round(viewSpan * .9));
34242
+ const canPanPrev = view.fromMs > dayBounds.fromMs;
34243
+ const canPanNext = view.toMs < dayBounds.toMs;
34244
+ const handlePanPrev = () => {
34245
+ onViewChange(panWindow(view, dayBounds, -panStepMs));
34246
+ };
34247
+ const handlePanNext = () => {
34248
+ onViewChange(panWindow(view, dayBounds, panStepMs));
34249
+ };
34239
34250
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
34240
34251
  className: "flex items-center gap-2",
34241
34252
  children: [
@@ -34249,23 +34260,48 @@ function TimelineControls({ day, onDayChange, view, dayBounds, onViewChange }) {
34249
34260
  }),
34250
34261
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
34251
34262
  className: "ml-auto flex items-center gap-1",
34252
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
34253
- type: "button",
34254
- onClick: handleZoomOut,
34255
- disabled: !canZoomOut,
34256
- title: "Zoom out",
34257
- "aria-label": "Zoom out",
34258
- className: "rounded p-1 text-foreground-subtle transition-colors hover:bg-background/60 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40",
34259
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZoomOut, { size: 13 })
34260
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
34261
- type: "button",
34262
- onClick: handleZoomIn,
34263
- disabled: !canZoomIn,
34264
- title: "Zoom in",
34265
- "aria-label": "Zoom in",
34266
- className: "rounded p-1 text-foreground-subtle transition-colors hover:bg-background/60 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40",
34267
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZoomIn, { size: 13 })
34268
- })]
34263
+ children: [
34264
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
34265
+ type: "button",
34266
+ onClick: handlePanPrev,
34267
+ disabled: !canPanPrev,
34268
+ title: "Earlier (pan back)",
34269
+ "aria-label": "Pan earlier",
34270
+ className: "rounded p-1 text-foreground-subtle transition-colors hover:bg-background/60 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40",
34271
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronLeft, { size: 14 })
34272
+ }),
34273
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
34274
+ type: "button",
34275
+ onClick: handlePanNext,
34276
+ disabled: !canPanNext,
34277
+ title: "Later (pan forward)",
34278
+ "aria-label": "Pan later",
34279
+ className: "rounded p-1 text-foreground-subtle transition-colors hover:bg-background/60 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40",
34280
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronRight, { size: 14 })
34281
+ }),
34282
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
34283
+ className: "mx-0.5 h-3 w-px bg-border",
34284
+ "aria-hidden": "true"
34285
+ }),
34286
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
34287
+ type: "button",
34288
+ onClick: handleZoomOut,
34289
+ disabled: !canZoomOut,
34290
+ title: "Zoom out",
34291
+ "aria-label": "Zoom out",
34292
+ className: "rounded p-1 text-foreground-subtle transition-colors hover:bg-background/60 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40",
34293
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZoomOut, { size: 13 })
34294
+ }),
34295
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
34296
+ type: "button",
34297
+ onClick: handleZoomIn,
34298
+ disabled: !canZoomIn,
34299
+ title: "Zoom in",
34300
+ "aria-label": "Zoom in",
34301
+ className: "rounded p-1 text-foreground-subtle transition-colors hover:bg-background/60 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40",
34302
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ZoomIn, { size: 13 })
34303
+ })
34304
+ ]
34269
34305
  }),
34270
34306
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
34271
34307
  className: "text-[9px] text-foreground-subtle",
package/dist/index.js CHANGED
@@ -34173,11 +34173,13 @@ function parseDateInput(value) {
34173
34173
  return new Date(y, m - 1, d);
34174
34174
  }
34175
34175
  /**
34176
- * Date selector + zoom-in / zoom-out buttons for the recording timeline.
34177
- * Zoom cycles through ZOOM_LEVELS (widest → narrowest), anchored on the view's
34178
- * RIGHT edge — so on today's timeline "now" stays pinned to the right instead
34179
- * of drifting to a midday range. Horizontal pan (wheel) then moves the window
34180
- * back/forward in time. Pan is wired via wheel events in RecordingTimeline.
34176
+ * Date selector + prev/next pan + zoom-in / zoom-out buttons for the recording
34177
+ * timeline. Zoom cycles through ZOOM_LEVELS (widest → narrowest), anchored on
34178
+ * the view's RIGHT edge — so on today's timeline "now" stays pinned to the right
34179
+ * instead of drifting to a midday range. The / buttons step the visible
34180
+ * window earlier/later within the day (the discoverable equivalent of the
34181
+ * horizontal wheel-pan wired in RecordingTimeline), so a zoomed-in day can be
34182
+ * navigated back and forth without a mouse wheel.
34181
34183
  */
34182
34184
  function TimelineControls({ day, onDayChange, view, dayBounds, onViewChange }) {
34183
34185
  const handleDateChange = (e) => {
@@ -34212,6 +34214,15 @@ function TimelineControls({ day, onDayChange, view, dayBounds, onViewChange }) {
34212
34214
  };
34213
34215
  const canZoomIn = currentLevelIdx < ZOOM_LEVELS.length - 1;
34214
34216
  const canZoomOut = currentLevelIdx > 0;
34217
+ const panStepMs = Math.max(1, Math.round(viewSpan * .9));
34218
+ const canPanPrev = view.fromMs > dayBounds.fromMs;
34219
+ const canPanNext = view.toMs < dayBounds.toMs;
34220
+ const handlePanPrev = () => {
34221
+ onViewChange(panWindow(view, dayBounds, -panStepMs));
34222
+ };
34223
+ const handlePanNext = () => {
34224
+ onViewChange(panWindow(view, dayBounds, panStepMs));
34225
+ };
34215
34226
  return /* @__PURE__ */ jsxs("div", {
34216
34227
  className: "flex items-center gap-2",
34217
34228
  children: [
@@ -34225,23 +34236,48 @@ function TimelineControls({ day, onDayChange, view, dayBounds, onViewChange }) {
34225
34236
  }),
34226
34237
  /* @__PURE__ */ jsxs("div", {
34227
34238
  className: "ml-auto flex items-center gap-1",
34228
- children: [/* @__PURE__ */ jsx("button", {
34229
- type: "button",
34230
- onClick: handleZoomOut,
34231
- disabled: !canZoomOut,
34232
- title: "Zoom out",
34233
- "aria-label": "Zoom out",
34234
- className: "rounded p-1 text-foreground-subtle transition-colors hover:bg-background/60 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40",
34235
- children: /* @__PURE__ */ jsx(ZoomOut, { size: 13 })
34236
- }), /* @__PURE__ */ jsx("button", {
34237
- type: "button",
34238
- onClick: handleZoomIn,
34239
- disabled: !canZoomIn,
34240
- title: "Zoom in",
34241
- "aria-label": "Zoom in",
34242
- className: "rounded p-1 text-foreground-subtle transition-colors hover:bg-background/60 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40",
34243
- children: /* @__PURE__ */ jsx(ZoomIn, { size: 13 })
34244
- })]
34239
+ children: [
34240
+ /* @__PURE__ */ jsx("button", {
34241
+ type: "button",
34242
+ onClick: handlePanPrev,
34243
+ disabled: !canPanPrev,
34244
+ title: "Earlier (pan back)",
34245
+ "aria-label": "Pan earlier",
34246
+ className: "rounded p-1 text-foreground-subtle transition-colors hover:bg-background/60 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40",
34247
+ children: /* @__PURE__ */ jsx(ChevronLeft, { size: 14 })
34248
+ }),
34249
+ /* @__PURE__ */ jsx("button", {
34250
+ type: "button",
34251
+ onClick: handlePanNext,
34252
+ disabled: !canPanNext,
34253
+ title: "Later (pan forward)",
34254
+ "aria-label": "Pan later",
34255
+ className: "rounded p-1 text-foreground-subtle transition-colors hover:bg-background/60 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40",
34256
+ children: /* @__PURE__ */ jsx(ChevronRight, { size: 14 })
34257
+ }),
34258
+ /* @__PURE__ */ jsx("span", {
34259
+ className: "mx-0.5 h-3 w-px bg-border",
34260
+ "aria-hidden": "true"
34261
+ }),
34262
+ /* @__PURE__ */ jsx("button", {
34263
+ type: "button",
34264
+ onClick: handleZoomOut,
34265
+ disabled: !canZoomOut,
34266
+ title: "Zoom out",
34267
+ "aria-label": "Zoom out",
34268
+ className: "rounded p-1 text-foreground-subtle transition-colors hover:bg-background/60 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40",
34269
+ children: /* @__PURE__ */ jsx(ZoomOut, { size: 13 })
34270
+ }),
34271
+ /* @__PURE__ */ jsx("button", {
34272
+ type: "button",
34273
+ onClick: handleZoomIn,
34274
+ disabled: !canZoomIn,
34275
+ title: "Zoom in",
34276
+ "aria-label": "Zoom in",
34277
+ className: "rounded p-1 text-foreground-subtle transition-colors hover:bg-background/60 hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40",
34278
+ children: /* @__PURE__ */ jsx(ZoomIn, { size: 13 })
34279
+ })
34280
+ ]
34245
34281
  }),
34246
34282
  /* @__PURE__ */ jsx("span", {
34247
34283
  className: "text-[9px] text-foreground-subtle",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/ui-library",
3
- "version": "1.1.23",
3
+ "version": "1.1.24",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",