@picked/svelte 0.0.1-dev.1793772853474 → 0.0.1-dev.1793835766402

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 (62) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/plugins/devtools/DevToolsExperience.svelte +169 -84
  3. package/dist/plugins/devtools/components/AdaptedToolHost.svelte +9 -3
  4. package/dist/plugins/devtools/customTools.d.ts +16 -7
  5. package/dist/plugins/devtools/customTools.js +1 -1
  6. package/dist/plugins/devtools/derive/answer-display/answer-display.d.ts +1 -1
  7. package/dist/plugins/devtools/derive/answer-display/answer-display.js +1 -1
  8. package/dist/plugins/devtools/derive/guide-sections/guide-sections.js +1 -1
  9. package/dist/plugins/devtools/derive/index.d.ts +3 -3
  10. package/dist/plugins/devtools/derive/index.js +1 -1
  11. package/dist/plugins/devtools/derive/journey-outline/journey-outline.js +1 -1
  12. package/dist/plugins/devtools/derive/journey-tree/journey-tree.js +1 -1
  13. package/dist/plugins/devtools/derive/persona-builder/persona-builder.js +1 -1
  14. package/dist/plugins/devtools/derive/personas/index.d.ts +2 -2
  15. package/dist/plugins/devtools/derive/personas/index.js +1 -1
  16. package/dist/plugins/devtools/derive/personas/personas.d.ts +89 -8
  17. package/dist/plugins/devtools/derive/personas/personas.js +1 -1
  18. package/dist/plugins/devtools/derive/plain-language/index.d.ts +1 -1
  19. package/dist/plugins/devtools/derive/plain-language/index.js +1 -1
  20. package/dist/plugins/devtools/derive/plain-language/plain-language.d.ts +20 -25
  21. package/dist/plugins/devtools/derive/plain-language/plain-language.js +1 -1
  22. package/dist/plugins/devtools/derive/plain-logic/plain-logic.d.ts +1 -1
  23. package/dist/plugins/devtools/derive/plain-logic/plain-logic.js +1 -1
  24. package/dist/plugins/devtools/derive/safety-posture/safety-posture.js +1 -1
  25. package/dist/plugins/devtools/index.d.ts +1 -1
  26. package/dist/plugins/devtools/launcher/Launcher.svelte +13 -4
  27. package/dist/plugins/devtools/options.d.ts +27 -24
  28. package/dist/plugins/devtools/options.js +1 -1
  29. package/dist/plugins/devtools/review/answers/AnswersPanel.svelte +14 -14
  30. package/dist/plugins/devtools/review/guide/GuidePanel.svelte +1 -1
  31. package/dist/plugins/devtools/review/index.d.ts +2 -2
  32. package/dist/plugins/devtools/review/journey/ExperienceDetails.svelte +129 -0
  33. package/dist/plugins/devtools/review/journey/JourneyMap.svelte +16 -14
  34. package/dist/plugins/devtools/review/journey/JourneyPanel.svelte +70 -24
  35. package/dist/plugins/devtools/review/journey/JourneyTimeline.svelte +22 -21
  36. package/dist/plugins/devtools/review/personas/PersonaBuilder.svelte +15 -46
  37. package/dist/plugins/devtools/review/personas/PersonaCard.svelte +227 -44
  38. package/dist/plugins/devtools/review/personas/PersonasPanel.svelte +191 -78
  39. package/dist/plugins/devtools/review/personas/load-persona.d.ts +43 -22
  40. package/dist/plugins/devtools/review/personas/load-persona.js +1 -1
  41. package/dist/plugins/devtools/review/personas/persona-route.d.ts +87 -0
  42. package/dist/plugins/devtools/review/personas/persona-route.js +1 -0
  43. package/dist/plugins/devtools/review/personas/persona-session.d.ts +94 -0
  44. package/dist/plugins/devtools/review/personas/persona-session.js +1 -0
  45. package/dist/plugins/devtools/review/session/SessionPanel.svelte +11 -11
  46. package/dist/plugins/devtools/review/variations/VariationsPanel.svelte +12 -13
  47. package/dist/plugins/devtools/screens/custom-tools/CustomToolsScreen.svelte +11 -25
  48. package/dist/plugins/devtools/sidebar/Sidebar.svelte +2 -33
  49. package/dist/plugins/devtools/sidebar/SidebarRow.svelte +5 -42
  50. package/dist/plugins/devtools/sidebar/nav.d.ts +26 -28
  51. package/dist/plugins/devtools/sidebar/nav.js +1 -1
  52. package/package.json +2 -2
  53. package/dist/plugins/devtools/screens/experience-instances/ExperienceInstancesListScreen.svelte +0 -10
  54. package/dist/plugins/devtools/screens/experiences/ExperienceDetailsScreen.svelte +0 -44
  55. package/dist/plugins/devtools/screens/experiences/ExperienceExperienceInstancesListScreen.svelte +0 -13
  56. package/dist/plugins/devtools/screens/experiences/ExperienceScreen.svelte +0 -32
  57. package/dist/plugins/devtools/screens/experiences/ExperienceTreeScreen.svelte +0 -500
  58. package/dist/plugins/devtools/screens/experiences/ExperiencesListScreen.svelte +0 -22
  59. package/dist/plugins/devtools/screens/features/FeaturesListScreen.svelte +0 -239
  60. package/dist/plugins/devtools/screens/responses/ResponseTableRow.svelte +0 -286
  61. package/dist/plugins/devtools/screens/responses/ResponsesListScreen.svelte +0 -12
  62. package/dist/plugins/devtools/screens/responses/ResponsesTable.svelte +0 -88
