@hyve-sdk/js 2.5.0-canary.1 → 2.5.0-canary.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/dist/react.d.mts CHANGED
@@ -544,5 +544,91 @@ interface MachineViewProps {
544
544
  * <MachineView machineId="daily-streak" style={{ width: "100%", height: 400 }} />
545
545
  */
546
546
  declare function MachineView({ machineId, className, style }: MachineViewProps): react_jsx_runtime.JSX.Element | null;
547
+ interface MachineViewButtonProps {
548
+ /** The machine ID to pass to MachineView */
549
+ machineId: string;
550
+ /** Button content */
551
+ children?: ReactNode;
552
+ /** Optional className applied to the trigger button */
553
+ className?: string;
554
+ /** Optional inline styles applied to the trigger button */
555
+ style?: CSSProperties;
556
+ /** Optional title shown in the dialog header */
557
+ title?: string;
558
+ /** Width of the dialog panel. Defaults to 520 */
559
+ dialogWidth?: number | string;
560
+ /** Height of the MachineView iframe inside the dialog. Defaults to 400 */
561
+ viewHeight?: number | string;
562
+ }
563
+ /**
564
+ * A button that opens a dialog containing a MachineView for the given machine ID.
565
+ * Must be used within a HyveSdkProvider.
566
+ *
567
+ * @example
568
+ * <MachineViewButton machineId="daily-streak" title="Daily Streak">
569
+ * Open Streak
570
+ * </MachineViewButton>
571
+ */
572
+ declare function MachineViewButton({ machineId, children, className, style, title, dialogWidth, viewHeight, }: MachineViewButtonProps): react_jsx_runtime.JSX.Element;
573
+ interface MachineViewImageButtonProps {
574
+ /** The machine ID to pass to MachineView */
575
+ machineId: string;
576
+ /** Image source URL */
577
+ src: string;
578
+ /** Alt text for the image */
579
+ alt?: string;
580
+ /** Optional className applied to the trigger button */
581
+ className?: string;
582
+ /** Optional inline styles applied to the trigger button */
583
+ style?: CSSProperties;
584
+ /** Optional inline styles applied to the img element */
585
+ imgStyle?: CSSProperties;
586
+ /** Optional title shown in the dialog header */
587
+ title?: string;
588
+ /** Width of the dialog panel. Defaults to 520 */
589
+ dialogWidth?: number | string;
590
+ /** Height of the MachineView iframe inside the dialog. Defaults to 400 */
591
+ viewHeight?: number | string;
592
+ }
593
+ /**
594
+ * An image that acts as a button to open a dialog containing a MachineView.
595
+ * Must be used within a HyveSdkProvider.
596
+ *
597
+ * @example
598
+ * <MachineViewImageButton
599
+ * machineId="daily-streak"
600
+ * src="/icons/streak.png"
601
+ * alt="Daily Streak"
602
+ * title="Daily Streak"
603
+ * imgStyle={{ width: 48, height: 48 }}
604
+ * />
605
+ */
606
+ declare function MachineViewImageButton({ machineId, src, alt, className, style, imgStyle, title, dialogWidth, viewHeight, }: MachineViewImageButtonProps): react_jsx_runtime.JSX.Element;
607
+ interface MachineViewFullscreenProps {
608
+ /** The machine ID to pass to MachineView */
609
+ machineId: string;
610
+ /** Called when the user dismisses the dialog (ESC key or close button) */
611
+ onClose?: () => void;
612
+ /** Optional title shown in the top bar */
613
+ title?: string;
614
+ }
615
+ /**
616
+ * Renders a MachineView fullscreen immediately on mount.
617
+ * Adapts to all viewport sizes including mobile portrait and landscape.
618
+ * Must be used within a HyveSdkProvider.
619
+ *
620
+ * Mount this component to show the fullscreen view; unmount it to hide it.
621
+ *
622
+ * @example
623
+ * // Conditionally render to show/hide
624
+ * {showStreak && (
625
+ * <MachineViewFullscreen
626
+ * machineId="daily-streak"
627
+ * title="Daily Streak"
628
+ * onClose={() => setShowStreak(false)}
629
+ * />
630
+ * )}
631
+ */
632
+ declare function MachineViewFullscreen({ machineId, onClose, title, }: MachineViewFullscreenProps): react_jsx_runtime.JSX.Element;
547
633
 
548
- export { HyveSdkProvider, MachineView, useHyveSdk };
634
+ export { HyveSdkProvider, MachineView, MachineViewButton, MachineViewFullscreen, MachineViewImageButton, useHyveSdk };
package/dist/react.d.ts CHANGED
@@ -544,5 +544,91 @@ interface MachineViewProps {
544
544
  * <MachineView machineId="daily-streak" style={{ width: "100%", height: 400 }} />
545
545
  */
546
546
  declare function MachineView({ machineId, className, style }: MachineViewProps): react_jsx_runtime.JSX.Element | null;
547
+ interface MachineViewButtonProps {
548
+ /** The machine ID to pass to MachineView */
549
+ machineId: string;
550
+ /** Button content */
551
+ children?: ReactNode;
552
+ /** Optional className applied to the trigger button */
553
+ className?: string;
554
+ /** Optional inline styles applied to the trigger button */
555
+ style?: CSSProperties;
556
+ /** Optional title shown in the dialog header */
557
+ title?: string;
558
+ /** Width of the dialog panel. Defaults to 520 */
559
+ dialogWidth?: number | string;
560
+ /** Height of the MachineView iframe inside the dialog. Defaults to 400 */
561
+ viewHeight?: number | string;
562
+ }
563
+ /**
564
+ * A button that opens a dialog containing a MachineView for the given machine ID.
565
+ * Must be used within a HyveSdkProvider.
566
+ *
567
+ * @example
568
+ * <MachineViewButton machineId="daily-streak" title="Daily Streak">
569
+ * Open Streak
570
+ * </MachineViewButton>
571
+ */
572
+ declare function MachineViewButton({ machineId, children, className, style, title, dialogWidth, viewHeight, }: MachineViewButtonProps): react_jsx_runtime.JSX.Element;
573
+ interface MachineViewImageButtonProps {
574
+ /** The machine ID to pass to MachineView */
575
+ machineId: string;
576
+ /** Image source URL */
577
+ src: string;
578
+ /** Alt text for the image */
579
+ alt?: string;
580
+ /** Optional className applied to the trigger button */
581
+ className?: string;
582
+ /** Optional inline styles applied to the trigger button */
583
+ style?: CSSProperties;
584
+ /** Optional inline styles applied to the img element */
585
+ imgStyle?: CSSProperties;
586
+ /** Optional title shown in the dialog header */
587
+ title?: string;
588
+ /** Width of the dialog panel. Defaults to 520 */
589
+ dialogWidth?: number | string;
590
+ /** Height of the MachineView iframe inside the dialog. Defaults to 400 */
591
+ viewHeight?: number | string;
592
+ }
593
+ /**
594
+ * An image that acts as a button to open a dialog containing a MachineView.
595
+ * Must be used within a HyveSdkProvider.
596
+ *
597
+ * @example
598
+ * <MachineViewImageButton
599
+ * machineId="daily-streak"
600
+ * src="/icons/streak.png"
601
+ * alt="Daily Streak"
602
+ * title="Daily Streak"
603
+ * imgStyle={{ width: 48, height: 48 }}
604
+ * />
605
+ */
606
+ declare function MachineViewImageButton({ machineId, src, alt, className, style, imgStyle, title, dialogWidth, viewHeight, }: MachineViewImageButtonProps): react_jsx_runtime.JSX.Element;
607
+ interface MachineViewFullscreenProps {
608
+ /** The machine ID to pass to MachineView */
609
+ machineId: string;
610
+ /** Called when the user dismisses the dialog (ESC key or close button) */
611
+ onClose?: () => void;
612
+ /** Optional title shown in the top bar */
613
+ title?: string;
614
+ }
615
+ /**
616
+ * Renders a MachineView fullscreen immediately on mount.
617
+ * Adapts to all viewport sizes including mobile portrait and landscape.
618
+ * Must be used within a HyveSdkProvider.
619
+ *
620
+ * Mount this component to show the fullscreen view; unmount it to hide it.
621
+ *
622
+ * @example
623
+ * // Conditionally render to show/hide
624
+ * {showStreak && (
625
+ * <MachineViewFullscreen
626
+ * machineId="daily-streak"
627
+ * title="Daily Streak"
628
+ * onClose={() => setShowStreak(false)}
629
+ * />
630
+ * )}
631
+ */
632
+ declare function MachineViewFullscreen({ machineId, onClose, title, }: MachineViewFullscreenProps): react_jsx_runtime.JSX.Element;
547
633
 
548
- export { HyveSdkProvider, MachineView, useHyveSdk };
634
+ export { HyveSdkProvider, MachineView, MachineViewButton, MachineViewFullscreen, MachineViewImageButton, useHyveSdk };
package/dist/react.js CHANGED
@@ -22,6 +22,9 @@ var react_exports = {};
22
22
  __export(react_exports, {
23
23
  HyveSdkProvider: () => HyveSdkProvider,
24
24
  MachineView: () => MachineView,
25
+ MachineViewButton: () => MachineViewButton,
26
+ MachineViewFullscreen: () => MachineViewFullscreen,
27
+ MachineViewImageButton: () => MachineViewImageButton,
25
28
  useHyveSdk: () => useHyveSdk
26
29
  });
27
30
  module.exports = __toCommonJS(react_exports);
@@ -2293,9 +2296,290 @@ function MachineView({ machineId, className, style }) {
2293
2296
  }
2294
2297
  );
2295
2298
  }
