@almadar/shell-web 0.0.0-stage → 1.0.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/bundling.d.mts +18 -0
- package/bundling.mjs +28 -0
- package/dist/ArbitraryClassCompiler-CO_iASBn.d.ts +195 -0
- package/dist/AvlGlyph-EPJKFEO3.js +6 -0
- package/dist/AvlStateMachine-RKZIKNGC.js +9 -0
- package/dist/AvlTransitionDetail-63SD6GZF.js +11 -0
- package/dist/AvlTransitionExplainer-ZBTLOM3T.js +12 -0
- package/dist/BehaviorView-YS5G4GNB.js +11 -0
- package/dist/Canvas3DHost-BkZQB5l2.d.ts +552 -0
- package/dist/EventBusProvider-BFFHfN4O.d.ts +296 -0
- package/dist/FileTree-BCFnBEuQ.d.ts +254 -0
- package/dist/FlowCanvas-3JRMNJLV.css +1756 -0
- package/dist/FlowCanvas-AUMTWMNG.js +26 -0
- package/dist/GameAudioProvider-ceM_n0ey.d.ts +90 -0
- package/dist/KaTeX_AMS-Regular-CYEKBG2K.woff +0 -0
- package/dist/KaTeX_AMS-Regular-JKX5W2C4.ttf +0 -0
- package/dist/KaTeX_AMS-Regular-U6PRYMIZ.woff2 +0 -0
- package/dist/KaTeX_Caligraphic-Bold-5QL5CMTE.woff2 +0 -0
- package/dist/KaTeX_Caligraphic-Bold-WZ3QSGD3.woff +0 -0
- package/dist/KaTeX_Caligraphic-Bold-ZTS3R3HK.ttf +0 -0
- package/dist/KaTeX_Caligraphic-Regular-3LKEU76G.woff +0 -0
- package/dist/KaTeX_Caligraphic-Regular-A7XRTZ5Q.ttf +0 -0
- package/dist/KaTeX_Caligraphic-Regular-KX5MEWCF.woff2 +0 -0
- package/dist/KaTeX_Fraktur-Bold-2QVFK6NQ.woff2 +0 -0
- package/dist/KaTeX_Fraktur-Bold-T4SWXBMT.woff +0 -0
- package/dist/KaTeX_Fraktur-Bold-WGHVTYOR.ttf +0 -0
- package/dist/KaTeX_Fraktur-Regular-2PEIFJSJ.woff2 +0 -0
- package/dist/KaTeX_Fraktur-Regular-5U4OPH2X.ttf +0 -0
- package/dist/KaTeX_Fraktur-Regular-PQMHCIK6.woff +0 -0
- package/dist/KaTeX_Main-Bold-2GA4IZIN.woff +0 -0
- package/dist/KaTeX_Main-Bold-W5FBVCZM.ttf +0 -0
- package/dist/KaTeX_Main-Bold-YP5VVQRP.woff2 +0 -0
- package/dist/KaTeX_Main-BoldItalic-4P4C7HJH.woff +0 -0
- package/dist/KaTeX_Main-BoldItalic-N4V3DX7S.woff2 +0 -0
- package/dist/KaTeX_Main-BoldItalic-ODMLBJJQ.ttf +0 -0
- package/dist/KaTeX_Main-Italic-I43T2HSR.ttf +0 -0
- package/dist/KaTeX_Main-Italic-RELBIK7M.woff2 +0 -0
- package/dist/KaTeX_Main-Italic-SASNQFN2.woff +0 -0
- package/dist/KaTeX_Main-Regular-ARRPAO67.woff2 +0 -0
- package/dist/KaTeX_Main-Regular-P5I74A2A.woff +0 -0
- package/dist/KaTeX_Main-Regular-W74P5G27.ttf +0 -0
- package/dist/KaTeX_Math-BoldItalic-6EBV3DK5.woff +0 -0
- package/dist/KaTeX_Math-BoldItalic-K4WTGH3J.woff2 +0 -0
- package/dist/KaTeX_Math-BoldItalic-VB447A4D.ttf +0 -0
- package/dist/KaTeX_Math-Italic-6KGCHLFN.woff2 +0 -0
- package/dist/KaTeX_Math-Italic-KKK3USB2.woff +0 -0
- package/dist/KaTeX_Math-Italic-SON4MRCA.ttf +0 -0
- package/dist/KaTeX_SansSerif-Bold-RRNVJFFW.woff2 +0 -0
- package/dist/KaTeX_SansSerif-Bold-STQ6RXC7.ttf +0 -0
- package/dist/KaTeX_SansSerif-Bold-X5M5EMOD.woff +0 -0
- package/dist/KaTeX_SansSerif-Italic-HMPFTM52.woff2 +0 -0
- package/dist/KaTeX_SansSerif-Italic-PSN4QKYX.woff +0 -0
- package/dist/KaTeX_SansSerif-Italic-WTBAZBGY.ttf +0 -0
- package/dist/KaTeX_SansSerif-Regular-2TL3USAE.ttf +0 -0
- package/dist/KaTeX_SansSerif-Regular-OQCII6EP.woff +0 -0
- package/dist/KaTeX_SansSerif-Regular-XIQ62X4E.woff2 +0 -0
- package/dist/KaTeX_Script-Regular-72OLXYNA.ttf +0 -0
- package/dist/KaTeX_Script-Regular-A5IFOEBS.woff +0 -0
- package/dist/KaTeX_Script-Regular-APUWIHLP.woff2 +0 -0
- package/dist/KaTeX_Size1-Regular-4HRHTS65.woff +0 -0
- package/dist/KaTeX_Size1-Regular-5LRUTBFT.woff2 +0 -0
- package/dist/KaTeX_Size1-Regular-7K6AASVL.ttf +0 -0
- package/dist/KaTeX_Size2-Regular-222HN3GT.ttf +0 -0
- package/dist/KaTeX_Size2-Regular-K5ZHAIS6.woff +0 -0
- package/dist/KaTeX_Size2-Regular-LELKET5D.woff2 +0 -0
- package/dist/KaTeX_Size3-Regular-TLFPAHDE.woff +0 -0
- package/dist/KaTeX_Size3-Regular-UFCO6WCA.ttf +0 -0
- package/dist/KaTeX_Size3-Regular-WQRQ47UD.woff2 +0 -0
- package/dist/KaTeX_Size4-Regular-7PGNVPQK.ttf +0 -0
- package/dist/KaTeX_Size4-Regular-CDMV7U5C.woff2 +0 -0
- package/dist/KaTeX_Size4-Regular-PKMWZHNC.woff +0 -0
- package/dist/KaTeX_Typewriter-Regular-3F5K6SQ6.ttf +0 -0
- package/dist/KaTeX_Typewriter-Regular-MJMFSK64.woff +0 -0
- package/dist/KaTeX_Typewriter-Regular-VBYJ4NRC.woff2 +0 -0
- package/dist/KernelEngineContext-CcxGYtlr.d.ts +33 -0
- package/dist/LayersPanel-M2LHWUFF.js +6 -0
- package/dist/ModuleCard-QHDGK5XK.js +7 -0
- package/dist/OrbInspector-MHLJ6OEE.css +1756 -0
- package/dist/OrbInspector-QCPEPUPH.js +26 -0
- package/dist/Select-B-iDdnvE.d.ts +185 -0
- package/dist/ServerBridge-Bqsj-lOU.d.ts +124 -0
- package/dist/ThemeContext-DJmO59xd.d.ts +147 -0
- package/dist/UISlotContext-Dl_ewwCI.d.ts +79 -0
- package/dist/UISlotRenderer-C7WWOK43.js +26 -0
- package/dist/UISlotRenderer-KVFO6J7R.css +1756 -0
- package/dist/auth/browser/index.d.ts +2 -0
- package/dist/auth/browser/index.js +2 -0
- package/dist/auth/react/index.d.ts +56 -0
- package/dist/auth/react/index.js +157 -0
- package/dist/avl/index.css +1756 -0
- package/dist/avl/index.d.ts +2248 -0
- package/dist/avl/index.js +2693 -0
- package/dist/avl-3d-context-BycmO6tG.d.ts +201 -0
- package/dist/avl-schema-parser-CtJxJ9KU.d.ts +132 -0
- package/dist/avl-zoom-state-CKMVuBFg.d.ts +17 -0
- package/dist/chunk-3BBUBJFF.js +339 -0
- package/dist/chunk-3S54FWRC.js +131 -0
- package/dist/chunk-3VZ36ZKO.js +775 -0
- package/dist/chunk-4T3P43NS.js +1133 -0
- package/dist/chunk-4YXBKHHM.js +11488 -0
- package/dist/chunk-57DC34LY.js +525 -0
- package/dist/chunk-5QTYQTPS.js +15 -0
- package/dist/chunk-A2LR6VQQ.js +349 -0
- package/dist/chunk-AB3X7QTE.js +505 -0
- package/dist/chunk-AE7VCQB6.js +561 -0
- package/dist/chunk-AGXD77SL.js +98 -0
- package/dist/chunk-AU7O65OX.js +66 -0
- package/dist/chunk-CPLN6NBQ.js +701 -0
- package/dist/chunk-DZBQA2OW.js +176 -0
- package/dist/chunk-E6KA4J6N.js +227 -0
- package/dist/chunk-EOWMARUB.js +16 -0
- package/dist/chunk-G7DCAZ22.js +19 -0
- package/dist/chunk-GFXCPUMX.js +1334 -0
- package/dist/chunk-HH5KSMH5.js +311 -0
- package/dist/chunk-ILQXJ2AR.js +280 -0
- package/dist/chunk-ILZ7ORX7.js +432 -0
- package/dist/chunk-K4MOPSEL.js +674 -0
- package/dist/chunk-LHP2TK7O.js +47587 -0
- package/dist/chunk-P4ZFUQFF.js +93 -0
- package/dist/chunk-PCR37T3U.js +296 -0
- package/dist/chunk-PRXQGGCO.js +580 -0
- package/dist/chunk-REXYVBUO.js +191 -0
- package/dist/chunk-ROICKAU7.js +24 -0
- package/dist/chunk-SP5CDJ6K.js +338 -0
- package/dist/chunk-TUPZWTRE.js +1051 -0
- package/dist/chunk-TXAUOLWZ.js +490 -0
- package/dist/chunk-TZZBINQY.js +82 -0
- package/dist/chunk-UTDC2NEA.js +14 -0
- package/dist/chunk-UU57VNS2.js +1053 -0
- package/dist/chunk-UXLE3IPR.js +421 -0
- package/dist/chunk-VO2TTLS5.js +94 -0
- package/dist/chunk-X3DMMX27.js +11 -0
- package/dist/chunk-YHMRX6YA.js +455 -0
- package/dist/components/index.css +1756 -0
- package/dist/components/index.d.ts +11299 -0
- package/dist/components/index.js +1110 -0
- package/dist/context/index.d.ts +8 -0
- package/dist/context/index.js +8 -0
- package/dist/core.d.ts +2599 -0
- package/dist/core.js +3 -0
- package/dist/design-classes/index.cjs +431 -0
- package/dist/design-classes/index.d.cts +165 -0
- package/dist/design-classes/index.d.ts +165 -0
- package/dist/design-classes/index.js +399 -0
- package/dist/emojiItems-QGSNAABW.js +20 -0
- package/dist/fx-CmQjnHmT.d.ts +371 -0
- package/dist/hooks/index.d.ts +971 -0
- package/dist/hooks/index.js +8 -0
- package/dist/index.d.ts +408 -0
- package/dist/index.js +178 -0
- package/dist/katexPlugin-FA7NX4PE.css +1161 -0
- package/dist/katexPlugin-NCDKOOQY.js +2 -0
- package/dist/kernel-client-TZKGHJRY.js +516 -0
- package/dist/kernel-wire-wNdAPfhJ.d.ts +88 -0
- package/dist/lib/index.d.ts +602 -0
- package/dist/lib/index.js +1289 -0
- package/dist/paintDispatch-CuJLsr9Y.d.ts +688 -0
- package/dist/parseLessonSegments-GpCeMrb2.d.ts +334 -0
- package/dist/perf-CKiBKbkw.d.ts +22 -0
- package/dist/perf-Dr28-AgT.d.ts +57 -0
- package/dist/prism-X5YWKXO5.js +136 -0
- package/dist/providers/index.css +1756 -0
- package/dist/providers/index.d.ts +355 -0
- package/dist/providers/index.js +29 -0
- package/dist/renderer/index.d.ts +465 -0
- package/dist/renderer/index.js +4 -0
- package/dist/runtime/index.css +1756 -0
- package/dist/runtime/index.d.ts +239 -0
- package/dist/runtime/index.js +28 -0
- package/dist/slot-host-CPzrxLo9.d.ts +48 -0
- package/dist/ssr/index.cjs +9739 -0
- package/dist/ssr/index.d.cts +464 -0
- package/dist/ssr/index.d.ts +464 -0
- package/dist/ssr/index.js +9703 -0
- package/dist/storage/browser/index.d.ts +1 -0
- package/dist/storage/browser/index.js +2 -0
- package/dist/test-support.d.ts +42 -0
- package/dist/test-support.js +181 -0
- package/dist/themeTokens-CRd8AEDF.d.ts +125 -0
- package/dist/three/index.css +503 -0
- package/dist/three/index.d.ts +1185 -0
- package/dist/three/index.js +3908 -0
- package/dist/useUISlots-CiobNFGb.d.ts +211 -0
- package/dist/verification-C5pTeMJv.d.ts +66 -0
- package/dist/verificationRegistry-CVrcxG1s.d.ts +122 -0
- package/dist/wrapCallbackForEvent-B9QLbhxX.d.ts +19 -0
- package/index.css +199 -0
- package/package.json +273 -3
- package/src/core/lib/band-shapes.json +7 -0
- package/src/core/locales/ar.json +1276 -0
- package/src/core/locales/en.json +1276 -0
- package/src/core/locales/index.ts +54 -0
- package/src/core/locales/sl.json +1276 -0
- package/src/core/tokens/native-tokens.json +369 -0
- package/tailwind-compile.cjs +29 -0
- package/tailwind-preset.cjs +1020 -0
- package/themes/_base.css +451 -0
- package/themes/_contract.md +307 -0
- package/themes/_fonts-kenney.css +11 -0
- package/themes/_fonts.css +12 -0
- package/themes/_foundation.css +105 -0
- package/themes/_head.css +22 -0
- package/themes/_presets.css +67 -0
- package/themes/almadar-heritage.css +455 -0
- package/themes/almadar-website.css +269 -0
- package/themes/almadar.css +269 -0
- package/themes/aqua.css +455 -0
- package/themes/arabesque.css +459 -0
- package/themes/art-deco.css +457 -0
- package/themes/art-nouveau.css +459 -0
- package/themes/atelier.css +463 -0
- package/themes/bauhaus.css +461 -0
- package/themes/bloomberg-dense.css +463 -0
- package/themes/blueprint.css +457 -0
- package/themes/clay.css +449 -0
- package/themes/comic.css +453 -0
- package/themes/constructivist.css +457 -0
- package/themes/corporate.css +449 -0
- package/themes/cyberpunk.css +453 -0
- package/themes/frutiger-aero.css +458 -0
- package/themes/game-adventure.css +201 -0
- package/themes/game-rpg.css +203 -0
- package/themes/game-sci-fi.css +201 -0
- package/themes/game-ui-pack.css +200 -0
- package/themes/gazette.css +449 -0
- package/themes/glass.css +457 -0
- package/themes/gothic.css +453 -0
- package/themes/index.css +21 -0
- package/themes/ink-wash.css +459 -0
- package/themes/kawaii.css +459 -0
- package/themes/kflow.css +310 -0
- package/themes/kiosk.css +449 -0
- package/themes/linear-clean.css +463 -0
- package/themes/luxury.css +451 -0
- package/themes/mac-classic.css +455 -0
- package/themes/material.css +463 -0
- package/themes/memphis.css +453 -0
- package/themes/mid-century.css +455 -0
- package/themes/minimalist.css +449 -0
- package/themes/mudcloth.css +459 -0
- package/themes/nata.css +310 -0
- package/themes/neon.css +453 -0
- package/themes/neumorphic.css +451 -0
- package/themes/newsprint.css +455 -0
- package/themes/notion-editorial.css +463 -0
- package/themes/orb.css +465 -0
- package/themes/pixel.css +449 -0
- package/themes/prism.css +309 -0
- package/themes/rawi.css +310 -0
- package/themes/retro.css +452 -0
- package/themes/risograph.css +463 -0
- package/themes/scandi.css +469 -0
- package/themes/sketch.css +455 -0
- package/themes/solarpunk.css +469 -0
- package/themes/steampunk.css +451 -0
- package/themes/swiss.css +455 -0
- package/themes/terminal.css +466 -0
- package/themes/trait-wars.css +487 -0
- package/themes/ukiyo-e.css +459 -0
- package/themes/vaporwave.css +455 -0
- package/themes/victorian.css +453 -0
- package/themes/wabi-sabi.css +459 -0
- package/themes/win95.css +455 -0
- package/themes/wireframe.css +439 -0
- package/themes/zine.css +455 -0
- package/README.md +0 -3
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { UISlot, RenderItemLambda, EventPayloadValue, RowSetMarker } from '@almadar/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* useUISlots Hook
|
|
6
|
+
*
|
|
7
|
+
* Core hook for managing UI slot rendering in the trait-driven architecture.
|
|
8
|
+
* Traits use render_ui effects to dynamically render content into slots.
|
|
9
|
+
*
|
|
10
|
+
* Slots:
|
|
11
|
+
* - main: Primary content area
|
|
12
|
+
* - sidebar: Left/right sidebar
|
|
13
|
+
* - modal: Modal overlay
|
|
14
|
+
* - drawer: Slide-in drawer
|
|
15
|
+
* - overlay: Full-screen overlay
|
|
16
|
+
* - center: Centered popup
|
|
17
|
+
* - toast: Toast notifications
|
|
18
|
+
* - hud-top: Game HUD top bar
|
|
19
|
+
* - hud-bottom: Game HUD bottom bar
|
|
20
|
+
* - floating: Draggable floating panel
|
|
21
|
+
*
|
|
22
|
+
* Multi-source model (2026-04-24):
|
|
23
|
+
* A slot can receive renders from multiple source traits across independent
|
|
24
|
+
* batches (e.g. in the playground, ProbeCreate renders "main" on INIT, then
|
|
25
|
+
* later ProbePersistor cascades a render into "main" too). Prior code stored
|
|
26
|
+
* a single SlotContent per slot and last-writer-wins silently dropped
|
|
27
|
+
* earlier traits' frames. Internally the manager now holds a
|
|
28
|
+
* `Record<UISlot, Record<sourceKey, SlotContent>>` map and consumers see an
|
|
29
|
+
* aggregated view: a single SlotContent for single-source slots, or a
|
|
30
|
+
* synthetic `stack` wrapper when 2+ sources are active simultaneously.
|
|
31
|
+
* This mirrors the compiled-path page layout's VStack-of-trait-views.
|
|
32
|
+
*
|
|
33
|
+
* @packageDocumentation
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Render-prop callback after fn-form-lambda conversion or
|
|
38
|
+
* `wrapCallbackForEvent` wrapping. Pattern components consume these as
|
|
39
|
+
* `renderItem` / `onTabChange` / `onClick` / etc. The arg list is
|
|
40
|
+
* contravariant (`never[]` accepts any caller shape — event handlers,
|
|
41
|
+
* 2-arg `(item, index)` render-props, etc.); the return is the union of
|
|
42
|
+
* shapes seen at this layer. Pattern-level prop types narrow the
|
|
43
|
+
* signature for each consumer downstream.
|
|
44
|
+
*/
|
|
45
|
+
type SlotCallback = (...args: never[]) => void | React__default.ReactNode | EventPayloadValue;
|
|
46
|
+
/**
|
|
47
|
+
* Render-ui prop value: any leaf flowing from a `(render-ui slot {...})`
|
|
48
|
+
* effect into a React pattern component. The union enumerates every
|
|
49
|
+
* shape the renderer can receive — no `unknown` escape hatch.
|
|
50
|
+
*
|
|
51
|
+
* - JSON primitives (`string`, `number`, `boolean`, `Date`, `null`,
|
|
52
|
+
* `undefined`) come through `BindingResolver`.
|
|
53
|
+
* - `RenderItemLambda` is the unconverted tuple form `["fn", arg, body]`;
|
|
54
|
+
* `SlotCallback` is the post-conversion callable form.
|
|
55
|
+
* - `React.ReactNode` covers substituted `<TraitFrame>` elements.
|
|
56
|
+
* - The recursive array + object branches mirror the `EventPayloadValue`
|
|
57
|
+
* shape but with `SlotPropValue` leaves so functions and React nodes
|
|
58
|
+
* can appear at any depth (e.g. `tabs[].content: "@trait.X"` surviving
|
|
59
|
+
* substitution into a `ReactElement`).
|
|
60
|
+
*/
|
|
61
|
+
type SlotPropValue = string | number | boolean | Date | null | undefined | RenderItemLambda | SlotCallback | React__default.ReactElement | RowSetMarker | ReadonlyArray<SlotPropValue> | {
|
|
62
|
+
readonly [key: string]: SlotPropValue;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Pattern-specific props carried by a rendered slot. The slot manager
|
|
66
|
+
* routes these from `(render-ui slot {...})` effects to React pattern
|
|
67
|
+
* components without coercion.
|
|
68
|
+
*/
|
|
69
|
+
type SlotProps = Record<string, SlotPropValue>;
|
|
70
|
+
/**
|
|
71
|
+
* Content rendered in a slot
|
|
72
|
+
*/
|
|
73
|
+
interface SlotContent {
|
|
74
|
+
/** Unique ID for this content */
|
|
75
|
+
id: string;
|
|
76
|
+
/** Pattern/component type to render */
|
|
77
|
+
pattern: string;
|
|
78
|
+
/** Props to pass to the pattern component. A bare string is a whole-slot
|
|
79
|
+
* trait-embed reference (`(render-ui main "@trait.X")`) — the renderer lifts
|
|
80
|
+
* it to a TraitFrame. */
|
|
81
|
+
props: SlotProps | string;
|
|
82
|
+
/** Priority for conflict resolution (higher wins) */
|
|
83
|
+
priority: number;
|
|
84
|
+
/** Auto-dismiss timestamp (for toasts) */
|
|
85
|
+
autoDismissAt?: number;
|
|
86
|
+
/** Callback when dismissed */
|
|
87
|
+
onDismiss?: () => void;
|
|
88
|
+
/** Source trait that rendered this content */
|
|
89
|
+
sourceTrait?: string;
|
|
90
|
+
/** Stable node ID from the schema pattern tree (for edit mode overlay targeting) */
|
|
91
|
+
nodeId?: string;
|
|
92
|
+
/** Slot this content was rendered into (= SlotRenderConfig.target) — contextual-edit address. */
|
|
93
|
+
slot?: string;
|
|
94
|
+
/** Transition event key that produced this render (raw, as fired). */
|
|
95
|
+
transitionEvent?: string;
|
|
96
|
+
/** State the trait was in when this render fired (the from-state). */
|
|
97
|
+
fromState?: string;
|
|
98
|
+
/** linkedEntity of the source trait — contextual-edit address. */
|
|
99
|
+
entity?: string;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Configuration for render_ui effect
|
|
103
|
+
*/
|
|
104
|
+
interface SlotRenderConfig {
|
|
105
|
+
/** Target slot */
|
|
106
|
+
target: UISlot;
|
|
107
|
+
/** Pattern/component to render */
|
|
108
|
+
pattern: string;
|
|
109
|
+
/** Props for the pattern — or a bare `@trait.X` embed string */
|
|
110
|
+
props?: SlotProps | string;
|
|
111
|
+
/** Priority (default: 0) */
|
|
112
|
+
priority?: number;
|
|
113
|
+
/** Auto-dismiss after ms (for toasts) */
|
|
114
|
+
autoDismissMs?: number;
|
|
115
|
+
/** Callback on dismiss */
|
|
116
|
+
onDismiss?: () => void;
|
|
117
|
+
/** Source trait name */
|
|
118
|
+
sourceTrait?: string;
|
|
119
|
+
/** Transition event key that produced this render (raw, as fired). */
|
|
120
|
+
transitionEvent?: string;
|
|
121
|
+
/** State the trait was in when this render fired (the from-state). */
|
|
122
|
+
fromState?: string;
|
|
123
|
+
/** linkedEntity of the source trait. */
|
|
124
|
+
entity?: string;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Callback for slot changes
|
|
128
|
+
*/
|
|
129
|
+
type SlotChangeCallback = (slot: UISlot, content: SlotContent | null) => void;
|
|
130
|
+
/**
|
|
131
|
+
* Fires when a specific trait's current render-ui output changes.
|
|
132
|
+
* Used by `<TraitFrame>` to subscribe only to the trait it embeds,
|
|
133
|
+
* avoiding wide re-renders when unrelated slots update.
|
|
134
|
+
*
|
|
135
|
+
* Per-trait index stores exactly one entry per trait (the most recent
|
|
136
|
+
* render), so the callback signature carries just the new content —
|
|
137
|
+
* no per-slot disambiguation needed.
|
|
138
|
+
*/
|
|
139
|
+
type TraitChangeCallback = (content: SlotContent | null) => void;
|
|
140
|
+
/**
|
|
141
|
+
* UI Slot Manager interface
|
|
142
|
+
*/
|
|
143
|
+
interface UISlotManager {
|
|
144
|
+
/**
|
|
145
|
+
* Current aggregate content for each slot. Single-source slots hold
|
|
146
|
+
* that source's SlotContent; multi-source slots hold a synthetic
|
|
147
|
+
* `stack` wrapper whose `children` prop is the list of per-source
|
|
148
|
+
* pattern configs in insertion order. Single consumers can continue
|
|
149
|
+
* to read `slots[slot]` without knowing the slot is multi-source.
|
|
150
|
+
*/
|
|
151
|
+
slots: Partial<Record<UISlot, SlotContent | null>>;
|
|
152
|
+
/** Render content to a slot */
|
|
153
|
+
render: (config: SlotRenderConfig) => string;
|
|
154
|
+
/** Clear all source entries from a slot */
|
|
155
|
+
clear: (slot: UISlot) => void;
|
|
156
|
+
/** Clear a single source's contribution from a slot, keeping others */
|
|
157
|
+
clearBySource: (slot: UISlot, sourceTrait: string) => void;
|
|
158
|
+
/** Clear content by ID */
|
|
159
|
+
clearById: (id: string) => void;
|
|
160
|
+
/** Clear all slots */
|
|
161
|
+
clearAll: () => void;
|
|
162
|
+
/** Subscribe to slot changes */
|
|
163
|
+
subscribe: (callback: SlotChangeCallback) => () => void;
|
|
164
|
+
/** Check if a slot has content */
|
|
165
|
+
hasContent: (slot: UISlot) => boolean;
|
|
166
|
+
/** Get aggregated content for a slot (single or synthetic stack) */
|
|
167
|
+
getContent: (slot: UISlot) => SlotContent | null;
|
|
168
|
+
/**
|
|
169
|
+
* Look up the most recent `render-ui` output a given trait produced,
|
|
170
|
+
* keyed by `SlotContent.sourceTrait`. Returns `null` when the trait
|
|
171
|
+
* hasn't rendered yet.
|
|
172
|
+
*
|
|
173
|
+
* Backs the `@trait.X` binding's client-side resolution via
|
|
174
|
+
* `<TraitFrame>`. See `docs/Almadar_Std_Gaps.md` §3.8. The binding is
|
|
175
|
+
* single-segment — there's intentionally no slot disambiguation.
|
|
176
|
+
*/
|
|
177
|
+
getTraitContent: (traitName: string) => SlotContent | null;
|
|
178
|
+
/**
|
|
179
|
+
* Subscribe to changes in a specific trait's render output. Returns
|
|
180
|
+
* an unsubscribe function.
|
|
181
|
+
*
|
|
182
|
+
* Scoped per-trait so `<TraitFrame>` components only re-render when
|
|
183
|
+
* the trait they embed actually changes — not on every slot update.
|
|
184
|
+
*/
|
|
185
|
+
subscribeTrait: (traitName: string, callback: TraitChangeCallback) => () => void;
|
|
186
|
+
/**
|
|
187
|
+
* Update only the per-trait sidecar without writing to any slot.
|
|
188
|
+
*
|
|
189
|
+
* Used for embed-aware slot routing: when a trait is referenced via
|
|
190
|
+
* `@trait.X` by a sibling layout's render-ui, its render output should
|
|
191
|
+
* not stack into the same slot the layout writes — the layout owns the
|
|
192
|
+
* slot and embeds the trait's frame via `<TraitFrame>`. This method
|
|
193
|
+
* keeps the per-trait sidecar (`traitIndexRef`) up-to-date so
|
|
194
|
+
* `<TraitFrame>` re-renders, while leaving `slots[target]` untouched.
|
|
195
|
+
*
|
|
196
|
+
* Mirrors what the compiled-path codegen does structurally — atoms
|
|
197
|
+
* inlined as JSX inside the layout's pattern, not writing slots.
|
|
198
|
+
*/
|
|
199
|
+
updateTraitContent: (traitName: string, content: Omit<SlotContent, 'id' | 'sourceTrait'>) => string;
|
|
200
|
+
}
|
|
201
|
+
declare const DEFAULT_SLOTS: Partial<Record<UISlot, SlotContent | null>>;
|
|
202
|
+
/**
|
|
203
|
+
* Create a UI Slot Manager instance.
|
|
204
|
+
*
|
|
205
|
+
* This is the internal hook that creates the manager.
|
|
206
|
+
* Use `useUISlots()` from context in components.
|
|
207
|
+
*/
|
|
208
|
+
declare function useUISlotManager(): UISlotManager;
|
|
209
|
+
|
|
210
|
+
export { DEFAULT_SLOTS as D, useUISlotManager as u };
|
|
211
|
+
export type { SlotChangeCallback as S, UISlotManager as U, SlotContent as a, SlotRenderConfig as b, SlotPropValue as c };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { OrbitalVerificationAPI, EventPayload, BusEvent } from '@almadar/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Renderer-agnostic `window.__orbitalVerification` bridge.
|
|
5
|
+
*
|
|
6
|
+
* The single observation point Playwright-based verifiers
|
|
7
|
+
* (`runtime-verify`, `orbital-verify`, `@almadar-io/verify`) use to read
|
|
8
|
+
* state out of a live app and drive events into it. The wire types live
|
|
9
|
+
* in `@almadar/core` (see `types/verification.ts`); this module owns only
|
|
10
|
+
* the minimal exposure plumbing so any UI library — React, Web
|
|
11
|
+
* Components, or a future renderer — can populate the same contract
|
|
12
|
+
* without duplicating it.
|
|
13
|
+
*
|
|
14
|
+
* Framework-specific state (transition traces, reducer snapshots, bridge
|
|
15
|
+
* health) is left empty by default; a renderer that tracks them can
|
|
16
|
+
* override the readers after {@link ensureVerificationApi} runs. The two
|
|
17
|
+
* bindings every renderer must provide are {@link bindEventBus} (so
|
|
18
|
+
* automation can `sendEvent`) and {@link bindTraitStateGetter} (so
|
|
19
|
+
* automation can `getTraitState`).
|
|
20
|
+
*
|
|
21
|
+
* @packageDocumentation
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
declare global {
|
|
25
|
+
interface Window {
|
|
26
|
+
__orbitalVerification?: OrbitalVerificationAPI;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Minimal structural surface a renderer's event bus must satisfy to be
|
|
31
|
+
* driven by automation. Matches the runtime `EventBus` (`emit` +
|
|
32
|
+
* optional `onAny`) without forcing a concrete class, so any UI
|
|
33
|
+
* library's bus — including `@almadar/runtime`'s own — plugs in.
|
|
34
|
+
*/
|
|
35
|
+
interface VerificationBus {
|
|
36
|
+
emit: (type: string, payload?: EventPayload) => void;
|
|
37
|
+
onAny?: (listener: (event: BusEvent) => void) => () => void;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Ensure `window.__orbitalVerification` exists with the required
|
|
41
|
+
* readers, then return it. Returns `undefined` outside a DOM (SSR /
|
|
42
|
+
* tests without a window). Idempotent: an existing object is returned
|
|
43
|
+
* untouched so a renderer that already registered readers keeps them.
|
|
44
|
+
*/
|
|
45
|
+
declare function ensureVerificationApi(): OrbitalVerificationAPI | undefined;
|
|
46
|
+
/** Read the current bridge, if any. SSR-safe. */
|
|
47
|
+
declare function getOrbitalVerification(): OrbitalVerificationAPI | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Bind the renderer's event bus so automation can send events and read
|
|
50
|
+
* a rolling emission log.
|
|
51
|
+
*
|
|
52
|
+
* `sendEvent(event, payload, traitScope)` mirrors the React bridge:
|
|
53
|
+
* when `traitScope` is provided the event is emitted on the qualified
|
|
54
|
+
* key `UI:${traitScope}.${event}` (matching codegen-emitted
|
|
55
|
+
* subscription keys); otherwise the legacy bare form `UI:${event}` is
|
|
56
|
+
* used. An already-`UI:`-prefixed event is emitted verbatim.
|
|
57
|
+
*/
|
|
58
|
+
declare function bindEventBus(eventBus: VerificationBus): void;
|
|
59
|
+
/**
|
|
60
|
+
* Bind a trait-state getter so automation can query a trait's current
|
|
61
|
+
* state machine state by name.
|
|
62
|
+
*/
|
|
63
|
+
declare function bindTraitStateGetter(getter: (traitName: string) => string | undefined): void;
|
|
64
|
+
|
|
65
|
+
export { bindTraitStateGetter as a, bindEventBus as b, ensureVerificationApi as e, getOrbitalVerification as g };
|
|
66
|
+
export type { VerificationBus as V };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { D as DrawableNode } from './paintDispatch-CuJLsr9Y.js';
|
|
2
|
+
import { OrbitalVerificationAPI, TraitStateSnapshot, EventPayload, BusEvent, VerificationCheck, BridgeHealth, VerificationSnapshot, VerificationSummary, TransitionTrace, EventRequest, EventResponse, ServerResponseTrace, EffectTrace, CheckStatus, ServerEffectResult, AssetLoadStatus } from '@almadar/core';
|
|
3
|
+
import { EventTransport } from '@almadar/shell-runtime/client/EventTransport';
|
|
4
|
+
import './verification-C5pTeMJv.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Verification Registry - Tracks runtime verification checks and transition traces
|
|
8
|
+
*
|
|
9
|
+
* Provides:
|
|
10
|
+
* 1. A checklist of pass/fail checks (INIT has fetch, bridge connected, etc.)
|
|
11
|
+
* 2. A full transition timeline with effect execution results
|
|
12
|
+
* 3. ServerBridge health snapshot
|
|
13
|
+
* 4. window.__orbitalVerification for Playwright/automation
|
|
14
|
+
*
|
|
15
|
+
* @packageDocumentation
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
type ChangeListener = () => void;
|
|
19
|
+
/**
|
|
20
|
+
* Per-trait snapshot getter. Each generated trait logic hook (or
|
|
21
|
+
* `useTraitStateMachine` trait binding) registers one on mount so the
|
|
22
|
+
* verifier can read the live reducer state for that trait.
|
|
23
|
+
*/
|
|
24
|
+
type TraitSnapshotGetter = () => TraitStateSnapshot;
|
|
25
|
+
declare function registerCheck(id: string, label: string, status?: CheckStatus, details?: string): void;
|
|
26
|
+
declare function updateCheck(id: string, status: CheckStatus, details?: string): void;
|
|
27
|
+
declare function getAllChecks(): VerificationCheck[];
|
|
28
|
+
declare function recordTransition(trace: Omit<TransitionTrace, "id">): void;
|
|
29
|
+
declare function getTransitions(): TransitionTrace[];
|
|
30
|
+
declare function getTransitionsForTrait(traitName: string): TransitionTrace[];
|
|
31
|
+
/**
|
|
32
|
+
* Record a server response as a timeline entry.
|
|
33
|
+
* Creates a synthetic transition entry with type "server-response" to show
|
|
34
|
+
* what the server returned (clientEffects, data counts, emitted events).
|
|
35
|
+
*
|
|
36
|
+
* `effectResults` — the server's persist/set/call-service outcomes, already
|
|
37
|
+
* mapped to `EffectTrace` by the caller — populate `entry.effects` so a
|
|
38
|
+
* denied or failed persist is visible on this synthetic entry too. Before
|
|
39
|
+
* this it was always `[]`: the ONLY entry the driver's per-event
|
|
40
|
+
* `server:<orbital>` lookup (`default-snapshot.ts`'s `lastEffectResultsFor`)
|
|
41
|
+
* can find carried nothing.
|
|
42
|
+
*/
|
|
43
|
+
declare function recordServerResponse(orbitalName: string, event: string, response: Omit<ServerResponseTrace, "orbitalName" | "timestamp"> & {
|
|
44
|
+
effectResults?: EffectTrace[];
|
|
45
|
+
}): void;
|
|
46
|
+
/** A server response's `effectResults` as timeline traces, carrying each persist's real outcome (entity, action, resulting id, denied). */
|
|
47
|
+
declare function serverEffectTraces(results: readonly ServerEffectResult[] | undefined): EffectTrace[];
|
|
48
|
+
/** Record one answered server leg on the timeline as a `server:<orbital>` trace. */
|
|
49
|
+
declare function recordOrbitalResponse(orbitalName: string, request: EventRequest, response: EventResponse): void;
|
|
50
|
+
/** `transport` with every answered post recorded on the verification timeline; the one place the circuit client's server responses are captured. */
|
|
51
|
+
declare function recordingTransport(transport: EventTransport): EventTransport;
|
|
52
|
+
declare function updateBridgeHealth(health: BridgeHealth): void;
|
|
53
|
+
declare function getBridgeHealth(): BridgeHealth | null;
|
|
54
|
+
declare function getSummary(): VerificationSummary;
|
|
55
|
+
declare function getSnapshot(): VerificationSnapshot;
|
|
56
|
+
/**
|
|
57
|
+
* Per-trait snapshot for the verifier.
|
|
58
|
+
*
|
|
59
|
+
* Iterates every registered trait getter and collects the live reducer
|
|
60
|
+
* state. Empty until at least one trait hook calls `registerTraitSnapshot`.
|
|
61
|
+
* A getter that throws is logged and skipped — one broken trait must not
|
|
62
|
+
* poison the rest of the snapshot.
|
|
63
|
+
*/
|
|
64
|
+
declare function getTraitSnapshots(): TraitStateSnapshot[];
|
|
65
|
+
declare function subscribeToVerification(listener: ChangeListener): () => void;
|
|
66
|
+
declare global {
|
|
67
|
+
interface Window {
|
|
68
|
+
__orbitalVerification?: OrbitalVerificationAPI;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** Whether a verifier is driving this page: the `__ALMADAR_VERIFY__` window flag it sets before the bundle runs. */
|
|
72
|
+
declare function verifierAttached(): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Wait for a transition matching the given event to appear.
|
|
75
|
+
* Returns the trace or null on timeout.
|
|
76
|
+
*/
|
|
77
|
+
declare function waitForTransition(event: string, timeoutMs?: number): Promise<TransitionTrace | null>;
|
|
78
|
+
/**
|
|
79
|
+
* Bind the EventBus so automation can send events and log emissions.
|
|
80
|
+
* Call this during app initialization.
|
|
81
|
+
*/
|
|
82
|
+
declare function bindEventBus(eventBus: {
|
|
83
|
+
emit: (type: string, payload?: EventPayload) => void;
|
|
84
|
+
onAny?: (listener: (event: BusEvent) => void) => () => void;
|
|
85
|
+
}): void;
|
|
86
|
+
declare function bindConfigApplier(applyConfig: NonNullable<OrbitalVerificationAPI['applyConfig']>): () => void;
|
|
87
|
+
/**
|
|
88
|
+
* Bind a trait state getter so automation can query current states.
|
|
89
|
+
*/
|
|
90
|
+
declare function bindTraitStateGetter(getter: (traitName: string) => string | undefined): void;
|
|
91
|
+
/**
|
|
92
|
+
* Register a per-trait snapshot provider. The generated trait logic hook
|
|
93
|
+
* (or `useTraitStateMachine`) calls this once on mount, passing a getter
|
|
94
|
+
* that reads the current reducer state via a ref. Returns an unregister
|
|
95
|
+
* function for cleanup on unmount.
|
|
96
|
+
*
|
|
97
|
+
* Calling this twice for the same `traitName` replaces the previous
|
|
98
|
+
* getter (e.g. page navigation remounts the trait; the new registration
|
|
99
|
+
* wins).
|
|
100
|
+
*/
|
|
101
|
+
declare function registerTraitSnapshot(traitName: string, getter: TraitSnapshotGetter): () => void;
|
|
102
|
+
/**
|
|
103
|
+
* Register a canvas frame capture function.
|
|
104
|
+
* Called by game organisms (IsometricCanvas, PlatformerCanvas)
|
|
105
|
+
* so the verifier can snapshot canvas content at checkpoints.
|
|
106
|
+
*/
|
|
107
|
+
declare function bindCanvasCapture(captureFn: () => string | null): void;
|
|
108
|
+
/**
|
|
109
|
+
* Bind a reader for the last drawables list received by a canvas host.
|
|
110
|
+
* Lets verification scripts inspect exactly which neutral descriptors reached
|
|
111
|
+
* the painter without re-deriving them from state.
|
|
112
|
+
*/
|
|
113
|
+
declare function bindLastDrawables(getDrawables: () => DrawableNode[] | null): void;
|
|
114
|
+
/**
|
|
115
|
+
* Update asset load status for canvas verification.
|
|
116
|
+
* Game organisms call this when images load or fail.
|
|
117
|
+
*/
|
|
118
|
+
declare function updateAssetStatus(url: string, status: AssetLoadStatus): void;
|
|
119
|
+
declare function clearVerification(): void;
|
|
120
|
+
|
|
121
|
+
export { bindConfigApplier as a, bindCanvasCapture as b, bindEventBus as c, bindLastDrawables as d, bindTraitStateGetter as e, clearVerification as f, getAllChecks as g, getBridgeHealth as h, getSnapshot as i, getSummary as j, getTraitSnapshots as k, getTransitions as l, getTransitionsForTrait as m, recordServerResponse as n, recordTransition as o, recordingTransport as p, registerCheck as q, recordOrbitalResponse as r, registerTraitSnapshot as s, serverEffectTraces as t, subscribeToVerification as u, updateAssetStatus as v, updateBridgeHealth as w, updateCheck as x, verifierAttached as y, waitForTransition as z };
|
|
122
|
+
export type { TraitSnapshotGetter as T };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { PatternCallbackArg } from '@almadar/core/patterns';
|
|
2
|
+
import { EventPayload, EventPayloadValue } from '@almadar/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Build the runtime wrapper that turns a string-typed callback prop
|
|
6
|
+
* (e.g. `onTabChange: "TAB_CHANGED"`) into a function the component can
|
|
7
|
+
* invoke. The wrapper consumes the component's positional callback args
|
|
8
|
+
* by name and dispatches an OBJECT payload `{ argName: value, ... }` so
|
|
9
|
+
* the bus carries the trait's declared event payload, not a raw
|
|
10
|
+
* positional spread. Mirrors the codegen wrapper in
|
|
11
|
+
* `orbital-shell-typescript/src/codegen/pattern.rs` (C2 compiled path).
|
|
12
|
+
*
|
|
13
|
+
* Single-sourcing this logic across runtime and codegen (shared shape,
|
|
14
|
+
* not shared code — codegen emits string source) is what keeps the two
|
|
15
|
+
* paths from silently diverging on payload shape.
|
|
16
|
+
*/
|
|
17
|
+
declare function wrapCallbackForEvent(qualifiedEvent: string, callbackArgs: PatternCallbackArg[] | undefined, emit: (eventKey: string, payload?: EventPayload) => void): (...args: EventPayloadValue[]) => void;
|
|
18
|
+
|
|
19
|
+
export { wrapCallbackForEvent as w };
|
package/index.css
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Design System Styles
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/* Load Plus Jakarta Sans from Google Fonts (Track A: preferred UI font) */
|
|
6
|
+
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap');
|
|
7
|
+
|
|
8
|
+
/* React Flow's base styles (the canvas's node layering); ui's overrides below load after them. */
|
|
9
|
+
@import '@xyflow/react/dist/style.css';
|
|
10
|
+
|
|
11
|
+
@tailwind base;
|
|
12
|
+
@tailwind components;
|
|
13
|
+
@tailwind utilities;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Default fallback theme (minimalist-light — UI/UX improved per Track A eval)
|
|
17
|
+
* Applied when no data-theme attribute is set.
|
|
18
|
+
*/
|
|
19
|
+
:root:not([data-theme]) {
|
|
20
|
+
--shadow-main: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.06);
|
|
21
|
+
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
|
|
22
|
+
--shadow-lg: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
|
|
23
|
+
--shadow-inner: inset 0 1px 2px rgba(0, 0, 0, 0.05);
|
|
24
|
+
--shadow-none: none;
|
|
25
|
+
/* Track A: more pronounced hover lift for interactive cards */
|
|
26
|
+
--shadow-hover: 0 8px 30px -8px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.08);
|
|
27
|
+
--shadow-active: 0 1px 2px rgba(0, 0, 0, 0.05);
|
|
28
|
+
|
|
29
|
+
--radius-none: 0px;
|
|
30
|
+
--radius-sm: 6px;
|
|
31
|
+
/* Track A: bump radii from 8/12 → 10/14 for a more modern feel */
|
|
32
|
+
--radius-md: 10px;
|
|
33
|
+
--radius-lg: 14px;
|
|
34
|
+
--radius-xl: 18px;
|
|
35
|
+
--radius-full: 9999px;
|
|
36
|
+
|
|
37
|
+
--border-width: 1px;
|
|
38
|
+
--border-width-thin: 1px;
|
|
39
|
+
--border-width-thick: 2px;
|
|
40
|
+
|
|
41
|
+
--color-primary: #18181b;
|
|
42
|
+
--color-primary-hover: #27272a;
|
|
43
|
+
--color-primary-foreground: #fafafa;
|
|
44
|
+
--color-secondary: #fafafa;
|
|
45
|
+
--color-secondary-hover: #f4f4f5;
|
|
46
|
+
--color-secondary-foreground: #18181b;
|
|
47
|
+
--color-accent: #18181b;
|
|
48
|
+
--color-accent-foreground: #fafafa;
|
|
49
|
+
--color-muted: #f1f5f9;
|
|
50
|
+
/* Track A: slightly darker muted-foreground for legibility */
|
|
51
|
+
--color-muted-foreground: #64748b;
|
|
52
|
+
/* Track A: background ≠ card → natural surface elevation */
|
|
53
|
+
--color-background: #f8fafc;
|
|
54
|
+
--color-foreground: #0f172a;
|
|
55
|
+
--color-card: #ffffff;
|
|
56
|
+
--color-card-foreground: #0f172a;
|
|
57
|
+
--color-surface: #f1f5f9;
|
|
58
|
+
/* Track A: soften border — semi-transparent instead of solid gray */
|
|
59
|
+
--color-border: rgba(0, 0, 0, 0.08);
|
|
60
|
+
--color-input: #e2e8f0;
|
|
61
|
+
--color-ring: #18181b;
|
|
62
|
+
|
|
63
|
+
--color-error: #dc2626;
|
|
64
|
+
--color-error-foreground: #ffffff;
|
|
65
|
+
--color-success: #16a34a;
|
|
66
|
+
--color-success-foreground: #ffffff;
|
|
67
|
+
--color-warning: #ca8a04;
|
|
68
|
+
--color-warning-foreground: #000000;
|
|
69
|
+
--color-info: #2563eb;
|
|
70
|
+
--color-info-foreground: #ffffff;
|
|
71
|
+
|
|
72
|
+
/* Track A: Plus Jakarta Sans as first preference, Inter as fallback */
|
|
73
|
+
--font-family:
|
|
74
|
+
"Plus Jakarta Sans", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
75
|
+
--font-weight-normal: 400;
|
|
76
|
+
--font-weight-medium: 500;
|
|
77
|
+
--font-weight-bold: 600;
|
|
78
|
+
--letter-spacing: -0.015em;
|
|
79
|
+
--line-height: 1.6;
|
|
80
|
+
|
|
81
|
+
--icon-stroke-width: 1.5;
|
|
82
|
+
--icon-color: currentColor;
|
|
83
|
+
|
|
84
|
+
--transition-fast: 150ms;
|
|
85
|
+
--transition-normal: 250ms;
|
|
86
|
+
--transition-slow: 400ms;
|
|
87
|
+
--transition-timing: cubic-bezier(0.4, 0, 0.2, 1);
|
|
88
|
+
|
|
89
|
+
--hover-scale: 1.01;
|
|
90
|
+
--hover-translate-y: -2px;
|
|
91
|
+
--hover-translate-x: 0;
|
|
92
|
+
--active-scale: 0.99;
|
|
93
|
+
--active-translate-y: 0;
|
|
94
|
+
|
|
95
|
+
--focus-ring-width: 2px;
|
|
96
|
+
--focus-ring-offset: 2px;
|
|
97
|
+
--focus-ring-color: #18181b;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
html {
|
|
101
|
+
font-family: var(--font-family);
|
|
102
|
+
line-height: var(--line-height);
|
|
103
|
+
letter-spacing: var(--letter-spacing);
|
|
104
|
+
font-weight: var(--font-weight-normal);
|
|
105
|
+
color-scheme: light dark;
|
|
106
|
+
font-synthesis: none;
|
|
107
|
+
text-rendering: optimizeLegibility;
|
|
108
|
+
-webkit-font-smoothing: antialiased;
|
|
109
|
+
-moz-osx-font-smoothing: grayscale;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
body {
|
|
113
|
+
margin: 0;
|
|
114
|
+
min-height: 100vh;
|
|
115
|
+
background-color: var(--color-background);
|
|
116
|
+
color: var(--color-foreground);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
#root {
|
|
120
|
+
min-height: 100vh;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
::-webkit-scrollbar {
|
|
124
|
+
width: 8px;
|
|
125
|
+
height: 8px;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
::-webkit-scrollbar-track {
|
|
129
|
+
background: var(--color-muted);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
::-webkit-scrollbar-thumb {
|
|
133
|
+
background: var(--color-muted-foreground);
|
|
134
|
+
border-radius: var(--radius-sm);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
::-webkit-scrollbar-thumb:hover {
|
|
138
|
+
background: var(--color-foreground);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* ReactFlow (@xyflow/react) Controls — theme overrides for FlowCanvas zoom buttons
|
|
143
|
+
*
|
|
144
|
+
* Without these, the bottom-left zoom in/out/fit buttons render as plain white
|
|
145
|
+
* squares from ReactFlow's default stylesheet, ignoring the active theme.
|
|
146
|
+
* Targets: .react-flow__controls + .react-flow__controls-button
|
|
147
|
+
*/
|
|
148
|
+
.react-flow__controls {
|
|
149
|
+
background: var(--color-card) !important;
|
|
150
|
+
border: 1px solid var(--color-border) !important;
|
|
151
|
+
border-radius: var(--radius-md) !important;
|
|
152
|
+
box-shadow: var(--shadow-main) !important;
|
|
153
|
+
overflow: hidden;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.react-flow__controls-button {
|
|
157
|
+
background: transparent !important;
|
|
158
|
+
border: none !important;
|
|
159
|
+
border-bottom: 1px solid var(--color-border) !important;
|
|
160
|
+
color: var(--color-foreground) !important;
|
|
161
|
+
fill: var(--color-foreground) !important;
|
|
162
|
+
width: 28px;
|
|
163
|
+
height: 28px;
|
|
164
|
+
transition: background var(--transition-fast) var(--transition-timing);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.react-flow__controls-button:last-child {
|
|
168
|
+
border-bottom: none !important;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.react-flow__controls-button:hover {
|
|
172
|
+
background: var(--color-muted) !important;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.react-flow__controls-button svg {
|
|
176
|
+
fill: var(--color-foreground) !important;
|
|
177
|
+
width: 14px;
|
|
178
|
+
height: 14px;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@layer utilities {
|
|
182
|
+
.shadow-theme { box-shadow: var(--shadow-main); }
|
|
183
|
+
.shadow-theme-sm { box-shadow: var(--shadow-sm); }
|
|
184
|
+
.shadow-theme-lg { box-shadow: var(--shadow-lg); }
|
|
185
|
+
.rounded-theme { border-radius: var(--radius-md); }
|
|
186
|
+
.rounded-theme-sm { border-radius: var(--radius-sm); }
|
|
187
|
+
.rounded-theme-lg { border-radius: var(--radius-lg); }
|
|
188
|
+
.border-theme { border-width: var(--border-width); border-color: var(--color-border); }
|
|
189
|
+
.bg-theme-primary { background-color: var(--color-primary); }
|
|
190
|
+
.bg-theme-secondary { background-color: var(--color-secondary); }
|
|
191
|
+
.bg-theme-background { background-color: var(--color-background); }
|
|
192
|
+
.bg-theme-card { background-color: var(--color-card); }
|
|
193
|
+
.text-theme-foreground { color: var(--color-foreground); }
|
|
194
|
+
.text-theme-muted { color: var(--color-muted-foreground); }
|
|
195
|
+
.text-theme-primary { color: var(--color-primary); }
|
|
196
|
+
.font-theme-normal { font-weight: var(--font-weight-normal); }
|
|
197
|
+
.font-theme-medium { font-weight: var(--font-weight-medium); }
|
|
198
|
+
.font-theme-bold { font-weight: var(--font-weight-bold); }
|
|
199
|
+
}
|