@evotecit/canopyx 0.3.16 → 0.3.20
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-board.css +50 -0
- package/CanopyX.Html/Assets/canopyx-board.js +39 -0
- package/CanopyX.Html/Assets/canopyx-buckets.js +15 -0
- package/CanopyX.Html/Assets/canopyx-calculations.css +7 -0
- package/CanopyX.Html/Assets/canopyx-calculations.js +52 -0
- package/CanopyX.Html/Assets/canopyx-calendar-edit.js +3 -3
- package/CanopyX.Html/Assets/canopyx-calendar.css +74 -80
- package/CanopyX.Html/Assets/canopyx-calendar.js +26 -31
- package/CanopyX.Html/Assets/canopyx-cell-range.css +4 -4
- package/CanopyX.Html/Assets/canopyx-cell-range.js +16 -14
- package/CanopyX.Html/Assets/canopyx-changes.css +61 -79
- package/CanopyX.Html/Assets/canopyx-changes.js +18 -15
- package/CanopyX.Html/Assets/canopyx-column-groups.css +5 -1
- package/CanopyX.Html/Assets/canopyx-column-groups.js +15 -9
- package/CanopyX.Html/Assets/canopyx-compare.css +37 -0
- package/CanopyX.Html/Assets/canopyx-compare.js +12 -0
- package/CanopyX.Html/Assets/canopyx-data.js +3 -3
- package/CanopyX.Html/Assets/canopyx-detail-rows.css +4 -4
- package/CanopyX.Html/Assets/canopyx-detail-rows.js +1 -1
- package/CanopyX.Html/Assets/canopyx-editing.css +5 -5
- package/CanopyX.Html/Assets/canopyx-editing.js +2 -2
- package/CanopyX.Html/Assets/canopyx-enhance.js +5 -5
- package/CanopyX.Html/Assets/canopyx-export.js +54 -13
- package/CanopyX.Html/Assets/canopyx-facets.css +32 -22
- package/CanopyX.Html/Assets/canopyx-facets.js +19 -15
- package/CanopyX.Html/Assets/canopyx-filter-editor.css +75 -89
- package/CanopyX.Html/Assets/canopyx-filter-editor.js +20 -16
- package/CanopyX.Html/Assets/canopyx-flow-checks.css +3 -3
- package/CanopyX.Html/Assets/canopyx-flow-checks.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-command.css +3 -3
- package/CanopyX.Html/Assets/canopyx-flow-command.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-dialog.css +4 -4
- package/CanopyX.Html/Assets/canopyx-flow-dialog.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-drafts.css +2 -2
- package/CanopyX.Html/Assets/canopyx-flow-drafts.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-entry.css +142 -17
- package/CanopyX.Html/Assets/canopyx-flow-entry.js +5 -5
- package/CanopyX.Html/Assets/canopyx-flow-host.css +2 -2
- package/CanopyX.Html/Assets/canopyx-flow-host.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-module.mjs +5 -5
- package/CanopyX.Html/Assets/canopyx-flow-pick.css +4 -4
- package/CanopyX.Html/Assets/canopyx-flow-pick.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-preview.css +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-preview.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-records.css +2 -2
- package/CanopyX.Html/Assets/canopyx-flow-records.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-tasks.css +4 -4
- package/CanopyX.Html/Assets/canopyx-flow-tasks.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow.css +41 -41
- package/CanopyX.Html/Assets/canopyx-flow.js +1 -1
- package/CanopyX.Html/Assets/canopyx-format-editor.css +9 -9
- package/CanopyX.Html/Assets/canopyx-format-editor.js +2 -2
- package/CanopyX.Html/Assets/canopyx-formatting.css +13 -13
- package/CanopyX.Html/Assets/canopyx-formatting.js +12 -11
- package/CanopyX.Html/Assets/canopyx-forms.css +3 -3
- package/CanopyX.Html/Assets/canopyx-forms.js +1 -1
- package/CanopyX.Html/Assets/canopyx-grid-module.mjs +220 -155
- package/CanopyX.Html/Assets/canopyx-grid-options.css +8 -8
- package/CanopyX.Html/Assets/canopyx-grid-options.js +9 -2
- package/CanopyX.Html/Assets/canopyx-grid.css +285 -150
- package/CanopyX.Html/Assets/canopyx-grid.js +220 -155
- package/CanopyX.Html/Assets/canopyx-grouping.css +23 -16
- package/CanopyX.Html/Assets/canopyx-grouping.js +24 -17
- package/CanopyX.Html/Assets/canopyx-highlight.css +10 -10
- package/CanopyX.Html/Assets/canopyx-highlight.js +1 -1
- package/CanopyX.Html/Assets/canopyx-interactive.css +215 -91
- package/CanopyX.Html/Assets/canopyx-interactive.js +47 -52
- package/CanopyX.Html/Assets/canopyx-labels-de.js +177 -9
- package/CanopyX.Html/Assets/canopyx-labels-es.js +177 -9
- package/CanopyX.Html/Assets/canopyx-labels-fr.js +176 -8
- package/CanopyX.Html/Assets/canopyx-labels-it.js +176 -8
- package/CanopyX.Html/Assets/canopyx-labels-pl.js +176 -8
- package/CanopyX.Html/Assets/canopyx-layouts.css +49 -21
- package/CanopyX.Html/Assets/canopyx-layouts.js +36 -14
- package/CanopyX.Html/Assets/canopyx-link.css +3 -3
- package/CanopyX.Html/Assets/canopyx-link.js +4 -4
- package/CanopyX.Html/Assets/canopyx-links.js +2 -2
- package/CanopyX.Html/Assets/canopyx-live.css +3 -5
- package/CanopyX.Html/Assets/canopyx-live.js +3 -3
- package/CanopyX.Html/Assets/canopyx-matrix.css +32 -39
- package/CanopyX.Html/Assets/canopyx-matrix.js +11 -11
- package/CanopyX.Html/Assets/canopyx-module.mjs +47 -52
- package/CanopyX.Html/Assets/canopyx-office-export.js +2936 -0
- package/CanopyX.Html/Assets/canopyx-pager.css +1 -1
- package/CanopyX.Html/Assets/canopyx-pager.js +1 -1
- package/CanopyX.Html/Assets/canopyx-path.css +45 -0
- package/CanopyX.Html/Assets/canopyx-path.js +28 -0
- package/CanopyX.Html/Assets/canopyx-pivot.css +75 -0
- package/CanopyX.Html/Assets/canopyx-pivot.js +72 -0
- package/CanopyX.Html/Assets/canopyx-plan.css +63 -0
- package/CanopyX.Html/Assets/canopyx-plan.js +71 -0
- package/CanopyX.Html/Assets/canopyx-presenters.js +2 -2
- package/CanopyX.Html/Assets/canopyx-record-panel.css +51 -45
- package/CanopyX.Html/Assets/canopyx-record-panel.js +30 -22
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +262 -197
- package/CanopyX.Html/Assets/canopyx-reporting.css +300 -164
- package/CanopyX.Html/Assets/canopyx-reporting.js +262 -197
- package/CanopyX.Html/Assets/canopyx-stack.css +35 -0
- package/CanopyX.Html/Assets/canopyx-stack.js +24 -0
- package/CanopyX.Html/Assets/canopyx-time-slider.css +18 -0
- package/CanopyX.Html/Assets/canopyx-time-slider.js +27 -0
- package/CanopyX.Html/Assets/canopyx-timeline.css +19 -19
- package/CanopyX.Html/Assets/canopyx-timeline.js +6 -5
- package/CanopyX.Html/Assets/canopyx-tree-tools.css +47 -46
- package/CanopyX.Html/Assets/canopyx-tree-tools.js +15 -12
- package/CanopyX.Html/Assets/canopyx-ui-menu.css +41 -0
- package/CanopyX.Html/Assets/canopyx-ui-menu.js +64 -0
- package/CanopyX.Html/Assets/canopyx-ui-navigation.css +73 -0
- package/CanopyX.Html/Assets/canopyx-ui-navigation.js +39 -0
- package/CanopyX.Html/Assets/canopyx-ui-overlays.css +79 -0
- package/CanopyX.Html/Assets/canopyx-ui-overlays.js +45 -0
- package/CanopyX.Html/Assets/canopyx-ui-picker.css +12 -0
- package/CanopyX.Html/Assets/canopyx-ui-picker.js +6 -0
- package/CanopyX.Html/Assets/canopyx-ui-stepper.css +174 -0
- package/CanopyX.Html/Assets/canopyx-ui-stepper.js +48 -0
- package/CanopyX.Html/Assets/canopyx-ui-tabs.css +153 -0
- package/CanopyX.Html/Assets/canopyx-ui-tabs.js +47 -0
- package/CanopyX.Html/Assets/canopyx-values.css +5 -0
- package/CanopyX.Html/Assets/canopyx-values.js +13 -0
- package/CanopyX.Html/Assets/canopyx-view-intents.css +12 -0
- package/CanopyX.Html/Assets/canopyx-view-intents.js +56 -0
- package/CanopyX.Html/Assets/canopyx.css +212 -85
- package/CanopyX.Html/Assets/canopyx.js +38 -26
- package/JavaScript/board.d.ts +30 -0
- package/JavaScript/changes.d.ts +4 -1
- package/JavaScript/column-groups.d.ts +24 -4
- package/JavaScript/facets.d.ts +5 -3
- package/JavaScript/grid.d.ts +161 -17
- package/JavaScript/hosts.d.ts +16 -1
- package/JavaScript/index.d.ts +4 -2
- package/JavaScript/locales/de.mjs +177 -9
- package/JavaScript/locales/es.mjs +177 -9
- package/JavaScript/locales/fr.mjs +176 -8
- package/JavaScript/locales/it.mjs +176 -8
- package/JavaScript/locales/pl.mjs +176 -8
- package/JavaScript/matrix.d.ts +4 -1
- package/JavaScript/path.d.ts +33 -0
- package/JavaScript/pivot.d.ts +135 -0
- package/JavaScript/plan.d.ts +23 -0
- package/JavaScript/protocol.d.ts +18 -3
- package/JavaScript/records.d.ts +4 -0
- package/JavaScript/stack.d.ts +28 -0
- package/JavaScript/time-slider.d.ts +58 -0
- package/JavaScript/ui.d.ts +261 -0
- package/JavaScript/view-intents.d.ts +45 -0
- package/README.md +76 -187
- package/README.nuget.md +63 -87
- package/ThirdParty/OfficeIMO/LICENSE +21 -0
- package/ThirdParty/OfficeIMO/README.md +13 -0
- package/package.json +76 -3
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
(function(global){"use strict";const installed=new WeakSet();const part={version:"
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"b760f978327dbab0",requires:["ui-overlays","presenters"],install(context){if(installed.has(context.DataGrid.prototype))return;const{UI_IMPL,UI_TOOLS,DataGrid,h,setText,gridButton,gridVariant,gridInputLabel,gridOption,gridScalar,gridDateInputMoment,gridQuery,gridQueryStart,GRID_FILTER_LABELS,gridResultShape,gridQueryRows,gridOrder,gridKeyCompare,gridFacetKey,columnNumericTone,columnValueTone,gridColumnProjection,gridCellRenderer,cellValue,cellText,foldText,reachable,gridMatchesGroup,gridDecorateButton,gridIcon,numberFormat,numberText,fill,announceMenu,reportingRangeRows,applyTone,toneOf,badgeElement,isCellObject,RECORD_IMPL,overlayTheme}=context;const buildFilters=DataGrid.prototype.buildGridFilters;function gridOverlayTheme(grid,element){for(const name of(grid.opts.overlayClass||"").split(/\s+/).filter(Boolean)) element.classList.add(name);
|
|
2
2
|
overlayTheme(grid.host,element)}
|
|
3
|
-
function gridRestoreFocus(grid,returnFocus,rowId,column){if(grid.destroyed)return;if(returnFocus?.isConnected&&reachable(returnFocus)){returnFocus.focus({preventScroll:true});return}
|
|
3
|
+
function gridRestoreFocus(grid,returnFocus,rowId,column,openedFrom=returnFocus){if(grid.destroyed)return;const active=document.activeElement;if(active&&active!==document.body&&active!==document.documentElement&&active!==openedFrom&&active!==returnFocus&&reachable(active))return;if(returnFocus?.isConnected&&reachable(returnFocus)){returnFocus.focus({preventScroll:true});return}
|
|
4
4
|
const row=[...grid.rowCache.values()].find(item=>!item.status&&item.key===rowId);const index=grid.visibleColumns().findIndex(item=>item.id===column?.id);if(row&&index>=0)grid.focusCell(row,index,0);else if(row)grid.setFocus(row,true);else grid.grid.focus({preventScroll:true})}
|
|
5
|
-
const COLUMNS_MENU={moveColumnChoice(column,target,after){column.pin=target.pin;const ids=this.columns.map(item=>item.id).filter(id=>id!==column.id);ids.splice(ids.indexOf(target.id)+ after,0,column.id);this.setColumnOrder(ids)},renderGridColumns(panel){if(!this.columnList){const find=this.columnFind=h("input","cx-grid-column-find"),actions=h("div","cx-grid-column-actions");find.type="search";find.placeholder=this.labels.gridFindColumn;find.setAttribute("aria-label",find.placeholder);find.hidden=this.columns.length<9;find.oninput=()=>this.syncColumnControls();actions.append(gridButton(this.labels.gridShowAllColumns,()=>this.showAllColumns()),gridButton(this.labels.gridResetColumns,()=>this.resetColumns()));panel.replaceChildren(find,this.columnList=h("div"),actions)}
|
|
5
|
+
const COLUMNS_MENU={moveColumnChoice(column,target,after){column.pin=target.pin;const ids=this.columns.map(item=>item.id).filter(id=>id!==column.id);ids.splice(ids.indexOf(target.id)+ after,0,column.id);this.setColumnOrder(ids)},renderGridColumns(panel){if(!this.columnList){const find=this.columnFind=h("input","cx-grid-column-find"),actions=h("div","cx-grid-column-actions");find.type="search";find.placeholder=this.labels.gridFindColumn;find.setAttribute("aria-label",find.placeholder);find.hidden=this.columns.length<9;find.oninput=()=>this.syncColumnControls();actions.append(gridButton(this.labels.gridShowAllColumns,()=>this.showAllColumns()),gridButton(this.labels.gridResetColumns,()=>this.resetColumns()));if(this.view.calculatedColumnsEditable)actions.append(gridButton(this.labels.gridCalculationAdd,event=>this.openCalculatedColumn(event.currentTarget)));panel.replaceChildren(find,this.columnList=h("div"),actions)}
|
|
6
6
|
this.syncColumnControls()},syncColumnControls(){const list=this.columnList,active=document.activeElement,query=foldText(this.columnFind?.value.trim()||"");if(!list)return;const focus=list.contains(active)&&active.closest(".cx-grid-column-choice").dataset.cxColumn,held=focus&&active.matches(".cx-grid-column-handle"),last=this.columns.filter(item=>!item.hidden).length<2;list.textContent="";for(const column of this.columns){const row=h("div","cx-grid-column-choice"),label=h("label"),input=h("input"),name=h("span","cx-grid-column-name"),handle=h("button","cx-grid-column-handle"),note=column.fitHidden||column.responsiveHidden?this.labels.gridResponsiveHidden:column.pin==="left"?this.labels.gridPinnedLeft:column.pin==="right"?this.labels.gridPinnedRight:"";input.type="checkbox";input.checked=!column.hidden;input.disabled=!column.hidden&&last;input.onchange=()=>{input.focus({preventScroll:true});this.setColumnVisible(column.id,input.checked)};setText(name,name.title=column.title);handle.type="button";setText(handle,"⋮⋮");handle.setAttribute("aria-label",fill(this.labels.gridReorderColumn,{column:column.title}));label.append(input,name);row.append(handle,label);row.hidden=!!query&&!foldText(column.title).includes(query);if(note){const span=h("span","cx-grid-column-note");setText(span,note);row.append(span)}
|
|
7
7
|
if(this.openColumnMenu&&this.tools.columnMenus!==false){const menu=gridDecorateButton(gridButton("",()=>this.openColumnMenu(column.id,menu)),"more",true);menu.classList.add("cx-grid-column-options","icon");menu.setAttribute("aria-label",fill(this.labels.gridColumnMenu,{column:column.title}));menu.setAttribute("aria-haspopup","menu");row.append(menu)}
|
|
8
8
|
row.onkeydown=event=>{const target=event.altKey&&this.columns[this.columns.indexOf(column)+(event.key==="ArrowUp"?-1:event.key==="ArrowDown"?1:NaN)];if(target){event.preventDefault();event.stopPropagation();this.moveColumnChoice(column,target,event.key==="ArrowDown")}};handle.onpointerdown=event=>{if(event.button)return;event.preventDefault();handle.focus();handle.setPointerCapture(event.pointerId);let target,after;const clear=()=>{for(const item of list.children)item.classList.remove("cx-drop-before","cx-drop-after")};handle.onpointermove=move=>{clear();const over=document.elementFromPoint(move.clientX,move.clientY)?.closest(".cx-grid-column-choice");target=over!==row&&list.contains(over)&&this.columns[[...list.children].indexOf(over)];if(target){const box=over.getBoundingClientRect();after=move.clientY>box.top+box.height / 2; over.classList.add(after ? "cx-drop-after" : "cx-drop-before"); }
|
|
@@ -29,13 +29,13 @@ const values=["isNull","isNotNull"].includes(operator)?[]:operator==="in"?[...fi
|
|
|
29
29
|
if(item.operator===operator){filters.push(...item.filters);groups.push(...item.groups)}
|
|
30
30
|
else(item.groups?groups:filters).push(item)}
|
|
31
31
|
return!filters.length&&!groups.length?operator==="and":!filters.length&&groups.length===1?groups[0]:{operator,filters,groups}}
|
|
32
|
-
function gridColumnClauses(query,id){const clauses=[],has=group=>group.filters.some(item=>item.column===id)||group.groups.some(has),only=group=>group.filters.every(item=>item.column===id)&&group.groups.every(only);const remove=group=>{if(!group)return undefined;if(only(group)){clauses.push(group);return undefined}
|
|
32
|
+
function gridColumnClauses(query,id){if(query.tupleFilters?.some(tuple=>tuple.columns.some(field=>field.column===id)))throw new Error("complex");const clauses=[],has=group=>group.filters.some(item=>item.column===id)||group.groups.some(has),only=group=>group.filters.every(item=>item.column===id)&&group.groups.every(only);const remove=group=>{if(!group)return undefined;if(only(group)){clauses.push(group);return undefined}
|
|
33
33
|
if(group.operator==="or"&&has(group))throw new Error("complex");const filters=group.filters.filter(item=>{if(item.column!==id)return true;clauses.push(item);return false}),groups=group.groups.map(remove).filter(Boolean);if(!filters.length&&!groups.length)return undefined;return gridColumnGroup(group.operator,[...filters,...groups])};const filters=(query.filters||[]).filter(item=>{if(item.column!==id)return true;clauses.push(item);return false}),filterGroup=remove(query.filterGroup);return{clauses,query:{...query,filters,filterGroup}}}
|
|
34
34
|
function gridInstallColumnClause(query,id,clause){const base=gridColumnClauses(query,id).query;if(!clause)return gridQueryStart(base);if(!clause.groups)return gridQueryStart(base,{filters:[...base.filters,clause]});return gridQueryStart(base,{filterGroup:base.filterGroup?gridColumnGroup("and",[base.filterGroup,clause]):clause})}
|
|
35
35
|
Object.assign(DataGrid.prototype,{columnFacetItems(column,search="",signal){if(!column||column.filterable===false)throw new Error("CanopyX: facets require a filterable column.");if(this.view.source.kind==="host")return this.getFacets(column.id,{search,includeCurrentFilter:false,limit:200,signal});const query=gridColumnProjection(this.queryForChange(false,true),column.id),columns=new Map(this.view.columns.map(item=>[item.id,item])),rows=gridQueryRows(this.view,query,columns,false),buckets=new Map();for(const row of rows){const value=cellValue(row.cells[column.id])??null,key=gridFacetKey(value,column),item=buckets.get(key);if(item)item.count++;else buckets.set(key,{value,count:1})}
|
|
36
36
|
const items=[...buckets.values()].filter(item=>foldText(cellText(item.value,column,this.fmt)).includes(foldText(search)));items.sort((a,b)=>a.value===null||b.value===null?(a.value===b.value?0:a.value===null?1:-1):
|
|
37
|
-
column.valueOrder?.length?gridKeyCompare(a.value,b.value,column,"asc"):gridOrder(typeof a.value,typeof b.value)||gridOrder(foldText(a.value),foldText(b.value)));return{items:items.slice(0,200),matched:rows.length,totalValues:items.length,truncated:items.length>200}},openColumnFilter(id,anchor){if(!this.acceptedQuery||this.pendingQuery)return;const column=this.columns.find(item=>item.id===id);if(!column||column.filterable===false)throw new Error("CanopyX: column filters require a filterable column.");const panel=this.openGridPopover(anchor,"cx-column-filter",column.title+": "+this.labels.gridFilterColumn,id);const head=h("div","cx-pop-h"),body=h("div","cx-pop-b"),footer=h("div","cx-pop-f"),error=h("p","cx-grid-control-error");setText(head,column.title);error.setAttribute("role","status");panel.append(head,body,error,footer);let timer,clauses,draft;const signal=this.gridPopover.controller.signal,filters=this.reportingFilters;const complex=()=>{setText(body,this.labels.gridComplexFilter);if(filters)body.appendChild(gridButton(this.labels.gridEditAsText,()=>{this.closeGridPopover(false);filters.details.open=true}))};try{({clauses}=gridColumnClauses(this.queryForChange(),id))}catch(_){complex();return}
|
|
38
|
-
const flush=()=>{clearTimeout(timer);timer=null;if(signal.aborted||draft===undefined)return;try{const promise=this.setQuery(gridInstallColumnClause(this.queryForChange(true),id,draft));draft=undefined;this.reportingFilterSubmitEpoch=this.queryEpoch;promise.then(()=>setText(error,""),failure=>setText(error,failure.message))}catch(failure){setText(error,failure.message)}};const apply=clause=>{draft=clause??null;clearTimeout(timer);timer=setTimeout(flush,200)};apply.cancel=()=>{clearTimeout(timer);draft=undefined};signal.addEventListener("abort",()=>clearTimeout(timer),{once:true});footer.append(gridButton(this.labels.gridClearColumnFilter,()=>{clearTimeout(timer);this.setQuery(gridInstallColumnClause(this.queryForChange(true),id,null)).catch(failure=>this.emit("error",{error:failure}));this.closeGridPopover()}),gridButton(this.labels.gridDone,()=>{flush();this.closeGridPopover()}));const custom=item=>item.groups?item.filters.some(custom)||item.groups.some(custom):!Object.hasOwn(GRID_FILTER_LABELS,item.operator);const faceted=!clauses.some(custom)&&column.kind==="text"&&(this.view.source.kind==="inline"||this.view.reporting?.facetColumns?.includes(id)&&typeof this.source.facet==="function");if(!faceted&&clauses.some(item=>item.groups&&(item.groups.length||item.filters.length>2))||!faceted&&clauses.length>2)complex();else if(faceted)this.renderColumnValues(column,body,clauses,apply,error,signal);else this.renderColumnConditions(column,body,clauses,apply,error);this.gridPopover.position()},renderColumnValues(column,body,clauses,apply,error,signal){const search=h("input","cx-input"),all=h("input"),list=h("div","cx-val-list"),status=h("p","cx-muted");search.type="search";search.setAttribute("aria-label",this.labels.gridFilterValues);search.placeholder=this.labels.gridFilterValues;all.type="checkbox";all.checked=!clauses.length;const allLabel=h("label","cx-val-all"),allCount=h("span","cx-val-n");allCount.setAttribute("aria-hidden","true");allLabel.append(all,this.labels.gridSelectAllValues,allCount);body.append(search,allLabel,list,status);const criteria=()=>JSON.stringify([gridResultShape(gridColumnProjection(this.getQuery(),column.id)),this.snapshot.revision]),originalCriteria=criteria();this.host.addEventListener("canopyx:query",()=>{if(criteria()!==originalCriteria)this.closeGridPopover(false)},{signal});let baseline=gridColumnGroup("and",clauses),items=[],selected=new Map(),request=0,facetController;signal.addEventListener("abort",()=>facetController?.abort(),{once:true});const key=value=>gridFacetKey(value,column),columns=new Map([[column.id,column]]),matchesClause=(value,clause)=>typeof clause==="boolean"?clause:gridMatchesGroup({cells:{[column.id]:value}},clause,columns),predicate=(operator,values=[])=>({column:column.id,operator,values}),matches=value=>matchesClause(value,baseline),chosen=value=>selected.get(key(value))?.checked??matches(value);const syncAll=()=>{all.checked=items.length>0&&items.every(item=>chosen(item.value));all.indeterminate=!all.checked&&items.some(item=>chosen(item.value))};const commit=()=>{const withoutEdited=clause=>{if(clause.groups)return gridColumnGroup(clause.operator,[...clause.filters,...clause.groups].map(withoutEdited));if(clause.operator==="in"){const values=clause.values.filter(value=>!selected.has(key(value)));return values.length?{...clause,values}:false}
|
|
37
|
+
column.valueOrder?.length?gridKeyCompare(a.value,b.value,column,"asc"):gridOrder(typeof a.value,typeof b.value)||gridOrder(foldText(a.value),foldText(b.value)));return{items:items.slice(0,200),matched:rows.length,totalValues:items.length,truncated:items.length>200}},openColumnFilter(id,anchor){if(!this.acceptedQuery||this.pendingQuery)return;const column=this.columns.find(item=>item.id===id);if(!column||column.filterable===false)throw new Error("CanopyX: column filters require a filterable column.");const panel=this.openGridPopover(anchor,"cx-column-filter",column.title+": "+this.labels.gridFilterColumn,id);if(!panel)return;const head=h("div","cx-pop-h"),body=h("div","cx-pop-b"),footer=h("div","cx-pop-f"),error=h("p","cx-grid-control-error");setText(head,column.title);error.setAttribute("role","status");panel.append(head,body,error,footer);let timer,clauses,draft;const signal=this.gridPopover.controller.signal,filters=this.reportingFilters;const complex=()=>{setText(body,this.labels.gridComplexFilter);if(filters)body.appendChild(gridButton(this.labels.gridEditAsText,()=>{this.closeGridPopover(false);filters.details.open=true}))};try{({clauses}=gridColumnClauses(this.queryForChange(),id))}catch(_){complex();return}
|
|
38
|
+
const flush=()=>{clearTimeout(timer);timer=null;if(signal.aborted||draft===undefined)return;try{const promise=this.setQuery(gridInstallColumnClause(this.queryForChange(true),id,draft));draft=undefined;this.reportingFilterSubmitEpoch=this.queryEpoch;promise.then(()=>setText(error,""),failure=>setText(error,failure.message))}catch(failure){setText(error,failure.message)}};const apply=clause=>{draft=clause??null;clearTimeout(timer);timer=setTimeout(flush,200)};apply.cancel=()=>{clearTimeout(timer);draft=undefined};signal.addEventListener("abort",()=>clearTimeout(timer),{once:true});footer.append(gridVariant(gridButton(this.labels.gridClearColumnFilter,()=>{clearTimeout(timer);this.setQuery(gridInstallColumnClause(this.queryForChange(true),id,null)).catch(failure=>this.emit("error",{error:failure}));this.closeGridPopover()}),"ghost"),gridVariant(gridButton(this.labels.gridDone,()=>{flush();this.closeGridPopover()}),"primary"));const custom=item=>item.groups?item.filters.some(custom)||item.groups.some(custom):!Object.hasOwn(GRID_FILTER_LABELS,item.operator);const faceted=!clauses.some(custom)&&column.kind==="text"&&(this.view.source.kind==="inline"||this.view.reporting?.facetColumns?.includes(id)&&typeof this.source.facet==="function");if(!faceted&&clauses.some(item=>item.groups&&(item.groups.length||item.filters.length>2))||!faceted&&clauses.length>2)complex();else if(faceted)this.renderColumnValues(column,body,clauses,apply,error,signal);else this.renderColumnConditions(column,body,clauses,apply,error);this.gridPopover.position()},renderColumnValues(column,body,clauses,apply,error,signal){const search=h("input","cx-input"),all=h("input"),list=h("div","cx-val-list"),status=h("p","cx-muted");search.type="search";search.setAttribute("aria-label",this.labels.gridFilterValues);search.placeholder=this.labels.gridFilterValues;all.type="checkbox";all.checked=!clauses.length;const allLabel=h("label","cx-val-all"),allCount=h("span","cx-val-n");allCount.setAttribute("aria-hidden","true");allLabel.append(all,this.labels.gridSelectAllValues,allCount);body.append(search,allLabel,list,status);const criteria=()=>JSON.stringify([gridResultShape(gridColumnProjection(this.getQuery(),column.id)),this.snapshot.revision]),originalCriteria=criteria();this.host.addEventListener("canopyx:query",()=>{if(criteria()!==originalCriteria)this.closeGridPopover(false)},{signal});let baseline=gridColumnGroup("and",clauses),items=[],selected=new Map(),request=0,facetController;signal.addEventListener("abort",()=>facetController?.abort(),{once:true});const key=value=>gridFacetKey(value,column),columns=new Map([[column.id,column]]),matchesClause=(value,clause)=>typeof clause==="boolean"?clause:gridMatchesGroup({cells:{[column.id]:value}},clause,columns),predicate=(operator,values=[])=>({column:column.id,operator,values}),matches=value=>matchesClause(value,baseline),chosen=value=>selected.get(key(value))?.checked??matches(value);const syncAll=()=>{all.checked=items.length>0&&items.every(item=>chosen(item.value));all.indeterminate=!all.checked&&items.some(item=>chosen(item.value))};const commit=()=>{const withoutEdited=clause=>{if(clause.groups)return gridColumnGroup(clause.operator,[...clause.filters,...clause.groups].map(withoutEdited));if(clause.operator==="in"){const values=clause.values.filter(value=>!selected.has(key(value)));return values.length?{...clause,values}:false}
|
|
39
39
|
if(["eq","ne","isNull","isNotNull"].includes(clause.operator)&&selected.has(key(clause.values[0]??null)))return["ne","isNotNull"].includes(clause.operator);return clause};let clause=typeof baseline==="boolean"?baseline:withoutEdited(baseline);const included=[],excluded=[];for(const item of selected.values())if(item.checked!==matchesClause(item.value,clause))(item.checked?included:excluded).push(item.value);clause=gridColumnGroup("and",[clause,...excluded.map(value=>predicate(value==null?"isNotNull":"ne",value==null?[]:[value]))]);const additions=[],raw=included.filter(value=>value!=null);if(raw.length<included.length)additions.push(predicate("isNull"));if(raw.length)additions.push(predicate("in",raw));clause=gridColumnGroup("or",[clause,...additions]);apply(clause===true?undefined:clause===false?gridColumnGroup("and",[predicate("isNull"),predicate("isNotNull")]):clause)};const render=()=>{list.replaceChildren();for(const item of items){const label=h("label","cx-val"),check=h("input"),value=h("span","cx-facet-value"),count=h("span","cx-val-n");check.type="checkbox";check.checked=chosen(item.value);const options=column.presenter;if(options&&!['statusStrip','sparklineBars','sparklineLine','change','identifier','longText','list','tags'].includes(options.kind))gridCellRenderer(this,column,options)({id:"facet",cells:{[column.id]:item.value}},value);else setText(value,cellText(item.value,column,this.fmt)||"—");setText(count,numberFormat(this.lang).format(item.count));label.append(check,value,count);list.appendChild(label);check.addEventListener("change",()=>{if(check.checked===matches(item.value))selected.delete(key(item.value));else selected.set(key(item.value),{value:item.value,checked:check.checked});syncAll();commit()})}
|
|
40
40
|
syncAll()};const load=async()=>{const generation=++request;facetController?.abort();facetController=new AbortController();setText(status,this.labels.loading);try{const page=await this.columnFacetItems(column,search.value,facetController.signal);if(signal.aborted||generation!==request)return;const previous=new Map(items.map(item=>[key(item.value),item]));for(const item of page.items)previous.set(key(item.value),item);items=[...previous.values()];render();for(const row of list.children)row.hidden=!foldText(row.querySelector('.cx-facet-value').textContent).includes(foldText(search.value));if(!search.value){search.hidden=page.totalValues<=12;setText(allCount,numberFormat(this.lang).format(page.totalValues))}
|
|
41
41
|
setText(status,page.truncated?fill(this.labels.gridFacetCounts,{count:page.matched,shown:page.items.length,total:page.totalValues}):"");this.gridPopover?.position()}catch(failure){if(!signal.aborted&&generation===request&&failure.name!=="AbortError")setText(error,failure.message)}};all.addEventListener("change",()=>{baseline=all.checked;selected.clear();render();commit()});search.addEventListener("input",load);load()}});function gridDateInput(value,local){const date=new Date(value);return Number.isFinite(date.getTime())?new Date(date.getTime()-(local?date.getTimezoneOffset()*60000:0)).toISOString().slice(0,-1):""}
|
|
@@ -45,29 +45,33 @@ DataGrid.prototype.renderColumnConditions=function(column,body,clauses,apply,err
|
|
|
45
45
|
if(![...operator.options].some(option=>option.value===name))operator.appendChild(gridOption(name,GRID_FILTER_LABELS[name]||name));operator.setAttribute("aria-label",this.labels.gridOperator);input.setAttribute("aria-label",this.labels.gridConditionValue);input.type=date?"datetime-local":text?"text":"number";if(!text)input.step="any";if(filter){operator.value=filter.operator;input.value=date?gridDateInput(filter.values[0],this.local):String(filter.values[0]??"")}
|
|
46
46
|
input.disabled=["isNull","isNotNull"].includes(operator.value);row._condition={operator,input,original:filter?{filter,input:input.value}:null};row.append(operator,input);if(rows.children.length){const remove=gridDecorateButton(gridButton("",()=>{row.remove();join.hidden=true;addButton.hidden=false;update()}),"close",true);remove.setAttribute("aria-label",this.labels.gridDeleteCondition);row.appendChild(remove);rows.appendChild(row)}else rows.appendChild(row);input.addEventListener("input",update);operator.addEventListener("change",()=>{input.disabled=["isNull","isNotNull"].includes(operator.value);update()})};if(date){preset=h("select","cx-input");preset.setAttribute("aria-label",this.labels.gridDateRange);for(const[value,label]of[["range","gridDateRange"],...GRID_DATE_PRESETS])preset.appendChild(gridOption(value,this.labels[label]));preset.addEventListener("change",()=>{if(preset.value==="range")return;const[start,end]=gridDatePreset(this.local,preset.value);rows.replaceChildren();add({column:column.id,operator:"ge",values:[start]});add({column:column.id,operator:"lt",values:[end]});join.value="and";join.hidden=false;addButton.hidden=true;apply(read())});body.appendChild(preset)}
|
|
47
47
|
const addButton=gridButton(this.labels.gridAddCondition,()=>{add(null);join.hidden=false;addButton.hidden=true;rows.lastElementChild.querySelector('input').focus()});addButton.classList.add("cx-link");add(filters[0]);if(filters[1]){add(filters[1]);join.hidden=false;addButton.hidden=true}
|
|
48
|
-
join.addEventListener("change",update);body.append(rows,join,addButton);if(date){const zone=h("p","cx-muted");setText(zone,new Intl.DateTimeFormat(this.lang,{timeZone:this.local?undefined:"UTC"}).resolvedOptions().timeZone);body.appendChild(zone)}};const FILTER_SUMMARY=DataGrid.prototype.syncQuerySummary;DataGrid.prototype.syncQuerySummary=function(){FILTER_SUMMARY.call(this);const controls=this.reportingFilters,query=this.getQuery(),shape=JSON.stringify([query?.filters||[],query?.filterGroup||null]);if(!controls?.details.open||shape===this.reportingFilterDraftBase)return;if(this.reportingFilterSubmitEpoch===this.queryEpoch)this.reportingFilterDraftBase=shape;else{const hadFocus=controls.panel.contains(document.activeElement);controls.details.open=false;if(hadFocus)controls.details.querySelector("summary").focus({preventScroll:true})}};function gridFilterDepth(group){return group?1+Math.max(0,...group.groups.map(gridFilterDepth)):0}
|
|
48
|
+
join.addEventListener("change",update);body.append(rows,join,addButton);if(date){const zone=h("p","cx-muted");setText(zone,new Intl.DateTimeFormat(this.lang,{timeZone:this.local?undefined:"UTC"}).resolvedOptions().timeZone);body.appendChild(zone)}};const FILTER_SUMMARY=DataGrid.prototype.syncQuerySummary;DataGrid.prototype.syncQuerySummary=function(){FILTER_SUMMARY.call(this);const controls=this.reportingFilters,query=this.getQuery(),shape=JSON.stringify([query?.filters||[],query?.filterGroup||null,query?.tupleFilters||null]);if(!controls?.details.open||shape===this.reportingFilterDraftBase)return;if(this.reportingFilterSubmitEpoch===this.queryEpoch)this.reportingFilterDraftBase=shape;else{const hadFocus=controls.panel.contains(document.activeElement);controls.details.open=false;if(hadFocus)controls.details.querySelector("summary").focus({preventScroll:true})}};function gridFilterDepth(group){return group?1+Math.max(0,...group.groups.map(gridFilterDepth)):0}
|
|
49
49
|
function gridFilterSegment(grid,initial,onChange){const segment=h("div","cx-seg"),buttons=[];segment.setAttribute("role","group");segment.setAttribute("aria-label",grid.labels.gridFilterMatch);segment._operator=initial;for(const[value,label]of[["and","gridFilterAll"],["or","gridFilterAny"]]){const button=gridButton(grid.labels[label],()=>{segment._operator=value;sync();onChange()});button.dataset.cxJoin=value;segment.appendChild(button);buttons.push(button)}
|
|
50
50
|
function sync(){for(const button of buttons){button.setAttribute("aria-pressed",String(button.dataset.cxJoin===segment._operator));button.classList.toggle("on",button.dataset.cxJoin===segment._operator)}}
|
|
51
51
|
sync();return segment}
|
|
52
|
-
DataGrid.prototype.renderGridFilters=function(panel){panel.replaceChildren();panel.classList.add("cx-fb");this.reportingFilterDraftBase=JSON.stringify([this.queryForChange().filters||[],this.queryForChange().filterGroup||null]);const form=h("form","cx-grid-filter-form cx-fb"),head=h("div","cx-pop-h"),body=h("div","cx-pop-b"),footer=h("div","cx-pop-f"),error=h("p","cx-grid-control-error");setText(head,this.labels.gridFilters);error.setAttribute("role","status");panel.append(head,form);form.append(body,error,footer);panel._filterLifetime?.abort();const controller=panel._filterLifetime=new AbortController();let timer,editingText=false,text,draft;const flush=()=>{clearTimeout(timer);timer=null;if(!draft||!panel.isConnected||!panel.parentElement.open||this.destroyed)return;const query=draft;draft=null;try{const validated=gridQuery(this.view,query);if(gridResultShape(validated)===gridResultShape(this.queryForChange()))return;const promise=this.setQuery(validated);this.reportingFilterSubmitEpoch=this.queryEpoch;promise.then(()=>setText(error,""),failure=>setText(error,failure.message))}catch(failure){setText(error,this.labels.gridInvalidFilter)}};const apply=query=>{draft=query;clearTimeout(timer);timer=setTimeout(flush,200)};controller.signal.addEventListener("abort",()=>clearTimeout(timer),{once:true});this.lifetime.signal.addEventListener("abort",()=>controller.abort(),{once:true,signal:controller.signal});document.addEventListener("click",event=>{for(const box of form.querySelectorAll(".cx-ms[open]"))if(!box.contains(event.target))box.open=false},{signal:controller.signal});form.addEventListener("keydown",event=>{const box=event.target.closest(".cx-ms[open]");if(event.key==="Escape"&&box){box.open=false;box.firstChild.focus();event.stopPropagation()}});panel.parentElement.addEventListener("toggle",()=>{if(!panel.parentElement.open)controller.abort()},{signal:controller.signal});const close=()=>{clearTimeout(timer);panel.parentElement.open=false;panel.parentElement.querySelector("summary").focus()};footer.append(gridButton(this.labels.gridClearFilters,()=>{clearTimeout(timer);this.setQuery(gridQueryStart(this.queryForChange(true),{filters:[],filterGroup:undefined})).catch(failure=>setText(error,failure.message));this.renderGridFilters(panel)}),gridButton(this.labels.gridDone,()=>{draft=gridQueryStart(draft||this.queryForChange(),{search:this.queryForChange(true).search});flush();close()}));if(
|
|
52
|
+
DataGrid.prototype.renderGridFilters=function(panel){panel.replaceChildren();panel.classList.add("cx-fb");this.reportingFilterDraftBase=JSON.stringify([this.queryForChange().filters||[],this.queryForChange().filterGroup||null,this.queryForChange().tupleFilters||null]);const form=h("form","cx-grid-filter-form cx-fb"),head=h("div","cx-pop-h"),body=h("div","cx-pop-b"),footer=h("div","cx-pop-f"),error=h("p","cx-grid-control-error");setText(head,this.labels.gridFilters);error.setAttribute("role","status");panel.append(head,form);form.append(body,error,footer);panel._filterLifetime?.abort();const controller=panel._filterLifetime=new AbortController();let timer,editingText=false,text,draft;const flush=()=>{clearTimeout(timer);timer=null;if(!draft||!panel.isConnected||!panel.parentElement.open||this.destroyed)return;const query=draft;draft=null;try{const validated=gridQuery(this.view,query);if(gridResultShape(validated)===gridResultShape(this.queryForChange()))return;const promise=this.setQuery(validated);this.reportingFilterSubmitEpoch=this.queryEpoch;promise.then(()=>setText(error,""),failure=>setText(error,failure.message))}catch(failure){setText(error,this.labels.gridInvalidFilter)}};const apply=query=>{draft=query;clearTimeout(timer);timer=setTimeout(flush,200)};controller.signal.addEventListener("abort",()=>clearTimeout(timer),{once:true});this.lifetime.signal.addEventListener("abort",()=>controller.abort(),{once:true,signal:controller.signal});document.addEventListener("click",event=>{for(const box of form.querySelectorAll(".cx-ms[open]"))if(!box.contains(event.target))box.open=false},{signal:controller.signal});form.addEventListener("keydown",event=>{const box=event.target.closest(".cx-ms[open]");if(event.key==="Escape"&&box){box.open=false;box.firstChild.focus();event.stopPropagation()}});panel.parentElement.addEventListener("toggle",()=>{if(!panel.parentElement.open)controller.abort()},{signal:controller.signal});const close=()=>{clearTimeout(timer);panel.parentElement.open=false;panel.parentElement.querySelector("summary").focus()};footer.append(gridVariant(gridButton(this.labels.gridClearFilters,()=>{clearTimeout(timer);this.setQuery(gridQueryStart(this.queryForChange(true),{filters:[],filterGroup:undefined,tupleFilters:undefined})).catch(failure=>setText(error,failure.message));this.renderGridFilters(panel)}),"ghost"),gridVariant(gridButton(this.labels.gridDone,()=>{draft=gridQueryStart(draft||this.queryForChange(),{search:this.queryForChange(true).search});flush();close()}),"primary"));if(this.queryForChange().tupleFilters?.length){const notice=h("p");setText(notice,this.labels.gridComplexFilter);body.appendChild(notice)}
|
|
53
|
+
if(gridFilterDepth(this.queryForChange().filterGroup)>2){const notice=h("p");setText(notice,this.labels.gridDeepFilters);text=h("textarea","cx-filter-text");text.setAttribute("aria-label",this.labels.gridFilterText);text.readOnly=true;text.value=JSON.stringify({filters:this.queryForChange().filters||[],filterGroup:this.queryForChange().filterGroup},null,2);const edit=gridButton(this.labels.gridEditAsText,()=>{editingText=true;text.readOnly=false;text.focus()});body.append(notice,text,edit);text.addEventListener("input",()=>{try{const value=JSON.parse(text.value);apply(gridQueryStart(this.queryForChange(true),{filters:value.filters||[],filterGroup:value.filterGroup}))}catch(_){clearTimeout(timer);draft=null;setText(error,this.labels.gridInvalidFilter)}});return}
|
|
53
54
|
const update=()=>{try{syncWords(root);apply(readQuery());setText(error,"")}catch(_){clearTimeout(timer);draft=null;setText(error,this.labels.gridInvalidFilter)}};const makeGroup=(parent,definition,depth)=>{const block=h("div",depth?"cx-grid-filter-group":"cx-filter-root"),heading=h("div","cx-group-h"),rows=h("div","cx-condition-rows"),children=h("div","cx-grid-filter-group-children"),actions=h("div","cx-adds");const segment=gridFilterSegment(this,definition?.operator||"and",update);if(!depth)heading.append(document.createTextNode(this.labels.gridShowRowsWhere+" "));heading.append(segment,document.createTextNode(" "+(depth?this.labels.gridOfThese:this.labels.gridOfTheseAreTrue)));block._group={segment,rows,children};block.append(heading,rows,children,actions);parent.appendChild(block);const add=predicate=>{if(form.querySelectorAll('.cx-grid-filter').length>=64)return;this.addGridFilter(rows,predicate);const row=rows.lastElementChild;if(!row)return;row._design=true;row.classList.add("cx-cond");row._filter.type.closest("label").hidden=row._filter.type.value==="string";const word=h("span","w");row.prepend(word);const typeLabel=row._filter.type.closest('label');if(this.columns.find(column=>column.id===row._filter.column.value)?.presenter?.kind==="boolean"){row._filter.type.value="boolean";row._filter.type.dispatchEvent(new Event("change"));typeLabel.hidden=true}
|
|
54
55
|
const remove=row.querySelector(':scope > button');if(remove){remove.replaceChildren(gridIcon("close"));remove.classList.add("icon");remove.setAttribute("aria-label",this.labels.gridDeleteCondition);remove.addEventListener("click",update)}
|
|
55
56
|
syncWords(block);return row};const condition=gridButton(this.labels.gridAddCondition,()=>{const row=add(null);row?._filter.column.focus()});condition.classList.add("cx-link");const group=gridButton(this.labels.gridAddGroup,()=>{makeGroup(children,null,depth+1);syncWords(block)});group.classList.add("cx-link");group.disabled=depth>=2;actions.append(condition,group);if(depth){const remove=gridDecorateButton(gridButton("",()=>{const target=parent.parentElement.querySelector(":scope > .cx-adds > button");block.remove();update();target?.focus()}),"close",true);remove.classList.add("icon");remove.setAttribute("aria-label",this.labels.gridDeleteFilterGroup);heading.appendChild(remove)}
|
|
56
57
|
const predicates=definition?.filters||[];(this.view.reporting&&reportingRangeRows&&definition?.operator==="and"?reportingRangeRows(predicates):predicates).forEach(add);(definition?.groups||[]).forEach(child=>makeGroup(children,child,depth+1));return block};const syncWords=block=>{const data=block._group;[...data.rows.children].forEach((row,index)=>setText(row.querySelector('.w'),index===0?this.labels.gridWhere:data.segment._operator==="and"?this.labels.gridAnd:this.labels.gridOr));for(const child of data.children.children)syncWords(child)};const readBlock=block=>{const{segment,rows,children}=block._group,filters=[],groups=[...children.children].map(readBlock).filter(Boolean);for(const row of rows.children){if(!row._filter.original&&!row._filter.edited)continue;const predicates=[].concat(this.readGridFilter(row));if(segment._operator==="or"&&predicates.length>1)groups.push({operator:"and",filters:predicates,groups:[]});else filters.push(...predicates)}
|
|
57
58
|
return filters.length||groups.length?{operator:segment._operator,filters,groups}:null};const readQuery=()=>{if(editingText){const value=JSON.parse(text.value);return gridQueryStart(this.queryForChange(true),{filters:value.filters||[],filterGroup:value.filterGroup})}
|
|
58
|
-
const value=readBlock(root);if(!value)return gridQueryStart(this.queryForChange(true),{filters:[],filterGroup:undefined});if(value.operator==="or")return gridQueryStart(this.queryForChange(true),{filters:[],filterGroup:value});return gridQueryStart(this.queryForChange(true),{filters:value.filters,filterGroup:value.groups.length===1?value.groups[0]:value.groups.length?{operator:"and",filters:[],groups:value.groups}:undefined})};const root=makeGroup(body,{operator:"and",filters:this.queryForChange().filters||[],groups:this.queryForChange().filterGroup?[this.queryForChange().filterGroup]:[]},0);syncWords(root);form.addEventListener("input",update);form.addEventListener("change",update);form.addEventListener("submit",event=>{event.preventDefault();update()})};
|
|
59
|
-
|
|
60
|
-
positionPending=false;const current=this.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
finally{
|
|
64
|
-
|
|
59
|
+
const value=readBlock(root);if(!value)return gridQueryStart(this.queryForChange(true),{filters:[],filterGroup:undefined,tupleFilters:undefined});if(value.operator==="or")return gridQueryStart(this.queryForChange(true),{filters:[],filterGroup:value});return gridQueryStart(this.queryForChange(true),{filters:value.filters,filterGroup:value.groups.length===1?value.groups[0]:value.groups.length?{operator:"and",filters:[],groups:value.groups}:undefined})};const root=makeGroup(body,{operator:"and",filters:this.queryForChange().filters||[],groups:this.queryForChange().filterGroup?[this.queryForChange().filterGroup]:[]},0);syncWords(root);form.addEventListener("input",update);form.addEventListener("change",update);form.addEventListener("submit",event=>{event.preventDefault();update()})};Object.assign(DataGrid.prototype,{openGridPopover(anchor,className,title,columnId,createOverlay){anchor=this.resolveColumnAnchor(columnId,anchor);if(!anchor)return null;this.closeGridPopover(false);const panel=h("div","cx-host cx-grid-overlay cx-pop cx-popover "+className),controller=new AbortController(),signal=controller.signal;for(const name of(this.opts.overlayClass||"").split(/\s+/).filter(Boolean))panel.classList.add(name);
|
|
60
|
+
panel.dataset.hfxPart="popover";panel.setAttribute("role","dialog");panel.setAttribute("aria-label",title);panel.tabIndex=-1;panel.id=this.id+"-popover";anchor.setAttribute("aria-controls",panel.id);anchor.setAttribute("aria-expanded","true");document.body.appendChild(panel);const pressed=new Set();let positionPending=false,releaseFrame=0;const position=()=>{if(signal.aborted)return;if(pressed.size||releaseFrame){positionPending=true;return}
|
|
61
|
+
positionPending=false;const current=this.resolveColumnAnchor(columnId,anchor,true);if(!current){this.closeGridPopover(false);return}
|
|
62
|
+
const phone=this.host.clientWidth<=640;panel.classList.toggle("cx-phone",phone);panel.dataset.phone=String(phone);if(phone){panel.style.margin="0";panel.style.left="0";panel.style.top="auto";panel.style.bottom="0";panel.style.width="100%";panel.style.maxHeight="80vh"}
|
|
63
|
+
else{panel.style.margin="";panel.style.width="";panel.style.bottom="auto";panel.style.maxHeight=Math.min(500,global.innerHeight-16)+"px";UI_TOOLS.position(panel,current,"bottom-start")}};const overlay=createOverlay?createOverlay(panel,signal):UI_TOOLS.overlay(panel,{host:this.host,trigger:anchor,kind:"popover",initialFocus:panel},signal);this.gridPopover={panel,controller,anchor,columnId,position,overlay};for(const type of["cx-popover:close","cx-menu:close"])panel.addEventListener(type,event=>{if(event.target===panel&&this.gridPopover?.panel===panel)this.closeGridPopover(event.detail.reason==="cancel")},{signal});panel.addEventListener("pointerdown",event=>pressed.add(event.pointerId),{signal});const release=event=>{if(!pressed.delete(event.pointerId))return;if(!releaseFrame)releaseFrame=global.requestAnimationFrame(()=>{releaseFrame=0;if(positionPending)position()})};for(const type of["pointerup","pointercancel"])global.addEventListener(type,release,{capture:true,signal});global.addEventListener("resize",position,{signal});global.addEventListener("scroll",position,{capture:true,signal});this.lifetime.signal.addEventListener("abort",()=>controller.abort(),{once:true,signal});signal.addEventListener("abort",()=>{global.cancelAnimationFrame(releaseFrame);pressed.clear();if(this.gridPopover?.panel===panel)this.gridPopover=null;anchor.setAttribute("aria-expanded","false");panel.remove()},{once:true});overlay.open();announceMenu(panel);UI_TOOLS.observe(this.host,position,signal);queueMicrotask(position);return panel},async openColumnMenu(id,anchor){const request=this.pendingColumnMenu={anchor};try{await this.requirePart("ui-menu");if(this.destroyed||this.pendingColumnMenu!==request)return;anchor=this.resolveColumnAnchor(id,anchor);if(anchor)UI_IMPL.columnMenu.call(this,id,anchor,{gridIcon,gridQueryStart})}catch(error){if(!this.destroyed&&this.pendingColumnMenu===request){this.setNotice(this.labels.gridLoadFailed,true);this.emit("error",{error})}}
|
|
64
|
+
finally{if(this.pendingColumnMenu===request)this.pendingColumnMenu=null}}});let activeRecordDrawer;DataGrid.prototype.openGridDrawer=function(record,index,returnFocus,options){const openedFrom=document.activeElement;if(activeRecordDrawer?.contains(returnFocus))returnFocus=activeRecordDrawer._returnFocus;if(activeRecordDrawer){activeRecordDrawer._replaced=true;activeRecordDrawer._cxOverlay.close("replace",false,true);activeRecordDrawer.remove()}
|
|
65
|
+
const dialog=h("dialog","cx-host cx-grid-overlay cx-drawer"),head=h("div","cx-drawer-h"),identity=h("div"),title=h("h4"),subtitle=h("p"),body=h("div","cx-drawer-body");dialog._returnFocus=returnFocus;for(const name of(this.opts.overlayClass||"").split(/\s+/).filter(Boolean))dialog.classList.add(name);
|
|
66
|
+
const restoreTheme=UI_TOOLS.theme(this.host,dialog);dialog.dataset.hfxPart="drawer";dialog.dataset.side="end";head.dataset.hfxPart="header";title.dataset.hfxPart="title";body.dataset.hfxPart="body";title.id=this.id+"-record-title";title.tabIndex=-1;title.setAttribute("aria-level","2");dialog.setAttribute("aria-labelledby",title.id);const previous=gridDecorateButton(gridButton("",()=>navigate(-1)),"up",true),next=gridDecorateButton(gridButton("",()=>navigate(1)),"down",true),close=gridDecorateButton(gridButton("",()=>dialog._cxOverlay.close()),"close",true);previous.setAttribute("aria-label",this.labels.gridPreviousRecord);next.setAttribute("aria-label",this.labels.gridNextRecord);close.setAttribute("aria-label",this.labels.gridCloseRecord);for(const button of[previous,next,close])button.classList.add("icon");identity.append(title,subtitle);head.append(identity,previous,next,close);dialog.append(head,body);document.body.appendChild(dialog);activeRecordDrawer=dialog;this.recordDrawer=dialog;DataGrid.activeDrawers.set(dialog,this);const primary=this.visibleColumns()[0],shape=gridResultShape(this.acceptedQuery),owner=this.dataLifetime;let retiredForNavigation=false,paints=null;const modal=(this.opts.recordDrawerModal??this.view.recordDrawerModal)===true;const lifetime=new AbortController(),overlay=dialog._cxOverlay=UI_IMPL.drawer(dialog,{host:this.host,container:this.host,focus:false,dismissible:modal,modal,closeWhenHidden:true},lifetime.signal);lifetime.signal.addEventListener("abort",restoreTheme,{once:true});const placed=()=>Number.isInteger(index);const steps=()=>{previous.disabled=!placed()||index<=0||this.cursor&&index<=this.rowBounds().first;next.disabled=!placed()||index>=this.rowCount()-1};const paint=(row,position)=>{record=row;index=position;paints?.abort();paints=new AbortController();setText(title,cellText(row.cells[primary.id],primary,this.fmt)||row.id);const options=primary.presenter;const secondary=row.cells[primary.id]?.secondary||options?.secondaryColumn&&cellText(row.cells[options.secondaryColumn],this.columns.find(column=>column.id===options.secondaryColumn),this.fmt)||"";setText(subtitle,secondary);subtitle.hidden=!secondary;dialog._cxRecord=row;dialog._cxIndex=index;dialog.setAttribute("data-cx-record",row.id);dialog.setAttribute("data-cx-view",this.view.id);steps();this.paintDrawerBody(row,body,dialog,{index,signal:paints.signal});dialog.dispatchEvent(new CustomEvent("cx-drawer-paint",{detail:{id:row.id,index}}))};const navigate=async direction=>{const position=index+direction;if(!placed()||position<0||position>=this.rowCount()||this.pendingQuery)return;dialog._navigating=true;previous.disabled=next.disabled=true;try{await this.focusResult(position,false);if(this.destroyed||this.pendingQuery||gridResultShape(this.acceptedQuery)!==shape)return;const row=this.rowCache.get(position);if(!row)return;if(dialog.isConnected){paint(row.h,position);this.focusRing(title)}else if(retiredForNavigation)await this.openDetails(row.key)}catch(error){if(error.name!=="AbortError")this.emit("error",{error})}
|
|
67
|
+
finally{dialog._navigating=false;if(dialog.isConnected)steps()}};dialog._cxPaint=paint;dialog.addEventListener("keydown",event=>{if(["ArrowUp","ArrowDown"].includes(event.key)&&!event.defaultPrevented&&!event.target.matches('input,textarea,select,[contenteditable],[role=tab]')&&!event.target.closest(".cx-record-nested")){event.preventDefault();navigate(event.key==="ArrowUp"?-1:1)}});const abort=()=>{retiredForNavigation=dialog._navigating;overlay.close("data",false,true)};owner.signal.addEventListener("abort",abort,{once:true});const refreshHooks=()=>DataGrid.refreshDrawerHooks(this,dialog);this.host.addEventListener("canopyx:format",refreshHooks);dialog.addEventListener("close",()=>{lifetime.abort();owner.signal.removeEventListener("abort",abort);this.host.removeEventListener("canopyx:format",refreshHooks);DataGrid.activeDrawers.delete(dialog);cancelAnimationFrame(dialog._cxHooksFrame);paints?.abort();dialog.remove();if(activeRecordDrawer===dialog)activeRecordDrawer=null;if(this.recordDrawer===dialog)this.recordDrawer=null;if(!this.recordDrawer&&!dialog._navigating&&!dialog._replaced&&!dialog._cxHidden&&!this.destroyed)gridRestoreFocus(this,returnFocus,record.id,primary,openedFrom)},{once:true});RECORD_IMPL.decorate?.(this,dialog,{head,identity,title,subtitle,body,options:options||{}});DataGrid.applyDrawerHooks(this,dialog);paint(record,index);if(overlay.open())this.focusRing(title);return dialog};Object.assign(DataGrid.prototype,{paintDrawerBody(row,body,dialog,context){if(RECORD_IMPL.paint&&this.recordNeeded(row))return RECORD_IMPL.paint(this,row,body,dialog,context);body.replaceChildren();const sections=new Map();for(const column of this.columns){if(column.drawer===false)continue;const name=column.section||this.labels.gridDetailsSection;if(!sections.has(name)){const heading=h("div","cx-drawer-s"),list=h("dl","cx-dl");setText(heading,name);sections.set(name,list);body.append(heading,list)}
|
|
65
68
|
const label=h("dt"),value=h("dd");setText(label,column.title);label.setAttribute("data-cx-field",column.id);value.setAttribute("data-cx-field",column.id);this.paintDrawerValue(column,row,value,context);sections.get(name).append(label,value)}},paintDrawerValue(column,row,value,context){const cell=row.cells[column.id],object=isCellObject(cell),presenter=column.presenter||(column.wrap?{kind:"longText"}:null);if(column.render&&column.hostRenderer!==false){try{if(column.render(row,value,{column:column.id,index:this.columns.indexOf(column),signal:context.signal,onDispose:cleanup=>{if(context.signal.aborted)cleanup();else context.signal.addEventListener("abort",cleanup,{once:true})}})===true)return}
|
|
66
69
|
catch(error){this.emit("error",{error})}}
|
|
67
70
|
if(presenter){gridCellRenderer(this,{...column,renderWidth:context.width||260},presenter,true,this.columns.includes(column))(row,value);const rule=columnNumericTone(column,cellValue(cell));if(rule){const label=h("span","p-sub");setText(label,rule.label);value.appendChild(label)}
|
|
68
71
|
return}
|
|
69
72
|
const text=cellText(cell,column,this.fmt),blank=object&&cellValue(cell)==null&&cell.text==="",span=h("span");applyTone(span,"cx-drawer-text"+(text||blank?"":" p-missing"),toneOf(columnValueTone(column,cell)||(object?cell.tone:null)));setText(span,text||blank?text:"—");if(object&&cell.title)span.title=cell.title;value.appendChild(span);const rule=columnNumericTone(column,cellValue(cell));if(rule){span.title=rule.label;const label=h("span","p-sub");setText(label,rule.label);value.appendChild(label)}
|
|
70
|
-
if(object)for(const badge of cell.badges||[])value.appendChild(badgeElement(badge))},drawerFields(dialog=this.recordDrawer){return dialog?[...dialog.querySelectorAll("dd[data-cx-field],.cx-record-block-b[data-cx-field]")].filter(value=>value.closest(".cx-drawer")===dialog).map(value=>{const id=value.getAttribute("data-cx-field");return{id,column:this.columns.find(column=>column.id===id)||null,term:value.previousElementSibling,value}}):[]}});DataGrid.prototype.showReportingText=function(column,text,returnFocus,rowId,mono=false){if(this.destroyed||this.pendingQuery||!this.acceptedQuery)return;this.reportingText?.close();const dialog=h("dialog","cx-host cx-grid-overlay cx-text-dialog cx-reporting-text"),head=h("div","cx-drawer-h"),title=h("h4"),content=h("pre",mono?"p-mono":"");
|
|
73
|
+
if(object)for(const badge of cell.badges||[])value.appendChild(badgeElement(badge))},drawerFields(dialog=this.recordDrawer){return dialog?[...dialog.querySelectorAll("dd[data-cx-field],.cx-record-block-b[data-cx-field]")].filter(value=>value.closest(".cx-drawer")===dialog).map(value=>{const id=value.getAttribute("data-cx-field");return{id,column:this.columns.find(column=>column.id===id)||null,term:value.previousElementSibling,value}}):[]}});DataGrid.prototype.showReportingText=function(column,text,returnFocus,rowId,mono=false,extra){if(this.destroyed||this.pendingQuery||!this.acceptedQuery)return;this.reportingText?._cxOverlay.close("replace",false,true);const dialog=h("dialog","cx-host cx-grid-overlay cx-dialog cx-text-dialog cx-reporting-text"),head=h("div","cx-drawer-h"),title=h("h4"),body=h("div"),content=h("pre",mono?"p-mono":"");for(const name of(this.opts.overlayClass||"").split(/\s+/).filter(Boolean))dialog.classList.add(name);
|
|
74
|
+
dialog.dataset.hfxPart="dialog";head.dataset.hfxPart="header";title.dataset.hfxPart="title";body.dataset.hfxPart="body";title.id=this.id+"-text-title";title.setAttribute("aria-level","2");setText(title,column.title);dialog.setAttribute("aria-labelledby",title.id);const copy=gridDecorateButton(gridButton(this.labels.gridCopy,()=>this.writeClipboard(text).catch(error=>this.emit("error",{error}))),"copy",true);const close=gridDecorateButton(gridButton("",()=>dialog._cxOverlay.close()),"close",true);close.classList.add("icon");close.setAttribute("aria-label",this.labels.gridCloseCell);setText(content,text);content.hidden=!!extra&&!text;copy.hidden=content.hidden;content.tabIndex=0;head.append(title,copy,close);body.append(content);if(extra)body.append(extra);dialog.append(head,body);if(extra?.tagName==="FORM"){extra.id=this.id+"-analyst-form";const footer=h("div");footer.dataset.hfxPart="footer";const cancel=gridButton(this.labels.cancelEdit,()=>dialog._cxOverlay.close());const apply=extra.querySelector('[type="submit"]');apply.setAttribute("form",extra.id);footer.append(cancel,apply);dialog.append(footer)}document.body.appendChild(dialog);this.reportingText=dialog;const lifetime=new AbortController(),overlay=dialog._cxOverlay=UI_IMPL.dialog(dialog,{host:this.host,container:this.host,focus:false},lifetime.signal);const signal=this.dataLifetime.signal,abort=()=>overlay.close("data",false,true);signal.addEventListener("abort",abort,{once:true});dialog.addEventListener("close",()=>{lifetime.abort();signal.removeEventListener("abort",abort);dialog.remove();if(this.reportingText===dialog)this.reportingText=null;if(!this.reportingText&&!signal.aborted)gridRestoreFocus(this,returnFocus,rowId,column)},{once:true});overlay.open();(extra?.querySelector("button,select,input,textarea")||content).focus()};DataGrid.prototype.calculateGridAggregates=async function(columns){const controller=this.statusAggregateController=new AbortController(),signal=controller.signal,owner=this.dataLifetime,abort=()=>controller.abort();owner.signal.addEventListener("abort",abort,{once:true});setText(this.statusAggregates,this.labels.loading);try{const totals=new Map(columns.map(column=>[column.id,{count:0,sum:0,min:Infinity,max:-Infinity}]));let read=0;const selected=this.prepareExport({scope:"selected",columns:columns.map(column=>column.id),signal}).rows();for await(const row of selected){if(++read>50000)throw new Error(this.labels.gridUnknownCount);for(const column of columns){const value=cellValue(row.cells[column.id]);if(typeof value!=="number")continue;const total=totals.get(column.id);total.count++;total.sum+=value;total.min=Math.min(total.min,value);total.max=Math.max(total.max,value)}}
|
|
71
75
|
if(signal.aborted||this.destroyed)return;this.statusAggregates.replaceChildren();for(const column of columns){const total=totals.get(column.id),item=h("span"),number={format:value=>numberText(value,this.lang,column.format)};setText(item,column.title+": "+(total.count?number.format(total.sum):"—"));item.title=fill(this.labels.gridSelectionAggregate,{count:total.count,sum:number.format(total.sum),average:total.count?number.format(total.sum/total.count):"—",minimum:total.count?number.format(total.min):"—",maximum:total.count?number.format(total.max):"—"});this.statusAggregates.appendChild(item);}
|
|
72
76
|
}catch(error){if(!signal.aborted&&!this.destroyed)setText(this.statusAggregates,this.labels.gridNoData)}
|
|
73
77
|
finally{owner.signal.removeEventListener("abort",abort)}};Object.assign(DataGrid.prototype,COLUMNS_MENU,{buildGridFilters:buildFilters});context.GRID_REPORTING?.installFilters?.({gridDateInput});installed.add(context.DataGrid.prototype)}};(global.CanopyXParts||=[]).push(["filter-editor",part])})(typeof window!=="undefined"?window:globalThis);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* The flow-checks part: a button,its state in words with a mark,the host's message and details; the review page's list. */
|
|
2
|
-
.cx-flow-checks{padding-top:var(--cx-size-4px);border-top:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
|
|
2
|
+
.cx-flow-checks{padding-top:var(--cx-size-4px);border-top:var(--cx-size-1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));}
|
|
3
3
|
.cx-flow-step > .cx-flow-checks{margin-top:var(--cx-flow-gap);}
|
|
4
4
|
.cx-flow-check-item{margin-top:var(--cx-size-10px);}
|
|
5
5
|
.cx-flow-check-head{display:flex;flex-wrap:wrap;align-items:center;gap:var(--cx-size-6px) var(--cx-size-12px);}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
.cx-flow-check-message{margin-top:var(--cx-size-4px);font-size:var(--cx-size-13d5px);}
|
|
15
15
|
.cx-flow-check-details{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:var(--cx-size-2px) var(--cx-size-14px);margin-top:var(--cx-size-6px);padding:var(--cx-size-8px) var(--cx-size-10px);border-radius:var(--hfx-radius-sm,4px);background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));font-size:var(--cx-size-13px);}
|
|
16
16
|
.cx-flow-check-details > div{display:contents;}
|
|
17
|
-
.cx-flow-check-details dt{color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
|
|
17
|
+
.cx-flow-check-details dt{color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));}
|
|
18
18
|
.cx-flow-check-details dd{margin:0;overflow-wrap:anywhere;}
|
|
19
19
|
.cx-flow-check-ack{margin-top:var(--cx-size-6px);}
|
|
20
20
|
.cx-flow-review-checks{margin-top:var(--cx-size-20px);}
|
|
@@ -22,5 +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(--
|
|
25
|
+
.cx-flow-check-item[data-cx-state="fail"]{padding:var(--hfx-space-3,0.75rem);border:var(--hfx-border-width,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
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,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:"53394e75b7d1b0e2",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
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
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)))
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/* The flow-command part: the equivalent command with its tabs and Copy. */
|
|
2
|
-
.cx-flow-command{border:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));}
|
|
2
|
+
.cx-flow-command{border:var(--cx-size-1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));}
|
|
3
3
|
.cx-flow-command > summary{padding:var(--cx-size-8px) var(--cx-size-12px);font-weight:600;cursor:pointer;}
|
|
4
|
-
.cx-flow-command[open] > summary{border-bottom:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
|
|
4
|
+
.cx-flow-command[open] > summary{border-bottom:var(--cx-size-1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));}
|
|
5
5
|
.cx-flow-command-tools{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--cx-size-8px);padding:var(--cx-size-8px) var(--cx-size-12px) 0;}
|
|
6
6
|
.cx-flow-tabs{display:flex;flex-wrap:wrap;gap:var(--cx-size-4px);}
|
|
7
7
|
.cx-flow-tab{min-height:var(--cx-size-28px);padding:0 var(--cx-size-10px);border:var(--cx-size-1px) solid transparent;border-radius:var(--hfx-radius-sm,4px);background:transparent;color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));font:inherit;font-size:var(--cx-size-13px);cursor:pointer;}
|
|
8
|
-
.cx-flow-tab[aria-selected="true"]{border-color:var(--hfx-color-border-strong,light-dark(#cdd0d5,#363a42));background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));font-weight:600;}
|
|
8
|
+
.cx-flow-tab[aria-selected="true"]{border-color:var(--hfx-color-border-strong,light-dark(#cdd0d5,#363a42));background:var(--hfx-color-surface-card,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));font-weight:600;}
|
|
9
9
|
.cx-flow-tab:focus-visible,.cx-flow-code:focus-visible,.cx-flow-command > summary:focus-visible{outline:var(--hfx-focus-width,2px) solid var(--hfx-color-focus-ring,light-dark(#02726a,#37c9b8));outline-offset:var(--hfx-focus-offset,2px);}
|
|
10
10
|
.cx-flow-code{margin:var(--cx-size-8px) var(--cx-size-12px) var(--cx-size-12px);padding:var(--cx-size-10px) var(--cx-size-12px);border-radius:var(--hfx-radius-sm,4px);background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));
|
|
11
11
|
font:var(--cx-size-12d5px)/1.5 var(--hfx-font-mono,"Cascadia Mono","Cascadia Code",Consolas,"SFMono-Regular",Menlo,monospace);white-space:pre-wrap;overflow-wrap:anywhere;max-height:var(--cx-size-320px);overflow:auto;}
|
|
@@ -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:"a30245a47f6d4530",requires:["flow"],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={flowCommandTab:"Command",flowPatchTab:"JSON patch",flowCommandTitle:"Equivalent command"};Object.assign(FLOW_LABELS,FLOW_PART_LABELS);const FLOW_PLAIN_CHARACTERS={powershell:"-_./:\\=+%",posix:"-_./:=@%+,",windows:"-_./:\\=@%+,"};const FLOW_COMMAND_STYLES=["powershell","posix","windows"];FLOW_HOST.command={read(raw){flowKeys(raw,["name","style","variants"],"The command");const name=flowString(raw.name,200,"The command name",true),style=raw.style??"powershell";if(!FLOW_COMMAND_STYLES.includes(style)||/[\u0000-\u001f]/.test(name)) flowFail("the command has an unknown style or a control character");
|
|
2
2
|
const variants=raw.variants??[];if(!Array.isArray(variants)||variants.length>8)flowFail("a command has at most 8 variants");const ids=new Set(["command","patch"]);return{name,style,variants:variants.map(variant=>{flowKeys(variant,["id","label"],"A command variant");const id=flowName(variant.id,"A variant id");if(ids.has(id))flowFail("the command variant '"+id+"' is used twice");ids.add(id);return Object.freeze({id,label:flowString(variant.label,60,"A variant label",true)})})}},line:view=>flowCommandLine(view),document(doc,model){if(doc.command!==undefined)model.command=this.read(doc.command)},review(view,section){if(view.model.command)section.appendChild(view.commandPanel())},proposal(view,proposal){if(view.model.command)proposal.command=flowCommandLine(view)}};function flowCommandParameter(name,style){const bare=name.replace(/^[-/]+/, "");
|
|
3
3
|
return style==="posix"?(name.startsWith("-")?name:(bare.length===1?"-":"--")+ bare):style==="windows"?"/"+bare:"-"+bare}
|
|
4
4
|
function flowCommandQuote(value,style){const allowed=FLOW_PLAIN_CHARACTERS[style];let plain=value.length>0;for(let index=0;plain&&index<value.length;index++)plain=/[\p{L}\p{Nd}]/u.test(value[index]) || allowed.includes(value[index]);
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
.cx-flow-launcher{display:contents;}
|
|
4
4
|
.cx-flow-launcher > .cx-flow-launch{height:auto;min-height:var(--cx-size-36px);padding:0 var(--cx-size-16px);}
|
|
5
5
|
.cx-flow-dialog{box-sizing:border-box;width:min(var(--cx-size-640px),calc(var(--cx-size-100vw) - var(--cx-size-32px)));max-height:calc(var(--cx-size-100vh) - var(--cx-size-32px));padding:0;border:0;border-radius:var(--hfx-radius-overlay,var(--hfx-radius-lg,10px));
|
|
6
|
-
background:transparent;color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));overflow:auto;box-shadow:var(--hfx-elevation-3,0 2px 4px rgba(22,24,28,.06),0 16px 36px -16px rgba(22,24,28,.28));}
|
|
6
|
+
background:transparent;color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));overflow:auto;box-shadow:var(--hfx-elevation-3,0 2px 4px rgba(22,24,28,.06),0 16px 36px -16px rgba(22,24,28,.28));}
|
|
7
7
|
.cx-flow-dialog::backdrop{background:var(--hfx-color-overlay,light-dark(rgba(22,24,28,0.42),rgba(0,0,0,0.66)));}
|
|
8
8
|
.cx-flow-dialog.cx-flow-drawer{margin:0 0 0 auto;inset-inline-end:0;inset-inline-start:auto;width:min(var(--cx-size-560px,560px),var(--cx-size-100vw));height:var(--cx-size-100vh);max-height:none;border-radius:var(--hfx-radius-none,0);}
|
|
9
9
|
.cx-flow-dialog.cx-flow-drawer > .cx-flow{min-height:100%;border-radius:var(--hfx-radius-none,0);border-block:0;border-inline-end:0;}
|
|
10
10
|
.cx-flow-head-close{position:relative;padding-inline-end:calc(var(--cx-flow-pad) + var(--cx-size-36px));}
|
|
11
11
|
.cx-flow-close{position:absolute;inset-block-start:var(--cx-size-10px);inset-inline-end:var(--cx-size-10px);border-color:transparent;background:transparent;}
|
|
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));}
|
|
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-surface-line,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(--
|
|
16
|
-
.cx-flow-head-close .cx-flow-close{inset-block-start:var(--
|
|
15
|
+
@media(max-width:639.98px){.cx-flow-dialog .cx-flow{--cx-flow-pad:var(--hfx-space-4,1rem);}}
|
|
16
|
+
.cx-flow-head-close .cx-flow-close{inset-block-start:var(--hfx-space-2,0.5rem);}
|
|
@@ -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:"8c45e0a8bb6a8ab9",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);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/* The flow-drafts part: drafts,presets and the changed marks. */
|
|
2
|
-
.cx-flow-mark-changed{margin-inline-start:var(--cx-size-8px);padding:0 var(--cx-size-6px);border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));border:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));
|
|
2
|
+
.cx-flow-mark-changed{margin-inline-start:var(--cx-size-8px);padding:0 var(--cx-size-6px);border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));border:var(--cx-size-1px) solid var(--hfx-color-surface-line,var(--hfx-color-border,light-dark(#e2e4e7,#272a30)));
|
|
3
3
|
font-size:var(--cx-size-11d5px);font-weight:500;color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));vertical-align:1px;}
|
|
4
4
|
.cx-flow-presets{display:flex;flex-wrap:wrap;align-items:center;gap:var(--cx-size-6px) var(--cx-size-12px);margin-top:var(--cx-size-10px);font-size:var(--cx-size-13d5px);}
|
|
5
5
|
.cx-flow-presets-label{color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));font-weight:600;}
|
|
6
6
|
.cx-flow .cx-flow-preset{width:auto;min-width:var(--cx-size-180px);max-width:var(--cx-size-320px);}
|
|
7
7
|
.cx-flow-preset-name{display:flex;flex-wrap:wrap;gap:var(--cx-size-6px);flex-basis:100%;}
|
|
8
8
|
.cx-flow-preset-name .cx-flow-input{max-width:var(--cx-size-280px);}
|
|
9
|
-
.cx-flow-draft-note{margin-top:var(--cx-size-6px);font-size:var(--cx-size-12px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
|
|
9
|
+
.cx-flow-draft-note{margin-top:var(--cx-size-6px);font-size:var(--cx-size-12px);color:var(--hfx-color-text-secondary,var(--hfx-color-text-muted,light-dark(#626770,#8f949d)));}
|
|
10
10
|
.cx-flow-resume{display:flex;flex-wrap:wrap;align-items:center;gap:var(--cx-size-6px) var(--cx-size-12px);margin:var(--cx-size-12px) var(--cx-flow-pad) 0;padding:var(--cx-size-10px) var(--cx-size-14px);
|
|
11
11
|
border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));border-inline-start:var(--cx-size-3px) solid var(--hfx-color-accent,light-dark(#11776f,#37c9b8));background:var(--hfx-color-accent-subtle,light-dark(#e7f1f1,#1b3435));}
|
|
12
12
|
.cx-flow-resume.cx-flow-resume-stale{border-inline-start-color:var(--hfx-color-status-warn-fg,light-dark(#8c5c05,#eeb640));background:var(--hfx-color-status-warn-bg,light-dark(#f8efde,#3b3322));}
|
|
@@ -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:"fac75bf905a77d0b",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={flowChangedMark:"Changed",flowSaveDraft:"Save draft",flowDraftSaved:"Draft saved",flowDraftFailed:"The draft was not saved.",flowDraftFound:"Saved draft",flowDraftFrom:"You have a draft saved {time}.",flowDraftStale:"The settings changed after this draft was saved.",flowDraftResume:"Resume where you left off",flowDraftRestart:"Start again",flowStartFrom:"Start from",flowPresetSave:"Save as preset",flowPresetNone:"Defaults",flowPresetsSaved:"Saved presets",flowPresetApplied:"Started from {preset}",flowPresetName:"Preset name",flowPresetFailed:"The preset was not saved.",flowPresetSaved:"Saved the preset {preset}",flowPresetChanges:"[one]Based on {preset}, {count} change[other]Based on {preset}, {count} changes",flowPresetCurrent:"Current settings"};Object.assign(FLOW_LABELS,FLOW_PART_LABELS);const FLOW_DRAFT_DELAY=800;function flowPreset(raw,model){flowKeys(raw,["id","label","description","values"],"A preset");const preset={id:flowName(raw.id,"A preset id"),label:flowString(raw.label,200,"A preset label",true),description:flowString(raw.description,1000,"A preset description"),values:{}};if(!flowIs(raw.values))flowFail("preset "+preset.id+" needs an object of values");for(const[id,value]of Object.entries(raw.values)){const field=model.fields.get(id);if(!field||field.type==="secret"||!flowFits(field,value))flowFail("preset "+preset.id+" has no value for '"+id+"' that fits a field");preset.values[id]=value}
|
|
2
2
|
return Object.freeze(preset)}
|
|
3
3
|
function flowMark(view,fv,on){if(on&&!fv.mark){fv.mark=h("span","cx-flow-mark-changed");setText(fv.mark,view.labels.flowChangedMark)}
|
|
4
4
|
if(on&&fv.mark.parentNode!==fv.label)fv.label.appendChild(fv.mark);else if(!on)fv.mark?.remove()}
|