playwright-director 0.2.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 (122) hide show
  1. package/README.md +860 -0
  2. package/dist/Tutorial.d.ts +108 -0
  3. package/dist/Tutorial.d.ts.map +1 -0
  4. package/dist/Tutorial.js +767 -0
  5. package/dist/Tutorial.js.map +1 -0
  6. package/dist/bin/export-transcript.d.ts +3 -0
  7. package/dist/bin/export-transcript.d.ts.map +1 -0
  8. package/dist/bin/export-transcript.js +111 -0
  9. package/dist/bin/export-transcript.js.map +1 -0
  10. package/dist/cursor.d.ts +24 -0
  11. package/dist/cursor.d.ts.map +1 -0
  12. package/dist/cursor.js +96 -0
  13. package/dist/cursor.js.map +1 -0
  14. package/dist/index.d.ts +16 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +12 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/init.d.ts +3 -0
  19. package/dist/init.d.ts.map +1 -0
  20. package/dist/init.js +183 -0
  21. package/dist/init.js.map +1 -0
  22. package/dist/merge.d.ts +26 -0
  23. package/dist/merge.d.ts.map +1 -0
  24. package/dist/merge.js +65 -0
  25. package/dist/merge.js.map +1 -0
  26. package/dist/music.d.ts +29 -0
  27. package/dist/music.d.ts.map +1 -0
  28. package/dist/music.js +107 -0
  29. package/dist/music.js.map +1 -0
  30. package/dist/overlay-html.d.ts +44 -0
  31. package/dist/overlay-html.d.ts.map +1 -0
  32. package/dist/overlay-html.js +150 -0
  33. package/dist/overlay-html.js.map +1 -0
  34. package/dist/overlay.d.ts +39 -0
  35. package/dist/overlay.d.ts.map +1 -0
  36. package/dist/overlay.js +134 -0
  37. package/dist/overlay.js.map +1 -0
  38. package/dist/postinstall.d.ts +3 -0
  39. package/dist/postinstall.d.ts.map +1 -0
  40. package/dist/postinstall.js +38 -0
  41. package/dist/postinstall.js.map +1 -0
  42. package/dist/reporter.d.ts +22 -0
  43. package/dist/reporter.d.ts.map +1 -0
  44. package/dist/reporter.js +166 -0
  45. package/dist/reporter.js.map +1 -0
  46. package/dist/site/build-site.d.ts +2 -0
  47. package/dist/site/build-site.d.ts.map +1 -0
  48. package/dist/site/build-site.js +82 -0
  49. package/dist/site/build-site.js.map +1 -0
  50. package/dist/site/embed.d.ts +48 -0
  51. package/dist/site/embed.d.ts.map +1 -0
  52. package/dist/site/embed.js +45 -0
  53. package/dist/site/embed.js.map +1 -0
  54. package/dist/site/generate-manifest.d.ts +15 -0
  55. package/dist/site/generate-manifest.d.ts.map +1 -0
  56. package/dist/site/generate-manifest.js +106 -0
  57. package/dist/site/generate-manifest.js.map +1 -0
  58. package/dist/site/scaffold.d.ts +3 -0
  59. package/dist/site/scaffold.d.ts.map +1 -0
  60. package/dist/site/scaffold.js +70 -0
  61. package/dist/site/scaffold.js.map +1 -0
  62. package/dist/site/scan-tutorials.d.ts +12 -0
  63. package/dist/site/scan-tutorials.d.ts.map +1 -0
  64. package/dist/site/scan-tutorials.js +54 -0
  65. package/dist/site/scan-tutorials.js.map +1 -0
  66. package/dist/site/types.d.ts +75 -0
  67. package/dist/site/types.d.ts.map +1 -0
  68. package/dist/site/types.js +2 -0
  69. package/dist/site/types.js.map +1 -0
  70. package/dist/skill-stamp.d.ts +21 -0
  71. package/dist/skill-stamp.d.ts.map +1 -0
  72. package/dist/skill-stamp.js +39 -0
  73. package/dist/skill-stamp.js.map +1 -0
  74. package/dist/slugify.d.ts +19 -0
  75. package/dist/slugify.d.ts.map +1 -0
  76. package/dist/slugify.js +29 -0
  77. package/dist/slugify.js.map +1 -0
  78. package/dist/stage-presets.d.ts +51 -0
  79. package/dist/stage-presets.d.ts.map +1 -0
  80. package/dist/stage-presets.js +45 -0
  81. package/dist/stage-presets.js.map +1 -0
  82. package/dist/styles.css +637 -0
  83. package/dist/timeline.d.ts +87 -0
  84. package/dist/timeline.d.ts.map +1 -0
  85. package/dist/timeline.js +108 -0
  86. package/dist/timeline.js.map +1 -0
  87. package/dist/transcript.d.ts +87 -0
  88. package/dist/transcript.d.ts.map +1 -0
  89. package/dist/transcript.js +291 -0
  90. package/dist/transcript.js.map +1 -0
  91. package/dist/tts-provider.d.ts +69 -0
  92. package/dist/tts-provider.d.ts.map +1 -0
  93. package/dist/tts-provider.js +182 -0
  94. package/dist/tts-provider.js.map +1 -0
  95. package/dist/types.d.ts +109 -0
  96. package/dist/types.d.ts.map +1 -0
  97. package/dist/types.js +2 -0
  98. package/dist/types.js.map +1 -0
  99. package/dist/voice-prerender.d.ts +41 -0
  100. package/dist/voice-prerender.d.ts.map +1 -0
  101. package/dist/voice-prerender.js +122 -0
  102. package/dist/voice-prerender.js.map +1 -0
  103. package/dist/voice.d.ts +76 -0
  104. package/dist/voice.d.ts.map +1 -0
  105. package/dist/voice.js +244 -0
  106. package/dist/voice.js.map +1 -0
  107. package/package.json +87 -0
  108. package/skills/tutorialize/SKILL.md +54 -0
  109. package/skills/tutorialize/agent.md +58 -0
  110. package/skills/tutorialize/references/api.md +489 -0
  111. package/skills/tutorialize/references/storytelling.md +193 -0
  112. package/src/styles.css +637 -0
  113. package/templates/site/public/.gitkeep +0 -0
  114. package/templates/site/public/widget.js +273 -0
  115. package/templates/site/src/components/TutorialsHome.astro +141 -0
  116. package/templates/site/src/components/VideoCard.astro +192 -0
  117. package/templates/site/src/components/VideoModal.astro +170 -0
  118. package/templates/site/src/data/.gitkeep +0 -0
  119. package/templates/site/src/layouts/Base.astro +56 -0
  120. package/templates/site/src/pages/[slug].astro +745 -0
  121. package/templates/site/src/pages/index.astro +5 -0
  122. package/templates/site/src/styles/tutorials.css +303 -0
