@cntrl-site/sdk-nextjs 1.0.19-alpha.3 → 1.0.20

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 (38) hide show
  1. package/jest.config.js +2 -2
  2. package/lib/components/Article.js +8 -9
  3. package/lib/components/Head.js +1 -1
  4. package/lib/components/Item.js +13 -33
  5. package/lib/components/items/CodeEmbedItem.js +8 -10
  6. package/lib/components/items/CustomItem.js +7 -9
  7. package/lib/components/items/GroupItem.js +8 -10
  8. package/lib/components/items/ImageItem.js +15 -19
  9. package/lib/components/items/RectangleItem.js +8 -10
  10. package/lib/components/items/RichTextItem.js +7 -9
  11. package/lib/components/items/VideoItem.js +12 -14
  12. package/lib/components/items/VimeoEmbed.js +15 -17
  13. package/lib/components/items/YoutubeEmbed.js +13 -16
  14. package/lib/utils/{StateStyles/StateStyles.js → HoverStyles/HoverStyles.js} +24 -36
  15. package/package.json +4 -7
  16. package/src/components/Article.tsx +28 -31
  17. package/src/components/ArticleWrapper.tsx +2 -1
  18. package/src/components/Head.tsx +11 -7
  19. package/src/components/Item.tsx +18 -38
  20. package/src/components/items/CodeEmbedItem.tsx +9 -11
  21. package/src/components/items/CustomItem.tsx +9 -11
  22. package/src/components/items/GroupItem.tsx +9 -11
  23. package/src/components/items/ImageItem.tsx +19 -24
  24. package/src/components/items/RectangleItem.tsx +10 -12
  25. package/src/components/items/RichTextItem.tsx +9 -16
  26. package/src/components/items/VideoItem.tsx +15 -17
  27. package/src/components/items/VimeoEmbed.tsx +16 -18
  28. package/src/components/items/YoutubeEmbed.tsx +16 -18
  29. package/src/utils/{StateStyles/StateStyles.ts → HoverStyles/HoverStyles.ts} +27 -41
  30. package/lib/components/useStatesClassNames.js +0 -18
  31. package/lib/components/useStatesTransitions.js +0 -89
  32. package/lib/provider/InteractionsContext.js +0 -45
  33. package/lib/utils/getStatesCSS.js +0 -16
  34. package/src/components/useStatesClassNames.ts +0 -23
  35. package/src/components/useStatesTransitions.ts +0 -95
  36. package/src/provider/InteractionsContext.test.tsx +0 -97
  37. package/src/provider/InteractionsContext.tsx +0 -65
  38. package/src/utils/getStatesCSS.ts +0 -24
@@ -1,12 +1,12 @@
1
- import { StateParams, ArticleItemType, AnchorSide, ItemState, ItemStatesMap } from '@cntrl-site/sdk';
1
+ import { HoverParams, ArticleItemType, AnchorSide, ItemHoverState } from '@cntrl-site/sdk';
2
2
  import { CntrlColor } from '@cntrl-site/color';
3
3
  import { getItemTopStyle } from '../getItemTopStyle';
4
4
 
5
- type StateParamsGetter = (value: any, anchorSide?: AnchorSide) => string;
6
- type AllKeys<T> = T extends any ? keyof T : never;
7
- type StatePropertyKey = AllKeys<ItemStatesMap[keyof ItemStatesMap]>;
5
+ type UnionToIntersection<U> = (U extends any ? (arg: U) => void : never) extends (arg: infer I) => void ? I : never;
6
+ type HoverParamsGetter = (value: any, anchorSide?: AnchorSide) => string;
7
+ type ItemHoverParams = Omit<UnionToIntersection<ItemHoverState>, 'autoplay'>;
8
8
 
