@evotecit/canopyx 0.3.13 → 0.3.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CanopyX.Html/Assets/canopyx-calendar-edit.js +36 -18
- package/CanopyX.Html/Assets/canopyx-calendar-ics.js +7 -5
- package/CanopyX.Html/Assets/canopyx-calendar.css +124 -116
- package/CanopyX.Html/Assets/canopyx-calendar.js +74 -54
- package/CanopyX.Html/Assets/canopyx-cell-range.css +8 -8
- package/CanopyX.Html/Assets/canopyx-cell-range.js +1 -1
- package/CanopyX.Html/Assets/canopyx-changes.css +113 -113
- package/CanopyX.Html/Assets/canopyx-changes.js +7 -10
- package/CanopyX.Html/Assets/canopyx-column-groups.css +5 -5
- package/CanopyX.Html/Assets/canopyx-column-groups.js +1 -1
- package/CanopyX.Html/Assets/canopyx-data.js +2 -2
- package/CanopyX.Html/Assets/canopyx-detail-rows.css +9 -9
- package/CanopyX.Html/Assets/canopyx-detail-rows.js +2 -2
- package/CanopyX.Html/Assets/canopyx-editing.css +18 -18
- package/CanopyX.Html/Assets/canopyx-editing.js +1 -1
- package/CanopyX.Html/Assets/canopyx-enhance.js +2 -2
- package/CanopyX.Html/Assets/canopyx-facets.css +33 -33
- package/CanopyX.Html/Assets/canopyx-facets.js +5 -6
- package/CanopyX.Html/Assets/canopyx-filter-editor.css +57 -57
- package/CanopyX.Html/Assets/canopyx-filter-editor.js +7 -5
- package/CanopyX.Html/Assets/canopyx-flow-checks.css +13 -11
- package/CanopyX.Html/Assets/canopyx-flow-checks.js +5 -4
- package/CanopyX.Html/Assets/canopyx-flow-command.css +7 -7
- package/CanopyX.Html/Assets/canopyx-flow-command.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-dialog.css +9 -7
- package/CanopyX.Html/Assets/canopyx-flow-dialog.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-drafts.css +7 -7
- package/CanopyX.Html/Assets/canopyx-flow-drafts.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-entry.css +17 -76
- package/CanopyX.Html/Assets/canopyx-flow-entry.js +11 -5
- package/CanopyX.Html/Assets/canopyx-flow-facts.js +2 -0
- package/CanopyX.Html/Assets/canopyx-flow-host.css +4 -4
- package/CanopyX.Html/Assets/canopyx-flow-host.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-module.mjs +11 -5
- package/CanopyX.Html/Assets/canopyx-flow-pick.css +4 -4
- package/CanopyX.Html/Assets/canopyx-flow-pick.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-preview.css +6 -6
- package/CanopyX.Html/Assets/canopyx-flow-preview.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-records.css +3 -3
- package/CanopyX.Html/Assets/canopyx-flow-records.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow-tasks.css +17 -17
- package/CanopyX.Html/Assets/canopyx-flow-tasks.js +1 -1
- package/CanopyX.Html/Assets/canopyx-flow.css +79 -79
- package/CanopyX.Html/Assets/canopyx-flow.js +8 -7
- package/CanopyX.Html/Assets/canopyx-format-editor.css +23 -23
- package/CanopyX.Html/Assets/canopyx-format-editor.js +2 -3
- package/CanopyX.Html/Assets/canopyx-formatting.css +17 -17
- package/CanopyX.Html/Assets/canopyx-formatting.js +5 -5
- package/CanopyX.Html/Assets/canopyx-forms.css +5 -5
- package/CanopyX.Html/Assets/canopyx-forms.js +1 -1
- package/CanopyX.Html/Assets/canopyx-grid-module.mjs +97 -54
- package/CanopyX.Html/Assets/canopyx-grid-options.css +10 -0
- package/CanopyX.Html/Assets/canopyx-grid-options.js +47 -0
- package/CanopyX.Html/Assets/canopyx-grid.css +199 -261
- package/CanopyX.Html/Assets/canopyx-grid.js +97 -54
- package/CanopyX.Html/Assets/canopyx-grouping.css +17 -17
- package/CanopyX.Html/Assets/canopyx-grouping.js +12 -9
- package/CanopyX.Html/Assets/canopyx-highlight.css +14 -14
- package/CanopyX.Html/Assets/canopyx-highlight.js +2 -2
- package/CanopyX.Html/Assets/canopyx-interactive.css +94 -155
- package/CanopyX.Html/Assets/canopyx-interactive.js +33 -14
- package/CanopyX.Html/Assets/canopyx-labels-de.js +5 -0
- package/CanopyX.Html/Assets/canopyx-labels-es.js +5 -0
- package/CanopyX.Html/Assets/canopyx-labels-fr.js +5 -0
- package/CanopyX.Html/Assets/canopyx-labels-it.js +5 -0
- package/CanopyX.Html/Assets/canopyx-labels-pl.js +5 -0
- package/CanopyX.Html/Assets/canopyx-layouts.css +17 -17
- package/CanopyX.Html/Assets/canopyx-layouts.js +2 -10
- package/CanopyX.Html/Assets/canopyx-link.css +7 -7
- package/CanopyX.Html/Assets/canopyx-link.js +1 -1
- package/CanopyX.Html/Assets/canopyx-live.css +9 -9
- package/CanopyX.Html/Assets/canopyx-live.js +20 -15
- package/CanopyX.Html/Assets/canopyx-matrix.css +74 -74
- package/CanopyX.Html/Assets/canopyx-matrix.js +3 -4
- package/CanopyX.Html/Assets/canopyx-module.mjs +33 -14
- package/CanopyX.Html/Assets/canopyx-pager.css +2 -2
- package/CanopyX.Html/Assets/canopyx-pager.js +1 -1
- package/CanopyX.Html/Assets/canopyx-presenters.js +2 -2
- package/CanopyX.Html/Assets/canopyx-record-panel.css +57 -49
- package/CanopyX.Html/Assets/canopyx-record-panel.js +13 -8
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +101 -57
- package/CanopyX.Html/Assets/canopyx-reporting.css +214 -276
- package/CanopyX.Html/Assets/canopyx-reporting.js +101 -57
- package/CanopyX.Html/Assets/canopyx-timeline.css +28 -28
- package/CanopyX.Html/Assets/canopyx-timeline.js +11 -10
- package/CanopyX.Html/Assets/canopyx-tree-tools.css +47 -47
- package/CanopyX.Html/Assets/canopyx-tree-tools.js +3 -3
- package/CanopyX.Html/Assets/canopyx.css +81 -142
- package/CanopyX.Html/Assets/canopyx.js +33 -14
- package/JavaScript/calendar.d.ts +15 -0
- package/JavaScript/flow.d.ts +6 -0
- package/JavaScript/grid.d.ts +29 -4
- package/JavaScript/live.d.ts +2 -0
- package/JavaScript/locales/de.mjs +5 -0
- package/JavaScript/locales/es.mjs +5 -0
- package/JavaScript/locales/fr.mjs +5 -0
- package/JavaScript/locales/it.mjs +5 -0
- package/JavaScript/locales/pl.mjs +5 -0
- package/JavaScript/plugins.d.ts +4 -0
- package/JavaScript/protocol.d.ts +1 -1
- package/JavaScript/records.d.ts +18 -4
- package/README.md +6 -2
- package/package.json +5 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(global){"use strict";const installed=new WeakSet();const part={version:"
|
|
1
|
+
(function(global){"use strict";const installed=new WeakSet();const part={version:"82aa828bc880087b",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;
|
|
2
2
|
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
3
|
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
4
|
if(kind==="records")recordCheckRows(cell.records.rows||cell.records.roots,depth+1)}
|
|
@@ -72,7 +72,7 @@ function recordCollection(ctx,field,list,element){if(!list||typeof list!=="objec
|
|
|
72
72
|
fill(labels.recordCount,{shown:recordCount(ctx,rows.length),total:recordCount(ctx,total)}));if(total>5||total>rows.length||ctx.print)head.appendChild(count);if(!ctx.print&&list.target?.view){const openAll=recordButton(labels.recordOpenAll,()=>recordOpenAll(ctx,field,list).catch(error=>ctx.view.emit("error",{error})),"cx-record-open-all","open");openAll.disabled=!recordCanOpenAll(list);head.appendChild(openAll)}
|
|
73
73
|
const body=h("div","cx-record-collection-b");if(head.firstChild)block.appendChild(head);block.appendChild(body);if(ctx.print)recordTable(ctx,list,body);else if(ctx.phone&&!list.roots)recordCards(ctx,field,list,body);else recordNested(ctx,field,list,body);if(!ctx.print&&!list.roots&&rows.length<total&&recordLoader(ctx.view)){const more=recordButton(labels.recordLoadMore,()=>recordMore(ctx,field,list,more),"cx-record-load-more");block.appendChild(more)}
|
|
74
74
|
element.appendChild(block)}
|
|
75
|
-
function recordNested(ctx,field,list,body){const grid=recordGridHelpers(),host=h("div","cx-host cx-record-nested"),rows=list.rows,tree=!!list.roots||!grid.createDataGrid;
|
|
75
|
+
function recordNested(ctx,field,list,body){const grid=recordGridHelpers(),host=h("div","cx-host cx-record-nested"),rows=list.rows,tree=!!list.roots||!grid.createDataGrid;const columns=list.columns.map(column=>({kind:"text",sortable:true,...column})),id="cx-record-" + ++recordNestedSeq;const byKey=new Map(rows.map((row,at)=>["r"+String(at).padStart(6,"0"),row]));const open=item=>{const row=byKey.get(item.id)||item,ref=recordRowRef(list,row);if(ref)ctx.navigate(ref,host)};let api;if(tree){const roots=list.roots||rows.map(row=>({id:row.id,label:recordRowTitle(list,row,ctx.fmt),cells:row.cells}));host.classList.add("cx-record-nested-tree");api=createTreeGrid(host,{view:{protocol:PROTOCOL,type:"view",id,label:field.title,columns,source:{kind:"inline"},roots,rowHeight:30},labels:ctx.view.opts.labels,toolbar:false,onDetails:({node})=>open(node)})}else{const length=Math.min(Math.max(list.pageLength||10,1),100),paged=rows.length>length;api=grid.createDataGrid(host,{view:{protocol:PROTOCOL,type:"grid",id,label:field.title,rowHeight:30,pageSize:Math.min(10000,Math.max(rows.length,1)),selection:"none",search:rows.length>8,columns,source:{kind:"inline"},rows:[...byKey].map(([key,row])=>({...row,id:key})),toolbar:{filters:false,columns:false,views:false,export:false,more:false,count:false,columnMenus:false},...(paged?{presentation:"paged",pageLength:length}:{}),rowAction:rows.some(row=>recordRowRef(list,row))?"details":"none"},labels:ctx.view.opts.labels,...(rows.length>8?{}:{toolbar:false}),onDetails:({row})=>open(row)})}
|
|
76
76
|
host.style.setProperty("--cx-record-rows",String(Math.min(tree?(list.roots||rows).length:Math.min(rows.length,list.pageLength||10),12)));body.appendChild(host);recordOnDispose(ctx.signal,()=>api.destroy());api.ready?.catch(error=>{if(!ctx.signal.aborted)ctx.view.emit("error",{error})})}
|
|
77
77
|
function recordCards(ctx,field,list,body){const holder=h("div","cx-record-cards"),rows=list.rows,columns=list.columns,step=10;const card=row=>{const item=h("div","cx-record-card"),title=h("div","cx-record-card-title"),ref=recordRowRef(list,row),text=recordRowTitle(list,row,ctx.fmt);item.setAttribute("role","group");item.setAttribute("aria-label",text);if(ref)recordLink(ctx,{value:text,ref},{id:field.id,kind:"text"},title);else setText(title,text);const fields=h("dl","cx-dl");for(const column of columns.slice(1)){const cell=row.cells?.[column.id],spec={id:column.id,title:column.title,kind:column.kind||"text"};if(recordEmpty(cell,spec,ctx.fmt))continue;const term=h("dt"),value=h("dd");setText(term,column.title);recordValue(ctx,spec,cell,value,1);fields.append(term,value)}
|
|
78
78
|
item.append(title,fields);return item};for(const row of rows.slice(0,step))holder.appendChild(card(row));body.appendChild(holder);if(rows.length>step){const more=recordButton(fill(ctx.labels.recordShowAll,{count:recordCount(ctx,rows.length)}),()=>{more.remove();for(const row of rows.slice(step))holder.appendChild(card(row));holder.children[step]?.querySelector("button")?.focus()},"cx-record-more");body.appendChild(more)}}
|
|
@@ -136,7 +136,7 @@ return api.openRecord(ref.id,{stack:[...state.stack,entry].slice(-20),returnFocu
|
|
|
136
136
|
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
137
|
.then(()=>recordRetire(dialog),error=>{recordAnnounce(dialog,fill(view.labels.recordUnavailable,{id:entry.id}));view.emit("error",{error})})}
|
|
138
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(()=>{})}
|
|
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
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
141
|
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
142
|
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}
|
|
@@ -155,13 +155,18 @@ view._recordLinkOpen=record?recordLinkPath(recordLinkRead(view)||[]):null}
|
|
|
155
155
|
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
156
|
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
157
|
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);
|
|
159
|
-
const
|
|
158
|
+
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
|
+
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
|
+
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=false}};const item={label,task:run,visible,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)}
|
|
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")))}
|
|
160
164
|
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;
|
|
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
|
|
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=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.find(button=>!button.hidden)?.focus()};const buttons=items.map(item=>{const button=recordButton(item.label,()=>{show(false);toggle.focus();Promise.resolve().then(item.task).catch(failed)},"cx-record-menu-item");button.setAttribute("role","menuitem");button.tabIndex=-1;item.button=button;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
167
|
if(event.key==="Tab"){show(false);return}
|
|
164
|
-
const
|
|
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()}
|
|
165
170
|
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
171
|
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
172
|
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)})}
|