2299
+ var OVERLAY_STYLE = {
2300
+ position: "fixed",
2301
+ inset: 0,
2302
+ zIndex: 9999,
2303
+ display: "flex",
2304
+ alignItems: "center",
2305
+ justifyContent: "center",
2306
+ backgroundColor: "rgba(0, 0, 0, 0.6)",
2307
+ padding: "16px"
2308
+ };
2309
+ var PANEL_STYLE = {
2310
+ position: "relative",
2311
+ backgroundColor: "#ffffff",
2312
+ borderRadius: "12px",
2313
+ overflow: "hidden",
2314
+ boxShadow: "0 20px 60px rgba(0, 0, 0, 0.35)",
2315
+ display: "flex",
2316
+ flexDirection: "column",
2317
+ width: "100%"
2318
+ };
2319
+ var HEADER_STYLE = {
2320
+ display: "flex",
2321
+ alignItems: "center",
2322
+ justifyContent: "space-between",
2323
+ padding: "16px 20px",
2324
+ borderBottom: "1px solid #e5e7eb",
2325
+ flexShrink: 0
2326
+ };
2327
+ var TITLE_STYLE = {
2328
+ margin: 0,
2329
+ fontSize: "16px",
2330
+ fontWeight: 600,
2331
+ color: "#111827",
2332
+ lineHeight: 1.4
2333
+ };
2334
+ var CLOSE_BUTTON_BASE = {
2335
+ display: "flex",
2336
+ alignItems: "center",
2337
+ justifyContent: "center",
2338
+ width: "32px",
2339
+ height: "32px",
2340
+ border: "none",
2341
+ borderRadius: "6px",
2342
+ cursor: "pointer",
2343
+ backgroundColor: "transparent",
2344
+ color: "#6b7280",
2345
+ fontSize: "20px",
2346
+ lineHeight: 1,
2347
+ flexShrink: 0
2348
+ };
2349
+ var CLOSE_BUTTON_ABSOLUTE = {
2350
+ ...CLOSE_BUTTON_BASE,
2351
+ position: "absolute",
2352
+ top: "10px",
2353
+ right: "10px",
2354
+ zIndex: 1
2355
+ };
2356
+ function MachineViewDialog({
2357
+ machineId,
2358
+ open,
2359
+ onClose,
2360
+ title,
2361
+ dialogWidth,
2362
+ viewHeight
2363
+ }) {
2364
+ (0, import_react.useEffect)(() => {
2365
+ if (!open) return;
2366
+ const onKeyDown = (e) => {
2367
+ if (e.key === "Escape") onClose();
2368
+ };
2369
+ window.addEventListener("keydown", onKeyDown);
2370
+ return () => window.removeEventListener("keydown", onKeyDown);
2371
+ }, [open, onClose]);
2372
+ if (!open) return null;
2373
+ const panelWidth = typeof dialogWidth === "number" ? `${dialogWidth}px` : dialogWidth;
2374
+ const iframeHeight = typeof viewHeight === "number" ? `${viewHeight}px` : viewHeight;
2375
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2376
+ "div",
2377
+ {
2378
+ style: OVERLAY_STYLE,
2379
+ onClick: (e) => {
2380
+ if (e.target === e.currentTarget) onClose();
2381
+ },
2382
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...PANEL_STYLE, maxWidth: panelWidth }, children: [
2383
+ title ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: HEADER_STYLE, children: [
2384
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: TITLE_STYLE, children: title }),
2385
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2386
+ "button",
2387
+ {
2388
+ style: CLOSE_BUTTON_BASE,
2389
+ onClick: onClose,
2390
+ "aria-label": "Close dialog",
2391
+ children: "\u2715"
2392
+ }
2393
+ )
2394
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2395
+ "button",
2396
+ {
2397
+ style: CLOSE_BUTTON_ABSOLUTE,
2398
+ onClick: onClose,
2399
+ "aria-label": "Close dialog",
2400
+ children: "\u2715"
2401
+ }
2402
+ ),
2403
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2404
+ MachineView,
2405
+ {
2406
+ machineId,
2407
+ style: {
2408
+ width: "100%",
2409
+ height: iframeHeight,
2410
+ border: "none",
2411
+ display: "block"
2412
+ }
2413
+ }
2414
+ )
2415
+ ] })
2416
+ }
2417
+ );
2418
+ }
2419
+ function MachineViewButton({
2420
+ machineId,
2421
+ children = "Open",
2422
+ className,
2423
+ style,
2424
+ title,
2425
+ dialogWidth = 520,
2426
+ viewHeight = 400
2427
+ }) {
2428
+ const [open, setOpen] = (0, import_react.useState)(false);
2429
+ const close = (0, import_react.useCallback)(() => setOpen(false), []);
2430
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2431
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className, style, onClick: () => setOpen(true), children }),
2432
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2433
+ MachineViewDialog,
2434
+ {
2435
+ machineId,
2436
+ open,
2437
+ onClose: close,
2438
+ title,
2439
+ dialogWidth,
2440
+ viewHeight
2441
+ }
2442
+ )
2443
+ ] });
2444
+ }
2445
+ var IMAGE_BUTTON_STYLE = {
2446
+ padding: 0,
2447
+ border: "none",
2448
+ background: "none",
2449
+ cursor: "pointer",
2450
+ display: "inline-flex",
2451
+ alignItems: "center",
2452
+ justifyContent: "center"
2453
+ };
2454
+ function MachineViewImageButton({
2455
+ machineId,
2456
+ src,
2457
+ alt = "",
2458
+ className,
2459
+ style,
2460
+ imgStyle,
2461
+ title,
2462
+ dialogWidth = 520,
2463
+ viewHeight = 400
2464
+ }) {
2465
+ const [open, setOpen] = (0, import_react.useState)(false);
2466
+ const close = (0, import_react.useCallback)(() => setOpen(false), []);
2467
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2468
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2469
+ "button",
2470
+ {
2471
+ className,
2472
+ style: { ...IMAGE_BUTTON_STYLE, ...style },
2473
+ onClick: () => setOpen(true),
2474
+ "aria-label": alt || title || "Open",
2475
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src, alt, style: imgStyle })
2476
+ }
2477
+ ),
2478
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2479
+ MachineViewDialog,
2480
+ {
2481
+ machineId,
2482
+ open,
2483
+ onClose: close,
2484
+ title,
2485
+ dialogWidth,
2486
+ viewHeight
2487
+ }
2488
+ )
2489
+ ] });
2490
+ }
2491
+ var FULLSCREEN_CONTAINER_STYLE = {
2492
+ position: "fixed",
2493
+ inset: 0,
2494
+ zIndex: 9999,
2495
+ display: "flex",
2496
+ flexDirection: "column",
2497
+ backgroundColor: "#ffffff"
2498
+ };
2499
+ var FULLSCREEN_TOPBAR_STYLE = {
2500
+ display: "flex",
2501
+ alignItems: "center",
2502
+ justifyContent: "space-between",
2503
+ height: "52px",
2504
+ minHeight: "52px",
2505
+ padding: "0 12px 0 20px",
2506
+ borderBottom: "1px solid #e5e7eb",
2507
+ flexShrink: 0
2508
+ };
2509
+ var FULLSCREEN_TITLE_STYLE = {
2510
+ margin: 0,
2511
+ fontSize: "16px",
2512
+ fontWeight: 600,
2513
+ color: "#111827",
2514
+ lineHeight: 1.4,
2515
+ overflow: "hidden",
2516
+ whiteSpace: "nowrap",
2517
+ textOverflow: "ellipsis"
2518
+ };
2519
+ var FULLSCREEN_CLOSE_STYLE = {
2520
+ display: "flex",
2521
+ alignItems: "center",
2522
+ justifyContent: "center",
2523
+ width: "44px",
2524
+ height: "44px",
2525
+ border: "none",
2526
+ borderRadius: "8px",
2527
+ cursor: "pointer",
2528
+ backgroundColor: "transparent",
2529
+ color: "#6b7280",
2530
+ fontSize: "20px",
2531
+ lineHeight: 1,
2532
+ flexShrink: 0
2533
+ };
2534
+ var FULLSCREEN_IFRAME_STYLE = {
2535
+ flex: 1,
2536
+ minHeight: 0,
2537
+ width: "100%",
2538
+ border: "none",
2539
+ display: "block"
2540
+ };
2541
+ function MachineViewFullscreen({
2542
+ machineId,
2543
+ onClose,
2544
+ title
2545
+ }) {
2546
+ (0, import_react.useEffect)(() => {
2547
+ const prev = document.body.style.overflow;
2548
+ document.body.style.overflow = "hidden";
2549
+ return () => {
2550
+ document.body.style.overflow = prev;
2551
+ };
2552
+ }, []);
2553
+ (0, import_react.useEffect)(() => {
2554
+ if (!onClose) return;
2555
+ const onKeyDown = (e) => {
2556
+ if (e.key === "Escape") onClose();
2557
+ };
2558
+ window.addEventListener("keydown", onKeyDown);
2559
+ return () => window.removeEventListener("keydown", onKeyDown);
2560
+ }, [onClose]);
2561
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: FULLSCREEN_CONTAINER_STYLE, children: [
2562
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: FULLSCREEN_TOPBAR_STYLE, children: [
2563
+ title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: FULLSCREEN_TITLE_STYLE, children: title }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {}),
2564
+ onClose && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2565
+ "button",
2566
+ {
2567
+ style: FULLSCREEN_CLOSE_STYLE,
2568
+ onClick: onClose,
2569
+ "aria-label": "Close",
2570
+ children: "\u2715"
2571
+ }
2572
+ )
2573
+ ] }),
2574
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MachineView, { machineId, style: FULLSCREEN_IFRAME_STYLE })
2575
+ ] });
2576
+ }
2296
2577
  // Annotate the CommonJS export names for ESM import in node:
