@sitecore-feaas/clientside 0.1.51 → 0.1.53

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.
@@ -3,6 +3,7 @@ import ReactDOM from 'react-dom'
3
3
  import { FEAASBase } from '../components/FEAASBase.js'
4
4
  import { ReactJSX, ReactModules } from '../components/FEAASElement.js'
5
5
  import { kebabCase, reverseKebabCase } from '../utils/string.js'
6
+ import { Component, FEAASComponentProps } from './react.js'
6
7
 
7
8
  const convertSchemaPropertiesToKebabCase = (schema: any) => {
8
9
  if (!schema) return
@@ -19,12 +20,38 @@ const convertSchemaPropertiesToKebabCase = (schema: any) => {
19
20
  return { ...schema, properties: kebabSchemaProperties, required: kebabRequiredProperties }
20
21
  }
21
22
 
23
+ // TODO: parse object, number, array, boolean etc props
24
+
25
+ export const parseProps = (propName: string, propValue: string, properties: any) => {
26
+ switch (properties?.[propName]?.type) {
27
+ case 'string':
28
+ return propValue
29
+ case 'object':
30
+ return JSON.parse(propValue)
31
+ case 'array':
32
+ return JSON.parse(propValue)
33
+ case 'number':
34
+ return +propValue
35
+ case 'integer':
36
+ return +propValue
37
+ case 'boolean':
38
+ return propValue === 'true'
39
+ default:
40
+ return propValue
41
+ }
42
+ }
43
+
22
44
  export function FEAASExternalProps(element: FEAASBase = this) {
23
45
  const attributes = element.getAttributeNames()
46
+ const id = element.getAttribute('data-external-id')
47
+ const schema: any = FEAASExternal.registered[id]?.schema
24
48
  const props = attributes.reduce((prev, curr) => {
25
- if (!curr.startsWith('data-attribute') && !['class', 'id', 'contenteditable'].includes(curr))
26
- return { ...prev, [reverseKebabCase(curr)]: element.getAttribute(curr) }
27
- else return prev
49
+ if (!curr.startsWith('data-attribute') && !['class', 'id', 'contenteditable'].includes(curr)) {
50
+ const value = element.getAttribute(curr)
51
+ return { ...prev, [reverseKebabCase(curr)]: parseProps(curr, value, schema?.properties) }
52
+ } else {
53
+ return prev
54
+ }
28
55
  }, {})
29
56
  return props
30
57
  }
@@ -62,22 +89,23 @@ export default class FEAASExternal extends FEAASBase<FEAASExternalProps, ReactMo
62
89
  const components = Object.keys(FEAASExternal.registered).map((name) => ({
63
90
  ...FEAASExternal.registered[name],
64
91
  name,
65
- schema: convertSchemaPropertiesToKebabCase(FEAASExternal.registered[name].schema),
66
- component: FEAASExternal.registered[name].component.toString()
92
+ schema: convertSchemaPropertiesToKebabCase(FEAASExternal.registered[name].schema)
93
+ //component: FEAASExternal.registered[name].component.toString()
67
94
  }))
95
+
68
96
  // send components from iframe to parent window
69
97
  window?.parent?.postMessage(
70
98
  JSON.stringify({
71
99
  action: 'register-components',
72
100
  data: components
73
101
  }),
74
- window?.parent?.origin
102
+ '*'
75
103
  )
76
104
  }, 500)
77
105
  }
78
106
  }
79
107
 
80
- static loadComponents() {
108
+ /*static loadComponents() {
81
109
  const components = JSON.parse(sessionStorage.getItem('feaas-external-components'))
82
110
  components.forEach((c: { name: string; schema: any; component: React.FC }) => {
83
111
  const name = c.name
@@ -85,6 +113,12 @@ export default class FEAASExternal extends FEAASBase<FEAASExternalProps, ReactMo
85
113
  const component = eval('(' + c.component + ')')
86
114
  FEAASExternal.registerComponent(component, schema, name)
87
115
  })
116
+ }*/
117
+
118
+ static Preview(props: Partial<FEAASComponentProps<any>> & { src: string }) {
119
+ const src =
120
+ props?.src || (typeof window !== 'undefined' ? window.location.search.match(/feaasSrc=([^&]+)/)?.[1] : null)
121
+ return src ? <Component src={src} {...props} /> : null
88
122
  }
89
123
  }
