@explorer02/cfm-survey-sdk 0.2.6 → 0.2.8
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.
- package/dist/cli/index.js +25 -25
- package/dist/cli/index.mjs +24 -24
- package/package.json +1 -1
- package/templates/docs/00-integration/agent-execution-flow.md +8 -5
- package/templates/docs/00-integration/agent-operating-contract.md +2 -0
- package/templates/docs/00-integration/apply-ui-config.md +15 -2
- package/templates/docs/00-integration/wizard-chrome-contract.md +84 -11
- package/templates/docs/00-integration/wizard-config-handoff.md +6 -2
- package/templates/docs/00-integration/wizard-post-customize-build.md +405 -0
- package/templates/docs/00-integration/wizard-question-type-styling.md +25 -4
- package/templates/docs/MANIFEST.json +3 -1
- package/templates/docs/index.md +4 -3
- package/templates/docs/templates/Header.tsx +61 -35
- package/templates/docs/templates/Question.tsx +1 -0
- package/templates/docs/templates/RatingScale.tsx +66 -59
- package/templates/docs/templates/uiConfig.ts +33 -0
- package/templates/docs/templates/verify-agent-build.sh +6 -0
- package/templates/preview-harness/preview-bridge.inline.js +17 -3
- package/templates/preview-harness/vite-app/src/preview-live-overrides.css +7 -0
- package/templates/previewBridge.ts +16 -4
- package/templates/survey-theme.css +7 -0
- package/templates/wizard-dist/assets/{PreviewMock-7peNZK-z.js → PreviewMock-tTMvwuEy.js} +1 -1
- package/templates/wizard-dist/assets/{TypePanel-BxHnE3cm.js → TypePanel-B9Ls7BSq.js} +1 -1
- package/templates/wizard-dist/assets/index-CjkIlOUI.css +1 -0
- package/templates/wizard-dist/assets/{index-DtZhNwPS.js → index-CoCrnnxt.js} +6 -6
- package/templates/wizard-dist/index.html +2 -2
- package/templates/wizard-dist/assets/index-BhWM50Yu.css +0 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var jo=Object.defineProperty;var we=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(o,t)=>(typeof require<"u"?require:o)[t]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var B=(e,o)=>()=>(e&&(o=e(e=0)),o);var Ie=(e,o)=>{for(var t in o)jo(e,t,{get:o[t],enumerable:!0})};var c,U=B(()=>{"use strict";c={reset:"\x1B[0m",bold:"\x1B[1m",green:"\x1B[32m",red:"\x1B[31m",cyan:"\x1B[36m",yellow:"\x1B[33m",dim:"\x1B[2m"}});var Q,be=B(()=>{"use strict";Q=["MCQ","TEXTFIELD","NPS_SCALE","CFM_MATRIX","CSAT_MATRIX","RATING_MATRIX","SLIDER_MATRIX","FILE_UPLOAD","TEXT_AND_MEDIA","HEATMAP","RANK_ORDER"]});function Mo(e){let o={};for(let t of e)Xe[t]&&(o[t]={...Xe[t]});return o}function Uo(e=[],o){return{version:"1.0",instanceId:o,surveyTypes:e,global:{surveyTitle:"Customer Feedback Survey",companyName:"Sprinklr",browserTabTitle:"Customer Feedback Survey",thankYouMessage:"Thank you for your valuable feedback!",logo:{fileName:null,url:null},header:{height:120,logoBoxWidth:120,logoBoxHeight:120,logoPadding:10,logoPlacement:"left",showCompanyName:!0,companyNamePlacement:"left",companyNameFontSize:18,companyNameFontWeight:600,companyNameColor:"#1A1F36",backgroundColor:"#FFFFFF",shadowEnabled:!0,borderBottomColor:"#E5E7EB",contentPaddingX:40},footer:{backgroundColor:"#262626",textColor:"#9CA3AF",linkColor:"#9CA3AF",linkHoverColor:"#FFFFFF",showLogo:!0,logoWidth:120,logoHeight:32,logoPlacement:"left",copyrightText:"\xA9 Company Name",layout:"row",paddingY:24,paddingX:40,links:[]},theme:{pageBackground:"#FFFFFF",cardBackground:"#FFFFFF",cardBorderColor:"#E5E7EB",cardPadding:24,cardShadowEnabled:!0,selectedBackground:"#E8F5FD",zebraRowColor:"rgba(249,250,251,0.8)",rowBandColor:"#F3F4F6",validationBorder:"#333333",validationBackground:"#D9D9D9",tooltipBackground:"#1F2937",progressTrackHeight:12,progressTrackColor:"#E5E7EB",progressFillColor:"#1A1F36",stickyChromePaddingTop:16,stickyChromePaddingBottom:20,languageSelectorBackground:"#FFFFFF",languageSelectorTextColor:"#2563EB",languageSelectorBorderColor:"#2563EB"},layout:{showHeader:!0,showFooter:!0,showProgressBar:!0,showLanguageSwitcher:!1,showNextButton:!0,showBackButton:!0,showQuestionNumbers:!0,showRequiredAsterisk:!0,width:"standard",borderStyle:"rounded",fontStyle:"modern"},buttons:{next:"Next",back:"Back",submit:"Submit"},colorScheme:{..._},colorSource:"auto",typography:{fontFamily:"Inter, sans-serif",headingWeight:700},motion:{enabled:!1,durationMs:200}},questionTypes:Mo(e),placeholders:{firstName:"Alex",lastName:"Customer",email:"alex@example.com"},customFields:{},debug:{enabled:!1,sampleAnswers:{}},deploy:{target:"aws",autoDeploy:!1}}}function H(e,o){return{...e,...o??{}}}function qe(e){let o=(e.surveyTypes??[]).filter(r=>Q.includes(r)),t=Uo(o,e.instanceId),n=e.global??{},i=t.global,s={...t.questionTypes};if(e.questionTypes)for(let[r,a]of Object.entries(e.questionTypes))s[r]={...s[r]??{},...a};return{...t,...e,configuredAt:void 0,surveyTypes:o.length?o:t.surveyTypes,global:{...i,...n,header:H(i.header,n.header),footer:H(i.footer,n.footer),theme:H(i.theme,n.theme),layout:H(i.layout,n.layout),buttons:H(i.buttons,n.buttons),logo:H(i.logo,n.logo),colorScheme:H(i.colorScheme,n.colorScheme),typography:H(i.typography,n.typography),motion:H(i.motion,n.motion)},questionTypes:s,placeholders:{...t.placeholders,...e.placeholders??{}},customFields:{...t.customFields,...e.customFields??{}},debug:{enabled:e.debug?.enabled??t.debug?.enabled??!1,sampleAnswers:e.debug?.sampleAnswers??t.debug?.sampleAnswers},deploy:{...t.deploy,...e.deploy??{}}}}var _,Xe,Qe=B(()=>{"use strict";be();_={primary:"#1A1F36",secondary:"#E8F5FD",accent:"#00B5AD",background:"#FFFFFF",text:"#1A1F36",buttonText:"#FFFFFF"},Xe={MCQ:{cardStyle:"outlined",selectedAccent:_.accent,optionGap:8,borderRadius:8,cardPadding:12,selectedBackground:_.secondary,hoverBorderColor:_.accent},TEXTFIELD:{inputRadius:8,focusRing:_.accent,borderColor:"#E5E7EB",inputPadding:12,inputHeight:44,placeholderColor:"#9CA3AF"},NPS_SCALE:{buttonStyle:"standard",selectedFill:_.secondary,labelColor:_.text,trackBarColor:"#F2F2F2",trackHighlightColor:"#FBE8F3",cellSize:40,cellGap:4},CFM_MATRIX:{rowLabelWidth:180,cellSelectedColor:_.accent,headerStyle:"bold",bipolarColumnWidthPercent:25,carouselDotColor:"#2563EB",cellPadding:8},CSAT_MATRIX:{rowLabelWidth:180,cellSelectedColor:_.accent,headerStyle:"bold",bipolarColumnWidthPercent:25,carouselDotColor:_.primary,cellPadding:8,accentColor:_.accent,emojiSize:24,unselectedOpacity:.5,selectedRingColor:_.accent,cellSize:40,tooltipBg:"#1F2937"},RATING_MATRIX:{starColor:"#F59E0B",badgeColor:_.primary,rowLabelWidth:180,unselectedStarOpacity:.5},SLIDER_MATRIX:{trackColor:_.accent,thumbColor:_.primary,tickColor:"#9CA3AF",rowLabelWidth:180,rowBandColor:"#F3F4F6",tickBadgeSize:28},FILE_UPLOAD:{dropzoneStyle:"dashed",accentColor:_.accent,dropzonePadding:24},TEXT_AND_MEDIA:{mediaMaxWidth:100,mediaRadius:8,captionColor:"#6B7280",captionSize:14},HEATMAP:{pinColor:_.accent,pinSize:12,pinBorderColor:"#FFFFFF",overlayOpacity:.3},RANK_ORDER:{itemBg:"#F9FAFB",dragHandleColor:"#9CA3AF",rankBadgeColor:_.primary,itemPadding:12,itemGap:8}}});import*as Ce from"fs";import*as ue from"path";function eo(e){let o={},t=/--cfm-[\w-]+\s*:\s*([^;]+);/g,n;for(;(n=t.exec(e))!==null;){let i=n[0].split(":")[0].trim(),s=n[1].trim();o[i]=s}return o}function b(e){if(!e)return;let o=parseFloat(e.replace(/px$/,""));return Number.isFinite(o)?o:void 0}function Ze(e){if(!e)return;let o=parseFloat(e.replace(/%$/,""));return Number.isFinite(o)?o:void 0}function ge(e){if(!e)return;let o=parseFloat(e);return Number.isFinite(o)?o:void 0}function oo(e){let o={global:{},questionTypes:{}},t=o.global,n={},i={},s={},r={},a={},l={},y={},m=o.questionTypes;if(e["--cfm-primary"]&&(n.primary=e["--cfm-primary"]),e["--cfm-secondary"]&&(n.secondary=e["--cfm-secondary"]),e["--cfm-accent"]&&(n.accent=e["--cfm-accent"]),e["--cfm-background"]&&(n.background=e["--cfm-background"]),e["--cfm-text"]&&(n.text=e["--cfm-text"]),e["--cfm-button-text"]&&(n.buttonText=e["--cfm-button-text"]),e["--cfm-max-width"]&&Ge[e["--cfm-max-width"]]&&(a.width=Ge[e["--cfm-max-width"]]),e["--cfm-border-radius"]&&Ke[e["--cfm-border-radius"]]&&(a.borderStyle=Ke[e["--cfm-border-radius"]]),e["--cfm-font-family"]&&(l.fontFamily=e["--cfm-font-family"],Ye[e["--cfm-font-family"]]&&(a.fontStyle=Ye[e["--cfm-font-family"]])),e["--cfm-heading-weight"]&&(l.headingWeight=ge(e["--cfm-heading-weight"])),e["--cfm-motion-duration"]){let A=b(e["--cfm-motion-duration"]);A!==void 0&&(y.durationMs=A,y.enabled=A>0)}e["--cfm-header-height"]&&(i.height=b(e["--cfm-header-height"])),e["--cfm-header-logo-width"]&&(i.logoBoxWidth=b(e["--cfm-header-logo-width"])),e["--cfm-header-logo-height"]&&(i.logoBoxHeight=b(e["--cfm-header-logo-height"])),e["--cfm-header-logo-padding"]&&(i.logoPadding=b(e["--cfm-header-logo-padding"])),e["--cfm-header-bg"]&&(i.backgroundColor=e["--cfm-header-bg"]),e["--cfm-header-company-color"]&&(i.companyNameColor=e["--cfm-header-company-color"]),e["--cfm-header-company-size"]&&(i.companyNameFontSize=b(e["--cfm-header-company-size"])),e["--cfm-header-company-weight"]&&(i.companyNameFontWeight=ge(e["--cfm-header-company-weight"])),e["--cfm-header-border"]&&(i.borderBottomColor=e["--cfm-header-border"]),e["--cfm-header-padding-x"]&&(i.contentPaddingX=b(e["--cfm-header-padding-x"])),e["--cfm-footer-bg"]&&(s.backgroundColor=e["--cfm-footer-bg"]),e["--cfm-footer-text"]&&(s.textColor=e["--cfm-footer-text"]),e["--cfm-footer-link"]&&(s.linkColor=e["--cfm-footer-link"]),e["--cfm-footer-link-hover"]&&(s.linkHoverColor=e["--cfm-footer-link-hover"]),e["--cfm-footer-logo-width"]&&(s.logoWidth=b(e["--cfm-footer-logo-width"])),e["--cfm-footer-logo-height"]&&(s.logoHeight=b(e["--cfm-footer-logo-height"])),e["--cfm-footer-padding-y"]&&(s.paddingY=b(e["--cfm-footer-padding-y"])),e["--cfm-footer-padding-x"]&&(s.paddingX=b(e["--cfm-footer-padding-x"])),e["--cfm-background"]&&(r.pageBackground=e["--cfm-background"]),e["--cfm-card-bg"]&&(r.cardBackground=e["--cfm-card-bg"]),e["--cfm-card-border-color"]&&(r.cardBorderColor=e["--cfm-card-border-color"]),e["--cfm-card-padding"]&&(r.cardPadding=b(e["--cfm-card-padding"])),e["--cfm-card-shadow"]&&(r.cardShadowEnabled=e["--cfm-card-shadow"]!=="none"),e["--cfm-selected-bg"]&&(r.selectedBackground=e["--cfm-selected-bg"]),e["--cfm-zebra-row"]&&(r.zebraRowColor=e["--cfm-zebra-row"]),e["--cfm-row-band"]&&(r.rowBandColor=e["--cfm-row-band"]),e["--cfm-validation-border"]&&(r.validationBorder=e["--cfm-validation-border"]),e["--cfm-validation-bg"]&&(r.validationBackground=e["--cfm-validation-bg"]),e["--cfm-tooltip-bg"]&&(r.tooltipBackground=e["--cfm-tooltip-bg"]),e["--cfm-progress-height"]&&(r.progressTrackHeight=b(e["--cfm-progress-height"])),e["--cfm-progress-track"]&&(r.progressTrackColor=e["--cfm-progress-track"]),e["--cfm-progress-fill"]&&(r.progressFillColor=e["--cfm-progress-fill"]),e["--cfm-sticky-pt"]&&(r.stickyChromePaddingTop=b(e["--cfm-sticky-pt"])),e["--cfm-sticky-pb"]&&(r.stickyChromePaddingBottom=b(e["--cfm-sticky-pb"]));let C={};e["--cfm-mcq-selected-accent"]&&(C.selectedAccent=e["--cfm-mcq-selected-accent"]),e["--cfm-mcq-border-radius"]&&(C.borderRadius=b(e["--cfm-mcq-border-radius"])),e["--cfm-mcq-option-gap"]&&(C.optionGap=b(e["--cfm-mcq-option-gap"])),e["--cfm-mcq-card-padding"]&&(C.cardPadding=b(e["--cfm-mcq-card-padding"])),e["--cfm-mcq-selected-bg"]&&(C.selectedBackground=e["--cfm-mcq-selected-bg"]),e["--cfm-mcq-hover-border"]&&(C.hoverBorderColor=e["--cfm-mcq-hover-border"]),Object.keys(C).length&&(m.MCQ=C);let S={};e["--cfm-input-radius"]&&(S.inputRadius=b(e["--cfm-input-radius"])),e["--cfm-input-focus-ring"]&&(S.focusRing=e["--cfm-input-focus-ring"]),e["--cfm-input-border"]&&(S.borderColor=e["--cfm-input-border"]),e["--cfm-input-padding"]&&(S.inputPadding=b(e["--cfm-input-padding"])),e["--cfm-input-height"]&&(S.inputHeight=b(e["--cfm-input-height"])),e["--cfm-input-placeholder"]&&(S.placeholderColor=e["--cfm-input-placeholder"]),Object.keys(S).length&&(m.TEXTFIELD=S);let E={};e["--cfm-nps-selected-fill"]&&(E.selectedFill=e["--cfm-nps-selected-fill"]),e["--cfm-nps-label-color"]&&(E.labelColor=e["--cfm-nps-label-color"]),e["--cfm-nps-track-bar"]&&(E.trackBarColor=e["--cfm-nps-track-bar"]),e["--cfm-nps-track-highlight"]&&(E.trackHighlightColor=e["--cfm-nps-track-highlight"]),e["--cfm-nps-cell-size"]&&(E.cellSize=b(e["--cfm-nps-cell-size"])),e["--cfm-nps-cell-gap"]&&(E.cellGap=b(e["--cfm-nps-cell-gap"])),Object.keys(E).length&&(m.NPS_SCALE=E);let v=b(e["--cfm-matrix-row-width"]),x={};v!==void 0&&(x.rowLabelWidth=v),e["--cfm-matrix-selected"]&&(x.cellSelectedColor=e["--cfm-matrix-selected"]),e["--cfm-matrix-bipolar-width"]&&(x.bipolarColumnWidthPercent=Ze(e["--cfm-matrix-bipolar-width"])),e["--cfm-matrix-carousel-dot"]&&(x.carouselDotColor=e["--cfm-matrix-carousel-dot"]),e["--cfm-matrix-cell-padding"]&&(x.cellPadding=b(e["--cfm-matrix-cell-padding"])),Object.keys(x).length&&(m.CFM_MATRIX=x);let d={...x};e["--cfm-csat-accent"]&&(d.accentColor=e["--cfm-csat-accent"]),e["--cfm-csat-emoji-size"]&&(d.emojiSize=b(e["--cfm-csat-emoji-size"])),e["--cfm-csat-unselected-opacity"]&&(d.unselectedOpacity=ge(e["--cfm-csat-unselected-opacity"])),e["--cfm-csat-ring-color"]&&(d.selectedRingColor=e["--cfm-csat-ring-color"]),e["--cfm-csat-cell-size"]&&(d.cellSize=b(e["--cfm-csat-cell-size"])),e["--cfm-csat-tooltip-bg"]&&(d.tooltipBg=e["--cfm-csat-tooltip-bg"]),(Object.keys(d).length>Object.keys(x).length||e["--cfm-csat-accent"])&&(m.CSAT_MATRIX=d);let f={};e["--cfm-star-color"]&&(f.starColor=e["--cfm-star-color"]),e["--cfm-badge-color"]&&(f.badgeColor=e["--cfm-badge-color"]),v!==void 0&&(f.rowLabelWidth=v),e["--cfm-star-unselected-opacity"]&&(f.unselectedStarOpacity=ge(e["--cfm-star-unselected-opacity"])),Object.keys(f).length&&(m.RATING_MATRIX=f);let T={};e["--cfm-slider-track"]&&(T.trackColor=e["--cfm-slider-track"]),e["--cfm-slider-thumb"]&&(T.thumbColor=e["--cfm-slider-thumb"]),e["--cfm-slider-tick"]&&(T.tickColor=e["--cfm-slider-tick"]),v!==void 0&&(T.rowLabelWidth=v),e["--cfm-slider-row-band"]&&(T.rowBandColor=e["--cfm-slider-row-band"]),e["--cfm-slider-tick-size"]&&(T.tickBadgeSize=b(e["--cfm-slider-tick-size"])),Object.keys(T).length&&(m.SLIDER_MATRIX=T);let $={};e["--cfm-upload-accent"]&&($.accentColor=e["--cfm-upload-accent"]),e["--cfm-upload-padding"]&&($.dropzonePadding=b(e["--cfm-upload-padding"])),Object.keys($).length&&(m.FILE_UPLOAD=$);let h={};e["--cfm-media-max-width"]&&(h.mediaMaxWidth=Ze(e["--cfm-media-max-width"])),e["--cfm-media-radius"]&&(h.mediaRadius=b(e["--cfm-media-radius"])),e["--cfm-media-caption-color"]&&(h.captionColor=e["--cfm-media-caption-color"]),e["--cfm-media-caption-size"]&&(h.captionSize=b(e["--cfm-media-caption-size"])),Object.keys(h).length&&(m.TEXT_AND_MEDIA=h);let P={};e["--cfm-heatmap-pin"]&&(P.pinColor=e["--cfm-heatmap-pin"]),e["--cfm-heatmap-pin-size"]&&(P.pinSize=b(e["--cfm-heatmap-pin-size"])),e["--cfm-heatmap-pin-border"]&&(P.pinBorderColor=e["--cfm-heatmap-pin-border"]),e["--cfm-heatmap-overlay-opacity"]&&(P.overlayOpacity=ge(e["--cfm-heatmap-overlay-opacity"])),Object.keys(P).length&&(m.HEATMAP=P);let w={};return e["--cfm-rank-item-bg"]&&(w.itemBg=e["--cfm-rank-item-bg"]),e["--cfm-rank-badge"]&&(w.rankBadgeColor=e["--cfm-rank-badge"]),e["--cfm-rank-handle"]&&(w.dragHandleColor=e["--cfm-rank-handle"]),e["--cfm-rank-item-padding"]&&(w.itemPadding=b(e["--cfm-rank-item-padding"])),e["--cfm-rank-item-gap"]&&(w.itemGap=b(e["--cfm-rank-item-gap"])),Object.keys(w).length&&(m.RANK_ORDER=w),Object.keys(n).length&&(t.colorScheme=n),Object.keys(i).length&&(t.header=i),Object.keys(s).length&&(t.footer=s),Object.keys(r).length&&(t.theme=r),Object.keys(a).length&&(t.layout=a),Object.keys(l).length&&(t.typography=l),Object.keys(y).length&&(t.motion=y),o}function ne(e){let o=[ue.join(e,"src","styles","survey-theme.css"),ue.join(e,"src","app","survey-theme.css"),ue.join(e,"src","styles","globals.css"),ue.join(e,"src","app","globals.css")];for(let t of o)if(Ce.existsSync(t)&&Ce.readFileSync(t,"utf8").includes("--cfm-"))return t;return null}var Ge,Ke,Ye,$e=B(()=>{"use strict";Ge={"36rem":"narrow","48rem":"standard","64rem":"wide"},Ke={"0px":"sharp","12px":"rounded","9999px":"pill"},Ye={"system-ui, sans-serif":"system","Inter, sans-serif":"modern","Georgia, serif":"serif"}});import*as xe from"fs";import*as to from"path";function Bo(e){for(let o of zo){let t=to.join(e,o);if(xe.existsSync(t))return t}return null}function Wo(e){let o=e.trim();if(!o||o.startsWith("http")||o.startsWith("data:"))return null;let t=o.split("?")[0];return t.startsWith("/")?t.slice(1):t}function no(e){let o=Bo(e);if(!o)return null;let t=xe.readFileSync(o,"utf8"),n=t.match(/data-cfm-logo[\s\S]*?src=["']([^"']+)["']/i)??t.match(/src=["']([^"']+)["'][\s\S]*?data-cfm-logo/i);if(n){let r=Wo(n[1]);if(r)return{mode:"image",publicPath:r,fileName:r}}let i=t.match(/data-cfm-logo-text[^>]*>([^<]+)</i);if(i)return{mode:"text",label:i[1].trim()};let s=t.match(/data-cfm-company[^>]*>([^<]+)</i);return s&&!n?{mode:"text",label:s[1].trim()}:null}var zo,io=B(()=>{"use strict";zo=["src/components/Header.tsx","components/Header.tsx","app/components/Header.tsx"]});var lo={};Ie(lo,{logSeedSource:()=>Fe,resolveInitialConfig:()=>re,writeResolvedUiConfig:()=>Ne});import*as W from"fs";import*as V from"path";function je(e){return e.filter(o=>Q.includes(o))}function ro(e){try{let o=JSON.parse(W.readFileSync(e,"utf8"));return o.version!=="1.0"?null:(delete o.configuredAt,o)}catch{return null}}function Vo(e){let o={global:{}};if(!W.existsSync(e))return o;let t=W.readFileSync(e,"utf8"),n=new Set;for(let s of Q)t.includes(s)&&n.add(s);n.size&&(o.surveyTypes=[...n]);let i=t.match(/\*\*Branding source:\*\*\s*(.+)/i);if(i){let s=i[1].trim(),r=s.match(/company[:\s]+([^,;]+)/i),a=s.match(/title[:\s]+([^,;]+)/i);if(r&&(o.global.companyName=r[1].trim()),a){let l=a[1].trim();o.global.surveyTitle=l,o.global.browserTabTitle=l}}return o}function ao(e,o){let t=V.join(e,o);if(!W.existsSync(t))return null;let n=W.readFileSync(t);if(n.length>Jo)return{fileName:o,dataUrl:""};let i=V.extname(o).toLowerCase(),s=Ho[i]??"application/octet-stream";return{fileName:o,dataUrl:`data:${s};base64,${n.toString("base64")}`}}function so(e,o){if(!o)return null;if(o.url&&typeof o.url=="string")return{fileName:o.fileName??null,url:o.url};if(o.fileName){let t=ao(e,o.fileName);if(t)return{fileName:t.fileName,url:t.dataUrl||null}}return o.fileName===null&&o.url===null?{fileName:null,url:null}:null}function co(e,o){let t=e.global??{},n=o.global??{},i=e.questionTypes??{},s=o.questionTypes??{},r={...i};for(let[a,l]of Object.entries(s))r[a]={...r[a]??{},...l};return{...e,...o,surveyTypes:o.surveyTypes??e.surveyTypes,global:{...t,...n,header:{...t.header,...n.header},footer:{...t.footer,...n.footer},theme:{...t.theme,...n.theme},layout:{...t.layout,...n.layout},buttons:{...t.buttons,...n.buttons},logo:{...t.logo,...n.logo},colorScheme:{...t.colorScheme,...n.colorScheme},typography:{...t.typography,...n.typography},motion:{...t.motion,...n.motion}},questionTypes:r,placeholders:{...e.placeholders,...o.placeholders},customFields:{...e.customFields,...o.customFields},deploy:{...e.deploy,...o.deploy}}}function re(e){let o=e.projectRoot??process.env.INIT_CWD??process.cwd(),t=V.join(o,"survey-ui-config.json"),n=V.join(o,"implementation_plan.md"),i=V.join(o,"public"),s=je(e.surveyTypes),r={},a="defaults",l=ne(o);if(l){let w=W.readFileSync(l,"utf8"),A=eo(w);Object.keys(A).length>0&&(r=oo(A),a="survey-theme.css")}let y=Vo(n);r=co(r,y);let m=ro(t);m&&(r=co(r,m),a="survey-ui-config.json");let C=V.join(o,"survey-ui-config.final.json"),S=ro(C),E=!!m?.configuredAt,v=!!S?.configuredAt;if(S&&v&&!E){let w=so(i,S.global?.logo);w&&(r.global={...r.global??{},logo:{fileName:w.fileName,url:w.url}})}let x=so(i,r.global?.logo),d=no(o),f=!!m?.configuredAt,T=x?.fileName!=null&&/^logo_\d+_/i.test(x.fileName),$=d?.mode==="image"?d.fileName:null,h=!f&&T&&$!=null&&x?.fileName!==$;if(x&&!h)r.global={...r.global??{},logo:{fileName:x.fileName,url:x.url}};else if(d?.mode==="image"){let w=ao(i,d.fileName);r.global={...r.global??{},logo:{fileName:d.fileName,url:w?.dataUrl||null}}}else d?.mode==="text"&&(r.global={...r.global??{},logo:{fileName:null,url:null},companyName:r.global?.companyName??d.label});return r.surveyTypes=je(r.surveyTypes??s),r.surveyTypes?.length||(r.surveyTypes=s),e.instanceId&&(r.instanceId=e.instanceId),{config:qe(r),source:a}}function Fe(e){console.log(e==="survey-ui-config.json"?`${ie.dim} Seeding wizard from survey-ui-config.json${ie.reset}`:e==="survey-theme.css"?`${ie.dim} Seeding wizard from survey-theme.css + defaults${ie.reset}`:`${ie.dim} Seeding wizard from SDK defaults${ie.reset}`)}function Ne(e={}){let o=e.projectRoot??process.env.INIT_CWD??process.cwd(),t=e.surveyTypes??je(Q),{config:n}=re({projectRoot:o,surveyTypes:t,instanceId:e.instanceId}),i=V.join(o,"survey-ui-config.json");return W.writeFileSync(i,JSON.stringify(n,null,2),"utf8"),i}var ie,Jo,Ho,pe=B(()=>{"use strict";U();Qe();$e();be();io();ie=c,Jo=512e3,Ho={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml"}});import*as ae from"fs";import*as le from"path";function yo(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function wo(e,o){return JSON.stringify(e)===JSON.stringify(o)}function ce(e){return typeof e=="string"&&e.startsWith("data:")&&e.length>80?`${e.slice(0,48)}\u2026 (${e.length} chars)`:e}function So(e,o,t,n){if(wo(e,o)){n.unchangedCount+=1;return}if(e===void 0&&o!==void 0){n.added.push({path:t,before:void 0,after:ce(o)});return}if(e!==void 0&&o===void 0){n.removed.push({path:t,before:ce(e),after:void 0});return}if(Array.isArray(e)&&Array.isArray(o)){wo(e,o)?n.unchangedCount+=1:n.changed.push({path:t,before:ce(e),after:ce(o)});return}if(yo(e)&&yo(o)){let i=new Set([...Object.keys(e),...Object.keys(o)]);for(let s of i){if(ct.has(s)&&t==="")continue;let r=t?`${t}.${s}`:s;So(e[s],o[s],r,n)}return}n.changed.push({path:t,before:ce(e),after:ce(o)})}function Le(e,o){let t={changed:[],added:[],removed:[],unchangedCount:0};return So(e,o,"",t),t}function ke(e){let o=["# UI Config Diff (seed \u2192 final)","",`**Changed:** ${e.changed.length} \xB7 **Added:** ${e.added.length} \xB7 **Removed:** ${e.removed.length}`,"","> Review only \u2014 run `npx cfm-sdk confirm-ui-config` to apply final config to the project.",""],t=(n,i)=>{if(i.length){o.push(`## ${n}`,"");for(let s of i)o.push(`### \`${s.path}\``),o.push(`- **Before:** \`${JSON.stringify(s.before)}\``),o.push(`- **After:** \`${JSON.stringify(s.after)}\``),o.push("")}};return t("Changed",e.changed),t("Added",e.added),t("Removed",e.removed),!e.changed.length&&!e.added.length&&!e.removed.length&&o.push("_No differences \u2014 final config matches seed._",""),o.join(`
|
|
3
|
-
`)}function K(e){return{seedPath:le.join(e,"survey-ui-config.seed.json"),finalPath:le.join(e,"survey-ui-config.final.json"),diffJsonPath:le.join(e,"survey-ui-config.diff.json"),diffMdPath:le.join(e,"survey-ui-config.diff.md"),activeConfigPath:le.join(e,"survey-ui-config.json")}}function Pe(e,o,t){let n=K(e),i=
|
|
2
|
+
var jo=Object.defineProperty;var we=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(o,t)=>(typeof require<"u"?require:o)[t]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var B=(e,o)=>()=>(e&&(o=e(e=0)),o);var Ie=(e,o)=>{for(var t in o)jo(e,t,{get:o[t],enumerable:!0})};var c,U=B(()=>{"use strict";c={reset:"\x1B[0m",bold:"\x1B[1m",green:"\x1B[32m",red:"\x1B[31m",cyan:"\x1B[36m",yellow:"\x1B[33m",dim:"\x1B[2m"}});var Q,be=B(()=>{"use strict";Q=["MCQ","TEXTFIELD","NPS_SCALE","CFM_MATRIX","CSAT_MATRIX","RATING_MATRIX","SLIDER_MATRIX","FILE_UPLOAD","TEXT_AND_MEDIA","HEATMAP","RANK_ORDER"]});function Mo(e){let o={};for(let t of e)qe[t]&&(o[t]={...qe[t]});return o}function Uo(e=[],o){return{version:"1.0",instanceId:o,surveyTypes:e,global:{surveyTitle:"Customer Feedback Survey",companyName:"Sprinklr",browserTabTitle:"Customer Feedback Survey",thankYouMessage:"Thank you for your valuable feedback!",logo:{fileName:null,url:null},header:{height:120,logoBoxWidth:120,logoBoxHeight:120,logoPadding:10,logoPlacement:"left",showCompanyName:!0,companyNamePlacement:"left",companyNameFontSize:18,companyNameFontWeight:600,companyNameColor:"#1A1F36",backgroundColor:"#FFFFFF",shadowEnabled:!0,borderBottomColor:"#E5E7EB",contentPaddingX:40},footer:{backgroundColor:"#262626",textColor:"#9CA3AF",linkColor:"#9CA3AF",linkHoverColor:"#FFFFFF",showLogo:!0,logoWidth:120,logoHeight:32,logoPlacement:"left",copyrightText:"\xA9 Company Name",layout:"row",paddingY:24,paddingX:40,links:[]},theme:{pageBackground:"#FFFFFF",cardBackground:"#FFFFFF",cardBorderColor:"#E5E7EB",cardPadding:24,cardShadowEnabled:!0,selectedBackground:"#E8F5FD",zebraRowColor:"rgba(249,250,251,0.8)",rowBandColor:"#F3F4F6",validationBorder:"#333333",validationBackground:"#D9D9D9",tooltipBackground:"#1F2937",progressTrackHeight:12,progressTrackColor:"#E5E7EB",progressFillColor:"#1A1F36",stickyChromePaddingTop:16,stickyChromePaddingBottom:20,languageSelectorBackground:"#FFFFFF",languageSelectorTextColor:"#2563EB",languageSelectorBorderColor:"#2563EB"},layout:{showHeader:!0,showFooter:!0,showProgressBar:!0,showLanguageSwitcher:!1,showNextButton:!0,showBackButton:!0,showQuestionNumbers:!0,showRequiredAsterisk:!0,width:"standard",borderStyle:"rounded",fontStyle:"modern"},buttons:{next:"Next",back:"Back",submit:"Submit"},colorScheme:{..._},colorSource:"auto",typography:{fontFamily:"Inter, sans-serif",headingWeight:700},motion:{enabled:!1,durationMs:200}},questionTypes:Mo(e),placeholders:{firstName:"Alex",lastName:"Customer",email:"alex@example.com"},customFields:{},debug:{enabled:!1,sampleAnswers:{}},deploy:{target:"aws",autoDeploy:!1}}}function H(e,o){return{...e,...o??{}}}function Qe(e){let o=(e.surveyTypes??[]).filter(r=>Q.includes(r)),t=Uo(o,e.instanceId),n=e.global??{},i=t.global,s={...t.questionTypes};if(e.questionTypes)for(let[r,a]of Object.entries(e.questionTypes))s[r]={...s[r]??{},...a};return{...t,...e,configuredAt:void 0,surveyTypes:o.length?o:t.surveyTypes,global:{...i,...n,header:H(i.header,n.header),footer:H(i.footer,n.footer),theme:H(i.theme,n.theme),layout:H(i.layout,n.layout),buttons:H(i.buttons,n.buttons),logo:H(i.logo,n.logo),colorScheme:H(i.colorScheme,n.colorScheme),typography:H(i.typography,n.typography),motion:H(i.motion,n.motion)},questionTypes:s,placeholders:{...t.placeholders,...e.placeholders??{}},customFields:{...t.customFields,...e.customFields??{}},debug:{enabled:e.debug?.enabled??t.debug?.enabled??!1,sampleAnswers:e.debug?.sampleAnswers??t.debug?.sampleAnswers},deploy:{...t.deploy,...e.deploy??{}}}}var _,qe,Ge=B(()=>{"use strict";be();_={primary:"#1A1F36",secondary:"#E8F5FD",accent:"#00B5AD",background:"#FFFFFF",text:"#1A1F36",buttonText:"#FFFFFF"},qe={MCQ:{cardStyle:"outlined",selectedAccent:_.accent,optionGap:8,borderRadius:8,cardPadding:12,selectedBackground:_.secondary,hoverBorderColor:_.accent},TEXTFIELD:{inputRadius:8,focusRing:_.accent,borderColor:"#E5E7EB",inputPadding:12,inputHeight:44,placeholderColor:"#9CA3AF"},NPS_SCALE:{buttonStyle:"standard",selectedFill:_.secondary,labelColor:_.text,trackBarColor:"#F2F2F2",trackHighlightColor:"#FBE8F3",cellSize:40,cellGap:4},CFM_MATRIX:{rowLabelWidth:180,cellSelectedColor:_.accent,headerStyle:"bold",bipolarColumnWidthPercent:25,carouselDotColor:"#2563EB",cellPadding:8},CSAT_MATRIX:{rowLabelWidth:180,cellSelectedColor:_.accent,headerStyle:"bold",bipolarColumnWidthPercent:25,carouselDotColor:_.primary,cellPadding:8,accentColor:_.accent,emojiSize:24,unselectedOpacity:.5,selectedRingColor:_.accent,cellSize:40,tooltipBg:"#1F2937"},RATING_MATRIX:{starColor:"#F59E0B",badgeColor:_.primary,rowLabelWidth:180,unselectedStarOpacity:.5},SLIDER_MATRIX:{trackColor:_.accent,thumbColor:_.primary,tickColor:"#9CA3AF",rowLabelWidth:180,rowBandColor:"#F3F4F6",tickBadgeSize:28},FILE_UPLOAD:{dropzoneStyle:"dashed",accentColor:_.accent,dropzonePadding:24},TEXT_AND_MEDIA:{mediaMaxWidth:100,mediaRadius:8,captionColor:"#6B7280",captionSize:14},HEATMAP:{pinColor:_.accent,pinSize:12,pinBorderColor:"#FFFFFF",overlayOpacity:.3},RANK_ORDER:{itemBg:"#F9FAFB",dragHandleColor:"#9CA3AF",rankBadgeColor:_.primary,itemPadding:12,itemGap:8}}});import*as Ce from"fs";import*as ue from"path";function oo(e){let o={},t=/--cfm-[\w-]+\s*:\s*([^;]+);/g,n;for(;(n=t.exec(e))!==null;){let i=n[0].split(":")[0].trim(),s=n[1].trim();o[i]=s}return o}function b(e){if(!e)return;let o=parseFloat(e.replace(/px$/,""));return Number.isFinite(o)?o:void 0}function eo(e){if(!e)return;let o=parseFloat(e.replace(/%$/,""));return Number.isFinite(o)?o:void 0}function ge(e){if(!e)return;let o=parseFloat(e);return Number.isFinite(o)?o:void 0}function to(e){let o={global:{},questionTypes:{}},t=o.global,n={},i={},s={},r={},a={},l={},y={},m=o.questionTypes;if(e["--cfm-primary"]&&(n.primary=e["--cfm-primary"]),e["--cfm-secondary"]&&(n.secondary=e["--cfm-secondary"]),e["--cfm-accent"]&&(n.accent=e["--cfm-accent"]),e["--cfm-background"]&&(n.background=e["--cfm-background"]),e["--cfm-text"]&&(n.text=e["--cfm-text"]),e["--cfm-button-text"]&&(n.buttonText=e["--cfm-button-text"]),e["--cfm-max-width"]&&Ke[e["--cfm-max-width"]]&&(a.width=Ke[e["--cfm-max-width"]]),e["--cfm-border-radius"]&&Ye[e["--cfm-border-radius"]]&&(a.borderStyle=Ye[e["--cfm-border-radius"]]),e["--cfm-font-family"]&&(l.fontFamily=e["--cfm-font-family"],Ze[e["--cfm-font-family"]]&&(a.fontStyle=Ze[e["--cfm-font-family"]])),e["--cfm-heading-weight"]&&(l.headingWeight=ge(e["--cfm-heading-weight"])),e["--cfm-motion-duration"]){let A=b(e["--cfm-motion-duration"]);A!==void 0&&(y.durationMs=A,y.enabled=A>0)}e["--cfm-header-height"]&&(i.height=b(e["--cfm-header-height"])),e["--cfm-header-logo-width"]&&(i.logoBoxWidth=b(e["--cfm-header-logo-width"])),e["--cfm-header-logo-height"]&&(i.logoBoxHeight=b(e["--cfm-header-logo-height"])),e["--cfm-header-logo-padding"]&&(i.logoPadding=b(e["--cfm-header-logo-padding"])),e["--cfm-header-bg"]&&(i.backgroundColor=e["--cfm-header-bg"]),e["--cfm-header-company-color"]&&(i.companyNameColor=e["--cfm-header-company-color"]),e["--cfm-header-company-size"]&&(i.companyNameFontSize=b(e["--cfm-header-company-size"])),e["--cfm-header-company-weight"]&&(i.companyNameFontWeight=ge(e["--cfm-header-company-weight"])),e["--cfm-header-border"]&&(i.borderBottomColor=e["--cfm-header-border"]),e["--cfm-header-padding-x"]&&(i.contentPaddingX=b(e["--cfm-header-padding-x"])),e["--cfm-footer-bg"]&&(s.backgroundColor=e["--cfm-footer-bg"]),e["--cfm-footer-text"]&&(s.textColor=e["--cfm-footer-text"]),e["--cfm-footer-link"]&&(s.linkColor=e["--cfm-footer-link"]),e["--cfm-footer-link-hover"]&&(s.linkHoverColor=e["--cfm-footer-link-hover"]),e["--cfm-footer-logo-width"]&&(s.logoWidth=b(e["--cfm-footer-logo-width"])),e["--cfm-footer-logo-height"]&&(s.logoHeight=b(e["--cfm-footer-logo-height"])),e["--cfm-footer-padding-y"]&&(s.paddingY=b(e["--cfm-footer-padding-y"])),e["--cfm-footer-padding-x"]&&(s.paddingX=b(e["--cfm-footer-padding-x"])),e["--cfm-background"]&&(r.pageBackground=e["--cfm-background"]),e["--cfm-card-bg"]&&(r.cardBackground=e["--cfm-card-bg"]),e["--cfm-card-border-color"]&&(r.cardBorderColor=e["--cfm-card-border-color"]),e["--cfm-card-padding"]&&(r.cardPadding=b(e["--cfm-card-padding"])),e["--cfm-card-shadow"]&&(r.cardShadowEnabled=e["--cfm-card-shadow"]!=="none"),e["--cfm-selected-bg"]&&(r.selectedBackground=e["--cfm-selected-bg"]),e["--cfm-zebra-row"]&&(r.zebraRowColor=e["--cfm-zebra-row"]),e["--cfm-row-band"]&&(r.rowBandColor=e["--cfm-row-band"]),e["--cfm-validation-border"]&&(r.validationBorder=e["--cfm-validation-border"]),e["--cfm-validation-bg"]&&(r.validationBackground=e["--cfm-validation-bg"]),e["--cfm-tooltip-bg"]&&(r.tooltipBackground=e["--cfm-tooltip-bg"]),e["--cfm-progress-height"]&&(r.progressTrackHeight=b(e["--cfm-progress-height"])),e["--cfm-progress-track"]&&(r.progressTrackColor=e["--cfm-progress-track"]),e["--cfm-progress-fill"]&&(r.progressFillColor=e["--cfm-progress-fill"]),e["--cfm-sticky-pt"]&&(r.stickyChromePaddingTop=b(e["--cfm-sticky-pt"])),e["--cfm-sticky-pb"]&&(r.stickyChromePaddingBottom=b(e["--cfm-sticky-pb"]));let C={};e["--cfm-mcq-selected-accent"]&&(C.selectedAccent=e["--cfm-mcq-selected-accent"]),e["--cfm-mcq-border-radius"]&&(C.borderRadius=b(e["--cfm-mcq-border-radius"])),e["--cfm-mcq-option-gap"]&&(C.optionGap=b(e["--cfm-mcq-option-gap"])),e["--cfm-mcq-card-padding"]&&(C.cardPadding=b(e["--cfm-mcq-card-padding"])),e["--cfm-mcq-selected-bg"]&&(C.selectedBackground=e["--cfm-mcq-selected-bg"]),e["--cfm-mcq-hover-border"]&&(C.hoverBorderColor=e["--cfm-mcq-hover-border"]),Object.keys(C).length&&(m.MCQ=C);let S={};e["--cfm-input-radius"]&&(S.inputRadius=b(e["--cfm-input-radius"])),e["--cfm-input-focus-ring"]&&(S.focusRing=e["--cfm-input-focus-ring"]),e["--cfm-input-border"]&&(S.borderColor=e["--cfm-input-border"]),e["--cfm-input-padding"]&&(S.inputPadding=b(e["--cfm-input-padding"])),e["--cfm-input-height"]&&(S.inputHeight=b(e["--cfm-input-height"])),e["--cfm-input-placeholder"]&&(S.placeholderColor=e["--cfm-input-placeholder"]),Object.keys(S).length&&(m.TEXTFIELD=S);let E={};e["--cfm-nps-selected-fill"]&&(E.selectedFill=e["--cfm-nps-selected-fill"]),e["--cfm-nps-label-color"]&&(E.labelColor=e["--cfm-nps-label-color"]),e["--cfm-nps-track-bar"]&&(E.trackBarColor=e["--cfm-nps-track-bar"]),e["--cfm-nps-track-highlight"]&&(E.trackHighlightColor=e["--cfm-nps-track-highlight"]),e["--cfm-nps-cell-size"]&&(E.cellSize=b(e["--cfm-nps-cell-size"])),e["--cfm-nps-cell-gap"]&&(E.cellGap=b(e["--cfm-nps-cell-gap"])),Object.keys(E).length&&(m.NPS_SCALE=E);let v=b(e["--cfm-matrix-row-width"]),x={};v!==void 0&&(x.rowLabelWidth=v),e["--cfm-matrix-selected"]&&(x.cellSelectedColor=e["--cfm-matrix-selected"]),e["--cfm-matrix-bipolar-width"]&&(x.bipolarColumnWidthPercent=eo(e["--cfm-matrix-bipolar-width"])),e["--cfm-matrix-carousel-dot"]&&(x.carouselDotColor=e["--cfm-matrix-carousel-dot"]),e["--cfm-matrix-cell-padding"]&&(x.cellPadding=b(e["--cfm-matrix-cell-padding"])),Object.keys(x).length&&(m.CFM_MATRIX=x);let d={...x};e["--cfm-csat-accent"]&&(d.accentColor=e["--cfm-csat-accent"]),e["--cfm-csat-emoji-size"]&&(d.emojiSize=b(e["--cfm-csat-emoji-size"])),e["--cfm-csat-unselected-opacity"]&&(d.unselectedOpacity=ge(e["--cfm-csat-unselected-opacity"])),e["--cfm-csat-ring-color"]&&(d.selectedRingColor=e["--cfm-csat-ring-color"]),e["--cfm-csat-cell-size"]&&(d.cellSize=b(e["--cfm-csat-cell-size"])),e["--cfm-csat-tooltip-bg"]&&(d.tooltipBg=e["--cfm-csat-tooltip-bg"]),(Object.keys(d).length>Object.keys(x).length||e["--cfm-csat-accent"])&&(m.CSAT_MATRIX=d);let f={};e["--cfm-star-color"]&&(f.starColor=e["--cfm-star-color"]),e["--cfm-badge-color"]&&(f.badgeColor=e["--cfm-badge-color"]),v!==void 0&&(f.rowLabelWidth=v),e["--cfm-star-unselected-opacity"]&&(f.unselectedStarOpacity=ge(e["--cfm-star-unselected-opacity"])),Object.keys(f).length&&(m.RATING_MATRIX=f);let T={};e["--cfm-slider-track"]&&(T.trackColor=e["--cfm-slider-track"]),e["--cfm-slider-thumb"]&&(T.thumbColor=e["--cfm-slider-thumb"]),e["--cfm-slider-tick"]&&(T.tickColor=e["--cfm-slider-tick"]),v!==void 0&&(T.rowLabelWidth=v),e["--cfm-slider-row-band"]&&(T.rowBandColor=e["--cfm-slider-row-band"]),e["--cfm-slider-tick-size"]&&(T.tickBadgeSize=b(e["--cfm-slider-tick-size"])),Object.keys(T).length&&(m.SLIDER_MATRIX=T);let $={};e["--cfm-upload-accent"]&&($.accentColor=e["--cfm-upload-accent"]),e["--cfm-upload-padding"]&&($.dropzonePadding=b(e["--cfm-upload-padding"])),Object.keys($).length&&(m.FILE_UPLOAD=$);let h={};e["--cfm-media-max-width"]&&(h.mediaMaxWidth=eo(e["--cfm-media-max-width"])),e["--cfm-media-radius"]&&(h.mediaRadius=b(e["--cfm-media-radius"])),e["--cfm-media-caption-color"]&&(h.captionColor=e["--cfm-media-caption-color"]),e["--cfm-media-caption-size"]&&(h.captionSize=b(e["--cfm-media-caption-size"])),Object.keys(h).length&&(m.TEXT_AND_MEDIA=h);let P={};e["--cfm-heatmap-pin"]&&(P.pinColor=e["--cfm-heatmap-pin"]),e["--cfm-heatmap-pin-size"]&&(P.pinSize=b(e["--cfm-heatmap-pin-size"])),e["--cfm-heatmap-pin-border"]&&(P.pinBorderColor=e["--cfm-heatmap-pin-border"]),e["--cfm-heatmap-overlay-opacity"]&&(P.overlayOpacity=ge(e["--cfm-heatmap-overlay-opacity"])),Object.keys(P).length&&(m.HEATMAP=P);let w={};return e["--cfm-rank-item-bg"]&&(w.itemBg=e["--cfm-rank-item-bg"]),e["--cfm-rank-badge"]&&(w.rankBadgeColor=e["--cfm-rank-badge"]),e["--cfm-rank-handle"]&&(w.dragHandleColor=e["--cfm-rank-handle"]),e["--cfm-rank-item-padding"]&&(w.itemPadding=b(e["--cfm-rank-item-padding"])),e["--cfm-rank-item-gap"]&&(w.itemGap=b(e["--cfm-rank-item-gap"])),Object.keys(w).length&&(m.RANK_ORDER=w),Object.keys(n).length&&(t.colorScheme=n),Object.keys(i).length&&(t.header=i),Object.keys(s).length&&(t.footer=s),Object.keys(r).length&&(t.theme=r),Object.keys(a).length&&(t.layout=a),Object.keys(l).length&&(t.typography=l),Object.keys(y).length&&(t.motion=y),o}function ne(e){let o=[ue.join(e,"src","styles","survey-theme.css"),ue.join(e,"src","app","survey-theme.css"),ue.join(e,"src","styles","globals.css"),ue.join(e,"src","app","globals.css")];for(let t of o)if(Ce.existsSync(t)&&Ce.readFileSync(t,"utf8").includes("--cfm-"))return t;return null}var Ke,Ye,Ze,$e=B(()=>{"use strict";Ke={"36rem":"narrow","48rem":"standard","64rem":"wide"},Ye={"0px":"sharp","12px":"rounded","9999px":"pill"},Ze={"system-ui, sans-serif":"system","Inter, sans-serif":"modern","Georgia, serif":"serif"}});import*as xe from"fs";import*as no from"path";function Bo(e){for(let o of zo){let t=no.join(e,o);if(xe.existsSync(t))return t}return null}function Wo(e){let o=e.trim();if(!o||o.startsWith("http")||o.startsWith("data:"))return null;let t=o.split("?")[0];return t.startsWith("/")?t.slice(1):t}function io(e){let o=Bo(e);if(!o)return null;let t=xe.readFileSync(o,"utf8"),n=t.match(/data-cfm-logo[\s\S]*?src=["']([^"']+)["']/i)??t.match(/src=["']([^"']+)["'][\s\S]*?data-cfm-logo/i);if(n){let r=Wo(n[1]);if(r)return{mode:"image",publicPath:r,fileName:r}}let i=t.match(/data-cfm-logo-text[^>]*>([^<]+)</i);if(i)return{mode:"text",label:i[1].trim()};let s=t.match(/data-cfm-company[^>]*>([^<]+)</i);return s&&!n?{mode:"text",label:s[1].trim()}:null}var zo,ro=B(()=>{"use strict";zo=["src/components/Header.tsx","components/Header.tsx","app/components/Header.tsx"]});var fo={};Ie(fo,{logSeedSource:()=>Fe,resolveInitialConfig:()=>re,writeResolvedUiConfig:()=>Ne});import*as W from"fs";import*as V from"path";function je(e){return e.filter(o=>Q.includes(o))}function so(e){try{let o=JSON.parse(W.readFileSync(e,"utf8"));return o.version!=="1.0"?null:(delete o.configuredAt,o)}catch{return null}}function Vo(e){let o={global:{}};if(!W.existsSync(e))return o;let t=W.readFileSync(e,"utf8"),n=new Set;for(let s of Q)t.includes(s)&&n.add(s);n.size&&(o.surveyTypes=[...n]);let i=t.match(/\*\*Branding source:\*\*\s*(.+)/i);if(i){let s=i[1].trim(),r=s.match(/company[:\s]+([^,;]+)/i),a=s.match(/title[:\s]+([^,;]+)/i);if(r&&(o.global.companyName=r[1].trim()),a){let l=a[1].trim();o.global.surveyTitle=l,o.global.browserTabTitle=l}}return o}function lo(e,o){let t=V.join(e,o);if(!W.existsSync(t))return null;let n=W.readFileSync(t);if(n.length>Jo)return{fileName:o,dataUrl:""};let i=V.extname(o).toLowerCase(),s=Ho[i]??"application/octet-stream";return{fileName:o,dataUrl:`data:${s};base64,${n.toString("base64")}`}}function co(e,o){if(!o)return null;if(o.url&&typeof o.url=="string")return{fileName:o.fileName??null,url:o.url};if(o.fileName){let t=lo(e,o.fileName);if(t)return{fileName:t.fileName,url:t.dataUrl||null}}return o.fileName===null&&o.url===null?{fileName:null,url:null}:null}function ao(e,o){let t=e.global??{},n=o.global??{},i=e.questionTypes??{},s=o.questionTypes??{},r={...i};for(let[a,l]of Object.entries(s))r[a]={...r[a]??{},...l};return{...e,...o,surveyTypes:o.surveyTypes??e.surveyTypes,global:{...t,...n,header:{...t.header,...n.header},footer:{...t.footer,...n.footer},theme:{...t.theme,...n.theme},layout:{...t.layout,...n.layout},buttons:{...t.buttons,...n.buttons},logo:{...t.logo,...n.logo},colorScheme:{...t.colorScheme,...n.colorScheme},typography:{...t.typography,...n.typography},motion:{...t.motion,...n.motion}},questionTypes:r,placeholders:{...e.placeholders,...o.placeholders},customFields:{...e.customFields,...o.customFields},deploy:{...e.deploy,...o.deploy}}}function re(e){let o=e.projectRoot??process.env.INIT_CWD??process.cwd(),t=V.join(o,"survey-ui-config.json"),n=V.join(o,"implementation_plan.md"),i=V.join(o,"public"),s=je(e.surveyTypes),r={},a="defaults",l=ne(o);if(l){let w=W.readFileSync(l,"utf8"),A=oo(w);Object.keys(A).length>0&&(r=to(A),a="survey-theme.css")}let y=Vo(n);r=ao(r,y);let m=so(t);m&&(r=ao(r,m),a="survey-ui-config.json");let C=V.join(o,"survey-ui-config.final.json"),S=so(C),E=!!m?.configuredAt,v=!!S?.configuredAt;if(S&&v&&!E){let w=co(i,S.global?.logo);w&&(r.global={...r.global??{},logo:{fileName:w.fileName,url:w.url}})}let x=co(i,r.global?.logo),d=io(o),f=!!m?.configuredAt,T=x?.fileName!=null&&/^logo_\d+_/i.test(x.fileName),$=d?.mode==="image"?d.fileName:null,h=!f&&T&&$!=null&&x?.fileName!==$;if(x&&!h)r.global={...r.global??{},logo:{fileName:x.fileName,url:x.url}};else if(d?.mode==="image"){let w=lo(i,d.fileName);r.global={...r.global??{},logo:{fileName:d.fileName,url:w?.dataUrl||null}}}else d?.mode==="text"&&(r.global={...r.global??{},logo:{fileName:null,url:null},companyName:r.global?.companyName??d.label});return r.surveyTypes=je(r.surveyTypes??s),r.surveyTypes?.length||(r.surveyTypes=s),e.instanceId&&(r.instanceId=e.instanceId),{config:Qe(r),source:a}}function Fe(e){console.log(e==="survey-ui-config.json"?`${ie.dim} Seeding wizard from survey-ui-config.json${ie.reset}`:e==="survey-theme.css"?`${ie.dim} Seeding wizard from survey-theme.css + defaults${ie.reset}`:`${ie.dim} Seeding wizard from SDK defaults${ie.reset}`)}function Ne(e={}){let o=e.projectRoot??process.env.INIT_CWD??process.cwd(),t=e.surveyTypes??je(Q),{config:n}=re({projectRoot:o,surveyTypes:t,instanceId:e.instanceId}),i=V.join(o,"survey-ui-config.json");return W.writeFileSync(i,JSON.stringify(n,null,2),"utf8"),i}var ie,Jo,Ho,pe=B(()=>{"use strict";U();Ge();$e();be();ro();ie=c,Jo=512e3,Ho={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml"}});import*as ae from"fs";import*as le from"path";function yo(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function wo(e,o){return JSON.stringify(e)===JSON.stringify(o)}function ce(e){return typeof e=="string"&&e.startsWith("data:")&&e.length>80?`${e.slice(0,48)}\u2026 (${e.length} chars)`:e}function So(e,o,t,n){if(wo(e,o)){n.unchangedCount+=1;return}if(e===void 0&&o!==void 0){n.added.push({path:t,before:void 0,after:ce(o)});return}if(e!==void 0&&o===void 0){n.removed.push({path:t,before:ce(e),after:void 0});return}if(Array.isArray(e)&&Array.isArray(o)){wo(e,o)?n.unchangedCount+=1:n.changed.push({path:t,before:ce(e),after:ce(o)});return}if(yo(e)&&yo(o)){let i=new Set([...Object.keys(e),...Object.keys(o)]);for(let s of i){if(ct.has(s)&&t==="")continue;let r=t?`${t}.${s}`:s;So(e[s],o[s],r,n)}return}n.changed.push({path:t,before:ce(e),after:ce(o)})}function Me(e,o){let t={changed:[],added:[],removed:[],unchangedCount:0};return So(e,o,"",t),t}function ke(e){let o=["# UI Config Diff (seed \u2192 final)","",`**Changed:** ${e.changed.length} \xB7 **Added:** ${e.added.length} \xB7 **Removed:** ${e.removed.length}`,"","> Review only \u2014 run `npx cfm-sdk confirm-ui-config` to apply final config to the project.",""],t=(n,i)=>{if(i.length){o.push(`## ${n}`,"");for(let s of i)o.push(`### \`${s.path}\``),o.push(`- **Before:** \`${JSON.stringify(s.before)}\``),o.push(`- **After:** \`${JSON.stringify(s.after)}\``),o.push("")}};return t("Changed",e.changed),t("Added",e.added),t("Removed",e.removed),!e.changed.length&&!e.added.length&&!e.removed.length&&o.push("_No differences \u2014 final config matches seed._",""),o.join(`
|
|
3
|
+
`)}function K(e){return{seedPath:le.join(e,"survey-ui-config.seed.json"),finalPath:le.join(e,"survey-ui-config.final.json"),diffJsonPath:le.join(e,"survey-ui-config.diff.json"),diffMdPath:le.join(e,"survey-ui-config.diff.md"),activeConfigPath:le.join(e,"survey-ui-config.json")}}function Pe(e,o,t){let n=K(e),i=Me(o,t);return ae.writeFileSync(n.seedPath,JSON.stringify(o,null,2),"utf8"),ae.writeFileSync(n.finalPath,JSON.stringify(t,null,2),"utf8"),ae.writeFileSync(n.diffJsonPath,JSON.stringify(i,null,2),"utf8"),ae.writeFileSync(n.diffMdPath,ke(i),"utf8"),ae.writeFileSync(n.activeConfigPath,JSON.stringify(o,null,2),"utf8"),i}var ct,Ee=B(()=>{"use strict";ct=new Set(["configuredAt","instanceId"])});import*as Y from"fs";import*as Co from"http";import*as $o from"https";import*as Ue from"path";function ve(e){if(!e.config)return null;let o=JSON.parse(JSON.stringify(e.config)),n=o.global?.logo;return e.logoUrl&&n&&(n.url=e.logoUrl),o}function bo(e){return new Promise((o,t)=>{let n=new URL(e);(n.protocol==="https:"?$o:Co).get(n,s=>{if((s.statusCode??500)>=400){t(new Error(`Logo download failed HTTP ${s.statusCode}`));return}let r=[];s.on("data",a=>r.push(a)),s.on("end",()=>o(Buffer.concat(r)))}).on("error",t)})}async function at(e,o={}){return new Promise((t,n)=>{let i=new URL(e),r=(i.protocol==="https:"?$o:Co).request(i,{method:"GET",headers:o.headers??{}},a=>{let l="";a.on("data",y=>l+=y),a.on("end",()=>{if((a.statusCode??500)>=400){n(new Error(`HTTP ${a.statusCode}: ${l}`));return}try{t(JSON.parse(l))}catch{n(new Error(`Invalid JSON: ${l.slice(0,200)}`))}})});r.on("error",n),r.end()})}async function Z(e){let{projectRoot:o,fileName:t,logoUrl:n,jwt:i,apiBase:s,surveyId:r}=e,a=Ue.join(o,"public");Y.existsSync(a)||Y.mkdirSync(a,{recursive:!0});let l=Ue.join(a,t);if(n){let y=await bo(n);return Y.writeFileSync(l,y),l}if(i&&s&&r){let y=await at(`${s.replace(/\/$/,"")}/wizard/logo/${encodeURIComponent(r)}/${encodeURIComponent(t)}`,{headers:{Authorization:`Bearer ${i}`}}),m=await bo(y.downloadUrl);return Y.writeFileSync(l,m),l}throw new Error("Logo download requires logoUrl from wizard poll or CFM_INSTANCE_ID + CFM_DEPLOY_API_BASE")}var Re=B(()=>{"use strict"});var Eo={};Ie(Eo,{runConfirmUiConfig:()=>pt});import*as J from"fs";function ut(e){try{let o=e.split(".")[1];return JSON.parse(Buffer.from(o,"base64url").toString("utf8")).surveyId??null}catch{return null}}async function pt(e={}){let o=process.env.INIT_CWD??process.cwd(),t=K(o);if(!J.existsSync(t.finalPath))throw new Error(`Missing ${t.finalPath}. Run customize-ui with --review and complete the wizard first.`);let n=JSON.parse(J.readFileSync(J.existsSync(t.seedPath)?t.seedPath:t.activeConfigPath,"utf8")),i=JSON.parse(J.readFileSync(t.finalPath,"utf8")),s=Me(n,i);if(console.log(`
|
|
4
4
|
${z.bold}${z.cyan}\u{1F4CB} UI config review${z.reset}
|
|
5
5
|
`),console.log(ke(s)),e.diffOnly){J.writeFileSync(t.diffJsonPath,JSON.stringify(s,null,2),"utf8"),J.writeFileSync(t.diffMdPath,ke(s),"utf8"),console.log(`${z.dim} Updated ${t.diffMdPath}${z.reset}`);return}J.writeFileSync(t.activeConfigPath,JSON.stringify(i,null,2),"utf8"),console.log(`${z.green}\u2705 Applied final config \u2192 ${t.activeConfigPath}${z.reset}`);let r=i.global?.logo;if(!r?.fileName)return;let a=process.env.CFM_INSTANCE_ID,l=(process.env.CFM_DEPLOY_API_BASE??"").replace(/\/$/,""),y=a?ut(a):null;try{await Z({projectRoot:o,fileName:r.fileName,logoUrl:r.url,jwt:a??void 0,apiBase:l||void 0,surveyId:y??void 0}),console.log(`${z.green} Logo saved to public/${r.fileName}${z.reset}`),r.url&&console.log(`${z.dim} Public logo URL: ${r.url}${z.reset}`)}catch(m){console.log(`${z.yellow} Logo not downloaded \u2014 ${m instanceof Error?m.message:String(m)}${z.reset}`)}}var z,vo=B(()=>{"use strict";U();Ee();Re();z=c});var Ro={};Ie(Ro,{runFetchUiConfig:()=>St});import*as ye from"fs";import*as mt from"http";import*as ht from"https";async function yt(e,o={}){return new Promise((t,n)=>{let i=new URL(e),r=(i.protocol==="https:"?ht:mt).request(i,{method:"GET",headers:o.headers??{}},a=>{let l="";a.on("data",y=>l+=y),a.on("end",()=>{if((a.statusCode??500)>=400){n(new Error(`HTTP ${a.statusCode}: ${l}`));return}try{t(JSON.parse(l))}catch{n(new Error(`Invalid JSON: ${l.slice(0,200)}`))}})});r.on("error",n),r.end()})}function wt(e){try{let o=e.split(".")[1];return JSON.parse(Buffer.from(o,"base64url").toString("utf8")).surveyId??null}catch{return null}}async function St(e={}){let o=process.env.CFM_INSTANCE_ID,t=(process.env.CFM_DEPLOY_API_BASE??"").replace(/\/$/,""),n=e.sessionId??process.env.CFM_WIZARD_SESSION_ID;if(!o)throw new Error("CFM_INSTANCE_ID (JWT) is required");if(!t)throw new Error("CFM_DEPLOY_API_BASE is required");if(!n)throw new Error("CFM_WIZARD_SESSION_ID or --session= is required");let i=wt(o);if(!i)throw new Error("Could not parse surveyId from CFM_INSTANCE_ID JWT");let s=process.env.INIT_CWD??process.cwd(),r=K(s),a=ye.existsSync(r.seedPath)?r.seedPath:r.activeConfigPath;if(!ye.existsSync(a))throw new Error(`Missing seed config at ${a}. Run customize-ui --review first.`);let l=await yt(`${t}/wizard/config/${encodeURIComponent(i)}?sessionId=${encodeURIComponent(n)}`,{headers:{Authorization:`Bearer ${o}`}});if(l.status!=="ready"||!l.config)throw new Error(`Wizard not complete yet (status: ${l.status})`);let y=ve(l)??l.config,m=JSON.parse(ye.readFileSync(a,"utf8")),C=Pe(s,m,y),S=y.global?.logo;if(S?.fileName)try{await Z({projectRoot:s,fileName:S.fileName,logoUrl:l.logoUrl,jwt:o,apiBase:t,surveyId:i}),console.log(`${L.green} Logo saved to public/${S.fileName}${L.reset}`)}catch(E){console.warn(`${L.yellow} Logo download failed: ${E}${L.reset}`)}console.log(`
|
|
6
|
-
${L.green}\u2705 Fetched final config (review mode)${L.reset}`),console.log(`${L.green} Final: ${r.finalPath}${L.reset}`),console.log(`${L.green} Diff: ${r.diffMdPath}${L.reset}`),console.log(`${L.yellow} ${C.changed.length} changed, ${C.added.length} added, ${C.removed.length} removed${L.reset}`),console.log(`${L.dim} Apply when ready: npx cfm-sdk confirm-ui-config${L.reset}`)}var L,Io=B(()=>{"use strict";U();Ee();Re();L=c});U();U();import{execSync as
|
|
6
|
+
${L.green}\u2705 Fetched final config (review mode)${L.reset}`),console.log(`${L.green} Final: ${r.finalPath}${L.reset}`),console.log(`${L.green} Diff: ${r.diffMdPath}${L.reset}`),console.log(`${L.yellow} ${C.changed.length} changed, ${C.added.length} added, ${C.removed.length} removed${L.reset}`),console.log(`${L.dim} Apply when ready: npx cfm-sdk confirm-ui-config${L.reset}`)}var L,Io=B(()=>{"use strict";U();Ee();Re();L=c});U();U();import{execSync as Be,spawn as Fo}from"child_process";function oe(e){try{let o=process.platform==="win32"?`where ${e}`:`command -v ${e}`;return Be(o,{stdio:"ignore"}),!0}catch{return!1}}var No={stdio:"inherit",shell:process.platform==="win32"?"cmd.exe":"/bin/sh"};function de(e,o){try{let t=`${e} ${o.join(" ")}`;return Be(t,No),!0}catch{return!1}}function Se(e,o){return new Promise(t=>{Fo(e,o,{stdio:"inherit",shell:!0}).on("close",i=>{t(i)})})}import Ao from"readline/promises";import{stdin as _o,stdout as Do}from"process";async function te(e){let o=Ao.createInterface({input:_o,output:Do});try{return(await o.question(e)).trim()}finally{o.close()}}async function We(){let e=parseInt(process.version.slice(1).split(".")[0],10);if(console.log(`${c.dim}Step 1/4: Checking Node.js version (current: ${process.version})...${c.reset}`),e<18){console.log(`\u26A0\uFE0F ${c.yellow}Outdated Node.js version detected. v18.0.0 or higher is required.${c.reset}`),console.log(`${c.dim}Note: If you already have a higher version installed via nvm, please run 'nvm use <version>' first.${c.reset}
|
|
7
7
|
`);let o=await te("Would you like to install/upgrade Node.js v18+ automatically? (y/N): ");o.toLowerCase()==="y"||o.toLowerCase()==="yes"||(console.log(`
|
|
8
8
|
\u274C ${c.red}Aborted. Please manually upgrade Node.js to v18+ and try again.${c.reset}
|
|
9
9
|
`),process.exit(1));let n=process.platform==="win32",i=process.platform==="darwin";n?oe("winget")?(console.log(`
|
|
@@ -22,18 +22,18 @@ ${L.green}\u2705 Fetched final config (review mode)${L.reset}`),console.log(`${L
|
|
|
22
22
|
\u274C ${c.red}Homebrew package manager (brew) is not installed on this system.${c.reset}`),console.log(`${c.bold}\u{1F449} To proceed, please either:${c.reset}`),console.log(" 1. Install Homebrew by running the following command in your terminal:"),console.log(` ${c.cyan}/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"${c.reset}`),console.log(` 2. Or manually download and install Node.js (v18+) from: https://nodejs.org/
|
|
23
23
|
`),process.exit(1)):(console.log(`
|
|
24
24
|
\u274C ${c.red}Please install or update Node.js to v18+ using your system's package manager.${c.reset}
|
|
25
|
-
`),process.exit(1))}else console.log(`\u2714 ${c.green}Node.js version (v${e}) is sufficient.${c.reset}`)}U();async function
|
|
25
|
+
`),process.exit(1))}else console.log(`\u2714 ${c.green}Node.js version (v${e}) is sufficient.${c.reset}`)}U();async function Je(){console.log(`
|
|
26
26
|
${c.dim}Step 2/4: Checking Vercel CLI...${c.reset}`);let e="vercel",o=!1;if(oe("vercel"))console.log(`\u2714 ${c.green}Vercel CLI is installed!${c.reset}`);else{console.log(`\u2753 ${c.yellow}Vercel CLI was not found on your system.${c.reset}`);let t=await te("\u{1F449} Would you like to install Vercel CLI globally? (Y/n): ");t.toLowerCase()==="y"||t===""?(console.log(`
|
|
27
27
|
\u{1F4E5} ${c.cyan}Installing Vercel CLI globally... (npm install -g vercel)${c.reset}`),de("npm",["install","-g","vercel"])&&oe("vercel")?console.log(`\u2714 ${c.green}Vercel CLI installed successfully!${c.reset}`):(console.log(`
|
|
28
|
-
\u26A0\uFE0F ${c.yellow}Global installation failed or permissions restricted.${c.reset}`),console.log(`\u2139 ${c.dim}Falling back: Running Vercel dynamically via npx.${c.reset}`),e="npx --yes vercel",o=!0)):(console.log(`\u2139 ${c.dim}Skipping global installation. Running Vercel dynamically via npx.${c.reset}`),e="npx --yes vercel",o=!0)}return{vercelCmd:e,useNpx:o}}U();import{execSync as Oo}from"child_process";var Lo={stdio:"ignore",shell:process.platform==="win32"?"cmd.exe":"/bin/sh"};async function
|
|
28
|
+
\u26A0\uFE0F ${c.yellow}Global installation failed or permissions restricted.${c.reset}`),console.log(`\u2139 ${c.dim}Falling back: Running Vercel dynamically via npx.${c.reset}`),e="npx --yes vercel",o=!0)):(console.log(`\u2139 ${c.dim}Skipping global installation. Running Vercel dynamically via npx.${c.reset}`),e="npx --yes vercel",o=!0)}return{vercelCmd:e,useNpx:o}}U();import{execSync as Oo}from"child_process";var Lo={stdio:"ignore",shell:process.platform==="win32"?"cmd.exe":"/bin/sh"};async function He(e){console.log(`
|
|
29
29
|
${c.dim}Step 3/4: Checking Vercel Login...${c.reset}`);let o=!!process.env.VERCEL_TOKEN,t=!1;if(o)console.log(`\u2714 ${c.green}VERCEL_TOKEN environment variable detected. Skipping login check.${c.reset}`),t=!0;else try{Oo(e?"npx --yes vercel whoami":"vercel whoami",Lo),t=!0,console.log(`\u2714 ${c.green}Logged in!${c.reset}`)}catch{t=!1}if(!t){console.log(`\u{1F511} ${c.yellow}Not logged in to Vercel.${c.reset}`),await te("\u{1F449} Press [Enter] to login to Vercel... ");let n=["login"],i=e?"npx":"vercel",s=e?["--yes","vercel",...n]:n;if(await Se(i,s)!==0)throw new Error("Vercel login failed or was aborted.");console.log(`
|
|
30
|
-
\u2714 ${c.green}Logged in successfully!${c.reset}`)}return o}U();async function
|
|
30
|
+
\u2714 ${c.green}Logged in successfully!${c.reset}`)}return o}U();async function Ve(e,o){console.log(`
|
|
31
31
|
${c.dim}Step 4/4: Deploying project to production...${c.reset}`);let t=["--prod","--yes"];o&&t.push("--token",process.env.VERCEL_TOKEN);let n=e?"npx":"vercel",i=e?["--yes","vercel",...t]:t;if(console.log(`${c.cyan}\u26A1 Running deployment in: ${process.cwd()}${c.reset}
|
|
32
32
|
`),await Se(n,i)!==0)throw new Error("Vercel deployment failed.");console.log(`
|
|
33
33
|
${c.bold}${c.green}\u{1F389} Deployment completed successfully!${c.reset}
|
|
34
|
-
`)}async function
|
|
34
|
+
`)}async function Xe(){console.log(`
|
|
35
35
|
${c.bold}${c.cyan}\u{1F680} Starting CFM Vercel Deployment...${c.reset}
|
|
36
|
-
`),await
|
|
36
|
+
`),await We();let{vercelCmd:e,useNpx:o}=await Je(),t=await He(o);await Ve(o,t)}U();import*as he from"http";import*as k from"fs";import*as F from"path";function O(e){return e instanceof Error?e.message:String(e)}pe();U();import*as I from"fs";import*as R from"path";$e();$e();import*as u from"fs";import*as p from"path";import{execSync as Xo}from"child_process";function G(e,o){if(u.existsSync(e)){u.mkdirSync(o,{recursive:!0});for(let t of u.readdirSync(e,{withFileTypes:!0})){let n=p.join(e,t.name),i=p.join(o,t.name);t.isDirectory()?G(n,i):u.copyFileSync(n,i)}}}function Ae(e){let o=[],t=e;for(let n=0;n<6;n++){let i=p.join(t,"node_modules");u.existsSync(i)&&o.push(i);let s=p.dirname(t);if(s===t)break;t=s}return o}function qo(e,o){let t=Ae(e);for(let n of t)for(let i of["@explorer02/cfm-survey-sdk","@repo/sdk"])for(let s of["mjs","js"]){let r=p.join(n,i,"dist",`index.${s}`);if(u.existsSync(r))return r}for(let n of["mjs","js"]){let i=p.join(o,"dist",`index.${n}`);if(u.existsSync(i))return i}throw new Error("Could not resolve @explorer02/cfm-survey-sdk for preview build")}function Qo(e,o){let t=[...Ae(o).map(n=>p.join(n,"vite","bin","vite.js")),p.join(e,"node_modules","vite","bin","vite.js")];for(let n of t)if(u.existsSync(n))return n;throw new Error("Vite is required for agent preview builds. Install vite in the project or SDK package.")}function Go(e){let o=p.join(e,"src","components");if(!u.existsSync(p.join(o,"Question.tsx")))throw new Error(`Missing src/components/Question.tsx in ${e}. Build the survey UI before export-previews.`);let t=p.join(e,"src","lib"),n=p.join(e,"public");return{componentsDir:o,libDir:u.existsSync(t)?t:void 0,publicDir:u.existsSync(n)?n:void 0}}function Ko(e){let o=`import React from 'react';
|
|
37
37
|
import { mountPreview } from '../mount';
|
|
38
38
|
`;switch(e){case"header":return`${o}import Header from '@/components/Header';
|
|
39
39
|
import ProgressBar from '@/components/ProgressBar';
|
|
@@ -113,7 +113,7 @@ ${s}
|
|
|
113
113
|
});
|
|
114
114
|
`;u.writeFileSync(p.join(e,"vite.config.mjs"),r)}function Zo(e,o){let t=u.readFileSync(e,"utf8");if(t.includes("preview-bridge.inline"))return;let n=`<script>${o}</script>`;t=t.includes("</body>")?t.replace("</body>",`${n}
|
|
115
115
|
</body>`):`${t}
|
|
116
|
-
${n}`,u.writeFileSync(e,t)}function et(e){return e.replace(/_/g," ")}async function
|
|
116
|
+
${n}`,u.writeFileSync(e,t)}function et(e){return e.replace(/_/g," ")}async function go(e){let{projectRoot:o,outputDir:t,keys:n}=e,i=p.join(__dirname,"..",".."),s=p.join(i,"templates","preview-harness","vite-app");if(!u.existsSync(s))throw new Error(`Missing Vite preview harness template at ${s}`);let r=Go(o),a=p.join(t,".preview-vite-work");u.existsSync(a)&&u.rmSync(a,{recursive:!0,force:!0}),G(s,a),u.mkdirSync(p.join(a,"agent","src"),{recursive:!0}),G(r.componentsDir,p.join(a,"agent","src","components")),r.libDir&&G(r.libDir,p.join(a,"agent","src","lib")),r.publicDir&&G(r.publicDir,p.join(a,"agent","public"));let l=ne(o),y=p.join(a,"src","survey-theme.css");u.writeFileSync(y,l?u.readFileSync(l,"utf8"):u.readFileSync(p.join(i,"templates","survey-theme.css"),"utf8")),u.mkdirSync(p.join(a,"src","entries"),{recursive:!0});for(let f of n)u.mkdirSync(p.join(a,f),{recursive:!0}),u.writeFileSync(p.join(a,f,"index.html"),`<!DOCTYPE html>
|
|
117
117
|
<html lang="en">
|
|
118
118
|
<head>
|
|
119
119
|
<meta charset="UTF-8" />
|
|
@@ -124,24 +124,24 @@ ${n}`,u.writeFileSync(e,t)}function et(e){return e.replace(/_/g," ")}async funct
|
|
|
124
124
|
<div id="root"></div>
|
|
125
125
|
<script type="module" src="../src/entries/${f}.tsx"></script>
|
|
126
126
|
</body>
|
|
127
|
-
</html>`),u.writeFileSync(p.join(a,"src","entries",`${f}.tsx`),Ko(f));u.writeFileSync(p.join(a,"tsconfig.json"),JSON.stringify({compilerOptions:{target:"ES2020",lib:["ES2020","DOM","DOM.Iterable"],module:"ESNext",moduleResolution:"bundler",jsx:"react-jsx",strict:!0,skipLibCheck:!0,paths:{"@/*":["./agent/src/*"]}},include:["src","agent/src","stubs"]},null,2)),Yo(a,o,i,n);let m=Qo(i,o),C=Ae(o).join(p.delimiter);Xo(`node "${m}" build --config "${p.join(a,"vite.config.mjs")}"`,{cwd:a,stdio:"inherit",env:{...process.env,NODE_PATH:C}});let S=p.join(t,"previews");u.mkdirSync(S,{recursive:!0});let E=p.join(a,"dist"),v=u.readFileSync(p.join(i,"templates","preview-harness","preview-bridge.inline.js"),"utf8");for(let f of n){let T=p.join(E,f),$=p.join(S,f);if(!u.existsSync(p.join(T,"index.html")))throw new Error(`Vite build did not produce ${f}/index.html`);u.existsSync($)&&u.rmSync($,{recursive:!0,force:!0}),G(T,$),Zo(p.join($,"index.html"),v)}let x=p.join(E,"assets");u.existsSync(x)&&G(x,p.join(S,"assets"));let d=p.join(a,"agent","public");if(u.existsSync(d))for(let f of u.readdirSync(d)){let T=p.join(d,f);u.statSync(T).isFile()&&u.copyFileSync(T,p.join(S,f))}u.rmSync(a,{recursive:!0,force:!0})}import*as _e from"fs";import*as De from"path";function Te(e){if(e)return e;let o=process.cwd();if(_e.existsSync(De.join(o,"src","components","Question.tsx")))return o;let t=process.env.INIT_CWD;return t&&_e.existsSync(De.join(t,"src","components","Question.tsx"))?t:o}var D=c;function ot(){return R.join(__dirname,"..","..","templates")}function tt(e){let o=I.readFileSync(e,"utf8"),t=new Set,n=["MCQ","TEXTFIELD","NPS_SCALE","CFM_MATRIX","CSAT_MATRIX","RATING_MATRIX","SLIDER_MATRIX","FILE_UPLOAD","TEXT_AND_MEDIA","HEATMAP","RANK_ORDER"];for(let i of n)o.includes(i)&&t.add(i);return t.size?[...t]:n}function nt(e,o){let t=["header","footer","chrome","survey_page","intro","end"],n={MCQ:["MCQ_single","MCQ_multiple"],TEXTFIELD:["TEXTFIELD_short","TEXTFIELD_long"],NPS_SCALE:["NPS_SCALE"],CFM_MATRIX:["CFM_likert","CFM_bipolar"],CSAT_MATRIX:["CSAT_emoji","CSAT_star","CSAT_numbered","CSAT_graphics","CSAT_carousel","CSAT_dropdown"],RATING_MATRIX:["RATING_star","RATING_numbered","RATING_radio","RATING_emoji","RATING_graphics","RATING_slider"],SLIDER_MATRIX:["SLIDER_matrix"],FILE_UPLOAD:["FILE_UPLOAD"],HEATMAP:["HEATMAP"],RANK_ORDER:["RANK_drag","RANK_dropdown"]},i=new Set(t);for(let s of o)for(let r of n[s]??[])i.add(r);return e.filter(s=>i.has(s))}function Oe(e,o,t){if(I.existsSync(e))for(let n of I.readdirSync(e)){let i=R.join(e,n),s=R.posix.join(o,n);if(I.statSync(i).isDirectory())Oe(i,s,t);else{let r=R.extname(n).toLowerCase(),a=r===".html"?"text/html":r===".css"?"text/css":r===".js"?"application/javascript":r===".json"?"application/json":r===".svg"?"image/svg+xml":r===".jpg"||r===".jpeg"?"image/jpeg":r===".png"?"image/png":"application/octet-stream";t.push({path:s,contentType:a,sizeBytes:I.statSync(i).size})}}}async function se(e={}){let o=Te(e.projectRoot),t=e.outputDir??R.join(o,"out"),n=ot(),i=R.join(n,"preview-harness");e.useTemplatesOnly&&console.log(`${D.dim} Using SDK template preview harness only (--use-templates-only)${D.reset}`);let s=R.join(i,"previewPages.js"),{PREVIEW_PAGE_DEFS:r,buildPreviewHtml:a,PREVIEW_KEYS:l}=we(s),y=(()=>{let d=ne(o);return d?(console.log(`${D.dim} Using project theme: ${R.relative(o,d)}${D.reset}`),I.readFileSync(d,"utf8")):I.readFileSync(R.join(n,"survey-theme.css"),"utf8")})(),m=I.readFileSync(R.join(i,"preview-bridge.inline.js"),"utf8"),C=e.surveyTypes;if(!C){let d=R.join(o,"implementation_plan.md");C=I.existsSync(d)?tt(d):["MCQ","TEXTFIELD","NPS_SCALE","CFM_MATRIX","CSAT_MATRIX","RATING_MATRIX","SLIDER_MATRIX","FILE_UPLOAD","TEXT_AND_MEDIA","HEATMAP","RANK_ORDER"]}let S=nt(l,C),E=R.join(t,"previews");if(I.existsSync(E)&&(I.rmSync(E,{recursive:!0,force:!0}),console.log(`${D.dim} Cleared previous preview output${D.reset}`)),I.mkdirSync(E,{recursive:!0}),!e.useTemplatesOnly)try{console.log(`${D.dim} Building previews from agent components (Vite)\u2026${D.reset}`),await
|
|
128
|
-
${
|
|
129
|
-
${
|
|
130
|
-
`),it(d)}),v.on("error",E);let x=()=>{
|
|
127
|
+
</html>`),u.writeFileSync(p.join(a,"src","entries",`${f}.tsx`),Ko(f));u.writeFileSync(p.join(a,"tsconfig.json"),JSON.stringify({compilerOptions:{target:"ES2020",lib:["ES2020","DOM","DOM.Iterable"],module:"ESNext",moduleResolution:"bundler",jsx:"react-jsx",strict:!0,skipLibCheck:!0,paths:{"@/*":["./agent/src/*"]}},include:["src","agent/src","stubs"]},null,2)),Yo(a,o,i,n);let m=Qo(i,o),C=Ae(o).join(p.delimiter);Xo(`node "${m}" build --config "${p.join(a,"vite.config.mjs")}"`,{cwd:a,stdio:"inherit",env:{...process.env,NODE_PATH:C}});let S=p.join(t,"previews");u.mkdirSync(S,{recursive:!0});let E=p.join(a,"dist"),v=u.readFileSync(p.join(i,"templates","preview-harness","preview-bridge.inline.js"),"utf8");for(let f of n){let T=p.join(E,f),$=p.join(S,f);if(!u.existsSync(p.join(T,"index.html")))throw new Error(`Vite build did not produce ${f}/index.html`);u.existsSync($)&&u.rmSync($,{recursive:!0,force:!0}),G(T,$),Zo(p.join($,"index.html"),v)}let x=p.join(E,"assets");u.existsSync(x)&&G(x,p.join(S,"assets"));let d=p.join(a,"agent","public");if(u.existsSync(d))for(let f of u.readdirSync(d)){let T=p.join(d,f);u.statSync(T).isFile()&&u.copyFileSync(T,p.join(S,f))}u.rmSync(a,{recursive:!0,force:!0})}import*as _e from"fs";import*as De from"path";function Te(e){if(e)return e;let o=process.cwd();if(_e.existsSync(De.join(o,"src","components","Question.tsx")))return o;let t=process.env.INIT_CWD;return t&&_e.existsSync(De.join(t,"src","components","Question.tsx"))?t:o}var D=c;function ot(){return R.join(__dirname,"..","..","templates")}function tt(e){let o=I.readFileSync(e,"utf8"),t=new Set,n=["MCQ","TEXTFIELD","NPS_SCALE","CFM_MATRIX","CSAT_MATRIX","RATING_MATRIX","SLIDER_MATRIX","FILE_UPLOAD","TEXT_AND_MEDIA","HEATMAP","RANK_ORDER"];for(let i of n)o.includes(i)&&t.add(i);return t.size?[...t]:n}function nt(e,o){let t=["header","footer","chrome","survey_page","intro","end"],n={MCQ:["MCQ_single","MCQ_multiple"],TEXTFIELD:["TEXTFIELD_short","TEXTFIELD_long"],NPS_SCALE:["NPS_SCALE"],CFM_MATRIX:["CFM_likert","CFM_bipolar"],CSAT_MATRIX:["CSAT_emoji","CSAT_star","CSAT_numbered","CSAT_graphics","CSAT_carousel","CSAT_dropdown"],RATING_MATRIX:["RATING_star","RATING_numbered","RATING_radio","RATING_emoji","RATING_graphics","RATING_slider"],SLIDER_MATRIX:["SLIDER_matrix"],FILE_UPLOAD:["FILE_UPLOAD"],HEATMAP:["HEATMAP"],RANK_ORDER:["RANK_drag","RANK_dropdown"]},i=new Set(t);for(let s of o)for(let r of n[s]??[])i.add(r);return e.filter(s=>i.has(s))}function Oe(e,o,t){if(I.existsSync(e))for(let n of I.readdirSync(e)){let i=R.join(e,n),s=R.posix.join(o,n);if(I.statSync(i).isDirectory())Oe(i,s,t);else{let r=R.extname(n).toLowerCase(),a=r===".html"?"text/html":r===".css"?"text/css":r===".js"?"application/javascript":r===".json"?"application/json":r===".svg"?"image/svg+xml":r===".jpg"||r===".jpeg"?"image/jpeg":r===".png"?"image/png":"application/octet-stream";t.push({path:s,contentType:a,sizeBytes:I.statSync(i).size})}}}async function se(e={}){let o=Te(e.projectRoot),t=e.outputDir??R.join(o,"out"),n=ot(),i=R.join(n,"preview-harness");e.useTemplatesOnly&&console.log(`${D.dim} Using SDK template preview harness only (--use-templates-only)${D.reset}`);let s=R.join(i,"previewPages.js"),{PREVIEW_PAGE_DEFS:r,buildPreviewHtml:a,PREVIEW_KEYS:l}=we(s),y=(()=>{let d=ne(o);return d?(console.log(`${D.dim} Using project theme: ${R.relative(o,d)}${D.reset}`),I.readFileSync(d,"utf8")):I.readFileSync(R.join(n,"survey-theme.css"),"utf8")})(),m=I.readFileSync(R.join(i,"preview-bridge.inline.js"),"utf8"),C=e.surveyTypes;if(!C){let d=R.join(o,"implementation_plan.md");C=I.existsSync(d)?tt(d):["MCQ","TEXTFIELD","NPS_SCALE","CFM_MATRIX","CSAT_MATRIX","RATING_MATRIX","SLIDER_MATRIX","FILE_UPLOAD","TEXT_AND_MEDIA","HEATMAP","RANK_ORDER"]}let S=nt(l,C),E=R.join(t,"previews");if(I.existsSync(E)&&(I.rmSync(E,{recursive:!0,force:!0}),console.log(`${D.dim} Cleared previous preview output${D.reset}`)),I.mkdirSync(E,{recursive:!0}),!e.useTemplatesOnly)try{console.log(`${D.dim} Building previews from agent components (Vite)\u2026${D.reset}`),await go({projectRoot:o,outputDir:t,keys:S});let d={};for(let T of S)d[T]=`previews/${T}/index.html`;I.writeFileSync(R.join(t,"previews","manifest.json"),JSON.stringify(d,null,2));let f=[];return Oe(R.join(t,"previews"),"previews",f),console.log(`${D.green}\u2705 Exported ${S.length} agent component previews \u2192 ${t}${D.reset}`),{outputDir:t,manifestPath:R.join(t,"previews","manifest.json"),files:f,surveyTypes:C}}catch(d){console.warn(`${D.yellow}\u26A0 Agent Vite preview build failed; falling back to template harness.${D.reset}`),console.warn(`${D.dim} ${O(d)}${D.reset}`)}for(let d of r){if(!S.includes(d.key))continue;let f=R.join(t,"previews",d.key);I.mkdirSync(f,{recursive:!0}),I.writeFileSync(R.join(f,"index.html"),a(d,y,m))}let v={};for(let d of S)v[d]=`previews/${d}/index.html`;I.writeFileSync(R.join(t,"previews","manifest.json"),JSON.stringify(v,null,2));let x=[];return Oe(R.join(t,"previews"),"previews",x),console.log(`${D.green}\u2705 Exported ${S.length} preview pages \u2192 ${t}${D.reset}`),{outputDir:t,manifestPath:R.join(t,"previews","manifest.json"),files:x,surveyTypes:C}}var j=c,me=["MCQ","TEXTFIELD","NPS_SCALE","CFM_MATRIX","CSAT_MATRIX","RATING_MATRIX","SLIDER_MATRIX","FILE_UPLOAD","TEXT_AND_MEDIA","HEATMAP","RANK_ORDER"];function mo(e){return new Promise(o=>{let t=he.createServer();t.listen(e,()=>{t.close(()=>o(e))}),t.on("error",()=>o(mo(e+1)))})}function uo(e){return new Promise((o,t)=>{let n="";e.on("data",i=>n+=i),e.on("end",()=>o(n)),e.on("error",t)})}function it(e){let{exec:o}=we("child_process"),t=process.platform==="darwin"?`open "${e}"`:process.platform==="win32"?`start "" "${e}"`:`xdg-open "${e}"`;o(t)}function po(e){let o=F.extname(e).toLowerCase();return{".html":"text/html",".js":"application/javascript",".css":"text/css",".json":"application/json",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".woff2":"font/woff2",".ico":"image/x-icon"}[o]??"application/octet-stream"}function rt(e){let o=new Set,t,n=e.match(/\*\*instanceId:\*\*\s*(.+)/i);if(n){let s=n[1].replace(/[()[\]]/g,"").trim();s&&!s.startsWith("(")&&s!=="JWT"&&(t=s)}for(let s of me)e.includes(s)&&o.add(s);let i=e.matchAll(/\|\s*`([A-Z_]+)`\s*\|/g);for(let s of i)me.includes(s[1])&&o.add(s[1]);return{surveyTypes:o.size>0?[...o]:[...me],instanceId:t}}async function st(e){return new Promise(o=>{try{let t=he.get(e,n=>{o((n.statusCode??500)<500),n.resume()});t.on("error",()=>o(!1)),t.setTimeout(2e3,()=>{t.destroy(),o(!1)})}catch{o(!1)}})}function Le(e){let o=F.join(e,"out","previews");k.existsSync(o)&&(k.rmSync(o,{recursive:!0,force:!0}),console.log(`${j.dim} Removed local preview files: out/previews/${j.reset}`))}async function ho(){let e=process.env.INIT_CWD||process.cwd(),o=F.join(e,"public"),t=F.join(e,"survey-ui-config.json"),n=F.join(e,"implementation_plan.md"),i=F.join(__dirname,"..","..","templates"),s=F.join(i,"wizard-dist"),r=process.env.CFM_PREVIEW_URL??"http://localhost:3000",a={},l=F.join(e,"out","previews"),y=F.join(l,"manifest.json");k.existsSync(y)||(console.log(`${j.dim} Exporting component previews for local wizard\u2026${j.reset}`),await se({projectRoot:e,surveyTypes:[...me]})),k.existsSync(y)&&(a=JSON.parse(k.readFileSync(y,"utf8")));let m=await mo(4200),C=`http://localhost:${m}`;return new Promise((S,E)=>{let v=he.createServer(async(d,f)=>{try{let T=d.url??"/";if(d.method==="GET"&&T==="/api/inventory"){let $;if(k.existsSync(n)){let w=k.readFileSync(n,"utf8");$=rt(w).instanceId}if(k.existsSync(t))try{let w=JSON.parse(k.readFileSync(t,"utf8"));w.instanceId&&($=w.instanceId)}catch{}let h=[...me],{config:P}=re({projectRoot:e,surveyTypes:h,instanceId:$});f.writeHead(200,{"Content-Type":"application/json"}),f.end(JSON.stringify({surveyTypes:h,instanceId:$,previewUrl:r,initialConfig:P,previewManifest:Object.fromEntries(Object.keys(a).map(w=>[w,`${C}/previews/${w}/index.html`]))}));return}if(d.method==="GET"&&T==="/api/preview-url"){let $=await st(r);f.writeHead(200,{"Content-Type":"application/json"}),f.end(JSON.stringify({url:r,connected:$}));return}if(d.method==="POST"&&T.split("?")[0]==="/api/wizard-quit"){Le(e),f.writeHead(200,{"Content-Type":"application/json"}),f.end(JSON.stringify({ok:!0,deleted:"out/previews"})),setTimeout(()=>{v.close(()=>{E(new Error("Client quit the wizard without saving. Local preview garbage collection complete (out/previews removed)."))})},300);return}if(d.method==="POST"&&T==="/api/upload-logo"){let $=await uo(d),h=JSON.parse($);k.existsSync(o)||k.mkdirSync(o,{recursive:!0});let P=h.base64.replace(/^data:image\/\w+;base64,/,""),w=Buffer.from(P,"base64"),A=F.extname(h.filename),M=F.basename(h.filename,A).toLowerCase().replace(/[^a-z0-9_-]/g,""),ee=`logo_${Date.now()}_${M}${A||".png"}`;k.writeFileSync(F.join(o,ee),w),f.writeHead(200,{"Content-Type":"application/json"}),f.end(JSON.stringify({fileName:ee}));return}if(d.method==="POST"&&T==="/api/save-config"){let $=await uo(d),h=JSON.parse($);h.configuredAt=new Date().toISOString();let P=h.global?.logo;P?.url?.startsWith("data:")&&(P.url=null),k.writeFileSync(t,JSON.stringify(h,null,2),"utf8"),console.log(`
|
|
128
|
+
${j.green}\u2705 UI configuration saved to ${t}${j.reset}`),Le(e),console.log(`${j.dim} Local preview garbage collection complete (out/previews removed)${j.reset}`),f.writeHead(200,{"Content-Type":"application/json"}),f.end(JSON.stringify({ok:!0})),setTimeout(()=>{v.close(()=>S())},500);return}if(d.method==="GET"){let $=T.split("?")[0];if($==="/"&&($="/index.html"),$.startsWith("/previews/")&&k.existsSync(l)){let w=$.replace(/^\/previews\//,""),A=F.join(l,w),M=F.normalize(A);if(M.startsWith(l)&&k.existsSync(M)&&k.statSync(M).isFile()){let ee=k.readFileSync(M);f.writeHead(200,{"Content-Type":po(M)}),f.end(ee);return}}let h=k.existsSync(s),P=h?F.join(s,$):F.join(i,"wizard.html");if(h&&k.existsSync(P)&&k.statSync(P).isFile()){let w=k.readFileSync(P);f.writeHead(200,{"Content-Type":po(P)}),f.end(w);return}if(!h&&$==="/index.html"){let w=k.readFileSync(F.join(i,"wizard.html"),"utf8");f.writeHead(200,{"Content-Type":"text/html"}),f.end(w);return}}f.writeHead(404,{"Content-Type":"text/plain"}),f.end("Not found")}catch(T){f.writeHead(500,{"Content-Type":"text/plain"}),f.end(`Server error: ${O(T)}`)}});v.listen(m,()=>{let d=C;console.log(`
|
|
129
|
+
${j.bold}${j.cyan}\u{1F3A8} Survey UI Customization Wizard${j.reset}`),console.log(`${j.dim} Running at ${j.reset}${j.green}${d}${j.reset}`),console.log(`${j.dim} Live previews: ${j.reset}${Object.keys(a).length} components`),console.log(`${j.dim} Preview target: ${j.reset}${r}`),console.log(`${j.dim} Default wizard \u2014 saves directly to survey-ui-config.json when client clicks Review & Build${j.reset}
|
|
130
|
+
`),it(d)}),v.on("error",E);let x=()=>{Le(e),v.close(()=>process.exit(130))};process.once("SIGINT",x),process.once("SIGTERM",x)})}U();import*as fe from"fs";import*as xo from"path";import*as To from"http";import*as ko from"https";be();pe();Ee();Re();var g=c;function lt(e){let{exec:o}=we("child_process"),t=process.platform==="darwin"?`open "${e}"`:process.platform==="win32"?`start "" "${e}"`:`xdg-open "${e}"`;o(t)}function ft(e){return new Promise(o=>setTimeout(o,e))}async function ze(e,o={}){return new Promise((t,n)=>{let i=new URL(e),r=(i.protocol==="https:"?ko:To).request(i,{method:o.method??"GET",headers:o.headers??{}},a=>{let l="";a.on("data",y=>l+=y),a.on("end",()=>{if((a.statusCode??500)>=400){n(new Error(`HTTP ${a.statusCode}: ${l}`));return}try{t(JSON.parse(l))}catch{n(new Error(`Invalid JSON: ${l.slice(0,200)}`))}})});r.on("error",n),o.body&&r.write(o.body),r.end()})}async function dt(e,o,t,n){return new Promise((i,s)=>{let r=new URL(e),a=r.protocol==="https:"?ko:To,l={"Content-Type":t,"Content-Length":o.length};n&&(l["X-Wizard-Session"]=n.sessionSecret,l["X-Wizard-Session-Id"]=n.sessionId);let y=a.request(r,{method:"PUT",headers:l},m=>{if((m.statusCode??500)>=400){let C="";m.on("data",S=>C+=S),m.on("end",()=>s(new Error(`PUT failed ${m.statusCode}: ${C}`)));return}m.resume(),i()});y.on("error",s),y.write(o),y.end()})}function gt(e){try{let o=e.split(".")[1];return JSON.parse(Buffer.from(o,"base64url").toString("utf8")).surveyId??null}catch{return null}}async function Po(e={}){let o=e.wait!==!1,t=e.pollIntervalMs??Number(process.env.CFM_WIZARD_POLL_MS??3e3),n=e.timeoutMs??Number(process.env.CFM_WIZARD_TIMEOUT_MS??72e5),i=process.env.CFM_INSTANCE_ID,s=(process.env.CFM_DEPLOY_API_BASE??"http://localhost:3000").replace(/\/$/,"");if(!i)throw new Error("CFM_INSTANCE_ID (JWT) is required");let r=gt(i);if(!r)throw new Error("Could not parse surveyId from CFM_INSTANCE_ID JWT");let a=Te(),l=K(a),y=l.activeConfigPath,m=e.apply?!1:e.review!==!1;console.log(`
|
|
131
131
|
${g.bold}${g.cyan}\u{1F3A8} CFM UI Customization (AWS)${g.reset}
|
|
132
132
|
`),m&&(console.log(`${g.dim} Review mode: seed kept in survey-ui-config.json; final + diff written on complete.${g.reset}`),console.log(`${g.dim} Apply later with: npx cfm-sdk confirm-ui-config${g.reset}
|
|
133
|
-
`));let C=[...Q],{outputDir:S,files:E}=await se({projectRoot:a,useTemplatesOnly:e.useTemplatesOnly,surveyTypes:C}),v=E.map(h=>({path:h.path,contentType:h.contentType,sizeBytes:h.sizeBytes})),{config:x,source:d}=re({projectRoot:a,surveyTypes:C,instanceId:r});x.surveyTypes=C,Fe(d),m&&(fe.writeFileSync(l.seedPath,JSON.stringify(x,null,2),"utf8"),fe.writeFileSync(y,JSON.stringify(x,null,2),"utf8"),console.log(`${g.dim} Seed snapshot \u2192 survey-ui-config.json (+ .seed.json)${g.reset}`));let f=await
|
|
133
|
+
`));let C=[...Q],{outputDir:S,files:E}=await se({projectRoot:a,useTemplatesOnly:e.useTemplatesOnly,surveyTypes:C}),v=E.map(h=>({path:h.path,contentType:h.contentType,sizeBytes:h.sizeBytes})),{config:x,source:d}=re({projectRoot:a,surveyTypes:C,instanceId:r});x.surveyTypes=C,Fe(d),m&&(fe.writeFileSync(l.seedPath,JSON.stringify(x,null,2),"utf8"),fe.writeFileSync(y,JSON.stringify(x,null,2),"utf8"),console.log(`${g.dim} Seed snapshot \u2192 survey-ui-config.json (+ .seed.json)${g.reset}`));let f=await ze(`${s}/wizard/session/start`,{method:"POST",headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json"},body:JSON.stringify({files:v,surveyTypes:C,initialConfig:x})});console.log(`${g.dim} Uploading ${v.length} preview files\u2026${g.reset}`);for(let h of f.uploads){let P=xo.join(S,h.path),w=fe.readFileSync(P),A=v.find(M=>M.path===h.path)?.contentType??"application/octet-stream";await dt(h.uploadUrl,w,A,{sessionId:f.sessionId,sessionSecret:f.sessionSecret})}if(await ze(`${s}/wizard/previews/upload/complete`,{method:"POST",headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json"},body:JSON.stringify({sessionId:f.sessionId})}),console.log(`${g.green}\u2705 Previews uploaded${g.reset}`),console.log(`${g.dim} ${v.length} component preview page(s) \u2192 EC2 local server (disk)${g.reset}`),console.log(`
|
|
134
134
|
${g.bold}${g.cyan}\u{1F517} Client wizard link \u2014 share with the client:${g.reset}`),console.log(`${g.green} ${f.wizardUrl}${g.reset}`),console.log(`${g.dim} (Deployed on EC2 \u2014 client customizes here; agent keeps CLI open until submit)${g.reset}
|
|
135
|
-
`),lt(f.wizardUrl),!o){console.log(`${g.yellow}--no-wait: wizard URL (not polling):${g.reset}`),console.log(f.wizardUrl),m&&console.log(`${g.dim} When wizard completes, poll manually or re-run without --no-wait to capture final + diff.${g.reset}`);return}let T=Date.now()+n,$=0;for(;Date.now()<T;){$+=1,process.stdout.write(`\r${g.dim}Waiting for client to finish wizard\u2026 (poll ${$})${g.reset}`);let h=await
|
|
135
|
+
`),lt(f.wizardUrl),!o){console.log(`${g.yellow}--no-wait: wizard URL (not polling):${g.reset}`),console.log(f.wizardUrl),m&&console.log(`${g.dim} When wizard completes, poll manually or re-run without --no-wait to capture final + diff.${g.reset}`);return}let T=Date.now()+n,$=0;for(;Date.now()<T;){$+=1,process.stdout.write(`\r${g.dim}Waiting for client to finish wizard\u2026 (poll ${$})${g.reset}`);let h=await ze(`${s}/wizard/config/${encodeURIComponent(r)}?sessionId=${f.sessionId}`,{headers:{Authorization:`Bearer ${i}`}});if(h.status==="abandoned")throw console.log(`
|
|
136
136
|
${g.yellow}\u26A0 Client quit the wizard \u2014 session cleaned up on S3${g.reset}`),new Error("Client quit the wizard without saving. S3 preview garbage was removed. Re-run customize-ui to start a new session.");if(h.status==="ready"&&h.config){let P=ve(h)??h.config;if(console.log(`
|
|
137
|
-
${g.green}\u2705 Configuration ready${g.reset}`),h.logoUrl&&console.log(`${g.dim} Logo URL: ${h.logoUrl}${g.reset}`),m){let A=Pe(a,x,P);console.log(`${g.green} Seed (unchanged active): ${y}${g.reset}`),console.log(`${g.green} Final: ${l.finalPath}${g.reset}`),console.log(`${g.green} Diff: ${l.diffMdPath}${g.reset}`),console.log(`${g.yellow} ${A.changed.length} changed, ${A.added.length} added, ${A.removed.length} removed${g.reset}`);let M=P.global?.logo;if(M?.fileName)try{await Z({projectRoot:a,fileName:M.fileName,logoUrl:h.logoUrl,jwt:i,apiBase:s,surveyId:r}),console.log(`${g.green} Logo saved to public/${M.fileName}${g.reset}`)}catch(ee){console.warn(`${g.yellow} Logo download deferred: ${O(ee)}${g.reset}`)}console.log(`${g.dim} Apply when ready: npx cfm-sdk confirm-ui-config${g.reset}`);return}fe.writeFileSync(y,JSON.stringify(P,null,2),"utf8"),console.log(`${g.green} Written ${y}${g.reset}`);let w=P.global?.logo;w?.fileName&&(await Z({projectRoot:a,fileName:w.fileName,logoUrl:h.logoUrl,jwt:i,apiBase:s,surveyId:r}),console.log(`${g.green} Logo saved to public/${w.fileName}${g.reset}`));return}await ft(t)}throw new Error("Timed out waiting for wizard completion")}pe();U();var
|
|
137
|
+
${g.green}\u2705 Configuration ready${g.reset}`),h.logoUrl&&console.log(`${g.dim} Logo URL: ${h.logoUrl}${g.reset}`),m){let A=Pe(a,x,P);console.log(`${g.green} Seed (unchanged active): ${y}${g.reset}`),console.log(`${g.green} Final: ${l.finalPath}${g.reset}`),console.log(`${g.green} Diff: ${l.diffMdPath}${g.reset}`),console.log(`${g.yellow} ${A.changed.length} changed, ${A.added.length} added, ${A.removed.length} removed${g.reset}`);let M=P.global?.logo;if(M?.fileName)try{await Z({projectRoot:a,fileName:M.fileName,logoUrl:h.logoUrl,jwt:i,apiBase:s,surveyId:r}),console.log(`${g.green} Logo saved to public/${M.fileName}${g.reset}`)}catch(ee){console.warn(`${g.yellow} Logo download deferred: ${O(ee)}${g.reset}`)}console.log(`${g.dim} Apply when ready: npx cfm-sdk confirm-ui-config${g.reset}`);return}fe.writeFileSync(y,JSON.stringify(P,null,2),"utf8"),console.log(`${g.green} Written ${y}${g.reset}`);let w=P.global?.logo;w?.fileName&&(await Z({projectRoot:a,fileName:w.fileName,logoUrl:h.logoUrl,jwt:i,apiBase:s,surveyId:r}),console.log(`${g.green} Logo saved to public/${w.fileName}${g.reset}`));return}await ft(t)}throw new Error("Timed out waiting for wizard completion")}pe();U();var N=c,q=process.argv.slice(2),X=q[0];async function bt(){if(X==="customize"||X==="init"){X==="init"&&console.log(`${N.yellow}\u26A0 cfm-sdk init is deprecated. Use \`cfm-sdk customize\` instead.${N.reset}
|
|
138
138
|
`);try{await ho()}catch(e){console.error(`
|
|
139
|
-
${
|
|
140
|
-
${
|
|
141
|
-
${
|
|
142
|
-
${
|
|
143
|
-
${
|
|
144
|
-
${
|
|
145
|
-
${
|
|
146
|
-
${
|
|
139
|
+
${N.red}\u274C Error: ${O(e)}${N.reset}`),process.exit(1)}}else if(X==="customize-ui"){let e=q.includes("--use-templates-only"),o=q.includes("--no-wait"),t=q.includes("--apply"),n=q.includes("--no-review")?!1:!t;try{await Po({useTemplatesOnly:e,wait:!o,review:n,apply:t})}catch(i){console.error(`
|
|
140
|
+
${N.red}\u274C Error: ${O(i)}${N.reset}`),process.exit(1)}}else if(X==="confirm-ui-config"){let e=q.includes("--diff-only");try{let{runConfirmUiConfig:o}=await Promise.resolve().then(()=>(vo(),Eo));await o({diffOnly:e})}catch(o){console.error(`
|
|
141
|
+
${N.red}\u274C Error: ${O(o)}${N.reset}`),process.exit(1)}}else if(X==="fetch-ui-config"){let o=q.find(t=>t.startsWith("--session="))?.split("=")[1];try{let{runFetchUiConfig:t}=await Promise.resolve().then(()=>(Io(),Ro));await t({sessionId:o})}catch(t){console.error(`
|
|
142
|
+
${N.red}\u274C Error: ${O(t)}${N.reset}`),process.exit(1)}}else if(X==="export-previews"){let e=q.includes("--use-templates-only");try{await se({useTemplatesOnly:e})}catch(o){console.error(`
|
|
143
|
+
${N.red}\u274C Error: ${O(o)}${N.reset}`),process.exit(1)}}else if(X==="resolve-ui-config"){let e=q.includes("--write");try{if(e){let o=Ne();console.log(`${N.green}\u2705 Wrote ${o}${N.reset}`)}else{let{resolveInitialConfig:o}=await Promise.resolve().then(()=>(pe(),fo)),{config:t,source:n}=o({surveyTypes:[]});console.log(JSON.stringify({source:n,config:t},null,2))}}catch(o){console.error(`
|
|
144
|
+
${N.red}\u274C Error: ${O(o)}${N.reset}`),process.exit(1)}}else if(X==="deploy")try{await Xe()}catch(e){console.error(`
|
|
145
|
+
${N.red}\u274C Error: ${O(e)}${N.reset}`),process.exit(1)}else console.log(`
|
|
146
|
+
${N.bold}${N.cyan}CFM SDK CLI Tool${N.reset}`),console.log(`
|
|
147
147
|
Usage:`),console.log(" npx cfm-sdk customize \u2013 Local UI customization wizard"),console.log(" npx cfm-sdk customize-ui \u2013 AWS wizard (review mode: seed + diff, no auto-apply)"),console.log(" npx cfm-sdk customize-ui --apply \u2013 AWS wizard (legacy: write final config immediately)"),console.log(" npx cfm-sdk confirm-ui-config \u2013 Apply survey-ui-config.final.json after review"),console.log(" npx cfm-sdk fetch-ui-config \u2013 Pull final + diff after client completes (--no-wait)"),console.log(" npx cfm-sdk export-previews \u2013 Build component preview pages only"),console.log(" npx cfm-sdk resolve-ui-config --write \u2013 Write draft survey-ui-config.json from project"),console.log(" npx cfm-sdk deploy \u2013 Deploy to Vercel"),process.exit(0)}bt();
|
package/package.json
CHANGED
|
@@ -127,6 +127,8 @@ Machine-readable routing: [`MANIFEST.json`](../MANIFEST.json) `phases[]`.
|
|
|
127
127
|
| Source (`docs/templates/`) | Destination |
|
|
128
128
|
|----------------------------|-------------|
|
|
129
129
|
| `Header.tsx`, `Footer.tsx`, `ProgressBar.tsx`, `SurveyStickyChrome.tsx`, `LanguageSelector.tsx`, `PreviewBridgeInit.tsx` | `src/components/` |
|
|
130
|
+
| `uiConfig.ts` | `src/lib/uiConfig.ts` |
|
|
131
|
+
| `RatingScale.tsx` | `src/components/` |
|
|
130
132
|
| `survey-theme.css` | `src/styles/survey-theme.css` |
|
|
131
133
|
| `selectionStyles.ts` | `src/lib/surveyUi/selectionStyles.ts` |
|
|
132
134
|
| `labelStyles.ts` | `src/lib/surveyUi/labelStyles.ts` |
|
|
@@ -222,25 +224,26 @@ Share EC2 link; keep CLI open until `✅ Configuration ready`. See `wizard-confi
|
|
|
222
224
|
|
|
223
225
|
### Phase 6c — Apply wizard changes (mandatory when wizard used)
|
|
224
226
|
|
|
225
|
-
**Read:** `wizard-config-handoff.md`, `apply-ui-config.md`, `wizard-question-type-styling.md`
|
|
227
|
+
**Read:** `wizard-post-customize-build.md` (runbook + all format matrix), `wizard-config-handoff.md`, `apply-ui-config.md`, `wizard-question-type-styling.md`
|
|
226
228
|
|
|
227
229
|
**Input file:**
|
|
228
230
|
- AWS: `survey-ui-config.final.json`
|
|
229
231
|
- Local: `survey-ui-config.json`
|
|
230
232
|
|
|
231
|
-
**Do (in order)
|
|
233
|
+
**Do (in order)** — full checklist in `wizard-post-customize-build.md`:
|
|
232
234
|
1. Validate JSON against `templates/survey-ui-config.schema.json`
|
|
233
235
|
2. Read **entire** `survey-ui-config.diff.md` (AWS) — every path must be applied
|
|
234
236
|
3. Regenerate `src/styles/survey-theme.css` from **full** final config (not partial)
|
|
235
237
|
4. Update all `data-cfm-*` content hooks (title, buttons, footer, logo)
|
|
236
238
|
5. Apply layout toggles in `SurveyPage` / chrome
|
|
237
239
|
6. Wire `placeholders`, `customFields`, `debug` from final config
|
|
238
|
-
7. Apply
|
|
240
|
+
7. Apply **all** `questionTypes.*` blocks (10 wizard families + TEXT_AND_MEDIA theme vars) — see format matrix in `wizard-post-customize-build.md`
|
|
239
241
|
8. AWS: `npx cfm-sdk confirm-ui-config` (promotes final → active + downloads logo)
|
|
240
|
-
9. When `global.logo.fileName` is set:
|
|
242
|
+
9. When `global.logo.fileName` is set: Header via `uiConfig.ts` `src="./{fileName}"`; verify `public/{fileName}` exists
|
|
241
243
|
10. Re-run `verify-agent-build.sh` + `npm run build`
|
|
242
244
|
11. Verify logo in static output: `test -f out/$(jq -r '.global.logo.fileName' survey-ui-config.json)` when fileName set
|
|
243
|
-
12. **Do not**
|
|
245
|
+
12. **Do not** re-run `export-previews` or wizard — apply config to client app only
|
|
246
|
+
13. **Do not** change dispatch logic in `Question.tsx`
|
|
244
247
|
|
|
245
248
|
**Blocking:** Do not proceed to Phase 7 until diff paths are applied and verify passes.
|
|
246
249
|
|
|
@@ -123,6 +123,8 @@ Use this table when deciding what to read. **Do not substitute similar-sounding
|
|
|
123
123
|
| Logo from any `public/logo_*` | `Header.tsx` `data-cfm-logo` / `data-cfm-logo-text` contract |
|
|
124
124
|
| `global.logo.url` as Header `src` | `./{fileName}` from `public/` built into `out/` — see `aws-deploy.md` § Logos |
|
|
125
125
|
| Wizard logo “in memory” on CloudFront | Re-apply `fileName`, rebuild, redeploy — preview `data:` ≠ deploy bundle |
|
|
126
|
+
| Bare `UI_CONFIG` in SurveyPage/components | Import `src/lib/uiConfig.ts` or `survey-ui-config.json` — `ReferenceError` blank page |
|
|
127
|
+
| Changed `global.logo.fileName` at deploy time | Use wizard `fileName` + matching `public/` file — see logo pipeline in `wizard-chrome-contract.md` |
|
|
126
128
|
| `getVisible*` without 4th arg when CRM logic exists | Pass `customFieldValues` — `hookContract.visibilityHelpers` |
|
|
127
129
|
| New question types or SDK actions | Only documented `onAction` types in `useSurveySDK.md` |
|
|
128
130
|
| Placeholder unstable inline object | Stable ref + `useMemo` on hook options |
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Apply UI Config (`survey-ui-config.json`)
|
|
2
2
|
|
|
3
3
|
> **Phase 6c** — after wizard handoff. Read [`wizard-config-handoff.md`](wizard-config-handoff.md) first (wait protocol + review artifacts).
|
|
4
|
+
> **Runbook (all types/formats + build gate):** [`wizard-post-customize-build.md`](wizard-post-customize-build.md).
|
|
4
5
|
> **Build-time contract:** [`wizard-preview-build-guide.md`](wizard-preview-build-guide.md).
|
|
5
6
|
> **Per-type tokens:** [`wizard-question-type-styling.md`](wizard-question-type-styling.md).
|
|
6
7
|
|
|
@@ -76,8 +77,8 @@ Import in `globals.css`: `@import './styles/survey-theme.css';`
|
|
|
76
77
|
| `global.buttons.next` | SurveyPage | `data-cfm-btn-next` text |
|
|
77
78
|
| `global.buttons.back` | SurveyPage | `data-cfm-btn-back` text |
|
|
78
79
|
| `global.buttons.submit` | SurveyPage submit label | button text |
|
|
79
|
-
| `global.logo.fileName` | Header | `data-cfm-logo` src=`./${fileName}`
|
|
80
|
-
| `global.logo.url` | Download source only | EC2: CloudFront `/assets/` URL → `confirm-ui-config` copies to `public/`. **Never** use as `img src`
|
|
80
|
+
| `global.logo.fileName` | Header | `data-cfm-logo` src=`./${fileName}` via `uiConfig.ts` — **deploy truth**; must match `public/{fileName}` |
|
|
81
|
+
| `global.logo.url` | Download source only | EC2: CloudFront `/assets/` URL → `confirm-ui-config` copies to `public/`. **Never** use as `img src` |
|
|
81
82
|
| `global.footer.copyrightText` | Footer | `data-cfm-copyright` |
|
|
82
83
|
| `global.footer.links[]` | Footer | `data-cfm-footer-links` (render links) |
|
|
83
84
|
| `questionTypes.MCQ.optionStyle` | `:root` or survey wrapper | `data-cfm-mcq-style` |
|
|
@@ -130,6 +131,17 @@ Wizard preview keeps the image in **browser memory** (`data:` URL). CloudFront o
|
|
|
130
131
|
3. **`global.logo.url` after local wizard:** must be `null` (CLI strips `data:` on save). If you still see `data:image/…` in JSON, re-save from wizard or clear `url` manually.
|
|
131
132
|
4. **AWS static export:** `src="./{fileName}"` (leading `./`). Absolute `/file.png` breaks under `/sites/{surveyId}/{deployId}/`.
|
|
132
133
|
5. Prefer plain `<img data-cfm-logo>` over `next/image` for logo files — simpler relative paths in `out/`.
|
|
134
|
+
6. Copy [`templates/uiConfig.ts`](../templates/uiConfig.ts) — Header/Footer import `getLogoSrc()` / `getCompanyName()`. **Never** reference bare `UI_CONFIG` (runtime crash).
|
|
135
|
+
|
|
136
|
+
**After wizard save — logo apply (mandatory):**
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# Confirm wizard wrote both artifacts
|
|
140
|
+
ls public/$(jq -r '.global.logo.fileName' survey-ui-config.json)
|
|
141
|
+
jq '.global.logo.fileName' survey-ui-config.json
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Update `Header.tsx` only via template / `uiConfig.ts` — do not hand-edit `fileName` to a seed SVG.
|
|
133
145
|
|
|
134
146
|
**Verify before Phase 7:**
|
|
135
147
|
|
|
@@ -385,6 +397,7 @@ Do not re-run the wizard unless the client explicitly requests another session.
|
|
|
385
397
|
|
|
386
398
|
| Doc | Role |
|
|
387
399
|
|-----|------|
|
|
400
|
+
| [`wizard-post-customize-build.md`](wizard-post-customize-build.md) | Phase 6c runbook — format matrix + verify/build gate |
|
|
388
401
|
| [`wizard-config-handoff.md`](wizard-config-handoff.md) | Wait + capture + confirm order |
|
|
389
402
|
| [`wizard-question-type-styling.md`](wizard-question-type-styling.md) | Visual selection patterns |
|
|
390
403
|
| [`agent-operating-contract.md`](agent-operating-contract.md) | Do not change dispatch logic |
|
|
@@ -19,7 +19,13 @@ Pipeline: [`wizard-preview-build-guide.md`](wizard-preview-build-guide.md) · [`
|
|
|
19
19
|
| Question card padding/shadow/colors not live-updating | Question wrapper uses `var(--cfm-card-*)` — not hardcoded `bg-white shadow-sm` |
|
|
20
20
|
| MCQ / NPS / dropzone style pickers | Root reads `html[data-cfm-mcq-style]`, `[data-cfm-nps-button-style]`, `[data-cfm-dropzone-style]` from bridge |
|
|
21
21
|
| Scale selection colors not updating | Import `selectionStyles.ts`; use `var(--cfm-matrix-selected)` / `var(--cfm-input-focus-ring)` |
|
|
22
|
-
|
|
|
22
|
+
| Company name not showing after logo | Copy `Header.tsx` template — brand row is `[logo][data-cfm-company]` in one flex container |
|
|
23
|
+
| Company shows when empty | Bridge clears `[data-cfm-company]` when `companyName` is `""` — do not hardcode "Company Name" as visible default |
|
|
24
|
+
| NPS colors / rings not updating | Copy `RatingScale.tsx` + `selectionStyles.ts` — no hardcoded `#e20074` |
|
|
25
|
+
| Text placeholder color not updating | `data-cfm-textfield` + `--cfm-input-placeholder` in CSS / `::placeholder` rule |
|
|
26
|
+
| Matrix 2nd row toggle | Harness adds row via `previewMultiStatement` — `LikertMatrixScale` must render all `statementRows` from props |
|
|
27
|
+
| Blank page after deploy | **Never** reference `UI_CONFIG` without import — use `src/lib/uiConfig.ts` |
|
|
28
|
+
| Logo wrong on CloudFront | Never change `global.logo.fileName` manually — use wizard file in `public/` |
|
|
23
29
|
|
|
24
30
|
---
|
|
25
31
|
|
|
@@ -35,6 +41,8 @@ cp templates/docs/templates/LanguageSelector.tsx src/components/LanguageSelector
|
|
|
35
41
|
cp templates/docs/templates/PreviewBridgeInit.tsx src/components/PreviewBridgeInit.tsx
|
|
36
42
|
cp templates/previewBridge.ts src/lib/previewBridge.ts
|
|
37
43
|
cp templates/survey-theme.css src/styles/survey-theme.css
|
|
44
|
+
cp templates/docs/templates/uiConfig.ts src/lib/uiConfig.ts
|
|
45
|
+
cp templates/docs/templates/RatingScale.tsx src/components/RatingScale.tsx
|
|
38
46
|
cp templates/docs/templates/selectionStyles.ts src/lib/surveyUi/selectionStyles.ts
|
|
39
47
|
cp templates/docs/templates/labelStyles.ts src/lib/surveyUi/labelStyles.ts
|
|
40
48
|
```
|
|
@@ -157,6 +165,72 @@ TEXTFIELD placeholder live preview: `data-cfm-textfield` on input/textarea.
|
|
|
157
165
|
|
|
158
166
|
---
|
|
159
167
|
|
|
168
|
+
### Branding & header — company name after logo
|
|
169
|
+
|
|
170
|
+
**Layout rule:** Logo and company name share one flex row (`.cfm-header-brand`):
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
[ data-cfm-logo img ] [ data-cfm-company text ]
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
| State | What preview shows |
|
|
177
|
+
|-------|-------------------|
|
|
178
|
+
| No logo, no company | Empty header brand slot (no text) |
|
|
179
|
+
| No logo, company set | `data-cfm-logo-text` shows company name |
|
|
180
|
+
| Logo uploaded, company set | Image visible + `data-cfm-company` text **after** logo |
|
|
181
|
+
| Logo uploaded, company empty | Image only; company span hidden |
|
|
182
|
+
|
|
183
|
+
Wizard **Logo** step controls size via `global.header.logoBoxWidth`, `logoBoxHeight`, `logoPadding` → CSS vars `--cfm-header-logo-width/height/padding`.
|
|
184
|
+
|
|
185
|
+
**Agent must copy** [`uiConfig.ts`](../templates/uiConfig.ts) — Header reads `survey-ui-config.json` at build time. **Never** use a global `UI_CONFIG` variable (causes `ReferenceError` blank page).
|
|
186
|
+
|
|
187
|
+
### Logo pipeline (wizard → CloudFront) — all 4 steps must match
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
1. Wizard upload → public/logo_{timestamp}_{name}.jpg
|
|
191
|
+
2. save-config → survey-ui-config.json global.logo.fileName (same name)
|
|
192
|
+
3. Phase 6c apply → Header img src="./{fileName}" via uiConfig.ts
|
|
193
|
+
4. build + deploy → out/{fileName} → S3 deploy prefix → CloudFront
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Forbidden during deploy troubleshooting:**
|
|
197
|
+
- Changing `global.logo.fileName` to `telekom-logo.svg` because JPG "wasn't ready"
|
|
198
|
+
- Using `global.logo.url` (data: or /assets/ URL) as img src
|
|
199
|
+
|
|
200
|
+
If deploy preflight fails on missing logo: wait for wizard save (file lands in `public/`), then rebuild — do not substitute a different filename.
|
|
201
|
+
|
|
202
|
+
See [`aws-deploy.md`](aws-deploy.md) § Logos & local assets.
|
|
203
|
+
|
|
204
|
+
### Question card — cell selected + focus ring
|
|
205
|
+
|
|
206
|
+
Theme → Question card exposes two tokens used on **every** radio/scale cell:
|
|
207
|
+
|
|
208
|
+
| Token | CSS var | Visual |
|
|
209
|
+
|-------|---------|--------|
|
|
210
|
+
| Cell selected | `--cfm-matrix-selected` | **Fill** inside outer ring (annulus) |
|
|
211
|
+
| Focus ring | `--cfm-input-focus-ring` | **Outer border** + **inner dot** |
|
|
212
|
+
|
|
213
|
+
Copy [`selectionStyles.ts`](../templates/selectionStyles.ts) and use in `RatingScale.tsx`, `LikertMatrixScale.tsx`, `CsatMatrixScale.tsx`, MCQ options.
|
|
214
|
+
|
|
215
|
+
### Per-type live preview (all 11 types)
|
|
216
|
+
|
|
217
|
+
| Type | Required wiring |
|
|
218
|
+
|------|-----------------|
|
|
219
|
+
| MCQ | `var(--cfm-mcq-*)` on option cards; `html[data-cfm-mcq-style]` |
|
|
220
|
+
| TEXTFIELD | `data-cfm-textfield` + `--cfm-input-placeholder` on `::placeholder` |
|
|
221
|
+
| NPS_SCALE | Copy wizard `RatingScale.tsx`; `selectionStyles` on radio rings |
|
|
222
|
+
| CFM_MATRIX | `matrixRadioRingStyle`; render **all** `statementRows` (wizard multi-row toggle adds 2nd row in harness) |
|
|
223
|
+
| CSAT/RATING_MATRIX | `CsatMatrixScale.tsx` + `labelStyles.ts` |
|
|
224
|
+
| SLIDER_MATRIX | `CustomSliderTrack.tsx` + slider tick vars |
|
|
225
|
+
| FILE_UPLOAD | `data-cfm-dropzone-style` + `--cfm-upload-border-color` |
|
|
226
|
+
| HEATMAP | `--cfm-heatmap-pin*` |
|
|
227
|
+
| RANK_ORDER | `--cfm-rank-*` |
|
|
228
|
+
| TEXT_AND_MEDIA | `--cfm-media-*` |
|
|
229
|
+
|
|
230
|
+
Full table: [`wizard-question-type-styling.md`](wizard-question-type-styling.md).
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
160
234
|
## SurveyPage wiring (content phase)
|
|
161
235
|
|
|
162
236
|
```tsx
|
|
@@ -171,19 +245,17 @@ Intro / end / paused: standalone `<Header />` (not sticky chrome). Footer still
|
|
|
171
245
|
|
|
172
246
|
---
|
|
173
247
|
|
|
174
|
-
## Local wizard
|
|
175
|
-
|
|
176
|
-
When the client **quits** local wizard (`npx cfm-sdk customize`) without saving:
|
|
177
|
-
|
|
178
|
-
1. Wizard SPA calls `POST /api/wizard-quit` on the customize server
|
|
179
|
-
2. CLI deletes `out/previews/` on agent disk
|
|
180
|
-
3. CLI exits; no orphan preview folders
|
|
248
|
+
## Local wizard — preview garbage collection
|
|
181
249
|
|
|
182
|
-
|
|
250
|
+
| Event | Action |
|
|
251
|
+
|-------|--------|
|
|
252
|
+
| Client **saves** (Review & Build) | `POST /api/save-config` → writes config → **deletes `out/previews/`** → CLI exits |
|
|
253
|
+
| Client **quits** without saving | `POST /api/wizard-quit` → deletes `out/previews/` → CLI exits |
|
|
254
|
+
| Agent **Ctrl+C** on customize CLI | Same cleanup on shutdown |
|
|
183
255
|
|
|
184
|
-
|
|
256
|
+
EC2 `customize-ui`: quit/save uses disk session GC — see [`wizard-config-handoff.md`](wizard-config-handoff.md).
|
|
185
257
|
|
|
186
|
-
|
|
258
|
+
**Note:** GC removes **preview export cache** (`out/previews/`), not your `src/` or production `out/` build. Re-run `export-previews` on next wizard session.
|
|
187
259
|
|
|
188
260
|
---
|
|
189
261
|
|
|
@@ -205,6 +277,7 @@ EC2 `customize-ui`: quit calls `POST /wizard/session/quit` — disk session fold
|
|
|
205
277
|
| Doc | Role |
|
|
206
278
|
|-----|------|
|
|
207
279
|
| [`wizard-preview-build-guide.md`](wizard-preview-build-guide.md) | Full build guide |
|
|
280
|
+
| [`wizard-post-customize-build.md`](wizard-post-customize-build.md) | After wizard save — apply all formats + build |
|
|
208
281
|
| [`wizard-question-type-styling.md`](wizard-question-type-styling.md) | Per-type CSS vars |
|
|
209
282
|
| [`10-header-footer.md`](../01-components/10-header-footer.md) | Branding patterns |
|
|
210
283
|
| [`12-survey-chrome.md`](../03-ui-specs/12-survey-chrome.md) | Chrome layout spec |
|