@wix/site-service-interactions 1.0.13 → 1.0.14

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 (69) hide show
  1. package/cjs/build/definition/index.js.map +1 -1
  2. package/cjs/build/implementations/InteractionsScriptElement.js.map +1 -1
  3. package/cjs/build/implementations/configEntries.js +4 -6
  4. package/cjs/build/implementations/configEntries.js.map +1 -1
  5. package/cjs/build/implementations/coreInteractions.js +1 -1
  6. package/cjs/build/implementations/coreInteractions.js.map +1 -1
  7. package/cjs/build/implementations/interactions.js +1 -1
  8. package/cjs/build/implementations/interactions.js.map +1 -1
  9. package/cjs/build/implementations/interactionsExternal.js +1 -1
  10. package/cjs/build/implementations/interactionsExternal.js.map +1 -1
  11. package/cjs/build/implementations/interactionsService.js.map +1 -1
  12. package/cjs/build/implementations/reviveScriptElement.js.map +1 -1
  13. package/cjs/build/implementations/v2/InteractionsScriptElement.js.map +1 -1
  14. package/cjs/build/implementations/v2/authoredStyles.js +6 -11
  15. package/cjs/build/implementations/v2/authoredStyles.js.map +1 -1
  16. package/cjs/build/implementations/v2/cdnUrls.js.map +1 -1
  17. package/cjs/build/implementations/v2/clickTriggerCss.js +1 -1
  18. package/cjs/build/implementations/v2/clickTriggerCss.js.map +1 -1
  19. package/cjs/build/implementations/v2/configCss.js.map +1 -1
  20. package/cjs/build/implementations/v2/configStyleHeadContent.js.map +1 -1
  21. package/cjs/build/implementations/v2/interactionsScriptContent.js +2 -2
  22. package/cjs/build/implementations/v2/interactionsScriptContent.js.map +1 -1
  23. package/cjs/build/implementations/v2/motionPresets.js +1 -1
  24. package/cjs/build/implementations/v2/motionPresets.js.map +1 -1
  25. package/cjs/package.json +1 -1
  26. package/definition/package.json +1 -1
  27. package/dist/definition/index.js.map +1 -1
  28. package/dist/implementations/InteractionsScriptElement.js.map +1 -1
  29. package/dist/implementations/configEntries.js +4 -6
  30. package/dist/implementations/configEntries.js.map +1 -1
  31. package/dist/implementations/coreInteractions.js +1 -1
  32. package/dist/implementations/coreInteractions.js.map +1 -1
  33. package/dist/implementations/interactions.js +1 -1
  34. package/dist/implementations/interactions.js.map +1 -1
  35. package/dist/implementations/interactionsExternal.js +1 -1
  36. package/dist/implementations/interactionsExternal.js.map +1 -1
  37. package/dist/implementations/interactionsService.js.map +1 -1
  38. package/dist/implementations/reviveScriptElement.js.map +1 -1
  39. package/dist/implementations/v2/InteractionsScriptElement.js.map +1 -1
  40. package/dist/implementations/v2/authoredStyles.js +6 -11
  41. package/dist/implementations/v2/authoredStyles.js.map +1 -1
  42. package/dist/implementations/v2/cdnUrls.js.map +1 -1
  43. package/dist/implementations/v2/clickTriggerCss.js +1 -1
  44. package/dist/implementations/v2/clickTriggerCss.js.map +1 -1
  45. package/dist/implementations/v2/configCss.js.map +1 -1
  46. package/dist/implementations/v2/configStyleHeadContent.js.map +1 -1
  47. package/dist/implementations/v2/interactionsScriptContent.js +2 -2
  48. package/dist/implementations/v2/interactionsScriptContent.js.map +1 -1
  49. package/dist/implementations/v2/motionPresets.js +1 -1
  50. package/dist/implementations/v2/motionPresets.js.map +1 -1
  51. package/implementations/package.json +1 -1
  52. package/package.json +22 -22
  53. package/src/definition/index.ts +11 -11
  54. package/src/implementations/InteractionsScriptElement.tsx +16 -16
  55. package/src/implementations/configEntries.ts +61 -63
  56. package/src/implementations/coreInteractions.ts +86 -86
  57. package/src/implementations/interactions.ts +8 -8
  58. package/src/implementations/interactionsExternal.ts +11 -11
  59. package/src/implementations/interactionsService.ts +8 -8
  60. package/src/implementations/reviveScriptElement.ts +8 -8
  61. package/src/implementations/v2/InteractionsScriptElement.tsx +21 -26
  62. package/src/implementations/v2/authoredStyles.ts +74 -79
  63. package/src/implementations/v2/cdnUrls.ts +1 -1
  64. package/src/implementations/v2/clickTriggerCss.ts +25 -25
  65. package/src/implementations/v2/configCss.ts +3 -3
  66. package/src/implementations/v2/configStyleHeadContent.ts +3 -3
  67. package/src/implementations/v2/interactionsScriptContent.ts +31 -31
  68. package/src/implementations/v2/motionPresets.ts +27 -27
  69. package/types/package.json +1 -1
