@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.
- package/.idea/codeStyles/codeStyleConfig.xml +5 -0
- package/.idea/modules.xml +8 -0
- package/.idea/sdk-nextjs.iml +12 -0
- package/.idea/vcs.xml +6 -0
- package/lib/interactions/InteractionsRegistry.js +53 -2
- package/lib/interactions/ItemInteractionCtrl.js +1 -1
- package/lib/provider/InteractionsContext.js +10 -0
- package/package.json +2 -2
- package/src/interactions/InteractionsRegistry.ts +52 -6
- package/src/interactions/ItemInteractionCtrl.ts +4 -3
- package/src/interactions/types.ts +4 -4
- package/src/provider/InteractionsContext.tsx +12 -1
- package/cntrl-site-sdk-nextjs-1.8.1.tgz +0 -0
|
@@ -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
|
@@ -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
|
-
|
|
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) =>
|
|
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));
|
|
@@ -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.
|
|
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.
|
|
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
|
-
|
|
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<
|
|
100
|
-
const available = new Set<
|
|
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
|
-
|
|
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.
|
|
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 =
|
|
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 {
|
|
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:
|
|
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.
|
|
39
|
+
this.registry.notifyItemTrigger(this.itemId, type);
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
receiveAction(type: 'play' | 'pause') {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { ArticleItemType,
|
|
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:
|
|
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<
|
|
18
|
-
|
|
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
|