akanjs 3.0.2 → 3.1.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/base/baseEnv.ts +0 -4
- package/base/primitiveRegistry.ts +2 -2
- package/client/cookie.ts +5 -1
- package/client/csrLocation.ts +122 -0
- package/client/csrTypes.ts +32 -4
- package/client/device.ts +2 -1
- package/client/frameConfig.ts +78 -7
- package/client/index.ts +3 -0
- package/client/makePageProto.tsx +3 -2
- package/client/native/external-view.ts +1 -0
- package/client/route/RootLayoutDefinition.ts +7 -1
- package/client/route/RouteHead.ts +108 -0
- package/client/route/index.ts +1 -0
- package/client/router.ts +36 -23
- package/client/rscNavigation.ts +8 -2
- package/client/viewportMeta.ts +60 -0
- package/client/webManifest.ts +18 -0
- package/common/Logger.ts +7 -2
- package/common/PipelineNames.ts +31 -0
- package/common/PipelinePattern.ts +70 -0
- package/common/PipelinePlanSchema.ts +490 -0
- package/common/backoff.ts +14 -0
- package/common/index.ts +39 -0
- package/common/pipelinePlan.ts +259 -0
- package/common/routeConvention.ts +1 -0
- package/common/types.ts +17 -0
- package/constant/constantRegistry.ts +26 -6
- package/dictionary/base.dictionary.ts +8 -0
- package/dictionary/trans.ts +9 -1
- package/document/into.ts +5 -0
- package/fetch/client/fetchClient.ts +135 -31
- package/fetch/client/httpClient.ts +45 -0
- package/fetch/client/wsClient.ts +125 -16
- package/fetch/fetchType/buildFetch.type.ts +1 -0
- package/index.ts +243 -10
- package/package.json +1 -5
- package/server/akanApp.ts +5 -2
- package/server/akanServer.ts +44 -8
- package/server/artifact/builderRpc.ts +8 -3
- package/server/artifact/ipcTypes.ts +5 -2
- package/server/di/diLifecycle.ts +39 -3
- package/server/di/utils.ts +28 -1
- package/server/ed25519Key.ts +48 -0
- package/server/index.ts +1 -0
- package/server/machine/index.ts +2 -0
- package/server/machine/machineAccount.ts +27 -0
- package/server/machine/machineToken.ts +151 -0
- package/server/mcp/McpApps.ts +256 -0
- package/server/mcp/McpDispatcher.ts +31 -7
- package/server/mcp/McpRouter.ts +209 -46
- package/server/ops/opsToken.ts +3 -10
- package/server/resolver/database.resolver.ts +3 -0
- package/server/resolver/signal.resolver.ts +40 -3
- package/server/routeElementComposer.tsx +78 -2
- package/server/routeState.ts +6 -0
- package/server/routeTreeBuilder.ts +26 -9
- package/server/routing/apiRouter.ts +6 -3
- package/server/routing/roomReplay.ts +88 -0
- package/server/rscClient.tsx +53 -8
- package/server/rscWorker.tsx +141 -27
- package/server/rscWorkerHost.ts +18 -5
- package/server/sitemap.ts +14 -0
- package/server/ssrFromRscRenderer.tsx +12 -6
- package/server/ssrTypes.ts +3 -1
- package/server/systemPageDocument.tsx +38 -30
- package/server/types.tsx +2 -0
- package/server/webRouter.ts +74 -5
- package/service/injectInfo.ts +9 -1
- package/service/ipcTypes.ts +2 -1
- package/service/predefinedAdaptor/database.adaptor.ts +1 -146
- package/service/predefinedAdaptor/queue.adaptor.ts +44 -6
- package/service/predefinedAdaptor/queueBackoff.ts +12 -0
- package/service/predefinedAdaptor/solidQueue.adaptor.ts +17 -13
- package/service/predefinedAdaptor/sql/SqlDocumentStore.ts +44 -2
- package/service/predefinedAdaptor/sql/dialect/postgres.ts +3 -0
- package/service/predefinedAdaptor/sql/dialect/sqlite.ts +5 -2
- package/service/predefinedAdaptor/sql/search/fts5.ts +1 -1
- package/service/predefinedAdaptor/sql/types.ts +8 -6
- package/service/predefinedAdaptor/sql/values.ts +0 -23
- package/service/serve.ts +5 -1
- package/signal/agent.signal.ts +1 -1
- package/signal/base.signal.ts +2 -2
- package/signal/endpointIdempotency.ts +53 -0
- package/signal/internalArg.ts +14 -0
- package/signal/mcp/McpDocument.ts +38 -1
- package/signal/mcp/mcpProtocol.ts +18 -0
- package/signal/signalContext.ts +58 -30
- package/signal/signalRegistry.ts +14 -4
- package/signal/types.ts +18 -3
- package/store/agent/StoreSurfaceSource.ts +1 -1
- package/store/agentic/StToolBuilder.ts +3 -0
- package/test/conformance.ts +9 -33
- package/types/base/baseEnv.d.ts +0 -4
- package/types/base/primitiveRegistry.d.ts +1 -1
- package/types/client/csrLocation.d.ts +32 -0
- package/types/client/csrTypes.d.ts +40 -4
- package/types/client/frameConfig.d.ts +14 -2
- package/types/client/index.d.ts +3 -0
- package/types/client/native/external-view.d.ts +1 -0
- package/types/client/route/RootLayoutDefinition.d.ts +2 -1
- package/types/client/route/RouteHead.d.ts +13 -0
- package/types/client/route/index.d.ts +1 -0
- package/types/client/router.d.ts +6 -0
- package/types/client/rscNavigation.d.ts +4 -0
- package/types/client/viewportMeta.d.ts +18 -0
- package/types/client/webManifest.d.ts +4 -0
- package/types/common/PipelineNames.d.ts +6 -0
- package/types/common/PipelinePattern.d.ts +14 -0
- package/types/common/PipelinePlanSchema.d.ts +9 -0
- package/types/common/backoff.d.ts +10 -0
- package/types/common/index.d.ts +5 -0
- package/types/common/pipelinePlan.d.ts +224 -0
- package/types/common/types.d.ts +16 -0
- package/types/constant/constantRegistry.d.ts +5 -2
- package/types/dictionary/base.dictionary.d.ts +1 -1
- package/types/dictionary/dictionary.d.ts +8 -8
- package/types/document/into.d.ts +9 -0
- package/types/fetch/client/fetchClient.d.ts +31 -4
- package/types/fetch/client/httpClient.d.ts +8 -0
- package/types/fetch/client/wsClient.d.ts +26 -2
- package/types/fetch/fetchType/buildFetch.type.d.ts +1 -0
- package/types/index.d.ts +230 -9
- package/types/server/akanServer.d.ts +16 -1
- package/types/server/artifact/builderRpc.d.ts +7 -2
- package/types/server/artifact/ipcTypes.d.ts +5 -1
- package/types/server/di/utils.d.ts +1 -0
- package/types/server/ed25519Key.d.ts +13 -0
- package/types/server/index.d.ts +1 -0
- package/types/server/machine/index.d.ts +2 -0
- package/types/server/machine/machineAccount.d.ts +5 -0
- package/types/server/machine/machineToken.d.ts +29 -0
- package/types/server/machine.d.ts +1 -0
- package/types/server/mcp/McpApps.d.ts +50 -0
- package/types/server/mcp/McpDispatcher.d.ts +4 -1
- package/types/server/mcp/McpRouter.d.ts +4 -0
- package/types/server/resolver/signal.resolver.d.ts +2 -1
- package/types/server/routeElementComposer.d.ts +24 -4
- package/types/server/routeState.d.ts +4 -1
- package/types/server/routing/roomReplay.d.ts +24 -0
- package/types/server/rscWorkerHost.d.ts +5 -2
- package/types/server/sitemap.d.ts +2 -0
- package/types/server/ssrFromRscRenderer.d.ts +3 -3
- package/types/server/ssrTypes.d.ts +4 -1
- package/types/server/systemPageDocument.d.ts +2 -0
- package/types/server/types.d.ts +4 -1
- package/types/server/webRouter.d.ts +3 -1
- package/types/service/ipcTypes.d.ts +2 -0
- package/types/service/predefinedAdaptor/database.adaptor.d.ts +1 -24
- package/types/service/predefinedAdaptor/queue.adaptor.d.ts +10 -3
- package/types/service/predefinedAdaptor/queueBackoff.d.ts +4 -0
- package/types/service/predefinedAdaptor/solidQueue.adaptor.d.ts +3 -3
- package/types/service/predefinedAdaptor/sql/SqlDocumentStore.d.ts +6 -1
- package/types/service/predefinedAdaptor/sql/dialect/postgres.d.ts +1 -0
- package/types/service/predefinedAdaptor/sql/dialect/sqlite.d.ts +1 -0
- package/types/service/predefinedAdaptor/sql/search/fts5.d.ts +1 -1
- package/types/service/predefinedAdaptor/sql/types.d.ts +9 -5
- package/types/service/predefinedAdaptor/sql/values.d.ts +0 -3
- package/types/service/serve.d.ts +3 -0
- package/types/signal/endpointIdempotency.d.ts +7 -0
- package/types/signal/internalArg.d.ts +10 -0
- package/types/signal/mcp/McpDocument.d.ts +8 -0
- package/types/signal/mcp/mcpProtocol.d.ts +17 -0
- package/types/signal/signalContext.d.ts +5 -3
- package/types/signal/signalRegistry.d.ts +4 -4
- package/types/signal/types.d.ts +21 -1
- package/types/store/agentic/StToolBuilder.d.ts +2 -0
- package/types/test/conformance.d.ts +7 -10
- package/types/ui/Agent/Chat.d.ts +5 -1
- package/types/ui/Agent/EmbedApproval.d.ts +1 -0
- package/types/ui/Agent/index.d.ts +3 -0
- package/types/ui/Agent/useKeyboardFrame.d.ts +2 -0
- package/types/ui/Agent/useScreenActions.d.ts +18 -0
- package/types/ui/BottomSheet.d.ts +1 -0
- package/types/ui/Constant/Doc.d.ts +11 -17
- package/types/ui/Constant/index.d.ts +7 -2
- package/types/ui/Constant/schemaDoc.d.ts +11 -0
- package/types/ui/Dialog/Modal.d.ts +6 -1
- package/types/ui/Dialog/index.d.ts +1 -1
- package/types/ui/Dialog/modalSurface.d.ts +12 -0
- package/types/ui/Layout/BottomTab.d.ts +11 -2
- package/types/ui/Layout/FrameSlotFallback.d.ts +9 -0
- package/types/ui/Layout/Navbar.d.ts +4 -1
- package/types/ui/Layout/TopInset.d.ts +1 -1
- package/types/ui/Layout/index.d.ts +3 -3
- package/types/ui/Link/Action.d.ts +5 -1
- package/types/ui/Link/Anchor.d.ts +5 -3
- package/types/ui/Link/activePath.d.ts +13 -0
- package/types/ui/Link/index.d.ts +1 -1
- package/types/ui/Modal.d.ts +6 -1
- package/types/ui/Model/EditModal.d.ts +6 -1
- package/types/ui/Model/New.d.ts +6 -1
- package/types/ui/Model/ViewEditModal.d.ts +6 -1
- package/types/ui/Model/ViewModal.d.ts +6 -1
- package/types/ui/Model/newFormOrigin.d.ts +7 -0
- package/types/ui/Portal.d.ts +3 -1
- package/types/ui/Reference/origin.d.ts +12 -0
- package/types/ui/Signal/Doc.d.ts +23 -18
- package/types/ui/Signal/Listener.d.ts +2 -6
- package/types/ui/Signal/Object.d.ts +6 -10
- package/types/ui/Signal/Response.d.ts +3 -6
- package/types/ui/Signal/RestApi.d.ts +11 -15
- package/types/ui/Signal/WebSocket.d.ts +11 -21
- package/types/ui/Signal/endpointEntries.d.ts +8 -0
- package/types/ui/Signal/index.d.ts +35 -12
- package/types/ui/Signal/signalText.d.ts +178 -0
- package/types/ui/System/CSR.d.ts +2 -2
- package/types/ui/System/Client.d.ts +4 -3
- package/types/ui/System/Common.d.ts +27 -6
- package/types/ui/System/SSR.d.ts +6 -6
- package/types/ui/Tooltip.d.ts +4 -2
- package/types/ui/index.d.ts +2 -1
- package/types/ui/overlayLayer.d.ts +6 -0
- package/types/ui/overlayPosition.d.ts +17 -0
- package/types/vendor/@akanjs/native/packages/cli/src/api.d.ts +14 -3
- package/types/vendor/@akanjs/native/packages/cli/src/commands/update.d.ts +1 -1
- package/types/vendor/@akanjs/native/packages/cli/src/config.d.ts +30 -5
- package/types/vendor/@akanjs/native/packages/cli/src/lib/compat.d.ts +8 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/desktop-server.d.ts +5 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/distribution.d.ts +22 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/project.d.ts +4 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/publish.d.ts +16 -10
- package/types/vendor/@akanjs/native/packages/cli/src/lib/updates.d.ts +51 -7
- package/types/vendor/@akanjs/native/packages/cli/src/lib/vectors.d.ts +1 -1
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/windows-installer.d.ts +7 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/windows.d.ts +5 -0
- package/types/vendor/@akanjs/native/packages/core/src/kernel.d.ts +36 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/plugin.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/server.d.ts +11 -0
- package/types/vendor/@akanjs/native/plugins/external-view/src/desktop.d.ts +17 -0
- package/types/vendor/@akanjs/native/plugins/external-view/src/index.d.ts +132 -0
- package/types/vendor/@akanjs/native/plugins/external-view/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/updates/src/index.d.ts +8 -0
- package/types/vendor/@akanjs/native/plugins/window/src/desktop.d.ts +4 -1
- package/types/vendor/@akanjs/native/plugins/window/src/index.d.ts +49 -0
- package/types/vendor/use-agentic/types.d.ts +2 -0
- package/types/webkit/CsrStack.d.ts +1 -1
- package/types/webkit/McpAppAgent.d.ts +14 -0
- package/types/webkit/McpAppApprovals.d.ts +8 -0
- package/types/webkit/McpAppBridge.d.ts +101 -0
- package/types/webkit/McpAppView.d.ts +21 -0
- package/types/webkit/index.d.ts +1 -0
- package/types/webkit/useLocation.d.ts +1 -1
- package/types/webkit/useVisualViewportFrame.d.ts +13 -0
- package/ui/Agent/Chat.tsx +29 -10
- package/ui/Agent/Composer.tsx +2 -1
- package/ui/Agent/EmbedApproval.tsx +17 -0
- package/ui/Agent/RichInput.tsx +1 -1
- package/ui/Agent/index.ts +2 -0
- package/ui/Agent/useKeyboardFrame.ts +10 -0
- package/ui/Agent/useScreenActions.ts +45 -0
- package/ui/BottomSheet.tsx +82 -53
- package/ui/Constant/Doc.tsx +113 -60
- package/ui/Constant/index.ts +2 -2
- package/ui/Constant/schemaDoc.ts +86 -26
- package/ui/Dialog/LegacyModal.tsx +53 -52
- package/ui/Dialog/Modal.tsx +93 -49
- package/ui/Dialog/modalSurface.ts +61 -0
- package/ui/DragAction.tsx +1 -1
- package/ui/DraggableList.tsx +1 -1
- package/ui/Dropdown.tsx +4 -6
- package/ui/KeyboardAvoiding.tsx +1 -1
- package/ui/Layout/BottomInset.tsx +20 -14
- package/ui/Layout/BottomTab.tsx +42 -16
- package/ui/Layout/FrameSlotFallback.tsx +59 -0
- package/ui/Layout/Navbar.tsx +37 -11
- package/ui/Layout/Sider.tsx +1 -1
- package/ui/Layout/TopInset.tsx +15 -14
- package/ui/Link/Action.tsx +15 -5
- package/ui/Link/Anchor.tsx +25 -13
- package/ui/Link/activePath.ts +25 -0
- package/ui/Link/index.tsx +1 -1
- package/ui/Load/Pagination.tsx +1 -1
- package/ui/Load/Units.tsx +1 -1
- package/ui/Loading/ProgressBar.tsx +1 -1
- package/ui/Modal.tsx +9 -0
- package/ui/Model/EditModal.tsx +16 -1
- package/ui/Model/New.tsx +25 -2
- package/ui/Model/NewWrapper_Client.tsx +2 -0
- package/ui/Model/ViewEditModal.tsx +9 -0
- package/ui/Model/ViewModal.tsx +16 -1
- package/ui/Model/newFormOrigin.ts +45 -0
- package/ui/Popconfirm.tsx +5 -7
- package/ui/Portal.tsx +4 -7
- package/ui/Reference/origin.ts +31 -0
- package/ui/ScreenNavigator.tsx +1 -1
- package/ui/Select.tsx +2 -7
- package/ui/Signal/Arg.tsx +2 -2
- package/ui/Signal/Doc.tsx +125 -63
- package/ui/Signal/Endpoint.tsx +11 -10
- package/ui/Signal/Listener.tsx +7 -10
- package/ui/Signal/Object.tsx +7 -14
- package/ui/Signal/Response.tsx +24 -24
- package/ui/Signal/RestApi.tsx +63 -52
- package/ui/Signal/WebSocket.tsx +65 -72
- package/ui/Signal/endpointEntries.ts +25 -0
- package/ui/Signal/index.ts +23 -6
- package/ui/Signal/signalText.ts +59 -0
- package/ui/System/CSR.tsx +34 -8
- package/ui/System/Client.tsx +36 -5
- package/ui/System/Common.tsx +76 -32
- package/ui/System/SSR.tsx +73 -31
- package/ui/Toast.tsx +1 -1
- package/ui/Tooltip.tsx +84 -30
- package/ui/index.ts +11 -1
- package/ui/overlayLayer.ts +25 -2
- package/ui/overlayPosition.ts +90 -0
- package/ui/recipe/inputRecipe.ts +8 -1
- package/ui/styles.css +152 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeActivity.kt +22 -2
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeKernel.kt +37 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeUpdateReports.kt +169 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeUpdates.kt +110 -38
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeVectors.kt +20 -0
- package/vendor/@akanjs/native/native/desktop/Cargo.lock +16 -16
- package/vendor/@akanjs/native/native/desktop/src/external.rs +651 -0
- package/vendor/@akanjs/native/native/desktop/src/json.rs +23 -0
- package/vendor/@akanjs/native/native/desktop/src/lib.rs +228 -5
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeApp.swift +2 -1
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeKernel.swift +47 -1
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeUpdateReports.swift +145 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeUpdates.swift +112 -43
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeVectors.swift +18 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeViewController.swift +24 -2
- package/vendor/@akanjs/native/packages/cli/src/api.ts +22 -6
- package/vendor/@akanjs/native/packages/cli/src/commands/build.ts +24 -8
- package/vendor/@akanjs/native/packages/cli/src/commands/update.ts +11 -9
- package/vendor/@akanjs/native/packages/cli/src/config.ts +35 -7
- package/vendor/@akanjs/native/packages/cli/src/lib/compat.ts +2 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/configkeys.ts +6 -4
- package/vendor/@akanjs/native/packages/cli/src/lib/desktop-server.ts +11 -1
- package/vendor/@akanjs/native/packages/cli/src/lib/distribution.ts +73 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/project.ts +15 -3
- package/vendor/@akanjs/native/packages/cli/src/lib/publish.ts +70 -23
- package/vendor/@akanjs/native/packages/cli/src/lib/updates.ts +159 -23
- package/vendor/@akanjs/native/packages/cli/src/lib/vectors.ts +2 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/android.ts +9 -4
- package/vendor/@akanjs/native/packages/cli/src/platforms/desktop-update.ts +1 -1
- package/vendor/@akanjs/native/packages/cli/src/platforms/desktop.ts +4 -2
- package/vendor/@akanjs/native/packages/cli/src/platforms/ios.ts +9 -4
- package/vendor/@akanjs/native/packages/cli/src/platforms/windows-installer.ts +25 -11
- package/vendor/@akanjs/native/packages/cli/src/platforms/windows.ts +14 -3
- package/vendor/@akanjs/native/packages/core/src/kernel.ts +49 -0
- package/vendor/@akanjs/native/packages/core/vectors/updates.json +31 -0
- package/vendor/@akanjs/native/packages/desktop/src/main.ts +3 -0
- package/vendor/@akanjs/native/packages/desktop/src/plugin.ts +2 -0
- package/vendor/@akanjs/native/packages/desktop/src/server.ts +70 -6
- package/vendor/@akanjs/native/plugins/external-view/native-plugin.json +23 -0
- package/vendor/@akanjs/native/plugins/external-view/src/desktop.ts +321 -0
- package/vendor/@akanjs/native/plugins/external-view/src/index.ts +106 -0
- package/vendor/@akanjs/native/plugins/updates/android/UpdatesPlugin.kt +133 -41
- package/vendor/@akanjs/native/plugins/updates/ios/UpdatesPlugin.swift +101 -36
- package/vendor/@akanjs/native/plugins/updates/native-plugin.json +4 -2
- package/vendor/@akanjs/native/plugins/updates/src/desktop.ts +15 -1
- package/vendor/@akanjs/native/plugins/updates/src/index.ts +7 -1
- package/vendor/@akanjs/native/plugins/window/native-plugin.json +4 -0
- package/vendor/@akanjs/native/plugins/window/src/desktop.ts +68 -1
- package/vendor/@akanjs/native/plugins/window/src/index.ts +47 -0
- package/vendor/use-agentic/ToolRunner.ts +8 -1
- package/vendor/use-agentic/types.ts +2 -0
- package/webkit/CsrRouteTable.ts +1 -0
- package/webkit/CsrStack.ts +9 -2
- package/webkit/McpAppAgent.ts +138 -0
- package/webkit/McpAppApprovals.ts +56 -0
- package/webkit/McpAppBridge.ts +291 -0
- package/webkit/McpAppView.ts +258 -0
- package/webkit/bootCsr.tsx +54 -5
- package/webkit/index.ts +1 -0
- package/webkit/useCsrValues.ts +16 -10
- package/webkit/useFrameRuntime.ts +10 -1
- package/webkit/useLocation.ts +4 -3
- package/webkit/useVisualViewportFrame.tsx +52 -0
- package/service/predefinedAdaptor/sql/driver/libsql.ts +0 -45
- package/types/service/predefinedAdaptor/sql/driver/libsql.d.ts +0 -20
- package/types/ui/Agent/useKeyboardInset.d.ts +0 -1
- package/types/ui/ServerPortal.d.ts +0 -15
- package/ui/Agent/useKeyboardInset.ts +0 -19
- package/ui/ServerPortal.tsx +0 -49
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useDrag } from "@use-gesture/react";
|
|
3
3
|
import { cn, usePage } from "akanjs/client";
|
|
4
|
-
import { animated } from "akanjs/ui";
|
|
5
4
|
import { useBodyScrollLock, useEscapeKey } from "akanjs/webkit";
|
|
6
5
|
import { type ReactNode, useCallback, useContext, useEffect, useId, useRef, useState } from "react";
|
|
7
6
|
import { createPortal } from "react-dom";
|
|
8
7
|
import { BiX } from "react-icons/bi";
|
|
9
8
|
import { config, useSpring } from "react-spring";
|
|
9
|
+
import { animated } from "../animated";
|
|
10
10
|
import { buttonRecipe } from "../Button";
|
|
11
|
-
import { useOverlayLayerProps } from "../overlayLayer";
|
|
11
|
+
import { OverlayPortalProvider, overlayZ, useOverlayLayerProps, useOverlayPortal } from "../overlayLayer";
|
|
12
12
|
|
|
13
13
|
import { DialogContext } from "./Provider";
|
|
14
14
|
|
|
@@ -38,7 +38,8 @@ export const LegacyModal = ({ className, bodyClassName, confirmClose, children,
|
|
|
38
38
|
const contentId = useId();
|
|
39
39
|
const overlayLayerProps = useOverlayLayerProps();
|
|
40
40
|
const [{ translate }, api] = useSpring(() => ({ translate: 1 }));
|
|
41
|
-
const
|
|
41
|
+
const portalElement = useOverlayPortal();
|
|
42
|
+
const [root, setRoot] = useState<HTMLDivElement | null>(null);
|
|
42
43
|
const [isMounted, setIsMounted] = useState(open);
|
|
43
44
|
const [showBackground, setShowBackground] = useState(false);
|
|
44
45
|
|
|
@@ -111,11 +112,6 @@ export const LegacyModal = ({ className, bodyClassName, confirmClose, children,
|
|
|
111
112
|
return `${t * 100}%`;
|
|
112
113
|
});
|
|
113
114
|
|
|
114
|
-
useEffect(() => {
|
|
115
|
-
if (typeof document === "undefined") return;
|
|
116
|
-
setPortalElement(document.body);
|
|
117
|
-
}, []);
|
|
118
|
-
|
|
119
115
|
useEffect(() => {
|
|
120
116
|
if (open) {
|
|
121
117
|
void openModal();
|
|
@@ -171,65 +167,70 @@ export const LegacyModal = ({ className, bodyClassName, confirmClose, children,
|
|
|
171
167
|
<>
|
|
172
168
|
<div
|
|
173
169
|
{...overlayLayerProps}
|
|
174
|
-
className={cn("fixed inset-0
|
|
170
|
+
className={cn("fixed inset-0", showBackground && "animate-fadeIn bg-black/50 backdrop-blur-sm")}
|
|
171
|
+
style={{ zIndex: overlayZ.modal }}
|
|
175
172
|
/>
|
|
176
173
|
<div
|
|
177
174
|
{...overlayLayerProps}
|
|
178
|
-
|
|
175
|
+
ref={setRoot}
|
|
176
|
+
className="fixed inset-0 flex items-center justify-center p-4"
|
|
177
|
+
style={{ zIndex: overlayZ.modal }}
|
|
179
178
|
onClick={(event) => {
|
|
180
179
|
if (event.target !== event.currentTarget) return;
|
|
181
180
|
requestClose();
|
|
182
181
|
}}
|
|
183
182
|
>
|
|
184
|
-
<
|
|
185
|
-
ref={ref}
|
|
186
|
-
style={{ translateY, opacity }}
|
|
187
|
-
|
|
188
|
-
className={cn(
|
|
189
|
-
"relative flex max-h-full w-full max-w-2xl flex-col overflow-hidden rounded-box border border-border bg-card text-card-foreground shadow-2xl shadow-black/25 outline-none",
|
|
190
|
-
className,
|
|
191
|
-
)}
|
|
192
|
-
role="dialog"
|
|
193
|
-
aria-modal="true"
|
|
194
|
-
aria-labelledby={title ? titleId : undefined}
|
|
195
|
-
aria-describedby={contentId}
|
|
196
|
-
tabIndex={-1}
|
|
197
|
-
>
|
|
183
|
+
<OverlayPortalProvider value={root}>
|
|
198
184
|
<animated.div
|
|
199
|
-
{
|
|
185
|
+
ref={ref}
|
|
186
|
+
style={{ translateY, opacity }}
|
|
187
|
+
|
|
200
188
|
className={cn(
|
|
201
|
-
"flex
|
|
202
|
-
|
|
189
|
+
"relative flex max-h-full w-full max-w-2xl flex-col overflow-hidden rounded-box border border-border bg-card text-card-foreground shadow-2xl shadow-black/25 outline-none",
|
|
190
|
+
className,
|
|
203
191
|
)}
|
|
192
|
+
role="dialog"
|
|
193
|
+
aria-modal="true"
|
|
194
|
+
aria-labelledby={title ? titleId : undefined}
|
|
195
|
+
aria-describedby={contentId}
|
|
196
|
+
tabIndex={-1}
|
|
204
197
|
>
|
|
205
|
-
<div
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
198
|
+
<animated.div
|
|
199
|
+
{...bind()}
|
|
200
|
+
className={cn(
|
|
201
|
+
"flex shrink-0 touch-pan-y flex-col",
|
|
202
|
+
title && "border-border/70 border-b bg-card/80 backdrop-blur-sm",
|
|
203
|
+
)}
|
|
204
|
+
>
|
|
205
|
+
<div className="flex justify-center pt-2 md:hidden">
|
|
206
|
+
<div className="h-1 w-10 rounded-full bg-foreground/15" />
|
|
207
|
+
</div>
|
|
208
|
+
<div className="flex items-start gap-3 px-5 pt-4 pb-3">
|
|
209
|
+
<div className="min-w-0 flex-1 font-semibold text-lg leading-snug" id={titleId}>
|
|
210
|
+
{title}
|
|
211
|
+
</div>
|
|
212
|
+
<button
|
|
213
|
+
aria-label="Close"
|
|
214
|
+
className={buttonRecipe(
|
|
215
|
+
{ variant: "ghost", size: "icon" },
|
|
216
|
+
"-mt-1 -mr-2 size-8 shrink-0 rounded-full text-foreground/45 hover:text-foreground",
|
|
217
|
+
)}
|
|
218
|
+
onClick={() => requestClose()}
|
|
219
|
+
type="button"
|
|
220
|
+
>
|
|
221
|
+
<BiX className="text-2xl" />
|
|
222
|
+
</button>
|
|
211
223
|
</div>
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
onClick={() => requestClose()}
|
|
219
|
-
type="button"
|
|
220
|
-
>
|
|
221
|
-
<BiX className="text-2xl" />
|
|
222
|
-
</button>
|
|
224
|
+
</animated.div>
|
|
225
|
+
<div
|
|
226
|
+
className={cn("min-h-0 flex-1 overflow-y-auto overflow-x-hidden px-5 pt-4 pb-5", bodyClassName)}
|
|
227
|
+
id={contentId}
|
|
228
|
+
>
|
|
229
|
+
{children}
|
|
223
230
|
</div>
|
|
231
|
+
{action ? <div className="shrink-0 border-border/70 border-t bg-muted/30 px-5 py-4">{action}</div> : null}
|
|
224
232
|
</animated.div>
|
|
225
|
-
|
|
226
|
-
className={cn("min-h-0 flex-1 overflow-y-auto overflow-x-hidden px-5 pt-4 pb-5", bodyClassName)}
|
|
227
|
-
id={contentId}
|
|
228
|
-
>
|
|
229
|
-
{children}
|
|
230
|
-
</div>
|
|
231
|
-
{action ? <div className="shrink-0 border-border/70 border-t bg-muted/30 px-5 py-4">{action}</div> : null}
|
|
232
|
-
</animated.div>
|
|
233
|
+
</OverlayPortalProvider>
|
|
233
234
|
</div>
|
|
234
235
|
</>,
|
|
235
236
|
portalElement,
|
package/ui/Dialog/Modal.tsx
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { useDrag } from "@use-gesture/react";
|
|
2
3
|
import { cn, usePage } from "akanjs/client";
|
|
3
4
|
import { useBodyScrollLock, useEscapeKey } from "akanjs/webkit";
|
|
4
5
|
import { type ReactNode, useCallback, useContext, useEffect, useId, useRef, useState } from "react";
|
|
5
6
|
import { createPortal } from "react-dom";
|
|
6
7
|
import { BiX } from "react-icons/bi";
|
|
7
8
|
import { buttonRecipe } from "../Button";
|
|
8
|
-
import { useOverlayLayerProps } from "../overlayLayer";
|
|
9
|
+
import { OverlayPortalProvider, overlayZ, useOverlayLayerProps, useOverlayPortal } from "../overlayLayer";
|
|
9
10
|
|
|
11
|
+
import { isSheetNow, type ModalPlacement, type ModalPresentation, modalSurfaceOf } from "./modalSurface";
|
|
10
12
|
import { DialogContext } from "./Provider";
|
|
11
13
|
|
|
14
|
+
const DISMISS_DRAG_PX = 120;
|
|
15
|
+
|
|
12
16
|
export interface ModalProps {
|
|
13
17
|
className?: string;
|
|
14
18
|
bodyClassName?: string;
|
|
@@ -17,8 +21,21 @@ export interface ModalProps {
|
|
|
17
21
|
closeButton?: ReactNode | false;
|
|
18
22
|
children?: ReactNode;
|
|
19
23
|
onCancel?: () => void;
|
|
24
|
+
/** `auto` is a full-screen sheet below `md`, which a drag down on its handle or title dismisses. */
|
|
25
|
+
presentation?: ModalPresentation;
|
|
26
|
+
/** `right` is a full-height side sheet from `md` up. */
|
|
27
|
+
placement?: ModalPlacement;
|
|
20
28
|
}
|
|
21
|
-
export const Modal = ({
|
|
29
|
+
export const Modal = ({
|
|
30
|
+
className,
|
|
31
|
+
bodyClassName,
|
|
32
|
+
confirmClose,
|
|
33
|
+
closeButton,
|
|
34
|
+
children,
|
|
35
|
+
onCancel,
|
|
36
|
+
presentation = "dialog",
|
|
37
|
+
placement = "center",
|
|
38
|
+
}: ModalProps) => {
|
|
22
39
|
const { open, setOpen, registerDismiss, title, action } = useContext(DialogContext);
|
|
23
40
|
const { l } = usePage();
|
|
24
41
|
const ref = useRef<HTMLDivElement>(null);
|
|
@@ -26,8 +43,10 @@ export const Modal = ({ className, bodyClassName, confirmClose, closeButton, chi
|
|
|
26
43
|
const titleId = useId();
|
|
27
44
|
const contentId = useId();
|
|
28
45
|
const overlayLayerProps = useOverlayLayerProps();
|
|
29
|
-
|
|
30
|
-
const [
|
|
46
|
+
const portalElement = useOverlayPortal();
|
|
47
|
+
const [root, setRoot] = useState<HTMLDivElement | null>(null);
|
|
48
|
+
const [dragY, setDragY] = useState(0);
|
|
49
|
+
const surface = modalSurfaceOf(presentation, placement);
|
|
31
50
|
|
|
32
51
|
const requestClose = useCallback(() => {
|
|
33
52
|
if (confirmClose && !window.confirm(l("base.confirmClose"))) return;
|
|
@@ -35,10 +54,19 @@ export const Modal = ({ className, bodyClassName, confirmClose, closeButton, chi
|
|
|
35
54
|
onCancel?.();
|
|
36
55
|
}, [confirmClose, l, onCancel, setOpen]);
|
|
37
56
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
57
|
+
const bindDismissDrag = useDrag(
|
|
58
|
+
({ down, movement: [, my], velocity: [, vy], direction: [, dy] }) => {
|
|
59
|
+
if (!isSheetNow(presentation, placement)) return;
|
|
60
|
+
if (down) {
|
|
61
|
+
setDragY(Math.max(0, my));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
setDragY(0);
|
|
65
|
+
if (my > DISMISS_DRAG_PX || (vy > 0.5 && dy > 0)) requestClose();
|
|
66
|
+
},
|
|
67
|
+
{ axis: "y", filterTaps: true },
|
|
68
|
+
);
|
|
69
|
+
const dragProps = presentation === "dialog" ? {} : bindDismissDrag();
|
|
42
70
|
|
|
43
71
|
useBodyScrollLock(open);
|
|
44
72
|
useEscapeKey(open, requestClose);
|
|
@@ -69,55 +97,71 @@ export const Modal = ({ className, bodyClassName, confirmClose, closeButton, chi
|
|
|
69
97
|
return createPortal(
|
|
70
98
|
<div
|
|
71
99
|
{...overlayLayerProps}
|
|
72
|
-
|
|
100
|
+
ref={setRoot}
|
|
101
|
+
className={cn("fixed inset-0 flex bg-black/40", surface.root)}
|
|
102
|
+
style={{ zIndex: overlayZ.modal }}
|
|
73
103
|
onClick={(event) => {
|
|
74
104
|
if (event.target !== event.currentTarget) return;
|
|
75
105
|
requestClose();
|
|
76
106
|
}}
|
|
77
107
|
>
|
|
78
|
-
<
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
108
|
+
<OverlayPortalProvider value={root}>
|
|
109
|
+
<div
|
|
110
|
+
ref={ref}
|
|
111
|
+
|
|
112
|
+
className={cn(
|
|
113
|
+
"relative flex w-full flex-col overflow-hidden bg-card text-card-foreground shadow-lg outline-none",
|
|
114
|
+
surface.panel,
|
|
115
|
+
dragY === 0 && "transition-transform",
|
|
116
|
+
className,
|
|
117
|
+
)}
|
|
118
|
+
style={dragY ? { transform: `translateY(${dragY}px)` } : undefined}
|
|
119
|
+
role="dialog"
|
|
120
|
+
aria-modal="true"
|
|
121
|
+
aria-labelledby={title ? titleId : undefined}
|
|
122
|
+
aria-describedby={contentId}
|
|
123
|
+
tabIndex={-1}
|
|
124
|
+
>
|
|
125
|
+
{/* The dismissal is on the slot, not on the button inside it, so a replacement needs no wiring — a
|
|
92
126
|
click on whatever the caller put here bubbles to exactly one handler. */}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
127
|
+
{closeButton === false ? null : (
|
|
128
|
+
<div className={cn("absolute right-3 z-10", surface.close)} onClick={() => requestClose()}>
|
|
129
|
+
{closeButton ?? (
|
|
130
|
+
<button
|
|
131
|
+
aria-label="Close"
|
|
132
|
+
className={buttonRecipe({ variant: "ghost", size: "icon" }, "size-8")}
|
|
133
|
+
type="button"
|
|
134
|
+
>
|
|
135
|
+
<BiX className="text-xl" />
|
|
136
|
+
</button>
|
|
137
|
+
)}
|
|
138
|
+
</div>
|
|
139
|
+
)}
|
|
140
|
+
{presentation === "dialog" ? null : (
|
|
141
|
+
<div {...dragProps} className={cn("shrink-0 touch-none justify-center pt-2", surface.handle)}>
|
|
142
|
+
<div className="h-1 w-10 rounded-full bg-foreground/15" />
|
|
143
|
+
</div>
|
|
144
|
+
)}
|
|
145
|
+
{title ? (
|
|
146
|
+
<div
|
|
147
|
+
{...dragProps}
|
|
148
|
+
className={cn(
|
|
149
|
+
"shrink-0 border-border border-b py-3.5 pr-14 pl-5 font-semibold text-base leading-snug",
|
|
150
|
+
presentation !== "dialog" && "touch-none",
|
|
151
|
+
)}
|
|
152
|
+
id={titleId}
|
|
153
|
+
>
|
|
154
|
+
{title}
|
|
155
|
+
</div>
|
|
156
|
+
) : null}
|
|
157
|
+
<div className={cn("min-h-0 flex-1 overflow-y-auto px-5 py-4", bodyClassName)} id={contentId}>
|
|
158
|
+
{children}
|
|
112
159
|
</div>
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
160
|
+
{action ? (
|
|
161
|
+
<div className="flex shrink-0 justify-end gap-2 border-border border-t px-5 py-3">{action}</div>
|
|
162
|
+
) : null}
|
|
116
163
|
</div>
|
|
117
|
-
|
|
118
|
-
<div className="flex shrink-0 justify-end gap-2 border-border border-t px-5 py-3">{action}</div>
|
|
119
|
-
) : null}
|
|
120
|
-
</div>
|
|
164
|
+
</OverlayPortalProvider>
|
|
121
165
|
</div>,
|
|
122
166
|
portalElement,
|
|
123
167
|
);
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/** How the modal shows on a phone: a centred dialog, a full-screen sheet, or a sheet below `md` and a dialog above. */
|
|
2
|
+
export type ModalPresentation = "dialog" | "sheet" | "auto";
|
|
3
|
+
/** Where the modal sits from `md` up: centred, or a full-height sheet on the right edge. */
|
|
4
|
+
export type ModalPlacement = "center" | "right";
|
|
5
|
+
|
|
6
|
+
interface SurfaceClassNames {
|
|
7
|
+
root: string;
|
|
8
|
+
panel: string;
|
|
9
|
+
close: string;
|
|
10
|
+
handle: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const presentationClassNames: { [presentation in ModalPresentation]: SurfaceClassNames } = {
|
|
14
|
+
dialog: {
|
|
15
|
+
root: "items-center justify-center p-4",
|
|
16
|
+
panel: "max-h-full max-w-2xl rounded-box border border-border",
|
|
17
|
+
close: "top-3",
|
|
18
|
+
handle: "hidden",
|
|
19
|
+
},
|
|
20
|
+
sheet: {
|
|
21
|
+
root: "items-stretch justify-stretch p-0",
|
|
22
|
+
panel:
|
|
23
|
+
"h-full max-h-full max-w-none rounded-none border-0 pt-[env(safe-area-inset-top)] pb-[env(safe-area-inset-bottom)]",
|
|
24
|
+
close: "top-[calc(env(safe-area-inset-top)+0.75rem)]",
|
|
25
|
+
handle: "flex",
|
|
26
|
+
},
|
|
27
|
+
auto: {
|
|
28
|
+
root: "items-stretch p-0 md:items-center md:justify-center md:p-4",
|
|
29
|
+
panel:
|
|
30
|
+
"h-full max-h-full rounded-none border-0 pt-[env(safe-area-inset-top)] pb-[env(safe-area-inset-bottom)] md:h-auto md:max-w-2xl md:rounded-box md:border md:border-border md:pt-0 md:pb-0",
|
|
31
|
+
close: "top-[calc(env(safe-area-inset-top)+0.75rem)] md:top-3",
|
|
32
|
+
handle: "flex md:hidden",
|
|
33
|
+
},
|
|
34
|
+
} as const;
|
|
35
|
+
|
|
36
|
+
const placementClassNames: { [placement in ModalPlacement]: Pick<SurfaceClassNames, "root" | "panel"> } = {
|
|
37
|
+
center: { root: "", panel: "" },
|
|
38
|
+
right: {
|
|
39
|
+
root: "md:items-stretch md:justify-end md:p-0",
|
|
40
|
+
panel: "md:h-full md:max-h-full md:max-w-md md:rounded-none md:border-0 md:border-border md:border-l",
|
|
41
|
+
},
|
|
42
|
+
} as const;
|
|
43
|
+
|
|
44
|
+
export const modalSurfaceOf = (presentation: ModalPresentation, placement: ModalPlacement) => {
|
|
45
|
+
const shape = presentationClassNames[presentation];
|
|
46
|
+
const side = placementClassNames[placement];
|
|
47
|
+
return {
|
|
48
|
+
root: [shape.root, side.root],
|
|
49
|
+
panel: [shape.panel, side.panel],
|
|
50
|
+
close: shape.close,
|
|
51
|
+
handle: shape.handle,
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/** Whether a drag down dismisses: only while the modal is drawn as a sheet at the current width. */
|
|
56
|
+
export const isSheetNow = (presentation: ModalPresentation, placement: ModalPlacement) => {
|
|
57
|
+
if (presentation === "dialog") return false;
|
|
58
|
+
const wide = typeof window !== "undefined" && window.matchMedia("(min-width: 48rem)").matches;
|
|
59
|
+
if (!wide) return true;
|
|
60
|
+
return presentation === "sheet" && placement === "center";
|
|
61
|
+
};
|
package/ui/DragAction.tsx
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import { useGesture } from "@use-gesture/react";
|
|
3
3
|
import type { ReactDOMAttributes } from "@use-gesture/react/dist/declarations/src/types";
|
|
4
4
|
import { cn } from "akanjs/client";
|
|
5
|
-
import { animated } from "akanjs/ui";
|
|
6
5
|
import { type ReactNode, useContext, useRef } from "react";
|
|
7
6
|
import { SpringValue, useSpring } from "react-spring";
|
|
8
7
|
import { sharedContext } from "../client/sharedContext";
|
|
8
|
+
import { animated } from "./animated";
|
|
9
9
|
|
|
10
10
|
interface DragActionContextType {
|
|
11
11
|
bind: () => ReactDOMAttributes;
|
package/ui/DraggableList.tsx
CHANGED
|
@@ -4,12 +4,12 @@ import { useGesture } from "@use-gesture/react";
|
|
|
4
4
|
import { cn } from "akanjs/client";
|
|
5
5
|
import { clamp } from "akanjs/common";
|
|
6
6
|
import { useFieldTool } from "akanjs/store";
|
|
7
|
-
import { animated } from "akanjs/ui";
|
|
8
7
|
import { type ReactElement, type ReactNode, useContext, useRef } from "react";
|
|
9
8
|
import { BiTrash } from "react-icons/bi";
|
|
10
9
|
import { MdDragIndicator } from "react-icons/md";
|
|
11
10
|
import { sharedContext } from "../client/sharedContext";
|
|
12
11
|
import { agentAttrs } from "./agentAttrs";
|
|
12
|
+
import { animated } from "./animated";
|
|
13
13
|
import { buttonRecipe } from "./Button";
|
|
14
14
|
import { useUiRecipe } from "./UiOverride";
|
|
15
15
|
|
package/ui/Dropdown.tsx
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
OverlayOwnerProvider,
|
|
13
13
|
overlayZ,
|
|
14
14
|
useOverlayLayerProps,
|
|
15
|
+
useOverlayPortal,
|
|
15
16
|
useOverlayScope,
|
|
16
17
|
} from "./overlayLayer";
|
|
17
18
|
import { useOverlayPosition } from "./overlayPosition";
|
|
@@ -49,8 +50,7 @@ export const DefaultDropdown = ({
|
|
|
49
50
|
namespace,
|
|
50
51
|
}: DropdownProps) => {
|
|
51
52
|
const [opened, setOpened] = useState(false);
|
|
52
|
-
|
|
53
|
-
const [portal, setPortal] = useState<HTMLElement | null>(null);
|
|
53
|
+
const portal = useOverlayPortal();
|
|
54
54
|
const ref = useRef<HTMLDivElement>(null);
|
|
55
55
|
const menuRef = useRef<HTMLUListElement>(null);
|
|
56
56
|
const scope = useOverlayScope(useId());
|
|
@@ -75,9 +75,6 @@ export const DefaultDropdown = ({
|
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
const toggle = opened ? closeDropdown : openDropdown;
|
|
78
|
-
useEffect(() => {
|
|
79
|
-
setPortal(document.body);
|
|
80
|
-
}, []);
|
|
81
78
|
useEffect(() => {
|
|
82
79
|
if (!opened) return;
|
|
83
80
|
const onMouseDown = (e: MouseEvent) => {
|
|
@@ -104,7 +101,8 @@ export const DefaultDropdown = ({
|
|
|
104
101
|
left: position?.left ?? 0,
|
|
105
102
|
visibility: position ? undefined : "hidden",
|
|
106
103
|
}}
|
|
107
|
-
|
|
104
|
+
|
|
105
|
+
onClickCapture={(e) => {
|
|
108
106
|
|
|
109
107
|
if (isOwnOverlayClick(e.target, scope)) return;
|
|
110
108
|
if (e.target instanceof Element && e.target.closest(keepOpenSelector)) return;
|
package/ui/KeyboardAvoiding.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useCsr } from "akanjs/client";
|
|
3
3
|
import { st } from "akanjs/store";
|
|
4
|
-
import { animated } from "akanjs/ui";
|
|
5
4
|
import { type ReactNode, useEffect, useRef } from "react";
|
|
6
5
|
import { useSpring } from "react-spring";
|
|
6
|
+
import { animated } from "./animated";
|
|
7
7
|
|
|
8
8
|
interface KeyboardAvoidingProps {
|
|
9
9
|
children: ReactNode;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { getEnv } from "akanjs/base";
|
|
3
3
|
import { cn, DEFAULT_BOTTOM_INSET, debugFrame, type FrameSlotRegistration, usePathCtx } from "akanjs/client";
|
|
4
|
-
import { type ReactNode, useLayoutEffect,
|
|
4
|
+
import { type ReactNode, useLayoutEffect, useState } from "react";
|
|
5
5
|
|
|
6
6
|
import { Portal } from "../Portal";
|
|
7
|
+
import { FrameSlotFallback } from "./FrameSlotFallback";
|
|
7
8
|
|
|
8
9
|
export interface BottomInsetProps {
|
|
9
10
|
className?: string;
|
|
@@ -29,7 +30,8 @@ export const BottomInset = ({
|
|
|
29
30
|
frameCache,
|
|
30
31
|
}: BottomInsetProps) => {
|
|
31
32
|
const [measuredHeight, setMeasuredHeight] = useState<number>();
|
|
32
|
-
|
|
33
|
+
|
|
34
|
+
const [contentElement, setContentElement] = useState<HTMLDivElement | null>(null);
|
|
33
35
|
const pathCtx = usePathCtx();
|
|
34
36
|
const pathRoute = pathCtx.location?.pathRoute;
|
|
35
37
|
const path = pathCtx.location?.pathRoute?.path;
|
|
@@ -40,7 +42,7 @@ export const BottomInset = ({
|
|
|
40
42
|
const resolvedEstimatedHeight = estimatedHeight ?? pathRoute?.pageState.bottomInset ?? DEFAULT_BOTTOM_INSET;
|
|
41
43
|
const useDeclaredHeight = pathRoute?.explicitPageConfigKeys?.bottomInset === true;
|
|
42
44
|
const readContentHeight = () => {
|
|
43
|
-
const element =
|
|
45
|
+
const element = contentElement;
|
|
44
46
|
if (!element) return undefined;
|
|
45
47
|
const height = Math.ceil(element.getBoundingClientRect().height);
|
|
46
48
|
return height > 0 ? height : undefined;
|
|
@@ -84,7 +86,7 @@ export const BottomInset = ({
|
|
|
84
86
|
useDeclaredHeight,
|
|
85
87
|
]);
|
|
86
88
|
useLayoutEffect(() => {
|
|
87
|
-
const element =
|
|
89
|
+
const element = contentElement;
|
|
88
90
|
if (!element || typeof ResizeObserver === "undefined") return;
|
|
89
91
|
const update = () => {
|
|
90
92
|
const height = readContentHeight();
|
|
@@ -99,18 +101,22 @@ export const BottomInset = ({
|
|
|
99
101
|
const observer = new ResizeObserver(update);
|
|
100
102
|
observer.observe(element);
|
|
101
103
|
return () => observer.disconnect();
|
|
102
|
-
}, []);
|
|
104
|
+
}, [contentElement]);
|
|
103
105
|
|
|
106
|
+
const content = (
|
|
107
|
+
<div
|
|
108
|
+
ref={setContentElement}
|
|
109
|
+
data-akan-frame-slot="bottomInset"
|
|
110
|
+
data-akan-frame-role={frameRole}
|
|
111
|
+
className={cn("pointer-events-auto w-full", className)}
|
|
112
|
+
>
|
|
113
|
+
{children}
|
|
114
|
+
</div>
|
|
115
|
+
);
|
|
116
|
+
const fallbackSlot = frameRole === "keyboardAccessory" ? "keyboardInset" : "bottomInset";
|
|
104
117
|
return (
|
|
105
|
-
<Portal id={portalId}>
|
|
106
|
-
|
|
107
|
-
ref={contentRef}
|
|
108
|
-
data-akan-frame-slot="bottomInset"
|
|
109
|
-
data-akan-frame-role={frameRole}
|
|
110
|
-
className={cn("pointer-events-auto w-full", className)}
|
|
111
|
-
>
|
|
112
|
-
{children}
|
|
113
|
-
</div>
|
|
118
|
+
<Portal id={portalId} fallback={<FrameSlotFallback slot={fallbackSlot}>{content}</FrameSlotFallback>}>
|
|
119
|
+
{content}
|
|
114
120
|
</Portal>
|
|
115
121
|
);
|
|
116
122
|
};
|