akanjs 3.0.0-alpha.2 → 3.0.0-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/base/symbols.ts +4 -0
- package/client/clientRuntime.ts +8 -0
- package/client/cn.ts +7 -0
- package/client/csrTypes.ts +2 -0
- package/client/frameDebug.ts +3 -2
- package/common/Logger.ts +4 -0
- package/common/deepObjectify.ts +21 -7
- package/common/index.ts +14 -0
- package/common/mcpExposure.ts +99 -0
- package/common/pathSet.ts +17 -5
- package/common/routeConvention.ts +30 -0
- package/constant/crystalize.ts +3 -1
- package/constant/fieldInfo.ts +6 -0
- package/constant/getDefault.ts +37 -9
- package/constant/immerify.ts +1 -1
- package/constant/index.ts +2 -0
- package/constant/labelOf.ts +17 -0
- package/constant/mask.ts +60 -0
- package/constant/purify.ts +17 -11
- package/constant/types.ts +14 -12
- package/dictionary/DictionaryLookup.ts +30 -0
- package/dictionary/agent.dictionary.ts +31 -0
- package/dictionary/agentTurn.dictionary.ts +29 -0
- package/dictionary/base.dictionary.ts +8 -0
- package/dictionary/dictInfo.ts +8 -0
- package/dictionary/dictionary.ts +9 -3
- package/dictionary/index.ts +1 -0
- package/document/database.ts +21 -0
- package/document/filterMeta.ts +7 -0
- package/document/index.ts +1 -0
- package/document/into.ts +7 -1
- package/document/noDocumentError.ts +12 -0
- package/fetch/agentTurn.ts +19 -0
- package/fetch/client/fetchClient.ts +71 -13
- package/fetch/client/wsClient.ts +17 -2
- package/fetch/fetchType/endpointFetch.type.ts +10 -4
- package/fetch/index.ts +1 -0
- package/local/apps/serverLifecycle/serverLifecycle-local.db +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local.db-shm +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local.db-wal +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local_solid.db +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-shm +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-wal +0 -0
- package/package.json +11 -9
- package/server/akanApp.ts +30 -34
- package/server/akanOption.ts +65 -7
- package/server/akanServer.ts +172 -7
- package/server/animatedImage.ts +83 -0
- package/server/artifact/routeClientCache.ts +14 -0
- package/server/assetEncoding.ts +47 -0
- package/server/devtools/signalSerializer.ts +2 -2
- package/server/devtools/types.ts +2 -2
- package/server/di/diLifecycle.ts +31 -3
- package/server/di/predefinedAdaptor.ts +6 -0
- package/server/imageOptimizer.ts +33 -46
- package/server/index.ts +1 -2
- package/server/mcp/McpAuth.ts +177 -0
- package/server/mcp/McpDispatcher.ts +245 -0
- package/server/mcp/McpEventStream.ts +76 -0
- package/server/mcp/McpExecutionContext.ts +105 -0
- package/server/mcp/McpRouter.ts +591 -0
- package/server/mcp/index.ts +5 -0
- package/server/resolver/CascadeRunner.ts +1 -1
- package/server/resolver/database.resolver.ts +42 -5
- package/server/resolver/service.resolver.ts +29 -0
- package/server/resolver/signal.resolver.ts +16 -1
- package/server/routeTreeBuilder.ts +2 -44
- package/server/rscWorker.tsx +6 -2
- package/server/subRouteIndexDocument.tsx +61 -0
- package/server/systemPageDocument.tsx +2 -2
- package/server/systemPages.tsx +49 -16
- package/server/vendor/akanjs-fetch.ts +1 -0
- package/server/webRouter.ts +159 -35
- package/service/agent.service.ts +14 -0
- package/service/base.service.ts +2 -1
- package/service/index.ts +1 -0
- package/service/predefinedAdaptor/database.adaptor.ts +78 -24
- package/service/predefinedAdaptor/deepseekLlm.ts +230 -0
- package/service/predefinedAdaptor/index.ts +3 -0
- package/service/predefinedAdaptor/insightQuery.ts +183 -0
- package/service/predefinedAdaptor/llm.adaptor.ts +76 -0
- package/service/predefinedAdaptor/role.adaptor.ts +2 -0
- package/service/predefinedAdaptor/schedule.adaptor.ts +12 -5
- package/service/serviceModule.ts +17 -0
- package/service/types.ts +4 -0
- package/signal/agent/AgentCatalogue.ts +165 -0
- package/signal/agent/index.ts +1 -0
- package/signal/agent.signal.ts +42 -0
- package/signal/agentTurn.ts +8 -0
- package/signal/agentTurnStream.ts +48 -0
- package/signal/base.signal.ts +2 -1
- package/signal/endpointInfo.ts +38 -2
- package/signal/guard.ts +13 -1
- package/signal/guards.ts +52 -1
- package/signal/index.ts +6 -0
- package/signal/mcp/McpDocument.ts +286 -0
- package/signal/mcp/McpProgress.ts +106 -0
- package/signal/mcp/McpUriTemplate.ts +85 -0
- package/signal/mcp/Msg.ts +368 -0
- package/signal/mcp/index.ts +5 -0
- package/signal/mcp/mcpProtocol.ts +120 -0
- package/signal/middleware.ts +7 -3
- package/signal/openapi/openapi.ts +32 -171
- package/signal/schema/JsonSchemaBuilder.ts +211 -0
- package/signal/schema/index.ts +1 -0
- package/signal/signalContext.ts +85 -9
- package/signal/slice.ts +9 -9
- package/signal/types.ts +1 -1
- package/store/action.ts +11 -22
- package/store/actionTag.ts +33 -0
- package/store/agent/AgentBridge.ts +323 -0
- package/store/agent/AgentContext.ts +74 -0
- package/store/agent/AgentPrompts.ts +82 -0
- package/store/agent/AgentVisibility.ts +68 -0
- package/store/agent/ScreenReader.ts +208 -0
- package/store/agent/StoreCatalogue.ts +351 -0
- package/store/agent/StoreSurfaceSource.ts +122 -0
- package/store/agent/index.ts +9 -0
- package/store/agent/storeSurface.ts +28 -0
- package/store/agent/types.ts +50 -0
- package/store/agentic/StToolBuilder.ts +199 -0
- package/store/agentic/attachAgentic.ts +22 -0
- package/store/agentic/index.ts +5 -0
- package/store/agentic/readableValue.ts +17 -0
- package/store/agentic/useStExpose.ts +18 -0
- package/store/agentic/useStState.ts +35 -0
- package/store/baseSt.ts +7 -0
- package/store/databaseStateNames.ts +31 -0
- package/store/formSetterNames.ts +21 -0
- package/store/index.ts +8 -0
- package/store/rootStore.ts +3 -1
- package/store/sliceRole.ts +36 -0
- package/store/state.ts +2 -12
- package/store/store.ts +19 -1
- package/store/storeInstance.ts +165 -20
- package/store/storeRegistry.ts +16 -1
- package/store/types.ts +18 -0
- package/store/withSelector.ts +7 -8
- package/test/registerDom.ts +4 -0
- package/types/base/symbols.d.ts +4 -0
- package/types/client/cn.d.ts +5 -0
- package/types/client/csrTypes.d.ts +2 -0
- package/types/common/Logger.d.ts +2 -0
- package/types/common/deepObjectify.d.ts +4 -2
- package/types/common/index.d.ts +2 -1
- package/types/common/mcpExposure.d.ts +60 -0
- package/types/common/routeConvention.d.ts +8 -0
- package/types/constant/fieldInfo.d.ts +1 -0
- package/types/constant/getDefault.d.ts +5 -0
- package/types/constant/index.d.ts +2 -0
- package/types/constant/labelOf.d.ts +6 -0
- package/types/constant/mask.d.ts +34 -0
- package/types/constant/purify.d.ts +2 -2
- package/types/constant/types.d.ts +2 -2
- package/types/dictionary/DictionaryLookup.d.ts +14 -0
- package/types/dictionary/agent.dictionary.d.ts +1 -0
- package/types/dictionary/agentTurn.dictionary.d.ts +1 -0
- package/types/dictionary/base.dictionary.d.ts +1 -1
- package/types/dictionary/dictInfo.d.ts +6 -0
- package/types/dictionary/dictionary.d.ts +11 -9
- package/types/dictionary/index.d.ts +1 -0
- package/types/document/database.d.ts +20 -0
- package/types/document/filterMeta.d.ts +1 -0
- package/types/document/index.d.ts +1 -0
- package/types/document/into.d.ts +6 -1
- package/types/document/noDocumentError.d.ts +12 -0
- package/types/fetch/agentTurn.d.ts +593 -0
- package/types/fetch/client/fetchClient.d.ts +10 -0
- package/types/fetch/fetchType/endpointFetch.type.d.ts +5 -3
- package/types/fetch/index.d.ts +1 -0
- package/types/server/akanOption.d.ts +35 -7
- package/types/server/akanServer.d.ts +44 -1
- package/types/server/animatedImage.d.ts +7 -0
- package/types/server/artifact/routeClientCache.d.ts +6 -0
- package/types/server/assetEncoding.d.ts +7 -0
- package/types/server/devtools/types.d.ts +2 -2
- package/types/server/di/predefinedAdaptor.d.ts +4 -1
- package/types/server/index.d.ts +0 -2
- package/types/server/mcp/McpAuth.d.ts +62 -0
- package/types/server/mcp/McpDispatcher.d.ts +54 -0
- package/types/server/mcp/McpEventStream.d.ts +18 -0
- package/types/server/mcp/McpExecutionContext.d.ts +44 -0
- package/types/server/mcp/McpRouter.d.ts +60 -0
- package/types/server/mcp/index.d.ts +5 -0
- package/types/server/mcp.d.ts +1 -0
- package/types/server/subRouteIndexDocument.d.ts +8 -0
- package/types/server/systemPageDocument.d.ts +1 -0
- package/types/server/systemPages.d.ts +5 -0
- package/types/server/vendor/akanjs-fetch.d.ts +1 -0
- package/types/service/agent.service.d.ts +12 -0
- package/types/service/base.service.d.ts +4 -0
- package/types/service/index.d.ts +1 -0
- package/types/service/predefinedAdaptor/database.adaptor.d.ts +24 -2
- package/types/service/predefinedAdaptor/deepseekLlm.d.ts +64 -0
- package/types/service/predefinedAdaptor/index.d.ts +3 -0
- package/types/service/predefinedAdaptor/insightQuery.d.ts +50 -0
- package/types/service/predefinedAdaptor/llm.adaptor.d.ts +68 -0
- package/types/service/predefinedAdaptor/role.adaptor.d.ts +2 -0
- package/types/service/predefinedAdaptor/schedule.adaptor.d.ts +10 -6
- package/types/service/types.d.ts +4 -1
- package/types/signal/agent/AgentCatalogue.d.ts +100 -0
- package/types/signal/agent/index.d.ts +1 -0
- package/types/signal/agent.d.ts +1 -0
- package/types/signal/agent.signal.d.ts +29 -0
- package/types/signal/agentTurn.d.ts +9 -0
- package/types/signal/agentTurnStream.d.ts +16 -0
- package/types/signal/base.signal.d.ts +1 -1
- package/types/signal/endpointInfo.d.ts +21 -3
- package/types/signal/guard.d.ts +11 -0
- package/types/signal/guards.d.ts +22 -1
- package/types/signal/index.d.ts +6 -0
- package/types/signal/mcp/McpDocument.d.ts +65 -0
- package/types/signal/mcp/McpProgress.d.ts +40 -0
- package/types/signal/mcp/McpUriTemplate.d.ts +26 -0
- package/types/signal/mcp/Msg.d.ts +143 -0
- package/types/signal/mcp/index.d.ts +5 -0
- package/types/signal/mcp/mcpProtocol.d.ts +107 -0
- package/types/signal/mcp.d.ts +1 -0
- package/types/signal/openapi/openapi.d.ts +3 -3
- package/types/signal/schema/JsonSchemaBuilder.d.ts +47 -0
- package/types/signal/schema/index.d.ts +1 -0
- package/types/signal/schema.d.ts +1 -0
- package/types/signal/signalContext.d.ts +16 -1
- package/types/signal/slice.d.ts +8 -8
- package/types/signal/types.d.ts +1 -1
- package/types/store/actionTag.d.ts +21 -0
- package/types/store/agent/AgentBridge.d.ts +77 -0
- package/types/store/agent/AgentContext.d.ts +16 -0
- package/types/store/agent/AgentPrompts.d.ts +31 -0
- package/types/store/agent/AgentVisibility.d.ts +21 -0
- package/types/store/agent/ScreenReader.d.ts +11 -0
- package/types/store/agent/StoreCatalogue.d.ts +26 -0
- package/types/store/agent/StoreSurfaceSource.d.ts +18 -0
- package/types/store/agent/index.d.ts +9 -0
- package/types/store/agent/storeSurface.d.ts +14 -0
- package/types/store/agent/types.d.ts +49 -0
- package/types/store/agent.d.ts +1 -0
- package/types/store/agentic/StToolBuilder.d.ts +41 -0
- package/types/store/agentic/attachAgentic.d.ts +14 -0
- package/types/store/agentic/index.d.ts +5 -0
- package/types/store/agentic/readableValue.d.ts +3 -0
- package/types/store/agentic/useStExpose.d.ts +8 -0
- package/types/store/agentic/useStState.d.ts +12 -0
- package/types/store/agentic.d.ts +1 -0
- package/types/store/baseSt.d.ts +29 -22
- package/types/store/databaseStateNames.d.ts +25 -0
- package/types/store/formSetterNames.d.ts +16 -0
- package/types/store/index.d.ts +7 -0
- package/types/store/rootStore.d.ts +5 -1
- package/types/store/sliceRole.d.ts +25 -0
- package/types/store/store.d.ts +7 -2
- package/types/store/storeInstance.d.ts +33 -1
- package/types/store/storeRegistry.d.ts +5 -0
- package/types/store/types.d.ts +15 -0
- package/types/store/withSelector.d.ts +7 -8
- package/types/test/registerDom.d.ts +1 -0
- package/types/ui/Agent/Approval.d.ts +7 -0
- package/types/ui/Agent/Bubble.d.ts +13 -0
- package/types/ui/Agent/Chat.d.ts +24 -0
- package/types/ui/Agent/Context.d.ts +9 -0
- package/types/ui/Agent/Dock.d.ts +16 -0
- package/types/ui/Agent/Guide.d.ts +9 -0
- package/types/ui/Agent/Section.d.ts +10 -0
- package/types/ui/Agent/StateKey.d.ts +16 -0
- package/types/ui/Agent/Tool.d.ts +15 -0
- package/types/ui/Agent/Transcript.d.ts +13 -0
- package/types/ui/Agent/Zone.d.ts +23 -0
- package/types/ui/Agent/fetchRunner.d.ts +12 -0
- package/types/ui/Agent/index.d.ts +17 -0
- package/types/ui/Agent/index_.d.ts +1 -0
- package/types/ui/Agent/sessionHistory.d.ts +12 -0
- package/types/ui/Agent.d.ts +1 -0
- package/types/ui/Badge.d.ts +1 -1
- package/types/ui/Button.d.ts +1 -1
- package/types/ui/CsrImage.d.ts +1 -1
- package/types/ui/Dropdown.d.ts +2 -0
- package/types/ui/Image.d.ts +3 -3
- package/types/ui/Layout/BottomInset.d.ts +2 -1
- package/types/ui/Layout/index.d.ts +1 -1
- package/types/ui/Signal/style.d.ts +4 -1
- package/types/ui/UiOverride/context.d.ts +14 -2
- package/types/ui/agentAttrs.d.ts +14 -0
- package/types/ui/index.d.ts +4 -1
- package/types/ui/overlayLayer.d.ts +24 -0
- package/types/ui/recipe/badgeRecipe.d.ts +7 -3
- package/types/ui/recipe/buttonRecipe.d.ts +7 -3
- package/types/ui/recipe/inputRecipe.d.ts +5 -1
- package/types/vendor/use-agentic/AgentProvider.d.ts +18 -0
- package/types/vendor/use-agentic/AgentScope.d.ts +9 -0
- package/types/vendor/use-agentic/AgentSession.d.ts +50 -0
- package/types/vendor/use-agentic/Agentic.d.ts +21 -0
- package/types/vendor/use-agentic/AgenticSurface.d.ts +44 -0
- package/types/vendor/use-agentic/httpRunner.d.ts +15 -0
- package/types/vendor/use-agentic/index.d.ts +13 -0
- package/types/vendor/use-agentic/surfaceContext.d.ts +5 -0
- package/types/vendor/use-agentic/types.d.ts +133 -0
- package/types/vendor/use-agentic/useAgent.d.ts +4 -0
- package/types/vendor/use-agentic/useAgentGuide.d.ts +6 -0
- package/types/vendor/use-agentic/useAgentResource.d.ts +7 -0
- package/types/vendor/use-agentic/useAgentState.d.ts +13 -0
- package/types/vendor/use-agentic/useAgentTool.d.ts +16 -0
- package/types/vendor/use-agentic.d.ts +1 -0
- package/types/webkit/index.d.ts +3 -0
- package/types/webkit/lazy.d.ts +12 -0
- package/types/webkit/useCsrValues.d.ts +3 -3
- package/types/webkit/useEscapeKey.d.ts +5 -0
- package/types/webkit/useFrameRuntime.d.ts +6 -1
- package/types/webkit/useScreenScope.d.ts +18 -0
- package/ui/Agent/Approval.tsx +29 -0
- package/ui/Agent/Bubble.tsx +74 -0
- package/ui/Agent/Chat.tsx +225 -0
- package/ui/Agent/Context.tsx +38 -0
- package/ui/Agent/Dock.tsx +72 -0
- package/ui/Agent/Guide.tsx +16 -0
- package/ui/Agent/Section.tsx +24 -0
- package/ui/Agent/StateKey.tsx +44 -0
- package/ui/Agent/Tool.tsx +66 -0
- package/ui/Agent/Transcript.tsx +33 -0
- package/ui/Agent/Zone.tsx +48 -0
- package/ui/Agent/fetchRunner.ts +30 -0
- package/ui/Agent/index.ts +12 -0
- package/ui/Agent/index_.tsx +4 -0
- package/ui/Agent/sessionHistory.ts +33 -0
- package/ui/Badge.tsx +3 -3
- package/ui/BottomSheet.tsx +5 -0
- package/ui/Button.tsx +6 -2
- package/ui/Constant/Doc.tsx +1 -1
- package/ui/CsrImage.tsx +1 -1
- package/ui/Data/ListContainer.tsx +1 -1
- package/ui/DatePicker.tsx +5 -4
- package/ui/Dialog/Modal.tsx +12 -15
- package/ui/DraggableList.tsx +3 -1
- package/ui/Dropdown.tsx +33 -11
- package/ui/Field.tsx +30 -16
- package/ui/Image.tsx +3 -3
- package/ui/Input.tsx +14 -5
- package/ui/Layout/BottomInset.tsx +6 -1
- package/ui/Load/Units.tsx +11 -2
- package/ui/Load/View.tsx +7 -2
- package/ui/Loading/ProgressBar.tsx +8 -1
- package/ui/Menu.tsx +7 -8
- package/ui/Model/EditModal.tsx +37 -2
- package/ui/Model/SureToRemove.tsx +2 -1
- package/ui/Model/index_.tsx +42 -15
- package/ui/ObjectId.tsx +3 -4
- package/ui/Pagination.tsx +3 -4
- package/ui/Popconfirm.tsx +8 -7
- package/ui/Select.tsx +6 -4
- package/ui/Signal/RestApi.tsx +43 -16
- package/ui/Signal/WebSocket.tsx +1 -1
- package/ui/Signal/style.ts +6 -1
- package/ui/Switch.tsx +2 -0
- package/ui/System/CSR.tsx +6 -2
- package/ui/System/ThemeToggle.tsx +55 -33
- package/ui/ToggleSelect.tsx +4 -3
- package/ui/Tooltip.tsx +2 -1
- package/ui/UiOverride/context.ts +14 -2
- package/ui/agentAttrs.ts +19 -0
- package/ui/index.ts +10 -1
- package/ui/overlayLayer.ts +39 -0
- package/ui/recipe/badgeRecipe.ts +22 -3
- package/ui/recipe/buttonRecipe.ts +51 -2
- package/ui/recipe/factory.ts +2 -2
- package/ui/recipe/inputRecipe.ts +18 -4
- package/vendor/use-agentic/AgentProvider.tsx +39 -0
- package/vendor/use-agentic/AgentScope.tsx +20 -0
- package/vendor/use-agentic/AgentSession.ts +292 -0
- package/vendor/use-agentic/Agentic.tsx +44 -0
- package/vendor/use-agentic/AgenticSurface.ts +294 -0
- package/vendor/use-agentic/WIRE.md +57 -0
- package/vendor/use-agentic/httpRunner.ts +115 -0
- package/vendor/use-agentic/index.ts +14 -0
- package/vendor/use-agentic/surfaceContext.ts +9 -0
- package/vendor/use-agentic/types.ts +144 -0
- package/vendor/use-agentic/useAgent.ts +17 -0
- package/vendor/use-agentic/useAgentGuide.ts +16 -0
- package/vendor/use-agentic/useAgentResource.ts +30 -0
- package/vendor/use-agentic/useAgentState.ts +61 -0
- package/vendor/use-agentic/useAgentTool.ts +55 -0
- package/webkit/bootCsr.tsx +2 -33
- package/webkit/index.ts +3 -0
- package/webkit/lazy.tsx +27 -3
- package/webkit/useCsrValues.ts +121 -4
- package/webkit/useEscapeKey.tsx +42 -0
- package/webkit/useFrameRuntime.ts +65 -32
- package/webkit/useScreenScope.tsx +49 -0
|
@@ -8,6 +8,7 @@ import { AiOutlineDelete } from "react-icons/ai";
|
|
|
8
8
|
|
|
9
9
|
import { buttonRecipe } from "../Button";
|
|
10
10
|
import { Modal } from "../Modal";
|
|
11
|
+
import { inputRecipe } from "../recipe";
|
|
11
12
|
|
|
12
13
|
interface SureToRemoveProps {
|
|
13
14
|
className?: string;
|
|
@@ -95,7 +96,7 @@ export default function SureToRemove({
|
|
|
95
96
|
</div>
|
|
96
97
|
{typeNameToRemove ? (
|
|
97
98
|
<input
|
|
98
|
-
className="
|
|
99
|
+
className={inputRecipe({}, "text-center")}
|
|
99
100
|
placeholder={`${l(`${modelName}.modelName` as "base.new")} name`}
|
|
100
101
|
value={repeatName}
|
|
101
102
|
onChange={(e) => {
|
package/ui/Model/index_.tsx
CHANGED
|
@@ -1,17 +1,44 @@
|
|
|
1
1
|
import { lazy } from "akanjs/webkit";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Every Model export carries its own Suspense boundary.
|
|
5
|
+
*
|
|
6
|
+
* These mount on interaction — a modal body, a dropdown item, a confirm shell — long after the page is
|
|
7
|
+
* painted, and a chunk that resolves then would otherwise suspend all the way to the route and repaint
|
|
8
|
+
* the page as its loading fallback, once per fresh load.
|
|
9
|
+
*/
|
|
10
|
+
const withSuspense = { suspense: true } as const;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A fallback here may only be a host element. This module has no `"use client"`, so a client component
|
|
14
|
+
* referenced from it — `Loading.Skeleton` was the one tried — resolves to `undefined` inside the thunk
|
|
15
|
+
* and the render throws "Element type is invalid", taking the whole page segment under the layout with
|
|
16
|
+
* it. Marking the barrel `"use client"` is worse: `Model.*` becomes a real server→client boundary and
|
|
17
|
+
* apps passing crystalized model instances as props fail serialization at boot. Plain markup crosses
|
|
18
|
+
* neither line.
|
|
19
|
+
*
|
|
20
|
+
* Only the two exports that occupy space of their own get it. The triggers wrap the caller's own
|
|
21
|
+
* children, so a fixed block would put a slab where a small button belongs, and the modals render `null`
|
|
22
|
+
* until opened, so a block would appear where nothing ever shows. For those the collapse is a blink the
|
|
23
|
+
* size of a button; here it is the page body dropping to zero height and snapping back.
|
|
24
|
+
*/
|
|
25
|
+
const bodyFallback = {
|
|
26
|
+
suspense: true,
|
|
27
|
+
loading: () => <div className="min-h-40 w-full animate-pulse rounded-md bg-muted" />,
|
|
28
|
+
} as const;
|
|
29
|
+
|
|
30
|
+
export const ViewModal = lazy(() => import("./ViewModal"), withSuspense);
|
|
31
|
+
export const EditModal = lazy(() => import("./EditModal"), withSuspense);
|
|
32
|
+
export const View = lazy(() => import("./View"), bodyFallback);
|
|
33
|
+
export const SureToRemove = lazy(() => import("./SureToRemove"), withSuspense);
|
|
34
|
+
export const Remove = lazy(() => import("./Remove"), withSuspense);
|
|
35
|
+
export const NewWrapper = lazy(() => import("./NewWrapper"), withSuspense);
|
|
36
|
+
export const EditWrapper = lazy(() => import("./EditWrapper"), withSuspense);
|
|
37
|
+
export const RemoveWrapper = lazy(() => import("./RemoveWrapper"), withSuspense);
|
|
38
|
+
export const LoadInit = lazy(() => import("./LoadInit"), withSuspense);
|
|
39
|
+
export const LoadView = lazy(() => import("./LoadView"), withSuspense);
|
|
40
|
+
export const ViewWrapper = lazy(() => import("./ViewWrapper"), withSuspense);
|
|
41
|
+
export const ViewEditModal = lazy(() => import("./ViewEditModal"), withSuspense);
|
|
42
|
+
export const Edit = lazy(() => import("./Edit"), withSuspense);
|
|
43
|
+
export const New = lazy(() => import("./New"), withSuspense);
|
|
44
|
+
export const AdminPanel = lazy(() => import("./AdminPanel"), bodyFallback);
|
package/ui/ObjectId.tsx
CHANGED
|
@@ -4,6 +4,7 @@ import { AiOutlineCheck, AiOutlineCopy } from "react-icons/ai";
|
|
|
4
4
|
|
|
5
5
|
import { buttonRecipe } from "./Button";
|
|
6
6
|
import { Tooltip } from "./Tooltip";
|
|
7
|
+
import { useUiRecipe } from "./UiOverride";
|
|
7
8
|
|
|
8
9
|
interface ObjectIdProps {
|
|
9
10
|
id: string;
|
|
@@ -11,6 +12,7 @@ interface ObjectIdProps {
|
|
|
11
12
|
|
|
12
13
|
export const ObjectId = ({ id }: ObjectIdProps) => {
|
|
13
14
|
const [isCopied, setIsCopied] = useState(false);
|
|
15
|
+
const recipe = useUiRecipe("button") ?? buttonRecipe;
|
|
14
16
|
const shortenedId = `${id.substring(0, 4)}...${id.substring(id.length - 5)}`;
|
|
15
17
|
const handleCopyClick = () => {
|
|
16
18
|
void navigator.clipboard.writeText(id);
|
|
@@ -24,10 +26,7 @@ export const ObjectId = ({ id }: ObjectIdProps) => {
|
|
|
24
26
|
<Tooltip content={id} variant="primary">
|
|
25
27
|
<div className="font-semibold text-xs">{shortenedId}</div>
|
|
26
28
|
</Tooltip>
|
|
27
|
-
<button
|
|
28
|
-
className={buttonRecipe({ variant: "ghost", size: "icon" }, "size-6 rounded-full")}
|
|
29
|
-
onClick={handleCopyClick}
|
|
30
|
-
>
|
|
29
|
+
<button className={recipe({ variant: "ghost", size: "icon" }, "size-6 rounded-full")} onClick={handleCopyClick}>
|
|
31
30
|
{isCopied ? <AiOutlineCheck /> : <AiOutlineCopy />}
|
|
32
31
|
</button>
|
|
33
32
|
</div>
|
package/ui/Pagination.tsx
CHANGED
|
@@ -4,10 +4,7 @@ import type { FC, ReactNode } from "react";
|
|
|
4
4
|
import { BiChevronLeft, BiChevronRight, BiDotsHorizontalRounded } from "react-icons/bi";
|
|
5
5
|
|
|
6
6
|
import { buttonRecipe } from "./Button";
|
|
7
|
-
import { createOverridable } from "./UiOverride";
|
|
8
|
-
|
|
9
|
-
/** Square ghost button style shared by every pager control (canonical buttonRecipe). */
|
|
10
|
-
const pageBtn = buttonRecipe({ variant: "ghost", size: "icon" });
|
|
7
|
+
import { createOverridable, useUiRecipe } from "./UiOverride";
|
|
11
8
|
|
|
12
9
|
export interface PaginationProps {
|
|
13
10
|
/** Current 1-based page number. */
|
|
@@ -36,6 +33,8 @@ export const DefaultPagination: FC<PaginationProps> = ({
|
|
|
36
33
|
renderEmpty,
|
|
37
34
|
classNames,
|
|
38
35
|
}) => {
|
|
36
|
+
|
|
37
|
+
const pageBtn = (useUiRecipe("button") ?? buttonRecipe)({ variant: "ghost", size: "icon" });
|
|
39
38
|
const totalPages = Math.ceil(total / (itemsPerPage || 1));
|
|
40
39
|
const handleLeftClick = () => {
|
|
41
40
|
if (currentPage <= 1) return;
|
package/ui/Popconfirm.tsx
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
import { useSpring } from "@react-spring/web";
|
|
3
3
|
|
|
4
4
|
import { cn, usePage } from "akanjs/client";
|
|
5
|
+
import { useEscapeKey } from "akanjs/webkit";
|
|
5
6
|
import { type ButtonHTMLAttributes, type ReactNode, useEffect, useState } from "react";
|
|
6
7
|
import { BiMessageRoundedError } from "react-icons/bi";
|
|
7
8
|
import { animated } from "./animated";
|
|
8
9
|
import { buttonRecipe } from "./Button";
|
|
9
|
-
import { createOverridable } from "./UiOverride";
|
|
10
|
+
import { createOverridable, useUiRecipe } from "./UiOverride";
|
|
10
11
|
|
|
11
12
|
type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
12
13
|
loading?: boolean;
|
|
@@ -48,6 +49,8 @@ export const DefaultPopconfirm = ({
|
|
|
48
49
|
decoClassName,
|
|
49
50
|
}: PopconfirmProps) => {
|
|
50
51
|
const { l } = usePage();
|
|
52
|
+
|
|
53
|
+
const recipe = useUiRecipe("button") ?? buttonRecipe;
|
|
51
54
|
const [isConfirming, setIsConfirming] = useState(false);
|
|
52
55
|
|
|
53
56
|
const popconfirmProps = useSpring({
|
|
@@ -82,6 +85,8 @@ export const DefaultPopconfirm = ({
|
|
|
82
85
|
setIsConfirming(false);
|
|
83
86
|
};
|
|
84
87
|
|
|
88
|
+
useEscapeKey(isConfirming, handleCancel);
|
|
89
|
+
|
|
85
90
|
return (
|
|
86
91
|
<>
|
|
87
92
|
<div className="relative inline-block">
|
|
@@ -115,17 +120,13 @@ export const DefaultPopconfirm = ({
|
|
|
115
120
|
</div>
|
|
116
121
|
<div className="flex justify-end gap-2">
|
|
117
122
|
<button
|
|
118
|
-
className={
|
|
123
|
+
className={recipe({ variant: "outline", size: "xs" })}
|
|
119
124
|
onClick={handleCancel}
|
|
120
125
|
{...cancelButtonProps}
|
|
121
126
|
>
|
|
122
127
|
{cancelText ?? l("base.cancel")}
|
|
123
128
|
</button>
|
|
124
|
-
<button
|
|
125
|
-
className={buttonRecipe({ variant: "primary", size: "xs" })}
|
|
126
|
-
onClick={handleConfirm}
|
|
127
|
-
{...okButtonProps}
|
|
128
|
-
>
|
|
129
|
+
<button className={recipe({ variant: "primary", size: "xs" })} onClick={handleConfirm} {...okButtonProps}>
|
|
129
130
|
{okText ?? l("base.ok")}
|
|
130
131
|
</button>
|
|
131
132
|
</div>
|
package/ui/Select.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import { BiCheck, BiChevronDown, BiX } from "react-icons/bi";
|
|
|
7
7
|
import { BsQuestionCircleFill } from "react-icons/bs";
|
|
8
8
|
import { TiDelete } from "react-icons/ti";
|
|
9
9
|
|
|
10
|
+
import { agentAttrs } from "./agentAttrs";
|
|
10
11
|
import { useUiOverride } from "./UiOverride";
|
|
11
12
|
|
|
12
13
|
interface LabelOption<T> {
|
|
@@ -164,7 +165,7 @@ const DefaultSelect = <
|
|
|
164
165
|
}, [value]);
|
|
165
166
|
|
|
166
167
|
return (
|
|
167
|
-
<div className={cn("relative min-w-[150px]", className)} ref={dropdownRef}>
|
|
168
|
+
<div {...agentAttrs(onChange)} className={cn("relative min-w-[150px]", className)} ref={dropdownRef}>
|
|
168
169
|
<div
|
|
169
170
|
data-open={isOpen}
|
|
170
171
|
className={cn(
|
|
@@ -217,7 +218,7 @@ const DefaultSelect = <
|
|
|
217
218
|
{searchable ? (
|
|
218
219
|
<input
|
|
219
220
|
type="text"
|
|
220
|
-
className="
|
|
221
|
+
className="w-full flex-1 border-none bg-transparent shadow-none outline-none focus:border-none focus:shadow-none focus:outline-none"
|
|
221
222
|
placeholder={selectedValues.length > 0 ? "" : placeholder}
|
|
222
223
|
value={searchText}
|
|
223
224
|
onChange={(e) => {
|
|
@@ -262,8 +263,9 @@ const DefaultSelect = <
|
|
|
262
263
|
<div
|
|
263
264
|
data-open={isOpen}
|
|
264
265
|
className={cn(
|
|
265
|
-
"scrollbar-thin scrollbar-thumb-foreground/20 scrollbar-track scrollbar-track-foreground/40 absolute z-20 mt-0.5 w-full overflow-y-
|
|
266
|
-
|
|
266
|
+
"scrollbar-thin scrollbar-thumb-foreground/20 scrollbar-track scrollbar-track-foreground/40 absolute z-20 mt-0.5 w-full overflow-y-auto rounded-md border-border bg-muted shadow-lg transition-all",
|
|
267
|
+
|
|
268
|
+
"origin-center duration-200 data-[open=false]:max-h-0 data-[open=true]:max-h-[270px] data-[open=true]:border data-[open=false]:border-none",
|
|
267
269
|
selectorClassName,
|
|
268
270
|
)}
|
|
269
271
|
>
|
package/ui/Signal/RestApi.tsx
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { PrimitiveRegistry } from "akanjs/base";
|
|
3
3
|
import { usePage } from "akanjs/client";
|
|
4
|
+
import { mcpHintsOf, mcpRefusalOf } from "akanjs/common";
|
|
4
5
|
import { type ConstantCls, ConstantRegistry } from "akanjs/constant";
|
|
5
6
|
import { FetchClient, type FetchProxy } from "akanjs/fetch";
|
|
6
7
|
import type { SerializedEndpoint } from "akanjs/signal";
|
|
7
8
|
import { st } from "akanjs/store";
|
|
8
9
|
import { useMemo, useState } from "react";
|
|
9
10
|
import { AiOutlineApi, AiOutlineCopy, AiOutlineFileWord, AiOutlineSend } from "react-icons/ai";
|
|
11
|
+
import { badgeRecipe } from "../Badge";
|
|
10
12
|
import { buttonRecipe } from "../Button";
|
|
11
13
|
import { Copy } from "../Copy";
|
|
12
14
|
import { Signal } from ".";
|
|
@@ -14,7 +16,7 @@ import Arg from "./Arg";
|
|
|
14
16
|
import { SignalCollapse } from "./Collapse";
|
|
15
17
|
import { getExampleData } from "./makeExample";
|
|
16
18
|
import Response from "./Response";
|
|
17
|
-
import { getEndpointBadgeClassName, getGuardBadgeClassName, signalUi } from "./style";
|
|
19
|
+
import { getEndpointBadgeClassName, getGuardBadgeClassName, getMcpBadgeClassName, signalUi } from "./style";
|
|
18
20
|
|
|
19
21
|
type RestApiFetchFn = (
|
|
20
22
|
...args: [...args: unknown[], option: { token?: string; crystalize?: boolean }]
|
|
@@ -36,17 +38,21 @@ const RestApiEndpoints = ({ refName, fetch, prefix, endpoints, openAll, httpUri
|
|
|
36
38
|
const tryRoles = st.use.tryRoles();
|
|
37
39
|
const signal = fetch.serializedSignal[refName];
|
|
38
40
|
const signalPrefix = prefix ?? signal.prefix;
|
|
39
|
-
const baseEndpointEntries = Object.entries(FetchClient.getBaseEndpoint(refName, signal))
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
41
|
+
const baseEndpointEntries = Object.entries(FetchClient.getBaseEndpoint(refName, signal)).map(([key, endpoint]) => ({
|
|
42
|
+
key,
|
|
43
|
+
endpoint,
|
|
44
|
+
}));
|
|
45
|
+
const sliceEndpointEntries = Object.entries(signal.slice ?? {}).flatMap(([suffix, slice]) =>
|
|
46
|
+
Object.entries(FetchClient.getEndpointFromSlice(refName, suffix, slice)).map(([key, endpoint]) => ({
|
|
47
|
+
key,
|
|
48
|
+
endpoint,
|
|
49
|
+
})),
|
|
50
|
+
);
|
|
51
|
+
const customEndpointEntries = Object.entries(signal.endpoint).map(([key, endpoint]) => ({ key, endpoint }));
|
|
52
|
+
const endpointEntries = [...baseEndpointEntries, ...sliceEndpointEntries, ...customEndpointEntries]
|
|
53
|
+
.filter(({ key }) => !endpoints || endpoints.includes(key))
|
|
54
|
+
.sort((a, b) => (a.key > b.key ? 1 : -1))
|
|
55
|
+
.filter(({ endpoint }) => {
|
|
50
56
|
if (endpoint.type === "pubsub" || endpoint.type === "message") return false;
|
|
51
57
|
if (!endpoint.guards?.length) return true;
|
|
52
58
|
if (endpoint.guards?.includes("Public") && tryRoles.includes("Public")) return true;
|
|
@@ -63,13 +69,13 @@ const RestApiEndpoints = ({ refName, fetch, prefix, endpoints, openAll, httpUri
|
|
|
63
69
|
});
|
|
64
70
|
return (
|
|
65
71
|
<div>
|
|
66
|
-
{endpointEntries.map((
|
|
72
|
+
{endpointEntries.map(({ key, endpoint }) => (
|
|
67
73
|
<RestApiEndpoint
|
|
68
|
-
key={
|
|
74
|
+
key={key}
|
|
69
75
|
signalPrefix={signalPrefix}
|
|
70
76
|
refName={refName}
|
|
71
77
|
fetch={fetch}
|
|
72
|
-
endpointKey={
|
|
78
|
+
endpointKey={key}
|
|
73
79
|
endpoint={endpoint}
|
|
74
80
|
open={openAll}
|
|
75
81
|
httpUri={httpUri}
|
|
@@ -102,13 +108,20 @@ const RestApiEndpoint = ({
|
|
|
102
108
|
const { l } = usePage();
|
|
103
109
|
const [viewStatus, setViewStatus] = useState<"doc" | "test">("doc");
|
|
104
110
|
const path = FetchClient.makeHttpUrl(endpointKey, endpoint, signalPrefix, new Map());
|
|
111
|
+
|
|
112
|
+
const mcpRefusal = mcpRefusalOf(endpoint);
|
|
105
113
|
return (
|
|
106
114
|
<SignalCollapse
|
|
107
115
|
open={open}
|
|
108
116
|
contentClassName="bg-background/60"
|
|
109
117
|
summary={
|
|
110
118
|
<div className="flex flex-wrap items-center gap-2">
|
|
111
|
-
|
|
119
|
+
{/* Only a mutation is a POST — enumerate that side, because a `prompt` is a GET beside the queries and
|
|
120
|
+
a new read-shaped type would inherit the right verb rather than be mislabelled. */}
|
|
121
|
+
<div className={getEndpointBadgeClassName(endpoint.type)}>
|
|
122
|
+
{endpoint.type === "mutation" ? "POST" : "GET"}
|
|
123
|
+
</div>
|
|
124
|
+
<div className={getMcpBadgeClassName(!mcpRefusal)}>{mcpRefusal ? "MCP refused" : "MCP"}</div>
|
|
112
125
|
<div className="font-bold text-lg">{path}</div>
|
|
113
126
|
<div className="text-foreground/70 text-sm">{l._(`${refName}.signal.${endpointKey}`)}</div>
|
|
114
127
|
</div>
|
|
@@ -127,6 +140,20 @@ const RestApiEndpoint = ({
|
|
|
127
140
|
))}
|
|
128
141
|
</div>
|
|
129
142
|
) : null}
|
|
143
|
+
<div className="mt-2 flex flex-wrap items-center gap-2 font-normal text-sm">
|
|
144
|
+
<span className="text-foreground/70">MCP</span>
|
|
145
|
+
{mcpRefusal ? (
|
|
146
|
+
<span className="text-warning">{mcpRefusal}</span>
|
|
147
|
+
) : (
|
|
148
|
+
Object.entries(mcpHintsOf(endpointKey, endpoint))
|
|
149
|
+
.filter(([, on]) => on)
|
|
150
|
+
.map(([hint]) => (
|
|
151
|
+
<span className={badgeRecipe({ variant: "outline", size: "sm" })} key={hint}>
|
|
152
|
+
{hint}
|
|
153
|
+
</span>
|
|
154
|
+
))
|
|
155
|
+
)}
|
|
156
|
+
</div>
|
|
130
157
|
<div className="mt-2 font-normal text-foreground/70 text-sm">
|
|
131
158
|
{l._(`${refName}.signal.${endpointKey}.desc`)}
|
|
132
159
|
</div>
|
package/ui/Signal/WebSocket.tsx
CHANGED
|
@@ -18,7 +18,7 @@ const WebSocketEndpoints = ({ refName, fetch, openAll }: WebSocketEndpointsProps
|
|
|
18
18
|
const endpointEntries = Object.entries(signal.endpoint)
|
|
19
19
|
.sort(([keyA], [keyB]) => (keyA > keyB ? 1 : -1))
|
|
20
20
|
.filter(([key, endpoint]) => {
|
|
21
|
-
if (endpoint.type
|
|
21
|
+
if (endpoint.type !== "pubsub" && endpoint.type !== "message") return false;
|
|
22
22
|
|
|
23
23
|
return false;
|
|
24
24
|
});
|
package/ui/Signal/style.ts
CHANGED
|
@@ -15,12 +15,17 @@ export const signalUi = {
|
|
|
15
15
|
"min-h-[300px] w-full rounded-xl border border-border bg-background p-4 font-normal text-foreground text-sm",
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
+
/** Writes carry the accent, reads do not — so the two write types are named and everything else reads. */
|
|
18
19
|
export const getEndpointBadgeClassName = (type: string) =>
|
|
19
|
-
badgeRecipe({ variant: type === "
|
|
20
|
+
badgeRecipe({ variant: type === "mutation" || type === "message" ? "secondary" : "primary" });
|
|
20
21
|
|
|
21
22
|
export const getGuardBadgeClassName = (guard: string) =>
|
|
22
23
|
badgeRecipe({ variant: guard === "Public" ? "primary" : guard === "None" ? "default" : "secondary" });
|
|
23
24
|
|
|
25
|
+
/** Published to agents carries the accent; opted in and refused is outlined, because it is a thing to go fix. */
|
|
26
|
+
export const getMcpBadgeClassName = (exposed: boolean) =>
|
|
27
|
+
badgeRecipe({ variant: exposed ? "accent" : "warning", size: "sm", outline: !exposed });
|
|
28
|
+
|
|
24
29
|
export const getStatusBadgeClassName = (status: string) =>
|
|
25
30
|
badgeRecipe({
|
|
26
31
|
variant: status === "error" ? "error" : status === "success" || status === "listening" ? "primary" : "outline",
|
package/ui/Switch.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "akanjs/client";
|
|
3
3
|
import { useState } from "react";
|
|
4
|
+
import { agentAttrs } from "./agentAttrs";
|
|
4
5
|
|
|
5
6
|
export interface SwitchProps {
|
|
6
7
|
checked?: boolean;
|
|
@@ -36,6 +37,7 @@ export const Switch = ({
|
|
|
36
37
|
const state = isChecked ? "checked" : "unchecked";
|
|
37
38
|
return (
|
|
38
39
|
<button
|
|
40
|
+
{...agentAttrs(onChange)}
|
|
39
41
|
type="button"
|
|
40
42
|
role="switch"
|
|
41
43
|
aria-checked={isChecked}
|
package/ui/System/CSR.tsx
CHANGED
|
@@ -226,6 +226,7 @@ const CSRWrapper = ({
|
|
|
226
226
|
: bottomInset?.containerStyle
|
|
227
227
|
}
|
|
228
228
|
animationDuration={frameLayout.keyboard.animationDuration}
|
|
229
|
+
animationEasing={frameLayout.keyboard.animationEasing}
|
|
229
230
|
>
|
|
230
231
|
<CSRFrameSlotTargets slot="keyboardInset" />
|
|
231
232
|
</KeyboardLayer>
|
|
@@ -281,14 +282,17 @@ const KeyboardLayer = ({
|
|
|
281
282
|
className,
|
|
282
283
|
style,
|
|
283
284
|
animationDuration,
|
|
285
|
+
animationEasing,
|
|
284
286
|
children,
|
|
285
|
-
}: FrameLayerProps & { animationDuration?: number }) => (
|
|
287
|
+
}: FrameLayerProps & { animationDuration?: number; animationEasing?: string }) => (
|
|
286
288
|
<animated.div
|
|
287
289
|
id={id}
|
|
288
290
|
className={className}
|
|
289
291
|
style={{
|
|
290
292
|
...(style ?? {}),
|
|
291
|
-
transition: `top ${animationDuration ??
|
|
293
|
+
transition: `top ${animationDuration ?? 420}ms ${animationEasing ?? "cubic-bezier(0.16, 1, 0.3, 1)"}, height ${
|
|
294
|
+
animationDuration ?? 420
|
|
295
|
+
}ms ${animationEasing ?? "cubic-bezier(0.16, 1, 0.3, 1)"}`,
|
|
292
296
|
willChange: "top, height",
|
|
293
297
|
}}
|
|
294
298
|
>
|
|
@@ -1,18 +1,35 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { setCookie } from "akanjs/client";
|
|
4
|
+
import { st } from "akanjs/store";
|
|
4
5
|
import { useCallback, useEffect, useState } from "react";
|
|
5
|
-
|
|
6
6
|
import { buttonRecipe } from "../Button";
|
|
7
7
|
import { Dropdown } from "../Dropdown";
|
|
8
8
|
import { Switch } from "../Switch";
|
|
9
9
|
|
|
10
|
+
interface ThemeAgentSurfaceProps {
|
|
11
|
+
themes: string[];
|
|
12
|
+
current?: string;
|
|
13
|
+
onApply: (theme: string) => void;
|
|
14
|
+
}
|
|
15
|
+
const ThemeAgentSurface = ({ themes, current, onApply }: ThemeAgentSurfaceProps) => {
|
|
16
|
+
st.expose("theme", current ?? null);
|
|
17
|
+
st.tool("setTheme", { desc: `Switch this page's color theme. One of: ${themes.join(", ")}.` })
|
|
18
|
+
.arg("theme", String)
|
|
19
|
+
.exec((theme) => {
|
|
20
|
+
if (!themes.includes(theme)) throw new Error(`Unknown theme "${theme}". One of: ${themes.join(", ")}.`);
|
|
21
|
+
onApply(theme);
|
|
22
|
+
});
|
|
23
|
+
return null;
|
|
24
|
+
};
|
|
25
|
+
|
|
10
26
|
export interface ThemeToggleProps {
|
|
11
27
|
themes?: string[];
|
|
12
28
|
}
|
|
13
29
|
|
|
14
30
|
export const ThemeToggle = ({ themes }: ThemeToggleProps) => {
|
|
15
31
|
const [theme, setTheme] = useState<string | undefined>(undefined);
|
|
32
|
+
const stTheme = st.use.theme();
|
|
16
33
|
useEffect(() => {
|
|
17
34
|
if (!themes) return;
|
|
18
35
|
const currentTheme = document.documentElement.getAttribute("data-theme");
|
|
@@ -25,9 +42,11 @@ export const ThemeToggle = ({ themes }: ThemeToggleProps) => {
|
|
|
25
42
|
setTheme(theme);
|
|
26
43
|
}, []);
|
|
27
44
|
if (!themes || themes.length <= 1) return null;
|
|
45
|
+
const agentSurface = <ThemeAgentSurface current={theme} onApply={applyTheme} themes={themes} />;
|
|
28
46
|
if (themes.length === 2)
|
|
29
47
|
return (
|
|
30
48
|
<div className="flex items-center gap-1 text-foreground">
|
|
49
|
+
{agentSurface}
|
|
31
50
|
<svg aria-label="sun" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" className="size-4">
|
|
32
51
|
<g strokeLinejoin="round" strokeLinecap="round" strokeWidth="2" fill="none" stroke="currentColor">
|
|
33
52
|
<circle cx="12" cy="12" r="4"></circle>
|
|
@@ -55,37 +74,40 @@ export const ThemeToggle = ({ themes }: ThemeToggleProps) => {
|
|
|
55
74
|
</div>
|
|
56
75
|
);
|
|
57
76
|
return (
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
77
|
+
<>
|
|
78
|
+
{agentSurface}
|
|
79
|
+
<Dropdown
|
|
80
|
+
className="mb-72"
|
|
81
|
+
buttonClassName="m-1"
|
|
82
|
+
value={
|
|
83
|
+
<>
|
|
84
|
+
Theme
|
|
85
|
+
<svg
|
|
86
|
+
width="12px"
|
|
87
|
+
height="12px"
|
|
88
|
+
className="inline-block h-2 w-2 fill-current opacity-60"
|
|
89
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
90
|
+
viewBox="0 0 2048 2048"
|
|
91
|
+
>
|
|
92
|
+
<path d="M1799 349l242 241-1017 1017L7 590l242-241 775 775 775-775z"></path>
|
|
93
|
+
</svg>
|
|
94
|
+
</>
|
|
95
|
+
}
|
|
96
|
+
dropdownClassName="w-52 bg-border"
|
|
97
|
+
content={themes.map((theme) => (
|
|
98
|
+
<li key={theme}>
|
|
99
|
+
<button
|
|
100
|
+
type="button"
|
|
101
|
+
className={buttonRecipe({ variant: "ghost", size: "sm" }, "w-full justify-start")}
|
|
102
|
+
onClick={() => {
|
|
103
|
+
applyTheme(theme);
|
|
104
|
+
}}
|
|
105
|
+
>
|
|
106
|
+
{theme}
|
|
107
|
+
</button>
|
|
108
|
+
</li>
|
|
109
|
+
))}
|
|
110
|
+
/>
|
|
111
|
+
</>
|
|
90
112
|
);
|
|
91
113
|
};
|
package/ui/ToggleSelect.tsx
CHANGED
|
@@ -3,10 +3,9 @@ import { cn, usePage } from "akanjs/client";
|
|
|
3
3
|
import { type ComponentType, createElement } from "react";
|
|
4
4
|
|
|
5
5
|
import { buttonRecipe } from "./Button";
|
|
6
|
-
import { createOverridable, useUiOverride } from "./UiOverride";
|
|
6
|
+
import { createOverridable, useUiOverride, useUiRecipe } from "./UiOverride";
|
|
7
7
|
|
|
8
|
-
/** Toggle-select cell: outline button, filled success when selected. */
|
|
9
|
-
const toggleBtn = buttonRecipe({ variant: "outline", size: "sm" });
|
|
8
|
+
/** Toggle-select cell: outline button (recipe slot), filled success when selected. */
|
|
10
9
|
const selectedCls = "border-transparent bg-success/70 text-success-foreground hover:bg-success/70";
|
|
11
10
|
|
|
12
11
|
export interface ToggleSelectProps<I extends string | number | boolean | null> {
|
|
@@ -30,6 +29,7 @@ const DefaultToggleSelect = <I extends string | number | boolean | null>({
|
|
|
30
29
|
disabled,
|
|
31
30
|
}: ToggleSelectProps<I>) => {
|
|
32
31
|
const { l } = usePage();
|
|
32
|
+
const toggleBtn = (useUiRecipe("button") ?? buttonRecipe)({ variant: "outline", size: "sm" });
|
|
33
33
|
const validateResult = value !== null ? validate(value) : false;
|
|
34
34
|
|
|
35
35
|
const invalidMessage =
|
|
@@ -97,6 +97,7 @@ const DefaultMulti = ({
|
|
|
97
97
|
disabled,
|
|
98
98
|
}: MultiProps) => {
|
|
99
99
|
const { l } = usePage();
|
|
100
|
+
const toggleBtn = (useUiRecipe("button") ?? buttonRecipe)({ variant: "outline", size: "sm" });
|
|
100
101
|
const validateResult = validate(value);
|
|
101
102
|
|
|
102
103
|
const invalidMessage =
|
package/ui/Tooltip.tsx
CHANGED
|
@@ -35,7 +35,8 @@ const sideClass = {
|
|
|
35
35
|
const DefaultTooltip = ({ content, children, side = "top", className, variant = "default" }: TooltipProps) => {
|
|
36
36
|
if (content === undefined || content === null || content === "") return <>{children}</>;
|
|
37
37
|
return (
|
|
38
|
-
|
|
38
|
+
|
|
39
|
+
<span className="group/tooltip relative inline-flex w-fit">
|
|
39
40
|
{children}
|
|
40
41
|
<span
|
|
41
42
|
role="tooltip"
|
package/ui/UiOverride/context.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { type ComponentType, createContext } from "react";
|
|
3
3
|
import type { ClassNameValue as ClassValue } from "tailwind-merge";
|
|
4
|
+
import type { ChatProps as AgentChatProps } from "../Agent/Chat";
|
|
4
5
|
import type { BadgeProps } from "../Badge";
|
|
5
6
|
import type { ButtonProps } from "../Button";
|
|
6
7
|
import type { DatePickerProps, RangePickerProps, TimePickerProps } from "../DatePicker";
|
|
@@ -17,7 +18,7 @@ import type { ModalProps } from "../Modal";
|
|
|
17
18
|
import type { PaginationProps } from "../Pagination";
|
|
18
19
|
import type { PopconfirmProps } from "../Popconfirm";
|
|
19
20
|
import type { ItemProps as RadioItemProps, RadioProps } from "../Radio";
|
|
20
|
-
import type { BadgeVariants, ButtonVariants } from "../recipe";
|
|
21
|
+
import type { BadgeVariants, ButtonVariants, InputSurfaceVariants } from "../recipe";
|
|
21
22
|
import type { SelectProps } from "../Select";
|
|
22
23
|
import type { TableProps } from "../Table";
|
|
23
24
|
import type { MultiProps as ToggleSelectMultiProps, ToggleSelectProps } from "../ToggleSelect";
|
|
@@ -48,6 +49,7 @@ export interface AkanUiOverrides {
|
|
|
48
49
|
Menu: ComponentType<MenuProps>;
|
|
49
50
|
Tooltip: ComponentType<TooltipProps>;
|
|
50
51
|
Unauthorized: ComponentType<UnauthorizedProps>;
|
|
52
|
+
AgentChat: ComponentType<AgentChatProps>;
|
|
51
53
|
|
|
52
54
|
Button: ComponentType<ButtonProps<unknown>>;
|
|
53
55
|
Select: ComponentType<SelectProps<string | number | boolean | null | undefined>>;
|
|
@@ -87,11 +89,21 @@ export type AkanModalComponent = AkanUiOverrides["Modal"];
|
|
|
87
89
|
* manifest: `override({ recipes: { button: neonButtonRecipe } })`. A recipe swap changes
|
|
88
90
|
* only the className factory — the component's structure/behavior (async states, focus,
|
|
89
91
|
* a11y) is untouched. Each replacement must accept the framework recipe's full variant
|
|
90
|
-
* contract, so every call site keeps working
|
|
92
|
+
* contract, so every call site keeps working (a replacement with *extra* optional axes is
|
|
93
|
+
* assignable — contravariance — but those axes are only reachable from code that knows the
|
|
94
|
+
* replacement's own type).
|
|
95
|
+
*
|
|
96
|
+
* Scope: a recipe slot is a **client-side, route-scoped restyle**. It reaches framework
|
|
97
|
+
* client components, which resolve through `useUiRecipe(...)`. It never reaches a raw
|
|
98
|
+
* `xRecipe(...)` call in app JSX (statically imported — no context), nor server components
|
|
99
|
+
* (`Unit`/`View`), which intentionally render the canonical framework recipe. Extending the
|
|
100
|
+
* *vocabulary* is not this slot's job: add the axis to the framework recipe, or author an
|
|
101
|
+
* app recipe in `apps/<app>/ui/Recipe/`.
|
|
91
102
|
*/
|
|
92
103
|
export interface AkanUiRecipes {
|
|
93
104
|
button: (variants?: ButtonVariants, className?: ClassValue) => string;
|
|
94
105
|
badge: (variants?: BadgeVariants, className?: ClassValue) => string;
|
|
106
|
+
input: (variants?: InputSurfaceVariants, className?: ClassValue) => string;
|
|
95
107
|
}
|
|
96
108
|
|
|
97
109
|
/** Shape of an `_overrides.tsx` manifest: component slots plus an optional recipe-slot map. */
|
package/ui/agentAttrs.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { actionTagOf } from "akanjs/store";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The `data-akan-*` attributes for a handler the caller passed by reference.
|
|
5
|
+
*
|
|
6
|
+
* `{}` when the handler is an inline arrow, which is the honest answer: a closure the caller wrote says nothing
|
|
7
|
+
* about what it does, and a guessed annotation is worse than none. The house form for a model field is the setter
|
|
8
|
+
* itself (`onChange={st.do.setNameOnUser}`), so the fields that matter are annotated without an app writing anything.
|
|
9
|
+
*
|
|
10
|
+
* What it buys, beyond an in-page agent: an accessibility tree and E2E selectors that name the action rather than a
|
|
11
|
+
* class, and an external browser agent — one this framework has no bridge into — reading the same names.
|
|
12
|
+
*/
|
|
13
|
+
export const agentAttrs = (
|
|
14
|
+
handler: unknown,
|
|
15
|
+
): { "data-akan-action"?: string; "data-akan-state"?: string } | Record<string, never> => {
|
|
16
|
+
const tag = actionTagOf(handler);
|
|
17
|
+
if (!tag) return {};
|
|
18
|
+
return { "data-akan-action": tag.action, ...(tag.state ? { "data-akan-state": tag.state } : {}) };
|
|
19
|
+
};
|