@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.
Files changed (150) hide show
  1. package/CanopyX.Html/Assets/canopyx-board.css +50 -0
  2. package/CanopyX.Html/Assets/canopyx-board.js +39 -0
  3. package/CanopyX.Html/Assets/canopyx-buckets.js +15 -0
  4. package/CanopyX.Html/Assets/canopyx-calculations.css +7 -0
  5. package/CanopyX.Html/Assets/canopyx-calculations.js +52 -0
  6. package/CanopyX.Html/Assets/canopyx-calendar-edit.js +3 -3
  7. package/CanopyX.Html/Assets/canopyx-calendar.css +74 -80
  8. package/CanopyX.Html/Assets/canopyx-calendar.js +26 -31
  9. package/CanopyX.Html/Assets/canopyx-cell-range.css +4 -4
  10. package/CanopyX.Html/Assets/canopyx-cell-range.js +16 -14
  11. package/CanopyX.Html/Assets/canopyx-changes.css +61 -79
  12. package/CanopyX.Html/Assets/canopyx-changes.js +18 -15
  13. package/CanopyX.Html/Assets/canopyx-column-groups.css +5 -1
  14. package/CanopyX.Html/Assets/canopyx-column-groups.js +15 -9
  15. package/CanopyX.Html/Assets/canopyx-compare.css +37 -0
  16. package/CanopyX.Html/Assets/canopyx-compare.js +12 -0
  17. package/CanopyX.Html/Assets/canopyx-data.js +3 -3
  18. package/CanopyX.Html/Assets/canopyx-detail-rows.css +4 -4
  19. package/CanopyX.Html/Assets/canopyx-detail-rows.js +1 -1
  20. package/CanopyX.Html/Assets/canopyx-editing.css +5 -5
  21. package/CanopyX.Html/Assets/canopyx-editing.js +2 -2
  22. package/CanopyX.Html/Assets/canopyx-enhance.js +5 -5
  23. package/CanopyX.Html/Assets/canopyx-export.js +54 -13
  24. package/CanopyX.Html/Assets/canopyx-facets.css +32 -22
  25. package/CanopyX.Html/Assets/canopyx-facets.js +19 -15
  26. package/CanopyX.Html/Assets/canopyx-filter-editor.css +75 -89
  27. package/CanopyX.Html/Assets/canopyx-filter-editor.js +20 -16
  28. package/CanopyX.Html/Assets/canopyx-flow-checks.css +3 -3
  29. package/CanopyX.Html/Assets/canopyx-flow-checks.js +1 -1
  30. package/CanopyX.Html/Assets/canopyx-flow-command.css +3 -3
  31. package/CanopyX.Html/Assets/canopyx-flow-command.js +1 -1
  32. package/CanopyX.Html/Assets/canopyx-flow-dialog.css +4 -4
  33. package/CanopyX.Html/Assets/canopyx-flow-dialog.js +1 -1
  34. package/CanopyX.Html/Assets/canopyx-flow-drafts.css +2 -2
  35. package/CanopyX.Html/Assets/canopyx-flow-drafts.js +1 -1
  36. package/CanopyX.Html/Assets/canopyx-flow-entry.css +142 -17
  37. package/CanopyX.Html/Assets/canopyx-flow-entry.js +5 -5
  38. package/CanopyX.Html/Assets/canopyx-flow-host.css +2 -2
  39. package/CanopyX.Html/Assets/canopyx-flow-host.js +1 -1
  40. package/CanopyX.Html/Assets/canopyx-flow-module.mjs +5 -5
  41. package/CanopyX.Html/Assets/canopyx-flow-pick.css +4 -4
  42. package/CanopyX.Html/Assets/canopyx-flow-pick.js +1 -1
  43. package/CanopyX.Html/Assets/canopyx-flow-preview.css +1 -1
  44. package/CanopyX.Html/Assets/canopyx-flow-preview.js +1 -1
  45. package/CanopyX.Html/Assets/canopyx-flow-records.css +2 -2
  46. package/CanopyX.Html/Assets/canopyx-flow-records.js +1 -1
  47. package/CanopyX.Html/Assets/canopyx-flow-tasks.css +4 -4
  48. package/CanopyX.Html/Assets/canopyx-flow-tasks.js +1 -1
  49. package/CanopyX.Html/Assets/canopyx-flow.css +41 -41
  50. package/CanopyX.Html/Assets/canopyx-flow.js +1 -1
  51. package/CanopyX.Html/Assets/canopyx-format-editor.css +9 -9
  52. package/CanopyX.Html/Assets/canopyx-format-editor.js +2 -2
  53. package/CanopyX.Html/Assets/canopyx-formatting.css +13 -13
  54. package/CanopyX.Html/Assets/canopyx-formatting.js +12 -11
  55. package/CanopyX.Html/Assets/canopyx-forms.css +3 -3
  56. package/CanopyX.Html/Assets/canopyx-forms.js +1 -1
  57. package/CanopyX.Html/Assets/canopyx-grid-module.mjs +220 -155
  58. package/CanopyX.Html/Assets/canopyx-grid-options.css +8 -8
  59. package/CanopyX.Html/Assets/canopyx-grid-options.js +9 -2
  60. package/CanopyX.Html/Assets/canopyx-grid.css +285 -150
  61. package/CanopyX.Html/Assets/canopyx-grid.js +220 -155
  62. package/CanopyX.Html/Assets/canopyx-grouping.css +23 -16
  63. package/CanopyX.Html/Assets/canopyx-grouping.js +24 -17
  64. package/CanopyX.Html/Assets/canopyx-highlight.css +10 -10
  65. package/CanopyX.Html/Assets/canopyx-highlight.js +1 -1
  66. package/CanopyX.Html/Assets/canopyx-interactive.css +215 -91
  67. package/CanopyX.Html/Assets/canopyx-interactive.js +47 -52
  68. package/CanopyX.Html/Assets/canopyx-labels-de.js +177 -9
  69. package/CanopyX.Html/Assets/canopyx-labels-es.js +177 -9
  70. package/CanopyX.Html/Assets/canopyx-labels-fr.js +176 -8
  71. package/CanopyX.Html/Assets/canopyx-labels-it.js +176 -8
  72. package/CanopyX.Html/Assets/canopyx-labels-pl.js +176 -8
  73. package/CanopyX.Html/Assets/canopyx-layouts.css +49 -21
  74. package/CanopyX.Html/Assets/canopyx-layouts.js +36 -14
  75. package/CanopyX.Html/Assets/canopyx-link.css +3 -3
  76. package/CanopyX.Html/Assets/canopyx-link.js +4 -4
  77. package/CanopyX.Html/Assets/canopyx-links.js +2 -2
  78. package/CanopyX.Html/Assets/canopyx-live.css +3 -5
  79. package/CanopyX.Html/Assets/canopyx-live.js +3 -3
  80. package/CanopyX.Html/Assets/canopyx-matrix.css +32 -39
  81. package/CanopyX.Html/Assets/canopyx-matrix.js +11 -11
  82. package/CanopyX.Html/Assets/canopyx-module.mjs +47 -52
  83. package/CanopyX.Html/Assets/canopyx-office-export.js +2936 -0
  84. package/CanopyX.Html/Assets/canopyx-pager.css +1 -1
  85. package/CanopyX.Html/Assets/canopyx-pager.js +1 -1
  86. package/CanopyX.Html/Assets/canopyx-path.css +45 -0
  87. package/CanopyX.Html/Assets/canopyx-path.js +28 -0
  88. package/CanopyX.Html/Assets/canopyx-pivot.css +75 -0
  89. package/CanopyX.Html/Assets/canopyx-pivot.js +72 -0
  90. package/CanopyX.Html/Assets/canopyx-plan.css +63 -0
  91. package/CanopyX.Html/Assets/canopyx-plan.js +71 -0
  92. package/CanopyX.Html/Assets/canopyx-presenters.js +2 -2
  93. package/CanopyX.Html/Assets/canopyx-record-panel.css +51 -45
  94. package/CanopyX.Html/Assets/canopyx-record-panel.js +30 -22
  95. package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +262 -197
  96. package/CanopyX.Html/Assets/canopyx-reporting.css +300 -164
  97. package/CanopyX.Html/Assets/canopyx-reporting.js +262 -197
  98. package/CanopyX.Html/Assets/canopyx-stack.css +35 -0
  99. package/CanopyX.Html/Assets/canopyx-stack.js +24 -0
  100. package/CanopyX.Html/Assets/canopyx-time-slider.css +18 -0
  101. package/CanopyX.Html/Assets/canopyx-time-slider.js +27 -0
  102. package/CanopyX.Html/Assets/canopyx-timeline.css +19 -19
  103. package/CanopyX.Html/Assets/canopyx-timeline.js +6 -5
  104. package/CanopyX.Html/Assets/canopyx-tree-tools.css +47 -46
  105. package/CanopyX.Html/Assets/canopyx-tree-tools.js +15 -12
  106. package/CanopyX.Html/Assets/canopyx-ui-menu.css +41 -0
  107. package/CanopyX.Html/Assets/canopyx-ui-menu.js +64 -0
  108. package/CanopyX.Html/Assets/canopyx-ui-navigation.css +73 -0
  109. package/CanopyX.Html/Assets/canopyx-ui-navigation.js +39 -0
  110. package/CanopyX.Html/Assets/canopyx-ui-overlays.css +79 -0
  111. package/CanopyX.Html/Assets/canopyx-ui-overlays.js +45 -0
  112. package/CanopyX.Html/Assets/canopyx-ui-picker.css +12 -0
  113. package/CanopyX.Html/Assets/canopyx-ui-picker.js +6 -0
  114. package/CanopyX.Html/Assets/canopyx-ui-stepper.css +174 -0
  115. package/CanopyX.Html/Assets/canopyx-ui-stepper.js +48 -0
  116. package/CanopyX.Html/Assets/canopyx-ui-tabs.css +153 -0
  117. package/CanopyX.Html/Assets/canopyx-ui-tabs.js +47 -0
  118. package/CanopyX.Html/Assets/canopyx-values.css +5 -0
  119. package/CanopyX.Html/Assets/canopyx-values.js +13 -0
  120. package/CanopyX.Html/Assets/canopyx-view-intents.css +12 -0
  121. package/CanopyX.Html/Assets/canopyx-view-intents.js +56 -0
  122. package/CanopyX.Html/Assets/canopyx.css +212 -85
  123. package/CanopyX.Html/Assets/canopyx.js +38 -26
  124. package/JavaScript/board.d.ts +30 -0
  125. package/JavaScript/changes.d.ts +4 -1
  126. package/JavaScript/column-groups.d.ts +24 -4
  127. package/JavaScript/facets.d.ts +5 -3
  128. package/JavaScript/grid.d.ts +161 -17
  129. package/JavaScript/hosts.d.ts +16 -1
  130. package/JavaScript/index.d.ts +4 -2
  131. package/JavaScript/locales/de.mjs +177 -9
  132. package/JavaScript/locales/es.mjs +177 -9
  133. package/JavaScript/locales/fr.mjs +176 -8
  134. package/JavaScript/locales/it.mjs +176 -8
  135. package/JavaScript/locales/pl.mjs +176 -8
  136. package/JavaScript/matrix.d.ts +4 -1
  137. package/JavaScript/path.d.ts +33 -0
  138. package/JavaScript/pivot.d.ts +135 -0
  139. package/JavaScript/plan.d.ts +23 -0
  140. package/JavaScript/protocol.d.ts +18 -3
  141. package/JavaScript/records.d.ts +4 -0
  142. package/JavaScript/stack.d.ts +28 -0
  143. package/JavaScript/time-slider.d.ts +58 -0
  144. package/JavaScript/ui.d.ts +261 -0
  145. package/JavaScript/view-intents.d.ts +45 -0
  146. package/README.md +76 -187
  147. package/README.nuget.md +63 -87
  148. package/ThirdParty/OfficeIMO/LICENSE +21 -0
  149. package/ThirdParty/OfficeIMO/README.md +13 -0
  150. package/package.json +76 -3
