@picked/react 0.0.1-dev.1785287094311 → 0.0.1-dev.1785305085063
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.
|
@@ -13,6 +13,15 @@ interface HtmlRenderProps {
|
|
|
13
13
|
* client-only mount or a later content change attaches and writes the shadow root imperatively
|
|
14
14
|
* instead. A non-matching value or a `null` content renders nothing.
|
|
15
15
|
*
|
|
16
|
+
* Inside a Picked live-preview session the update path changes: content arrives at typing speed, so
|
|
17
|
+
* after the first render the shadow root is **morphed** rather than rewritten, and page scripts are
|
|
18
|
+
* **frozen** — nothing re-executes. The two are one behaviour and must never be separated. Freezing
|
|
19
|
+
* is what stops a customer's analytics and third-party pixels firing once per keystroke from the
|
|
20
|
+
* dashboard; morphing is what keeps the page alive without them, since a wholesale rewrite would
|
|
21
|
+
* detach every listener with nothing left to re-bind it. Markup inserted during a preview morph has
|
|
22
|
+
* its scripts neutralised, so a newly-added section renders but has no behaviour until the next full
|
|
23
|
+
* load — reported to the embedder so the editor can say so.
|
|
24
|
+
*
|
|
16
25
|
* @param {HtmlRenderProps} props - The component props.
|
|
17
26
|
* @returns {React.JSX.Element} The shadow-root host element.
|
|
18
27
|
* @example
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HtmlRender.d.ts","sourceRoot":"","sources":["../../src/experience/HtmlRender.tsx"],"names":[],"mappings":"AAAA,8GAA8G;AAC9G,OAAO,KAA4B,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"HtmlRender.d.ts","sourceRoot":"","sources":["../../src/experience/HtmlRender.tsx"],"names":[],"mappings":"AAAA,8GAA8G;AAC9G,OAAO,KAA4B,MAAM,OAAO,CAAA;AAWhD,UAAU,eAAe;IACvB,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,iBAAS,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE,eAAe,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAuChE;AAED,eAAe,UAAU,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useEffect as
|
|
1
|
+
import{morphInto as e}from"./morph.js";import{useEffect as t,useRef as n}from"react";import{isHtmlAssetValue as r,isPreviewSession as i,rehydrateScripts as a,reportInertScriptSubtrees as o,supportsShadowRoot as s,supportsWindow as c}from"@picked/client";import{jsx as l}from"react/jsx-runtime";function u({html:u}){let d=(r(u)?u:null)?.content??``,f=n(null),p=n(!1);return t(()=>{let t=f.current;if(!s()||!t)return;let n=t.shadowRoot,r=!p.current;if(p.current=!0,n&&r){d&&a(n);return}let c=n??t.attachShadow({mode:`open`});if(!r&&i()){let{inertScriptSubtrees:t}=e(c,d);o(t);return}c.innerHTML=d,d&&a(c)},[d]),c()?l(`div`,{ref:f,suppressHydrationWarning:!0}):l(`div`,{ref:f,suppressHydrationWarning:!0,dangerouslySetInnerHTML:{__html:`<template shadowrootmode="open">${d}</template>`}})}export{u as default};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Outcome of a morph pass. Returned by {@link morphInto}. */
|
|
2
|
+
interface MorphResult {
|
|
3
|
+
/**
|
|
4
|
+
* How many inserted subtrees contained at least one `<script>`. Those scripts are neutralised
|
|
5
|
+
* before insertion, so the markup renders but has no behaviour until the next full load. The
|
|
6
|
+
* dashboard surfaces this count so an author who adds a section understands why its carousel is
|
|
7
|
+
* inert, instead of filing it as a bug.
|
|
8
|
+
*/
|
|
9
|
+
inertScriptSubtrees: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Morphs a root's children to match `markup`, preserving every node the new markup did not change.
|
|
13
|
+
*
|
|
14
|
+
* Scripts are never executed: existing ones are left untouched (mutating a script's text does not
|
|
15
|
+
* re-run it) and inserted ones are neutralised before they reach the document. The returned count
|
|
16
|
+
* reports how many inserted subtrees were affected, so the editor can say so.
|
|
17
|
+
*
|
|
18
|
+
* @param {ParentNode & Node} root - The live root — typically a shadow root — to update.
|
|
19
|
+
* @param {string} markup - The desired markup.
|
|
20
|
+
* @returns {MorphResult} How many inserted subtrees had their scripts neutralised.
|
|
21
|
+
* @example
|
|
22
|
+
* const { inertScriptSubtrees } = morphInto(shadowRoot, '<h1>Hello</h1>')
|
|
23
|
+
*/
|
|
24
|
+
export declare function morphInto(root: ParentNode & Node, markup: string): MorphResult;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=morph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"morph.d.ts","sourceRoot":"","sources":["../../src/experience/morph.ts"],"names":[],"mappings":"AAmBA,8DAA8D;AAC9D,UAAU,WAAW;IACnB;;;;;OAKG;IACH,mBAAmB,EAAE,MAAM,CAAA;CAC5B;AAuHD;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAO9E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{PICKED_SCRIPT_TYPE as e}from"@picked/client";var t=`data-picked-hydrated`;function n(t){let n=t.querySelectorAll(`script`),r=t.tagName===`SCRIPT`;if(n.length===0&&!r)return!1;r&&t.setAttribute(`type`,e);for(let t of Array.from(n))t.setAttribute(`type`,e);return!0}function r(e,t,r){let i=t.importNode(e,!0);return i instanceof Element&&n(i)&&(r.inertScriptSubtrees+=1),i}function i(e,n){for(let t of Array.from(n.attributes))e.getAttribute(t.name)!==t.value&&e.setAttribute(t.name,t.value);for(let r of Array.from(e.attributes))r.name!==t&&(n.hasAttribute(r.name)||e.removeAttribute(r.name))}function a(e,t){return e.nodeType===t.nodeType&&e.nodeName===t.nodeName}function o(e,t,n,s){let c=Array.from(e.childNodes),l=Array.from(t.childNodes);for(let[t,u]of l.entries()){let l=c[t];if(!l){e.appendChild(r(u,n,s));continue}if(!a(l,u)){e.replaceChild(r(u,n,s),l);continue}if(l instanceof Element&&u instanceof Element){i(l,u),o(l,u,n,s);continue}l.nodeValue!==u.nodeValue&&(l.nodeValue=u.nodeValue)}for(let e of c.slice(l.length))e.remove()}function s(e,t){let n={inertScriptSubtrees:0},r=e.ownerDocument??globalThis.document,i=r.createElement(`template`);return i.innerHTML=t,o(e,i.content,r,n),n}export{s as morphInto};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@picked/react",
|
|
3
|
-
"version": "0.0.1-dev.
|
|
3
|
+
"version": "0.0.1-dev.1785305085063",
|
|
4
4
|
"devDependencies": {
|
|
5
5
|
"@picked/client": "workspace:*",
|
|
6
6
|
"@repo/eslint-config": "workspace:*",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
},
|
|
86
86
|
"module": "./dist/index.js",
|
|
87
87
|
"peerDependencies": {
|
|
88
|
-
"@picked/client": "0.0.1-dev.
|
|
88
|
+
"@picked/client": "0.0.1-dev.1785305085063",
|
|
89
89
|
"effector": "^23.3.0",
|
|
90
90
|
"react": "19.2.2",
|
|
91
91
|
"react-dom": "19.2.2"
|