@moldable-ai/ui 0.2.18 → 0.2.19
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/components/chat/chat-panel.d.ts +18 -12
- package/dist/components/chat/chat-panel.d.ts.map +1 -1
- package/dist/components/chat/chat-panel.js +73 -19
- package/dist/components/chat/index.d.ts +2 -1
- package/dist/components/chat/index.d.ts.map +1 -1
- package/dist/components/chat/index.js +2 -1
- package/dist/components/chat/model-effort-power-effects.d.ts +7 -0
- package/dist/components/chat/model-effort-power-effects.d.ts.map +1 -0
- package/dist/components/chat/model-effort-power-effects.js +54 -0
- package/dist/components/chat/model-effort-selector.d.ts +26 -0
- package/dist/components/chat/model-effort-selector.d.ts.map +1 -0
- package/dist/components/chat/model-effort-selector.js +179 -0
- package/dist/components/chat/model-effort-ultra-effects.d.ts +5 -0
- package/dist/components/chat/model-effort-ultra-effects.d.ts.map +1 -0
- package/dist/components/chat/model-effort-ultra-effects.js +56 -0
- package/dist/components/hardware/bluetooth-panel-helpers.d.ts +9 -0
- package/dist/components/hardware/bluetooth-panel-helpers.d.ts.map +1 -0
- package/dist/components/hardware/bluetooth-panel-helpers.js +37 -0
- package/dist/components/hardware/bluetooth-panel.d.ts +56 -0
- package/dist/components/hardware/bluetooth-panel.d.ts.map +1 -0
- package/dist/components/hardware/bluetooth-panel.js +470 -0
- package/dist/components/hardware/camera-preview.d.ts +39 -0
- package/dist/components/hardware/camera-preview.d.ts.map +1 -0
- package/dist/components/hardware/camera-preview.js +228 -0
- package/dist/components/hardware/capability-badge.d.ts +23 -0
- package/dist/components/hardware/capability-badge.d.ts.map +1 -0
- package/dist/components/hardware/capability-badge.js +39 -0
- package/dist/components/hardware/capability-matrix.d.ts +14 -0
- package/dist/components/hardware/capability-matrix.d.ts.map +1 -0
- package/dist/components/hardware/capability-matrix.js +97 -0
- package/dist/components/hardware/clipboard-button.d.ts +26 -0
- package/dist/components/hardware/clipboard-button.d.ts.map +1 -0
- package/dist/components/hardware/clipboard-button.js +114 -0
- package/dist/components/hardware/device-io-controls.d.ts +4 -0
- package/dist/components/hardware/device-io-controls.d.ts.map +1 -0
- package/dist/components/hardware/device-io-controls.js +28 -0
- package/dist/components/hardware/device-list.d.ts +20 -0
- package/dist/components/hardware/device-list.d.ts.map +1 -0
- package/dist/components/hardware/device-list.js +14 -0
- package/dist/components/hardware/display-map.d.ts +23 -0
- package/dist/components/hardware/display-map.d.ts.map +1 -0
- package/dist/components/hardware/display-map.js +114 -0
- package/dist/components/hardware/haptic-button.d.ts +26 -0
- package/dist/components/hardware/haptic-button.d.ts.map +1 -0
- package/dist/components/hardware/haptic-button.js +94 -0
- package/dist/components/hardware/hardware-panel.d.ts +11 -0
- package/dist/components/hardware/hardware-panel.d.ts.map +1 -0
- package/dist/components/hardware/hardware-panel.js +28 -0
- package/dist/components/hardware/hid-panel.d.ts +40 -0
- package/dist/components/hardware/hid-panel.d.ts.map +1 -0
- package/dist/components/hardware/hid-panel.js +373 -0
- package/dist/components/hardware/index.d.ts +27 -0
- package/dist/components/hardware/index.d.ts.map +1 -0
- package/dist/components/hardware/index.js +26 -0
- package/dist/components/hardware/live-indicator.d.ts +15 -0
- package/dist/components/hardware/live-indicator.d.ts.map +1 -0
- package/dist/components/hardware/live-indicator.js +26 -0
- package/dist/components/hardware/local-auth-button.d.ts +33 -0
- package/dist/components/hardware/local-auth-button.d.ts.map +1 -0
- package/dist/components/hardware/local-auth-button.js +115 -0
- package/dist/components/hardware/location-panel.d.ts +29 -0
- package/dist/components/hardware/location-panel.d.ts.map +1 -0
- package/dist/components/hardware/location-panel.js +154 -0
- package/dist/components/hardware/microphone-meter.d.ts +35 -0
- package/dist/components/hardware/microphone-meter.d.ts.map +1 -0
- package/dist/components/hardware/microphone-meter.js +244 -0
- package/dist/components/hardware/midi-monitor.d.ts +54 -0
- package/dist/components/hardware/midi-monitor.d.ts.map +1 -0
- package/dist/components/hardware/midi-monitor.js +534 -0
- package/dist/components/hardware/notification-panel.d.ts +24 -0
- package/dist/components/hardware/notification-panel.d.ts.map +1 -0
- package/dist/components/hardware/notification-panel.js +124 -0
- package/dist/components/hardware/power-blocker-controller.d.ts +19 -0
- package/dist/components/hardware/power-blocker-controller.d.ts.map +1 -0
- package/dist/components/hardware/power-blocker-controller.js +83 -0
- package/dist/components/hardware/power-panel.d.ts +67 -0
- package/dist/components/hardware/power-panel.d.ts.map +1 -0
- package/dist/components/hardware/power-panel.js +309 -0
- package/dist/components/hardware/readout.d.ts +10 -0
- package/dist/components/hardware/readout.d.ts.map +1 -0
- package/dist/components/hardware/readout.js +11 -0
- package/dist/components/hardware/screen-share-preview.d.ts +36 -0
- package/dist/components/hardware/screen-share-preview.d.ts.map +1 -0
- package/dist/components/hardware/screen-share-preview.js +191 -0
- package/dist/components/hardware/secure-storage-panel.d.ts +36 -0
- package/dist/components/hardware/secure-storage-panel.d.ts.map +1 -0
- package/dist/components/hardware/secure-storage-panel.js +193 -0
- package/dist/components/hardware/serial-console.d.ts +64 -0
- package/dist/components/hardware/serial-console.d.ts.map +1 -0
- package/dist/components/hardware/serial-console.js +399 -0
- package/dist/components/hardware/shortcut-recorder.d.ts +35 -0
- package/dist/components/hardware/shortcut-recorder.d.ts.map +1 -0
- package/dist/components/hardware/shortcut-recorder.js +217 -0
- package/dist/components/hardware/stream-log.d.ts +35 -0
- package/dist/components/hardware/stream-log.d.ts.map +1 -0
- package/dist/components/hardware/stream-log.js +65 -0
- package/dist/components/hardware/system-audio-monitor.d.ts +34 -0
- package/dist/components/hardware/system-audio-monitor.d.ts.map +1 -0
- package/dist/components/hardware/system-audio-monitor.js +275 -0
- package/dist/components/hardware/usb-panel.d.ts +54 -0
- package/dist/components/hardware/usb-panel.d.ts.map +1 -0
- package/dist/components/hardware/usb-panel.js +363 -0
- package/dist/components/hardware/use-capability.d.ts +20 -0
- package/dist/components/hardware/use-capability.d.ts.map +1 -0
- package/dist/components/hardware/use-capability.js +61 -0
- package/dist/components/ui/input-group.d.ts +1 -1
- package/dist/components/ui/slider.d.ts +4 -1
- package/dist/components/ui/slider.d.ts.map +1 -1
- package/dist/components/ui/slider.js +2 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/lib/native-hardware/bluetooth-access.d.ts +14 -0
- package/dist/lib/native-hardware/bluetooth-access.d.ts.map +1 -0
- package/dist/lib/native-hardware/bluetooth-access.js +40 -0
- package/dist/lib/native-hardware/bluetooth-connection.d.ts +19 -0
- package/dist/lib/native-hardware/bluetooth-connection.d.ts.map +1 -0
- package/dist/lib/native-hardware/bluetooth-connection.js +88 -0
- package/dist/lib/native-hardware/bluetooth-gatt.d.ts +7 -0
- package/dist/lib/native-hardware/bluetooth-gatt.d.ts.map +1 -0
- package/dist/lib/native-hardware/bluetooth-gatt.js +77 -0
- package/dist/lib/native-hardware/bluetooth-internal.d.ts +10 -0
- package/dist/lib/native-hardware/bluetooth-internal.d.ts.map +1 -0
- package/dist/lib/native-hardware/bluetooth-internal.js +105 -0
- package/dist/lib/native-hardware/bluetooth-native-fallback.d.ts +33 -0
- package/dist/lib/native-hardware/bluetooth-native-fallback.d.ts.map +1 -0
- package/dist/lib/native-hardware/bluetooth-native-fallback.js +214 -0
- package/dist/lib/native-hardware/bluetooth-types.d.ts +85 -0
- package/dist/lib/native-hardware/bluetooth-types.d.ts.map +1 -0
- package/dist/lib/native-hardware/bluetooth-types.js +2 -0
- package/dist/lib/native-hardware/bluetooth.d.ts +7 -0
- package/dist/lib/native-hardware/bluetooth.d.ts.map +1 -0
- package/dist/lib/native-hardware/bluetooth.js +4 -0
- package/dist/lib/native-hardware/bridge.d.ts +23 -0
- package/dist/lib/native-hardware/bridge.d.ts.map +1 -0
- package/dist/lib/native-hardware/bridge.js +266 -0
- package/dist/lib/native-hardware/capabilities.d.ts +7 -0
- package/dist/lib/native-hardware/capabilities.d.ts.map +1 -0
- package/dist/lib/native-hardware/capabilities.js +95 -0
- package/dist/lib/native-hardware/clipboard.d.ts +11 -0
- package/dist/lib/native-hardware/clipboard.d.ts.map +1 -0
- package/dist/lib/native-hardware/clipboard.js +55 -0
- package/dist/lib/native-hardware/device-io-errors.d.ts +11 -0
- package/dist/lib/native-hardware/device-io-errors.d.ts.map +1 -0
- package/dist/lib/native-hardware/device-io-errors.js +82 -0
- package/dist/lib/native-hardware/displays.d.ts +38 -0
- package/dist/lib/native-hardware/displays.d.ts.map +1 -0
- package/dist/lib/native-hardware/displays.js +12 -0
- package/dist/lib/native-hardware/global-shortcuts.d.ts +86 -0
- package/dist/lib/native-hardware/global-shortcuts.d.ts.map +1 -0
- package/dist/lib/native-hardware/global-shortcuts.js +351 -0
- package/dist/lib/native-hardware/haptics.d.ts +25 -0
- package/dist/lib/native-hardware/haptics.d.ts.map +1 -0
- package/dist/lib/native-hardware/haptics.js +18 -0
- package/dist/lib/native-hardware/hid-native.d.ts +26 -0
- package/dist/lib/native-hardware/hid-native.d.ts.map +1 -0
- package/dist/lib/native-hardware/hid-native.js +229 -0
- package/dist/lib/native-hardware/hid.d.ts +52 -0
- package/dist/lib/native-hardware/hid.d.ts.map +1 -0
- package/dist/lib/native-hardware/hid.js +160 -0
- package/dist/lib/native-hardware/index.d.ts +38 -0
- package/dist/lib/native-hardware/index.d.ts.map +1 -0
- package/dist/lib/native-hardware/index.js +20 -0
- package/dist/lib/native-hardware/local-authentication.d.ts +32 -0
- package/dist/lib/native-hardware/local-authentication.d.ts.map +1 -0
- package/dist/lib/native-hardware/local-authentication.js +46 -0
- package/dist/lib/native-hardware/location.d.ts +49 -0
- package/dist/lib/native-hardware/location.d.ts.map +1 -0
- package/dist/lib/native-hardware/location.js +114 -0
- package/dist/lib/native-hardware/media-permissions.d.ts +28 -0
- package/dist/lib/native-hardware/media-permissions.d.ts.map +1 -0
- package/dist/lib/native-hardware/media-permissions.js +37 -0
- package/dist/lib/native-hardware/media.d.ts +17 -0
- package/dist/lib/native-hardware/media.d.ts.map +1 -0
- package/dist/lib/native-hardware/media.js +99 -0
- package/dist/lib/native-hardware/midi-access.d.ts +13 -0
- package/dist/lib/native-hardware/midi-access.d.ts.map +1 -0
- package/dist/lib/native-hardware/midi-access.js +66 -0
- package/dist/lib/native-hardware/midi-internal.d.ts +12 -0
- package/dist/lib/native-hardware/midi-internal.d.ts.map +1 -0
- package/dist/lib/native-hardware/midi-internal.js +88 -0
- package/dist/lib/native-hardware/midi-native-fallback.d.ts +27 -0
- package/dist/lib/native-hardware/midi-native-fallback.d.ts.map +1 -0
- package/dist/lib/native-hardware/midi-native-fallback.js +127 -0
- package/dist/lib/native-hardware/midi-ports.d.ts +6 -0
- package/dist/lib/native-hardware/midi-ports.d.ts.map +1 -0
- package/dist/lib/native-hardware/midi-ports.js +115 -0
- package/dist/lib/native-hardware/midi-types.d.ts +25 -0
- package/dist/lib/native-hardware/midi-types.d.ts.map +1 -0
- package/dist/lib/native-hardware/midi-types.js +1 -0
- package/dist/lib/native-hardware/midi.d.ts +6 -0
- package/dist/lib/native-hardware/midi.d.ts.map +1 -0
- package/dist/lib/native-hardware/midi.js +3 -0
- package/dist/lib/native-hardware/native-device-io.d.ts +28 -0
- package/dist/lib/native-hardware/native-device-io.d.ts.map +1 -0
- package/dist/lib/native-hardware/native-device-io.js +91 -0
- package/dist/lib/native-hardware/native-device-lifecycle.d.ts +13 -0
- package/dist/lib/native-hardware/native-device-lifecycle.d.ts.map +1 -0
- package/dist/lib/native-hardware/native-device-lifecycle.js +40 -0
- package/dist/lib/native-hardware/notifications.d.ts +38 -0
- package/dist/lib/native-hardware/notifications.d.ts.map +1 -0
- package/dist/lib/native-hardware/notifications.js +50 -0
- package/dist/lib/native-hardware/power-session.d.ts +113 -0
- package/dist/lib/native-hardware/power-session.d.ts.map +1 -0
- package/dist/lib/native-hardware/power-session.js +264 -0
- package/dist/lib/native-hardware/secure-storage.d.ts +36 -0
- package/dist/lib/native-hardware/secure-storage.d.ts.map +1 -0
- package/dist/lib/native-hardware/secure-storage.js +64 -0
- package/dist/lib/native-hardware/serial-native.d.ts +23 -0
- package/dist/lib/native-hardware/serial-native.d.ts.map +1 -0
- package/dist/lib/native-hardware/serial-native.js +181 -0
- package/dist/lib/native-hardware/serial.d.ts +76 -0
- package/dist/lib/native-hardware/serial.d.ts.map +1 -0
- package/dist/lib/native-hardware/serial.js +212 -0
- package/dist/lib/native-hardware/system-audio.d.ts +127 -0
- package/dist/lib/native-hardware/system-audio.d.ts.map +1 -0
- package/dist/lib/native-hardware/system-audio.js +330 -0
- package/dist/lib/native-hardware/types.d.ts +62 -0
- package/dist/lib/native-hardware/types.d.ts.map +1 -0
- package/dist/lib/native-hardware/types.js +27 -0
- package/dist/lib/native-hardware/usb-native.d.ts +39 -0
- package/dist/lib/native-hardware/usb-native.d.ts.map +1 -0
- package/dist/lib/native-hardware/usb-native.js +217 -0
- package/dist/lib/native-hardware/usb.d.ts +85 -0
- package/dist/lib/native-hardware/usb.d.ts.map +1 -0
- package/dist/lib/native-hardware/usb.js +222 -0
- package/package.json +1 -1
- package/src/styles/index.css +377 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
declare function DeviceList({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export interface DeviceListItemProps extends React.ComponentProps<'div'> {
|
|
4
|
+
/** Icon shown in the leading square well. */
|
|
5
|
+
icon?: React.ReactNode;
|
|
6
|
+
name: React.ReactNode;
|
|
7
|
+
/** Secondary line, rendered in mono (IDs, vendor codes, paths). */
|
|
8
|
+
description?: React.ReactNode;
|
|
9
|
+
/** Shows a green dot + "Connected" next to the name. */
|
|
10
|
+
connected?: boolean;
|
|
11
|
+
/** Trailing actions (buttons, badges). */
|
|
12
|
+
action?: React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
declare function DeviceListItem({ icon, name, description, connected, action, className, children, ...props }: DeviceListItemProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export interface DeviceListEmptyProps extends React.ComponentProps<'div'> {
|
|
16
|
+
icon?: React.ReactNode;
|
|
17
|
+
}
|
|
18
|
+
declare function DeviceListEmpty({ icon, className, children, ...props }: DeviceListEmptyProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export { DeviceList, DeviceListItem, DeviceListEmpty };
|
|
20
|
+
//# sourceMappingURL=device-list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-list.d.ts","sourceRoot":"","sources":["../../../src/components/hardware/device-list.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAYvE;AAED,MAAM,WAAW,mBAAoB,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IACtE,6CAA6C;IAC7C,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,IAAI,EAAE,KAAK,CAAC,SAAS,CAAA;IACrB,mEAAmE;IACnE,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC7B,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACzB;AAED,iBAAS,cAAc,CAAC,EACtB,IAAI,EACJ,IAAI,EACJ,WAAW,EACX,SAAiB,EACjB,MAAM,EACN,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,mBAAmB,2CA2DrB;AAED,MAAM,WAAW,oBAAqB,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IACvE,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACvB;AAED,iBAAS,eAAe,CAAC,EACvB,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,oBAAoB,2CAkBtB;AAED,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,eAAe,EAAE,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from '../../lib/utils';
|
|
4
|
+
function DeviceList({ className, ...props }) {
|
|
5
|
+
return (_jsx("div", { "data-slot": "device-list", role: "list", className: cn('divide-border divide-y overflow-hidden rounded-lg border', className), ...props }));
|
|
6
|
+
}
|
|
7
|
+
function DeviceListItem({ icon, name, description, connected = false, action, className, children, ...props }) {
|
|
8
|
+
return (_jsxs("div", { "data-slot": "device-list-item", role: "listitem", className: cn('animate-in fade-in slide-in-from-bottom-1 flex items-center gap-3 px-3 py-2.5 duration-300 motion-reduce:animate-none', props.onClick &&
|
|
9
|
+
'hover:bg-muted/50 focus-visible:bg-muted/50 cursor-pointer outline-none transition-colors', className), ...props, children: [icon ? (_jsx("div", { "data-slot": "device-list-item-icon", className: "text-muted-foreground bg-muted/50 flex size-8 shrink-0 items-center justify-center rounded-md border [&_svg:not([class*='size-'])]:size-4", children: icon })) : null, _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { "data-slot": "device-list-item-name", className: "truncate text-sm font-medium", children: name }), connected ? (_jsxs("span", { "data-slot": "device-list-item-connected", className: "text-status-running inline-flex shrink-0 items-center gap-1 text-[10px] font-medium uppercase tracking-wide", children: [_jsx("span", { className: "bg-status-running size-1.5 rounded-full" }), "Connected"] })) : null] }), description ? (_jsx("div", { "data-slot": "device-list-item-description", className: "text-muted-foreground mt-0.5 truncate font-mono text-xs", children: description })) : null, children] }), action ? (_jsx("div", { "data-slot": "device-list-item-action", className: "flex shrink-0 items-center gap-1.5", children: action })) : null] }));
|
|
10
|
+
}
|
|
11
|
+
function DeviceListEmpty({ icon, className, children, ...props }) {
|
|
12
|
+
return (_jsxs("div", { "data-slot": "device-list-empty", className: cn('text-muted-foreground flex flex-col items-center gap-2 px-4 py-8 text-center text-sm', className), ...props, children: [icon ? (_jsx("div", { className: "opacity-60 [&_svg:not([class*='size-'])]:size-5", children: icon })) : null, children] }));
|
|
13
|
+
}
|
|
14
|
+
export { DeviceList, DeviceListItem, DeviceListEmpty };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type MoldableDisplay } from '../../lib/native-hardware';
|
|
3
|
+
export type MoldableDisplaysStatus = 'loading' | 'ready' | 'unavailable';
|
|
4
|
+
/**
|
|
5
|
+
* Display arrangement state behind `DisplayMap`. One-shot query by design —
|
|
6
|
+
* the host does not expose display change events.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useMoldableDisplays(): {
|
|
9
|
+
displays: MoldableDisplay[];
|
|
10
|
+
status: MoldableDisplaysStatus;
|
|
11
|
+
error: Error | null;
|
|
12
|
+
refresh: () => void;
|
|
13
|
+
};
|
|
14
|
+
export interface DisplayMapProps extends React.ComponentProps<'div'> {
|
|
15
|
+
onSelectDisplay?: (display: MoldableDisplay | null) => void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* To-scale map of the native monitor arrangement. Hover or click a display to
|
|
19
|
+
* inspect its name, resolution, position, and scale factor.
|
|
20
|
+
*/
|
|
21
|
+
declare function DisplayMap({ className, onSelectDisplay, ...props }: DisplayMapProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export { DisplayMap };
|
|
23
|
+
//# sourceMappingURL=display-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display-map.d.ts","sourceRoot":"","sources":["../../../src/components/hardware/display-map.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,2BAA2B,CAAA;AAgBlC,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAA;AAExE;;;GAGG;AACH,wBAAgB,mBAAmB;;;;;EAiClC;AAgCD,MAAM,WAAW,eAAgB,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IAClE,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,KAAK,IAAI,CAAA;CAC5D;AAED;;;GAGG;AACH,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,2CA2K5E;AAED,OAAO,EAAE,UAAU,EAAE,CAAA"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { Monitor, RefreshCw } from 'lucide-react';
|
|
4
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
5
|
+
import { getMoldableDisplays, } from '../../lib/native-hardware';
|
|
6
|
+
import { cn } from '../../lib/utils';
|
|
7
|
+
import { Button } from '../ui/button';
|
|
8
|
+
import { Spinner } from '../ui/spinner';
|
|
9
|
+
import { CapabilityBadge } from './capability-badge';
|
|
10
|
+
import { HardwarePanel, HardwarePanelAction, HardwarePanelContent, HardwarePanelFooter, HardwarePanelHeader, HardwarePanelIcon, HardwarePanelTitle, } from './hardware-panel';
|
|
11
|
+
import { Readout, ReadoutItem } from './readout';
|
|
12
|
+
/**
|
|
13
|
+
* Display arrangement state behind `DisplayMap`. One-shot query by design —
|
|
14
|
+
* the host does not expose display change events.
|
|
15
|
+
*/
|
|
16
|
+
export function useMoldableDisplays() {
|
|
17
|
+
const [displays, setDisplays] = useState([]);
|
|
18
|
+
const [status, setStatus] = useState('loading');
|
|
19
|
+
const [error, setError] = useState(null);
|
|
20
|
+
const generationRef = useRef(0);
|
|
21
|
+
const refresh = useCallback(() => {
|
|
22
|
+
const generation = ++generationRef.current;
|
|
23
|
+
setStatus('loading');
|
|
24
|
+
setError(null);
|
|
25
|
+
getMoldableDisplays()
|
|
26
|
+
.then((result) => {
|
|
27
|
+
if (generationRef.current !== generation)
|
|
28
|
+
return;
|
|
29
|
+
setDisplays(result.displays);
|
|
30
|
+
setStatus('ready');
|
|
31
|
+
})
|
|
32
|
+
.catch((cause) => {
|
|
33
|
+
if (generationRef.current !== generation)
|
|
34
|
+
return;
|
|
35
|
+
setDisplays([]);
|
|
36
|
+
setError(cause instanceof Error ? cause : new Error(String(cause)));
|
|
37
|
+
setStatus('unavailable');
|
|
38
|
+
});
|
|
39
|
+
}, []);
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
refresh();
|
|
42
|
+
const liveGeneration = generationRef;
|
|
43
|
+
return () => {
|
|
44
|
+
liveGeneration.current++;
|
|
45
|
+
};
|
|
46
|
+
}, [refresh]);
|
|
47
|
+
return { displays, status, error, refresh };
|
|
48
|
+
}
|
|
49
|
+
function computeDisplayBounds(displays) {
|
|
50
|
+
let minX = Infinity;
|
|
51
|
+
let minY = Infinity;
|
|
52
|
+
let maxX = -Infinity;
|
|
53
|
+
let maxY = -Infinity;
|
|
54
|
+
for (const display of displays) {
|
|
55
|
+
minX = Math.min(minX, display.position.x);
|
|
56
|
+
minY = Math.min(minY, display.position.y);
|
|
57
|
+
maxX = Math.max(maxX, display.position.x + display.size.width);
|
|
58
|
+
maxY = Math.max(maxY, display.position.y + display.size.height);
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
minX,
|
|
62
|
+
minY,
|
|
63
|
+
width: Math.max(1, maxX - minX),
|
|
64
|
+
height: Math.max(1, maxY - minY),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function displayName(display, index) {
|
|
68
|
+
return display.name ?? `Display ${index + 1}`;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* To-scale map of the native monitor arrangement. Hover or click a display to
|
|
72
|
+
* inspect its name, resolution, position, and scale factor.
|
|
73
|
+
*/
|
|
74
|
+
function DisplayMap({ className, onSelectDisplay, ...props }) {
|
|
75
|
+
const { displays, status, refresh } = useMoldableDisplays();
|
|
76
|
+
const [selected, setSelected] = useState(null);
|
|
77
|
+
const onSelectDisplayRef = useRef(onSelectDisplay);
|
|
78
|
+
onSelectDisplayRef.current = onSelectDisplay;
|
|
79
|
+
const select = (index) => {
|
|
80
|
+
setSelected(index);
|
|
81
|
+
onSelectDisplayRef.current?.(displays[index] ?? null);
|
|
82
|
+
};
|
|
83
|
+
const primaryIndex = displays.findIndex((display) => display.primary);
|
|
84
|
+
const selectedIndex = selected !== null && selected < displays.length
|
|
85
|
+
? selected
|
|
86
|
+
: primaryIndex >= 0
|
|
87
|
+
? primaryIndex
|
|
88
|
+
: displays.length > 0
|
|
89
|
+
? 0
|
|
90
|
+
: null;
|
|
91
|
+
const selectedDisplay = selectedIndex === null ? null : (displays[selectedIndex] ?? null);
|
|
92
|
+
const bounds = computeDisplayBounds(displays);
|
|
93
|
+
const mapWidth = Math.round((200 * bounds.width) / bounds.height);
|
|
94
|
+
return (_jsxs(HardwarePanel, { "data-slot": "display-map", "data-status": status, className: className, ...props, children: [_jsxs(HardwarePanelHeader, { children: [_jsx(HardwarePanelIcon, { children: _jsx(Monitor, {}) }), _jsx(HardwarePanelTitle, { children: "Displays" }), _jsx(CapabilityBadge, { capability: "displays" }), _jsx(HardwarePanelAction, { children: _jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Refresh displays", onClick: () => {
|
|
95
|
+
setSelected(null);
|
|
96
|
+
refresh();
|
|
97
|
+
}, children: _jsx(RefreshCw, {}) }) })] }), _jsx(HardwarePanelContent, { children: status === 'ready' && displays.length > 0 ? (_jsxs("div", { className: "animate-in fade-in space-y-4 duration-300 motion-reduce:animate-none", children: [_jsx("div", { className: "bg-muted/20 flex justify-center overflow-hidden rounded-lg border p-4", children: _jsx("div", { "data-slot": "display-map-canvas", className: "relative", style: {
|
|
98
|
+
aspectRatio: `${bounds.width} / ${bounds.height}`,
|
|
99
|
+
width: `min(100%, ${mapWidth}px)`,
|
|
100
|
+
}, children: displays.map((display, index) => {
|
|
101
|
+
const isSelected = index === selectedIndex;
|
|
102
|
+
return (_jsxs("button", { type: "button", "data-slot": "display-map-display", "data-primary": display.primary || undefined, "data-selected": isSelected || undefined, "aria-label": `Select ${displayName(display, index)}`, onClick: () => select(index), onMouseEnter: () => select(index), onFocus: () => select(index), className: cn('animate-in fade-in zoom-in-95 absolute flex flex-col items-start justify-end gap-0.5 overflow-hidden rounded-md border p-1.5 text-left duration-300 motion-reduce:animate-none', isSelected
|
|
103
|
+
? 'bg-primary/10 border-primary'
|
|
104
|
+
: 'bg-muted/40 hover:bg-muted/70', !isSelected && display.primary && 'border-primary'), style: {
|
|
105
|
+
left: `${((display.position.x - bounds.minX) / bounds.width) * 100}%`,
|
|
106
|
+
top: `${((display.position.y - bounds.minY) / bounds.height) * 100}%`,
|
|
107
|
+
width: `${(display.size.width / bounds.width) * 100}%`,
|
|
108
|
+
height: `${(display.size.height / bounds.height) * 100}%`,
|
|
109
|
+
animationDelay: `${index * 75}ms`,
|
|
110
|
+
animationFillMode: 'backwards',
|
|
111
|
+
}, children: [display.primary ? (_jsx("span", { className: "border-primary/40 bg-primary/10 text-primary absolute right-1 top-1 rounded-full border px-1 py-px text-[8px] font-medium leading-none", children: "Primary" })) : null, _jsx("span", { className: "w-full truncate text-[10px] font-medium leading-tight", children: displayName(display, index) }), _jsxs("span", { className: "text-muted-foreground font-mono text-[9px] tabular-nums leading-none", children: [display.size.width, "\u00D7", display.size.height] })] }, `${display.position.x},${display.position.y},${index}`));
|
|
112
|
+
}) }) }), selectedDisplay ? (_jsxs(Readout, { className: "grid-cols-2 sm:grid-cols-4", children: [_jsx(ReadoutItem, { label: "Name", value: displayName(selectedDisplay, selectedIndex ?? 0) }), _jsx(ReadoutItem, { label: "Resolution", value: `${selectedDisplay.size.width}×${selectedDisplay.size.height}` }), _jsx(ReadoutItem, { label: "Position", value: `${selectedDisplay.position.x}, ${selectedDisplay.position.y}` }), _jsx(ReadoutItem, { label: "Scale factor", value: `${selectedDisplay.scaleFactor}×` })] })) : null] })) : (_jsx("div", { className: "animate-in fade-in flex flex-col items-center gap-3 py-6 text-center duration-300 motion-reduce:animate-none", children: status === 'loading' ? (_jsxs(_Fragment, { children: [_jsx(Spinner, { className: "text-muted-foreground" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "Reading display arrangement\u2026" })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground bg-background shadow-xs flex size-10 items-center justify-center rounded-lg border [&_svg]:size-5", children: _jsx(Monitor, {}) }), status === 'unavailable' ? (_jsxs(_Fragment, { children: [_jsx("p", { className: "text-sm font-medium", children: "Displays unavailable" }), _jsx("p", { className: "text-muted-foreground max-w-64 text-xs", children: "Display metadata is only available inside Moldable." })] })) : (_jsx("p", { className: "text-muted-foreground text-xs", children: "No displays reported" }))] })) })) }), _jsx(HardwarePanelFooter, { children: _jsxs("span", { className: "truncate", children: [displays.length, " ", displays.length === 1 ? 'display' : 'displays'] }) })] }));
|
|
113
|
+
}
|
|
114
|
+
export { DisplayMap };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type MoldableHapticAvailability, type MoldableHapticPattern } from '../../lib/native-hardware';
|
|
3
|
+
import { Button } from '../ui/button';
|
|
4
|
+
/**
|
|
5
|
+
* Haptic feedback state behind `HapticButton`. `perform` never throws — it
|
|
6
|
+
* resolves `false` when the host rejects or is unavailable.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useMoldableHaptics(): {
|
|
9
|
+
availability: MoldableHapticAvailability | null;
|
|
10
|
+
patterns: MoldableHapticPattern[];
|
|
11
|
+
supported: boolean;
|
|
12
|
+
perform: (pattern?: MoldableHapticPattern) => Promise<boolean>;
|
|
13
|
+
};
|
|
14
|
+
export interface HapticButtonProps extends React.ComponentProps<typeof Button> {
|
|
15
|
+
/** Haptic pattern to perform on click. Defaults to `generic`. */
|
|
16
|
+
pattern?: MoldableHapticPattern;
|
|
17
|
+
/** Called with whether the OS accepted the feedback request. */
|
|
18
|
+
onPerformed?: (ok: boolean) => void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A `Button` that performs native haptic feedback on click, with a matching
|
|
22
|
+
* press-and-jiggle animation so the tap reads even without hardware feedback.
|
|
23
|
+
*/
|
|
24
|
+
declare function HapticButton({ pattern, onPerformed, onClick, className, children, ...props }: HapticButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
export { HapticButton };
|
|
26
|
+
//# sourceMappingURL=haptic-button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"haptic-button.d.ts","sourceRoot":"","sources":["../../../src/components/hardware/haptic-button.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,qBAAqB,EAG3B,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAIrC;;;GAGG;AACH,wBAAgB,kBAAkB;;;;wBAqBd,qBAAqB;EAiBxC;AAkBD,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC;IAC5E,iEAAiE;IACjE,OAAO,CAAC,EAAE,qBAAqB,CAAA;IAC/B,gEAAgE;IAChE,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,IAAI,CAAA;CACpC;AAED;;;GAGG;AACH,iBAAS,YAAY,CAAC,EACpB,OAAmB,EACnB,WAAW,EACX,OAAO,EACP,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,iBAAiB,2CAmDnB;AAED,OAAO,EAAE,YAAY,EAAE,CAAA"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Vibrate } from 'lucide-react';
|
|
4
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
5
|
+
import { getMoldableHapticAvailability, performMoldableHapticFeedback, } from '../../lib/native-hardware';
|
|
6
|
+
import { cn } from '../../lib/utils';
|
|
7
|
+
import { Button } from '../ui/button';
|
|
8
|
+
const EMPTY_PATTERNS = [];
|
|
9
|
+
/**
|
|
10
|
+
* Haptic feedback state behind `HapticButton`. `perform` never throws — it
|
|
11
|
+
* resolves `false` when the host rejects or is unavailable.
|
|
12
|
+
*/
|
|
13
|
+
export function useMoldableHaptics() {
|
|
14
|
+
const [availability, setAvailability] = useState(null);
|
|
15
|
+
const generationRef = useRef(0);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const generation = ++generationRef.current;
|
|
18
|
+
getMoldableHapticAvailability()
|
|
19
|
+
.then((value) => {
|
|
20
|
+
if (generationRef.current === generation)
|
|
21
|
+
setAvailability(value);
|
|
22
|
+
})
|
|
23
|
+
.catch(() => {
|
|
24
|
+
// Haptics availability is best-effort outside Moldable.
|
|
25
|
+
});
|
|
26
|
+
const liveGeneration = generationRef;
|
|
27
|
+
return () => {
|
|
28
|
+
liveGeneration.current++;
|
|
29
|
+
};
|
|
30
|
+
}, []);
|
|
31
|
+
const perform = useCallback(async (pattern = 'generic') => {
|
|
32
|
+
try {
|
|
33
|
+
const result = await performMoldableHapticFeedback(pattern);
|
|
34
|
+
return result.accepted === true;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}, []);
|
|
40
|
+
return {
|
|
41
|
+
availability,
|
|
42
|
+
patterns: availability?.patterns ?? EMPTY_PATTERNS,
|
|
43
|
+
supported: availability?.apiAvailable ?? false,
|
|
44
|
+
perform,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const HAPTIC_PRESS_STYLE = `
|
|
48
|
+
@keyframes moldable-haptic-press {
|
|
49
|
+
0% { transform: scale(1) translateX(0); }
|
|
50
|
+
20% { transform: scale(0.96) translateX(-1.5px); }
|
|
51
|
+
45% { transform: scale(0.97) translateX(1.5px); }
|
|
52
|
+
70% { transform: scale(0.98) translateX(-1px); }
|
|
53
|
+
100% { transform: scale(1) translateX(0); }
|
|
54
|
+
}
|
|
55
|
+
[data-slot='haptic-button'][data-state='pressed'] {
|
|
56
|
+
animation: moldable-haptic-press 150ms ease-in-out;
|
|
57
|
+
}
|
|
58
|
+
@media (prefers-reduced-motion: reduce) {
|
|
59
|
+
[data-slot='haptic-button'][data-state='pressed'] { animation: none; }
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
62
|
+
/**
|
|
63
|
+
* A `Button` that performs native haptic feedback on click, with a matching
|
|
64
|
+
* press-and-jiggle animation so the tap reads even without hardware feedback.
|
|
65
|
+
*/
|
|
66
|
+
function HapticButton({ pattern = 'generic', onPerformed, onClick, className, children, ...props }) {
|
|
67
|
+
const { perform } = useMoldableHaptics();
|
|
68
|
+
const [pressed, setPressed] = useState(false);
|
|
69
|
+
const onPerformedRef = useRef(onPerformed);
|
|
70
|
+
onPerformedRef.current = onPerformed;
|
|
71
|
+
const frameRef = useRef(0);
|
|
72
|
+
const timeoutRef = useRef(0);
|
|
73
|
+
useEffect(() => () => {
|
|
74
|
+
window.cancelAnimationFrame(frameRef.current);
|
|
75
|
+
window.clearTimeout(timeoutRef.current);
|
|
76
|
+
}, []);
|
|
77
|
+
const triggerPress = () => {
|
|
78
|
+
window.cancelAnimationFrame(frameRef.current);
|
|
79
|
+
window.clearTimeout(timeoutRef.current);
|
|
80
|
+
// Drop the attribute for a frame so rapid clicks restart the animation.
|
|
81
|
+
setPressed(false);
|
|
82
|
+
frameRef.current = window.requestAnimationFrame(() => {
|
|
83
|
+
setPressed(true);
|
|
84
|
+
timeoutRef.current = window.setTimeout(() => setPressed(false), 180);
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
const handleClick = (event) => {
|
|
88
|
+
triggerPress();
|
|
89
|
+
void perform(pattern).then((ok) => onPerformedRef.current?.(ok));
|
|
90
|
+
onClick?.(event);
|
|
91
|
+
};
|
|
92
|
+
return (_jsxs(_Fragment, { children: [_jsx("style", { children: HAPTIC_PRESS_STYLE }), _jsx(Button, { "data-slot": "haptic-button", "data-state": pressed ? 'pressed' : 'idle', className: cn('motion-reduce:animate-none', className), onClick: handleClick, ...props, children: children ?? (_jsxs(_Fragment, { children: [_jsx(Vibrate, {}), " Haptic"] })) })] }));
|
|
93
|
+
}
|
|
94
|
+
export { HapticButton };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
declare function HardwarePanel({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
declare function HardwarePanelHeader({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
declare function HardwarePanelIcon({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
declare function HardwarePanelTitle({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
declare function HardwarePanelDescription({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
declare function HardwarePanelAction({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
declare function HardwarePanelContent({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
declare function HardwarePanelFooter({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export { HardwarePanel, HardwarePanelHeader, HardwarePanelIcon, HardwarePanelTitle, HardwarePanelDescription, HardwarePanelAction, HardwarePanelContent, HardwarePanelFooter, };
|
|
11
|
+
//# sourceMappingURL=hardware-panel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hardware-panel.d.ts","sourceRoot":"","sources":["../../../src/components/hardware/hardware-panel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAW1E;AAED,iBAAS,mBAAmB,CAAC,EAC3B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAQ7B;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAW7B;AAED,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAQ7B;AAED,iBAAS,wBAAwB,CAAC,EAChC,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAQ7B;AAED,iBAAS,mBAAmB,CAAC,EAC3B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAQ7B;AAED,iBAAS,oBAAoB,CAAC,EAC5B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAQ7B;AAED,iBAAS,mBAAmB,CAAC,EAC3B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAW7B;AAED,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,GACpB,CAAA"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from '../../lib/utils';
|
|
4
|
+
function HardwarePanel({ className, ...props }) {
|
|
5
|
+
return (_jsx("div", { "data-slot": "hardware-panel", className: cn('bg-card text-card-foreground shadow-xs flex flex-col overflow-hidden rounded-xl border', className), ...props }));
|
|
6
|
+
}
|
|
7
|
+
function HardwarePanelHeader({ className, ...props }) {
|
|
8
|
+
return (_jsx("div", { "data-slot": "hardware-panel-header", className: cn('flex items-center gap-2.5 border-b px-4 py-3', className), ...props }));
|
|
9
|
+
}
|
|
10
|
+
function HardwarePanelIcon({ className, ...props }) {
|
|
11
|
+
return (_jsx("div", { "data-slot": "hardware-panel-icon", className: cn("text-muted-foreground bg-muted/50 flex size-7 shrink-0 items-center justify-center rounded-md border [&_svg:not([class*='size-'])]:size-3.5", className), ...props }));
|
|
12
|
+
}
|
|
13
|
+
function HardwarePanelTitle({ className, ...props }) {
|
|
14
|
+
return (_jsx("div", { "data-slot": "hardware-panel-title", className: cn('text-sm font-medium leading-none', className), ...props }));
|
|
15
|
+
}
|
|
16
|
+
function HardwarePanelDescription({ className, ...props }) {
|
|
17
|
+
return (_jsx("div", { "data-slot": "hardware-panel-description", className: cn('text-muted-foreground mt-1 text-xs', className), ...props }));
|
|
18
|
+
}
|
|
19
|
+
function HardwarePanelAction({ className, ...props }) {
|
|
20
|
+
return (_jsx("div", { "data-slot": "hardware-panel-action", className: cn('ml-auto flex shrink-0 items-center gap-2', className), ...props }));
|
|
21
|
+
}
|
|
22
|
+
function HardwarePanelContent({ className, ...props }) {
|
|
23
|
+
return (_jsx("div", { "data-slot": "hardware-panel-content", className: cn('flex-1 p-4', className), ...props }));
|
|
24
|
+
}
|
|
25
|
+
function HardwarePanelFooter({ className, ...props }) {
|
|
26
|
+
return (_jsx("div", { "data-slot": "hardware-panel-footer", className: cn('text-muted-foreground bg-muted/30 flex items-center gap-2 border-t px-4 py-2 text-xs', className), ...props }));
|
|
27
|
+
}
|
|
28
|
+
export { HardwarePanel, HardwarePanelHeader, HardwarePanelIcon, HardwarePanelTitle, HardwarePanelDescription, HardwarePanelAction, HardwarePanelContent, HardwarePanelFooter, };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type MoldableHidDevice, type MoldableHidDeviceFilter, type MoldableHidInputReportEvent } from '../../lib/native-hardware';
|
|
3
|
+
export type MoldableHidStatus = 'idle' | 'requesting' | 'error';
|
|
4
|
+
export interface UseMoldableHidOptions {
|
|
5
|
+
onInputReport?: (event: MoldableHidInputReportEvent) => void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* HID state machine behind `HidDevicePanel`: granted-device list, chooser
|
|
9
|
+
* requests, open/close with input-report streaming, and output reports. Use
|
|
10
|
+
* directly to build custom HID UI on the same lifecycle handling.
|
|
11
|
+
*/
|
|
12
|
+
export declare function useMoldableHid(options?: UseMoldableHidOptions): {
|
|
13
|
+
devices: MoldableHidDevice[];
|
|
14
|
+
status: MoldableHidStatus;
|
|
15
|
+
error: Error | null;
|
|
16
|
+
openIds: string[];
|
|
17
|
+
entries: import("./stream-log").StreamLogEntry[];
|
|
18
|
+
deviceId: (device: MoldableHidDevice) => string;
|
|
19
|
+
refresh: () => Promise<void>;
|
|
20
|
+
request: (filters?: readonly MoldableHidDeviceFilter[]) => Promise<void>;
|
|
21
|
+
open: (device: MoldableHidDevice) => Promise<void>;
|
|
22
|
+
close: (device: MoldableHidDevice) => Promise<boolean>;
|
|
23
|
+
sendReport: (device: MoldableHidDevice, reportId: number, data: BufferSource) => Promise<boolean>;
|
|
24
|
+
sendFeatureReport: (device: MoldableHidDevice, reportId: number, data: BufferSource) => Promise<boolean>;
|
|
25
|
+
receiveFeatureReport: (device: MoldableHidDevice, reportId: number) => Promise<DataView<ArrayBufferLike> | undefined>;
|
|
26
|
+
forget: (device: MoldableHidDevice) => Promise<boolean>;
|
|
27
|
+
clearEntries: () => void;
|
|
28
|
+
};
|
|
29
|
+
export interface HidDevicePanelProps extends React.ComponentProps<'div'> {
|
|
30
|
+
/** Chooser filters (empty shows every device the runtime allows). */
|
|
31
|
+
filters?: readonly MoldableHidDeviceFilter[];
|
|
32
|
+
onInputReport?: (event: MoldableHidInputReportEvent) => void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* HID device panel: chooser access, granted-device list with open/close, and
|
|
36
|
+
* a live hex log of incoming input reports.
|
|
37
|
+
*/
|
|
38
|
+
declare function HidDevicePanel({ className, filters, onInputReport, ...props }: HidDevicePanelProps): import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
export { HidDevicePanel };
|
|
40
|
+
//# sourceMappingURL=hid-panel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hid-panel.d.ts","sourceRoot":"","sources":["../../../src/components/hardware/hid-panel.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,2BAA2B,EAWjC,MAAM,2BAA2B,CAAA;AAsBlC,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,YAAY,GAAG,OAAO,CAAA;AA0D/D,MAAM,WAAW,qBAAqB;IACpC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,2BAA2B,KAAK,IAAI,CAAA;CAC7D;AAOD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B;;;;;;uBAe1B,iBAAiB,KAAG,MAAM;;wBAyC9C,SAAS,uBAAuB,EAAE;mBA4BnC,iBAAiB;oBA+CjB,iBAAiB;yBAoBjB,iBAAiB,YAAY,MAAM,QAAQ,YAAY;gCAuBvD,iBAAiB,YAAY,MAAM,QAAQ,YAAY;mCAuBvD,iBAAiB,YAAY,MAAM;qBAsBnC,iBAAiB;;EAoDnC;AAED,MAAM,WAAW,mBAAoB,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IACtE,qEAAqE;IACrE,OAAO,CAAC,EAAE,SAAS,uBAAuB,EAAE,CAAA;IAC5C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,2BAA2B,KAAK,IAAI,CAAA;CAC7D;AAyGD;;;GAGG;AACH,iBAAS,cAAc,CAAC,EACtB,SAAS,EACT,OAAO,EACP,aAAa,EACb,GAAG,KAAK,EACT,EAAE,mBAAmB,2CAgHrB;AAED,OAAO,EAAE,cAAc,EAAE,CAAA"}
|