@cntrl-site/sdk-nextjs 1.4.4 → 1.5.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.
@@ -98,6 +98,20 @@ const VimeoEmbedItem = ({ item, sectionId, onResize, interactionCtrl, onVisibili
98
98
  vimeoPlayer.pause();
99
99
  }
100
100
  }, [isInteractive, onVisibilityChange, vimeoPlayer]);
101
+ (0, react_1.useEffect)(() => {
102
+ if (!vimeoPlayer || !interactionCtrl)
103
+ return;
104
+ interactionCtrl.setActionReceiver((type) => {
105
+ switch (type) {
106
+ case 'play':
107
+ vimeoPlayer.play();
108
+ break;
109
+ case 'pause':
110
+ vimeoPlayer.pause();
111
+ break;
112
+ }
113
+ });
114
+ }, [interactionCtrl, vimeoPlayer]);
101
115
  return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: (_e = item.link) === null || _e === void 0 ? void 0 : _e.url, target: (_f = item.link) === null || _f === void 0 ? void 0 : _f.target, children: [(0, jsx_runtime_1.jsxs)("div", { className: `embed-video-wrapper-${item.id}`, ref: setRef, style: Object.assign(Object.assign(Object.assign(Object.assign({}, (opacity !== undefined ? { opacity } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), { transition: (_g = wrapperStateParams === null || wrapperStateParams === void 0 ? void 0 : wrapperStateParams.transition) !== null && _g !== void 0 ? _g : 'none' }), onMouseEnter: () => {
102
116
  if (!vimeoPlayer || play !== 'on-hover')
103
117
  return;
@@ -96,6 +96,20 @@ const YoutubeEmbedItem = ({ item, sectionId, onResize, interactionCtrl, onVisibi
96
96
  player.pauseVideo();
97
97
  }
98
98
  }, [isInteractive, onVisibilityChange, player]);
99
+ (0, react_1.useEffect)(() => {
100
+ if (!player || !interactionCtrl)
101
+ return;
102
+ interactionCtrl.setActionReceiver((type) => {
103
+ switch (type) {
104
+ case 'play':
105
+ player.playVideo();
106
+ break;
107
+ case 'pause':
108
+ player.pauseVideo();
109
+ break;
110
+ }
111
+ });
112
+ }, [interactionCtrl, player]);
99
113
  return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: (_e = item.link) === null || _e === void 0 ? void 0 : _e.url, target: (_f = item.link) === null || _f === void 0 ? void 0 : _f.target, children: [(0, jsx_runtime_1.jsxs)("div", { className: `embed-youtube-video-wrapper-${item.id}`, onMouseEnter: () => {
100
114
  if (!player || play !== 'on-hover')
101
115
  return;
@@ -109,7 +109,7 @@ class InteractionsRegistry {
109
109
  return available;
110
110
  }
111
111
  notifyTrigger(itemId, triggerType) {
112
- var _a;
112
+ var _a, _b;
113
113
  const timestamp = Date.now();
114
114
  for (const interaction of this.interactions) {
115
115
  const currentStateId = this.getCurrentStateByInteractionId(interaction.id);
@@ -122,6 +122,14 @@ class InteractionsRegistry {
122
122
  const isNewStateActive = matchingTrigger.to === activeStateId;
123
123
  this.setCurrentStateForInteraction(interaction.id, matchingTrigger.to);
124
124
  const transitioningItems = (_a = this.stateItemsIdsMap[activeStateId]) !== null && _a !== void 0 ? _a : [];
125
+ const state = interaction.states.find((state) => state.id === matchingTrigger.to);
126
+ const actions = (_b = state === null || state === void 0 ? void 0 : state.actions) !== null && _b !== void 0 ? _b : [];
127
+ for (const action of actions) {
128
+ const ctrl = this.ctrls.get(action.itemId);
129
+ if (!ctrl)
130
+ continue;
131
+ ctrl.receiveAction(action.type);
132
+ }
125
133
  this.itemsStages = this.itemsStages.map((stage) => {
126
134
  if (stage.interactionId !== interaction.id)
127
135
  return stage;
@@ -58,6 +58,13 @@ class ItemInteractionController {
58
58
  sendTrigger(type) {
59
59
  this.registry.notifyTrigger(this.itemId, type);
60
60
  }
61
+ receiveAction(type) {
62
+ var _a;
63
+ (_a = this.actionReceiver) === null || _a === void 0 ? void 0 : _a.call(this, type);
64
+ }
65
+ setActionReceiver(action) {
66
+ this.actionReceiver = action;
67
+ }
61
68
  receiveChange() {
62
69
  this.onChange();
63
70
  }
@@ -8,18 +8,27 @@ var Allowed;
8
8
  })(Allowed || (Allowed = {}));
9
9
  function getYoutubeId({ hostname, pathname, search }) {
10
10
  if (hostname !== Allowed.Full && hostname !== Allowed.Tiny) {
11
- throw new Error(`Cannot get valid youtube ID from "${hostname}" - address is not whitelisted`);
11
+ throw new Error(`Cannot get valid YouTube ID from "${hostname}" - address is not whitelisted`);
12
12
  }
13
13
  switch (hostname) {
14
14
  case Allowed.Tiny:
15
15
  return pathname.replace('/', '');
16
16
  case Allowed.Full:
17
- const searchParams = new URLSearchParams(search);
18
- const id = searchParams.get('v');
19
- if (!id) {
20
- throw new Error("Cannot get valid youtube ID from search params.");
17
+ if (pathname.startsWith('/shorts/')) {
18
+ const shortsId = pathname.split('/shorts/')[1];
19
+ if (!shortsId) {
20
+ throw new Error('Cannot get valid YouTube Shorts ID from the pathname.');
21
+ }
22
+ return shortsId;
23
+ }
24
+ else {
25
+ const searchParams = new URLSearchParams(search);
26
+ const id = searchParams.get('v');
27
+ if (!id) {
28
+ throw new Error('Cannot get valid YouTube ID from search params.');
29
+ }
30
+ return id;
21
31
  }
22
- return id;
23
32
  }
24
33
  }
25
34
  exports.getYoutubeId = getYoutubeId;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cntrl-site/sdk-nextjs",
3
- "version": "1.4.4",
3
+ "version": "1.5.1",
4
4
  "description": "SDK for Next.js",
5
5
  "author": "arsen@momdesign.nyc",
6
6
  "license": "MIT",
@@ -31,7 +31,7 @@
31
31
  "@antfu/eslint-config": "^3.8.0",
32
32
  "@cntrl-site/color": "^1.0.0",
33
33
  "@cntrl-site/effects": "^1.3.2",
34
- "@cntrl-site/sdk": "^1.16.1",
34
+ "@cntrl-site/sdk": "^1.17.0",
35
35
  "@types/vimeo__player": "^2.18.0",
36
36
  "@vimeo/player": "^2.25.0",
37
37
  "html-react-parser": "^3.0.1",
@@ -92,6 +92,20 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId
92
92
  }
93
93
  }, [isInteractive, onVisibilityChange, vimeoPlayer]);
94
94
 
95
+ useEffect(() => {
96
+ if (!vimeoPlayer || !interactionCtrl) return;
97
+ interactionCtrl.setActionReceiver((type) => {
98
+ switch(type) {
99
+ case 'play':
100
+ vimeoPlayer.play();
101
+ break;
102
+ case 'pause':
103
+ vimeoPlayer.pause();
104
+ break;
105
+ }
106
+ });
107
+ }, [interactionCtrl, vimeoPlayer]);
108
+
95
109
  return (
96
110
  <LinkWrapper url={item.link?.url} target={item.link?.target}>
97
111
  <div
@@ -91,6 +91,20 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, secti
91
91
  }
92
92
  }, [isInteractive, onVisibilityChange, player]);
93
93
 
94
+ useEffect(() => {
95
+ if (!player || !interactionCtrl) return;
96
+ interactionCtrl.setActionReceiver((type) => {
97
+ switch(type) {
98
+ case 'play':
99
+ player.playVideo();
100
+ break;
101
+ case 'pause':
102
+ player.pauseVideo();
103
+ break;
104
+ }
105
+ });
106
+ }, [interactionCtrl, player]);
107
+
94
108
  return (
95
109
  <LinkWrapper url={item.link?.url} target={item.link?.target}>
96
110
  <div
@@ -121,6 +121,13 @@ export class InteractionsRegistry implements InteractionsRegistryPort {
121
121
  const isNewStateActive = matchingTrigger.to === activeStateId;
122
122
  this.setCurrentStateForInteraction(interaction.id, matchingTrigger.to);
123
123
  const transitioningItems = this.stateItemsIdsMap[activeStateId] ?? [];
124
+ const state = interaction.states.find((state) => state.id === matchingTrigger.to);
125
+ const actions = state?.actions ?? [];
126
+ for (const action of actions) {
127
+ const ctrl = this.ctrls.get(action.itemId);
128
+ if (!ctrl) continue;
129
+ ctrl.receiveAction(action.type);
130
+ }
124
131
  this.itemsStages = this.itemsStages.map((stage) => {
125
132
  if (stage.interactionId !== interaction.id) return stage;
126
133
  return {
@@ -166,8 +173,7 @@ export class InteractionsRegistry implements InteractionsRegistryPort {
166
173
  });
167
174
  this.ctrls.get(itemId)?.receiveChange();
168
175
  }
169
-
170
-
176
+
171
177
  private getCurrentStateByInteractionId(id: InteractionId): string {
172
178
  let state;
173
179
  for (const interactionId of Object.keys(this.interactionStateMap)) {
@@ -5,10 +5,11 @@ import { InteractionTrigger } from '@cntrl-site/sdk';
5
5
 
6
6
  export class ItemInteractionController implements ItemInteractionCtrl {
7
7
  private transitionsInProgress: Set<string> = new Set();
8
+ private actionReceiver: ((type: 'play' | 'pause') => void) | undefined;
8
9
  constructor(
9
10
  private itemId: string,
10
11
  private registry: InteractionsRegistryPort,
11
- private onChange: () => void
12
+ private onChange: () => void,
12
13
  ) {
13
14
  this.registry.register(itemId, this);
14
15
  }
@@ -37,6 +38,14 @@ export class ItemInteractionController implements ItemInteractionCtrl {
37
38
  this.registry.notifyTrigger(this.itemId, type);
38
39
  }
39
40
 
41
+ receiveAction(type: 'play' | 'pause') {
42
+ this.actionReceiver?.(type);
43
+ }
44
+
45
+ setActionReceiver(action: (type: 'play' | 'pause') => void) {
46
+ this.actionReceiver = action;
47
+ }
48
+
40
49
  handleTransitionStart = (types: string[]) => {
41
50
  this.transitionsInProgress.clear();
42
51
  for (const type of types) {
@@ -7,6 +7,8 @@ export interface ItemInteractionCtrl {
7
7
  handleTransitionEnd?: (styleKey: string) => void;
8
8
  handleTransitionStart?: (styleKeys: string[]) => void;
9
9
  receiveChange: () => void;
10
+ receiveAction: (type: 'play' | 'pause') => void;
11
+ setActionReceiver: (action: (type: 'play' | 'pause') => void) => void;
10
12
  }
11
13
 
12
14
  export interface InteractionsRegistryPort {
@@ -5,17 +5,25 @@ enum Allowed {
5
5
 
6
6
  export function getYoutubeId({ hostname, pathname, search }: URL): string {
7
7
  if (hostname !== Allowed.Full && hostname !== Allowed.Tiny) {
8
- throw new Error(`Cannot get valid youtube ID from "${hostname}" - address is not whitelisted`);
8
+ throw new Error(`Cannot get valid YouTube ID from "${hostname}" - address is not whitelisted`);
9
9
  }
10
10
  switch (hostname) {
11
11
  case Allowed.Tiny:
12
12
  return pathname.replace('/', '');
13
13
  case Allowed.Full:
14
- const searchParams = new URLSearchParams(search);
15
- const id = searchParams.get('v');
16
- if (!id) {
17
- throw new Error("Cannot get valid youtube ID from search params.");
14
+ if (pathname.startsWith('/shorts/')) {
15
+ const shortsId = pathname.split('/shorts/')[1];
16
+ if (!shortsId) {
17
+ throw new Error('Cannot get valid YouTube Shorts ID from the pathname.');
18
+ }
19
+ return shortsId;
20
+ } else {
21
+ const searchParams = new URLSearchParams(search);
22
+ const id = searchParams.get('v');
23
+ if (!id) {
24
+ throw new Error('Cannot get valid YouTube ID from search params.');
25
+ }
26
+ return id;
18
27
  }
19
- return id;
20
28
  }
21
29
  }
@@ -1,5 +0,0 @@
1
- <component name="ProjectCodeStyleConfiguration">
2
- <state>
3
- <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
4
- </state>
5
- </component>
@@ -1,15 +0,0 @@
1
- <component name="InspectionProjectProfileManager">
2
- <profile version="1.0">
3
- <option name="myName" value="Project Default" />
4
- <inspection_tool class="HtmlUnknownAttribute" enabled="true" level="WARNING" enabled_by_default="true">
5
- <option name="myValues">
6
- <value>
7
- <list size="1">
8
- <item index="0" class="java.lang.String" itemvalue="jsx" />
9
- </list>
10
- </value>
11
- </option>
12
- <option name="myCustomValuesEnabled" value="true" />
13
- </inspection_tool>
14
- </profile>
15
- </component>
package/.idea/modules.xml DELETED
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="ProjectModuleManager">
4
- <modules>
5
- <module fileurl="file://$PROJECT_DIR$/.idea/sdk-nextjs.iml" filepath="$PROJECT_DIR$/.idea/sdk-nextjs.iml" />
6
- </modules>
7
- </component>
8
- </project>
@@ -1,12 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <module type="WEB_MODULE" version="4">
3
- <component name="NewModuleRootManager">
4
- <content url="file://$MODULE_DIR$">
5
- <excludeFolder url="file://$MODULE_DIR$/temp" />
6
- <excludeFolder url="file://$MODULE_DIR$/.tmp" />
7
- <excludeFolder url="file://$MODULE_DIR$/tmp" />
8
- </content>
9
- <orderEntry type="inheritedJdk" />
10
- <orderEntry type="sourceFolder" forTests="false" />
11
- </component>
12
- </module>
package/.idea/vcs.xml DELETED
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="VcsDirectoryMappings">
4
- <mapping directory="$PROJECT_DIR$" vcs="Git" />
5
- </component>
6
- </project>