90
124
 
package/src/ui/react.tsx CHANGED
@@ -6,7 +6,7 @@ export { renderHTMLContent }
6
6
  export { External } from './FEAASExternal.js'
7
7
 
8
8
  export function FEAASEmbed({ data, ...props }: FEAASComponentProps<any>) {
9
- if ('template' in props && typeof props.template == 'string') {
9
+ if ('template' in props && props.template) {
10
10
  var html = renderHTMLContent(props.template, data || {})
11
11
  }
12
12
  if ('src' in props) {
@@ -6,136 +6,76 @@ import { Component } from '../src/ui/react.js'
6
6
  import ReactDOM from 'react-dom'
7
7
  import React from 'react'
8
8
 
9
+ async function test(react: any, html: string) {
10
+ const div = document.createElement('div')
11
+ document.body.appendChild(div)
12
+ const root = ReactDOM.render(react, div)
13
+ expect(div.innerHTML).toEqual(html)
14
+
15
+ const div2 = document.createElement('div')
16
+ document.body.appendChild(div2)
17
+ div2.innerHTML = html
18
+
19
+ var onHydrate
20
+ const promise = new Promise((r) => {
21
+ onHydrate = r
22
+ })
23
+ ReactDOM.hydrate(react, div2, onHydrate)
24
+ await promise
25
+ expect(div2.innerHTML).toEqual(html)
26
+ }
27
+
9
28
  describe('React', () => {
10
- it('render react component', () => {
11
- const div = document.createElement('div')
12
- document.body.appendChild(div)
13
- const root = ReactDOM.render(
29
+ it('render react component', async () => {
30
+ await test(
14
31
  <section>
15
32
  <Component src='library/test'></Component>
16
33
  </section>,
17
- div
18
- )
19
- expect(div.innerHTML).toEqual(
20
34
  '<section><feaas-component library="library" component="test" src="library/test"></feaas-component></section>'
21
35
  )
22
- const div2 = document.createElement('div')
23
- document.body.appendChild(div2)
24
- div2.innerHTML = div.innerHTML
25
- ReactDOM.hydrate(
36
+ })
37
+ it('render react with empty template', async () => {
38
+ await test(
26
39
  <section>
27
- <Component src='library/test'></Component>
40
+ <Component src='library/test' template=''></Component>
28
41
  </section>,
29
- div2
30
- )
31
- expect(div2.innerHTML).toEqual(
32
42
  '<section><feaas-component library="library" component="test" src="library/test"></feaas-component></section>'
33
43
  )
34
44
  })
35
- it('render react component with src and overrides', () => {
36
- const div = document.createElement('div')
37
- document.body.appendChild(div)
38
- const root = ReactDOM.render(
45
+ it('render react component with src and overrides', async () => {
46
+ await test(
39
47
  <section>
40
48
  <Component src='library/test' component='test2'></Component>
41
49
  </section>,
42
- div
43
- )
44
- expect(div.innerHTML).toEqual(
45
- '<section><feaas-component library="library" component="test2" src="library/test"></feaas-component></section>'
46
- )
47
- const div2 = document.createElement('div')
48
- document.body.appendChild(div2)
49
- div2.innerHTML = div.innerHTML
50
- ReactDOM.hydrate(
51
- <section>
52
- <Component src='library/test' component='test2'></Component>
53
- </section>,
54
- div2
55
- )
56
- expect(div2.innerHTML).toEqual(
57
50
  '<section><feaas-component library="library" component="test2" src="library/test"></feaas-component></section>'
58
51
  )
59
52
  })
60
- it('render react component with extras', () => {
61
- const div = document.createElement('div')
62
- document.body.appendChild(div)
63
- const root = ReactDOM.render(
53
+ it('render react component with extras', async () => {
54
+ await test(
64
55
  <section>
65
56
  <Component src='library/test' version='v1'></Component>
66
57
  </section>,
67
- div
68
- )
69
- expect(div.innerHTML).toEqual(
70
- '<section><feaas-component library="library" component="test" version="v1" src="library/test"></feaas-component></section>'
71
- )
72
- const div2 = document.createElement('div')
73
- document.body.appendChild(div2)
74
- div2.innerHTML = div.innerHTML
75
- ReactDOM.hydrate(
76
- <section>
77
- <Component src='library/test' version='v1'></Component>
78
- </section>,
79
- div2
80
- )
81
- expect(div2.innerHTML).toEqual(
82
58
  '<section><feaas-component library="library" component="test" version="v1" src="library/test"></feaas-component></section>'
83
59
  )
84
60
  })
85
- it('render react template', () => {
86
- const div = document.createElement('div')
87
- document.body.appendChild(div)
88
- const root = ReactDOM.render(
61
+ it('render react template', async () => {
62
+ await test(
89
63
  <section>
90
64
  <Component src='library/test' template={'<div data-path-src="abc">'}></Component>
91
65
  </section>,
92
- div
93
- )
94
- expect(div.innerHTML).toEqual(
95
- '<section><feaas-component library="library" component="test" src="library/test"><div data-path-src="abc"></div></feaas-component></section>'
96
- )
97
- const div2 = document.createElement('div')
98
- document.body.appendChild(div2)
99
- div2.innerHTML = div.innerHTML
100
- ReactDOM.hydrate(
101
- <section>
102
- <Component src='library/test' template={'<div data-path-src="abc">'}></Component>
103
- </section>,
104
- div2
105
- )
106
- expect(div2.innerHTML).toEqual(
107
66
  '<section><feaas-component library="library" component="test" src="library/test"><div data-path-src="abc"></div></feaas-component></section>'
108
67
  )
109
68
  })
110
- it('render template with data and src', () => {
111
- const div = document.createElement('div')
112
- document.body.appendChild(div)
113
- const root = ReactDOM.render(
114
- <section>
115
- <Component src='library/test' template={'<div data-path-src="abc">'} data={{ abc: 321 }}></Component>
116
- </section>,
117
- div
118
- )
119
- expect(div.innerHTML).toEqual(
120
- '<section><feaas-component library="library" component="test" src="library/test" data="{&quot;abc&quot;:321}"><div data-path-src="abc"></div></feaas-component></section>'
121
- )
122
- const div2 = document.createElement('div')
123
- document.body.appendChild(div2)
124
- div2.innerHTML = div.innerHTML
125
- ReactDOM.hydrate(
69
+ it('render template with data and src', async () => {
70
+ await test(
126
71
  <section>
127
72
  <Component src='library/test' template={'<div data-path-src="abc">'} data={{ abc: 321 }}></Component>
128
73
  </section>,
129
- div2
130
- )
131
- expect(div2.innerHTML).toEqual(
132
74
  '<section><feaas-component library="library" component="test" src="library/test" data="{&quot;abc&quot;:321}"><div data-path-src="abc"></div></feaas-component></section>'
133
75
  )
134
76
  })
135
- it('render template with data but without src', () => {
136
- const div = document.createElement('div')
137
- document.body.appendChild(div)
138
- const root = ReactDOM.render(
77
+ it('render template with data but without src', async () => {
78
+ test(
139
79
  <section>
140
80
  <Component
141
81
  library='library'
@@ -144,76 +84,22 @@ describe('React', () => {
144
84
  data={{ abc: 321 }}
145
85
  ></Component>
146
86
  </section>,
147
- div
148
- )
149
- expect(div.innerHTML).toEqual(
150
- '<section><feaas-component library="library" component="test" data="{&quot;abc&quot;:321}"><div data-path-src="abc"></div></feaas-component></section>'
151
- )
152
- const div2 = document.createElement('div')
153
- document.body.appendChild(div2)
154
- div2.innerHTML = div.innerHTML
155
- ReactDOM.hydrate(
156
- <section>
157
- <Component
158
- library='library'
159
- component='test'
160
- template={'<div data-path-src="abc">'}
161
- data={{ abc: 321 }}
162
- ></Component>
163
- </section>,
164
- div2
165
- )
166
- expect(div2.innerHTML).toEqual(
167
87
  '<section><feaas-component library="library" component="test" data="{&quot;abc&quot;:321}"><div data-path-src="abc"></div></feaas-component></section>'
168
88
  )
169
89
  })
170
- it('render template with data with src and stringy data', () => {
171
- const div = document.createElement('div')
172
- document.body.appendChild(div)
173
- const root = ReactDOM.render(
174
- <section>
175
- <Component src='library/test' template={'<div data-path-src="abc">'} data={'{"abc":321}'}></Component>
176
- </section>,
177
- div
178
- )
179
- expect(div.innerHTML).toEqual(
180
- '<section><feaas-component library="library" component="test" src="library/test" data="{&quot;abc&quot;:321}"><div data-path-src="abc"></div></feaas-component></section>'
181
- )
182
- const div2 = document.createElement('div')
183
- document.body.appendChild(div2)
184
- div2.innerHTML = div.innerHTML
185
- ReactDOM.hydrate(
90
+ it('render template with data with src and stringy data', async () => {
91
+ test(
186
92
  <section>
187
93
  <Component src='library/test' template={'<div data-path-src="abc">'} data={'{"abc":321}'}></Component>
188
94
  </section>,
189
- div2
190
- )
191
- expect(div2.innerHTML).toEqual(
192
95
  '<section><feaas-component library="library" component="test" src="library/test" data="{&quot;abc&quot;:321}"><div data-path-src="abc"></div></feaas-component></section>'
193
96
  )
194
97
  })
195
- it('render template with data and template', () => {
196
- const div = document.createElement('div')
197
- document.body.appendChild(div)
198
- const root = ReactDOM.render(
98
+ it('render template with data and template', async () => {
99
+ test(
199
100
  <section>
200
101
  <Component template={'<div data-path-src="abc">'} data={'{"abc":321}'}></Component>
201
102
  </section>,
202
- div
203
- )
204
- expect(div.innerHTML).toEqual(
205
- '<section><feaas-component data="{&quot;abc&quot;:321}"><div data-path-src="abc"></div></feaas-component></section>'
206
- )
207
- const div2 = document.createElement('div')
208
- document.body.appendChild(div2)
209
- div2.innerHTML = div.innerHTML
210
- ReactDOM.hydrate(
211
- <section>
212
- <Component template={'<div data-path-src="abc">'} data={'{"abc":321}'}></Component>
213
- </section>,
214
- div2
215
- )
216
- expect(div2.innerHTML).toEqual(
217
103
  '<section><feaas-component data="{&quot;abc&quot;:321}"><div data-path-src="abc"></div></feaas-component></section>'
218
104
  )
219
105
  })
@@ -1,17 +1,27 @@
1
1
  import { beforeEach, describe, expect, it } from 'vitest'
2
2
  import React from 'react'
3
3
  import * as Clientside from '../src/ui/react.js'
4
- import FEAASExternal from "../src/ui/FEAASExternal.js";
4
+ import FEAASExternal from '../src/ui/FEAASExternal.js'
5
5
 
6
6
  describe('External', () => {
7
7
  function Hello(props: { firstName: string; telephone: string }) {
8
8
  return React.createElement('div', {}, `Hello my name is ${props.firstName} and my tel is ${props.telephone}`)
9
9
  }
10
+ const helloSchema = {
11
+ properties: {
12
+ firstName: {
13
+ type: 'string'
14
+ },
15
+ telephone: {
16
+ type: 'number'
17
+ }
18
+ }
19
+ }
10
20
  function Hello2(props: { firstName: string; address: string }) {
11
21
  return React.createElement('div', {}, `Hello my name is ${props.firstName} and my address is ${props.address}`)
12
22
  }
13
23
  it('can register and render component', async () => {
14
- Clientside.External.registerComponent(Hello, {}, 'MyTestComponent')
24
+ Clientside.External.registerComponent(Hello, helloSchema, 'MyTestComponent')
15
25
  document.body.innerHTML =
16
26
  '<feaas-external id="external-component" class="-component" data-attributes-keys="first-name,telephone" first-name="Chuck" telephone="45657890875643" data-attributes="{&quot;first-name&quot;:&quot;Chuck&quot;,&quot;telephone&quot;:&quot;45657890875643&quot;}" data-external-id="MyTestComponent" contenteditable="false"></feaas-external>'
17
27
  const component = document.getElementById('external-component') as FEAASExternal
@@ -46,4 +56,5 @@ describe('External', () => {
46
56
  await expect(component2.whenRendered).resolves.toEqual(component2)
47
57
  expect(component2.innerHTML).toEqual('<div>Hello my name is George and my address is Test street 12</div>')
48
58
  })
59
+ // TODO: add test for props parsing
49
60
  })