@sitecore-feaas/clientside 0.3.7 → 0.3.9

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.
@@ -82,14 +82,12 @@ export const parseProps = (propName: string, propValue: string, properties: JSON
82
82
  }
83
83
  }
84
84
 
85
- export function FEAASExternalProps(element: FEAASElement) {
86
- const attributes = element.getAttributeNames()
85
+ export function FEAASExternalProps(element: FEAASElement): any {
87
86
  const id = element.getAttribute('data-external-id')
88
87
  const schema: JSONSchema = FEAASExternal.registered[id]?.schema
89
- const props = attributes.reduce((prev, curr) => {
90
- if (!curr.startsWith('data-attribute') && !['class', 'id', 'contenteditable'].includes(curr)) {
91
- const value = element.getAttribute(curr)
92
- return { ...prev, [reverseKebabCase(curr)]: parseProps(reverseKebabCase(curr), value, schema?.properties) }
88
+ const props = Array.from(element.attributes).reduce((prev, { name, value }) => {
89
+ if (!name.startsWith('data-attribute') && !['class', 'id', 'contenteditable'].includes(name)) {
90
+ return { ...prev, [reverseKebabCase(name)]: parseProps(reverseKebabCase(name), value, schema?.properties) }
93
91
  } else {
94
92
  return prev
95
93
  }
@@ -109,10 +107,19 @@ export default class FEAASExternal extends FEAASElement<FEAASExternalProps, Reac
109
107
  return Promise.resolve({ React, ReactDOM })
110
108
  }
111
109
 
110
+ update() {
111
+ const { dataExternalId: id } = this.props
112
+ const Component = FEAASExternal.registered[id]?.component
113
+ if (!Component && this.childNodes.length > 0) return
114
+ return super.update()
115
+ }
116
+
112
117
  render(props: FEAASExternalProps, { React }: ReactModules): ReactJSX {
113
118
  const { dataExternalId: id } = props
114
119
  const Component = FEAASExternal.registered[id]?.component
115
- if (!Component) console.warn('FEAASExternal: The component you requested is not registered')
120
+ if (!Component) {
121
+ console.warn('FEAASExternal: The component you requested is not registered')
122
+ }
116
123
  return <>{Component && <Component {...props} />}</>
117
124
  }
118
125
 
package/src/ui/react.tsx CHANGED
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  FEAASComponentProps,
3
+ FEAASElement,
3
4
  fetchComponent,
4
5
  getComponentURL,
5
6
  getStylesheetURL,
@@ -9,7 +10,7 @@ import React from 'react'
9
10
  import { renderHTMLContent, HTMLNode, parseHTMLContent } from '../dom/html.js'
10
11
  import { DataSettings } from '../utils/settings.js'
11
12
  export { renderHTMLContent }
12
- import { getComponent } from './FEAASExternal.js'
13
+ import { FEAASExternalProps, getComponent } from './FEAASExternal.js'
13
14
  export { External, linkComponents, registerComponent, getComponent } from './FEAASExternal.js'
14
15
  export * from './index.js'
15
16
  export * from '../headless.js'
@@ -40,12 +41,17 @@ export function FEAASReactComponent({ data, ...props }: FEAASReactComponentProps
40
41
  let children: null | React.ReactNode
41
42
 
42
43
  if ('template' in props && props.template) {
43
- children = parseHTMLContent(props.template, data || {}).map((node) =>
44
- HTMLNodeToReact(node, (node) => {
45
- if (node.localName == 'feaas-external' && getComponent(node.getAttribute('data-external-id'))) {
46
- return [FEAASReactExternal, {}]
47
- }
48
- })
44
+ children = parseHTMLContent(props.template, data || {}).map((node, index) =>
45
+ HTMLNodeToReact(
46
+ node,
47
+ (node) => {
48
+ if (node.localName == 'feaas-external' && getComponent(node.getAttribute('data-external-id'))) {
49
+ const { dataExternalId, ...props } = FEAASExternalProps(node as any)
50
+ return [FEAASReactExternal, props]
51
+ }
52
+ },
53
+ index
54
+ )
49
55
  )
50
56
  }
51
57
 
@@ -63,7 +69,7 @@ export function FEAASReactComponent({ data, ...props }: FEAASReactComponentProps
63
69
  )}
64
70
  <feaas-component
65
71
  {...props}
66
- suppressHydrationWarning={true}
72
+ suppressHydrationWarning
67
73
  template={null}
68
74
  data={typeof data == 'string' ? data : data ? JSON.stringify(data) : null}
69
75
  >
@@ -75,9 +81,10 @@ export function FEAASReactComponent({ data, ...props }: FEAASReactComponentProps
75
81
 
76
82
  export function FEAASReactExternal(props: { 'data-external-id': string }) {
77
83
  const Component = getComponent(props['data-external-id'])?.component
84
+ // execute component as a function to supress hydration errors inside
78
85
  return (
79
- <feaas-external {...props}>
80
- <Component {...props} />
86
+ <feaas-external {...props} suppressHydrationWarning>
87
+ {typeof Component == 'function' ? Component({ ...props }) : <Component {...props} />}
81
88
  </feaas-external>
82
89
  )
83
90
  }
@@ -85,12 +92,13 @@ export function FEAASReactExternal(props: { 'data-external-id': string }) {
85
92
  /** Turn HTMLNode into React tree. It accepts callback to customize the behavior */
86
93
  export function HTMLNodeToReact(
87
94
  node: HTMLNode,
88
- callback?: (node: HTMLNode) => [tagName: any, attributes: Record<string, any>]
95
+ callback?: (node: HTMLNode) => [tagName: any, attributes: Record<string, any>],
96
+ key?: any
89
97
  ): React.ReactNode {
90
98
  if (node.nodeType === 3) {
91
99
  return node.textContent
92
100
  }
93
- const children = Array.from(node.childNodes).map((child) => HTMLNodeToReact(child, callback))
101
+ const children = Array.from(node.childNodes).map((child, index) => HTMLNodeToReact(child, callback, index))
94
102
 
95
103
  const attributes: { [key: string]: string } = {}
96
104
  for (let i = 0; i < node.attributes.length; i++) {
@@ -100,7 +108,7 @@ export function HTMLNodeToReact(
100
108
 
101
109
  const reactNode = callback?.(node)
102
110
  const reactName = reactNode?.[0] || node.nodeName.toLowerCase()
103
- const reactAttributes = Object.assign(attributes, reactName?.[1] || {})
111
+ const reactAttributes = Object.assign({ key, suppressHydrationWarning: true }, attributes, reactNode?.[1] || {})
104
112
  return React.createElement(reactName, reactAttributes, ['img', 'br', 'input'].includes(reactName) ? null : children)
105
113
  }
106
114