@twick/visualizer 0.15.20 → 0.15.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twick/visualizer",
3
- "version": "0.15.20",
3
+ "version": "0.15.21",
4
4
  "license": "https://github.com/ncounterspecialist/twick/blob/main/LICENSE.md",
5
5
  "scripts": {
6
6
  "start": "twick editor --projectFile ./src/live.tsx",
@@ -22,18 +22,19 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "@preact/signals": "^1.2.1",
25
- "@twick/2d": "^0.15.20",
26
- "@twick/core": "^0.15.20",
27
- "@twick/renderer": "^0.15.20",
28
- "@twick/vite-plugin": "^0.15.20",
29
- "date-fns": "^4.1.0",
30
- "preact": "^10.19.2",
25
+ "@twick/2d": "^0.15.21",
26
+ "@twick/core": "^0.15.21",
27
+ "@twick/effects": "0.15.21",
28
+ "@twick/media-utils": "0.15.21",
29
+ "@twick/renderer": "^0.15.21",
30
+ "@twick/vite-plugin": "^0.15.21",
31
31
  "crelt": "^1.0.6",
32
- "@twick/media-utils": "0.15.20"
32
+ "date-fns": "^4.1.0",
33
+ "preact": "^10.19.2"
33
34
  },
34
35
  "devDependencies": {
35
- "@twick/cli": "^0.15.20",
36
- "@twick/ui": "^0.15.20",
36
+ "@twick/cli": "^0.15.21",
37
+ "@twick/ui": "^0.15.21",
37
38
  "typescript": "5.4.2",
38
39
  "typedoc": "^0.25.8",
39
40
  "typedoc-plugin-markdown": "^3.17.1",
@@ -3,6 +3,8 @@ import { CaptionElement } from "../elements/caption.element";
3
3
  import { CircleElement } from "../elements/circle.element";
4
4
  import { ImageElement } from "../elements/image.element";
5
5
  import { RectElement } from "../elements/rect.element";
6
+ import { ArrowElement } from "../elements/arrow.element";
7
+ import { LineElement } from "../elements/line.element";
6
8
  import { SceneElement } from "../elements/scene.element";
7
9
  import { TextElement } from "../elements/text.element";
8
10
  import { VideoElement } from "../elements/video.element";
@@ -33,6 +35,8 @@ export class ElementController {
33
35
  elementController.register(AudioElement);
34
36
  elementController.register(CircleElement);
35
37
  elementController.register(RectElement);
38
+ elementController.register(ArrowElement);
39
+ elementController.register(LineElement);
36
40
  }
37
41
 
38
42
  const elementController = new ElementController();
@@ -0,0 +1,75 @@
1
+ import { ElementParams } from "../helpers/types";
2
+ import { all, createRef, waitFor } from "@twick/core";
3
+ import { Layout, Polygon, Rect } from "@twick/2d";
4
+ import { addAnimation } from "../helpers/element.utils";
5
+ import { logger } from "../helpers/log.utils";
6
+
7
+ const HEAD_OFFSET = 2;
8
+
9
+ /**
10
+ * Arrow element: bar + triangle (callout) for the visualizer.
11
+ * Matches canvas arrow layout: bar from left, triangle overlapping at the tip.
12
+ */
13
+ export const ArrowElement = {
14
+ name: "arrow",
15
+
16
+ *create({ containerRef, element, view }: ElementParams) {
17
+ const elementRef = createRef<any>();
18
+ yield* waitFor(element?.s ?? 0);
19
+ logger(`ArrowElement: ${element?.id}`);
20
+
21
+ const w = element?.props?.width ?? 220;
22
+ const h = element?.props?.height ?? 14;
23
+ const fill = element?.props?.fill ?? "#f59e0b";
24
+ const radius = element?.props?.radius ?? 4;
25
+ const rotation = element?.props?.rotation ?? 0;
26
+ const opacity = element?.props?.opacity ?? 1;
27
+ const cx = element?.props?.x ?? 0;
28
+ const cy = element?.props?.y ?? 0;
29
+
30
+ // Match canvas triangle size: Polygon is inscribed in its size box so appears
31
+ // smaller than Fabric’s Triangle (which fills its box). Scale up ~1.3×.
32
+ const HEAD_SIZE_MULT = 1.8 * 1.3;
33
+ const headSize = h * HEAD_SIZE_MULT;
34
+ const barLength = w - headSize * 0.5 + HEAD_OFFSET;
35
+ const barWidth = w;
36
+
37
+ // Single group so one ref for animations
38
+ const arrowGroup = (
39
+ <Layout
40
+ ref={elementRef}
41
+ key={element?.id}
42
+ x={cx}
43
+ y={cy}
44
+ rotation={rotation}
45
+ opacity={opacity}
46
+ >
47
+ <Rect
48
+ x={-barWidth / 2 + barLength / 2}
49
+ y={0}
50
+ width={barLength}
51
+ height={h}
52
+ fill={fill}
53
+ radius={radius}
54
+ />
55
+ <Polygon
56
+ x={barWidth / 2 - headSize * 0.25}
57
+ y={0}
58
+ width={headSize}
59
+ height={headSize}
60
+ sides={3}
61
+ fill={fill}
62
+ rotation={90}
63
+ />
64
+ </Layout>
65
+ );
66
+
67
+ yield containerRef().add(arrowGroup);
68
+
69
+ yield* all(
70
+ addAnimation({ elementRef, element: element!, view }),
71
+ waitFor(Math.max(0, (element?.e ?? 0) - (element?.s ?? 0)))
72
+ );
73
+ yield elementRef().remove();
74
+ },
75
+ };
@@ -9,5 +9,7 @@ export { AudioElement } from './audio.element';
9
9
  export { TextElement } from './text.element';
10
10
  export { CaptionElement } from './caption.element';
11
11
  export { RectElement } from './rect.element';
12
+ export { ArrowElement } from './arrow.element';
13
+ export { LineElement } from './line.element';
12
14
  export { CircleElement } from './circle.element';
13
15
  export { SceneElement } from './scene.element';
@@ -0,0 +1,17 @@
1
+ import { ElementParams } from "../helpers/types";
2
+ import { RectElement } from "./rect.element";
3
+
4
+ /**
5
+ * LineElement: visualizer representation for line/segment shapes.
6
+ * Uses the same renderer as RectElement so width/height/fill/rotation
7
+ * map directly to the exported video.
8
+ */
9
+ export const LineElement = {
10
+ name: "line",
11
+
12
+ *create(params: ElementParams) {
13
+ // Delegate to RectElement to reuse rendering and animation behavior.
14
+ yield* RectElement.create(params);
15
+ },
16
+ };
17
+
@@ -122,6 +122,10 @@ export const TextElement = {
122
122
  alignItems={"center"}
123
123
  justifyContent={"center"}
124
124
  layout
125
+ x={element.props?.x}
126
+ y={element.props?.y}
127
+ rotation={element.props?.rotation}
128
+ opacity={element.props?.opacity}
125
129
  >
126
130
  <Txt
127
131
  ref={innerTextRef}
@@ -41,6 +41,7 @@ export const TRACK_TYPES = {
41
41
  CAPTION: "caption",
42
42
  SCENE: "scene",
43
43
  ELEMENT: "element",
44
+ EFFECT: "effect",
44
45
  } as const;
45
46
 
46
47
  export const CAPTION_STYLE: Record<string, CaptionStyle> = {
package/src/project.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  import { makeProject } from "@twick/core";
2
+ import { getActiveEffectsForFrame } from "@twick/effects";
2
3
  import { scene } from "./visualizer";
3
4
 
4
- export default makeProject({
5
+ const project = makeProject({
5
6
  scenes: [scene],
6
7
  });
8
+ (project as import("@twick/core").Project).getActiveEffectsForFrame =
9
+ getActiveEffectsForFrame;
10
+ export default project;