@evotecit/canopyx 0.3.16 → 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.
- package/CanopyX.Html/Assets/canopyx-board.css +50 -0
- package/CanopyX.Html/Assets/canopyx-board.js +39 -0
- package/CanopyX.Html/Assets/canopyx-buckets.js +15 -0
- package/CanopyX.Html/Assets/canopyx-calculations.css +7 -0
- package/CanopyX.Html/Assets/canopyx-calculations.js +52 -0
- package/CanopyX.Html/Assets/canopyx-calendar-edit.js +3 -3
- package/CanopyX.Html/Assets/canopyx-calendar.css +5 -24
- package/CanopyX.Html/Assets/canopyx-calendar.js +14 -19
- package/CanopyX.Html/Assets/canopyx-cell-range.js +16 -14
- package/CanopyX.Html/Assets/canopyx-changes.css +6 -24
- package/CanopyX.Html/Assets/canopyx-changes.js +18 -15
- package/CanopyX.Html/Assets/canopyx-compare.css +37 -0
- package/CanopyX.Html/Assets/canopyx-compare.js +12 -0
- package/CanopyX.Html/Assets/canopyx-data.js +3 -3
- package/CanopyX.Html/Assets/canopyx-editing.css +2 -2
- package/CanopyX.Html/Assets/canopyx-editing.js +2 -2
- package/CanopyX.Html/Assets/canopyx-enhance.js +4 -4
- package/CanopyX.Html/Assets/canopyx-export.js +54 -13
- package/CanopyX.Html/Assets/canopyx-facets.css +14 -5
- package/CanopyX.Html/Assets/canopyx-facets.js +19 -15
- package/CanopyX.Html/Assets/canopyx-filter-editor.css +71 -85
- package/CanopyX.Html/Assets/canopyx-filter-editor.js +20 -16
- package/CanopyX.Html/Assets/canopyx-flow-checks.css +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-checks.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-dialog.css +2 -2
- package/CanopyX.Html/Assets/canopyx-flow-dialog.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-entry.css +136 -12
- package/CanopyX.Html/Assets/canopyx-flow-entry.js +2 -2
- package/CanopyX.Html/Assets/canopyx-flow-module.mjs +2 -2
- package/CanopyX.Html/Assets/canopyx-format-editor.js +2 -2
- package/CanopyX.Html/Assets/canopyx-formatting.js +10 -9
- package/CanopyX.Html/Assets/canopyx-grid-module.mjs +182 -128
- package/CanopyX.Html/Assets/canopyx-grid.css +228 -96
- package/CanopyX.Html/Assets/canopyx-grid.js +182 -128
- package/CanopyX.Html/Assets/canopyx-grouping.css +22 -15
- package/CanopyX.Html/Assets/canopyx-grouping.js +24 -17
- package/CanopyX.Html/Assets/canopyx-interactive.css +197 -74
- package/CanopyX.Html/Assets/canopyx-interactive.js +38 -45
- package/CanopyX.Html/Assets/canopyx-labels-de.js +177 -9
- package/CanopyX.Html/Assets/canopyx-labels-es.js +177 -9
- package/CanopyX.Html/Assets/canopyx-labels-fr.js +176 -8
- package/CanopyX.Html/Assets/canopyx-labels-it.js +176 -8
- package/CanopyX.Html/Assets/canopyx-labels-pl.js +176 -8
- package/CanopyX.Html/Assets/canopyx-layouts.css +48 -20
- package/CanopyX.Html/Assets/canopyx-layouts.js +36 -14
- package/CanopyX.Html/Assets/canopyx-link.js +2 -2
- package/CanopyX.Html/Assets/canopyx-live.css +1 -3
- package/CanopyX.Html/Assets/canopyx-live.js +3 -3
- package/CanopyX.Html/Assets/canopyx-matrix.css +1 -8
- package/CanopyX.Html/Assets/canopyx-matrix.js +11 -11
- package/CanopyX.Html/Assets/canopyx-module.mjs +38 -45
- package/CanopyX.Html/Assets/canopyx-office-export.js +2936 -0
- package/CanopyX.Html/Assets/canopyx-path.css +45 -0
- package/CanopyX.Html/Assets/canopyx-path.js +28 -0
- package/CanopyX.Html/Assets/canopyx-pivot.css +75 -0
- package/CanopyX.Html/Assets/canopyx-pivot.js +72 -0
- package/CanopyX.Html/Assets/canopyx-plan.css +56 -0
- package/CanopyX.Html/Assets/canopyx-plan.js +67 -0
- package/CanopyX.Html/Assets/canopyx-presenters.js +2 -2
- package/CanopyX.Html/Assets/canopyx-record-panel.css +8 -7
- package/CanopyX.Html/Assets/canopyx-record-panel.js +15 -14
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +222 -161
- package/CanopyX.Html/Assets/canopyx-reporting.css +240 -107
- package/CanopyX.Html/Assets/canopyx-reporting.js +222 -161
- package/CanopyX.Html/Assets/canopyx-stack.css +35 -0
- package/CanopyX.Html/Assets/canopyx-stack.js +24 -0
- package/CanopyX.Html/Assets/canopyx-time-slider.css +18 -0
- package/CanopyX.Html/Assets/canopyx-time-slider.js +27 -0
- package/CanopyX.Html/Assets/canopyx-timeline.js +6 -5
- package/CanopyX.Html/Assets/canopyx-tree-tools.css +36 -35
- package/CanopyX.Html/Assets/canopyx-tree-tools.js +15 -12
- package/CanopyX.Html/Assets/canopyx-ui-menu.css +41 -0
- package/CanopyX.Html/Assets/canopyx-ui-menu.js +64 -0
- package/CanopyX.Html/Assets/canopyx-ui-navigation.css +73 -0
- package/CanopyX.Html/Assets/canopyx-ui-navigation.js +39 -0
- package/CanopyX.Html/Assets/canopyx-ui-overlays.css +79 -0
- package/CanopyX.Html/Assets/canopyx-ui-overlays.js +42 -0
- package/CanopyX.Html/Assets/canopyx-ui-picker.css +12 -0
- package/CanopyX.Html/Assets/canopyx-ui-picker.js +6 -0
- package/CanopyX.Html/Assets/canopyx-ui-stepper.css +174 -0
- package/CanopyX.Html/Assets/canopyx-ui-stepper.js +48 -0
- package/CanopyX.Html/Assets/canopyx-ui-tabs.css +153 -0
- package/CanopyX.Html/Assets/canopyx-ui-tabs.js +47 -0
- package/CanopyX.Html/Assets/canopyx-values.css +5 -0
- package/CanopyX.Html/Assets/canopyx-values.js +13 -0
- package/CanopyX.Html/Assets/canopyx-view-intents.css +12 -0
- package/CanopyX.Html/Assets/canopyx-view-intents.js +56 -0
- package/CanopyX.Html/Assets/canopyx.css +197 -71
- package/CanopyX.Html/Assets/canopyx.js +29 -19
- package/JavaScript/board.d.ts +30 -0
- package/JavaScript/changes.d.ts +4 -1
- package/JavaScript/facets.d.ts +5 -3
- package/JavaScript/grid.d.ts +150 -16
- package/JavaScript/hosts.d.ts +14 -1
- package/JavaScript/index.d.ts +4 -2
- package/JavaScript/locales/de.mjs +177 -9
- package/JavaScript/locales/es.mjs +177 -9
- package/JavaScript/locales/fr.mjs +176 -8
- package/JavaScript/locales/it.mjs +176 -8
- package/JavaScript/locales/pl.mjs +176 -8
- package/JavaScript/matrix.d.ts +4 -1
- package/JavaScript/path.d.ts +33 -0
- package/JavaScript/pivot.d.ts +135 -0
- package/JavaScript/plan.d.ts +23 -0
- package/JavaScript/protocol.d.ts +16 -3
- package/JavaScript/records.d.ts +2 -0
- package/JavaScript/stack.d.ts +28 -0
- package/JavaScript/time-slider.d.ts +58 -0
- package/JavaScript/ui.d.ts +261 -0
- package/JavaScript/view-intents.d.ts +45 -0
- package/README.md +22 -3
- package/ThirdParty/OfficeIMO/LICENSE +21 -0
- package/ThirdParty/OfficeIMO/README.md +13 -0
- 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:
|
|
40
|
-
.cx-record-toggle .cx-
|
|
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,11 +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;}}
|
|
112
|
-
.cx-record-footer{flex:none;display:flex;justify-content:flex-end;gap:var(--
|
|
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));}
|
|
113
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));}
|
|
114
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;}
|
|
115
|
-
.cx-record-subtitle{margin:var(--
|
|
116
|
-
.cx-record-drawer .cx-dl dt{color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));font-size:var(--
|
|
117
|
-
.cx-record-drawer .cx-dl dd{font-size:var(--
|
|
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);}
|
|
118
119
|
.cx-drawer.cx-record-drawer .cx-drawer-h h4{width:auto;max-width:100%;overflow-wrap:anywhere;}
|
|
119
|
-
.cx-drawer.cx-record-drawer .cx-drawer-h > :not(:first-child){flex:none;}
|
|
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:"
|
|
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)
|
|
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{
|
|
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;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=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)}
|
|
@@ -158,15 +161,13 @@ dialog.id||=view.id+"-record";dialog.classList.add("cx-record-drawer");const sta
|
|
|
158
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}
|
|
159
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)}
|
|
160
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}
|
|
161
|
-
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)=>{let running=false,button;const run=async()=>{if(running||!visible())return;running=true;if(button)button.disabled=true;try{return await task()}
|
|
162
|
-
finally{running=false;if(button)button.disabled=
|
|
163
|
-
button=recordButton(label,()=>{Promise.resolve().then(run).catch(failed)},"cx-record-btn cx-record-primary");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")))}
|
|
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")))}
|
|
164
167
|
if(switches.export!==false){add(labels.recordExportCsv,()=>recordDownload(view,dialog,"csv"));add(labels.recordExportJson,()=>recordDownload(view,dialog,"json"))}
|
|
165
|
-
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))}
|
|
166
|
-
if(!items.length)return;const menu=h("div","cx-record-menu"),toggle=
|
|
167
|
-
|
|
168
|
-
const visible=buttons.filter(button=>!button.hidden),at=visible.indexOf(document.activeElement);if(at<0||!["ArrowDown","ArrowUp","Home","End"].includes(event.key))return;event.preventDefault();event.stopPropagation();visible[{ArrowDown:(at+1)%visible.length,ArrowUp:(at-1+visible.length)%visible.length,Home:0,End:visible.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)});const paint=()=>{for(const item of items){const visible=item.visible();item.button.hidden=!visible;if(item.footer)item.footer.hidden=!visible||!item.primary()}
|
|
169
|
-
menu.hidden=!items.some(item=>!item.button.hidden);const footer=dialog.querySelector(".cx-record-footer");if(footer)footer.hidden=!items.some(item=>item.footer&&!item.footer.hidden);if(menu.hidden)show(false)};dialog.addEventListener("cx-drawer-paint",paint);paint()}
|
|
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()}
|
|
170
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)}
|
|
171
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)}
|
|
172
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)})}
|