@evotecit/canopyx 0.3.15 → 0.3.18

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 (118) 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 +5 -24
  8. package/CanopyX.Html/Assets/canopyx-calendar.js +14 -19
  9. package/CanopyX.Html/Assets/canopyx-cell-range.js +16 -14
  10. package/CanopyX.Html/Assets/canopyx-changes.css +6 -24
  11. package/CanopyX.Html/Assets/canopyx-changes.js +18 -15
  12. package/CanopyX.Html/Assets/canopyx-compare.css +37 -0
  13. package/CanopyX.Html/Assets/canopyx-compare.js +12 -0
  14. package/CanopyX.Html/Assets/canopyx-data.js +3 -3
  15. package/CanopyX.Html/Assets/canopyx-editing.css +2 -2
  16. package/CanopyX.Html/Assets/canopyx-editing.js +2 -2
  17. package/CanopyX.Html/Assets/canopyx-enhance.js +4 -4
  18. package/CanopyX.Html/Assets/canopyx-export.js +54 -13
  19. package/CanopyX.Html/Assets/canopyx-facets.css +14 -5
  20. package/CanopyX.Html/Assets/canopyx-facets.js +19 -15
  21. package/CanopyX.Html/Assets/canopyx-filter-editor.css +71 -85
  22. package/CanopyX.Html/Assets/canopyx-filter-editor.js +20 -16
  23. package/CanopyX.Html/Assets/canopyx-flow-checks.css +2 -0
  24. package/CanopyX.Html/Assets/canopyx-flow-checks.js +5 -4
  25. package/CanopyX.Html/Assets/canopyx-flow-dialog.css +2 -0
  26. package/CanopyX.Html/Assets/canopyx-flow-dialog.js +1 -1
  27. package/CanopyX.Html/Assets/canopyx-flow-entry.css +136 -12
  28. package/CanopyX.Html/Assets/canopyx-flow-entry.js +5 -5
  29. package/CanopyX.Html/Assets/canopyx-flow-facts.js +2 -0
  30. package/CanopyX.Html/Assets/canopyx-flow-module.mjs +5 -5
  31. package/CanopyX.Html/Assets/canopyx-flow.js +8 -7
  32. package/CanopyX.Html/Assets/canopyx-format-editor.js +2 -2
  33. package/CanopyX.Html/Assets/canopyx-formatting.js +10 -9
  34. package/CanopyX.Html/Assets/canopyx-grid-module.mjs +185 -131
  35. package/CanopyX.Html/Assets/canopyx-grid.css +228 -96
  36. package/CanopyX.Html/Assets/canopyx-grid.js +185 -131
  37. package/CanopyX.Html/Assets/canopyx-grouping.css +22 -15
  38. package/CanopyX.Html/Assets/canopyx-grouping.js +24 -17
  39. package/CanopyX.Html/Assets/canopyx-interactive.css +197 -74
  40. package/CanopyX.Html/Assets/canopyx-interactive.js +38 -45
  41. package/CanopyX.Html/Assets/canopyx-labels-de.js +177 -9
  42. package/CanopyX.Html/Assets/canopyx-labels-es.js +177 -9
  43. package/CanopyX.Html/Assets/canopyx-labels-fr.js +176 -8
  44. package/CanopyX.Html/Assets/canopyx-labels-it.js +176 -8
  45. package/CanopyX.Html/Assets/canopyx-labels-pl.js +176 -8
  46. package/CanopyX.Html/Assets/canopyx-layouts.css +48 -20
  47. package/CanopyX.Html/Assets/canopyx-layouts.js +36 -14
  48. package/CanopyX.Html/Assets/canopyx-link.js +2 -2
  49. package/CanopyX.Html/Assets/canopyx-live.css +1 -3
  50. package/CanopyX.Html/Assets/canopyx-live.js +20 -15
  51. package/CanopyX.Html/Assets/canopyx-matrix.css +1 -8
  52. package/CanopyX.Html/Assets/canopyx-matrix.js +11 -11
  53. package/CanopyX.Html/Assets/canopyx-module.mjs +38 -45
  54. package/CanopyX.Html/Assets/canopyx-office-export.js +2936 -0
  55. package/CanopyX.Html/Assets/canopyx-path.css +45 -0
  56. package/CanopyX.Html/Assets/canopyx-path.js +28 -0
  57. package/CanopyX.Html/Assets/canopyx-pivot.css +75 -0
  58. package/CanopyX.Html/Assets/canopyx-pivot.js +72 -0
  59. package/CanopyX.Html/Assets/canopyx-plan.css +56 -0
  60. package/CanopyX.Html/Assets/canopyx-plan.js +67 -0
  61. package/CanopyX.Html/Assets/canopyx-presenters.js +2 -2
  62. package/CanopyX.Html/Assets/canopyx-record-panel.css +11 -2
  63. package/CanopyX.Html/Assets/canopyx-record-panel.js +18 -12
  64. package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +225 -164
  65. package/CanopyX.Html/Assets/canopyx-reporting.css +240 -107
  66. package/CanopyX.Html/Assets/canopyx-reporting.js +225 -164
  67. package/CanopyX.Html/Assets/canopyx-stack.css +35 -0
  68. package/CanopyX.Html/Assets/canopyx-stack.js +24 -0
  69. package/CanopyX.Html/Assets/canopyx-time-slider.css +18 -0
  70. package/CanopyX.Html/Assets/canopyx-time-slider.js +27 -0
  71. package/CanopyX.Html/Assets/canopyx-timeline.js +6 -5
  72. package/CanopyX.Html/Assets/canopyx-tree-tools.css +36 -35
  73. package/CanopyX.Html/Assets/canopyx-tree-tools.js +15 -12
  74. package/CanopyX.Html/Assets/canopyx-ui-menu.css +41 -0
  75. package/CanopyX.Html/Assets/canopyx-ui-menu.js +64 -0
  76. package/CanopyX.Html/Assets/canopyx-ui-navigation.css +73 -0
  77. package/CanopyX.Html/Assets/canopyx-ui-navigation.js +39 -0
  78. package/CanopyX.Html/Assets/canopyx-ui-overlays.css +79 -0
  79. package/CanopyX.Html/Assets/canopyx-ui-overlays.js +42 -0
  80. package/CanopyX.Html/Assets/canopyx-ui-picker.css +12 -0
  81. package/CanopyX.Html/Assets/canopyx-ui-picker.js +6 -0
  82. package/CanopyX.Html/Assets/canopyx-ui-stepper.css +174 -0
  83. package/CanopyX.Html/Assets/canopyx-ui-stepper.js +48 -0
  84. package/CanopyX.Html/Assets/canopyx-ui-tabs.css +153 -0
  85. package/CanopyX.Html/Assets/canopyx-ui-tabs.js +47 -0
  86. package/CanopyX.Html/Assets/canopyx-values.css +5 -0
  87. package/CanopyX.Html/Assets/canopyx-values.js +13 -0
  88. package/CanopyX.Html/Assets/canopyx-view-intents.css +12 -0
  89. package/CanopyX.Html/Assets/canopyx-view-intents.js +56 -0
  90. package/CanopyX.Html/Assets/canopyx.css +197 -71
  91. package/CanopyX.Html/Assets/canopyx.js +29 -19
  92. package/JavaScript/board.d.ts +30 -0
  93. package/JavaScript/changes.d.ts +4 -1
  94. package/JavaScript/facets.d.ts +5 -3
  95. package/JavaScript/flow.d.ts +6 -0
  96. package/JavaScript/grid.d.ts +153 -17
  97. package/JavaScript/hosts.d.ts +14 -1
  98. package/JavaScript/index.d.ts +4 -2
  99. package/JavaScript/live.d.ts +2 -0
  100. package/JavaScript/locales/de.mjs +177 -9
  101. package/JavaScript/locales/es.mjs +177 -9
  102. package/JavaScript/locales/fr.mjs +176 -8
  103. package/JavaScript/locales/it.mjs +176 -8
  104. package/JavaScript/locales/pl.mjs +176 -8
  105. package/JavaScript/matrix.d.ts +4 -1
  106. package/JavaScript/path.d.ts +33 -0
  107. package/JavaScript/pivot.d.ts +135 -0
  108. package/JavaScript/plan.d.ts +23 -0
  109. package/JavaScript/protocol.d.ts +16 -3
  110. package/JavaScript/records.d.ts +20 -4
  111. package/JavaScript/stack.d.ts +28 -0
  112. package/JavaScript/time-slider.d.ts +58 -0
  113. package/JavaScript/ui.d.ts +261 -0
  114. package/JavaScript/view-intents.d.ts +45 -0
  115. package/README.md +22 -3
  116. package/ThirdParty/OfficeIMO/LICENSE +21 -0
  117. package/ThirdParty/OfficeIMO/README.md +13 -0
  118. package/package.json +76 -3