9
- const stateTransformationMap: Record<StatePropertyKey, StateParamsGetter> = {
9
+ const hoverTransformationMap: Record<keyof ItemHoverParams, HoverParamsGetter> = {
10
10
  'width': (width: number) => `width: ${width * 100}vw !important;`,
11
11
  'height': (height: number) => `height: ${height * 100}vw !important;`,
12
12
  'top': (top: number, anchorSide?: AnchorSide) => `top: ${getItemTopStyle(top, anchorSide)} !important;`,
@@ -25,7 +25,7 @@ const stateTransformationMap: Record<StatePropertyKey, StateParamsGetter> = {
25
25
  'wordSpacing': (wordSpacing: number) => `word-spacing: ${wordSpacing * 100}vw !important;`
26
26
  };
27
27
 
28
- const CSSPropertyNameMap: Record<keyof ItemState<ArticleItemType>, string> = {
28
+ const CSSPropertyNameMap: Record<keyof ItemHoverParams, string> = {
29
29
  'width': 'width',
30
30
  'height': 'height',
31
31
  'top': 'top',
@@ -44,56 +44,42 @@ const CSSPropertyNameMap: Record<keyof ItemState<ArticleItemType>, string> = {
44
44
  'color': 'color'
45
45
  };
46
46
 
47
- export function getStateStyles<T extends ArticleItemType>(
48
- values: Array<StatePropertyKey>,
49
- state?: ItemStatesMap[T],
50
- anchorSide?: AnchorSide
47
+ export function getTransitions<T extends ArticleItemType>(
48
+ values: Array<keyof ItemHoverParams>,
49
+ hover?: ItemHoverParams
51
50
  ): string {
52
- if (!state) return '';
53
-
54
- const stateValues = values.reduce<string[]>((acc, valueName) => {
55
- // @ts-ignore
56
- if (valueName in state && state[valueName] !== undefined) {
57
- // @ts-ignore
58
- const stateProperties = state[valueName] as StateParams<string | number>;
59
- const getter = stateTransformationMap[valueName] as StateParamsGetter;
51
+ if (!hover) return 'unset';
52
+ const transitionValues = values.reduce<string[]>((acc, valueName) => {
53
+ if (valueName in hover && hover[valueName] !== undefined) {
54
+ const hoverProperties = hover[valueName] as HoverParams<string | number>;
60
55
  return [
61
56
  ...acc,
62
- getter(stateProperties.value, anchorSide)
57
+ `${CSSPropertyNameMap[valueName]} ${hoverProperties!.duration}ms ${hoverProperties!.timing} ${hoverProperties!.delay}ms`
63
58
  ];
64
59
  }
65
60
  return acc;
66
61
  }, []);
67
-
68
- if (!stateValues.length) return '';
69
- // @ts-ignore
70
- const transitionStr = getTransitions(values, state);
71
- stateValues.push(`transition: ${transitionStr};`);
72
- return stateValues.join('\n');
62
+ if (!transitionValues.length) return 'unset';
63
+ return transitionValues.join(', ');
73
64
  }
74
65
 
75
- export function getTransitions<T extends ArticleItemType>(
76
- values: Array<StatePropertyKey>,
77
- state?: ItemStatesMap[T]
66
+ export function getHoverStyles<T extends ArticleItemType>(
67
+ values: Array<keyof ItemHoverParams>,
68
+ hover?: ItemHoverParams,
69
+ anchorSide?: AnchorSide
78
70
  ): string {
79
- if (!state) return 'unset';
80
- const transitionValues = values.reduce<string[]>((acc, valueName) => {
81
- // @ts-ignore TODO
82
- if (valueName in state && state[valueName] !== undefined) {
83
- // @ts-ignore TODO
84
- const stateProperties = state[valueName] as StateParams<string | number>;
71
+ if (!hover) return '';
72
+ const hoverValues = values.reduce<string[]>((acc, valueName) => {
73
+ if (valueName in hover && hover[valueName] !== undefined) {
74
+ const hoverProperties = hover[valueName] as HoverParams<string | number>;
85
75
  return [
86
76
  ...acc,
87
- // @ts-ignore
88
- `${CSSPropertyNameMap[valueName]} ${stateProperties!.duration}ms ${stateProperties!.timing} ${stateProperties!.delay}ms`
77
+ hoverTransformationMap[valueName](hoverProperties.value, anchorSide)
89
78
  ];
90
79
  }
91
80
  return acc;
92
81
  }, []);
93
- if (!transitionValues.length) return 'unset';
94
- return transitionValues.join(', ');
82
+ if (!hoverValues.length) return '';
83
+ return hoverValues.join('\n');
95
84
  }
96
85
 
97
- // export function getStateTransitions<T extends ArticleItemType>(
98
- //
99
- // )
@@ -1,18 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useStatesClassNames = void 0;
4
- const react_1 = require("react");
5
- const InteractionsContext_1 = require("../provider/InteractionsContext");
6
- const useCurrentLayout_1 = require("../common/useCurrentLayout");
7
- function useStatesClassNames(itemId, itemStates, uniquePrefix) {
8
- const { interactionsStatesMap } = (0, react_1.useContext)(InteractionsContext_1.InteractionsContext);
9
- const { layoutId } = (0, useCurrentLayout_1.useCurrentLayout)();
10
- const activeStates = Object.values(interactionsStatesMap);
11
- const statesForLayout = layoutId ? itemStates[layoutId] : {};
12
- const stateClassNames = Object.keys(statesForLayout !== null && statesForLayout !== void 0 ? statesForLayout : {})
13
- .filter((stateId) => activeStates.includes(stateId))
14
- .map((stateId) => `${uniquePrefix}-${itemId}-state-${stateId}`)
15
- .join(' ');
16
- return stateClassNames;
17
- }
18
- exports.useStatesClassNames = useStatesClassNames;
@@ -1,89 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useStatesTransitions = void 0;
4
- const react_1 = require("react");
5
- const InteractionsContext_1 = require("../provider/InteractionsContext");
6
- const useCurrentLayout_1 = require("../common/useCurrentLayout");
7
- function useStatesTransitions(el, state, values) {
8
- const { interactionsStatesMap } = (0, react_1.useContext)(InteractionsContext_1.InteractionsContext);
9
- const { layoutId } = (0, useCurrentLayout_1.useCurrentLayout)();
10
- const activeStates = Object.values(interactionsStatesMap);
11
- const statesForLayout = (0, react_1.useMemo)(() => layoutId ? state[layoutId] : {}, [state, layoutId]);
12
- const itemStatesIds = statesForLayout ? Object.keys(statesForLayout) : [];
13
- const itemActiveStateId = activeStates.find((stateId) => itemStatesIds.includes(stateId));
14
- (0, react_1.useEffect)(() => {
15
- if (!itemActiveStateId || !el)
16
- return;
17
- const state = statesForLayout[itemActiveStateId];
18
- const transitionStr = getTransition(state, 'in', values);
19
- const slowestProp = getSlowestProperty(state, 'in', values);
20
- if (!transitionStr)
21
- return;
22
- el.style.transition = transitionStr;
23
- el.ontransitionend = (e) => {
24
- e.stopPropagation();
25
- if (e.target !== el || e.propertyName !== slowestProp)
26
- return;
27
- el.style.transition = 'none';
28
- };
29
- return () => {
30
- const transitionStr = getTransition(state, 'out', values);
31
- const slowestProp = getSlowestProperty(state, 'out', values);
32
- if (!transitionStr)
33
- return;
34
- el.style.transition = transitionStr;
35
- el.ontransitionend = (e) => {
36
- e.stopPropagation();
37
- if (e.target !== el || e.propertyName !== slowestProp)
38
- return;
39
- el.style.transition = 'none';
40
- };
41
- };
42
- }, [itemActiveStateId, statesForLayout, el]);
43
- }
44
- exports.useStatesTransitions = useStatesTransitions;
45
- const CSSPropertyNameMap = {
46
- 'width': 'width',
47
- 'height': 'height',
48
- 'top': 'top',
49
- 'left': 'left',
50
- 'scale': 'transform',
51
- 'angle': 'transform',
52
- 'opacity': 'opacity',
53
- 'radius': 'border-radius',
54
- 'strokeWidth': 'border-width',
55
- 'strokeColor': 'border-color',
56
- 'fillColor': 'background-color',
57
- 'blur': 'filter',
58
- 'backdropBlur': 'backdrop-filter',
59
- 'letterSpacing': 'letter-spacing',
60
- 'wordSpacing': 'word-spacing',
61
- 'color': 'color'
62
- };
63
- function getTransition(state, direction, values) {
64
- return Object.entries(state)
65
- .filter(([key]) => values.includes(key))
66
- .map(([key, params]) => {
67
- const cssKey = CSSPropertyNameMap[key];
68
- if (!cssKey) {
69
- throw new Error(`Cannot translate "${key}" to a CSS property.`);
70
- }
71
- return `${cssKey} ${params[direction].duration}ms ${params[direction].timing} ${params[direction].delay}ms`;
72
- }, [])
73
- .join(', ');
74
- }
75
- function getSlowestProperty(state, direction, values) {
76
- const mappedEntries = Object.entries(state)
77
- .filter(([key]) => values.includes(key))
78
- .map(([key, params]) => {
79
- const transitionParams = params[direction];
80
- return {
81
- key,
82
- time: transitionParams.duration + transitionParams.delay
83
- };
84
- });
85
- if (mappedEntries.length === 0)
86
- return '';
87
- const { key } = mappedEntries.reduce((slowest, current) => current.time > slowest.time ? current : slowest);
88
- return CSSPropertyNameMap[key];
89
- }
@@ -1,45 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.InteractionsProvider = exports.InteractionsContext = void 0;
4
- const jsx_runtime_1 = require("react/jsx-runtime");
5
- const react_1 = require("react");
6
- const defaultState = {
7
- interactionsStatesMap: {},
8
- interactions: [],
9
- transitionTo: () => { },
10
- getItemTrigger: () => null
11
- };
12
- exports.InteractionsContext = (0, react_1.createContext)(defaultState);
13
- const InteractionsProvider = ({ interactions, children }) => {
14
- const defaultStatesMap = interactions.reduce((map, { id, startStateId }) => {
15
- map[id] = startStateId;
16
- return map;
17
- }, {});
18
- const [interactionsStatesMap, setInteractionsStatesMap] = (0, react_1.useState)(defaultStatesMap);
19
- const transitionTo = (interactionId, stateId) => {
20
- setInteractionsStatesMap((map) => (Object.assign(Object.assign({}, map), { [interactionId]: stateId })));
21
- };
22
- const getItemTrigger = (itemId, triggerType) => {
23
- for (const interaction of interactions) {
24
- const activeStateId = interactionsStatesMap[interaction.id];
25
- const matchingTrigger = interaction.triggers.find((trigger) => trigger.itemId === itemId &&
26
- trigger.from === activeStateId &&
27
- trigger.type === triggerType);
28
- if (matchingTrigger) {
29
- return {
30
- id: interaction.id,
31
- from: matchingTrigger.from,
32
- to: matchingTrigger.to,
33
- };
34
- }
35
- }
36
- return null;
37
- };
38
- return ((0, jsx_runtime_1.jsx)(exports.InteractionsContext.Provider, { value: {
39
- transitionTo,
40
- interactionsStatesMap,
41
- interactions,
42
- getItemTrigger
43
- }, children: children }));
44
- };
45
- exports.InteractionsProvider = InteractionsProvider;
@@ -1,16 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getStatesCSS = void 0;
4
- const StateStyles_1 = require("./StateStyles/StateStyles");
5
- function getStatesCSS(itemId, classNamePrefix, keys, states, anchorSide) {
6
- return states
7
- ? Object.entries(states).map(([stateId, params]) => {
8
- return `
9
- .${classNamePrefix}-${itemId}-state-${stateId} {
10
- ${(0, StateStyles_1.getStateStyles)(keys, params, anchorSide)};
11
- }
12
- `;
13
- }).join('\n')
14
- : '';
15
- }
16
- exports.getStatesCSS = getStatesCSS;
@@ -1,23 +0,0 @@
1
- import { ItemStateParams } from '@cntrl-site/sdk';
2
- import { useContext } from 'react';
3
- import { InteractionsContext } from '../provider/InteractionsContext';
4
- import { useCurrentLayout } from '../common/useCurrentLayout';
5
-
6
- export function useStatesClassNames(
7
- itemId: string,
8
- itemStates: Record<LayoutId, Record<StateId, ItemStateParams>>,
9
- uniquePrefix: string, // unique in terms of item type, ie. rectangle, code-embed, group etc
10
- ): string {
11
- const { interactionsStatesMap } = useContext(InteractionsContext);
12
- const { layoutId } = useCurrentLayout();
13
- const activeStates = Object.values(interactionsStatesMap);
14
- const statesForLayout = layoutId ? itemStates[layoutId] : {};
15
- const stateClassNames = Object.keys(statesForLayout ?? {})
16
- .filter((stateId) => activeStates.includes(stateId))
17
- .map((stateId) => `${uniquePrefix}-${itemId}-state-${stateId}`)
18
- .join(' ');
19
- return stateClassNames;
20
- }
21
-
22
- type StateId = string;
23
- type LayoutId = string;
@@ -1,95 +0,0 @@
1
- import { ArticleItemType, ItemState, ItemStateParams, ItemStatesMap } from '@cntrl-site/sdk';
2
- import { useContext, useEffect, useMemo } from 'react';
3
- import { InteractionsContext } from '../provider/InteractionsContext';
4
- import { useCurrentLayout } from '../common/useCurrentLayout';
5
-
6
- type AllKeys<T> = T extends any ? keyof T : never;
7
- type StatePropertyKey = AllKeys<ItemStatesMap[keyof ItemStatesMap]>;
8
-
9
- export function useStatesTransitions(
10
- el: HTMLElement | null,
11
- state: ItemState<ArticleItemType>,
12
- values: StatePropertyKey[]
13
- ) {
14
- const { interactionsStatesMap } = useContext(InteractionsContext);
15
- const { layoutId } = useCurrentLayout();
16
- const activeStates = Object.values(interactionsStatesMap);
17
- const statesForLayout = useMemo(() => layoutId ? state[layoutId] : {}, [state, layoutId]);
18
- const itemStatesIds = statesForLayout ? Object.keys(statesForLayout) : [];
19
- const itemActiveStateId = activeStates.find((stateId) => itemStatesIds.includes(stateId));
20
- useEffect(() => {
21
- if (!itemActiveStateId || !el) return;
22
- const state = statesForLayout[itemActiveStateId];
23
- const transitionStr = getTransition(state, 'in', values);
24
- const slowestProp = getSlowestProperty(state, 'in', values);
25
- if (!transitionStr) return;
26
- el.style.transition = transitionStr;
27
- el.ontransitionend = (e) => {
28
- e.stopPropagation();
29
- if (e.target !== el || e.propertyName !== slowestProp) return;
30
- el.style.transition = 'none';
31
- };
32
- return () => {
33
- const transitionStr = getTransition(state, 'out', values);
34
- const slowestProp = getSlowestProperty(state, 'out', values);
35
- if (!transitionStr) return;
36
- el.style.transition = transitionStr;
37
- el.ontransitionend = (e) => {
38
- e.stopPropagation();
39
- if (e.target !== el || e.propertyName !== slowestProp) return;
40
- el.style.transition = 'none';
41
- };
42
- };
43
- }, [itemActiveStateId, statesForLayout, el]);
44
- }
45
-
46
- const CSSPropertyNameMap: Record<keyof ItemState<ArticleItemType>, string> = {
47
- 'width': 'width',
48
- 'height': 'height',
49
- 'top': 'top',
50
- 'left': 'left',
51
- 'scale': 'transform',
52
- 'angle': 'transform',
53
- 'opacity': 'opacity',
54
- 'radius': 'border-radius',
55
- 'strokeWidth': 'border-width',
56
- 'strokeColor': 'border-color',
57
- 'fillColor': 'background-color',
58
- 'blur': 'filter',
59
- 'backdropBlur': 'backdrop-filter',
60
- 'letterSpacing': 'letter-spacing',
61
- 'wordSpacing': 'word-spacing',
62
- 'color': 'color'
63
- };
64
-
65
- function getTransition(
66
- state: ItemStateParams,
67
- direction: 'in' | 'out',
68
- values: string[]
69
- ) {
70
- return Object.entries(state)
71
- .filter(([key]) => values.includes(key))
72
- .map(([key, params]) => {
73
- const cssKey = CSSPropertyNameMap[key];
74
- if (!cssKey) {
75
- throw new Error(`Cannot translate "${key}" to a CSS property.`);
76
- }
77
- return `${cssKey} ${params[direction].duration}ms ${params[direction].timing} ${params[direction].delay}ms`;
78
- }, [])
79
- .join(', ');
80
- }
81
-
82
- function getSlowestProperty(state: ItemStateParams, direction: 'in' | 'out', values: string[]): string {
83
- const mappedEntries = Object.entries(state)
84
- .filter(([key]) => values.includes(key))
85
- .map(([key, params]) => {
86
- const transitionParams = params[direction];
87
- return {
88
- key,
89
- time: transitionParams.duration + transitionParams.delay
90
- }
91
- });
92
- if (mappedEntries.length === 0) return '';
93
- const { key } = mappedEntries.reduce((slowest, current) => current.time > slowest.time ? current : slowest);
94
- return CSSPropertyNameMap[key];
95
- }
@@ -1,97 +0,0 @@
1
- import React from 'react';
2
- import { render, waitFor } from '@testing-library/react';
3
- import { InteractionsProvider, InteractionsContext } from './InteractionsContext';
4
- import { Interaction } from '@cntrl-site/sdk';
5
-
6
- describe('InteractionsProvider', () => {
7
- const interactions: Interaction[] = [
8
- {
9
- id: 'interaction1',
10
- startStateId: 'state1',
11
- triggers: [
12
- { itemId: 'item1', type: 'click', from: 'state1', to: 'state2' }
13
- ],
14
- states: [{ id: 'state1' }, { id: 'state2' }]
15
- },
16
- {
17
- id: 'interaction2',
18
- startStateId: 'state3',
19
- triggers: [
20
- { itemId: 'item2', type: 'hover-in', from: 'state3', to: 'state4' }
21
- ],
22
- states: [{ id: 'state3' }, { id: 'state4' }]
23
- }
24
- ];
25
-
26
- it('should generate correct default interactionsStatesMap', () => {
27
- let contextValue;
28
-
29
- render(
30
- <InteractionsProvider interactions={interactions}>
31
- <InteractionsContext.Consumer>
32
- {value => {
33
- contextValue = value;
34
- return null;
35
- }}
36
- </InteractionsContext.Consumer>
37
- </InteractionsProvider>
38
- );
39
-
40
- expect(contextValue!).toBeDefined();
41
- expect(contextValue!.interactionsStatesMap).toEqual({
42
- interaction1: 'state1',
43
- interaction2: 'state3'
44
- });
45
- });
46
-
47
- it('should correctly update interactionsStatesMap when transitionTo is called', async () => {
48
- let contextValue;
49
-
50
- render(
51
- <InteractionsProvider interactions={interactions}>
52
- <InteractionsContext.Consumer>
53
- {value => {
54
- contextValue = value;
55
- return null;
56
- }}
57
- </InteractionsContext.Consumer>
58
- </InteractionsProvider>
59
- );
60
-
61
- expect(contextValue!).toBeDefined();
62
- contextValue!.transitionTo('interaction1', 'state2');
63
-
64
- await waitFor(() => {
65
- expect(contextValue!.interactionsStatesMap['interaction1']).toBe('state2');
66
- });
67
- });
68
-
69
- it('should return the correct trigger using getItemTrigger', () => {
70
- let contextValue;
71
-
72
- render(
73
- <InteractionsProvider interactions={interactions}>
74
- <InteractionsContext.Consumer>
75
- {value => {
76
- contextValue = value;
77
- return null;
78
- }}
79
- </InteractionsContext.Consumer>
80
- </InteractionsProvider>
81
- );
82
-
83
- expect(contextValue!).toBeDefined();
84
-
85
- // Check the correct trigger is returned
86
- const trigger = contextValue!.getItemTrigger('item1', 'click');
87
- expect(trigger).toEqual({
88
- id: 'interaction1',
89
- from: 'state1',
90
- to: 'state2',
91
- });
92
-
93
- // Check that no trigger is returned when conditions don't match
94
- const noTrigger = contextValue!.getItemTrigger('item1', 'hover-on');
95
- expect(noTrigger).toBeNull();
96
- });
97
- });
@@ -1,65 +0,0 @@
1
- import { createContext, FC, PropsWithChildren, useState } from 'react';
2
- import { Interaction, InteractionTrigger } from '@cntrl-site/sdk';
3
-
4
- const defaultState = {
5
- interactionsStatesMap: {},
6
- interactions: [],
7
- transitionTo: () => {},
8
- getItemTrigger: () => null
9
- };
10
-
11
- export const InteractionsContext = createContext<{
12
- interactionsStatesMap: StatesMap,
13
- interactions: Interaction[],
14
- transitionTo: (interactionId: string, stateId: string) => void,
15
- getItemTrigger: (itemId: string, triggerType: TriggerType) => Trigger | null
16
- }>(defaultState);
17
-
18
- interface Props {
19
- interactions: Interaction[];
20
- }
21
-
22
- export const InteractionsProvider: FC<PropsWithChildren<Props>> = ({ interactions, children }) => {
23
- const defaultStatesMap = interactions.reduce<Record<string, string>>((map, { id, startStateId }) => {
24
- map[id] = startStateId;
25
- return map;
26
- }, {});
27
- const [interactionsStatesMap, setInteractionsStatesMap] = useState(defaultStatesMap);
28
- const transitionTo = (interactionId: string, stateId: string) => {
29
- setInteractionsStatesMap((map) => ({ ...map, [interactionId]: stateId }));
30
- };
31
- const getItemTrigger = (itemId: string, triggerType: TriggerType): Trigger | null => {
32
- for (const interaction of interactions) {
33
- const activeStateId = interactionsStatesMap[interaction.id];
34
- const matchingTrigger = interaction.triggers.find((trigger) =>
35
- trigger.itemId === itemId &&
36
- trigger.from === activeStateId &&
37
- trigger.type === triggerType
38
- );
39
- if (matchingTrigger) {
40
- return {
41
- id: interaction.id,
42
- from: matchingTrigger.from,
43
- to: matchingTrigger.to,
44
- };
45
- }
46
- }
47
- return null;
48
- };
49
- return (
50
- <InteractionsContext.Provider value={{
51
- transitionTo,
52
- interactionsStatesMap,
53
- interactions,
54
- getItemTrigger
55
- }}>
56
- {children}
57
- </InteractionsContext.Provider>
58
- );
59
- };
60
-
61
- type StatesMap = Record<InteractionId, StateId>;
62
- type Trigger = { id: InteractionId, from: StateId, to: StateId };
63
- type TriggerType = InteractionTrigger['type'];
64
- type InteractionId = string;
65
- type StateId = string;
@@ -1,24 +0,0 @@
1
- import { AnchorSide, ArticleItemType, ItemStatesMap } from '@cntrl-site/sdk';
2
- import { getStateStyles } from './StateStyles/StateStyles';
3
-
4
- type AllKeys<T> = T extends any ? keyof T : never;
5
- type StatePropertyKey = AllKeys<ItemStatesMap[keyof ItemStatesMap]>;
6
-
7
- export function getStatesCSS<T extends ArticleItemType>(
8
- itemId: string,
9
- classNamePrefix: string,
10
- keys: Array<StatePropertyKey>,
11
- states: Record<string, ItemStatesMap[T]> | undefined,
12
- anchorSide?: AnchorSide
13
- ) {
14
- return states
15
- ? Object.entries(states).map(([stateId, params]) => {
16
- return `
17
- .${classNamePrefix}-${itemId}-state-${stateId} {
18
- ${getStateStyles(keys, params, anchorSide)};
19
- }
20
- `;
21
- }).join('\n')
22
- : '';
23
- }
24
-