@@ -19,117 +19,117 @@ import { getV2ConfigStyleHeadContent } from './v2/configStyleHeadContent'
19
19
  import { getV2ModulePreloadHeadContent } from './v2/interactionsScriptContent'
20
20
  import { getAuthoredStylesCss } from './v2/authoredStyles'
21
21
  import {
22
- getInteractConfigEntries,
23
- getInteractiveKeys,
24
- getResolvedConfigEntries,
25
- resolveInteractKeyConflicts,
22
+ getInteractConfigEntries,
23
+ getInteractiveKeys,
24
+ getResolvedConfigEntries,
25
+ resolveInteractKeyConflicts,
26
26
  } from './configEntries'
27
27
 
28
28
  /** An entry without interactions contributes CSS only; nothing has to load Interact for it. */
29
29
  const getRuntimeConfigs = (entries: InteractConfigEntry[]): InteractConfig[] =>
30
- entries.map(({ interact }) => interact).filter(({ interactions }) => interactions.length > 0)
30
+ entries.map(({ interact }) => interact).filter(({ interactions }) => interactions.length > 0)
31
31
 
32
32
  const initInteract = (entries: InteractConfigEntry[], isReducedMotion: boolean) => {
33
- // Bundled runtime is v1. v2 on the client is the CDN loader.
34
- Interact.forceReducedMotion = isReducedMotion
35
- Interact.setup({
36
- scrollOptionsGetter: () => globalThis.document.getElementById('site-root'),
37
- allowA11yTriggers: true,
38
- viewEnter: {
39
- useSafeViewEnter: true,
40
- },
41
- })
42
- for (const { interact } of entries) {
43
- Interact.create(interact as InteractV1Config)
44
- }
33
+ // Bundled runtime is v1. v2 on the client is the CDN loader.
34
+ Interact.forceReducedMotion = isReducedMotion
35
+ Interact.setup({
36
+ scrollOptionsGetter: () => globalThis.document.getElementById('site-root'),
37
+ allowA11yTriggers: true,
38
+ viewEnter: {
39
+ useSafeViewEnter: true,
40
+ },
41
+ })
42
+ for (const { interact } of entries) {
43
+ Interact.create(interact as InteractV1Config)
44
+ }
45
45
  }
46
46
 
47
47
  const getV2HeadContent = (entries: InteractConfigEntry[]): string => {
48
- const generatedCss = entries
49
- .map(({ interact }) => getV2ConfigCss(interact).trim())
50
- .filter(Boolean)
51
- .join('\n')
52
- const css = [getAuthoredStylesCss(entries).trim(), generatedCss].filter(Boolean).join('\n')
48
+ const generatedCss = entries
49
+ .map(({ interact }) => getV2ConfigCss(interact).trim())
50
+ .filter(Boolean)
51
+ .join('\n')
52
+ const css = [getAuthoredStylesCss(entries).trim(), generatedCss].filter(Boolean).join('\n')
53
53
 
54
- return (
55
- (getRuntimeConfigs(entries).length ? getV2ModulePreloadHeadContent() : '') +
56
- (css ? getV2ConfigStyleHeadContent(css) : '')
57
- )
54
+ return (
55
+ (getRuntimeConfigs(entries).length ? getV2ModulePreloadHeadContent() : '') +
56
+ (css ? getV2ConfigStyleHeadContent(css) : '')
57
+ )
58
58
  }
59
59
 