@@ -1,8 +1,8 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"e0db9c3f94866fa2",requires:["presenters"],install(context){if(installed.has(context.DataGrid.prototype))return;const{DataGrid,h,setText,gridButton,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);
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(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}
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()})};function gridMenuFocus(panel,event){const items=[...panel.querySelectorAll('[role="menuitem"]')].filter(item=>!item.disabled),index=items.indexOf(document.activeElement);if(!items.length)return;let next;if(["ArrowDown","ArrowUp","Home","End"].includes(event.key))next=event.key==="Home"?0:event.key==="End"?items.length-1:(index+(event.key==="ArrowDown"?1:-1)+items.length)%items.length;else if(event.key.length===1&&!event.ctrlKey&&!event.metaKey&&!event.altKey){const now=performance.now();panel._typeAhead=now-(panel._typeAt||0)>700?event.key:panel._typeAhead+event.key;panel._typeAt=now;const matches=items.map((_,i)=>(index+i+1)%items.length);next=matches.find(i=>foldText(items[i].textContent.trim()).startsWith(foldText(panel._typeAhead)))}else return;if(next===undefined)return;event.preventDefault();items.forEach((item,i)=>item.tabIndex=i===next?0:-1);items[next].focus({preventScroll:true})}
59
- Object.assign(DataGrid.prototype,{openGridPopover(anchor,className,title,columnId){this.closeGridPopover(false);const panel=h("div","cx-host cx-grid-overlay cx-pop "+className),controller=new AbortController(),signal=controller.signal;gridOverlayTheme(this,panel);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);announceMenu(panel);const pressed=new Set();let positionPending=false,releaseFrame=0;const position=()=>{if(signal.aborted)return;if(pressed.size||releaseFrame){positionPending=true;return}
60
- positionPending=false;const current=this.headCells.find(cell=>cell.dataset.cxColumn===columnId)||(anchor.checkVisibility()?anchor:this.grid),bounds=current.getBoundingClientRect();if(panel.classList.toggle("cx-phone",this.host.clientWidth<=640)){panel.style.left="0";panel.style.top="auto";panel.style.bottom="0";panel.style.width="100%";panel.style.maxHeight="80vh"}
61
- else{panel.style.width="";panel.style.bottom="auto";panel.style.maxHeight=Math.min(500,global.innerHeight-16)+"px";panel.style.left=Math.max(8,Math.min(bounds.left,global.innerWidth-panel.offsetWidth-8))+"px";panel.style.top=Math.max(8,Math.min(bounds.bottom,global.innerHeight-panel.offsetHeight-8))+"px"}};this.gridPopover={panel,controller,anchor,columnId,position};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});panel.addEventListener("keydown",event=>{if(event.key==="Escape"){event.preventDefault();event.stopPropagation();this.closeGridPopover()}else gridMenuFocus(panel,event)},{signal});this.lifetime.signal.addEventListener("abort",()=>controller.abort(),{once:true,signal});signal.addEventListener("abort",()=>{global.cancelAnimationFrame(releaseFrame);pressed.clear();panel.remove()},{once:true});queueMicrotask(()=>{if(signal.aborted)return;position();if(!panel.contains(document.activeElement))panel.focus({preventScroll:true})});return panel},openColumnMenu(id,anchor){const column=this.columns.find(item=>item.id===id),panel=this.openGridPopover(anchor,"cx-column-menu",fill(this.labels.gridColumnMenu,{column:column.title}),id);const menu=h("div");menu.setAttribute("role","menu");menu.setAttribute("aria-label",panel.getAttribute("aria-label"));panel.appendChild(menu);const icons=new Map([[this.labels.gridSortAscending,"up"],[this.labels.gridSortDescending,"down"],[this.labels.gridFilterColumn,"filter"],[this.labels.gridPinLeft,"pin"],[this.labels.gridPinRight,"pin"],[this.labels.gridFitContent,"fit"],[this.labels.gridHideColumn,"hide"]]);const paths={pin:'<path d="M9 4h6l-1 6 3 3H7l3-3zM12 13v7"/>',fit:'<path d="M4 12h16M7 9l-3 3 3 3M17 9l3 3-3 3M4 5v14M20 5v14"/>',hide:'<path d="M3 3l18 18M10.6 6.1A9.8 9.8 0 0 1 12 6c5 0 8.5 4.5 9 6-.3.8-1.2 2.3-2.6 3.6M6.4 7.6C4.6 8.9 3.4 10.8 3 12c.5 1.5 4 6 9 6 1.6 0 3-.4 4.3-1.1"/>'};const add=(label,action,disabled=false)=>{const button=gridButton(label,()=>{this.closeGridPopover(false);Promise.resolve().then(action).catch(error=>this.emit("error",{error}))});const icon=h("span","ico"),name=icons.get(label);if(name){icon.appendChild(gridIcon(name,paths[name]))}button.prepend(icon);button.classList.add("cx-mi");button.setAttribute("role","menuitem");button.tabIndex=-1;button.disabled=disabled;menu.appendChild(button)};const sort=direction=>this.setQuery(gridQueryStart(this.queryForChange(true),{sort:[...(this.queryForChange().sort||[]).filter(item=>item.column!==id),...direction?[{column:id,direction}]:[]]}));add(this.labels.gridSortAscending,()=>sort("asc"),!column.sortable||this.view.reporting?.grouping?.column===id);add(this.labels.gridSortDescending,()=>sort("desc"),!column.sortable||this.view.reporting?.grouping?.column===id);add(this.labels.gridClearSort,()=>sort(null),!(this.getQuery()?.sort||[]).some(item=>item.column===id));menu.appendChild(h("hr","cx-menu-rule"));add(this.labels.gridFilterColumn,()=>this.openColumnFilter(id,this.headRow.querySelector('[data-cx-column-menu="'+CSS.escape(id)+'"]')||anchor),column.filterable===false);menu.appendChild(h("hr","cx-menu-rule"));for(const[pin,label]of[["left","gridPinLeft"],["right","gridPinRight"],["none","gridUnpin"]])add(this.labels[label],()=>this.setColumnPinned(id,pin));menu.appendChild(h("hr","cx-menu-rule"));add(this.labels.gridFitContent,()=>this.autoFitColumn(id),!this.acceptedQuery||!!this.pendingQuery);add(this.labels.gridFitAllColumns,()=>this.autoFitColumns(),!this.acceptedQuery||!!this.pendingQuery);add(this.labels.gridHideColumn,()=>this.setColumnVisible(id,false),this.columns.filter(item=>!item.hidden).length===1);const first=panel.querySelector('[role="menuitem"]:not(:disabled)');if(first){first.tabIndex=0;first.focus()}}});let activeRecordDrawer;DataGrid.prototype.openGridDrawer=function(record,index,returnFocus,options){if(activeRecordDrawer?.contains(returnFocus))returnFocus=activeRecordDrawer._returnFocus;if(activeRecordDrawer){activeRecordDrawer._replaced=true;activeRecordDrawer.close();activeRecordDrawer.remove()}
62
- 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;gridOverlayTheme(this,dialog);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.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 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})}
63
- finally{dialog._navigating=false;if(dialog.isConnected)steps()}};dialog._cxPaint=paint;dialog.addEventListener("keydown",event=>{if(event.key==="Escape"&&!event.defaultPrevented){event.preventDefault();dialog.close()}
64
- else 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;dialog.close()};owner.signal.addEventListener("abort",abort,{once:true});const refreshHooks=()=>DataGrid.refreshDrawerHooks(this,dialog);this.host.addEventListener("canopyx:format",refreshHooks);dialog.addEventListener("close",()=>{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&&!this.destroyed)gridRestoreFocus(this,returnFocus,record.id,primary)},{once:true});RECORD_IMPL.decorate?.(this,dialog,{head,identity,title,subtitle,body,options:options||{}});DataGrid.applyDrawerHooks(this,dialog);paint(record,index);const phone=this.host.clientWidth<=640;dialog.classList.toggle("cx-phone",phone);if(phone)dialog.showModal();else dialog.show();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)}
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":"");gridOverlayTheme(this,dialog);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.close()),"close",true);close.classList.add("icon");close.setAttribute("aria-label",this.labels.gridCloseCell);setText(content,text);content.tabIndex=0;head.append(title,copy,close);dialog.append(head,content);document.body.appendChild(dialog);this.reportingText=dialog;const signal=this.dataLifetime.signal,abort=()=>dialog.close();signal.addEventListener("abort",abort,{once:true});dialog.addEventListener("keydown",event=>{if(event.key!=="Tab"||event.altKey||event.ctrlKey||event.metaKey)return;const controls=[content,copy,close],index=controls.indexOf(document.activeElement);event.preventDefault();controls[(index+(event.shiftKey?-1:1)+controls.length)%controls.length].focus({preventScroll:true})});dialog.addEventListener("close",()=>{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});dialog.showModal();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)}}
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(--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));}
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:"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)}
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:"a6c75cf736c93444",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");
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(--cx-size-16px);}}
16
- .cx-flow-head-close .cx-flow-close{inset-block-start:var(--cx-size-8px);}
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:"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}
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:"40dc8e50169fa271",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}
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()}