@@ -36,8 +36,9 @@ body .cx-host.cx-drawer.cx-record-drawer{max-width:var(--cx-size-640px);}
36
36
  .cx-record-section:last-child{border-bottom:0;}
37
37
  .cx-record-section .cx-record-section{border-bottom:0;margin:0 var(--cx-size-16px) var(--cx-size-4px);border-inline-start:var(--cx-size-2px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
38
38
  .cx-record-section-h{margin:0;font:inherit;}
39
- .cx-drawer .cx-record-toggle{width:100%;padding:var(--cx-size-10px) var(--cx-size-16px) var(--cx-size-4px);border-radius:var(--hfx-radius-none,0);font-size:var(--cx-size-11d5px);font-weight:700;letter-spacing:var(--cx-size-d06em);text-transform:uppercase;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
40
- .cx-record-toggle .cx-ico{width:var(--cx-size-14px);height:var(--cx-size-14px);transform:rotate(90deg);transition:transform .12s;}
39
+ .cx-drawer .cx-record-toggle{width:100%;padding:calc(var(--hfx-space-1,0.25rem)*2.5) 0 var(--hfx-space-1,0.25rem);border:0;border-radius:var(--hfx-radius-none,0);font-size:var(--hfx-type-small-size,0.8125rem);font-weight:var(--hfx-weight-semibold,600);letter-spacing:0;text-transform:none;color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));}
40
+ .cx-record-toggle > .cx-record-btn-label{flex:1;min-width:0;text-align:start;order:0;}
41
+ .cx-record-toggle .cx-ico{width:var(--cx-size-14px);height:var(--cx-size-14px);order:1;margin-inline-start:auto;transform:rotate(90deg);transition:transform .12s;}
41
42
  .cx-record-toggle[aria-expanded="false"] .cx-ico{transform:none;}
42
43
  .cx-drawer .cx-record-section .cx-record-section .cx-record-toggle{padding:var(--cx-size-6px) var(--cx-size-10px) var(--cx-size-2px);font-size:var(--cx-size-13px);letter-spacing:0;text-transform:none;color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));}