60
60
  const initRuntime = (
61
- entries: InteractConfigEntry[],
62
- isReducedMotion: boolean,
63
- getService: ServicesManager['getService'],
64
- useV2: boolean
61
+ entries: InteractConfigEntry[],
62
+ isReducedMotion: boolean,
63
+ getService: ServicesManager['getService'],
64
+ useV2: boolean
65
65
  ) => {
66
- const runtimeConfigs = getRuntimeConfigs(entries)
67
- if (!runtimeConfigs.length) {
68
- return
69
- }
66
+ const runtimeConfigs = getRuntimeConfigs(entries)
67
+ if (!runtimeConfigs.length) {
68
+ return
69
+ }
70
70
 
71
- const pageId = getService(PagesDefinition).currentPageId()
72
- if (!pageId) {
73
- return
74
- }
71
+ const pageId = getService(PagesDefinition).currentPageId()
72
+ if (!pageId) {
73
+ return
74
+ }
75
75
 
76
- const { addTopComponent } = getService(ProvideComponentServiceDefinition)
76
+ const { addTopComponent } = getService(ProvideComponentServiceDefinition)
77
77
 
78
- if (!useV2) {
79
- // v1 serializes a single config and has no path for authored-style CSS, so anything beyond
80
- // that would be silently dropped.
81
- if (entries.length > 1 || entries.some(({ styles }) => styles?.length)) {
82
- throw new Error('Multiple interactions config entries and authored styles require Interact v2.')
83
- }
84
- addTopComponent(createInteractionsScriptElement(runtimeConfigs[0], isReducedMotion, pageId))
85
- return
86
- }
78
+ if (!useV2) {
79
+ // v1 serializes a single config and has no path for authored-style CSS, so anything beyond
80
+ // that would be silently dropped.
81
+ if (entries.length > 1 || entries.some(({ styles }) => styles?.length)) {
82
+ throw new Error('Multiple interactions config entries and authored styles require Interact v2.')
83
+ }
84
+ addTopComponent(createInteractionsScriptElement(runtimeConfigs[0], isReducedMotion, pageId))
85
+ return
86
+ }
87
87
 
88
- addTopComponent(createV2InteractionsScriptElement(runtimeConfigs, isReducedMotion, pageId))
88
+ addTopComponent(createV2InteractionsScriptElement(runtimeConfigs, isReducedMotion, pageId))
89
89
  }
90
90
 
91
91
  const getInteractiveComps = (entries: InteractConfigEntry[]): Set<string> => {
92
- const keys = new Set<string>()
93
- for (const entry of entries) {
94
- getInteractiveKeys(entry).forEach(key => keys.add(key))
95
- }
96
- return keys
92
+ const keys = new Set<string>()
93
+ for (const entry of entries) {
94
+ getInteractiveKeys(entry).forEach((key) => keys.add(key))
95
+ }
96
+ return keys
97
97
  }
98
98
 