2297
2578
  0 && (module.exports = {
2298
2579
  HyveSdkProvider,
2299
2580
  MachineView,
2581
+ MachineViewButton,
2582
+ MachineViewFullscreen,
2583
+ MachineViewImageButton,
2300
2584
  useHyveSdk
2301
2585
  });
package/dist/react.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  // src/react.tsx
2
2
  import {
3
3
  createContext,
4
+ useCallback,
4
5
  useContext,
5
6
  useEffect,
6
7
  useRef,
@@ -2187,7 +2188,7 @@ var HyveClient = class {
2187
2188
  };
2188
2189
 
2189
2190
  // src/react.tsx
2190
- import { jsx } from "react/jsx-runtime";
2191
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2191
2192
  var HyveSdkContext = createContext(null);
2192
2193
  function HyveSdkProvider({
2193
2194
  client,
@@ -2273,8 +2274,289 @@ function MachineView({ machineId, className, style }) {
2273
2274
  }
2274
2275
  );
2275
2276
  }
2277
+ var OVERLAY_STYLE = {
2278
+ position: "fixed",
2279
+ inset: 0,
2280
+ zIndex: 9999,
2281
+ display: "flex",
2282
+ alignItems: "center",
2283
+ justifyContent: "center",
2284
+ backgroundColor: "rgba(0, 0, 0, 0.6)",
2285
+ padding: "16px"
2286
+ };
2287
+ var PANEL_STYLE = {
2288
+ position: "relative",
2289
+ backgroundColor: "#ffffff",
2290
+ borderRadius: "12px",
2291
+ overflow: "hidden",
2292
+ boxShadow: "0 20px 60px rgba(0, 0, 0, 0.35)",
2293
+ display: "flex",
2294
+ flexDirection: "column",
2295
+ width: "100%"
2296
+ };
2297
+ var HEADER_STYLE = {
2298
+ display: "flex",
2299
+ alignItems: "center",
2300
+ justifyContent: "space-between",
2301
+ padding: "16px 20px",
2302
+ borderBottom: "1px solid #e5e7eb",
2303
+ flexShrink: 0
2304
+ };
2305
+ var TITLE_STYLE = {
2306
+ margin: 0,
2307
+ fontSize: "16px",
2308
+ fontWeight: 600,
2309
+ color: "#111827",
2310
+ lineHeight: 1.4
2311
+ };
2312
+ var CLOSE_BUTTON_BASE = {
2313
+ display: "flex",
2314
+ alignItems: "center",
2315
+ justifyContent: "center",
2316
+ width: "32px",
2317
+ height: "32px",
2318
+ border: "none",
2319
+ borderRadius: "6px",
2320
+ cursor: "pointer",
2321
+ backgroundColor: "transparent",
2322
+ color: "#6b7280",
2323
+ fontSize: "20px",
2324
+ lineHeight: 1,
2325
+ flexShrink: 0
2326
+ };
2327
+ var CLOSE_BUTTON_ABSOLUTE = {
2328
+ ...CLOSE_BUTTON_BASE,
2329
+ position: "absolute",
2330
+ top: "10px",
2331
+ right: "10px",
2332
+ zIndex: 1
2333
+ };
2334
+ function MachineViewDialog({
2335
+ machineId,
2336
+ open,
2337
+ onClose,
2338
+ title,
2339
+ dialogWidth,
2340
+ viewHeight
2341
+ }) {
2342
+ useEffect(() => {
2343
+ if (!open) return;
2344
+ const onKeyDown = (e) => {
2345
+ if (e.key === "Escape") onClose();
2346
+ };
2347
+ window.addEventListener("keydown", onKeyDown);
2348
+ return () => window.removeEventListener("keydown", onKeyDown);
2349
+ }, [open, onClose]);
2350
+ if (!open) return null;
2351
+ const panelWidth = typeof dialogWidth === "number" ? `${dialogWidth}px` : dialogWidth;
2352
+ const iframeHeight = typeof viewHeight === "number" ? `${viewHeight}px` : viewHeight;
2353
+ return /* @__PURE__ */ jsx(
2354
+ "div",
2355
+ {
2356
+ style: OVERLAY_STYLE,
2357
+ onClick: (e) => {
2358
+ if (e.target === e.currentTarget) onClose();
2359
+ },
2360
+ children: /* @__PURE__ */ jsxs("div", { style: { ...PANEL_STYLE, maxWidth: panelWidth }, children: [
2361
+ title ? /* @__PURE__ */ jsxs("div", { style: HEADER_STYLE, children: [
2362
+ /* @__PURE__ */ jsx("p", { style: TITLE_STYLE, children: title }),
2363
+ /* @__PURE__ */ jsx(
2364
+ "button",
2365
+ {
2366
+ style: CLOSE_BUTTON_BASE,
2367
+ onClick: onClose,
2368
+ "aria-label": "Close dialog",
2369
+ children: "\u2715"
2370
+ }
2371
+ )
2372
+ ] }) : /* @__PURE__ */ jsx(
2373
+ "button",
2374
+ {
2375
+ style: CLOSE_BUTTON_ABSOLUTE,
2376
+ onClick: onClose,
2377
+ "aria-label": "Close dialog",
2378
+ children: "\u2715"
2379
+ }
2380
+ ),
2381
+ /* @__PURE__ */ jsx(
2382
+ MachineView,
2383
+ {
2384
+ machineId,
2385
+ style: {
2386
+ width: "100%",
2387
+ height: iframeHeight,
2388
+ border: "none",
2389
+ display: "block"
2390
+ }
2391
+ }
2392
+ )
2393
+ ] })
2394
+ }
2395
+ );
2396
+ }
2397
+ function MachineViewButton({
2398
+ machineId,
2399
+ children = "Open",
2400
+ className,
2401
+ style,
2402
+ title,
2403
+ dialogWidth = 520,
2404
+ viewHeight = 400
2405
+ }) {
2406
+ const [open, setOpen] = useState(false);
2407
+ const close = useCallback(() => setOpen(false), []);
2408
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2409
+ /* @__PURE__ */ jsx("button", { className, style, onClick: () => setOpen(true), children }),
2410
+ /* @__PURE__ */ jsx(
2411
+ MachineViewDialog,
2412
+ {
2413
+ machineId,
2414
+ open,
2415
+ onClose: close,
2416
+ title,
2417
+ dialogWidth,
2418
+ viewHeight
2419
+ }
2420
+ )
2421
+ ] });
2422
+ }
2423
+ var IMAGE_BUTTON_STYLE = {
2424
+ padding: 0,
2425
+ border: "none",
2426
+ background: "none",
2427
+ cursor: "pointer",
2428
+ display: "inline-flex",
2429
+ alignItems: "center",
2430
+ justifyContent: "center"
2431
+ };
2432
+ function MachineViewImageButton({
2433
+ machineId,
2434
+ src,
2435
+ alt = "",
2436
+ className,
2437
+ style,
2438
+ imgStyle,
2439
+ title,
2440
+ dialogWidth = 520,
2441
+ viewHeight = 400
2442
+ }) {
2443
+ const [open, setOpen] = useState(false);
2444
+ const close = useCallback(() => setOpen(false), []);
2445
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2446
+ /* @__PURE__ */ jsx(
2447
+ "button",
2448
+ {
2449
+ className,
2450
+ style: { ...IMAGE_BUTTON_STYLE, ...style },
2451
+ onClick: () => setOpen(true),
2452
+ "aria-label": alt || title || "Open",
2453
+ children: /* @__PURE__ */ jsx("img", { src, alt, style: imgStyle })
2454
+ }
2455
+ ),
2456
+ /* @__PURE__ */ jsx(
2457
+ MachineViewDialog,
2458
+ {
2459
+ machineId,
2460
+ open,
2461
+ onClose: close,
2462
+ title,
2463
+ dialogWidth,
2464
+ viewHeight
2465
+ }
2466
+ )
2467
+ ] });
2468
+ }
2469
+ var FULLSCREEN_CONTAINER_STYLE = {
2470
+ position: "fixed",
2471
+ inset: 0,
2472
+ zIndex: 9999,
2473
+ display: "flex",
2474
+ flexDirection: "column",
2475
+ backgroundColor: "#ffffff"
2476
+ };
2477
+ var FULLSCREEN_TOPBAR_STYLE = {
2478
+ display: "flex",
2479
+ alignItems: "center",
2480
+ justifyContent: "space-between",
2481
+ height: "52px",
2482
+ minHeight: "52px",
2483
+ padding: "0 12px 0 20px",
2484
+ borderBottom: "1px solid #e5e7eb",
2485
+ flexShrink: 0
2486
+ };
2487
+ var FULLSCREEN_TITLE_STYLE = {
2488
+ margin: 0,
2489
+ fontSize: "16px",
2490
+ fontWeight: 600,
2491
+ color: "#111827",
2492
+ lineHeight: 1.4,
2493
+ overflow: "hidden",
2494
+ whiteSpace: "nowrap",
2495
+ textOverflow: "ellipsis"
2496
+ };
2497
+ var FULLSCREEN_CLOSE_STYLE = {
2498
+ display: "flex",
2499
+ alignItems: "center",
2500
+ justifyContent: "center",
2501
+ width: "44px",
2502
+ height: "44px",
2503
+ border: "none",
2504
+ borderRadius: "8px",
2505
+ cursor: "pointer",
2506
+ backgroundColor: "transparent",
2507
+ color: "#6b7280",
2508
+ fontSize: "20px",
2509
+ lineHeight: 1,
2510
+ flexShrink: 0
2511
+ };
2512
+ var FULLSCREEN_IFRAME_STYLE = {
2513
+ flex: 1,
2514
+ minHeight: 0,
2515
+ width: "100%",
2516
+ border: "none",
2517
+ display: "block"
2518
+ };
2519
+ function MachineViewFullscreen({
2520
+ machineId,
2521
+ onClose,
2522
+ title
2523
+ }) {
2524
+ useEffect(() => {
2525
+ const prev = document.body.style.overflow;
2526
+ document.body.style.overflow = "hidden";
2527
+ return () => {
2528
+ document.body.style.overflow = prev;
2529
+ };
2530
+ }, []);
2531
+ useEffect(() => {
2532
+ if (!onClose) return;
2533
+ const onKeyDown = (e) => {
2534
+ if (e.key === "Escape") onClose();
2535
+ };
2536
+ window.addEventListener("keydown", onKeyDown);
2537
+ return () => window.removeEventListener("keydown", onKeyDown);
2538
+ }, [onClose]);
2539
+ return /* @__PURE__ */ jsxs("div", { style: FULLSCREEN_CONTAINER_STYLE, children: [
2540
+ /* @__PURE__ */ jsxs("div", { style: FULLSCREEN_TOPBAR_STYLE, children: [
2541
+ title ? /* @__PURE__ */ jsx("p", { style: FULLSCREEN_TITLE_STYLE, children: title }) : /* @__PURE__ */ jsx("span", {}),
2542
+ onClose && /* @__PURE__ */ jsx(
2543
+ "button",
2544
+ {
2545
+ style: FULLSCREEN_CLOSE_STYLE,
2546
+ onClick: onClose,
2547
+ "aria-label": "Close",
2548
+ children: "\u2715"
2549
+ }
2550
+ )
2551
+ ] }),
2552
+ /* @__PURE__ */ jsx(MachineView, { machineId, style: FULLSCREEN_IFRAME_STYLE })
2553
+ ] });
2554
+ }
2276
2555
  export {
2277
2556
  HyveSdkProvider,
2278
2557
  MachineView,
2558
+ MachineViewButton,
2559
+ MachineViewFullscreen,
2560
+ MachineViewImageButton,
2279
2561
  useHyveSdk
2280
2562
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyve-sdk/js",
3
- "version": "2.5.0-canary.1",
3
+ "version": "2.5.0-canary.2",
4
4
  "description": "Hyve SDK - TypeScript wrapper for Hyve game server integration",
5
5
  "private": false,
6
6
  "publishConfig": {