@evotecit/canopyx 0.3.20 → 0.3.21
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-grid-module.mjs +4 -5
- package/CanopyX.Html/Assets/canopyx-grid.js +3 -4
- package/CanopyX.Html/Assets/canopyx-interactive.js +3 -4
- package/CanopyX.Html/Assets/canopyx-labels-de.js +4 -0
- package/CanopyX.Html/Assets/canopyx-labels-es.js +4 -0
- package/CanopyX.Html/Assets/canopyx-labels-fr.js +4 -0
- package/CanopyX.Html/Assets/canopyx-labels-it.js +4 -0
- package/CanopyX.Html/Assets/canopyx-labels-pl.js +4 -0
- package/CanopyX.Html/Assets/canopyx-module.mjs +4 -5
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +4 -5
- package/CanopyX.Html/Assets/canopyx-reporting.js +3 -4
- package/CanopyX.Html/Assets/canopyx-ui-accordion.css +119 -0
- package/CanopyX.Html/Assets/canopyx-ui-accordion.js +33 -0
- package/CanopyX.Html/Assets/canopyx-ui-module.mjs +39 -0
- package/CanopyX.Html/Assets/canopyx-ui-navigation.css +4 -4
- package/CanopyX.Html/Assets/canopyx-ui-navigation.js +5 -5
- package/CanopyX.Html/Assets/canopyx-ui-overlays.js +1 -1
- package/CanopyX.Html/Assets/canopyx-ui-stepper.js +1 -1
- package/CanopyX.Html/Assets/canopyx-ui-tabs.css +1 -0
- package/CanopyX.Html/Assets/canopyx-ui-tabs.js +7 -4
- package/CanopyX.Html/Assets/canopyx-ui.css +119 -0
- package/CanopyX.Html/Assets/canopyx-ui.js +37 -0
- package/CanopyX.Html/Assets/canopyx.js +3 -4
- package/JavaScript/locales/de.mjs +4 -0
- package/JavaScript/locales/es.mjs +4 -0
- package/JavaScript/locales/fr.mjs +4 -0
- package/JavaScript/locales/it.mjs +4 -0
- package/JavaScript/locales/pl.mjs +4 -0
- package/JavaScript/protocol.d.ts +1 -0
- package/JavaScript/ui.d.ts +70 -2
- package/package.json +14 -1
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/* Shared semantic tokens are bundled by Sync-Assets.ps1. Only component geometry lives here. */
|
|
2
|
+
.cx-host,.cx-static{
|
|
3
|
+
--cx-compact:0;
|
|
4
|
+
--cx-row-h:var(--hfx-row-height,calc(40px - var(--cx-compact,0) * 8px));
|
|
5
|
+
--cx-size-d04em:.04em;
|
|
6
|
+
--cx-size-46ch:46ch;
|
|
7
|
+
--cx-size-440px:440px;
|
|
8
|
+
--cx-size-140px:140px;
|
|
9
|
+
--cx-size-d06em:.06em;
|
|
10
|
+
--cx-size-210px:210px;
|
|
11
|
+
--cx-size-neg-4px:-4px;
|
|
12
|
+
--cx-size-56px:56px;
|
|
13
|
+
--cx-size-64px:64px;
|
|
14
|
+
--cx-size-160px:160px;
|
|
15
|
+
--cx-size-12d5px:12.5px;
|
|
16
|
+
--cx-size-640px:640px;
|
|
17
|
+
--cx-size-17px:17px;
|
|
18
|
+
--cx-size-60vh:60vh;
|
|
19
|
+
--cx-size-11d5px:11.5px;
|
|
20
|
+
--cx-size-13d5px:13.5px;
|
|
21
|
+
--cx-size-38px:38px;
|
|
22
|
+
--cx-size-26px:26px;
|
|
23
|
+
--cx-size-52px:52px;
|
|
24
|
+
--cx-size-30px:30px;
|
|
25
|
+
--cx-size-72px:72px;
|
|
26
|
+
--cx-size-244px:244px;
|
|
27
|
+
--cx-size-44px:44px;
|
|
28
|
+
--cx-size-85vh:85vh;
|
|
29
|
+
--cx-size-480px:480px;
|
|
30
|
+
--cx-size-14px:14px;
|
|
31
|
+
--cx-size-1px:1px;
|
|
32
|
+
--cx-size-neg-1px:-1px;
|
|
33
|
+
--cx-size-8px:8px;
|
|
34
|
+
--cx-size-12px:12px;
|
|
35
|
+
--cx-size-4px:4px;
|
|
36
|
+
--cx-size-10px:10px;
|
|
37
|
+
--cx-size-11px:11px;
|
|
38
|
+
--cx-size-1d5px:1.5px;
|
|
39
|
+
--cx-size-5px:5px;
|
|
40
|
+
--cx-size-280px:280px;
|
|
41
|
+
--cx-size-34px:34px;
|
|
42
|
+
--cx-size-6px:6px;
|
|
43
|
+
--cx-size-32px:32px;
|
|
44
|
+
--cx-size-7px:7px;
|
|
45
|
+
--cx-size-420px:420px;
|
|
46
|
+
--cx-size-100vw:100vw;
|
|
47
|
+
--cx-size-16px:16px;
|
|
48
|
+
--cx-size-320px:320px;
|
|
49
|
+
--cx-size-2px:2px;
|
|
50
|
+
--cx-size-neg-2px:-2px;
|
|
51
|
+
--cx-size-180px:180px;
|
|
52
|
+
--cx-size-9px:9px;
|
|
53
|
+
--cx-size-neg-3px:-3px;
|
|
54
|
+
--cx-size-18px:18px;
|
|
55
|
+
--cx-size-1d6px:1.6px;
|
|
56
|
+
--cx-size-999px:999px;
|
|
57
|
+
--cx-size-100vh:100vh;
|
|
58
|
+
--cx-size-340px:340px;
|
|
59
|
+
--cx-size-20px:20px;
|
|
60
|
+
--cx-size-36px:36px;
|
|
61
|
+
--cx-size-3px:3px;
|
|
62
|
+
--cx-size-13px:13px;
|
|
63
|
+
--cx-size-360px:360px;
|
|
64
|
+
--cx-size-22px:22px;
|
|
65
|
+
--cx-size-24px:24px;
|
|
66
|
+
--cx-size-80vh:80vh;
|
|
67
|
+
--cx-size-240px:240px;
|
|
68
|
+
--cx-size-d875em:.875em;
|
|
69
|
+
--cx-size-92px:92px;
|
|
70
|
+
--cx-size-28px:28px;
|
|
71
|
+
--cx-scrollbar-thumb:color-mix(in srgb,var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5))) 28%,transparent);
|
|
72
|
+
--cx-scrollbar-thumb-hover:color-mix(in srgb,var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5))) 46%,transparent);
|
|
73
|
+
--cx-scrollbar-track:transparent;
|
|
74
|
+
--cx-scrollbar-size:10px;
|
|
75
|
+
}
|
|
76
|
+
.cx-host{
|
|
77
|
+
box-sizing:border-box;
|
|
78
|
+
display:flex;
|
|
79
|
+
flex-direction:column;
|
|
80
|
+
min-height:0;
|
|
81
|
+
color:var(--hfx-color-text-primary,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)));
|
|
82
|
+
background:var(--hfx-color-surface-card,var(--hfx-color-surface,light-dark(#ffffff,#16181c)));
|
|
83
|
+
font-family:var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);
|
|
84
|
+
font-size:var(--hfx-control-font-size,calc(var(--hfx-type-body-size,0.875rem) - var(--cx-compact,0) * .0625rem));
|
|
85
|
+
line-height:var(--hfx-type-small-line,1.4);
|
|
86
|
+
}
|
|
87
|
+
.cx-host:where(:not(.cx-drawer,.cx-dialog,.cx-popover,.cx-menu,.cx-tooltip)){
|
|
88
|
+
height:480px;
|
|
89
|
+
}
|
|
90
|
+
.cx-host[data-cx-chrome="embedded"]{background:transparent;border:0;border-radius:0;}
|
|
91
|
+
.cx-host[data-cx-chrome="embedded"] > .cx-grid{border-inline:0;border-bottom:0;border-radius:0;background:transparent;}
|
|
92
|
+
.cx-host[data-cx-chrome="embedded"] > :is(.cx-grid-notice,.cx-grid-status,.cx-grid-pager){background:transparent;}
|
|
93
|
+
.cx-host[data-cx-chrome="embedded"] :is(.cx-toolbar,.cx-grid-query-summary,.cx-grid-status,.cx-grid-pager){padding-inline:var(--hfx-card-padding-x,calc(20px - var(--cx-compact,0) * 4px));}
|
|
94
|
+
.cx-host[data-cx-chrome="embedded"] :is(.cx-hrow,.cx-row) > :first-child{padding-inline-start:var(--hfx-card-padding-x,calc(20px - var(--cx-compact,0) * 4px));}
|
|
95
|
+
.cx-host[data-cx-chrome="embedded"] :is(.cx-hrow,.cx-row) > :last-child{padding-inline-end:var(--hfx-card-padding-x,calc(20px - var(--cx-compact,0) * 4px));}
|
|
96
|
+
.cx-host *,.cx-host *::before,.cx-host *::after{box-sizing:border-box;}
|
|
97
|
+
.cx-host .cx-button.cx-filter-chip{display:inline-flex;align-items:center;justify-content:flex-start;gap:var(--hfx-space-1-5,6px);min-width:0;}
|
|
98
|
+
.cx-filter-chip > .cx-chip-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:var(--hfx-type-small-line,1.4);}
|
|
99
|
+
.cx-filter-chip > .cx-chip-remove{flex:none;}
|
|
100
|
+
@media print{.cx-filter-chip > .cx-chip-label{white-space:normal;overflow:visible;text-overflow:clip;}}
|
|
101
|
+
@media not (forced-colors:active){
|
|
102
|
+
:where(.cx-host,.cx-host *){scrollbar-color:var(--cx-scrollbar-thumb) var(--cx-scrollbar-track);scrollbar-width:thin;}
|
|
103
|
+
.cx-host::-webkit-scrollbar,.cx-host ::-webkit-scrollbar{width:var(--cx-scrollbar-size);height:var(--cx-scrollbar-size);}
|
|
104
|
+
.cx-host::-webkit-scrollbar-track,.cx-host ::-webkit-scrollbar-track,.cx-host ::-webkit-scrollbar-corner{background:var(--cx-scrollbar-track);}
|
|
105
|
+
.cx-host::-webkit-scrollbar-thumb,.cx-host ::-webkit-scrollbar-thumb{background:var(--cx-scrollbar-thumb) padding-box;border:calc(var(--hfx-border-width,1px)*2) solid transparent;border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));}
|
|
106
|
+
.cx-host ::-webkit-scrollbar-thumb:hover{background-color:var(--cx-scrollbar-thumb-hover);}
|
|
107
|
+
}
|
|
108
|
+
.cx-sr-only{
|
|
109
|
+
position:absolute !important;
|
|
110
|
+
width:1px;height:1px;padding:0;
|
|
111
|
+
margin:calc(var(--hfx-border-width,1px)*-1);
|
|
112
|
+
overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
|
|
113
|
+
}
|
|
114
|
+
.cx-host[data-cx-density="compact"]{--cx-compact:1;}
|
|
115
|
+
@layer hfx.fallbacks{
|
|
116
|
+
:where([data-cx-fallback-mode="auto"],.cx-static[data-theme="auto"],.cx-static[data-cx-theme="auto"]){color-scheme:light dark;}
|
|
117
|
+
:where([data-cx-fallback-mode="light"],.cx-static[data-theme="light"],.cx-static[data-cx-theme="light"]){color-scheme:light;}
|
|
118
|
+
:where([data-cx-fallback-mode="dark"],.cx-static[data-theme="dark"],.cx-static[data-cx-theme="dark"]){color-scheme:dark;}
|
|
119
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/* CanopyX UI entry: standalone UI primitives. */
|
|
2
|
+
(function(global){"use strict";if(global.CanopyX){return}
|
|
3
|
+
function h(tag,className){const element=document.createElement(tag);if(className)element.className=className;return element}
|
|
4
|
+
function setText(element,value){element.textContent=value==null?"":String(value)}
|
|
5
|
+
function fill(template,values){return template.replace(/\{(\w+)\}/g, (match, name) => (values && Object.hasOwn(values, name) ? String(values[name]) : match));
|
|
6
|
+
}
|
|
7
|
+
const pluralRules=new Map();function plural(template,count,lang){if(!template.startsWith("["))return template;const forms={};for(const match of template.matchAll(/\[(zero|one|two|few|many|other)\]([^[]*)/g)) forms[match[1]] = match[2];
|
|
8
|
+
let rules=pluralRules.get(lang);if(!rules){try{rules=new Intl.PluralRules(lang||"en")}catch(_){rules=new Intl.PluralRules("en")}pluralRules.set(lang,rules)}
|
|
9
|
+
return forms[rules.select(Number(count))]??forms.other??template}
|
|
10
|
+
let pageNonce=typeof document!=="undefined"&&document.currentScript?.nonce||"",trustPolicy;function setNonce(nonce){if(typeof nonce!=="string"||!nonce)throw new Error("CanopyX: invalid nonce.");pageNonce=nonce}
|
|
11
|
+
function withNonce(element){const nonce=pageNonce||document.querySelector("script[nonce]")?.nonce;if(nonce)element.nonce=nonce;return element}
|
|
12
|
+
function trusted(kind,value){if(trustPolicy===undefined){try{trustPolicy=global.trustedTypes?.createPolicy("canopyx",{createHTML:text=>text,createScript:text=>text,createScriptURL:text=>text})||null}
|
|
13
|
+
catch(_){trustPolicy=null}}
|
|
14
|
+
return trustPolicy?trustPolicy["create"+kind](value):value}
|
|
15
|
+
function hostHtml(element,html,sanitize,kind){const text=String(html??""),value=sanitize?sanitize(text,{kind}):text;if(value?.nodeType)element.replaceChildren(value);else if(typeof value==="string")element.innerHTML=trusted("HTML",value);else if(global.trustedTypes?.isHTML?.(value))element.innerHTML=value;else throw new Error("CanopyX: invalid sanitizeHtml result.")}
|
|
16
|
+
const STATUS_FALLBACKS={"--hfx-color-status-bad-bg":"light-dark(#f9e4e4,#3c272a)","--hfx-color-status-bad-fg":"light-dark(#b8292a,#f47171)","--hfx-color-status-good-bg":"light-dark(#e2f0e9,#1f362f)","--hfx-color-status-good-fg":"light-dark(#177345,#4cc78a)","--hfx-color-status-info-bg":"light-dark(#e4ecfa,#262f41)","--hfx-color-status-info-fg":"light-dark(#2b5fc0,#74a2f7)","--hfx-color-status-neutral-bg":"light-dark(#eeeff0,#2a2c31)","--hfx-color-status-neutral-fg":"light-dark(#5b6069,#a0a5ae)","--hfx-color-status-warn-bg":"light-dark(#f8efde,#3b3322)","--hfx-color-status-warn-fg":"light-dark(#8c5c05,#eeb640)"};const MODE_ATTRIBUTES=["data-theme","data-cx-theme","data-hfx-mode","data-bs-theme","data-hfx-theme","data-hfx-tokens"];const THEME_ATTRIBUTES=[...MODE_ATTRIBUTES,"data-hfx-style","data-hfx-density","data-cx-fallback-mode","style","class"];function watchTheme(host,signal){const attributes=THEME_ATTRIBUTES;const previous=host.getAttribute("data-cx-fallback-mode");const refresh=()=>{const parent=host.parentElement&&getComputedStyle(host.parentElement);const inherited=parent?.colorScheme;const surface=parent&&["--hfx-color-surface-card","--hfx-color-surface"].some(name=>parent.getPropertyValue(name).trim());let mode=null;if(!surface){outer:for(let owner=host;owner;owner=owner.parentElement)for(const attribute of MODE_ATTRIBUTES){const value=owner.getAttribute(attribute);if(value==="light"||value==="dark"){mode=value;break outer}}}
|
|
17
|
+
if(surface||!mode&&inherited&&inherited!=="normal"){if(host.hasAttribute("data-cx-fallback-mode"))host.removeAttribute("data-cx-fallback-mode")}else if(host.getAttribute("data-cx-fallback-mode")!==(mode||"auto"))host.setAttribute("data-cx-fallback-mode",mode||"auto")};const observer=new MutationObserver(refresh);for(let owner=host;owner;owner=owner.parentElement)observer.observe(owner,{attributes:true,attributeFilter:attributes});refresh();const dispose=()=>{observer.disconnect();if(previous===null)host.removeAttribute("data-cx-fallback-mode");else host.setAttribute("data-cx-fallback-mode",previous)};signal?.addEventListener("abort",dispose,{once:true});return dispose}
|
|
18
|
+
function overlayTheme(host,element,inherit=false){for(const name of["data-hfx-style","data-hfx-mode","data-hfx-density"]){const owner=host.closest("["+name+"]");if(owner&&!inherit)element.setAttribute(name,owner.getAttribute(name));else element.removeAttribute(name)}
|
|
19
|
+
const theme=getComputedStyle(host),parent=inherit&&host.parentElement&&getComputedStyle(host.parentElement);element.style.colorScheme=theme.colorScheme;const copied=[];for(const name of theme)if((name.startsWith("--cx-")||name.startsWith("--hfx-"))&&(!parent||theme.getPropertyValue(name)!==parent.getPropertyValue(name))){element.style.setProperty(name,theme.getPropertyValue(name));copied.push(name)}
|
|
20
|
+
return copied}
|
|
21
|
+
function watchOverlayTheme(host,element,signal){if(signal?.aborted)return()=>{};let copied=[];const refresh=()=>{for(const name of copied)element.style.removeProperty(name);copied=overlayTheme(host,element,element.parentElement===host.parentElement)};const observer=new MutationObserver(refresh);for(let owner=host;owner;owner=owner.parentElement)observer.observe(owner,{attributes:true,attributeFilter:THEME_ATTRIBUTES});const media=["(prefers-color-scheme:dark)","(prefers-contrast:more)","(forced-colors:active)"].map(query=>matchMedia(query));for(const query of media)query.addEventListener("change",refresh);const dispose=()=>{observer.disconnect();for(const query of media)query.removeEventListener("change",refresh);signal?.removeEventListener("abort",dispose)};signal?.addEventListener("abort",dispose,{once:true});dispose.refresh=refresh;refresh();return dispose}
|
|
22
|
+
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"ui-overlays":["24afaa117ebf3fb5","canopyx-ui-overlays.dedc42d3a501a387.js","canopyx-ui-overlays.3668a9a74004ea8e.css"],"ui-menu":["352b1ee391133ff0","canopyx-ui-menu.f9abee36db8f6ad2.js","canopyx-ui-menu.2f3478cc5f5c272f.css"],"ui-picker":["d415103478faf52a","canopyx-ui-picker.13e544bd68aca998.js","canopyx-ui-picker.59c85a1988a287a9.css"],"ui-navigation":["2553d01c5276d56a","canopyx-ui-navigation.c4ebc214197f140d.js","canopyx-ui-navigation.0afd07bbdc5aecb5.css"],"ui-tabs":["19ece8184f3daf4a","canopyx-ui-tabs.6cd35b2afd89f530.js","canopyx-ui-tabs.7bb6c6f1341e87e9.css"],"ui-stepper":["5682c49db1b85314","canopyx-ui-stepper.96973189b0f6e0c4.js","canopyx-ui-stepper.1d4a9db373b8d2f2.css"],"ui-accordion":["1424f075b78d0ccd","canopyx-ui-accordion.d0d5daa7f73d0859.js","canopyx-ui-accordion.a3ef9c27cea5b7a4.css"]},PART_CODE=new Map(),SHARED_PARTS={},partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
|
|
23
|
+
function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
|
|
24
|
+
part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
|
|
25
|
+
function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
|
|
26
|
+
function loadPart(part){return part.ready||=Promise.resolve().then(async()=>{const[version,scriptFile,styleFile]=Object.hasOwn(PARTS,part.name)?PARTS[part.name]:[];part.version=version;if(!version)throw new Error("CanopyX: no "+part.label+".");if(PART_CODE.get(part.name)?.version!==part.version||part.styleReady===null){const find=type=>[...document.querySelectorAll('script[type="application/x-canopyx-'+type+'"][data-cx-version="'+part.version+'"]')].find(item=>!pageNonce||item.nonce===pageNonce);const payload=find(part.name),script=h("script"),embeddedStyle=styleFile&&find(part.name+"-style");if(payload){if(embeddedStyle){const style=h("style");style.nonce=payload.nonce;setText(style,embeddedStyle.textContent);document.head.appendChild(style)}
|
|
27
|
+
script.textContent=trusted("Script",payload.textContent);script.nonce=payload.nonce;document.head.appendChild(script);script.remove()}else{const base=global.CanopyXFilterEditorBase,runtime=PART_URL||typeof base==="string"&&base||document.baseURI,hashed=PART_URL&&/\.[a-f\d]{16}\.js(?:[?#]|$)/.test(PART_URL);
|
|
28
|
+
const load=(element,attribute,file,kind)=>new Promise((resolve,reject)=>{const url=new URL(file,runtime).href;element[attribute]=attribute==="src"?trusted("ScriptURL",url):url;element.onload=resolve;element.onerror=()=>{element.remove();reject(new Error("CanopyX: "+part.label+" "+kind+" unavailable."))};document.head.appendChild(withNonce(element))});const link=h("link");link.rel="stylesheet";const style=styleFile&&(part.styleReady||=load(link,"href",hashed?styleFile:"canopyx-"+part.name+".css","stylesheet")
|
|
29
|
+
.catch(error=>{part.styleReady=null;throw error}));const code=PART_CODE.get(part.name)?.version===part.version||(part.scriptReady||=load(script,"src",hashed?scriptFile:"canopyx-"+part.name+".js","script")
|
|
30
|
+
.finally(()=>script.remove()).catch(error=>{part.scriptReady=null;throw error}));await Promise.all([style,code])}}
|
|
31
|
+
const code=PART_CODE.get(part.name);if(code?.version!==part.version)throw new Error("CanopyX: "+part.label+" and runtime must come from the same build.");for(const name of code.requires||[])await loadPart(part.parts[name]||SHARED_PARTS[name]);code.install(part.context())}).catch(error=>{part.ready=null;throw error})}
|
|
32
|
+
const partQueue=global.CanopyXParts=global.CanopyXParts||[];partQueue.forEach(entry=>registerPart(...entry));partQueue.length=0;partQueue.push=(...entries)=>{entries.forEach(entry=>registerPart(...entry));return 0};function UiHost(){}
|
|
33
|
+
const UI_IMPL={},UI_TOOLS={},uiInstances=new WeakMap();const UI_KINDS={tabs:"ui-tabs",stepper:"ui-stepper",accordion:"ui-accordion",menu:"ui-menu",dialog:"ui-overlays",drawer:"ui-overlays",popover:"ui-overlays",tooltip:"ui-overlays"};const uiContext=()=>({UI_IMPL,UI_TOOLS,h,setText,fill,watchTheme,overlayTheme,hostHtml});for(const name of Object.keys(PARTS).filter(part=>part.startsWith("ui-")))SHARED_PARTS[name]=definePart(UiHost,name,name.replace("ui-","UI "),uiContext);function createUi(kind,target,options={}){const root=typeof target==="string"?document.querySelector(target):target;if(root?.nodeType!==1)throw new Error("CanopyX: "+kind+" needs an element.");let registrations=uiInstances.get(root);if(!registrations)uiInstances.set(root,registrations=new Map());if(registrations.has(kind))return registrations.get(kind);const lifetime=new AbortController();watchTheme(root,lifetime.signal);let instance=null;const ready=loadPart(SHARED_PARTS[UI_KINDS[kind]]).then(()=>{if(lifetime.signal.aborted)throw new DOMException("UI component destroyed.","AbortError");instance=UI_IMPL[kind](root,options,lifetime.signal);return instance.ready||instance});const api={element:root,ready:ready.then(()=>api),destroy(){if(lifetime.signal.aborted)return;lifetime.abort();instance?.destroy?.();registrations.delete(kind)}};for(const name of["select","getSelected","refresh","preparePrint","open","close","next","back","skip","finish","setStepState","getState","toggle","getOpen","filter"])api[name]=(...args)=>{if(lifetime.signal.aborted)throw new Error("CanopyX: UI component destroyed.");return instance?instance[name]?.(...args):ready.then(()=>instance[name]?.(...args))};api.ready.catch(error=>{if(error.name!=="AbortError")root.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});registrations.set(kind,Object.freeze(api));return api}
|
|
34
|
+
function bindContextMenu(target,items,options={}){if(typeof target!=="string"&&target?.nodeType!==1)throw new Error("CanopyX: contextMenu needs an element or selector.");if(typeof target==="string")document.documentElement.matches(target);let disposed=false,cleanup=null;const dispose=()=>{disposed=true;cleanup?.()};dispose.ready=loadPart(SHARED_PARTS["ui-menu"]).then(()=>{if(!disposed)cleanup=UI_IMPL.contextMenu(target,items,options)});dispose.open=(...args)=>disposed?false:cleanup?cleanup.open(...args):dispose.ready.then(()=>!disposed&&cleanup.open(...args));dispose.close=(...args)=>cleanup?.close(...args);return dispose}
|
|
35
|
+
function mountUi(root=document){const mounted=[];for(const kind of Object.keys(UI_KINDS)){const selector="[data-cx-"+kind+"]",nodes=[...root.querySelectorAll(selector)];if(root.matches?.(selector))nodes.unshift(root);for(const element of nodes){if(kind==="menu"&&element.parentElement?.closest(selector))continue;if(kind==="stepper"&&["report","static"].includes(element.dataset.mode))continue;mounted.push(createUi(kind,element))}}
|
|
36
|
+
return mounted}
|
|
37
|
+
const UI_API={mountUi,contextMenu:bindContextMenu};for(const kind of Object.keys(UI_KINDS))UI_API[kind]=(target,options)=>createUi(kind,target,options);global.CanopyX=Object.freeze(Object.assign({registerPart,setNonce},UI_API));const navigation=global.performance&&performance.getEntriesByType?performance.getEntriesByType("navigation")[0]:null;if(document.readyState==="loading"||(document.readyState==="interactive"&&navigation&&navigation.domContentLoadedEventStart===0)){document.addEventListener("DOMContentLoaded",()=>mountUi(document))}else{mountUi(document)}})(typeof window!=="undefined"?window:this);
|
|
@@ -75,8 +75,7 @@ function fill(template,values){return template.replace(/\{(\w+)\}/g, (match, nam
|
|
|
75
75
|
const pluralRules=new Map();function plural(template,count,lang){if(!template.startsWith("["))return template;const forms={};for(const match of template.matchAll(/\[(zero|one|two|few|many|other)\]([^[]*)/g)) forms[match[1]] = match[2];
|
|
76
76
|
let rules=pluralRules.get(lang);if(!rules){try{rules=new Intl.PluralRules(lang||"en")}catch(_){rules=new Intl.PluralRules("en")}pluralRules.set(lang,rules)}
|
|
77
77
|
return forms[rules.select(Number(count))]??forms.other??template}
|
|
78
|
-
let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",hiddenColumns:"[one]+{count} column[other]+{count} columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{
|
|
79
|
-
if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix|change|board|plan|path|stack|time|compare|viewIntent)[A-Z]\w{0,63}$/.test(name) && !uiLabel) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
78
|
+
let DEFAULT_LABELS=Object.freeze({searchPlaceholder:"Search",searchResults:"Search results",searchResultCount:"{count} results",searchResultCountOfTotal:"{count} of {total} results",searchResultCountOfMany:"{count} of many results",searchNoResults:"No results",searchTooShort:"Type at least {min} characters",searchWordTooShort:"Type a word of at least {min} characters",searchFailed:"Search failed: {error}",columns:"Columns",hiddenColumns:"[one]+{count} column[other]+{count} columns",visibleColumns:"Visible columns",resizeColumn:"Resize {column}",columnWidth:"{width} pixels",loading:"Loading…",loadError:"Could not load: {error} (Enter to retry)",queryFailed:"Could not update the view: {error}",showMore:"Show more ({loaded} of {total} loaded)",showMoreUnknownTotal:"Show more ({loaded} loaded)",pageLoaded:"{loaded} of {total} loaded",itemsLoaded:"{count} items",yes:"Yes",no:"No",utcTime:"{time} UTC",localTime:"{time} local time",mountError:"This view could not be displayed: {error}"});function labelsFor(...sources){const labels=Object.assign({},DEFAULT_LABELS);for(const source of sources){if(source==null)continue;if(typeof source!=="object"||Array.isArray(source))throw new Error("CanopyX: labels must be an object of strings.");Object.keys(source).forEach((name)=>{if(!Object.hasOwn(DEFAULT_LABELS,name)&&!/^(?:gridEdit|format|calendar|flow|matrix|change|board|plan|path|stack|time|compare|viewIntent|tabs|stepper|accordion|dialog|drawer|state)[A-Z]\w{0,63}$/.test(name)) throw new Error("CanopyX: there is no label '" + name + "'.");
|
|
80
79
|
if(typeof source[name]!=="string"||!/\S/.test(source[name])) throw new Error("CanopyX: label '" + name + "' must be a string with visible text.");
|
|
81
80
|
if((name==="utcTime"||name==="localTime")&&source[name].indexOf("{time}")<0)throw new Error("CanopyX: label '"+name+"' must hold {time}.");labels[name]=source[name]})}
|
|
82
81
|
return Object.freeze(labels)}
|
|
@@ -531,7 +530,7 @@ close()}else{return}
|
|
|
531
530
|
e.preventDefault()});input.addEventListener("blur",()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);blurTimer=setTimeout(close,150)});this.cancelSearch=()=>{cancelNavigation();sequence++;clearTimeout(timer);clearTimeout(blurTimer);hits=[];close()};box.appendChild(input);box.appendChild(list);box.appendChild(status);bar.appendChild(box);this.searchInput=input}});function watchFlyout(anchorElement,panel,isOpen){const lifetime=new AbortController();let flyout=null,pending=null;const ready=()=>flyout?Promise.resolve(flyout):pending||=loadPart(SHARED_PARTS["ui-overlays"]).then(()=>{if(!lifetime.signal.aborted)flyout=UI_TOOLS.toolbarFlyout(anchorElement,panel,isOpen,lifetime.signal);return flyout}).catch(error=>{pending=null;throw error});const invoke=method=>{if(lifetime.signal.aborted||!isOpen())return;if(flyout){flyout[method]();return}
|
|
532
531
|
ready().then(value=>{if(!lifetime.signal.aborted&&isOpen())value?.[method]()}).catch(error=>{if(!lifetime.signal.aborted)(anchorElement.closest(".cx-host")||anchorElement)
|
|
533
532
|
.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))})};return{position:()=>invoke("position"),open:()=>invoke("open"),close:()=>flyout?.close(),dispose:()=>lifetime.abort()}}
|
|
534
|
-
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"ui-overlays":["
|
|
533
|
+
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"ui-overlays":["24afaa117ebf3fb5","canopyx-ui-overlays.dedc42d3a501a387.js","canopyx-ui-overlays.3668a9a74004ea8e.css"],"ui-menu":["352b1ee391133ff0","canopyx-ui-menu.f9abee36db8f6ad2.js","canopyx-ui-menu.2f3478cc5f5c272f.css"],"ui-picker":["d415103478faf52a","canopyx-ui-picker.13e544bd68aca998.js","canopyx-ui-picker.59c85a1988a287a9.css"],"ui-navigation":["2553d01c5276d56a","canopyx-ui-navigation.c4ebc214197f140d.js","canopyx-ui-navigation.0afd07bbdc5aecb5.css"],"ui-tabs":["19ece8184f3daf4a","canopyx-ui-tabs.6cd35b2afd89f530.js","canopyx-ui-tabs.7bb6c6f1341e87e9.css"],"ui-stepper":["5682c49db1b85314","canopyx-ui-stepper.96973189b0f6e0c4.js","canopyx-ui-stepper.1d4a9db373b8d2f2.css"],"ui-accordion":["1424f075b78d0ccd","canopyx-ui-accordion.d0d5daa7f73d0859.js","canopyx-ui-accordion.a3ef9c27cea5b7a4.css"],"tree-tools":["ef0d06c82135ae2e","canopyx-tree-tools.1c4b9e286dde6065.js","canopyx-tree-tools.350dd0ee46757029.css"],"export":["15abf3205094bda6","canopyx-export.68b90138463329fe.js"],"office-export":["4fb7a4d570390ee9","canopyx-office-export.7e62c385b884e75b.js"],"links":["c6579c9401f0971d","canopyx-links.b25760079f57e6e1.js"],"search":["521eebd6e1bbbd35","canopyx-search.14c69f4551c69f23.js"],"link":["7485f5c9875e9f9b","canopyx-link.9066770aa822fe0f.js","canopyx-link.997fefec6b85f0c5.css"],"highlight":["5ebf0042011ba4fd","canopyx-highlight.ff11a0ca8e30102b.js","canopyx-highlight.9c26291cbcd0962b.css"],"layouts":["90267e35e7edf3a4","canopyx-layouts.058b8a396f909a79.js","canopyx-layouts.ca17f42babc4192a.css"],"record-panel":["cb6bcd1baf644a51","canopyx-record-panel.557c676822e8624f.js","canopyx-record-panel.174846a640de979f.css"]},PART_CODE=new Map(),SHARED_PARTS={},partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
|
|
535
534
|
function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
|
|
536
535
|
part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
|
|
537
536
|
function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
|
|
@@ -593,7 +592,7 @@ const wanted=Array.from(new Set(ids||this.rows.filter((w)=>!w.status).map((w)=>w
|
|
|
593
592
|
const navigation=navigationScope(this,this.dataLifetime.signal);let doc;try{doc=await navigation.wait(this.source.counts(wanted,this.sourceRequest(this.dataLifetime.signal)))}
|
|
594
593
|
finally{navigation.dispose()}
|
|
595
594
|
if(navigation.cancelled())return null;if(this.queryAware)snapshotRevision(doc,this.datasetRevision);checkDocument(doc,"counts");this.applyCounts(Object.assign({},doc,{items:doc.items.filter(item=>{const captured=mine.get(item.id);return captured&&this.keyMap.get(item.id)===captured.w&&captured.w.countRevision===captured.revision})}),true);return doc}});function UiHost(){}
|
|
596
|
-
const UI_IMPL={},UI_TOOLS={},uiInstances=new WeakMap();const UI_KINDS={tabs:"ui-tabs",stepper:"ui-stepper",menu:"ui-menu",dialog:"ui-overlays",drawer:"ui-overlays",popover:"ui-overlays",tooltip:"ui-overlays"};const uiContext=()=>({UI_IMPL,UI_TOOLS,h,setText,fill,watchTheme,overlayTheme,hostHtml});for(const name of
|
|
595
|
+
const UI_IMPL={},UI_TOOLS={},uiInstances=new WeakMap();const UI_KINDS={tabs:"ui-tabs",stepper:"ui-stepper",accordion:"ui-accordion",menu:"ui-menu",dialog:"ui-overlays",drawer:"ui-overlays",popover:"ui-overlays",tooltip:"ui-overlays"};const uiContext=()=>({UI_IMPL,UI_TOOLS,h,setText,fill,watchTheme,overlayTheme,hostHtml});for(const name of Object.keys(PARTS).filter(part=>part.startsWith("ui-")))SHARED_PARTS[name]=definePart(UiHost,name,name.replace("ui-","UI "),uiContext);function createUi(kind,target,options={}){const root=typeof target==="string"?document.querySelector(target):target;if(root?.nodeType!==1)throw new Error("CanopyX: "+kind+" needs an element.");let registrations=uiInstances.get(root);if(!registrations)uiInstances.set(root,registrations=new Map());if(registrations.has(kind))return registrations.get(kind);const lifetime=new AbortController();watchTheme(root,lifetime.signal);let instance=null;const ready=loadPart(SHARED_PARTS[UI_KINDS[kind]]).then(()=>{if(lifetime.signal.aborted)throw new DOMException("UI component destroyed.","AbortError");instance=UI_IMPL[kind](root,options,lifetime.signal);return instance.ready||instance});const api={element:root,ready:ready.then(()=>api),destroy(){if(lifetime.signal.aborted)return;lifetime.abort();instance?.destroy?.();registrations.delete(kind)}};for(const name of["select","getSelected","refresh","preparePrint","open","close","next","back","skip","finish","setStepState","getState","toggle","getOpen","filter"])api[name]=(...args)=>{if(lifetime.signal.aborted)throw new Error("CanopyX: UI component destroyed.");return instance?instance[name]?.(...args):ready.then(()=>instance[name]?.(...args))};api.ready.catch(error=>{if(error.name!=="AbortError")root.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});registrations.set(kind,Object.freeze(api));return api}
|
|
597
596
|
function bindContextMenu(target,items,options={}){if(typeof target!=="string"&&target?.nodeType!==1)throw new Error("CanopyX: contextMenu needs an element or selector.");if(typeof target==="string")document.documentElement.matches(target);let disposed=false,cleanup=null;const dispose=()=>{disposed=true;cleanup?.()};dispose.ready=loadPart(SHARED_PARTS["ui-menu"]).then(()=>{if(!disposed)cleanup=UI_IMPL.contextMenu(target,items,options)});dispose.open=(...args)=>disposed?false:cleanup?cleanup.open(...args):dispose.ready.then(()=>!disposed&&cleanup.open(...args));dispose.close=(...args)=>cleanup?.close(...args);return dispose}
|
|
598
597
|
function mountUi(root=document){const mounted=[];for(const kind of Object.keys(UI_KINDS)){const selector="[data-cx-"+kind+"]",nodes=[...root.querySelectorAll(selector)];if(root.matches?.(selector))nodes.unshift(root);for(const element of nodes){if(kind==="menu"&&element.parentElement?.closest(selector))continue;if(kind==="stepper"&&["report","static"].includes(element.dataset.mode))continue;mounted.push(createUi(kind,element))}}
|
|
599
598
|
return mounted}
|
|
@@ -914,6 +914,10 @@ const labels = Object.freeze({
|
|
|
914
914
|
timePosition: "Momentaufnahme {index} von {count}",
|
|
915
915
|
timeFrame: "Momentaufnahme um {time}",
|
|
916
916
|
timeReducedMotion: "Die zeitgesteuerte Wiedergabe ist wegen reduzierter Bewegung deaktiviert. Momentaufnahmen manuell durchgehen.",
|
|
917
|
+
accordionSearch: "Abschnitte filtern",
|
|
918
|
+
accordionNoMatches: "Keine passenden Abschnitte",
|
|
919
|
+
accordionCopyTitle: "Titel kopieren",
|
|
920
|
+
accordionCopied: "Kopiert",
|
|
917
921
|
tabsMore: "Mehr",
|
|
918
922
|
tabsMoreSelected: "Mehr: {label}",
|
|
919
923
|
tabsScrollPrevious: "Vorherige Tabs",
|
|
@@ -914,6 +914,10 @@ const labels = Object.freeze({
|
|
|
914
914
|
timePosition: "Instantánea {index} de {count}",
|
|
915
915
|
timeFrame: "Instantánea de {time}",
|
|
916
916
|
timeReducedMotion: "La reproducción automática está desactivada porque el movimiento reducido está activado. Recorre las instantáneas manualmente.",
|
|
917
|
+
accordionSearch: "Filtrar secciones",
|
|
918
|
+
accordionNoMatches: "No hay secciones coincidentes",
|
|
919
|
+
accordionCopyTitle: "Copiar título",
|
|
920
|
+
accordionCopied: "Copiado",
|
|
917
921
|
tabsMore: "Más",
|
|
918
922
|
tabsMoreSelected: "Más: {label}",
|
|
919
923
|
tabsScrollPrevious: "Pestañas anteriores",
|
|
@@ -914,6 +914,10 @@ const labels = Object.freeze({
|
|
|
914
914
|
timePosition: "Instantané {index} sur {count}",
|
|
915
915
|
timeFrame: "Instantané du {time}",
|
|
916
916
|
timeReducedMotion: "La lecture automatique est désactivée car les mouvements réduits sont activés. Parcourez les instantanés manuellement.",
|
|
917
|
+
accordionSearch: "Filtrer les sections",
|
|
918
|
+
accordionNoMatches: "Aucune section correspondante",
|
|
919
|
+
accordionCopyTitle: "Copier le titre",
|
|
920
|
+
accordionCopied: "Copié",
|
|
917
921
|
tabsMore: "Plus",
|
|
918
922
|
tabsMoreSelected: "Plus : {label}",
|
|
919
923
|
tabsScrollPrevious: "Onglets précédents",
|
|
@@ -914,6 +914,10 @@ const labels = Object.freeze({
|
|
|
914
914
|
timePosition: "Istantanea {index} di {count}",
|
|
915
915
|
timeFrame: "Istantanea del {time}",
|
|
916
916
|
timeReducedMotion: "La riproduzione automatica è disattivata perché è attiva la riduzione del movimento. Scorri le istantanee manualmente.",
|
|
917
|
+
accordionSearch: "Filtra le sezioni",
|
|
918
|
+
accordionNoMatches: "Nessuna sezione corrispondente",
|
|
919
|
+
accordionCopyTitle: "Copia titolo",
|
|
920
|
+
accordionCopied: "Copiato",
|
|
917
921
|
tabsMore: "Altro",
|
|
918
922
|
tabsMoreSelected: "Altro: {label}",
|
|
919
923
|
tabsScrollPrevious: "Schede precedenti",
|
|
@@ -914,6 +914,10 @@ const labels = Object.freeze({
|
|
|
914
914
|
timePosition: "Stan {index} z {count}",
|
|
915
915
|
timeFrame: "Stan z {time}",
|
|
916
916
|
timeReducedMotion: "Automatyczne odtwarzanie jest wyłączone z powodu ograniczenia ruchu. Przeglądaj stany ręcznie.",
|
|
917
|
+
accordionSearch: "Filtruj sekcje",
|
|
918
|
+
accordionNoMatches: "Brak pasujących sekcji",
|
|
919
|
+
accordionCopyTitle: "Kopiuj tytuł",
|
|
920
|
+
accordionCopied: "Skopiowano",
|
|
917
921
|
tabsMore: "Więcej",
|
|
918
922
|
tabsMoreSelected: "Więcej: {label}",
|
|
919
923
|
tabsScrollPrevious: "Poprzednie karty",
|
package/JavaScript/protocol.d.ts
CHANGED
|
@@ -275,6 +275,7 @@ export type LabelName =
|
|
|
275
275
|
| "calendarResized" | "calendarSeriesMoved" | "calendarSeriesTime" | "calendarMoveHelp" | "calendarEdit" | "calendarSaveFailed" | "calendarExport" | "calendarTimeRange" | "calendarSelected"
|
|
276
276
|
| "calendarLane" | "calendarHighlighted"
|
|
277
277
|
/** Standalone UI primitives; their English defaults load with the optional UI parts. */
|
|
278
|
+
| "accordionSearch" | "accordionNoMatches" | "accordionCopyTitle" | "accordionCopied"
|
|
278
279
|
| "tabsMore" | "tabsMoreSelected" | "tabsScrollPrevious" | "tabsScrollNext" | "tabsSection" | "tabsPosition" | "tabsPause" | "tabsPlay" | "tabsMotionDisabled"
|
|
279
280
|
| "stepperStepOf" | "stepperBack" | "stepperNext" | "stepperFinish" | "stepperSkip" | "stepperSaveDraft"
|
|
280
281
|
| "stepperAllSteps" | "stepperOptional" | "stepperCompleted" | "stepperSkipped" | "stepperIssues" | "stepperIssue"
|
package/JavaScript/ui.d.ts
CHANGED
|
@@ -70,6 +70,10 @@ export interface UiTabsOptions extends UiNavigationOptions {
|
|
|
70
70
|
transition?: "none" | "fade" | "slide";
|
|
71
71
|
hash?: boolean;
|
|
72
72
|
hashHistory?: "replace" | "push";
|
|
73
|
+
/** Remembers the selected tab in localStorage, under the root id (true) or this key. A link in the address wins. */
|
|
74
|
+
remember?: boolean | string;
|
|
75
|
+
/** Horizontal tabs share the full width equally. */
|
|
76
|
+
justified?: boolean;
|
|
73
77
|
tabs?: readonly UiTabOptions[];
|
|
74
78
|
/** Optional automatic progression. Manual selection stops it; reduced motion disables it.
|
|
75
79
|
* False disables settings emitted by the .NET builder. */
|
|
@@ -94,7 +98,65 @@ export interface UiNavigationController extends UiController {
|
|
|
94
98
|
/** Prepares deferred print bodies without navigation. Await before window.print(); rejects on load failure or cancellation. */
|
|
95
99
|
preparePrint(): Promise<void>;
|
|
96
100
|
}
|
|
97
|
-
export interface UiTabsController extends UiNavigationController {
|
|
101
|
+
export interface UiTabsController extends UiNavigationController {
|
|
102
|
+
/** Selects the next or previous enabled tab, stopping at the ends. Resolves false when there is none. */
|
|
103
|
+
next(): Promise<boolean>;
|
|
104
|
+
back(): Promise<boolean>;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** An accordion section. In beforeChange, open is the state being requested. */
|
|
108
|
+
export interface UiAccordionItem extends UiNavigationItem {
|
|
109
|
+
readonly open: boolean;
|
|
110
|
+
}
|
|
111
|
+
/** Deferred settings for one section, matched by its data-accordion-id. */
|
|
112
|
+
export interface UiAccordionSectionOptions extends UiDeferredOptions<UiAccordionItem> {
|
|
113
|
+
id: string;
|
|
114
|
+
}
|
|
115
|
+
/** Accordion over the .NET heading and panel contract. Each section loads on its own; closing one aborts its pending loader. */
|
|
116
|
+
export interface UiAccordionOptions extends UiDeferredOptions<UiAccordionItem> {
|
|
117
|
+
/** Lets several sections stay open. Defaults to false: opening a section closes the open one. */
|
|
118
|
+
multiple?: boolean;
|
|
119
|
+
/** Section identities or indexes to open, instead of the markup's own. A link in the address and remembered state win over this. */
|
|
120
|
+
open?: readonly (string | number)[];
|
|
121
|
+
style?: "default" | "flush" | "separated" | "section";
|
|
122
|
+
indicator?: "chevron" | "plus";
|
|
123
|
+
indicatorPosition?: "end" | "start";
|
|
124
|
+
transition?: "none" | "slide";
|
|
125
|
+
print?: "all" | "selected";
|
|
126
|
+
/** Writes open sections to the address as repeated `root-id=section-id` pairs. Requires a root id. */
|
|
127
|
+
hash?: boolean;
|
|
128
|
+
hashHistory?: "replace" | "push";
|
|
129
|
+
/** Remembers open sections in localStorage, under the root id (true) or this key. */
|
|
130
|
+
remember?: boolean | string;
|
|
131
|
+
/** A filter box above the sections. Filtering hides sections without closing them.
|
|
132
|
+
* It reads the header text; `or`, `|`, quoted phrases and a leading `-` or `!` are understood. */
|
|
133
|
+
search?: boolean | {
|
|
134
|
+
placeholder?: string;
|
|
135
|
+
/** Delay after typing, in milliseconds. Defaults to 150. */
|
|
136
|
+
debounce?: number;
|
|
137
|
+
};
|
|
138
|
+
/** Adds a copy-title button to every section, or removes the ones the markup asks for. */
|
|
139
|
+
copyTitle?: boolean;
|
|
140
|
+
/** Renders an encoded icon name from the markup into a decorative node or plain text. */
|
|
141
|
+
renderIcon?: (icon: string, item: Partial<UiAccordionItem>) => Node | string | null | void;
|
|
142
|
+
labels?: UiLabels;
|
|
143
|
+
sections?: readonly UiAccordionSectionOptions[];
|
|
144
|
+
/** Returning false cancels. In a single-open accordion from is the section that would close; to.open is the requested state. */
|
|
145
|
+
beforeChange?: (from: UiAccordionItem | undefined, to: UiAccordionItem, signal: AbortSignal) => boolean | void | Promise<boolean | void>;
|
|
146
|
+
}
|
|
147
|
+
export interface UiAccordionController extends UiController {
|
|
148
|
+
open(idOrIndex: string | number): Promise<boolean>;
|
|
149
|
+
close(idOrIndex: string | number): Promise<boolean>;
|
|
150
|
+
toggle(idOrIndex: string | number): Promise<boolean>;
|
|
151
|
+
/** The open section identities in display order. */
|
|
152
|
+
getOpen(): UiResult<string[]>;
|
|
153
|
+
/** Filters sections by header text and returns how many remain visible. An empty query shows all. */
|
|
154
|
+
filter(query?: string): UiResult<number>;
|
|
155
|
+
/** Rediscovers the current markup and updates presentation. */
|
|
156
|
+
refresh(): UiResult<void>;
|
|
157
|
+
/** Prepares deferred print bodies without opening sections. Await before window.print(); rejects on load failure or cancellation. */
|
|
158
|
+
preparePrint(): Promise<void>;
|
|
159
|
+
}
|
|
98
160
|
|
|
99
161
|
/** Step states are presentation supplied by the host or by successful navigation and validation. */
|
|
100
162
|
export type UiStepState = "upcoming" | "current" | "done" | "error" | "skipped" | "disabled";
|
|
@@ -241,21 +303,27 @@ export function contextMenu(target: UiTarget,
|
|
|
241
303
|
options?: UiContextMenuOptions): UiContextMenuDisposer;
|
|
242
304
|
export function tabs(target: UiTarget, options?: UiTabsOptions): UiTabsController;
|
|
243
305
|
export function stepper(target: UiTarget, options?: UiStepperOptions): UiStepperController;
|
|
306
|
+
export function accordion(target: UiTarget, options?: UiAccordionOptions): UiAccordionController;
|
|
244
307
|
export function dialog(target: UiTarget, options?: UiDialogOptions): UiDialogController;
|
|
245
308
|
export function drawer(target: UiTarget, options?: UiDrawerOptions): UiDialogController;
|
|
246
309
|
export function popover(target: UiTarget, options?: UiOverlayOptions): UiOverlayController;
|
|
247
310
|
export function tooltip(target: UiTarget, options?: UiOverlayOptions): UiOverlayController;
|
|
248
311
|
export function menu(target: UiTarget, options?: UiMenuOptions): UiMenuController;
|
|
249
312
|
|
|
250
|
-
/** Named UI exports shared by tree
|
|
313
|
+
/** Named UI exports shared by the tree, grid, reporting and UI entry points. */
|
|
251
314
|
export interface UiApi {
|
|
252
315
|
mountUi: typeof mountUi;
|
|
253
316
|
contextMenu: typeof contextMenu;
|
|
254
317
|
tabs: typeof tabs;
|
|
255
318
|
stepper: typeof stepper;
|
|
319
|
+
accordion: typeof accordion;
|
|
256
320
|
dialog: typeof dialog;
|
|
257
321
|
drawer: typeof drawer;
|
|
258
322
|
popover: typeof popover;
|
|
259
323
|
tooltip: typeof tooltip;
|
|
260
324
|
menu: typeof menu;
|
|
261
325
|
}
|
|
326
|
+
|
|
327
|
+
/** The UI entry point (`@evotecit/canopyx/ui`): the UI factories, the part registration and the nonce setter. */
|
|
328
|
+
declare const CanopyXUi: UiApi & { registerPart(name: string, part: { version: string; requires?: string[]; install(context: object): void }): void; setNonce(nonce: string): void };
|
|
329
|
+
export default CanopyXUi;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evotecit/canopyx",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.21",
|
|
4
4
|
"description": "Interactive tree grids and data tables with virtual rows, search, filters and offline HTML reports.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -116,6 +116,14 @@
|
|
|
116
116
|
"./ui-tabs.css": "./CanopyX.Html/Assets/canopyx-ui-tabs.css",
|
|
117
117
|
"./ui-stepper.js": "./CanopyX.Html/Assets/canopyx-ui-stepper.js",
|
|
118
118
|
"./ui-stepper.css": "./CanopyX.Html/Assets/canopyx-ui-stepper.css",
|
|
119
|
+
"./ui-accordion.js": "./CanopyX.Html/Assets/canopyx-ui-accordion.js",
|
|
120
|
+
"./ui-accordion.css": "./CanopyX.Html/Assets/canopyx-ui-accordion.css",
|
|
121
|
+
"./ui": {
|
|
122
|
+
"types": "./JavaScript/ui.d.ts",
|
|
123
|
+
"import": "./CanopyX.Html/Assets/canopyx-ui-module.mjs"
|
|
124
|
+
},
|
|
125
|
+
"./ui.js": "./CanopyX.Html/Assets/canopyx-ui.js",
|
|
126
|
+
"./ui.css": "./CanopyX.Html/Assets/canopyx-ui.css",
|
|
119
127
|
"./locales/pl": {
|
|
120
128
|
"types": "./JavaScript/locales/pl.d.ts",
|
|
121
129
|
"import": "./JavaScript/locales/pl.mjs"
|
|
@@ -256,6 +264,11 @@
|
|
|
256
264
|
"CanopyX.Html/Assets/canopyx-ui-tabs.css",
|
|
257
265
|
"CanopyX.Html/Assets/canopyx-ui-stepper.js",
|
|
258
266
|
"CanopyX.Html/Assets/canopyx-ui-stepper.css",
|
|
267
|
+
"CanopyX.Html/Assets/canopyx-ui-accordion.js",
|
|
268
|
+
"CanopyX.Html/Assets/canopyx-ui-accordion.css",
|
|
269
|
+
"CanopyX.Html/Assets/canopyx-ui.js",
|
|
270
|
+
"CanopyX.Html/Assets/canopyx-ui.css",
|
|
271
|
+
"CanopyX.Html/Assets/canopyx-ui-module.mjs",
|
|
259
272
|
"CanopyX.Html/Assets/canopyx-board.js",
|
|
260
273
|
"CanopyX.Html/Assets/canopyx-board.css",
|
|
261
274
|
"CanopyX.Html/Assets/canopyx-plan.js",
|