dialkit 1.3.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.
Files changed (71) hide show
  1. package/README.md +433 -3
  2. package/dist/icons.d.ts +5 -1
  3. package/dist/icons.js +18 -0
  4. package/dist/icons.js.map +1 -1
  5. package/dist/index.cjs +3222 -479
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.cts +274 -6
  8. package/dist/index.d.ts +274 -6
  9. package/dist/index.js +3154 -416
  10. package/dist/index.js.map +1 -1
  11. package/dist/solid/index.d.ts +225 -3
  12. package/dist/solid/index.js +5761 -2500
  13. package/dist/solid/index.js.map +1 -1
  14. package/dist/store/index.cjs +57 -16
  15. package/dist/store/index.cjs.map +1 -1
  16. package/dist/store/index.d.cts +14 -2
  17. package/dist/store/index.d.ts +14 -2
  18. package/dist/store/index.js +52 -16
  19. package/dist/store/index.js.map +1 -1
  20. package/dist/styles.css +788 -0
  21. package/dist/svelte/components/ControlRenderer.svelte +5 -2
  22. package/dist/svelte/components/ControlRenderer.svelte.d.ts +2 -0
  23. package/dist/svelte/components/ControlRenderer.svelte.d.ts.map +1 -1
  24. package/dist/svelte/components/DialRoot.svelte +43 -6
  25. package/dist/svelte/components/DialRoot.svelte.d.ts.map +1 -1
  26. package/dist/svelte/components/Panel.svelte +7 -1
  27. package/dist/svelte/components/Panel.svelte.d.ts +2 -0
  28. package/dist/svelte/components/Panel.svelte.d.ts.map +1 -1
  29. package/dist/svelte/components/Timeline/ClipPopover.svelte +206 -0
  30. package/dist/svelte/components/Timeline/ClipPopover.svelte.d.ts +26 -0
  31. package/dist/svelte/components/Timeline/ClipPopover.svelte.d.ts.map +1 -0
  32. package/dist/svelte/components/Timeline/DialTimeline.svelte +125 -0
  33. package/dist/svelte/components/Timeline/DialTimeline.svelte.d.ts +13 -0
  34. package/dist/svelte/components/Timeline/DialTimeline.svelte.d.ts.map +1 -0
  35. package/dist/svelte/components/Timeline/TimelineClip.svelte +233 -0
  36. package/dist/svelte/components/Timeline/TimelineClip.svelte.d.ts +24 -0
  37. package/dist/svelte/components/Timeline/TimelineClip.svelte.d.ts.map +1 -0
  38. package/dist/svelte/components/Timeline/TimelineSection.svelte +803 -0
  39. package/dist/svelte/components/Timeline/TimelineSection.svelte.d.ts +12 -0
  40. package/dist/svelte/components/Timeline/TimelineSection.svelte.d.ts.map +1 -0
  41. package/dist/svelte/components/Timeline/TimelineToggleButton.svelte +25 -0
  42. package/dist/svelte/components/Timeline/TimelineToggleButton.svelte.d.ts +4 -0
  43. package/dist/svelte/components/Timeline/TimelineToggleButton.svelte.d.ts.map +1 -0
  44. package/dist/svelte/components/TransitionControl.svelte +26 -11
  45. package/dist/svelte/components/TransitionControl.svelte.d.ts +9 -0
  46. package/dist/svelte/components/TransitionControl.svelte.d.ts.map +1 -1
  47. package/dist/svelte/createDialTimeline.svelte.d.ts +4 -0
  48. package/dist/svelte/createDialTimeline.svelte.d.ts.map +1 -0
  49. package/dist/svelte/createDialTimeline.svelte.js +73 -0
  50. package/dist/svelte/index.d.ts +4 -0
  51. package/dist/svelte/index.d.ts.map +1 -1
  52. package/dist/svelte/index.js +3 -0
  53. package/dist/svelte/theme-css.d.ts +1 -1
  54. package/dist/svelte/theme-css.d.ts.map +1 -1
  55. package/dist/svelte/theme-css.js +788 -0
  56. package/dist/timeline/index.cjs +1288 -0
  57. package/dist/timeline/index.cjs.map +1 -0
  58. package/dist/timeline/index.d.cts +443 -0
  59. package/dist/timeline/index.d.ts +443 -0
  60. package/dist/timeline/index.js +1233 -0
  61. package/dist/timeline/index.js.map +1 -0
  62. package/dist/vue/index.d.ts +273 -7
  63. package/dist/vue/index.js +4116 -1517
  64. package/dist/vue/index.js.map +1 -1
  65. package/package.json +23 -13
  66. package/dist/solid/index.cjs +0 -3536
  67. package/dist/solid/index.cjs.map +0 -1
  68. package/dist/solid/index.d.cts +0 -295
  69. package/dist/vue/index.cjs +0 -3497
  70. package/dist/vue/index.cjs.map +0 -1
  71. package/dist/vue/index.d.cts +0 -722