99
99
  export const coreInteractions = (config: IInteractionsServiceConfig, getService: ServicesManager['getService']) => {
100
- const { reducedMotion: isReducedMotion } = getService(DeviceInfoDefinition)
101
- const { isOpen } = getService(ExperimentsDefinition)
102
- const useV2 = isOpen('specs.thunderbolt.vsm_interactions_v2')
103
- // The v1 runtime has no preset registration and doesn't understand LEGACY_* names; skip
104
- // aliasing on those paths so named reaction effects remain resolvable.
105
- const entries = resolveInteractKeyConflicts((useV2 ? getResolvedConfigEntries : getInteractConfigEntries)(config))
100
+ const { reducedMotion: isReducedMotion } = getService(DeviceInfoDefinition)
101
+ const { isOpen } = getService(ExperimentsDefinition)
102
+ const useV2 = isOpen('specs.thunderbolt.vsm_interactions_v2')
103
+ // The v1 runtime has no preset registration and doesn't understand LEGACY_* names; skip
104
+ // aliasing on those paths so named reaction effects remain resolvable.
105
+ const entries = resolveInteractKeyConflicts((useV2 ? getResolvedConfigEntries : getInteractConfigEntries)(config))
106
106
 
107
- if (useV2) {
108
- // Both belong in the head: the preload links only help while the document is still parsing,
109
- // and the generated CSS hides elements before their entrance effect, so it has to apply
110
- // before the body renders.
111
- if (!process.env.browser) {
112
- const headContent = getV2HeadContent(entries)
113
- // GENERAL rather than setHead's AFTER_SECURITY default: thunderbolt only reads the
114
- // after-security bucket on its SEO path, so the default drops this on every normal
115
- // request. GENERAL reaches the document as raw markup before `</head>`.
116
- if (headContent) {
117
- getService(HeadAppenderDefinition).setHead(headContent, HeadContentType.GENERAL)
118
- }
119
- }
107
+ if (useV2) {
108
+ // Both belong in the head: the preload links only help while the document is still parsing,
109
+ // and the generated CSS hides elements before their entrance effect, so it has to apply
110
+ // before the body renders.
111
+ if (!process.env.browser) {
112
+ const headContent = getV2HeadContent(entries)
113
+ // GENERAL rather than setHead's AFTER_SECURITY default: thunderbolt only reads the
114
+ // after-security bucket on its SEO path, so the default drops this on every normal
115
+ // request. GENERAL reaches the document as raw markup before `</head>`.
116
+ if (headContent) {
117
+ getService(HeadAppenderDefinition).setHead(headContent, HeadContentType.GENERAL)
118
+ }
119
+ }
120
120
 
121
- initRuntime(entries, isReducedMotion, getService, true)
122
- } else if (isOpen('specs.thunderbolt.interactionsInSsr')) {
123
- // Emits the config and loader scripts. Works in both environments: SSR serves markup the
124
- // parser executes, and on the client the loader's ref revives it into a script that runs —
125
- // which is what pages rendered only on the client (password-protected / members-only,
126
- // client-side navigation) need, since they never get a server-rendered document.
127
- initRuntime(entries, isReducedMotion, getService, false)
128
- } else {
129
- initInteract(entries, isReducedMotion)
130
- }
121
+ initRuntime(entries, isReducedMotion, getService, true)
122
+ } else if (isOpen('specs.thunderbolt.interactionsInSsr')) {
123
+ // Emits the config and loader scripts. Works in both environments: SSR serves markup the
124
+ // parser executes, and on the client the loader's ref revives it into a script that runs —
125
+ // which is what pages rendered only on the client (password-protected / members-only,
126
+ // client-side navigation) need, since they never get a server-rendered document.
127
+ initRuntime(entries, isReducedMotion, getService, false)
128
+ } else {
129
+ initInteract(entries, isReducedMotion)
130
+ }
131
131
 
132
- return {
133
- interactiveComps: getInteractiveComps(entries),
134
- }
132
+ return {
133
+ interactiveComps: getInteractiveComps(entries),
134
+ }
135
135
  }
@@ -3,16 +3,16 @@ import type { IInteractionsService, IInteractionsServiceConfig } from '../defini
3
3
  import { coreInteractions } from './coreInteractions'
4
4
 
5
5
  export const createInteractions = (
6
- config: IInteractionsServiceConfig,
7
- getService: ServicesManager['getService']
6
+ config: IInteractionsServiceConfig,
7
+ getService: ServicesManager['getService']
8
8
  ): IInteractionsService => {
9
- const { interactiveComps } = coreInteractions(config, getService)
9
+ const { interactiveComps } = coreInteractions(config, getService)
10
10
 
11
- const getConfigPath = (path: string) => path.replace(/\[[^\]]+]/g, '[]')
11
+ const getConfigPath = (path: string) => path.replace(/\[[^\]]+]/g, '[]')
12
12
 
13
- const hasInteractions: IInteractionsService['hasInteractions'] = path => interactiveComps.has(getConfigPath(path))
13
+ const hasInteractions: IInteractionsService['hasInteractions'] = (path) => interactiveComps.has(getConfigPath(path))
14
14
 
15
- return {
16
- hasInteractions,
17
- }
15
+ return {
16
+ hasInteractions,
17
+ }
18
18
  }
@@ -5,21 +5,21 @@ import { coreInteractions } from './coreInteractions'
5
5
  import { hasClickTriggerCss, wixInteractElementCss } from './stylesToAdd'
6
6
 
7
7
  export const createInteractionsExternal = (
8
- config: IInteractionsServiceConfig,
9
- getService: ServicesManager['getService']
8
+ config: IInteractionsServiceConfig,
9
+ getService: ServicesManager['getService']
10
10
  ): IInteractionsService => {
11
- const provideCssService = getService(ProvideCssDefinition)
11
+ const provideCssService = getService(ProvideCssDefinition)
12
12
 
13
- const styles = [wixInteractElementCss, hasClickTriggerCss]
14
- const cssToAdd = styles.join('\n')
13
+ const styles = [wixInteractElementCss, hasClickTriggerCss]
14
+ const cssToAdd = styles.join('\n')
15
15
 
16
- provideCssService.addStyle(cssToAdd)
16
+ provideCssService.addStyle(cssToAdd)
17
17
 
18
- const { interactiveComps } = coreInteractions(config, getService)
18
+ const { interactiveComps } = coreInteractions(config, getService)
19
19
 
20
- const hasInteractions: IInteractionsService['hasInteractions'] = path => interactiveComps.has(path)
20
+ const hasInteractions: IInteractionsService['hasInteractions'] = (path) => interactiveComps.has(path)
21
21
 
22
- return {
23
- hasInteractions,
24
- }
22
+ return {
23
+ hasInteractions,
24
+ }
25
25
  }