@@ -1 +1 @@
1
- import{NODE_LABELS as e,deslug as t,screenName as n}from"../plain-language/plain-language.js";import{describeRule as r}from"../plain-logic/plain-logic.js";var i=88,a=220,o=110,s=56,c=2e3,l=new Map([[`true`,{arm:`yes`,label:`Yes`,order:0}],[`false`,{arm:`no`,label:`Otherwise`,order:1}]]),u={kind:`system`,label:e.action,detail:null,rule:null,stepKey:null};function d(e,n,i){let a=e.conditionId===void 0?void 0:n.get(e.conditionId),o=r(a?.logic,i),s=a===void 0?o:t(a.name);return{kind:`decision`,label:o===`a rule this panel can't put into words`?s:o,detail:a?.name??null,rule:JSON.stringify(a?.logic??null,null,2),stepKey:null}}function f(r,i,a){if(r.type===`origin`)return{kind:`start`,label:e.origin,detail:null,rule:null,stepKey:null};if(r.type===`step`)return{kind:`screen`,label:n(r.name,r.stepKey),detail:r.stepKey??null,rule:null,stepKey:r.stepKey??null};if(r.type===`condition`)return d(r,i,a);if(r.type===`experience`){let e=r.experienceKey??`another journey`;return{kind:`journey`,label:t(e),detail:e,rule:null,stepKey:null}}let o=r.actionKey??r.name??r.type;return{kind:`system`,label:t(o),detail:o,rule:null,stepKey:null}}function p(e,t,n){return e!==null&&e===n?`current`:e!==null&&t.has(e)?`visited`:`ahead`}function m(e,t,n){let r=new Set,i=[...e];for(let e=0;e<i.length;e+=1)for(let a of t.get(i[e])??[]){if(r.has(a))continue;let e=n.get(a);e!==void 0&&e!==`screen`&&e!==`start`&&(r.add(a),i.push(a))}return r}function h(e,t,n,r){let i=new Map,a=new Map;for(let[t,o]of e)a.set(t,o.kind),i.set(t,p(o.stepKey,n,r));let o=[...e].filter(([e,t])=>t.kind===`screen`&&i.get(e)!==`ahead`).map(([e])=>e);if(o.length===0)return i;let s=new Map,c=new Map;for(let e of t)s.set(e.sourceNodeId,[...s.get(e.sourceNodeId)??[],e.destinationNodeId]),c.set(e.destinationNodeId,[...c.get(e.destinationNodeId)??[],e.sourceNodeId]);let l=[...e].filter(([,e])=>e.kind===`start`).map(([e])=>e),u=m([...o,...l],s,a),d=m(o,c,a);for(let t of e.keys())u.has(t)&&d.has(t)&&i.set(t,`visited`);for(let e of l)i.set(e,`visited`);return i}function g(e,t,n,r){return{id:e,nodeId:t,reference:n,handle:r,parent:null,children:[],index:0,depth:0,prelim:0,mod:0,change:0,shift:0,thread:null,ancestor:null,defaultAncestor:null,x:0}}function _(e){let t=new Map;for(let n of e){let e=t.get(n.sourceNodeId)??[];e.some(e=>e.destinationNodeId===n.destinationNodeId)||(e.push(n),t.set(n.sourceNodeId,e))}let n=e=>e.sourceHandle===void 0?2:l.get(e.sourceHandle)?.order??2;for(let e of t.values())e.sort((e,t)=>n(e)-n(t));return t}function v(e,t,n,r){let i=[],a=[],o=new Set([e.destinationNodeId]),s=[e.destinationNodeId];for(let c=0;c<s.length;c+=1){let l=(t.get(s[c])??[]).filter(e=>r.has(e.destinationNodeId));l.length===0&&a.push({edge:e,id:s[c]});for(let t of l){let r=t.destinationNodeId;o.has(r)||(o.add(r),n(r)?s.push(r):i.push({...e,id:`${e.id}~${r}`,destinationNodeId:r}))}}return{out:i,ended:a}}function y(e,t,n){let r=new Map,i=new Map;for(let[a,o]of e){if(t(a))continue;let s=[],c=[];for(let r of o){if(!n.has(r.destinationNodeId))continue;if(!t(r.destinationNodeId)){s.push(r);continue}let i=v(r,e,t,n);s.push(...i.out),c.push(...i.ended)}r.set(a,s.filter((e,t)=>s.findIndex(t=>t.destinationNodeId===e.destinationNodeId)===t)),c.length>0&&i.set(a,c)}return{through:r,ends:i}}function b(e,t,n){return e.map(({edge:e,id:r})=>{let i=t.kind===`decision`&&e.sourceHandle!==void 0?l.get(e.sourceHandle):void 0;return{id:r,key:`${e.id}~${r}`,label:n.get(r)?.label??r,armLabel:i?.label??null,arm:i?.arm??null}})}function x(e,t,n,r){let i=r;for(let r of t){if(!n.has(r.destinationNodeId))continue;if(i>=c)return{count:i,cut:!0};let t=g(r.destinationNodeId,r.destinationNodeId,!1,r.sourceHandle);t.parent=e,t.index=e.children.length,t.depth=e.depth+1,e.children.push(t),i+=1}return{count:i,cut:!1}}function S(e,t,n){let r=g(e,e,!1,void 0),i=new Set,a=[r],o=1,s=!1;for(let e=a.pop();e!==void 0;e=a.pop()){if(i.has(e.nodeId)){e.reference=!0,e.id=`${e.parent?.id??``}>${e.nodeId}`;continue}i.add(e.nodeId);let r=x(e,t.get(e.nodeId)??[],n,o);o=r.count,s||=r.cut;for(let t=e.children.length-1;t>=0;--t)a.push(e.children[t])}return{root:r,truncated:s}}function C(e,t){return(e.parent===t.parent?1:2)*88}function w(e){return e.children.at(0)??e.thread}function T(e){return e.children.at(-1)??e.thread}function E(e,t,n){let r=n/(t.index-e.index);t.change-=r,t.shift+=n,e.change+=r,t.prelim+=n,t.mod+=n}function D(e){let t=0,n=0;for(let r=e.children.length-1;r>=0;--r){let i=e.children[r];i.prelim+=t,i.mod+=t,n+=i.change,t+=i.shift+n}}function O(e,t,n){let r=e.ancestor??e;return r.parent===t.parent?r:n}function k(e,t,n){if(t===null||e.parent===null)return n;let r=n,i=e,a=e,o=t,s=e.parent.children[0],c=i.mod,l=a.mod,u=o.mod,d=s.mod;for(o=T(o),i=w(i);o!==null&&i!==null;){s=w(s)??s,a=T(a)??a,a.ancestor=e;let t=o.prelim+u-i.prelim-c+C(o,i);t>0&&(E(O(o,e,r),e,t),c+=t,l+=t),u+=o.mod,c+=i.mod,d+=s.mod,l+=a.mod,o=T(o),i=w(i)}return o!==null&&T(a)===null&&(a.thread=o,a.mod+=u-l),i!==null&&w(s)===null&&(s.thread=i,s.mod+=c-d,r=e),r}function A(e,t){let n=e.parent??t,r=e.index>0?n.children[e.index-1]:null;if(e.children.length>0){D(e);let t=(e.children[0].prelim+(e.children.at(-1)?.prelim??0))/2;r===null?e.prelim=t:(e.prelim=r.prelim+C(e,r),e.mod=e.prelim-t)}else r!==null&&(e.prelim=r.prelim+C(e,r));n.defaultAncestor=k(e,r,n.defaultAncestor??n.children[0])}function j(e){let t=[e],n=[];for(let e=t.pop();e!==void 0;e=t.pop())n.push(e),t.push(...e.children);return n.reverse()}function M(e){let t=[e],n=[];for(let e=t.pop();e!==void 0;e=t.pop()){n.push(e);for(let n=e.children.length-1;n>=0;--n)t.push(e.children[n])}return n}function N(e){let t=g(``,``,!1,void 0);t.children=[e];let n=j(e);for(let e of n)A(e,t);e.mod=-e.prelim,e.x=e.prelim+e.mod;for(let e=n.length-1;e>=0;--e){let t=n[e];t.parent!==null&&(t.x=t.prelim+t.parent.mod,t.mod+=t.parent.mod)}return n}function P(e,t,n,r){let i=(e+n)/2;return`M ${e} ${t} C ${i} ${t}, ${i} ${r}, ${n} ${r}`}function F(e,t,n,r){let i=n<=e,a=i?60+(e-n)*.15:Math.max(60,(n-e)/2),o=i?n+a:n-a;return{path:`M ${e} ${t} C ${e+a} ${t}, ${o} ${r}, ${n} ${r}`,back:i}}var I={nodes:[],links:[],jumps:[],width:0,height:0,truncated:!1};function L({nodes:e,edges:t,conditions:n,fieldLookup:r,visited:i,currentStepKey:a}){let c=e.find(e=>e.type===`origin`);if(c===void 0)return I;let d=new Map(n.map(e=>[e.id,e])),p=new Map(e.map(e=>[e.id,f(e,d,r)])),m=h(p,t,i,a),g=e=>p.get(e)?.kind===`system`,{through:v,ends:x}=y(_(t),g,new Set(p.keys())),C=new Set([...p.keys()].filter(e=>!g(e))),{root:w,truncated:T}=S(c.id,v,C),E=N(w),D=1/0,O=-1/0,k=0;for(let e of E)D=Math.min(D,e.x),O=Math.max(O,e.x),k=Math.max(k,e.depth);let A=M(w),j=A.map(e=>{let t=p.get(e.nodeId)??u;return{...t,id:e.id,nodeId:e.nodeId,state:m.get(e.nodeId)??`ahead`,reference:e.reference,leaf:e.children.length===0,ends:e.reference?[]:b(x.get(e.nodeId)??[],t,p),depth:e.depth,x:o+e.depth*220,y:s+(e.x-D)}}),L=new Map(j.map(e=>[e.id,e])),R=A.flatMap(e=>{let t=e.parent===null?void 0:L.get(e.parent.id),n=L.get(e.id);if(t===void 0||n===void 0)return[];let r=t.kind===`decision`&&e.handle!==void 0?l.get(e.handle):void 0;return[{id:n.id,from:t.id,to:n.id,arm:r?.arm??null,label:r?.label??null,path:P(t.x,t.y,n.x,n.y),labelX:(t.x+n.x)/2,labelY:(t.y+n.y)/2-6,travelled:t.state!==`ahead`&&n.state!==`ahead`}]}),z=new Map(j.filter(e=>!e.reference).map(e=>[e.nodeId,e]));return{nodes:j,links:R,jumps:j.flatMap(e=>{let t=e.reference?z.get(e.nodeId):void 0;return t===void 0?[]:[{id:e.id,from:e.id,to:t.id,...F(e.x,e.y,t.x,t.y)}]}),width:220+k*220,height:112+(O-D),truncated:T}}export{l as ARMS,i as BREADTH,a as DEPTH,u as FALLBACK,L as buildTree,f as describeNode,h as graphStates,b as namedEnds,_ as orderedOutgoing,y as withoutActions};
1
+ import{NODE_LABELS as e,deslug as t,screenName as n}from"../plain-language/plain-language.js";import{describeRule as r}from"../plain-logic/plain-logic.js";var i=88,a=220,o=110,s=56,c=2e3,l=new Map([[`true`,{arm:`yes`,label:`Yes`,order:0}],[`false`,{arm:`no`,label:`Otherwise`,order:1}]]),u={kind:`system`,label:e.action,detail:null,rule:null,stepKey:null};function d(e,n,i){let a=e.conditionId===void 0?void 0:n.get(e.conditionId),o=r(a?.logic,i),s=a===void 0?o:t(a.name);return{kind:`decision`,label:o===`a rule this panel can't put into words`?s:o,detail:a?.name??null,rule:JSON.stringify(a?.logic??null,null,2),stepKey:null}}function f(r,i,a){if(r.type===`origin`)return{kind:`start`,label:e.origin,detail:null,rule:null,stepKey:null};if(r.type===`step`)return{kind:`screen`,label:n(r.name,r.stepKey),detail:r.stepKey??null,rule:null,stepKey:r.stepKey??null};if(r.type===`condition`)return d(r,i,a);if(r.type===`experience`){let e=r.experienceKey??`another experience`;return{kind:`journey`,label:t(e),detail:e,rule:null,stepKey:null}}let o=r.actionKey??r.name??r.type;return{kind:`system`,label:t(o),detail:o,rule:null,stepKey:null}}function p(e,t,n){return e!==null&&e===n?`current`:e!==null&&t.has(e)?`visited`:`ahead`}function m(e,t,n){let r=new Set,i=[...e];for(let e=0;e<i.length;e+=1)for(let a of t.get(i[e])??[]){if(r.has(a))continue;let e=n.get(a);e!==void 0&&e!==`screen`&&e!==`start`&&(r.add(a),i.push(a))}return r}function h(e,t,n,r){let i=new Map,a=new Map;for(let[t,o]of e)a.set(t,o.kind),i.set(t,p(o.stepKey,n,r));let o=[...e].filter(([e,t])=>t.kind===`screen`&&i.get(e)!==`ahead`).map(([e])=>e);if(o.length===0)return i;let s=new Map,c=new Map;for(let e of t)s.set(e.sourceNodeId,[...s.get(e.sourceNodeId)??[],e.destinationNodeId]),c.set(e.destinationNodeId,[...c.get(e.destinationNodeId)??[],e.sourceNodeId]);let l=[...e].filter(([,e])=>e.kind===`start`).map(([e])=>e),u=m([...o,...l],s,a),d=m(o,c,a);for(let t of e.keys())u.has(t)&&d.has(t)&&i.set(t,`visited`);for(let e of l)i.set(e,`visited`);return i}function g(e,t,n,r){return{id:e,nodeId:t,reference:n,handle:r,parent:null,children:[],index:0,depth:0,prelim:0,mod:0,change:0,shift:0,thread:null,ancestor:null,defaultAncestor:null,x:0}}function _(e){let t=new Map;for(let n of e){let e=t.get(n.sourceNodeId)??[];e.some(e=>e.destinationNodeId===n.destinationNodeId)||(e.push(n),t.set(n.sourceNodeId,e))}let n=e=>e.sourceHandle===void 0?2:l.get(e.sourceHandle)?.order??2;for(let e of t.values())e.sort((e,t)=>n(e)-n(t));return t}function v(e,t,n,r){let i=[],a=[],o=new Set([e.destinationNodeId]),s=[e.destinationNodeId];for(let c=0;c<s.length;c+=1){let l=(t.get(s[c])??[]).filter(e=>r.has(e.destinationNodeId));l.length===0&&a.push({edge:e,id:s[c]});for(let t of l){let r=t.destinationNodeId;o.has(r)||(o.add(r),n(r)?s.push(r):i.push({...e,id:`${e.id}~${r}`,destinationNodeId:r}))}}return{out:i,ended:a}}function y(e,t,n){let r=new Map,i=new Map;for(let[a,o]of e){if(t(a))continue;let s=[],c=[];for(let r of o){if(!n.has(r.destinationNodeId))continue;if(!t(r.destinationNodeId)){s.push(r);continue}let i=v(r,e,t,n);s.push(...i.out),c.push(...i.ended)}r.set(a,s.filter((e,t)=>s.findIndex(t=>t.destinationNodeId===e.destinationNodeId)===t)),c.length>0&&i.set(a,c)}return{through:r,ends:i}}function b(e,t,n){return e.map(({edge:e,id:r})=>{let i=t.kind===`decision`&&e.sourceHandle!==void 0?l.get(e.sourceHandle):void 0;return{id:r,key:`${e.id}~${r}`,label:n.get(r)?.label??r,armLabel:i?.label??null,arm:i?.arm??null}})}function x(e,t,n,r){let i=r;for(let r of t){if(!n.has(r.destinationNodeId))continue;if(i>=c)return{count:i,cut:!0};let t=g(r.destinationNodeId,r.destinationNodeId,!1,r.sourceHandle);t.parent=e,t.index=e.children.length,t.depth=e.depth+1,e.children.push(t),i+=1}return{count:i,cut:!1}}function S(e,t,n){let r=g(e,e,!1,void 0),i=new Set,a=[r],o=1,s=!1;for(let e=a.pop();e!==void 0;e=a.pop()){if(i.has(e.nodeId)){e.reference=!0,e.id=`${e.parent?.id??``}>${e.nodeId}`;continue}i.add(e.nodeId);let r=x(e,t.get(e.nodeId)??[],n,o);o=r.count,s||=r.cut;for(let t=e.children.length-1;t>=0;--t)a.push(e.children[t])}return{root:r,truncated:s}}function C(e,t){return(e.parent===t.parent?1:2)*88}function w(e){return e.children.at(0)??e.thread}function T(e){return e.children.at(-1)??e.thread}function E(e,t,n){let r=n/(t.index-e.index);t.change-=r,t.shift+=n,e.change+=r,t.prelim+=n,t.mod+=n}function D(e){let t=0,n=0;for(let r=e.children.length-1;r>=0;--r){let i=e.children[r];i.prelim+=t,i.mod+=t,n+=i.change,t+=i.shift+n}}function O(e,t,n){let r=e.ancestor??e;return r.parent===t.parent?r:n}function k(e,t,n){if(t===null||e.parent===null)return n;let r=n,i=e,a=e,o=t,s=e.parent.children[0],c=i.mod,l=a.mod,u=o.mod,d=s.mod;for(o=T(o),i=w(i);o!==null&&i!==null;){s=w(s)??s,a=T(a)??a,a.ancestor=e;let t=o.prelim+u-i.prelim-c+C(o,i);t>0&&(E(O(o,e,r),e,t),c+=t,l+=t),u+=o.mod,c+=i.mod,d+=s.mod,l+=a.mod,o=T(o),i=w(i)}return o!==null&&T(a)===null&&(a.thread=o,a.mod+=u-l),i!==null&&w(s)===null&&(s.thread=i,s.mod+=c-d,r=e),r}function A(e,t){let n=e.parent??t,r=e.index>0?n.children[e.index-1]:null;if(e.children.length>0){D(e);let t=(e.children[0].prelim+(e.children.at(-1)?.prelim??0))/2;r===null?e.prelim=t:(e.prelim=r.prelim+C(e,r),e.mod=e.prelim-t)}else r!==null&&(e.prelim=r.prelim+C(e,r));n.defaultAncestor=k(e,r,n.defaultAncestor??n.children[0])}function j(e){let t=[e],n=[];for(let e=t.pop();e!==void 0;e=t.pop())n.push(e),t.push(...e.children);return n.reverse()}function M(e){let t=[e],n=[];for(let e=t.pop();e!==void 0;e=t.pop()){n.push(e);for(let n=e.children.length-1;n>=0;--n)t.push(e.children[n])}return n}function N(e){let t=g(``,``,!1,void 0);t.children=[e];let n=j(e);for(let e of n)A(e,t);e.mod=-e.prelim,e.x=e.prelim+e.mod;for(let e=n.length-1;e>=0;--e){let t=n[e];t.parent!==null&&(t.x=t.prelim+t.parent.mod,t.mod+=t.parent.mod)}return n}function P(e,t,n,r){let i=(e+n)/2;return`M ${e} ${t} C ${i} ${t}, ${i} ${r}, ${n} ${r}`}function F(e,t,n,r){let i=n<=e,a=i?60+(e-n)*.15:Math.max(60,(n-e)/2),o=i?n+a:n-a;return{path:`M ${e} ${t} C ${e+a} ${t}, ${o} ${r}, ${n} ${r}`,back:i}}var I={nodes:[],links:[],jumps:[],width:0,height:0,truncated:!1};function L({nodes:e,edges:t,conditions:n,fieldLookup:r,visited:i,currentStepKey:a}){let c=e.find(e=>e.type===`origin`);if(c===void 0)return I;let d=new Map(n.map(e=>[e.id,e])),p=new Map(e.map(e=>[e.id,f(e,d,r)])),m=h(p,t,i,a),g=e=>p.get(e)?.kind===`system`,{through:v,ends:x}=y(_(t),g,new Set(p.keys())),C=new Set([...p.keys()].filter(e=>!g(e))),{root:w,truncated:T}=S(c.id,v,C),E=N(w),D=1/0,O=-1/0,k=0;for(let e of E)D=Math.min(D,e.x),O=Math.max(O,e.x),k=Math.max(k,e.depth);let A=M(w),j=A.map(e=>{let t=p.get(e.nodeId)??u;return{...t,id:e.id,nodeId:e.nodeId,state:m.get(e.nodeId)??`ahead`,reference:e.reference,leaf:e.children.length===0,ends:e.reference?[]:b(x.get(e.nodeId)??[],t,p),depth:e.depth,x:o+e.depth*220,y:s+(e.x-D)}}),L=new Map(j.map(e=>[e.id,e])),R=A.flatMap(e=>{let t=e.parent===null?void 0:L.get(e.parent.id),n=L.get(e.id);if(t===void 0||n===void 0)return[];let r=t.kind===`decision`&&e.handle!==void 0?l.get(e.handle):void 0;return[{id:n.id,from:t.id,to:n.id,arm:r?.arm??null,label:r?.label??null,path:P(t.x,t.y,n.x,n.y),labelX:(t.x+n.x)/2,labelY:(t.y+n.y)/2-6,travelled:t.state!==`ahead`&&n.state!==`ahead`}]}),z=new Map(j.filter(e=>!e.reference).map(e=>[e.nodeId,e]));return{nodes:j,links:R,jumps:j.flatMap(e=>{let t=e.reference?z.get(e.nodeId):void 0;return t===void 0?[]:[{id:e.id,from:e.id,to:t.id,...F(e.x,e.y,t.x,t.y)}]}),width:220+k*220,height:112+(O-D),truncated:T}}export{l as ARMS,i as BREADTH,a as DEPTH,u as FALLBACK,L as buildTree,f as describeNode,h as graphStates,b as namedEnds,_ as orderedOutgoing,y as withoutActions};
@@ -1 +1 @@
1
- import{isBlank as e}from"../answer-history/answer-history.js";var t=400;function n(e,t,n){let r=e.edges.filter(e=>e.sourceNodeId===t.id),i=r.find(e=>e.sourceHandle===n),a=r.at(0);return n!==null&&(a=t.type===`condition`?i:i??r.find(e=>e.sourceHandle==null)),e.nodes.find(e=>e.id===a?.destinationNodeId)}function r(e){return e?.nodes.find(e=>e.type===`origin`)}function i(t,n){return t===void 0||e(t)?!1:n===void 0?!0:Array.isArray(t)?t.every(e=>n.includes(e)):n.includes(t)}async function a(e,t,n){let r=[],i=[];for(let[a,o]of e.entries())(o.condition==null||await n.evaluate(o.condition,t))&&(r.push(o.value),i.push(a));return{values:r,positions:i}}async function o(t,n,r){let i={...n};for(let n of t.fieldKeys)Object.hasOwn(r.answers,n)&&!e(r.answers[n])&&(i[n]=r.answers[n]);let o={fields:[],offered:{},options:{}};for(let e of t.fieldKeys){let t=r.field(e),n=t?.condition!=null&&!await r.evaluate(t.condition,i);if(r.codeOwned.has(e)||n||(o.fields.push(e),t?.options==null||t.options.length===0))continue;let{values:s,positions:c}=await a(t.options,i,r);o.offered[e]=s,o.options[e]=c}return o}function s(e,t){let r=n(e.journey,e.node,t);return r===void 0?void 0:{journey:e.journey,node:r}}function c(e,t){let n=e.journeys.get(t),i=r(n);return n===void 0||i===void 0?void 0:{journey:n,node:i}}async function l(e,t,n,r){let a=e.node.stepId===void 0?void 0:n.steps.get(e.node.stepId);if(a===void 0||n.selfAdvancing.has(a.key))return{next:s(e,null)};let{fields:c,offered:l,options:u}=await o(a,r.held,n),d=c.every(e=>i(n.answers[e],l[e]));r.rows.push({kind:`screen`,id:t,experienceKey:e.journey.key,experienceName:e.journey.name,stepKey:a.key,stepName:a.name??null,fields:c,options:u,complete:d});for(let e of c)i(n.answers[e],l[e])&&(r.held[e]=n.answers[e]);let f={experienceKey:e.journey.key,experienceName:e.journey.name,stepKey:a.key,stepName:a.name??null};return r.lastScreen=f,d?(r.passed.push({experienceKey:e.journey.key,stepKey:a.key}),{next:s(e,null)}):{stop:f}}async function u(e,t,n,r){let i=e.node.conditionId===void 0?void 0:n.conditions.get(e.node.conditionId);if(i===void 0)return r.rows.push({kind:`end`,id:t,reason:`end`,name:e.node.name??null}),{stop:null};let a=await n.evaluate(i.logic,r.held);if(n.readsOf(i.logic).some(e=>!n.asked.has(e)||n.codeOwned.has(e))){a=n.choices[t]??a;let e=i.name??i.key??`A decision the site makes`;r.rows.push({kind:`choice`,id:t,question:e,value:a})}return{next:s(e,a?`true`:`false`)}}function d(e,t,n,r){let{node:i}=e,a=i.type===`experience`?i.experienceKey:n.handoffs[i.actionKey??``];if(a!==void 0){let e=c(n,a);return e===void 0?(r.rows.push({kind:`end`,id:t,reason:`handoff`,name:i.name??a}),{stop:null}):{next:e}}if(i.type!==`action`)return{next:s(e,null)};let o=e.journey.edges.some(e=>e.sourceNodeId===i.id&&e.sourceHandle===`false`),l=!0;if(o){l=n.choices[t]??!0;let e=`${i.name??i.actionKey??`This step`} works`;r.rows.push({kind:`choice`,id:t,question:e,value:l})}return{next:s(e,l?`true`:`false`)}}async function f(e,t,n,r){switch(e.node.type){case`step`:return l(e,t,n,r);case`condition`:return u(e,t,n,r);case`action`:case`experience`:return d(e,t,n,r);default:return{next:s(e,null)}}}async function p(e){let n={held:{},rows:[],passed:[],lastScreen:null},r=e=>({rows:n.rows,answers:{...n.held},passed:n.passed,landing:e??n.lastScreen}),i=new Set,a=c(e,e.start);for(let o=0;o<t;o++){if(a===void 0)return n.rows.push({kind:`end`,id:`end-${o}`,reason:`end`,name:null}),r(null);let t=`${a.journey.key}/${a.node.id}`;if(i.has(t)){let i=a.node.stepId,o=i===void 0?void 0:e.steps.get(i);return n.rows.push({kind:`end`,id:`${t}#loop`,reason:`loop`,name:o?.name??null}),r(null)}i.add(t);let s=await f(a,t,e,n);if(`stop`in s)return r(s.stop);a=s.next}return n.rows.push({kind:`end`,id:`limit`,reason:`limit`,name:null}),r(null)}function m(e){let t=Array.isArray(e)?e.at(0):e;if(typeof t!=`string`||!t.startsWith(`responses.`))return;let n=t.slice(10).split(`.`).at(0);return n===void 0||n.length===0?void 0:n}function h(e){let t=new Set,n=e=>{if(Array.isArray(e))for(let t of e)n(t);else if(typeof e==`object`&&e)for(let[r,i]of Object.entries(e)){let e=r===`var`?m(i):void 0;e!==void 0&&t.add(e),n(i)}};return n(e),[...t]}function g(e,t){let n=e.filter(e=>!t.has(e.key)).map(e=>({experience:e,tree:e.treeStore.getState()}));return{journeys:new Map(n.map(({experience:e,tree:t})=>[e.key,{key:e.key,name:e.name,nodes:t.nodes,edges:t.edges}])),steps:new Map(n.flatMap(({tree:e})=>e.steps.map(e=>[e.id,e]))),conditions:new Map(n.flatMap(({tree:e})=>e.conditions.map(e=>[e.id,e])))}}export{g as builderGraph,h as responseKeysOf,p as walkDraft};
1
+ import{isBlank as e}from"../answer-history/answer-history.js";var t=400;function n(e,t,n){let r=e.edges.filter(e=>e.sourceNodeId===t.id),i=r.find(e=>e.sourceHandle===n),a=r.at(0);return n!==null&&(a=t.type===`condition`?i:i??r.find(e=>e.sourceHandle==null)),e.nodes.find(e=>e.id===a?.destinationNodeId)}function r(e){return e?.nodes.find(e=>e.type===`origin`)}function i(t,n){return t===void 0||e(t)?!1:n===void 0?!0:Array.isArray(t)?t.every(e=>n.includes(e)):n.includes(t)}async function a(e,t,n){let r=[],i=[];for(let[a,o]of e.entries())(o.condition==null||await n.evaluate(o.condition,t))&&(r.push(o.value),i.push(a));return{values:r,positions:i}}async function o(t,n,r){let i={...n};for(let n of t.fieldKeys)Object.hasOwn(r.answers,n)&&!e(r.answers[n])&&(i[n]=r.answers[n]);let o={fields:[],offered:{},options:{}};for(let e of t.fieldKeys){let t=r.field(e),n=t?.condition!=null&&!await r.evaluate(t.condition,i);if(r.codeOwned.has(e)||n||(o.fields.push(e),t?.options==null||t.options.length===0))continue;let{values:s,positions:c}=await a(t.options,i,r);o.offered[e]=s,o.options[e]=c}return o}function s(e,t){let r=n(e.journey,e.node,t);return r===void 0?void 0:{journey:e.journey,node:r}}function c(e,t){let n=e.journeys.get(t),i=r(n);return n===void 0||i===void 0?void 0:{journey:n,node:i}}async function l(e,t,n,r){let a=e.node.stepId===void 0?void 0:n.steps.get(e.node.stepId);if(a===void 0||n.selfAdvancing.has(a.key))return{next:s(e,null)};let{fields:c,offered:l,options:u}=await o(a,r.held,n),d=c.every(e=>i(n.answers[e],l[e]));r.rows.push({kind:`screen`,id:t,experienceKey:e.journey.key,experienceName:e.journey.name,stepKey:a.key,stepName:a.name??null,fields:c,options:u,complete:d});for(let e of c)i(n.answers[e],l[e])&&(r.held[e]=n.answers[e]);let f={experienceKey:e.journey.key,experienceName:e.journey.name,stepKey:a.key,stepName:a.name??null};return r.lastScreen=f,d?(r.passed.push({experienceKey:e.journey.key,stepKey:a.key}),{next:s(e,null)}):{stop:f}}async function u(e,t,n,r){let i=e.node.conditionId===void 0?void 0:n.conditions.get(e.node.conditionId);if(i===void 0)return r.rows.push({kind:`end`,id:t,reason:`end`,name:e.node.name??null}),{stop:null};let a=await n.evaluate(i.logic,r.held);if(n.readsOf(i.logic).some(e=>!n.asked.has(e)||n.codeOwned.has(e))){a=n.choices[t]??a;let e=i.name??i.key??`An unnamed condition`;r.rows.push({kind:`choice`,id:t,question:e,value:a})}return{next:s(e,a?`true`:`false`)}}function d(e,t,n,r){let{node:i}=e,a=i.type===`experience`?i.experienceKey:n.handoffs[i.actionKey??``];if(a!==void 0){let e=c(n,a);return e===void 0?(r.rows.push({kind:`end`,id:t,reason:`handoff`,name:i.name??a}),{stop:null}):{next:e}}if(i.type!==`action`)return{next:s(e,null)};let o=e.journey.edges.some(e=>e.sourceNodeId===i.id&&e.sourceHandle===`false`),l=!0;if(o){l=n.choices[t]??!0;let e=`${i.name??i.actionKey??`This action`} works`;r.rows.push({kind:`choice`,id:t,question:e,value:l})}return{next:s(e,l?`true`:`false`)}}async function f(e,t,n,r){switch(e.node.type){case`step`:return l(e,t,n,r);case`condition`:return u(e,t,n,r);case`action`:case`experience`:return d(e,t,n,r);default:return{next:s(e,null)}}}async function p(e){let n={held:{},rows:[],passed:[],lastScreen:null},r=e=>({rows:n.rows,answers:{...n.held},passed:n.passed,landing:e??n.lastScreen}),i=new Set,a=c(e,e.start);for(let o=0;o<t;o++){if(a===void 0)return n.rows.push({kind:`end`,id:`end-${o}`,reason:`end`,name:null}),r(null);let t=`${a.journey.key}/${a.node.id}`;if(i.has(t)){let i=a.node.stepId,o=i===void 0?void 0:e.steps.get(i);return n.rows.push({kind:`end`,id:`${t}#loop`,reason:`loop`,name:o?.name??null}),r(null)}i.add(t);let s=await f(a,t,e,n);if(`stop`in s)return r(s.stop);a=s.next}return n.rows.push({kind:`end`,id:`limit`,reason:`limit`,name:null}),r(null)}function m(e){let t=Array.isArray(e)?e.at(0):e;if(typeof t!=`string`||!t.startsWith(`responses.`))return;let n=t.slice(10).split(`.`).at(0);return n===void 0||n.length===0?void 0:n}function h(e){let t=new Set,n=e=>{if(Array.isArray(e))for(let t of e)n(t);else if(typeof e==`object`&&e)for(let[r,i]of Object.entries(e)){let e=r===`var`?m(i):void 0;e!==void 0&&t.add(e),n(i)}};return n(e),[...t]}function g(e,t){let n=e.filter(e=>!t.has(e.key)).map(e=>({experience:e,tree:e.treeStore.getState()}));return{journeys:new Map(n.map(({experience:e,tree:t})=>[e.key,{key:e.key,name:e.name,nodes:t.nodes,edges:t.edges}])),steps:new Map(n.flatMap(({tree:e})=>e.steps.map(e=>[e.id,e]))),conditions:new Map(n.flatMap(({tree:e})=>e.conditions.map(e=>[e.id,e])))}}export{g as builderGraph,h as responseKeysOf,p as walkDraft};
@@ -1,3 +1,3 @@
1
1
  /** @file Public entrypoint for personas: building, saving, reading and describing them. */
