dialkit 1.4.0 → 1.4.1

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/vue/index.js CHANGED
@@ -2106,6 +2106,10 @@ var ICON_PAUSE = [
2106
2106
  "M16.75 3C15.2312 3 14 4.23122 14 5.75V18.25C14 19.7688 15.2312 21 16.75 21H17.25C18.7688 21 20 19.7688 20 18.25V5.75C20 4.23122 18.7688 3 17.25 3H16.75Z"
2107
2107
  ];
2108
2108
  var ICON_PLAY = "M9.24394 2.36758C7.41419 1.18362 5 2.49701 5 4.67639V19.3238C5 21.5032 7.41419 22.8166 9.24394 21.6326L20.5624 14.3089C22.2371 13.2253 22.2372 10.775 20.5624 9.69129L9.24394 2.36758Z";
2109
+ var ICON_REPLAY = [
2110
+ "M12 2.5C17.2466 2.50016 21.5 6.7534 21.5 12C21.5 17.2466 17.2466 21.4998 12 21.5C7.52191 21.5 3.76987 18.4025 2.76465 14.2344C2.63517 13.6975 2.96508 13.1578 3.50195 13.0283C4.03883 12.8988 4.57851 13.2288 4.70801 13.7656C5.5016 17.0563 8.46701 19.5 12 19.5C16.142 19.4998 19.5 16.142 19.5 12C19.5 7.85796 16.142 4.50016 12 4.5C9.32981 4.5 6.98389 5.89541 5.6543 8H7.5C8.05228 8 8.5 8.44772 8.5 9C8.5 9.55228 8.05228 10 7.5 10H3.5C2.94772 10 2.5 9.55228 2.5 9V5C2.5 4.44772 2.94772 4 3.5 4C4.05228 4 4.5 4.44772 4.5 5V6.16797C6.2376 3.93677 8.95063 2.5 12 2.5Z",
2111
+ "M10 9.94043C10 9.33379 10.6826 8.97849 11.1797 9.32617L14.1221 11.3857C14.5486 11.6843 14.5486 12.3157 14.1221 12.6143L11.1797 14.6738C10.6826 15.0215 10 14.6662 10 14.0596V9.94043Z"
2112
+ ];
2109
2113
  var ICON_TIMELINE = [
2110
2114
  "M18.868 10C20.8517 10.0003 22.2886 11.8914 21.7577 13.8027L20.369 18.8027C20.0083 20.1012 18.826 20.9999 17.4784 21H6.51941C5.17179 21 3.98948 20.1012 3.62878 18.8027L2.24011 13.8027C1.7092 11.8913 3.14603 10.0003 5.12976 10H18.868Z",
2111
2115
  "M18.9989 6.5C19.5511 6.50007 19.9989 6.94776 19.9989 7.5C19.9989 8.05224 19.5511 8.49993 18.9989 8.5H4.9989C4.44661 8.5 3.9989 8.05228 3.9989 7.5C3.9989 6.94772 4.44661 6.5 4.9989 6.5H18.9989Z",
@@ -4786,8 +4790,11 @@ var SECOND_TICK_STEPS = [
4786
4790
  ];
4787
4791
  var MIN_TIMELINE_MAX_ZOOM = 8;
4788
4792
  var PLAYHEAD_FLAG_WIDTH = 52;
4793
+ var PLAYHEAD_FLAG_EDGE_OVERHANG = 1;
4789
4794
  var POPOVER_WIDTH = 280;
4790
4795
  var ZOOM_DRAG_DISTANCE = 180;
4796
+ var DEFAULT_DOCK_MAX_HEIGHT = 400;
4797
+ var MIN_DOCK_MAX_HEIGHT = 120;
4791
4798
  var DialTimeline = defineComponent19({
4792
4799
  name: "DialKitTimeline",
4793
4800
  props: {
@@ -4805,10 +4812,36 @@ var DialTimeline = defineComponent19({
4805
4812
  const timelines = ref15(TimelineStore.getTimelines());
4806
4813
  const dockVisible = ref15(TimelineUiStore.getVisible());
4807
4814
  const mounted = ref15(false);
4815
+ const dockMaxHeight = ref15(DEFAULT_DOCK_MAX_HEIGHT);
4816
+ const dockRef = ref15(null);
4808
4817
  const controllerId = /* @__PURE__ */ Symbol("dialkit-timeline-visibility");
4809
4818
  let unsubscribeTimelines;
4810
4819
  let unsubscribeVisibility;
4811
4820
  let unregisterController;
4821
+ let resizeCleanup = null;
4822
+ const handleResizePointerDown = (event) => {
4823
+ if (!dockRef.value) return;
4824
+ event.preventDefault();
4825
+ event.stopPropagation();
4826
+ resizeCleanup?.();
4827
+ const pointerY = event.clientY;
4828
+ const startHeight = dockRef.value.getBoundingClientRect().height;
4829
+ const move = (next) => {
4830
+ next.preventDefault();
4831
+ const viewportMax = Math.max(MIN_DOCK_MAX_HEIGHT, window.innerHeight - 24);
4832
+ dockMaxHeight.value = clamp(startHeight + pointerY - next.clientY, MIN_DOCK_MAX_HEIGHT, viewportMax);
4833
+ };
4834
+ const finish = () => {
4835
+ window.removeEventListener("pointermove", move);
4836
+ window.removeEventListener("pointerup", finish);
4837
+ window.removeEventListener("pointercancel", finish);
4838
+ resizeCleanup = null;
4839
+ };
4840
+ window.addEventListener("pointermove", move, { passive: false });
4841
+ window.addEventListener("pointerup", finish);
4842
+ window.addEventListener("pointercancel", finish);
4843
+ resizeCleanup = finish;
4844
+ };
4812
4845
  onMounted13(() => {
4813
4846
  mounted.value = true;
4814
4847
  unsubscribeVisibility = TimelineUiStore.subscribe(() => {
@@ -4835,6 +4868,7 @@ var DialTimeline = defineComponent19({
4835
4868
  unregisterController?.();
4836
4869
  unsubscribeTimelines?.();
4837
4870
  unsubscribeVisibility?.();
4871
+ resizeCleanup?.();
4838
4872
  });
4839
4873
  return () => {
4840
4874
  if (!props.productionEnabled || !mounted.value || timelines.value.length === 0) return null;
@@ -4844,7 +4878,19 @@ var DialTimeline = defineComponent19({
4844
4878
  "data-theme": props.theme,
4845
4879
  hidden: !dockVisible.value
4846
4880
  }, [
4847
- h19("div", { class: "dialkit-timeline-dock" }, timelines.value.map((meta) => h19(TimelineSection, {
4881
+ h19("div", {
4882
+ class: "dialkit-timeline-resize-handle",
4883
+ role: "separator",
4884
+ "aria-label": "Resize timeline height",
4885
+ "aria-orientation": "horizontal",
4886
+ title: "Drag to resize timeline",
4887
+ onPointerdown: handleResizePointerDown
4888
+ }),
4889
+ h19("div", {
4890
+ ref: dockRef,
4891
+ class: "dialkit-timeline-dock",
4892
+ style: { maxHeight: `min(${dockMaxHeight.value}px, calc(100vh - 24px))` }
4893
+ }, timelines.value.map((meta) => h19(TimelineSection, {
4848
4894
  key: meta.id,
4849
4895
  meta,
4850
4896
  defaultOpen: props.defaultOpen,
@@ -4885,6 +4931,23 @@ var PlayPauseButton = defineComponent19({
4885
4931
  };
4886
4932
  }
4887
4933
  });
4934
+ var ReplayButton = defineComponent19({
4935
+ props: { onReplay: { type: Function, required: true } },
4936
+ setup(props) {
4937
+ return () => h19("button", {
4938
+ class: "dialkit-toolbar-add",
4939
+ title: "Replay",
4940
+ "aria-label": "Replay",
4941
+ onClick: props.onReplay
4942
+ }, [
4943
+ h19(
4944
+ "svg",
4945
+ { viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true" },
4946
+ ICON_REPLAY.map((path) => h19("path", { d: path, fill: "currentColor" }))
4947
+ )
4948
+ ]);
4949
+ }
4950
+ });
4888
4951
  var iconStyle = {
4889
4952
  position: "absolute",
4890
4953
  inset: 0,
@@ -4961,8 +5024,6 @@ var TimelinePlayheadFlag = defineComponent19({
4961
5024
  viewEnd: { type: Number, required: true },
4962
5025
  laneWidth: { type: Number, required: true },
4963
5026
  ruler: Object,
4964
- headerClearStart: { type: Number, required: true },
4965
- headerClearEnd: { type: Number, required: true },
4966
5027
  onResetView: { type: Function, required: true }
4967
5028
  },
4968
5029
  setup(props) {
@@ -4990,13 +5051,20 @@ var TimelinePlayheadFlag = defineComponent19({
4990
5051
  return () => {
4991
5052
  if (time.value < props.viewStart || time.value > props.viewEnd || props.laneWidth <= 0) return null;
4992
5053
  const x = clamp((time.value - props.viewStart) * props.pxPerSecond, 0, props.laneWidth);
4993
- const left = x - PLAYHEAD_FLAG_WIDTH / 2;
4994
- const placement = left >= props.headerClearStart && left + PLAYHEAD_FLAG_WIDTH <= props.headerClearEnd ? "raised" : "lowered";
5054
+ const flagCenter = clamp(
5055
+ x,
5056
+ PLAYHEAD_FLAG_WIDTH / 2 - PLAYHEAD_FLAG_EDGE_OVERHANG,
5057
+ props.laneWidth - PLAYHEAD_FLAG_WIDTH / 2 + PLAYHEAD_FLAG_EDGE_OVERHANG
5058
+ );
5059
+ const flagOffset = flagCenter - x;
5060
+ const edge = flagOffset > 0.5 ? "start" : flagOffset < -0.5 ? "end" : "center";
4995
5061
  return h19("div", {
4996
5062
  class: "dialkit-timeline-playhead-control",
4997
- "data-edge": "center",
4998
- "data-placement": placement,
4999
- style: { left: `calc(var(--dial-timeline-label-w) + ${x}px)` },
5063
+ "data-edge": edge,
5064
+ style: {
5065
+ left: `calc(var(--dial-timeline-label-w) + ${x}px)`,
5066
+ "--dial-timeline-playhead-flag-offset": `${flagOffset}px`
5067
+ },
5000
5068
  role: "slider",
5001
5069
  "aria-label": "Timeline current time",
5002
5070
  "aria-valuemin": 0,
@@ -5037,8 +5105,10 @@ var TimelinePlayheadFlag = defineComponent19({
5037
5105
  cleanup = finish;
5038
5106
  }
5039
5107
  }, [
5040
- h19("div", { class: "dialkit-timeline-playhead-flag" }, time.value.toFixed(2)),
5041
- h19("div", { class: "dialkit-timeline-playhead-stem" })
5108
+ h19("div", { class: "dialkit-timeline-playhead-stem" }),
5109
+ h19("div", { class: "dialkit-timeline-playhead-anchor" }, [
5110
+ h19("div", { class: "dialkit-timeline-playhead-flag" }, time.value.toFixed(2))
5111
+ ])
5042
5112
  ]);
5043
5113
  };
5044
5114
  }
@@ -5070,33 +5140,21 @@ var TimelineSection = defineComponent19({
5070
5140
  const presets = ref15(DialStore.getPresets(props.meta.id));
5071
5141
  const activePresetId = ref15(DialStore.getActivePresetId(props.meta.id));
5072
5142
  const laneAreaRef = ref15(null);
5073
- const titleRef = ref15(null);
5074
- const actionsRef = ref15(null);
5143
+ const horizontalScrollRef = ref15(null);
5075
5144
  const laneWidth = ref15(0);
5076
- const flagClearRange = ref15({ start: 0, end: 0 });
5077
5145
  let unsubscribeValues;
5078
5146
  let resizeObserver;
5079
5147
  const measure = () => {
5080
- if (!laneAreaRef.value || !titleRef.value || !actionsRef.value) return;
5081
- const ruler = laneAreaRef.value.getBoundingClientRect();
5082
- const title = titleRef.value.getBoundingClientRect();
5083
- const actions = actionsRef.value.getBoundingClientRect();
5084
- laneWidth.value = ruler.width;
5085
- flagClearRange.value = {
5086
- start: Math.round(title.right + 10 - ruler.left),
5087
- end: Math.round(actions.left - 10 - ruler.left)
5088
- };
5148
+ if (laneAreaRef.value) laneWidth.value = laneAreaRef.value.getBoundingClientRect().width;
5089
5149
  };
5090
5150
  const connectMeasure = async () => {
5091
5151
  resizeObserver?.disconnect();
5092
5152
  if (!open.value) return;
5093
5153
  await nextTick4();
5094
- if (!laneAreaRef.value || !titleRef.value || !actionsRef.value) return;
5154
+ if (!laneAreaRef.value) return;
5095
5155
  measure();
5096
5156
  resizeObserver = new ResizeObserver(measure);
5097
5157
  resizeObserver.observe(laneAreaRef.value);
5098
- resizeObserver.observe(titleRef.value);
5099
- resizeObserver.observe(actionsRef.value);
5100
5158
  };
5101
5159
  onMounted13(() => {
5102
5160
  unsubscribeValues = DialStore.subscribe(props.meta.id, () => {
@@ -5128,6 +5186,13 @@ var TimelineSection = defineComponent19({
5128
5186
  watch8([() => props.meta.duration, zoom], () => {
5129
5187
  viewStart.value = clampViewStart(viewStart.value, props.meta.duration, props.meta.duration / zoom.value);
5130
5188
  });
5189
+ watch8([open, pxPerSecond, safeViewStart], async () => {
5190
+ await nextTick4();
5191
+ const scroller = horizontalScrollRef.value;
5192
+ if (!scroller || pxPerSecond.value <= 0) return;
5193
+ const next = safeViewStart.value * pxPerSecond.value;
5194
+ if (Math.abs(scroller.scrollLeft - next) > 0.5) scroller.scrollLeft = next;
5195
+ });
5131
5196
  const centerViewAt = (time) => {
5132
5197
  if (zoom.value <= 1 || props.meta.duration <= 0) return;
5133
5198
  const duration = props.meta.duration / zoom.value;
@@ -5137,6 +5202,26 @@ var TimelineSection = defineComponent19({
5137
5202
  zoom.value = 1;
5138
5203
  viewStart.value = 0;
5139
5204
  };
5205
+ const handleReplay = () => {
5206
+ viewStart.value = 0;
5207
+ TimelineStore.replay(props.meta.id);
5208
+ };
5209
+ const handleHorizontalScroll = (event) => {
5210
+ if (pxPerSecond.value <= 0) return;
5211
+ viewStart.value = clampViewStart(
5212
+ event.currentTarget.scrollLeft / pxPerSecond.value,
5213
+ props.meta.duration,
5214
+ visibleDuration.value
5215
+ );
5216
+ };
5217
+ const handleTimelineWheel = (event) => {
5218
+ const scroller = horizontalScrollRef.value;
5219
+ if (!scroller || zoom.value <= 1) return;
5220
+ const delta = Math.abs(event.deltaX) > Math.abs(event.deltaY) ? event.deltaX : event.shiftKey ? event.deltaY : 0;
5221
+ if (delta === 0) return;
5222
+ event.preventDefault();
5223
+ scroller.scrollLeft += delta;
5224
+ };
5140
5225
  let zoomDrag = null;
5141
5226
  let rulerScrub = null;
5142
5227
  let trackScrub = null;
@@ -5320,7 +5405,7 @@ var TimelineSection = defineComponent19({
5320
5405
  return () => h19("div", { class: "dialkit-timeline-section" }, [
5321
5406
  h19("div", { class: "dialkit-timeline-header", "data-open": open.value || void 0 }, [
5322
5407
  h19("div", { class: "dialkit-timeline-identity" }, [
5323
- h19("span", { ref: titleRef, class: "dialkit-timeline-title" }, props.meta.name)
5408
+ h19("span", { class: "dialkit-timeline-title" }, props.meta.name)
5324
5409
  ]),
5325
5410
  !open.value ? h19(TimelineOverview, {
5326
5411
  id: props.meta.id,
@@ -5329,8 +5414,9 @@ var TimelineSection = defineComponent19({
5329
5414
  viewEnd: viewEnd.value,
5330
5415
  onNavigate: centerViewAt
5331
5416
  }) : null,
5332
- h19("div", { ref: actionsRef, class: "dialkit-timeline-actions" }, [
5417
+ h19("div", { class: "dialkit-timeline-actions" }, [
5333
5418
  h19(PlayPauseButton, { id: props.meta.id }),
5419
+ h19(ReplayButton, { onReplay: handleReplay }),
5334
5420
  h19("button", { class: "dialkit-toolbar-add", title: "Add timeline version", "aria-label": "Add timeline version", onClick: handleAddPreset }, [
5335
5421
  h19(
5336
5422
  "svg",
@@ -5364,6 +5450,7 @@ var TimelineSection = defineComponent19({
5364
5450
  ]),
5365
5451
  open.value ? h19("div", {
5366
5452
  class: "dialkit-timeline-body",
5453
+ onWheel: handleTimelineWheel,
5367
5454
  onPointerdown: (event) => {
5368
5455
  const target = event.target;
5369
5456
  if (target.closest(".dialkit-timeline-label, button")) return;
@@ -5457,11 +5544,17 @@ var TimelineSection = defineComponent19({
5457
5544
  viewEnd: viewEnd.value,
5458
5545
  laneWidth: laneWidth.value,
5459
5546
  ruler: laneAreaRef.value ?? void 0,
5460
- headerClearStart: flagClearRange.value.start,
5461
- headerClearEnd: flagClearRange.value.end,
5462
5547
  onResetView: resetView
5463
5548
  }) : null
5464
- ])]) : null,
5549
+ ]), zoom.value > 1 ? h19("div", { class: "dialkit-timeline-scroll-row" }, [
5550
+ h19("div", { class: "dialkit-timeline-label" }),
5551
+ h19("div", {
5552
+ ref: horizontalScrollRef,
5553
+ class: "dialkit-timeline-horizontal-scroll",
5554
+ "aria-label": "Timeline horizontal scroll",
5555
+ onScroll: handleHorizontalScroll
5556
+ }, [h19("div", { style: { width: `${laneWidth.value * zoom.value}px` } })])
5557
+ ]) : null]) : null,
5465
5558
  popover.value ? h19(ClipPopover, {
5466
5559
  panelId: props.meta.id,
5467
5560
  popover: popover.value,