@@ -6,15 +6,15 @@ import { createInteractions } from './interactions'
6
6
  import { createInteractionsExternal } from './interactionsExternal'
7
7
 
8
8
  export const InteractionsService = implementStaticService(
9
- InteractionsDefinition,
10
- ({ config, getService }: StaticServiceFactoryOpts<IInteractionsServiceConfig>) => {
11
- return createInteractions(config, getService)
12
- }
9
+ InteractionsDefinition,
10
+ ({ config, getService }: StaticServiceFactoryOpts<IInteractionsServiceConfig>) => {
11
+ return createInteractions(config, getService)
12
+ }
13
13
  )
14
14
 
15
15
  export const InteractionsServiceExternal = implementStaticService(
16
- InteractionsDefinition,
17
- ({ config, getService }: StaticServiceFactoryOpts<IInteractionsServiceConfig>) => {
18
- return createInteractionsExternal(config, getService)
19
- }
16
+ InteractionsDefinition,
17
+ ({ config, getService }: StaticServiceFactoryOpts<IInteractionsServiceConfig>) => {
18
+ return createInteractionsExternal(config, getService)
19
+ }
20
20
  )
@@ -16,14 +16,14 @@
16
16
  * connected, and `connect()` returns early for them, so only the first instance serves a key.
17
17
  */
18
18
  export const reviveScriptElement = (rendered: HTMLScriptElement | null) => {
19
- if (!rendered?.isConnected) {
20
- return
21
- }
19
+ if (!rendered?.isConnected) {
20
+ return
21
+ }
22
22
 
23
- const executable = globalThis.document.createElement('script')
24
- executable.type = rendered.type
25
- executable.id = rendered.id
26
- executable.textContent = rendered.textContent
23
+ const executable = globalThis.document.createElement('script')
24
+ executable.type = rendered.type
25
+ executable.id = rendered.id
26
+ executable.textContent = rendered.textContent
27
27
 
28
- rendered.replaceWith(executable)
28
+ rendered.replaceWith(executable)
29
29
  }
@@ -11,32 +11,27 @@ const DANGEROUSLY_SET_INNER_HTML = ['dangerously', 'Set', 'Inner', 'HTML']
11
11
  * element early. `\u003c` is valid JSON that `JSON.parse` reads back as `<`.
12
12
  */
13
13
  const serializeConfigForScriptElement = (config: InteractConfig | InteractConfig[]): string =>
14
- JSON.stringify(config).replace(/</g, '\\u003c')
14
+ JSON.stringify(config).replace(/</g, '\\u003c')
15
15
 
16
16
  export const createV2InteractionsScriptElement =
