@cntrl-site/sdk-nextjs 1.8.8 → 1.8.9-alpha.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.
@@ -0,0 +1,5 @@
1
+ <component name="ProjectCodeStyleConfiguration">
2
+ <state>
3
+ <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
4
+ </state>
5
+ </component>
@@ -0,0 +1,8 @@
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>
@@ -0,0 +1,12 @@
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 ADDED
@@ -0,0 +1,6 @@
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>
@@ -93,6 +93,8 @@ class InteractionsRegistry {
93
93
  for (const interaction of this.interactions) {
94
94
  const { triggers } = interaction;
95
95
  for (const trigger of triggers) {
96
+ if (!('itemId' in trigger))
97
+ continue;
96
98
  if (trigger.itemId !== itemId)
97
99
  continue;
98
100
  if (activeStates.includes(trigger.from)) {
@@ -102,12 +104,59 @@ class InteractionsRegistry {
102
104
  }
103
105
  return available;
104
106
  }
105
- notifyTrigger(itemId, triggerType) {
107
+ notifyScrollTrigger(position) {
108
+ var _a, _b;
109
+ const timestamp = Date.now();
110
+ for (const interaction of this.interactions) {
111
+ const currentStateId = this.getCurrentStateByInteractionId(interaction.id);
112
+ const matchingTrigger = interaction.triggers.find((trigger) => 'position' in trigger && (trigger.position < position ? trigger.from : trigger.to) === currentStateId // refactor
113
+ );
114
+ if (!matchingTrigger || !('position' in matchingTrigger))
115
+ continue;
116
+ const activeStateId = this.getActiveInteractionState(interaction.id);
117
+ const targetStateId = matchingTrigger.position > position ? matchingTrigger.from : matchingTrigger.to;
118
+ const isNewStateActive = targetStateId === activeStateId;
119
+ this.setCurrentStateForInteraction(interaction.id, targetStateId !== null && targetStateId !== void 0 ? targetStateId : activeStateId);
120
+ const transitioningItems = (_a = this.stateItemsIdsMap[activeStateId]) !== null && _a !== void 0 ? _a : [];
121
+ const state = interaction.states.find((state) => state.id === targetStateId);
122
+ const actions = (_b = state === null || state === void 0 ? void 0 : state.actions) !== null && _b !== void 0 ? _b : [];
123
+ for (const action of actions) {
124
+ const ctrl = this.ctrls.get(action.itemId);
125
+ if (!ctrl)
126
+ continue;
127
+ ctrl.receiveAction(action.type);
128
+ }
129
+ const itemsStages = this.itemsStages.map((stage) => {
130
+ if (stage.interactionId !== interaction.id)
131
+ return stage;
132
+ return {
133
+ itemId: stage.itemId,
134
+ interactionId: stage.interactionId,
135
+ type: 'transitioning',
136
+ from: stage.type === 'transitioning' ? stage.to : stage.stateId,
137
+ to: targetStateId,
138
+ direction: isNewStateActive ? 'in' : 'out',
139
+ updated: timestamp
140
+ };
141
+ });
142
+ this.itemsStages = itemsStages;
143
+ const itemsToNotify = new Set(transitioningItems);
144
+ for (const trigger of interaction.triggers) {
145
+ if (!('itemId' in trigger))
146
+ continue;
147
+ itemsToNotify.add(trigger.itemId);
148
+ }
149
+ this.notifyItemCtrlsChange(Array.from(itemsToNotify));
150
+ this.notifyTransitionStartForItems(transitioningItems, activeStateId);
151
+ }
152
+ }
153
+ notifyItemTrigger(itemId, triggerType) {
106
154
  var _a, _b;
107
155
  const timestamp = Date.now();
108
156
  for (const interaction of this.interactions) {
109
157
  const currentStateId = this.getCurrentStateByInteractionId(interaction.id);
110
- const matchingTrigger = interaction.triggers.find((trigger) => trigger.itemId === itemId
158
+ const matchingTrigger = interaction.triggers.find((trigger) => 'itemId' in trigger
159
+ && trigger.itemId === itemId
111
160
  && trigger.from === currentStateId
112
161
  && trigger.type === triggerType);
113
162
  if (!matchingTrigger)
@@ -139,6 +188,8 @@ class InteractionsRegistry {
139
188
  });
140
189
  const itemsToNotify = new Set(transitioningItems);
141
190
  for (const trigger of interaction.triggers) {
191
+ if (!('itemId' in trigger))
192
+ continue;
142
193
  itemsToNotify.add(trigger.itemId);
143
194
  }
144
195
  this.notifyItemCtrlsChange(Array.from(itemsToNotify));
@@ -56,7 +56,7 @@ class ItemInteractionController {
56
56
  return triggers.has(triggerType);
57
57
  }
58
58
  sendTrigger(type) {
59
- this.registry.notifyTrigger(this.itemId, type);
59
+ this.registry.notifyItemTrigger(this.itemId, type);
60
60
  }
61
61
  receiveAction(type) {
62
62
  var _a;
@@ -13,6 +13,16 @@ const InteractionsProvider = ({ article, children }) => {
13
13
  return;
14
14
  return new InteractionsRegistry_1.InteractionsRegistry(article, layoutId);
15
15
  }, [layoutId]);
16
+ (0, react_1.useEffect)(() => {
17
+ if (!registry)
18
+ return;
19
+ const handleScroll = () => {
20
+ const scrollY = window.scrollY;
21
+ registry.notifyScrollTrigger(scrollY);
22
+ };
23
+ window.addEventListener('scroll', handleScroll, { passive: true });
24
+ return () => window.removeEventListener('scroll', handleScroll);
25
+ }, [registry]);
16
26
  return ((0, jsx_runtime_1.jsx)(exports.InteractionsContext.Provider, { value: registry, children: children }));
17
27
  };
18
28
  exports.InteractionsProvider = InteractionsProvider;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cntrl-site/sdk-nextjs",
3
- "version": "1.8.8",
3
+ "version": "1.8.9-alpha.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.22.8",
34
+ "@cntrl-site/sdk": "^1.22.9-alpha.0",
35
35
  "@types/vimeo__player": "^2.18.0",
36
36
  "@vimeo/player": "^2.25.0",
37
37
  "html-react-parser": "^3.0.1",
@@ -3,7 +3,7 @@ import {
3
3
  Article,
4
4
  ArticleItemType,
5
5
  Interaction,
6
- InteractionTrigger,
6
+ InteractionItemTrigger,
7
7
  ItemAny,
8
8
  } from '@cntrl-site/sdk';
9
9
  import { isItemType } from '../utils/isItemType';
@@ -96,12 +96,13 @@ export class InteractionsRegistry implements InteractionsRegistryPort {
96
96
  return itemStyles;
97
97
  }
98
98
 
99
- getItemAvailableTriggers(itemId: string): Set<InteractionTrigger['type']> {
100
- const available = new Set<InteractionTrigger['type']>();
99
+ getItemAvailableTriggers(itemId: string): Set<InteractionItemTrigger['type']> {
100
+ const available = new Set<InteractionItemTrigger['type']>();
101
101
  const activeStates = Object.values(this.interactionStateMap);
102
102
  for (const interaction of this.interactions) {
103
103
  const { triggers } = interaction;
104
104
  for (const trigger of triggers) {
105
+ if (!('itemId' in trigger)) continue;
105
106
  if (trigger.itemId !== itemId) continue;
106
107
  if (activeStates.includes(trigger.from)) {
107
108
  available.add(trigger.type);
@@ -111,12 +112,56 @@ export class InteractionsRegistry implements InteractionsRegistryPort {
111
112
  return available;
112
113
  }
113
114
 
114
- notifyTrigger(itemId: string, triggerType: TriggerType): void {
115
+ notifyScrollTrigger(position: number) {
115
116
  const timestamp = Date.now();
116
117
  for (const interaction of this.interactions) {
117
118
  const currentStateId = this.getCurrentStateByInteractionId(interaction.id);
118
119
  const matchingTrigger = interaction.triggers.find((trigger) =>
119
- trigger.itemId === itemId
120
+ 'position' in trigger && (trigger.position < position ? trigger.from : trigger.to) === currentStateId // refactor
121
+ );
122
+ if (!matchingTrigger || !('position' in matchingTrigger)) continue;
123
+ const activeStateId = this.getActiveInteractionState(interaction.id);
124
+ const targetStateId = matchingTrigger.position > position ? matchingTrigger.from : matchingTrigger.to;
125
+ const isNewStateActive = targetStateId === activeStateId;
126
+ this.setCurrentStateForInteraction(interaction.id, targetStateId ?? activeStateId);
127
+ const transitioningItems = this.stateItemsIdsMap[activeStateId] ?? [];
128
+ const state = interaction.states.find((state) => state.id === targetStateId);
129
+ const actions = state?.actions ?? [];
130
+ for (const action of actions) {
131
+ const ctrl = this.ctrls.get(action.itemId);
132
+ if (!ctrl) continue;
133
+ ctrl.receiveAction(action.type);
134
+ }
135
+ const itemsStages = this.itemsStages.map((stage) => {
136
+ if (stage.interactionId !== interaction.id) return stage;
137
+ return {
138
+ itemId: stage.itemId,
139
+ interactionId: stage.interactionId,
140
+ type: 'transitioning' as const,
141
+ from: stage.type === 'transitioning' ? stage.to : stage.stateId!,
142
+ to: targetStateId,
143
+ direction: isNewStateActive ? 'in' as const : 'out' as const,
144
+ updated: timestamp
145
+ };
146
+ });
147
+ this.itemsStages = itemsStages;
148
+ const itemsToNotify = new Set<ItemId>(transitioningItems);
149
+ for (const trigger of interaction.triggers) {
150
+ if (!('itemId' in trigger)) continue;
151
+ itemsToNotify.add(trigger.itemId);
152
+ }
153
+ this.notifyItemCtrlsChange(Array.from(itemsToNotify));
154
+ this.notifyTransitionStartForItems(transitioningItems, activeStateId);
155
+ }
156
+ }
157
+
158
+ notifyItemTrigger(itemId: string, triggerType: TriggerType): void {
159
+ const timestamp = Date.now();
160
+ for (const interaction of this.interactions) {
161
+ const currentStateId = this.getCurrentStateByInteractionId(interaction.id);
162
+ const matchingTrigger = interaction.triggers.find((trigger) =>
163
+ 'itemId' in trigger
164
+ && trigger.itemId === itemId
120
165
  && trigger.from === currentStateId
121
166
  && trigger.type === triggerType
122
167
  );
@@ -146,6 +191,7 @@ export class InteractionsRegistry implements InteractionsRegistryPort {
146
191
  });
147
192
  const itemsToNotify = new Set<ItemId>(transitioningItems);
148
193
  for (const trigger of interaction.triggers) {
194
+ if (!('itemId' in trigger)) continue;
149
195
  itemsToNotify.add(trigger.itemId);
150
196
  }
151
197
  this.notifyItemCtrlsChange(Array.from(itemsToNotify));
@@ -269,7 +315,7 @@ type TransitioningStage = {
269
315
  type ActiveStage = { type: 'active'; itemId: string; interactionId: string; stateId?: string; isStartState: boolean; updated: number; };
270
316
  type InteractionStateMap = Record<InteractionId, StateId>;
271
317
  type StateItemsIdsMap = Record<StateId, ItemId[]>;
272
- type TriggerType = InteractionTrigger['type'];
318
+ type TriggerType = InteractionItemTrigger['type'];
273
319
  type InteractionId = string;
274
320
  type StateId = string;
275
321
  type ItemId = string;
@@ -1,11 +1,12 @@
1
1
  import { InteractionsRegistryPort, ItemInteractionCtrl } from './types';
2
2
  import { getTransition } from './getTransition';
3
3
  import { getStyleKeysFromCSSProperty } from './CSSPropertyNameMap';
4
- import { InteractionTrigger } from '@cntrl-site/sdk';
4
+ import { InteractionItemTrigger } from '@cntrl-site/sdk';
5
5
 
6
6
  export class ItemInteractionController implements ItemInteractionCtrl {
7
7
  private transitionsInProgress: Set<string> = new Set();
8
8
  private actionReceiver: ((type: 'play' | 'pause') => void) | undefined;
9
+
9
10
  constructor(
10
11
  private itemId: string,
11
12
  private registry: InteractionsRegistryPort,
@@ -29,13 +30,13 @@ export class ItemInteractionController implements ItemInteractionCtrl {
29
30
  };
30
31
  }
31
32
 
32
- getHasTrigger(itemId: string, triggerType: InteractionTrigger['type']): boolean {
33
+ getHasTrigger(itemId: string, triggerType: InteractionItemTrigger['type']): boolean {
33
34
  const triggers = this.registry.getItemAvailableTriggers(itemId);
34
35
  return triggers.has(triggerType);
35
36
  }
36
37
 
37
38
  sendTrigger(type: 'click' | 'hover-in' | 'hover-out') {
38
- this.registry.notifyTrigger(this.itemId, type);
39
+ this.registry.notifyItemTrigger(this.itemId, type);
39
40
  }
40
41
 
41
42
  receiveAction(type: 'play' | 'pause') {
@@ -1,8 +1,8 @@
1
- import { ArticleItemType, InteractionTrigger, ItemState } from '@cntrl-site/sdk';
1
+ import { ArticleItemType, InteractionItemTrigger, ItemState } from '@cntrl-site/sdk';
2
2
 
3
3
  export interface ItemInteractionCtrl {
4
4
  getState(keys: string[]): StateCSSInfo;
5
- getHasTrigger(itemId: string, triggerType: InteractionTrigger['type']): boolean;
5
+ getHasTrigger(itemId: string, triggerType: InteractionItemTrigger['type']): boolean;
6
6
  sendTrigger(type: 'click' | 'hover-in' | 'hover-out'): void;
7
7
  handleTransitionEnd?: (styleKey: string) => void;
8
8
  handleTransitionStart?: (styleKeys: string[]) => void;
@@ -14,8 +14,8 @@ export interface ItemInteractionCtrl {
14
14
  export interface InteractionsRegistryPort {
15
15
  register(itemId: string, ctrl: ItemInteractionCtrl): void;
16
16
  getStatePropsForItem(itemId: string): StateProps;
17
- getItemAvailableTriggers(itemId: string): Set<InteractionTrigger['type']>;
18
- notifyTrigger(itemId: string, type: TriggerType): void;
17
+ getItemAvailableTriggers(itemId: string): Set<InteractionItemTrigger['type']>;
18
+ notifyItemTrigger(itemId: string, type: TriggerType): void;
19
19
  notifyTransitionEnd(itemId: string): void;
20
20
  }
21
21
 
@@ -1,4 +1,4 @@
1
- import { createContext, FC, PropsWithChildren, useContext, useMemo } from 'react';
1
+ import { createContext, FC, PropsWithChildren, useContext, useEffect, useMemo } from 'react';
2
2
  import { InteractionsRegistry } from '../interactions/InteractionsRegistry';
3
3
  import { Article } from '@cntrl-site/sdk';
4
4
  import { useCurrentLayout } from '../common/useCurrentLayout';
@@ -15,6 +15,17 @@ export const InteractionsProvider: FC<PropsWithChildren<Props>> = ({ article, ch
15
15
  if (!layoutId) return;
16
16
  return new InteractionsRegistry(article, layoutId);
17
17
  }, [layoutId]);
18
+
19
+ useEffect(() => {
20
+ if (!registry) return;
21
+ const handleScroll = () => {
22
+ const scrollY = window.scrollY;
23
+ registry.notifyScrollTrigger(scrollY);
24
+ };
25
+ window.addEventListener('scroll', handleScroll, { passive: true });
26
+ return () => window.removeEventListener('scroll', handleScroll);
27
+ }, [registry]);
28
+
18
29
  return (
19
30
  <InteractionsContext.Provider value={registry}>
20
31
  {children}
Binary file