@arcanejs/toolkit 0.0.2 → 0.1.0

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.
Files changed (59) hide show
  1. package/dist/backend/components/base.d.mts +2 -0
  2. package/dist/backend/components/base.d.ts +2 -0
  3. package/dist/backend/components/base.js +189 -0
  4. package/dist/backend/components/base.mjs +10 -0
  5. package/dist/backend/components/button.d.mts +30 -0
  6. package/dist/backend/components/button.d.ts +30 -0
  7. package/dist/backend/components/button.js +168 -0
  8. package/dist/backend/components/button.mjs +7 -0
  9. package/dist/backend/components/group.d.mts +51 -0
  10. package/dist/backend/components/group.d.ts +51 -0
  11. package/dist/backend/components/group.js +287 -0
  12. package/dist/backend/components/group.mjs +9 -0
  13. package/dist/backend/components/label.d.mts +21 -0
  14. package/dist/backend/components/label.d.ts +21 -0
  15. package/dist/backend/components/label.js +105 -0
  16. package/dist/backend/components/label.mjs +7 -0
  17. package/dist/backend/components/rect.d.mts +20 -0
  18. package/dist/backend/components/rect.d.ts +20 -0
  19. package/dist/backend/components/rect.js +105 -0
  20. package/dist/backend/components/rect.mjs +7 -0
  21. package/dist/backend/components/slider-button.d.mts +31 -0
  22. package/dist/backend/components/slider-button.d.ts +31 -0
  23. package/dist/backend/components/slider-button.js +161 -0
  24. package/dist/backend/components/slider-button.mjs +7 -0
  25. package/dist/backend/components/switch.d.mts +24 -0
  26. package/dist/backend/components/switch.d.ts +24 -0
  27. package/dist/backend/components/switch.js +144 -0
  28. package/dist/backend/components/switch.mjs +7 -0
  29. package/dist/backend/components/tabs.d.mts +28 -0
  30. package/dist/backend/components/tabs.d.ts +28 -0
  31. package/dist/backend/components/tabs.js +209 -0
  32. package/dist/backend/components/tabs.mjs +9 -0
  33. package/dist/backend/components/text-input.d.mts +26 -0
  34. package/dist/backend/components/text-input.d.ts +26 -0
  35. package/dist/backend/components/text-input.js +146 -0
  36. package/dist/backend/components/text-input.mjs +7 -0
  37. package/dist/backend/components/timeline.d.mts +17 -0
  38. package/dist/backend/components/timeline.d.ts +17 -0
  39. package/dist/backend/components/timeline.js +109 -0
  40. package/dist/backend/components/timeline.mjs +7 -0
  41. package/dist/base-BJAPu0O1.d.mts +234 -0
  42. package/dist/base-BJAPu0O1.d.ts +234 -0
  43. package/dist/chunk-37VNFO5S.mjs +42 -0
  44. package/dist/chunk-3ZBM7Q4A.mjs +55 -0
  45. package/dist/chunk-6LL3X7ZZ.mjs +44 -0
  46. package/dist/chunk-DBW4OPGN.mjs +33 -0
  47. package/dist/chunk-DP3QFYSS.mjs +66 -0
  48. package/dist/chunk-GQZA5K4M.mjs +29 -0
  49. package/dist/chunk-HF77PS7J.mjs +171 -0
  50. package/dist/chunk-HVFTRNLQ.mjs +59 -0
  51. package/dist/chunk-P6X5GIDT.mjs +29 -0
  52. package/dist/chunk-S5DQIYC2.mjs +107 -0
  53. package/dist/frontend.js +26321 -0
  54. package/dist/frontend.js.map +7 -0
  55. package/dist/index.d.mts +75 -1
  56. package/dist/index.d.ts +75 -1
  57. package/dist/index.js +852 -1
  58. package/dist/index.mjs +288 -2
  59. package/package.json +86 -6
package/dist/index.js CHANGED
@@ -1,4 +1,855 @@
1
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);
2
29
 
3
30
  // src/index.ts
