@evotecit/canopyx 0.3.13 → 0.3.15
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 +11 -11
- package/CanopyX.Html/Assets/canopyx-flow-checks.js +1 -1
- 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 +7 -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 +9 -3
- 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 +9 -3
- 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 +1 -1
- 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 +94 -51
- 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 +94 -51
- 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 +2 -2
- 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 +49 -49
- package/CanopyX.Html/Assets/canopyx-record-panel.js +2 -2
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +98 -54
- package/CanopyX.Html/Assets/canopyx-reporting.css +214 -276
- package/CanopyX.Html/Assets/canopyx-reporting.js +98 -54
- 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/grid.d.ts +26 -3
- 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/README.md +6 -2
- package/package.json +5 -1
|
@@ -1,24 +1,7 @@
|
|
|
1
|
-
/*
|
|
1
|
+
/* Shared semantic tokens are bundled by Sync-Assets.ps1. Only component geometry lives here. */
|
|
2
2
|
.cx-host,.cx-static{
|
|
3
|
-
--cx-
|
|
4
|
-
--cx-
|
|
5
|
-
--cx-accent:#11776f;
|
|
6
|
-
--cx-line:#e2e4e7;
|
|
7
|
-
--cx-tone-info:#0a728b;
|
|
8
|
-
--cx-tone-success:#177345;
|
|
9
|
-
--cx-tone-warning:#8c5c05;
|
|
10
|
-
--cx-tone-danger:#b8292a;
|
|
11
|
-
--cx-font:Calibri,Carlito,"Segoe UI",system-ui,sans-serif;
|
|
12
|
-
--cx-font-mono:"IBM Plex Mono","Cascadia Mono",Consolas,monospace;
|
|
13
|
-
--cx-font-size:14px;
|
|
14
|
-
--cx-radius:6px;
|
|
15
|
-
--cx-radius-sm:4px;
|
|
16
|
-
--cx-control-h:32px;
|
|
17
|
-
--cx-row-h:28px;
|
|
18
|
-
--cx-head-h:36px;
|
|
19
|
-
--cx-cell-px:12px;
|
|
20
|
-
--cx-on-accent:#ffffff;
|
|
21
|
-
--cx-shadow-ink:#000;
|
|
3
|
+
--cx-compact:0;
|
|
4
|
+
--cx-row-h:var(--hfx-row-height,calc(40px - var(--cx-compact,0) * 8px));
|
|
22
5
|
--cx-size-d04em:.04em;
|
|
23
6
|
--cx-size-46ch:46ch;
|
|
24
7
|
--cx-size-440px:440px;
|
|
@@ -90,59 +73,11 @@
|
|
|
90
73
|
--cx-size-d875em:.875em;
|
|
91
74
|
--cx-size-92px:92px;
|
|
92
75
|
--cx-size-28px:28px;
|
|
93
|
-
--cx-
|
|
94
|
-
--cx-
|
|
95
|
-
--cx-
|
|
96
|
-
--cx-head-bg:color-mix(in srgb,var(--cx-text) 3.5%,var(--cx-surface));
|
|
97
|
-
--cx-group-bg:color-mix(in srgb,var(--cx-text) 2.5%,var(--cx-surface));
|
|
98
|
-
--cx-alt-bg:var(--cx-group-bg);
|
|
99
|
-
--cx-hover-bg:color-mix(in srgb,var(--cx-text) 4%,var(--cx-surface));
|
|
100
|
-
--cx-selected-bg:color-mix(in srgb,var(--cx-accent) 11%,var(--cx-surface));
|
|
101
|
-
--cx-accent-text:color-mix(in srgb,var(--cx-accent) 98%,var(--cx-text));
|
|
102
|
-
--cx-accent-soft:color-mix(in srgb,var(--cx-accent) 13%,var(--cx-surface));
|
|
103
|
-
--cx-line-strong:color-mix(in srgb,var(--cx-text) 22%,var(--cx-surface));
|
|
104
|
-
--cx-row-line:var(--cx-line);
|
|
105
|
-
--cx-panel-shadow:0 8px 28px color-mix(in srgb,var(--cx-shadow-ink) 14%,transparent),0 1px 3px color-mix(in srgb,var(--cx-shadow-ink) 8%,transparent);
|
|
106
|
-
--cx-tone-danger-bg:color-mix(in srgb,var(--cx-tone-danger) 11%,var(--cx-surface));
|
|
107
|
-
--cx-tone-warning-bg:color-mix(in srgb,var(--cx-tone-warning) 13%,var(--cx-surface));
|
|
108
|
-
--cx-tone-success-bg:color-mix(in srgb,var(--cx-tone-success) 11%,var(--cx-surface));
|
|
109
|
-
--cx-tone-info-bg:color-mix(in srgb,var(--cx-tone-info) 11%,var(--cx-surface));
|
|
110
|
-
--cx-quiet:color-mix(in srgb,var(--cx-tone-success) 55%,var(--cx-surface));
|
|
111
|
-
--cx-scrollbar-thumb:color-mix(in srgb,var(--cx-text) 28%,transparent);
|
|
112
|
-
--cx-scrollbar-thumb-hover:color-mix(in srgb,var(--cx-text) 46%,transparent);
|
|
76
|
+
--cx-size-1px:1px;--cx-size-neg-1px:-1px;
|
|
77
|
+
--cx-scrollbar-thumb:color-mix(in srgb,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)) 28%,transparent);
|
|
78
|
+
--cx-scrollbar-thumb-hover:color-mix(in srgb,var(--hfx-color-text,light-dark(#16181c,#f2f3f5)) 46%,transparent);
|
|
113
79
|
--cx-scrollbar-track:transparent;
|
|
114
80
|
--cx-scrollbar-size:10px;
|
|
115
|
-
color-scheme:light;
|
|
116
|
-
}
|
|
117
|
-
.cx-host[data-cx-theme="dark"],.cx-static[data-cx-theme="dark"]{
|
|
118
|
-
color-scheme:dark;
|
|
119
|
-
--cx-surface:#16181c;
|
|
120
|
-
--cx-text:#f2f3f5;
|
|
121
|
-
--cx-accent:#37c9b8;
|
|
122
|
-
--cx-line:#272a30;
|
|
123
|
-
--cx-tone-info:#3ec3dd;
|
|
124
|
-
--cx-tone-success:#4cc78a;
|
|
125
|
-
--cx-tone-warning:#eeb640;
|
|
126
|
-
--cx-tone-danger:#f47171;
|
|
127
|
-
--cx-on-accent:#0c0d10;
|
|
128
|
-
--cx-head-bg:color-mix(in srgb,var(--cx-text) 4.5%,var(--cx-surface));
|
|
129
|
-
--cx-panel-shadow:0 10px 32px color-mix(in srgb,var(--cx-shadow-ink) 55%,transparent),0 0 0 1px var(--cx-line);
|
|
130
|
-
}
|
|
131
|
-
@media (prefers-color-scheme:dark){
|
|
132
|
-
.cx-host[data-cx-theme="auto"],.cx-static[data-cx-theme="auto"]{
|
|
133
|
-
color-scheme:dark;
|
|
134
|
-
--cx-surface:#16181c;
|
|
135
|
-
--cx-text:#f2f3f5;
|
|
136
|
-
--cx-accent:#37c9b8;
|
|
137
|
-
--cx-line:#272a30;
|
|
138
|
-
--cx-tone-info:#3ec3dd;
|
|
139
|
-
--cx-tone-success:#4cc78a;
|
|
140
|
-
--cx-tone-warning:#eeb640;
|
|
141
|
-
--cx-tone-danger:#f47171;
|
|
142
|
-
--cx-on-accent:#0c0d10;
|
|
143
|
-
--cx-head-bg:color-mix(in srgb,var(--cx-text) 4.5%,var(--cx-surface));
|
|
144
|
-
--cx-panel-shadow:0 10px 32px color-mix(in srgb,var(--cx-shadow-ink) 55%,transparent),0 0 0 1px var(--cx-line);
|
|
145
|
-
}
|
|
146
81
|
}
|
|
147
82
|
.cx-host{
|
|
148
83
|
box-sizing:border-box;
|
|
@@ -150,10 +85,10 @@ display:flex;
|
|
|
150
85
|
flex-direction:column;
|
|
151
86
|
height:var(--cx-size-480px);
|
|
152
87
|
min-height:0;
|
|
153
|
-
color:var(--
|
|
154
|
-
background:var(--
|
|
155
|
-
font-family:var(--
|
|
156
|
-
font-size:var(--
|
|
88
|
+
color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));
|
|
89
|
+
background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));
|
|
90
|
+
font-family:var(--hfx-font-sans,"Segoe UI Variable Text","Segoe UI",system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif);
|
|
91
|
+
font-size:var(--hfx-control-font-size,calc(var(--hfx-type-body-size,0.875rem) - var(--cx-compact,0) * .0625rem));
|
|
157
92
|
line-height:1.4;
|
|
158
93
|
}
|
|
159
94
|
.cx-host *,.cx-host *::before,.cx-host *::after{box-sizing:border-box;}
|
|
@@ -165,7 +100,7 @@ line-height:1.4;
|
|
|
165
100
|
:where(.cx-host,.cx-host *){scrollbar-color:var(--cx-scrollbar-thumb) var(--cx-scrollbar-track);scrollbar-width:thin;}
|
|
166
101
|
.cx-host::-webkit-scrollbar,.cx-host ::-webkit-scrollbar{width:var(--cx-scrollbar-size);height:var(--cx-scrollbar-size);}
|
|
167
102
|
.cx-host::-webkit-scrollbar-track,.cx-host ::-webkit-scrollbar-track,.cx-host ::-webkit-scrollbar-corner{background:var(--cx-scrollbar-track);}
|
|
168
|
-
.cx-host::-webkit-scrollbar-thumb,.cx-host ::-webkit-scrollbar-thumb{background:var(--cx-scrollbar-thumb) padding-box;border:var(--cx-size-2px) solid transparent;border-radius:var(--
|
|
103
|
+
.cx-host::-webkit-scrollbar-thumb,.cx-host ::-webkit-scrollbar-thumb{background:var(--cx-scrollbar-thumb) padding-box;border:var(--cx-size-2px) solid transparent;border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));}
|
|
169
104
|
.cx-host ::-webkit-scrollbar-thumb:hover{background-color:var(--cx-scrollbar-thumb-hover);}
|
|
170
105
|
}
|
|
171
106
|
.cx-sr-only{
|
|
@@ -174,6 +109,12 @@ position:absolute !important;
|
|
|
174
109
|
width:var(--cx-size-1px);height:var(--cx-size-1px);padding:0;margin:var(--cx-size-neg-1px);
|
|
175
110
|
overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
|
|
176
111
|
}
|
|
112
|
+
.cx-host[data-cx-density="compact"]{--cx-compact:1;}
|
|
113
|
+
@layer hfx.fallbacks{
|
|
114
|
+
:where([data-cx-fallback-mode="auto"],.cx-static[data-theme="auto"],.cx-static[data-cx-theme="auto"]){color-scheme:light dark;}
|
|
115
|
+
:where([data-cx-fallback-mode="light"],.cx-static[data-theme="light"],.cx-static[data-cx-theme="light"]){color-scheme:light;}
|
|
116
|
+
:where([data-cx-fallback-mode="dark"],.cx-static[data-theme="dark"],.cx-static[data-cx-theme="dark"]){color-scheme:dark;}
|
|
117
|
+
}
|
|
177
118
|
.cx-host.cx-flow-host{min-height:0;display:block;background:transparent;}
|
|
178
119
|
.cx-host:where(.cx-flow-host:not([data-cx-height])){height:auto;}
|
|
179
120
|
body.cx-page > .cx-host.cx-flow-host:not([data-cx-height]),body.cx-page > .cx-main > .cx-host.cx-flow-host:not([data-cx-height]){height:auto;padding:0;}
|
|
@@ -17,6 +17,12 @@ function trusted(kind,value){if(trustPolicy===undefined){try{trustPolicy=global.
|
|
|
17
17
|
catch(_){trustPolicy=null}}
|
|
18
18
|
return trustPolicy?trustPolicy["create"+kind](value):value}
|
|
19
19
|
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.")}
|
|
20
|
+
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;let mode=null;if(!parent?.getPropertyValue("--hfx-color-surface").trim()){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}}}
|
|
21
|
+
if(parent?.getPropertyValue("--hfx-color-surface").trim()||!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}
|
|
22
|
+
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)}
|
|
23
|
+
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)}
|
|
24
|
+
return copied}
|
|
25
|
+
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}
|
|
20
26
|
function boundedPattern(source,exact=true,whole=false){const bad=()=>{throw new Error("CanopyX: pattern requires literals, character classes and at most one variable repetition anchored at the start; groups, alternatives and backreferences are unsupported.")};if(typeof source!=="string"||source.length>256)bad();let width=0,variable=0;for(let i=0;i<source.length;){const unit=source[i++];if(unit==="^"&&i===1||unit==="$"&&i===source.length)continue;if(unit==="\\"){const escape=source[i++];if(!escape||!/^[dDsSwWbBnrtfv\\.^$*+?{}\[\]()|/]$/.test(escape)) bad();
|
|
21
27
|
}else if(unit==="["){let closed=false;while(i<source.length){const c=source[i++];if(c==="\\"){const escape=source[i++];if(!escape||!/^[dDsSwWbnrtfv\\.^$*+?{}\[\]()|/-]$/.test(escape)) bad(); }
|
|
22
28
|
else if(c==="]"){closed=true;break}}
|
|
@@ -52,7 +58,7 @@ function gridDateInputMoment(text,local){const match=/^(\d{4})-(\d{2})-(\d{2})T(
|
|
|
52
58
|
if(!match)return null;const moment=gridMomentFromParts(Number(match[1]),Number(match[2]),Number(match[3]),Number(match[4]),Number(match[5]),Number(match[6]||0),local);if(moment)moment.setTime(moment.getTime()+ Number((match[7]||"").padEnd(3,"0")));return moment}
|
|
53
59
|
function gridFreeze(value){if(value&&typeof value==="object"&&!Object.isFrozen(value)){Object.values(value).forEach(gridFreeze);Object.freeze(value)}
|
|
54
60
|
return value}
|
|
55
|
-
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"forms":["
|
|
61
|
+
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"forms":["0d77c25f4fa14425","canopyx-forms.3b18e30a2aeb56dd.js","canopyx-forms.e3a0e1f016287057.css"],"flow":["e7dea789e4893860","canopyx-flow.bce98a6e89aa358e.js","canopyx-flow.68af38159226dd08.css"],"flow-host":["6f335df747cc5f05","canopyx-flow-host.ea0be90307b19d0f.js","canopyx-flow-host.87b00b9ed5899f1f.css"],"flow-checks":["3ca22040c60d5689","canopyx-flow-checks.7856290d3c486f84.js","canopyx-flow-checks.d3b182bf1d633e48.css"],"flow-options":["60450342239ded26","canopyx-flow-options.d31458a54aa4b1e7.js"],"flow-pick":["e5f79a9e81e93898","canopyx-flow-pick.e17b209908086225.js","canopyx-flow-pick.7ec005490120da23.css"],"flow-records":["d02b7dc1c7f75805","canopyx-flow-records.5efc3b14cf70b524.js","canopyx-flow-records.cf62ae7260a46ec4.css"],"flow-drafts":["40dc8e50169fa271","canopyx-flow-drafts.67fb3ab7fbc22606.js","canopyx-flow-drafts.f8535eb8992ea36a.css"],"flow-preview":["3d8ffe456323db95","canopyx-flow-preview.4731603add2f8e84.js","canopyx-flow-preview.f1c740bc97130a7d.css"],"flow-command":["a6c75cf736c93444","canopyx-flow-command.f3608c38cc18f333.js","canopyx-flow-command.279d6ad310e39e97.css"],"flow-tasks":["8d9ea504e81e8fcd","canopyx-flow-tasks.eeb43b791491b43b.js","canopyx-flow-tasks.5c0dc5743e02c670.css"],"flow-dialog":["a9b5bce11baa2499","canopyx-flow-dialog.271f746b459ec0da.js","canopyx-flow-dialog.7f5a8ca5841006af.css"],"flow-links":["2c14b19c9236e90d","canopyx-flow-links.7b6cfe42d28b6067.js"],"flow-endpoint":["f5cddfc9545e0920","canopyx-flow-endpoint.b31146202bd76aac.js"],"flow-consent":["22121778bc0d07c5","canopyx-flow-consent.749b97f13039bc71.js","canopyx-flow-consent.9f6580d3673ae8bf.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
|
|
56
62
|
function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
|
|
57
63
|
part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
|
|
58
64
|
function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
|
|
@@ -66,8 +72,8 @@ const partQueue=global.CanopyXParts=global.CanopyXParts||[];partQueue.forEach(en
|
|
|
66
72
|
const FORMS_IMPL={},FLOW_IMPL={},activeFlows=new WeakMap();const FORMS_PART=definePart(FlowHost,"forms","forms",()=>({FORMS_IMPL,h,setText,fill,gridFreeze,gridMomentFromParts,boundedPattern,foldText}));const FLOW_VIEWS=typeof FLOW_GRID_VIEWS==="object"?FLOW_GRID_VIEWS:Object.freeze({grid:null,tree:null,reporting:false});const FLOW_PART=definePart(FlowHost,"flow","flow view",()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,foldText,boundedPattern,numberFormat,gridFreeze}));const FLOW_FEATURES={};for(const name of["host","checks","options","pick","records","drafts","preview","command","tasks","dialog","links","endpoint","consent"])
|
|
67
73
|
FLOW_FEATURES[name]=definePart(FlowHost,"flow-"+name,"flow "+name,()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat,FLOW_VIEWS}));if(typeof DataGrid==="function")DataGrid.prototype.parts.forms=FORMS_PART;const FLOW_DOC_PARTS={command:"command",presets:"drafts",draft:"drafts",deepLinks:"links",endpoint:"endpoint"},FLOW_DOC_PLAIN={draft:"none",deepLinks:false};function flowFeatures(doc,hooks){const names=new Set(),add=(name,on)=>on&&names.add(name),list=value=>Array.isArray(value)?value:[];const object=value=>value!==null&&typeof value==="object"&&!Array.isArray(value),has=(value,...keys)=>object(value)&&keys.some(key=>value[key]!==undefined);for(const[key,name]of Object.entries(FLOW_DOC_PARTS))add(name,doc[key]!==undefined&&doc[key]!==FLOW_DOC_PLAIN[key]);add("tasks",doc.mode==="tasks");add("dialog",has(doc.layout,"launch")||has(doc.layout,"container")&&doc.layout.container!=="inline");add("preview",list(doc.endpoint?.routes).includes("preview"));for(const step of list(doc.steps).filter(object)){add("checks",step.checks!==undefined);add("pick",step.type==="pick");add("preview",step.preview===true);add("consent",has(step,"confirm","acknowledge"));for(const block of[step,...list(step.sections)]){if(block!==step)add("options",has(block,"source","dependsOn"));for(const field of object(block)?list(block.fields):[]){add("options",has(field,"dependsOn")||has(field,"source")&&field.source!=="document");add("records",object(field)&&field.type==="records")}}}
|
|
68
74
|
hooks=object(hooks)?hooks:{};return{required:[...names],optional:[typeof hooks.preview==="function"&&"preview",object(hooks.presetStore)&&"drafts"].filter(name=>name&&!names.has(name))}}
|
|
69
|
-
const FLOW_ASYNC_METHODS=["next","back","goTo","setState","validate","submit","runCheck","refreshOptions","saveDraft","setPreset"];const FLOW_SYNC_METHODS=["getStep","getValues","setValues","getState","isDirty","reset","setFieldError","setProgress","complete","setStepState","open","close"];function createFlow(host,options){if(!host||!options||!options.flow||typeof options.flow!=="object")throw new Error("CanopyX: createFlow needs a host element and a flow document.");const existing=activeFlows.get(host);if(existing)return existing;let impl=null,destroyed=false,mountError=null;const destroyedError=()=>new Error("CanopyX: this flow has been destroyed.");const requireImpl=name=>{if(destroyed)throw destroyedError();if(!impl)throw new Error("CanopyX: flow is not ready; await api.ready before calling "+name+"().");return impl};const editors=Object.assign({},...[...PLUGINS.values()].map(item=>item.editors||{}));const{required,optional}=flowFeatures(options.flow,options.hooks);const ready=Promise.all([loadPart(FLOW_PART),...required.map(name=>loadPart(FLOW_FEATURES[name])),...optional.map(name=>loadPart(FLOW_FEATURES[name])
|
|
70
|
-
.catch(error=>host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error,hook:"part"},bubbles:true}))))]).then(async()=>{if(destroyed)throw destroyedError();impl=FLOW_IMPL.create(host,options,editors);return impl.ready});const api={element:host,flow:options.flow,view:options.flow};for(const name of FLOW_SYNC_METHODS)api[name]=(...args)=>requireImpl(name)[name](...args);for(const name of FLOW_ASYNC_METHODS)api[name]=(...args)=>{if(destroyed)return Promise.reject(destroyedError());return ready.then(()=>requireImpl(name)[name](...args))};api.ready=ready.then(()=>{if(destroyed)throw destroyedError();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;try{impl?.destroy()}
|
|
75
|
+
const FLOW_ASYNC_METHODS=["next","back","goTo","setState","validate","submit","runCheck","refreshOptions","saveDraft","setPreset"];const FLOW_SYNC_METHODS=["getStep","getValues","setValues","getState","isDirty","reset","setFieldError","setProgress","complete","setStepState","open","close"];function createFlow(host,options){if(!host||!options||!options.flow||typeof options.flow!=="object")throw new Error("CanopyX: createFlow needs a host element and a flow document.");const existing=activeFlows.get(host);if(existing)return existing;const disposeTheme=watchTheme(host);let impl=null,destroyed=false,mountError=null;const destroyedError=()=>new Error("CanopyX: this flow has been destroyed.");const requireImpl=name=>{if(destroyed)throw destroyedError();if(!impl)throw new Error("CanopyX: flow is not ready; await api.ready before calling "+name+"().");return impl};const editors=Object.assign({},...[...PLUGINS.values()].map(item=>item.editors||{}));const{required,optional}=flowFeatures(options.flow,options.hooks);const ready=Promise.all([loadPart(FLOW_PART),...required.map(name=>loadPart(FLOW_FEATURES[name])),...optional.map(name=>loadPart(FLOW_FEATURES[name])
|
|
76
|
+
.catch(error=>host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error,hook:"part"},bubbles:true}))))]).then(async()=>{if(destroyed)throw destroyedError();impl=FLOW_IMPL.create(host,options,editors);return impl.ready});const api={element:host,flow:options.flow,view:options.flow};for(const name of FLOW_SYNC_METHODS)api[name]=(...args)=>requireImpl(name)[name](...args);for(const name of FLOW_ASYNC_METHODS)api[name]=(...args)=>{if(destroyed)return Promise.reject(destroyedError());return ready.then(()=>requireImpl(name)[name](...args))};api.ready=ready.then(()=>{if(destroyed)throw destroyedError();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;disposeTheme();try{impl?.destroy()}
|
|
71
77
|
finally{impl=null;mountError?.remove();if(activeFlows.get(host)===api){activeFlows.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");host.removeAttribute("data-cx-ready");host.removeAttribute("data-cx-error");host.classList.remove("cx-flow-host")}}};ready.catch(error=>{if(destroyed)return;const notice=mountError=h("div","cx-mount-error");notice.setAttribute("role","alert");setText(notice,error&&error.message?error.message:String(error));host.appendChild(notice);host.setAttribute("data-cx-error",notice.textContent);host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});Object.freeze(api);activeFlows.set(host,api);host.classList.add("cx-host","cx-flow-host");host.setAttribute("data-canopyx-mounted","true");host.canopyx=api;return api}
|
|
72
78
|
const FLOW_API={createFlow};const configured=new Map();const flowId=value=>typeof value==="string"&&/^[A-Za-z][A-Za-z0-9_-]{0,63}$/.test(value);
|
|
73
79
|
function configure(id,options){if(!flowId(id)||!options||typeof options!=="object")throw new Error("CanopyX: configure needs a flow id and an options object.");if([...document.querySelectorAll("[data-canopyx-mounted]")].some(host=>host.canopyx?.view?.id===id))
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* Flow-host part: what the host-connected parts share,loading lines and quiet buttons. Each feature part brings its own */
|
|
2
|
-
.cx-flow-loading{margin-top:var(--cx-size-4px);font-size:var(--cx-size-13px);color:var(--
|
|
3
|
-
.cx-flow-loading.cx-flow-error{color:var(--
|
|
4
|
-
.cx-flow-btn.cx-flow-quiet{border-color:transparent;background:transparent;color:var(--
|
|
5
|
-
.cx-flow-btn.cx-flow-quiet:hover{background:var(--
|
|
2
|
+
.cx-flow-loading{margin-top:var(--cx-size-4px);font-size:var(--cx-size-13px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
|
|
3
|
+
.cx-flow-loading.cx-flow-error{color:var(--hfx-color-status-bad-fg,light-dark(#b8292a,#f47171));}
|
|
4
|
+
.cx-flow-btn.cx-flow-quiet{border-color:transparent;background:transparent;color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));}
|
|
5
|
+
.cx-flow-btn.cx-flow-quiet:hover{background:var(--hfx-color-hover,light-dark(#f5f5f5,#232529));color:var(--hfx-color-text,light-dark(#16181c,#f2f3f5));}
|
|
@@ -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:"6f335df747cc5f05",requires:["flow"],install(context){if(installed.has(context.FLOW_IMPL))return;const{FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat}=context;const{FlowView,FLOW_HOST,FLOW_LABELS,flowFail,flowIs,flowKeys,flowName,flowString,flowFlag,flowScalar,flowFits,flowField,flowOptions,flowCondition,flowRefs,flowTest,flowCopy,flowSameValue,flowEmpty,flowNormal,flowDate,flowFieldView}=FLOW_IMPL.core;const FLOW_PART_LABELS={flowTimedOut:"The host did not answer in time.",flowNoHostHook:"No host answers this.",flowRetry:"Try again",flowCancel:"Cancel"};Object.assign(FLOW_LABELS,FLOW_PART_LABELS);const FLOW_HOST_HOOKS=["options","fields","check","preview","status"],FLOW_HOST_GROUPS=["commands","draftStore","presetStore","pickers"];const FLOW_HOST_CALLBACKS=["onCheck","onLeaving","formatLink","parseLink"];const flowEmit=FlowView.prototype.emit,flowRestore=FlowView.prototype.setState;Object.assign(FlowView.prototype,{emit(name,detail,callback,cancelable){const go=flowEmit.call(this,name,detail,callback,cancelable);if(name==="flowValueChanged")this.afterChange(this.model.fields.get(detail.field));return go},setState(state){const before=new Map(this.values),moved=flowRestore.call(this,state);for(const field of[...this.model.fields.values()])if(!flowSameValue(before.get(field.id),this.values.get(field.id)))this.afterChange(field);this.refreshVisibility();return moved},hostState(){if(!this.checkHostOptions(this.options,this.options.hooks??{}))flowFail("invalid flow options");this.optionState=new Map();this.checkState=new Map();this.pickers=new Map();this.stepStatus=new Map();this.timeout=this.options.timeout??30000},checkHostOptions(options,hooks){return!(FLOW_HOST_HOOKS.some(name=>hooks[name]!=null&&typeof hooks[name]!=="function")||FLOW_HOST_GROUPS.some(name=>hooks[name]!=null&&!flowIs(hooks[name]))||
|
|
2
2
|
FLOW_HOST_CALLBACKS.some(name=>options[name]!=null&&typeof options[name]!=="function")||options.timeout!=null&&!(Number.isInteger(options.timeout)&&options.timeout>=100&&options.timeout<=600000)||
|
|
3
3
|
options.headers!=null&&!(flowIs(options.headers)&&Object.values(options.headers).every(value=>typeof value==="string")))},timed(name,run,controller=new AbortController()){const relay=()=>controller.abort(),lifetime=this.lifetime.signal;lifetime.addEventListener("abort",relay,{once:true});let timer=0,cancel;const cancelled=new Promise(resolve=>{cancel=()=>resolve({cancelled:true})});controller.signal.addEventListener("abort",cancel,{once:true});if(lifetime.aborted)controller.abort();if(controller.signal.aborted)cancel();const expired=new Promise(resolve=>{timer=setTimeout(()=>{const error=new Error(this.labels.flowTimedOut);this.report(error,name);resolve({failed:error.message,timedOut:true});controller.abort()},this.timeout)});const work=Promise.resolve().then(()=>controller.signal.aborted?undefined:run(controller.signal)).then(value=>({value}),error=>{if(controller.signal.aborted)return{cancelled:true};this.report(error,name);return{failed:error&&error.message?error.message:String(error)}});return Promise.race([work,cancelled,expired]).finally(()=>{clearTimeout(timer);lifetime.removeEventListener("abort",relay);controller.signal.removeEventListener("abort",cancel)})},afterChange(field){if(!field||this.destroyed||!this.checkState)return;this.checksChanged?.(field);for(const other of[...this.model.fields.values()])if(other.dependsOn.includes(field.id))this.dependentChanged?.(other);for(const step of this.model.steps)for(const block of step.blocks)if(block.section?.host&&block.section.dependsOn.includes(field.id)&&(this.sections.has(step.id)||this.sectionState?.has(block.section.id)))this.loadFields(step,block);this.markPreset?.();this.draftChanged?.()},setAnswer(field,value,source){const previous=this.values.get(field.id)??null;this.answersChanged();this.values.set(field.id,flowCopy(value));this.forgetHost(field);this.fields.get(field.id)?.mount(flowCopy(value));this.errors.delete(field.id);this.fields.get(field.id)?.message(null);this.emit("flowValueChanged",{field:field.id,value:flowCopy(value),previous:flowCopy(previous),source},"onValueChange");this.refreshVisibility();this.refreshReview()},startHostFeatures(){this.loadPresets?.();this.loadDraft?.();this.startLinks?.()},stepMoved(){if(this.checkState){this.draftChanged?.(true);this.linkMoved?.()}},releaseHostWork(){if(!this.checkState)return;for(const state of this.optionState.values())state.controller?.abort();for(const state of this.sectionState?.values()||[])state.controller?.abort();for(const state of this.checkState.values())state.controller?.abort();this.previewController?.abort();this.statusController?.abort();for(const picker of this.pickers.values()){try{picker.api?.destroy()}catch(error){this.report(error,"picker")}}
|
|
4
4
|
this.optionState.clear();this.sectionState?.clear();this.checkState.clear();this.pickers.clear();clearTimeout(this.draftTimer);this.preset=null}});installed.add(context.FLOW_IMPL)}};(global.CanopyXParts||=[]).push(["flow-host",part])})(typeof window!=="undefined"?window:globalThis);
|
|
@@ -19,6 +19,12 @@ function trusted(kind,value){if(trustPolicy===undefined){try{trustPolicy=global.
|
|
|
19
19
|
catch(_){trustPolicy=null}}
|
|
20
20
|
return trustPolicy?trustPolicy["create"+kind](value):value}
|
|
21
21
|
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.")}
|
|
22
|
+
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;let mode=null;if(!parent?.getPropertyValue("--hfx-color-surface").trim()){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}}}
|
|
23
|
+
if(parent?.getPropertyValue("--hfx-color-surface").trim()||!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}
|
|
24
|
+
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)}
|
|
25
|
+
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)}
|
|
26
|
+
return copied}
|
|
27
|
+
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
28
|
function boundedPattern(source,exact=true,whole=false){const bad=()=>{throw new Error("CanopyX: pattern requires literals, character classes and at most one variable repetition anchored at the start; groups, alternatives and backreferences are unsupported.")};if(typeof source!=="string"||source.length>256)bad();let width=0,variable=0;for(let i=0;i<source.length;){const unit=source[i++];if(unit==="^"&&i===1||unit==="$"&&i===source.length)continue;if(unit==="\\"){const escape=source[i++];if(!escape||!/^[dDsSwWbBnrtfv\\.^$*+?{}\[\]()|/]$/.test(escape)) bad();
|
|
23
29
|
}else if(unit==="["){let closed=false;while(i<source.length){const c=source[i++];if(c==="\\"){const escape=source[i++];if(!escape||!/^[dDsSwWbnrtfv\\.^$*+?{}\[\]()|/-]$/.test(escape)) bad(); }
|
|
24
30
|
else if(c==="]"){closed=true;break}}
|
|
@@ -54,7 +60,7 @@ function gridDateInputMoment(text,local){const match=/^(\d{4})-(\d{2})-(\d{2})T(
|
|
|
54
60
|
if(!match)return null;const moment=gridMomentFromParts(Number(match[1]),Number(match[2]),Number(match[3]),Number(match[4]),Number(match[5]),Number(match[6]||0),local);if(moment)moment.setTime(moment.getTime()+ Number((match[7]||"").padEnd(3,"0")));return moment}
|
|
55
61
|
function gridFreeze(value){if(value&&typeof value==="object"&&!Object.isFrozen(value)){Object.values(value).forEach(gridFreeze);Object.freeze(value)}
|
|
56
62
|
return value}
|
|
57
|
-
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"forms":["
|
|
63
|
+
const PART_URL=typeof document!=="undefined"&&document.currentScript?.src;const PARTS={"forms":["0d77c25f4fa14425","canopyx-forms.3b18e30a2aeb56dd.js","canopyx-forms.e3a0e1f016287057.css"],"flow":["e7dea789e4893860","canopyx-flow.bce98a6e89aa358e.js","canopyx-flow.68af38159226dd08.css"],"flow-host":["6f335df747cc5f05","canopyx-flow-host.ea0be90307b19d0f.js","canopyx-flow-host.87b00b9ed5899f1f.css"],"flow-checks":["3ca22040c60d5689","canopyx-flow-checks.7856290d3c486f84.js","canopyx-flow-checks.d3b182bf1d633e48.css"],"flow-options":["60450342239ded26","canopyx-flow-options.d31458a54aa4b1e7.js"],"flow-pick":["e5f79a9e81e93898","canopyx-flow-pick.e17b209908086225.js","canopyx-flow-pick.7ec005490120da23.css"],"flow-records":["d02b7dc1c7f75805","canopyx-flow-records.5efc3b14cf70b524.js","canopyx-flow-records.cf62ae7260a46ec4.css"],"flow-drafts":["40dc8e50169fa271","canopyx-flow-drafts.67fb3ab7fbc22606.js","canopyx-flow-drafts.f8535eb8992ea36a.css"],"flow-preview":["3d8ffe456323db95","canopyx-flow-preview.4731603add2f8e84.js","canopyx-flow-preview.f1c740bc97130a7d.css"],"flow-command":["a6c75cf736c93444","canopyx-flow-command.f3608c38cc18f333.js","canopyx-flow-command.279d6ad310e39e97.css"],"flow-tasks":["8d9ea504e81e8fcd","canopyx-flow-tasks.eeb43b791491b43b.js","canopyx-flow-tasks.5c0dc5743e02c670.css"],"flow-dialog":["a9b5bce11baa2499","canopyx-flow-dialog.271f746b459ec0da.js","canopyx-flow-dialog.7f5a8ca5841006af.css"],"flow-links":["2c14b19c9236e90d","canopyx-flow-links.7b6cfe42d28b6067.js"],"flow-endpoint":["f5cddfc9545e0920","canopyx-flow-endpoint.b31146202bd76aac.js"],"flow-consent":["22121778bc0d07c5","canopyx-flow-consent.749b97f13039bc71.js","canopyx-flow-consent.9f6580d3673ae8bf.css"]},PART_CODE=new Map(),partName=name=>typeof name==="string"&&/^[a-z][a-z\d-]{0,31}$/.test(name);
|
|
58
64
|
function registerPart(name,part){if(!partName(name)||!part||typeof part.version!=="string"||typeof part.install!=="function"||
|
|
59
65
|
part.requires!==undefined&&!(Array.isArray(part.requires)&&part.requires.every(partName)))throw new Error("CanopyX: invalid part.");PART_CODE.set(name,part)}
|
|
60
66
|
function definePart(View,name,label,context){const parts=View.prototype.parts||={};return parts[name]={name,label,context,parts}}
|
|
@@ -68,8 +74,8 @@ const partQueue=global.CanopyXParts=global.CanopyXParts||[];partQueue.forEach(en
|
|
|
68
74
|
const FORMS_IMPL={},FLOW_IMPL={},activeFlows=new WeakMap();const FORMS_PART=definePart(FlowHost,"forms","forms",()=>({FORMS_IMPL,h,setText,fill,gridFreeze,gridMomentFromParts,boundedPattern,foldText}));const FLOW_VIEWS=typeof FLOW_GRID_VIEWS==="object"?FLOW_GRID_VIEWS:Object.freeze({grid:null,tree:null,reporting:false});const FLOW_PART=definePart(FlowHost,"flow","flow view",()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,foldText,boundedPattern,numberFormat,gridFreeze}));const FLOW_FEATURES={};for(const name of["host","checks","options","pick","records","drafts","preview","command","tasks","dialog","links","endpoint","consent"])
|
|
69
75
|
FLOW_FEATURES[name]=definePart(FlowHost,"flow-"+name,"flow "+name,()=>({FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat,FLOW_VIEWS}));if(typeof DataGrid==="function")DataGrid.prototype.parts.forms=FORMS_PART;const FLOW_DOC_PARTS={command:"command",presets:"drafts",draft:"drafts",deepLinks:"links",endpoint:"endpoint"},FLOW_DOC_PLAIN={draft:"none",deepLinks:false};function flowFeatures(doc,hooks){const names=new Set(),add=(name,on)=>on&&names.add(name),list=value=>Array.isArray(value)?value:[];const object=value=>value!==null&&typeof value==="object"&&!Array.isArray(value),has=(value,...keys)=>object(value)&&keys.some(key=>value[key]!==undefined);for(const[key,name]of Object.entries(FLOW_DOC_PARTS))add(name,doc[key]!==undefined&&doc[key]!==FLOW_DOC_PLAIN[key]);add("tasks",doc.mode==="tasks");add("dialog",has(doc.layout,"launch")||has(doc.layout,"container")&&doc.layout.container!=="inline");add("preview",list(doc.endpoint?.routes).includes("preview"));for(const step of list(doc.steps).filter(object)){add("checks",step.checks!==undefined);add("pick",step.type==="pick");add("preview",step.preview===true);add("consent",has(step,"confirm","acknowledge"));for(const block of[step,...list(step.sections)]){if(block!==step)add("options",has(block,"source","dependsOn"));for(const field of object(block)?list(block.fields):[]){add("options",has(field,"dependsOn")||has(field,"source")&&field.source!=="document");add("records",object(field)&&field.type==="records")}}}
|
|
70
76
|
hooks=object(hooks)?hooks:{};return{required:[...names],optional:[typeof hooks.preview==="function"&&"preview",object(hooks.presetStore)&&"drafts"].filter(name=>name&&!names.has(name))}}
|
|
71
|
-
const FLOW_ASYNC_METHODS=["next","back","goTo","setState","validate","submit","runCheck","refreshOptions","saveDraft","setPreset"];const FLOW_SYNC_METHODS=["getStep","getValues","setValues","getState","isDirty","reset","setFieldError","setProgress","complete","setStepState","open","close"];function createFlow(host,options){if(!host||!options||!options.flow||typeof options.flow!=="object")throw new Error("CanopyX: createFlow needs a host element and a flow document.");const existing=activeFlows.get(host);if(existing)return existing;let impl=null,destroyed=false,mountError=null;const destroyedError=()=>new Error("CanopyX: this flow has been destroyed.");const requireImpl=name=>{if(destroyed)throw destroyedError();if(!impl)throw new Error("CanopyX: flow is not ready; await api.ready before calling "+name+"().");return impl};const editors=Object.assign({},...[...PLUGINS.values()].map(item=>item.editors||{}));const{required,optional}=flowFeatures(options.flow,options.hooks);const ready=Promise.all([loadPart(FLOW_PART),...required.map(name=>loadPart(FLOW_FEATURES[name])),...optional.map(name=>loadPart(FLOW_FEATURES[name])
|
|
72
|
-
.catch(error=>host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error,hook:"part"},bubbles:true}))))]).then(async()=>{if(destroyed)throw destroyedError();impl=FLOW_IMPL.create(host,options,editors);return impl.ready});const api={element:host,flow:options.flow,view:options.flow};for(const name of FLOW_SYNC_METHODS)api[name]=(...args)=>requireImpl(name)[name](...args);for(const name of FLOW_ASYNC_METHODS)api[name]=(...args)=>{if(destroyed)return Promise.reject(destroyedError());return ready.then(()=>requireImpl(name)[name](...args))};api.ready=ready.then(()=>{if(destroyed)throw destroyedError();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;try{impl?.destroy()}
|
|
77
|
+
const FLOW_ASYNC_METHODS=["next","back","goTo","setState","validate","submit","runCheck","refreshOptions","saveDraft","setPreset"];const FLOW_SYNC_METHODS=["getStep","getValues","setValues","getState","isDirty","reset","setFieldError","setProgress","complete","setStepState","open","close"];function createFlow(host,options){if(!host||!options||!options.flow||typeof options.flow!=="object")throw new Error("CanopyX: createFlow needs a host element and a flow document.");const existing=activeFlows.get(host);if(existing)return existing;const disposeTheme=watchTheme(host);let impl=null,destroyed=false,mountError=null;const destroyedError=()=>new Error("CanopyX: this flow has been destroyed.");const requireImpl=name=>{if(destroyed)throw destroyedError();if(!impl)throw new Error("CanopyX: flow is not ready; await api.ready before calling "+name+"().");return impl};const editors=Object.assign({},...[...PLUGINS.values()].map(item=>item.editors||{}));const{required,optional}=flowFeatures(options.flow,options.hooks);const ready=Promise.all([loadPart(FLOW_PART),...required.map(name=>loadPart(FLOW_FEATURES[name])),...optional.map(name=>loadPart(FLOW_FEATURES[name])
|
|
78
|
+
.catch(error=>host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error,hook:"part"},bubbles:true}))))]).then(async()=>{if(destroyed)throw destroyedError();impl=FLOW_IMPL.create(host,options,editors);return impl.ready});const api={element:host,flow:options.flow,view:options.flow};for(const name of FLOW_SYNC_METHODS)api[name]=(...args)=>requireImpl(name)[name](...args);for(const name of FLOW_ASYNC_METHODS)api[name]=(...args)=>{if(destroyed)return Promise.reject(destroyedError());return ready.then(()=>requireImpl(name)[name](...args))};api.ready=ready.then(()=>{if(destroyed)throw destroyedError();return api});api.ready.catch(()=>{});api.destroy=()=>{if(destroyed)return;destroyed=true;disposeTheme();try{impl?.destroy()}
|
|
73
79
|
finally{impl=null;mountError?.remove();if(activeFlows.get(host)===api){activeFlows.delete(host);if(host.canopyx===api)delete host.canopyx;host.removeAttribute("data-canopyx-mounted");host.removeAttribute("data-cx-ready");host.removeAttribute("data-cx-error");host.classList.remove("cx-flow-host")}}};ready.catch(error=>{if(destroyed)return;const notice=mountError=h("div","cx-mount-error");notice.setAttribute("role","alert");setText(notice,error&&error.message?error.message:String(error));host.appendChild(notice);host.setAttribute("data-cx-error",notice.textContent);host.dispatchEvent(new CustomEvent("canopyx:error",{detail:{error},bubbles:true}))});Object.freeze(api);activeFlows.set(host,api);host.classList.add("cx-host","cx-flow-host");host.setAttribute("data-canopyx-mounted","true");host.canopyx=api;return api}
|
|
74
80
|
const FLOW_API={createFlow};const configured=new Map();const flowId=value=>typeof value==="string"&&/^[A-Za-z][A-Za-z0-9_-]{0,63}$/.test(value);
|
|
75
81
|
function configure(id,options){if(!flowId(id)||!options||typeof options!=="object")throw new Error("CanopyX: configure needs a flow id and an options object.");if([...document.querySelectorAll("[data-canopyx-mounted]")].some(host=>host.canopyx?.view?.id===id))
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
.cx-flow-step:has(.cx-flow-type-pick){max-width:none;}
|
|
7
7
|
.cx-flow-pick{display:grid;gap:var(--cx-size-12px);}
|
|
8
8
|
@container (min-width:860px){.cx-flow-pick.cx-flow-pick-tray{grid-template-columns:minmax(0,1fr) var(--cx-size-260px);align-items:start;}}
|
|
9
|
-
.cx-flow-pick-view{min-width:0;border:var(--cx-size-1px) solid var(--
|
|
9
|
+
.cx-flow-pick-view{min-width:0;border:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));overflow:hidden;}
|
|
10
10
|
.cx-flow-pick-view > .cx-host{height:100%;}
|
|
11
|
-
.cx-flow-tray{display:flex;flex-direction:column;gap:var(--cx-size-6px);padding:var(--cx-size-10px) var(--cx-size-12px);border:var(--cx-size-1px) solid var(--
|
|
11
|
+
.cx-flow-tray{display:flex;flex-direction:column;gap:var(--cx-size-6px);padding:var(--cx-size-10px) var(--cx-size-12px);border:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));background:var(--hfx-color-surface-sunken,light-dark(#f7f8f9,#111317));}
|
|
12
12
|
.cx-flow-tray-head{display:flex;align-items:baseline;justify-content:space-between;gap:var(--cx-size-8px);}
|
|
13
13
|
.cx-flow-tray-title{font-size:var(--cx-size-13d5px);font-weight:600;}
|
|
14
14
|
.cx-flow-tray-list{list-style:none;padding:0;display:flex;flex-direction:column;gap:var(--cx-size-4px);max-height:var(--cx-size-320px);overflow:auto;}
|
|
15
|
-
.cx-flow-tray-item{display:flex;align-items:center;gap:var(--cx-size-6px);min-height:var(--cx-size-28px);padding-inline-start:var(--cx-size-8px);border-radius:var(--
|
|
15
|
+
.cx-flow-tray-item{display:flex;align-items:center;gap:var(--cx-size-6px);min-height:var(--cx-size-28px);padding-inline-start:var(--cx-size-8px);border-radius:var(--hfx-radius-sm,4px);background:var(--hfx-color-surface,light-dark(#ffffff,#16181c));}
|
|
16
16
|
.cx-flow-tray-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--cx-size-13d5px);}
|
|
17
17
|
.cx-flow-tray .cx-flow-icon-btn{width:var(--cx-size-28px);height:var(--cx-size-28px);border-color:transparent;background:transparent;font-size:var(--cx-size-16px);}
|
|
18
|
-
.cx-flow-tray-more,.cx-flow-tray-empty{font-size:var(--cx-size-13px);color:var(--
|
|
18
|
+
.cx-flow-tray-more,.cx-flow-tray-empty{font-size:var(--cx-size-13px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
|
|
19
19
|
@media print{.cx-flow-tray .cx-flow-icon-btn{display:none;}}
|
|
@@ -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:"e5f79a9e81e93898",requires:["flow","flow-host"],install(context){if(installed.has(context.FLOW_IMPL))return;const{FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat,FLOW_VIEWS}=context;const{FlowView,FLOW_HOST,FLOW_LABELS,flowFail,flowIs,flowKeys,flowName,flowString,flowFlag,flowScalar,flowFits,flowField,flowOptions,flowCondition,flowRefs,flowTest,flowCopy,flowSameValue,flowEmpty,flowNormal,flowDate,flowFieldView}=FLOW_IMPL.core;const{EDIT_EDITORS,formRuleSpec,formCheck}=FORMS_IMPL;const FLOW_PART_LABELS={flowPickMore:"and {count} more",flowPickCount:"[one]{count} chosen[other]{count} chosen",flowPickChosen:"Chosen",flowPickNone:"Nothing chosen yet.",flowPickOneByOne:"Choose the records one by one or a page at a time."};Object.assign(FLOW_LABELS,FLOW_PART_LABELS);const FLOW_PICK_VISIBLE=60;FLOW_HOST.pick={read(raw,step,model){flowKeys(raw,["field","view","label","tray","height"],"The pick of step "+step.id);if(!flowIs(raw.view)||raw.view.protocol!=="canopyx/2"||!["grid","view"].includes(raw.view.type))flowFail("the pick of step "+step.id+" needs a grid or tree view document");if(raw.tray!==undefined&&typeof raw.tray!=="boolean")flowFail("the tray of step "+step.id+" is true or false");flowKeys(raw.field,["id","label","help","required","when","parameter","path","sensitive","validation","default"],"The field of pick step "+step.id);const field=flowField(Object.assign({},raw.field,{type:"pick"}),step,null,model),columns=Array.isArray(raw.view.columns)?raw.view.columns:[];const label=raw.label??(columns[0]&&columns[0].id);if(typeof label!=="string"||!columns.some(column=>column&&column.id===label))flowFail("the pick of step "+step.id+" needs a label column the view declares");if(raw.height!==undefined&&(!Number.isInteger(raw.height)||raw.height<160||raw.height>1200))flowFail("the pick of step "+step.id+" needs a height of 160 to 1200 pixels");step.pick=Object.freeze({view:raw.view,kind:raw.view.type==="grid"?"grid":"tree",label,tray:raw.tray!==false,height:raw.height??420,field});step.blocks.push({section:null,fields:[field]})},built(view,step,section){if(step.pick?.field.label===step.title)section.querySelector(".cx-flow-label")?.classList.add("cx-flow-label-quiet")},input:(context,field,view)=>flowPickInput(context,field,view),fits:(field,value)=>Array.isArray(value)&&value.length<=1000&&value.every(item=>flowIs(item)&&Object.keys(item).every(key=>key==="id"||key==="label")&&
|
|
2
2
|
typeof item.id==="string"&&item.id.length>0&&item.id.length<=256&&typeof item.label==="string"&&item.label.length<=400)&&new Set(value.map(item=>item.id)).size===value.length,display:(view,value)=>value.slice(0,12).map(item=>item.label||item.id).join("\n")+(value.length>12?"\n"+fill(view.labels.flowPickMore,{count:value.length-12}):"")};const flowAnswer=FlowView.prototype.read;Object.assign(FlowView.prototype,{read(id){const value=flowAnswer.call(this,id);return this.model.fields.get(id)?.type==="pick"&&Array.isArray(value)?value.map(item=>item.id):value}});function flowPickText(cell,fallback){if(cell!==null&&typeof cell==="object")return typeof cell.text==="string"?cell.text:cell.value==null?fallback:String(cell.value);return cell==null?fallback:String(cell)}
|
|
3
3
|
function flowPickInput(context,field,view){const pick=field.step.pick,labels=view.labels,box=h("div","cx-flow-pick" +(pick.tray?" cx-flow-pick-tray":""));let items=(Array.isArray(context.value)?context.value:[]).map(item=>({id:item.id,label:item.label}));let picker=view.pickers.get(field.id);if(!picker)picker=flowPickView(view,field,pick);const changed=()=>box.dispatchEvent(new Event("change",{bubbles:true}));const tray=pick.tray?h("section","cx-flow-tray"):null,trayList=h("ul","cx-flow-tray-list"),trayHead=h("h4","cx-flow-tray-title"),clear=h("button","cx-flow-link");const count=h("p","cx-flow-count");count.setAttribute("aria-live","polite");const paint=()=>{setText(count,fill(plural(labels.flowPickCount,items.length,view.lang),{count:numberFormat(view.lang,0,0).format(items.length)}));if(!tray)return;trayList.replaceChildren(...items.slice(0,FLOW_PICK_VISIBLE).map(item=>{const row=h("li","cx-flow-tray-item"),text=h("span","cx-flow-tray-label"),remove=h("button","cx-flow-icon-btn");setText(text,item.label||item.id);text.title=item.label||item.id;remove.type="button";setText(remove,"×");remove.hidden=context.readOnly;remove.setAttribute("aria-label",fill(labels.flowRemoveItem,{item:item.label||item.id}));remove.addEventListener("click",()=>{const at=items.findIndex(entry=>entry.id===item.id);items=items.filter(entry=>entry.id!==item.id);picker.select(items.map(entry=>entry.id));paint();changed();(trayList.children[Math.min(at,trayList.children.length-1)]?.querySelector("button")||clear).focus()});row.append(text,remove);return row}));if(items.length>FLOW_PICK_VISIBLE){const more=h("li","cx-flow-tray-more");setText(more,fill(labels.flowPickMore,{count:items.length-FLOW_PICK_VISIBLE}));trayList.appendChild(more)}
|
|
4
4
|
clear.hidden=!items.length||context.readOnly;const none=!items.length;trayList.hidden=none;count.hidden=none;tray.querySelector(".cx-flow-tray-empty").hidden=!none};if(tray){setText(trayHead,labels.flowPickChosen);clear.type="button";setText(clear,labels.flowSelectNone);clear.addEventListener("click",()=>{items=[];picker.select([]);paint();changed()});const head=h("div","cx-flow-tray-head"),empty=h("p","cx-flow-tray-empty");setText(empty,labels.flowPickNone);head.append(trayHead,clear);tray.setAttribute("aria-label",labels.flowPickChosen);tray.append(head,count,trayList,empty)}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/* The flow-preview part: the host's preview on the review page. */
|
|
2
|
-
.cx-flow-preview{padding:var(--cx-size-10px) var(--cx-size-14px) var(--cx-size-12px);border-radius:var(--
|
|
2
|
+
.cx-flow-preview{padding:var(--cx-size-10px) var(--cx-size-14px) var(--cx-size-12px);border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));border:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
|
|
3
3
|
.cx-flow-preview .cx-flow-review-title{border-bottom:0;padding-bottom:0;}
|
|
4
4
|
.cx-flow-preview-title{margin-top:var(--cx-size-6px);font-weight:600;}
|
|
5
5
|
.cx-flow-preview-rows .cx-flow-answer{grid-template-columns:minmax(var(--cx-size-140px),36%) minmax(0,1fr);}
|
|
6
|
-
.cx-flow-preview-note{margin-top:var(--cx-size-6px);font-size:var(--cx-size-13px);color:var(--
|
|
7
|
-
.cx-flow-tone-success{color:var(--
|
|
8
|
-
.cx-flow-tone-info{color:var(--
|
|
9
|
-
.cx-flow-tone-warning{color:var(--
|
|
10
|
-
.cx-flow-tone-danger{color:var(--
|
|
6
|
+
.cx-flow-preview-note{margin-top:var(--cx-size-6px);font-size:var(--cx-size-13px);color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));}
|
|
7
|
+
.cx-flow-tone-success{color:var(--hfx-color-status-good-fg,light-dark(#177345,#4cc78a));}
|
|
8
|
+
.cx-flow-tone-info{color:var(--hfx-color-status-info-fg,light-dark(#2b5fc0,#74a2f7));}
|
|
9
|
+
.cx-flow-tone-warning{color:var(--hfx-color-status-warn-fg,light-dark(#8c5c05,#eeb640));font-weight:600;}
|
|
10
|
+
.cx-flow-tone-danger{color:var(--hfx-color-status-bad-fg,light-dark(#b8292a,#f47171));font-weight:600;}
|
|
11
11
|
.cx-flow-step > .cx-flow-preview{margin-top:var(--cx-flow-gap);}
|
|
@@ -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:"3d8ffe456323db95",requires:["flow","flow-host"],install(context){if(installed.has(context.FLOW_IMPL))return;const{FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat}=context;const{FlowView,FLOW_HOST,FLOW_LABELS,flowFail,flowIs,flowKeys,flowName,flowString,flowFlag,flowScalar,flowFits,flowField,flowOptions,flowCondition,flowRefs,flowTest,flowCopy,flowSameValue,flowEmpty,flowNormal,flowDate,flowFieldView}=FLOW_IMPL.core;const{EDIT_EDITORS,formRuleSpec,formCheck}=FORMS_IMPL;const FLOW_PART_LABELS={flowPreview:"Preview",flowPreviewLoading:"Loading the preview…",flowPreviewFailed:"The preview could not load: {message}",flowPreviewNone:"Nothing to preview."};Object.assign(FLOW_LABELS,FLOW_PART_LABELS);const FLOW_PREVIEW_TONES=["info","success","warning","danger"];FLOW_HOST.preview={review(view,section){if(typeof view.hooks.preview==="function")section.appendChild(view.previewBlock())}};Object.assign(FlowView.prototype,{previewBlock(){const labels=this.labels,block=h("section","cx-flow-preview"),heading=h("h4","cx-flow-review-title"),body=h("div","cx-flow-preview-body");heading.id=this.id+"-rp";setText(heading,labels.flowPreview);block.setAttribute("aria-labelledby",heading.id);block.setAttribute("aria-busy","true");const loading=h("p","cx-flow-loading");setText(loading,labels.flowPreviewLoading);body.appendChild(loading);block.append(heading,body);this.previewController?.abort();const controller=this.previewController=new AbortController();this.timed("preview",signal=>this.hooks.preview(this.getValues(),{signal}),controller).then(answer=>{if(this.previewController!==controller||this.destroyed||answer.cancelled)return;block.removeAttribute("aria-busy");if(answer.failed){const failed=h("p","cx-flow-error");setText(failed,fill(labels.flowPreviewFailed,{message:answer.failed}));body.replaceChildren(failed);return}
|
|
2
2
|
body.replaceChildren(...this.previewContent(answer.value))});return block},previewContent(value){const text=item=>typeof item==="string"&&/\S/.test(item) ? item.slice(0, 1000) : null, nodes = [];
|
|
3
3
|
const content=Array.isArray(value)?{rows:value}:flowIs(value)?value:null;if(!content){const none=h("p","cx-flow-none");setText(none,this.labels.flowPreviewNone);return[none]}
|
|
4
4
|
if(text(content.title)){const title=h("p","cx-flow-preview-title");setText(title,text(content.title));nodes.push(title)}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/* The flow-records part: a compact table of editors. */
|
|
2
2
|
.cx-flow-records-scroll{max-width:100%;overflow-x:auto;}
|
|
3
3
|
.cx-flow-records-table{border-collapse:collapse;min-width:min(100%,var(--cx-size-440px));}
|
|
4
|
-
.cx-flow-records-table th{padding:0 var(--cx-size-8px) var(--cx-size-6px) 0;font-size:var(--cx-size-12px);font-weight:600;color:var(--
|
|
4
|
+
.cx-flow-records-table th{padding:0 var(--cx-size-8px) var(--cx-size-6px) 0;font-size:var(--cx-size-12px);font-weight:600;color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));text-align:start;white-space:nowrap;}
|
|
5
5
|
.cx-flow-records-table td{padding:0 var(--cx-size-8px) var(--cx-size-6px) 0;vertical-align:top;}
|
|
6
6
|
.cx-flow-records-table .cx-flow-input{min-width:var(--cx-size-92px);}
|
|
7
|
-
.cx-flow-records-table input[type="checkbox"].cx-flow-input{width:var(--cx-size-18px);min-width:0;height:var(--cx-flow-control);margin:0;accent-color:var(--
|
|
7
|
+
.cx-flow-records-table input[type="checkbox"].cx-flow-input{width:var(--cx-size-18px);min-width:0;height:var(--cx-flow-control);margin:0;accent-color:var(--hfx-color-accent,light-dark(#11776f,#37c9b8));}
|
|
8
8
|
.cx-flow-records-actions{width:var(--cx-flow-control);}
|
|
9
|
-
.cx-flow-records-empty{font-size:var(--cx-size-13px);color:var(--
|
|
9
|
+
.cx-flow-records-empty{font-size:var(--cx-size-13px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
|
|
@@ -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:"d02b7dc1c7f75805",requires:["flow"],install(context){if(installed.has(context.FLOW_IMPL))return;const{FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat}=context;const{FlowView,FLOW_HOST,FLOW_LABELS,flowFail,flowIs,flowKeys,flowName,flowString,flowFlag,flowScalar,flowFits,flowField,flowOptions,flowCondition,flowRefs,flowTest,flowCopy,flowSameValue,flowEmpty,flowNormal,flowDate,flowFieldView}=FLOW_IMPL.core;const{EDIT_EDITORS,formRuleSpec,formCheck}=FORMS_IMPL;const FLOW_PART_LABELS={flowRecordActions:"Actions",flowRecordCell:"{column}, row {row}",flowRecordRemove:"Remove row {row}",flowRecordAdd:"Add row",flowRecordsEmpty:"No rows yet.",flowRecordProblem:"Row {row}: {message}",flowRecordsCount:"[one]{count} row[other]{count} rows"};Object.assign(FLOW_LABELS,FLOW_PART_LABELS);const FLOW_RECORD_TYPES=["text","number","date","time","select","toggle"];function flowRecordColumns(raw,bad){if(!Array.isArray(raw)||!raw.length||raw.length>16)bad("needs 1 to 16 columns");const ids=new Set();return raw.map(column=>{flowKeys(column,["id","title","type","required","options","validation","width"],"A records column");const id=flowName(column.id,"A column id"),type=column.type??"text",rules=column.validation??{};if(ids.has(id))bad("has two columns named "+id);ids.add(id);if(!FLOW_RECORD_TYPES.includes(type))bad("has a column of an unknown type");flowKeys(rules,["min","max","minLength","maxLength","pattern","message"],"The validation of column "+id);if((rules.min!==undefined||rules.max!==undefined)&&type!=="number"||[rules.minLength,rules.maxLength,rules.pattern].some(value=>value!==undefined)&&type!=="text")bad("has checks its column type does not take");if((column.options!==undefined)!==(type==="select")||type==="select"&&!(Array.isArray(column.options)&&column.options.length))bad("needs options as a select column only");if(column.width!==undefined&&(!Number.isInteger(column.width)||column.width<60||column.width>480))bad("needs a column width of 60 to 480 pixels");const required=flowFlag(column.required,"required"),shared=formRuleSpec({},{required,min:rules.min,max:rules.max,minLength:rules.minLength,maxLength:rules.maxLength,pattern:rules.pattern,message:rules.message},bad);return Object.freeze({id,title:flowString(column.title,200,"A column title",true),type,required,width:column.width??null,options:type==="select"?flowOptions(column.options,bad):[],spec:Object.freeze({id,pattern:shared.pattern,rules:shared.rules})})})}
|
|
2
2
|
function flowCellFits(column,value){if(value===null)return true;switch(column.type){case "number":return Number.isFinite(value)&&Math.abs(value)<=Number.MAX_SAFE_INTEGER;case "toggle":return typeof value==="boolean";case "date":return flowFits({type:"date"},value);case "time":return flowFits({type:"time"},value);case "select":return column.options.some(option=>option.value===value);default:return typeof value==="string"&&value.length<=4096}}
|
|
3
3
|
FLOW_HOST.records={columns:flowRecordColumns,fits:(field,value)=>Array.isArray(value)&&value.length<=1000&&value.every(row=>flowIs(row)&&
|
|
4
4
|
Object.keys(row).every(key=>field.columns.some(column=>column.id===key))&&field.columns.every(column=>flowCellFits(column,row[column.id]??null))),input:(context,field,view)=>flowRecordsInput(context,field,view),problem:(view,field,rows)=>flowRecordsProblem(view,field,rows),display:(view,value)=>fill(plural(view.labels.flowRecordsCount,value.length,view.lang),{count:numberFormat(view.lang,0,0).format(value.length)})};function flowRecordsInput(context,field,view){const labels=view.labels,group=h("div","cx-flow-records"),table=h("table","cx-flow-records-table"),head=h("thead"),body=h("tbody");const add=h("button","cx-flow-btn cx-flow-list-add"),rows=[],max=field.items.max??1000;group.setAttribute("role","group");const headRow=h("tr");for(const column of field.columns){const th=h("th");th.scope="col";setText(th,column.title);if(column.width)th.style.width=column.width+"px";if(column.required)th.classList.add("cx-flow-records-required");headRow.appendChild(th)}
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
/* The flow-tasks part: the hub of a task list. */
|
|
2
2
|
.cx-flow-tasks > .cx-flow-rail{display:none;}
|
|
3
|
-
.cx-flow-hub-progress{margin-top:var(--cx-size-4px);color:var(--
|
|
3
|
+
.cx-flow-hub-progress{margin-top:var(--cx-size-4px);color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));font-size:var(--cx-size-13d5px);}
|
|
4
4
|
.cx-flow-step > .cx-flow-task-groups{margin-top:var(--cx-flow-gap);}
|
|
5
5
|
.cx-flow-task-group + .cx-flow-task-group{margin-top:var(--cx-size-16px);}
|
|
6
|
-
.cx-flow-task-list{list-style:none;padding:0;border-top:var(--cx-size-1px) solid var(--
|
|
6
|
+
.cx-flow-task-list{list-style:none;padding:0;border-top:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
|
|
7
7
|
.cx-flow-task-group > .cx-flow-section-title{padding-bottom:var(--cx-size-6px);}
|
|
8
|
-
.cx-flow-task{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:var(--cx-size-2px) var(--cx-size-12px);padding:var(--cx-size-4px) 0;border-bottom:var(--cx-size-1px) solid var(--
|
|
8
|
+
.cx-flow-task{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:var(--cx-size-2px) var(--cx-size-12px);padding:var(--cx-size-4px) 0;border-bottom:var(--cx-size-1px) solid var(--hfx-color-border,light-dark(#e2e4e7,#272a30));}
|
|
9
9
|
.cx-flow-task-open{display:flex;flex-direction:column;align-items:flex-start;gap:var(--cx-size-2px);min-height:var(--cx-size-44px);padding:var(--cx-size-6px) var(--cx-size-8px);margin-inline-start:calc(var(--cx-size-8px) * -1);
|
|
10
|
-
border:0;border-radius:var(--
|
|
11
|
-
.cx-flow-task-open:hover{background:var(--
|
|
12
|
-
.cx-flow-task-open:focus-visible{outline:var(--
|
|
13
|
-
.cx-flow-task-open[aria-disabled="true"]{color:var(--
|
|
10
|
+
border:0;border-radius:var(--hfx-radius-control,var(--hfx-radius-md,6px));background:transparent;color:var(--hfx-color-accent-text,light-dark(#02726a,#37c9b8));font:inherit;text-align:start;cursor:pointer;}
|
|
11
|
+
.cx-flow-task-open:hover{background:var(--hfx-color-hover,light-dark(#f5f5f5,#232529));}
|
|
12
|
+
.cx-flow-task-open:focus-visible{outline:var(--hfx-focus-width,2px) solid var(--hfx-color-focus-ring,light-dark(#02726a,#37c9b8));outline-offset:var(--hfx-focus-offset,2px);}
|
|
13
|
+
.cx-flow-task-open[aria-disabled="true"]{color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));cursor:default;}
|
|
14
14
|
.cx-flow-task-open[aria-disabled="true"]:hover{background:transparent;}
|
|
15
15
|
.cx-flow-task-title{font-weight:600;text-decoration:underline;text-underline-offset:var(--cx-size-2px);}
|
|
16
16
|
.cx-flow-task-open[aria-disabled="true"] .cx-flow-task-title{text-decoration:none;}
|
|
17
|
-
.cx-flow-task-summary{font-size:var(--cx-size-13px);color:var(--
|
|
18
|
-
.cx-flow-task-state{display:inline-flex;align-items:center;gap:var(--cx-size-6px);font-size:var(--cx-size-13px);color:var(--
|
|
17
|
+
.cx-flow-task-summary{font-size:var(--cx-size-13px);color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));}
|
|
18
|
+
.cx-flow-task-state{display:inline-flex;align-items:center;gap:var(--cx-size-6px);font-size:var(--cx-size-13px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));white-space:nowrap;}
|
|
19
19
|
.cx-flow-task-mark{display:inline-flex;align-items:center;justify-content:center;min-width:var(--cx-size-18px);height:var(--cx-size-18px);border-radius:50%;font-size:var(--cx-size-12px);font-weight:700;}
|
|
20
|
-
.cx-flow-task[data-cx-state="complete"] .cx-flow-task-mark{color:var(--
|
|
21
|
-
.cx-flow-task[data-cx-state="complete"] .cx-flow-task-state{color:var(--
|
|
22
|
-
.cx-flow-task[data-cx-state="needsAction"] :is(.cx-flow-task-state,.cx-flow-task-mark){color:var(--
|
|
23
|
-
.cx-flow-task[data-cx-state="needsAction"] .cx-flow-task-mark{background:var(--
|
|
24
|
-
.cx-flow-task[data-cx-state="error"] :is(.cx-flow-task-state,.cx-flow-task-mark){color:var(--
|
|
25
|
-
.cx-flow-task[data-cx-state="error"] .cx-flow-task-mark{background:var(--
|
|
26
|
-
.cx-flow-task-blockers{grid-column:1 / -1;margin:0 0 var(--cx-size-4px);padding-inline-start:var(--cx-size-18px);font-size:var(--cx-size-13px);color:var(--
|
|
27
|
-
.cx-flow-hub-note{font-size:var(--cx-size-13px);color:var(--
|
|
20
|
+
.cx-flow-task[data-cx-state="complete"] .cx-flow-task-mark{color:var(--hfx-color-status-good-fg,light-dark(#177345,#4cc78a));background:var(--hfx-color-status-good-bg,light-dark(#e2f0e9,#1f362f));}
|
|
21
|
+
.cx-flow-task[data-cx-state="complete"] .cx-flow-task-state{color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));}
|
|
22
|
+
.cx-flow-task[data-cx-state="needsAction"] :is(.cx-flow-task-state,.cx-flow-task-mark){color:var(--hfx-color-status-warn-fg,light-dark(#8c5c05,#eeb640));}
|
|
23
|
+
.cx-flow-task[data-cx-state="needsAction"] .cx-flow-task-mark{background:var(--hfx-color-status-warn-bg,light-dark(#f8efde,#3b3322));}
|
|
24
|
+
.cx-flow-task[data-cx-state="error"] :is(.cx-flow-task-state,.cx-flow-task-mark){color:var(--hfx-color-status-bad-fg,light-dark(#b8292a,#f47171));}
|
|
25
|
+
.cx-flow-task[data-cx-state="error"] .cx-flow-task-mark{background:var(--hfx-color-status-bad-bg,light-dark(#f9e4e4,#3c272a));}
|
|
26
|
+
.cx-flow-task-blockers{grid-column:1 / -1;margin:0 0 var(--cx-size-4px);padding-inline-start:var(--cx-size-18px);font-size:var(--cx-size-13px);color:var(--hfx-color-text-secondary,light-dark(#4d525b,#b0b4bc));}
|
|
27
|
+
.cx-flow-hub-note{font-size:var(--cx-size-13px);color:var(--hfx-color-text-muted,light-dark(#626770,#8f949d));}
|
|
28
28
|
.cx-flow-next[aria-disabled="true"]{opacity:.55;cursor:default;}
|
|
29
29
|
@media (forced-colors:active){.cx-flow-task-mark{forced-color-adjust:none;border:var(--cx-size-1px) solid CanvasText;}}
|
|
@@ -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:"8d9ea504e81e8fcd",requires:["flow","flow-host"],install(context){if(installed.has(context.FLOW_IMPL))return;const{FLOW_IMPL,FORMS_IMPL,h,setText,fill,plural,numberFormat}=context;const{FlowView,FLOW_HOST,FLOW_LABELS,flowFail,flowIs,flowKeys,flowName,flowString,flowFlag,flowScalar,flowFits,flowField,flowOptions,flowCondition,flowRefs,flowTest,flowCopy,flowSameValue,flowEmpty,flowNormal,flowDate,flowFieldView}=FLOW_IMPL.core;const{EDIT_EDITORS,formRuleSpec,formCheck}=FORMS_IMPL;const FLOW_PART_LABELS={flowTasks:"Tasks",flowTasksProgress:"{done} of {count} tasks complete",flowTaskNeedsAction:"Needs action",flowTaskBlocked:"Cannot start yet",flowTasksReview:"Review and submit",flowTasksIncomplete:"Complete the required tasks first.",flowBackToTasks:"Back to tasks",flowSaveAndReturn:"Save and return"};Object.assign(FLOW_LABELS,FLOW_PART_LABELS);const FLOW_TASK_STATES=["complete","needsAction","blocked","notStarted"];const FLOW_TASK_MARKS={complete:"✓",error:"!",needsAction:"!",blocked:"—",notStarted:""};function flowTaskOrder(parent,nodes){const wanted=new Set(nodes);for(const child of[...parent.children])if(!wanted.has(child))child.remove();let at=parent.firstChild;for(const node of nodes){if(node===at)at=at.nextSibling;else parent.insertBefore(node,at)}}
|
|
2
2
|
const{back:flowStepBack,goTo:flowStepGoTo,renderStage:flowStepStage,renderRail:flowStepRail,renderActions:flowStepActions,lastStep:flowLastStep,orientation:flowOrientation,begin:flowTaskBegin,setState:flowTaskRestore,submit:flowTaskSubmit,validateAll:flowTaskValidate}=FlowView.prototype;Object.assign(FlowView.prototype,{begin(values){this.hub??=this.model.mode==="tasks"?{id:"#tasks",type:"hub",title:null,asks:false,blocks:[],checks:[]}:null;this.hubNode=undefined;flowTaskBegin.call(this,values)},setState(state){const controller=this.statusController,result=flowTaskRestore.call(this,state);if(controller&&this.statusController===controller&&!this.destroyed&&this.step===this.hub)this.loadStatus();return result},orientation(){return this.hub?"tasks":flowOrientation.call(this)},lastStep(){return this.hub?this.step.type==="review":flowLastStep.call(this)},renderActions(){if(!this.hub||this.phase!=="form")return flowStepActions.call(this);if(this.step===this.hub){this.actions.hidden=false;if(this.hubAction?.go.parentNode!==this.actions){this.actions.replaceChildren();this.hubActions()}
|
|
3
3
|
this.paintHubActions();return}
|
|
4
4
|
flowStepActions.call(this);const back=this.actions.querySelector(".cx-flow-back");setText(back,this.labels.flowBackToTasks);back.hidden=false;if(!this.lastStep())setText(this.actions.querySelector(".cx-flow-next"),this.labels.flowSaveAndReturn)},taskButton(step){return step!==this.hub&&this.stage.querySelector('[data-cx-task="'+CSS.escape(step.id)+ '"] button')},async back(){return this.hub?!this.busy&&this.phase==="form"&&this.step!==this.hub&&this.go(this.hub,"back"):flowStepBack.call(this)},async goTo(id){if(!this.hub)return flowStepGoTo.call(this,id);if(this.busy||this.phase!=="form")return false;if(id===this.hub.id)return this.go(this.hub,"back");const target=this.visibleSteps().find(step=>step.id===id);return target&&this.taskOpens(target)?this.go(target,"forward"):false},renderStage(){if(this.hub&&this.step===this.hub&&this.phase==="form"){if(this.stage.firstChild!==this.hubNode)this.stage.replaceChildren(this.hubSection());else this.paintHub()}else flowStepStage.call(this)},renderRail(){if(!this.hub)return flowStepRail.call(this);if(!this.root)return;this.railKey=this.visibleSteps().map(step=>step.id).join();if(this.step===this.hub&&this.phase==="form")this.paintHub()},tasks(){return this.visibleSteps().filter(step=>step.type!=="review")},counted(step){return step.asks&&!step.optional},taskState(step){const host=this.stepStatus.get(step.id);if(host?.state==="blocked")return "blocked";if(this.stepErrorCount(step))return "error";if(host?.state==="needsAction")return "needsAction";if(host?.state==="complete"||this.completed.has(step.id))return "complete";return "notStarted"},taskOpens(step){return step.type==="review"?this.tasksReady():this.taskState(step)!=="blocked"},tasksReady(){return this.tasks().filter(step=>this.counted(step)).every(step=>this.taskState(step)==="complete")},async submit(){if(this.hub&&!this.tasksReady()){this.announce(this.labels.flowTasksIncomplete);return null}
|