@@ -0,0 +1,233 @@
1
+ <script lang="ts">
2
+ import { DialStore } from 'dialkit/store';
3
+ import {
4
+ clampClipMove,
5
+ clampClipResizeEnd,
6
+ clampClipResizeStart,
7
+ clampStepResize,
8
+ clampTrackDelay,
9
+ formatSeconds,
10
+ } from 'dialkit/timeline';
11
+ import type { TimelineClipLoop, TimelineClipMeta, TimelineStepStatic } from 'dialkit/timeline';
12
+
13
+ const DRAG_THRESHOLD_PX = 3;
14
+
15
+ type DragState = {
16
+ mode: 'move' | 'start' | 'end' | 'boundary';
17
+ boundaryIndex?: number;
18
+ pointerX: number;
19
+ at: number;
20
+ duration: number;
21
+ stepDurations?: number[];
22
+ clickEl: HTMLElement | null;
23
+ moved: boolean;
24
+ };
25
+
26
+ let {
27
+ timelineId,
28
+ clip,
29
+ at,
30
+ duration,
31
+ loop,
32
+ steps,
33
+ fixedDuration,
34
+ composite = false,
35
+ baseAt = 0,
36
+ delayMode = false,
37
+ pxPerSecond,
38
+ viewStart,
39
+ timelineDuration,
40
+ selected,
41
+ selectedStepKey,
42
+ onClick,
43
+ onDrag,
44
+ } = $props<{
45
+ timelineId: string;
46
+ clip: TimelineClipMeta;
47
+ at: number;
48
+ duration: number;
49
+ loop: TimelineClipLoop;
50
+ steps?: TimelineStepStatic[];
51
+ fixedDuration: boolean;
52
+ composite?: boolean;
53
+ baseAt?: number;
54
+ delayMode?: boolean;
55
+ pxPerSecond: number;
56
+ viewStart: number;
57
+ timelineDuration: number;
58
+ selected: boolean;
59
+ selectedStepKey?: string;
60
+ onClick: (clip: TimelineClipMeta, rect: DOMRect, stepKey?: string) => void;
61
+ onDrag: () => void;
62
+ }>();
63
+
64
+ let drag: DragState | null = null;
65
+ let dragging = $state(false);
66
+ const isSteps = $derived(Boolean(steps?.length));
67
+ const width = $derived(Math.max(duration * pxPerSecond, 14));
68
+ const resizable = $derived(duration > 0 && !fixedDuration && !composite);
69
+ const durationText = $derived(`${fixedDuration && !composite ? '~' : ''}${formatSeconds(duration)}`);
70
+ const looping = $derived(loop === 'repeat' && duration > 0);
71
+ const ghostCycles = $derived.by(() => {
72
+ const result: Array<{ start: number; duration: number; index: number }> = [];
73
+ if (!looping) return result;
74
+ const first = Math.max(1, Math.floor((viewStart - at) / duration));
75
+ for (let offset = 0; offset < 256; offset++) {
76
+ const index = first + offset;
77
+ const start = at + duration * index;
78
+ if (start >= timelineDuration - 1e-6) break;
79
+ result.push({ start, duration: Math.min(duration, timelineDuration - start), index });
80
+ }
81
+ return result;
82
+ });
83
+ const boundaries = $derived.by(() => {
84
+ let total = 0;
85
+ return steps?.map((step: TimelineStepStatic) => (total += step.duration)) ?? [];
86
+ });
87
+ const barTitle = $derived(composite
88
+ ? `${clip.label} — composite of its property tracks${looping ? ' · repeats through timeline' : ''} · click to expand`
89
+ : `${clip.label} — ${formatSeconds(at)} for ${durationText}${fixedDuration ? ' (duration set by spring physics)' : ''}${looping ? ' · repeats through timeline' : ''}${delayMode ? ' · drag to phase-shift' : ''}`);
90
+
91
+ function handlePointerDown(event: PointerEvent) {
92
+ if (event.shiftKey) return;
93
+ event.stopPropagation();
94
+ const target = event.target as HTMLElement;
95
+ let mode: DragState['mode'] = 'move';
96
+ let boundaryIndex: number | undefined;
97
+ if (target.dataset.boundary !== undefined) {
98
+ mode = 'boundary';
99
+ boundaryIndex = Number(target.dataset.boundary);
100
+ } else if (!fixedDuration) {
101
+ const edge = target.dataset.edge as 'start' | 'end' | undefined;
102
+ if (edge) mode = edge;
103
+ }
104
+ drag = {
105
+ mode,
106
+ boundaryIndex,
107
+ pointerX: event.clientX,
108
+ at,
109
+ duration,
110
+ stepDurations: steps?.map((step: TimelineStepStatic) => step.duration),
111
+ clickEl: target.closest?.('[data-step]') as HTMLElement | null,
112
+ moved: false,
113
+ };
114
+ (event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);
115
+ }
116
+
117
+ function handlePointerMove(event: PointerEvent) {
118
+ if (!drag || pxPerSecond <= 0) return;
119
+ const dx = event.clientX - drag.pointerX;
120
+ if (!drag.moved) {
121
+ if (Math.abs(dx) <= DRAG_THRESHOLD_PX) return;
122
+ drag.moved = true;
123
+ dragging = true;
124
+ onDrag();
125
+ }
126
+ const dt = dx / pxPerSecond;
127
+ if (drag.mode === 'boundary' && steps && drag.stepDurations) {
128
+ const index = drag.boundaryIndex ?? 0;
129
+ const others = drag.stepDurations.reduce((sum, value, stepIndex) => stepIndex === index ? sum : sum + value, 0);
130
+ DialStore.updateValue(
131
+ timelineId,
132
+ `${clip.key}.${steps[index].key ?? ''}.duration`,
133
+ clampStepResize(drag.stepDurations[index] + dt, drag.at, others, timelineDuration)
134
+ );
135
+ } else if (drag.mode === 'move') {
136
+ if (delayMode) {
137
+ DialStore.updateValue(timelineId, `${clip.key}.delay`, clampTrackDelay(drag.at + dt - baseAt, baseAt, drag.duration, timelineDuration));
138
+ } else {
139
+ DialStore.updateValue(timelineId, `${clip.key}.at`, clampClipMove(drag.at + dt, drag.duration, timelineDuration));
140
+ }
141
+ } else if (drag.mode === 'end') {
142
+ DialStore.updateValue(timelineId, `${clip.key}.duration`, clampClipResizeEnd(drag.duration + dt, drag.at, timelineDuration));
143
+ } else if (steps && drag.stepDurations) {
144
+ const next = clampClipResizeStart(Math.max(drag.at + dt, Math.max(baseAt, 0)), drag.at, drag.stepDurations[0]);
145
+ DialStore.updateValues(timelineId, {
146
+ [delayMode ? `${clip.key}.delay` : `${clip.key}.at`]: delayMode ? Math.max(0, next.at - baseAt) : next.at,
147
+ [`${clip.key}.${steps[0].key ?? ''}.duration`]: next.duration,
148
+ });
149
+ } else {
150
+ const next = clampClipResizeStart(Math.max(drag.at + dt, Math.max(baseAt, 0)), drag.at, drag.duration);
151
+ DialStore.updateValues(timelineId, {
152
+ [delayMode ? `${clip.key}.delay` : `${clip.key}.at`]: delayMode ? Math.max(0, next.at - baseAt) : next.at,
153
+ [`${clip.key}.duration`]: next.duration,
154
+ });
155
+ }
156
+ }
157
+
158
+ function finish(event?: PointerEvent) {
159
+ const previous = drag;
160
+ drag = null;
161
+ dragging = false;
162
+ if (previous && !previous.moved && event) {
163
+ const anchor = previous.clickEl ?? event.currentTarget as HTMLElement;
164
+ onClick(clip, anchor.getBoundingClientRect(), previous.clickEl?.dataset.step);
165
+ }
166
+ }
167
+ </script>
168
+
169
+ {#each ghostCycles as cycle (cycle.index)}
170
+ <div
171
+ class="dialkit-timeline-clip-ghost"
172
+ data-steps={isSteps || undefined}
173
+ aria-hidden="true"
174
+ style:left={`${(cycle.start - viewStart) * pxPerSecond + 1}px`}
175
+ style:width={`${Math.max(1, cycle.duration * pxPerSecond - 2)}px`}
176
+ style:background={clip.color}
177
+ >
178
+ {#each steps ?? [] as step, index (step.key ?? index)}
179
+ <span class="dialkit-timeline-clip-ghost-segment" style:width={`${step.duration * pxPerSecond}px`}></span>
180
+ {/each}
181
+ </div>
182
+ {/each}
183
+
184
+ <div
185
+ class="dialkit-timeline-clip"
186
+ data-steps={isSteps || undefined}
187
+ data-composite={composite || undefined}
188
+ data-selected={selected || undefined}
189
+ data-dragging={dragging || undefined}
190
+ style:left={`${(at - viewStart) * pxPerSecond}px`}
191
+ style:width={`${width}px`}
192
+ style:background={composite ? `${clip.color}80` : clip.color}
193
+ onpointerdown={handlePointerDown}
194
+ onpointermove={handlePointerMove}
195
+ onpointerup={finish}
196
+ onpointercancel={() => finish()}
197
+ onlostpointercapture={() => finish()}
198
+ title={barTitle}
199
+ role="button"
200
+ tabindex="0"
201
+ aria-label={barTitle}
202
+ >
203
+ {#if composite}
204
+ {#if width > 56}<span class="dialkit-timeline-clip-duration">{durationText}</span>{/if}
205
+ {:else if isSteps}
206
+ {#each steps ?? [] as step, index (step.key ?? index)}
207
+ <div
208
+ class="dialkit-timeline-clip-segment"
209
+ data-step={step.key ?? undefined}
210
+ data-selected={selectedStepKey === step.key || undefined}
211
+ style:width={`${step.duration * pxPerSecond}px`}
212
+ >
213
+ {#if step.duration * pxPerSecond > 52}
214
+ <span class="dialkit-timeline-clip-duration">{formatSeconds(step.duration)}</span>
215
+ {/if}
216
+ </div>
217
+ {/each}
218
+ {#each steps ?? [] as step, index (step.key ?? index)}
219
+ {#if !step.isPhysics}
220
+ <div class="dialkit-timeline-clip-handle" data-boundary={index} style:left={`${boundaries[index] * pxPerSecond - 4}px`}></div>
221
+ {/if}
222
+ {/each}
223
+ {#if !steps?.[0]?.isPhysics}<div class="dialkit-timeline-clip-handle" data-edge="start"></div>{/if}
224
+ {:else}
225
+ {#if resizable}<div class="dialkit-timeline-clip-handle" data-edge="start"></div>{/if}
226
+ {#if width > 56}<span class="dialkit-timeline-clip-duration">{durationText}</span>{/if}
227
+ {#if resizable}<div class="dialkit-timeline-clip-handle" data-edge="end"></div>{/if}
228
+ {/if}
229
+ </div>
230
+
231
+ {#if looping}
232
+ <span class="dialkit-timeline-loop-infinity" aria-hidden="true" title="Repeats indefinitely">∞</span>
233
+ {/if}
@@ -0,0 +1,24 @@
1
+ import type { TimelineClipLoop, TimelineClipMeta, TimelineStepStatic } from 'dialkit/timeline';
2
+ type $$ComponentProps = {
3
+ timelineId: string;
4
+ clip: TimelineClipMeta;
5
+ at: number;
6
+ duration: number;
7
+ loop: TimelineClipLoop;
8
+ steps?: TimelineStepStatic[];
9
+ fixedDuration: boolean;
10
+ composite?: boolean;
11
+ baseAt?: number;
12
+ delayMode?: boolean;
13
+ pxPerSecond: number;
14
+ viewStart: number;
15
+ timelineDuration: number;
16
+ selected: boolean;
17
+ selectedStepKey?: string;
18
+ onClick: (clip: TimelineClipMeta, rect: DOMRect, stepKey?: string) => void;
19
+ onDrag: () => void;
20
+ };
21
+ declare const TimelineClip: import("svelte").Component<$$ComponentProps, {}, "">;
22
+ type TimelineClip = ReturnType<typeof TimelineClip>;
23
+ export default TimelineClip;
24
+ //# sourceMappingURL=TimelineClip.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TimelineClip.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/components/Timeline/TimelineClip.svelte.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAa9F,KAAK,gBAAgB,GAAG;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,gBAAgB,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC7B,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3E,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB,CAAC;AA4KJ,QAAA,MAAM,YAAY,sDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}