@bendyline/squisq-react 2.0.1 → 2.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 (87) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +20 -0
  3. package/README.md +6 -0
  4. package/dist/index.d.ts +101 -96
  5. package/dist/index.js +1483 -782
  6. package/dist/squisq-player.full.global.js +4165 -0
  7. package/dist/squisq-player.global.js +561 -168
  8. package/dist/standalone-source.d.ts +1 -0
  9. package/dist/standalone-source.js +1 -1
  10. package/dist/styles/index.css +64 -0
  11. package/package.json +8 -4
  12. package/dist/index.js.map +0 -1
  13. package/dist/squisq-player.css +0 -2
  14. package/dist/squisq-player.css.map +0 -1
  15. package/dist/squisq-player.global.js.map +0 -1
  16. package/src/BlockRenderer.tsx +0 -194
  17. package/src/CaptionOverlay.tsx +0 -111
  18. package/src/DocControlsBottom.tsx +0 -109
  19. package/src/DocControlsOverlay.tsx +0 -190
  20. package/src/DocControlsSidebar.tsx +0 -113
  21. package/src/DocControlsSlideshow.tsx +0 -360
  22. package/src/DocPlayer.tsx +0 -1528
  23. package/src/DocPlayerWithSidebar.tsx +0 -155
  24. package/src/DocProgressBar.tsx +0 -257
  25. package/src/InlineAudioPlayer.tsx +0 -46
  26. package/src/InlineVideoPlayer.tsx +0 -70
  27. package/src/LinearDocView.tsx +0 -569
  28. package/src/MarkdownRenderer.tsx +0 -624
  29. package/src/MediaClipLayer.tsx +0 -145
  30. package/src/SocialCaptionOverlay.tsx +0 -255
  31. package/src/__tests__/BlockRenderer.test.tsx +0 -235
  32. package/src/__tests__/DocControlsSlideshow.test.tsx +0 -221
  33. package/src/__tests__/DocPlayer.test.tsx +0 -635
  34. package/src/__tests__/DocPlayerStylesSentinel.test.tsx +0 -41
  35. package/src/__tests__/DocProgressBar.test.tsx +0 -102
  36. package/src/__tests__/JsonView.test.tsx +0 -111
  37. package/src/__tests__/LinearDocView.test.tsx +0 -426
  38. package/src/__tests__/MapLayer.test.tsx +0 -63
  39. package/src/__tests__/MarkdownRenderer.test.tsx +0 -357
  40. package/src/__tests__/MediaClipLayer.test.tsx +0 -70
  41. package/src/__tests__/MediaContext.test.tsx +0 -51
  42. package/src/__tests__/PathLayer.test.tsx +0 -84
  43. package/src/__tests__/TableLayer.test.tsx +0 -142
  44. package/src/__tests__/VideoLayer.test.tsx +0 -94
  45. package/src/__tests__/exports.test.ts +0 -55
  46. package/src/__tests__/fillStyle.test.tsx +0 -160
  47. package/src/__tests__/standaloneEntry.test.tsx +0 -103
  48. package/src/__tests__/transitionStyles.test.ts +0 -125
  49. package/src/__tests__/useAudioSync.test.ts +0 -49
  50. package/src/__tests__/useDocPlayback.transition.test.ts +0 -113
  51. package/src/__tests__/useJsonViewTokens.test.ts +0 -41
  52. package/src/__tests__/useSlideSwipe.test.ts +0 -81
  53. package/src/__tests__/useViewportOrientation.test.ts +0 -22
  54. package/src/hooks/AudioController.ts +0 -114
  55. package/src/hooks/MediaContext.tsx +0 -97
  56. package/src/hooks/index.ts +0 -11
  57. package/src/hooks/useAudioSync.ts +0 -456
  58. package/src/hooks/useAutoSurface.ts +0 -33
  59. package/src/hooks/useDocPlayback.ts +0 -265
  60. package/src/hooks/useMediaSchedule.ts +0 -39
  61. package/src/hooks/useSlideSwipe.ts +0 -265
  62. package/src/hooks/useViewportOrientation.ts +0 -115
  63. package/src/index.ts +0 -70
  64. package/src/jsonView/JsonView.tsx +0 -51
  65. package/src/jsonView/RenderNode.tsx +0 -51
  66. package/src/jsonView/index.ts +0 -2
  67. package/src/jsonView/json-view.css +0 -206
  68. package/src/jsonView/useJsonViewTokens.ts +0 -32
  69. package/src/jsonView/viewers.tsx +0 -343
  70. package/src/layers/ImageLayer.tsx +0 -297
  71. package/src/layers/MapLayer.tsx +0 -185
  72. package/src/layers/PathLayer.tsx +0 -155
  73. package/src/layers/ShapeLayer.tsx +0 -158
  74. package/src/layers/TableLayer.tsx +0 -129
  75. package/src/layers/TextLayer.tsx +0 -571
  76. package/src/layers/TreeLayer.tsx +0 -167
  77. package/src/layers/VideoLayer.tsx +0 -171
  78. package/src/layers/index.ts +0 -6
  79. package/src/standalone-entry.tsx +0 -337
  80. package/src/standalone-source.d.ts +0 -10
  81. package/src/styles/doc-animations.css +0 -2431
  82. package/src/styles/index.css +0 -7
  83. package/src/types.ts +0 -183
  84. package/src/utils/animationUtils.ts +0 -13
  85. package/src/utils/fillStyle.tsx +0 -148
  86. package/src/utils/layerUtils.ts +0 -42
  87. package/src/utils/mapTileUtils.ts +0 -375