17
- (config: InteractConfig | InteractConfig[], isReducedMotion: boolean, pageId: string): FunctionComponent =>
18
- () => {
19
- // This ID is also interpolated into raw module-script text. Percent-encoding removes
20
- // script delimiters and template-literal syntax while keeping the ID deterministic.
21
- const safePageId = encodeURIComponent(pageId)
22
- const configId = `interactions-config-${safePageId}`
23
- const interactionsScriptContent = getV2InteractionsScriptContent(configId, isReducedMotion)
24
- const configProps = {
25
- [DANGEROUSLY_SET_INNER_HTML.join('')]: { __html: serializeConfigForScriptElement(config) },
26
- }
27
- const loaderProps = {
28
- [DANGEROUSLY_SET_INNER_HTML.join('')]: { __html: interactionsScriptContent },
29
- }
17
+ (config: InteractConfig | InteractConfig[], isReducedMotion: boolean, pageId: string): FunctionComponent =>
18
+ () => {
19
+ // This ID is also interpolated into raw module-script text. Percent-encoding removes
20
+ // script delimiters and template-literal syntax while keeping the ID deterministic.
21
+ const safePageId = encodeURIComponent(pageId)
22
+ const configId = `interactions-config-${safePageId}`
23
+ const interactionsScriptContent = getV2InteractionsScriptContent(configId, isReducedMotion)
24
+ const configProps = {
25
+ [DANGEROUSLY_SET_INNER_HTML.join('')]: { __html: serializeConfigForScriptElement(config) },
26
+ }
27
+ const loaderProps = {
28
+ [DANGEROUSLY_SET_INNER_HTML.join('')]: { __html: interactionsScriptContent },
29
+ }
30
30
 
31
- return (
32
- <>
33
- <script type="application/json" id={configId} {...configProps} />
34
- <script
35
- type="module"
36
- id={`interactions-loader-${safePageId}`}
37
- ref={reviveScriptElement}
38
- {...loaderProps}
39
- />
40
- </>
41
- )
42
- }
31
+ return (
32
+ <>
33
+ <script type="application/json" id={configId} {...configProps} />
34
+ <script type="module" id={`interactions-loader-${safePageId}`} ref={reviveScriptElement} {...loaderProps} />
35
+ </>
36
+ )
37
+ }
@@ -3,106 +3,101 @@ import type { InteractConfigEntry, InteractStyleRule } from '../../definition'
3
3
  const SELECTOR_TOKEN = /"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|[()[\]]|,/g
4
4
 
5
5
  const escapeCssString = (value: string): string =>
