@evotecit/canopyx 0.3.15 → 0.3.16
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/CanopyX.Html/Assets/canopyx-flow-checks.css +2 -0
- package/CanopyX.Html/Assets/canopyx-flow-checks.js +5 -4
- package/CanopyX.Html/Assets/canopyx-flow-dialog.css +2 -0
- package/CanopyX.Html/Assets/canopyx-flow-dialog.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-entry.js +4 -4
- package/CanopyX.Html/Assets/canopyx-flow-facts.js +2 -0
- package/CanopyX.Html/Assets/canopyx-flow-module.mjs +4 -4
- package/CanopyX.Html/Assets/canopyx-flow.js +8 -7
- package/CanopyX.Html/Assets/canopyx-grid-module.mjs +5 -5
- package/CanopyX.Html/Assets/canopyx-grid.js +5 -5
- package/CanopyX.Html/Assets/canopyx-interactive.js +1 -1
- package/CanopyX.Html/Assets/canopyx-live.js +19 -14
- package/CanopyX.Html/Assets/canopyx-module.mjs +1 -1
- package/CanopyX.Html/Assets/canopyx-record-panel.css +8 -0
- package/CanopyX.Html/Assets/canopyx-record-panel.js +12 -7
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +5 -5
- package/CanopyX.Html/Assets/canopyx-reporting.js +5 -5
- package/CanopyX.Html/Assets/canopyx.js +1 -1
- package/JavaScript/flow.d.ts +6 -0
- package/JavaScript/grid.d.ts +3 -1
- package/JavaScript/live.d.ts +2 -0
- package/JavaScript/records.d.ts +18 -4
- package/README.md +2 -2
- package/package.json +1 -1
|
@@ -22,3 +22,5 @@
|
|
|
22
22
|
.cx-flow-answer[data-cx-state="warning"] .cx-flow-answer-value{color:var(--hfx-color-status-warn-fg,light-dark(#8c5c05,#eeb640));}
|
|
23
23
|
@media (forced-colors:active){.cx-flow-check-mark{forced-color-adjust:none;border:var(--cx-size-1px) solid CanvasText;}}
|
|
24
24
|
@media print{.cx-flow-check-head button,.cx-flow-check-again{display:none;}}
|
|
25
|
+
.cx-flow-check-item[data-cx-state="fail"]{padding:var(--cx-size-12px);border:var(--cx-size-1px) solid var(--hfx-color-status-bad-fg,light-dark(#b8292a,#f47171));border-radius:var(--hfx-radius-sm,4px);background:var(--hfx-color-status-bad-bg,light-dark(#f9e4e4,#3c272a));color:var(--hfx-color-status-bad-fg,light-dark(#b8292a,#f47171));}
|
|
26
|
+
.cx-flow-step:has(.cx-flow-checks) input.cx-flow-input[readonly]{padding-inline:0;border-color:transparent;background:transparent;box-shadow:none;color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
(function(global){"use strict";const installed=new WeakSet();const part={version:"
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"318849d97560c594",requires:["flow","flow-host"],install(context){if(installed.has(context.FLOW_IMPL))return;const{FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat}=context;const{FlowView,FLOW_HOST,FLOW_LABELS,flowFail,flowIs,flowKeys,flowName,flowString,flowFlag,flowScalar,flowFits,flowField,flowOptions,flowCondition,flowRefs,flowTest,flowCopy,flowSameValue,flowEmpty,flowNormal,flowDate,flowFieldView}=FLOW_IMPL.core;const{EDIT_EDITORS,formRuleSpec,formCheck}=FORMS_IMPL;const FLOW_PART_LABELS={flowRunAgain:"Run again",flowRunCheckAgain:"Run “{check}” again",flowChecks:"Checks",flowCheckAcknowledge:"Continue despite the warning",flowCheckRunning:"Checking…",flowCheckNotRun:"Not run",flowCheckStale:"The answers changed since the check",flowCheckPassed:"Passed at {time}",flowCheckWarning:"Warning at {time}",flowCheckFailed:"Failed at {time}",flowCheckInvalid:"The check gave no usable answer.",flowCheckNeeded:"Run “{check}” on these answers.",flowCheckNotPassed:"“{check}” did not pass.",flowCheckConfirmWarning:"Confirm the warning of “{check}”."};Object.assign(FLOW_LABELS,FLOW_PART_LABELS);const FLOW_CHECK_MARKS={pass:"✓",warning:"!",fail:"×",running:"…"};FLOW_HOST.checks={read(raw,step,model){if(step.type!=="form"||!Array.isArray(raw)||!raw.length||raw.length>8)flowFail("step "+step.id+" has 1 to 8 checks, as a form step only");for(const entry of raw){flowKeys(entry,["id","label","description","fields","required"],"A check");const id=flowName(entry.id,"A check id");if(model.checks.has(id))flowFail("the check id '"+id+"' is used twice");if(!Array.isArray(entry.fields)||!entry.fields.length||entry.fields.length>64||entry.fields.some(name=>typeof name!=="string"))flowFail("check "+id+" needs 1 to 64 field ids");if(entry.required!==undefined&&!["pass","run"].includes(entry.required))flowFail("check "+id+" requires pass or run");const check=Object.freeze({id,step,label:flowString(entry.label,200,"A check label",true),description:flowString(entry.description,1000,"A check description"),fields:Object.freeze([...new Set(entry.fields)]),required:entry.required??null});model.checks.set(id,check);step.checks.push(check)}},finish(model){for(const check of model.checks.values())for(const id of check.fields)if(!model.fields.has(id))flowFail("check "+check.id+" names the unknown field '"+id+"'")},built(view,step,section){if(step.checks.length){section.appendChild(view.checkBlock(step));queueMicrotask(()=>step.checks.forEach(check=>view.paintCheck(check)))}},review:(view,section)=>view.reviewChecks(section),proposal(view,proposal){const checks=view.checkSummary();if(Object.keys(checks).length)proposal.checks=checks}};Object.assign(FlowView.prototype,{checkBlock(step){const block=h("div","cx-flow-checks"),title=h("h4","cx-flow-section-title");title.id=this.id+"-c-"+step.id;setText(title,this.labels.flowChecks);block.setAttribute("role","group");block.setAttribute("aria-labelledby",title.id);block.appendChild(title);for(const check of step.checks){const item=h("div","cx-flow-check-item"),head=h("div","cx-flow-check-head"),run=h("button","cx-flow-btn"),cancel=h("button","cx-flow-btn cx-flow-quiet");const status=h("span","cx-flow-check-status"),mark=h("span","cx-flow-check-mark"),text=h("span"),message=h("p","cx-flow-check-message"),details=h("dl","cx-flow-check-details");const ack=h("label","cx-flow-switch cx-flow-check-ack"),box=h("input"),ackText=h("span");item.dataset.cxCheck=check.id;run.type=cancel.type="button";setText(run,check.label);setText(cancel,this.labels.flowCancel);cancel.hidden=true;status.setAttribute("role","status");mark.setAttribute("aria-hidden","true");status.append(mark,text);status.id=this.id+"-cs-"+check.id;run.setAttribute("aria-describedby",status.id);run.addEventListener("click",()=>this.runCheck(check.id).catch(error=>this.report(error,"check")));cancel.addEventListener("click",()=>this.checkState.get(check.id)?.controller?.abort());box.type="checkbox";setText(ackText,this.labels.flowCheckAcknowledge);ack.append(box,ackText);ack.hidden=true;box.addEventListener("change",()=>{const state=this.checkState.get(check.id);if(state)state.acknowledged=box.checked;this.paintCheck(check);this.renderRail()});head.append(run,status,cancel);item.appendChild(head);if(check.description){const description=h("p","cx-flow-help");setText(description,check.description);item.appendChild(description)}
|
|
2
2
|
item.append(message,details,ack);item._cx={run,cancel,mark,text,message,details,ack,box};block.appendChild(item)}
|
|
3
|
-
return block},paintCheck(check){const section=this.sections.get(check.step.id),item=section?.querySelector('[data-cx-check="'+check.id+'"]');if(!item)return;const parts=item._cx,state=this.checkState.get(check.id),labels=this.labels,result=state?.result;const phase=state?.running?"running":!result?"none":state.stale?"stale":result.status;item.dataset.cxState=phase;setText(parts.mark,FLOW_CHECK_MARKS[phase]||"");setText(parts.text,phase==="running"?labels.flowCheckRunning:phase==="none"?labels.flowCheckNotRun:phase==="stale"?labels.flowCheckStale:
|
|
4
|
-
fill(phase==="pass"?labels.flowCheckPassed:phase==="warning"?labels.flowCheckWarning:labels.flowCheckFailed,{time:this.checkTime(state.at)}));parts.run.disabled=!!state?.running;parts.cancel.hidden=!state?.running;parts.message.hidden=!result?.message||phase==="running";setText(parts.message,result?.message||"");parts.details.replaceChildren(...(phase==="running"?[]:result?.details||[]).map(row=>{const line=h("div"),term=h("dt"),value=h("dd");setText(term,row.label);setText(value,row.value);line.append(term,value);return line}));parts.details.hidden=!parts.details.children.length;parts.ack.hidden=!(check.required==="run"&&phase==="warning");parts.box.checked=!!state?.acknowledged},checkTime(at){try{return new Intl.DateTimeFormat(this.lang||undefined,{timeStyle:"short"}).format(new Date(at))}catch(error){return at}},checksChanged(field){const affected=new Map([[field.id,true]]);const changed=id=>{if(!affected.has(id))affected.set(id,[...this.model.fields.get(id).refs].some(changed));return affected.get(id)};
|
|
5
|
-
|
|
3
|
+
return block},paintCheck(check){const section=this.sections.get(check.step.id),item=section?.querySelector('[data-cx-check="'+check.id+'"]');if(!item)return;const parts=item._cx,state=this.checkState.get(check.id),labels=this.labels,result=state?.result;const phase=state?.running?"running":!result?"none":state.stale?"stale":result.status;item.dataset.cxState=phase;setText(parts.run,result?labels.flowRunAgain:check.label);parts.run.setAttribute("aria-label",result?fill(labels.flowRunCheckAgain,{check:check.label}):check.label);parts.run.classList.toggle("cx-primary",phase==="fail");setText(parts.mark,FLOW_CHECK_MARKS[phase]||"");setText(parts.text,phase==="running"?labels.flowCheckRunning:phase==="none"?labels.flowCheckNotRun:phase==="stale"?labels.flowCheckStale:
|
|
4
|
+
fill(phase==="pass"?labels.flowCheckPassed:phase==="warning"?labels.flowCheckWarning:labels.flowCheckFailed,{time:this.checkTime(state.at)}));parts.run.disabled=!!state?.running;parts.cancel.hidden=!state?.running;parts.message.hidden=!result?.message||phase==="running";setText(parts.message,result?.message||"");parts.details.replaceChildren(...(phase==="running"?[]:result?.details||[]).map(row=>{const line=h("div"),term=h("dt"),value=h("dd");setText(term,row.label);setText(value,row.value);line.append(term,value);return line}));parts.details.hidden=!parts.details.children.length;parts.ack.hidden=!(check.required==="run"&&phase==="warning");parts.box.checked=!!state?.acknowledged},checkTime(at){try{return new Intl.DateTimeFormat(this.lang||undefined,{timeStyle:"short"}).format(new Date(at))}catch(error){return at}},checksChanged(field){if(!this.model.checks.size)return;const affected=new Map([[field.id,true]]);const changed=id=>{if(!affected.has(id))affected.set(id,[...this.model.fields.get(id).refs].some(changed));return affected.get(id)};this.invalidateChecks([...this.model.checks.values()].filter(check=>check.fields.some(changed)).map(check=>check.id))},invalidateChecks(ids){if(!this.model.checks.size)flowFail("this flow has no checks to invalidate");const names=ids===undefined?[...this.model.checks.keys()]:ids;if(!Array.isArray(names)||names.length>512||names.some(id=>typeof id!=="string"||!this.model.checks.has(id)))
|
|
5
|
+
flowFail("invalidateChecks needs existing check ids, or no argument for every check");let invalidated=false;for(const id of new Set(names)){const check=this.model.checks.get(id),state=this.checkState.get(id);if(!state)continue;state.controller?.abort();Object.assign(state,{stale:true,acknowledged:false,running:false,controller:null,ticket:{}});this.paintCheck(check);invalidated=true}
|
|
6
|
+
if(invalidated){this.answersChanged();this.renderRail();this.reviewStale=true;this.paintReview(true)}},async runCheck(id){const check=this.model.checks.get(id);if(!check)flowFail("there is no check '"+id+"'");const state=this.checkState.get(id)||{},controller=new AbortController(),ticket={};state.controller?.abort();Object.assign(state,{controller,ticket,running:true});this.checkState.set(id,state);this.paintCheck(check);this.paintReview();const secrets=new Map(check.fields.map(name=>this.model.fields.get(name)).filter(field=>field.type==="secret"&&this.visible(field)&&this.secrets.has(field.id)).map(field=>[field.id,this.secrets.get(field.id)]));const revoke=()=>secrets.clear();controller.signal.addEventListener("abort",revoke,{once:true});const run=typeof this.hooks.check==="function"?signal=>this.hooks.check(id,this.getValues(),{signal,secret:name=>{const value=secrets.get(name)??null;secrets.delete(name);return value}}):()=>{throw new Error(this.labels.flowNoHostHook)};const answer=await this.timed("check",run,controller);revoke();controller.signal.removeEventListener("abort",revoke);if(this.checkState.get(id)!==state||state.ticket!==ticket||this.destroyed)return null;state.running=false;if(answer.cancelled){this.paintCheck(check);this.paintReview();return null}
|
|
6
7
|
const result=answer.failed?{status:"fail",message:answer.failed,details:[],fieldErrors:{}}:this.checkResult(answer.value);for(const[field,message]of Object.entries(state.result?.fieldErrors||{}))if(!Object.hasOwn(result.fieldErrors,field)&&this.hostErrors.get(field)===message){this.hostErrors.delete(field);if(this.errors.get(field)===message)this.setError(this.model.fields.get(field),null)}
|
|
7
8
|
Object.assign(state,{result,at:new Date().toISOString(),stale:false,acknowledged:false});for(const[field,message]of Object.entries(result.fieldErrors)){this.hostErrors.set(field,message);this.setError(this.model.fields.get(field),message)}
|
|
8
9
|
this.paintCheck(check);this.renderRail();this.reviewStale=true;this.paintReview(true);const detail=flowCopy({check:id,result:{status:result.status,message:result.message,details:result.details,at:state.at}});this.emit("flowCheck",detail,"onCheck");return detail.result},checkResult(value){const text=item=>typeof item==="string"&&/\S/.test(item) ? item.slice(0, 1000) : null;
|
|
@@ -12,3 +12,5 @@ background:transparent;color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));o
|
|
|
12
12
|
.cx-flow-discard{display:flex;flex-wrap:wrap;align-items:center;gap:var(--cx-size-8px) var(--cx-size-12px);padding:var(--cx-size-10px) var(--cx-flow-pad);border-bottom:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));background:var(--hfx-color-status-warn-bg,light-dark(#f8efde,#3b3322));}
|
|
13
13
|
.cx-flow-discard p{flex:1;font-weight:600;}
|
|
14
14
|
@media (max-width:639.98px){.cx-flow-dialog,.cx-flow-dialog.cx-flow-drawer{width:var(--cx-size-100vw);max-width:none;height:var(--cx-size-100vh);max-height:none;margin:0;border-radius:var(--hfx-radius-none,0);}.cx-flow-dialog > .cx-flow{min-height:100%;border-radius:var(--hfx-radius-none,0);border:0;}}
|
|
15
|
+
@media(max-width:639.98px){.cx-flow-dialog .cx-flow{--cx-flow-pad:var(--cx-size-16px);}}
|
|
16
|
+
.cx-flow-head-close .cx-flow-close{inset-block-start:var(--cx-size-8px);}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
(function(global){"use strict";const installed=new WeakSet();const part={version:"
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"217410758cdb73da",requires:["flow","flow-host"],install(context){if(installed.has(context.FLOW_IMPL))return;const{FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat}=context;const{FlowView,FLOW_HOST,FLOW_LABELS,flowFail,flowIs,flowKeys,flowName,flowString,flowFlag,flowScalar,flowFits,flowField,flowOptions,flowCondition,flowRefs,flowTest,flowCopy,flowSameValue,flowEmpty,flowNormal,flowDate,flowFieldView}=FLOW_IMPL.core;const{EDIT_EDITORS,formRuleSpec,formCheck}=FORMS_IMPL;const FLOW_PART_LABELS={flowClose:"Close",flowDiscardQuestion:"Discard your answers?",flowDiscard:"Discard",flowKeepEditing:"Keep editing"};Object.assign(FLOW_LABELS,FLOW_PART_LABELS);const flowRelease=FlowView.prototype.destroy;FLOW_HOST.dialog={document(doc,model){const raw=doc.layout;if(!raw)return;model.container=raw.container??"inline";if(!["inline","dialog","drawer"].includes(model.container))flowFail("the flow layout has an unknown container");if(raw.launch!==undefined&&model.container==="inline")flowFail("only a dialog or drawer flow has a launch button");model.launch=flowString(raw.launch,80,"The launch label")}};Object.assign(FlowView.prototype,{destroy(){flowRelease.call(this);this.shell?.remove()},buildContainer(){const labels=this.labels,shell=this.shell=h("div","cx-flow-launcher"),launch=this.launcher=h("button","cx-flow-btn cx-primary cx-flow-launch");launch.type="button";setText(launch,this.model.launch||this.model.title);launch.setAttribute("aria-haspopup","dialog");const dialog=this.dialog=h("dialog","cx-flow-dialog" +(this.model.container==="drawer"?" cx-flow-drawer":""));dialog.setAttribute("aria-labelledby",this.id+"-title");const close=h("button","cx-flow-icon-btn cx-flow-close");close.type="button";setText(close,"×");close.setAttribute("aria-label",labels.flowClose);this.head.classList.add("cx-flow-head-close");this.head.appendChild(close);const confirm=this.discardBar=h("div","cx-flow-discard"),question=h("p"),discard=h("button","cx-flow-btn"),keep=h("button","cx-flow-btn cx-primary");confirm.setAttribute("role","alertdialog");confirm.setAttribute("aria-labelledby",this.id+"-discard");confirm.hidden=true;question.id=this.id+"-discard";setText(question,labels.flowDiscardQuestion);discard.type=keep.type="button";setText(discard,labels.flowDiscard);setText(keep,labels.flowKeepEditing);confirm.append(question,keep,discard);this.root.insertBefore(confirm,this.layout);dialog.appendChild(this.root);shell.append(launch,dialog);this.host.appendChild(shell);const signal=this.lifetime.signal;launch.addEventListener("click",()=>this.open(),{signal});close.addEventListener("click",()=>this.close(),{signal});dialog.addEventListener("cancel",event=>{event.preventDefault();this.close()},{signal});keep.addEventListener("click",()=>{confirm.hidden=true;this.stage.querySelector(".cx-flow-step-title")?.focus()},{signal});discard.addEventListener("click",()=>this.close(true),{signal})},cancelButton(){if(!this.dialog)return null;const cancel=h("button","cx-flow-btn cx-flow-quiet");cancel.type="button";setText(cancel,this.labels.flowCancel);cancel.addEventListener("click",()=>this.close());return cancel},open(){if(!this.dialog||this.dialog.open)return!!this.dialog;this.discardBar.hidden=true;this.dialog.showModal();this.measure();this.render();(this.stage.querySelector(".cx-flow-step-title")||this.root).focus({preventScroll:true});return true},close(force){if(!this.dialog?.open)return false;if(!force&&this.phase==="form"&&this.isDirty()){if(!this.emit("flowLeaving",{reason:"close"},"onLeaving",true))return false;this.discardBar.hidden=false;this.discardBar.querySelector(".cx-primary").focus();return false}
|
|
2
2
|
this.discardBar.hidden=true;this.dialog.close();if(force||this.phase!=="form"){this.panel=null;this.reset()}
|
|
3
3
|
this.launcher.focus();return true}});installed.add(context.FLOW_IMPL)}};(global.CanopyXParts||=[]).push(["flow-dialog",part])})(typeof window!=="undefined"?window:globalThis);
|
|
@@ -58,7 +58,7 @@ function gridDateInputMoment(text,local){const match=/^(\d{4})-(\d{2})-(\d{2})T(
|
|
|
58
58
|
if(!match)return null;const moment=gridMomentFromParts(Number(match[1]),Number(match[2]),Number(match[3]),Number(match[4]),Number(match[5]),Number(match[6]||0),local);if(moment)moment.setTime(moment.getTime()+ Number((match[7]||"").padEnd(3,"0")));return moment}
|
|
59
59
|
function gridFreeze(value){if(value&&typeof value==="object"&&!Object.isFrozen(value)){Object.values(value).forEach(gridFreeze);Object.freeze(value)}
|
|
60
60
|
return value}
|
|
61
|
-
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"forms":["0d77c25f4fa14425","canopyx-forms.3b18e30a2aeb56dd.js","canopyx-forms.e3a0e1f016287057.css"],"flow":["
|
|
61
|
+
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"forms":["0d77c25f4fa14425","canopyx-forms.3b18e30a2aeb56dd.js","canopyx-forms.e3a0e1f016287057.css"],"flow":["93f8d2eb57cc1770","canopyx-flow.c3f65a21ced2d654.js","canopyx-flow.68af38159226dd08.css"],"flow-host":["6f335df747cc5f05","canopyx-flow-host.ea0be90307b19d0f.js","canopyx-flow-host.87b00b9ed5899f1f.css"],"flow-checks":["318849d97560c594","canopyx-flow-checks.21dcc732a9145c71.js","canopyx-flow-checks.5a98f4038542c1d3.css"],"flow-options":["60450342239ded26","canopyx-flow-options.d31458a54aa4b1e7.js"],"flow-pick":["e5f79a9e81e93898","canopyx-flow-pick.e17b209908086225.js","canopyx-flow-pick.7ec005490120da23.css"],"flow-records":["d02b7dc1c7f75805","canopyx-flow-records.5efc3b14cf70b524.js","canopyx-flow-records.cf62ae7260a46ec4.css"],"flow-drafts":["40dc8e50169fa271","canopyx-flow-drafts.67fb3ab7fbc22606.js","canopyx-flow-drafts.f8535eb8992ea36a.css"],"flow-preview":["3d8ffe456323db95","canopyx-flow-preview.4731603add2f8e84.js","canopyx-flow-preview.f1c740bc97130a7d.css"],"flow-command":["a6c75cf736c93444","canopyx-flow-command.f3608c38cc18f333.js","canopyx-flow-command.279d6ad310e39e97.css"],"flow-tasks":["8d9ea504e81e8fcd","canopyx-flow-tasks.eeb43b791491b43b.js","canopyx-flow-tasks.5c0dc5743e02c670.css"],"flow-dialog":["217410758cdb73da","canopyx-flow-dialog.e45cf5f0b12f802a.js","canopyx-flow-dialog.35310d9dc1d73395.css"],"flow-links":["2c14b19c9236e90d","canopyx-flow-links.7b6cfe42d28b6067.js"],"flow-endpoint":["f5cddfc9545e0920","canopyx-flow-endpoint.b31146202bd76aac.js"],"flow-facts":["385b5e61ed487e16","canopyx-flow-facts.8dad3bc07a71fdb0.js"],"flow-consent":["22121778bc0d07c5","canopyx-flow-consent.749b97f13039bc71.js","canopyx-flow-consent.9f6580d3673ae8bf.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
|
|
62
62
|
function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
|
|
63
63
|
part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
|
|
64
64
|
function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
|
|
@@ -69,10 +69,10 @@ const load=(element,attribute,file,kind)=>new Promise((resolve,reject)=>{const u
|
|
|
69
69
|
.finally(()=>script.remove()).catch(error=>{part.scriptReady=null;throw error}));await Promise.all([style,code])}}
|
|
70
70
|
const code=PART_CODE.get(part.name);if(code?.version!==part.version)throw new Error("CanopyX: "+part.label+" and runtime must come from the same build.");for(const name of code.requires||[])await loadPart(part.parts[name]);code.install(part.context())}).catch(error=>{part.ready=null;throw error})}
|
|
71
71
|
const partQueue=global.CanopyXParts=global.CanopyXParts||[];partQueue.forEach(entry=>registerPart(...entry));partQueue.length=0;partQueue.push=(...entries)=>{entries.forEach(entry=>registerPart(...entry));return 0};class FlowHost{}
|
|
72
|
-
const FORMS_IMPL={},FLOW_IMPL={},activeFlows=new WeakMap();const FORMS_PART=definePart(FlowHost,"forms","forms",()=>({FORMS_IMPL,h,setText,fill,gridFreeze,gridMomentFromParts,boundedPattern,foldText}));const FLOW_VIEWS=typeof FLOW_GRID_VIEWS==="object"?FLOW_GRID_VIEWS:Object.freeze({grid:null,tree:null,reporting:false});const FLOW_PART=definePart(FlowHost,"flow","flow view",()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,foldText,boundedPattern,numberFormat,gridFreeze}));const FLOW_FEATURES={};for(const name of["host","checks","options","pick","records","drafts","preview","command","tasks","dialog","links","endpoint","consent"])
|
|
73
|
-
FLOW_FEATURES[name]=definePart(FlowHost,"flow-"+name,"flow "+name,()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat,FLOW_VIEWS}));if(typeof DataGrid==="function")DataGrid.prototype.parts.forms=FORMS_PART;const FLOW_DOC_PARTS={command:"command",presets:"drafts",draft:"drafts",deepLinks:"links",endpoint:"endpoint"},FLOW_DOC_PLAIN={draft:"none",deepLinks:false};function flowFeatures(doc,hooks){const names=new Set(),add=(name,on)=>on&&names.add(name),list=value=>Array.isArray(value)?value:[];const object=value=>value!==null&&typeof value==="object"&&!Array.isArray(value),has=(value,...keys)=>object(value)&&keys.some(key=>value[key]!==undefined);for(const[key,name]of Object.entries(FLOW_DOC_PARTS))add(name,doc[key]!==undefined&&doc[key]!==FLOW_DOC_PLAIN[key]);add("tasks",doc.mode==="tasks");add("dialog",has(doc.layout,"launch")||has(doc.layout,"container")&&doc.layout.container!=="inline");add("preview",list(doc.endpoint?.routes).includes("preview"));for(const step of list(doc.steps).filter(object)){add("checks",step.checks!==undefined);add("pick",step.type==="pick");add("preview",step.preview===true);add("consent",has(step,"confirm","acknowledge"));for(const block of[step,...list(step.sections)]){if(block!==step)add("options",has(block,"source","dependsOn"));for(const field of object(block)?list(block.fields):[]){add("options",has(field,"dependsOn")||has(field,"source")&&field.source!=="document");add("records",object(field)&&field.type==="records")}}}
|
|
72
|
+
const FORMS_IMPL={},FLOW_IMPL={},activeFlows=new WeakMap();const FORMS_PART=definePart(FlowHost,"forms","forms",()=>({FORMS_IMPL,h,setText,fill,gridFreeze,gridMomentFromParts,boundedPattern,foldText}));const FLOW_VIEWS=typeof FLOW_GRID_VIEWS==="object"?FLOW_GRID_VIEWS:Object.freeze({grid:null,tree:null,reporting:false});const FLOW_PART=definePart(FlowHost,"flow","flow view",()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,foldText,boundedPattern,numberFormat,gridFreeze}));const FLOW_FEATURES={};for(const name of["host","checks","options","pick","records","drafts","preview","command","tasks","dialog","links","endpoint","consent","facts"])
|
|
73
|
+
FLOW_FEATURES[name]=definePart(FlowHost,"flow-"+name,"flow "+name,()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat,FLOW_VIEWS}));if(typeof DataGrid==="function")DataGrid.prototype.parts.forms=FORMS_PART;const FLOW_DOC_PARTS={command:"command",presets:"drafts",draft:"drafts",deepLinks:"links",endpoint:"endpoint"},FLOW_DOC_PLAIN={draft:"none",deepLinks:false};function flowFeatures(doc,hooks){const names=new Set(),add=(name,on)=>on&&names.add(name),list=value=>Array.isArray(value)?value:[];const object=value=>value!==null&&typeof value==="object"&&!Array.isArray(value),has=(value,...keys)=>object(value)&&keys.some(key=>value[key]!==undefined);for(const[key,name]of Object.entries(FLOW_DOC_PARTS))add(name,doc[key]!==undefined&&doc[key]!==FLOW_DOC_PLAIN[key]);add("tasks",doc.mode==="tasks");add("dialog",has(doc.layout,"launch")||has(doc.layout,"container")&&doc.layout.container!=="inline");add("preview",list(doc.endpoint?.routes).includes("preview"));for(const step of list(doc.steps).filter(object)){add("facts",step.facts!==undefined);add("checks",step.checks!==undefined);add("pick",step.type==="pick");add("preview",step.preview===true);add("consent",has(step,"confirm","acknowledge"));for(const block of[step,...list(step.sections)]){if(block!==step)add("options",has(block,"source","dependsOn"));for(const field of object(block)?list(block.fields):[]){add("options",has(field,"dependsOn")||has(field,"source")&&field.source!=="document");add("records",object(field)&&field.type==="records")}}}
|
|
74
74
|
hooks=object(hooks)?hooks:{};return{required:[...names],optional:[typeof hooks.preview==="function"&&"preview",object(hooks.presetStore)&&"drafts"].filter(name=>name&&!names.has(name))}}
|
|
75
|
-
const FLOW_ASYNC_METHODS=["next","back","goTo","setState","validate","submit","runCheck","refreshOptions","saveDraft","setPreset"];const FLOW_SYNC_METHODS=["getStep","getValues","setValues","getState","isDirty","reset","setFieldError","setProgress","complete","setStepState","open","close"];function createFlow(host,options){if(!host||!options||!options.flow||typeof options.flow!=="object")throw new Error("CanopyX: createFlow needs a host element and a flow document.");const existing=activeFlows.get(host);if(existing)return existing;const disposeTheme=watchTheme(host);let impl=null,destroyed=false,mountError=null;const destroyedError=()=>new Error("CanopyX: this flow has been destroyed.");const requireImpl=name=>{if(destroyed)throw destroyedError();if(!impl)throw new Error("CanopyX: flow is not ready; await api.ready before calling "+name+"().");return impl};const editors=Object.assign({},...[...PLUGINS.values()].map(item=>item.editors||{}));const{required,optional}=flowFeatures(options.flow,options.hooks);const ready=Promise.all([loadPart(FLOW_PART),...required.map(name=>loadPart(FLOW_FEATURES[name])),...optional.map(name=>loadPart(FLOW_FEATURES[name])
|
|
75
|
+
const FLOW_ASYNC_METHODS=["next","back","goTo","setState","validate","submit","runCheck","refreshOptions","saveDraft","setPreset"];const FLOW_SYNC_METHODS=["getStep","getValues","setValues","getState","isDirty","reset","setFieldError","setProgress","complete","setStepState","invalidateChecks","open","close"];function createFlow(host,options){if(!host||!options||!options.flow||typeof options.flow!=="object")throw new Error("CanopyX: createFlow needs a host element and a flow document.");const existing=activeFlows.get(host);if(existing)return existing;const disposeTheme=watchTheme(host);let impl=null,destroyed=false,mountError=null;const destroyedError=()=>new Error("CanopyX: this flow has been destroyed.");const requireImpl=name=>{if(destroyed)throw destroyedError();if(!impl)throw new Error("CanopyX: flow is not ready; await api.ready before calling "+name+"().");return impl};const editors=Object.assign({},...[...PLUGINS.values()].map(item=>item.editors||{}));const{required,optional}=flowFeatures(options.flow,options.hooks);const ready=Promise.all([loadPart(FLOW_PART),...required.map(name=>loadPart(FLOW_FEATURES[name])),...optional.map(name=>loadPart(FLOW_FEATURES[name])
|
|
76
76
|
.catch(error=>host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error,hook:"part"},bubbles:true}))))]).then(async()=>{if(destroyed)throw destroyedError();impl=FLOW_IMPL.create(host,options,editors);return impl.ready});const api={element:host,flow:options.flow,view:options.flow};for(const name of FLOW_SYNC_METHODS)api[name]=(...args)=>requireImpl(name)[name](...args);for(const name of FLOW_ASYNC_METHODS)api[name]=(...args)=>{if(destroyed)return Promise.reject(destroyedError());return ready.then(()=>requireImpl(name)[name](...args))};api.ready=ready.then(()=>{if(destroyed)throw destroyedError();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;disposeTheme();try{impl?.destroy()}
|
|
77
77
|
finally{impl=null;mountError?.remove();if(activeFlows.get(host)===api){activeFlows.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");host.removeAttribute("data-cx-ready");host.removeAttribute("data-cx-error");host.classList.remove("cx-flow-host")}}};ready.catch(error=>{if(destroyed)return;const notice=mountError=h("div","cx-mount-error");notice.setAttribute("role","alert");setText(notice,error&&error.message?error.message:String(error));host.appendChild(notice);host.setAttribute("data-cx-error",notice.textContent);host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});Object.freeze(api);activeFlows.set(host,api);host.classList.add("cx-host","cx-flow-host");host.setAttribute("data-canopyx-mounted","true");host.canopyx=api;return api}
|
|
78
78
|
const FLOW_API={createFlow};const configured=new Map();const flowId=value=>typeof value==="string"&&/^[A-Za-z][A-Za-z0-9_-]{0,63}$/.test(value);
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"385b5e61ed487e16",requires:["flow"],install(context){if(installed.has(context.FLOW_IMPL))return;const{FLOW_IMPL,h,setText}=context;const{FlowView,FLOW_HOST,flowFail,flowKeys,flowString}=FLOW_IMPL.core;FLOW_HOST.facts={finish(model){for(const step of model.steps){const facts=step.raw.facts;if(facts===undefined)continue;if(step.type!=="info"||!Array.isArray(facts)||facts.length>32)flowFail("only information steps hold up to 32 read-only facts");step.facts=facts.map(fact=>{flowKeys(fact,["label","value"],"A flow fact");return{label:flowString(fact.label,200,"A fact label",true),value:flowString(fact.value,32768,"A fact value",true)}})}},render(section,facts){const list=h("dl","cx-flow-answers");for(const fact of facts){const item=h("div","cx-flow-answer"),label=h("dt"),value=h("dd","cx-flow-answer-value");setText(label,fact.label);setText(value,fact.value);item.append(label,value);list.appendChild(item)}
|
|
2
|
+
section.appendChild(list)}};const flowFactsShell=FlowView.prototype.stepShell;FlowView.prototype.stepShell=function(step){const section=flowFactsShell.call(this,step);if(step.facts?.length)FLOW_HOST.facts.render(section,step.facts);return section};installed.add(context.FLOW_IMPL)}};(global.CanopyXParts||=[]).push(["flow-facts",part])})(typeof window!=="undefined"?window:globalThis);
|
|
@@ -60,7 +60,7 @@ function gridDateInputMoment(text,local){const match=/^(\d{4})-(\d{2})-(\d{2})T(
|
|
|
60
60
|
if(!match)return null;const moment=gridMomentFromParts(Number(match[1]),Number(match[2]),Number(match[3]),Number(match[4]),Number(match[5]),Number(match[6]||0),local);if(moment)moment.setTime(moment.getTime()+ Number((match[7]||"").padEnd(3,"0")));return moment}
|
|
61
61
|
function gridFreeze(value){if(value&&typeof value==="object"&&!Object.isFrozen(value)){Object.values(value).forEach(gridFreeze);Object.freeze(value)}
|
|
62
62
|
return value}
|
|
63
|
-
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"forms":["0d77c25f4fa14425","canopyx-forms.3b18e30a2aeb56dd.js","canopyx-forms.e3a0e1f016287057.css"],"flow":["
|
|
63
|
+
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"forms":["0d77c25f4fa14425","canopyx-forms.3b18e30a2aeb56dd.js","canopyx-forms.e3a0e1f016287057.css"],"flow":["93f8d2eb57cc1770","canopyx-flow.c3f65a21ced2d654.js","canopyx-flow.68af38159226dd08.css"],"flow-host":["6f335df747cc5f05","canopyx-flow-host.ea0be90307b19d0f.js","canopyx-flow-host.87b00b9ed5899f1f.css"],"flow-checks":["318849d97560c594","canopyx-flow-checks.21dcc732a9145c71.js","canopyx-flow-checks.5a98f4038542c1d3.css"],"flow-options":["60450342239ded26","canopyx-flow-options.d31458a54aa4b1e7.js"],"flow-pick":["e5f79a9e81e93898","canopyx-flow-pick.e17b209908086225.js","canopyx-flow-pick.7ec005490120da23.css"],"flow-records":["d02b7dc1c7f75805","canopyx-flow-records.5efc3b14cf70b524.js","canopyx-flow-records.cf62ae7260a46ec4.css"],"flow-drafts":["40dc8e50169fa271","canopyx-flow-drafts.67fb3ab7fbc22606.js","canopyx-flow-drafts.f8535eb8992ea36a.css"],"flow-preview":["3d8ffe456323db95","canopyx-flow-preview.4731603add2f8e84.js","canopyx-flow-preview.f1c740bc97130a7d.css"],"flow-command":["a6c75cf736c93444","canopyx-flow-command.f3608c38cc18f333.js","canopyx-flow-command.279d6ad310e39e97.css"],"flow-tasks":["8d9ea504e81e8fcd","canopyx-flow-tasks.eeb43b791491b43b.js","canopyx-flow-tasks.5c0dc5743e02c670.css"],"flow-dialog":["217410758cdb73da","canopyx-flow-dialog.e45cf5f0b12f802a.js","canopyx-flow-dialog.35310d9dc1d73395.css"],"flow-links":["2c14b19c9236e90d","canopyx-flow-links.7b6cfe42d28b6067.js"],"flow-endpoint":["f5cddfc9545e0920","canopyx-flow-endpoint.b31146202bd76aac.js"],"flow-facts":["385b5e61ed487e16","canopyx-flow-facts.8dad3bc07a71fdb0.js"],"flow-consent":["22121778bc0d07c5","canopyx-flow-consent.749b97f13039bc71.js","canopyx-flow-consent.9f6580d3673ae8bf.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
|
|
64
64
|
function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
|
|
65
65
|
part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
|
|
66
66
|
function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
|
|
@@ -71,10 +71,10 @@ const load=(element,attribute,file,kind)=>new Promise((resolve,reject)=>{const u
|
|
|
71
71
|
.finally(()=>script.remove()).catch(error=>{part.scriptReady=null;throw error}));await Promise.all([style,code])}}
|
|
72
72
|
const code=PART_CODE.get(part.name);if(code?.version!==part.version)throw new Error("CanopyX: "+part.label+" and runtime must come from the same build.");for(const name of code.requires||[])await loadPart(part.parts[name]);code.install(part.context())}).catch(error=>{part.ready=null;throw error})}
|
|
73
73
|
const partQueue=global.CanopyXParts=global.CanopyXParts||[];partQueue.forEach(entry=>registerPart(...entry));partQueue.length=0;partQueue.push=(...entries)=>{entries.forEach(entry=>registerPart(...entry));return 0};class FlowHost{}
|
|
74
|
-
const FORMS_IMPL={},FLOW_IMPL={},activeFlows=new WeakMap();const FORMS_PART=definePart(FlowHost,"forms","forms",()=>({FORMS_IMPL,h,setText,fill,gridFreeze,gridMomentFromParts,boundedPattern,foldText}));const FLOW_VIEWS=typeof FLOW_GRID_VIEWS==="object"?FLOW_GRID_VIEWS:Object.freeze({grid:null,tree:null,reporting:false});const FLOW_PART=definePart(FlowHost,"flow","flow view",()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,foldText,boundedPattern,numberFormat,gridFreeze}));const FLOW_FEATURES={};for(const name of["host","checks","options","pick","records","drafts","preview","command","tasks","dialog","links","endpoint","consent"])
|
|
75
|
-
FLOW_FEATURES[name]=definePart(FlowHost,"flow-"+name,"flow "+name,()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat,FLOW_VIEWS}));if(typeof DataGrid==="function")DataGrid.prototype.parts.forms=FORMS_PART;const FLOW_DOC_PARTS={command:"command",presets:"drafts",draft:"drafts",deepLinks:"links",endpoint:"endpoint"},FLOW_DOC_PLAIN={draft:"none",deepLinks:false};function flowFeatures(doc,hooks){const names=new Set(),add=(name,on)=>on&&names.add(name),list=value=>Array.isArray(value)?value:[];const object=value=>value!==null&&typeof value==="object"&&!Array.isArray(value),has=(value,...keys)=>object(value)&&keys.some(key=>value[key]!==undefined);for(const[key,name]of Object.entries(FLOW_DOC_PARTS))add(name,doc[key]!==undefined&&doc[key]!==FLOW_DOC_PLAIN[key]);add("tasks",doc.mode==="tasks");add("dialog",has(doc.layout,"launch")||has(doc.layout,"container")&&doc.layout.container!=="inline");add("preview",list(doc.endpoint?.routes).includes("preview"));for(const step of list(doc.steps).filter(object)){add("checks",step.checks!==undefined);add("pick",step.type==="pick");add("preview",step.preview===true);add("consent",has(step,"confirm","acknowledge"));for(const block of[step,...list(step.sections)]){if(block!==step)add("options",has(block,"source","dependsOn"));for(const field of object(block)?list(block.fields):[]){add("options",has(field,"dependsOn")||has(field,"source")&&field.source!=="document");add("records",object(field)&&field.type==="records")}}}
|
|
74
|
+
const FORMS_IMPL={},FLOW_IMPL={},activeFlows=new WeakMap();const FORMS_PART=definePart(FlowHost,"forms","forms",()=>({FORMS_IMPL,h,setText,fill,gridFreeze,gridMomentFromParts,boundedPattern,foldText}));const FLOW_VIEWS=typeof FLOW_GRID_VIEWS==="object"?FLOW_GRID_VIEWS:Object.freeze({grid:null,tree:null,reporting:false});const FLOW_PART=definePart(FlowHost,"flow","flow view",()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,foldText,boundedPattern,numberFormat,gridFreeze}));const FLOW_FEATURES={};for(const name of["host","checks","options","pick","records","drafts","preview","command","tasks","dialog","links","endpoint","consent","facts"])
|
|
75
|
+
FLOW_FEATURES[name]=definePart(FlowHost,"flow-"+name,"flow "+name,()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat,FLOW_VIEWS}));if(typeof DataGrid==="function")DataGrid.prototype.parts.forms=FORMS_PART;const FLOW_DOC_PARTS={command:"command",presets:"drafts",draft:"drafts",deepLinks:"links",endpoint:"endpoint"},FLOW_DOC_PLAIN={draft:"none",deepLinks:false};function flowFeatures(doc,hooks){const names=new Set(),add=(name,on)=>on&&names.add(name),list=value=>Array.isArray(value)?value:[];const object=value=>value!==null&&typeof value==="object"&&!Array.isArray(value),has=(value,...keys)=>object(value)&&keys.some(key=>value[key]!==undefined);for(const[key,name]of Object.entries(FLOW_DOC_PARTS))add(name,doc[key]!==undefined&&doc[key]!==FLOW_DOC_PLAIN[key]);add("tasks",doc.mode==="tasks");add("dialog",has(doc.layout,"launch")||has(doc.layout,"container")&&doc.layout.container!=="inline");add("preview",list(doc.endpoint?.routes).includes("preview"));for(const step of list(doc.steps).filter(object)){add("facts",step.facts!==undefined);add("checks",step.checks!==undefined);add("pick",step.type==="pick");add("preview",step.preview===true);add("consent",has(step,"confirm","acknowledge"));for(const block of[step,...list(step.sections)]){if(block!==step)add("options",has(block,"source","dependsOn"));for(const field of object(block)?list(block.fields):[]){add("options",has(field,"dependsOn")||has(field,"source")&&field.source!=="document");add("records",object(field)&&field.type==="records")}}}
|
|
76
76
|
hooks=object(hooks)?hooks:{};return{required:[...names],optional:[typeof hooks.preview==="function"&&"preview",object(hooks.presetStore)&&"drafts"].filter(name=>name&&!names.has(name))}}
|
|
77
|
-
const FLOW_ASYNC_METHODS=["next","back","goTo","setState","validate","submit","runCheck","refreshOptions","saveDraft","setPreset"];const FLOW_SYNC_METHODS=["getStep","getValues","setValues","getState","isDirty","reset","setFieldError","setProgress","complete","setStepState","open","close"];function createFlow(host,options){if(!host||!options||!options.flow||typeof options.flow!=="object")throw new Error("CanopyX: createFlow needs a host element and a flow document.");const existing=activeFlows.get(host);if(existing)return existing;const disposeTheme=watchTheme(host);let impl=null,destroyed=false,mountError=null;const destroyedError=()=>new Error("CanopyX: this flow has been destroyed.");const requireImpl=name=>{if(destroyed)throw destroyedError();if(!impl)throw new Error("CanopyX: flow is not ready; await api.ready before calling "+name+"().");return impl};const editors=Object.assign({},...[...PLUGINS.values()].map(item=>item.editors||{}));const{required,optional}=flowFeatures(options.flow,options.hooks);const ready=Promise.all([loadPart(FLOW_PART),...required.map(name=>loadPart(FLOW_FEATURES[name])),...optional.map(name=>loadPart(FLOW_FEATURES[name])
|
|
77
|
+
const FLOW_ASYNC_METHODS=["next","back","goTo","setState","validate","submit","runCheck","refreshOptions","saveDraft","setPreset"];const FLOW_SYNC_METHODS=["getStep","getValues","setValues","getState","isDirty","reset","setFieldError","setProgress","complete","setStepState","invalidateChecks","open","close"];function createFlow(host,options){if(!host||!options||!options.flow||typeof options.flow!=="object")throw new Error("CanopyX: createFlow needs a host element and a flow document.");const existing=activeFlows.get(host);if(existing)return existing;const disposeTheme=watchTheme(host);let impl=null,destroyed=false,mountError=null;const destroyedError=()=>new Error("CanopyX: this flow has been destroyed.");const requireImpl=name=>{if(destroyed)throw destroyedError();if(!impl)throw new Error("CanopyX: flow is not ready; await api.ready before calling "+name+"().");return impl};const editors=Object.assign({},...[...PLUGINS.values()].map(item=>item.editors||{}));const{required,optional}=flowFeatures(options.flow,options.hooks);const ready=Promise.all([loadPart(FLOW_PART),...required.map(name=>loadPart(FLOW_FEATURES[name])),...optional.map(name=>loadPart(FLOW_FEATURES[name])
|
|
78
78
|
.catch(error=>host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error,hook:"part"},bubbles:true}))))]).then(async()=>{if(destroyed)throw destroyedError();impl=FLOW_IMPL.create(host,options,editors);return impl.ready});const api={element:host,flow:options.flow,view:options.flow};for(const name of FLOW_SYNC_METHODS)api[name]=(...args)=>requireImpl(name)[name](...args);for(const name of FLOW_ASYNC_METHODS)api[name]=(...args)=>{if(destroyed)return Promise.reject(destroyedError());return ready.then(()=>requireImpl(name)[name](...args))};api.ready=ready.then(()=>{if(destroyed)throw destroyedError();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;disposeTheme();try{impl?.destroy()}
|
|
79
79
|
finally{impl=null;mountError?.remove();if(activeFlows.get(host)===api){activeFlows.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");host.removeAttribute("data-cx-ready");host.removeAttribute("data-cx-error");host.classList.remove("cx-flow-host")}}};ready.catch(error=>{if(destroyed)return;const notice=mountError=h("div","cx-mount-error");notice.setAttribute("role","alert");setText(notice,error&&error.message?error.message:String(error));host.appendChild(notice);host.setAttribute("data-cx-error",notice.textContent);host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});Object.freeze(api);activeFlows.set(host,api);host.classList.add("cx-host","cx-flow-host");host.setAttribute("data-canopyx-mounted","true");host.canopyx=api;return api}
|
|
80
80
|
const FLOW_API={createFlow};const configured=new Map();const flowId=value=>typeof value==="string"&&/^[A-Za-z][A-Za-z0-9_-]{0,63}$/.test(value);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(global){"use strict";const installed=new WeakSet();const part={version:"
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"93f8d2eb57cc1770",requires:["forms"],install(context){if(installed.has(context.FLOW_IMPL))return;const{FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,foldText,boundedPattern,numberFormat,gridFreeze}=context;const{editParseNumber,EDIT_EDITORS,formRuleSpec,formCheck,FORM_LABELS}=FORMS_IMPL;const FLOW_LABELS={flowSteps:"Steps",flowStepOf:"Step {current} of {count}",flowStepAnnounce:"Step {current} of {count}, {title}",flowNext:"Next",flowBack:"Back",flowSubmit:"Submit",flowSubmitting:"Submitting…",flowReviewTitle:"Check your answers",flowChange:"Change",flowChangeField:"Change {field}",flowNotProvided:"Not provided",flowOptional:"(optional)",flowStepOptional:"Optional",flowStepComplete:"Complete",flowStepCurrent:"Current step",flowStepErrors:"Errors: {count}",flowStepLocked:"Complete the earlier steps first",flowStepNotStarted:"Not started",flowErrorSummary:"Fix these before you continue",flowReady:"Ready to submit",flowNotReady:"Errors to fix: {count}",flowWarnings:"Warnings: {count}",flowChangesOnly:"Show changes only",flowNoChanges:"No answers have changed.",flowWas:"Was: {value}",flowChangedCount:"Changed answers: {count}",flowSecretSet:"Set",flowSecretKept:"Unchanged",flowSecretNotSet:"Not set",flowSecretHint:"A value is saved. Leave blank to keep it.",flowSecretShow:"Show",flowSecretHide:"Hide",flowSecretReveal:"Show {field}",flowOn:"On",flowOff:"Off",flowAdd:"Add",flowAddItem:"Add to {field}",flowRemoveItem:"Remove {item}",flowItemLabel:"{field}, item {index}",flowSelectAll:"Select all",flowSelectNone:"Clear",flowSelectedCount:"{count} of {total} selected",flowUnit:"Unit",flowUnitSeconds:"seconds",flowUnitMinutes:"minutes",flowUnitHours:"hours",flowUnitDays:"days",flowSeconds:"[one]{count} second[other]{count} seconds",flowMinutes:"[one]{count} minute[other]{count} minutes",flowHours:"[one]{count} hour[other]{count} hours",flowDays:"[one]{count} day[other]{count} days",flowDurationInvalid:"{field} must be a whole number.",flowItemsMin:"{field} needs at least {min}.",flowItemsMax:"{field} allows at most {max}.",flowItemEmail:"“{item}” is not an email address.",flowItemHost:"“{item}” is not a host name.",flowItemIp:"“{item}” is not an IP address.",flowItemCidr:"“{item}” is not a network range.",flowItemUrl:"“{item}” is not a web address.",flowItemPattern:"“{item}” does not have the expected format.",flowSaved:"Saved",flowAccepted:"In progress",flowProgress:"{done} of {total}",flowConflict:"These settings changed while you were editing them.",flowReload:"Reload current settings",flowNotSubmitted:"The answers were not submitted.",flowNoHost:"No host received the answers.",flowStartAgain:"Start another",flowCopy:"Copy",flowCopied:"Copied",flowSavedIt:"I have saved it",flowShownOnce:"Shown only once. Copy it now."};function flowLabels(...sources){const labels={...FORM_LABELS,...FLOW_LABELS};for(const source of sources){if(source==null)continue;if(!flowIs(source))flowFail("labels must be an object of strings");for(const[name,text]of Object.entries(source)){if(!Object.hasOwn(labels,name))continue;if(typeof text!=="string"||!/\S/.test(text)) flowFail("label '" + name + "' must be a string with visible text");
|
|
2
2
|
labels[name]=text}}
|
|
3
3
|
return Object.freeze(labels)}
|
|
4
4
|
const FLOW_NAME=/^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
|
|
@@ -19,12 +19,12 @@ if(field.path!==undefined&&(typeof field.path!=="string"||!/^[A-Za-z0-9_-]+(\.[A
|
|
|
19
19
|
if(raw.keepWhenBlank!==undefined&&(type!=="secret"||typeof raw.keepWhenBlank!=="boolean"))bad("can keep a blank value only as a secret");if(raw.reveal!==undefined&&(type!=="secret"||typeof raw.reveal!=="boolean"))bad("has a reveal setting but is not a secret");if((raw.onText!==undefined||raw.offText!==undefined)&&type!=="toggle")bad("names on and off texts but is not a toggle");if(raw.rows!==undefined&&(type!=="textarea"||!Number.isInteger(raw.rows)||raw.rows<2||raw.rows>20))bad("needs 2 to 20 rows, as a text area only");if(raw.display!==undefined&&(type!=="choice"||!["cards","list"].includes(raw.display)))bad("has an unknown display");if(raw.editor!==undefined?type!=="custom"||typeof raw.editor!=="string"||!/^[A-Za-z][A-Za-z0-9_-]{0,63}$/.test(raw.editor) : type === "custom") bad("needs an editor name as a custom field only");
|
|
20
20
|
if(raw.step!==undefined&&type!=="number")bad("has a step but is not a number");if(raw.placeholder!==undefined&&!["text","number","lookup","textarea","list"].includes(type))bad("has a placeholder, which text, number, lookup, text area and list fields take");const choosing=["select","choice","multiChoice","lookup"].includes(type);if(raw.source!==undefined&&(raw.source!=="document"||!choosing)||raw.dependsOn!==undefined)flowHost("options").field(field,raw,choosing,bad);if(raw.options!==undefined&&!choosing)bad("has options but does not choose");if(choosing&&!field.host&&!(Array.isArray(raw.options)&&raw.options.length))bad("needs options");if(raw.options!==undefined&&!Array.isArray(raw.options))bad("needs a list of options");field.options=flowOptions(raw.options||[],bad);if((raw.columns!==undefined)!==(type==="records"))bad("needs columns as a records field only");if(type==="records")field.columns=flowHost("records").columns(raw.columns,bad);const list=type==="list"||type==="multiChoice"||type==="records"||type==="pick";if(list&&[rules.min,rules.max,rules.minLength,rules.maxLength,rules.pattern].some(value=>value!==undefined))bad("checks items, not lengths or ranges");if(!list&&[rules.minItems,rules.maxItems].some(value=>value!==undefined)||type!=="list"&&(rules.item!==undefined||rules.itemPattern!==undefined))bad("has rules only lists take");if((rules.min!==undefined||rules.max!==undefined)&&!["number","datetime","duration"].includes(type))bad("has a range but is not a number, date and time or duration");if([rules.minLength,rules.maxLength,rules.pattern].some(value=>value!==undefined)&&!["text","textarea","secret"].includes(type))bad("has lengths or a pattern, which text, text area and secret fields take");if(rules.minLength>rules.maxLength)bad("needs the shorter length first");const count=value=>value===undefined||Number.isInteger(value)&&value>=0&&value<=1000;if(!count(rules.minItems)||!count(rules.maxItems)||rules.minItems>rules.maxItems)bad("needs 0 to 1000 items, the fewest first");if(rules.item!==undefined&&!["email","host","ip","cidr","url"].includes(rules.item))bad("has an unknown item rule");let itemPattern=null;if(rules.itemPattern!==undefined)try{itemPattern=boundedPattern(rules.itemPattern,true,true)}catch(error){bad("has an invalid or unsafe item pattern")}
|
|
21
21
|
const range=type==="duration"?{min:rules.min===undefined?undefined:flowSeconds(rules.min),max:rules.max===undefined?undefined:flowSeconds(rules.max)}:rules;if(type==="duration"&&(range.min===null||range.max===null))bad("needs ISO 8601 durations as its range");if(type==="number"&&![rules.min,rules.max].every(bound=>bound===undefined||Number.isFinite(bound)&&Math.abs(bound)<=Number.MAX_SAFE_INTEGER))bad("needs numbers as its range");if(type==="datetime"&&![rules.min,rules.max].every(bound=>bound===undefined||flowFits({type:"datetime"},bound)))bad("needs ISO 8601 moments as its range");const low=type==="datetime"&&typeof range.min==="string"?Date.parse(range.min):range.min,high=type==="datetime"&&typeof range.max==="string"?Date.parse(range.max):range.max;if(low!==undefined&&high!==undefined&&low>high)bad("needs the lower limit first");const shared=formRuleSpec({step:raw.step,placeholder:raw.placeholder},{required:field.required,min:range.min,max:range.max,minLength:rules.minLength,maxLength:rules.maxLength,pattern:rules.pattern,message:rules.message},bad);field.spec=Object.freeze({id,pattern:shared.pattern,rules:shared.rules});field.items=Object.freeze({min:rules.minItems,max:rules.maxItems,rule:rules.item,pattern:itemPattern});const units=raw.units??["minutes","hours","days"];if(raw.units!==undefined&&type!=="duration"||!Array.isArray(units)||!units.length||units.some(unit=>!Object.hasOwn(FLOW_UNITS,unit))||new Set(units).size!==units.length)bad("has invalid duration units");field.units=Object.keys(FLOW_UNITS).filter(unit=>units.includes(unit));if(raw.default!==undefined&&(type==="secret"||list&&!Array.isArray(raw.default)||!flowFits(field,raw.default)))bad("has a default that does not fit it");field.start=raw.default===undefined?(list?[]:null):raw.default;model.fields.set(id,field);return field}
|
|
22
|
-
function flowRead(doc){flowKeys(doc,["kind","version","id","title","description","mode","layout","density","timeZone","steps","initial","storedSecrets","baseline","submit","labels","command","presets","draft","deepLinks","endpoint"],"A flow document");if(doc.kind!=="flow"||doc.version!==1)flowFail("
|
|
22
|
+
function flowRead(doc){flowKeys(doc,["kind","version","id","title","description","mode","layout","density","timeZone","steps","initial","storedSecrets","baseline","submit","labels","command","presets","draft","deepLinks","endpoint"],"A flow document");if(doc.kind!=="flow"||doc.version!==1)flowFail("expected flow document version 1");const model={id:flowName(doc.id,"The flow id"),title:flowString(doc.title,200,"The flow title",true),description:flowString(doc.description,1000,"The flow description"),mode:doc.mode??"linear",density:doc.density??"normal",local:doc.timeZone==="local",fields:new Map(),steps:[],sections:new Set(),checks:new Map()};if(!["linear","free","tasks"].includes(model.mode)||!["compact","normal","comfortable"].includes(model.density)||doc.timeZone!==undefined&&!["utc","local"].includes(doc.timeZone))flowFail("unknown flow mode, density or time zone");if(doc.layout!==undefined)flowKeys(doc.layout,["orientation","container","launch"],"The flow layout");model.orientation=doc.layout?.orientation??"auto";if(!["auto","horizontal","vertical"].includes(model.orientation))flowFail("the flow layout has an unknown orientation");if(!Array.isArray(doc.steps)||!doc.steps.length||doc.steps.length>64)flowFail("a flow needs 1 to 64 steps");for(const[index,raw]of doc.steps.entries()){flowKeys(raw,["id","title","description","type","fields","sections","when","optional","declaration","changesOnly","checks","group","pick","confirm","acknowledge","preview","facts"],"A flow step");const step={id:flowName(raw.id,"A step id"),title:flowString(raw.title,200,"A step title",raw.type!=="review"),description:flowString(raw.description,1000,"A step description"),type:raw.type??"form",optional:flowFlag(raw.optional,"optional"),declaration:flowString(raw.declaration,1000,"The declaration"),changesOnly:raw.changesOnly!==false,group:flowString(raw.group,200,"A step group"),blocks:[],checks:[],raw};if(model.steps.some(other=>other.id===step.id))flowFail("the step id '"+step.id+"' is used twice");if(!["form","info","review","pick"].includes(step.type))flowFail("step "+step.id+" has an unknown type");step.asks=step.type==="form"||step.type==="pick";if(step.type==="review"&&index!==doc.steps.length-1)flowFail("the review step must be the last step");if(step.type==="review"&&(raw.when!==undefined||raw.optional===true||raw.group!==undefined))flowFail("the review step takes no condition or group and is never optional");const reviewKey=["declaration","changesOnly","confirm","acknowledge","preview"].find(key=>raw[key]!==undefined);if(step.type!=="review"&&reviewKey)flowFail("only a review step has "+reviewKey);if(raw.changesOnly!==undefined&&typeof raw.changesOnly!=="boolean")flowFail("changesOnly must be true or false");if(step.type!=="form"&&(raw.fields!==undefined||raw.sections!==undefined))flowFail("only a form step has fields and sections");if((raw.pick!==undefined)!==(step.type==="pick"))flowFail("only pick steps require a pick");if(raw.fields!==undefined&&!Array.isArray(raw.fields)||raw.sections!==undefined&&!Array.isArray(raw.sections))flowFail("fields and sections must be arrays");if(raw.fields?.length)step.blocks.push({section:null,fields:raw.fields.map(field=>flowField(field,step,null,model))});if((raw.sections||[]).length>64)flowFail("step "+step.id+" holds at most 64 sections");for(const rawSection of raw.sections||[]){flowKeys(rawSection,["id","label","description","fields","when","source","dependsOn"],"A flow section");const section={id:flowName(rawSection.id,"A section id"),label:flowString(rawSection.label,200,"A section label",true),description:flowString(rawSection.description,1000,"A section description"),host:false,dependsOn:[],raw:rawSection};if(model.sections.has(section.id))flowFail("the section id '"+section.id+"' is used twice");model.sections.add(section.id);if(rawSection.source!==undefined||rawSection.dependsOn!==undefined)flowHost("options").section(section,rawSection);else if(!Array.isArray(rawSection.fields))flowFail("section "+section.id+" needs an array of fields");step.blocks.push({section,fields:(rawSection.fields||[]).map(field=>flowField(field,step,section,model))})}
|
|
23
23
|
if(step.type==="pick")flowHost("pick").read(raw.pick,step,model);if(step.type==="review"){step.preview=flowFlag(raw.preview,"preview");if(raw.confirm!==undefined||raw.acknowledge!==undefined)flowHost("consent").read(raw,step)}
|
|
24
24
|
if(raw.checks!==undefined)flowHost("checks").read(raw.checks,step,model);model.steps.push(step)}
|
|
25
25
|
const paths=new Set();for(const path of[...model.fields.values()].map(field=>field.path).filter(Boolean)){if(paths.has(path))flowFail("the path '"+path+"' is used twice");paths.add(path)}
|
|
26
26
|
for(const path of paths)for(let at=path.indexOf(".");at>0;at=path.indexOf(".",at+1))if(paths.has(path.slice(0,at)))flowFail("the path '"+path+"' lies inside '"+path.slice(0,at)+ "'");flowConditions(model);flowEach("finish",model);flowEditMode(doc,model);Object.assign(model,{container:"inline",command:null,presets:[],draft:"none",deepLinks:false,endpoint:null});flowEach("document",doc,model);if(doc.submit!==undefined)flowKeys(doc.submit,["label"],"The flow's submit");model.submitLabel=flowString(doc.submit?.label,80,"The submit label");model.labels=doc.labels;return model}
|
|
27
|
-
function flowEditMode(doc,model){if(doc.initial!==undefined){if(!flowIs(doc.initial))flowFail("initial must be an object of field values");for(const[id,value]of Object.entries(doc.initial)){const field=model.fields.get(id);if(!field||field.type==="secret"||!flowFits(field,value))flowFail("initial
|
|
27
|
+
function flowEditMode(doc,model){if(doc.initial!==undefined){if(!flowIs(doc.initial))flowFail("initial must be an object of field values");for(const[id,value]of Object.entries(doc.initial)){const field=model.fields.get(id);if(!field||field.type==="secret"||!flowFits(field,value))flowFail("initial value does not fit field "+id)}}
|
|
28
28
|
model.initial=doc.initial?{...doc.initial}:null;if(doc.storedSecrets!==undefined&&(!Array.isArray(doc.storedSecrets)||doc.storedSecrets.some(id=>model.fields.get(id)?.type!=="secret")||new Set(doc.storedSecrets).size!==doc.storedSecrets.length))
|
|
29
29
|
flowFail("storedSecrets lists only secret fields");model.stored=new Set(doc.storedSecrets||[]);if(doc.baseline!==undefined&&(typeof doc.baseline!=="string"||!doc.baseline.length||doc.baseline.length>256))flowFail("the baseline is 1 to 256 characters");model.baseline=doc.baseline??null;if(!model.initial&&(model.stored.size||model.baseline!==null))model.initial={}}
|
|
30
30
|
function flowOptions(raw,bad){if(raw.length>1000)bad("needs at most 1000 options");const options=raw.map(option=>{flowKeys(flowIs(option)?option:{value:option},["value","label","description","badge","disabledReason","group"],"An option");const item=flowIs(option)?option:{value:option};if(!flowScalar(item.value))bad("has an invalid option value");return Object.freeze({value:item.value,label:flowString(item.label,200,"An option label")??String(item.value),description:flowString(item.description,1000,"An option description"),badge:flowString(item.badge,40,"An option badge"),disabledReason:flowString(item.disabledReason,400,"A disabled reason"),group:flowString(item.group,200,"An option group")})});if(new Set(options.map(option=>option.value)).size!==options.length)bad("needs options with distinct values");return options}
|
|
@@ -97,7 +97,7 @@ stepFields(step){return step.blocks.flatMap(block=>block.fields).filter(field=>t
|
|
|
97
97
|
reviewStep(){const last=this.model.steps[this.model.steps.length-1];return last.type==="review"?last:null}
|
|
98
98
|
getValues(){const values={};for(const field of this.model.fields.values())if(field.type!=="secret"&&this.visible(field))values[field.id]=flowCopy(this.values.get(field.id)??null);return values}
|
|
99
99
|
answersChanged(){this.answerRevision++;this.retireOperation()}
|
|
100
|
-
beginOperation(){let cancel;const cancelled=new Promise(resolve=>
|
|
100
|
+
beginOperation(){let cancel;const cancelled=new Promise(resolve=>cancel=resolve);const abort=new AbortController();const generation=this.generation,revision=this.answerRevision,ticket={cancel:()=>{abort.abort();cancel()},signal:abort.signal};ticket.current=()=>!this.destroyed&&generation===this.generation&&revision===this.answerRevision&&this.operation===ticket;ticket.wait=work=>Promise.race([work,cancelled]);this.operation=ticket;this.busy=true;return ticket}
|
|
101
101
|
retireOperation(render=true){const ticket=this.operation;if(!ticket)return;this.operation=null;ticket.close?.();this.busy=false;ticket.cancel();if(render&&!this.destroyed&&this.phase==="form"&&this.actions)this.renderActions()}
|
|
102
102
|
changed(field,source){const fv=this.fields.get(field.id);if(!fv||this.destroyed||field.readOnly)return;const result=fv.read();if(fv.pending!==(result.error||null))this.answersChanged();fv.pending=result.error||null;if(result.error)this.completed.delete(field.step.id);if(field.type==="secret"){const before=this.secrets.get(field.id)??null;if(result.value)this.secrets.set(field.id,result.value);else this.secrets.delete(field.id);if(before!==(result.value||null)){this.answersChanged();this.forgetHost(field);this.emit("flowValueChanged",{field:field.id,source:"edit"},"onValueChange")}}else if(!result.error){const previous=this.values.get(field.id)??null;if(!flowSameValue(previous,result.value)){this.answersChanged();this.values.set(field.id,result.value);this.forgetHost(field);this.emit("flowValueChanged",{field:field.id,value:flowCopy(result.value),previous:flowCopy(previous),source:"edit"},"onValueChange")}}
|
|
103
103
|
if(source!=="blur"&&this.errors.has(field.id))this.checkField(field);this.refreshVisibility()}
|
|
@@ -145,7 +145,8 @@ flowEach("built",this,step,section);return section},async go(target,direction,qu
|
|
|
145
145
|
if(target!==from){this.emit("flowStepChanged",{from:from.id,to:target.id},"onStepChange");this.stepMoved?.()}
|
|
146
146
|
return true},async next(){if(this.busy||this.phase!=="form"||this.step===this.hub)return false;const step=this.step,steps=this.visibleSteps(),pressed=document.activeElement,generation=this.generation;if(step.asks){const ticket=this.beginOperation();this.renderActions();let result;try{result=await ticket.wait(this.validateStep(step,true,ticket.current));if(!ticket.current())return false}finally{if(ticket.current())this.retireOperation()}
|
|
147
147
|
if(this.destroyed||generation!==this.generation||this.step!==step||result.moved)return false;if(!result.valid){const stayed=document.activeElement===pressed||!this.root.contains(document.activeElement);this.renderRail();this.renderActions();this.showSummary(step,stayed);return false}
|
|
148
|
-
const summary=this.sections.get(step.id)?._cxSummary;if(summary)summary.hidden=true
|
|
148
|
+
const summary=this.sections.get(step.id)?._cxSummary;if(summary)summary.hidden=true}
|
|
149
|
+
this.completed.add(step.id);const review=this.reviewStep();const target=this.returnToReview&&review&&this.stepVisible(review)?review:this.hub||steps[steps.indexOf(step)+ 1];if(target===review)this.returnToReview=false;return this.go(target,"forward")},async back(){if(this.busy||this.phase!=="form")return false;const steps=this.visibleSteps(),at=steps.indexOf(this.step);return at>0?this.go(steps[at-1],"back"):false},async goTo(id){if(this.busy||this.phase!=="form")return false;const steps=this.visibleSteps(),target=steps.find(step=>step.id===id);if(!target)return false;const open=this.reachable(target,steps)?target:steps.find(step=>step.asks&&!this.completed.has(step.id))||target;return this.go(open,steps.indexOf(open)<steps.indexOf(this.step)?"back":"forward")},change(field){this.returnToReview=true;return this.go(field.step,"back").then(moved=>{if(moved){const fv=this.fields.get(field.id);if(fv)fv.focus()}
|
|
149
150
|
return moved})}});const FLOW_ITEM_RULES={email:value=>/^[^\s@]+@[^\s@]+\.[^\s@.]+$/.test(value),
|
|
150
151
|
host:value=>value.length<=253&&/^(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)*[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.?$/.test(value),
|
|
151
152
|
ip:value=>flowIPv4(value)||flowIPv6(value),cidr:value=>{const[address,prefix,extra]=value.split("/");return extra===undefined&&/^\d{1,3}$/.test(prefix || "") && (flowIPv4(address) && Number(prefix) <= 32 || flowIPv6(address) && Number(prefix) <= 128); },
|
|
@@ -185,7 +186,7 @@ const value=flowCopy(this.values.get(field.id)??null),from=flowNormal(this.initi
|
|
|
185
186
|
const proposal={kind:"flowSubmission",flow:model.id,version:1,mode:edit?"edit":"create"};if(model.baseline!==null)proposal.baseline=model.baseline;Object.assign(proposal,{values,secrets,changes,patch});flowEach("proposal",this,proposal);return proposal},async submit(){if(this.busy||this.phase!=="form")return null;const ticket=this.beginOperation(),current=ticket.current,wait=ticket.wait;this.banner=null;this.hostErrors.clear();this.hostStepErrors.clear();this.renderActions();try{const result=await wait(this.validateAll(current));if(!current())return null;if(!result.valid){const review=this.reviewStep();if(review&&this.stepVisible(review)){if(this.step!==review)await this.go(review,"forward");else{this.reviewStale=true;this.render()}}
|
|
186
187
|
else{const first=result.errors.find(error=>error.step);await this.go(this.model.steps.find(step=>step.id===first?.step)||this.step,"back");if(first?.step)this.showSummary(this.step)}
|
|
187
188
|
return null}
|
|
188
|
-
const proposal=this.submission(),secrets=new Map([...this.secrets].filter(([id])=>this.visible(this.model.fields.get(id)))),read=new Set();let answer,answered=false,open=true;const close=ticket.close=()=>{open=false;secrets.clear()};const detail=Object.assign(flowCopy(proposal),{respondWith:value=>{if(!answered&&open){answered=true;answer=Promise.resolve(value);answer.catch(()=>{})}},secret:id=>{if(!open||read.has(id)||!secrets.has(id))return null;read.add(id);return secrets.get(id)}});Object.freeze(detail);const go=this.emit("flowSubmit",detail,null,true);if(!go||!current()){close();return null}
|
|
189
|
+
const proposal=this.submission(),secrets=new Map([...this.secrets].filter(([id])=>this.visible(this.model.fields.get(id)))),read=new Set();let answer,answered=false,open=true;const close=ticket.close=()=>{open=false;secrets.clear()};const detail=Object.assign(flowCopy(proposal),{respondWith:value=>{if(!answered&&open){answered=true;answer=Promise.resolve(value);answer.catch(()=>{})}},secret:id=>{if(!open||read.has(id)||!secrets.has(id))return null;read.add(id);return secrets.get(id)}});Object.freeze(Object.defineProperty(detail,"signal",{value:ticket.signal}));const go=this.emit("flowSubmit",detail,null,true);if(!go||!current()){close();return null}
|
|
189
190
|
if(!answered&&typeof this.options.onSubmit==="function"){const value=await wait(this.hook("onSubmit",()=>this.options.onSubmit(detail)));if(!current()){close();return null}
|
|
190
191
|
if(value.failed){answered=true;answer={status:"error",message:value.failed}}
|
|
191
192
|
else if(value.value!==undefined){answered=true;answer=value.value}}
|
|
@@ -213,5 +214,5 @@ item.append(term,value);list.appendChild(item)}
|
|
|
213
214
|
panel.appendChild(list)}
|
|
214
215
|
if(answer.links.length){const links=h("ul","cx-flow-links");for(const link of answer.links){const item=h("li"),anchor=h("a","cx-flow-link");anchor.href=link.href;setText(anchor,link.label);item.appendChild(anchor);links.appendChild(item)}
|
|
215
216
|
panel.appendChild(links)}
|
|
216
|
-
const actions=h("div","cx-flow-actions cx-flow-panel-actions"),again=h("button","cx-flow-btn");again.type="button";setText(again,labels.flowStartAgain);const acknowledged=()=>{again.disabled=[...panel.querySelectorAll(".cx-flow-saved-it")].some(box=>!box.checked)};panel.addEventListener("change",acknowledged);acknowledged();again.addEventListener("click",()=>{this.panel=null;this.reset();this.stage.querySelector(".cx-flow-step-title")?.focus()});actions.appendChild(again);panel.appendChild(actions);return panel},progressPanel(answer){const panel=this.panelShell("progress",this.labels.flowAccepted),text=h("p","cx-flow-panel-text"),bar=h("progress","cx-flow-bar");setText(text,answer.message||"");bar.setAttribute("aria-labelledby",panel.firstChild.id);panel.append(text,bar);return panel}});function flowCreate(host,options,editors){const view=new FlowView(host,options,editors);const impl={ready:Promise.resolve().then(()=>{if(!view.destroyed)host.setAttribute("data-cx-ready","");view.emit("flowReady",{flow:view.model.id,step:view.step.id},"onReady");return impl}),next:()=>view.next(),back:()=>view.back(),goTo:id=>view.goTo(id),getStep:()=>view.getStep(),getValues:()=>view.getValues(),setValues:values=>view.setValues(values),getState:()=>view.getState(),setState:state=>view.setState(state),isDirty:()=>view.isDirty(),reset:()=>view.reset(),validate:id=>view.validate(id),setFieldError:(id,message)=>view.setFieldError(id,message),submit:()=>view.submit(),setProgress:progress=>view.setProgress(progress),complete:answer=>view.complete(answer),destroy:()=>view.destroy()};const part=(name,none)=>(...args)=>view[name]?view[name](...args):none??flowFail("this flow does not use "+name);return Object.assign(impl,{runCheck:part("runCheck"),refreshOptions:part("refreshOptions"),setStepState:part("setStepState"),setPreset:part("setPreset"),saveDraft:()=>part("saveDraft",false)(true),open:()=>part("open",false)(),close:()=>part("close",false)()})}
|
|
217
|
+
const actions=h("div","cx-flow-actions cx-flow-panel-actions"),again=h("button","cx-flow-btn");again.type="button";setText(again,labels.flowStartAgain);const acknowledged=()=>{again.disabled=[...panel.querySelectorAll(".cx-flow-saved-it")].some(box=>!box.checked)};panel.addEventListener("change",acknowledged);acknowledged();again.addEventListener("click",()=>{this.panel=null;this.reset();this.stage.querySelector(".cx-flow-step-title")?.focus()});actions.appendChild(again);panel.appendChild(actions);return panel},progressPanel(answer){const panel=this.panelShell("progress",this.labels.flowAccepted),text=h("p","cx-flow-panel-text"),bar=h("progress","cx-flow-bar");setText(text,answer.message||"");bar.setAttribute("aria-labelledby",panel.firstChild.id);panel.append(text,bar);return panel}});function flowCreate(host,options,editors){const view=new FlowView(host,options,editors);const impl={ready:Promise.resolve().then(()=>{if(!view.destroyed)host.setAttribute("data-cx-ready","");view.emit("flowReady",{flow:view.model.id,step:view.step.id},"onReady");return impl}),next:()=>view.next(),back:()=>view.back(),goTo:id=>view.goTo(id),getStep:()=>view.getStep(),getValues:()=>view.getValues(),setValues:values=>view.setValues(values),getState:()=>view.getState(),setState:state=>view.setState(state),isDirty:()=>view.isDirty(),reset:()=>view.reset(),validate:id=>view.validate(id),setFieldError:(id,message)=>view.setFieldError(id,message),submit:()=>view.submit(),setProgress:progress=>view.setProgress(progress),complete:answer=>view.complete(answer),destroy:()=>view.destroy()};const part=(name,none)=>(...args)=>view[name]?view[name](...args):none??flowFail("this flow does not use "+name);return Object.assign(impl,{runCheck:part("runCheck"),invalidateChecks:part("invalidateChecks"),refreshOptions:part("refreshOptions"),setStepState:part("setStepState"),setPreset:part("setPreset"),saveDraft:()=>part("saveDraft",false)(true),open:()=>part("open",false)(),close:()=>part("close",false)()})}
|
|
217
218
|
Object.assign(FLOW_IMPL,{create:flowCreate,core:{FlowView,FLOW_HOST,FLOW_LABELS,flowFail,flowIs,flowKeys,flowName,flowString,flowFlag,flowScalar,flowFits,flowField,flowOptions,flowCondition,flowRefs,flowTest,flowCopy,flowSameValue,flowEmpty,flowNormal,flowDate,flowFieldView}});installed.add(context.FLOW_IMPL)}};(global.CanopyXParts||=[]).push(["flow",part])})(typeof window!=="undefined"?window:globalThis);
|
|
@@ -527,7 +527,7 @@ if(active>=0){list.children[active].setAttribute("aria-selected","false")}
|
|
|
527
527
|
active=active<0?(delta<0?hits.length-1:0):(active+delta+hits.length)%hits.length;const item=list.children[active];item.setAttribute("aria-selected","true");input.setAttribute("aria-activedescendant",item.id);item.scrollIntoView({block:"nearest"})};input.addEventListener("input",()=>{cancelNavigation();sequence++;clearTimeout(timer);hits=[];close();timer=setTimeout(run,150)});input.addEventListener("keydown",(e)=>{if(e.defaultPrevented||e.isComposing)return;if(e.key==="ArrowDown"||e.key==="ArrowUp"){move(e.key==="ArrowDown"?1:-1)}else if(e.key==="Enter"){if(!list.hidden){choose(active>=0?active:0)}}else if(e.key==="Escape"){cancelNavigation();sequence++;clearTimeout(timer);if(list.hidden){input.value=""}
|
|
528
528
|
close()}else{return}
|
|
529
529
|
e.preventDefault()});input.addEventListener("blur",()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);blurTimer=setTimeout(close,150)});this.cancelSearch=()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);hits=[];close()};box.appendChild(input);box.appendChild(list);box.appendChild(status);bar.appendChild(box);this.searchInput=input}});function watchFlyout(anchorElement,panel,isOpen){const position=()=>{if(!isOpen())return;const anchor=anchorElement.getBoundingClientRect(),fixed=getComputedStyle(panel).position==="fixed";const below=Math.max(0,global.innerHeight-anchor.bottom-8);const above=Math.max(0,anchor.top-8);const opensAbove=below<120&&above>below,room=opensAbove?above:below;panel.style.maxHeight=(panel.classList.contains("cx-fb")?room:Math.min(320,room))+ "px";panel.style.top=opensAbove?"auto":fixed?anchor.bottom+"px":"100%";panel.style.bottom=opensAbove?fixed?global.innerHeight-anchor.top+"px":"100%":"auto";const width=panel.getBoundingClientRect().width;panel.style.left=Math.max(8,Math.min(anchor.left,global.innerWidth-width-8))-(fixed?0:anchor.left)+ "px"};global.addEventListener("resize",position);global.addEventListener("scroll",position,true);return{position,dispose:()=>{global.removeEventListener("resize",position);global.removeEventListener("scroll",position,true)}}}
|
|
530
|
-
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["ee95c5cc39223ef4","canopyx-tree-tools.ab224d048d87d4a8.js","canopyx-tree-tools.3a4ac9c0bfe85039.css"],"presenters":["4337e3756b443220","canopyx-presenters.c8c9d0651df602b1.js"],"filter-editor":["e0db9c3f94866fa2","canopyx-filter-editor.bd27d6fec3d8b005.js","canopyx-filter-editor.0aa102aa92982a0f.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.js"],"history":["7d9901d2fe04df72","canopyx-history.9432e724bf14c9ed.js"],"pager":["3dcab112113081dd","canopyx-pager.15bb475e4365fe79.js","canopyx-pager.e39f321db5bdfde4.css"],"enhance":["a101e32b0f8a1644","canopyx-enhance.dd25035ab5f23d01.js"],"data":["d74a01c46f1c40cc","canopyx-data.afe3b097f19b5797.js"],"forms":["0d77c25f4fa14425","canopyx-forms.3b18e30a2aeb56dd.js","canopyx-forms.e3a0e1f016287057.css"],"flow":["
|
|
530
|
+
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["ee95c5cc39223ef4","canopyx-tree-tools.ab224d048d87d4a8.js","canopyx-tree-tools.3a4ac9c0bfe85039.css"],"presenters":["4337e3756b443220","canopyx-presenters.c8c9d0651df602b1.js"],"filter-editor":["e0db9c3f94866fa2","canopyx-filter-editor.bd27d6fec3d8b005.js","canopyx-filter-editor.0aa102aa92982a0f.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.js"],"history":["7d9901d2fe04df72","canopyx-history.9432e724bf14c9ed.js"],"pager":["3dcab112113081dd","canopyx-pager.15bb475e4365fe79.js","canopyx-pager.e39f321db5bdfde4.css"],"enhance":["a101e32b0f8a1644","canopyx-enhance.dd25035ab5f23d01.js"],"data":["d74a01c46f1c40cc","canopyx-data.afe3b097f19b5797.js"],"forms":["0d77c25f4fa14425","canopyx-forms.3b18e30a2aeb56dd.js","canopyx-forms.e3a0e1f016287057.css"],"flow":["93f8d2eb57cc1770","canopyx-flow.c3f65a21ced2d654.js","canopyx-flow.68af38159226dd08.css"],"flow-host":["6f335df747cc5f05","canopyx-flow-host.ea0be90307b19d0f.js","canopyx-flow-host.87b00b9ed5899f1f.css"],"flow-checks":["318849d97560c594","canopyx-flow-checks.21dcc732a9145c71.js","canopyx-flow-checks.5a98f4038542c1d3.css"],"flow-options":["60450342239ded26","canopyx-flow-options.d31458a54aa4b1e7.js"],"flow-pick":["e5f79a9e81e93898","canopyx-flow-pick.e17b209908086225.js","canopyx-flow-pick.7ec005490120da23.css"],"flow-records":["d02b7dc1c7f75805","canopyx-flow-records.5efc3b14cf70b524.js","canopyx-flow-records.cf62ae7260a46ec4.css"],"flow-drafts":["40dc8e50169fa271","canopyx-flow-drafts.67fb3ab7fbc22606.js","canopyx-flow-drafts.f8535eb8992ea36a.css"],"flow-preview":["3d8ffe456323db95","canopyx-flow-preview.4731603add2f8e84.js","canopyx-flow-preview.f1c740bc97130a7d.css"],"flow-command":["a6c75cf736c93444","canopyx-flow-command.f3608c38cc18f333.js","canopyx-flow-command.279d6ad310e39e97.css"],"flow-tasks":["8d9ea504e81e8fcd","canopyx-flow-tasks.eeb43b791491b43b.js","canopyx-flow-tasks.5c0dc5743e02c670.css"],"flow-dialog":["217410758cdb73da","canopyx-flow-dialog.e45cf5f0b12f802a.js","canopyx-flow-dialog.35310d9dc1d73395.css"],"flow-links":["2c14b19c9236e90d","canopyx-flow-links.7b6cfe42d28b6067.js"],"flow-endpoint":["f5cddfc9545e0920","canopyx-flow-endpoint.b31146202bd76aac.js"],"flow-facts":["385b5e61ed487e16","canopyx-flow-facts.8dad3bc07a71fdb0.js"],"flow-consent":["22121778bc0d07c5","canopyx-flow-consent.749b97f13039bc71.js","canopyx-flow-consent.9f6580d3673ae8bf.css"],"matrix":["da5c61ff2cb9ebda","canopyx-matrix.ed85d343a2f623b2.js","canopyx-matrix.195d1a1dda7a6f14.css"],"changes":["2810fb06a78b85e3","canopyx-changes.b4d09ab480688573.js","canopyx-changes.4bc51f4c6ae04082.css"],"editing":["579a74b205923fd5","canopyx-editing.ecebf88153edf03a.js","canopyx-editing.e0a3e646f4093e3b.css"],"column-groups":["cd6d93e033719439","canopyx-column-groups.922e21b9bdf57efa.js","canopyx-column-groups.6a6c9704c4ee7884.css"],"cell-range":["91e39c68baaf1d09","canopyx-cell-range.a12cda7cbddf4aea.js","canopyx-cell-range.ce87ff1c2023feae.css"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"formatting":["d3795e4b933d83a8","canopyx-formatting.ec13b95ea1f2b023.js","canopyx-formatting.922dc9fc7e6d35a7.css"],"format-editor":["b8c229ddfc1f218b","canopyx-format-editor.4a220f27a369d34e.js","canopyx-format-editor.dbdf4a154e7e5f48.css"],"link":["e7268bbe59e2dfa8","canopyx-link.e883be9525ead7b7.js","canopyx-link.b872151e9cbbd0ce.css"],"detail-rows":["e4150bb67f40d597","canopyx-detail-rows.e7f93158e19cbb28.js","canopyx-detail-rows.cabc50f51ed091ad.css"],"grouping":["eedafc8438ac1b2b","canopyx-grouping.e7767e781127573d.js","canopyx-grouping.98fa290cd1652f71.css"],"highlight":["459b28e174406d32","canopyx-highlight.10ef4bb28c5a8f5b.js","canopyx-highlight.ab1040f93cbb5dbb.css"],"layouts":["606fcf6dcd00d420","canopyx-layouts.606c8fe836149ffe.js","canopyx-layouts.56a636b0f1a03185.css"],"facets":["2ffa91f40c9b9b21","canopyx-facets.2ad845e5213e7f5b.js","canopyx-facets.8d4c02348420a425.css"],"live":["3b3c9833ff68a72b","canopyx-live.e4b062f6eeb0ea36.js","canopyx-live.39fe32cd642f60d2.css"],"record-panel":["82aa828bc880087b","canopyx-record-panel.e0736e2285995701.js","canopyx-record-panel.4b9f1a99c5b76321.css"],"calendar":["463aadb3a2169631","canopyx-calendar.3f539daa1b0a1b6f.js","canopyx-calendar.2d299b0318447276.css"],"calendar-recurrence":["64bcc24d785bd1af","canopyx-calendar-recurrence.4b7f430c2a64de23.js"],"calendar-edit":["29a711a1cfd4be9a","canopyx-calendar-edit.ef7728c17ca4851b.js"],"calendar-ics":["ac8b2950fccbfb0f","canopyx-calendar-ics.4a18c1c4a1520418.js"],"timeline":["22c9e15c108aeaa1","canopyx-timeline.2b5fe21a0f24aa08.js","canopyx-timeline.e3c962ae517931d2.css"],"grid-options":["e74170bbb841519c","canopyx-grid-options.c5fa91fc19205d5a.js","canopyx-grid-options.9c393c5122332461.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
|
|
531
531
|
function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
|
|
532
532
|
part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
|
|
533
533
|
function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
|
|
@@ -793,7 +793,7 @@ if(offset){const snapshot={revision:page.revision,total:page.total,matched:page.
|
|
|
793
793
|
gridOperationActive(this,lifetime.signal);const hadFocus=this.canvas.contains(document.activeElement),previousId=this.focused&&this.focused.key;const retireSelection=this.view.rowIdentity==="ordinal"&&this.snapshot&&this.snapshot.revision!==page.revision;this.pages.clear();this.rowCache.clear();this.placeholders.clear();this.focused=null;this.acceptedQuery=gridQuery(this.view,{...query,revision:page.revision});this.snapshot={revision:page.revision,total:page.total,matched:page.matched};if(retireSelection)this.clearSnapshotSelection();this.pageLength=length;if(paging)this.pageAll=!!paging.allRows;this.pageOffset=this.cursor?page.offset:this.paged?query.offset:0;if(this.cursor)this.cursorWindow={end:page.offset+page.items.length,next:page.nextCursor,previous:page.previousCursor};if(this.autoRows){if(!same)this.rowHeights.clear();this.rowOffsets=null}
|
|
794
794
|
this.storePage(page);this.pendingQuery=null;this.pendingPaging=null;this.lastFailedQuery=null;this.lastFailedPaging=null;this.version++;const hasRows=this.cursor?page.items.length:page.matched;this.total=(this.cursor?page.items.length:this.paged?Math.min(length,page.matched-this.pageOffset):page.matched)*this.rowH;this.grid.setAttribute("aria-rowcount",page.matched===null?"-1":String(page.matched+1 +(this.headDepth||0)));this.grid.tabIndex=hasRows?-1:0;this.syncScrollRange(this.paged?0:query.offset*this.rowH);this.buildHeader();this.syncColumnControls();this.setNotice(hasRows?"":this.labels.searchNoResults,false);this.grid.setAttribute("aria-busy","false");if(hadFocus||this.focusOrigin){this.focused=[...this.rowCache.values()].find(row=>row.key===previousId)||this.rowCache.get(this.cursor?page.offset:query.offset)||null}
|
|
795
795
|
this.render();if(hadFocus){const element=this.focused&&this.rendered.get(this.focused);(element||this.grid).focus({preventScroll:true})}
|
|
796
|
-
this.host.setAttribute("data-cx-ready","true");if(this.searchInput&&!this.searchComposing&&this.searchTimer==null)this.searchInput.value=query.search;this.syncQuerySummary();this.syncPager();this.emit("query",{query:this.acceptedQuery,revision:page.revision,total:page.total,matched:page.matched});this.stateChanged();return this.getQuery()}catch(error){if(epoch===this.queryEpoch&&!this.destroyed){this.pendingQuery=null;this.pendingPaging=null;this.lastFailedQuery=initial;this.lastFailedPaging={...paging,pageLength:length};this.dataLifetime.abort();this.dataLifetime=new AbortController();this.grid.setAttribute("aria-busy","false");this.setNotice(fill(this.labels.queryFailed,{error:error.message})
|
|
796
|
+
this.host.setAttribute("data-cx-ready","true");if(this.searchInput&&!this.searchComposing&&this.searchTimer==null)this.searchInput.value=query.search;this.syncQuerySummary();this.syncPager();this.emit("query",{query:this.acceptedQuery,revision:page.revision,total:page.total,matched:page.matched});this.stateChanged();return this.getQuery()}catch(error){if(epoch===this.queryEpoch&&!this.destroyed){const cancelled=lifetime.signal.aborted&&error?.name==="AbortError";this.pendingQuery=null;this.pendingPaging=null;this.lastFailedQuery=cancelled?null:initial;this.lastFailedPaging=cancelled?null:{...paging,pageLength:length};this.dataLifetime.abort();this.dataLifetime=new AbortController();this.grid.setAttribute("aria-busy","false");this.setNotice(cancelled?"":fill(this.labels.queryFailed,{error:error.message}),!cancelled);this.syncPager();if(!cancelled)this.emit("error",{error})}
|
|
797
797
|
throw error}}
|
|
798
798
|
querySortHeader(id,event){const previous=gridQuery(this.view,this.queryForChange(true)),sorts=previous.sort.slice();const found=sorts.findIndex(sort=>sort.column===id),old=found>=0?sorts[found].direction:null;const authored=this.columns.find(column=>column.id===id).orderSequence;const sequence=authored?.length?authored:["asc","desc","none"];const direction=sequence[(sequence.indexOf(old||"none")+ 1)%sequence.length];const next=direction==="none"?null:direction;const changed=event&&event.shiftKey?sorts.filter(sort=>sort.column!==id):[];if(next)changed.splice(event&&event.shiftKey&&found>=0?Math.min(found,changed.length):changed.length,0,{column:id,direction:next});this.setQuery(gridQueryStart(previous,{sort:changed})).catch(()=>{})}
|
|
799
799
|
sort(sorts){return this.setQuery(gridQueryStart(this.queryForChange(true),{sort:sorts}))}
|
|
@@ -1228,10 +1228,10 @@ this.dropRow=null}
|
|
|
1228
1228
|
dropPlacement(event,row){const bounds=row.getBoundingClientRect(),fraction=(event.clientY-bounds.top)/ bounds.height;
|
|
1229
1229
|
return fraction<0.25?"before":fraction>0.75?"after":"inside"}
|
|
1230
1230
|
destroy(){this.clearDropRow();this.dragLease=null;super.destroy()}};class FlowHost{}
|
|
1231
|
-
const FORMS_IMPL={},FLOW_IMPL={},activeFlows=new WeakMap();const FORMS_PART=definePart(FlowHost,"forms","forms",()=>({FORMS_IMPL,h,setText,fill,gridFreeze,gridMomentFromParts,boundedPattern,foldText}));const FLOW_VIEWS=typeof FLOW_GRID_VIEWS==="object"?FLOW_GRID_VIEWS:Object.freeze({grid:null,tree:null,reporting:false});const FLOW_PART=definePart(FlowHost,"flow","flow view",()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,foldText,boundedPattern,numberFormat,gridFreeze}));const FLOW_FEATURES={};for(const name of["host","checks","options","pick","records","drafts","preview","command","tasks","dialog","links","endpoint","consent"])
|
|
1232
|
-
FLOW_FEATURES[name]=definePart(FlowHost,"flow-"+name,"flow "+name,()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat,FLOW_VIEWS}));if(typeof DataGrid==="function")DataGrid.prototype.parts.forms=FORMS_PART;const FLOW_DOC_PARTS={command:"command",presets:"drafts",draft:"drafts",deepLinks:"links",endpoint:"endpoint"},FLOW_DOC_PLAIN={draft:"none",deepLinks:false};function flowFeatures(doc,hooks){const names=new Set(),add=(name,on)=>on&&names.add(name),list=value=>Array.isArray(value)?value:[];const object=value=>value!==null&&typeof value==="object"&&!Array.isArray(value),has=(value,...keys)=>object(value)&&keys.some(key=>value[key]!==undefined);for(const[key,name]of Object.entries(FLOW_DOC_PARTS))add(name,doc[key]!==undefined&&doc[key]!==FLOW_DOC_PLAIN[key]);add("tasks",doc.mode==="tasks");add("dialog",has(doc.layout,"launch")||has(doc.layout,"container")&&doc.layout.container!=="inline");add("preview",list(doc.endpoint?.routes).includes("preview"));for(const step of list(doc.steps).filter(object)){add("checks",step.checks!==undefined);add("pick",step.type==="pick");add("preview",step.preview===true);add("consent",has(step,"confirm","acknowledge"));for(const block of[step,...list(step.sections)]){if(block!==step)add("options",has(block,"source","dependsOn"));for(const field of object(block)?list(block.fields):[]){add("options",has(field,"dependsOn")||has(field,"source")&&field.source!=="document");add("records",object(field)&&field.type==="records")}}}
|
|
1231
|
+
const FORMS_IMPL={},FLOW_IMPL={},activeFlows=new WeakMap();const FORMS_PART=definePart(FlowHost,"forms","forms",()=>({FORMS_IMPL,h,setText,fill,gridFreeze,gridMomentFromParts,boundedPattern,foldText}));const FLOW_VIEWS=typeof FLOW_GRID_VIEWS==="object"?FLOW_GRID_VIEWS:Object.freeze({grid:null,tree:null,reporting:false});const FLOW_PART=definePart(FlowHost,"flow","flow view",()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,foldText,boundedPattern,numberFormat,gridFreeze}));const FLOW_FEATURES={};for(const name of["host","checks","options","pick","records","drafts","preview","command","tasks","dialog","links","endpoint","consent","facts"])
|
|
1232
|
+
FLOW_FEATURES[name]=definePart(FlowHost,"flow-"+name,"flow "+name,()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat,FLOW_VIEWS}));if(typeof DataGrid==="function")DataGrid.prototype.parts.forms=FORMS_PART;const FLOW_DOC_PARTS={command:"command",presets:"drafts",draft:"drafts",deepLinks:"links",endpoint:"endpoint"},FLOW_DOC_PLAIN={draft:"none",deepLinks:false};function flowFeatures(doc,hooks){const names=new Set(),add=(name,on)=>on&&names.add(name),list=value=>Array.isArray(value)?value:[];const object=value=>value!==null&&typeof value==="object"&&!Array.isArray(value),has=(value,...keys)=>object(value)&&keys.some(key=>value[key]!==undefined);for(const[key,name]of Object.entries(FLOW_DOC_PARTS))add(name,doc[key]!==undefined&&doc[key]!==FLOW_DOC_PLAIN[key]);add("tasks",doc.mode==="tasks");add("dialog",has(doc.layout,"launch")||has(doc.layout,"container")&&doc.layout.container!=="inline");add("preview",list(doc.endpoint?.routes).includes("preview"));for(const step of list(doc.steps).filter(object)){add("facts",step.facts!==undefined);add("checks",step.checks!==undefined);add("pick",step.type==="pick");add("preview",step.preview===true);add("consent",has(step,"confirm","acknowledge"));for(const block of[step,...list(step.sections)]){if(block!==step)add("options",has(block,"source","dependsOn"));for(const field of object(block)?list(block.fields):[]){add("options",has(field,"dependsOn")||has(field,"source")&&field.source!=="document");add("records",object(field)&&field.type==="records")}}}
|
|
1233
1233
|
hooks=object(hooks)?hooks:{};return{required:[...names],optional:[typeof hooks.preview==="function"&&"preview",object(hooks.presetStore)&&"drafts"].filter(name=>name&&!names.has(name))}}
|
|
1234
|
-
const FLOW_ASYNC_METHODS=["next","back","goTo","setState","validate","submit","runCheck","refreshOptions","saveDraft","setPreset"];const FLOW_SYNC_METHODS=["getStep","getValues","setValues","getState","isDirty","reset","setFieldError","setProgress","complete","setStepState","open","close"];function createFlow(host,options){if(!host||!options||!options.flow||typeof options.flow!=="object")throw new Error("CanopyX: createFlow needs a host element and a flow document.");const existing=activeFlows.get(host);if(existing)return existing;const disposeTheme=watchTheme(host);let impl=null,destroyed=false,mountError=null;const destroyedError=()=>new Error("CanopyX: this flow has been destroyed.");const requireImpl=name=>{if(destroyed)throw destroyedError();if(!impl)throw new Error("CanopyX: flow is not ready; await api.ready before calling "+name+"().");return impl};const editors=Object.assign({},...[...PLUGINS.values()].map(item=>item.editors||{}));const{required,optional}=flowFeatures(options.flow,options.hooks);const ready=Promise.all([loadPart(FLOW_PART),...required.map(name=>loadPart(FLOW_FEATURES[name])),...optional.map(name=>loadPart(FLOW_FEATURES[name])
|
|
1234
|
+
const FLOW_ASYNC_METHODS=["next","back","goTo","setState","validate","submit","runCheck","refreshOptions","saveDraft","setPreset"];const FLOW_SYNC_METHODS=["getStep","getValues","setValues","getState","isDirty","reset","setFieldError","setProgress","complete","setStepState","invalidateChecks","open","close"];function createFlow(host,options){if(!host||!options||!options.flow||typeof options.flow!=="object")throw new Error("CanopyX: createFlow needs a host element and a flow document.");const existing=activeFlows.get(host);if(existing)return existing;const disposeTheme=watchTheme(host);let impl=null,destroyed=false,mountError=null;const destroyedError=()=>new Error("CanopyX: this flow has been destroyed.");const requireImpl=name=>{if(destroyed)throw destroyedError();if(!impl)throw new Error("CanopyX: flow is not ready; await api.ready before calling "+name+"().");return impl};const editors=Object.assign({},...[...PLUGINS.values()].map(item=>item.editors||{}));const{required,optional}=flowFeatures(options.flow,options.hooks);const ready=Promise.all([loadPart(FLOW_PART),...required.map(name=>loadPart(FLOW_FEATURES[name])),...optional.map(name=>loadPart(FLOW_FEATURES[name])
|
|
1235
1235
|
.catch(error=>host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error,hook:"part"},bubbles:true}))))]).then(async()=>{if(destroyed)throw destroyedError();impl=FLOW_IMPL.create(host,options,editors);return impl.ready});const api={element:host,flow:options.flow,view:options.flow};for(const name of FLOW_SYNC_METHODS)api[name]=(...args)=>requireImpl(name)[name](...args);for(const name of FLOW_ASYNC_METHODS)api[name]=(...args)=>{if(destroyed)return Promise.reject(destroyedError());return ready.then(()=>requireImpl(name)[name](...args))};api.ready=ready.then(()=>{if(destroyed)throw destroyedError();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;disposeTheme();try{impl?.destroy()}
|
|
1236
1236
|
finally{impl=null;mountError?.remove();if(activeFlows.get(host)===api){activeFlows.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");host.removeAttribute("data-cx-ready");host.removeAttribute("data-cx-error");host.classList.remove("cx-flow-host")}}};ready.catch(error=>{if(destroyed)return;const notice=mountError=h("div","cx-mount-error");notice.setAttribute("role","alert");setText(notice,error&&error.message?error.message:String(error));host.appendChild(notice);host.setAttribute("data-cx-error",notice.textContent);host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});Object.freeze(api);activeFlows.set(host,api);host.classList.add("cx-host","cx-flow-host");host.setAttribute("data-canopyx-mounted","true");host.canopyx=api;return api}
|
|
1237
1237
|
const FLOW_API={createFlow};function createTreeGrid(host,options){if(!host||!options||!options.view){throw new Error("CanopyX: createTreeGrid needs a host element and a view document.")}
|
|
@@ -525,7 +525,7 @@ if(active>=0){list.children[active].setAttribute("aria-selected","false")}
|
|
|
525
525
|
active=active<0?(delta<0?hits.length-1:0):(active+delta+hits.length)%hits.length;const item=list.children[active];item.setAttribute("aria-selected","true");input.setAttribute("aria-activedescendant",item.id);item.scrollIntoView({block:"nearest"})};input.addEventListener("input",()=>{cancelNavigation();sequence++;clearTimeout(timer);hits=[];close();timer=setTimeout(run,150)});input.addEventListener("keydown",(e)=>{if(e.defaultPrevented||e.isComposing)return;if(e.key==="ArrowDown"||e.key==="ArrowUp"){move(e.key==="ArrowDown"?1:-1)}else if(e.key==="Enter"){if(!list.hidden){choose(active>=0?active:0)}}else if(e.key==="Escape"){cancelNavigation();sequence++;clearTimeout(timer);if(list.hidden){input.value=""}
|
|
526
526
|
close()}else{return}
|
|
527
527
|
e.preventDefault()});input.addEventListener("blur",()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);blurTimer=setTimeout(close,150)});this.cancelSearch=()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);hits=[];close()};box.appendChild(input);box.appendChild(list);box.appendChild(status);bar.appendChild(box);this.searchInput=input}});function watchFlyout(anchorElement,panel,isOpen){const position=()=>{if(!isOpen())return;const anchor=anchorElement.getBoundingClientRect(),fixed=getComputedStyle(panel).position==="fixed";const below=Math.max(0,global.innerHeight-anchor.bottom-8);const above=Math.max(0,anchor.top-8);const opensAbove=below<120&&above>below,room=opensAbove?above:below;panel.style.maxHeight=(panel.classList.contains("cx-fb")?room:Math.min(320,room))+ "px";panel.style.top=opensAbove?"auto":fixed?anchor.bottom+"px":"100%";panel.style.bottom=opensAbove?fixed?global.innerHeight-anchor.top+"px":"100%":"auto";const width=panel.getBoundingClientRect().width;panel.style.left=Math.max(8,Math.min(anchor.left,global.innerWidth-width-8))-(fixed?0:anchor.left)+ "px"};global.addEventListener("resize",position);global.addEventListener("scroll",position,true);return{position,dispose:()=>{global.removeEventListener("resize",position);global.removeEventListener("scroll",position,true)}}}
|
|
528
|
-
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["ee95c5cc39223ef4","canopyx-tree-tools.ab224d048d87d4a8.js","canopyx-tree-tools.3a4ac9c0bfe85039.css"],"presenters":["4337e3756b443220","canopyx-presenters.c8c9d0651df602b1.js"],"filter-editor":["e0db9c3f94866fa2","canopyx-filter-editor.bd27d6fec3d8b005.js","canopyx-filter-editor.0aa102aa92982a0f.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.js"],"history":["7d9901d2fe04df72","canopyx-history.9432e724bf14c9ed.js"],"pager":["3dcab112113081dd","canopyx-pager.15bb475e4365fe79.js","canopyx-pager.e39f321db5bdfde4.css"],"enhance":["a101e32b0f8a1644","canopyx-enhance.dd25035ab5f23d01.js"],"data":["d74a01c46f1c40cc","canopyx-data.afe3b097f19b5797.js"],"forms":["0d77c25f4fa14425","canopyx-forms.3b18e30a2aeb56dd.js","canopyx-forms.e3a0e1f016287057.css"],"flow":["
|
|
528
|
+
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"tree-tools":["ee95c5cc39223ef4","canopyx-tree-tools.ab224d048d87d4a8.js","canopyx-tree-tools.3a4ac9c0bfe85039.css"],"presenters":["4337e3756b443220","canopyx-presenters.c8c9d0651df602b1.js"],"filter-editor":["e0db9c3f94866fa2","canopyx-filter-editor.bd27d6fec3d8b005.js","canopyx-filter-editor.0aa102aa92982a0f.css"],"export":["9203882f58fa0155","canopyx-export.cedfec6462c161b4.js"],"history":["7d9901d2fe04df72","canopyx-history.9432e724bf14c9ed.js"],"pager":["3dcab112113081dd","canopyx-pager.15bb475e4365fe79.js","canopyx-pager.e39f321db5bdfde4.css"],"enhance":["a101e32b0f8a1644","canopyx-enhance.dd25035ab5f23d01.js"],"data":["d74a01c46f1c40cc","canopyx-data.afe3b097f19b5797.js"],"forms":["0d77c25f4fa14425","canopyx-forms.3b18e30a2aeb56dd.js","canopyx-forms.e3a0e1f016287057.css"],"flow":["93f8d2eb57cc1770","canopyx-flow.c3f65a21ced2d654.js","canopyx-flow.68af38159226dd08.css"],"flow-host":["6f335df747cc5f05","canopyx-flow-host.ea0be90307b19d0f.js","canopyx-flow-host.87b00b9ed5899f1f.css"],"flow-checks":["318849d97560c594","canopyx-flow-checks.21dcc732a9145c71.js","canopyx-flow-checks.5a98f4038542c1d3.css"],"flow-options":["60450342239ded26","canopyx-flow-options.d31458a54aa4b1e7.js"],"flow-pick":["e5f79a9e81e93898","canopyx-flow-pick.e17b209908086225.js","canopyx-flow-pick.7ec005490120da23.css"],"flow-records":["d02b7dc1c7f75805","canopyx-flow-records.5efc3b14cf70b524.js","canopyx-flow-records.cf62ae7260a46ec4.css"],"flow-drafts":["40dc8e50169fa271","canopyx-flow-drafts.67fb3ab7fbc22606.js","canopyx-flow-drafts.f8535eb8992ea36a.css"],"flow-preview":["3d8ffe456323db95","canopyx-flow-preview.4731603add2f8e84.js","canopyx-flow-preview.f1c740bc97130a7d.css"],"flow-command":["a6c75cf736c93444","canopyx-flow-command.f3608c38cc18f333.js","canopyx-flow-command.279d6ad310e39e97.css"],"flow-tasks":["8d9ea504e81e8fcd","canopyx-flow-tasks.eeb43b791491b43b.js","canopyx-flow-tasks.5c0dc5743e02c670.css"],"flow-dialog":["217410758cdb73da","canopyx-flow-dialog.e45cf5f0b12f802a.js","canopyx-flow-dialog.35310d9dc1d73395.css"],"flow-links":["2c14b19c9236e90d","canopyx-flow-links.7b6cfe42d28b6067.js"],"flow-endpoint":["f5cddfc9545e0920","canopyx-flow-endpoint.b31146202bd76aac.js"],"flow-facts":["385b5e61ed487e16","canopyx-flow-facts.8dad3bc07a71fdb0.js"],"flow-consent":["22121778bc0d07c5","canopyx-flow-consent.749b97f13039bc71.js","canopyx-flow-consent.9f6580d3673ae8bf.css"],"matrix":["da5c61ff2cb9ebda","canopyx-matrix.ed85d343a2f623b2.js","canopyx-matrix.195d1a1dda7a6f14.css"],"changes":["2810fb06a78b85e3","canopyx-changes.b4d09ab480688573.js","canopyx-changes.4bc51f4c6ae04082.css"],"editing":["579a74b205923fd5","canopyx-editing.ecebf88153edf03a.js","canopyx-editing.e0a3e646f4093e3b.css"],"column-groups":["cd6d93e033719439","canopyx-column-groups.922e21b9bdf57efa.js","canopyx-column-groups.6a6c9704c4ee7884.css"],"cell-range":["91e39c68baaf1d09","canopyx-cell-range.a12cda7cbddf4aea.js","canopyx-cell-range.ce87ff1c2023feae.css"],"links":["f1ab7e32b501ce37","canopyx-links.d96addeefb3eccf5.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"formatting":["d3795e4b933d83a8","canopyx-formatting.ec13b95ea1f2b023.js","canopyx-formatting.922dc9fc7e6d35a7.css"],"format-editor":["b8c229ddfc1f218b","canopyx-format-editor.4a220f27a369d34e.js","canopyx-format-editor.dbdf4a154e7e5f48.css"],"link":["e7268bbe59e2dfa8","canopyx-link.e883be9525ead7b7.js","canopyx-link.b872151e9cbbd0ce.css"],"detail-rows":["e4150bb67f40d597","canopyx-detail-rows.e7f93158e19cbb28.js","canopyx-detail-rows.cabc50f51ed091ad.css"],"grouping":["eedafc8438ac1b2b","canopyx-grouping.e7767e781127573d.js","canopyx-grouping.98fa290cd1652f71.css"],"highlight":["459b28e174406d32","canopyx-highlight.10ef4bb28c5a8f5b.js","canopyx-highlight.ab1040f93cbb5dbb.css"],"layouts":["606fcf6dcd00d420","canopyx-layouts.606c8fe836149ffe.js","canopyx-layouts.56a636b0f1a03185.css"],"facets":["2ffa91f40c9b9b21","canopyx-facets.2ad845e5213e7f5b.js","canopyx-facets.8d4c02348420a425.css"],"live":["3b3c9833ff68a72b","canopyx-live.e4b062f6eeb0ea36.js","canopyx-live.39fe32cd642f60d2.css"],"record-panel":["82aa828bc880087b","canopyx-record-panel.e0736e2285995701.js","canopyx-record-panel.4b9f1a99c5b76321.css"],"calendar":["463aadb3a2169631","canopyx-calendar.3f539daa1b0a1b6f.js","canopyx-calendar.2d299b0318447276.css"],"calendar-recurrence":["64bcc24d785bd1af","canopyx-calendar-recurrence.4b7f430c2a64de23.js"],"calendar-edit":["29a711a1cfd4be9a","canopyx-calendar-edit.ef7728c17ca4851b.js"],"calendar-ics":["ac8b2950fccbfb0f","canopyx-calendar-ics.4a18c1c4a1520418.js"],"timeline":["22c9e15c108aeaa1","canopyx-timeline.2b5fe21a0f24aa08.js","canopyx-timeline.e3c962ae517931d2.css"],"grid-options":["e74170bbb841519c","canopyx-grid-options.c5fa91fc19205d5a.js","canopyx-grid-options.9c393c5122332461.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
|
|
529
529
|
function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
|
|
530
530
|
part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
|
|
531
531
|
function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
|
|
@@ -791,7 +791,7 @@ if(offset){const snapshot={revision:page.revision,total:page.total,matched:page.
|
|
|
791
791
|
gridOperationActive(this,lifetime.signal);const hadFocus=this.canvas.contains(document.activeElement),previousId=this.focused&&this.focused.key;const retireSelection=this.view.rowIdentity==="ordinal"&&this.snapshot&&this.snapshot.revision!==page.revision;this.pages.clear();this.rowCache.clear();this.placeholders.clear();this.focused=null;this.acceptedQuery=gridQuery(this.view,{...query,revision:page.revision});this.snapshot={revision:page.revision,total:page.total,matched:page.matched};if(retireSelection)this.clearSnapshotSelection();this.pageLength=length;if(paging)this.pageAll=!!paging.allRows;this.pageOffset=this.cursor?page.offset:this.paged?query.offset:0;if(this.cursor)this.cursorWindow={end:page.offset+page.items.length,next:page.nextCursor,previous:page.previousCursor};if(this.autoRows){if(!same)this.rowHeights.clear();this.rowOffsets=null}
|
|
792
792
|
this.storePage(page);this.pendingQuery=null;this.pendingPaging=null;this.lastFailedQuery=null;this.lastFailedPaging=null;this.version++;const hasRows=this.cursor?page.items.length:page.matched;this.total=(this.cursor?page.items.length:this.paged?Math.min(length,page.matched-this.pageOffset):page.matched)*this.rowH;this.grid.setAttribute("aria-rowcount",page.matched===null?"-1":String(page.matched+1 +(this.headDepth||0)));this.grid.tabIndex=hasRows?-1:0;this.syncScrollRange(this.paged?0:query.offset*this.rowH);this.buildHeader();this.syncColumnControls();this.setNotice(hasRows?"":this.labels.searchNoResults,false);this.grid.setAttribute("aria-busy","false");if(hadFocus||this.focusOrigin){this.focused=[...this.rowCache.values()].find(row=>row.key===previousId)||this.rowCache.get(this.cursor?page.offset:query.offset)||null}
|
|
793
793
|
this.render();if(hadFocus){const element=this.focused&&this.rendered.get(this.focused);(element||this.grid).focus({preventScroll:true})}
|
|
794
|
-
this.host.setAttribute("data-cx-ready","true");if(this.searchInput&&!this.searchComposing&&this.searchTimer==null)this.searchInput.value=query.search;this.syncQuerySummary();this.syncPager();this.emit("query",{query:this.acceptedQuery,revision:page.revision,total:page.total,matched:page.matched});this.stateChanged();return this.getQuery()}catch(error){if(epoch===this.queryEpoch&&!this.destroyed){this.pendingQuery=null;this.pendingPaging=null;this.lastFailedQuery=initial;this.lastFailedPaging={...paging,pageLength:length};this.dataLifetime.abort();this.dataLifetime=new AbortController();this.grid.setAttribute("aria-busy","false");this.setNotice(fill(this.labels.queryFailed,{error:error.message})
|
|
794
|
+
this.host.setAttribute("data-cx-ready","true");if(this.searchInput&&!this.searchComposing&&this.searchTimer==null)this.searchInput.value=query.search;this.syncQuerySummary();this.syncPager();this.emit("query",{query:this.acceptedQuery,revision:page.revision,total:page.total,matched:page.matched});this.stateChanged();return this.getQuery()}catch(error){if(epoch===this.queryEpoch&&!this.destroyed){const cancelled=lifetime.signal.aborted&&error?.name==="AbortError";this.pendingQuery=null;this.pendingPaging=null;this.lastFailedQuery=cancelled?null:initial;this.lastFailedPaging=cancelled?null:{...paging,pageLength:length};this.dataLifetime.abort();this.dataLifetime=new AbortController();this.grid.setAttribute("aria-busy","false");this.setNotice(cancelled?"":fill(this.labels.queryFailed,{error:error.message}),!cancelled);this.syncPager();if(!cancelled)this.emit("error",{error})}
|
|
795
795
|
throw error}}
|
|
796
796
|
querySortHeader(id,event){const previous=gridQuery(this.view,this.queryForChange(true)),sorts=previous.sort.slice();const found=sorts.findIndex(sort=>sort.column===id),old=found>=0?sorts[found].direction:null;const authored=this.columns.find(column=>column.id===id).orderSequence;const sequence=authored?.length?authored:["asc","desc","none"];const direction=sequence[(sequence.indexOf(old||"none")+ 1)%sequence.length];const next=direction==="none"?null:direction;const changed=event&&event.shiftKey?sorts.filter(sort=>sort.column!==id):[];if(next)changed.splice(event&&event.shiftKey&&found>=0?Math.min(found,changed.length):changed.length,0,{column:id,direction:next});this.setQuery(gridQueryStart(previous,{sort:changed})).catch(()=>{})}
|
|
797
797
|
sort(sorts){return this.setQuery(gridQueryStart(this.queryForChange(true),{sort:sorts}))}
|
|
@@ -1226,10 +1226,10 @@ this.dropRow=null}
|
|
|
1226
1226
|
dropPlacement(event,row){const bounds=row.getBoundingClientRect(),fraction=(event.clientY-bounds.top)/ bounds.height;
|
|
1227
1227
|
return fraction<0.25?"before":fraction>0.75?"after":"inside"}
|
|
1228
1228
|
destroy(){this.clearDropRow();this.dragLease=null;super.destroy()}};class FlowHost{}
|
|
1229
|
-
const FORMS_IMPL={},FLOW_IMPL={},activeFlows=new WeakMap();const FORMS_PART=definePart(FlowHost,"forms","forms",()=>({FORMS_IMPL,h,setText,fill,gridFreeze,gridMomentFromParts,boundedPattern,foldText}));const FLOW_VIEWS=typeof FLOW_GRID_VIEWS==="object"?FLOW_GRID_VIEWS:Object.freeze({grid:null,tree:null,reporting:false});const FLOW_PART=definePart(FlowHost,"flow","flow view",()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,foldText,boundedPattern,numberFormat,gridFreeze}));const FLOW_FEATURES={};for(const name of["host","checks","options","pick","records","drafts","preview","command","tasks","dialog","links","endpoint","consent"])
|
|
1230
|
-
FLOW_FEATURES[name]=definePart(FlowHost,"flow-"+name,"flow "+name,()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat,FLOW_VIEWS}));if(typeof DataGrid==="function")DataGrid.prototype.parts.forms=FORMS_PART;const FLOW_DOC_PARTS={command:"command",presets:"drafts",draft:"drafts",deepLinks:"links",endpoint:"endpoint"},FLOW_DOC_PLAIN={draft:"none",deepLinks:false};function flowFeatures(doc,hooks){const names=new Set(),add=(name,on)=>on&&names.add(name),list=value=>Array.isArray(value)?value:[];const object=value=>value!==null&&typeof value==="object"&&!Array.isArray(value),has=(value,...keys)=>object(value)&&keys.some(key=>value[key]!==undefined);for(const[key,name]of Object.entries(FLOW_DOC_PARTS))add(name,doc[key]!==undefined&&doc[key]!==FLOW_DOC_PLAIN[key]);add("tasks",doc.mode==="tasks");add("dialog",has(doc.layout,"launch")||has(doc.layout,"container")&&doc.layout.container!=="inline");add("preview",list(doc.endpoint?.routes).includes("preview"));for(const step of list(doc.steps).filter(object)){add("checks",step.checks!==undefined);add("pick",step.type==="pick");add("preview",step.preview===true);add("consent",has(step,"confirm","acknowledge"));for(const block of[step,...list(step.sections)]){if(block!==step)add("options",has(block,"source","dependsOn"));for(const field of object(block)?list(block.fields):[]){add("options",has(field,"dependsOn")||has(field,"source")&&field.source!=="document");add("records",object(field)&&field.type==="records")}}}
|
|
1229
|
+
const FORMS_IMPL={},FLOW_IMPL={},activeFlows=new WeakMap();const FORMS_PART=definePart(FlowHost,"forms","forms",()=>({FORMS_IMPL,h,setText,fill,gridFreeze,gridMomentFromParts,boundedPattern,foldText}));const FLOW_VIEWS=typeof FLOW_GRID_VIEWS==="object"?FLOW_GRID_VIEWS:Object.freeze({grid:null,tree:null,reporting:false});const FLOW_PART=definePart(FlowHost,"flow","flow view",()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,foldText,boundedPattern,numberFormat,gridFreeze}));const FLOW_FEATURES={};for(const name of["host","checks","options","pick","records","drafts","preview","command","tasks","dialog","links","endpoint","consent","facts"])
|
|
1230
|
+
FLOW_FEATURES[name]=definePart(FlowHost,"flow-"+name,"flow "+name,()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat,FLOW_VIEWS}));if(typeof DataGrid==="function")DataGrid.prototype.parts.forms=FORMS_PART;const FLOW_DOC_PARTS={command:"command",presets:"drafts",draft:"drafts",deepLinks:"links",endpoint:"endpoint"},FLOW_DOC_PLAIN={draft:"none",deepLinks:false};function flowFeatures(doc,hooks){const names=new Set(),add=(name,on)=>on&&names.add(name),list=value=>Array.isArray(value)?value:[];const object=value=>value!==null&&typeof value==="object"&&!Array.isArray(value),has=(value,...keys)=>object(value)&&keys.some(key=>value[key]!==undefined);for(const[key,name]of Object.entries(FLOW_DOC_PARTS))add(name,doc[key]!==undefined&&doc[key]!==FLOW_DOC_PLAIN[key]);add("tasks",doc.mode==="tasks");add("dialog",has(doc.layout,"launch")||has(doc.layout,"container")&&doc.layout.container!=="inline");add("preview",list(doc.endpoint?.routes).includes("preview"));for(const step of list(doc.steps).filter(object)){add("facts",step.facts!==undefined);add("checks",step.checks!==undefined);add("pick",step.type==="pick");add("preview",step.preview===true);add("consent",has(step,"confirm","acknowledge"));for(const block of[step,...list(step.sections)]){if(block!==step)add("options",has(block,"source","dependsOn"));for(const field of object(block)?list(block.fields):[]){add("options",has(field,"dependsOn")||has(field,"source")&&field.source!=="document");add("records",object(field)&&field.type==="records")}}}
|
|
1231
1231
|
hooks=object(hooks)?hooks:{};return{required:[...names],optional:[typeof hooks.preview==="function"&&"preview",object(hooks.presetStore)&&"drafts"].filter(name=>name&&!names.has(name))}}
|
|
1232
|
-
const FLOW_ASYNC_METHODS=["next","back","goTo","setState","validate","submit","runCheck","refreshOptions","saveDraft","setPreset"];const FLOW_SYNC_METHODS=["getStep","getValues","setValues","getState","isDirty","reset","setFieldError","setProgress","complete","setStepState","open","close"];function createFlow(host,options){if(!host||!options||!options.flow||typeof options.flow!=="object")throw new Error("CanopyX: createFlow needs a host element and a flow document.");const existing=activeFlows.get(host);if(existing)return existing;const disposeTheme=watchTheme(host);let impl=null,destroyed=false,mountError=null;const destroyedError=()=>new Error("CanopyX: this flow has been destroyed.");const requireImpl=name=>{if(destroyed)throw destroyedError();if(!impl)throw new Error("CanopyX: flow is not ready; await api.ready before calling "+name+"().");return impl};const editors=Object.assign({},...[...PLUGINS.values()].map(item=>item.editors||{}));const{required,optional}=flowFeatures(options.flow,options.hooks);const ready=Promise.all([loadPart(FLOW_PART),...required.map(name=>loadPart(FLOW_FEATURES[name])),...optional.map(name=>loadPart(FLOW_FEATURES[name])
|
|
1232
|
+
const FLOW_ASYNC_METHODS=["next","back","goTo","setState","validate","submit","runCheck","refreshOptions","saveDraft","setPreset"];const FLOW_SYNC_METHODS=["getStep","getValues","setValues","getState","isDirty","reset","setFieldError","setProgress","complete","setStepState","invalidateChecks","open","close"];function createFlow(host,options){if(!host||!options||!options.flow||typeof options.flow!=="object")throw new Error("CanopyX: createFlow needs a host element and a flow document.");const existing=activeFlows.get(host);if(existing)return existing;const disposeTheme=watchTheme(host);let impl=null,destroyed=false,mountError=null;const destroyedError=()=>new Error("CanopyX: this flow has been destroyed.");const requireImpl=name=>{if(destroyed)throw destroyedError();if(!impl)throw new Error("CanopyX: flow is not ready; await api.ready before calling "+name+"().");return impl};const editors=Object.assign({},...[...PLUGINS.values()].map(item=>item.editors||{}));const{required,optional}=flowFeatures(options.flow,options.hooks);const ready=Promise.all([loadPart(FLOW_PART),...required.map(name=>loadPart(FLOW_FEATURES[name])),...optional.map(name=>loadPart(FLOW_FEATURES[name])
|
|
1233
1233
|
.catch(error=>host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error,hook:"part"},bubbles:true}))))]).then(async()=>{if(destroyed)throw destroyedError();impl=FLOW_IMPL.create(host,options,editors);return impl.ready});const api={element:host,flow:options.flow,view:options.flow};for(const name of FLOW_SYNC_METHODS)api[name]=(...args)=>requireImpl(name)[name](...args);for(const name of FLOW_ASYNC_METHODS)api[name]=(...args)=>{if(destroyed)return Promise.reject(destroyedError());return ready.then(()=>requireImpl(name)[name](...args))};api.ready=ready.then(()=>{if(destroyed)throw destroyedError();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;disposeTheme();try{impl?.destroy()}
|
|
1234
1234
|
finally{impl=null;mountError?.remove();if(activeFlows.get(host)===api){activeFlows.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");host.removeAttribute("data-cx-ready");host.removeAttribute("data-cx-error");host.classList.remove("cx-flow-host")}}};ready.catch(error=>{if(destroyed)return;const notice=mountError=h("div","cx-mount-error");notice.setAttribute("role","alert");setText(notice,error&&error.message?error.message:String(error));host.appendChild(notice);host.setAttribute("data-cx-error",notice.textContent);host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});Object.freeze(api);activeFlows.set(host,api);host.classList.add("cx-host","cx-flow-host");host.setAttribute("data-canopyx-mounted","true");host.canopyx=api;return api}
|
|
1235
1235
|
const FLOW_API={createFlow};function createTreeGrid(host,options){if(!host||!options||!options.view){throw new Error("CanopyX: createTreeGrid needs a host element and a view document.")}
|