@vuu-ui/vuu-shell 0.7.2-debug → 0.7.2

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/cjs/index.js CHANGED
@@ -1,1069 +1,4 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/index.ts
31
- var src_exports = {};
32
- __export(src_exports, {
33
- ConnectionStatusIcon: () => ConnectionStatusIcon,
34
- DEFAULT_DENSITY: () => DEFAULT_DENSITY2,
35
- DEFAULT_THEME: () => DEFAULT_THEME,
36
- DEFAULT_THEME_MODE: () => DEFAULT_THEME_MODE,
37
- DensitySwitch: () => DensitySwitch,
38
- Feature: () => Feature,
39
- LoginPanel: () => LoginPanel,
40
- SessionEditingForm: () => SessionEditingForm,
41
- Shell: () => Shell,
42
- ShellContextProvider: () => ShellContextProvider,
43
- ThemeContext: () => ThemeContext,
44
- ThemeProvider: () => ThemeProvider,
45
- ThemeSwitch: () => ThemeSwitch,
46
- getAuthDetailsFromCookies: () => getAuthDetailsFromCookies,
47
- logout: () => logout,
48
- redirectToLogin: () => redirectToLogin,
49
- useShellContext: () => useShellContext
50
- });
51
- module.exports = __toCommonJS(src_exports);
52
-
53
- // src/connection-status/ConnectionStatusIcon.tsx
54
- var import_react = __toESM(require("react"));
55
- var import_classnames = __toESM(require("classnames"));
56
- var import_jsx_runtime = require("react/jsx-runtime");
57
- var ConnectionStatusIcon = ({ connectionStatus, className, element = "span", ...props }) => {
58
- const [classBase6, setClassBase] = (0, import_react.useState)("vuuConnectingStatus");
59
- (0, import_react.useEffect)(() => {
60
- switch (connectionStatus) {
61
- case "connected":
62
- case "reconnected":
63
- setClassBase("vuuActiveStatus");
64
- break;
65
- case "connecting":
66
- setClassBase("vuuConnectingStatus");
67
- break;
68
- case "disconnected":
69
- setClassBase("vuuDisconnectedStatus");
70
- break;
71
- default:
72
- break;
73
- }
74
- }, [connectionStatus]);
75
- const statusIcon = import_react.default.createElement(
76
- element,
77
- {
78
- ...props,
79
- className: (0, import_classnames.default)("vuuStatus vuuIcon", classBase6, className)
80
- }
81
- );
82
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "vuuStatus-container salt-theme", children: [
83
- statusIcon,
84
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "vuuStatus-text", children: [
85
- "Status: ",
86
- connectionStatus.toUpperCase()
87
- ] })
88
- ] }) });
89
- };
90
-
91
- // src/density-switch/DensitySwitch.tsx
92
- var import_salt_lab = require("@heswell/salt-lab");
93
- var import_react2 = require("react");
94
- var import_classnames2 = __toESM(require("classnames"));
95
- var import_jsx_runtime2 = require("react/jsx-runtime");
96
- var classBase = "vuuDensitySwitch";
97
- var densities = ["high", "medium", "low", "touch"];
98
- var DEFAULT_DENSITY = "high";
99
- var DensitySwitch = ({
100
- className: classNameProp,
101
- defaultDensity = DEFAULT_DENSITY,
102
- onDensityChange
103
- }) => {
104
- const handleSelectionChange = (0, import_react2.useCallback)((_event, selectedItem) => {
105
- onDensityChange(selectedItem);
106
- }, [onDensityChange]);
107
- const className = (0, import_classnames2.default)(classBase, classNameProp);
108
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
109
- import_salt_lab.Dropdown,
110
- {
111
- className,
112
- source: densities,
113
- defaultSelected: defaultDensity,
114
- onSelectionChange: handleSelectionChange
115
- }
116
- );
117
- };
118
-
119
- // src/feature/Feature.tsx
120
- var import_react4 = __toESM(require("react"));
121
- var import_vuu_layout = require("@vuu-ui/vuu-layout");
122
-
123
- // src/feature/ErrorBoundary.jsx
124
- var import_react3 = __toESM(require("react"));
125
- var import_jsx_runtime3 = require("react/jsx-runtime");
126
- var ErrorBoundary = class extends import_react3.default.Component {
127
- constructor(props) {
128
- super(props);
129
- this.state = { errorMessage: null };
130
- }
131
- static getDerivedStateFromError(error2) {
132
- return { errorMessage: error2.message };
133
- }
134
- componentDidCatch(error2, errorInfo) {
135
- console.log(error2, errorInfo);
136
- }
137
- render() {
138
- if (this.state.errorMessage) {
139
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
140
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h1", { children: "Something went wrong." }),
141
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: this.state.errorMessage })
142
- ] });
143
- }
144
- return this.props.children;
145
- }
146
- };
147
-
148
- // src/feature/Loader.tsx
149
- var import_jsx_runtime4 = require("react/jsx-runtime");
150
- var Loader = () => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "hwLoader", children: "loading" });
151
-
152
- // src/feature/Feature.tsx
153
- var import_jsx_runtime5 = require("react/jsx-runtime");
154
- var componentsMap = /* @__PURE__ */ new Map();
155
- var useCachedFeature = (url) => {
156
- (0, import_react4.useEffect)(
157
- () => () => {
158
- componentsMap.delete(url);
159
- },
160
- [url]
161
- );
162
- if (!componentsMap.has(url)) {
163
- componentsMap.set(
164
- url,
165
- import_react4.default.lazy(() => import(
166
- /* @vite-ignore */
167
- url
168
- ))
169
- );
170
- }
171
- return componentsMap.get(url);
172
- };
173
- function RawFeature({
174
- url,
175
- css,
176
- params,
177
- ...props
178
- }) {
179
- console.log("Feature render", { css, url, props });
180
- (0, import_react4.useEffect)(() => {
181
- console.log("%cFeature mount", "color: green;");
182
- return () => {
183
- console.log("%cFeature unmount", "color:red;");
184
- };
185
- }, []);
186
- if (css) {
187
- import(
188
- /* @vite-ignore */
189
- css
190
- ).then(
191
- (cssModule) => {
192
- console.log("%cInject Styles", "color: blue;font-weight: bold");
193
- document.adoptedStyleSheets = [
194
- ...document.adoptedStyleSheets,
195
- cssModule.default
196
- ];
197
- }
198
- );
199
- }
200
- const LazyFeature = useCachedFeature(url);
201
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react4.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Loader, {}), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(LazyFeature, { ...props, ...params }) }) });
202
- }
203
- var Feature = import_react4.default.memo(RawFeature);
204
- Feature.displayName = "Feature";
205
- (0, import_vuu_layout.registerComponent)("Feature", Feature, "view");
206
-
207
- // src/login/LoginPanel.tsx
208
- var import_react5 = require("react");
209
- var import_core = require("@salt-ds/core");
210
- var import_salt_lab2 = require("@heswell/salt-lab");
211
- var import_jsx_runtime6 = require("react/jsx-runtime");
212
- var classBase2 = "vuuLoginPanel";
213
- var LoginPanel = ({ onSubmit }) => {
214
- const [username, setUserName] = (0, import_react5.useState)("");
215
- const [password, setPassword] = (0, import_react5.useState)("");
216
- const login = () => {
217
- onSubmit(username, password);
218
- };
219
- const handleUsername = (_event, value) => {
220
- setUserName(value);
221
- };
222
- const handlePassword = (_event, value) => {
223
- setPassword(value);
224
- };
225
- const dataIsValid = username.trim() !== "" && password.trim() !== "";
226
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: classBase2, children: [
227
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_salt_lab2.FormField, { label: "Username", style: { width: 200 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_salt_lab2.Input, { value: username, id: "text-username", onChange: handleUsername }) }),
228
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_salt_lab2.FormField, { label: "Password", style: { width: 200 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
229
- import_salt_lab2.Input,
230
- {
231
- type: "password",
232
- value: password,
233
- id: "text-password",
234
- onChange: handlePassword
235
- }
236
- ) }),
237
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
238
- import_core.Button,
239
- {
240
- className: `${classBase2}-login`,
241
- disabled: !dataIsValid,
242
- onClick: login,
243
- variant: "cta",
244
- children: "Login"
245
- }
246
- )
247
- ] });
248
- };
249
-
250
- // src/login/login-utils.ts
251
- var import_vuu_utils = require("@vuu-ui/vuu-utils");
252
- var getAuthDetailsFromCookies = () => {
253
- const username = (0, import_vuu_utils.getCookieValue)("vuu-username");
254
- const token = (0, import_vuu_utils.getCookieValue)("vuu-auth-token");
255
- return [username, token];
256
- };
257
- var redirectToLogin = (loginUrl = "login.html") => {
258
- window.location.href = loginUrl;
259
- };
260
- var logout = (loginUrl) => {
261
- document.cookie = "vuu-username= ; expires = Thu, 01 Jan 1970 00:00:00 GMT";
262
- document.cookie = "vuu-auth-token= ; expires = Thu, 01 Jan 1970 00:00:00 GMT";
263
- redirectToLogin(loginUrl);
264
- };
265
-
266
- // src/session-editing-form/SessionEditingForm.tsx
267
- var import_react6 = require("react");
268
- var import_classnames3 = __toESM(require("classnames"));
269
- var import_core2 = require("@salt-ds/core");
270
- var import_core3 = require("@salt-ds/core");
271
- var import_vuu_data = require("@vuu-ui/vuu-data");
272
- var import_vuu_utils2 = require("@vuu-ui/vuu-utils");
273
- var import_jsx_runtime7 = require("react/jsx-runtime");
274
- var classBase3 = "vuuSessionEditingForm";
275
- var getField = (fields, name) => {
276
- const field = fields.find((f) => f.name === name);
277
- if (field) {
278
- return field;
279
- } else {
280
- throw Error(`SessionEditingForm, no field '${name}' found`);
281
- }
282
- };
283
- var getFieldNameAndValue = (evt) => {
284
- const {
285
- dataset: { field },
286
- value
287
- } = evt.target;
288
- if (field === void 0) {
289
- throw Error("SessionEditingForm, form field has no field name");
290
- }
291
- return [field, value];
292
- };
293
- var Status = {
294
- uninitialised: 0,
295
- unchanged: 1,
296
- changed: 2,
297
- invalid: 3
298
- };
299
- function getTypedValue(value, type, throwIfUndefined = false) {
300
- switch (type) {
301
- case "int":
302
- case "long": {
303
- const typedValue = parseInt(value, 10);
304
- if ((0, import_vuu_utils2.isValidNumber)(typedValue)) {
305
- return typedValue;
306
- } else if (throwIfUndefined) {
307
- throw Error("SessionEditingForm getTypedValue");
308
- } else {
309
- return void 0;
310
- }
311
- }
312
- case "double": {
313
- const typedValue = parseFloat(value);
314
- if ((0, import_vuu_utils2.isValidNumber)(typedValue)) {
315
- return typedValue;
316
- }
317
- return void 0;
318
- }
319
- case "boolean":
320
- return value === "true" ? true : false;
321
- default:
322
- return value;
323
- }
324
- }
325
- var getDataSource = (dataSource, schema) => {
326
- if (dataSource) {
327
- return dataSource;
328
- } else if (schema) {
329
- return new import_vuu_data.RemoteDataSource({
330
- bufferSize: 0,
331
- table: schema.table,
332
- columns: schema.columns.map((col) => col.name)
333
- });
334
- } else {
335
- throw Error(
336
- "SessionEditingForm: either a DataSource or a TableSchema must be provided"
337
- );
338
- }
339
- };
340
- var SessionEditingForm = ({
341
- className,
342
- config: { fields, key: keyField },
343
- dataSource: dataSourceProp,
344
- id: idProp,
345
- onClose,
346
- schema,
347
- ...htmlAttributes
348
- }) => {
349
- const [values, setValues] = (0, import_react6.useState)();
350
- const [errorMessage, setErrorMessage] = (0, import_react6.useState)("");
351
- const formContentRef = (0, import_react6.useRef)(null);
352
- const initialDataRef = (0, import_react6.useRef)();
353
- const dataStatusRef = (0, import_react6.useRef)(Status.uninitialised);
354
- const dataSource = (0, import_react6.useMemo)(() => {
355
- const applyServerData = (data) => {
356
- if (columnMap) {
357
- const values2 = {};
358
- for (const column of dataSource.columns) {
359
- values2[column] = data[columnMap[column]];
360
- }
361
- if (dataStatusRef.current === Status.uninitialised) {
362
- dataStatusRef.current = Status.unchanged;
363
- initialDataRef.current = values2;
364
- }
365
- setValues(values2);
366
- }
367
- };
368
- const ds = getDataSource(dataSourceProp, schema);
369
- const columnMap = (0, import_vuu_utils2.buildColumnMap)(ds.columns);
370
- ds.subscribe({ range: { from: 0, to: 5 } }, (message) => {
371
- if (message.type === "viewport-update" && message.rows) {
372
- if (dataStatusRef.current === Status.uninitialised) {
373
- applyServerData(message.rows[0]);
374
- } else {
375
- console.log("what do we do with server updates");
376
- }
377
- }
378
- });
379
- return ds;
380
- }, [dataSourceProp, schema]);
381
- const id = (0, import_core2.useIdMemo)(idProp);
382
- const handleChange = (0, import_react6.useCallback)(
383
- (evt) => {
384
- const [field, value] = getFieldNameAndValue(evt);
385
- const { type } = getField(fields, field);
386
- const typedValue = getTypedValue(value, type);
387
- setValues((values2 = {}) => {
388
- const newValues = {
389
- ...values2,
390
- [field]: typedValue
391
- };
392
- const notUpdated = (0, import_vuu_utils2.shallowEquals)(newValues, initialDataRef.current);
393
- dataStatusRef.current = notUpdated ? Status.unchanged : typedValue !== void 0 ? Status.changed : Status.invalid;
394
- return newValues;
395
- });
396
- },
397
- [fields]
398
- );
399
- const handleBlur = (0, import_react6.useCallback)(
400
- (evt) => {
401
- const [field, value] = getFieldNameAndValue(evt);
402
- const { type } = getField(fields, field);
403
- console.log("BLUR", {
404
- keyField
405
- });
406
- const rowKey = values == null ? void 0 : values[keyField];
407
- const typedValue = getTypedValue(value, type, true);
408
- if (typeof rowKey === "string") {
409
- dataSource.menuRpcCall({
410
- rowKey,
411
- field,
412
- value: typedValue,
413
- type: "VP_EDIT_CELL_RPC"
414
- });
415
- }
416
- },
417
- [dataSource, fields, keyField, values]
418
- );
419
- const handleSubmit = (0, import_react6.useCallback)(async () => {
420
- const response = await dataSource.menuRpcCall({
421
- type: "VP_EDIT_SUBMIT_FORM_RPC"
422
- });
423
- if ((0, import_vuu_data.isErrorResponse)(response)) {
424
- setErrorMessage(response.error);
425
- }
426
- }, [dataSource]);
427
- const handleKeyDown = (0, import_react6.useCallback)(
428
- (evt) => {
429
- if (evt.key === "Enter" && dataStatusRef.current === Status.changed) {
430
- handleSubmit();
431
- }
432
- },
433
- [handleSubmit]
434
- );
435
- const handleCancel = (0, import_react6.useCallback)(() => {
436
- onClose();
437
- }, [onClose]);
438
- const getFormControl = (field) => {
439
- var _a;
440
- const value = String((_a = values == null ? void 0 : values[field.name]) != null ? _a : "");
441
- if (field.readonly || field.name === keyField) {
442
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `${classBase3}-fieldValue vuuReadOnly`, children: value });
443
- } else {
444
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
445
- "input",
446
- {
447
- className: `${classBase3}-fieldValue`,
448
- "data-field": field.name,
449
- onBlur: handleBlur,
450
- onChange: handleChange,
451
- type: "text",
452
- value,
453
- id: `${id}-input-${field.name}`
454
- }
455
- );
456
- }
457
- };
458
- (0, import_react6.useEffect)(() => {
459
- if (formContentRef.current) {
460
- const firstInput = formContentRef.current.querySelector(
461
- "input"
462
- );
463
- if (firstInput) {
464
- setTimeout(() => {
465
- firstInput.focus();
466
- console.log("select item");
467
- firstInput.select();
468
- }, 100);
469
- }
470
- }
471
- }, []);
472
- const isDirty = dataStatusRef.current === Status.changed;
473
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { ...htmlAttributes, className: (0, import_classnames3.default)(classBase3, className), children: [
474
- errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
475
- "div",
476
- {
477
- className: `${classBase3}-errorBanner`,
478
- "data-icon": "error",
479
- title: errorMessage,
480
- children: "Error, edit(s) not saved"
481
- }
482
- ) : void 0,
483
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
484
- "div",
485
- {
486
- className: `${classBase3}-content`,
487
- ref: formContentRef,
488
- onKeyDown: handleKeyDown,
489
- children: fields.map((field) => {
490
- var _a;
491
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `${classBase3}-field`, children: [
492
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
493
- "label",
494
- {
495
- className: (0, import_classnames3.default)(`${classBase3}-fieldLabel`, {
496
- [`${classBase3}-required`]: field.required
497
- }),
498
- htmlFor: `${id}-input-${field.name}`,
499
- children: (_a = field == null ? void 0 : field.label) != null ? _a : field.description
500
- }
501
- ),
502
- getFormControl(field)
503
- ] }, field.name);
504
- })
505
- }
506
- ),
507
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `${classBase3}-buttonbar salt-theme salt-density-high`, children: [
508
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
509
- import_core3.Button,
510
- {
511
- type: "submit",
512
- variant: "cta",
513
- disabled: !isDirty,
514
- onClick: handleSubmit,
515
- children: "Submit"
516
- }
517
- ),
518
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_core3.Button, { variant: "secondary", onClick: handleCancel, children: "Cancel" })
519
- ] })
520
- ] });
521
- };
522
-
523
- // src/shell.tsx
524
- var import_vuu_data2 = require("@vuu-ui/vuu-data");
525
- var import_classnames6 = __toESM(require("classnames"));
526
- var import_react12 = require("react");
527
-
528
- // src/ShellContextProvider.tsx
529
- var import_react7 = require("react");
530
- var import_jsx_runtime8 = require("react/jsx-runtime");
531
- var defaultConfig = {};
532
- var ShellContext = (0, import_react7.createContext)(defaultConfig);
533
- var Provider = ({
534
- children,
535
- context,
536
- inheritedContext
537
- }) => {
538
- const mergedContext = {
539
- ...inheritedContext,
540
- ...context
541
- };
542
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ShellContext.Provider, { value: mergedContext, children });
543
- };
544
- var ShellContextProvider = ({
545
- children,
546
- value
547
- }) => {
548
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ShellContext.Consumer, { children: (context) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Provider, { context: value, inheritedContext: context, children }) });
549
- };
550
- var useShellContext = () => {
551
- return (0, import_react7.useContext)(ShellContext);
552
- };
553
-
554
- // src/layout-config/use-layout-config.ts
555
- var import_react8 = require("react");
556
-
557
- // src/layout-config/local-config.ts
558
- var loadLocalConfig = (saveUrl, user, id = "latest") => new Promise((resolve, reject) => {
559
- console.log(
560
- `load local config at ${saveUrl} for user ${user.username}, id ${id}`
561
- );
562
- const data = localStorage.getItem(saveUrl);
563
- if (data) {
564
- const layout = JSON.parse(data);
565
- resolve(layout);
566
- } else {
567
- reject();
568
- }
569
- });
570
- var saveLocalConfig = (saveUrl, user, data) => new Promise((resolve, reject) => {
571
- try {
572
- localStorage.setItem(saveUrl, JSON.stringify(data));
573
- resolve(void 0);
574
- } catch {
575
- reject();
576
- }
577
- });
578
-
579
- // src/layout-config/remote-config.ts
580
- var loadRemoteConfig = (saveUrl, user, id = "latest") => new Promise((resolve, reject) => {
581
- fetch(`${saveUrl}/${user.username}/${id}`, {}).then((response) => {
582
- if (response.ok) {
583
- resolve(response.json());
584
- } else {
585
- reject(void 0);
586
- }
587
- }).catch(() => {
588
- reject(void 0);
589
- });
590
- });
591
- var saveRemoteConfig = (saveUrl, user, data) => new Promise((resolve, reject) => {
592
- fetch(`${saveUrl}/${user.username}`, {
593
- method: "POST",
594
- headers: {
595
- "Content-Type": "application/json"
596
- },
597
- body: JSON.stringify(data)
598
- }).then((response) => {
599
- if (response.ok) {
600
- resolve(void 0);
601
- } else {
602
- reject();
603
- }
604
- });
605
- });
606
-
607
- // src/layout-config/use-layout-config.ts
608
- var useLayoutConfig = ({
609
- saveLocation,
610
- saveUrl = "api/vui",
611
- user,
612
- defaultLayout
613
- }) => {
614
- const [layout, _setLayout] = (0, import_react8.useState)(defaultLayout);
615
- const usingRemote = saveLocation === "remote";
616
- const loadConfig = usingRemote ? loadRemoteConfig : loadLocalConfig;
617
- const saveConfig = usingRemote ? saveRemoteConfig : saveLocalConfig;
618
- const setLayout = (layout2) => {
619
- _setLayout(layout2);
620
- };
621
- const load = (0, import_react8.useCallback)(
622
- async (id = "latest") => {
623
- try {
624
- const layout2 = await loadConfig(saveUrl, user, id);
625
- setLayout(layout2);
626
- } catch {
627
- setLayout(defaultLayout);
628
- }
629
- },
630
- [defaultLayout, loadConfig, saveUrl, user]
631
- );
632
- (0, import_react8.useEffect)(() => {
633
- load();
634
- }, [load]);
635
- const saveData = (0, import_react8.useCallback)(
636
- (data) => {
637
- saveConfig(saveUrl, user, data);
638
- },
639
- [saveConfig, saveUrl, user]
640
- );
641
- const loadLayoutById = (0, import_react8.useCallback)(
642
- (id) => {
643
- load(id);
644
- },
645
- [load]
646
- );
647
- return [layout, saveData, loadLayoutById];
648
- };
649
-
650
- // src/shell.tsx
651
- var import_vuu_layout2 = require("@vuu-ui/vuu-layout");
652
-
653
- // src/app-header/AppHeader.tsx
654
- var import_react11 = require("react");
655
-
656
- // src/user-profile/UserProfile.tsx
657
- var import_core5 = require("@salt-ds/core");
658
- var import_salt_lab4 = require("@heswell/salt-lab");
659
- var import_icons2 = require("@salt-ds/icons");
660
-
661
- // src/user-profile/UserPanel.tsx
662
- var import_vuu_utils3 = require("@vuu-ui/vuu-utils");
663
- var import_salt_lab3 = require("@heswell/salt-lab");
664
- var import_core4 = require("@salt-ds/core");
665
- var import_icons = require("@salt-ds/icons");
666
- var import_react9 = require("react");
667
-
668
- // src/get-layout-history.ts
669
- var getLayoutHistory = async (user) => {
670
- const history = await fetch(`api/vui/${user.username}`, {}).then((response) => {
671
- return response.ok ? response.json() : null;
672
- }).catch(() => {
673
- console.log("error getting history");
674
- });
675
- return history;
676
- };
677
-
678
- // src/user-profile/UserPanel.tsx
679
- var import_jsx_runtime9 = require("react/jsx-runtime");
680
- var byLastUpdate = ({ lastUpdate: l1 }, { lastUpdate: l2 }) => {
681
- return l2 === l1 ? 0 : l2 < l1 ? -1 : 1;
682
- };
683
- var HistoryListItem = (props) => {
684
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_salt_lab3.ListItem, { ...props });
685
- };
686
- var UserPanel = (0, import_react9.forwardRef)(function UserPanel2({ loginUrl, onNavigate, user, layoutId = "latest" }, forwardedRef) {
687
- const [history, setHistory] = (0, import_react9.useState)([]);
688
- (0, import_react9.useEffect)(() => {
689
- async function getHistory() {
690
- const history2 = await getLayoutHistory(user);
691
- const sortedHistory = history2.filter((item) => item.id !== "latest").sort(byLastUpdate).map(({ id, lastUpdate }) => ({
692
- lastUpdate,
693
- id,
694
- label: `Saved at ${(0, import_vuu_utils3.formatDate)(new Date(lastUpdate), "kk:mm:ss")}`
695
- }));
696
- console.log({ sortedHistory });
697
- setHistory(sortedHistory);
698
- }
699
- getHistory();
700
- }, [user]);
701
- const handleHisorySelected = (0, import_react9.useCallback)(
702
- (evt, selected2) => {
703
- if (selected2) {
704
- onNavigate(selected2.id);
705
- }
706
- },
707
- [onNavigate]
708
- );
709
- const handleLogout = (0, import_react9.useCallback)(() => {
710
- logout(loginUrl);
711
- }, [loginUrl]);
712
- const selected = history.length === 0 ? null : layoutId === "latest" ? history[0] : history.find((i) => i.id === layoutId);
713
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "vuuUserPanel", ref: forwardedRef, children: [
714
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
715
- import_salt_lab3.List,
716
- {
717
- ListItem: HistoryListItem,
718
- className: "vuuUserPanel-history",
719
- onSelect: handleHisorySelected,
720
- selected,
721
- source: history
722
- }
723
- ),
724
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "vuuUserPanel-buttonBar", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_core4.Button, { "aria-label": "logout", onClick: handleLogout, children: [
725
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_icons.ExportIcon, {}),
726
- " Logout"
727
- ] }) })
728
- ] });
729
- });
730
-
731
- // src/user-profile/UserProfile.tsx
732
- var import_jsx_runtime10 = require("react/jsx-runtime");
733
- var UserProfile = ({
734
- layoutId,
735
- loginUrl,
736
- onNavigate,
737
- user
738
- }) => {
739
- const handleNavigate = (id) => {
740
- onNavigate(id);
741
- };
742
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_salt_lab4.DropdownBase, { className: "vuuUserProfile", placement: "bottom-end", children: [
743
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_core5.Button, { variant: "secondary", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons2.UserSolidIcon, {}) }),
744
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
745
- UserPanel,
746
- {
747
- layoutId,
748
- loginUrl,
749
- onNavigate: handleNavigate,
750
- user
751
- }
752
- )
753
- ] });
754
- };
755
-
756
- // src/theme-switch/ThemeSwitch.tsx
757
- var import_salt_lab5 = require("@heswell/salt-lab");
758
- var import_classnames4 = __toESM(require("classnames"));
759
- var import_core6 = require("@salt-ds/core");
760
- var import_react10 = require("react");
761
- var import_jsx_runtime11 = require("react/jsx-runtime");
762
- var classBase4 = "vuuThemeSwitch";
763
- var modes = ["light", "dark"];
764
- var ThemeSwitch = ({
765
- className: classNameProp,
766
- defaultMode: defaultModeProp,
767
- mode: modeProp,
768
- onChange,
769
- ...htmlAttributes
770
- }) => {
771
- const [mode, setMode] = (0, import_core6.useControlled)({
772
- controlled: modeProp,
773
- default: defaultModeProp != null ? defaultModeProp : "light",
774
- name: "ThemeSwitch",
775
- state: "mode"
776
- });
777
- const selectedIndex = modes.indexOf(mode);
778
- const handleChangeSecondary = (0, import_react10.useCallback)(
779
- (_evt, index) => {
780
- const mode2 = modes[index];
781
- setMode(mode2);
782
- onChange(mode2);
783
- },
784
- [onChange, setMode]
785
- );
786
- const className = (0, import_classnames4.default)(classBase4, classNameProp);
787
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
788
- import_salt_lab5.ToggleButtonGroup,
789
- {
790
- className,
791
- ...htmlAttributes,
792
- onChange: handleChangeSecondary,
793
- selectedIndex,
794
- children: [
795
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
796
- import_salt_lab5.ToggleButton,
797
- {
798
- "aria-label": "alert",
799
- tooltipText: "Light Theme",
800
- "data-icon": "light"
801
- }
802
- ),
803
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
804
- import_salt_lab5.ToggleButton,
805
- {
806
- "aria-label": "home",
807
- tooltipText: "Dark Theme",
808
- "data-icon": "dark"
809
- }
810
- )
811
- ]
812
- }
813
- );
814
- };
815
-
816
- // src/app-header/AppHeader.tsx
817
- var import_classnames5 = __toESM(require("classnames"));
818
- var import_jsx_runtime12 = require("react/jsx-runtime");
819
- var classBase5 = "vuuAppHeader";
820
- var AppHeader = ({
821
- className: classNameProp,
822
- layoutId,
823
- loginUrl,
824
- onNavigate,
825
- onSwitchTheme,
826
- themeMode = "light",
827
- user,
828
- ...htmlAttributes
829
- }) => {
830
- const className = (0, import_classnames5.default)(classBase5, classNameProp);
831
- const handleSwitchTheme = (0, import_react11.useCallback)(
832
- (mode) => onSwitchTheme == null ? void 0 : onSwitchTheme(mode),
833
- [onSwitchTheme]
834
- );
835
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("header", { className, ...htmlAttributes, children: [
836
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ThemeSwitch, { defaultMode: themeMode, onChange: handleSwitchTheme }),
837
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
838
- UserProfile,
839
- {
840
- layoutId,
841
- loginUrl,
842
- onNavigate,
843
- user
844
- }
845
- )
846
- ] });
847
- };
848
-
849
- // src/shell.tsx
850
- var import_vuu_utils4 = require("@vuu-ui/vuu-utils");
851
- var import_jsx_runtime13 = require("react/jsx-runtime");
852
- var { error } = (0, import_vuu_utils4.logger)("Shell");
853
- var warningLayout = {
854
- type: "View",
855
- props: {
856
- style: { height: "calc(100% - 6px)" }
857
- },
858
- children: [
859
- {
860
- props: {
861
- className: "vuuShell-warningPlaceholder"
862
- },
863
- type: "Placeholder"
864
- }
865
- ]
866
- };
867
- var Shell = ({
868
- children,
869
- className: classNameProp,
870
- defaultLayout = warningLayout,
871
- leftSidePanel,
872
- loginUrl,
873
- saveLocation = "remote",
874
- saveUrl,
875
- serverUrl,
876
- user,
877
- ...htmlAttributes
878
- }) => {
879
- const rootRef = (0, import_react12.useRef)(null);
880
- const paletteView = (0, import_react12.useRef)(null);
881
- const [open, setOpen] = (0, import_react12.useState)(false);
882
- const layoutId = (0, import_react12.useRef)("latest");
883
- const [layout, saveLayoutConfig, loadLayoutById] = useLayoutConfig({
884
- defaultLayout,
885
- saveLocation,
886
- user
887
- });
888
- const handleLayoutChange = (0, import_react12.useCallback)(
889
- (layout2) => {
890
- try {
891
- saveLayoutConfig(layout2);
892
- } catch {
893
- error == null ? void 0 : error("Failed to save layout");
894
- }
895
- },
896
- [saveLayoutConfig]
897
- );
898
- const handleSwitchTheme = (0, import_react12.useCallback)((mode) => {
899
- if (rootRef.current) {
900
- rootRef.current.dataset.mode = mode;
901
- }
902
- }, []);
903
- const handleDrawerClick = (e) => {
904
- var _a;
905
- const target = e.target;
906
- if (!((_a = paletteView.current) == null ? void 0 : _a.contains(target))) {
907
- setOpen(!open);
908
- }
909
- };
910
- const handleNavigate = (0, import_react12.useCallback)(
911
- (id) => {
912
- layoutId.current = id;
913
- loadLayoutById(id);
914
- },
915
- [loadLayoutById]
916
- );
917
- (0, import_react12.useEffect)(() => {
918
- if (serverUrl && user.token) {
919
- (0, import_vuu_data2.connectToServer)({
920
- authToken: user.token,
921
- url: serverUrl,
922
- username: user.username
923
- });
924
- }
925
- }, [serverUrl, user.token, user.username]);
926
- const getDrawers = () => {
927
- const drawers = [];
928
- if (leftSidePanel) {
929
- drawers.push(
930
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
931
- import_vuu_layout2.Drawer,
932
- {
933
- onClick: handleDrawerClick,
934
- open,
935
- position: "left",
936
- inline: true,
937
- peekaboo: true,
938
- sizeOpen: 200,
939
- toggleButton: "end",
940
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
941
- import_vuu_layout2.View,
942
- {
943
- className: "vuuShell-palette",
944
- id: "vw-app-palette",
945
- ref: paletteView,
946
- style: { height: "100%" },
947
- children: leftSidePanel
948
- },
949
- "app-palette"
950
- )
951
- },
952
- "left-panel"
953
- )
954
- );
955
- }
956
- return drawers;
957
- };
958
- const className = (0, import_classnames6.default)(
959
- "vuuShell",
960
- classNameProp,
961
- "salt-theme",
962
- "salt-density-high"
963
- );
964
- return (
965
- // ShellContext TBD
966
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(ShellContextProvider, { value: void 0, children: [
967
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_vuu_layout2.LayoutProvider, { layout, onLayoutChange: handleLayoutChange, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
968
- import_vuu_layout2.DraggableLayout,
969
- {
970
- className,
971
- "data-mode": "light",
972
- ref: rootRef,
973
- ...htmlAttributes,
974
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
975
- import_vuu_layout2.Flexbox,
976
- {
977
- className: "App",
978
- style: { flexDirection: "column", height: "100%", width: "100%" },
979
- children: [
980
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
981
- AppHeader,
982
- {
983
- layoutId: layoutId.current,
984
- loginUrl,
985
- user,
986
- onNavigate: handleNavigate,
987
- onSwitchTheme: handleSwitchTheme
988
- }
989
- ),
990
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_vuu_layout2.DockLayout, { style: { flex: 1 }, children: getDrawers().concat(
991
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
992
- import_vuu_layout2.DraggableLayout,
993
- {
994
- dropTarget: true,
995
- style: { width: "100%", height: "100%" }
996
- },
997
- "main-content"
998
- )
999
- ) })
1000
- ]
1001
- }
1002
- )
1003
- }
1004
- ) }),
1005
- children
1006
- ] })
1007
- );
1008
- };
1009
-
1010
- // src/theme-provider/ThemeProvider.tsx
1011
- var import_react13 = require("react");
1012
- var import_classnames7 = __toESM(require("classnames"));
1013
- var import_jsx_runtime14 = require("react/jsx-runtime");
1014
- var DEFAULT_DENSITY2 = "medium";
1015
- var DEFAULT_THEME = "salt-theme";
1016
- var DEFAULT_THEME_MODE = "light";
1017
- var ThemeContext = (0, import_react13.createContext)({
1018
- density: "high",
1019
- theme: "salt-theme",
1020
- themeMode: "light"
1021
- });
1022
- var createThemedChildren = (children, theme, themeMode, density) => {
1023
- var _a;
1024
- if ((0, import_react13.isValidElement)(children)) {
1025
- return (0, import_react13.cloneElement)(children, {
1026
- className: (0, import_classnames7.default)(
1027
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
1028
- (_a = children.props) == null ? void 0 : _a.className,
1029
- theme,
1030
- `salt-density-${density}`
1031
- ),
1032
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1033
- // @ts-expect-error
1034
- "data-mode": themeMode
1035
- });
1036
- } else {
1037
- console.warn(
1038
- `
1
+ "use strict";var pt=Object.create;var W=Object.defineProperty;var ft=Object.getOwnPropertyDescriptor;var gt=Object.getOwnPropertyNames;var ht=Object.getPrototypeOf,yt=Object.prototype.hasOwnProperty;var vt=(e,t)=>{for(var o in t)W(e,o,{get:t[o],enumerable:!0})},Se=(e,t,o,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of gt(t))!yt.call(e,n)&&n!==o&&W(e,n,{get:()=>t[n],enumerable:!(r=ft(t,n))||r.enumerable});return e};var w=(e,t,o)=>(o=e!=null?pt(ht(e)):{},Se(t||!e||!e.__esModule?W(o,"default",{value:e,enumerable:!0}):o,e)),St=e=>Se(W({},"__esModule",{value:!0}),e);var $t={};vt($t,{ConnectionStatusIcon:()=>Tt,DEFAULT_DENSITY:()=>it,DEFAULT_THEME:()=>lt,DEFAULT_THEME_MODE:()=>ut,DensitySwitch:()=>wt,Feature:()=>ie,LoginPanel:()=>bt,SessionEditingForm:()=>Nt,Shell:()=>At,ShellContextProvider:()=>fe,ThemeContext:()=>ye,ThemeProvider:()=>ct,ThemeSwitch:()=>ge,getAuthDetailsFromCookies:()=>Mt,logout:()=>ce,redirectToLogin:()=>He,useShellContext:()=>Ft});module.exports=St($t);var A=w(require("react")),Te=w(require("classnames"));var k=require("react/jsx-runtime"),Tt=({connectionStatus:e,className:t,element:o="span",...r})=>{let[n,a]=(0,A.useState)("vuuConnectingStatus");(0,A.useEffect)(()=>{switch(e){case"connected":case"reconnected":a("vuuActiveStatus");break;case"connecting":a("vuuConnectingStatus");break;case"disconnected":a("vuuDisconnectedStatus");break;default:break}},[e]);let l=A.default.createElement(o,{...r,className:(0,Te.default)("vuuStatus vuuIcon",n,t)});return(0,k.jsx)(k.Fragment,{children:(0,k.jsxs)("div",{className:"vuuStatus-container salt-theme",children:[l,(0,k.jsxs)("div",{className:"vuuStatus-text",children:["Status: ",e.toUpperCase()]})]})})};var xe=require("@heswell/salt-lab"),Ce=require("react"),Le=w(require("classnames")),we=require("react/jsx-runtime"),xt="vuuDensitySwitch",Ct=["high","medium","low","touch"],Lt="high",wt=({className:e,defaultDensity:t=Lt,onDensityChange:o})=>{let r=(0,Ce.useCallback)((a,l)=>{o(l)},[o]),n=(0,Le.default)(xt,e);return(0,we.jsx)(xe.Dropdown,{className:n,source:Ct,defaultSelected:t,onSelectionChange:r})};var N=w(require("react")),Me=require("@vuu-ui/vuu-layout");var De=w(require("react")),U=require("react/jsx-runtime"),Q=class extends De.default.Component{constructor(t){super(t),this.state={errorMessage:null}}static getDerivedStateFromError(t){return{errorMessage:t.message}}componentDidCatch(t,o){console.log(t,o)}render(){return this.state.errorMessage?(0,U.jsxs)(U.Fragment,{children:[(0,U.jsx)("h1",{children:"Something went wrong."}),(0,U.jsx)("p",{children:this.state.errorMessage})]}):this.props.children}};var be=require("react/jsx-runtime"),Ee=()=>(0,be.jsx)("div",{className:"hwLoader",children:"loading"});var q=require("react/jsx-runtime"),X=new Map,Dt=e=>((0,N.useEffect)(()=>()=>{X.delete(e)},[e]),X.has(e)||X.set(e,N.default.lazy(()=>import(e))),X.get(e));function Et({url:e,css:t,params:o,...r}){console.log("Feature render",{css:t,url:e,props:r}),(0,N.useEffect)(()=>(console.log("%cFeature mount","color: green;"),()=>{console.log("%cFeature unmount","color:red;")}),[]),t&&import(t).then(a=>{console.log("%cInject Styles","color: blue;font-weight: bold"),document.adoptedStyleSheets=[...document.adoptedStyleSheets,a.default]});let n=Dt(e);return(0,q.jsx)(Q,{children:(0,q.jsx)(N.Suspense,{fallback:(0,q.jsx)(Ee,{}),children:(0,q.jsx)(n,{...r,...o})})})}var ie=N.default.memo(Et);ie.displayName="Feature";(0,Me.registerComponent)("Feature",ie,"view");var le=require("react"),Ne=require("@salt-ds/core"),O=require("@heswell/salt-lab");var H=require("react/jsx-runtime"),Pe="vuuLoginPanel",bt=({onSubmit:e})=>{let[t,o]=(0,le.useState)(""),[r,n]=(0,le.useState)(""),a=()=>{e(t,r)},l=(m,u)=>{o(u)},c=(m,u)=>{n(u)},i=t.trim()!==""&&r.trim()!=="";return(0,H.jsxs)("div",{className:Pe,children:[(0,H.jsx)(O.FormField,{label:"Username",style:{width:200},children:(0,H.jsx)(O.Input,{value:t,id:"text-username",onChange:l})}),(0,H.jsx)(O.FormField,{label:"Password",style:{width:200},children:(0,H.jsx)(O.Input,{type:"password",value:r,id:"text-password",onChange:c})}),(0,H.jsx)(Ne.Button,{className:`${Pe}-login`,disabled:!i,onClick:a,variant:"cta",children:"Login"})]})};var ue=require("@vuu-ui/vuu-utils"),Mt=()=>{let e=(0,ue.getCookieValue)("vuu-username"),t=(0,ue.getCookieValue)("vuu-auth-token");return[e,t]},He=(e="login.html")=>{window.location.href=e},ce=e=>{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",He(e)};var g=require("react"),me=w(require("classnames")),ke=require("@salt-ds/core"),de=require("@salt-ds/core"),Z=require("@vuu-ui/vuu-data"),I=require("@vuu-ui/vuu-utils");var T=require("react/jsx-runtime"),b="vuuSessionEditingForm",Re=(e,t)=>{let o=e.find(r=>r.name===t);if(o)return o;throw Error(`SessionEditingForm, no field '${t}' found`)},Fe=e=>{let{dataset:{field:t},value:o}=e.target;if(t===void 0)throw Error("SessionEditingForm, form field has no field name");return[t,o]},M={uninitialised:0,unchanged:1,changed:2,invalid:3};function Ve(e,t,o=!1){switch(t){case"int":case"long":{let r=parseInt(e,10);if((0,I.isValidNumber)(r))return r;if(o)throw Error("SessionEditingForm getTypedValue");return}case"double":{let r=parseFloat(e);return(0,I.isValidNumber)(r)?r:void 0}case"boolean":return e==="true";default:return e}}var Pt=(e,t)=>{if(e)return e;if(t)return new Z.RemoteDataSource({bufferSize:0,table:t.table,columns:t.columns.map(o=>o.name)});throw Error("SessionEditingForm: either a DataSource or a TableSchema must be provided")},Nt=({className:e,config:{fields:t,key:o},dataSource:r,id:n,onClose:a,schema:l,...c})=>{let[i,m]=(0,g.useState)(),[u,h]=(0,g.useState)(""),d=(0,g.useRef)(null),p=(0,g.useRef)(),y=(0,g.useRef)(M.uninitialised),L=(0,g.useMemo)(()=>{let s=D=>{if(S){let E={};for(let B of L.columns)E[B]=D[S[B]];y.current===M.uninitialised&&(y.current=M.unchanged,p.current=E),m(E)}},f=Pt(r,l),S=(0,I.buildColumnMap)(f.columns);return f.subscribe({range:{from:0,to:5}},D=>{D.type==="viewport-update"&&D.rows&&(y.current===M.uninitialised?s(D.rows[0]):console.log("what do we do with server updates"))}),f},[r,l]),J=(0,ke.useIdMemo)(n),Y=(0,g.useCallback)(s=>{let[f,S]=Fe(s),{type:D}=Re(t,f),E=Ve(S,D);m((B={})=>{let ve={...B,[f]:E},dt=(0,I.shallowEquals)(ve,p.current);return y.current=dt?M.unchanged:E!==void 0?M.changed:M.invalid,ve})},[t]),oe=(0,g.useCallback)(s=>{let[f,S]=Fe(s),{type:D}=Re(t,f);console.log("BLUR",{keyField:o});let E=i==null?void 0:i[o],B=Ve(S,D,!0);typeof E=="string"&&L.menuRpcCall({rowKey:E,field:f,value:B,type:"VP_EDIT_CELL_RPC"})},[L,t,o,i]),_=(0,g.useCallback)(async()=>{let s=await L.menuRpcCall({type:"VP_EDIT_SUBMIT_FORM_RPC"});(0,Z.isErrorResponse)(s)&&h(s.error)},[L]),re=(0,g.useCallback)(s=>{s.key==="Enter"&&y.current===M.changed&&_()},[_]),ne=(0,g.useCallback)(()=>{a()},[a]),se=s=>{var S;let f=String((S=i==null?void 0:i[s.name])!=null?S:"");return s.readonly||s.name===o?(0,T.jsx)("div",{className:`${b}-fieldValue vuuReadOnly`,children:f}):(0,T.jsx)("input",{className:`${b}-fieldValue`,"data-field":s.name,onBlur:oe,onChange:Y,type:"text",value:f,id:`${J}-input-${s.name}`})};(0,g.useEffect)(()=>{if(d.current){let s=d.current.querySelector("input");s&&setTimeout(()=>{s.focus(),console.log("select item"),s.select()},100)}},[]);let ae=y.current===M.changed;return(0,T.jsxs)("div",{...c,className:(0,me.default)(b,e),children:[u?(0,T.jsx)("div",{className:`${b}-errorBanner`,"data-icon":"error",title:u,children:"Error, edit(s) not saved"}):void 0,(0,T.jsx)("div",{className:`${b}-content`,ref:d,onKeyDown:re,children:t.map(s=>{var f;return(0,T.jsxs)("div",{className:`${b}-field`,children:[(0,T.jsx)("label",{className:(0,me.default)(`${b}-fieldLabel`,{[`${b}-required`]:s.required}),htmlFor:`${J}-input-${s.name}`,children:(f=s==null?void 0:s.label)!=null?f:s.description}),se(s)]},s.name)})}),(0,T.jsxs)("div",{className:`${b}-buttonbar salt-theme salt-density-high`,children:[(0,T.jsx)(de.Button,{type:"submit",variant:"cta",disabled:!ae,onClick:_,children:"Submit"}),(0,T.jsx)(de.Button,{variant:"secondary",onClick:ne,children:"Cancel"})]})]})};var rt=require("@vuu-ui/vuu-data"),nt=w(require("classnames")),x=require("react");var ee=require("react"),j=require("react/jsx-runtime"),Ht={},pe=(0,ee.createContext)(Ht),Rt=({children:e,context:t,inheritedContext:o})=>{let r={...o,...t};return(0,j.jsx)(pe.Provider,{value:r,children:e})},fe=({children:e,value:t})=>(0,j.jsx)(pe.Consumer,{children:o=>(0,j.jsx)(Rt,{context:t,inheritedContext:o,children:e})}),Ft=()=>(0,ee.useContext)(pe);var R=require("react");var Ue=(e,t,o="latest")=>new Promise((r,n)=>{console.log(`load local config at ${e} for user ${t.username}, id ${o}`);let a=localStorage.getItem(e);if(a){let l=JSON.parse(a);r(l)}else n()}),Ie=(e,t,o)=>new Promise((r,n)=>{try{localStorage.setItem(e,JSON.stringify(o)),r(void 0)}catch{n()}});var Be=(e,t,o="latest")=>new Promise((r,n)=>{fetch(`${e}/${t.username}/${o}`,{}).then(a=>{a.ok?r(a.json()):n(void 0)}).catch(()=>{n(void 0)})}),Ae=(e,t,o)=>new Promise((r,n)=>{fetch(`${e}/${t.username}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o)}).then(a=>{a.ok?r(void 0):n()})});var Oe=({saveLocation:e,saveUrl:t="api/vui",user:o,defaultLayout:r})=>{let[n,a]=(0,R.useState)(r),l=e==="remote",c=l?Be:Ue,i=l?Ae:Ie,m=p=>{a(p)},u=(0,R.useCallback)(async(p="latest")=>{try{let y=await c(t,o,p);m(y)}catch{m(r)}},[r,c,t,o]);(0,R.useEffect)(()=>{u()},[u]);let h=(0,R.useCallback)(p=>{i(t,o,p)},[i,t,o]),d=(0,R.useCallback)(p=>{u(p)},[u]);return[n,h,d]};var v=require("@vuu-ui/vuu-layout");var et=require("react");var ze=require("@salt-ds/core"),Ke=require("@heswell/salt-lab"),Ye=require("@salt-ds/icons");var Je=require("@vuu-ui/vuu-utils"),te=require("@heswell/salt-lab"),_e=require("@salt-ds/core"),qe=require("@salt-ds/icons"),P=require("react");var $e=async e=>await fetch(`api/vui/${e.username}`,{}).then(o=>o.ok?o.json():null).catch(()=>{console.log("error getting history")});var F=require("react/jsx-runtime"),Vt=({lastUpdate:e},{lastUpdate:t})=>t===e?0:t<e?-1:1,kt=e=>(0,F.jsx)(te.ListItem,{...e}),Ge=(0,P.forwardRef)(function({loginUrl:t,onNavigate:o,user:r,layoutId:n="latest"},a){let[l,c]=(0,P.useState)([]);(0,P.useEffect)(()=>{async function h(){let p=(await $e(r)).filter(y=>y.id!=="latest").sort(Vt).map(({id:y,lastUpdate:L})=>({lastUpdate:L,id:y,label:`Saved at ${(0,Je.formatDate)(new Date(L),"kk:mm:ss")}`}));console.log({sortedHistory:p}),c(p)}h()},[r]);let i=(0,P.useCallback)((h,d)=>{d&&o(d.id)},[o]),m=(0,P.useCallback)(()=>{ce(t)},[t]),u=l.length===0?null:n==="latest"?l[0]:l.find(h=>h.id===n);return(0,F.jsxs)("div",{className:"vuuUserPanel",ref:a,children:[(0,F.jsx)(te.List,{ListItem:kt,className:"vuuUserPanel-history",onSelect:i,selected:u,source:l}),(0,F.jsx)("div",{className:"vuuUserPanel-buttonBar",children:(0,F.jsxs)(_e.Button,{"aria-label":"logout",onClick:m,children:[(0,F.jsx)(qe.ExportIcon,{})," Logout"]})})]})});var $=require("react/jsx-runtime"),We=({layoutId:e,loginUrl:t,onNavigate:o,user:r})=>(0,$.jsxs)(Ke.DropdownBase,{className:"vuuUserProfile",placement:"bottom-end",children:[(0,$.jsx)(ze.Button,{variant:"secondary",children:(0,$.jsx)(Ye.UserSolidIcon,{})}),(0,$.jsx)(Ge,{layoutId:e,loginUrl:t,onNavigate:a=>{o(a)},user:r})]});var G=require("@heswell/salt-lab"),Xe=w(require("classnames")),Ze=require("@salt-ds/core"),je=require("react");var z=require("react/jsx-runtime"),Ut="vuuThemeSwitch",Qe=["light","dark"],ge=({className:e,defaultMode:t,mode:o,onChange:r,...n})=>{let[a,l]=(0,Ze.useControlled)({controlled:o,default:t!=null?t:"light",name:"ThemeSwitch",state:"mode"}),c=Qe.indexOf(a),i=(0,je.useCallback)((u,h)=>{let d=Qe[h];l(d),r(d)},[r,l]),m=(0,Xe.default)(Ut,e);return(0,z.jsxs)(G.ToggleButtonGroup,{className:m,...n,onChange:i,selectedIndex:c,children:[(0,z.jsx)(G.ToggleButton,{"aria-label":"alert",tooltipText:"Light Theme","data-icon":"light"}),(0,z.jsx)(G.ToggleButton,{"aria-label":"home",tooltipText:"Dark Theme","data-icon":"dark"})]})};var tt=w(require("classnames"));var K=require("react/jsx-runtime"),It="vuuAppHeader",ot=({className:e,layoutId:t,loginUrl:o,onNavigate:r,onSwitchTheme:n,themeMode:a="light",user:l,...c})=>{let i=(0,tt.default)(It,e),m=(0,et.useCallback)(u=>n==null?void 0:n(u),[n]);return(0,K.jsxs)("header",{className:i,...c,children:[(0,K.jsx)(ge,{defaultMode:a,onChange:m}),(0,K.jsx)(We,{layoutId:t,loginUrl:o,onNavigate:r,user:l})]})};var st=require("@vuu-ui/vuu-utils");var C=require("react/jsx-runtime"),{error:he}=(0,st.logger)("Shell"),Bt={type:"View",props:{style:{height:"calc(100% - 6px)"}},children:[{props:{className:"vuuShell-warningPlaceholder"},type:"Placeholder"}]},At=({children:e,className:t,defaultLayout:o=Bt,leftSidePanel:r,loginUrl:n,saveLocation:a="remote",saveUrl:l,serverUrl:c,user:i,...m})=>{let u=(0,x.useRef)(null),h=(0,x.useRef)(null),[d,p]=(0,x.useState)(!1),y=(0,x.useRef)("latest"),[L,J,Y]=Oe({defaultLayout:o,saveLocation:a,user:i}),oe=(0,x.useCallback)(s=>{try{J(s)}catch{he==null||he("Failed to save layout")}},[J]),_=(0,x.useCallback)(s=>{u.current&&(u.current.dataset.mode=s)},[]),re=s=>{var S;let f=s.target;(S=h.current)!=null&&S.contains(f)||p(!d)},ne=(0,x.useCallback)(s=>{y.current=s,Y(s)},[Y]);(0,x.useEffect)(()=>{c&&i.token&&(0,rt.connectToServer)({authToken:i.token,url:c,username:i.username})},[c,i.token,i.username]);let se=()=>{let s=[];return r&&s.push((0,C.jsx)(v.Drawer,{onClick:re,open:d,position:"left",inline:!0,peekaboo:!0,sizeOpen:200,toggleButton:"end",children:(0,C.jsx)(v.View,{className:"vuuShell-palette",id:"vw-app-palette",ref:h,style:{height:"100%"},children:r},"app-palette")},"left-panel")),s},ae=(0,nt.default)("vuuShell",t,"salt-theme","salt-density-high");return(0,C.jsxs)(fe,{value:void 0,children:[(0,C.jsx)(v.LayoutProvider,{layout:L,onLayoutChange:oe,children:(0,C.jsx)(v.DraggableLayout,{className:ae,"data-mode":"light",ref:u,...m,children:(0,C.jsxs)(v.Flexbox,{className:"App",style:{flexDirection:"column",height:"100%",width:"100%"},children:[(0,C.jsx)(ot,{layoutId:y.current,loginUrl:n,user:i,onNavigate:ne,onSwitchTheme:_}),(0,C.jsx)(v.DockLayout,{style:{flex:1},children:se().concat((0,C.jsx)(v.DraggableLayout,{dropTarget:!0,style:{width:"100%",height:"100%"}},"main-content"))})]})})}),e]})};var V=require("react"),at=w(require("classnames")),mt=require("react/jsx-runtime"),it="medium",lt="salt-theme",ut="light",ye=(0,V.createContext)({density:"high",theme:"salt-theme",themeMode:"light"}),Ot=(e,t,o,r)=>{var n;return(0,V.isValidElement)(e)?(0,V.cloneElement)(e,{className:(0,at.default)((n=e.props)==null?void 0:n.className,t,`salt-density-${r}`),"data-mode":o}):(console.warn(`
1039
2
  ThemeProvider can only apply CSS classes for theming to a single nested child element of the ThemeProvider.
1040
- Wrap elements with a single container`
1041
- );
1042
- return children;
1043
- }
1044
- };
1045
- var ThemeProvider = ({
1046
- children,
1047
- theme: themeProp,
1048
- themeMode: themeModeProp,
1049
- density: densityProp
1050
- }) => {
1051
- var _a, _b, _c;
1052
- const {
1053
- density: inheritedDensity,
1054
- themeMode: inheritedThemeMode,
1055
- theme: inheritedTheme
1056
- } = (0, import_react13.useContext)(ThemeContext);
1057
- const density = (_a = densityProp != null ? densityProp : inheritedDensity) != null ? _a : DEFAULT_DENSITY2;
1058
- const themeMode = (_b = themeModeProp != null ? themeModeProp : inheritedThemeMode) != null ? _b : DEFAULT_THEME_MODE;
1059
- const theme = (_c = themeProp != null ? themeProp : inheritedTheme) != null ? _c : DEFAULT_THEME;
1060
- const themedChildren = createThemedChildren(
1061
- children,
1062
- theme,
1063
- themeMode,
1064
- density
1065
- );
1066
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ThemeContext.Provider, { value: { themeMode, density, theme }, children: themedChildren });
1067
- };
1068
- ThemeProvider.displayName = "ThemeProvider";
3
+ Wrap elements with a single container`),e)},ct=({children:e,theme:t,themeMode:o,density:r})=>{var h,d,p;let{density:n,themeMode:a,theme:l}=(0,V.useContext)(ye),c=(h=r!=null?r:n)!=null?h:it,i=(d=o!=null?o:a)!=null?d:ut,m=(p=t!=null?t:l)!=null?p:lt,u=Ot(e,m,i,c);return(0,mt.jsx)(ye.Provider,{value:{themeMode:i,density:c,theme:m},children:u})};ct.displayName="ThemeProvider";
1069
4
  //# sourceMappingURL=index.js.map