diff --git a/packages/core/src/__tests__/__snapshots__/react-state-builder.test.ts.snap b/packages/core/src/__tests__/__snapshots__/react-state-builder.test.ts.snap new file mode 100644 index 0000000000..37f4d74f77 --- /dev/null +++ b/packages/core/src/__tests__/__snapshots__/react-state-builder.test.ts.snap @@ -0,0 +1,8157 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`React - stateType: builder > jsx > Javascript Test > AdvancedRef 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; +import { useRef, useEffect } from \\"react\\"; + +function MyBasicRefComponent(props) { + const inputRef = useRef(null); + const inputNoArgRef = useRef(null); + const state = useBuilderState({ + name: \\"PatrickJS\\", + onBlur: function onBlur() { + // Maintain focus + inputRef.current.focus(); + }, + lowerCaseName: function lowerCaseName() { + return state.name.toLowerCase(); + }, + }); + + useEffect(() => { + console.log(\\"Received an update\\"); + }, [inputRef.current, inputNoArgRef.current]); + + return ( + <> +
+ {props.showInput ? ( + <> + state.onBlur()} + onChange={(event) => (state.name = event.target.value)} + /> + + + + ) : null} + Hello + {state.lowerCaseName()}! I can run in React, Qwik, Vue, Solid, or Web + Component! +
+ + + ); +} + +export default MyBasicRefComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > Basic 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; + +export const DEFAULT_VALUES = { + name: \\"Steve\\", +}; + +function MyBasicComponent(props) { + const state = useBuilderState({ + name: \\"Steve\\", + underscore_fn_name() { + return \\"bar\\"; + }, + age: 1, + sports: [\\"\\"], + }); + + return ( + <> +
+ (state.name = myEvent.target.value)} + /> + Hello! I can run in React, Vue, Solid, or Liquid! > +
+ + + ); +} + +export default MyBasicComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > Basic Context 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; +import { useContext, useRef, useEffect } from \\"react\\"; +import { Injector, MyService, createInjector } from \\"@dummy/injection-js\\"; + +function MyBasicComponent(props) { + const state = useBuilderState({ + name: \\"PatrickJS\\", + onChange: function onChange() { + const change = myService.method(\\"change\\"); + console.log(change); + }, + }); + + const myService = useContext(MyService); + + const hasInitialized = useRef(false); + if (!hasInitialized.current) { + const hi = myService.method(\\"hi\\"); + console.log(hi); + hasInitialized.current = true; + } + + useEffect(() => { + const bye = myService.method(\\"hi\\"); + console.log(bye); + }, []); + + return ( + +
+ {myService.method(\\"hello\\") + state.name} + Hello! I can run in React, Vue, Solid, or Liquid! + state.onChange} /> +
+
+ ); +} + +export default MyBasicComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > Basic OnMount Update 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; +import { useRef, useEffect } from \\"react\\"; + +function MyBasicOnMountUpdateComponent(props) { + const state = useBuilderState({ + name: \\"PatrickJS\\", + names: [\\"Steve\\", \\"PatrickJS\\"], + }); + + const hasInitialized = useRef(false); + if (!hasInitialized.current) { + state.name = \\"PatrickJS onInit\\" + props.hi; + hasInitialized.current = true; + } + + useEffect(() => { + state.name = \\"PatrickJS onMount\\" + props.bye; + }, []); + + return
Hello {state.name}
; +} + +export default MyBasicOnMountUpdateComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > Basic Outputs 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; +import { useEffect } from \\"react\\"; + +function MyBasicOutputsComponent(props) { + const state = useBuilderState({ name: \\"PatrickJS\\" }); + + useEffect(() => { + props.onMessage(state.name); + props.onEvent(props.message); + }, []); + + return
; +} + +export default MyBasicOutputsComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > Basic Outputs Meta 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; +import { useEffect } from \\"react\\"; + +function MyBasicOutputsComponent(props) { + const state = useBuilderState({ name: \\"PatrickJS\\" }); + + useEffect(() => { + props.onMessage(state.name); + props.onEvent(props.message); + }, []); + + return
; +} + +export default MyBasicOutputsComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > BasicAttribute 1`] = ` +"import * as React from \\"react\\"; + +function MyComponent(props) { + const state = useBuilderState({}); + + return ; +} + +export default MyComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > BasicBooleanAttribute 1`] = ` +"import * as React from \\"react\\"; +import MyBooleanAttributeComponent from \\"./basic-boolean-attribute-component.raw\\"; + +function MyBooleanAttribute(props) { + const state = useBuilderState({}); + + return ( +
+ {props.children ? ( + <> + {props.children} + {props.type} + + ) : null} + + + +
+ ); +} + +export default MyBooleanAttribute; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > BasicChildComponent 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; +import MyBasicOnMountUpdateComponent from \\"./basic-onMount-update.raw\\"; +import MyBasicComponent from \\"./basic.raw\\"; + +function MyBasicChildComponent(props) { + const state = useBuilderState({ name: \\"Steve\\", dev: \\"PatrickJS\\" }); + + return ( +
+ +
+ +
+
+ ); +} + +export default MyBasicChildComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > BasicFor 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; +import { useEffect } from \\"react\\"; + +function MyBasicForComponent(props) { + const state = useBuilderState({ + name: \\"PatrickJS\\", + names: [\\"Steve\\", \\"PatrickJS\\"], + }); + + useEffect(() => { + console.log(\\"onMount code\\"); + }, []); + + return ( +
+ {state.names?.map((person) => ( + <> + { + state.name = event.target.value + \\" and \\" + person; + }} + /> + Hello + {person}! I can run in Qwik, Web Component, React, Vue, Solid, or + Liquid! + + ))} +
+ ); +} + +export default MyBasicForComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > BasicRef 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; +import { useRef } from \\"react\\"; + +function MyBasicRefComponent(props) { + const inputRef = useRef(null); + const inputNoArgRef = useRef(null); + const state = useBuilderState({ + name: \\"PatrickJS\\", + onBlur: function onBlur() { + // Maintain focus + inputRef.current.focus(); + }, + lowerCaseName: function lowerCaseName() { + return state.name.toLowerCase(); + }, + }); + + return ( + <> +
+ {props.showInput ? ( + <> + state.onBlur()} + onChange={(event) => (state.name = event.target.value)} + /> + + + + ) : null} + Hello + {state.lowerCaseName()}! I can run in React, Qwik, Vue, Solid, or Web + Component! +
+ + + ); +} + +export default MyBasicRefComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > BasicRefAssignment 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; +import { useRef } from \\"react\\"; + +function MyBasicRefAssignmentComponent(props) { + const holdValueRef = useRef(\\"Patrick\\"); + const state = useBuilderState({ + handlerClick: function handlerClick(event) { + event.preventDefault(); + console.log(\\"current value\\", holdValueRef.current); + holdValueRef.current = holdValueRef.current + \\"JS\\"; + }, + }); + + return ( +
+ +
+ ); +} + +export default MyBasicRefAssignmentComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > BasicRefPrevious 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; +import { useRef, useEffect } from \\"react\\"; + +export function usePrevious(value) { + // The ref object is a generic container whose current property is mutable ... + // ... and can hold any value, similar to an instance property on a class + let ref = useRef(null); // Store current value in ref + + onUpdate(() => { + ref = value; + }, [value]); // Only re-run if value changes + // Return previous value (happens before update in useEffect above) + + return ref; +} + +function MyPreviousComponent(props) { + const state = useBuilderState({ count: 0 }); + + const prevCount = useRef(state.count); + + useEffect(() => { + prevCount.current = state.count; + }, [state.count]); + + return ( +
+

+ Now: {state.count}, before: {prevCount.current} +

+ +
+ ); +} + +export default MyPreviousComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > Button 1`] = ` +"import * as React from \\"react\\"; + +function Button(props) { + const state = useBuilderState({}); + + return ( +
+ {props.link ? ( + + {props.text} + + ) : null} + {!props.link ? ( + + ) : null} +
+ ); +} + +export default Button; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > Columns 1`] = ` +"import * as React from \\"react\\"; + +function Column(props) { + const state = useBuilderState({ + getColumns() { + return props.columns || []; + }, + getGutterSize() { + return typeof props.space === \\"number\\" ? props.space || 0 : 20; + }, + getWidth(index) { + const columns = state.getColumns(); + return (columns[index] && columns[index].width) || 100 / columns.length; + }, + getColumnCssWidth(index) { + const columns = state.getColumns(); + const gutterSize = state.getGutterSize(); + const subtractWidth = + (gutterSize * (columns.length - 1)) / columns.length; + return \`calc(\${state.getWidth(index)}% - \${subtractWidth}px)\`; + }, + }); + + return ( + <> +
+ {props.columns?.map((column, index) => ( +
+ {column.content} + {index} +
+ ))} +
+ + + ); +} + +export default Column; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > ContentSlotHtml 1`] = ` +"import * as React from \\"react\\"; + +function ContentSlotCode(props) { + const state = useBuilderState({}); + + return ( +
+ <>{props.slotTesting} +
+
+
+
+ <>{props.children} +
+
+ ); +} + +export default ContentSlotCode; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > ContentSlotJSX 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; + +function ContentSlotJsxCode(props) { + const state = useBuilderState({ + name: \\"king\\", + showContent: false, + get cls() { + return props.slotContent && props.children ? \`\${state.name}-content\` : \\"\\"; + }, + show() { + props.slotContent ? 1 : \\"\\"; + }, + }); + + return ( + <> + {props.slotReference ? ( + <> +
state.show()} + className={state.cls} + > + {state.showContent && props.slotContent ? ( + <>{props.content || \\"{props.content}\\"} + ) : null} +
+
+
+
{props.children}
+
+ + ) : null} + + ); +} + +ContentSlotJsxCode.defaultProps = { + content: \\"\\", + slotReference: undefined, + slotContent: undefined, +}; + +export default ContentSlotJsxCode; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > CustomCode 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; +import { useRef, useEffect } from \\"react\\"; + +function CustomCode(props) { + const elem = useRef(null); + const state = useBuilderState({ + scriptsInserted: [], + scriptsRun: [], + findAndRunScripts() { + // TODO: Move this function to standalone one in '@builder.io/utils' + if (elem.current && typeof window !== \\"undefined\\") { + /** @type {HTMLScriptElement[]} */ + const scripts = elem.current.getElementsByTagName(\\"script\\"); + + for (let i = 0; i < scripts.length; i++) { + const script = scripts[i]; + + if (script.src) { + if (state.scriptsInserted.includes(script.src)) { + continue; + } + + state.scriptsInserted.push(script.src); + const newScript = document.createElement(\\"script\\"); + newScript.async = true; + newScript.src = script.src; + document.head.appendChild(newScript); + } else if ( + !script.type || + [ + \\"text/javascript\\", + \\"application/javascript\\", + \\"application/ecmascript\\", + ].includes(script.type) + ) { + if (state.scriptsRun.includes(script.innerText)) { + continue; + } + + try { + state.scriptsRun.push(script.innerText); + new Function(script.innerText)(); + } catch (error) { + console.warn(\\"\`CustomCode\`: Error running script:\\", error); + } + } + } + } + }, + }); + + useEffect(() => { + state.findAndRunScripts(); + }, []); + + return ( +
+ ); +} + +export default CustomCode; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > Embed 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; +import { useRef, useEffect } from \\"react\\"; + +function CustomCode(props) { + const elem = useRef(null); + const state = useBuilderState({ + scriptsInserted: [], + scriptsRun: [], + findAndRunScripts() { + // TODO: Move this function to standalone one in '@builder.io/utils' + if (elem.current && typeof window !== \\"undefined\\") { + /** @type {HTMLScriptElement[]} */ + const scripts = elem.current.getElementsByTagName(\\"script\\"); + + for (let i = 0; i < scripts.length; i++) { + const script = scripts[i]; + + if (script.src) { + if (state.scriptsInserted.includes(script.src)) { + continue; + } + + state.scriptsInserted.push(script.src); + const newScript = document.createElement(\\"script\\"); + newScript.async = true; + newScript.src = script.src; + document.head.appendChild(newScript); + } else if ( + !script.type || + [ + \\"text/javascript\\", + \\"application/javascript\\", + \\"application/ecmascript\\", + ].includes(script.type) + ) { + if (state.scriptsRun.includes(script.innerText)) { + continue; + } + + try { + state.scriptsRun.push(script.innerText); + new Function(script.innerText)(); + } catch (error) { + console.warn(\\"\`CustomCode\`: Error running script:\\", error); + } + } + } + } + }, + }); + + useEffect(() => { + state.findAndRunScripts(); + }, []); + + return ( +
+ ); +} + +export default CustomCode; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > Form 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; +import { useRef } from \\"react\\"; +import { Builder, builder } from \\"@builder.io/sdk\\"; +import { + BuilderBlock as BuilderBlockComponent, + BuilderBlocks, + get, + set, +} from \\"@fake\\"; + +function FormComponent(props) { + const formRef = useRef(null); + const state = useBuilderState({ + formState: \\"unsubmitted\\", + responseData: null, + formErrorMessage: \\"\\", + get submissionState() { + return (Builder.isEditing && props.previewState) || state.formState; + }, + onSubmit(event) { + const sendWithJs = + props.sendWithJs || props.sendSubmissionsTo === \\"email\\"; + + if (props.sendSubmissionsTo === \\"zapier\\") { + event.preventDefault(); + } else if (sendWithJs) { + if (!(props.action || props.sendSubmissionsTo === \\"email\\")) { + event.preventDefault(); + return; + } + + event.preventDefault(); + const el = event.currentTarget; + const headers = props.customHeaders || {}; + let body; + const formData = new FormData(el); // TODO: maybe support null + + const formPairs = Array.from( + event.currentTarget.querySelectorAll(\\"input,select,textarea\\") + ) + .filter((el) => !!el.name) + .map((el) => { + let value; + const key = el.name; + + if (el instanceof HTMLInputElement) { + if (el.type === \\"radio\\") { + if (el.checked) { + value = el.name; + return { + key, + value, + }; + } + } else if (el.type === \\"checkbox\\") { + value = el.checked; + } else if (el.type === \\"number\\" || el.type === \\"range\\") { + const num = el.valueAsNumber; + + if (!isNaN(num)) { + value = num; + } + } else if (el.type === \\"file\\") { + // TODO: one vs multiple files + value = el.files; + } else { + value = el.value; + } + } else { + value = el.value; + } + + return { + key, + value, + }; + }); + let contentType = props.contentType; + + if (props.sendSubmissionsTo === \\"email\\") { + contentType = \\"multipart/form-data\\"; + } + + Array.from(formPairs).forEach(({ value }) => { + if ( + value instanceof File || + (Array.isArray(value) && value[0] instanceof File) || + value instanceof FileList + ) { + contentType = \\"multipart/form-data\\"; + } + }); // TODO: send as urlEncoded or multipart by default + // because of ease of use and reliability in browser API + // for encoding the form? + + if (contentType !== \\"application/json\\") { + body = formData; + } else { + // Json + const json = {}; + Array.from(formPairs).forEach(({ value, key }) => { + set(json, key, value); + }); + body = JSON.stringify(json); + } + + if (contentType && contentType !== \\"multipart/form-data\\") { + if ( + /* Zapier doesn't allow content-type header to be sent from browsers */ !( + sendWithJs && props.action?.includes(\\"zapier.com\\") + ) + ) { + headers[\\"content-type\\"] = contentType; + } + } + const presubmitEvent = new CustomEvent(\\"presubmit\\", { + detail: { body }, + }); + if (formRef.current) { + formRef.current.dispatchEvent(presubmitEvent); + if (presubmitEvent.defaultPrevented) { + return; + } + } + state.formState = \\"sending\\"; + const formUrl = \`\${ + builder.env === \\"dev\\" ? \\"http://localhost:5000\\" : \\"https://builder.io\\" + }/api/v1/form-submit?apiKey=\${builder.apiKey}&to=\${btoa( + props.sendSubmissionsToEmail || \\"\\" + )}&name=\${encodeURIComponent(props.name || \\"\\")}\`; + fetch( + props.sendSubmissionsTo === \\"email\\" + ? formUrl + : props.action /* TODO: throw error if no action URL */, + { body, headers, method: props.method || \\"post\\" } + ).then( + async (res) => { + let body; + const contentType = res.headers.get(\\"content-type\\"); + if (contentType && contentType.indexOf(\\"application/json\\") !== -1) { + body = await res.json(); + } else { + body = await res.text(); + } + if (!res.ok && props.errorMessagePath) { + /* TODO: allow supplying an error formatter function */ let message = + get(body, props.errorMessagePath); + if (message) { + if (typeof message !== \\"string\\") { + /* TODO: ideally convert json to yaml so it woul dbe like error: - email has been taken */ message = + JSON.stringify(message); + } + state.formErrorMessage = message; + } + } + state.responseData = body; + state.formState = res.ok ? \\"success\\" : \\"error\\"; + if (res.ok) { + const submitSuccessEvent = new CustomEvent(\\"submit:success\\", { + detail: { res, body }, + }); + if (formRef.current) { + formRef.current.dispatchEvent(submitSuccessEvent); + if (submitSuccessEvent.defaultPrevented) { + return; + } + /* TODO: option to turn this on/off? */ if ( + props.resetFormOnSubmit !== false + ) { + formRef.current.reset(); + } + } + /* TODO: client side route event first that can be preventDefaulted */ if ( + props.successUrl + ) { + if (formRef.current) { + const event = new CustomEvent(\\"route\\", { + detail: { url: props.successUrl }, + }); + formRef.current.dispatchEvent(event); + if (!event.defaultPrevented) { + location.href = props.successUrl; + } + } else { + location.href = props.successUrl; + } + } + } + }, + (err) => { + const submitErrorEvent = new CustomEvent(\\"submit:error\\", { + detail: { error: err }, + }); + if (formRef.current) { + formRef.current.dispatchEvent(submitErrorEvent); + if (submitErrorEvent.defaultPrevented) { + return; + } + } + state.responseData = err; + state.formState = \\"error\\"; + } + ); + } + }, + }); + return ( + <> + {\\" \\"} +
state.onSubmit(event)} + {...props.attributes} + > + {props.builderBlock && props.builderBlock.children ? ( + <> + {props.builderBlock?.children?.map((block, index) => ( + + ))} + + ) : null} + {state.submissionState === \\"error\\" ? ( + + ) : null} + {state.submissionState === \\"sending\\" ? ( + + ) : null} + {state.submissionState === \\"error\\" && state.responseData ? ( +
+            {JSON.stringify(state.responseData, null, 2)}
+          
+ ) : null} + {state.submissionState === \\"success\\" ? ( + + ) : null} + {\\" \\"} + {\\" \\"} + + ); +} +export default FormComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > Image 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; +import { useRef, useEffect } from \\"react\\"; + +function Image(props) { + const pictureRef = useRef(null); + const state = useBuilderState({ + scrollListener: null, + imageLoaded: false, + setLoaded() { + state.imageLoaded = true; + }, + useLazyLoading() { + // TODO: Add more checks here, like testing for real web browsers + return !!props.lazy && state.isBrowser(); + }, + isBrowser: function isBrowser() { + return ( + typeof window !== \\"undefined\\" && + window.navigator.product != \\"ReactNative\\" + ); + }, + load: false, + }); + + useEffect(() => { + if (state.useLazyLoading()) { + // throttled scroll capture listener + const listener = () => { + if (pictureRef.current) { + const rect = pictureRef.current.getBoundingClientRect(); + const buffer = window.innerHeight / 2; + + if (rect.top < window.innerHeight + buffer) { + state.load = true; + state.scrollListener = null; + window.removeEventListener(\\"scroll\\", listener); + } + } + }; + + state.scrollListener = listener; + window.addEventListener(\\"scroll\\", listener, { + capture: true, + passive: true, + }); + listener(); + } + }, []); + + useEffect(() => { + return () => { + if (state.scrollListener) { + window.removeEventListener(\\"scroll\\", state.scrollListener); + } + }; + }, []); + + return ( + <> +
+ + {!state.useLazyLoading() || state.load ? ( + {props.altText} state.setLoaded()} + srcset={props.srcset} + sizes={props.sizes} + /> + ) : null} + + + {props.children} +
+ + + ); +} + +export default Image; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > Image State 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; + +function ImgStateComponent(props) { + const state = useBuilderState({ + canShow: true, + images: [\\"http://example.com/qwik.png\\"], + }); + + return ( +
+ {state.images?.map((item, itemIndex) => ( + + ))} +
+ ); +} + +export default ImgStateComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > Img 1`] = ` +"import * as React from \\"react\\"; +import { Builder } from \\"@builder.io/sdk\\"; + +function ImgComponent(props) { + const state = useBuilderState({}); + + return ( + {props.altText} + ); +} + +export default ImgComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > Input 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; +import { Builder } from \\"@builder.io/sdk\\"; + +function FormInputComponent(props) { + const state = useBuilderState({}); + + return ( + props.onChange?.(event.target.value)} + /> + ); +} + +export default FormInputComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > InputParent 1`] = ` +"import * as React from \\"react\\"; +import FormInputComponent from \\"./input.raw\\"; + +function Stepper(props) { + const state = useBuilderState({ + handleChange(value) { + console.log(value); + }, + }); + + return ( + state.handleChange(value)} + /> + ); +} + +export default Stepper; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > RawText 1`] = ` +"import * as React from \\"react\\"; + +function RawText(props) { + const state = useBuilderState({}); + + return ( + + ); +} + +export default RawText; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > Section 1`] = ` +"import * as React from \\"react\\"; + +function SectionComponent(props) { + const state = useBuilderState({}); + + return ( +
+ {props.children} +
+ ); +} + +export default SectionComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > Select 1`] = ` +"import * as React from \\"react\\"; +import { Builder } from \\"@builder.io/sdk\\"; + +function SelectComponent(props) { + const state = useBuilderState({}); + + return ( + + ); +} + +export default SelectComponent; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > SlotDefault 1`] = ` +"import * as React from \\"react\\"; + +function SlotCode(props) { + const state = useBuilderState({}); + + return ( +
+ <> + {props.children ||
Default content
} + +
+ ); +} + +export default SlotCode; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > SlotHtml 1`] = ` +"import * as React from \\"react\\"; +import ContentSlotCode from \\"./content-slot-jsx.raw\\"; + +function SlotCode(props) { + const state = useBuilderState({}); + + return ( +
+ Hello
}> +
+ ); +} + +export default SlotCode; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > SlotJsx 1`] = ` +"import * as React from \\"react\\"; +import ContentSlotCode from \\"./content-slot-jsx.raw\\"; + +function SlotCode(props) { + const state = useBuilderState({}); + + return ( +
+ Hello
} /> +
+ ); +} + +export default SlotCode; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > SlotNamed 1`] = ` +"import * as React from \\"react\\"; + +function SlotCode(props) { + const state = useBuilderState({}); + + return ( +
+ <>{props.myAwesomeSlot} + <>{props.top} + <>{props.left || \\"Default left\\"} + <>{props.children || \\"Default Child\\"} +
+ ); +} + +export default SlotCode; +" +`; + +exports[`React - stateType: builder > jsx > Javascript Test > Stamped.io 1`] = ` +"\\"use client\\"; +import * as React from \\"react\\"; +import { useEffect } from \\"react\\"; +import { kebabCase, snakeCase } from \\"lodash\\"; + +function SmileReviews(props) { + const state = useBuilderState({ + reviews: [], + name: \\"test\\", + showReviewPrompt: false, + kebabCaseValue() { + return kebabCase(\\"testThat\\"); + }, + snakeCaseValue() { + return snakeCase(\\"testThis\\"); + }, + }); + + useEffect(() => { + fetch( + \`https://stamped.io/api/widget/reviews?storeUrl=builder-io.myshopify.com&apiKey=\${ + props.apiKey || \\"pubkey-8bbDq7W6w4sB3OWeM1HUy2s47702hM\\" + }&productId=\${props.productId || \\"2410511106127\\"}\` + ) + .then((res) => res.json()) + .then((data) => { + state.reviews = data.data; + }); + }, []); + + return ( + <> +
+ + {state.showReviewPrompt || \\"asdf\\" ? ( + <> + + +