4
- console.log("hello world");
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ Button: () => Button,
34
+ Group: () => Group,
35
+ GroupHeader: () => GroupHeader,
36
+ Label: () => Label,
37
+ Rect: () => Rect,
38
+ SliderButton: () => SliderButton,
39
+ Switch: () => Switch,
40
+ Tab: () => Tab,
41
+ Tabs: () => Tabs,
42
+ TextInput: () => TextInput,
43
+ Timeline: () => Timeline,
44
+ Toolkit: () => Toolkit
45
+ });
46
+ module.exports = __toCommonJS(src_exports);
47
+
48
+ // src/backend/toolkit.ts
49
+ var import_lodash = __toESM(require("lodash"));
50
+ var import_diff = require("@arcanejs/diff/diff");
51
+
52
+ // src/backend/options.ts
53
+ var DEFAULT_LIGHT_DESK_OPTIONS = {
54
+ path: "/"
55
+ };
56
+
57
+ // src/backend/server.ts
58
+ var fs = __toESM(require("fs"));
59
+ var path = __toESM(require("path"));
60
+
61
+ // src/shared/static.ts
62
+ var FONTS = {
63
+ materialSymbolsOutlined: "material-symbols-outlined.woff2"
64
+ };
65
+
66
+ // src/backend/server.ts
67
+ var parentDir = path.basename(__dirname);
68
+ var DIST_DIR = (() => {
69
+ switch (parentDir) {
70
+ case "backend":
71
+ return path.resolve(__dirname, "../../dist");
72
+ case "dist":
73
+ return __dirname;
74
+ default:
75
+ throw new Error(`Server running from unknown location: ${__dirname}`);
76
+ }
77
+ })();
78
+ var STATIC_FILES = {
79
+ "/frontend.js": {
80
+ path: path.join(DIST_DIR, "frontend.js"),
81
+ contentType: "text/javascript"
82
+ },
83
+ "/frontend.js.map": {
84
+ path: path.join(DIST_DIR, "frontend.js.map"),
85
+ contentType: "text/plain"
86
+ },
87
+ [`/${FONTS.materialSymbolsOutlined}`]: {
88
+ path: require.resolve("material-symbols/material-symbols-outlined.woff2"),
89
+ contentType: "font/woff2"
90
+ }
91
+ };
92
+ console.log("STATIC_FILES", STATIC_FILES);
93
+ var Server = class {
94
+ constructor(options, onNewConnection, onClosedConnection, onMessage) {
95
+ this.options = options;
96
+ this.onNewConnection = onNewConnection;
97
+ this.onClosedConnection = onClosedConnection;
98
+ this.onMessage = onMessage;
99
+ }
100
+ handleHttpRequest = async (req, res) => {
101
+ console.log("handleHttpRequest", req.url);
102
+ if (req.url === this.options.path) {
103
+ const content = `
104
+ <html>
105
+ <head>
106
+ <title>Light Desk</title>
107
+ <meta name="viewport" content="width=device-width, initial-scale=1">
108
+ </head>
109
+ <body>
110
+ <div id="root"></div>
111
+ <script type="text/javascript" src="${this.options.path}frontend.js"></script>
112
+ </body>
113
+ </html>`;
114
+ res.writeHead(200, { "Content-Type": "text/html" });
115
+ res.end(content, "utf-8");
116
+ return;
117
+ }
118
+ if (req.url && req.url.startsWith(this.options.path)) {
119
+ const relativePath = req.url.substr(this.options.path.length - 1);
120
+ const f = STATIC_FILES[relativePath];
121
+ if (f) {
122
+ return fs.promises.stat(f.path).then(
123
+ () => {
124
+ this.sendStaticFile(f.path, res, f.contentType);
125
+ },
126
+ (err) => {
127
+ console.error(err);
128
+ res.writeHead(500, { "Content-Type": "text/plain" });
129
+ res.end("Expected static file not found", "utf-8");
130
+ }
131
+ );
132
+ }
133
+ }
134
+ res.writeHead(404, { "Content-Type": "text/plain" });
135
+ res.end("not found", "utf-8");
136
+ };
137
+ sendStaticFile = (file, response, contentType) => {
138
+ fs.readFile(file, function(error, content) {
139
+ if (error) {
140
+ if (error.code === "ENOENT") {
141
+ response.writeHead(404, { "Content-Type": "text/plain" });
142
+ response.end("file not found", "utf-8");
143
+ } else {
144
+ response.writeHead(500, { "Content-Type": "text/plain" });
145
+ response.end("Error", "utf-8");
146
+ console.error(error);
147
+ }
148
+ } else {
149
+ response.writeHead(200, { "Content-Type": contentType });
150
+ response.end(content, "utf-8");
151
+ }
152
+ });
153
+ };
154
+ handleWsConnection = (ws) => {
155
+ const connection = {
156
+ sendMessage: (msg) => ws.send(JSON.stringify(msg))
157
+ };
158
+ this.onNewConnection(connection);
159
+ console.log("new connection");
160
+ ws.on(
161
+ "message",
162
+ (msg) => this.onMessage(connection, JSON.parse(msg.toString()))
163
+ );
164
+ ws.on("close", () => this.onClosedConnection(connection));
165
+ };
166
+ };
167
+
168
+ // src/backend/util/id-map.ts
169
+ var IDMap = class {
170
+ idMap = /* @__PURE__ */ new WeakMap();
171
+ nextId = 0;
172
+ getId(object) {
173
+ let i = this.idMap.get(object);
174
+ if (i === void 0) {
175
+ i = this.nextId++;
176
+ this.idMap.set(object, i);
177
+ }
178
+ return i;
179
+ }
180
+ };
181
+
182
+ // src/backend/toolkit.ts
183
+ var import_ws = require("ws");
184
+ var import_http = require("http");
185
+ console.log(import_diff.diffJson);
186
+ var Toolkit = class {
187
+ options;
188
+ /**
189
+ * Mapping from components to unique IDs that identify them
190
+ */
191
+ componentIDMap = new IDMap();
192
+ connections = /* @__PURE__ */ new Map();
193
+ rootGroup = null;
194
+ constructor(options = {}) {
195
+ this.options = {
196
+ ...DEFAULT_LIGHT_DESK_OPTIONS,
197
+ ...options
198
+ };
199
+ if (!this.options.path.endsWith("/") || !this.options.path.startsWith("/")) {
200
+ throw new Error(
201
+ `path must start and end with "/", set to: ${this.options.path}`
202
+ );
203
+ }
204
+ }
205
+ start = (opts) => {
206
+ const server = new Server(
207
+ this.options,
208
+ this.onNewConnection,
209
+ this.onClosedConnection,
210
+ this.onMessage
211
+ );
212
+ if (opts.mode === "automatic") {
213
+ const httpServer = (0, import_http.createServer)(server.handleHttpRequest);
214
+ const wss = new import_ws.WebSocketServer({
215
+ server: httpServer
216
+ });
217
+ wss.on("connection", server.handleWsConnection);
218
+ httpServer.listen(opts.port, () => {
219
+ console.log(
220
+ `Light Desk Started: http://localhost:${opts.port}${this.options.path}`
221
+ );
222
+ });
223
+ } else if (opts.mode === "express") {
224
+ const wss = new import_ws.WebSocketServer({
225
+ server: opts.server
226
+ });
227
+ wss.on("connection", server.handleWsConnection);
228
+ opts.express.get(`${this.options.path}*`, server.handleHttpRequest);
229
+ } else if (opts.mode === "manual") {
230
+ opts.setup(server);
231
+ } else {
232
+ throw new Error(`Unsupported mode`);
233
+ }
234
+ };
235
+ setRoot = (group) => {
236
+ if (this.rootGroup) {
237
+ throw new Error("Can only set root group once");
238
+ }
239
+ this.rootGroup = group;
240
+ this.rootGroup.setParent(this);
241
+ };
242
+ updateTree = import_lodash.default.throttle(
243
+ () => {
244
+ setImmediate(() => {
245
+ if (!this.rootGroup) return;
246
+ const root = this.rootGroup.getProtoInfo(this.componentIDMap);
247
+ for (const [connection, meta] of this.connections.entries()) {
248
+ connection.sendMessage({
249
+ type: "tree-diff",
250
+ diff: (0, import_diff.diffJson)(meta.lastTreeSent, root)
251
+ });
252
+ meta.lastTreeSent = root;
253
+ }
254
+ });
255
+ },
256
+ 10,
257
+ { leading: true, trailing: true }
258
+ );
259
+ removeChild = (component) => {
260
+ if (this.rootGroup === component) {
261
+ this.rootGroup = null;
262
+ component.setParent(null);
263
+ }
264
+ };
265
+ onNewConnection = (connection) => {
266
+ const lastTreeSent = this.rootGroup?.getProtoInfo(this.componentIDMap) ?? void 0;
267
+ this.connections.set(connection, { lastTreeSent });
268
+ if (lastTreeSent) {
269
+ connection.sendMessage({
270
+ type: "tree-full",
271
+ root: lastTreeSent
272
+ });
273
+ }
274
+ };
275
+ onClosedConnection = (connection) => {
276
+ console.log("removing connection");
277
+ this.connections.delete(connection);
278
+ };
279
+ onMessage = (_connection, message) => {
280
+ console.log("got message", message);
281
+ switch (message.type) {
282
+ case "component-message":
283
+ if (this.rootGroup)
284
+ this.rootGroup.routeMessage(this.componentIDMap, message);
285
+ break;
286
+ }
287
+ };
288
+ };
289
+
290
+ // src/backend/components/base.ts
291
+ var Base = class {
292
+ /** @hidden */
293
+ parent = null;
294
+ /** @hidden */
295
+ defaultProps;
296
+ /** @hidden */
297
+ _props;
298
+ constructor(defaultProps, props) {
299
+ this.defaultProps = defaultProps;
300
+ this._props = Object.freeze({
301
+ ...defaultProps,
302
+ ...props
303
+ });
304
+ }
305
+ get props() {
306
+ return this._props;
307
+ }
308
+ set props(props) {
309
+ this.setProps(props);
310
+ }
311
+ setProps = (props) => {
312
+ this._props = Object.freeze({
313
+ ...this.defaultProps,
314
+ ...props
315
+ });
316
+ this.updateTree();
317
+ };
318
+ updateProps = (updates) => {
319
+ this._props = Object.freeze({
320
+ ...this._props,
321
+ ...updates
322
+ });
323
+ this.updateTree();
324
+ };
325
+ /** @hidden */
326
+ setParent(parent) {
327
+ if (this.parent && this.parent !== parent) {
328
+ this.parent.removeChild(this);
329
+ }
330
+ this.parent = parent;
331
+ }
332
+ /** @hidden */
333
+ updateTree() {
334
+ if (this.parent) this.parent.updateTree();
335
+ }
336
+ /** @hidden */
337
+ handleMessage(message) {
338
+ console.log("Component Received Message:", message);
339
+ }
340
+ routeMessage(_idMap, _message) {
341
+ }
342
+ };
343
+ var BaseParent = class extends Base {
344
+ /** @hidden */
345
+ children = [];
346
+ appendChildren = (...children) => {
347
+ for (const c of children) {
348
+ const newChildren = [...this.children.filter((ch) => ch !== c), c];
349
+ this.validateChildren(newChildren);
350
+ this.children = Object.freeze(newChildren);
351
+ c.setParent(this);
352
+ }
353
+ this.updateTree();
354
+ return children;
355
+ };
356
+ appendChild = (child) => {
357
+ this.appendChildren(child);
358
+ return child;
359
+ };
360
+ removeChild = (component) => {
361
+ const match = this.children.findIndex((c) => c === component);
362
+ if (match >= 0) {
363
+ const removingChild = this.children[match];
364
+ const newChildren = [
365
+ ...this.children.slice(0, match),
366
+ ...this.children.slice(match + 1)
367
+ ];
368
+ this.validateChildren(newChildren);
369
+ this.children = Object.freeze(newChildren);
370
+ removingChild?.setParent(null);
371
+ this.updateTree();
372
+ }
373
+ };
374
+ removeAllChildren = () => {
375
+ this.children.map((c) => c.setParent(null));
376
+ this.children = Object.freeze([]);
377
+ this.updateTree();
378
+ };
379
+ /**
380
+ * Return all children components that messages need to be routed to
381
+ */
382
+ getChildren = () => this.children;
383
+ /**
384
+ * TODO: we can do this better, right now it broadcasts the message to all
385
+ * components of the tree
386
+ *
387
+ * @hidden
388
+ */
389
+ routeMessage(idMap, message) {
390
+ if (idMap.getId(this) === message.componentKey) {
391
+ this.handleMessage(message);
392
+ } else {
393
+ for (const c of this.children) {
394
+ if (idMap.getId(c) === message.componentKey) {
395
+ c.handleMessage(message);
396
+ } else {
397
+ c.routeMessage(idMap, message);
398
+ }
399
+ }
400
+ }
401
+ }
402
+ insertBefore(child, beforeChild) {
403
+ const filteredChildren = this.children.filter((c) => c !== child);
404
+ let match = filteredChildren.findIndex((c) => c === beforeChild);
405
+ console.log("match", match);
406
+ if (match === -1) {
407
+ match = filteredChildren.length;
408
+ }
409
+ const newChildren = [
410
+ ...filteredChildren.slice(0, match),
411
+ child,
412
+ ...filteredChildren.slice(match)
413
+ ];
414
+ this.validateChildren(newChildren);
415
+ this.children = Object.freeze(newChildren);
416
+ child.setParent(this);
417
+ this.updateTree();
418
+ }
419
+ };
420
+ var EventEmitter = class {
421
+ listeners = /* @__PURE__ */ new Map();
422
+ addListener = (type, listener) => {
423
+ let set = this.listeners.get(type);
424
+ if (!set) {
425
+ set = /* @__PURE__ */ new Set();
426
+ this.listeners.set(type, set);
427
+ }
428
+ set.add(listener);
429
+ };
430
+ removeListener = (type, listener) => {
431
+ this.listeners.get(type)?.delete(listener);
432
+ };
433
+ emit = (type, ...args) => {
434
+ return Promise.all(
435
+ [...this.listeners.get(type) || []].map(
436
+ (l) => new Promise((resolve2, reject) => {
437
+ try {
438
+ resolve2(l(...args));
439
+ } catch (e) {
440
+ reject(e);
441
+ }
442
+ })
443
+ )
444
+ );
445
+ };
446
+ };
447
+
448
+ // src/backend/components/button.ts
449
+ var DEFAULT_PROPS = {
450
+ text: null,
451
+ icon: null,
452
+ mode: "normal",
453
+ error: null
454
+ };
455
+ var Button = class extends Base {
456
+ /** @hidden */
457
+ events = new EventEmitter();
458
+ constructor(props) {
459
+ super(DEFAULT_PROPS, props);
460
+ }
461
+ addListener = this.events.addListener;
462
+ removeListener = this.events.removeListener;
463
+ setText = (text) => {
464
+ this.updateProps({ text });
465
+ return this;
466
+ };
467
+ setIcon = (icon) => {
468
+ this.updateProps({ icon: icon ?? null });
469
+ return this;
470
+ };
471
+ setMode = (mode) => {
472
+ this.updateProps({
473
+ mode,
474
+ error: null
475
+ });
476
+ return this;
477
+ };
478
+ /** @hidden */
479
+ getProtoInfo = (idMap) => {
480
+ return {
481
+ component: "button",
482
+ key: idMap.getId(this),
483
+ text: this.props.text || "",
484
+ state: this.props.error ? { state: "error", error: this.props.error } : { state: this.props.mode },
485
+ icon: this.props.icon ?? void 0
486
+ };
487
+ };
488
+ /** @hidden */
489
+ handleMessage = (message) => {
490
+ if (message.component === "button") {
491
+ this.events.emit("click").then(() => {
492
+ if (this.props.error) {
493
+ this.updateProps({
494
+ error: null
495
+ });
496
+ }
497
+ }).catch((e) => {
498
+ this.updateProps({
499
+ error: `${e}`
500
+ });
501
+ });
502
+ }
503
+ };
504
+ };
505
+
506
+ // src/shared/styles.ts
507
+ var GROUP_DEFAULT_STYLE = {
508
+ direction: "horizontal"
509
+ };
510
+
511
+ // src/backend/components/group.ts
512
+ var DEFAULT_PROPS2 = {
513
+ ...GROUP_DEFAULT_STYLE,
514
+ title: null,
515
+ labels: null,
516
+ headerComponents: null
517
+ };
518
+ var GroupHeader = class extends BaseParent {
519
+ validateChildren = () => {
520
+ };
521
+ /** @hidden */
522
+ getProtoInfo = (idMap) => ({
523
+ component: "group-header",
524
+ key: idMap.getId(this),
525
+ children: this.getChildren().map((c) => c.getProtoInfo(idMap))
526
+ });
527
+ };
528
+ var Group = class extends BaseParent {
529
+ /** @hidden */
530
+ events = new EventEmitter();
531
+ constructor(props) {
532
+ super(DEFAULT_PROPS2, props);
533
+ }
534
+ addListener = this.events.addListener;
535
+ removeListener = this.events.removeListener;
536
+ validateChildren = () => {
537
+ };
538
+ setOptions = (options) => {
539
+ this.updateProps(options);
540
+ };
541
+ setTitle = (title) => {
542
+ this.updateProps({ title });
543
+ };
544
+ addLabel = (label) => {
545
+ this.updateProps({ labels: [...this.props.labels || [], label] });
546
+ };
547
+ setLabels = (labels) => {
548
+ this.updateProps({ labels });
549
+ };
550
+ addHeaderChild = (child) => {
551
+ const header = new GroupHeader({});
552
+ header.appendChild(child);
553
+ this.appendChild(header);
554
+ return child;
555
+ };
556
+ removeHeaderChild = (child) => {
557
+ for (const c of this.getChildren()) {
558
+ if (c instanceof GroupHeader) {
559
+ c.removeChild(child);
560
+ }
561
+ }
562
+ };
563
+ removeAllHeaderChildren = () => {
564
+ for (const child of this.getChildren()) {
565
+ if (child instanceof GroupHeader) {
566
+ child.removeAllChildren();
567
+ }
568
+ }
569
+ };
570
+ /** @hidden */
571
+ getProtoInfo = (idMap) => {
572
+ const children = [];
573
+ const headers = [];
574
+ for (const c of this.getChildren()) {
575
+ const childProto = c.getProtoInfo(idMap);
576
+ if (childProto.component === "group-header") {
577
+ headers.push(childProto);
578
+ } else {
579
+ children.push(childProto);
580
+ }
581
+ }
582
+ return {
583
+ component: "group",
584
+ key: idMap.getId(this),
585
+ title: this.props.title ?? void 0,
586
+ direction: this.props.direction,
587
+ border: this.props.border,
588
+ wrap: this.props.wrap,
589
+ children,
590
+ headers: headers.length > 0 ? headers : void 0,
591
+ labels: this.props.labels ?? void 0,
592
+ editableTitle: this.props.editableTitle || false,
593
+ defaultCollapsibleState: this.props.defaultCollapsibleState
594
+ };
595
+ };
596
+ /** @hidden */
597
+ handleMessage = (message) => {
598
+ if (message.component === "group") {
599
+ this.events.emit("title-changed", message.title);
600
+ }
601
+ };
602
+ };
603
+
604
+ // src/backend/components/label.ts
605
+ var Label = class extends Base {
606
+ constructor(props) {
607
+ super({ text: null }, props);
608
+ }
609
+ /** @hidden */
610
+ getProtoInfo(idMap) {
611
+ return {
612
+ component: "label",
613
+ key: idMap.getId(this),
614
+ bold: this.props.bold,
615
+ text: this.props.text ?? ""
616
+ };
617
+ }
618
+ setText(text) {
619
+ this.updateProps({
620
+ text
621
+ });
622
+ return this;
623
+ }
624
+ };
625
+
626
+ // src/backend/components/rect.ts
627
+ var DEFAULT_PROPS3 = {
628
+ color: "rgba(0, 0, 0, 0)"
629
+ };
630
+ var Rect = class extends Base {
631
+ constructor(props) {
632
+ super(DEFAULT_PROPS3, props);
633
+ }
634
+ /** @hidden */
635
+ getProtoInfo(idMap) {
636
+ return {
637
+ component: "rect",
638
+ key: idMap.getId(this),
639
+ color: this.props.color
640
+ };
641
+ }
642
+ setColor(color) {
643
+ this.updateProps({ color });
644
+ return this;
645
+ }
646
+ };
647
+
648
+ // src/backend/components/slider-button.ts
649
+ var DEFAULT_PROPS4 = {
650
+ value: null,
651
+ min: 0,
652
+ max: 255,
653
+ step: 5,
654
+ mode: "writeBack"
655
+ };
656
+ var SliderButton = class extends Base {
657
+ /** @hidden */
658
+ events = new EventEmitter();
659
+ constructor(props) {
660
+ super(DEFAULT_PROPS4, props);
661
+ }
662
+ addListener = this.events.addListener;
663
+ removeListener = this.events.removeListener;
664
+ /** @hidden */
665
+ getProtoInfo(idMap) {
666
+ return {
667
+ component: "slider_button",
668
+ key: idMap.getId(this),
669
+ min: this.props.min,
670
+ max: this.props.max,
671
+ step: this.props.step,
672
+ value: this.props.value
673
+ };
674
+ }
675
+ /** @hidden */
676
+ handleMessage(message) {
677
+ if (message.component !== "slider_button") return;
678
+ const newValue = this.sanitizeNumber(message.value);
679
+ if (this.props.value === newValue) return;
680
+ if (this.props.mode === "writeBack") {
681
+ this.updateProps({ value: newValue });
682
+ }
683
+ this.events.emit("change", newValue);
684
+ }
685
+ setValue(value) {
686
+ const newValue = this.sanitizeNumber(value);
687
+ if (newValue === this.props.value) return;
688
+ this.updateProps({ value });
689
+ this.updateTree();
690
+ }
691
+ sanitizeNumber(value) {
692
+ const i = Math.round((value - this.props.min) / this.props.step);
693
+ const v = i * this.props.step + this.props.min;
694
+ const clampedValue = Math.max(this.props.min, Math.min(this.props.max, v));
695
+ return clampedValue;
696
+ }
697
+ };
698
+
699
+ // src/backend/components/switch.ts
700
+ var DEFAULT_PROPS5 = {
701
+ state: "off"
702
+ };
703
+ var Switch = class extends Base {
704
+ /** @hidden */
705
+ events = new EventEmitter();
706
+ constructor(props) {
707
+ super(DEFAULT_PROPS5, props);
708
+ }
709
+ addListener = this.events.addListener;
710
+ removeListener = this.events.removeListener;
711
+ /** @hidden */
712
+ getProtoInfo(idMap) {
713
+ return {
714
+ component: "switch",
715
+ key: idMap.getId(this),
716
+ state: this.props.state
717
+ };
718
+ }
719
+ /** @hidden */
720
+ handleMessage(message) {
721
+ if (message.component === "switch") {
722
+ const state = this.props.state === "on" ? "off" : "on";
723
+ this.updateProps({ state });
724
+ this.events.emit("change", state);
725
+ }
726
+ }
727
+ setValue(state) {
728
+ if (state === this.props.state) return;
729
+ this.updateProps({ state });
730
+ }
731
+ };
732
+
733
+ // src/backend/components/tabs.ts
734
+ var Tab = class extends BaseParent {
735
+ validateChildren = (children) => {
736
+ if (children.length > 1) {
737
+ throw new Error("Tab can only have one child");
738
+ }
739
+ };
740
+ /** @hidden */
741
+ getProtoInfo = (idMap) => ({
742
+ component: "tab",
743
+ key: idMap.getId(this),
744
+ name: this.props.name,
745
+ child: this.getChildren().slice(0, 1).map((c) => c.getProtoInfo(idMap))[0]
746
+ });
747
+ };
748
+ var Tabs = class extends BaseParent {
749
+ validateChildren = (children) => {
750
+ for (const child of children) {
751
+ if (!(child instanceof Tab)) {
752
+ throw new Error("Tabs can only have Tab children");
753
+ }
754
+ }
755
+ };
756
+ constructor(props) {
757
+ super({}, { ...props });
758
+ }
759
+ addTabs(...tabs) {
760
+ for (const t of tabs) {
761
+ const tab = new Tab({ name: t.name });
762
+ tab.appendChildren(t.component);
763
+ this.appendChild(tab);
764
+ }
765
+ }
766
+ addTab(name, component) {
767
+ this.addTabs({ name, component });
768
+ return component;
769
+ }
770
+ /** @hidden */
771
+ getProtoInfo(idMap) {
772
+ return {
773
+ component: "tabs",
774
+ key: idMap.getId(this),
775
+ tabs: this.getChildren().map((c) => c.getProtoInfo(idMap))
776
+ };
777
+ }
778
+ };
779
+
780
+ // src/backend/components/text-input.ts
781
+ var DEFAULT_PROPS6 = {
782
+ value: null
783
+ };
784
+ var TextInput = class extends Base {
785
+ /** @hidden */
786
+ events = new EventEmitter();
787
+ constructor(props) {
788
+ super(DEFAULT_PROPS6, props);
789
+ }
790
+ addListener = this.events.addListener;
791
+ removeListener = this.events.removeListener;
792
+ /** @hidden */
793
+ getProtoInfo = (idMap) => {
794
+ return {
795
+ component: "text-input",
796
+ key: idMap.getId(this),
797
+ value: this.props.value ?? ""
798
+ };
799
+ };
800
+ /** @hidden */
801
+ handleMessage = (message) => {
802
+ if (message.component === "text-input") {
803
+ if (this.props.value !== message.value) {
804
+ this.updateProps({ value: message.value });
805
+ this.events.emit("change", message.value);
806
+ }
807
+ }
808
+ };
809
+ getValue = () => this.props.value;
810
+ getValidatedValue = (validator) => this.props.value === "" ? null : validator(this.props.value || "");
811
+ setValue = (value) => {
812
+ this.updateProps({ value });
813
+ };
814
+ };
815
+
816
+ // src/backend/components/timeline.ts
817
+ var DEFAULT_PROPS7 = {
818
+ state: {
819
+ state: "stopped",
820
+ totalTimeMillis: 0,
821
+ currentTimeMillis: 0
822
+ },
823
+ title: null,
824
+ subtitles: null,
825
+ source: null
826
+ };
827
+ var Timeline = class extends Base {
828
+ constructor(props) {
829
+ super(DEFAULT_PROPS7, props);
830
+ }
831
+ /** @hidden */
832
+ getProtoInfo = (idMap) => ({
833
+ component: "timeline",
834
+ key: idMap.getId(this),
835
+ state: this.props.state,
836
+ title: this.props.title ?? void 0,
837
+ subtitles: this.props.subtitles ?? void 0,
838
+ source: this.props.source ?? void 0
839
+ });
840
+ };
841
+ // Annotate the CommonJS export names for ESM import in node:
842
+ 0 && (module.exports = {
843
+ Button,
844
+ Group,
845
+ GroupHeader,
846
+ Label,
847
+ Rect,
848
+ SliderButton,
849
+ Switch,
850
+ Tab,
851
+ Tabs,
852
+ TextInput,
853
+ Timeline,
854
+ Toolkit
855
+ });