@@ -0,0 +1,170 @@
1
+ ---
2
+ // Video modal component - handles inline video playback with prev/next navigation
3
+ ---
4
+
5
+ <div id="video-modal" class="video-modal" style="display: none;">
6
+ <button class="video-modal-close" aria-label="Close">×</button>
7
+ <div class="video-container">
8
+ <button class="video-nav video-nav-prev" aria-label="Previous" style="display: none;">‹</button>
9
+ <video controls id="modal-video">
10
+ <source src="" type="video/webm" />
11
+ </video>
12
+ <button class="video-nav video-nav-next" aria-label="Next" style="display: none;">›</button>
13
+ </div>
14
+ <div class="video-title-bar">
15
+ <span id="video-title"></span>
16
+ <span id="video-counter"></span>
17
+ </div>
18
+ </div>
19
+
20
+ <style>
21
+ .video-container {
22
+ display: flex;
23
+ align-items: center;
24
+ gap: 1rem;
25
+ max-width: 100%;
26
+ }
27
+
28
+ .video-nav {
29
+ background: rgba(255, 255, 255, 0.9);
30
+ border: none;
31
+ width: 50px;
32
+ height: 50px;
33
+ border-radius: 50%;
34
+ font-size: 2rem;
35
+ cursor: pointer;
36
+ transition: all 0.2s;
37
+ flex-shrink: 0;
38
+ display: flex;
39
+ align-items: center;
40
+ justify-content: center;
41
+ line-height: 1;
42
+ }
43
+
44
+ .video-nav:hover {
45
+ background: white;
46
+ transform: scale(1.1);
47
+ }
48
+
49
+ .video-nav:disabled {
50
+ opacity: 0.3;
51
+ cursor: not-allowed;
52
+ transform: none;
53
+ }
54
+
55
+ .video-title-bar {
56
+ display: flex;
57
+ justify-content: space-between;
58
+ align-items: center;
59
+ width: 100%;
60
+ max-width: 900px;
61
+ margin-top: 1rem;
62
+ padding: 0 60px;
63
+ color: white;
64
+ font-size: 0.9rem;
65
+ }
66
+
67
+ #video-title {
68
+ font-weight: 500;
69
+ }
70
+
71
+ #video-counter {
72
+ opacity: 0.7;
73
+ }
74
+ </style>
75
+
76
+ <script>
77
+ document.addEventListener('DOMContentLoaded', () => {
78
+ const modal = document.getElementById('video-modal') as HTMLDivElement;
79
+ const video = document.getElementById('modal-video') as HTMLVideoElement;
80
+ const closeBtn = modal?.querySelector('.video-modal-close');
81
+ const prevBtn = modal?.querySelector('.video-nav-prev') as HTMLButtonElement;
82
+ const nextBtn = modal?.querySelector('.video-nav-next') as HTMLButtonElement;
83
+ const videoSource = video?.querySelector('source');
84
+ const titleEl = document.getElementById('video-title');
85
+ const counterEl = document.getElementById('video-counter');
86
+
87
+ // Collect all video cards
88
+ const cards = Array.from(document.querySelectorAll('.video-card'));
89
+ let currentIndex = 0;
90
+
91
+ const playVideo = (index: number) => {
92
+ if (index < 0 || index >= cards.length) return;
93
+
94
+ currentIndex = index;
95
+ const card = cards[index];
96
+ const videoUrl = card.getAttribute('data-video-url');
97
+ const title = card.querySelector('.video-title')?.textContent || '';
98
+
99
+ if (videoUrl && videoSource && video) {
100
+ videoSource.src = videoUrl;
101
+ video.load();
102
+ video.play();
103
+
104
+ // Update title and counter
105
+ if (titleEl) titleEl.textContent = title;
106
+ if (counterEl) counterEl.textContent = `${index + 1} / ${cards.length}`;
107
+
108
+ // Update nav buttons
109
+ if (prevBtn) {
110
+ prevBtn.style.display = 'flex';
111
+ prevBtn.disabled = index === 0;
112
+ }
113
+ if (nextBtn) {
114
+ nextBtn.style.display = 'flex';
115
+ nextBtn.disabled = index === cards.length - 1;
116
+ }
117
+ }
118
+ };
119
+
120
+ // Open modal on card click
121
+ cards.forEach((card, index) => {
122
+ card.addEventListener('click', () => {
123
+ if (modal) {
124
+ modal.style.display = 'flex';
125
+ playVideo(index);
126
+ }
127
+ });
128
+ });
129
+
130
+ // Navigation
131
+ prevBtn?.addEventListener('click', (e) => {
132
+ e.stopPropagation();
133
+ playVideo(currentIndex - 1);
134
+ });
135
+
136
+ nextBtn?.addEventListener('click', (e) => {
137
+ e.stopPropagation();
138
+ playVideo(currentIndex + 1);
139
+ });
140
+
141
+ // Auto-advance on video end
142
+ video?.addEventListener('ended', () => {
143
+ if (currentIndex < cards.length - 1) {
144
+ playVideo(currentIndex + 1);
145
+ }
146
+ });
147
+
148
+ // Close modal
149
+ const closeModal = () => {
150
+ if (modal && video) {
151
+ modal.style.display = 'none';
152
+ video.pause();
153
+ }
154
+ };
155
+
156
+ closeBtn?.addEventListener('click', closeModal);
157
+ modal?.addEventListener('click', (e) => {
158
+ if (e.target === modal) closeModal();
159
+ });
160
+
161
+ // Keyboard navigation
162
+ document.addEventListener('keydown', (e) => {
163
+ if (modal?.style.display !== 'flex') return;
164
+
165
+ if (e.key === 'Escape') closeModal();
166
+ if (e.key === 'ArrowLeft') playVideo(currentIndex - 1);
167
+ if (e.key === 'ArrowRight') playVideo(currentIndex + 1);
168
+ });
169
+ });
170
+ </script>
File without changes
@@ -0,0 +1,56 @@
1
+ ---
2
+ import '../styles/tutorials.css';
3
+ import siteConfig from '../data/site-config.json';
4
+
5
+ interface Props {
6
+ title: string;
7
+ description?: string;
8
+ }
9
+
10
+ const config = siteConfig as any;
11
+ const base = import.meta.env.BASE_URL.replace(/\/$/, '');
12
+ const { title, description = config.title } = Astro.props;
13
+
14
+ const cssVars = [
15
+ config.primaryColor && `--color-primary: ${config.primaryColor}`,
16
+ config.font && `--font-family: ${config.font}`,
17
+ ]
18
+ .filter(Boolean)
19
+ .join('; ');
20
+ ---
21
+
22
+ <!doctype html>
23
+ <html lang={config.lang || 'en'}>
24
+ <head>
25
+ <meta charset="UTF-8" />
26
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
27
+ <meta name="description" content={description} />
28
+ <title>{title} | {config.title}</title>
29
+ </head>
30
+ <body style={cssVars || undefined}>
31
+ <header>
32
+ <div class="header-content">
33
+ <a href={`${base}/`} class="logo">
34
+ {
35
+ config.logo ? (
36
+ <img src={config.logo} alt={config.title} class="logo-img" />
37
+ ) : (
38
+ <span class="logo-icon">🎬</span>
39
+ )
40
+ }
41
+ <span class="logo-text">{config.title}</span>
42
+ </a>
43
+ </div>
44
+ </header>
45
+ <main>
46
+ <slot />
47
+ </main>
48
+ <footer>
49
+ <div class="footer-content">
50
+ <span>© {new Date().getFullYear()} {config.title}</span>
51
+ <span>·</span>
52
+ <span>Built with playwright-director</span>
53
+ </div>
54
+ </footer>
55
+ </body>
56
+ </html>