@@ -1,221 +0,0 @@
1
- import { describe, it, expect, vi } from 'vitest';
2
- import { render, fireEvent } from '@testing-library/react';
3
- import { DocControlsSlideshow } from '../DocControlsSlideshow';
4
- import type { PlaybackState, SlideNavActions } from '../types';
5
-
6
- const slides = [
7
- { id: 'intro', label: '1', summary: 'Introduction' },
8
- { id: 'results', label: '2', summary: 'Key results' },
9
- { id: 'next', label: '3', summary: 'What comes next' },
10
- ];
11
-
12
- function makeState(overrides: Partial<PlaybackState> = {}): PlaybackState {
13
- return {
14
- isPlaying: false,
15
- currentTime: 0,
16
- totalDuration: 60,
17
- currentBlockIndex: 2,
18
- totalBlocks: 10,
19
- docProgress: 0.2,
20
- hasCaptions: false,
21
- captionsEnabled: false,
22
- captionMode: 'off',
23
- currentSegmentIndex: 0,
24
- currentSegmentName: null,
25
- currentBlock: null,
26
- ...overrides,
27
- };
28
- }
29
-
30
- function makeSlideNav(overrides: Partial<SlideNavActions> = {}): SlideNavActions {
31
- return {
32
- nextSlide: overrides.nextSlide ?? (() => {}),
33
- prevSlide: overrides.prevSlide ?? (() => {}),
34
- goToSlide: overrides.goToSlide ?? (() => {}),
35
- };
36
- }
37
-
38
- describe('DocControlsSlideshow', () => {
39
- it('renders prev, next buttons and slide counter', () => {
40
- const { getByTestId } = render(
41
- <DocControlsSlideshow state={makeState()} slideNav={makeSlideNav()} />,
42
- );
43
- expect(getByTestId('slide-prev')).toBeTruthy();
44
- expect(getByTestId('slide-next')).toBeTruthy();
45
- expect(getByTestId('slide-counter')).toBeTruthy();
46
- });
47
-
48
- it('shows correct slide counter text', () => {
49
- const { getByTestId } = render(
50
- <DocControlsSlideshow
51
- state={makeState({ currentBlockIndex: 4, totalBlocks: 12 })}
52
- slideNav={makeSlideNav()}
53
- />,
54
- );
55
- expect(getByTestId('slide-counter').textContent).toBe('5 / 12');
56
- });
57
-
58
- it('opens an upward slide picker with block summaries', () => {
59
- const { getByTestId, getByRole } = render(
60
- <DocControlsSlideshow
61
- state={makeState({ currentBlockIndex: 1, totalBlocks: slides.length })}
62
- slideNav={makeSlideNav()}
63
- slides={slides}
64
- />,
65
- );
66
-
67
- fireEvent.click(getByTestId('slide-counter'));
68
-
69
- const picker = getByRole('menu', { name: 'Choose a slide' });
70
- expect(picker.style.bottom).toBe('calc(100% + 8px)');
71
- expect(getByTestId('slide-picker-item-0').textContent).toContain('1Introduction');
72
- expect(getByTestId('slide-picker-item-1').textContent).toContain('2Key results');
73
- expect(getByTestId('slide-picker-item-1').getAttribute('aria-current')).toBe('true');
74
- });
75
-
76
- it('uses the available player height above the toolbar', () => {
77
- const { getByTestId } = render(
78
- <div className="doc-player">
79
- <DocControlsSlideshow
80
- state={makeState({ currentBlockIndex: 1, totalBlocks: slides.length })}
81
- slideNav={makeSlideNav()}
82
- slides={slides}
83
- />
84
- </div>,
85
- );
86
- const controls = getByTestId('slideshow-controls');
87
- const player = controls.parentElement as HTMLElement;
88
- const rect = (top: number, height: number) =>
89
- ({
90
- x: 0,
91
- y: top,
92
- top,
93
- right: 640,
94
- bottom: top + height,
95
- left: 0,
96
- width: 640,
97
- height,
98
- toJSON: () => ({}),
99
- }) as DOMRect;
100
- const playerBounds = vi.spyOn(player, 'getBoundingClientRect').mockReturnValue(rect(0, 480));
101
- const controlsBounds = vi
102
- .spyOn(controls, 'getBoundingClientRect')
103
- .mockReturnValue(rect(420, 40));
104
-
105
- fireEvent.click(getByTestId('slide-counter'));
106
-
107
- expect(getByTestId('slide-picker').style.maxHeight).toBe('396px');
108
- playerBounds.mockRestore();
109
- controlsBounds.mockRestore();
110
- });
111
-
112
- it('navigates directly to a selected slide and closes the picker', () => {
113
- let selectedIndex = -1;
114
- const { getByTestId, queryByTestId } = render(
115
- <DocControlsSlideshow
116
- state={makeState({ currentBlockIndex: 0, totalBlocks: slides.length })}
117
- slideNav={makeSlideNav({ goToSlide: (index) => (selectedIndex = index) })}
118
- slides={slides}
119
- />,
120
- );
121
-
122
- fireEvent.click(getByTestId('slide-counter'));
123
- fireEvent.click(getByTestId('slide-picker-item-2'));
124
-
125
- expect(selectedIndex).toBe(2);
126
- expect(queryByTestId('slide-picker')).toBeNull();
127
- });
128
-
129
- it('closes the slide picker with Escape', () => {
130
- const { getByTestId, queryByTestId } = render(
131
- <DocControlsSlideshow
132
- state={makeState({ currentBlockIndex: 0, totalBlocks: slides.length })}
133
- slideNav={makeSlideNav()}
134
- slides={slides}
135
- />,
136
- );
137
-
138
- fireEvent.click(getByTestId('slide-counter'));
139
- fireEvent.keyDown(document, { key: 'Escape' });
140
-
141
- expect(queryByTestId('slide-picker')).toBeNull();
142
- expect(document.activeElement).toBe(getByTestId('slide-counter'));
143
- });
144
-
145
- it('disables prev button on first slide', () => {
146
- const { getByTestId } = render(
147
- <DocControlsSlideshow
148
- state={makeState({ currentBlockIndex: 0 })}
149
- slideNav={makeSlideNav()}
150
- />,
151
- );
152
- const prevBtn = getByTestId('slide-prev') as HTMLButtonElement;
153
- expect(prevBtn.disabled).toBe(true);
154
- });
155
-
156
- it('disables next button on last slide', () => {
157
- const { getByTestId } = render(
158
- <DocControlsSlideshow
159
- state={makeState({ currentBlockIndex: 9, totalBlocks: 10 })}
160
- slideNav={makeSlideNav()}
161
- />,
162
- );
163
- const nextBtn = getByTestId('slide-next') as HTMLButtonElement;
164
- expect(nextBtn.disabled).toBe(true);
165
- });
166
-
167
- it('enables both buttons on a middle slide', () => {
168
- const { getByTestId } = render(
169
- <DocControlsSlideshow
170
- state={makeState({ currentBlockIndex: 3, totalBlocks: 10 })}
171
- slideNav={makeSlideNav()}
172
- />,
173
- );
174
- const prevBtn = getByTestId('slide-prev') as HTMLButtonElement;
175
- const nextBtn = getByTestId('slide-next') as HTMLButtonElement;
176
- expect(prevBtn.disabled).toBe(false);
177
- expect(nextBtn.disabled).toBe(false);
178
- });
179
-
180
- it('calls nextSlide when next button is clicked', () => {
181
- let called = false;
182
- const nav = makeSlideNav({
183
- nextSlide: () => {
184
- called = true;
185
- },
186
- });
187
- const { getByTestId } = render(<DocControlsSlideshow state={makeState()} slideNav={nav} />);
188
- fireEvent.click(getByTestId('slide-next'));
189
- expect(called).toBe(true);
190
- });
191
-
192
- it('calls prevSlide when prev button is clicked', () => {
193
- let called = false;
194
- const nav = makeSlideNav({
195
- prevSlide: () => {
196
- called = true;
197
- },
198
- });
199
- const { getByTestId } = render(<DocControlsSlideshow state={makeState()} slideNav={nav} />);
200
- fireEvent.click(getByTestId('slide-prev'));
201
- expect(called).toBe(true);
202
- });
203
-
204
- it('shows dash for empty doc', () => {
205
- const { getByTestId } = render(
206
- <DocControlsSlideshow
207
- state={makeState({ currentBlockIndex: -1, totalBlocks: 0 })}
208
- slideNav={makeSlideNav()}
209
- />,
210
- );
211
- expect(getByTestId('slide-counter').textContent).toBe('—');
212
- });
213
-
214
- it('has correct aria-labels', () => {
215
- const { getByTestId } = render(
216
- <DocControlsSlideshow state={makeState()} slideNav={makeSlideNav()} />,
217
- );
218
- expect(getByTestId('slide-prev').getAttribute('aria-label')).toBe('Previous slide');
219
- expect(getByTestId('slide-next').getAttribute('aria-label')).toBe('Next slide');
220
- });
221
- });