2
- export { PERSONA_STORAGE_PREFIX, buildPersona, customerAnswers, describeLanding, entryUrlOf, passedScreens, personaStorageKey, readAnswers, readEntryUrl, readSavedPersonas, sitePersonas, writeSavedPersonas, } from './personas';
3
- export type { BuildPersonaResult, Persona, PersonaCapture, PersonaDefinition, PersonaDraft, PersonaLanding, PersonaLoader, PersonaScreen, PersonaSource, PersonaStorageGetter, } from './personas';
2
+ export { PERSONA_STORAGE_PREFIX, applyEdits, buildPersona, customerAnswers, describeLanding, entryUrlOf, groupPersonas, matchesSearch, passedScreens, personaStorageKey, readAnswers, readEntryUrl, readLanding, readPassed, readSavedPersonas, sitePersonas, startOf, writeSavedPersonas, } from './personas';
3
+ export type { BuildPersonaResult, EditedPersonas, Persona, PersonaCapture, PersonaDefinition, PersonaDraft, PersonaGroup, PersonaLanding, PersonaScreen, PersonaSetup, PersonaSource, PersonaStorageGetter, } from './personas';
@@ -1 +1 @@
1
- export{PERSONA_STORAGE_PREFIX,buildPersona,customerAnswers,describeLanding,entryUrlOf,passedScreens,personaStorageKey,readAnswers,readEntryUrl,readSavedPersonas,sitePersonas,writeSavedPersonas}from"./personas.js";
1
+ export{PERSONA_STORAGE_PREFIX,applyEdits,buildPersona,customerAnswers,describeLanding,entryUrlOf,groupPersonas,matchesSearch,passedScreens,personaStorageKey,readAnswers,readEntryUrl,readLanding,readPassed,readSavedPersonas,sitePersonas,startOf,writeSavedPersonas}from"./personas.js";
@@ -20,18 +20,28 @@ export interface PersonaScreen {
20
20
  experienceKey: string;
21
21
  stepKey: string;
22
22
  }
