@sortsys/ui 0.1.6 → 0.1.7

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/dist/dev.jsx CHANGED
@@ -1,328 +1,1607 @@
1
- function Y(e){let t=()=>["ss_button",e.isIconOnly?"ss_button--icon":"",e.class??""].filter(Boolean).join(" ");return<button type={e.type??"button"}class={t()}disabled={e.disabled}aria-label={e.ariaLabel}form={e.form}onclick={e.onclick}>
2
- {e.children}
3
- </button>}function Ut(e){let{icon:t,color:n,class:r,style:o,children:s,...l}=e;return<div{...l}class={`ss_callout ss_callout--${n} ${r??""}`}style={o}>
1
+ // src/components/SSButton.tsx
2
+ function SSButton(props) {
3
+ const classes = () => [
4
+ "ss_button",
5
+ props.isIconOnly ? "ss_button--icon" : "",
6
+ props.class ?? ""
7
+ ].filter(Boolean).join(" ");
8
+ return <button
9
+ type={props.type ?? "button"}
10
+ class={classes()}
11
+ disabled={props.disabled}
12
+ aria-label={props.ariaLabel}
13
+ form={props.form}
14
+ onclick={props.onclick}
15
+ >
16
+ {props.children}
17
+ </button>;
18
+ }
19
+
20
+ // src/components/SSCallout.tsx
21
+ function SSCallout(props) {
22
+ const { icon, color, class: className, style, children: children2, ...rest } = props;
23
+ return <div
24
+ {...rest}
25
+ class={`ss_callout ss_callout--${color} ${className ?? ""}`}
26
+ style={style}
27
+ >
4
28
  <span class="ss_callout__icon">
5
- {t}
29
+ {icon}
6
30
  </span>
7
31
  <div class="ss_callout__content">
8
- <span>{s}</span>
32
+ <span>{children2}</span>
9
33
  </div>
10
- </div>}function zt(e){let t=`ss_chip ss_chip--${e.color??"blue"} ${e.class??""}`;return"onclick"in e&&e.onclick?<button type="button"class={`${t} ss_chip--clickable`}style={e.style}onclick={e.onclick}>
11
- <span class="ss_chip__label">{e.children}</span>
12
- </button>:<div class={t}style={e.style}>
13
- <span class="ss_chip__label">{e.children}</span>
14
- {"ondismiss"in e&&e.ondismiss&&<button type="button"class="ss_chip__dismiss"aria-label="Entfernen"onclick={e.ondismiss}>
15
- <svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-x"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M18 6l-12 12"/><path d="M6 6l12 12"/></svg>
34
+ </div>;
35
+ }
36
+
37
+ // src/components/SSChip.tsx
38
+ function SSChip(props) {
39
+ const commonClass = `ss_chip ss_chip--${props.color ?? "blue"} ${props.class ?? ""}`;
40
+ if ("onclick" in props && props.onclick) {
41
+ return <button
42
+ type="button"
43
+ class={`${commonClass} ss_chip--clickable`}
44
+ style={props.style}
45
+ onclick={props.onclick}
46
+ >
47
+ <span class="ss_chip__label">{props.children}</span>
48
+ </button>;
49
+ }
50
+ return <div class={commonClass} style={props.style}>
51
+ <span class="ss_chip__label">{props.children}</span>
52
+ {"ondismiss" in props && props.ondismiss && <button
53
+ type="button"
54
+ class="ss_chip__dismiss"
55
+ aria-label="Entfernen"
56
+ onclick={props.ondismiss}
57
+ >
58
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-x"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M18 6l-12 12" /><path d="M6 6l12 12" /></svg>
16
59
  </button>}
17
- </div>}var T={context:void 0,registry:void 0,effects:void 0,done:!1,getContextId(){return dt(this.context.count)},getNextContextId(){return dt(this.context.count++)}};function dt(e){let t=String(e),n=t.length-1;return T.context.id+(n?String.fromCharCode(96+n):"")+t}function Kt(e){T.context=e}var Wt=!1,Yt=(e,t)=>e===t,Xe=Symbol("solid-proxy"),pt=typeof Proxy=="function",yt=Symbol("solid-track");var qe={equals:Yt},ft=null,vt=Pt,z=1,Fe=2,St={owned:null,cleanups:null,context:null,owner:null},tt={},C=null,h=null,Pe=null,ke=null,O=null,$=null,j=null,Ue=0;function Ee(e,t){let n=O,r=C,o=e.length===0,s=t===void 0?r:t,l=o?St:{owned:null,cleanups:null,context:s?s.context:null,owner:s},i=o?e:()=>e(()=>V(()=>ee(l)));C=l,O=null;try{return U(i,!0)}finally{O=n,C=r}}function S(e,t){t=t?Object.assign({},qe,t):qe;let n={value:e,observers:null,observerSlots:null,comparator:t.equals||void 0},r=o=>(typeof o=="function"&&(h&&h.running&&h.sources.has(n)?o=o(n.tValue):o=o(n.value)),Et(n,o));return[kt.bind(n),r]}function ht(e,t,n){let r=Ke(e,t,!0,z);Pe&&h&&h.running?$.push(r):Te(r)}function G(e,t,n){let r=Ke(e,t,!1,z);Pe&&h&&h.running?$.push(r):Te(r)}function N(e,t,n){vt=en;let r=Ke(e,t,!1,z),o=De&&B(De);o&&(r.suspense=o),(!n||!n.render)&&(r.user=!0),j?j.push(r):Te(r)}function D(e,t,n){n=n?Object.assign({},qe,n):qe;let r=Ke(e,t,!0,0);return r.observers=null,r.observerSlots=null,r.comparator=n.equals||void 0,Pe&&h&&h.running?(r.tState=z,$.push(r)):Te(r),kt.bind(r)}function Gt(e){return e&&typeof e=="object"&&"then"in e}function ot(e,t,n){let r,o,s;typeof t=="function"?(r=e,o=t,s=n||{}):(r=!0,o=e,s=t||{});let l=null,i=tt,c=null,d=!1,u=!1,a="initialValue"in s,m=typeof r=="function"&&D(r),b=new Set,[x,y]=(s.storage||S)(s.initialValue),[k,E]=S(void 0),[L,g]=S(void 0,{equals:!1}),[p,f]=S(a?"ready":"unresolved");T.context&&(c=T.getNextContextId(),s.ssrLoadFrom==="initial"?i=s.initialValue:T.load&&T.has(c)&&(i=T.load(c)));function v(_,P,I,H){return l===_&&(l=null,H!==void 0&&(a=!0),(_===i||P===i)&&s.onHydrated&&queueMicrotask(()=>s.onHydrated(H,{value:P})),i=tt,h&&_&&d?(h.promises.delete(_),d=!1,U(()=>{h.running=!0,F(P,I)},!1)):F(P,I)),P}function F(_,P){U(()=>{P===void 0&&y(()=>_),f(P!==void 0?"errored":a?"ready":"unresolved"),E(P);for(let I of b.keys())I.decrement();b.clear()},!1)}function A(){let _=De&&B(De),P=x(),I=k();if(I!==void 0&&!l)throw I;return O&&!O.user&&_&&ht(()=>{L(),l&&(_.resolved&&h&&d?h.promises.add(l):b.has(_)||(_.increment(),b.add(_)))}),P}function w(_=!0){if(_!==!1&&u)return;u=!1;let P=m?m():r;if(d=h&&h.running,P==null||P===!1){v(l,V(x));return}h&&l&&h.promises.delete(l);let I,H=i!==tt?i:V(()=>{try{return o(P,{value:x(),refetching:_})}catch(xe){I=xe}});if(I!==void 0){v(l,void 0,Ve(I),P);return}else if(!Gt(H))return v(l,H,void 0,P),H;return l=H,"v"in H?(H.s===1?v(l,H.v,void 0,P):v(l,void 0,Ve(H.v),P),H):(u=!0,queueMicrotask(()=>u=!1),U(()=>{f(a?"refreshing":"pending"),g()},!1),H.then(xe=>v(H,xe,void 0,P),xe=>v(H,void 0,Ve(xe),P)))}Object.defineProperties(A,{state:{get:()=>p()},error:{get:()=>k()},loading:{get(){let _=p();return _==="pending"||_==="refreshing"}},latest:{get(){if(!a)return A();let _=k();if(_&&!l)throw _;return x()}}});let M=C;return m?ht(()=>(M=C,w(!1))):w(!1),[A,{refetch:_=>ze(M,()=>w(_)),mutate:y}]}function V(e){if(!ke&&O===null)return e();let t=O;O=null;try{return ke?ke.untrack(e):e()}finally{O=t}}function X(e){N(()=>V(e))}function R(e){return C===null||(C.cleanups===null?C.cleanups=[e]:C.cleanups.push(e)),e}function _t(){return O}function Ce(){return C}function ze(e,t){let n=C,r=O;C=e,O=null;try{return U(t,!0)}catch(o){We(o)}finally{C=n,O=r}}function $e(e){if(h&&h.running)return e(),h.done;let t=O,n=C;return Promise.resolve().then(()=>{O=t,C=n;let r;return(Pe||De)&&(r=h||(h={sources:new Set,effects:[],promises:new Set,disposed:new Set,queue:new Set,running:!0}),r.done||(r.done=new Promise(o=>r.resolve=o)),r.running=!0),U(e,!1),O=C=null,r?r.done:void 0})}var[Lr,mt]=S(!1);function Z(e,t){let n=Symbol("context");return{id:n,Provider:tn(n),defaultValue:e}}function B(e){let t;return C&&C.context&&(t=C.context[e.id])!==void 0?t:e.defaultValue}function xt(e){let t=D(e),n=D(()=>rt(t()));return n.toArray=()=>{let r=n();return Array.isArray(r)?r:r!=null?[r]:[]},n}var De;function kt(){let e=h&&h.running;if(this.sources&&(e?this.tState:this.state))if((e?this.tState:this.state)===z)Te(this);else{let t=$;$=null,U(()=>Je(this),!1),$=t}if(O){let t=this.observers?this.observers.length:0;O.sources?(O.sources.push(this),O.sourceSlots.push(t)):(O.sources=[this],O.sourceSlots=[t]),this.observers?(this.observers.push(O),this.observerSlots.push(O.sources.length-1)):(this.observers=[O],this.observerSlots=[O.sources.length-1])}return e&&h.sources.has(this)?this.tValue:this.value}function Et(e,t,n){let r=h&&h.running&&h.sources.has(e)?e.tValue:e.value;if(!e.comparator||!e.comparator(r,t)){if(h){let o=h.running;(o||!n&&h.sources.has(e))&&(h.sources.add(e),e.tValue=t),o||(e.value=t)}else e.value=t;e.observers&&e.observers.length&&U(()=>{for(let o=0;o<e.observers.length;o+=1){let s=e.observers[o],l=h&&h.running;l&&h.disposed.has(s)||((l?!s.tState:!s.state)&&(s.pure?$.push(s):j.push(s),s.observers&&Ct(s)),l?s.tState=z:s.state=z)}if($.length>1e6)throw $=[],new Error},!1)}return t}function Te(e){if(!e.fn)return;ee(e);let t=Ue;gt(e,h&&h.running&&h.sources.has(e)?e.tValue:e.value,t),h&&!h.running&&h.sources.has(e)&&queueMicrotask(()=>{U(()=>{h&&(h.running=!0),O=C=e,gt(e,e.tValue,t),O=C=null},!1)})}function gt(e,t,n){let r,o=C,s=O;O=C=e;try{r=e.fn(t)}catch(l){return e.pure&&(h&&h.running?(e.tState=z,e.tOwned&&e.tOwned.forEach(ee),e.tOwned=void 0):(e.state=z,e.owned&&e.owned.forEach(ee),e.owned=null)),e.updatedAt=n+1,We(l)}finally{O=s,C=o}(!e.updatedAt||e.updatedAt<=n)&&(e.updatedAt!=null&&"observers"in e?Et(e,r,!0):h&&h.running&&e.pure?(h.sources.add(e),e.tValue=r):e.value=r,e.updatedAt=n)}function Ke(e,t,n,r=z,o){let s={fn:e,state:r,updatedAt:null,owned:null,sources:null,sourceSlots:null,cleanups:null,value:t,owner:C,context:C?C.context:null,pure:n};if(h&&h.running&&(s.state=0,s.tState=r),C===null||C!==St&&(h&&h.running&&C.pure?C.tOwned?C.tOwned.push(s):C.tOwned=[s]:C.owned?C.owned.push(s):C.owned=[s]),ke&&s.fn){let[l,i]=S(void 0,{equals:!1}),c=ke.factory(s.fn,i);R(()=>c.dispose());let d=()=>$e(i).then(()=>u.dispose()),u=ke.factory(s.fn,d);s.fn=a=>(l(),h&&h.running?u.track(a):c.track(a))}return s}function Ie(e){let t=h&&h.running;if((t?e.tState:e.state)===0)return;if((t?e.tState:e.state)===Fe)return Je(e);if(e.suspense&&V(e.suspense.inFallback))return e.suspense.effects.push(e);let n=[e];for(;(e=e.owner)&&(!e.updatedAt||e.updatedAt<Ue);){if(t&&h.disposed.has(e))return;(t?e.tState:e.state)&&n.push(e)}for(let r=n.length-1;r>=0;r--){if(e=n[r],t){let o=e,s=n[r+1];for(;(o=o.owner)&&o!==s;)if(h.disposed.has(o))return}if((t?e.tState:e.state)===z)Te(e);else if((t?e.tState:e.state)===Fe){let o=$;$=null,U(()=>Je(e,n[0]),!1),$=o}}}function U(e,t){if($)return e();let n=!1;t||($=[]),j?n=!0:j=[],Ue++;try{let r=e();return Qt(n),r}catch(r){n||(j=null),$=null,We(r)}}function Qt(e){if($&&(Pe&&h&&h.running?Zt($):Pt($),$=null),e)return;let t;if(h){if(!h.promises.size&&!h.queue.size){let r=h.sources,o=h.disposed;j.push.apply(j,h.effects),t=h.resolve;for(let s of j)"tState"in s&&(s.state=s.tState),delete s.tState;h=null,U(()=>{for(let s of o)ee(s);for(let s of r){if(s.value=s.tValue,s.owned)for(let l=0,i=s.owned.length;l<i;l++)ee(s.owned[l]);s.tOwned&&(s.owned=s.tOwned),delete s.tValue,delete s.tOwned,s.tState=0}mt(!1)},!1)}else if(h.running){h.running=!1,h.effects.push.apply(h.effects,j),j=null,mt(!0);return}}let n=j;j=null,n.length&&U(()=>vt(n),!1),t&&t()}function Pt(e){for(let t=0;t<e.length;t++)Ie(e[t])}function Zt(e){for(let t=0;t<e.length;t++){let n=e[t],r=h.queue;r.has(n)||(r.add(n),Pe(()=>{r.delete(n),U(()=>{h.running=!0,Ie(n)},!1),h&&(h.running=!1)}))}}function en(e){let t,n=0;for(t=0;t<e.length;t++){let r=e[t];r.user?e[n++]=r:Ie(r)}if(T.context){if(T.count){T.effects||(T.effects=[]),T.effects.push(...e.slice(0,n));return}Kt()}for(T.effects&&(T.done||!T.count)&&(e=[...T.effects,...e],n+=T.effects.length,delete T.effects),t=0;t<n;t++)Ie(e[t])}function Je(e,t){let n=h&&h.running;n?e.tState=0:e.state=0;for(let r=0;r<e.sources.length;r+=1){let o=e.sources[r];if(o.sources){let s=n?o.tState:o.state;s===z?o!==t&&(!o.updatedAt||o.updatedAt<Ue)&&Ie(o):s===Fe&&Je(o,t)}}}function Ct(e){let t=h&&h.running;for(let n=0;n<e.observers.length;n+=1){let r=e.observers[n];(t?!r.tState:!r.state)&&(t?r.tState=Fe:r.state=Fe,r.pure?$.push(r):j.push(r),r.observers&&Ct(r))}}function ee(e){let t;if(e.sources)for(;e.sources.length;){let n=e.sources.pop(),r=e.sourceSlots.pop(),o=n.observers;if(o&&o.length){let s=o.pop(),l=n.observerSlots.pop();r<o.length&&(s.sourceSlots[l]=r,o[r]=s,n.observerSlots[r]=l)}}if(e.tOwned){for(t=e.tOwned.length-1;t>=0;t--)ee(e.tOwned[t]);delete e.tOwned}if(h&&h.running&&e.pure)Tt(e,!0);else if(e.owned){for(t=e.owned.length-1;t>=0;t--)ee(e.owned[t]);e.owned=null}if(e.cleanups){for(t=e.cleanups.length-1;t>=0;t--)e.cleanups[t]();e.cleanups=null}h&&h.running?e.tState=0:e.state=0}function Tt(e,t){if(t||(e.tState=0,h.disposed.add(e)),e.owned)for(let n=0;n<e.owned.length;n++)Tt(e.owned[n])}function Ve(e){return e instanceof Error?e:new Error(typeof e=="string"?e:"Unknown error",{cause:e})}function bt(e,t,n){try{for(let r of t)r(e)}catch(r){We(r,n&&n.owner||null)}}function We(e,t=C){let n=ft&&t&&t.context&&t.context[ft],r=Ve(e);if(!n)throw r;j?j.push({fn(){bt(r,n,t)},state:z}):bt(r,n,t)}function rt(e){if(typeof e=="function"&&!e.length)return rt(e());if(Array.isArray(e)){let t=[];for(let n=0;n<e.length;n++){let r=rt(e[n]);Array.isArray(r)?t.push.apply(t,r):t.push(r)}return t}return e}function tn(e,t){return function(r){let o;return G(()=>o=V(()=>(C.context={...C.context,[e]:r.value},xt(()=>r.children))),void 0),o}}var nn=Symbol("fallback");function wt(e){for(let t=0;t<e.length;t++)e[t]()}function rn(e,t,n={}){let r=[],o=[],s=[],l=0,i=t.length>1?[]:null;return R(()=>wt(s)),()=>{let c=e()||[],d=c.length,u,a;return c[yt],V(()=>{let b,x,y,k,E,L,g,p,f;if(d===0)l!==0&&(wt(s),s=[],r=[],o=[],l=0,i&&(i=[])),n.fallback&&(r=[nn],o[0]=Ee(v=>(s[0]=v,n.fallback())),l=1);else if(l===0){for(o=new Array(d),a=0;a<d;a++)r[a]=c[a],o[a]=Ee(m);l=d}else{for(y=new Array(d),k=new Array(d),i&&(E=new Array(d)),L=0,g=Math.min(l,d);L<g&&r[L]===c[L];L++);for(g=l-1,p=d-1;g>=L&&p>=L&&r[g]===c[p];g--,p--)y[p]=o[g],k[p]=s[g],i&&(E[p]=i[g]);for(b=new Map,x=new Array(p+1),a=p;a>=L;a--)f=c[a],u=b.get(f),x[a]=u===void 0?-1:u,b.set(f,a);for(u=L;u<=g;u++)f=r[u],a=b.get(f),a!==void 0&&a!==-1?(y[a]=o[u],k[a]=s[u],i&&(E[a]=i[u]),a=x[a],b.set(f,a)):s[u]();for(a=L;a<d;a++)a in y?(o[a]=y[a],s[a]=k[a],i&&(i[a]=E[a],i[a](a))):o[a]=Ee(m);o=o.slice(0,l=d),r=c.slice(0)}return o});function m(b){if(s[a]=b,i){let[x,y]=S(a);return i[a]=y,t(c[a],x)}return t(c[a])}}}function je(){return!0}var st={get(e,t,n){return t===Xe?n:e.get(t)},has(e,t){return t===Xe?!0:e.has(t)},set:je,deleteProperty:je,getOwnPropertyDescriptor(e,t){return{configurable:!0,enumerable:!0,get(){return e.get(t)},set:je,deleteProperty:je}},ownKeys(e){return e.keys()}};function nt(e){return(e=typeof e=="function"?e():e)?e:{}}function sn(){for(let e=0,t=this.length;e<t;++e){let n=this[e]();if(n!==void 0)return n}}function He(...e){let t=!1;for(let l=0;l<e.length;l++){let i=e[l];t=t||!!i&&Xe in i,e[l]=typeof i=="function"?(t=!0,D(i)):i}if(pt&&t)return new Proxy({get(l){for(let i=e.length-1;i>=0;i--){let c=nt(e[i])[l];if(c!==void 0)return c}},has(l){for(let i=e.length-1;i>=0;i--)if(l in nt(e[i]))return!0;return!1},keys(){let l=[];for(let i=0;i<e.length;i++)l.push(...Object.keys(nt(e[i])));return[...new Set(l)]}},st);let n={},r=Object.create(null);for(let l=e.length-1;l>=0;l--){let i=e[l];if(!i)continue;let c=Object.getOwnPropertyNames(i);for(let d=c.length-1;d>=0;d--){let u=c[d];if(u==="__proto__"||u==="constructor")continue;let a=Object.getOwnPropertyDescriptor(i,u);if(!r[u])r[u]=a.get?{enumerable:!0,configurable:!0,get:sn.bind(n[u]=[a.get.bind(i)])}:a.value!==void 0?a:void 0;else{let m=n[u];m&&(a.get?m.push(a.get.bind(i)):a.value!==void 0&&m.push(()=>a.value))}}}let o={},s=Object.keys(r);for(let l=s.length-1;l>=0;l--){let i=s[l],c=r[i];c&&c.get?Object.defineProperty(o,i,c):o[i]=c?c.value:void 0}return o}function it(e,...t){let n=t.length;if(pt&&Xe in e){let o=n>1?t.flat():t[0],s=t.map(l=>new Proxy({get(i){return l.includes(i)?e[i]:void 0},has(i){return l.includes(i)&&i in e},keys(){return l.filter(i=>i in e)}},st));return s.push(new Proxy({get(l){return o.includes(l)?void 0:e[l]},has(l){return o.includes(l)?!1:l in e},keys(){return Object.keys(e).filter(l=>!o.includes(l))}},st)),s}let r=[];for(let o=0;o<=n;o++)r[o]={};for(let o of Object.getOwnPropertyNames(e)){let s=n;for(let c=0;c<t.length;c++)if(t[c].includes(o)){s=c;break}let l=Object.getOwnPropertyDescriptor(e,o);!l.get&&!l.set&&l.enumerable&&l.writable&&l.configurable?r[s][o]=l.value:Object.defineProperty(r[s],o,l)}return r}var on=0;function Q(){return T.context?T.getNextContextId():`cl-${on++}`}var ln=e=>`Stale read from <${e}>.`;function K(e){let t="fallback"in e&&{fallback:()=>e.fallback};return D(rn(()=>e.each,e.children,t||void 0))}function Se(e){let t=e.keyed,n=D(()=>e.when,void 0,void 0),r=t?n:D(n,void 0,{equals:(o,s)=>!o==!s});return D(()=>{let o=r();if(o){let s=e.children;return typeof s=="function"&&s.length>0?V(()=>s(t?o:()=>{if(!V(r))throw ln("Show");return n()})):s}return e.fallback},void 0,void 0)}function Sn(e){let t=D(()=>e.render(e.row)),[n]=ot(async()=>{let r=t();return r&&typeof r.then=="function"?await r:null});return<div>
18
- {(()=>{let r=t();return r&&typeof r.then=="function"?n()??"":r})()}
19
- </div>}function _n(e){let[t,n]=S(-1),[r,o]=S(null),[s,l]=S(1),i=()=>Math.max(1,e.pageSize??25),c=D(()=>{let k=t(),E=r();if(k<0||!E)return e.rows;let L=e.columns[k];if(!L?.sortKey)return e.rows;let g=e.rows.map((p,f)=>({row:p,idx:f,key:L.sortKey(p)}));return g.sort((p,f)=>p.key===f.key?p.idx-f.idx:p.key<f.key?E==="asc"?-1:1:E==="asc"?1:-1),g.map(p=>p.row)}),d=D(()=>Math.max(1,Math.ceil(c().length/i()))),u=D(()=>{let E=(Math.min(s(),d())-1)*i();return c().slice(E,E+i())});N(()=>{s()>d()&&l(d())});let a=k=>{if(t()!==k){n(k),o("asc"),l(1);return}if(r()==="asc"){o("desc");return}if(r()==="desc"){n(-1),o(null),l(1);return}o("asc"),l(1)},m=k=>{let E=Math.min(Math.max(1,k),d());l(E)},b=()=>e.paginationPosition??"bottom",x=()=>`ss_table ${b()==="top"?"ss_table--pagination-top":""} ${e.class??""}`,y=()=><div class="ss_table__pagination">
20
- <button type="button"class="ss_table__page_button"disabled={s()===1}aria-label="Erste Seite"onclick={()=>m(1)}>
21
- <svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-left-pipe"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M7 6v12"/><path d="M18 6l-6 6l6 6"/></svg>
60
+ </div>;
61
+ }
62
+
63
+ // src/components/SSDataTable.tsx
64
+ import { createEffect, createMemo, createResource, createSignal, For } from "solid-js";
65
+ function SSDataCell(props) {
66
+ const rendered = createMemo(() => props.render(props.row));
67
+ const [asyncContent] = createResource(async () => {
68
+ const value = rendered();
69
+ if (value && typeof value.then === "function") {
70
+ return await value;
71
+ }
72
+ return null;
73
+ });
74
+ return <div>
75
+ {(() => {
76
+ const value = rendered();
77
+ if (value && typeof value.then === "function") {
78
+ return asyncContent() ?? "";
79
+ }
80
+ return value;
81
+ })()}
82
+ </div>;
83
+ }
84
+ function SSDataTable(props) {
85
+ const [sortIndex, setSortIndex] = createSignal(-1);
86
+ const [sortDir, setSortDir] = createSignal(null);
87
+ const [page, setPage] = createSignal(1);
88
+ const pageSize = () => Math.max(1, props.pageSize ?? 25);
89
+ const sortedRows = createMemo(() => {
90
+ const index = sortIndex();
91
+ const dir = sortDir();
92
+ if (index < 0 || !dir) return props.rows;
93
+ const column = props.columns[index];
94
+ if (!column?.sortKey) return props.rows;
95
+ const entries = props.rows.map((row, idx) => ({
96
+ row,
97
+ idx,
98
+ key: column.sortKey(row)
99
+ }));
100
+ entries.sort((a, b) => {
101
+ if (a.key === b.key) return a.idx - b.idx;
102
+ if (a.key < b.key) return dir === "asc" ? -1 : 1;
103
+ return dir === "asc" ? 1 : -1;
104
+ });
105
+ return entries.map((entry) => entry.row);
106
+ });
107
+ const totalPages = createMemo(() => {
108
+ return Math.max(1, Math.ceil(sortedRows().length / pageSize()));
109
+ });
110
+ const pagedRows = createMemo(() => {
111
+ const current = Math.min(page(), totalPages());
112
+ const start = (current - 1) * pageSize();
113
+ return sortedRows().slice(start, start + pageSize());
114
+ });
115
+ createEffect(() => {
116
+ if (page() > totalPages()) setPage(totalPages());
117
+ });
118
+ const toggleSort = (index) => {
119
+ if (sortIndex() !== index) {
120
+ setSortIndex(index);
121
+ setSortDir("asc");
122
+ setPage(1);
123
+ return;
124
+ }
125
+ if (sortDir() === "asc") {
126
+ setSortDir("desc");
127
+ return;
128
+ }
129
+ if (sortDir() === "desc") {
130
+ setSortIndex(-1);
131
+ setSortDir(null);
132
+ setPage(1);
133
+ return;
134
+ }
135
+ setSortDir("asc");
136
+ setPage(1);
137
+ };
138
+ const goToPage = (next) => {
139
+ const safePage = Math.min(Math.max(1, next), totalPages());
140
+ setPage(safePage);
141
+ };
142
+ const paginationPosition = () => props.paginationPosition ?? "bottom";
143
+ const containerClass = () => `ss_table ${paginationPosition() === "top" ? "ss_table--pagination-top" : ""} ${props.class ?? ""}`;
144
+ const paginationBar = () => <div class="ss_table__pagination">
145
+ <button
146
+ type="button"
147
+ class="ss_table__page_button"
148
+ disabled={page() === 1}
149
+ aria-label="Erste Seite"
150
+ onclick={() => goToPage(1)}
151
+ >
152
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-left-pipe"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M7 6v12" /><path d="M18 6l-6 6l6 6" /></svg>
22
153
  </button>
23
- <button type="button"class="ss_table__page_button"disabled={s()===1}aria-label="Vorherige Seite"onclick={()=>m(s()-1)}>
24
- <svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-left"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M15 6l-6 6l6 6"/></svg>
154
+ <button
155
+ type="button"
156
+ class="ss_table__page_button"
157
+ disabled={page() === 1}
158
+ aria-label="Vorherige Seite"
159
+ onclick={() => goToPage(page() - 1)}
160
+ >
161
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-left"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M15 6l-6 6l6 6" /></svg>
25
162
  </button>
26
163
  <span class="ss_table__page_info">
27
- Seite {s()} von {d()}
164
+ Seite {page()} von {totalPages()}
28
165
  </span>
29
- <button type="button"class="ss_table__page_button"disabled={s()===d()}aria-label="Nächste Seite"onclick={()=>m(s()+1)}>
30
- <svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-right"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M9 6l6 6l-6 6"/></svg>
166
+ <button
167
+ type="button"
168
+ class="ss_table__page_button"
169
+ disabled={page() === totalPages()}
170
+ aria-label="Nächste Seite"
171
+ onclick={() => goToPage(page() + 1)}
172
+ >
173
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-right"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M9 6l6 6l-6 6" /></svg>
31
174
  </button>
32
- <button type="button"class="ss_table__page_button"disabled={s()===d()}aria-label="Letzte Seite"onclick={()=>m(d())}>
33
- <svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-right-pipe"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M6 6l6 6l-6 6"/><path d="M17 5v13"/></svg>
175
+ <button
176
+ type="button"
177
+ class="ss_table__page_button"
178
+ disabled={page() === totalPages()}
179
+ aria-label="Letzte Seite"
180
+ onclick={() => goToPage(totalPages())}
181
+ >
182
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-right-pipe"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M6 6l6 6l-6 6" /><path d="M17 5v13" /></svg>
34
183
  </button>
35
- </div>;return<div class={x()}style={e.style}>
36
- {b()==="top"&&y()}
184
+ </div>;
185
+ return <div class={containerClass()} style={props.style}>
186
+ {paginationPosition() === "top" && paginationBar()}
37
187
  <div class="ss_table__scroll">
38
188
  <table>
39
189
  <thead>
40
190
  <tr>
41
- <K each={e.columns}>
42
- {(k,E)=>{let L=!!k.sortKey,g=()=>t()===E(),p=()=>g()?r():null;return<th>
43
- {L?<button type="button"class="ss_table__sort_button"aria-sort={p()==="asc"?"ascending":p()==="desc"?"descending":"none"}data-sort={p()??"none"}onclick={()=>a(E())}>
44
- {k.label}
45
- <span class="ss_table__sort_icon"aria-hidden="true">
46
- {p()==="asc"?<svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-down"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M6 9l6 6l6 -6"/></svg>:p()==="desc"?<svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-up"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M6 15l6 -6l6 6"/></svg>:<svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-selector"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M8 9l4 -4l4 4"/><path d="M16 15l-4 4l-4 -4"/></svg>}
191
+ <For each={props.columns}>
192
+ {(column, index) => {
193
+ const sortable = !!column.sortKey;
194
+ const isActive = () => sortIndex() === index();
195
+ const currentDir = () => isActive() ? sortDir() : null;
196
+ return <th>
197
+ {sortable ? <button
198
+ type="button"
199
+ class="ss_table__sort_button"
200
+ aria-sort={currentDir() === "asc" ? "ascending" : currentDir() === "desc" ? "descending" : "none"}
201
+ data-sort={currentDir() ?? "none"}
202
+ onclick={() => toggleSort(index())}
203
+ >
204
+ {column.label}
205
+ <span class="ss_table__sort_icon" aria-hidden="true">
206
+ {currentDir() === "asc" ? <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-down"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M6 9l6 6l6 -6" /></svg> : currentDir() === "desc" ? <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-up"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M6 15l6 -6l6 6" /></svg> : <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-selector"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M8 9l4 -4l4 4" /><path d="M16 15l-4 4l-4 -4" /></svg>}
47
207
  </span>
48
- </button>:<span class="ss_table__header_label">{k.label}</span>}
49
- </th>}}
50
- </K>
208
+ </button> : <span class="ss_table__header_label">{column.label}</span>}
209
+ </th>;
210
+ }}
211
+ </For>
51
212
  </tr>
52
213
  </thead>
53
214
  <tbody>
54
- <K each={u()}>
55
- {k=><tr data-clickable={e.onRowClick?"true":void 0}onclick={()=>e.onRowClick?.(k)}>
56
- <K each={e.columns}>
57
- {E=><td>
58
- <Sn row={k}render={E.render}/>
215
+ <For each={pagedRows()}>
216
+ {(row) => <tr
217
+ data-clickable={props.onRowClick ? "true" : void 0}
218
+ onclick={() => props.onRowClick?.(row)}
219
+ >
220
+ <For each={props.columns}>
221
+ {(column) => <td>
222
+ <SSDataCell row={row} render={column.render} />
59
223
  </td>}
60
- </K>
224
+ </For>
61
225
  </tr>}
62
- </K>
226
+ </For>
63
227
  </tbody>
64
228
  </table>
65
229
  </div>
66
- {b()==="bottom"&&y()}
67
- </div>}function xn(e){let[t,n]=S(!1),[r,o]=S(!1),[s,l]=S("closed"),i,c=()=>n(!1);return N(()=>{if(t()){o(!0),requestAnimationFrame(()=>l("open"));return}if(!r())return;l("closed");let d=window.setTimeout(()=>o(!1),160);R(()=>window.clearTimeout(d))}),X(()=>{let d=a=>{let m=a.target;!i||!m||i.contains(m)||c()},u=a=>{a.key==="Escape"&&c()};document.addEventListener("mousedown",d),window.addEventListener("keydown",u),R(()=>{document.removeEventListener("mousedown",d),window.removeEventListener("keydown",u)})}),<div class={`ss_dropdown ${e.class??""}`}style={e.style}ref={d=>i=d}>
68
- <button type="button"class="ss_dropdown__trigger ss_button ss_button--icon"aria-haspopup="menu"aria-expanded={t()}aria-label={e.ariaLabel??"Aktionen \xF6ffnen"}onclick={()=>n(d=>!d)}>
69
- {e.icon??<svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-dots-vertical"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M11 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"/><path d="M11 19a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"/><path d="M11 5a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"/></svg>}
230
+ {paginationPosition() === "bottom" && paginationBar()}
231
+ </div>;
232
+ }
233
+
234
+ // src/components/SSDropdown.tsx
235
+ import { createSignal as createSignal2, For as For2, onCleanup, onMount, Show, createEffect as createEffect2 } from "solid-js";
236
+ function SSDropdown(props) {
237
+ const [open, setOpen] = createSignal2(false);
238
+ const [renderMenu, setRenderMenu] = createSignal2(false);
239
+ const [menuState, setMenuState] = createSignal2("closed");
240
+ let rootRef;
241
+ const close = () => setOpen(false);
242
+ createEffect2(() => {
243
+ if (open()) {
244
+ setRenderMenu(true);
245
+ requestAnimationFrame(() => setMenuState("open"));
246
+ return;
247
+ }
248
+ if (!renderMenu()) return;
249
+ setMenuState("closed");
250
+ const timeout = window.setTimeout(() => setRenderMenu(false), 160);
251
+ onCleanup(() => window.clearTimeout(timeout));
252
+ });
253
+ onMount(() => {
254
+ const handlePointerDown = (event) => {
255
+ const target = event.target;
256
+ if (!rootRef || !target) return;
257
+ if (!rootRef.contains(target)) close();
258
+ };
259
+ const handleKeyDown = (event) => {
260
+ if (event.key === "Escape") close();
261
+ };
262
+ document.addEventListener("mousedown", handlePointerDown);
263
+ window.addEventListener("keydown", handleKeyDown);
264
+ onCleanup(() => {
265
+ document.removeEventListener("mousedown", handlePointerDown);
266
+ window.removeEventListener("keydown", handleKeyDown);
267
+ });
268
+ });
269
+ return <div class={`ss_dropdown ${props.class ?? ""}`} style={props.style} ref={(el) => rootRef = el}>
270
+ <button
271
+ type="button"
272
+ class="ss_dropdown__trigger ss_button ss_button--icon"
273
+ aria-haspopup="menu"
274
+ aria-expanded={open()}
275
+ aria-label={props.ariaLabel ?? "Aktionen \xF6ffnen"}
276
+ onclick={() => setOpen((value) => !value)}
277
+ >
278
+ {props.icon ?? <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-dots-vertical"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M11 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" /><path d="M11 19a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" /><path d="M11 5a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" /></svg>}
70
279
  </button>
71
280
 
72
- <Se when={r()}>
73
- <div class="ss_dropdown__menu"role="menu"data-state={s()}>
74
- <K each={e.items}>
75
- {d=><button type="button"class="ss_dropdown__item"role={d.checked?"menuitemcheckbox":"menuitem"}aria-checked={d.checked?"true":void 0}onclick={async()=>{c(),await d.onclick?.()}}>
76
- <span class="ss_dropdown__item_icon">{d.icon}</span>
77
- <span class="ss_dropdown__item_label">{d.label}</span>
78
- {d.checked&&<span class="ss_dropdown__item_check"aria-hidden="true">
79
- <svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-check"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M5 12l5 5l10 -10"/></svg>
281
+ <Show when={renderMenu()}>
282
+ <div
283
+ class="ss_dropdown__menu"
284
+ role="menu"
285
+ data-state={menuState()}
286
+ >
287
+ <For2 each={props.items}>
288
+ {(item) => <button
289
+ type="button"
290
+ class="ss_dropdown__item"
291
+ role={item.checked ? "menuitemcheckbox" : "menuitem"}
292
+ aria-checked={item.checked ? "true" : void 0}
293
+ onclick={async () => {
294
+ close();
295
+ await item.onclick?.();
296
+ }}
297
+ >
298
+ <span class="ss_dropdown__item_icon">{item.icon}</span>
299
+ <span class="ss_dropdown__item_label">{item.label}</span>
300
+ {item.checked && <span class="ss_dropdown__item_check" aria-hidden="true">
301
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-check"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M5 12l5 5l10 -10" /></svg>
80
302
  </span>}
81
303
  </button>}
82
- </K>
304
+ </For2>
83
305
  </div>
84
- </Se>
85
- </div>}var Mt=200;function kn(e){let[t,n]=S(e.initiallyExpanded?"auto":0),r=D(()=>t()!==0),o,s,l=()=>{s&&clearTimeout(s);let i=o?.scrollHeight??0;if(r()){n(i),s=window.setTimeout(()=>n(0),1);return}n(i),s=window.setTimeout(()=>n("auto"),Mt)};return R(()=>{s&&clearTimeout(s)}),<div class={`ss_expandable ${e.class??""}`}style={e.style}data-state={r()?"open":"closed"}>
86
- <div class="ss_expandable__header"role="button"tabindex="0"aria-expanded={r()}onclick={l}onkeydown={i=>{(i.key==="Enter"||i.key===" ")&&(i.preventDefault(),l())}}>
87
- <span class="ss_expandable__icon"aria-hidden="true">
88
- {r()?<svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-down"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M6 9l6 6l6 -6"/></svg>:<svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-right"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M9 6l6 6l-6 6"/></svg>}
306
+ </Show>
307
+ </div>;
308
+ }
309
+
310
+ // src/components/SSExpandable.tsx
311
+ import { createMemo as createMemo2, createSignal as createSignal3, onCleanup as onCleanup2 } from "solid-js";
312
+ var TRANSITION_MS = 200;
313
+ function SSExpandable(props) {
314
+ const [height, setHeight] = createSignal3(props.initiallyExpanded ? "auto" : 0);
315
+ const isExpanded = createMemo2(() => height() !== 0);
316
+ let contentRef;
317
+ let timeoutId;
318
+ const toggle = () => {
319
+ if (timeoutId) clearTimeout(timeoutId);
320
+ const targetHeight = contentRef?.scrollHeight ?? 0;
321
+ if (isExpanded()) {
322
+ setHeight(targetHeight);
323
+ timeoutId = window.setTimeout(() => setHeight(0), 1);
324
+ return;
325
+ }
326
+ setHeight(targetHeight);
327
+ timeoutId = window.setTimeout(() => setHeight("auto"), TRANSITION_MS);
328
+ };
329
+ onCleanup2(() => {
330
+ if (timeoutId) clearTimeout(timeoutId);
331
+ });
332
+ return <div
333
+ class={`ss_expandable ${props.class ?? ""}`}
334
+ style={props.style}
335
+ data-state={isExpanded() ? "open" : "closed"}
336
+ >
337
+ <div
338
+ class="ss_expandable__header"
339
+ role="button"
340
+ tabindex="0"
341
+ aria-expanded={isExpanded()}
342
+ onclick={toggle}
343
+ onkeydown={(event) => {
344
+ if (event.key === "Enter" || event.key === " ") {
345
+ event.preventDefault();
346
+ toggle();
347
+ }
348
+ }}
349
+ >
350
+ <span class="ss_expandable__icon" aria-hidden="true">
351
+ {isExpanded() ? <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-down"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M6 9l6 6l6 -6" /></svg> : <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-right"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M9 6l6 6l-6 6" /></svg>}
89
352
  </span>
90
- <span class="ss_expandable__title">{e.title}</span>
353
+ <span class="ss_expandable__title">{props.title}</span>
91
354
  </div>
92
355
 
93
- <div ref={i=>o=i}class="ss_expandable__content"style={{height:typeof t()=="number"?`${t()}px`:t(),"transition-duration":`${Mt}ms`}}>
356
+ <div
357
+ ref={(el) => contentRef = el}
358
+ class="ss_expandable__content"
359
+ style={{
360
+ height: typeof height() === "number" ? `${height()}px` : height(),
361
+ "transition-duration": `${TRANSITION_MS}ms`
362
+ }}
363
+ >
94
364
  <div class='ss_expandable__divider_wrapper'>
95
- <div class="ss_expandable__divider"/>
96
- {e.children}
365
+ <div class="ss_expandable__divider" />
366
+ {props.children}
97
367
  </div>
98
368
  </div>
99
- </div>}function Ye(){let[e,t]=S(!1);return[e,async n=>{if(!e())try{t(!0),await n()}finally{t(!1)}}]}var _e=Z(),J=function(e){let[t,n]=Ye(),r={},o={loading:t,process:s=>n(()=>s(o)),field:s=>r[s]??null,setField:(s,l)=>{r[s]=l},delField:s=>{delete r[s]},setValues:s=>Object.entries(s).forEach(([l,i])=>r[l]?.setValue(i)),getValues:async()=>{let s=Object.entries(r),l=await Promise.all(s.map(([,i])=>i.getValue()));return Object.fromEntries(s.map(([i],c)=>[i,l[c]]))},validate:()=>Promise.all(Object.values(r).map(s=>s.validate())).then(),hasError:()=>Object.values(r).some(s=>s.hasError()),submit:()=>n(async()=>{await o.validate(),!o.hasError()&&await e.onsubmit?.(o)})};return<form class="ss_form"onsubmit={s=>{s.preventDefault(),o.submit()}}>
100
- <_e.Provider value={o}>
101
- {e.children}
102
- </_e.Provider>
103
- </form>};J.Input=function(e){let t=B(_e),[n,r]=S(""),[o,s]=S(null),l={getValue:()=>{let g=n().trim();return g||null},setValue:g=>{if(typeof g=="number"){r(g.toLocaleString());return}r(`${g}`)},hasError:()=>!!o(),validate:async()=>{let g=[...e.rules??[]];e.required&&g.unshift(J.rules.required);let p=await l.getValue();for(let f of g){let v=await f(p);if(v){s(v);return}}s(null)}};if(e.name&&t){let g=e.name;X(()=>t.setField(g,l)),R(()=>t.delField(g))}let i=null,[c,d]=S([]),[u,a]=S(-1),m;if(e.suggestions){let g=e.suggestions,[p,f]=S(!g.prepare);g.prepare&&X(async()=>{g.prepare&&(i=await g.prepare(),f(!0))});let v;N(()=>{if(clearTimeout(v??void 0),!p())return;d([]);let F=n().trim().toLowerCase();F&&(v=setTimeout(async()=>{let A=await g.getItems({query:F,init:i});d(A)},250))}),R(()=>clearTimeout(v??void 0))}N(()=>{let g=c();if(!g.length){a(-1);return}u()>=g.length&&a(g.length-1)});let b=g=>{let p=m;if(!p||g<0)return;let f=p.querySelectorAll("li")[g];if(!f)return;let v=f.offsetTop,F=v+f.offsetHeight,A=p.scrollTop,w=A+p.clientHeight;v<A?p.scrollTop=v:F>w&&(p.scrollTop=F-p.clientHeight)},x=g=>{let p=c();if(!p.length)return;let f=Math.max(-1,Math.min(u()+g,p.length-1));a(f),b(f)},y=g=>{r(e.suggestions.stringify({item:g,init:i})),a(-1)},k=g=>{if(c().length)if(g.key==="ArrowDown")g.preventDefault(),x(1);else if(g.key==="ArrowUp")g.preventDefault(),x(-1);else if(g.key==="Enter"&&u()>=0){g.preventDefault();let p=c()[u()];p&&y(p)}else g.key==="Escape"&&a(-1)},E=g=>{r(g),a(-1)},L=Q();return<div class="ss_form_input">
104
- <label for={e.id||L}>{e.label}</label>
369
+ </div>;
370
+ }
371
+
372
+ // src/components/SSForm.tsx
373
+ import { createContext, createEffect as createEffect3, createMemo as createMemo3, createSignal as createSignal5, createUniqueId, For as For3, onCleanup as onCleanup3, onMount as onMount2, untrack, useContext } from "solid-js";
374
+
375
+ // src/hooks/createLoading.ts
376
+ import { createSignal as createSignal4 } from "solid-js";
377
+ function createLoading() {
378
+ const [loading, setLoading] = createSignal4(false);
379
+ return [loading, async (callback) => {
380
+ if (loading()) return;
381
+ try {
382
+ setLoading(true);
383
+ await callback();
384
+ } finally {
385
+ setLoading(false);
386
+ }
387
+ }];
388
+ }
389
+
390
+ // src/components/SSForm.tsx
391
+ var SSFormContext = createContext();
392
+ var SSForm = function(props) {
393
+ const [loading, process] = createLoading();
394
+ const fields = {};
395
+ const context = {
396
+ loading,
397
+ process: (action) => process(() => action(context)),
398
+ field: (name) => fields[name] ?? null,
399
+ setField: (name, field) => {
400
+ fields[name] = field;
401
+ },
402
+ delField: (name) => {
403
+ delete fields[name];
404
+ },
405
+ setValues: (values) => Object.entries(values).forEach(([name, value]) => fields[name]?.setValue(value)),
406
+ getValues: async () => {
407
+ const entries = Object.entries(fields);
408
+ const values = await Promise.all(entries.map(([, field]) => field.getValue()));
409
+ return Object.fromEntries(entries.map(([name], i) => [name, values[i]]));
410
+ },
411
+ validate: () => Promise.all(Object.values(fields).map((field) => field.validate())).then(),
412
+ hasError: () => Object.values(fields).some((field) => field.hasError()),
413
+ submit: () => process(async () => {
414
+ await context.validate();
415
+ if (context.hasError()) return;
416
+ await props.onsubmit?.(context);
417
+ })
418
+ };
419
+ return <form class="ss_form" onsubmit={(e) => {
420
+ e.preventDefault();
421
+ context.submit();
422
+ }}>
423
+ <SSFormContext.Provider value={context}>
424
+ {props.children}
425
+ </SSFormContext.Provider>
426
+ </form>;
427
+ };
428
+ SSForm.Input = function(props) {
429
+ const context = useContext(SSFormContext);
430
+ const [value, setValue] = createSignal5("");
431
+ const [error, setError] = createSignal5(null);
432
+ const field = {
433
+ getValue: () => {
434
+ const trimmed = value().trim();
435
+ if (!trimmed) return null;
436
+ return trimmed;
437
+ },
438
+ setValue: (value2) => {
439
+ if (typeof value2 === "number") {
440
+ setValue(value2.toLocaleString());
441
+ return;
442
+ }
443
+ setValue(`${value2}`);
444
+ },
445
+ hasError: () => !!error(),
446
+ validate: async () => {
447
+ const rules = [...props.rules ?? []];
448
+ if (props.required) rules.unshift(SSForm.rules.required);
449
+ const value2 = await field.getValue();
450
+ for (const rule of rules) {
451
+ const newError = await rule(value2);
452
+ if (newError) {
453
+ setError(newError);
454
+ return;
455
+ }
456
+ }
457
+ setError(null);
458
+ }
459
+ };
460
+ if (props.name && context) {
461
+ const name = props.name;
462
+ onMount2(() => context.setField(name, field));
463
+ onCleanup3(() => context.delField(name));
464
+ }
465
+ let suggInitData = null;
466
+ const [suggItems, setSuggItems] = createSignal5([]);
467
+ const [suggIndex, setSuggIndex] = createSignal5(-1);
468
+ let suggListRef;
469
+ if (props.suggestions) {
470
+ const sugg = props.suggestions;
471
+ const [initialized, setInitialized] = createSignal5(!sugg.prepare);
472
+ if (sugg.prepare) onMount2(async () => {
473
+ if (!sugg.prepare) return;
474
+ suggInitData = await sugg.prepare();
475
+ setInitialized(true);
476
+ });
477
+ let timeout;
478
+ createEffect3(() => {
479
+ clearTimeout(timeout ?? void 0);
480
+ if (!initialized()) return;
481
+ setSuggItems([]);
482
+ const query = value().trim().toLowerCase();
483
+ if (!query) return;
484
+ timeout = setTimeout(async () => {
485
+ const items = await sugg.getItems({ query, init: suggInitData });
486
+ setSuggItems(items);
487
+ }, 250);
488
+ });
489
+ onCleanup3(() => clearTimeout(timeout ?? void 0));
490
+ }
491
+ createEffect3(() => {
492
+ const items = suggItems();
493
+ if (!items.length) {
494
+ setSuggIndex(-1);
495
+ return;
496
+ }
497
+ if (suggIndex() >= items.length) setSuggIndex(items.length - 1);
498
+ });
499
+ const scrollToIndex = (idx) => {
500
+ const list = suggListRef;
501
+ if (!list || idx < 0) return;
502
+ const item = list.querySelectorAll("li")[idx];
503
+ if (!item) return;
504
+ const itemTop = item.offsetTop;
505
+ const itemBottom = itemTop + item.offsetHeight;
506
+ const viewTop = list.scrollTop;
507
+ const viewBottom = viewTop + list.clientHeight;
508
+ if (itemTop < viewTop) list.scrollTop = itemTop;
509
+ else if (itemBottom > viewBottom) list.scrollTop = itemBottom - list.clientHeight;
510
+ };
511
+ const moveIndex = (delta) => {
512
+ const items = suggItems();
513
+ if (!items.length) return;
514
+ const next = Math.max(-1, Math.min(suggIndex() + delta, items.length - 1));
515
+ setSuggIndex(next);
516
+ scrollToIndex(next);
517
+ };
518
+ const selectSuggestion = (item) => {
519
+ setValue(props.suggestions.stringify({ item, init: suggInitData }));
520
+ setSuggIndex(-1);
521
+ };
522
+ const handleKeyDown = (e) => {
523
+ if (!suggItems().length) return;
524
+ if (e.key === "ArrowDown") {
525
+ e.preventDefault();
526
+ moveIndex(1);
527
+ } else if (e.key === "ArrowUp") {
528
+ e.preventDefault();
529
+ moveIndex(-1);
530
+ } else if (e.key === "Enter" && suggIndex() >= 0) {
531
+ e.preventDefault();
532
+ const item = suggItems()[suggIndex()];
533
+ if (item) selectSuggestion(item);
534
+ } else if (e.key === "Escape") {
535
+ setSuggIndex(-1);
536
+ }
537
+ };
538
+ const handleInputChange = (next) => {
539
+ setValue(next);
540
+ setSuggIndex(-1);
541
+ };
542
+ const _id = createUniqueId();
543
+ return <div class="ss_form_input">
544
+ <label for={props.id || _id}>{props.label}</label>
105
545
 
106
546
  <div class="ss__wrapper">
107
- {e.textArea?<textarea id={e.id||L}value={n()}oninput={g=>E(g.target.value)}onkeydown={k}disabled={e.disabled||t?.loading()}/>:<input id={e.id||L}value={n()}oninput={g=>E(g.target.value)}onkeydown={k}disabled={e.disabled||t?.loading()}type={e.type}/>}
108
-
109
- {!!c().length&&<ul class="ss__suggestions"ref={g=>m=g}>
110
- <K each={c()}>
111
- {(g,p)=>{let f=()=>{let v=document.activeElement;v instanceof HTMLElement&&v.blur(),y(g)};return<li onpointerdown={v=>v.preventDefault()}onclick={f}classList={{ss__hovered:p()===u()}}>
112
- {e.suggestions.stringify({item:g,init:i})}
113
- </li>}}
114
- </K>
547
+ {props.textArea ? <textarea
548
+ id={props.id || _id}
549
+ value={value()}
550
+ oninput={(e) => handleInputChange(e.target.value)}
551
+ onkeydown={handleKeyDown}
552
+ disabled={props.disabled || context?.loading()}
553
+ /> : <input
554
+ id={props.id || _id}
555
+ value={value()}
556
+ oninput={(e) => handleInputChange(e.target.value)}
557
+ onkeydown={handleKeyDown}
558
+ disabled={props.disabled || context?.loading()}
559
+ type={props.type}
560
+ />}
561
+
562
+ {!!suggItems().length && <ul class="ss__suggestions" ref={(el) => suggListRef = el}>
563
+ <For3 each={suggItems()}>
564
+ {(item, idx) => {
565
+ const handleSelect = () => {
566
+ const active = document.activeElement;
567
+ if (active instanceof HTMLElement) active.blur();
568
+ selectSuggestion(item);
569
+ };
570
+ return <li
571
+ onpointerdown={(e) => e.preventDefault()}
572
+ onclick={handleSelect}
573
+ classList={{ "ss__hovered": idx() === suggIndex() }}
574
+ >
575
+ {props.suggestions.stringify({ item, init: suggInitData })}
576
+ </li>;
577
+ }}
578
+ </For3>
115
579
  </ul>}
116
580
  </div>
117
581
 
118
- {!!o()&&<span role="alert">{o()}</span>}
119
- </div>};J.Date=function(e){let t=B(_e),[n,r]=S(""),[o,s]=S(null),[l,i]=S(!1),[c,d]=S(new Date),u,a=f=>`${f}`.padStart(2,"0"),m=f=>{let v=a(f.getDate()),F=a(f.getMonth()+1),A=f.getFullYear();return`${v}.${F}.${A}`},b=f=>{let v=f.trim();if(!v)return null;let F=/^(\d{1,2})\.(\d{1,2})\.(\d{4})$/.exec(v);if(!F)return null;let A=Number(F[1]),w=Number(F[2]),M=Number(F[3]);if(!A||!w)return null;let _=new Date(M,w-1,A);return _.getFullYear()!==M||_.getMonth()!==w-1||_.getDate()!==A?null:_};N(()=>{if(!l())return;let f=b(n());d(f??new Date)});let x={getValue:()=>{let f=n().trim();return f||null},setValue:f=>{if(f instanceof Date){r(m(f));return}r(`${f??""}`)},hasError:()=>!!o(),validate:async()=>{let f=[...e.rules??[]];e.required&&f.unshift(J.rules.required);let v=await x.getValue();for(let F of f){let A=await F(v);if(A){s(A);return}}if(v&&!b(v)){s("Ung\xFCltiges Datum");return}s(null)}};if(e.name&&t){let f=e.name;X(()=>t.setField(f,x)),R(()=>t.delField(f))}let y=Q(),k=f=>{let v=b(n());return v?v.getFullYear()===c().getFullYear()&&v.getMonth()===c().getMonth()&&v.getDate()===f:!1},E=f=>{let v=new Date;return v.getFullYear()===c().getFullYear()&&v.getMonth()===c().getMonth()&&v.getDate()===f},L=()=>{let f=c(),v=f.getFullYear(),F=f.getMonth(),A=new Date(v,F,1),w=new Date(v,F+1,0).getDate(),M=(A.getDay()+6)%7,_=[];for(let P=0;P<M;P+=1)_.push(null);for(let P=1;P<=w;P+=1)_.push(P);for(;_.length%7!==0;)_.push(null);return _},g=()=>c().toLocaleDateString("de-DE",{month:"long",year:"numeric"}),p=f=>{let v=new Date(c().getFullYear(),c().getMonth(),f);r(m(v)),i(!1)};return X(()=>{let f=F=>{if(!l())return;let A=F.target;u&&A&&!u.contains(A)&&i(!1)},v=F=>{F.key==="Escape"&&i(!1)};document.addEventListener("mousedown",f),window.addEventListener("keydown",v),R(()=>{document.removeEventListener("mousedown",f),window.removeEventListener("keydown",v)})}),<div class="ss_form_date"ref={f=>u=f}>
120
- <label for={e.id||y}>{e.label}</label>
582
+ {!!error() && <span role="alert">{error()}</span>}
583
+ </div>;
584
+ };
585
+ SSForm.Date = function(props) {
586
+ const context = useContext(SSFormContext);
587
+ const [value, setValue] = createSignal5("");
588
+ const [error, setError] = createSignal5(null);
589
+ const [open, setOpen] = createSignal5(false);
590
+ const [viewDate, setViewDate] = createSignal5(/* @__PURE__ */ new Date());
591
+ let containerRef;
592
+ const pad = (num) => `${num}`.padStart(2, "0");
593
+ const formatDate = (date) => {
594
+ const day = pad(date.getDate());
595
+ const month = pad(date.getMonth() + 1);
596
+ const year = date.getFullYear();
597
+ return `${day}.${month}.${year}`;
598
+ };
599
+ const parseDate = (input) => {
600
+ const trimmed = input.trim();
601
+ if (!trimmed) return null;
602
+ const match = /^(\d{1,2})\.(\d{1,2})\.(\d{4})$/.exec(trimmed);
603
+ if (!match) return null;
604
+ const day = Number(match[1]);
605
+ const month = Number(match[2]);
606
+ const year = Number(match[3]);
607
+ if (!day || !month) return null;
608
+ const date = new Date(year, month - 1, day);
609
+ if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) {
610
+ return null;
611
+ }
612
+ return date;
613
+ };
614
+ createEffect3(() => {
615
+ if (!open()) return;
616
+ const parsed = parseDate(value());
617
+ setViewDate(parsed ?? /* @__PURE__ */ new Date());
618
+ });
619
+ const field = {
620
+ getValue: () => {
621
+ const trimmed = value().trim();
622
+ if (!trimmed) return null;
623
+ return trimmed;
624
+ },
625
+ setValue: (value2) => {
626
+ if (value2 instanceof Date) {
627
+ setValue(formatDate(value2));
628
+ return;
629
+ }
630
+ setValue(`${value2 ?? ""}`);
631
+ },
632
+ hasError: () => !!error(),
633
+ validate: async () => {
634
+ const rules = [...props.rules ?? []];
635
+ if (props.required) rules.unshift(SSForm.rules.required);
636
+ const value2 = await field.getValue();
637
+ for (const rule of rules) {
638
+ const newError = await rule(value2);
639
+ if (newError) {
640
+ setError(newError);
641
+ return;
642
+ }
643
+ }
644
+ if (value2 && !parseDate(value2)) {
645
+ setError("Ung\xFCltiges Datum");
646
+ return;
647
+ }
648
+ setError(null);
649
+ }
650
+ };
651
+ if (props.name && context) {
652
+ const name = props.name;
653
+ onMount2(() => context.setField(name, field));
654
+ onCleanup3(() => context.delField(name));
655
+ }
656
+ const _id = createUniqueId();
657
+ const isSelected = (day) => {
658
+ const parsed = parseDate(value());
659
+ if (!parsed) return false;
660
+ return parsed.getFullYear() === viewDate().getFullYear() && parsed.getMonth() === viewDate().getMonth() && parsed.getDate() === day;
661
+ };
662
+ const isToday = (day) => {
663
+ const today = /* @__PURE__ */ new Date();
664
+ return today.getFullYear() === viewDate().getFullYear() && today.getMonth() === viewDate().getMonth() && today.getDate() === day;
665
+ };
666
+ const buildCalendar = () => {
667
+ const current = viewDate();
668
+ const year = current.getFullYear();
669
+ const month = current.getMonth();
670
+ const firstDay = new Date(year, month, 1);
671
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
672
+ const startOffset = (firstDay.getDay() + 6) % 7;
673
+ const cells = [];
674
+ for (let i = 0; i < startOffset; i += 1) cells.push(null);
675
+ for (let day = 1; day <= daysInMonth; day += 1) cells.push(day);
676
+ while (cells.length % 7 !== 0) cells.push(null);
677
+ return cells;
678
+ };
679
+ const monthLabel = () => {
680
+ return viewDate().toLocaleDateString("de-DE", { month: "long", year: "numeric" });
681
+ };
682
+ const handleSelect = (day) => {
683
+ const next = new Date(viewDate().getFullYear(), viewDate().getMonth(), day);
684
+ setValue(formatDate(next));
685
+ setOpen(false);
686
+ };
687
+ onMount2(() => {
688
+ const handleOutside = (event) => {
689
+ if (!open()) return;
690
+ const target = event.target;
691
+ if (containerRef && target && !containerRef.contains(target)) {
692
+ setOpen(false);
693
+ }
694
+ };
695
+ const handleKeyDown = (event) => {
696
+ if (event.key === "Escape") setOpen(false);
697
+ };
698
+ document.addEventListener("mousedown", handleOutside);
699
+ window.addEventListener("keydown", handleKeyDown);
700
+ onCleanup3(() => {
701
+ document.removeEventListener("mousedown", handleOutside);
702
+ window.removeEventListener("keydown", handleKeyDown);
703
+ });
704
+ });
705
+ return <div class="ss_form_date" ref={(el) => containerRef = el}>
706
+ <label for={props.id || _id}>{props.label}</label>
121
707
 
122
708
  <div class="ss__wrapper">
123
- <input id={e.id||y}value={n()}oninput={f=>r(f.target.value)}onfocus={()=>i(!0)}disabled={e.disabled||t?.loading()}readonly={!e.editable}type="text"inputmode="numeric"autocomplete="off"placeholder="TT.MM.JJJJ"/>
124
- <button type="button"class="ss_form_date__icon"aria-label="Kalender öffnen"aria-haspopup="dialog"aria-expanded={l()}onclick={()=>i(f=>!f)}disabled={e.disabled||t?.loading()}>
125
- <svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="currentColor"class="icon icon-tabler icons-tabler-filled icon-tabler-calendar-week"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M16 2c.183 0 .355 .05 .502 .135l.033 .02c.28 .177 .465 .49 .465 .845v1h1a3 3 0 0 1 2.995 2.824l.005 .176v12a3 3 0 0 1 -2.824 2.995l-.176 .005h-12a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-12a3 3 0 0 1 2.824 -2.995l.176 -.005h1v-1a1 1 0 0 1 .514 -.874l.093 -.046l.066 -.025l.1 -.029l.107 -.019l.12 -.007q .083 0 .161 .013l.122 .029l.04 .012l.06 .023c.328 .135 .568 .44 .61 .806l.007 .117v1h6v-1a1 1 0 0 1 1 -1m3 7h-14v9.625c0 .705 .386 1.286 .883 1.366l.117 .009h12c.513 0 .936 -.53 .993 -1.215l.007 -.16z"/><path d="M9.015 13a1 1 0 0 1 -1 1a1.001 1.001 0 1 1 -.005 -2c.557 0 1.005 .448 1.005 1"/><path d="M13.015 13a1 1 0 0 1 -1 1a1.001 1.001 0 1 1 -.005 -2c.557 0 1.005 .448 1.005 1"/><path d="M17.02 13a1 1 0 0 1 -1 1a1.001 1.001 0 1 1 -.005 -2c.557 0 1.005 .448 1.005 1"/><path d="M12.02 15a1 1 0 0 1 0 2a1.001 1.001 0 1 1 -.005 -2z"/><path d="M9.015 16a1 1 0 0 1 -1 1a1.001 1.001 0 1 1 -.005 -2c.557 0 1.005 .448 1.005 1"/></svg>
709
+ <input
710
+ id={props.id || _id}
711
+ value={value()}
712
+ oninput={(e) => setValue(e.target.value)}
713
+ onfocus={() => setOpen(true)}
714
+ disabled={props.disabled || context?.loading()}
715
+ readonly={!props.editable}
716
+ type="text"
717
+ inputmode="numeric"
718
+ autocomplete="off"
719
+ placeholder="TT.MM.JJJJ"
720
+ />
721
+ <button
722
+ type="button"
723
+ class="ss_form_date__icon"
724
+ aria-label="Kalender öffnen"
725
+ aria-haspopup="dialog"
726
+ aria-expanded={open()}
727
+ onclick={() => setOpen((value2) => !value2)}
728
+ disabled={props.disabled || context?.loading()}
729
+ >
730
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" class="icon icon-tabler icons-tabler-filled icon-tabler-calendar-week"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M16 2c.183 0 .355 .05 .502 .135l.033 .02c.28 .177 .465 .49 .465 .845v1h1a3 3 0 0 1 2.995 2.824l.005 .176v12a3 3 0 0 1 -2.824 2.995l-.176 .005h-12a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-12a3 3 0 0 1 2.824 -2.995l.176 -.005h1v-1a1 1 0 0 1 .514 -.874l.093 -.046l.066 -.025l.1 -.029l.107 -.019l.12 -.007q .083 0 .161 .013l.122 .029l.04 .012l.06 .023c.328 .135 .568 .44 .61 .806l.007 .117v1h6v-1a1 1 0 0 1 1 -1m3 7h-14v9.625c0 .705 .386 1.286 .883 1.366l.117 .009h12c.513 0 .936 -.53 .993 -1.215l.007 -.16z" /><path d="M9.015 13a1 1 0 0 1 -1 1a1.001 1.001 0 1 1 -.005 -2c.557 0 1.005 .448 1.005 1" /><path d="M13.015 13a1 1 0 0 1 -1 1a1.001 1.001 0 1 1 -.005 -2c.557 0 1.005 .448 1.005 1" /><path d="M17.02 13a1 1 0 0 1 -1 1a1.001 1.001 0 1 1 -.005 -2c.557 0 1.005 .448 1.005 1" /><path d="M12.02 15a1 1 0 0 1 0 2a1.001 1.001 0 1 1 -.005 -2z" /><path d="M9.015 16a1 1 0 0 1 -1 1a1.001 1.001 0 1 1 -.005 -2c.557 0 1.005 .448 1.005 1" /></svg>
126
731
  </button>
127
732
  </div>
128
733
 
129
- {l()&&<div class="ss_form_date__picker"role="dialog"aria-label="Datum auswählen">
734
+ {open() && <div class="ss_form_date__picker" role="dialog" aria-label="Datum auswählen">
130
735
  <div class="ss_form_date__header">
131
736
  <div class="ss_form_date__nav_group">
132
- <button type="button"class="ss_form_date__nav"onclick={()=>{let f=c();d(new Date(f.getFullYear()-1,f.getMonth(),1))}}>
133
- <svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-left-pipe"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M7 6v12"/><path d="M18 6l-6 6l6 6"/></svg>
737
+ <button type="button" class="ss_form_date__nav" onclick={() => {
738
+ const current = viewDate();
739
+ setViewDate(new Date(current.getFullYear() - 1, current.getMonth(), 1));
740
+ }}>
741
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-left-pipe"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M7 6v12" /><path d="M18 6l-6 6l6 6" /></svg>
134
742
  </button>
135
- <button type="button"class="ss_form_date__nav"onclick={()=>{let f=c();d(new Date(f.getFullYear(),f.getMonth()-1,1))}}>
136
- <svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-left"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M15 6l-6 6l6 6"/></svg>
743
+ <button type="button" class="ss_form_date__nav" onclick={() => {
744
+ const current = viewDate();
745
+ setViewDate(new Date(current.getFullYear(), current.getMonth() - 1, 1));
746
+ }}>
747
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-left"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M15 6l-6 6l6 6" /></svg>
137
748
  </button>
138
749
  </div>
139
- <div class="ss_form_date__title">{g()}</div>
750
+ <div class="ss_form_date__title">{monthLabel()}</div>
140
751
  <div class="ss_form_date__nav_group">
141
- <button type="button"class="ss_form_date__nav"onclick={()=>{let f=c();d(new Date(f.getFullYear(),f.getMonth()+1,1))}}>
142
- <svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-right"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M9 6l6 6l-6 6"/></svg>
752
+ <button type="button" class="ss_form_date__nav" onclick={() => {
753
+ const current = viewDate();
754
+ setViewDate(new Date(current.getFullYear(), current.getMonth() + 1, 1));
755
+ }}>
756
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-right"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M9 6l6 6l-6 6" /></svg>
143
757
  </button>
144
- <button type="button"class="ss_form_date__nav"onclick={()=>{let f=c();d(new Date(f.getFullYear()+1,f.getMonth(),1))}}>
145
- <svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-right-pipe"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M6 6l6 6l-6 6"/><path d="M17 5v13"/></svg>
758
+ <button type="button" class="ss_form_date__nav" onclick={() => {
759
+ const current = viewDate();
760
+ setViewDate(new Date(current.getFullYear() + 1, current.getMonth(), 1));
761
+ }}>
762
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-right-pipe"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M6 6l6 6l-6 6" /><path d="M17 5v13" /></svg>
146
763
  </button>
147
764
  </div>
148
765
  </div>
149
766
  <div class="ss_form_date__weekdays">
150
- {["Mo","Di","Mi","Do","Fr","Sa","So"].map(f=><span>{f}</span>)}
767
+ {["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"].map((day) => <span>{day}</span>)}
151
768
  </div>
152
769
  <div class="ss_form_date__grid">
153
- {L().map(f=>f?<button type="button"class="ss_form_date__day"classList={{"is-selected":k(f),"is-today":E(f)}}onclick={()=>p(f)}>
154
- {f}
155
- </button>:<span class="ss_form_date__day is-empty"/>)}
770
+ {buildCalendar().map((day) => day ? <button
771
+ type="button"
772
+ class="ss_form_date__day"
773
+ classList={{ "is-selected": isSelected(day), "is-today": isToday(day) }}
774
+ onclick={() => handleSelect(day)}
775
+ >
776
+ {day}
777
+ </button> : <span class="ss_form_date__day is-empty" />)}
156
778
  </div>
157
779
  </div>}
158
780
 
159
- {!!o()&&<span role="alert">{o()}</span>}
160
- </div>};J.Checkbox=function(e){let t=B(_e),[n,r]=S(!1),[o,s]=S(null),l={getValue:()=>n(),setValue:c=>r(!!c),hasError:()=>!!o(),validate:async()=>{let c=[...e.rules??[]];e.required&&c.unshift(J.rules.required);let d=await l.getValue();for(let u of c){let a=await u(d);if(a){s(a);return}}s(null)}};if(e.name&&t){let c=e.name;X(()=>t.setField(c,l)),R(()=>t.delField(c))}let i=Q();return<div class="ss_form_checkbox">
781
+ {!!error() && <span role="alert">{error()}</span>}
782
+ </div>;
783
+ };
784
+ SSForm.Checkbox = function(props) {
785
+ const context = useContext(SSFormContext);
786
+ const [value, setValue] = createSignal5(false);
787
+ const [error, setError] = createSignal5(null);
788
+ const field = {
789
+ getValue: () => value(),
790
+ setValue: (value2) => setValue(!!value2),
791
+ hasError: () => !!error(),
792
+ validate: async () => {
793
+ const rules = [...props.rules ?? []];
794
+ if (props.required) rules.unshift(SSForm.rules.required);
795
+ const value2 = await field.getValue();
796
+ for (const rule of rules) {
797
+ const newError = await rule(value2);
798
+ if (newError) {
799
+ setError(newError);
800
+ return;
801
+ }
802
+ }
803
+ setError(null);
804
+ }
805
+ };
806
+ if (props.name && context) {
807
+ const name = props.name;
808
+ onMount2(() => context.setField(name, field));
809
+ onCleanup3(() => context.delField(name));
810
+ }
811
+ const _id = createUniqueId();
812
+ return <div class="ss_form_checkbox">
161
813
  <div class="ss__wrapper">
162
- <input id={e.id||i}type="checkbox"checked={n()}onchange={c=>r(c.target.checked)}disabled={e.disabled||t?.loading()}/>
163
- <label for={e.id||i}>{e.label}</label>
814
+ <input
815
+ id={props.id || _id}
816
+ type="checkbox"
817
+ checked={value()}
818
+ onchange={(e) => setValue(e.target.checked)}
819
+ disabled={props.disabled || context?.loading()}
820
+ />
821
+ <label for={props.id || _id}>{props.label}</label>
164
822
  </div>
165
823
 
166
- {!!o()&&<span role="alert">{o()}</span>}
167
- </div>};J.useContext=function(){let e=B(_e);if(!e)return null;let{setField:t,delField:n,...r}=e;return r};J.Select=function(e){let t=B(_e),[n,r]=S([]),[o,s]=S(null),[l,i]=S(null),c=a=>{let m=a.map(b=>({id:b.id,label:e.buildOption(b)}));if(r(m),!a.length){s(null);return}o()&&m.some(b=>b.id===o())||s(m[0].id)};N(()=>{let a=e.getOptions();"then"in a&&typeof a.then=="function"||a instanceof Promise?a.then(c):c(a)});let d={getValue:()=>{let a=o();return n().some(b=>b.id===a)?a:null},setValue:a=>{let m=n();if(!m.length){s(null);return}let b=m[0].id;if(typeof a!="string"){s(b);return}let x=a.trim();if(!m.some(y=>y.id===x)){s(b);return}s(x)},hasError:()=>!!l(),validate:async()=>{let a=n(),m=await d.getValue();if(!m){i("Pflichtfeld");return}if(!a.some(b=>b.id===m)){i("Option nicht verf\xFCgbar");return}for(let b of e.rules??[]){let x=await b(m);if(x){i(x);return}}i(null)}};if(d.setOptions=c,e.name&&t){let a=e.name;X(()=>t.setField(a,d)),R(()=>t.delField(a))}let u=Q();return<div class="ss_form_select">
168
- <label for={e.id||u}>{e.label}</label>
824
+ {!!error() && <span role="alert">{error()}</span>}
825
+ </div>;
826
+ };
827
+ SSForm.useContext = function() {
828
+ const context = useContext(SSFormContext);
829
+ if (!context) return null;
830
+ const { setField, delField, ...publicContext } = context;
831
+ return publicContext;
832
+ };
833
+ SSForm.Select = function(props) {
834
+ const context = useContext(SSFormContext);
835
+ const [options, setOptions] = createSignal5([]);
836
+ const [value, setValue] = createSignal5(null);
837
+ const [error, setError] = createSignal5(null);
838
+ const handleSetOptions = (result) => {
839
+ const built = result.map((opt) => ({ id: opt.id, label: props.buildOption(opt) }));
840
+ setOptions(built);
841
+ if (!result.length) {
842
+ setValue(null);
843
+ return;
844
+ }
845
+ if (value() && built.some((e) => e.id === value())) return;
846
+ setValue(built[0].id);
847
+ };
848
+ createEffect3(() => {
849
+ const newOptions = props.getOptions();
850
+ if ("then" in newOptions && typeof newOptions.then === "function" || newOptions instanceof Promise) {
851
+ newOptions.then(handleSetOptions);
852
+ } else {
853
+ handleSetOptions(newOptions);
854
+ }
855
+ });
856
+ const field = {
857
+ getValue: () => {
858
+ const _value = value();
859
+ const availableOptions = options();
860
+ if (!availableOptions.some((e) => e.id === _value)) {
861
+ return null;
862
+ }
863
+ return _value;
864
+ },
865
+ setValue: (newValue) => {
866
+ const availableOptions = options();
867
+ if (!availableOptions.length) {
868
+ setValue(null);
869
+ return;
870
+ }
871
+ const defaultOption = availableOptions[0].id;
872
+ if (typeof newValue !== "string") {
873
+ setValue(defaultOption);
874
+ return;
875
+ }
876
+ const _newValue = newValue.trim();
877
+ if (!availableOptions.some((e) => e.id === _newValue)) {
878
+ setValue(defaultOption);
879
+ return;
880
+ }
881
+ setValue(_newValue);
882
+ },
883
+ hasError: () => !!error(),
884
+ validate: async () => {
885
+ const availableOptions = options();
886
+ const value2 = await field.getValue();
887
+ if (!value2) {
888
+ setError("Pflichtfeld");
889
+ return;
890
+ }
891
+ if (!availableOptions.some((e) => e.id === value2)) {
892
+ setError("Option nicht verf\xFCgbar");
893
+ return;
894
+ }
895
+ for (const rule of props.rules ?? []) {
896
+ const err = await rule(value2);
897
+ if (err) {
898
+ setError(err);
899
+ return;
900
+ }
901
+ }
902
+ setError(null);
903
+ }
904
+ };
905
+ field.setOptions = handleSetOptions;
906
+ if (props.name && context) {
907
+ const name = props.name;
908
+ onMount2(() => context.setField(name, field));
909
+ onCleanup3(() => context.delField(name));
910
+ }
911
+ const _id = createUniqueId();
912
+ return <div class="ss_form_select">
913
+ <label for={props.id || _id}>{props.label}</label>
169
914
 
170
915
  <div class="ss_form_select__field">
171
- <select id={e.id||u}onchange={a=>s(a.target.value)}disabled={e.disabled||t?.loading()}>
172
- <K each={n()}>
173
- {a=><option value={a.id}selected={o()===a.id}>{a.label}</option>}
174
- </K>
916
+ <select
917
+ id={props.id || _id}
918
+ onchange={(e) => setValue(e.target.value)}
919
+ disabled={props.disabled || context?.loading()}
920
+ >
921
+ <For3 each={options()}>
922
+ {(opt) => <option value={opt.id} selected={value() === opt.id}>{opt.label}</option>}
923
+ </For3>
175
924
  </select>
176
- <span class="ss_form_select__icon"aria-hidden="true">
177
- <svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-down"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M6 9l6 6l6 -6"/></svg>
925
+ <span class="ss_form_select__icon" aria-hidden="true">
926
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-down"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M6 9l6 6l6 -6" /></svg>
178
927
  </span>
179
928
  </div>
180
929
 
181
- {!!l()&&<span role="alert">{l()}</span>}
182
- </div>};J.ACSelect=function(e){let t=B(_e),[n,r]=S(""),[o,s]=S([]),[l,i]=S(null),c={getValue:()=>o(),setValue:w=>s(w),hasError:()=>!!l(),validate:async()=>{let w=await c.getValue(),M=e.minSelectedItems,_=e.maxSelectedItems;if(M&&w.length<M){i(`Mindestens ${M} ${M>1?"Elemente m\xFCssen":"Element muss"} ausgew\xE4hlt werden`);return}if(_&&w.length>_){i(`Maximal ${_} ${_>1?"Elemente d\xFCrfen":"Element darf"} ausgew\xE4hlt werden`);return}for(let P of e.rules??[]){let I=await P(w);if(I){i(I);return}}i(null)}};if(e.name&&t){let w=e.name;X(()=>t.setField(w,c)),R(()=>t.delField(w))}let d=null,[u,a]=S(!e.prepare);e.prepare&&X(async()=>{e.prepare&&(d=await e.prepare(),a(!0))});let[m,b]=S([]),[x,y]=S(-1),k,E;N(()=>{if(!u())return;clearTimeout(E);let w=n().trim().toLowerCase();if(!w){b(V(()=>o()));return}b([]),E=setTimeout(async()=>{let M=await e.getOptions({query:w,init:d});b(M)},250)}),N(()=>{n().trim().toLowerCase()||m().length!==o().length&&b(o())}),R(()=>clearTimeout(E)),N(()=>{let w=m();if(!w.length){y(-1);return}x()>=w.length&&y(w.length-1)});let L=w=>{let M=k;if(!M||w<0)return;let _=M.querySelectorAll("li")[w];if(!_)return;let P=_.offsetTop,I=P+_.offsetHeight,H=M.scrollTop,xe=H+M.clientHeight;P<H?M.scrollTop=P:I>xe&&(M.scrollTop=I-M.clientHeight)},g=w=>{let M=m();if(!M.length)return;let _=Math.max(-1,Math.min(x()+w,M.length-1));y(_),L(_)},p=Q(),f=D(()=>new Set(o().map(({id:w})=>w))),v=(w,M=!0)=>{let _=f().has(w.id);if(e.maxSelectedItems===1){s(_?[]:[w]),r(""),M&&y(-1);return}s(_?P=>P.filter(({id:I})=>I!==w.id):P=>[...P.filter(({id:I})=>I!==w.id),w]),M&&y(-1)},F=w=>{if(m().length)if(w.key==="ArrowDown")w.preventDefault(),g(1);else if(w.key==="ArrowUp")w.preventDefault(),g(-1);else if(w.key==="Enter"&&x()>=0){w.preventDefault();let M=m()[x()];M&&v(M,!1)}else w.key==="Escape"&&y(-1)},A=()=>e.disabled||t?.loading();return<div class="ss_form_ac_select">
183
- <label for={e.id||p}>{e.label}</label>
930
+ {!!error() && <span role="alert">{error()}</span>}
931
+ </div>;
932
+ };
933
+ SSForm.ACSelect = function(props) {
934
+ const context = useContext(SSFormContext);
935
+ const [query, setQuery] = createSignal5("");
936
+ const [value, setValue] = createSignal5([]);
937
+ const [error, setError] = createSignal5(null);
938
+ const field = {
939
+ getValue: () => value(),
940
+ setValue: (newValue) => setValue(newValue),
941
+ hasError: () => !!error(),
942
+ validate: async () => {
943
+ const value2 = await field.getValue();
944
+ const min = props.minSelectedItems;
945
+ const max = props.maxSelectedItems;
946
+ if (min) {
947
+ if (value2.length < min) {
948
+ setError(`Mindestens ${min} ${min > 1 ? "Elemente m\xFCssen" : "Element muss"} ausgew\xE4hlt werden`);
949
+ return;
950
+ }
951
+ }
952
+ if (max) {
953
+ if (value2.length > max) {
954
+ setError(`Maximal ${max} ${max > 1 ? "Elemente d\xFCrfen" : "Element darf"} ausgew\xE4hlt werden`);
955
+ return;
956
+ }
957
+ }
958
+ for (const rule of props.rules ?? []) {
959
+ const err = await rule(value2);
960
+ if (err) {
961
+ setError(err);
962
+ return;
963
+ }
964
+ }
965
+ setError(null);
966
+ }
967
+ };
968
+ if (props.name && context) {
969
+ const name = props.name;
970
+ onMount2(() => context.setField(name, field));
971
+ onCleanup3(() => context.delField(name));
972
+ }
973
+ let initData = null;
974
+ const [initialized, setInitialized] = createSignal5(!props.prepare);
975
+ if (props.prepare) onMount2(async () => {
976
+ if (!props.prepare) return;
977
+ initData = await props.prepare();
978
+ setInitialized(true);
979
+ });
980
+ const [suggItems, setSuggItems] = createSignal5([]);
981
+ const [suggIndex, setSuggIndex] = createSignal5(-1);
982
+ let suggListRef;
983
+ let timeout;
984
+ createEffect3(() => {
985
+ if (!initialized()) return;
986
+ clearTimeout(timeout);
987
+ const _query = query().trim().toLowerCase();
988
+ if (!_query) {
989
+ setSuggItems(untrack(() => value()));
990
+ return;
991
+ }
992
+ setSuggItems([]);
993
+ timeout = setTimeout(async () => {
994
+ const items = await props.getOptions({ query: _query, init: initData });
995
+ setSuggItems(items);
996
+ }, 250);
997
+ });
998
+ createEffect3(() => {
999
+ const _query = query().trim().toLowerCase();
1000
+ if (_query) return;
1001
+ if (suggItems().length !== value().length) setSuggItems(value());
1002
+ });
1003
+ onCleanup3(() => clearTimeout(timeout));
1004
+ createEffect3(() => {
1005
+ const items = suggItems();
1006
+ if (!items.length) {
1007
+ setSuggIndex(-1);
1008
+ return;
1009
+ }
1010
+ if (suggIndex() >= items.length) setSuggIndex(items.length - 1);
1011
+ });
1012
+ const scrollToIndex = (idx) => {
1013
+ const list = suggListRef;
1014
+ if (!list || idx < 0) return;
1015
+ const item = list.querySelectorAll("li")[idx];
1016
+ if (!item) return;
1017
+ const itemTop = item.offsetTop;
1018
+ const itemBottom = itemTop + item.offsetHeight;
1019
+ const viewTop = list.scrollTop;
1020
+ const viewBottom = viewTop + list.clientHeight;
1021
+ if (itemTop < viewTop) list.scrollTop = itemTop;
1022
+ else if (itemBottom > viewBottom) list.scrollTop = itemBottom - list.clientHeight;
1023
+ };
1024
+ const moveIndex = (delta) => {
1025
+ const items = suggItems();
1026
+ if (!items.length) return;
1027
+ const next = Math.max(-1, Math.min(suggIndex() + delta, items.length - 1));
1028
+ setSuggIndex(next);
1029
+ scrollToIndex(next);
1030
+ };
1031
+ const _id = createUniqueId();
1032
+ const selectedIds = createMemo3(() => {
1033
+ return new Set(value().map(({ id }) => id));
1034
+ });
1035
+ const selectItem = (item, resetIndex = true) => {
1036
+ const isSelected = selectedIds().has(item.id);
1037
+ if (props.maxSelectedItems === 1) {
1038
+ setValue(isSelected ? [] : [item]);
1039
+ setQuery("");
1040
+ if (resetIndex) setSuggIndex(-1);
1041
+ return;
1042
+ }
1043
+ if (isSelected) {
1044
+ setValue((value2) => value2.filter(({ id }) => id !== item.id));
1045
+ } else {
1046
+ setValue((value2) => [...value2.filter(({ id }) => id !== item.id), item]);
1047
+ }
1048
+ if (resetIndex) setSuggIndex(-1);
1049
+ };
1050
+ const handleKeyDown = (e) => {
1051
+ if (!suggItems().length) return;
1052
+ if (e.key === "ArrowDown") {
1053
+ e.preventDefault();
1054
+ moveIndex(1);
1055
+ } else if (e.key === "ArrowUp") {
1056
+ e.preventDefault();
1057
+ moveIndex(-1);
1058
+ } else if (e.key === "Enter" && suggIndex() >= 0) {
1059
+ e.preventDefault();
1060
+ const item = suggItems()[suggIndex()];
1061
+ if (item) selectItem(item, false);
1062
+ } else if (e.key === "Escape") {
1063
+ setSuggIndex(-1);
1064
+ }
1065
+ };
1066
+ const isDisabled = () => props.disabled || context?.loading();
1067
+ return <div class="ss_form_ac_select">
1068
+ <label for={props.id || _id}>{props.label}</label>
184
1069
 
185
- {e.maxSelectedItems===1&&e.renderSelection&&o().length===1?<div class="ss__selection">
1070
+ {props.maxSelectedItems === 1 && !!props.renderSelection && value().length === 1 ? <div class="ss__selection">
186
1071
  <div class="ss__content">
187
- {e.renderSelection({item:o()[0],init:d})}
1072
+ {props.renderSelection({ item: value()[0], init: initData })}
188
1073
  </div>
189
- <button type="button"class="ss__clear"disabled={A()}aria-label="Auswahl entfernen"onclick={()=>{s([]),r(""),setTimeout(()=>document.getElementById(e.id||p)?.focus(),0)}}>
1074
+ <button
1075
+ type="button"
1076
+ class="ss__clear"
1077
+ disabled={isDisabled()}
1078
+ aria-label="Auswahl entfernen"
1079
+ onclick={() => {
1080
+ setValue([]);
1081
+ setQuery("");
1082
+ setTimeout(() => document.getElementById(props.id || _id)?.focus(), 0);
1083
+ }}
1084
+ >
190
1085
  ×
191
1086
  </button>
192
- </div>:<div class="ss__wrapper">
1087
+ </div> : <div class="ss__wrapper">
193
1088
 
194
1089
  <div class="ss__input_row">
195
- {!!o().length&&<span class="ss__prefix"role="button"tabindex={A()?-1:0}aria-disabled={A()?"true":void 0}onkeydown={w=>{A()||(w.key==="Enter"||w.key===" ")&&(w.preventDefault(),s([]))}}onclick={()=>{A()||s([])}}>
196
- {o().length}
1090
+ {!!value().length && <span
1091
+ class="ss__prefix"
1092
+ role="button"
1093
+ tabindex={isDisabled() ? -1 : 0}
1094
+ aria-disabled={isDisabled() ? "true" : void 0}
1095
+ onkeydown={(event) => {
1096
+ if (isDisabled()) return;
1097
+ if (event.key === "Enter" || event.key === " ") {
1098
+ event.preventDefault();
1099
+ setValue([]);
1100
+ }
1101
+ }}
1102
+ onclick={() => {
1103
+ if (isDisabled()) return;
1104
+ setValue([]);
1105
+ }}
1106
+ >
1107
+ {value().length}
197
1108
  </span>}
198
1109
 
199
- <input id={e.id||p}value={n()}oninput={w=>{A()||(r(w.target.value),y(-1))}}onkeydown={F}disabled={A()}/>
1110
+ <input
1111
+ id={props.id || _id}
1112
+ value={query()}
1113
+ oninput={(e) => {
1114
+ if (isDisabled()) return;
1115
+ setQuery(e.target.value);
1116
+ setSuggIndex(-1);
1117
+ }}
1118
+ onkeydown={handleKeyDown}
1119
+ disabled={isDisabled()}
1120
+ />
200
1121
  </div>
201
1122
 
202
- {!!m().length&&<ul class="ss__suggestions"ref={w=>k=w}>
203
- <K each={m()}>
204
- {(w,M)=>{let _=()=>{A()||(v(w),document.getElementById(e.id||p)?.focus())};return<li onpointerdown={P=>P.preventDefault()}onclick={_}classList={{ss__selected:f().has(w.id),ss__hovered:M()===x()}}>
205
- {e.renderItem({item:w,init:d})}
206
- </li>}}
207
- </K>
1123
+ {!!suggItems().length && <ul class="ss__suggestions" ref={(el) => suggListRef = el}>
1124
+ <For3 each={suggItems()}>
1125
+ {(item, idx) => {
1126
+ const handleSelect = () => {
1127
+ if (isDisabled()) return;
1128
+ selectItem(item);
1129
+ document.getElementById(props.id || _id)?.focus();
1130
+ };
1131
+ return <li
1132
+ onpointerdown={(e) => e.preventDefault()}
1133
+ onclick={handleSelect}
1134
+ classList={{
1135
+ "ss__selected": selectedIds().has(item.id),
1136
+ "ss__hovered": idx() === suggIndex()
1137
+ }}
1138
+ >
1139
+ {props.renderItem({ item, init: initData })}
1140
+ </li>;
1141
+ }}
1142
+ </For3>
208
1143
  </ul>}
209
1144
  </div>}
210
1145
 
211
- {!!l()&&<span role="alert">{l()}</span>}
212
- </div>};J.SubmitButton=function(e){let t=B(_e);return<div>
213
- <Y type="submit"class="ss_form_submit"disabled={e.disabled||t?.loading()}>
214
- {e.children}
215
- </Y>
216
- </div>};J.rules={required:e=>e?null:"Pflichtfeld",minLength:e=>t=>{if(t===null&&(t=""),typeof t!="string")throw new Error(`invalid rule minLength(..) for non-string value ${t}`);return t.length<e?`Mindestens ${e} Zeichen`:null},maxLength:e=>t=>{if(t===null&&(t=""),typeof t!="string")throw new Error(`invalid rule maxLength(..) for non-string value ${t}`);return t.length<e?`Maximal ${e} Zeichen`:null},pattern:e=>t=>{if(t===null&&(t=""),typeof t!="string")throw new Error(`invalid rule pattern(..) for non-string value ${t}`);return e.test(t)?null:"Eingabe widerspricht erwartetem Muster"}};function En(e){return<div class={`ss_header ${e.class??""}`}style={e.style}>
1146
+ {!!error() && <span role="alert">{error()}</span>}
1147
+ </div>;
1148
+ };
1149
+ SSForm.SubmitButton = function(props) {
1150
+ const context = useContext(SSFormContext);
1151
+ return <div>
1152
+ <SSButton
1153
+ type="submit"
1154
+ class="ss_form_submit"
1155
+ disabled={props.disabled || context?.loading()}
1156
+ >
1157
+ {props.children}
1158
+ </SSButton>
1159
+ </div>;
1160
+ };
1161
+ SSForm.rules = {
1162
+ required: (value) => !value ? "Pflichtfeld" : null,
1163
+ minLength: (length) => (value) => {
1164
+ if (value === null) value = "";
1165
+ if (typeof value !== "string") {
1166
+ throw new Error(`invalid rule minLength(..) for non-string value ${value}`);
1167
+ }
1168
+ if (value.length < length) return `Mindestens ${length} Zeichen`;
1169
+ return null;
1170
+ },
1171
+ maxLength: (length) => (value) => {
1172
+ if (value === null) value = "";
1173
+ if (typeof value !== "string") {
1174
+ throw new Error(`invalid rule maxLength(..) for non-string value ${value}`);
1175
+ }
1176
+ if (value.length < length) return `Maximal ${length} Zeichen`;
1177
+ return null;
1178
+ },
1179
+ pattern: (pattern) => (value) => {
1180
+ if (value === null) value = "";
1181
+ if (typeof value !== "string") {
1182
+ throw new Error(`invalid rule pattern(..) for non-string value ${value}`);
1183
+ }
1184
+ if (!pattern.test(value)) return "Eingabe widerspricht erwartetem Muster";
1185
+ return null;
1186
+ }
1187
+ };
1188
+
1189
+ // src/components/SSHeader.tsx
1190
+ function SSHeader(props) {
1191
+ return <div class={`ss_header ${props.class ?? ""}`} style={props.style}>
217
1192
  <div class="ss_header__text">
218
- <h3 class="ss_header__title">{e.title}</h3>
219
- {e.subtitle&&<h5 class="ss_header__subtitle">{e.subtitle}</h5>}
1193
+ <h3 class="ss_header__title">{props.title}</h3>
1194
+ {props.subtitle && <h5 class="ss_header__subtitle">{props.subtitle}</h5>}
220
1195
  </div>
221
- <div class="ss_header__actions">{e.actions}</div>
222
- </div>}var Pn=["allowfullscreen","async","alpha","autofocus","autoplay","checked","controls","default","disabled","formnovalidate","hidden","indeterminate","inert","ismap","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","seamless","selected","adauctionheaders","browsingtopics","credentialless","defaultchecked","defaultmuted","defaultselected","defer","disablepictureinpicture","disableremoteplayback","preservespitch","shadowrootclonable","shadowrootcustomelementregistry","shadowrootdelegatesfocus","shadowrootserializable","sharedstoragewritable"],Cn=new Set(["className","value","readOnly","noValidate","formNoValidate","isMap","noModule","playsInline","adAuctionHeaders","allowFullscreen","browsingTopics","defaultChecked","defaultMuted","defaultSelected","disablePictureInPicture","disableRemotePlayback","preservesPitch","shadowRootClonable","shadowRootCustomElementRegistry","shadowRootDelegatesFocus","shadowRootSerializable","sharedStorageWritable",...Pn]),Tn=new Set(["innerHTML","textContent","innerText","children"]),Mn=Object.assign(Object.create(null),{className:"class",htmlFor:"for"}),An=Object.assign(Object.create(null),{class:"className",novalidate:{$:"noValidate",FORM:1},formnovalidate:{$:"formNoValidate",BUTTON:1,INPUT:1},ismap:{$:"isMap",IMG:1},nomodule:{$:"noModule",SCRIPT:1},playsinline:{$:"playsInline",VIDEO:1},readonly:{$:"readOnly",INPUT:1,TEXTAREA:1},adauctionheaders:{$:"adAuctionHeaders",IFRAME:1},allowfullscreen:{$:"allowFullscreen",IFRAME:1},browsingtopics:{$:"browsingTopics",IMG:1},defaultchecked:{$:"defaultChecked",INPUT:1},defaultmuted:{$:"defaultMuted",AUDIO:1,VIDEO:1},defaultselected:{$:"defaultSelected",OPTION:1},disablepictureinpicture:{$:"disablePictureInPicture",VIDEO:1},disableremoteplayback:{$:"disableRemotePlayback",AUDIO:1,VIDEO:1},preservespitch:{$:"preservesPitch",AUDIO:1,VIDEO:1},shadowrootclonable:{$:"shadowRootClonable",TEMPLATE:1},shadowrootdelegatesfocus:{$:"shadowRootDelegatesFocus",TEMPLATE:1},shadowrootserializable:{$:"shadowRootSerializable",TEMPLATE:1},sharedstoragewritable:{$:"sharedStorageWritable",IFRAME:1,IMG:1}});function On(e,t){let n=An[e];return typeof n=="object"?n[t]?n.$:void 0:n}var Ln=new Set(["beforeinput","click","dblclick","contextmenu","focusin","focusout","input","keydown","keyup","mousedown","mousemove","mouseout","mouseover","mouseup","pointerdown","pointermove","pointerout","pointerover","pointerup","touchend","touchmove","touchstart"]);var Rn={xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace"};function Fn(e,t,n){let r=n.length,o=t.length,s=r,l=0,i=0,c=t[o-1].nextSibling,d=null;for(;l<o||i<s;){if(t[l]===n[i]){l++,i++;continue}for(;t[o-1]===n[s-1];)o--,s--;if(o===l){let u=s<r?i?n[i-1].nextSibling:n[s-i]:c;for(;i<s;)e.insertBefore(n[i++],u)}else if(s===i)for(;l<o;)(!d||!d.has(t[l]))&&t[l].remove(),l++;else if(t[l]===n[s-1]&&n[i]===t[o-1]){let u=t[--o].nextSibling;e.insertBefore(n[i++],t[l++].nextSibling),e.insertBefore(n[--s],u),t[o]=n[s]}else{if(!d){d=new Map;let a=i;for(;a<s;)d.set(n[a],a++)}let u=d.get(t[l]);if(u!=null)if(i<u&&u<s){let a=l,m=1,b;for(;++a<o&&a<s&&!((b=d.get(t[a]))==null||b!==u+m);)m++;if(m>u-i){let x=t[l];for(;i<u;)e.insertBefore(n[i++],x)}else e.replaceChild(n[i++],t[l++])}else l++;else t[l++].remove()}}}var At="_$DX_DELEGATE";function It(e,t,n,r){let o,s=()=>{let i=r?document.createElementNS("http://www.w3.org/1998/Math/MathML","template"):document.createElement("template");return i.innerHTML=e,n?i.content.firstChild.firstChild:r?i.firstChild:i.content.firstChild},l=t?()=>V(()=>document.importNode(o||(o=s()),!0)):()=>(o||(o=s())).cloneNode(!0);return l.cloneNode=l,l}function $t(e,t=window.document){let n=t[At]||(t[At]=new Set);for(let r=0,o=e.length;r<o;r++){let s=e[r];n.has(s)||(n.add(s),t.addEventListener(s,qn))}}function lt(e,t,n){Oe(e)||(n==null?e.removeAttribute(t):e.setAttribute(t,n))}function Dn(e,t,n,r){Oe(e)||(r==null?e.removeAttributeNS(t,n):e.setAttributeNS(t,n,r))}function In(e,t,n){Oe(e)||(n?e.setAttribute(t,""):e.removeAttribute(t))}function $n(e,t){Oe(e)||(t==null?e.removeAttribute("class"):e.className=t)}function Hn(e,t,n,r){if(r)Array.isArray(n)?(e[`$$${t}`]=n[0],e[`$$${t}Data`]=n[1]):e[`$$${t}`]=n;else if(Array.isArray(n)){let o=n[0];e.addEventListener(t,n[0]=s=>o.call(e,n[1],s))}else e.addEventListener(t,n,typeof n!="function"&&n)}function Bn(e,t,n={}){let r=Object.keys(t||{}),o=Object.keys(n),s,l;for(s=0,l=o.length;s<l;s++){let i=o[s];!i||i==="undefined"||t[i]||(Lt(e,i,!1),delete n[i])}for(s=0,l=r.length;s<l;s++){let i=r[s],c=!!t[i];!i||i==="undefined"||n[i]===c||!c||(Lt(e,i,!0),n[i]=c)}return n}function Nn(e,t,n){if(!t)return n?lt(e,"style"):t;let r=e.style;if(typeof t=="string")return r.cssText=t;typeof n=="string"&&(r.cssText=n=void 0),n||(n={}),t||(t={});let o,s;for(s in n)t[s]==null&&r.removeProperty(s),delete n[s];for(s in t)o=t[s],o!==n[s]&&(r.setProperty(s,o),n[s]=o);return n}function Ht(e,t={},n,r){let o={};return r||G(()=>o.children=Ae(e,t.children,o.children)),G(()=>typeof t.ref=="function"&&jn(t.ref,e)),G(()=>Vn(e,t,n,!0,o,!0)),o}function jn(e,t,n){return V(()=>e(t,n))}function Ot(e,t,n,r){if(n!==void 0&&!r&&(r=[]),typeof t!="function")return Ae(e,t,r,n);G(o=>Ae(e,t(),o,n),r)}function Vn(e,t,n,r,o={},s=!1){t||(t={});for(let l in o)if(!(l in t)){if(l==="children")continue;o[l]=Rt(e,l,null,o[l],n,s,t)}for(let l in t){if(l==="children"){r||Ae(e,t.children);continue}let i=t[l];o[l]=Rt(e,l,i,o[l],n,s,t)}}function Oe(e){return!!T.context&&!T.done&&(!e||e.isConnected)}function Xn(e){return e.toLowerCase().replace(/-([a-z])/g,(t,n)=>n.toUpperCase())}function Lt(e,t,n){let r=t.trim().split(/\s+/);for(let o=0,s=r.length;o<s;o++)e.classList.toggle(r[o],n)}function Rt(e,t,n,r,o,s,l){let i,c,d,u,a;if(t==="style")return Nn(e,n,r);if(t==="classList")return Bn(e,n,r);if(n===r)return r;if(t==="ref")s||n(e);else if(t.slice(0,3)==="on:"){let m=t.slice(3);r&&e.removeEventListener(m,r,typeof r!="function"&&r),n&&e.addEventListener(m,n,typeof n!="function"&&n)}else if(t.slice(0,10)==="oncapture:"){let m=t.slice(10);r&&e.removeEventListener(m,r,!0),n&&e.addEventListener(m,n,!0)}else if(t.slice(0,2)==="on"){let m=t.slice(2).toLowerCase(),b=Ln.has(m);if(!b&&r){let x=Array.isArray(r)?r[0]:r;e.removeEventListener(m,x)}(b||n)&&(Hn(e,m,n,b),b&&$t([m]))}else if(t.slice(0,5)==="attr:")lt(e,t.slice(5),n);else if(t.slice(0,5)==="bool:")In(e,t.slice(5),n);else if((a=t.slice(0,5)==="prop:")||(d=Tn.has(t))||!o&&((u=On(t,e.tagName))||(c=Cn.has(t)))||(i=e.nodeName.includes("-")||"is"in l)){if(a)t=t.slice(5),c=!0;else if(Oe(e))return n;t==="class"||t==="className"?$n(e,n):i&&!c&&!d?e[Xn(t)]=n:e[u||t]=n}else{let m=o&&t.indexOf(":")>-1&&Rn[t.split(":")[0]];m?Dn(e,m,t,n):lt(e,Mn[t]||t,n)}return n}function qn(e){if(T.registry&&T.events&&T.events.find(([c,d])=>d===e))return;let t=e.target,n=`$$${e.type}`,r=e.target,o=e.currentTarget,s=c=>Object.defineProperty(e,"target",{configurable:!0,value:c}),l=()=>{let c=t[n];if(c&&!t.disabled){let d=t[`${n}Data`];if(d!==void 0?c.call(t,d,e):c.call(t,e),e.cancelBubble)return}return t.host&&typeof t.host!="string"&&!t.host._$host&&t.contains(e.target)&&s(t.host),!0},i=()=>{for(;l()&&(t=t._$host||t.parentNode||t.host););};if(Object.defineProperty(e,"currentTarget",{configurable:!0,get(){return t||document}}),T.registry&&!T.done&&(T.done=_$HY.done=!0),e.composedPath){let c=e.composedPath();s(c[0]);for(let d=0;d<c.length-2&&(t=c[d],!!l());d++){if(t._$host){t=t._$host,i();break}if(t.parentNode===o)break}}else i();s(r)}function Ae(e,t,n,r,o){let s=Oe(e);if(s){!n&&(n=[...e.childNodes]);let c=[];for(let d=0;d<n.length;d++){let u=n[d];u.nodeType===8&&u.data.slice(0,2)==="!$"?u.remove():c.push(u)}n=c}for(;typeof n=="function";)n=n();if(t===n)return n;let l=typeof t,i=r!==void 0;if(e=i&&n[0]&&n[0].parentNode||e,l==="string"||l==="number"){if(s||l==="number"&&(t=t.toString(),t===n))return n;if(i){let c=n[0];c&&c.nodeType===3?c.data!==t&&(c.data=t):c=document.createTextNode(t),n=Me(e,n,r,c)}else n!==""&&typeof n=="string"?n=e.firstChild.data=t:n=e.textContent=t}else if(t==null||l==="boolean"){if(s)return n;n=Me(e,n,r)}else{if(l==="function")return G(()=>{let c=t();for(;typeof c=="function";)c=c();n=Ae(e,c,n,r)}),()=>n;if(Array.isArray(t)){let c=[],d=n&&Array.isArray(n);if(at(c,t,n,o))return G(()=>n=Ae(e,c,n,r,!0)),()=>n;if(s){if(!c.length)return n;if(r===void 0)return n=[...e.childNodes];let u=c[0];if(u.parentNode!==e)return n;let a=[u];for(;(u=u.nextSibling)!==r;)a.push(u);return n=a}if(c.length===0){if(n=Me(e,n,r),i)return n}else d?n.length===0?Ft(e,c,r):Fn(e,n,c):(n&&Me(e),Ft(e,c));n=c}else if(t.nodeType){if(s&&t.parentNode)return n=i?[t]:t;if(Array.isArray(n)){if(i)return n=Me(e,n,r,t);Me(e,n,null,t)}else n==null||n===""||!e.firstChild?e.appendChild(t):e.replaceChild(t,e.firstChild);n=t}}return n}function at(e,t,n,r){let o=!1;for(let s=0,l=t.length;s<l;s++){let i=t[s],c=n&&n[e.length],d;if(!(i==null||i===!0||i===!1))if((d=typeof i)=="object"&&i.nodeType)e.push(i);else if(Array.isArray(i))o=at(e,i,c)||o;else if(d==="function")if(r){for(;typeof i=="function";)i=i();o=at(e,Array.isArray(i)?i:[i],Array.isArray(c)?c:[c])||o}else e.push(i),o=!0;else{let u=String(i);c&&c.nodeType===3&&c.data===u?e.push(c):e.push(document.createTextNode(u))}}return o}function Ft(e,t,n=null){for(let r=0,o=t.length;r<o;r++)e.insertBefore(t[r],n)}function Me(e,t,n,r){if(n===void 0)return e.textContent="";let o=r||document.createTextNode("");if(t.length){let s=!1;for(let l=t.length-1;l>=0;l--){let i=t[l];if(o!==i){let c=i.parentNode===e;!s&&!l?c?e.replaceChild(o,i):e.insertBefore(o,n):c&&i.remove()}else s=!0}}else e.insertBefore(o,n);return[o]}var Le=()=>{};var W=!1;var Jn="http://www.w3.org/2000/svg";function Un(e,t=!1,n=void 0){return t?document.createElementNS(Jn,e):document.createElement(e,{is:n})}function Bt(e){let{useShadow:t}=e,n=document.createTextNode(""),r=()=>e.mount||document.body,o=Ce(),s,l=!!T.context;return N(()=>{l&&(Ce().user=l=!1),s||(s=ze(o,()=>D(()=>e.children)));let i=r();if(i instanceof HTMLHeadElement){let[c,d]=S(!1),u=()=>d(!0);Ee(a=>Ot(i,()=>c()?a():s(),null)),R(u)}else{let c=Un(e.isSVG?"g":"div",e.isSVG),d=t&&c.attachShadow?c.attachShadow({mode:"open"}):c;Object.defineProperty(c,"_$host",{get(){return n.parentNode},configurable:!0}),Ot(d,s),i.appendChild(c),e.ref&&e.ref(c),R(()=>i.removeChild(c))}},void 0,{render:!l}),n}var zn=180;function Ge(e){let[t,n]=S(e.open),[r,o]=S("closed"),s=Q(),l,i,c;N(()=>{l&&clearTimeout(l),i&&cancelAnimationFrame(i),e.open?(t()||n(!0),o("closed"),i=requestAnimationFrame(()=>o("open"))):(o("closed"),t()&&(l=window.setTimeout(()=>n(!1),zn)))}),X(()=>{if(!e.open)return;if(e.lockScroll!==!1){let a=document.body.style.overflowY;document.body.style.overflowY="hidden",R(()=>{document.body.style.overflowY=a})}i=requestAnimationFrame(()=>c?.focus());let u=a=>{a.key==="Escape"&&e.dismissible!==!1&&e.onClose?.()};window.addEventListener("keydown",u),R(()=>window.removeEventListener("keydown",u))}),R(()=>{l&&clearTimeout(l),i&&cancelAnimationFrame(i)});let d=()=>{e.dismissible!==!1&&e.onClose?.()};return<Se when={t()}>
223
- <Bt>
224
- <div class="ss_modal"data-state={r()}aria-hidden={r()==="closed"}>
225
- <div class="ss_modal__backdrop"onclick={d}/>
226
- <div class="ss_modal__panel"classList={{"ss_modal__panel--sm":e.size==="sm","ss_modal__panel--lg":e.size==="lg","ss_modal__panel--fullscreen":e.fullscreen,"ss_modal__panel--no-fullscreen":e.disableResponsiveFullscreen}}ref={u=>c=u}role="dialog"aria-modal="true"aria-labelledby={e.title?s:void 0}tabindex="-1">
227
- {(e.title||e.onClose)&&<div class="ss_modal__header">
228
- {e.title&&<h2 id={s}class="ss_modal__title">
229
- {e.title}
1196
+ <div class="ss_header__actions">{props.actions}</div>
1197
+ </div>;
1198
+ }
1199
+
1200
+ // src/components/SSModal.tsx
1201
+ import { Show as Show3, createEffect as createEffect4, createSignal as createSignal6, createUniqueId as createUniqueId2, onCleanup as onCleanup4, onMount as onMount3 } from "solid-js";
1202
+ import { Portal } from "solid-js/web";
1203
+ var CLOSE_ANIMATION_MS = 180;
1204
+ function SSModal(props) {
1205
+ const [isMounted, setIsMounted] = createSignal6(props.open);
1206
+ const [state, setState] = createSignal6("closed");
1207
+ const titleId = createUniqueId2();
1208
+ let closeTimeout;
1209
+ let rafId;
1210
+ let panelRef;
1211
+ createEffect4(() => {
1212
+ if (closeTimeout) clearTimeout(closeTimeout);
1213
+ if (rafId) cancelAnimationFrame(rafId);
1214
+ if (props.open) {
1215
+ if (!isMounted()) setIsMounted(true);
1216
+ setState("closed");
1217
+ rafId = requestAnimationFrame(() => setState("open"));
1218
+ } else {
1219
+ setState("closed");
1220
+ if (isMounted()) {
1221
+ closeTimeout = window.setTimeout(() => setIsMounted(false), CLOSE_ANIMATION_MS);
1222
+ }
1223
+ }
1224
+ });
1225
+ onMount3(() => {
1226
+ if (!props.open) return;
1227
+ if (props.lockScroll !== false) {
1228
+ const prev = document.body.style.overflowY;
1229
+ document.body.style.overflowY = "hidden";
1230
+ onCleanup4(() => {
1231
+ document.body.style.overflowY = prev;
1232
+ });
1233
+ }
1234
+ rafId = requestAnimationFrame(() => panelRef?.focus());
1235
+ const handleKeyDown = (event) => {
1236
+ if (event.key === "Escape" && props.dismissible !== false) {
1237
+ props.onClose?.();
1238
+ }
1239
+ };
1240
+ window.addEventListener("keydown", handleKeyDown);
1241
+ onCleanup4(() => window.removeEventListener("keydown", handleKeyDown));
1242
+ });
1243
+ onCleanup4(() => {
1244
+ if (closeTimeout) clearTimeout(closeTimeout);
1245
+ if (rafId) cancelAnimationFrame(rafId);
1246
+ });
1247
+ const handleBackdropClick = () => {
1248
+ if (props.dismissible === false) return;
1249
+ props.onClose?.();
1250
+ };
1251
+ return <Show3 when={isMounted()}>
1252
+ <Portal>
1253
+ <div class="ss_modal" data-state={state()} aria-hidden={state() === "closed"}>
1254
+ <div class="ss_modal__backdrop" onclick={handleBackdropClick} />
1255
+ <div
1256
+ class="ss_modal__panel"
1257
+ classList={{
1258
+ "ss_modal__panel--sm": props.size === "sm",
1259
+ "ss_modal__panel--lg": props.size === "lg",
1260
+ "ss_modal__panel--fullscreen": props.fullscreen,
1261
+ "ss_modal__panel--no-fullscreen": props.disableResponsiveFullscreen
1262
+ }}
1263
+ ref={(el) => panelRef = el}
1264
+ role="dialog"
1265
+ aria-modal="true"
1266
+ aria-labelledby={props.title ? titleId : void 0}
1267
+ tabindex="-1"
1268
+ >
1269
+ {(props.title || props.onClose) && <div class="ss_modal__header">
1270
+ {props.title && <h2 id={titleId} class="ss_modal__title">
1271
+ {props.title}
230
1272
  </h2>}
231
- <Se when={e.onClose}>
232
- <Y type="button"class="ss_modal__close"isIconOnly ariaLabel="Dialog schließen"onclick={()=>{e.dismissible!==!1&&e.onClose?.()}}>
233
- <svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-x"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M18 6l-12 12"/><path d="M6 6l12 12"/></svg>
234
- </Y>
235
- </Se>
1273
+ <Show3 when={props.onClose}>
1274
+ <SSButton
1275
+ type="button"
1276
+ class="ss_modal__close"
1277
+ isIconOnly
1278
+ ariaLabel="Dialog schließen"
1279
+ onclick={() => {
1280
+ if (props.dismissible === false) return;
1281
+ props.onClose?.();
1282
+ }}
1283
+ >
1284
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-x"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M18 6l-12 12" /><path d="M6 6l12 12" /></svg>
1285
+ </SSButton>
1286
+ </Show3>
236
1287
  </div>}
237
1288
 
238
1289
  <div class="ss_modal__body">
239
- <div class="ss_modal__body_inner">{e.children}</div>
1290
+ <div class="ss_modal__body_inner">{props.children}</div>
240
1291
  </div>
241
1292
 
242
- <Se when={e.footer}>
243
- <div class="ss_modal__footer">{e.footer}</div>
244
- </Se>
1293
+ <Show3 when={props.footer}>
1294
+ <div class="ss_modal__footer">{props.footer}</div>
1295
+ </Show3>
245
1296
  </div>
246
1297
  </div>
247
- </Bt>
248
- </Se>}var Kn;function Wn(){(!window.history.state||window.history.state._depth==null)&&window.history.replaceState({...window.history.state,_depth:window.history.length-1},""),Kn=window.history.state._depth}W||Wn();var Yn=/^\/+|(\/)\/+$/g;function Nt(e,t=!1){let n=e.replace(Yn,"$1");return n?t||/^[?#]/.test(n)?n:"/"+n:""}function Gn(e,t){if(e==null)throw new Error(t);return e}var Qn=Z(),Zn=Z(),Qe=()=>Gn(B(Qn),"<A> and 'use' router primitives can be only used inside a Route."),er=()=>B(Zn)||Qe().base,tr=e=>{let t=er();return D(()=>t.resolvePath(e()))},nr=e=>{let t=Qe();return D(()=>{let n=e();return n!==void 0?t.renderPath(n):n})},Ze=()=>Qe().navigatorFactory(),Re=()=>Qe().location;var rr;function sr(){return rr}var or=!1;function ir(){return or}var lr="Location",ar=5e3,cr=18e4,ct=new Map;W||setInterval(()=>{let e=Date.now();for(let[t,n]of ct.entries())!n[4].count&&e-n[0]>cr&&ct.delete(t)},3e5);function Be(){if(!W)return ct;let e=Le();if(!e)throw new Error("Cannot find cache context");return(e.router||(e.router={})).cache||(e.router.cache=new Map)}function et(e,t){e.GET&&(e=e.GET);let n=(...r)=>{let o=Be(),s=sr(),l=ir(),c=Ce()?Ze():void 0,d=Date.now(),u=t+jt(r),a=o.get(u),m;if(W){let y=Le();if(y){let k=(y.router||(y.router={})).dataOnly;if(k){let E=y&&(y.router.data||(y.router.data={}));if(E&&u in E)return E[u];if(Array.isArray(k)&&!ur(u,k))return E[u]=void 0,Promise.resolve()}}}if(_t()&&!W&&(m=!0,R(()=>a[4].count--)),a&&a[0]&&(W||s==="native"||a[4].count||Date.now()-a[0]<ar)){m&&(a[4].count++,a[4][0]()),a[3]==="preload"&&s!=="preload"&&(a[0]=d);let y=a[1];return s!=="preload"&&(y="then"in a[1]?a[1].then(x(!1),x(!0)):x(!1)(a[1]),!W&&s==="navigate"&&$e(()=>a[4][1](a[0]))),l&&"then"in y&&y.catch(()=>{}),y}let b;if(!W&&T.has&&T.has(u)?(b=T.load(u),delete globalThis._$HY.r[u]):b=e(...r),a?(a[0]=d,a[1]=b,a[3]=s,!W&&s==="navigate"&&$e(()=>a[4][1](a[0]))):(o.set(u,a=[d,b,,s,S(d)]),a[4].count=0),m&&(a[4].count++,a[4][0]()),W){let y=Le();if(y&&y.router.dataOnly)return y.router.data[u]=b}if(s!=="preload"&&(b="then"in b?b.then(x(!1),x(!0)):x(!1)(b)),l&&"then"in b&&b.catch(()=>{}),W&&T.context&&T.context.async&&!T.context.noHydrate){let y=Le();(!y||!y.serverOnly)&&T.context.serialize(u,b)}return b;function x(y){return async k=>{if(k instanceof Response){let E=Le();if(E)for(let[g,p]of k.headers)g=="set-cookie"?E.response.headers.append("set-cookie",p):E.response.headers.set(g,p);let L=k.headers.get(lr);if(L!==null){c&&L.startsWith("/")?$e(()=>{c(L,{replace:!0})}):W?E&&(E.response.status=302):window.location.href=L;return}k.customBody&&(k=await k.customBody())}if(y)throw k;return a[2]=k,k}}};return n.keyFor=(...r)=>t+jt(r),n.key=t,n}et.get=e=>Be().get(e)[2];et.set=(e,t)=>{let n=Be(),r=Date.now(),o=n.get(e);o?(o[0]=r,o[1]=Promise.resolve(t),o[2]=t,o[3]="preload"):(n.set(e,o=[r,Promise.resolve(t),t,"preload",S(r)]),o[4].count=0)};et.delete=e=>Be().delete(e);et.clear=()=>Be().clear();function ur(e,t){for(let n of t)if(n&&e.startsWith(n))return!0;return!1}function jt(e){return JSON.stringify(e,(t,n)=>dr(n)?Object.keys(n).sort().reduce((r,o)=>(r[o]=n[o],r),{}):n)}function dr(e){let t;return e!=null&&typeof e=="object"&&(!(t=Object.getPrototypeOf(e))||t===Object.prototype)}var fr=It("<a>");function Vt(e){e=He({inactiveClass:"inactive",activeClass:"active"},e);let[,t]=it(e,["href","state","class","activeClass","inactiveClass","end"]),n=tr(()=>e.href),r=nr(n),o=Re(),s=D(()=>{let l=n();if(l===void 0)return[!1,!1];let i=Nt(l.split(/[?#]/,1)[0]).toLowerCase(),c=decodeURI(Nt(o.pathname).toLowerCase());return[e.end?i===c:c.startsWith(i+"/")||c===i,i===c]});return(()=>{var l=fr();return Ht(l,He(t,{get href(){return r()||e.href},get state(){return JSON.stringify(e.state)},get classList(){return{...e.class&&{[e.class]:!0},[e.inactiveClass]:!s()[0],[e.activeClass]:s()[0],...t.classList}},link:"",get"aria-current"(){return s()[1]?"page":void 0}}),!1,!1),l})()}var Xt=Z(),hr=0,mr=()=>`ss-modal-${hr++}`;function gr(){let e=B(Xt);if(!e)throw new Error("useSSModals must be used within SSModalsProvider");return e}function Sr(e){let t=Ze(),n=Re(),[r,o]=Ye(),s=()=>e.config.modalProps?.({hide:e.hide})??{},{primaryButtonText:l,secondaryButtonText:i,hideSecondaryButton:c,danger:d,...u}=s();return<Ge open={e.visible()}onClose={e.hide}{...u}footer={<>
249
- {!c&&<Y class="secondary"onclick={e.hide}>
250
- {i??"Abbrechen"}
251
- </Y>}
252
- <Y class={d?"danger":void 0}onclick={()=>o(()=>e.config.onPrimaryAction?.({hide:e.hide,navigate:t,pathname:n.pathname})??e.hide())}disabled={r()}>
253
- {l??"Weiter"}
254
- </Y>
255
- </>}>
256
- {e.config.content({hide:e.hide})}
257
- </Ge>}function _r(e){let t=Ze(),n=Re();return<J onsubmit={r=>e.config.onSubmit({hide:e.hide,context:r,navigate:t,pathname:n.pathname})}>
258
- <Er visible={e.visible}hide={e.hide}config={e.config}/>
259
- </J>}function Er(e){let t=J.useContext();if(!t)return null;let n=()=>e.config.modalProps?.({hide:e.hide,context:t})??{},{primaryButtonText:r,secondaryButtonText:o,hideSecondaryButton:s,danger:l,...i}=n();return<Ge open={e.visible()}onClose={e.hide}{...i}footer={<>
260
- {!s&&<Y class="secondary"onclick={e.hide}disabled={t.loading()}>
261
- {o??"Abbrechen"}
262
- </Y>}
263
- <Y class={l?"danger":void 0}onclick={()=>t.submit()}disabled={t.loading()}>
264
- {r??"Speichern"}
265
- </Y>
266
- </>}>
267
- {e.config.content({hide:e.hide,context:t})}
268
- </Ge>}function Pr(e){let[t,n]=S([]),r=new Map,o=new Map,s=220,l=u=>{let a=r.get(u);if(!a)return;a.setVisible(!1);let m=o.get(u);m&&window.clearTimeout(m);let b=window.setTimeout(()=>{n(x=>x.filter(y=>y.id!==u)),r.delete(u),o.delete(u)},s);o.set(u,b)},i=u=>{let a=mr(),[m,b]=S(!0),x={id:a,visible:m,setVisible:b,render:u};return r.set(a,x),n(y=>[...y,x]),a},c=u=>i(({hide:a,visible:m})=><Sr visible={m}hide={a}config={u}/>),d=u=>i(({hide:a,visible:m})=><_r visible={m}hide={a}config={u}/>);return R(()=>{o.forEach(u=>window.clearTimeout(u)),o.clear()}),<Xt.Provider value={{show:i,showDefault:c,showForm:d,hide:l}}>
269
- {e.children}
270
-
271
- <K each={t()}>
272
- {u=>{let a=()=>l(u.id);return u.render({id:u.id,hide:a,visible:u.visible})}}
273
- </K>
274
- </Xt.Provider>}var ut=Z();function Ne(e){let t=Q(),n=Re(),[r,o]=S([]),s=()=>{let d=document.getElementById(t);d&&(d.checked=!1)},l=d=>{o(u=>u.includes(d)?u:[...u,d])},i=d=>{o(u=>u.filter(a=>a!==d))},c=D(()=>{let d=n.pathname,u=null;for(let a of r())d.startsWith(a)&&(!u||a.length>u.length)&&(u=a);return u});return<ut.Provider value={{closeDrawer:s,activeHref:c,registerHref:l,unregisterHref:i}}>
275
- <div class={`ss_shell ${e.class??""}`}style={e.style}>
276
- <input id={t}type="checkbox"class="ss_shell__drawer_toggle_input"/>
1298
+ </Portal>
1299
+ </Show3>;
1300
+ }
1301
+
1302
+ // src/components/SSModals.tsx
1303
+ import { createContext as createContext2, createSignal as createSignal7, For as For4, onCleanup as onCleanup5, useContext as useContext2 } from "solid-js";
1304
+ import { useLocation, useNavigate } from "@solidjs/router";
1305
+ var SSModalsContext = createContext2();
1306
+ var modalCounter = 0;
1307
+ var nextModalId = () => `ss-modal-${modalCounter++}`;
1308
+ function useSSModals() {
1309
+ const context = useContext2(SSModalsContext);
1310
+ if (!context) {
1311
+ throw new Error("useSSModals must be used within SSModalsProvider");
1312
+ }
1313
+ return context;
1314
+ }
1315
+ function DefaultModal(props) {
1316
+ const navigate = useNavigate();
1317
+ const location = useLocation();
1318
+ const [loading, process] = createLoading();
1319
+ const modalProps = () => props.config.modalProps?.({ hide: props.hide }) ?? {};
1320
+ const {
1321
+ primaryButtonText,
1322
+ secondaryButtonText,
1323
+ hideSecondaryButton,
1324
+ danger,
1325
+ ...rest
1326
+ } = modalProps();
1327
+ return <SSModal
1328
+ open={props.visible()}
1329
+ onClose={props.hide}
1330
+ {...rest}
1331
+ footer={<>
1332
+ {!hideSecondaryButton && <SSButton class="secondary" onclick={props.hide}>
1333
+ {secondaryButtonText ?? "Abbrechen"}
1334
+ </SSButton>}
1335
+ <SSButton
1336
+ class={danger ? "danger" : void 0}
1337
+ onclick={() => process(
1338
+ () => props.config.onPrimaryAction?.({
1339
+ hide: props.hide,
1340
+ navigate,
1341
+ pathname: location.pathname
1342
+ }) ?? props.hide()
1343
+ )}
1344
+ disabled={loading()}
1345
+ >
1346
+ {primaryButtonText ?? "Weiter"}
1347
+ </SSButton>
1348
+ </>}
1349
+ >
1350
+ {props.config.content({ hide: props.hide })}
1351
+ </SSModal>;
1352
+ }
1353
+ function FormModal(props) {
1354
+ const navigate = useNavigate();
1355
+ const location = useLocation();
1356
+ return <SSForm
1357
+ onsubmit={(context) => props.config.onSubmit({
1358
+ hide: props.hide,
1359
+ context,
1360
+ navigate,
1361
+ pathname: location.pathname
1362
+ })}
1363
+ >
1364
+ <FormModalInner visible={props.visible} hide={props.hide} config={props.config} />
1365
+ </SSForm>;
1366
+ }
1367
+ function FormModalInner(props) {
1368
+ const context = SSForm.useContext();
1369
+ if (!context) return null;
1370
+ const modalProps = () => props.config.modalProps?.({ hide: props.hide, context }) ?? {};
1371
+ const {
1372
+ primaryButtonText,
1373
+ secondaryButtonText,
1374
+ hideSecondaryButton,
1375
+ danger,
1376
+ ...rest
1377
+ } = modalProps();
1378
+ return <SSModal
1379
+ open={props.visible()}
1380
+ onClose={props.hide}
1381
+ {...rest}
1382
+ footer={<>
1383
+ {!hideSecondaryButton && <SSButton class="secondary" onclick={props.hide} disabled={context.loading()}>
1384
+ {secondaryButtonText ?? "Abbrechen"}
1385
+ </SSButton>}
1386
+ <SSButton
1387
+ class={danger ? "danger" : void 0}
1388
+ onclick={() => context.submit()}
1389
+ disabled={context.loading()}
1390
+ >
1391
+ {primaryButtonText ?? "Speichern"}
1392
+ </SSButton>
1393
+ </>}
1394
+ >
1395
+ {props.config.content({ hide: props.hide, context })}
1396
+ </SSModal>;
1397
+ }
1398
+ function SSModalsProvider(props) {
1399
+ const [modals, setModals] = createSignal7([]);
1400
+ const modalsById = /* @__PURE__ */ new Map();
1401
+ const closeTimeouts = /* @__PURE__ */ new Map();
1402
+ const removeDelayMs = 220;
1403
+ const hide = (id) => {
1404
+ const modal = modalsById.get(id);
1405
+ if (!modal) return;
1406
+ modal.setVisible(false);
1407
+ const existing = closeTimeouts.get(id);
1408
+ if (existing) window.clearTimeout(existing);
1409
+ const timeout = window.setTimeout(() => {
1410
+ setModals((list) => list.filter((modal2) => modal2.id !== id));
1411
+ modalsById.delete(id);
1412
+ closeTimeouts.delete(id);
1413
+ }, removeDelayMs);
1414
+ closeTimeouts.set(id, timeout);
1415
+ };
1416
+ const show = (render) => {
1417
+ const id = nextModalId();
1418
+ const [visible, setVisible] = createSignal7(true);
1419
+ const entry = { id, visible, setVisible, render };
1420
+ modalsById.set(id, entry);
1421
+ setModals((list) => [...list, entry]);
1422
+ return id;
1423
+ };
1424
+ const showDefault = (config) => {
1425
+ return show(({ hide: hide2, visible }) => <DefaultModal visible={visible} hide={hide2} config={config} />);
1426
+ };
1427
+ const showForm = (config) => {
1428
+ return show(({ hide: hide2, visible }) => <FormModal visible={visible} hide={hide2} config={config} />);
1429
+ };
1430
+ onCleanup5(() => {
1431
+ closeTimeouts.forEach((timeout) => window.clearTimeout(timeout));
1432
+ closeTimeouts.clear();
1433
+ });
1434
+ return <SSModalsContext.Provider value={{ show, showDefault, showForm, hide }}>
1435
+ {props.children}
1436
+
1437
+ <For4 each={modals()}>
1438
+ {(modal) => {
1439
+ const hideModal = () => hide(modal.id);
1440
+ return modal.render({ id: modal.id, hide: hideModal, visible: modal.visible });
1441
+ }}
1442
+ </For4>
1443
+ </SSModalsContext.Provider>;
1444
+ }
1445
+
1446
+ // src/components/SSShell.tsx
1447
+ import { createContext as createContext3, createMemo as createMemo4, createSignal as createSignal8, createUniqueId as createUniqueId3, onCleanup as onCleanup6, onMount as onMount4, useContext as useContext3 } from "solid-js";
1448
+ import { useLocation as useLocation2 } from "@solidjs/router";
1449
+ var SSShellContext = createContext3();
1450
+ function SSShell(props) {
1451
+ const drawerId = createUniqueId3();
1452
+ const location = useLocation2();
1453
+ const [hrefs, setHrefs] = createSignal8([]);
1454
+ const closeDrawer = () => {
1455
+ const input = document.getElementById(drawerId);
1456
+ if (input) input.checked = false;
1457
+ };
1458
+ const registerHref = (href) => {
1459
+ setHrefs((prev) => prev.includes(href) ? prev : [...prev, href]);
1460
+ };
1461
+ const unregisterHref = (href) => {
1462
+ setHrefs((prev) => prev.filter((item) => item !== href));
1463
+ };
1464
+ const activeHref = createMemo4(() => {
1465
+ const path = location.pathname;
1466
+ let best = null;
1467
+ for (const href of hrefs()) {
1468
+ if (!path.startsWith(href)) continue;
1469
+ if (!best || href.length > best.length) {
1470
+ best = href;
1471
+ }
1472
+ }
1473
+ return best;
1474
+ });
1475
+ return <SSShellContext.Provider value={{ closeDrawer, activeHref, registerHref, unregisterHref }}>
1476
+ <div class={`ss_shell ${props.class ?? ""}`} style={props.style}>
1477
+ <input id={drawerId} type="checkbox" class="ss_shell__drawer_toggle_input" />
277
1478
 
278
1479
  <header class="ss_shell__header">
279
1480
  <div class="ss_shell__header_left">
280
- <label for={t}class="ss_shell__drawer_toggle ss_button ss_button--icon"aria-label="Navigation öffnen"role="button"tabindex="0">
281
- <svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="icon icon-tabler icons-tabler-outline icon-tabler-menu-2"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M4 6l16 0"/><path d="M4 12l16 0"/><path d="M4 18l16 0"/></svg>
1481
+ <label
1482
+ for={drawerId}
1483
+ class="ss_shell__drawer_toggle ss_button ss_button--icon"
1484
+ aria-label="Navigation öffnen"
1485
+ role="button"
1486
+ tabindex="0"
1487
+ >
1488
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-menu-2"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M4 6l16 0" /><path d="M4 12l16 0" /><path d="M4 18l16 0" /></svg>
282
1489
  </label>
283
- <div class="ss_shell__title">{e.title}</div>
1490
+ <div class="ss_shell__title">{props.title}</div>
284
1491
  </div>
285
- <div class="ss_shell__actions">{e.actions}</div>
1492
+ <div class="ss_shell__actions">{props.actions}</div>
286
1493
  </header>
287
1494
 
288
1495
  <div class="ss_shell__body">
289
- <nav class="ss_shell__nav"aria-label="Hauptnavigation">
290
- <div class="ss_shell__nav_inner">{e.nav}</div>
1496
+ <nav class="ss_shell__nav" aria-label="Hauptnavigation">
1497
+ <div class="ss_shell__nav_inner">{props.nav}</div>
291
1498
  </nav>
292
- <div class="ss_shell__main">{e.children}</div>
293
- <label for={t}class="ss_shell__scrim"aria-label="Navigation schließen"/>
1499
+ <div class="ss_shell__main">{props.children}</div>
1500
+ <label for={drawerId} class="ss_shell__scrim" aria-label="Navigation schließen" />
294
1501
  </div>
295
1502
  </div>
296
- </ut.Provider>}Ne.Nav=function(e){return<div class="ss_shell__nav_list">{e.children}</div>};Ne.NavLink=function(e){let t=B(ut);X(()=>t?.registerHref(e.href)),R(()=>t?.unregisterHref(e.href));let n=()=>t?.activeHref()===e.href;return<a class="ss_shell__nav_item"classList={{"ss_shell__nav_item--active":n()}}href={e.href}onclick={()=>{e.onclick?.(),t?.closeDrawer()}}>
297
- {e.icon&&<span class="ss_shell__nav_icon">{e.icon}</span>}
298
- <span class="ss_shell__nav_label">{e.children}</span>
299
- </a>};Ne.NavAction=function(e){let t=B(ut);return<button type="button"class="ss_shell__nav_item"onclick={()=>{e.onclick(),t?.closeDrawer()}}>
300
- {e.icon&&<span class="ss_shell__nav_icon">{e.icon}</span>}
301
- <span class="ss_shell__nav_label">{e.children}</span>
302
- </button>};Ne.NavGroup=function(e){return<details class="ss_shell__nav_group"open={e.initiallyExpanded}>
1503
+ </SSShellContext.Provider>;
1504
+ }
1505
+ SSShell.Nav = function(props) {
1506
+ return <div class="ss_shell__nav_list">{props.children}</div>;
1507
+ };
1508
+ SSShell.NavLink = function(props) {
1509
+ const context = useContext3(SSShellContext);
1510
+ onMount4(() => context?.registerHref(props.href));
1511
+ onCleanup6(() => context?.unregisterHref(props.href));
1512
+ const isActive = () => context?.activeHref() === props.href;
1513
+ return <a
1514
+ class="ss_shell__nav_item"
1515
+ classList={{ "ss_shell__nav_item--active": isActive() }}
1516
+ href={props.href}
1517
+ onclick={() => {
1518
+ props.onclick?.();
1519
+ context?.closeDrawer();
1520
+ }}
1521
+ >
1522
+ {props.icon && <span class="ss_shell__nav_icon">{props.icon}</span>}
1523
+ <span class="ss_shell__nav_label">{props.children}</span>
1524
+ </a>;
1525
+ };
1526
+ SSShell.NavAction = function(props) {
1527
+ const context = useContext3(SSShellContext);
1528
+ return <button
1529
+ type="button"
1530
+ class="ss_shell__nav_item"
1531
+ onclick={() => {
1532
+ props.onclick();
1533
+ context?.closeDrawer();
1534
+ }}
1535
+ >
1536
+ {props.icon && <span class="ss_shell__nav_icon">{props.icon}</span>}
1537
+ <span class="ss_shell__nav_label">{props.children}</span>
1538
+ </button>;
1539
+ };
1540
+ SSShell.NavGroup = function(props) {
1541
+ return <details class="ss_shell__nav_group" open={props.initiallyExpanded}>
303
1542
  <summary class="ss_shell__nav_group_header">
304
- {e.icon&&<span class="ss_shell__nav_icon">{e.icon}</span>}
305
- <span class="ss_shell__nav_label">{e.title}</span>
306
- <span class="ss_shell__nav_group_chevron"aria-hidden="true">
307
- <svg xmlns="http://www.w3.org/2000/svg"width="24"height="24"viewBox="0 0 24 24"fill="none"stroke="currentColor"stroke-width="2"stroke-linecap="round"stroke-linejoin="round"class="ss_shell__nav_group_chevron_svg"><path stroke="none"d="M0 0h24v24H0z"fill="none"/><path d="M9 6l6 6l-6 6"/></svg>
1543
+ {props.icon && <span class="ss_shell__nav_icon">{props.icon}</span>}
1544
+ <span class="ss_shell__nav_label">{props.title}</span>
1545
+ <span class="ss_shell__nav_group_chevron" aria-hidden="true">
1546
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="ss_shell__nav_group_chevron_svg"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M9 6l6 6l-6 6" /></svg>
308
1547
  </span>
309
1548
  </summary>
310
- <div class="ss_shell__nav_group_items">{e.children}</div>
311
- </details>};function Cr(e){return<div class={`ss_surface ${e.class??""}`}style={e.style}>
312
- {e.children}
313
- </div>}function Jt(e){return<div class={`ss_tile ${e.class??""}`}style={e.style}>
1549
+ <div class="ss_shell__nav_group_items">{props.children}</div>
1550
+ </details>;
1551
+ };
1552
+
1553
+ // src/components/SSSurface.tsx
1554
+ function SSSurface(props) {
1555
+ return <div class={`ss_surface ${props.class ?? ""}`} style={props.style}>
1556
+ {props.children}
1557
+ </div>;
1558
+ }
1559
+
1560
+ // src/components/SSTile.tsx
1561
+ import { A } from "@solidjs/router";
1562
+ function SSTile(props) {
1563
+ return <div class={`ss_tile ${props.class ?? ""}`} style={props.style}>
314
1564
  <div class="ss_tile__row">
315
- {e.icon&&<span class="ss_tile__icon">{e.icon}</span>}
1565
+ {props.icon && <span class="ss_tile__icon">{props.icon}</span>}
316
1566
  <div class="ss_tile__content">
317
- {e.href?<h5 class="ss_tile__title">
318
- <Vt class="ss_tile__link"href={e.href}onclick={e.onLinkClick}>
319
- {e.title}
320
- </Vt>
321
- </h5>:<h5 class="ss_tile__title">
322
- <span class="ss_tile__text">{e.title}</span>
1567
+ {props.href ? <h5 class="ss_tile__title">
1568
+ <A class="ss_tile__link" href={props.href} onclick={props.onLinkClick}>
1569
+ {props.title}
1570
+ </A>
1571
+ </h5> : <h5 class="ss_tile__title">
1572
+ <span class="ss_tile__text">{props.title}</span>
323
1573
  </h5>}
324
- {e.subtitle&&<div class="ss_tile__subtitle">{e.subtitle}</div>}
1574
+ {props.subtitle && <div class="ss_tile__subtitle">{props.subtitle}</div>}
325
1575
  </div>
326
- {e.trailing&&<div class="ss_tile__trailing">{e.trailing}</div>}
1576
+ {props.trailing && <div class="ss_tile__trailing">{props.trailing}</div>}
327
1577
  </div>
328
- </div>}function Tr(e){return function(t){let n=e(t.data);return<Jt{...n}onLinkClick={t.onLinkClick??n.onLinkClick}href={t.noLink?void 0:n.href}icon={t.noIcon?void 0:n.icon}/>}}export{Y as SSButton,Ut as SSCallout,zt as SSChip,_n as SSDataTable,xn as SSDropdown,kn as SSExpandable,J as SSForm,En as SSHeader,Ge as SSModal,Pr as SSModalsProvider,Ne as SSShell,Cr as SSSurface,Jt as SSTile,Tr as createSSTile,gr as useSSModals};
1578
+ </div>;
1579
+ }
1580
+ function createSSTile(build) {
1581
+ return function(props) {
1582
+ const built = build(props.data);
1583
+ return <SSTile
1584
+ {...built}
1585
+ onLinkClick={props.onLinkClick ?? built.onLinkClick}
1586
+ href={props.noLink ? void 0 : built.href}
1587
+ icon={props.noIcon ? void 0 : built.icon}
1588
+ />;
1589
+ };
1590
+ }
1591
+ export {
1592
+ SSButton,
1593
+ SSCallout,
1594
+ SSChip,
1595
+ SSDataTable,
1596
+ SSDropdown,
1597
+ SSExpandable,
1598
+ SSForm,
1599
+ SSHeader,
1600
+ SSModal,
1601
+ SSModalsProvider,
1602
+ SSShell,
1603
+ SSSurface,
1604
+ SSTile,
1605
+ createSSTile,
1606
+ useSSModals
1607
+ };