6
- value
7
- .replace(/\\/g, '\\\\')
8
- .replace(/"/g, '\\"')
9
- .replace(/\n/g, '\\a ')
10
- .replace(/\r/g, '\\d ')
11
- .replace(/\f/g, '\\c ')
6
+ value.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\a ').replace(/\r/g, '\\d ').replace(/\f/g, '\\c ')
12
7
 
13
8
  const splitSelectorList = (selector: string): string[] => {
14
- const parts: string[] = []
15
- let depth = 0
16
- let start = 0
9
+ const parts: string[] = []
10
+ let depth = 0
11
+ let start = 0
17
12
 
18
- SELECTOR_TOKEN.lastIndex = 0
19
- for (let match = SELECTOR_TOKEN.exec(selector); match; match = SELECTOR_TOKEN.exec(selector)) {
20
- const token = match[0]
21
- if (token === '(' || token === '[') {
22
- depth++
23
- } else if (token === ')' || token === ']') {
24
- depth--
25
- } else if (token === ',' && depth === 0) {
26
- parts.push(selector.slice(start, match.index))
27
- start = match.index + 1
28
- }
29
- }
13
+ SELECTOR_TOKEN.lastIndex = 0
14
+ for (let match = SELECTOR_TOKEN.exec(selector); match; match = SELECTOR_TOKEN.exec(selector)) {
15
+ const token = match[0]
16
+ if (token === '(' || token === '[') {
17
+ depth++
18
+ } else if (token === ')' || token === ']') {
19
+ depth--
20
+ } else if (token === ',' && depth === 0) {
21
+ parts.push(selector.slice(start, match.index))
22
+ start = match.index + 1
23
+ }
24
+ }
30
25
 
31
- parts.push(selector.slice(start))
32
- return parts.map(part => part.trim()).filter(Boolean)
26
+ parts.push(selector.slice(start))
27
+ return parts.map((part) => part.trim()).filter(Boolean)
33
28
  }
34
29
 
35
30
  const indentCssBlock = (css: string): string =>
36
- css
37
- .split('\n')
38
- .map(line => (line ? ` ${line}` : line))
39
- .join('\n')
31
+ css
32
+ .split('\n')
33
+ .map((line) => (line ? ` ${line}` : line))
34
+ .join('\n')
40
35
 
41
36
  const renderProperties = (properties: Record<string, string>): string =>
42
- Object.entries(properties)
43
- .map(([property, value]) => ` ${property}: ${value};`)
44
- .join('\n')
37
+ Object.entries(properties)
38
+ .map(([property, value]) => ` ${property}: ${value};`)
39
+ .join('\n')
45
40
 
46
41
  const wrapWithConditions = (block: string, rule: InteractStyleRule): string => {
47
- let result = block
48
- if (rule['@container']) {
49
- result = `@container ${rule['@container']} {\n${indentCssBlock(result)}\n}`
50
- }
51
- if (rule['@media']) {
52
- result = `@media ${rule['@media']} {\n${indentCssBlock(result)}\n}`
53
- }
54
- if (rule['@supports']) {
55
- result = `@supports ${rule['@supports']} {\n${indentCssBlock(result)}\n}`
56
- }
57
- return result
42
+ let result = block
43
+ if (rule['@container']) {
44
+ result = `@container ${rule['@container']} {\n${indentCssBlock(result)}\n}`
45
+ }
46
+ if (rule['@media']) {
47
+ result = `@media ${rule['@media']} {\n${indentCssBlock(result)}\n}`
48
+ }
49
+ if (rule['@supports']) {
50
+ result = `@supports ${rule['@supports']} {\n${indentCssBlock(result)}\n}`
51
+ }
52
+ return result
58
53
  }
59
54
 
60
55
  const buildRuleSelector = (namespace: string, rule: InteractStyleRule): string => {
61
- const scopeWrapper = `[data-interact-key="${escapeCssString(namespace)}"]`
62
- const scopeRoot = `${scopeWrapper} > :first-child`
56
+ const scopeWrapper = `[data-interact-key="${escapeCssString(namespace)}"]`
57
+ const scopeRoot = `${scopeWrapper} > :first-child`
63
58
 
64
- if (!rule.key) {
65
- if (!rule.selector) {
66
- return scopeRoot
67
- }
68
- return splitSelectorList(rule.selector)
69
- .map(selector => `${scopeRoot} ${selector}`)
70
- .join(', ')
71
- }
59
+ if (!rule.key) {
60
+ if (!rule.selector) {
61
+ return scopeRoot
62
+ }
63
+ return splitSelectorList(rule.selector)
64
+ .map((selector) => `${scopeRoot} ${selector}`)
65
+ .join(', ')
66
+ }
72
67
 
73
- const escapedKey = escapeCssString(rule.key)
74
- const keyWrapper = rule.key === namespace ? scopeWrapper : `${scopeWrapper} [data-interact-key="${escapedKey}"]`
75
- const keyRoot = `${keyWrapper} > :first-child`
76
- if (!rule.selector) {
77
- return keyRoot
78
- }
68
+ const escapedKey = escapeCssString(rule.key)
69
+ const keyWrapper = rule.key === namespace ? scopeWrapper : `${scopeWrapper} [data-interact-key="${escapedKey}"]`
70
+ const keyRoot = `${keyWrapper} > :first-child`
71
+ if (!rule.selector) {
72
+ return keyRoot
73
+ }
79
74
 
80
- const separator = /^\s/.test(rule.selector) ? ' ' : ''
81
- return splitSelectorList(rule.selector)
82
- .map(selector => `${keyRoot}${separator}${selector}`)
83
- .join(', ')
75
+ const separator = /^\s/.test(rule.selector) ? ' ' : ''
76
+ return splitSelectorList(rule.selector)
77
+ .map((selector) => `${keyRoot}${separator}${selector}`)
78
+ .join(', ')
84
79
  }
85
80
 
86
81
  const getEntryStylesCss = ({ namespace, styles = [] }: InteractConfigEntry): string => {
87
- if (!styles.length) {
88
- return ''
89
- }
90
- if (!namespace) {
91
- throw new Error('Interactions config entries with authored styles must define a namespace.')
92
- }
82
+ if (!styles.length) {
83
+ return ''
84
+ }
85
+ if (!namespace) {
86
+ throw new Error('Interactions config entries with authored styles must define a namespace.')
87
+ }
93
88
 
94
- return styles
95
- .map(rule => {
96
- const properties = renderProperties(rule.properties)
97
- if (!properties) {
98
- return ''
99
- }
100
- const block = `${buildRuleSelector(namespace, rule)} {\n${properties}\n}`
101
- return wrapWithConditions(block, rule)
102
- })
103
- .filter(Boolean)
104
- .join('\n\n')
89
+ return styles
90
+ .map((rule) => {
91
+ const properties = renderProperties(rule.properties)
92
+ if (!properties) {
93
+ return ''
94
+ }
95
+ const block = `${buildRuleSelector(namespace, rule)} {\n${properties}\n}`
96
+ return wrapWithConditions(block, rule)
97
+ })
98
+ .filter(Boolean)
99
+ .join('\n\n')
105
100
  }
106
101
 
107
102
  export const getAuthoredStylesCss = (entries: InteractConfigEntry[]): string =>
108
- entries.map(getEntryStylesCss).filter(Boolean).join('\n\n')
103
+ entries.map(getEntryStylesCss).filter(Boolean).join('\n\n')
@@ -3,4 +3,4 @@ export const INTERACT_V2_IMPORT_URL = 'https://cdn.jsdelivr.net/npm/@wix/interac
3
3
  export const LEGACY_WIX_MOTION_PRESETS_IMPORT_URL = 'https://cdn.jsdelivr.net/npm/@wix/wix-motion-presets@1.2.0/+esm'
4
4
 
5
5
  export const MOTION_PRESETS_IMPORT_URL =
6
- 'https://cdn.jsdelivr.net/npm/@wix/motion-presets@1.0.7/dist/browser/motion-presets.min.js'
6
+ 'https://cdn.jsdelivr.net/npm/@wix/motion-presets@1.0.7/dist/browser/motion-presets.min.js'
@@ -7,38 +7,38 @@ const escapeCssAttr = (value: string): string => value.replace(/\\/g, '\\\\').re
7
7
  * plus the `[data-interact-key="…"]` prefix from `CSSRuleToString`.
8
8
  */
9
9
  const getInteractionSourceSelector = (
10
- interaction: Pick<Interaction, 'key' | 'selector' | 'listContainer' | 'listItemSelector'>
10
+ interaction: Pick<Interaction, 'key' | 'selector' | 'listContainer' | 'listItemSelector'>
11
11
  ): string => {
12
- const { key, selector, listContainer, listItemSelector } = interaction
13
- const attrSelector = `[data-interact-key="${escapeCssAttr(key)}"]`
12
+ const { key, selector, listContainer, listItemSelector } = interaction
13
+ const attrSelector = `[data-interact-key="${escapeCssAttr(key)}"]`
14
14
 
15
- if (listContainer) {
16
- const itemFilter = listItemSelector ? ` > ${listItemSelector}` : ''
17
- const inner = selector ? `${listContainer}${itemFilter} ${selector}` : `${listContainer}${itemFilter || ' > *'}`
15
+ if (listContainer) {
16
+ const itemFilter = listItemSelector ? ` > ${listItemSelector}` : ''
17
+ const inner = selector ? `${listContainer}${itemFilter} ${selector}` : `${listContainer}${itemFilter || ' > *'}`
18
18
 
19
- return `${attrSelector} ${inner}`
20
- }
19
+ return `${attrSelector} ${inner}`
20
+ }
21
21
 
22
- if (selector) {
23
- return `${attrSelector} ${selector}`
24
- }
22
+ if (selector) {
23
+ return `${attrSelector} ${selector}`
24
+ }
25
25
 
26
- return `${attrSelector} > :first-child`
26
+ return `${attrSelector} > :first-child`
27
27
  }
28
28
 
29
29
  /** Emits `cursor: pointer` for click interaction triggers (`'activate' || 'click'`), one rule per unique source selector. */
30
30
  export const getClickTriggerCss = (config: InteractConfig): string => {
31
- const selectors = [
32
- ...new Set(
33
- config.interactions
34
- .filter(({ trigger }) => trigger === 'activate' || trigger === 'click')
35
- .map(getInteractionSourceSelector)
36
- ),
37
- ]
38
-
39
- if (!selectors.length) {
40
- return ''
41
- }
42
-
43
- return selectors.map(selector => `${selector} {\ncursor: pointer;\n}`).join('\n')
31
+ const selectors = [
32
+ ...new Set(
33
+ config.interactions
34
+ .filter(({ trigger }) => trigger === 'activate' || trigger === 'click')
35
+ .map(getInteractionSourceSelector)
36
+ ),
37
+ ]
38
+
39
+ if (!selectors.length) {
40
+ return ''
41
+ }
42
+
43
+ return selectors.map((selector) => `${selector} {\ncursor: pointer;\n}`).join('\n')
44
44
  }
@@ -11,8 +11,8 @@ Interact.registerEffects(motionPresets as unknown as PresetRegistry)
11
11
 
12
12
  /** Emit animation FOUC CSS and click-trigger cursor rules. */
13
13
  export const getV2ConfigCss = (config: InteractConfig): string => {
14
- const animationCss = generate(config, true).trim()
15
- const clickCss = getClickTriggerCss(config).trim()
14
+ const animationCss = generate(config, true).trim()
15
+ const clickCss = getClickTriggerCss(config).trim()
16
16
 
17
- return [animationCss, clickCss].filter(Boolean).join('\n')
17
+ return [animationCss, clickCss].filter(Boolean).join('\n')
18
18
  }