23
- /** Loads a persona the host's own way, in place of walking its journey with its answers. */
24
- export type PersonaLoader = (client: Picked) => void | Promise<void>;
23
+ /**
24
+ * Puts the page in the state a persona needs before its experience starts, such as a stubbed
25
+ * account or a location. It runs on every page of the persona's session, before the walk.
26
+ */
27
+ export type PersonaSetup = (client: Picked) => void | Promise<void>;
25
28
  /** A customer or situation to try the journey as. */
26
29
  export interface Persona {
27
30
  id: string;
28
31
  name: string;
29
32
  description: string | null;
30
33
  source: PersonaSource;
34
+ /** The heading it is listed under; `null` lists it under its source's heading. */
35
+ group: string | null;
31
36
  /** The answers in place once it loads. */
32
37
  responses: Readonly<Record<string, FieldValue>>;
33
38
  /** Where a load stops; `null` loads the answers only. */
34
39
  landing: PersonaLanding | null;
40
+ /**
41
+ * The experience a walk starts in, such as the page's entry experience. `null` starts in the
42
+ * experience of the first screen moved on from, else the landing's.
43
+ */
44
+ start: string | null;
35
45
  /**
36
46
  * The screens moved on from when it was saved, in the order first left. A load presses Continue
37
47
  * on a screen that asks nothing only when it is listed here.
@@ -49,8 +59,10 @@ export interface Persona {
49
59
  entryUrl: string | null;
50
60
  /** When it was saved, as an ISO time; `null` for a host-defined persona. */
51
61
  savedAt: string | null;
52
- /** The host's own loader; `null` for the standard one. */
53
- load: PersonaLoader | null;
62
+ /** The host's setup; `null` when it needs none. */
63
+ setup: PersonaSetup | null;
64
+ /** `true` for a host-defined persona that a reviewer edited in this browser. */
65
+ edited: boolean;
54
66
  }
55
67
  /** A persona as the host defines it in the plugin's `personas` option. */
