basalt-core 0.0.0-rc5
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/LICENSE +21 -0
- package/dist/cli/basalt.d.ts +3 -0
- package/dist/cli/basalt.d.ts.map +1 -0
- package/dist/cli/basalt.js +47 -0
- package/dist/cli/basalt.js.map +1 -0
- package/dist/cli/bundle-cli.d.ts +12 -0
- package/dist/cli/bundle-cli.d.ts.map +1 -0
- package/dist/cli/bundle-cli.js +124 -0
- package/dist/cli/bundle-cli.js.map +1 -0
- package/dist/cli/bundleWithAssets.d.ts +79 -0
- package/dist/cli/bundleWithAssets.d.ts.map +1 -0
- package/dist/cli/bundleWithAssets.js +198 -0
- package/dist/cli/bundleWithAssets.js.map +1 -0
- package/dist/cli/desktop.d.ts +339 -0
- package/dist/cli/desktop.d.ts.map +1 -0
- package/dist/cli/desktop.js +1029 -0
- package/dist/cli/desktop.js.map +1 -0
- package/dist/cli/doctor.d.ts +31 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +283 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/init.d.ts +77 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +442 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/metro.d.ts +49 -0
- package/dist/cli/metro.d.ts.map +1 -0
- package/dist/cli/metro.js +148 -0
- package/dist/cli/metro.js.map +1 -0
- package/dist/cli/packageApp.d.ts +102 -0
- package/dist/cli/packageApp.d.ts.map +1 -0
- package/dist/cli/packageApp.js +319 -0
- package/dist/cli/packageApp.js.map +1 -0
- package/dist/cli/steps.d.ts +34 -0
- package/dist/cli/steps.d.ts.map +1 -0
- package/dist/cli/steps.js +53 -0
- package/dist/cli/steps.js.map +1 -0
- package/dist/metro-config.d.ts +168 -0
- package/dist/metro-config.d.ts.map +1 -0
- package/dist/metro-config.js +671 -0
- package/dist/metro-config.js.map +1 -0
- package/dist/react-native.config.d.ts +7 -0
- package/dist/react-native.config.d.ts.map +1 -0
- package/dist/react-native.config.js +80 -0
- package/dist/react-native.config.js.map +1 -0
- package/dist/src/DragSource.d.ts +52 -0
- package/dist/src/DragSource.d.ts.map +1 -0
- package/dist/src/DragSource.js +97 -0
- package/dist/src/DragSource.js.map +1 -0
- package/dist/src/DropTarget.d.ts +58 -0
- package/dist/src/DropTarget.d.ts.map +1 -0
- package/dist/src/DropTarget.js +131 -0
- package/dist/src/DropTarget.js.map +1 -0
- package/dist/src/KeyHandler.d.ts +57 -0
- package/dist/src/KeyHandler.d.ts.map +1 -0
- package/dist/src/KeyHandler.js +48 -0
- package/dist/src/KeyHandler.js.map +1 -0
- package/dist/src/Menu.d.ts +72 -0
- package/dist/src/Menu.d.ts.map +1 -0
- package/dist/src/Menu.js +179 -0
- package/dist/src/Menu.js.map +1 -0
- package/dist/src/TitleBar.d.ts +75 -0
- package/dist/src/TitleBar.d.ts.map +1 -0
- package/dist/src/TitleBar.js +236 -0
- package/dist/src/TitleBar.js.map +1 -0
- package/dist/src/Window.d.ts +87 -0
- package/dist/src/Window.d.ts.map +1 -0
- package/dist/src/Window.js +248 -0
- package/dist/src/Window.js.map +1 -0
- package/dist/src/closeRequest.d.ts +55 -0
- package/dist/src/closeRequest.d.ts.map +1 -0
- package/dist/src/closeRequest.js +134 -0
- package/dist/src/closeRequest.js.map +1 -0
- package/dist/src/index.d.ts +45 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +92 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/overrides/Alert.d.ts +69 -0
- package/dist/src/overrides/Alert.d.ts.map +1 -0
- package/dist/src/overrides/Alert.js +112 -0
- package/dist/src/overrides/Alert.js.map +1 -0
- package/dist/src/overrides/BaseViewConfig.d.ts +28 -0
- package/dist/src/overrides/BaseViewConfig.d.ts.map +1 -0
- package/dist/src/overrides/BaseViewConfig.js +72 -0
- package/dist/src/overrides/BaseViewConfig.js.map +1 -0
- package/dist/src/overrides/Platform.linux.d.ts +10 -0
- package/dist/src/overrides/Platform.linux.d.ts.map +1 -0
- package/dist/src/overrides/Platform.linux.js +15 -0
- package/dist/src/overrides/Platform.linux.js.map +1 -0
- package/dist/src/overrides/Platform.macos.d.ts +10 -0
- package/dist/src/overrides/Platform.macos.d.ts.map +1 -0
- package/dist/src/overrides/Platform.macos.js +15 -0
- package/dist/src/overrides/Platform.macos.js.map +1 -0
- package/dist/src/overrides/Platform.windows.d.ts +10 -0
- package/dist/src/overrides/Platform.windows.d.ts.map +1 -0
- package/dist/src/overrides/Platform.windows.js +15 -0
- package/dist/src/overrides/Platform.windows.js.map +1 -0
- package/dist/src/overrides/ReactDevToolsSettingsManager.d.ts +24 -0
- package/dist/src/overrides/ReactDevToolsSettingsManager.d.ts.map +1 -0
- package/dist/src/overrides/ReactDevToolsSettingsManager.js +30 -0
- package/dist/src/overrides/ReactDevToolsSettingsManager.js.map +1 -0
- package/dist/src/overrides/RefreshControl.d.ts +52 -0
- package/dist/src/overrides/RefreshControl.d.ts.map +1 -0
- package/dist/src/overrides/RefreshControl.js +92 -0
- package/dist/src/overrides/RefreshControl.js.map +1 -0
- package/dist/src/overrides/ScrollView.d.ts +39 -0
- package/dist/src/overrides/ScrollView.d.ts.map +1 -0
- package/dist/src/overrides/ScrollView.js +59 -0
- package/dist/src/overrides/ScrollView.js.map +1 -0
- package/dist/src/overrides/Share.d.ts +96 -0
- package/dist/src/overrides/Share.d.ts.map +1 -0
- package/dist/src/overrides/Share.js +97 -0
- package/dist/src/overrides/Share.js.map +1 -0
- package/dist/src/overrides/TextInput.d.ts +81 -0
- package/dist/src/overrides/TextInput.d.ts.map +1 -0
- package/dist/src/overrides/TextInput.js +213 -0
- package/dist/src/overrides/TextInput.js.map +1 -0
- package/dist/src/overrides/View.d.ts +36 -0
- package/dist/src/overrides/View.d.ts.map +1 -0
- package/dist/src/overrides/View.js +99 -0
- package/dist/src/overrides/View.js.map +1 -0
- package/dist/src/overrides/createPlatform.d.ts +32 -0
- package/dist/src/overrides/createPlatform.d.ts.map +1 -0
- package/dist/src/overrides/createPlatform.js +84 -0
- package/dist/src/overrides/createPlatform.js.map +1 -0
- package/dist/src/overrides/setUpDeveloperTools.d.ts +28 -0
- package/dist/src/overrides/setUpDeveloperTools.d.ts.map +1 -0
- package/dist/src/overrides/setUpDeveloperTools.js +84 -0
- package/dist/src/overrides/setUpDeveloperTools.js.map +1 -0
- package/dist/src/overrides/setUpXHR.d.ts +46 -0
- package/dist/src/overrides/setUpXHR.d.ts.map +1 -0
- package/dist/src/overrides/setUpXHR.js +236 -0
- package/dist/src/overrides/setUpXHR.js.map +1 -0
- package/dist/src/quitRequest.d.ts +55 -0
- package/dist/src/quitRequest.d.ts.map +1 -0
- package/dist/src/quitRequest.js +121 -0
- package/dist/src/quitRequest.js.map +1 -0
- package/dist/src/resourcePath.d.ts +18 -0
- package/dist/src/resourcePath.d.ts.map +1 -0
- package/dist/src/resourcePath.js +31 -0
- package/dist/src/resourcePath.js.map +1 -0
- package/dist/src/responseBody.d.ts +76 -0
- package/dist/src/responseBody.d.ts.map +1 -0
- package/dist/src/responseBody.js +94 -0
- package/dist/src/responseBody.js.map +1 -0
- package/dist/src/responseHeaders.d.ts +40 -0
- package/dist/src/responseHeaders.d.ts.map +1 -0
- package/dist/src/responseHeaders.js +75 -0
- package/dist/src/responseHeaders.js.map +1 -0
- package/dist/src/titleBarState.d.ts +43 -0
- package/dist/src/titleBarState.d.ts.map +1 -0
- package/dist/src/titleBarState.js +77 -0
- package/dist/src/titleBarState.js.map +1 -0
- package/dist/src/useContextMenu.d.ts +113 -0
- package/dist/src/useContextMenu.d.ts.map +1 -0
- package/dist/src/useContextMenu.js +109 -0
- package/dist/src/useContextMenu.js.map +1 -0
- package/dist/src/useDialog.d.ts +98 -0
- package/dist/src/useDialog.d.ts.map +1 -0
- package/dist/src/useDialog.js +112 -0
- package/dist/src/useDialog.js.map +1 -0
- package/dist/src/useDisplays.d.ts +70 -0
- package/dist/src/useDisplays.d.ts.map +1 -0
- package/dist/src/useDisplays.js +118 -0
- package/dist/src/useDisplays.js.map +1 -0
- package/dist/src/useHandledKeys.d.ts +38 -0
- package/dist/src/useHandledKeys.d.ts.map +1 -0
- package/dist/src/useHandledKeys.js +70 -0
- package/dist/src/useHandledKeys.js.map +1 -0
- package/dist/src/useWindow.d.ts +140 -0
- package/dist/src/useWindow.d.ts.map +1 -0
- package/dist/src/useWindow.js +233 -0
- package/dist/src/useWindow.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/native/CMakeLists.txt +355 -0
- package/native/bootstrap.sh +613 -0
- package/native/cmake/CompilerFlags.cmake +49 -0
- package/native/cmake/Expo.cmake +125 -0
- package/native/cmake/ReactNativeCore.cmake +612 -0
- package/native/cmake/Reanimated.cmake +108 -0
- package/native/cmake/Skia.cmake +379 -0
- package/native/cmake/ThirdParty.cmake +290 -0
- package/native/cmake/Worklets.cmake +67 -0
- package/native/cmake/codegen/CMakeLists.txt +32 -0
- package/native/core/AppIdentity.cpp +85 -0
- package/native/core/AppIdentity.h +59 -0
- package/native/core/AppPaths.cpp +96 -0
- package/native/core/AppPaths.h +53 -0
- package/native/core/AppearanceModule.cpp +60 -0
- package/native/core/AppearanceModule.h +40 -0
- package/native/core/Backface.h +59 -0
- package/native/core/BlobModule.cpp +283 -0
- package/native/core/BlobModule.h +76 -0
- package/native/core/BlobRegistry.cpp +75 -0
- package/native/core/BlobRegistry.h +44 -0
- package/native/core/ColorScheme.cpp +105 -0
- package/native/core/ColorScheme.h +59 -0
- package/native/core/ComponentRegistry.h +30 -0
- package/native/core/ControlMetrics.h +37 -0
- package/native/core/CoreModules.cpp +592 -0
- package/native/core/CoreModules.h +308 -0
- package/native/core/DebuggingOverlay.cpp +106 -0
- package/native/core/DebuggingOverlay.h +65 -0
- package/native/core/DesktopControls.cpp +232 -0
- package/native/core/DesktopControls.h +170 -0
- package/native/core/DevBundle.cpp +108 -0
- package/native/core/DevBundle.h +69 -0
- package/native/core/DevMenu.cpp +99 -0
- package/native/core/DevMenu.h +75 -0
- package/native/core/DialogModule.cpp +150 -0
- package/native/core/DialogModule.h +51 -0
- package/native/core/DragAndDrop.cpp +45 -0
- package/native/core/DragAndDrop.h +225 -0
- package/native/core/ExpoImageComponent.cpp +79 -0
- package/native/core/ExpoImageComponent.h +80 -0
- package/native/core/ExpoModules.cpp +415 -0
- package/native/core/ExpoModules.h +115 -0
- package/native/core/ExpoRuntime.cpp +366 -0
- package/native/core/ExpoRuntime.h +42 -0
- package/native/core/FocusRing.h +36 -0
- package/native/core/FontRegistry.h +51 -0
- package/native/core/GestureHandlerModule.cpp +136 -0
- package/native/core/GestureHandlerModule.h +71 -0
- package/native/core/Gestures.cpp +533 -0
- package/native/core/Gestures.h +145 -0
- package/native/core/HoverTracker.cpp +69 -0
- package/native/core/HoverTracker.h +109 -0
- package/native/core/HttpClient.cpp +282 -0
- package/native/core/ImageBytes.cpp +205 -0
- package/native/core/ImageBytes.h +29 -0
- package/native/core/ImageCache.cpp +51 -0
- package/native/core/ImageCache.h +89 -0
- package/native/core/JsRuntimeAccess.cpp +70 -0
- package/native/core/JsRuntimeAccess.h +60 -0
- package/native/core/JsiPromise.h +51 -0
- package/native/core/KeyEvents.cpp +116 -0
- package/native/core/KeyEvents.h +144 -0
- package/native/core/LogBoxSurface.cpp +46 -0
- package/native/core/LogBoxSurface.h +68 -0
- package/native/core/MenuModel.h +117 -0
- package/native/core/MenuModule.cpp +209 -0
- package/native/core/MenuModule.h +66 -0
- package/native/core/MountingWalk.h +524 -0
- package/native/core/PackageModules.cpp.in +25 -0
- package/native/core/PackageModules.h +50 -0
- package/native/core/PlatformConstantsModule.cpp +63 -0
- package/native/core/PlatformConstantsModule.h +64 -0
- package/native/core/PlatformServices.h +213 -0
- package/native/core/PointerButtons.h +63 -0
- package/native/core/PullToRefresh.cpp +57 -0
- package/native/core/PullToRefresh.h +73 -0
- package/native/core/ReanimatedCompat.h +47 -0
- package/native/core/ReanimatedModule.cpp +203 -0
- package/native/core/ReanimatedModule.h +55 -0
- package/native/core/ScrollAnimation.cpp +59 -0
- package/native/core/ScrollAnimation.h +70 -0
- package/native/core/ScrollBounds.cpp +26 -0
- package/native/core/ScrollBounds.h +68 -0
- package/native/core/ScrollIndicator.cpp +50 -0
- package/native/core/ScrollIndicator.h +69 -0
- package/native/core/ScrollMomentum.cpp +71 -0
- package/native/core/ScrollMomentum.h +73 -0
- package/native/core/ScrollSnap.cpp +123 -0
- package/native/core/ScrollSnap.h +80 -0
- package/native/core/ShareFallback.cpp +101 -0
- package/native/core/ShareFallback.h +45 -0
- package/native/core/SkiaPictureViewComponent.cpp +11 -0
- package/native/core/SkiaPictureViewComponent.h +47 -0
- package/native/core/SourceCodeModule.cpp +55 -0
- package/native/core/SourceCodeModule.h +53 -0
- package/native/core/StatusBarModule.cpp +23 -0
- package/native/core/StatusBarModule.h +42 -0
- package/native/core/TestDialog.cpp +148 -0
- package/native/core/TestDialog.h +96 -0
- package/native/core/TestKeys.cpp +78 -0
- package/native/core/TestKeys.h +50 -0
- package/native/core/TestQuitFile.cpp +33 -0
- package/native/core/TestQuitFile.h +60 -0
- package/native/core/TestSettle.h +192 -0
- package/native/core/TitleBarRegions.h +31 -0
- package/native/core/TurboModuleProxy.cpp +51 -0
- package/native/core/TurboModuleProxy.h +46 -0
- package/native/core/UIManagerAccess.cpp +43 -0
- package/native/core/UIManagerAccess.h +43 -0
- package/native/core/WindowBoundsCache.cpp +319 -0
- package/native/core/WindowControl.h +235 -0
- package/native/core/WindowHost.h +158 -0
- package/native/core/WindowMethods.cpp +167 -0
- package/native/core/WindowMethods.h +84 -0
- package/native/core/WindowsModule.cpp +448 -0
- package/native/core/WindowsModule.h +133 -0
- package/native/core/WorkletsModule.cpp +199 -0
- package/native/core/WorkletsModule.h +57 -0
- package/native/core/portability_probe.cpp +210 -0
- package/native/tests/EventRecorder.h +124 -0
- package/native/tests/TestHarness.cpp +109 -0
- package/native/tests/TestHarness.h +89 -0
- package/native/tests/TreeDump.h +49 -0
- package/native/tests/test_app_identity.cpp +114 -0
- package/native/tests/test_app_paths.cpp +48 -0
- package/native/tests/test_appearance.cpp +107 -0
- package/native/tests/test_backface.cpp +79 -0
- package/native/tests/test_blobs.cpp +157 -0
- package/native/tests/test_controls.cpp +185 -0
- package/native/tests/test_devbundle.cpp +103 -0
- package/native/tests/test_drag_and_drop.cpp +143 -0
- package/native/tests/test_gestures.cpp +331 -0
- package/native/tests/test_hover.cpp +92 -0
- package/native/tests/test_image_cache.cpp +109 -0
- package/native/tests/test_js_runtime_access.cpp +137 -0
- package/native/tests/test_key_events.cpp +235 -0
- package/native/tests/test_momentum.cpp +138 -0
- package/native/tests/test_quit_file.cpp +104 -0
- package/native/tests/test_scroll_animation.cpp +120 -0
- package/native/tests/test_scroll_bounds.cpp +66 -0
- package/native/tests/test_scroll_indicator.cpp +149 -0
- package/native/tests/test_scroll_snap.cpp +112 -0
- package/native/tests/test_settle.cpp +115 -0
- package/native/tests/test_share.cpp +75 -0
- package/native/tests/test_sourcecode.cpp +62 -0
- package/native/tests/test_window_close.cpp +119 -0
- package/native/tests/test_window_limits.cpp +123 -0
- package/package.json +43 -0
- package/react-native.config.js +86 -0
- package/supported-versions.json +66 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The title bar requests currently mounted, and what they add up to.
|
|
4
|
+
*
|
|
5
|
+
* Kept apart from TitleBar.tsx, with no React Native in it, so that it can be
|
|
6
|
+
* tested with nothing but Node -- this is the part with rules in it.
|
|
7
|
+
*
|
|
8
|
+
* Several screens may each ask for something, as they do of <StatusBar>, and
|
|
9
|
+
* the most recently mounted request wins. But key by key: a screen that only
|
|
10
|
+
* sets a title does not reset the colour an app shell underneath it set, and
|
|
11
|
+
* when it unmounts the shell's title comes back.
|
|
12
|
+
*
|
|
13
|
+
* @format
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.TITLE_BAR_KEYS = void 0;
|
|
17
|
+
exports.createTitleBarStack = createTitleBarStack;
|
|
18
|
+
exports.sameRequest = sameRequest;
|
|
19
|
+
exports.TITLE_BAR_KEYS = [
|
|
20
|
+
'title',
|
|
21
|
+
'style',
|
|
22
|
+
'backgroundColor',
|
|
23
|
+
'textColor',
|
|
24
|
+
'borderColor',
|
|
25
|
+
];
|
|
26
|
+
function pick(options) {
|
|
27
|
+
const picked = {};
|
|
28
|
+
for (const key of exports.TITLE_BAR_KEYS) {
|
|
29
|
+
if (options != null && options[key] !== undefined) {
|
|
30
|
+
// Each key's type is preserved by the assignment below; the index here is
|
|
31
|
+
// the one place the compiler cannot see that, because `key` ranges over
|
|
32
|
+
// the union.
|
|
33
|
+
picked[key] = options[key];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return picked;
|
|
37
|
+
}
|
|
38
|
+
function createTitleBarStack() {
|
|
39
|
+
const entries = [];
|
|
40
|
+
let nextId = 1;
|
|
41
|
+
return {
|
|
42
|
+
push(options) {
|
|
43
|
+
const id = nextId++;
|
|
44
|
+
entries.push({ id, options: pick(options) });
|
|
45
|
+
return id;
|
|
46
|
+
},
|
|
47
|
+
update(id, options) {
|
|
48
|
+
const entry = entries.find(candidate => candidate.id === id);
|
|
49
|
+
if (entry != null) {
|
|
50
|
+
entry.options = pick(options);
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
remove(id) {
|
|
54
|
+
const index = entries.findIndex(candidate => candidate.id === id);
|
|
55
|
+
if (index !== -1) {
|
|
56
|
+
entries.splice(index, 1);
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
// Later entries override earlier ones, one key at a time.
|
|
60
|
+
resolve() {
|
|
61
|
+
const resolved = {};
|
|
62
|
+
for (const { options } of entries) {
|
|
63
|
+
Object.assign(resolved, options);
|
|
64
|
+
}
|
|
65
|
+
return resolved;
|
|
66
|
+
},
|
|
67
|
+
get size() {
|
|
68
|
+
return entries.length;
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// Whether two resolved requests would ask the host for the same thing, so that
|
|
73
|
+
// a re-render that changed nothing does not cross into native at all.
|
|
74
|
+
function sameRequest(a, b) {
|
|
75
|
+
return exports.TITLE_BAR_KEYS.every(key => (a ?? {})[key] === (b ?? {})[key]);
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=titleBarState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"titleBarState.js","sourceRoot":"","sources":["../../src/titleBarState.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;AAuDH,kDAsCC;AAID,kCAKC;AApGY,QAAA,cAAc,GAAG;IAC5B,OAAO;IACP,OAAO;IACP,iBAAiB;IACjB,WAAW;IACX,aAAa;CACL,CAAC;AAkCX,SAAS,IAAI,CAAC,OAAgC;IAC5C,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,KAAK,MAAM,GAAG,IAAI,sBAAc,EAAE,CAAC;QACjC,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAClD,0EAA0E;YAC1E,wEAAwE;YACxE,aAAa;YACZ,MAAuC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAgB,mBAAmB;IACjC,MAAM,OAAO,GAAkD,EAAE,CAAC;IAClE,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,OAAO;QACL,IAAI,CAAC,OAAgC;YACnC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,EAAC,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,EAAC,CAAC,CAAC;YAC3C,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,CAAC,EAAU,EAAE,OAAgC;YACjD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YAC7D,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;gBAClB,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;QAED,MAAM,CAAC,EAAU;YACf,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YAClE,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;gBACjB,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,0DAA0D;QAC1D,OAAO;YACL,MAAM,QAAQ,GAAoB,EAAE,CAAC;YACrC,KAAK,MAAM,EAAC,OAAO,EAAC,IAAI,OAAO,EAAE,CAAC;gBAChC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACnC,CAAC;YACD,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,IAAI,IAAI;YACN,OAAO,OAAO,CAAC,MAAM,CAAC;QACxB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,sEAAsE;AACtE,SAAgB,WAAW,CACzB,CAA0B,EAC1B,CAA0B;IAE1B,OAAO,sBAAc,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACxE,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A native context menu.
|
|
3
|
+
*
|
|
4
|
+
* const menu = useContextMenu();
|
|
5
|
+
*
|
|
6
|
+
* <Pressable
|
|
7
|
+
* onLongPress={event =>
|
|
8
|
+
* menu.show(
|
|
9
|
+
* [
|
|
10
|
+
* {label: 'Copy', onSelect: copy},
|
|
11
|
+
* {separator: true},
|
|
12
|
+
* {label: 'Delete', onSelect: remove, shortcut: 'Del'},
|
|
13
|
+
* {label: 'Paste', enabled: false},
|
|
14
|
+
* ],
|
|
15
|
+
* event.nativeEvent,
|
|
16
|
+
* )
|
|
17
|
+
* }
|
|
18
|
+
* />
|
|
19
|
+
*
|
|
20
|
+
* React Native has no API for this because a phone has no pointer to click the
|
|
21
|
+
* other button of. On a desktop it is the second thing an app wants after a
|
|
22
|
+
* menu bar -- and on Linux it is the *first*, because GNOME has no menu bar and
|
|
23
|
+
* `Menu.isSupported` is false there.
|
|
24
|
+
*
|
|
25
|
+
* ## One level, on purpose
|
|
26
|
+
*
|
|
27
|
+
* No submenus and no roles. A popup menu on all three desktops is a list, and
|
|
28
|
+
* the nesting an application menu has is what a menu *bar* is for -- so a
|
|
29
|
+
* `<Menu>` and this are different shapes rather than the same shape twice.
|
|
30
|
+
*
|
|
31
|
+
* ## Where it appears
|
|
32
|
+
*
|
|
33
|
+
* `show(items, where)` takes anything with an `x` and a `y` in the window's
|
|
34
|
+
* coordinates, which is what a press event's `nativeEvent` already is. Pass
|
|
35
|
+
* nothing and the menu opens wherever the pointer is, which is what a menu
|
|
36
|
+
* opened from the keyboard wants.
|
|
37
|
+
*
|
|
38
|
+
* ## What it answers
|
|
39
|
+
*
|
|
40
|
+
* `show()` resolves with the index chosen, or null if the menu was dismissed --
|
|
41
|
+
* and calls that item's `onSelect` first, which is what most callers want:
|
|
42
|
+
*
|
|
43
|
+
* const chosen = await menu.show(items);
|
|
44
|
+
*
|
|
45
|
+
* A promise rather than the device event `<Menu>` uses, because the two are
|
|
46
|
+
* different situations. A menu bar is installed once and its items are chosen
|
|
47
|
+
* at times nothing is waiting for; a context menu is opened by an app that is,
|
|
48
|
+
* right then, asking a question.
|
|
49
|
+
*
|
|
50
|
+
* ## A right-click
|
|
51
|
+
*
|
|
52
|
+
* <View
|
|
53
|
+
* onPointerDown={e => e.nativeEvent.button === 2 && menu.show(items, e.nativeEvent)}
|
|
54
|
+
* />
|
|
55
|
+
*
|
|
56
|
+
* A secondary click arrives as `onPointerDown` with W3C's `button === 2`, and
|
|
57
|
+
* does *not* fire `onPress` -- on any of the three. So the same view can be a
|
|
58
|
+
* button and have a context menu, which is what a desktop expects.
|
|
59
|
+
*
|
|
60
|
+
* `onLongPress` still works and is what a touch-first app should use. See
|
|
61
|
+
* native/core/PointerButtons.h for what each toolkit had to be told.
|
|
62
|
+
*
|
|
63
|
+
* @format
|
|
64
|
+
*/
|
|
65
|
+
/**
|
|
66
|
+
* One item in a context menu, as `native/core/MenuModel.h` reads it, plus the
|
|
67
|
+
* handler this file calls.
|
|
68
|
+
*
|
|
69
|
+
* `onSelect` is the only field the native side does not see: the promise
|
|
70
|
+
* carries the index back, and this calls the handler before settling it.
|
|
71
|
+
*/
|
|
72
|
+
export type ContextMenuItem = {
|
|
73
|
+
label?: string;
|
|
74
|
+
/** One of the platform roles; see native/core/MenuModel.h. */
|
|
75
|
+
role?: string;
|
|
76
|
+
/** "CmdOrCtrl+O", in Electron's spelling. Ignored for a role. */
|
|
77
|
+
accelerator?: string;
|
|
78
|
+
enabled?: boolean;
|
|
79
|
+
separator?: boolean;
|
|
80
|
+
submenu?: ReadonlyArray<ContextMenuItem>;
|
|
81
|
+
onSelect?: () => void;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Where to open it. A press event carries `pageX`/`pageY`; a caller with a
|
|
85
|
+
* point in hand carries `x`/`y`. Either, or neither for wherever the pointer
|
|
86
|
+
* is.
|
|
87
|
+
*/
|
|
88
|
+
export type ContextMenuPoint = {
|
|
89
|
+
x?: number;
|
|
90
|
+
y?: number;
|
|
91
|
+
pageX?: number;
|
|
92
|
+
pageY?: number;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Whether this platform can show one.
|
|
96
|
+
*
|
|
97
|
+
* True on all three, unlike `Menu.isSupported`: a menu bar is what GNOME does
|
|
98
|
+
* not have, and a popup menu is something every desktop has always had.
|
|
99
|
+
*/
|
|
100
|
+
export declare const isSupported: boolean;
|
|
101
|
+
declare function show(items: ReadonlyArray<ContextMenuItem>, where?: ContextMenuPoint | null): Promise<number | null>;
|
|
102
|
+
/**
|
|
103
|
+
* The imperative half, usable outside a component -- the same arrangement
|
|
104
|
+
* `useDialog()` and `windowControl` have.
|
|
105
|
+
*/
|
|
106
|
+
export declare const contextMenu: Readonly<{
|
|
107
|
+
show: typeof show;
|
|
108
|
+
isSupported: boolean;
|
|
109
|
+
}>;
|
|
110
|
+
export type ContextMenu = typeof contextMenu;
|
|
111
|
+
export declare function useContextMenu(): ContextMenu;
|
|
112
|
+
export {};
|
|
113
|
+
//# sourceMappingURL=useContextMenu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useContextMenu.d.ts","sourceRoot":"","sources":["../../src/useContextMenu.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAKH;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAYF;;;;;GAKG;AACH,eAAO,MAAM,WAAW,SAAsC,CAAC;AAE/D,iBAAe,IAAI,CACjB,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC,EACrC,KAAK,CAAC,EAAE,gBAAgB,GAAG,IAAI,GAC9B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoBxB;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW;;;EAAqC,CAAC;AAE9D,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC;AAE7C,wBAAgB,cAAc,IAAI,WAAW,CAK5C"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* A native context menu.
|
|
4
|
+
*
|
|
5
|
+
* const menu = useContextMenu();
|
|
6
|
+
*
|
|
7
|
+
* <Pressable
|
|
8
|
+
* onLongPress={event =>
|
|
9
|
+
* menu.show(
|
|
10
|
+
* [
|
|
11
|
+
* {label: 'Copy', onSelect: copy},
|
|
12
|
+
* {separator: true},
|
|
13
|
+
* {label: 'Delete', onSelect: remove, shortcut: 'Del'},
|
|
14
|
+
* {label: 'Paste', enabled: false},
|
|
15
|
+
* ],
|
|
16
|
+
* event.nativeEvent,
|
|
17
|
+
* )
|
|
18
|
+
* }
|
|
19
|
+
* />
|
|
20
|
+
*
|
|
21
|
+
* React Native has no API for this because a phone has no pointer to click the
|
|
22
|
+
* other button of. On a desktop it is the second thing an app wants after a
|
|
23
|
+
* menu bar -- and on Linux it is the *first*, because GNOME has no menu bar and
|
|
24
|
+
* `Menu.isSupported` is false there.
|
|
25
|
+
*
|
|
26
|
+
* ## One level, on purpose
|
|
27
|
+
*
|
|
28
|
+
* No submenus and no roles. A popup menu on all three desktops is a list, and
|
|
29
|
+
* the nesting an application menu has is what a menu *bar* is for -- so a
|
|
30
|
+
* `<Menu>` and this are different shapes rather than the same shape twice.
|
|
31
|
+
*
|
|
32
|
+
* ## Where it appears
|
|
33
|
+
*
|
|
34
|
+
* `show(items, where)` takes anything with an `x` and a `y` in the window's
|
|
35
|
+
* coordinates, which is what a press event's `nativeEvent` already is. Pass
|
|
36
|
+
* nothing and the menu opens wherever the pointer is, which is what a menu
|
|
37
|
+
* opened from the keyboard wants.
|
|
38
|
+
*
|
|
39
|
+
* ## What it answers
|
|
40
|
+
*
|
|
41
|
+
* `show()` resolves with the index chosen, or null if the menu was dismissed --
|
|
42
|
+
* and calls that item's `onSelect` first, which is what most callers want:
|
|
43
|
+
*
|
|
44
|
+
* const chosen = await menu.show(items);
|
|
45
|
+
*
|
|
46
|
+
* A promise rather than the device event `<Menu>` uses, because the two are
|
|
47
|
+
* different situations. A menu bar is installed once and its items are chosen
|
|
48
|
+
* at times nothing is waiting for; a context menu is opened by an app that is,
|
|
49
|
+
* right then, asking a question.
|
|
50
|
+
*
|
|
51
|
+
* ## A right-click
|
|
52
|
+
*
|
|
53
|
+
* <View
|
|
54
|
+
* onPointerDown={e => e.nativeEvent.button === 2 && menu.show(items, e.nativeEvent)}
|
|
55
|
+
* />
|
|
56
|
+
*
|
|
57
|
+
* A secondary click arrives as `onPointerDown` with W3C's `button === 2`, and
|
|
58
|
+
* does *not* fire `onPress` -- on any of the three. So the same view can be a
|
|
59
|
+
* button and have a context menu, which is what a desktop expects.
|
|
60
|
+
*
|
|
61
|
+
* `onLongPress` still works and is what a touch-first app should use. See
|
|
62
|
+
* native/core/PointerButtons.h for what each toolkit had to be told.
|
|
63
|
+
*
|
|
64
|
+
* @format
|
|
65
|
+
*/
|
|
66
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
67
|
+
exports.contextMenu = exports.isSupported = void 0;
|
|
68
|
+
exports.useContextMenu = useContextMenu;
|
|
69
|
+
const react_native_1 = require("react-native");
|
|
70
|
+
const NativeMenu = react_native_1.TurboModuleRegistry.get('BasaltMenu');
|
|
71
|
+
/**
|
|
72
|
+
* Whether this platform can show one.
|
|
73
|
+
*
|
|
74
|
+
* True on all three, unlike `Menu.isSupported`: a menu bar is what GNOME does
|
|
75
|
+
* not have, and a popup menu is something every desktop has always had.
|
|
76
|
+
*/
|
|
77
|
+
exports.isSupported = NativeMenu?.showContextMenu != null;
|
|
78
|
+
async function show(items, where) {
|
|
79
|
+
if (!exports.isSupported || !Array.isArray(items) || items.length === 0) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
// Negative is "wherever the pointer is"; see the header. `pageX`/`pageY` as
|
|
83
|
+
// well as `x`/`y`, because a press event carries the first pair and a caller
|
|
84
|
+
// with a point in hand carries the second.
|
|
85
|
+
const x = where?.x ?? where?.pageX ?? -1;
|
|
86
|
+
const y = where?.y ?? where?.pageY ?? -1;
|
|
87
|
+
// `isSupported` is what proves this is non-null, and the compiler cannot see
|
|
88
|
+
// through that -- it is computed at module scope from the same optional call.
|
|
89
|
+
const index = await NativeMenu.showContextMenu(items, x, y);
|
|
90
|
+
if (index == null) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
// Called before the promise settles, so that an app which only wants
|
|
94
|
+
// `onSelect` never has to await anything.
|
|
95
|
+
items[index]?.onSelect?.();
|
|
96
|
+
return index;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The imperative half, usable outside a component -- the same arrangement
|
|
100
|
+
* `useDialog()` and `windowControl` have.
|
|
101
|
+
*/
|
|
102
|
+
exports.contextMenu = Object.freeze({ show, isSupported: exports.isSupported });
|
|
103
|
+
function useContextMenu() {
|
|
104
|
+
// Frozen and module-level, so this is a stable identity rather than a new
|
|
105
|
+
// object every render: an app putting `menu` in a dependency array should not
|
|
106
|
+
// get a new one each time.
|
|
107
|
+
return exports.contextMenu;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=useContextMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useContextMenu.js","sourceRoot":"","sources":["../../src/useContextMenu.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;;;AAuFH,wCAKC;AAzFD,+CAAiD;AAyCjD,MAAM,UAAU,GAAG,kCAAmB,CAAC,GAAG,CAAmB,YAAY,CAAC,CAAC;AAE3E;;;;;GAKG;AACU,QAAA,WAAW,GAAG,UAAU,EAAE,eAAe,IAAI,IAAI,CAAC;AAE/D,KAAK,UAAU,IAAI,CACjB,KAAqC,EACrC,KAA+B;IAE/B,IAAI,CAAC,mBAAW,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,4EAA4E;IAC5E,6EAA6E;IAC7E,2CAA2C;IAC3C,MAAM,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,KAAK,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC;IACzC,MAAM,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,KAAK,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC;IAEzC,6EAA6E;IAC7E,8EAA8E;IAC9E,MAAM,KAAK,GAAG,MAAM,UAAW,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7D,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,qEAAqE;IACrE,0CAA0C;IAC1C,KAAK,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC;IAC3B,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACU,QAAA,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,EAAC,IAAI,EAAE,WAAW,EAAX,mBAAW,EAAC,CAAC,CAAC;AAI9D,SAAgB,cAAc;IAC5B,0EAA0E;IAC1E,8EAA8E;IAC9E,2BAA2B;IAC3B,OAAO,mBAAW,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The native file dialogs.
|
|
3
|
+
*
|
|
4
|
+
* const dialog = useDialog();
|
|
5
|
+
*
|
|
6
|
+
* const {canceled, paths} = await dialog.openFile({
|
|
7
|
+
* title: 'Choose an image',
|
|
8
|
+
* multiple: true,
|
|
9
|
+
* filters: [{name: 'Images', extensions: ['png', 'jpg', 'jpeg']}],
|
|
10
|
+
* });
|
|
11
|
+
*
|
|
12
|
+
* const {canceled, paths: [path]} = await dialog.saveFile({
|
|
13
|
+
* defaultPath: 'notes.md',
|
|
14
|
+
* });
|
|
15
|
+
*
|
|
16
|
+
* const {canceled, paths: [folder]} = await dialog.openFolder();
|
|
17
|
+
*
|
|
18
|
+
* React Native has no API for any of this, because a phone has no file dialog,
|
|
19
|
+
* so there is nothing here to be compatible with. The semantics follow
|
|
20
|
+
* Electron's -- the vocabulary a desktop developer already has -- and the shape
|
|
21
|
+
* is React Native's.
|
|
22
|
+
*
|
|
23
|
+
* ## Why every one of them answers `{canceled, paths}`
|
|
24
|
+
*
|
|
25
|
+
* Because "the person pressed Cancel" and "the person chose nothing" are
|
|
26
|
+
* different answers, and every API that collapses them is one somebody has to
|
|
27
|
+
* work around. `paths` is a list even for a save and a folder, where it always
|
|
28
|
+
* has one entry, so that an app moving between the three is not also moving
|
|
29
|
+
* between result types:
|
|
30
|
+
*
|
|
31
|
+
* const {canceled, paths: [path]} = await dialog.saveFile();
|
|
32
|
+
* if (canceled) return;
|
|
33
|
+
*
|
|
34
|
+
* ## Why a hook rather than a module
|
|
35
|
+
*
|
|
36
|
+
* `useDialog()` returns the same object every time and does not subscribe to
|
|
37
|
+
* anything, so as a hook it buys exactly one thing: it is the shape the rest of
|
|
38
|
+
* this package uses, and a component that calls it reads like a component. An
|
|
39
|
+
* app that wants it outside a component can import `dialog` instead -- it is
|
|
40
|
+
* the same object, and the hook returns it.
|
|
41
|
+
*
|
|
42
|
+
* On a host with no dialog module every call resolves `{canceled: true, paths:
|
|
43
|
+
* []}` rather than throwing, so the same code runs on a platform that has not
|
|
44
|
+
* implemented one yet.
|
|
45
|
+
*
|
|
46
|
+
* @format
|
|
47
|
+
*/
|
|
48
|
+
/**
|
|
49
|
+
* A file type a dialog offers to filter by. Extensions are bare -- 'png', not
|
|
50
|
+
* '.png' and not 'image/png' -- which is what all three desktops translate
|
|
51
|
+
* from.
|
|
52
|
+
*/
|
|
53
|
+
export type DialogFilter = {
|
|
54
|
+
name: string;
|
|
55
|
+
extensions: ReadonlyArray<string>;
|
|
56
|
+
};
|
|
57
|
+
export type DialogOptions = {
|
|
58
|
+
title?: string;
|
|
59
|
+
defaultPath?: string;
|
|
60
|
+
confirmLabel?: string;
|
|
61
|
+
/** Open only; a save and a folder choose one. */
|
|
62
|
+
multiple?: boolean;
|
|
63
|
+
filters?: ReadonlyArray<DialogFilter>;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Always both, and always a list. "The person pressed Cancel" and "the person
|
|
67
|
+
* chose nothing" are different answers; `paths` is a list even where it can
|
|
68
|
+
* only have one entry, so an app moving between the three calls is not also
|
|
69
|
+
* moving between result types.
|
|
70
|
+
*/
|
|
71
|
+
export type DialogResult = {
|
|
72
|
+
canceled: boolean;
|
|
73
|
+
paths: ReadonlyArray<string>;
|
|
74
|
+
};
|
|
75
|
+
export declare const dialog: Readonly<{
|
|
76
|
+
/**
|
|
77
|
+
* One or more existing files.
|
|
78
|
+
*
|
|
79
|
+
* `{title, defaultPath, confirmLabel, multiple, filters}`, all optional.
|
|
80
|
+
* `filters` is `[{name, extensions}]` with the extensions bare -- 'png', not
|
|
81
|
+
* '.png' and not 'image/png' -- which is what all three desktops translate
|
|
82
|
+
* from.
|
|
83
|
+
*/
|
|
84
|
+
openFile(options?: DialogOptions | null): Promise<DialogResult>;
|
|
85
|
+
/**
|
|
86
|
+
* A path to write to, which may not exist yet. `defaultPath` is the
|
|
87
|
+
* suggested name, optionally with a directory in front of it.
|
|
88
|
+
*
|
|
89
|
+
* Whether an existing file may be overwritten is the platform's question and
|
|
90
|
+
* it asks for itself; by the time this resolves, the answer was yes.
|
|
91
|
+
*/
|
|
92
|
+
saveFile(options?: DialogOptions | null): Promise<DialogResult>;
|
|
93
|
+
/** A directory. `filters` means nothing here and is ignored. */
|
|
94
|
+
openFolder(options?: DialogOptions | null): Promise<DialogResult>;
|
|
95
|
+
}>;
|
|
96
|
+
export type Dialog = typeof dialog;
|
|
97
|
+
export declare function useDialog(): Dialog;
|
|
98
|
+
//# sourceMappingURL=useDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDialog.d.ts","sourceRoot":"","sources":["../../src/useDialog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAKH;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;CACvC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAC9B,CAAC;AA6BF,eAAO,MAAM,MAAM;IACjB;;;;;;;OAOG;uBACsB,aAAa,GAAG,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC;IAOrE;;;;;;OAMG;uBACsB,aAAa,GAAG,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC;IAOrE,gEAAgE;yBACrC,aAAa,GAAG,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC;EAMvE,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC;AAEnC,wBAAgB,SAAS,IAAI,MAAM,CAIlC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The native file dialogs.
|
|
4
|
+
*
|
|
5
|
+
* const dialog = useDialog();
|
|
6
|
+
*
|
|
7
|
+
* const {canceled, paths} = await dialog.openFile({
|
|
8
|
+
* title: 'Choose an image',
|
|
9
|
+
* multiple: true,
|
|
10
|
+
* filters: [{name: 'Images', extensions: ['png', 'jpg', 'jpeg']}],
|
|
11
|
+
* });
|
|
12
|
+
*
|
|
13
|
+
* const {canceled, paths: [path]} = await dialog.saveFile({
|
|
14
|
+
* defaultPath: 'notes.md',
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* const {canceled, paths: [folder]} = await dialog.openFolder();
|
|
18
|
+
*
|
|
19
|
+
* React Native has no API for any of this, because a phone has no file dialog,
|
|
20
|
+
* so there is nothing here to be compatible with. The semantics follow
|
|
21
|
+
* Electron's -- the vocabulary a desktop developer already has -- and the shape
|
|
22
|
+
* is React Native's.
|
|
23
|
+
*
|
|
24
|
+
* ## Why every one of them answers `{canceled, paths}`
|
|
25
|
+
*
|
|
26
|
+
* Because "the person pressed Cancel" and "the person chose nothing" are
|
|
27
|
+
* different answers, and every API that collapses them is one somebody has to
|
|
28
|
+
* work around. `paths` is a list even for a save and a folder, where it always
|
|
29
|
+
* has one entry, so that an app moving between the three is not also moving
|
|
30
|
+
* between result types:
|
|
31
|
+
*
|
|
32
|
+
* const {canceled, paths: [path]} = await dialog.saveFile();
|
|
33
|
+
* if (canceled) return;
|
|
34
|
+
*
|
|
35
|
+
* ## Why a hook rather than a module
|
|
36
|
+
*
|
|
37
|
+
* `useDialog()` returns the same object every time and does not subscribe to
|
|
38
|
+
* anything, so as a hook it buys exactly one thing: it is the shape the rest of
|
|
39
|
+
* this package uses, and a component that calls it reads like a component. An
|
|
40
|
+
* app that wants it outside a component can import `dialog` instead -- it is
|
|
41
|
+
* the same object, and the hook returns it.
|
|
42
|
+
*
|
|
43
|
+
* On a host with no dialog module every call resolves `{canceled: true, paths:
|
|
44
|
+
* []}` rather than throwing, so the same code runs on a platform that has not
|
|
45
|
+
* implemented one yet.
|
|
46
|
+
*
|
|
47
|
+
* @format
|
|
48
|
+
*/
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.dialog = void 0;
|
|
51
|
+
exports.useDialog = useDialog;
|
|
52
|
+
const react_native_1 = require("react-native");
|
|
53
|
+
const NativeDialog = react_native_1.TurboModuleRegistry.get('BasaltDialog');
|
|
54
|
+
const CANCELED = Object.freeze({
|
|
55
|
+
canceled: true,
|
|
56
|
+
paths: Object.freeze([]),
|
|
57
|
+
});
|
|
58
|
+
/**
|
|
59
|
+
* Normalises whatever the native side answered.
|
|
60
|
+
*
|
|
61
|
+
* The host is this project's own and answers the right shape, so this is not
|
|
62
|
+
* defensive about it: what it is for is the host that has no module at all,
|
|
63
|
+
* where there is no answer to normalise.
|
|
64
|
+
*/
|
|
65
|
+
function answer(result) {
|
|
66
|
+
if (result == null || !Array.isArray(result.paths)) {
|
|
67
|
+
return CANCELED;
|
|
68
|
+
}
|
|
69
|
+
return { canceled: result.canceled === true, paths: result.paths };
|
|
70
|
+
}
|
|
71
|
+
exports.dialog = Object.freeze({
|
|
72
|
+
/**
|
|
73
|
+
* One or more existing files.
|
|
74
|
+
*
|
|
75
|
+
* `{title, defaultPath, confirmLabel, multiple, filters}`, all optional.
|
|
76
|
+
* `filters` is `[{name, extensions}]` with the extensions bare -- 'png', not
|
|
77
|
+
* '.png' and not 'image/png' -- which is what all three desktops translate
|
|
78
|
+
* from.
|
|
79
|
+
*/
|
|
80
|
+
async openFile(options) {
|
|
81
|
+
if (NativeDialog == null) {
|
|
82
|
+
return CANCELED;
|
|
83
|
+
}
|
|
84
|
+
return answer(await NativeDialog.openFile(options ?? {}));
|
|
85
|
+
},
|
|
86
|
+
/**
|
|
87
|
+
* A path to write to, which may not exist yet. `defaultPath` is the
|
|
88
|
+
* suggested name, optionally with a directory in front of it.
|
|
89
|
+
*
|
|
90
|
+
* Whether an existing file may be overwritten is the platform's question and
|
|
91
|
+
* it asks for itself; by the time this resolves, the answer was yes.
|
|
92
|
+
*/
|
|
93
|
+
async saveFile(options) {
|
|
94
|
+
if (NativeDialog == null) {
|
|
95
|
+
return CANCELED;
|
|
96
|
+
}
|
|
97
|
+
return answer(await NativeDialog.saveFile(options ?? {}));
|
|
98
|
+
},
|
|
99
|
+
/** A directory. `filters` means nothing here and is ignored. */
|
|
100
|
+
async openFolder(options) {
|
|
101
|
+
if (NativeDialog == null) {
|
|
102
|
+
return CANCELED;
|
|
103
|
+
}
|
|
104
|
+
return answer(await NativeDialog.openFolder(options ?? {}));
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
function useDialog() {
|
|
108
|
+
// The same object every render. Nothing here depends on a render, so a new
|
|
109
|
+
// one would only make every effect that lists it a dependency run again.
|
|
110
|
+
return exports.dialog;
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=useDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDialog.js","sourceRoot":"","sources":["../../src/useDialog.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;;;AAuGH,8BAIC;AAxGD,+CAAiD;AAsCjD,MAAM,YAAY,GAAG,kCAAmB,CAAC,GAAG,CAAqB,cAAc,CAAC,CAAC;AAEjF,MAAM,QAAQ,GAAiB,MAAM,CAAC,MAAM,CAAC;IAC3C,QAAQ,EAAE,IAAI;IACd,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAA0B;CAClD,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,SAAS,MAAM,CAAC,MAAgD;IAC9D,IAAI,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACnD,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,EAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,KAAK,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAC,CAAC;AACnE,CAAC;AAEY,QAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAClC;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,CAAC,OAA8B;QAC3C,IAAI,YAAY,IAAI,IAAI,EAAE,CAAC;YACzB,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,YAAY,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,QAAQ,CAAC,OAA8B;QAC3C,IAAI,YAAY,IAAI,IAAI,EAAE,CAAC;YACzB,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,YAAY,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,gEAAgE;IAChE,KAAK,CAAC,UAAU,CAAC,OAA8B;QAC7C,IAAI,YAAY,IAAI,IAAI,EAAE,CAAC;YACzB,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,YAAY,CAAC,UAAU,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9D,CAAC;CACF,CAAC,CAAC;AAIH,SAAgB,SAAS;IACvB,2EAA2E;IAC3E,yEAAyE;IACzE,OAAO,cAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What screens the desktop has, where they are, and how dense they are.
|
|
3
|
+
*
|
|
4
|
+
* React Native's `Dimensions` reports the *window*, which is the right answer
|
|
5
|
+
* to a different question. An app placing a window, or deciding how much it
|
|
6
|
+
* can show, is asking about the screen it is on and the ones beside it.
|
|
7
|
+
*
|
|
8
|
+
* ## What each desktop will and will not say
|
|
9
|
+
*
|
|
10
|
+
* Bounds and scale factor: everywhere. The work area -- what is left after a
|
|
11
|
+
* menu bar, taskbar or dock -- comes from macOS and Windows, and GTK 4 has no
|
|
12
|
+
* way to ask, so it reports the full bounds there. The pointer's position
|
|
13
|
+
* comes from macOS and Windows and never from GTK.
|
|
14
|
+
*
|
|
15
|
+
* None of those are gaps waiting to be filled. `gdk_monitor_get_workarea`,
|
|
16
|
+
* `gdk_display_get_primary_monitor` and reading the pointer were all in GTK 3
|
|
17
|
+
* and were removed: Wayland has no protocol a client can use for any of them.
|
|
18
|
+
* See native/gtk/GtkWindowControl.cpp.
|
|
19
|
+
*
|
|
20
|
+
* So an app that needs the work area should treat "equal to bounds" as the
|
|
21
|
+
* answer rather than as a failure, and one that needs the pointer should check
|
|
22
|
+
* `known`.
|
|
23
|
+
*
|
|
24
|
+
* @format
|
|
25
|
+
*/
|
|
26
|
+
/** One display, in the same logical pixels and coordinates windows use. */
|
|
27
|
+
export type Display = {
|
|
28
|
+
x: number;
|
|
29
|
+
y: number;
|
|
30
|
+
width: number;
|
|
31
|
+
height: number;
|
|
32
|
+
/** What is left after the desktop's furniture; equal to the bounds on GTK. */
|
|
33
|
+
workX: number;
|
|
34
|
+
workY: number;
|
|
35
|
+
workWidth: number;
|
|
36
|
+
workHeight: number;
|
|
37
|
+
/** Physical pixels per logical pixel. Never zero. */
|
|
38
|
+
scaleFactor: number;
|
|
39
|
+
primary: boolean;
|
|
40
|
+
};
|
|
41
|
+
export type PointerPosition = {
|
|
42
|
+
x: number;
|
|
43
|
+
y: number;
|
|
44
|
+
/** False where the desktop will not say -- always, on GTK. */
|
|
45
|
+
known: boolean;
|
|
46
|
+
};
|
|
47
|
+
/** Whether this platform can be asked at all. */
|
|
48
|
+
export declare const isSupported: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Every display, primary first.
|
|
51
|
+
*
|
|
52
|
+
* Synchronous, because the host keeps the list up to date rather than the
|
|
53
|
+
* platform asking the toolkit on demand -- see core/WindowControl.h. Empty
|
|
54
|
+
* before the host has reported anything, which an app can distinguish from
|
|
55
|
+
* "no displays" only by there being no such desktop.
|
|
56
|
+
*/
|
|
57
|
+
export declare function displays(): Display[];
|
|
58
|
+
/** Where the pointer is. A promise: nothing reports the pointer moving. */
|
|
59
|
+
export declare function pointerPosition(): Promise<PointerPosition>;
|
|
60
|
+
/**
|
|
61
|
+
* The displays, kept current.
|
|
62
|
+
*
|
|
63
|
+
* Re-reads whenever a monitor is plugged in, unplugged or rearranged. The
|
|
64
|
+
* event carries no payload for a reason -- several changes can arrive
|
|
65
|
+
* together, and re-reading is the only way to be right about all of them.
|
|
66
|
+
*/
|
|
67
|
+
export declare function useDisplays(): Display[];
|
|
68
|
+
/** The primary display, or null on a platform with none to report. */
|
|
69
|
+
export declare function primaryDisplay(): Display | null;
|
|
70
|
+
//# sourceMappingURL=useDisplays.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDisplays.d.ts","sourceRoot":"","sources":["../../src/useDisplays.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAMH,2EAA2E;AAC3E,MAAM,MAAM,OAAO,GAAG;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,8DAA8D;IAC9D,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAYF,iDAAiD;AACjD,eAAO,MAAM,WAAW,SAAqC,CAAC;AAE9D;;;;;;;GAOG;AACH,wBAAgB,QAAQ,IAAI,OAAO,EAAE,CAGpC;AAED,2EAA2E;AAC3E,wBAAgB,eAAe,IAAI,OAAO,CAAC,eAAe,CAAC,CAK1D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,IAAI,OAAO,EAAE,CAkBvC;AAED,sEAAsE;AACtE,wBAAgB,cAAc,IAAI,OAAO,GAAG,IAAI,CAG/C"}
|