43
44
  .cx-record-section .cx-record-section .cx-dl{padding:var(--cx-size-4px) var(--cx-size-10px) var(--cx-size-6px);}
@@ -109,3 +110,11 @@ html.cx-record-printing .cx-record-print{display:block;padding:0;font:var(--cx-s
109
110
  }
110
111
  @media (prefers-reduced-motion:reduce){.cx-record-toggle .cx-ico{transition:none;}}
111
112
  @media (forced-colors:active){.cx-record-tab[aria-selected="true"]{border-bottom-color:Highlight;}.cx-timeline-dot{forced-color-adjust:none;background:CanvasText;}}
113
+ .cx-record-footer{flex:none;display:flex;justify-content:flex-end;gap:var(--hfx-space-2,0.5rem);padding:var(--hfx-space-3,0.75rem) var(--hfx-space-4,1rem);border-top:var(--hfx-border-width,1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));}
114
+ .cx-record-footer .cx-record-primary{color:var(--hfx-color-accent-contrast,light-dark(#ffffff,#0c0d10));background:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));border-color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
115
+ .cx-record-footer .cx-record-primary:disabled{color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));border-color:var(--hfx-color-border,light-dark(#e2e4e7,#272a30));cursor:wait;}
116
+ .cx-record-subtitle{margin:var(--hfx-space-1,0.25rem) 0 0;font-size:var(--hfx-type-small-size,0.8125rem);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
117
+ .cx-record-drawer .cx-dl dt{color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font-size:var(--hfx-type-caption-size,0.75rem);font-weight:normal;}
118
+ .cx-record-drawer .cx-dl dd{font-size:var(--hfx-type-body-size,0.875rem);}
119
+ .cx-drawer.cx-record-drawer .cx-drawer-h h4{width:auto;max-width:100%;overflow-wrap:anywhere;}
120
+ .cx-drawer.cx-record-drawer .cx-drawer-h > :not(:first-child){flex:none;margin-inline:0;}
@@ -1,4 +1,5 @@
1
- (function(global){"use strict";const installed=new WeakSet();const part={version:"94adeb844689e329",install(context){if(installed.has(context.RECORD_IMPL))return;const{RECORD_IMPL,TreeGrid,h,setText,fill,cellText,cellValue,isCellObject,formatValue,toneOf,applyTone,toneColors,validateGridRows,badgeElement,loadSidecar,requireIdentifier,PROTOCOL,foldText,createTreeGrid,svgIcon,gridExportField,columnNumericTone,columnValueTone,validateColumnValues}=context;const RECORD_KINDS=["items","fields","records","events","changes"],RECORD_LINK_KEY=/^[A-Za-z][\w.-]{0,31}$/, RECORD_MAX_STRUCTURE_DEPTH = 8;
1
+ (function(global){"use strict";const installed=new WeakSet();const part={version:"2a4059ade4ca1439",requires:["ui-menu"],install(context){if(installed.has(context.RECORD_IMPL))return;const{RECORD_IMPL,UI_IMPL,TreeGrid,h,setText,fill,cellText,cellValue,isCellObject,formatValue,toneOf,applyTone,toneColors,validateGridRows,badgeElement,loadSidecar,requireIdentifier,PROTOCOL,foldText,createTreeGrid,svgIcon,gridExportField,columnNumericTone,columnValueTone,validateColumnValues}=context;function changeCellText(cell,column,fmt){if(cell==null)return "—";const structured=isCellObject(cell)&&["items","fields","records","events","changes"].some(name=>cell[name]);if(isCellObject(cell)&&cellValue(cell)==null&&!cell.text&&!structured)return "null";const text=cellText(cell,column,fmt);return text.length?text:'""'}
2
+ const RECORD_KINDS=["items","fields","records","events","changes"],RECORD_LINK_KEY=/^[A-Za-z][\w.-]{0,31}$/, RECORD_MAX_STRUCTURE_DEPTH = 8;
2
3
  const recordKind=cell=>{const kinds=isCellObject(cell)&&!Array.isArray(cell)?RECORD_KINDS.filter(name=>cell[name]!==undefined):[];if(kinds.length>1)recordFail("a cell carries at most one structured value.");return kinds[0]||null};const recordFail=message=>{throw new Error("CanopyX: "+message)};const recordText=(value,max=256)=>typeof value==="string"&&!!value.trim()&&value.length<=max;const recordGridHelpers=()=>RECORD_IMPL.grid||{};function recordCheckValue(cell,depth=0){if(cell==null)return;if(depth>RECORD_MAX_STRUCTURE_DEPTH)recordFail("structured values nest at most "+RECORD_MAX_STRUCTURE_DEPTH+" levels.");const kind=recordKind(cell);if(kind==="items")for(const item of cell.items||[])recordCheckValue(item,depth+1);if(kind==="fields")for(const field of cell.fields||[])recordCheckValue(field.value,depth+1);if(kind==="changes")for(const change of cell.changes||[]){recordCheckValue(change.before,depth+1);recordCheckValue(change.after,depth+1)}
3
4
  if(kind==="events")for(const event of cell.events||[])for(const change of event.changes||[]){recordCheckValue(change.before,depth+1);recordCheckValue(change.after,depth+1)}
4
5
  if(kind==="records")recordCheckRows(cell.records.rows||cell.records.roots,depth+1)}
@@ -36,7 +37,8 @@ return pack.then(records=>recordPayload(view,id,records.get(id)||null,revision))
36
37
  const request={protocol:PROTOCOL,type:"gridRecordQuery",view:view.view.id,id,...(revision!=null?{revision}:{}),...extra};const run=signal=>Promise.resolve(loader(request,{signal}));return(view.runGridHook?view.runGridHook(run,signal||view.dataLifetime?.signal):run(signal||view.lifetime.signal)).then(doc=>recordPayload(view,id,doc,revision))}
37
38
  function recordEnsure(view,id){const cache=view._recordPayloads||=new Map(),key=recordCacheKey(view,id);let entry=cache.get(key);if(entry)return entry;if(!recordLoader(view))return null;entry={state:"loading"};cache.set(key,entry);if(cache.size>64)cache.delete(cache.keys().next().value);entry.promise=recordFetch(view,id,{}).then(payload=>{entry.state="ready";entry.payload=payload;return payload},error=>{entry.state="error";entry.error=error;if(error.name!=="AbortError")view.emit("error",{error});throw error});entry.promise.catch(()=>{});return entry}
38
39
  const RECORD_ICONS={back:'<path d="m14 7-5 5 5 5"/>',print:'<path d="M7 9V4h10v5M7 17H5v-6h14v6h-2M8 14h8v6H8z"/>',link:'<path d="M10 14a4 4 0 0 0 5.7 0l3-3a4 4 0 0 0-5.7-5.7l-1 1M14 10a4 4 0 0 0-5.7 0l-3 3a4 4 0 0 0 5.7 5.7l1-1"/>',more:'<circle cx="5" cy="12" r="1.2"/><circle cx="12" cy="12" r="1.2"/><circle cx="19" cy="12" r="1.2"/>',open:'<path d="M14 5h5v5M19 5l-8 8M17 14v5H5V7h5"/>',chevron:'<path d="m9 6 6 6-6 6"/>'};function recordIcon(name){return svgIcon(RECORD_ICONS[name])}
39
- function recordButton(text,run,className,icon){const button=h("button","cx-record-btn" +(className?" "+className:""));button.type="button";if(icon)button.appendChild(recordIcon(icon));if(text)button.appendChild(document.createTextNode(text));button.addEventListener("click",event=>{event.stopPropagation();run(event)});return button}
40
+ function recordButton(text,run,className,icon){const button=h("button","cx-record-btn" +(className?" "+className:""));button.type="button";if(icon)button.appendChild(recordIcon(icon));if(text){const label=h("span","cx-record-btn-label");setText(label,text);button.appendChild(label)}
41
+ button.addEventListener("click",event=>{event.stopPropagation();run(event)});return button}
40
42
  const recordCount=(ctx,count)=>formatValue(count,"number",ctx.fmt);const recordRefValid=ref=>!!ref&&typeof ref==="object"&&typeof ref.id==="string"&&!!ref.id&&(ref.view===undefined||typeof ref.view==="string"&&!!ref.view);function recordPlain(ctx,field,cell,element){const text=cellText(cell,field.column||field,ctx.fmt),object=isCellObject(cell),blank=object&&cellValue(cell)==null&&cell.text==="",span=h("span");const column=field.column||field,rule=columnNumericTone(column,cellValue(cell));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;element.appendChild(span);if(rule){span.title=rule.label;const label=h("span","p-sub");setText(label,rule.label);element.appendChild(label)}
41
43
  if(object)for(const badge of cell.badges||[])element.appendChild(badgeElement(badge))}
42
44
  function recordLink(ctx,cell,field,element,className){const text=cellText(cell,field,ctx.fmt)||cell.ref.id;if(ctx.print||!recordRefValid(cell.ref)){recordPlain(ctx,field,cell,element);return null}
@@ -93,7 +95,8 @@ function recordTokens(ctx,field,items,other,cell,mark,word){const keys=new Set(o
93
95
  box.appendChild(chip)}
94
96
  cell.appendChild(box)}
95
97
  function recordChanges(ctx,field,changes,element,compact){const table=h("table","cx-record-diff" +(compact?" cx-record-diff-compact":"")),caption=h("caption","cx-sr-only"),head=h("tr"),body=h("tbody"),labels=ctx.labels;setText(caption,fill(labels.recordChanged,{count:recordCount(ctx,changes.length)}));for(const text of[labels.recordField,labels.recordBefore,labels.recordAfter]){const cell=h("th");cell.scope="col";setText(cell,text);head.appendChild(cell)}
96
- for(const change of changes){if(!change||!recordText(change.name,4096))recordFail("a change names its field.");const line=h("tr"),name=h("th"),before=h("td","cx-diff-before"),after=h("td","cx-diff-after"),spec={id:field.id,title:change.name,kind:change.kind||"text",nested:true};name.scope="row";setText(name,change.name);if(recordKind(change.before)==="items"&&recordKind(change.after)==="items"){recordTokens(ctx,spec,change.before.items,change.after.items,before,"cx-diff-removed",labels.recordRemoved);recordTokens(ctx,spec,change.after.items,change.before.items,after,"cx-diff-added",labels.recordAdded)}else{recordValue(ctx,spec,change.before??null,before,1);recordValue(ctx,spec,change.after??null,after,1)}
98
+ for(const change of changes){if(!change||!recordText(change.name,4096))recordFail("a change names its field.");const line=h("tr"),name=h("th"),before=h("td","cx-diff-before"),after=h("td","cx-diff-after"),spec={id:field.id,title:change.name,kind:change.kind||"text",nested:true};name.scope="row";setText(name,change.name);if(recordKind(change.before)==="items"&&recordKind(change.after)==="items"){recordTokens(ctx,spec,change.before.items,change.after.items,before,"cx-diff-removed",labels.recordRemoved);recordTokens(ctx,spec,change.after.items,change.before.items,after,"cx-diff-added",labels.recordAdded)}else{const paint=(value,element)=>recordValue(ctx,spec,recordKind(value)?value:
99
+ {...(isCellObject(value)?value:{value}),text:changeCellText(value,spec,ctx.fmt)},element,1);paint(change.before,before);paint(change.after,after)}
97
100
  line.append(name,before,after);body.appendChild(line)}
98
101
  const thead=h("thead");thead.appendChild(head);table.append(caption,thead,body);element.appendChild(table)}
99
102
  let RECORD_SHOW_EMPTY=false;const recordId=(dialog,kind,id)=>dialog.id+"-"+kind+"-"+String(id).replace(/[^\w-]/g, "_");
@@ -135,9 +138,9 @@ return api.openRecord(ref.id,{stack:[...state.stack,entry].slice(-20),returnFocu
135
138
  .then(()=>recordRetire(dialog),error=>{recordAnnounce(dialog,fill(ctx.labels.recordUnavailable,{id:ref.id}));view.emit("error",{error})})}
136
139
  function recordBack(view,dialog,steps=1){const stack=dialog._cxPanel?.stack||[],entry=stack[stack.length-steps],api=entry&&recordApi(entry.view);if(!api)return;api.openRecord(entry.id,{stack:stack.slice(0,stack.length-steps),tab:entry.tab,origin:entry.origin,back:true,returnFocus:dialog._returnFocus})
137
140
  .then(()=>recordRetire(dialog),error=>{recordAnnounce(dialog,fill(view.labels.recordUnavailable,{id:entry.id}));view.emit("error",{error})})}
138
- function recordRetire(dialog){if(dialog.isConnected&&dialog.open&&document.querySelectorAll("dialog.cx-drawer[open]").length>1){dialog._replaced=true;dialog.close();dialog.remove()}}
139
- RECORD_IMPL.open=async(view,id,options={})=>{requireIdentifier(id,"record ID");if(view.destroyed)recordFail("the view was destroyed.");await view.ready;const dialog=view.kind==="tree"?await recordOpenNode(view,id,options):await recordOpenRow(view,id,options);if(!dialog)return;const origin=options.origin&&dialog.querySelector('[data-cx-origin="'+CSS.escape(options.origin)+ '"]');if(origin)origin.focus({preventScroll:false});if(options.stack)recordAnnounce(dialog,fill(options.back?view.labels.recordBackTo:view.labels.recordShowing,{record:recordTitle(dialog)}))};async function recordOpenRow(view,id,options){await view.requirePart("filter-editor");let index=null,row=null;const loaded=[...view.rowCache.values()].find(item=>!item.status&&item.key===id);if(loaded){row=loaded.h;index=loaded._ri;if(!view.pendingQuery)await view.focusResult(index,false).catch(()=>{})}
140
- else if(view.acceptedQuery&&!view.pendingQuery&&typeof view.source.position==="function"){const position=await view.runGridHook(signal=>view.source.position(view.acceptedQuery,id,{signal}));if(Number.isInteger(position)&&position>=0&&position<view.rowCount()){await view.focusResult(position,false);const item=view.rowCache.get(position);if(item&&!item.status&&item.key===id){row=item.h;index=position}}}
141
+ function recordRetire(dialog){if(dialog.isConnected&&dialog.open&&document.querySelectorAll("dialog.cx-drawer[open]").length>1){dialog._replaced=true;dialog._cxOverlay.close("replace",false,true);dialog.remove()}}
142
+ RECORD_IMPL.open=async(view,id,options={})=>{requireIdentifier(id,"record ID");if(view.destroyed)recordFail("the view was destroyed.");await view.ready;if(options.reload===true)RECORD_IMPL.invalidate(view,id);const dialog=view.kind==="tree"?await recordOpenNode(view,id,options):await recordOpenRow(view,id,options);if(!dialog)return;const origin=options.origin&&dialog.querySelector('[data-cx-origin="'+CSS.escape(options.origin)+ '"]');if(origin)origin.focus({preventScroll:false});if(options.stack)recordAnnounce(dialog,fill(options.back?view.labels.recordBackTo:view.labels.recordShowing,{record:recordTitle(dialog)}))};async function recordOpenRow(view,id,options){await view.requirePart("filter-editor");let index=null,row=view.board?.rows.find(row=>row.id===id)||view.path?.rows.find(row=>row.id===id)||view.stack?.settings.records.get(id)||null;const loaded=[...view.rowCache.values()].find(item=>!item.status&&item.key===id);if(loaded){row=loaded.h;index=loaded._ri;if(!view.grid.hidden&&!view.pendingQuery)await view.focusResult(index,false).catch(()=>{})}
143
+ else if(!row&&view.acceptedQuery&&!view.pendingQuery&&typeof view.source.position==="function"){const position=await view.runGridHook(signal=>view.source.position(view.acceptedQuery,id,{signal}));if(Number.isInteger(position)&&position>=0&&position<view.rowCount()){await view.focusResult(position,false);const item=view.rowCache.get(position);if(item&&!item.status&&item.key===id){row=item.h;index=position}}}
141
144
  if(!row&&typeof view.source.row==="function")row=view.source.row(id);if(!row&&recordLoader(view)){const key=recordCacheKey(view,id);const payload=await recordFetch(view,id,{row:true});if(payload?.row){row=payload.row;(view._recordPayloads||=new Map()).set(key,{state:"ready",payload,promise:Promise.resolve(payload)})}}
142
145
  if(!row)recordFail("record "+id+" is not available.");const returnFocus=options.returnFocus||document.activeElement;if(typeof view.opts.onDetails==="function"){const record=recordGridHelpers().gridFreeze(JSON.parse(JSON.stringify(row)));await view.runGridHook(signal=>view.opts.onDetails({row:record,query:view.acceptedQuery,signal,returnFocus}));return null}
143
146
  return view.openGridDrawer(row,index,returnFocus,options)}
@@ -155,13 +158,16 @@ view._recordLinkOpen=record?recordLinkPath(recordLinkRead(view)||[]):null}
155
158
  RECORD_IMPL.start=view=>{if(view._recordStarted||!view.view.record?.deepLink)return;view._recordStarted=true;const read=()=>{const ids=recordLinkRead(view),key=ids?recordLinkPath(ids):null,owner=view._recordLinkOwner?.dialog;if(!ids){view._recordLinkOpen=null;view._recordLinkOwner=null;return}
156
159
  if(key===view._recordLinkOpen&&(!owner||owner.open||owner._replaced))return;view._recordLinkOwner=null;view._recordLinkOpen=key;RECORD_IMPL.open(view,ids[ids.length-1],{path:ids}).catch(error=>view.emit("error",{error}))};global.addEventListener("hashchange",read,{signal:view.lifetime.signal});view.lifetime.signal.addEventListener("abort",()=>{view._recordLinkOwner=null;view._recordLinkOpen=null},{once:true});Promise.resolve(view.ready).then(read,()=>{})};RECORD_IMPL.decorate=(view,dialog,{head,identity,options})=>{if(!view.view.record)return;try{recordSpec(view)}catch(error){return}
157
160
  dialog.id||=view.id+"-record";dialog.classList.add("cx-record-drawer");const state=dialog._cxPanel={stack:Array.isArray(options.stack)?options.stack:[],tab:options.tab||null,collapsed:new Map()},labels=view.labels;const live=h("div","cx-record-live cx-sr-only");live.setAttribute("aria-live","polite");dialog.appendChild(live);if(state.stack.length){const trail=h("nav","cx-record-trail"),crumbs=h("ol","cx-record-crumbs"),last=state.stack[state.stack.length-1];trail.setAttribute("aria-label",labels.recordTrail);const back=recordButton(labels.recordBack,()=>recordBack(view,dialog),"cx-record-back","back");back.setAttribute("aria-label",fill(labels.recordBackTo,{record:last.title||last.id}));state.stack.slice(-3).forEach((entry,at,list)=>{const item=h("li");item.appendChild(recordButton(entry.title||entry.id,()=>recordBack(view,dialog,list.length-at),"cx-record-crumb"));crumbs.appendChild(item)});trail.append(back,crumbs);identity.prepend(trail)}
158
- const summary=h("div","cx-record-summary");summary.hidden=true;head.after(summary);recordActionsMenu(view,dialog,identity);dialog.addEventListener("keydown",event=>{if(event.altKey&&event.key==="ArrowLeft"&&state.stack.length){event.preventDefault();recordBack(view,dialog)}});dialog.addEventListener("close",()=>{if(view.destroyed)return;const owner=view._recordLinkOwner;if(owner?.dialog!==dialog)return;if(dialog._replaced){view._recordLinkOwner=null;return}
159
- const ids=recordLinkRead(view);if(ids&&owner.link===recordLinkPrefix(view)+ recordLinkPath(ids))recordLinkWrite(view,null);view._recordLinkOwner=null;view._recordLinkOpen=null},{once:true})};function recordActionsMenu(view,dialog,identity){const spec=recordSpec(view),switches=spec.actions||{},labels=view.labels,items=[];const add=(label,task)=>items.push({label,task});if(switches.link!==false&&spec.deepLink)add(labels.recordCopyLink,()=>recordCopy(view,dialog,recordAddress(view,dialog._cxRecord)));if(switches.copy!==false){add(labels.recordCopyValues,()=>recordCopy(view,dialog,recordExport(view,dialog,"text")));add(labels.recordCopyJson,()=>recordCopy(view,dialog,recordExport(view,dialog,"json")))}
161
+ const summary=h("div","cx-record-summary");summary.hidden=true;head.after(summary);let projectedSubtitle;if(typeof view.opts.recordHeading==="function")dialog.addEventListener("cx-drawer-paint",()=>{if(projectedSubtitle){setText(projectedSubtitle,"");projectedSubtitle.hidden=true}
162
+ try{const heading=view.opts.recordHeading(Object.freeze(JSON.parse(JSON.stringify(dialog._cxRecord))));if(heading&&typeof heading.title==="string"&&heading.title.length<=512)setText(identity.querySelector("h4"),heading.title);if(heading&&typeof heading.subtitle==="string"&&heading.subtitle.length<=2000){let subtitle=identity.querySelector("p");if(!subtitle){subtitle=projectedSubtitle=h("p");identity.appendChild(subtitle)}
163
+ subtitle.classList.add("cx-record-subtitle");setText(subtitle,heading.subtitle);subtitle.hidden=!heading.subtitle}}catch(error){view.emit("error",{error})}});recordActionsMenu(view,dialog,identity);dialog.addEventListener("keydown",event=>{if(event.altKey&&event.key==="ArrowLeft"&&state.stack.length){event.preventDefault();recordBack(view,dialog)}});dialog.addEventListener("close",()=>{if(view.destroyed)return;const owner=view._recordLinkOwner;if(owner?.dialog!==dialog)return;if(dialog._replaced){view._recordLinkOwner=null;return}
164
+ const ids=recordLinkRead(view);if(ids&&owner.link===recordLinkPrefix(view)+ recordLinkPath(ids))recordLinkWrite(view,null);view._recordLinkOwner=null;view._recordLinkOpen=null},{once:true})};function recordActionsMenu(view,dialog,identity){dialog.querySelector(".cx-record-footer")?.remove();const spec=recordSpec(view),switches=spec.actions||{},labels=view.labels,items=[];const failed=error=>{recordAnnounce(dialog,error?.message??String(error));view.emit("error",{error})};const add=(label,task,prominent=false,visible=()=>true,disabled=false)=>{let running=false,button;const run=async()=>{if(running||disabled||!visible())return;running=true;if(button)button.disabled=true;try{return await task()}
165
+ finally{running=false;if(button)button.disabled=disabled}};const item={label,task:run,visible,disabled,primary:typeof prominent==="function"?prominent:()=>prominent===true};items.push(item);if(prominent){let footer=dialog.querySelector(".cx-record-footer");if(!footer){footer=h("footer","cx-record-footer");dialog.appendChild(footer)}
166
+ button=recordButton(label,()=>{Promise.resolve().then(run).catch(failed)},"cx-record-btn cx-record-primary");button.disabled=disabled;item.footer=button;footer.appendChild(button)}};if(switches.link!==false&&spec.deepLink)add(labels.recordCopyLink,()=>recordCopy(view,dialog,recordAddress(view,dialog._cxRecord)));if(switches.copy!==false){add(labels.recordCopyValues,()=>recordCopy(view,dialog,recordExport(view,dialog,"text")));add(labels.recordCopyJson,()=>recordCopy(view,dialog,recordExport(view,dialog,"json")))}
160
167
  if(switches.export!==false){add(labels.recordExportCsv,()=>recordDownload(view,dialog,"csv"));add(labels.recordExportJson,()=>recordDownload(view,dialog,"json"))}
161
- if(switches.print!==false)add(labels.recordPrint,()=>recordPrint(view,dialog));for(const action of[...(Array.isArray(view.opts.recordActions)?view.opts.recordActions:[]),...view.plugins.flatMap(item=>item.recordActions||[])]){if(!action||typeof action.label!=="string"||typeof action.run!=="function")continue;add(action.label,()=>{const record=dialog._cxRecord,entry=recordEntry(view,record.id);return action.run(Object.freeze({record:JSON.parse(JSON.stringify(record)),view:view.view.id,api:view.host.canopyx,payload:entry?.payload||null,signal:view.lifetime.signal}))})}
162
- if(!items.length)return;const menu=h("div","cx-record-menu"),toggle=recordButton("",()=>show(list.hidden),"cx-record-menu-btn","more"),list=h("div","cx-record-menu-list");list.id=dialog.id+"-actions";list.setAttribute("role","menu");list.setAttribute("aria-label",labels.recordActions);list.hidden=true;toggle.setAttribute("aria-label",labels.recordActions);toggle.title=labels.recordActions;toggle.setAttribute("aria-haspopup","menu");toggle.setAttribute("aria-expanded","false");toggle.setAttribute("aria-controls",list.id);const show=open=>{list.hidden=!open;toggle.setAttribute("aria-expanded",String(open));if(open)buttons[0].focus()};const buttons=items.map(item=>{const button=recordButton(item.label,()=>{show(false);toggle.focus();Promise.resolve().then(item.task).catch(error=>{recordAnnounce(dialog,error.message);view.emit("error",{error})})},"cx-record-menu-item");button.setAttribute("role","menuitem");button.tabIndex=-1;return button});list.append(...buttons);menu.append(toggle,list);identity.after(menu);menu.addEventListener("keydown",event=>{if(list.hidden)return;if(event.key==="Escape"){event.preventDefault();event.stopPropagation();show(false);toggle.focus();return}
163
- if(event.key==="Tab"){show(false);return}
164
- const at=buttons.indexOf(document.activeElement);if(at<0||!["ArrowDown","ArrowUp","Home","End"].includes(event.key))return;event.preventDefault();event.stopPropagation();buttons[{ArrowDown:(at+1)%buttons.length,ArrowUp:(at-1+buttons.length)%buttons.length,Home:0,End:buttons.length-1}[event.key]].focus()});menu.addEventListener("focusout",event=>{if(!menu.contains(event.relatedTarget)&&event.relatedTarget)show(false)});dialog.addEventListener("pointerdown",event=>{if(!menu.contains(event.target))show(false)})}
168
+ if(switches.print!==false)add(labels.recordPrint,()=>recordPrint(view,dialog));for(const action of[...(Array.isArray(view.opts.recordActions)?view.opts.recordActions:[]),...view.plugins.flatMap(item=>item.recordActions||[])]){if(!action||typeof action.label!=="string"||typeof action.run!=="function")continue;const context=()=>{const record=dialog._cxRecord,entry=record&&recordEntry(view,record.id);return Object.freeze({record:record?JSON.parse(JSON.stringify(record)):{id:""},view:view.view.id,api:view.host.canopyx,payload:entry?.state==="ready"?JSON.parse(JSON.stringify(entry.payload)):null,signal:view.lifetime.signal})};const condition=(value,fallback)=>{if(typeof value!=="function")return value===undefined?fallback:value===true;try{return value(context())===true}catch(error){failed(error);return false}};add(action.label,()=>action.run(context()),()=>condition(action.prominent,false),()=>condition(action.visible,true),action.disabled===true)}
169
+ if(!items.length)return;const menu=h("div","cx-record-menu"),toggle=h("button","cx-record-btn cx-record-menu-btn"),list=h("div","cx-menu"),actions=new Map();toggle.type="button";toggle.appendChild(recordIcon("more"));list.id=dialog.id+"-actions";list.setAttribute("role","menu");list.setAttribute("aria-label",labels.recordActions);list.hidden=true;toggle.setAttribute("aria-label",labels.recordActions);toggle.title=labels.recordActions;for(const item of items){const button=h("button","cx-record-btn cx-record-menu-item");button.type="button";setText(button,item.label);button.setAttribute("role","menuitem");button.disabled=item.disabled;button.dataset.itemId=String(actions.size);actions.set(button.dataset.itemId,item.task);item.button=button}
170
+ menu.append(toggle,list);identity.after(menu);const controller=UI_IMPL.menu(list,{host:view.host,trigger:toggle,label:labels.recordActions,placement:"bottom-end",onSelect:item=>Promise.resolve().then(actions.get(item.id)).catch(failed)});dialog.addEventListener("close",()=>controller.destroy(),{once:true});const paint=()=>{const shown=items.filter(item=>item.visible());for(const item of items)if(item.footer)item.footer.hidden=!shown.includes(item)||!item.primary();list.replaceChildren(...shown.map(item=>item.button));controller.refresh();menu.hidden=!shown.length;const footer=dialog.querySelector(".cx-record-footer");if(footer)footer.hidden=!items.some(item=>item.footer&&!item.footer.hidden);if(menu.hidden)controller.close("hidden",false,true)};dialog.addEventListener("cx-drawer-paint",paint);paint()}
165
171
  async function recordCopy(view,dialog,text){if(!global.navigator.clipboard?.writeText)recordFail("the clipboard is not available.");await global.navigator.clipboard.writeText(text);recordAnnounce(dialog,view.labels.recordCopied)}
166
172
  function recordFlat(cell,field,fmt){const kind=recordKind(cell),text=(value,spec=field)=>recordFlat(value,spec,fmt);if(kind==="items")return cell.items.map(item=>text(item)).join(", ");if(kind==="fields")return cell.fields.map(entry=>entry.name+": "+text(entry.value,{kind:entry.kind||"text"})).join("; ");if(kind==="records")return(cell.records.rows||cell.records.roots||[]).map(row=>cell.records.columns.map(column=>text(row.cells?.[column.id]??null,column)).filter(Boolean).join(" · ")).join("\n");if(kind==="events")return cell.events.map(event=>[event.time?formatValue(event.time,"datetime",fmt):"",event.kind,event.actor,event.summary].filter(Boolean).join(" · ")).join("\n");if(kind==="changes")return cell.changes.map(change=>change.name+": "+text(change.before??null)+ " → "+text(change.after??null)).join("\n");return cellText(cell,field.column||field,fmt)}
167
173
  function recordData(view,dialog){const record=dialog._cxRecord,entry=recordEntry(view,record.id),payload=entry?.state==="ready"?entry.payload:null;const fields=recordFields(view),layout=recordLayout(view,fields),items=[],seen=new Set();const walk=(sections,path)=>{for(const section of sections){const name=path?path+" / "+section.label:section.label;for(const field of section.fields)if(!seen.has(field.id)){seen.add(field.id);items.push({section:name,field,cell:recordCell(view,record,payload,field)})}