defuss-desktop 0.0.2 → 0.0.4

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/README.md CHANGED
@@ -92,10 +92,10 @@ Integrating `defuss-wm` in your project
92
92
 
93
93
  ```bash
94
94
  # install a decent package manager
95
- npm i -g pnpm@^9.13.2
95
+ npm i -g bun@^1.3.9
96
96
 
97
97
  # from your project root folder, add defuss-wm to your dependencies
98
- pnpm install defuss-wm
98
+ bun install defuss-wm
99
99
  ```
100
100
 
101
101
  #### 2. Set up your desktop environment:
@@ -198,8 +198,8 @@ All commands are run from the root of the project, from a terminal:
198
198
 
199
199
  | Command | Action |
200
200
  | :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
201
- | `pnpm build` | Build a new version of the window manager. |
202
- | `pnpm test` | Run the test suite for `defuss-wm`. |
201
+ | `bun build` | Build a new version of the window manager. |
202
+ | `bun test` | Run the test suite for `defuss-wm`. |
203
203
 
204
204
  ---
205
205
 
package/dist/index.cjs CHANGED
@@ -24,6 +24,124 @@ function Button({
24
24
  );
25
25
  }
26
26
 
27
+ const defaultTaskbarOptions = {
28
+ position: "bottom",
29
+ stateful: false,
30
+ theme: "default",
31
+ size: "medium"
32
+ };
33
+ class TaskbarManager {
34
+ position;
35
+ theme;
36
+ // e.g., 'windows-xp', 'macos', etc.
37
+ size;
38
+ constructor(options = defaultTaskbarOptions) {
39
+ this.position = options.position || "bottom";
40
+ this.theme = options.theme || "default";
41
+ this.size = options.size || "medium";
42
+ if (options.stateful) ;
43
+ }
44
+ getDimensions() {
45
+ const el = document.querySelector(".taskbar");
46
+ if (!el) {
47
+ return { width: 0, height: 0 };
48
+ }
49
+ return {
50
+ width: el.clientWidth,
51
+ height: el.clientHeight
52
+ };
53
+ }
54
+ }
55
+ globalThis.__defussTaskbarManager = globalThis.__defussTaskbarManager || new TaskbarManager();
56
+ const taskbarManager = globalThis.__defussTaskbarManager;
57
+
58
+ class DefussDesktopAppIcon {
59
+ constructor(config) {
60
+ this.config = config;
61
+ }
62
+ }
63
+ const defaultDesktopOptions = {
64
+ icons: [],
65
+ backgroundColor: "#000"
66
+ };
67
+ class DesktopManager {
68
+ constructor(options = defaultDesktopOptions) {
69
+ this.options = options;
70
+ }
71
+ el;
72
+ state;
73
+ resizeObserver;
74
+ resizeCallbacks = /* @__PURE__ */ new Set();
75
+ init(el, options = this.options) {
76
+ this.options = options;
77
+ this.el = el;
78
+ this.state = this.state || {
79
+ icons: this.options.icons.map((icon) => icon.config)
80
+ };
81
+ this.setupResizeObserver();
82
+ this.render(el);
83
+ }
84
+ render(el) {
85
+ el.style.backgroundColor = this.options.backgroundColor;
86
+ if (this.options.backgroundImage) {
87
+ el.style.backgroundImage = `url(${this.options.backgroundImage})`;
88
+ }
89
+ if (this.options.backgroundImageSize) {
90
+ el.style.backgroundSize = this.options.backgroundImageSize || "cover";
91
+ }
92
+ if (this.options.backgroundRepeat) {
93
+ el.style.backgroundRepeat = this.options.backgroundRepeat || "no-repeat";
94
+ }
95
+ if (this.options.backgroundPosition) {
96
+ el.style.backgroundPosition = this.options.backgroundPosition || "center";
97
+ }
98
+ }
99
+ addIcon(icon) {
100
+ this.options.icons.push(icon);
101
+ console.log(`Icon added: ${icon.config.name}`);
102
+ }
103
+ getDimensions() {
104
+ if (!this.el) {
105
+ throw new Error("Desktop not initialized. Call init() first.");
106
+ }
107
+ return {
108
+ width: this.el.offsetWidth,
109
+ height: this.el.offsetHeight - taskbarManager.getDimensions().height
110
+ // destop is root element minus taskbar height
111
+ };
112
+ }
113
+ setupResizeObserver() {
114
+ if (!this.el) return;
115
+ if (this.resizeObserver) {
116
+ this.resizeObserver.disconnect();
117
+ }
118
+ this.resizeObserver = new ResizeObserver(() => {
119
+ const dimensions = this.getDimensions();
120
+ this.resizeCallbacks.forEach((callback) => {
121
+ try {
122
+ callback(dimensions);
123
+ } catch (error) {
124
+ console.error("Error in desktop resize callback:", error);
125
+ }
126
+ });
127
+ });
128
+ this.resizeObserver.observe(this.el);
129
+ }
130
+ /**
131
+ * Register a callback for desktop resize events
132
+ * @param callback Function to call when desktop is resized
133
+ * @returns Unregister function to remove the callback
134
+ */
135
+ onResize(callback) {
136
+ this.resizeCallbacks.add(callback);
137
+ return () => {
138
+ this.resizeCallbacks.delete(callback);
139
+ };
140
+ }
141
+ }
142
+ globalThis.__defussDesktopManager = globalThis.__defussDesktopManager || new DesktopManager();
143
+ const desktopManager = globalThis.__defussDesktopManager;
144
+
27
145
  const defaultWindowOptions = {
28
146
  title: "Untitled",
29
147
  resizable: true,
@@ -46,7 +164,9 @@ class WindowManager {
46
164
  windows = [];
47
165
  constructor() {
48
166
  defuss.$(() => {
49
- desktopManager.onResize(defussRuntime.debounce(this.onDesktopResized.bind(this), 50));
167
+ if (desktopManager?.onResize) {
168
+ desktopManager.onResize(defussRuntime.debounce(this.onDesktopResized.bind(this), 50));
169
+ }
50
170
  });
51
171
  }
52
172
  onDesktopResized(dimensions) {
@@ -290,6 +410,11 @@ function Window({
290
410
  }
291
411
  }) {
292
412
  let isDragging = false;
413
+ let dragPointerId = null;
414
+ let dragStartMouse = { x: 0, y: 0 };
415
+ let dragStartWin = { x: 0, y: 0 };
416
+ let lastWin = { x, y };
417
+ let capturedTitleBar = null;
293
418
  const initialWindowState = windowManager.addWindow({
294
419
  id,
295
420
  title,
@@ -301,7 +426,7 @@ function Window({
301
426
  minimizable,
302
427
  maximizable
303
428
  });
304
- let dragStart = { x: initialWindowState.x, y: initialWindowState.y };
429
+ lastWin = { x: initialWindowState.x, y: initialWindowState.y };
305
430
  ref.state = {
306
431
  onClose: () => {
307
432
  console.log("Window closed");
@@ -315,15 +440,9 @@ function Window({
315
440
  console.log("Window maximized");
316
441
  onMaximize();
317
442
  },
318
- minimize: () => {
319
- windowManager.minimizeWindow(initialWindowState.id);
320
- },
321
- maximize: () => {
322
- windowManager.maximizeWindow(initialWindowState.id);
323
- },
324
- restore: () => {
325
- windowManager.restoreWindow(initialWindowState.id);
326
- },
443
+ minimize: () => windowManager.minimizeWindow(initialWindowState.id),
444
+ maximize: () => windowManager.maximizeWindow(initialWindowState.id),
445
+ restore: () => windowManager.restoreWindow(initialWindowState.id),
327
446
  close: () => {
328
447
  console.log("Closing window");
329
448
  windowManager.closeWindow(initialWindowState.id);
@@ -334,45 +453,67 @@ function Window({
334
453
  windowManager.updateWindow(initialWindowState.id, newState);
335
454
  },
336
455
  250
337
- // 1/4 second throttle
338
456
  );
339
- const onMouseMove = async (event) => {
457
+ const onWindowMouseDown = (_event) => windowManager.setActiveWindow(initialWindowState.id);
458
+ const getCurrentWinPos = () => {
459
+ const el = ref.current;
460
+ if (!el) return { x: lastWin.x, y: lastWin.y };
461
+ const left = Number.parseFloat(el.style.left);
462
+ const top = Number.parseFloat(el.style.top);
463
+ return {
464
+ x: Number.isFinite(left) ? left : el.offsetLeft,
465
+ y: Number.isFinite(top) ? top : el.offsetTop
466
+ };
467
+ };
468
+ const stopDragging = (event) => {
340
469
  if (!isDragging) return;
341
- const mouseEvent = event;
342
- const win = await defuss.$(ref);
343
- const deltaX = mouseEvent.clientX - dragStart.x;
344
- const deltaY = mouseEvent.clientY - dragStart.y;
345
- const currentOffset = await win.offset();
346
- if (currentOffset) {
347
- const newX = currentOffset.left + deltaX;
348
- const newY = currentOffset.top + deltaY;
349
- updateWindowState({ x: newX, y: newY });
350
- await win.css({
351
- left: `${newX}px`,
352
- top: `${newY}px`
353
- });
470
+ if (event && capturedTitleBar && typeof capturedTitleBar.releasePointerCapture === "function" && dragPointerId === event.pointerId) {
471
+ try {
472
+ capturedTitleBar.releasePointerCapture(event.pointerId);
473
+ } catch {
474
+ }
354
475
  }
355
- dragStart = { x: mouseEvent.clientX, y: mouseEvent.clientY };
476
+ isDragging = false;
477
+ dragPointerId = null;
478
+ capturedTitleBar = null;
479
+ windowManager.updateWindow(initialWindowState.id, { x: lastWin.x, y: lastWin.y });
356
480
  };
357
- const onWindowMouseDown = (event) => windowManager.setActiveWindow(initialWindowState.id);
358
- const onMouseDown = (event) => {
359
- if (event.target.tagName === "BUTTON") {
360
- isDragging = false;
361
- return;
362
- }
481
+ const onTitlePointerDown = (event) => {
482
+ if (event.pointerType === "mouse" && event.button !== 0) return;
483
+ const target = event.target;
484
+ if (target?.tagName === "BUTTON") return;
485
+ const titleBarEl = target?.closest?.(".title-bar");
486
+ if (!titleBarEl) return;
487
+ windowManager.setActiveWindow(initialWindowState.id);
363
488
  isDragging = true;
364
- dragStart = {
365
- x: event.clientX,
366
- y: event.clientY
367
- };
368
- defuss.$(document).on("mousemove", onMouseMove);
369
- defuss.$(document).on("mouseup", onMouseUp);
489
+ dragPointerId = event.pointerId;
490
+ capturedTitleBar = titleBarEl;
491
+ dragStartMouse = { x: event.clientX, y: event.clientY };
492
+ dragStartWin = getCurrentWinPos();
493
+ if (typeof titleBarEl.setPointerCapture === "function") {
494
+ titleBarEl.setPointerCapture(event.pointerId);
495
+ }
370
496
  event.preventDefault();
371
497
  };
372
- const onMouseUp = () => {
373
- isDragging = false;
374
- defuss.$(document).off("mousemove", onMouseMove);
375
- defuss.$(document).off("mouseup", onMouseUp);
498
+ const onTitlePointerMove = (event) => {
499
+ if (!isDragging) return;
500
+ if (dragPointerId !== null && event.pointerId !== dragPointerId) return;
501
+ const newX = dragStartWin.x + (event.clientX - dragStartMouse.x);
502
+ const newY = dragStartWin.y + (event.clientY - dragStartMouse.y);
503
+ lastWin = { x: newX, y: newY };
504
+ const el = ref.current;
505
+ if (el) {
506
+ el.style.left = `${newX}px`;
507
+ el.style.top = `${newY}px`;
508
+ }
509
+ updateWindowState({ x: newX, y: newY });
510
+ event.preventDefault();
511
+ };
512
+ const onTitlePointerUp = (event) => {
513
+ stopDragging(event);
514
+ };
515
+ const onTitlePointerCancel = (event) => {
516
+ stopDragging(event);
376
517
  };
377
518
  const onWindowMounted = () => {
378
519
  windowManager.updateWindow(initialWindowState.id, {
@@ -380,17 +521,18 @@ function Window({
380
521
  ref
381
522
  });
382
523
  windowManager.setActiveWindow(initialWindowState.id);
524
+ defuss.$(document).on("blur", () => stopDragging());
525
+ defuss.$(document).on("visibilitychange", () => {
526
+ if (document.hidden) stopDragging();
527
+ });
383
528
  };
384
529
  const onCloseClick = () => windowManager.closeWindow(initialWindowState.id);
385
- const onMaximizeClick = async () => {
530
+ const onMaximizeClick = () => {
386
531
  const currentState = windowManager.getWindow(initialWindowState.id);
387
- if (currentState?.maximized) {
388
- windowManager.restoreWindow(initialWindowState.id);
389
- } else {
390
- windowManager.maximizeWindow(initialWindowState.id);
391
- }
532
+ if (currentState?.maximized) windowManager.restoreWindow(initialWindowState.id);
533
+ else windowManager.maximizeWindow(initialWindowState.id);
392
534
  };
393
- const onMinimizeClick = async () => {
535
+ const onMinimizeClick = () => {
394
536
  windowManager.minimizeWindow(initialWindowState.id);
395
537
  };
396
538
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -412,36 +554,18 @@ function Window({
412
554
  {
413
555
  class: "title-bar",
414
556
  onMount: onWindowMounted,
415
- onMouseDown,
416
- onMouseUp,
417
- onMouseMove,
557
+ onPointerDown: onTitlePointerDown,
558
+ onPointerMove: onTitlePointerMove,
559
+ onPointerUp: onTitlePointerUp,
560
+ onPointerCancel: onTitlePointerCancel,
561
+ onDblClick: onMaximizeClick,
562
+ style: { touchAction: "none" },
418
563
  children: [
419
564
  /* @__PURE__ */ jsxRuntime.jsx("div", { class: "title-bar-text", children: title }),
420
565
  /* @__PURE__ */ jsxRuntime.jsxs("div", { class: "title-bar-controls", children: [
421
- /* @__PURE__ */ jsxRuntime.jsx(
422
- "button",
423
- {
424
- type: "button",
425
- "aria-label": "Minimize",
426
- onClick: onMinimizeClick
427
- }
428
- ),
429
- /* @__PURE__ */ jsxRuntime.jsx(
430
- "button",
431
- {
432
- type: "button",
433
- "aria-label": "Maximize",
434
- onClick: onMaximizeClick
435
- }
436
- ),
437
- /* @__PURE__ */ jsxRuntime.jsx(
438
- "button",
439
- {
440
- type: "button",
441
- "aria-label": "Close",
442
- onClick: onCloseClick
443
- }
444
- )
566
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", "aria-label": "Minimize", onClick: onMinimizeClick }),
567
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", "aria-label": "Maximize", onClick: onMaximizeClick }),
568
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", "aria-label": "Close", onClick: onCloseClick })
445
569
  ] })
446
570
  ]
447
571
  }
@@ -627,93 +751,6 @@ const LogonScreen = ({
627
751
  ] });
628
752
  };
629
753
 
630
- class DefussDesktopAppIcon {
631
- constructor(config) {
632
- this.config = config;
633
- }
634
- }
635
- const defaultDesktopOptions = {
636
- icons: [],
637
- backgroundColor: "#000"
638
- };
639
- class DesktopManager {
640
- constructor(options = defaultDesktopOptions) {
641
- this.options = options;
642
- }
643
- el;
644
- state;
645
- resizeObserver;
646
- resizeCallbacks = /* @__PURE__ */ new Set();
647
- init(el, options = this.options) {
648
- this.options = options;
649
- this.el = el;
650
- this.state = this.state || {
651
- icons: this.options.icons.map((icon) => icon.config)
652
- };
653
- this.setupResizeObserver();
654
- this.render(el);
655
- }
656
- render(el) {
657
- el.style.backgroundColor = this.options.backgroundColor;
658
- if (this.options.backgroundImage) {
659
- el.style.backgroundImage = `url(${this.options.backgroundImage})`;
660
- }
661
- if (this.options.backgroundImageSize) {
662
- el.style.backgroundSize = this.options.backgroundImageSize || "cover";
663
- }
664
- if (this.options.backgroundRepeat) {
665
- el.style.backgroundRepeat = this.options.backgroundRepeat || "no-repeat";
666
- }
667
- if (this.options.backgroundPosition) {
668
- el.style.backgroundPosition = this.options.backgroundPosition || "center";
669
- }
670
- }
671
- addIcon(icon) {
672
- this.options.icons.push(icon);
673
- console.log(`Icon added: ${icon.config.name}`);
674
- }
675
- getDimensions() {
676
- if (!this.el) {
677
- throw new Error("Desktop not initialized. Call init() first.");
678
- }
679
- return {
680
- width: this.el.offsetWidth,
681
- height: this.el.offsetHeight - taskbarManager.getDimensions().height
682
- // destop is root element minus taskbar height
683
- };
684
- }
685
- setupResizeObserver() {
686
- if (!this.el) return;
687
- if (this.resizeObserver) {
688
- this.resizeObserver.disconnect();
689
- }
690
- this.resizeObserver = new ResizeObserver(() => {
691
- const dimensions = this.getDimensions();
692
- this.resizeCallbacks.forEach((callback) => {
693
- try {
694
- callback(dimensions);
695
- } catch (error) {
696
- console.error("Error in desktop resize callback:", error);
697
- }
698
- });
699
- });
700
- this.resizeObserver.observe(this.el);
701
- }
702
- /**
703
- * Register a callback for desktop resize events
704
- * @param callback Function to call when desktop is resized
705
- * @returns Unregister function to remove the callback
706
- */
707
- onResize(callback) {
708
- this.resizeCallbacks.add(callback);
709
- return () => {
710
- this.resizeCallbacks.delete(callback);
711
- };
712
- }
713
- }
714
- globalThis.__defussDesktopManager = globalThis.__defussDesktopManager || new DesktopManager();
715
- const desktopManager = globalThis.__defussDesktopManager;
716
-
717
754
  const StartMenu = () => {
718
755
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { class: "slide-open crt", children: [
719
756
  /* @__PURE__ */ jsxRuntime.jsx("div", { class: "top", children: /* @__PURE__ */ jsxRuntime.jsx("h1", { children: "Aron Homberg" }) }),
@@ -851,15 +888,12 @@ class DequeryWithWindowManager extends defuss.CallChainImpl {
851
888
  */
852
889
  // register an app to the desktop shell
853
890
  createDesktopApp(options) {
854
- return defuss.createCall(this, "createDesktopApp", async () => {
855
- return new DefussApp(options);
856
- });
891
+ new DefussApp(options);
892
+ return this;
857
893
  }
858
894
  // create a desktop app icon
859
895
  createDesktopAppIcon(options) {
860
- return defuss.createCall(this, "createDesktopAppIcon", async () => {
861
- return new DefussDesktopAppIcon(options);
862
- });
896
+ return this;
863
897
  }
864
898
  }
865
899
  const $ = defuss.dequery.extend(DequeryWithWindowManager, [
@@ -868,37 +902,6 @@ const $ = defuss.dequery.extend(DequeryWithWindowManager, [
868
902
  "createDesktopAppIcon"
869
903
  ]);
870
904
 
871
- const defaultTaskbarOptions = {
872
- position: "bottom",
873
- stateful: false,
874
- theme: "default",
875
- size: "medium"
876
- };
877
- class TaskbarManager {
878
- position;
879
- theme;
880
- // e.g., 'windows-xp', 'macos', etc.
881
- size;
882
- constructor(options = defaultTaskbarOptions) {
883
- this.position = options.position || "bottom";
884
- this.theme = options.theme || "default";
885
- this.size = options.size || "medium";
886
- if (options.stateful) ;
887
- }
888
- getDimensions() {
889
- const el = document.querySelector(".taskbar");
890
- if (!el) {
891
- return { width: 0, height: 0 };
892
- }
893
- return {
894
- width: el.clientWidth,
895
- height: el.clientHeight
896
- };
897
- }
898
- }
899
- globalThis.__defussTaskbarManager = globalThis.__defussTaskbarManager || new TaskbarManager();
900
- const taskbarManager = globalThis.__defussTaskbarManager;
901
-
902
905
  const defaultSystemSoundFilePaths = [
903
906
  "/sounds/balloon.ogg",
904
907
  "/sounds/batterycritical.ogg",
package/dist/index.d.cts CHANGED
@@ -1,15 +1,15 @@
1
1
  import * as defuss from 'defuss';
2
- import { Props, CallChainImpl, Dequery, NodeType, Ref } from 'defuss';
2
+ import { Props, CallChainImpl, Dequery, Ref } from 'defuss';
3
3
 
4
- declare function Desktop({ ref }: Props): any;
4
+ declare function Desktop({ ref }: Props<HTMLDivElement>): JSX.Element;
5
5
 
6
- interface ButtonProps extends Props {
6
+ interface ButtonProps extends Props<HTMLButtonElement> {
7
7
  onClick?: () => void;
8
8
  disabled?: boolean;
9
9
  }
10
- declare function Button({ onClick, disabled, children, ref, }: ButtonProps): any;
10
+ declare function Button({ onClick, disabled, children, ref, }: ButtonProps): JSX.Element;
11
11
 
12
- interface LogonScreenProps extends Props {
12
+ interface LogonScreenProps extends Props<HTMLDivElement> {
13
13
  cDriveBasePath?: string;
14
14
  showGuestUser?: boolean;
15
15
  onTurnOffComputer?: () => void;
@@ -20,7 +20,7 @@ type LoginForm = {
20
20
  username: string;
21
21
  password: string;
22
22
  };
23
- declare const LogonScreen: ({ cDriveBasePath, showGuestUser, onTurnOffComputer, onGuestLogon, onUserLogonSubmit, ref, }: LogonScreenProps) => any;
23
+ declare const LogonScreen: ({ cDriveBasePath, showGuestUser, onTurnOffComputer, onGuestLogon, onUserLogonSubmit, ref, }: LogonScreenProps) => JSX.Element;
24
24
 
25
25
  interface DefussAppConfig {
26
26
  name: string;
@@ -85,20 +85,20 @@ declare class DesktopManager {
85
85
  }
86
86
  declare const desktopManager: DesktopManager;
87
87
 
88
- interface ShellProps extends Props {
88
+ interface ShellProps extends Props<HTMLDivElement> {
89
89
  desktopConfig: CreateDesktopOptions;
90
90
  }
91
- declare function Shell({ ref, desktopConfig, }: ShellProps): any;
91
+ declare function Shell({ ref, desktopConfig, }: ShellProps): JSX.Element;
92
92
 
93
- declare const Taskbar: () => any;
93
+ declare const Taskbar: () => JSX.Element;
94
94
 
95
- declare const StartButton: () => any;
95
+ declare const StartButton: () => JSX.Element;
96
96
 
97
- declare const StartMenu: () => any;
97
+ declare const StartMenu: () => JSX.Element;
98
98
 
99
99
  declare class DequeryWithWindowManager<NT> extends CallChainImpl<NT, DequeryWithWindowManager<NT> & Dequery<NT>> {
100
- createDesktopApp(options: DefussAppConfig): PromiseLike<DefussApp>;
101
- createDesktopAppIcon(options: DesktopIconConfig): PromiseLike<DefussDesktopAppIcon>;
100
+ createDesktopApp(options: DefussAppConfig): this & Dequery<NT>;
101
+ createDesktopAppIcon(options: DesktopIconConfig): this & Dequery<NT>;
102
102
  }
103
103
  /**
104
104
  * Extended dequery function with window management capabilities.
@@ -107,7 +107,7 @@ declare class DequeryWithWindowManager<NT> extends CallChainImpl<NT, DequeryWith
107
107
  * @param options - Optional dequery options
108
108
  * @returns Extended dequery instance with createWindow and createTaskbar methods
109
109
  */
110
- declare const $: <NT = defuss.DequerySyncMethodReturnType>(selectorRefOrEl: string | NodeType | defuss.Ref<any, NodeType> | defuss.RenderInput | Function, options?: (defuss.DequeryOptions<NT> & JSX.HTMLAttributesLowerCase & {
110
+ declare const $: <NT = defuss.NodeType>(selectorRefOrEl: string | defuss.NodeType | defuss.Ref<defuss.NodeType, any> | defuss.RenderInput | Function, options?: (defuss.DequeryOptions<NT> & JSX.HTMLAttributesLowerCase<defuss.DOMElement> & JSX.HTMLAttributesLowerCase<defuss.DOMElement> & {
111
111
  html?: string;
112
112
  text?: string;
113
113
  }) | undefined) => DequeryWithWindowManager<unknown>;
@@ -142,7 +142,7 @@ interface CreateWindowOptions {
142
142
  interface WindowState {
143
143
  id: string;
144
144
  el: HTMLElement;
145
- ref: Ref<WindowRefState>;
145
+ ref: Ref<HTMLElement, WindowRefState>;
146
146
  title: string;
147
147
  icon: string;
148
148
  width: number;
package/dist/index.d.mts CHANGED
@@ -1,15 +1,15 @@
1
1
  import * as defuss from 'defuss';
2
- import { Props, CallChainImpl, Dequery, NodeType, Ref } from 'defuss';
2
+ import { Props, CallChainImpl, Dequery, Ref } from 'defuss';
3
3
 
4
- declare function Desktop({ ref }: Props): any;
4
+ declare function Desktop({ ref }: Props<HTMLDivElement>): JSX.Element;
5
5
 
6
- interface ButtonProps extends Props {
6
+ interface ButtonProps extends Props<HTMLButtonElement> {
7
7
  onClick?: () => void;
8
8
  disabled?: boolean;
9
9
  }
10
- declare function Button({ onClick, disabled, children, ref, }: ButtonProps): any;
10
+ declare function Button({ onClick, disabled, children, ref, }: ButtonProps): JSX.Element;
11
11
 
12
- interface LogonScreenProps extends Props {
12
+ interface LogonScreenProps extends Props<HTMLDivElement> {
13
13
  cDriveBasePath?: string;
14
14
  showGuestUser?: boolean;
15
15
  onTurnOffComputer?: () => void;
@@ -20,7 +20,7 @@ type LoginForm = {
20
20
  username: string;
21
21
  password: string;
22
22
  };
23
- declare const LogonScreen: ({ cDriveBasePath, showGuestUser, onTurnOffComputer, onGuestLogon, onUserLogonSubmit, ref, }: LogonScreenProps) => any;
23
+ declare const LogonScreen: ({ cDriveBasePath, showGuestUser, onTurnOffComputer, onGuestLogon, onUserLogonSubmit, ref, }: LogonScreenProps) => JSX.Element;
24
24
 
25
25
  interface DefussAppConfig {
26
26
  name: string;
@@ -85,20 +85,20 @@ declare class DesktopManager {
85
85
  }
86
86
  declare const desktopManager: DesktopManager;
87
87
 
88
- interface ShellProps extends Props {
88
+ interface ShellProps extends Props<HTMLDivElement> {
89
89
  desktopConfig: CreateDesktopOptions;
90
90
  }
91
- declare function Shell({ ref, desktopConfig, }: ShellProps): any;
91
+ declare function Shell({ ref, desktopConfig, }: ShellProps): JSX.Element;
92
92
 
93
- declare const Taskbar: () => any;
93
+ declare const Taskbar: () => JSX.Element;
94
94
 
95
- declare const StartButton: () => any;
95
+ declare const StartButton: () => JSX.Element;
96
96
 
97
- declare const StartMenu: () => any;
97
+ declare const StartMenu: () => JSX.Element;
98
98
 
99
99
  declare class DequeryWithWindowManager<NT> extends CallChainImpl<NT, DequeryWithWindowManager<NT> & Dequery<NT>> {
100
- createDesktopApp(options: DefussAppConfig): PromiseLike<DefussApp>;
101
- createDesktopAppIcon(options: DesktopIconConfig): PromiseLike<DefussDesktopAppIcon>;
100
+ createDesktopApp(options: DefussAppConfig): this & Dequery<NT>;
101
+ createDesktopAppIcon(options: DesktopIconConfig): this & Dequery<NT>;
102
102
  }
103
103
  /**
104
104
  * Extended dequery function with window management capabilities.
@@ -107,7 +107,7 @@ declare class DequeryWithWindowManager<NT> extends CallChainImpl<NT, DequeryWith
107
107
  * @param options - Optional dequery options
108
108
  * @returns Extended dequery instance with createWindow and createTaskbar methods
109
109
  */
110
- declare const $: <NT = defuss.DequerySyncMethodReturnType>(selectorRefOrEl: string | NodeType | defuss.Ref<any, NodeType> | defuss.RenderInput | Function, options?: (defuss.DequeryOptions<NT> & JSX.HTMLAttributesLowerCase & {
110
+ declare const $: <NT = defuss.NodeType>(selectorRefOrEl: string | defuss.NodeType | defuss.Ref<defuss.NodeType, any> | defuss.RenderInput | Function, options?: (defuss.DequeryOptions<NT> & JSX.HTMLAttributesLowerCase<defuss.DOMElement> & JSX.HTMLAttributesLowerCase<defuss.DOMElement> & {
111
111
  html?: string;
112
112
  text?: string;
113
113
  }) | undefined) => DequeryWithWindowManager<unknown>;
@@ -142,7 +142,7 @@ interface CreateWindowOptions {
142
142
  interface WindowState {
143
143
  id: string;
144
144
  el: HTMLElement;
145
- ref: Ref<WindowRefState>;
145
+ ref: Ref<HTMLElement, WindowRefState>;
146
146
  title: string;
147
147
  icon: string;
148
148
  width: number;
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { createRef, $ as $$1, dequery, CallChainImpl, createCall } from 'defuss';
1
+ import { createRef, $ as $$1, dequery, CallChainImpl } from 'defuss';
2
2
  import { debounce, throttle } from 'defuss-runtime';
3
3
  import { jsx, jsxs } from 'defuss/jsx-runtime';
4
4
  import { access, transval, rule } from 'defuss-transval';
@@ -22,6 +22,124 @@ function Button({
22
22
  );
23
23
  }
24
24
 
25
+ const defaultTaskbarOptions = {
26
+ position: "bottom",
27
+ stateful: false,
28
+ theme: "default",
29
+ size: "medium"
30
+ };
31
+ class TaskbarManager {
32
+ position;
33
+ theme;
34
+ // e.g., 'windows-xp', 'macos', etc.
35
+ size;
36
+ constructor(options = defaultTaskbarOptions) {
37
+ this.position = options.position || "bottom";
38
+ this.theme = options.theme || "default";
39
+ this.size = options.size || "medium";
40
+ if (options.stateful) ;
41
+ }
42
+ getDimensions() {
43
+ const el = document.querySelector(".taskbar");
44
+ if (!el) {
45
+ return { width: 0, height: 0 };
46
+ }
47
+ return {
48
+ width: el.clientWidth,
49
+ height: el.clientHeight
50
+ };
51
+ }
52
+ }
53
+ globalThis.__defussTaskbarManager = globalThis.__defussTaskbarManager || new TaskbarManager();
54
+ const taskbarManager = globalThis.__defussTaskbarManager;
55
+
56
+ class DefussDesktopAppIcon {
57
+ constructor(config) {
58
+ this.config = config;
59
+ }
60
+ }
61
+ const defaultDesktopOptions = {
62
+ icons: [],
63
+ backgroundColor: "#000"
64
+ };
65
+ class DesktopManager {
66
+ constructor(options = defaultDesktopOptions) {
67
+ this.options = options;
68
+ }
69
+ el;
70
+ state;
71
+ resizeObserver;
72
+ resizeCallbacks = /* @__PURE__ */ new Set();
73
+ init(el, options = this.options) {
74
+ this.options = options;
75
+ this.el = el;
76
+ this.state = this.state || {
77
+ icons: this.options.icons.map((icon) => icon.config)
78
+ };
79
+ this.setupResizeObserver();
80
+ this.render(el);
81
+ }
82
+ render(el) {
83
+ el.style.backgroundColor = this.options.backgroundColor;
84
+ if (this.options.backgroundImage) {
85
+ el.style.backgroundImage = `url(${this.options.backgroundImage})`;
86
+ }
87
+ if (this.options.backgroundImageSize) {
88
+ el.style.backgroundSize = this.options.backgroundImageSize || "cover";
89
+ }
90
+ if (this.options.backgroundRepeat) {
91
+ el.style.backgroundRepeat = this.options.backgroundRepeat || "no-repeat";
92
+ }
93
+ if (this.options.backgroundPosition) {
94
+ el.style.backgroundPosition = this.options.backgroundPosition || "center";
95
+ }
96
+ }
97
+ addIcon(icon) {
98
+ this.options.icons.push(icon);
99
+ console.log(`Icon added: ${icon.config.name}`);
100
+ }
101
+ getDimensions() {
102
+ if (!this.el) {
103
+ throw new Error("Desktop not initialized. Call init() first.");
104
+ }
105
+ return {
106
+ width: this.el.offsetWidth,
107
+ height: this.el.offsetHeight - taskbarManager.getDimensions().height
108
+ // destop is root element minus taskbar height
109
+ };
110
+ }
111
+ setupResizeObserver() {
112
+ if (!this.el) return;
113
+ if (this.resizeObserver) {
114
+ this.resizeObserver.disconnect();
115
+ }
116
+ this.resizeObserver = new ResizeObserver(() => {
117
+ const dimensions = this.getDimensions();
118
+ this.resizeCallbacks.forEach((callback) => {
119
+ try {
120
+ callback(dimensions);
121
+ } catch (error) {
122
+ console.error("Error in desktop resize callback:", error);
123
+ }
124
+ });
125
+ });
126
+ this.resizeObserver.observe(this.el);
127
+ }
128
+ /**
129
+ * Register a callback for desktop resize events
130
+ * @param callback Function to call when desktop is resized
131
+ * @returns Unregister function to remove the callback
132
+ */
133
+ onResize(callback) {
134
+ this.resizeCallbacks.add(callback);
135
+ return () => {
136
+ this.resizeCallbacks.delete(callback);
137
+ };
138
+ }
139
+ }
140
+ globalThis.__defussDesktopManager = globalThis.__defussDesktopManager || new DesktopManager();
141
+ const desktopManager = globalThis.__defussDesktopManager;
142
+
25
143
  const defaultWindowOptions = {
26
144
  title: "Untitled",
27
145
  resizable: true,
@@ -44,7 +162,9 @@ class WindowManager {
44
162
  windows = [];
45
163
  constructor() {
46
164
  $$1(() => {
47
- desktopManager.onResize(debounce(this.onDesktopResized.bind(this), 50));
165
+ if (desktopManager?.onResize) {
166
+ desktopManager.onResize(debounce(this.onDesktopResized.bind(this), 50));
167
+ }
48
168
  });
49
169
  }
50
170
  onDesktopResized(dimensions) {
@@ -288,6 +408,11 @@ function Window({
288
408
  }
289
409
  }) {
290
410
  let isDragging = false;
411
+ let dragPointerId = null;
412
+ let dragStartMouse = { x: 0, y: 0 };
413
+ let dragStartWin = { x: 0, y: 0 };
414
+ let lastWin = { x, y };
415
+ let capturedTitleBar = null;
291
416
  const initialWindowState = windowManager.addWindow({
292
417
  id,
293
418
  title,
@@ -299,7 +424,7 @@ function Window({
299
424
  minimizable,
300
425
  maximizable
301
426
  });
302
- let dragStart = { x: initialWindowState.x, y: initialWindowState.y };
427
+ lastWin = { x: initialWindowState.x, y: initialWindowState.y };
303
428
  ref.state = {
304
429
  onClose: () => {
305
430
  console.log("Window closed");
@@ -313,15 +438,9 @@ function Window({
313
438
  console.log("Window maximized");
314
439
  onMaximize();
315
440
  },
316
- minimize: () => {
317
- windowManager.minimizeWindow(initialWindowState.id);
318
- },
319
- maximize: () => {
320
- windowManager.maximizeWindow(initialWindowState.id);
321
- },
322
- restore: () => {
323
- windowManager.restoreWindow(initialWindowState.id);
324
- },
441
+ minimize: () => windowManager.minimizeWindow(initialWindowState.id),
442
+ maximize: () => windowManager.maximizeWindow(initialWindowState.id),
443
+ restore: () => windowManager.restoreWindow(initialWindowState.id),
325
444
  close: () => {
326
445
  console.log("Closing window");
327
446
  windowManager.closeWindow(initialWindowState.id);
@@ -332,45 +451,67 @@ function Window({
332
451
  windowManager.updateWindow(initialWindowState.id, newState);
333
452
  },
334
453
  250
335
- // 1/4 second throttle
336
454
  );
337
- const onMouseMove = async (event) => {
455
+ const onWindowMouseDown = (_event) => windowManager.setActiveWindow(initialWindowState.id);
456
+ const getCurrentWinPos = () => {
457
+ const el = ref.current;
458
+ if (!el) return { x: lastWin.x, y: lastWin.y };
459
+ const left = Number.parseFloat(el.style.left);
460
+ const top = Number.parseFloat(el.style.top);
461
+ return {
462
+ x: Number.isFinite(left) ? left : el.offsetLeft,
463
+ y: Number.isFinite(top) ? top : el.offsetTop
464
+ };
465
+ };
466
+ const stopDragging = (event) => {
338
467
  if (!isDragging) return;
339
- const mouseEvent = event;
340
- const win = await $$1(ref);
341
- const deltaX = mouseEvent.clientX - dragStart.x;
342
- const deltaY = mouseEvent.clientY - dragStart.y;
343
- const currentOffset = await win.offset();
344
- if (currentOffset) {
345
- const newX = currentOffset.left + deltaX;
346
- const newY = currentOffset.top + deltaY;
347
- updateWindowState({ x: newX, y: newY });
348
- await win.css({
349
- left: `${newX}px`,
350
- top: `${newY}px`
351
- });
468
+ if (event && capturedTitleBar && typeof capturedTitleBar.releasePointerCapture === "function" && dragPointerId === event.pointerId) {
469
+ try {
470
+ capturedTitleBar.releasePointerCapture(event.pointerId);
471
+ } catch {
472
+ }
352
473
  }
353
- dragStart = { x: mouseEvent.clientX, y: mouseEvent.clientY };
474
+ isDragging = false;
475
+ dragPointerId = null;
476
+ capturedTitleBar = null;
477
+ windowManager.updateWindow(initialWindowState.id, { x: lastWin.x, y: lastWin.y });
354
478
  };
355
- const onWindowMouseDown = (event) => windowManager.setActiveWindow(initialWindowState.id);
356
- const onMouseDown = (event) => {
357
- if (event.target.tagName === "BUTTON") {
358
- isDragging = false;
359
- return;
360
- }
479
+ const onTitlePointerDown = (event) => {
480
+ if (event.pointerType === "mouse" && event.button !== 0) return;
481
+ const target = event.target;
482
+ if (target?.tagName === "BUTTON") return;
483
+ const titleBarEl = target?.closest?.(".title-bar");
484
+ if (!titleBarEl) return;
485
+ windowManager.setActiveWindow(initialWindowState.id);
361
486
  isDragging = true;
362
- dragStart = {
363
- x: event.clientX,
364
- y: event.clientY
365
- };
366
- $$1(document).on("mousemove", onMouseMove);
367
- $$1(document).on("mouseup", onMouseUp);
487
+ dragPointerId = event.pointerId;
488
+ capturedTitleBar = titleBarEl;
489
+ dragStartMouse = { x: event.clientX, y: event.clientY };
490
+ dragStartWin = getCurrentWinPos();
491
+ if (typeof titleBarEl.setPointerCapture === "function") {
492
+ titleBarEl.setPointerCapture(event.pointerId);
493
+ }
368
494
  event.preventDefault();
369
495
  };
370
- const onMouseUp = () => {
371
- isDragging = false;
372
- $$1(document).off("mousemove", onMouseMove);
373
- $$1(document).off("mouseup", onMouseUp);
496
+ const onTitlePointerMove = (event) => {
497
+ if (!isDragging) return;
498
+ if (dragPointerId !== null && event.pointerId !== dragPointerId) return;
499
+ const newX = dragStartWin.x + (event.clientX - dragStartMouse.x);
500
+ const newY = dragStartWin.y + (event.clientY - dragStartMouse.y);
501
+ lastWin = { x: newX, y: newY };
502
+ const el = ref.current;
503
+ if (el) {
504
+ el.style.left = `${newX}px`;
505
+ el.style.top = `${newY}px`;
506
+ }
507
+ updateWindowState({ x: newX, y: newY });
508
+ event.preventDefault();
509
+ };
510
+ const onTitlePointerUp = (event) => {
511
+ stopDragging(event);
512
+ };
513
+ const onTitlePointerCancel = (event) => {
514
+ stopDragging(event);
374
515
  };
375
516
  const onWindowMounted = () => {
376
517
  windowManager.updateWindow(initialWindowState.id, {
@@ -378,17 +519,18 @@ function Window({
378
519
  ref
379
520
  });
380
521
  windowManager.setActiveWindow(initialWindowState.id);
522
+ $$1(document).on("blur", () => stopDragging());
523
+ $$1(document).on("visibilitychange", () => {
524
+ if (document.hidden) stopDragging();
525
+ });
381
526
  };
382
527
  const onCloseClick = () => windowManager.closeWindow(initialWindowState.id);
383
- const onMaximizeClick = async () => {
528
+ const onMaximizeClick = () => {
384
529
  const currentState = windowManager.getWindow(initialWindowState.id);
385
- if (currentState?.maximized) {
386
- windowManager.restoreWindow(initialWindowState.id);
387
- } else {
388
- windowManager.maximizeWindow(initialWindowState.id);
389
- }
530
+ if (currentState?.maximized) windowManager.restoreWindow(initialWindowState.id);
531
+ else windowManager.maximizeWindow(initialWindowState.id);
390
532
  };
391
- const onMinimizeClick = async () => {
533
+ const onMinimizeClick = () => {
392
534
  windowManager.minimizeWindow(initialWindowState.id);
393
535
  };
394
536
  return /* @__PURE__ */ jsxs(
@@ -410,36 +552,18 @@ function Window({
410
552
  {
411
553
  class: "title-bar",
412
554
  onMount: onWindowMounted,
413
- onMouseDown,
414
- onMouseUp,
415
- onMouseMove,
555
+ onPointerDown: onTitlePointerDown,
556
+ onPointerMove: onTitlePointerMove,
557
+ onPointerUp: onTitlePointerUp,
558
+ onPointerCancel: onTitlePointerCancel,
559
+ onDblClick: onMaximizeClick,
560
+ style: { touchAction: "none" },
416
561
  children: [
417
562
  /* @__PURE__ */ jsx("div", { class: "title-bar-text", children: title }),
418
563
  /* @__PURE__ */ jsxs("div", { class: "title-bar-controls", children: [
419
- /* @__PURE__ */ jsx(
420
- "button",
421
- {
422
- type: "button",
423
- "aria-label": "Minimize",
424
- onClick: onMinimizeClick
425
- }
426
- ),
427
- /* @__PURE__ */ jsx(
428
- "button",
429
- {
430
- type: "button",
431
- "aria-label": "Maximize",
432
- onClick: onMaximizeClick
433
- }
434
- ),
435
- /* @__PURE__ */ jsx(
436
- "button",
437
- {
438
- type: "button",
439
- "aria-label": "Close",
440
- onClick: onCloseClick
441
- }
442
- )
564
+ /* @__PURE__ */ jsx("button", { type: "button", "aria-label": "Minimize", onClick: onMinimizeClick }),
565
+ /* @__PURE__ */ jsx("button", { type: "button", "aria-label": "Maximize", onClick: onMaximizeClick }),
566
+ /* @__PURE__ */ jsx("button", { type: "button", "aria-label": "Close", onClick: onCloseClick })
443
567
  ] })
444
568
  ]
445
569
  }
@@ -625,93 +749,6 @@ const LogonScreen = ({
625
749
  ] });
626
750
  };
627
751
 
628
- class DefussDesktopAppIcon {
629
- constructor(config) {
630
- this.config = config;
631
- }
632
- }
633
- const defaultDesktopOptions = {
634
- icons: [],
635
- backgroundColor: "#000"
636
- };
637
- class DesktopManager {
638
- constructor(options = defaultDesktopOptions) {
639
- this.options = options;
640
- }
641
- el;
642
- state;
643
- resizeObserver;
644
- resizeCallbacks = /* @__PURE__ */ new Set();
645
- init(el, options = this.options) {
646
- this.options = options;
647
- this.el = el;
648
- this.state = this.state || {
649
- icons: this.options.icons.map((icon) => icon.config)
650
- };
651
- this.setupResizeObserver();
652
- this.render(el);
653
- }
654
- render(el) {
655
- el.style.backgroundColor = this.options.backgroundColor;
656
- if (this.options.backgroundImage) {
657
- el.style.backgroundImage = `url(${this.options.backgroundImage})`;
658
- }
659
- if (this.options.backgroundImageSize) {
660
- el.style.backgroundSize = this.options.backgroundImageSize || "cover";
661
- }
662
- if (this.options.backgroundRepeat) {
663
- el.style.backgroundRepeat = this.options.backgroundRepeat || "no-repeat";
664
- }
665
- if (this.options.backgroundPosition) {
666
- el.style.backgroundPosition = this.options.backgroundPosition || "center";
667
- }
668
- }
669
- addIcon(icon) {
670
- this.options.icons.push(icon);
671
- console.log(`Icon added: ${icon.config.name}`);
672
- }
673
- getDimensions() {
674
- if (!this.el) {
675
- throw new Error("Desktop not initialized. Call init() first.");
676
- }
677
- return {
678
- width: this.el.offsetWidth,
679
- height: this.el.offsetHeight - taskbarManager.getDimensions().height
680
- // destop is root element minus taskbar height
681
- };
682
- }
683
- setupResizeObserver() {
684
- if (!this.el) return;
685
- if (this.resizeObserver) {
686
- this.resizeObserver.disconnect();
687
- }
688
- this.resizeObserver = new ResizeObserver(() => {
689
- const dimensions = this.getDimensions();
690
- this.resizeCallbacks.forEach((callback) => {
691
- try {
692
- callback(dimensions);
693
- } catch (error) {
694
- console.error("Error in desktop resize callback:", error);
695
- }
696
- });
697
- });
698
- this.resizeObserver.observe(this.el);
699
- }
700
- /**
701
- * Register a callback for desktop resize events
702
- * @param callback Function to call when desktop is resized
703
- * @returns Unregister function to remove the callback
704
- */
705
- onResize(callback) {
706
- this.resizeCallbacks.add(callback);
707
- return () => {
708
- this.resizeCallbacks.delete(callback);
709
- };
710
- }
711
- }
712
- globalThis.__defussDesktopManager = globalThis.__defussDesktopManager || new DesktopManager();
713
- const desktopManager = globalThis.__defussDesktopManager;
714
-
715
752
  const StartMenu = () => {
716
753
  return /* @__PURE__ */ jsxs("div", { class: "slide-open crt", children: [
717
754
  /* @__PURE__ */ jsx("div", { class: "top", children: /* @__PURE__ */ jsx("h1", { children: "Aron Homberg" }) }),
@@ -849,15 +886,12 @@ class DequeryWithWindowManager extends CallChainImpl {
849
886
  */
850
887
  // register an app to the desktop shell
851
888
  createDesktopApp(options) {
852
- return createCall(this, "createDesktopApp", async () => {
853
- return new DefussApp(options);
854
- });
889
+ new DefussApp(options);
890
+ return this;
855
891
  }
856
892
  // create a desktop app icon
857
893
  createDesktopAppIcon(options) {
858
- return createCall(this, "createDesktopAppIcon", async () => {
859
- return new DefussDesktopAppIcon(options);
860
- });
894
+ return this;
861
895
  }
862
896
  }
863
897
  const $ = dequery.extend(DequeryWithWindowManager, [
@@ -866,37 +900,6 @@ const $ = dequery.extend(DequeryWithWindowManager, [
866
900
  "createDesktopAppIcon"
867
901
  ]);
868
902
 
869
- const defaultTaskbarOptions = {
870
- position: "bottom",
871
- stateful: false,
872
- theme: "default",
873
- size: "medium"
874
- };
875
- class TaskbarManager {
876
- position;
877
- theme;
878
- // e.g., 'windows-xp', 'macos', etc.
879
- size;
880
- constructor(options = defaultTaskbarOptions) {
881
- this.position = options.position || "bottom";
882
- this.theme = options.theme || "default";
883
- this.size = options.size || "medium";
884
- if (options.stateful) ;
885
- }
886
- getDimensions() {
887
- const el = document.querySelector(".taskbar");
888
- if (!el) {
889
- return { width: 0, height: 0 };
890
- }
891
- return {
892
- width: el.clientWidth,
893
- height: el.clientHeight
894
- };
895
- }
896
- }
897
- globalThis.__defussTaskbarManager = globalThis.__defussTaskbarManager || new TaskbarManager();
898
- const taskbarManager = globalThis.__defussTaskbarManager;
899
-
900
903
  const defaultSystemSoundFilePaths = [
901
904
  "/sounds/balloon.ogg",
902
905
  "/sounds/batterycritical.ogg",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "defuss-desktop",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -19,9 +19,9 @@
19
19
  "type": "git"
20
20
  },
21
21
  "scripts": {
22
- "clean": "rm -rf ./dist && rm -rf ./node_modules/.pnpm",
23
- "pretest": "pnpm run build",
24
- "prebuild": "pnpm run clean",
22
+ "clean": "rm -rf ./dist && rm -rf ./node_modules/.bun",
23
+ "pretest": "bun run build",
24
+ "prebuild": "bun run clean",
25
25
  "build": "pkgroll",
26
26
  "postbuild": "npm run copy-scss",
27
27
  "copy-scss": "mkdir -p dist/scss dist/themes && cp index.scss dist/ && cp xp.scss dist/ && cp -r scss/* dist/scss/ && cp -r themes/* dist/themes/",
@@ -53,8 +53,8 @@
53
53
  "node": "^18.17.1 || ^20.3.0 || >=21.0.0"
54
54
  },
55
55
  "dependencies": {
56
- "defuss": "^2.1.10",
57
- "defuss-runtime": "^1.2.1",
56
+ "defuss": "^3.4.0",
57
+ "defuss-runtime": "^1.3.1",
58
58
  "defuss-transval": "^1.3.0"
59
59
  },
60
60
  "devDependencies": {
@@ -65,4 +65,4 @@
65
65
  "typescript": "^5.9.3",
66
66
  "vitest": "^4.0.17"
67
67
  }
68
- }
68
+ }