dialkit 1.2.1 → 1.4.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.
Files changed (88) hide show
  1. package/README.md +653 -6
  2. package/dist/dropdown-position.d.ts +15 -0
  3. package/dist/dropdown-position.js +22 -0
  4. package/dist/dropdown-position.js.map +1 -0
  5. package/dist/icons.d.ts +4 -1
  6. package/dist/icons.js +13 -0
  7. package/dist/icons.js.map +1 -1
  8. package/dist/index.cjs +3796 -768
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +315 -10
  11. package/dist/index.d.ts +315 -10
  12. package/dist/index.js +3733 -711
  13. package/dist/index.js.map +1 -1
  14. package/dist/panel-drag.d.ts +19 -0
  15. package/dist/panel-drag.js +72 -0
  16. package/dist/panel-drag.js.map +1 -0
  17. package/dist/solid/index.d.ts +264 -5
  18. package/dist/solid/index.js +5277 -1632
  19. package/dist/solid/index.js.map +1 -1
  20. package/dist/store/index.cjs +329 -57
  21. package/dist/store/index.cjs.map +1 -1
  22. package/dist/store/index.d.cts +43 -4
  23. package/dist/store/index.d.ts +43 -4
  24. package/dist/store/index.js +321 -56
  25. package/dist/store/index.js.map +1 -1
  26. package/dist/styles.css +809 -7
  27. package/dist/svelte/components/ControlRenderer.svelte +5 -2
  28. package/dist/svelte/components/ControlRenderer.svelte.d.ts +2 -0
  29. package/dist/svelte/components/ControlRenderer.svelte.d.ts.map +1 -1
  30. package/dist/svelte/components/DialRoot.svelte +218 -16
  31. package/dist/svelte/components/DialRoot.svelte.d.ts +1 -0
  32. package/dist/svelte/components/DialRoot.svelte.d.ts.map +1 -1
  33. package/dist/svelte/components/Folder.svelte +24 -13
  34. package/dist/svelte/components/Folder.svelte.d.ts +1 -0
  35. package/dist/svelte/components/Folder.svelte.d.ts.map +1 -1
  36. package/dist/svelte/components/Panel.svelte +104 -71
  37. package/dist/svelte/components/Panel.svelte.d.ts +4 -0
  38. package/dist/svelte/components/Panel.svelte.d.ts.map +1 -1
  39. package/dist/svelte/components/PresetManager.svelte +5 -5
  40. package/dist/svelte/components/PresetManager.svelte.d.ts.map +1 -1
  41. package/dist/svelte/components/SelectControl.svelte +6 -14
  42. package/dist/svelte/components/SelectControl.svelte.d.ts.map +1 -1
  43. package/dist/svelte/components/Timeline/ClipPopover.svelte +206 -0
  44. package/dist/svelte/components/Timeline/ClipPopover.svelte.d.ts +26 -0
  45. package/dist/svelte/components/Timeline/ClipPopover.svelte.d.ts.map +1 -0
  46. package/dist/svelte/components/Timeline/DialTimeline.svelte +76 -0
  47. package/dist/svelte/components/Timeline/DialTimeline.svelte.d.ts +13 -0
  48. package/dist/svelte/components/Timeline/DialTimeline.svelte.d.ts.map +1 -0
  49. package/dist/svelte/components/Timeline/TimelineClip.svelte +233 -0
  50. package/dist/svelte/components/Timeline/TimelineClip.svelte.d.ts +24 -0
  51. package/dist/svelte/components/Timeline/TimelineClip.svelte.d.ts.map +1 -0
  52. package/dist/svelte/components/Timeline/TimelineSection.svelte +756 -0
  53. package/dist/svelte/components/Timeline/TimelineSection.svelte.d.ts +12 -0
  54. package/dist/svelte/components/Timeline/TimelineSection.svelte.d.ts.map +1 -0
  55. package/dist/svelte/components/Timeline/TimelineToggleButton.svelte +25 -0
  56. package/dist/svelte/components/Timeline/TimelineToggleButton.svelte.d.ts +4 -0
  57. package/dist/svelte/components/Timeline/TimelineToggleButton.svelte.d.ts.map +1 -0
  58. package/dist/svelte/components/TransitionControl.svelte +26 -11
  59. package/dist/svelte/components/TransitionControl.svelte.d.ts +9 -0
  60. package/dist/svelte/components/TransitionControl.svelte.d.ts.map +1 -1
  61. package/dist/svelte/createDialKit.svelte.d.ts +11 -1
  62. package/dist/svelte/createDialKit.svelte.d.ts.map +1 -1
  63. package/dist/svelte/createDialKit.svelte.js +61 -34
  64. package/dist/svelte/createDialTimeline.svelte.d.ts +4 -0
  65. package/dist/svelte/createDialTimeline.svelte.d.ts.map +1 -0
  66. package/dist/svelte/createDialTimeline.svelte.js +73 -0
  67. package/dist/svelte/index.d.ts +7 -3
  68. package/dist/svelte/index.d.ts.map +1 -1
  69. package/dist/svelte/index.js +4 -1
  70. package/dist/svelte/theme-css.d.ts +1 -1
  71. package/dist/svelte/theme-css.d.ts.map +1 -1
  72. package/dist/svelte/theme-css.js +809 -7
  73. package/dist/timeline/index.cjs +1288 -0
  74. package/dist/timeline/index.cjs.map +1 -0
  75. package/dist/timeline/index.d.cts +443 -0
  76. package/dist/timeline/index.d.ts +443 -0
  77. package/dist/timeline/index.js +1233 -0
  78. package/dist/timeline/index.js.map +1 -0
  79. package/dist/vue/index.d.ts +325 -12
  80. package/dist/vue/index.js +3226 -280
  81. package/dist/vue/index.js.map +1 -1
  82. package/package.json +23 -13
  83. package/dist/solid/index.cjs +0 -3079
  84. package/dist/solid/index.cjs.map +0 -1
  85. package/dist/solid/index.d.cts +0 -258
  86. package/dist/vue/index.cjs +0 -3056
  87. package/dist/vue/index.cjs.map +0 -1
  88. package/dist/vue/index.d.cts +0 -675
@@ -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"}