56
68
  export interface PersonaDefinition {
@@ -59,16 +71,20 @@ export interface PersonaDefinition {
59
71
  name: string;
60
72
  /** Who they are, in a sentence. */
61
73
  description?: string;
74
+ /** The heading it is listed under, such as `Moving`. */
75
+ group?: string;
62
76
  /** The answers in place once it loads. */
63
77
  responses?: Readonly<Record<string, FieldValue>>;
64
78
  /** The journey it opens. */
65
79
  experienceKey?: string;
66
80
  /** The screen in that journey it lands on. */
67
81
  stepKey?: string;
82
+ /** The experience a walk starts in, such as the page's entry experience; `experienceKey` when absent. */
83
+ startExperienceKey?: string;
68
84
  /** The page a load starts on, such as a campaign landing; the page in front when absent. */
69
85
  entryUrl?: string;
70
- /** Loads it the host's own way, in place of the standard answers-then-journey load. */
71
- load?: PersonaLoader;
86
+ /** Prepares the page for it, such as stubbing an account, before each walk. */
87
+ setup?: PersonaSetup;
72
88
  }
73
89
  /** What the reviewer types when saving where they are. */
74
90
  export interface PersonaDraft {
@@ -117,6 +133,22 @@ export declare function personaStorageKey(projectId: string): string;
117
133
  * @example readAnswers({ age: 42 }) // { age: 42 }
118
134
  */
119
135
  export declare function readAnswers(value: unknown): Record<string, FieldValue>;
136
+ /**
137
+ * Reads a stored landing.
138
+ *
139
+ * @param {unknown} value - The value to read.
140
+ * @returns {PersonaLanding | null} The landing, or `null` when it names no journey.
141
+ * @example readLanding({ experienceKey: 'needs-analysis' })
142
+ */
143
+ export declare function readLanding(value: unknown): PersonaLanding | null;
144
+ /**
145
+ * Reads a stored list of passed screens, keeping only the well-formed entries.
146
+ *
147
+ * @param {unknown} value - The stored list.
148
+ * @returns {PersonaScreen[]} The screens, in order.
149
+ * @example readPassed([{ experienceKey: 'funnel', stepKey: 'postcode' }])
150
+ */
151
+ export declare function readPassed(value: unknown): PersonaScreen[];
120
152
  /**
121
153
  * Reads an entry URL, or `null` when it is not a path on this site.
122
154
  *
@@ -186,7 +218,7 @@ export declare function customerAnswers(responses: Readonly<Record<string, Field
186
218
  */
187
219
  export declare function buildPersona(draft: PersonaDraft, capture: PersonaCapture): BuildPersonaResult;
188
220
  /**
189
- * Reads the host's persona definitions, dropping any without an id or name. A host loader is
221
+ * Reads the host's persona definitions, dropping any without an id or name. A host setup is
190
222
  * wrapped so it can be any function the host passed.
191
223
  *
192
224
  * @param {unknown} definitions - The plugin's `personas` option.
@@ -199,6 +231,55 @@ export declare function sitePersonas(definitions: unknown): Persona[];
199
231
  *
200
232
  * @param {PersonaLanding | null} landing - The persona's landing.
201
233
  * @returns {string} A short phrase naming the screen and journey.
202
- * @example describeLanding(null) // 'Answers only'
234
+ * @example describeLanding(null) // 'Responses only'
203
235
  */
204
236
  export declare function describeLanding(landing: PersonaLanding | null): string;
237
+ /**
238
+ * The experience a persona's walk starts in.
239
+ *
240
+ * @param {Pick<Persona, 'passed' | 'start' | 'landing'>} persona - The persona.
241
+ * @returns {string | null} The experience key, or `null` for a persona with no journey.
242
+ * @example startOf(persona) // 'needs-analysis'
243
+ */
244
+ export declare function startOf(persona: Pick<Persona, 'passed' | 'start' | 'landing'>): string | null;
245
+ /** The host's personas with this browser's edits applied, and the reviewer's own. */
246
+ export interface EditedPersonas {
247
+ /** The host's personas, each replaced by its edit when this browser holds one. */
248
+ site: Persona[];
249
+ /** The personas this browser saved that edit none of the host's. */
250
+ own: Persona[];
251
+ }
252
+ /**
253
+ * Applies this browser's edits to the host's personas. An edit is a saved persona with a host
254
+ * persona's id; it keeps the host's heading, start and setup.
255
+ *
256
+ * @param {readonly Persona[]} site - The host's personas.
257
+ * @param {readonly Persona[]} saved - The personas saved in this browser.
258
+ * @returns {EditedPersonas} The host's personas as edited, and the reviewer's own.
259
+ * @example applyEdits(options.personas, readSavedPersonas(getStorage, projectId))
260
+ */
261
+ export declare function applyEdits(site: readonly Persona[], saved: readonly Persona[]): EditedPersonas;
262
+ /** Personas listed under one heading. */
263
+ export interface PersonaGroup {
264
+ title: string;
265
+ personas: Persona[];
266
+ }
267
+ /**
268
+ * Lists personas under their headings, in the order each heading first appears.
269
+ *
270
+ * @param {readonly Persona[]} personas - The personas.
271
+ * @param {string} fallback - The heading for a persona with no group.
272
+ * @returns {PersonaGroup[]} The headings and their personas.
273
+ * @example groupPersonas(personas, 'For this site')
274
+ */
275
+ export declare function groupPersonas(personas: readonly Persona[], fallback: string): PersonaGroup[];
276
+ /**
277
+ * Whether a persona matches what the reviewer searched for: every word appears in its name,
278
+ * description or heading.
279
+ *
280
+ * @param {Persona} persona - The persona.
281
+ * @param {string} search - What was typed.
282
+ * @returns {boolean} `true` when it matches, and always for an empty search.
283
+ * @example matchesSearch(persona, 'moving gas')
284
+ */
285
+ export declare function matchesSearch(persona: Persona, search: string): boolean;
@@ -1 +1 @@
1
- import{isBlank as e}from"../answer-history/answer-history.js";import{deslug as t}from"../plain-language/plain-language.js";var n=`picked-devtools-personas`,r=1;function i(e){return`${n}:${e}`}function a(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function o(e){return e===null||typeof e==`string`||typeof e==`boolean`?!0:typeof e==`number`?Number.isFinite(e):Array.isArray(e)?e.every(o):a(e)&&Object.values(e).every(o)}function s(e){if(!a(e))return{};let t={};for(let[n,r]of Object.entries(e))o(r)&&(t[n]=r);return t}function c(e){if(typeof e!=`string`)return null;let t=e.trim();return t.length>0?t:null}function l(e){if(!a(e))return null;let t=c(e.experienceKey);return t===null?null:{experienceKey:t,experienceName:c(e.experienceName),stepKey:c(e.stepKey),stepName:c(e.stepName)}}function u(e){return Array.isArray(e)?e.flatMap(e=>{if(!a(e))return[];let t=c(e.experienceKey),n=c(e.stepKey);return t===null||n===null?[]:[{experienceKey:t,stepKey:n}]}):[]}function d(e){if(!a(e))return{};let t={};for(let[n,r]of Object.entries(e))typeof r==`boolean`&&(t[n]=r);return t}function f(e){let t=c(e);return t!==null&&t.startsWith(`/`)&&!t.startsWith(`//`)?t:null}function p(e,t){let n=e.trim();if(n.length===0)return null;try{let e=new URL(n,t);return e.origin===t?`${e.pathname}${e.search}`:null}catch{return null}}function m(e){if(!a(e))return null;let t=c(e.id),n=c(e.name);return t===null||n===null?null:{id:t,name:n,description:c(e.description),source:`saved`,responses:s(e.responses),landing:l(e.landing),passed:u(e.passed),choices:d(e.choices),entryUrl:f(e.entryUrl),savedAt:c(e.savedAt),load:null}}function h(e,t){let n;try{n=e().getItem(i(t))}catch{return[]}if(n===null)return[];let r;try{r=JSON.parse(n)}catch{return[]}return!a(r)||!Array.isArray(r.personas)?[]:r.personas.map(m).filter(e=>e!==null)}function g(e,t,n){let a=n.map(e=>({id:e.id,name:e.name,description:e.description,responses:e.responses,landing:e.landing,passed:e.passed,choices:e.choices,entryUrl:e.entryUrl,savedAt:e.savedAt}));try{return e().setItem(i(t),JSON.stringify({version:r,personas:a})),!0}catch{return!1}}function _(e,t){let n=new Set,r=[];for(let{journey:i,screen:a}of e){let e=`${i}/${a}`;t.has(i)||n.has(e)||(n.add(e),r.push({experienceKey:i,stepKey:a}))}return r}function v(t,n){let r={};for(let[i,a]of Object.entries(t))n.has(i)&&!e(a)&&(r[i]=a);return r}function y(e,t){let n=c(e.name);return n===null?{ok:!1,error:`Give it a name.`}:Object.keys(t.responses).length===0&&t.journey===null?{ok:!1,error:`Nothing to save yet. Answer a question first.`}:{ok:!0,persona:{id:t.id,name:n,description:c(e.description),source:`saved`,responses:s(t.responses),landing:t.journey,passed:t.passed,choices:d(t.choices),entryUrl:f(t.entryUrl),savedAt:t.savedAt,load:null}}}function b(e){return Array.isArray(e)?e.flatMap(e=>{if(!a(e))return[];let t=c(e.id),n=c(e.name);if(t===null||n===null)return[];let r=c(e.experienceKey),i=e.load;return[{id:t,name:n,description:c(e.description),source:`site`,responses:s(e.responses),landing:r===null?null:{experienceKey:r,experienceName:null,stepKey:c(e.stepKey),stepName:null},passed:[],choices:{},entryUrl:f(e.entryUrl),savedAt:null,load:typeof i==`function`?async e=>{await Reflect.apply(i,void 0,[e])}:null}]}):[]}function x(e){if(e===null)return`Answers only`;let n=e.experienceName??t(e.experienceKey);return e.stepKey===null?`Opens ${n}`:`Lands on ${e.stepName??t(e.stepKey)} in ${n}`}export{n as PERSONA_STORAGE_PREFIX,y as buildPersona,v as customerAnswers,x as describeLanding,p as entryUrlOf,_ as passedScreens,i as personaStorageKey,s as readAnswers,f as readEntryUrl,h as readSavedPersonas,b as sitePersonas,g as writeSavedPersonas};
1
+ import{isBlank as e}from"../answer-history/answer-history.js";import{deslug as t}from"../plain-language/plain-language.js";var n=`picked-devtools-personas`,r=1;function i(e){return`${n}:${e}`}function a(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function o(e){return e===null||typeof e==`string`||typeof e==`boolean`?!0:typeof e==`number`?Number.isFinite(e):Array.isArray(e)?e.every(o):a(e)&&Object.values(e).every(o)}function s(e){if(!a(e))return{};let t={};for(let[n,r]of Object.entries(e))o(r)&&(t[n]=r);return t}function c(e){if(typeof e!=`string`)return null;let t=e.trim();return t.length>0?t:null}function l(e){if(!a(e))return null;let t=c(e.experienceKey);return t===null?null:{experienceKey:t,experienceName:c(e.experienceName),stepKey:c(e.stepKey),stepName:c(e.stepName)}}function u(e){return Array.isArray(e)?e.flatMap(e=>{if(!a(e))return[];let t=c(e.experienceKey),n=c(e.stepKey);return t===null||n===null?[]:[{experienceKey:t,stepKey:n}]}):[]}function d(e){if(!a(e))return{};let t={};for(let[n,r]of Object.entries(e))typeof r==`boolean`&&(t[n]=r);return t}function f(e){let t=c(e);return t!==null&&t.startsWith(`/`)&&!t.startsWith(`//`)?t:null}function p(e,t){let n=e.trim();if(n.length===0)return null;try{let e=new URL(n,t);return e.origin===t?`${e.pathname}${e.search}`:null}catch{return null}}function m(e){if(!a(e))return null;let t=c(e.id),n=c(e.name);return t===null||n===null?null:{id:t,name:n,description:c(e.description),source:`saved`,group:null,responses:s(e.responses),landing:l(e.landing),start:null,passed:u(e.passed),choices:d(e.choices),entryUrl:f(e.entryUrl),savedAt:c(e.savedAt),setup:null,edited:!1}}function h(e,t){let n;try{n=e().getItem(i(t))}catch{return[]}if(n===null)return[];let r;try{r=JSON.parse(n)}catch{return[]}return!a(r)||!Array.isArray(r.personas)?[]:r.personas.map(m).filter(e=>e!==null)}function g(e,t,n){let a=n.map(e=>({id:e.id,name:e.name,description:e.description,responses:e.responses,landing:e.landing,passed:e.passed,choices:e.choices,entryUrl:e.entryUrl,savedAt:e.savedAt}));try{return e().setItem(i(t),JSON.stringify({version:r,personas:a})),!0}catch{return!1}}function _(e,t){let n=new Set,r=[];for(let{journey:i,screen:a}of e){let e=`${i}/${a}`;t.has(i)||n.has(e)||(n.add(e),r.push({experienceKey:i,stepKey:a}))}return r}function v(t,n){let r={};for(let[i,a]of Object.entries(t))n.has(i)&&!e(a)&&(r[i]=a);return r}function y(e,t){let n=c(e.name);return n===null?{ok:!1,error:`Give it a name.`}:Object.keys(t.responses).length===0&&t.journey===null?{ok:!1,error:`Nothing to save yet. Give a response first.`}:{ok:!0,persona:{id:t.id,name:n,description:c(e.description),source:`saved`,group:null,responses:s(t.responses),landing:t.journey,start:null,passed:t.passed,choices:d(t.choices),entryUrl:f(t.entryUrl),savedAt:t.savedAt,setup:null,edited:!1}}}function b(e){return Array.isArray(e)?e.flatMap(e=>{if(!a(e))return[];let t=c(e.id),n=c(e.name);if(t===null||n===null)return[];let r=c(e.experienceKey),i=e.setup;return[{id:t,name:n,description:c(e.description),source:`site`,group:c(e.group),responses:s(e.responses),landing:r===null?null:{experienceKey:r,experienceName:null,stepKey:c(e.stepKey),stepName:null},start:c(e.startExperienceKey),passed:[],choices:{},entryUrl:f(e.entryUrl),savedAt:null,setup:typeof i==`function`?async e=>{await Reflect.apply(i,void 0,[e])}:null,edited:!1}]}):[]}function x(e){if(e===null)return`Responses only`;let n=e.experienceName??t(e.experienceKey);return e.stepKey===null?`Opens ${n}`:`Lands on ${e.stepName??t(e.stepKey)} in ${n}`}function S(e){return e.passed.at(0)?.experienceKey??e.start??e.landing?.experienceKey??null}function C(e,t){let n=new Map(t.map(e=>[e.id,e])),r=new Set(e.map(e=>e.id));return{site:e.map(e=>{let t=n.get(e.id);return t===void 0?e:{...t,source:`site`,group:e.group,start:e.start,setup:e.setup,edited:!0}}),own:t.filter(e=>!r.has(e.id))}}function w(e,t){let n=new Map;for(let r of e){let e=r.group??t;n.set(e,[...n.get(e)??[],r])}return[...n].map(([e,t])=>({title:e,personas:t}))}function T(e,t){let n=[e.name,e.description,e.group].join(` `).toLowerCase();return t.toLowerCase().split(/\s+/).filter(e=>e.length>0).every(e=>n.includes(e))}export{n as PERSONA_STORAGE_PREFIX,C as applyEdits,y as buildPersona,v as customerAnswers,x as describeLanding,p as entryUrlOf,w as groupPersonas,T as matchesSearch,_ as passedScreens,i as personaStorageKey,s as readAnswers,f as readEntryUrl,l as readLanding,u as readPassed,h as readSavedPersonas,b as sitePersonas,S as startOf,g as writeSavedPersonas};
@@ -1,3 +1,3 @@
1
1
  /** @file Public entrypoint for the review tools' vocabulary contract. */
2
- export { DEVELOPER_LABEL, NODE_LABELS, TAB_INTROS, TAB_LABELS, configSourceLabel, deslug, screenName, } from './plain-language';
2
+ export { NODE_LABELS, TAB_INTROS, TAB_LABELS, configSourceLabel, deslug, screenName, } from './plain-language';
3
3
  export type { ReviewTabId } from './plain-language';
@@ -1 +1 @@
1
- export{DEVELOPER_LABEL,NODE_LABELS,TAB_INTROS,TAB_LABELS,configSourceLabel,deslug,screenName}from"./plain-language.js";
1
+ export{NODE_LABELS,TAB_INTROS,TAB_LABELS,configSourceLabel,deslug,screenName}from"./plain-language.js";
@@ -1,21 +1,18 @@
1
1
  /**
2
- * @file The review tools' vocabulary contract: Picked's nouns translated into a reviewer's.
2
+ * @file The panel's vocabulary contract: every label and intro the review tabs share.
3
3
  *
4
- * One module owns every translation, so the mapping is reviewable in one place and cannot drift
5
- * into a component as a hard-coded string. The audience is a product, marketing or QA reviewer
6
- * who knows the client's journey and its customers, and has no reason to learn what an
7
- * experience, a field key or a bucket is. A word that only means something once you have seen the
8
- * Picked dashboard does not belong on a reviewer's screen.
9
- */
10
- /**
11
- * Each node type, named the way a reviewer would describe what the journey is doing there.
4
+ * One module owns these words, so they are reviewable in one place and cannot drift into a
5
+ * component as a hard-coded string. The panel speaks the dashboard's nouns (experience, step,
6
+ * field, response, condition, action, feature flag, visitor), so what a person reads in the panel
7
+ * is what they find in the dashboard.
12
8
  */
9
+ /** Each node type's label, in the dashboard's nouns. */
13
10
  export declare const NODE_LABELS: {
14
- readonly origin: 'Start';
15
- readonly step: 'Screen';
16
- readonly condition: 'Decision';
17
- readonly action: 'Checking details';
18
- readonly experience: 'Opens another journey';
11
+ readonly origin: 'Origin';
12
+ readonly step: 'Step';
13
+ readonly condition: 'Condition';
14
+ readonly action: 'Action';
15
+ readonly experience: 'Opens another experience';
19
16
  };
20
17
  /**
21
18
  * Turns a kebab or snake key into a sentence. It is a fallback for a step whose author gave it no
@@ -33,7 +30,7 @@ export declare function deslug(key: string): string;
33
30
  *
34
31
  * @param {string | undefined} name - The step's authored name.
35
32
  * @param {string | undefined} key - The step's key.
36
- * @returns {string} A non-empty label for the screen.
33
+ * @returns {string} A non-empty label for the step.
37
34
  * @example
38
35
  * screenName(undefined, 'plan-comparison') // 'Plan comparison'
39
36
  */
@@ -55,21 +52,19 @@ export declare function configSourceLabel(previewToken: string | undefined): str
55
52
  export declare const TAB_LABELS: {
56
53
  readonly guide: 'How to use';
57
54
  readonly session: 'This session';
58
- readonly answers: 'Answers';
59
- readonly journey: 'Journey map';
55
+ readonly answers: 'Responses';
56
+ readonly journey: 'Experiences';
60
57
  readonly personas: 'Personas & Scenarios';
61
- readonly variations: 'Variations';
58
+ readonly variations: 'Feature flags';
62
59
  };
63
60
  /** The id of one of the review tools' own tabs. */
64
61
  export type ReviewTabId = keyof typeof TAB_LABELS;
65
- /** The name of the sidebar section that holds the developer tools, apart from the review tabs. */
66
- export declare const DEVELOPER_LABEL = "Developer";
67
62
  /** The one-sentence purpose each tab leads with. Kept together so the tone stays consistent. */
68
63
  export declare const TAB_INTROS: {
69
64
  readonly guide: 'How to use each tab. Open a tab straight from its section.';
70
- readonly session: 'Where you are right now, and what you answered on each screen. Start here if something looks wrong.';
71
- readonly answers: 'Every question this journey can ask, and the answers given. Change one to see what the customer would see.';
72
- readonly journey: 'Every route this journey can take, with your route marked. Go back to any screen you have already visited.';
73
- readonly personas: 'Customers and situations to try this journey as. Load one to land where it would, or save where you are as a new one.';
74
- readonly variations: 'The variations running on this site. Force one on to review it, then copy the link to show someone else exactly what you saw.';
65
+ readonly session: 'Where you are right now, and your responses on each step. Start here if something looks wrong.';
66
+ readonly answers: 'Every field this experience can ask for, and the responses given. Change one to see what the visitor would see.';
67
+ readonly journey: 'Every experience on this site: the route each can take, with yours marked, and where and when it shows. Go back to any step you have already visited.';
68
+ readonly personas: 'Visitors and situations to try this experience as. Walk through as one, or jump to a step on its route.';
69
+ readonly variations: 'The feature flags running on this site. Force a variant to review it, then copy the link to show someone else exactly what you saw.';
75
70
  };
@@ -1 +1 @@
1
- var e={origin:`Start`,step:`Screen`,condition:`Decision`,action:`Checking details`,experience:`Opens another journey`};function t(e){let t=e.replace(/[-_]+/g,` `).trim();return t.length===0?e:t.charAt(0).toUpperCase()+t.slice(1)}function n(e,n){let r=e?.trim();return r!==void 0&&r.length>0?r:n!==void 0&&n.length>0?t(n):`Untitled screen`}function r(e){return e!==void 0&&e.length>0?`Viewing unpublished changes`:`Viewing published content`}var i={guide:`How to use`,session:`This session`,answers:`Answers`,journey:`Journey map`,personas:`Personas & Scenarios`,variations:`Variations`},a=`Developer`,o={guide:`How to use each tab. Open a tab straight from its section.`,session:`Where you are right now, and what you answered on each screen. Start here if something looks wrong.`,answers:`Every question this journey can ask, and the answers given. Change one to see what the customer would see.`,journey:`Every route this journey can take, with your route marked. Go back to any screen you have already visited.`,personas:`Customers and situations to try this journey as. Load one to land where it would, or save where you are as a new one.`,variations:`The variations running on this site. Force one on to review it, then copy the link to show someone else exactly what you saw.`};export{a as DEVELOPER_LABEL,e as NODE_LABELS,o as TAB_INTROS,i as TAB_LABELS,r as configSourceLabel,t as deslug,n as screenName};
1
+ var e={origin:`Origin`,step:`Step`,condition:`Condition`,action:`Action`,experience:`Opens another experience`};function t(e){let t=e.replace(/[-_]+/g,` `).trim();return t.length===0?e:t.charAt(0).toUpperCase()+t.slice(1)}function n(e,n){let r=e?.trim();return r!==void 0&&r.length>0?r:n!==void 0&&n.length>0?t(n):`Untitled step`}function r(e){return e!==void 0&&e.length>0?`Viewing unpublished changes`:`Viewing published content`}var i={guide:`How to use`,session:`This session`,answers:`Responses`,journey:`Experiences`,personas:`Personas & Scenarios`,variations:`Feature flags`},a={guide:`How to use each tab. Open a tab straight from its section.`,session:`Where you are right now, and your responses on each step. Start here if something looks wrong.`,answers:`Every field this experience can ask for, and the responses given. Change one to see what the visitor would see.`,journey:`Every experience on this site: the route each can take, with yours marked, and where and when it shows. Go back to any step you have already visited.`,personas:`Visitors and situations to try this experience as. Walk through as one, or jump to a step on its route.`,variations:`The feature flags running on this site. Force a variant to review it, then copy the link to show someone else exactly what you saw.`};export{e as NODE_LABELS,a as TAB_INTROS,i as TAB_LABELS,r as configSourceLabel,t as deslug,n as screenName};
@@ -15,7 +15,7 @@
15
15
  export interface FieldSummary {
16
16
  /** The short noun ("Purpose"). What a sentence is built from. */
17
17
  name?: string;
18
- /** The question the customer was asked. Used by the Answers table, not here. */
18
+ /** The label the visitor reads, which the Responses tab shows. */
19
19
  label?: string;
20
20
  options?: readonly {
21
21
  value: unknown;
@@ -1 +1 @@
1
- var e=`a rule this panel can't put into words`,t={"==":`is`,"===":`is`,"!=":`is not`,"!==":`is not`,">":`is more than`,">=":`is at least`,"<":`is less than`,"<=":`is at most`},n=`responses.`;function r(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function i(e){if(!r(e))return;let t=Object.keys(e);return t.length===1?t[0]:void 0}function a(e){if(typeof e==`string`)return e;if(Array.isArray(e)&&typeof e[0]==`string`)return e[0]}function o(e){if(!r(e)||i(e)!==`var`)return;let t=a(e.var);if(t!==void 0)return t.startsWith(n)?t.slice(10):t}function s(e,t){let n=t(e)?.name?.trim();return n!==void 0&&n.length>0?n:e.replace(/[-_]+/g,` `)}function c(t,n,r){if(n!==void 0){let e=r(n)?.options?.find(e=>e.value===t);if(e!==void 0)return e.label}return t===null?`nothing`:t===!0?`yes`:t===!1?`no`:typeof t==`string`?t.length===0?`nothing`:t:typeof t==`number`?String(t):e}function l(e,t){return e.length<=1?e.join(``):e.length===2?`${e[0]} ${t} ${e[1]}`:`${e.slice(0,-1).join(`, `)} ${t} ${e[e.length-1]}`}function u(n,r,i){let[a,l]=r,u=o(a);return u===void 0?e:`${s(u,i)} ${t[n]} ${c(l,u,i)}`}function d(t,n){let[r,i]=t,a=o(r);if(a===void 0||!Array.isArray(i))return e;let u=i.map(e=>c(e,a,n));return`${s(a,n)} is ${l(u,`or`)}`}function f(e){return e===!0?`Always`:e===!1?`Never`:e==null?`Always`:null}function p(e){return e.includes(` is not `)?e.replace(` is not `,` is `):e.includes(` is `)?e.replace(` is `,` is not `):e.endsWith(` has an answer`)?`${e.slice(0,-14)} has no answer`:`not: ${e}`}function m(n,r,i){if(n in t)return r.length>=2?u(n,r,i):e;if(n===`and`||n===`or`)return r.length===0?e:l(r.map(e=>h(e,i)),n);if(n===`!`||n===`not`){let t=h(r[0],i);return t===`a rule this panel can't put into words`?e:p(t)}if(n===`!!`){let t=o(r[0]);return t===void 0?e:`${s(t,i)} has an answer`}return n===`in`?d(r,i):e}function h(t,n){let a=f(t);if(a!==null)return a;let c=o(t);if(c!==void 0)return`${s(c,n)} has an answer`;let l=i(t);if(l===void 0||!r(t))return e;let u=t[l];return m(l,Array.isArray(u)?u:[u],n)}export{e as UNDESCRIBABLE,h as describeRule,o as varKeyOf};
1
+ var e=`a rule this panel can't put into words`,t={"==":`is`,"===":`is`,"!=":`is not`,"!==":`is not`,">":`is more than`,">=":`is at least`,"<":`is less than`,"<=":`is at most`},n=`responses.`;function r(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function i(e){if(!r(e))return;let t=Object.keys(e);return t.length===1?t[0]:void 0}function a(e){if(typeof e==`string`)return e;if(Array.isArray(e)&&typeof e[0]==`string`)return e[0]}function o(e){if(!r(e)||i(e)!==`var`)return;let t=a(e.var);if(t!==void 0)return t.startsWith(n)?t.slice(10):t}function s(e,t){let n=t(e)?.name?.trim();return n!==void 0&&n.length>0?n:e.replace(/[-_]+/g,` `)}function c(t,n,r){if(n!==void 0){let e=r(n)?.options?.find(e=>e.value===t);if(e!==void 0)return e.label}return t===null?`nothing`:t===!0?`yes`:t===!1?`no`:typeof t==`string`?t.length===0?`nothing`:t:typeof t==`number`?String(t):e}function l(e,t){return e.length<=1?e.join(``):e.length===2?`${e[0]} ${t} ${e[1]}`:`${e.slice(0,-1).join(`, `)} ${t} ${e[e.length-1]}`}function u(n,r,i){let[a,l]=r,u=o(a);return u===void 0?e:`${s(u,i)} ${t[n]} ${c(l,u,i)}`}function d(t,n){let[r,i]=t,a=o(r);if(a===void 0||!Array.isArray(i))return e;let u=i.map(e=>c(e,a,n));return`${s(a,n)} is ${l(u,`or`)}`}function f(e){return e===!0?`Always`:e===!1?`Never`:e==null?`Always`:null}function p(e){return e.includes(` is not `)?e.replace(` is not `,` is `):e.includes(` is `)?e.replace(` is `,` is not `):e.endsWith(` has a response`)?`${e.slice(0,-15)} has no response`:`not: ${e}`}function m(n,r,i){if(n in t)return r.length>=2?u(n,r,i):e;if(n===`and`||n===`or`)return r.length===0?e:l(r.map(e=>h(e,i)),n);if(n===`!`||n===`not`){let t=h(r[0],i);return t===`a rule this panel can't put into words`?e:p(t)}if(n===`!!`){let t=o(r[0]);return t===void 0?e:`${s(t,i)} has a response`}return n===`in`?d(r,i):e}function h(t,n){let a=f(t);if(a!==null)return a;let c=o(t);if(c!==void 0)return`${s(c,n)} has a response`;let l=i(t);if(l===void 0||!r(t))return e;let u=t[l];return m(l,Array.isArray(u)?u:[u],n)}export{e as UNDESCRIBABLE,h as describeRule,o as varKeyOf};
@@ -1 +1 @@
1
- function e(e){return e.readOnly?{readOnly:!0,canEditAnswers:!1,canNavigate:!1,reason:`You're on the live site — this is read-only so a real customer's session can't be changed.`,label:e.environmentLabel??`Live site`}:{readOnly:!1,canEditAnswers:!0,canNavigate:!0,reason:null,label:e.environmentLabel??null}}export{e as derivePosture};
1
+ function e(e){return e.readOnly?{readOnly:!0,canEditAnswers:!1,canNavigate:!1,reason:`You're on the live site — this is read-only so a real visitor's session can't be changed.`,label:e.environmentLabel??`Live site`}:{readOnly:!1,canEditAnswers:!0,canNavigate:!0,reason:null,label:e.environmentLabel??null}}export{e as derivePosture};
@@ -5,4 +5,4 @@ export type * from './plugin';
5
5
  export type * from './options';
6
6
  export type { CustomTool, CustomToolGuide, CustomToolIcon, CustomToolPlacement, } from './customTools';
7
7
  export type { DevtoolsSession } from './session-access';
8
- export type { PersonaDefinition, PersonaLoader } from './derive/personas';
8
+ export type { PersonaDefinition, PersonaSetup } from './derive/personas';
@@ -11,13 +11,20 @@
11
11
  autoHide: boolean
12
12
  /** The tag beside the button: a preview session, a preview whose workspace is gone, or none. */
13
13
  preview: 'preview' | 'unavailable' | null
14
+ /** The persona the tab walks through as, named in the tag; `null` outside a persona session. */
15
+ walkingAs?: string | null
14
16
  /** Opens the panel. */
15
17
  onOpen: () => void
16
18
  }
17
19
 
18
- const { position, autoHide, preview, onOpen }: Props = $props()
20
+ const { position, autoHide, preview, walkingAs = null, onOpen }: Props = $props()
19
21
 
20
22
  const edges = $derived(launcherEdges(position))
23
+ const tag = $derived(
24
+ [preview === 'preview' ? 'Preview mode' : '', walkingAs === null ? '' : `As ${walkingAs}`]
25
+ .filter((part) => part.length > 0)
26
+ .join(' · '),
27
+ )
21
28
  </script>
22
29
 
23
30
  <div
@@ -33,12 +40,14 @@
33
40
  aria-live="polite"
34
41
  title="This preview link's workspace no longer exists. The published site is shown."
35
42
  >Preview unavailable — showing published</span>
36
- {:else if preview === 'preview'}
37
- <span class="preview-tag" role="status" aria-live="polite">Preview mode</span>
43
+ {:else if tag.length > 0}
44
+ <span class="preview-tag" role="status" aria-live="polite" data-testid="devtools-launcher-tag">
45
+ {tag}
46
+ </span>
38
47
  {/if}
39
48
  <button
40
49
  class="floating-button"
41
- class:has-preview-tag={preview !== null}
50
+ class:has-preview-tag={preview === 'unavailable' || tag.length > 0}
42
51
  onclick={onOpen}
43
52
  aria-label="Open Picked Devtools"
44
53
  title="Open Picked Devtools"
@@ -20,26 +20,27 @@ export interface LauncherOptions {
20
20
  */
21
21
  autoHide?: boolean;
22
22
  }
23
- /** How loading a persona walks the journey. */
23
+ /** How loading a persona walks an experience. */
24
24
  export interface PersonaWalkOptions {
25
25
  /**
26
26
  * Step keys that move on by themselves, such as a loader that continues once its fetch lands.
27
- * The walk waits on them, where it presses Continue on any other screen.
27
+ * The walk waits on them, where it presses Continue on any other step.
28
28
  */
29
29
  selfAdvancingSteps?: readonly string[];
30
30
  /**
31
- * Answers every walk gives when a screen asks them, over the persona's own, such as "start over"
32
- * on a resume prompt.
31
+ * Responses every walk gives when a step asks for their fields, over the persona's own, such as
32
+ * "start over" on a resume prompt.
33
33
  */
34
- answers?: Readonly<Record<string, FieldValue>>;
34
+ responses?: Readonly<Record<string, FieldValue>>;
35
35
  /**
36
- * Actions that open another journey, by action key, with the journey's experience key. Building a
37
- * persona in the panel carries on in that journey where the action is; a launch node needs none.
36
+ * Actions that open another experience, by action key, with that experience's key. Building a
37
+ * persona in the panel carries on in that experience where the action is; a launch node needs
38
+ * none.
38
39
  */
39
40
  handoffs?: Readonly<Record<string, string>>;
40
41
  }
41
- /** A button the Answers tab shows after an answer is edited. */
42
- export interface AnswerFollowUp {
42
+ /** A button the Responses tab shows after a response is edited. */
43
+ export interface ResponseFollowUp {
43
44
  /** The button's text. */
44
45
  label: string;
45
46
  /** Runs when the button is pressed. */
@@ -71,7 +72,7 @@ export interface DevtoolsGuide {
71
72
  /** The options read by the devtools panel, as passed to `svelteDevtoolsPlugin`. */
72
73
  export interface DevtoolsPanelOptions {
73
74
  /**
74
- * When `true`, the panel withholds every write — answer edits, clears and resets, journey jumps —
75
+ * When `true`, the panel withholds every write — response edits, clears and resets, step jumps —
75
76
  * and says why. For a session that may belong to a real visitor, such as a preview link opened
76
77
  * on a live site. A preview token alone never makes a session read-only.
77
78
  *
@@ -80,27 +81,28 @@ export interface DevtoolsPanelOptions {
80
81
  readOnly?: boolean;
81
82
  /** The environment's name, shown as a badge in the panel header. */
82
83
  environmentLabel?: string;
83
- /** Experience keys the journey views never list or follow, such as a host's own internal widgets. */
84
+ /** Experience keys the panel never lists or follows, such as a host's own internal widgets. */
84
85
  hiddenExperienceKeys?: readonly string[];
85
86
  /**
86
87
  * Experience keys, topmost first. When several experiences are open, the first one listed here
87
- * is the journey the panel follows. Unlisted ones follow the most recently opened.
88
+ * is the experience the panel follows. Unlisted ones follow the most recently opened.
88
89
  */
89
- journeyPrecedence?: readonly string[];
90
- /** Field keys committed by code rather than answered by the visitor; Answers leaves them out. */
90
+ experiencePrecedence?: readonly string[];
91
+ /** Field keys that code commits and no visitor fills in; Responses leaves them out. */
91
92
  codeOwnedFields?: readonly string[];
92
- /** A button the Answers tab offers after an edit, such as re-running a fetch the answers feed. */
93
- answerFollowUp?: AnswerFollowUp;
93
+ /** A button the Responses tab offers after an edit, such as one that re-runs a fetch. */
94
+ responseFollowUp?: ResponseFollowUp;
94
95
  /** How to use content for host features that are not devtools tabs. */
95
96
  guide?: DevtoolsGuide;
96
97
  /** The floating button's corner and auto-hide. */
97
98
  launcher?: LauncherOptions;
98
99
  /**
99
- * Customers and situations every viewer can load from the Personas & Scenarios tab. Reviewers
100
- * also save their own there, in their browser.
100
+ * Visitors and situations every viewer can load from the Personas & Scenarios tab, or a function
101
+ * that loads them, such as a dynamic import a production build can drop. Reviewers also save
102
+ * their own there, in their browser.
101
103
  */
102
- personas?: readonly PersonaDefinition[];
103
- /** How loading a persona walks the journey. */
104
+ personas?: readonly PersonaDefinition[] | (() => Promise<readonly PersonaDefinition[]>);
105
+ /** How loading a persona walks an experience. */
104
106
  personaWalk?: PersonaWalkOptions;
105
107
  }
106
108
  /** The devtools options with every default applied. */
@@ -109,18 +111,19 @@ export interface ResolvedDevtoolsOptions {
109
111
  environmentLabel: string | undefined;
110
112
  /** Always includes the devtools experience itself. */
111
113
  hiddenExperienceKeys: ReadonlySet<string>;
112
- journeyPrecedence: readonly string[];
114
+ experiencePrecedence: readonly string[];
113
115
  codeOwnedFields: ReadonlySet<string>;
114
- answerFollowUp: AnswerFollowUp | null;
116
+ responseFollowUp: ResponseFollowUp | null;
115
117
  guide: {
116
118
  sections: Required<DevtoolsGuideSection>[];
117
119
  fixes: DevtoolsGuideFix[];
118
120
  };
119
121
  launcher: Required<LauncherOptions>;
120
- personas: Persona[];
122
+ /** The site's personas, loaded on the first call. */
123
+ personas: () => Promise<Persona[]>;
121
124
  personaWalk: {
122
125
  selfAdvancingSteps: ReadonlySet<string>;
123
- answers: Readonly<Record<string, FieldValue>>;
126
+ responses: Readonly<Record<string, FieldValue>>;
124
127
  handoffs: Readonly<Record<string, string>>;
125
128
  };
126
129
  }
@@ -1 +1 @@
1
- import{DEVTOOLS_EXPERIENCE_KEY as e,DEVTOOLS_PLUGIN_NAME as t}from"./constants.js";import{readAnswers as n,sitePersonas as r}from"./derive/personas/personas.js";var i=[`top-left`,`top-right`,`bottom-left`,`bottom-right`];function a(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function o(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}function s(e){if(!a(e))return{};let t={};for(let[n,r]of Object.entries(e))typeof r==`string`&&(t[n]=r);return t}function c(e){return i.some(t=>t===e)}function l(e){if(!a(e))return null;let{id:t,title:n,steps:r,notes:i}=e;return typeof t!=`string`||typeof n!=`string`||!Array.isArray(r)?null:{id:t,title:n,steps:o(r),notes:o(i)}}function u(e){if(!a(e))return null;let{problem:t,fix:n}=e;return typeof t!=`string`||typeof n!=`string`?null:{problem:t,fix:n}}function d(e){if(!a(e))return null;let{label:t,run:n}=e;return typeof t!=`string`||typeof n!=`function`?null:{label:t,run:e=>{Reflect.apply(n,void 0,[e])}}}function f(i){let f=i.getPluginConfig(t).options,p=a(f)?f:{},m=a(p.guide)?p.guide:{},h=a(p.launcher)?p.launcher:{},g=a(p.personaWalk)?p.personaWalk:{},_=p.environmentLabel;return{readOnly:p.readOnly===!0,environmentLabel:typeof _==`string`&&_.length>0?_:void 0,hiddenExperienceKeys:new Set([e,...o(p.hiddenExperienceKeys)]),journeyPrecedence:o(p.journeyPrecedence),codeOwnedFields:new Set(o(p.codeOwnedFields)),answerFollowUp:d(p.answerFollowUp),guide:{sections:(Array.isArray(m.sections)?m.sections:[]).map(l).filter(e=>e!==null),fixes:(Array.isArray(m.fixes)?m.fixes:[]).map(u).filter(e=>e!==null)},launcher:{position:c(h.position)?h.position:`bottom-right`,autoHide:typeof h.autoHide!=`boolean`||h.autoHide},personas:r(p.personas),personaWalk:{selfAdvancingSteps:new Set(o(g.selfAdvancingSteps)),answers:n(g.answers),handoffs:s(g.handoffs)}}}export{e as DEVTOOLS_EXPERIENCE_KEY,i as LAUNCHER_POSITIONS,f as readDevtoolsOptions};
1
+ import{DEVTOOLS_EXPERIENCE_KEY as e,DEVTOOLS_PLUGIN_NAME as t}from"./constants.js";import{readAnswers as n,sitePersonas as r}from"./derive/personas/personas.js";var i=[`top-left`,`top-right`,`bottom-left`,`bottom-right`];function a(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function o(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}function s(e){if(!a(e))return{};let t={};for(let[n,r]of Object.entries(e))typeof r==`string`&&(t[n]=r);return t}function c(e){return i.some(t=>t===e)}function l(e){if(!a(e))return null;let{id:t,title:n,steps:r,notes:i}=e;return typeof t!=`string`||typeof n!=`string`||!Array.isArray(r)?null:{id:t,title:n,steps:o(r),notes:o(i)}}function u(e){if(!a(e))return null;let{problem:t,fix:n}=e;return typeof t!=`string`||typeof n!=`string`?null:{problem:t,fix:n}}function d(e){if(!a(e))return null;let{label:t,run:n}=e;return typeof t!=`string`||typeof n!=`function`?null:{label:t,run:e=>{Reflect.apply(n,void 0,[e])}}}function f(e){if(typeof e!=`function`){let t=r(e);return()=>Promise.resolve(t)}let t=null;return()=>(t??=Promise.resolve().then(()=>Reflect.apply(e,void 0,[])).then(e=>r(e)).catch(()=>[]),t)}function p(r){let i=r.getPluginConfig(t).options,p=a(i)?i:{},m=a(p.guide)?p.guide:{},h=a(p.launcher)?p.launcher:{},g=a(p.personaWalk)?p.personaWalk:{},_=p.environmentLabel;return{readOnly:p.readOnly===!0,environmentLabel:typeof _==`string`&&_.length>0?_:void 0,hiddenExperienceKeys:new Set([e,...o(p.hiddenExperienceKeys)]),experiencePrecedence:o(p.experiencePrecedence),codeOwnedFields:new Set(o(p.codeOwnedFields)),responseFollowUp:d(p.responseFollowUp),guide:{sections:(Array.isArray(m.sections)?m.sections:[]).map(l).filter(e=>e!==null),fixes:(Array.isArray(m.fixes)?m.fixes:[]).map(u).filter(e=>e!==null)},launcher:{position:c(h.position)?h.position:`bottom-right`,autoHide:typeof h.autoHide!=`boolean`||h.autoHide},personas:f(p.personas),personaWalk:{selfAdvancingSteps:new Set(o(g.selfAdvancingSteps)),responses:n(g.responses),handoffs:s(g.handoffs)}}}export{e as DEVTOOLS_EXPERIENCE_KEY,i as LAUNCHER_POSITIONS,p as readDevtoolsOptions};