@vuu-ui/vuu-shell 0.6.24 → 0.6.25-debug

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/esm/index.js CHANGED
@@ -1,2 +1,661 @@
1
- import D,{Suspense as he}from"react";import{registerComponent as ge}from"@vuu-ui/vuu-layout";import ue from"react";import{Fragment as ce,jsx as U,jsxs as pe}from"react/jsx-runtime";var x=class extends ue.Component{constructor(e){super(e),this.state={errorMessage:null}}static getDerivedStateFromError(e){return{errorMessage:e.message}}componentDidCatch(e,o){console.log(e,o)}render(){return this.state.errorMessage?pe(ce,{children:[U("h1",{children:"Something went wrong."}),U("p",{children:this.state.errorMessage})]}):this.props.children}};import{jsx as de}from"react/jsx-runtime";var E=()=>de("div",{className:"hwLoader",children:"loading"});var k=async t=>{let e=new CSSStyleSheet;return fetch(t).then(o=>o.text()).then(o=>e.replace(o))};import{jsx as C}from"react/jsx-runtime";function fe({url:t,css:e,params:o,...r}){e&&k(e).then(n=>{document.adoptedStyleSheets=[...document.adoptedStyleSheets,n]});let s=D.lazy(()=>import(t));return C(x,{children:C(he,{fallback:C(E,{}),children:C(s,{...r,...o})})})}var I=D.memo(fe);I.displayName="Feature";ge("Feature",I,"view");import{useState as R}from"react";import{Button as ye}from"@salt-ds/core";import{FormField as B,Input as F}from"@heswell/salt-lab";import{jsx as v,jsxs as ve}from"react/jsx-runtime";var A="vuuLoginPanel",Nt=({onSubmit:t})=>{let[e,o]=R(""),[r,s]=R(""),n=()=>{t(e,r)},a=(l,u)=>{o(u)},m=(l,u)=>{s(u)},i=e.trim()!==""&&r.trim()!=="";return ve("div",{className:A,children:[v(B,{label:"Username",style:{width:200},children:v(F,{value:e,id:"text-username",onChange:a})}),v(B,{label:"Password",style:{width:200},children:v(F,{type:"password",value:r,id:"text-password",onChange:m})}),v(ye,{className:`${A}-login`,disabled:!i,onClick:n,variant:"cta",children:"Login"})]})};import{getCookieValue as V}from"@vuu-ui/vuu-utils";var Dt=()=>{let t=V("vuu-username"),e=V("vuu-auth-token");return[t,e]},xe=(t="/login.html")=>{window.location.href=t},O=t=>{document.cookie="vuu-username= ; expires = Thu, 01 Jan 1970 00:00:00 GMT",document.cookie="vuu-auth-token= ; expires = Thu, 01 Jan 1970 00:00:00 GMT",xe(t)};import{connectToServer as Ye}from"@vuu-ui/vuu-data";import{useCallback as H,useEffect as Ze,useRef as M,useState as ee}from"react";import{useCallback as P,useEffect as Ce,useState as Le}from"react";var Pe=(t,e)=>{let[o,r]=Le(e),s=i=>{r(i)},n=P(async(i="latest")=>{fetch(`api/vui/${t.username}/${i}`,{}).then(l=>l.ok?l.json():e).then(s).catch(()=>{s(e)})},[e,t.username]);Ce(()=>{n()},[n]);let a=P(i=>{fetch(`api/vui/${t.username}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)}).then(l=>l.ok?l.json():e)},[e,t]),m=P(i=>{n(i)},[n]);return[o,a,m]},$=Pe;import{createContext as Se,useContext as Te}from"react";import{jsx as S}from"react/jsx-runtime";var we={},T=Se(we),He=({children:t,context:e,inheritedContext:o})=>{let r={...o,...e};return S(T.Provider,{value:r,children:t})},G=({children:t,value:e})=>S(T.Consumer,{children:o=>S(He,{context:e,inheritedContext:o,children:t})}),Jt=()=>Te(T);import je from"classnames";import{Chest as et,DraggableLayout as te,Drawer as tt,Flexbox as ot,LayoutProvider as rt,View as nt}from"@vuu-ui/vuu-layout";import{useCallback as Ke}from"react";import{Button as Fe}from"@salt-ds/core";import{DropdownBase as Ae}from"@heswell/salt-lab";import{UserSolidIcon as Ve}from"@salt-ds/icons";import{formatDate as Me}from"@vuu-ui/vuu-utils";import{List as be,ListItem as Ne}from"@heswell/salt-lab";import{Button as Ue}from"@salt-ds/core";import{ExportIcon as Ee}from"@salt-ds/icons";import{forwardRef as ke,useCallback as _,useEffect as De,useState as Ie}from"react";var J=async t=>await fetch(`api/vui/${t.username}`,{}).then(o=>o.ok?o.json():null).catch(()=>{console.log("error getting history")});import{jsx as L,jsxs as z}from"react/jsx-runtime";var Re=({lastUpdate:t},{lastUpdate:e})=>e===t?0:e<t?-1:1,Be=t=>L(Ne,{...t}),q=ke(function({loginUrl:e,onNavigate:o,user:r,layoutId:s="latest"},n){let[a,m]=Ie([]);De(()=>{async function p(){let g=(await J(r)).filter(f=>f.id!=="latest").sort(Re).map(({id:f,lastUpdate:y})=>({lastUpdate:y,id:f,label:`Saved at ${Me(new Date(y),"kk:mm:ss")}`}));console.log({sortedHistory:g}),m(g)}p()},[r]);let i=_((p,d)=>{d&&o(d.id)},[o]),l=_(()=>{O(e)},[e]),u=a.length===0?null:s==="latest"?a[0]:a.find(p=>p.id===s);return z("div",{className:"vuuUserPanel",ref:n,children:[L(be,{ListItem:Be,className:"vuuUserPanel-history",onSelect:i,selected:u,source:a}),L("div",{className:"vuuUserPanel-buttonBar",children:z(Ue,{"aria-label":"logout",onClick:l,children:[L(Ee,{})," Logout"]})})]})});import{jsx as w,jsxs as Oe}from"react/jsx-runtime";var K=({layoutId:t,loginUrl:e,onNavigate:o,user:r})=>Oe(Ae,{className:"vuuUserProfile",placement:"bottom-end",children:[w(Fe,{variant:"secondary",children:w(Ve,{})}),w(q,{layoutId:t,loginUrl:e,onNavigate:n=>{o(n)},user:r})]});import{ToggleButton as Q,ToggleButtonGroup as $e}from"@heswell/salt-lab";import Ge from"classnames";import{useControlled as Je}from"@salt-ds/core";import{useCallback as _e}from"react";import{jsx as X,jsxs as qe}from"react/jsx-runtime";var ze="vuuThemeSwitch",W=["light","dark"],Y=({className:t,defaultMode:e,mode:o,onChange:r,...s})=>{let[n,a]=Je({controlled:o,default:e!=null?e:"light",name:"ThemeSwitch",state:"mode"}),m=W.indexOf(n),i=_e((u,p)=>{let d=W[p];a(d),r(d)},[r,a]),l=Ge(ze,t);return qe($e,{className:l,...s,onChange:i,selectedIndex:m,children:[X(Q,{"aria-label":"alert",tooltipText:"Light Theme","data-icon":"light"}),X(Q,{"aria-label":"home",tooltipText:"Dark Theme","data-icon":"dark"})]})};import Qe from"classnames";import{jsx as Z,jsxs as Xe}from"react/jsx-runtime";var We="vuuAppHeader",j=({className:t,layoutId:e,loginUrl:o,onNavigate:r,onSwitchTheme:s,themeMode:n="light",user:a,...m})=>{let i=Qe(We,t,"salt-density-medium"),l=Ke(u=>s==null?void 0:s(u),[s]);return Xe("header",{className:i,...m,children:[Z(Y,{defaultMode:n,onChange:l}),Z(K,{layoutId:e,loginUrl:o,onNavigate:r,user:a})]})};import{jsx as h,jsxs as oe}from"react/jsx-runtime";var st={type:"View",props:{style:{height:"calc(100% - 6px)"}},children:[{props:{className:"vuuShell-warningPlaceholder"},type:"Placeholder"}]},ir=({children:t,className:e,defaultLayout:o=st,leftSidePanel:r,loginUrl:s,serverUrl:n,user:a,...m})=>{let i=M(null),[l]=ee("high"),u=M(null),[p,d]=ee(!1),g=M("latest"),[f,y,b]=$(a,o),re=H(c=>{y(c)},[y]),ne=H(c=>{i.current&&(i.current.dataset.mode=c)},[]),se=c=>{var N;let me=c.target;(N=u.current)!=null&&N.contains(me)||d(!p)},ae=H(c=>{g.current=c,b(c)},[b]);Ze(()=>{n&&a.token&&Ye(n,a.token)},[n,a.token]);let ie=()=>{let c=[];return r&&c.push(h(tt,{onClick:se,open:p,position:"left",inline:!0,peekaboo:!0,sizeOpen:200,toggleButton:"end",children:h(nt,{className:"vuuShell-palette",id:"vw-app-palette",ref:u,style:{height:"100%"},children:r},"app-palette")},"left-panel")),c},le=je("vuuShell",e,"salt-theme",`salt-density-${l}`);return oe(G,{value:void 0,children:[h(rt,{layout:f,onLayoutChange:re,children:h(te,{className:le,"data-mode":"light",ref:i,...m,children:oe(ot,{className:"App",style:{flexDirection:"column",height:"100%",width:"100%"},children:[h(j,{layoutId:g.current,loginUrl:s,user:a,onNavigate:ae,onSwitchTheme:ne}),h(et,{style:{flex:1},children:ie().concat(h(te,{dropTarget:!0,style:{width:"100%",height:"100%"}},"main-content"))})]})})}),t]})};export{I as Feature,Nt as LoginPanel,ir as Shell,G as ShellContextProvider,Y as ThemeSwitch,Dt as getAuthDetailsFromCookies,O as logout,xe as redirectToLogin,Jt as useShellContext};
1
+ // src/connection-status/ConnectionStatusIcon.tsx
2
+ import React, { useEffect, useState } from "react";
3
+ import cx from "classnames";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ var ConnectionStatusIcon = ({ connectionStatus, className, element = "span", ...props }) => {
6
+ const [classBase5, setClassBase] = useState("vuuConnectingStatus");
7
+ useEffect(() => {
8
+ switch (connectionStatus) {
9
+ case "connected":
10
+ case "reconnected":
11
+ setClassBase("vuuActiveStatus");
12
+ break;
13
+ case "connecting":
14
+ setClassBase("vuuConnectingStatus");
15
+ break;
16
+ case "disconnected":
17
+ setClassBase("vuuDisconnectedStatus");
18
+ break;
19
+ default:
20
+ break;
21
+ }
22
+ }, [connectionStatus]);
23
+ const statusIcon = React.createElement(
24
+ element,
25
+ {
26
+ ...props,
27
+ className: cx("vuuStatus vuuIcon", classBase5, className)
28
+ }
29
+ );
30
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("div", { className: "vuuStatus-container salt-theme", children: [
31
+ statusIcon,
32
+ /* @__PURE__ */ jsxs("div", { className: "vuuStatus-text", children: [
33
+ "Status: ",
34
+ connectionStatus.toUpperCase()
35
+ ] })
36
+ ] }) });
37
+ };
38
+
39
+ // src/feature/Feature.tsx
40
+ import React3, { Suspense } from "react";
41
+ import { registerComponent } from "@vuu-ui/vuu-layout";
42
+
43
+ // src/feature/ErrorBoundary.jsx
44
+ import React2 from "react";
45
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
46
+ var ErrorBoundary = class extends React2.Component {
47
+ constructor(props) {
48
+ super(props);
49
+ this.state = { errorMessage: null };
50
+ }
51
+ static getDerivedStateFromError(error) {
52
+ return { errorMessage: error.message };
53
+ }
54
+ componentDidCatch(error, errorInfo) {
55
+ console.log(error, errorInfo);
56
+ }
57
+ render() {
58
+ if (this.state.errorMessage) {
59
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
60
+ /* @__PURE__ */ jsx2("h1", { children: "Something went wrong." }),
61
+ /* @__PURE__ */ jsx2("p", { children: this.state.errorMessage })
62
+ ] });
63
+ }
64
+ return this.props.children;
65
+ }
66
+ };
67
+
68
+ // src/feature/Loader.tsx
69
+ import { jsx as jsx3 } from "react/jsx-runtime";
70
+ var Loader = () => /* @__PURE__ */ jsx3("div", { className: "hwLoader", children: "loading" });
71
+
72
+ // src/feature/css-module-loader.ts
73
+ var importCSS = async (path) => {
74
+ const container = new CSSStyleSheet();
75
+ return fetch(path).then((x) => x.text()).then((x) => container.replace(x));
76
+ };
77
+
78
+ // src/feature/Feature.tsx
79
+ import { jsx as jsx4 } from "react/jsx-runtime";
80
+ function RawFeature({
81
+ url,
82
+ css,
83
+ params,
84
+ ...props
85
+ }) {
86
+ if (css) {
87
+ importCSS(css).then((styleSheet) => {
88
+ document.adoptedStyleSheets = [
89
+ ...document.adoptedStyleSheets,
90
+ styleSheet
91
+ ];
92
+ });
93
+ }
94
+ const LazyFeature = React3.lazy(() => import(
95
+ /* @vite-ignore */
96
+ url
97
+ ));
98
+ return /* @__PURE__ */ jsx4(ErrorBoundary, { children: /* @__PURE__ */ jsx4(Suspense, { fallback: /* @__PURE__ */ jsx4(Loader, {}), children: /* @__PURE__ */ jsx4(LazyFeature, { ...props, ...params }) }) });
99
+ }
100
+ var Feature = React3.memo(RawFeature);
101
+ Feature.displayName = "Feature";
102
+ registerComponent("Feature", Feature, "view");
103
+
104
+ // src/login/LoginPanel.tsx
105
+ import { useState as useState2 } from "react";
106
+ import { Button } from "@salt-ds/core";
107
+ import { FormField, Input } from "@heswell/salt-lab";
108
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
109
+ var classBase = "vuuLoginPanel";
110
+ var LoginPanel = ({ onSubmit }) => {
111
+ const [username, setUserName] = useState2("");
112
+ const [password, setPassword] = useState2("");
113
+ const login = () => {
114
+ onSubmit(username, password);
115
+ };
116
+ const handleUsername = (_event, value) => {
117
+ setUserName(value);
118
+ };
119
+ const handlePassword = (_event, value) => {
120
+ setPassword(value);
121
+ };
122
+ const dataIsValid = username.trim() !== "" && password.trim() !== "";
123
+ return /* @__PURE__ */ jsxs3("div", { className: classBase, children: [
124
+ /* @__PURE__ */ jsx5(FormField, { label: "Username", style: { width: 200 }, children: /* @__PURE__ */ jsx5(Input, { value: username, id: "text-username", onChange: handleUsername }) }),
125
+ /* @__PURE__ */ jsx5(FormField, { label: "Password", style: { width: 200 }, children: /* @__PURE__ */ jsx5(
126
+ Input,
127
+ {
128
+ type: "password",
129
+ value: password,
130
+ id: "text-password",
131
+ onChange: handlePassword
132
+ }
133
+ ) }),
134
+ /* @__PURE__ */ jsx5(
135
+ Button,
136
+ {
137
+ className: `${classBase}-login`,
138
+ disabled: !dataIsValid,
139
+ onClick: login,
140
+ variant: "cta",
141
+ children: "Login"
142
+ }
143
+ )
144
+ ] });
145
+ };
146
+
147
+ // src/login/login-utils.ts
148
+ import { getCookieValue } from "@vuu-ui/vuu-utils";
149
+ var getAuthDetailsFromCookies = () => {
150
+ const username = getCookieValue("vuu-username");
151
+ const token = getCookieValue("vuu-auth-token");
152
+ return [username, token];
153
+ };
154
+ var redirectToLogin = (loginUrl = "/login.html") => {
155
+ window.location.href = loginUrl;
156
+ };
157
+ var logout = (loginUrl) => {
158
+ document.cookie = "vuu-username= ; expires = Thu, 01 Jan 1970 00:00:00 GMT";
159
+ document.cookie = "vuu-auth-token= ; expires = Thu, 01 Jan 1970 00:00:00 GMT";
160
+ redirectToLogin(loginUrl);
161
+ };
162
+
163
+ // src/shell.tsx
164
+ import { connectToServer } from "@vuu-ui/vuu-data";
165
+ import {
166
+ useCallback as useCallback6,
167
+ useEffect as useEffect4,
168
+ useRef,
169
+ useState as useState5
170
+ } from "react";
171
+
172
+ // src/use-layout-config.js
173
+ import { useCallback, useEffect as useEffect2, useState as useState3 } from "react";
174
+ var useLayoutConfig = (user, defaultLayout) => {
175
+ const [layout, _setLayout] = useState3(defaultLayout);
176
+ const setLayout = (layout2) => {
177
+ _setLayout(layout2);
178
+ };
179
+ const load = useCallback(
180
+ async (id = "latest") => {
181
+ fetch(`api/vui/${user.username}/${id}`, {}).then((response) => {
182
+ return response.ok ? response.json() : defaultLayout;
183
+ }).then(setLayout).catch(() => {
184
+ setLayout(defaultLayout);
185
+ });
186
+ },
187
+ [defaultLayout, user.username]
188
+ );
189
+ useEffect2(() => {
190
+ load();
191
+ }, [load]);
192
+ const saveData = useCallback(
193
+ (data) => {
194
+ fetch(`api/vui/${user.username}`, {
195
+ method: "POST",
196
+ headers: {
197
+ "Content-Type": "application/json"
198
+ },
199
+ body: JSON.stringify(data)
200
+ }).then((response) => {
201
+ return response.ok ? response.json() : defaultLayout;
202
+ });
203
+ },
204
+ [defaultLayout, user]
205
+ );
206
+ const loadLayoutById = useCallback(
207
+ (id) => {
208
+ load(id);
209
+ },
210
+ [load]
211
+ );
212
+ return [layout, saveData, loadLayoutById];
213
+ };
214
+ var use_layout_config_default = useLayoutConfig;
215
+
216
+ // src/ShellContextProvider.tsx
217
+ import { createContext, useContext } from "react";
218
+ import { jsx as jsx6 } from "react/jsx-runtime";
219
+ var defaultConfig = {};
220
+ var ShellContext = createContext(defaultConfig);
221
+ var Provider = ({
222
+ children,
223
+ context,
224
+ inheritedContext
225
+ }) => {
226
+ const mergedContext = {
227
+ ...inheritedContext,
228
+ ...context
229
+ };
230
+ return /* @__PURE__ */ jsx6(ShellContext.Provider, { value: mergedContext, children });
231
+ };
232
+ var ShellContextProvider = ({
233
+ children,
234
+ value
235
+ }) => {
236
+ return /* @__PURE__ */ jsx6(ShellContext.Consumer, { children: (context) => /* @__PURE__ */ jsx6(Provider, { context: value, inheritedContext: context, children }) });
237
+ };
238
+ var useShellContext = () => {
239
+ return useContext(ShellContext);
240
+ };
241
+
242
+ // src/shell.tsx
243
+ import cx5 from "classnames";
244
+ import {
245
+ Chest,
246
+ DraggableLayout,
247
+ Drawer,
248
+ Flexbox,
249
+ LayoutProvider,
250
+ View
251
+ } from "@vuu-ui/vuu-layout";
252
+
253
+ // src/app-header/AppHeader.tsx
254
+ import { useCallback as useCallback5 } from "react";
255
+
256
+ // src/user-profile/UserProfile.tsx
257
+ import { Button as Button3 } from "@salt-ds/core";
258
+ import { DropdownBase } from "@heswell/salt-lab";
259
+ import { UserSolidIcon } from "@salt-ds/icons";
260
+
261
+ // src/user-profile/UserPanel.tsx
262
+ import { formatDate } from "@vuu-ui/vuu-utils";
263
+ import { List, ListItem } from "@heswell/salt-lab";
264
+ import { Button as Button2 } from "@salt-ds/core";
265
+ import { ExportIcon } from "@salt-ds/icons";
266
+ import {
267
+ forwardRef,
268
+ useCallback as useCallback2,
269
+ useEffect as useEffect3,
270
+ useState as useState4
271
+ } from "react";
272
+
273
+ // src/get-layout-history.ts
274
+ var getLayoutHistory = async (user) => {
275
+ const history = await fetch(`api/vui/${user.username}`, {}).then((response) => {
276
+ return response.ok ? response.json() : null;
277
+ }).catch(() => {
278
+ console.log("error getting history");
279
+ });
280
+ return history;
281
+ };
282
+
283
+ // src/user-profile/UserPanel.tsx
284
+ import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
285
+ var byLastUpdate = ({ lastUpdate: l1 }, { lastUpdate: l2 }) => {
286
+ return l2 === l1 ? 0 : l2 < l1 ? -1 : 1;
287
+ };
288
+ var HistoryListItem = (props) => {
289
+ return /* @__PURE__ */ jsx7(ListItem, { ...props });
290
+ };
291
+ var UserPanel = forwardRef(function UserPanel2({ loginUrl, onNavigate, user, layoutId = "latest" }, forwardedRef) {
292
+ const [history, setHistory] = useState4([]);
293
+ useEffect3(() => {
294
+ async function getHistory() {
295
+ const history2 = await getLayoutHistory(user);
296
+ const sortedHistory = history2.filter((item) => item.id !== "latest").sort(byLastUpdate).map(({ id, lastUpdate }) => ({
297
+ lastUpdate,
298
+ id,
299
+ label: `Saved at ${formatDate(new Date(lastUpdate), "kk:mm:ss")}`
300
+ }));
301
+ console.log({ sortedHistory });
302
+ setHistory(sortedHistory);
303
+ }
304
+ getHistory();
305
+ }, [user]);
306
+ const handleHisorySelected = useCallback2(
307
+ (evt, selected2) => {
308
+ if (selected2) {
309
+ onNavigate(selected2.id);
310
+ }
311
+ },
312
+ [onNavigate]
313
+ );
314
+ const handleLogout = useCallback2(() => {
315
+ logout(loginUrl);
316
+ }, [loginUrl]);
317
+ const selected = history.length === 0 ? null : layoutId === "latest" ? history[0] : history.find((i) => i.id === layoutId);
318
+ return /* @__PURE__ */ jsxs4("div", { className: "vuuUserPanel", ref: forwardedRef, children: [
319
+ /* @__PURE__ */ jsx7(
320
+ List,
321
+ {
322
+ ListItem: HistoryListItem,
323
+ className: "vuuUserPanel-history",
324
+ onSelect: handleHisorySelected,
325
+ selected,
326
+ source: history
327
+ }
328
+ ),
329
+ /* @__PURE__ */ jsx7("div", { className: "vuuUserPanel-buttonBar", children: /* @__PURE__ */ jsxs4(Button2, { "aria-label": "logout", onClick: handleLogout, children: [
330
+ /* @__PURE__ */ jsx7(ExportIcon, {}),
331
+ " Logout"
332
+ ] }) })
333
+ ] });
334
+ });
335
+
336
+ // src/user-profile/UserProfile.tsx
337
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
338
+ var UserProfile = ({
339
+ layoutId,
340
+ loginUrl,
341
+ onNavigate,
342
+ user
343
+ }) => {
344
+ const handleNavigate = (id) => {
345
+ onNavigate(id);
346
+ };
347
+ return /* @__PURE__ */ jsxs5(DropdownBase, { className: "vuuUserProfile", placement: "bottom-end", children: [
348
+ /* @__PURE__ */ jsx8(Button3, { variant: "secondary", children: /* @__PURE__ */ jsx8(UserSolidIcon, {}) }),
349
+ /* @__PURE__ */ jsx8(
350
+ UserPanel,
351
+ {
352
+ layoutId,
353
+ loginUrl,
354
+ onNavigate: handleNavigate,
355
+ user
356
+ }
357
+ )
358
+ ] });
359
+ };
360
+
361
+ // src/theme-switch/ThemeSwitch.tsx
362
+ import {
363
+ ToggleButton,
364
+ ToggleButtonGroup
365
+ } from "@heswell/salt-lab";
366
+ import cx2 from "classnames";
367
+ import { useControlled } from "@salt-ds/core";
368
+ import { useCallback as useCallback3 } from "react";
369
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
370
+ var classBase2 = "vuuThemeSwitch";
371
+ var modes = ["light", "dark"];
372
+ var ThemeSwitch = ({
373
+ className: classNameProp,
374
+ defaultMode: defaultModeProp,
375
+ mode: modeProp,
376
+ onChange,
377
+ ...htmlAttributes
378
+ }) => {
379
+ const [mode, setMode] = useControlled({
380
+ controlled: modeProp,
381
+ default: defaultModeProp != null ? defaultModeProp : "light",
382
+ name: "ThemeSwitch",
383
+ state: "mode"
384
+ });
385
+ const selectedIndex = modes.indexOf(mode);
386
+ const handleChangeSecondary = useCallback3(
387
+ (_evt, index) => {
388
+ const mode2 = modes[index];
389
+ setMode(mode2);
390
+ onChange(mode2);
391
+ },
392
+ [onChange, setMode]
393
+ );
394
+ const className = cx2(classBase2, classNameProp);
395
+ return /* @__PURE__ */ jsxs6(
396
+ ToggleButtonGroup,
397
+ {
398
+ className,
399
+ ...htmlAttributes,
400
+ onChange: handleChangeSecondary,
401
+ selectedIndex,
402
+ children: [
403
+ /* @__PURE__ */ jsx9(
404
+ ToggleButton,
405
+ {
406
+ "aria-label": "alert",
407
+ tooltipText: "Light Theme",
408
+ "data-icon": "light"
409
+ }
410
+ ),
411
+ /* @__PURE__ */ jsx9(
412
+ ToggleButton,
413
+ {
414
+ "aria-label": "home",
415
+ tooltipText: "Dark Theme",
416
+ "data-icon": "dark"
417
+ }
418
+ )
419
+ ]
420
+ }
421
+ );
422
+ };
423
+
424
+ // src/app-header/AppHeader.tsx
425
+ import cx4 from "classnames";
426
+
427
+ // src/density-switch/DensitySwitch.tsx
428
+ import { Dropdown } from "@heswell/salt-lab";
429
+ import { DEFAULT_DENSITY } from "@salt-ds/core";
430
+ import { useCallback as useCallback4 } from "react";
431
+ import cx3 from "classnames";
432
+ import { jsx as jsx10 } from "react/jsx-runtime";
433
+ var classBase3 = "vuuDensitySwitch";
434
+ var densities = ["high", "medium", "low", "touch"];
435
+ var DensitySwitch = ({
436
+ className: classNameProp,
437
+ defaultDensity = DEFAULT_DENSITY,
438
+ onDensityChange
439
+ }) => {
440
+ const handleSelectionChange = useCallback4((_event, selectedItem) => {
441
+ onDensityChange(selectedItem);
442
+ }, [onDensityChange]);
443
+ const className = cx3(classBase3, classNameProp);
444
+ return /* @__PURE__ */ jsx10(
445
+ Dropdown,
446
+ {
447
+ className,
448
+ source: densities,
449
+ defaultSelected: defaultDensity,
450
+ onSelectionChange: handleSelectionChange
451
+ }
452
+ );
453
+ };
454
+
455
+ // src/app-header/AppHeader.tsx
456
+ import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
457
+ var classBase4 = "vuuAppHeader";
458
+ var AppHeader = ({
459
+ className: classNameProp,
460
+ layoutId,
461
+ loginUrl,
462
+ onNavigate,
463
+ onSwitchTheme,
464
+ themeMode = "light",
465
+ onDensitySwitch,
466
+ density = "medium",
467
+ user,
468
+ ...htmlAttributes
469
+ }) => {
470
+ const className = cx4(classBase4, classNameProp, `salt-density-${density}`);
471
+ const handleSwitchTheme = useCallback5(
472
+ (mode) => onSwitchTheme == null ? void 0 : onSwitchTheme(mode),
473
+ [onSwitchTheme]
474
+ );
475
+ const handleDensitySwitch = useCallback5(
476
+ (density2) => onDensitySwitch == null ? void 0 : onDensitySwitch(density2),
477
+ [onDensitySwitch]
478
+ );
479
+ return /* @__PURE__ */ jsxs7("header", { className, ...htmlAttributes, children: [
480
+ /* @__PURE__ */ jsx11(ThemeSwitch, { defaultMode: themeMode, onChange: handleSwitchTheme }),
481
+ /* @__PURE__ */ jsx11(DensitySwitch, { defaultDensity: density, onDensityChange: handleDensitySwitch }),
482
+ /* @__PURE__ */ jsx11(
483
+ UserProfile,
484
+ {
485
+ layoutId,
486
+ loginUrl,
487
+ onNavigate,
488
+ user
489
+ }
490
+ )
491
+ ] });
492
+ };
493
+
494
+ // src/shell.tsx
495
+ import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
496
+ var warningLayout = {
497
+ type: "View",
498
+ props: {
499
+ style: { height: "calc(100% - 6px)" }
500
+ },
501
+ children: [
502
+ {
503
+ props: {
504
+ className: "vuuShell-warningPlaceholder"
505
+ },
506
+ type: "Placeholder"
507
+ }
508
+ ]
509
+ };
510
+ var Shell = ({
511
+ children,
512
+ className: classNameProp,
513
+ defaultLayout = warningLayout,
514
+ leftSidePanel,
515
+ loginUrl,
516
+ serverUrl,
517
+ user,
518
+ ...htmlAttributes
519
+ }) => {
520
+ const rootRef = useRef(null);
521
+ const [density, setDensity] = useState5("medium");
522
+ const paletteView = useRef(null);
523
+ const [open, setOpen] = useState5(false);
524
+ const layoutId = useRef("latest");
525
+ const [layout, setLayoutConfig, loadLayoutById] = use_layout_config_default(
526
+ user,
527
+ defaultLayout
528
+ );
529
+ const handleLayoutChange = useCallback6(
530
+ (layout2) => {
531
+ setLayoutConfig(layout2);
532
+ },
533
+ [setLayoutConfig]
534
+ );
535
+ const handleSwitchTheme = useCallback6((mode) => {
536
+ if (rootRef.current) {
537
+ rootRef.current.dataset.mode = mode;
538
+ }
539
+ }, []);
540
+ const handleDensitySwitch = useCallback6(
541
+ (density2) => {
542
+ setDensity(density2);
543
+ },
544
+ [setDensity]
545
+ );
546
+ const handleDrawerClick = (e) => {
547
+ var _a;
548
+ const target = e.target;
549
+ if (!((_a = paletteView.current) == null ? void 0 : _a.contains(target))) {
550
+ setOpen(!open);
551
+ }
552
+ };
553
+ const handleNavigate = useCallback6(
554
+ (id) => {
555
+ layoutId.current = id;
556
+ loadLayoutById(id);
557
+ },
558
+ [loadLayoutById]
559
+ );
560
+ useEffect4(() => {
561
+ if (serverUrl && user.token) {
562
+ connectToServer(serverUrl, user.token);
563
+ }
564
+ }, [serverUrl, user.token]);
565
+ const getDrawers = () => {
566
+ const drawers = [];
567
+ if (leftSidePanel) {
568
+ drawers.push(
569
+ /* @__PURE__ */ jsx12(
570
+ Drawer,
571
+ {
572
+ onClick: handleDrawerClick,
573
+ open,
574
+ position: "left",
575
+ inline: true,
576
+ peekaboo: true,
577
+ sizeOpen: 200,
578
+ toggleButton: "end",
579
+ children: /* @__PURE__ */ jsx12(
580
+ View,
581
+ {
582
+ className: "vuuShell-palette",
583
+ id: "vw-app-palette",
584
+ ref: paletteView,
585
+ style: { height: "100%" },
586
+ children: leftSidePanel
587
+ },
588
+ "app-palette"
589
+ )
590
+ },
591
+ "left-panel"
592
+ )
593
+ );
594
+ }
595
+ return drawers;
596
+ };
597
+ const className = cx5(
598
+ "vuuShell",
599
+ classNameProp,
600
+ "salt-theme",
601
+ `salt-density-${density}`
602
+ );
603
+ return (
604
+ // ShellContext TBD
605
+ /* @__PURE__ */ jsxs8(ShellContextProvider, { value: void 0, children: [
606
+ /* @__PURE__ */ jsx12(LayoutProvider, { layout, onLayoutChange: handleLayoutChange, children: /* @__PURE__ */ jsx12(
607
+ DraggableLayout,
608
+ {
609
+ className,
610
+ "data-mode": "light",
611
+ ref: rootRef,
612
+ ...htmlAttributes,
613
+ children: /* @__PURE__ */ jsxs8(
614
+ Flexbox,
615
+ {
616
+ className: "App",
617
+ style: { flexDirection: "column", height: "100%", width: "100%" },
618
+ children: [
619
+ /* @__PURE__ */ jsx12(
620
+ AppHeader,
621
+ {
622
+ layoutId: layoutId.current,
623
+ loginUrl,
624
+ user,
625
+ onNavigate: handleNavigate,
626
+ onSwitchTheme: handleSwitchTheme,
627
+ onDensitySwitch: handleDensitySwitch
628
+ }
629
+ ),
630
+ /* @__PURE__ */ jsx12(Chest, { style: { flex: 1 }, children: getDrawers().concat(
631
+ /* @__PURE__ */ jsx12(
632
+ DraggableLayout,
633
+ {
634
+ dropTarget: true,
635
+ style: { width: "100%", height: "100%" }
636
+ },
637
+ "main-content"
638
+ )
639
+ ) })
640
+ ]
641
+ }
642
+ )
643
+ }
644
+ ) }),
645
+ children
646
+ ] })
647
+ );
648
+ };
649
+ export {
650
+ ConnectionStatusIcon,
651
+ Feature,
652
+ LoginPanel,
653
+ Shell,
654
+ ShellContextProvider,
655
+ ThemeSwitch,
656
+ getAuthDetailsFromCookies,
657
+ logout,
658
+ redirectToLogin,
659
+ useShellContext
660
+ };
2
661
  //# sourceMappingURL=index.js.map