@softov/scena 0.1.2 → 0.1.3

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.
Files changed (276) hide show
  1. package/dist/core/builtins.d.ts +3 -0
  2. package/dist/{runtime → core}/builtins.js +1 -1
  3. package/dist/core/controls/command.d.ts +18 -0
  4. package/dist/{controls → core/controls}/command.js +2 -2
  5. package/dist/{controls → core/controls}/events.d.ts +1 -1
  6. package/dist/{controls → core/controls}/events.js +1 -1
  7. package/dist/core/controls/keybinding.d.ts +9 -0
  8. package/dist/{controls → core/controls}/keybinding.js +1 -1
  9. package/dist/core/controls/layout.d.ts +31 -0
  10. package/dist/{controls → core/controls}/layout.js +24 -7
  11. package/dist/core/controls/manifest.d.ts +21 -0
  12. package/dist/{controls → core/controls}/manifest.js +2 -2
  13. package/dist/core/controls/session.d.ts +16 -0
  14. package/dist/{controls → core/controls}/session.js +5 -13
  15. package/dist/{controls → core/controls}/shell.d.ts +2 -2
  16. package/dist/{controls → core/controls}/shell.js +1 -1
  17. package/dist/{controls → core/controls}/storage/layout-local.d.ts +1 -1
  18. package/dist/{controls → core/controls}/storage/session-local.d.ts +1 -1
  19. package/dist/{controls → core/controls}/when.d.ts +2 -2
  20. package/dist/{controls → core/controls}/when.js +1 -1
  21. package/dist/{converters → core/converters}/a2ui-v0.10.d.ts +1 -1
  22. package/dist/core/{component-graph.d.ts → graph/component-graph.d.ts} +1 -1
  23. package/dist/core/{component-graph.js → graph/component-graph.js} +1 -1
  24. package/dist/core/{mount-menu.d.ts → graph/mount-menu.d.ts} +1 -1
  25. package/dist/core/{mount-menu.js → graph/mount-menu.js} +1 -1
  26. package/dist/core/graph/mount-surface.d.ts +15 -0
  27. package/dist/core/{mount-surface.js → graph/mount-surface.js} +23 -4
  28. package/dist/core/{surface-presentation.d.ts → graph/surface-presentation.d.ts} +3 -3
  29. package/dist/{i18n → core/i18n}/i18n-backend.d.ts +1 -1
  30. package/dist/core/index.d.ts +34 -43
  31. package/dist/core/index.js +35 -38
  32. package/dist/core/{component-registry.d.ts → registry/component-registry.d.ts} +2 -2
  33. package/dist/core/{component-registry.js → registry/component-registry.js} +1 -1
  34. package/dist/core/registry/converter-registry.d.ts +2 -0
  35. package/dist/core/{converter-registry.js → registry/converter-registry.js} +1 -1
  36. package/dist/core/resolve/binding-resolver.d.ts +7 -0
  37. package/dist/core/{binding-resolver.js → resolve/binding-resolver.js} +2 -2
  38. package/dist/core/{dynamic-resolver.d.ts → resolve/dynamic-resolver.d.ts} +2 -2
  39. package/dist/core/{dynamic-resolver.js → resolve/dynamic-resolver.js} +1 -1
  40. package/dist/core/{path-resolver.d.ts → resolve/path-resolver.d.ts} +2 -2
  41. package/dist/core/{permissions.d.ts → resolve/permissions.d.ts} +1 -1
  42. package/dist/core/scena.d.ts +1 -1
  43. package/dist/core/scena.js +17 -16
  44. package/dist/core/{backends → store/backends}/modus-backend.d.ts +1 -1
  45. package/dist/core/{backends → store/backends}/storage-backend.d.ts +1 -1
  46. package/dist/core/{backends → store/backends}/yjs-backend.d.ts +1 -1
  47. package/dist/core/{reactive-store.d.ts → store/reactive-store.d.ts} +4 -4
  48. package/dist/core/{reactive-store.js → store/reactive-store.js} +2 -2
  49. package/dist/index.d.ts +8 -0
  50. package/dist/index.js +13 -0
  51. package/dist/porta/Limen.d.ts +1 -0
  52. package/dist/porta/Limen.js +1 -0
  53. package/dist/porta/PortaLock.d.ts +1 -0
  54. package/dist/porta/PortaLock.js +6 -2
  55. package/dist/porta/SigillumGate.d.ts +1 -0
  56. package/dist/porta/SigillumGate.js +1 -0
  57. package/dist/porta/commands.d.ts +1 -1
  58. package/dist/porta/login-form.block.d.ts +1 -1
  59. package/dist/porta/provider.d.ts +1 -1
  60. package/dist/porta/register-blocks.d.ts +2 -2
  61. package/dist/porta/register-blocks.js +4 -7
  62. package/dist/porta/register.d.ts +1 -1
  63. package/dist/porta/sigillum.d.ts +2 -2
  64. package/dist/react/DefaultShell.d.ts +47 -1
  65. package/dist/react/DefaultShell.js +81 -12
  66. package/dist/react/Scena.d.ts +2 -2
  67. package/dist/react/ScenaProvider.d.ts +1 -1
  68. package/dist/react/ShellSplitter.d.ts +1 -1
  69. package/dist/react/SurfaceArea.d.ts +5 -3
  70. package/dist/react/SurfaceArea.js +2 -2
  71. package/dist/react/ViewMount.d.ts +1 -1
  72. package/dist/react/ViewMount.js +4 -4
  73. package/dist/react/hooks/useI18n.d.ts +1 -1
  74. package/dist/react/hooks/useI18n.js +1 -1
  75. package/dist/react/hooks/useLabel.d.ts +1 -1
  76. package/dist/react/hooks/useLabel.js +1 -1
  77. package/dist/react/hooks/useLayout.d.ts +1 -1
  78. package/dist/react/hooks/useMounts.d.ts +1 -1
  79. package/dist/react/hooks/useStore.d.ts +1 -1
  80. package/dist/react/hooks/useStore.js +2 -2
  81. package/dist/react/hooks/useStoreLabel.d.ts +2 -2
  82. package/dist/react/hooks/useStoreLabel.js +1 -1
  83. package/dist/react/hooks/useSurfacePresentation.d.ts +3 -3
  84. package/dist/react/hooks/useSurfacePresentation.js +1 -1
  85. package/dist/react/mount-context.d.ts +1 -1
  86. package/dist/react/useSurfaceResize.d.ts +2 -2
  87. package/dist/runtime/client-handlers.d.ts +1 -1
  88. package/dist/runtime/in-memory-socket.d.ts +2 -2
  89. package/dist/runtime/index.d.ts +3 -3
  90. package/dist/runtime/index.js +2 -2
  91. package/dist/runtime/layout-commands.d.ts +3 -3
  92. package/dist/runtime/layout-commands.js +2 -2
  93. package/dist/runtime/opener-commands.d.ts +5 -5
  94. package/dist/runtime/opener-commands.js +3 -3
  95. package/dist/runtime/surface-bridge.d.ts +5 -5
  96. package/dist/runtime/surface-bridge.js +1 -1
  97. package/dist/{runtime → sdk}/args-schema.d.ts +1 -1
  98. package/dist/{core → sdk}/disposable.d.ts +3 -1
  99. package/dist/{types → sdk}/index.d.ts +1 -0
  100. package/dist/{types → sdk}/index.js +1 -0
  101. package/dist/{types → sdk}/label.d.ts +1 -0
  102. package/dist/{core → sdk}/label.js +0 -1
  103. package/dist/{types → sdk}/layout.d.ts +25 -0
  104. package/dist/{types → sdk}/mount-surface.d.ts +19 -1
  105. package/dist/{types → sdk}/scena.d.ts +2 -1
  106. package/dist/styles/bar.css +8 -4
  107. package/dist/styles/base.css +18 -16
  108. package/dist/styles/controller.d.ts +27 -0
  109. package/dist/styles/controller.js +74 -0
  110. package/dist/styles/form.css +10 -0
  111. package/dist/styles/index.d.ts +2 -0
  112. package/dist/styles/index.js +3 -0
  113. package/dist/styles/surface.css +69 -3
  114. package/dist/styles/themes/tokens.css +1 -1
  115. package/dist/ui/_utils.d.ts +1 -1
  116. package/dist/ui/_utils.js +2 -2
  117. package/dist/ui/campus/CampusMappa.js +1 -1
  118. package/dist/ui/chart/catalog.d.ts +1 -1
  119. package/dist/ui/control/ButtonBar.css +61 -0
  120. package/dist/ui/control/ButtonBar.d.ts +36 -0
  121. package/dist/ui/control/ButtonBar.js +42 -0
  122. package/dist/ui/control/ThemeModeToggle.css +22 -0
  123. package/dist/ui/control/ThemeModeToggle.d.ts +20 -0
  124. package/dist/ui/control/ThemeModeToggle.js +34 -0
  125. package/dist/ui/control/ThemePicker.css +24 -0
  126. package/dist/ui/control/ThemePicker.d.ts +27 -0
  127. package/dist/ui/control/ThemePicker.js +33 -0
  128. package/dist/ui/control/catalog.d.ts +1 -1
  129. package/dist/ui/control/catalog.js +5 -1
  130. package/dist/ui/control/index.d.ts +6 -0
  131. package/dist/ui/control/index.js +3 -0
  132. package/dist/ui/data/Filter.d.ts +1 -1
  133. package/dist/ui/data/Listable.d.ts +3 -2
  134. package/dist/ui/data/Listable.js +4 -2
  135. package/dist/ui/data/Pagination.d.ts +4 -1
  136. package/dist/ui/data/Pagination.js +37 -9
  137. package/dist/ui/data/Tree.d.ts +2 -2
  138. package/dist/ui/data/Tree.js +1 -1
  139. package/dist/ui/data/catalog.d.ts +1 -1
  140. package/dist/ui/display/Alert.css +15 -10
  141. package/dist/ui/display/Badge.css +22 -14
  142. package/dist/ui/display/Badge.d.ts +1 -1
  143. package/dist/ui/display/Badge.js +1 -1
  144. package/dist/ui/display/DetailHeader.css +3 -3
  145. package/dist/ui/display/DetailList.js +3 -2
  146. package/dist/ui/display/DetailNotFound.d.ts +1 -1
  147. package/dist/ui/display/DetailNotFound.js +1 -1
  148. package/dist/ui/display/Progress.d.ts +1 -1
  149. package/dist/ui/display/Progress.js +1 -1
  150. package/dist/ui/display/Spinner.d.ts +1 -1
  151. package/dist/ui/display/Spinner.js +1 -1
  152. package/dist/ui/display/StatusDot.css +46 -0
  153. package/dist/ui/display/StatusDot.d.ts +17 -0
  154. package/dist/ui/display/StatusDot.js +16 -0
  155. package/dist/ui/display/Svg.d.ts +1 -1
  156. package/dist/ui/display/Svg.js +1 -1
  157. package/dist/ui/display/catalog.d.ts +1 -1
  158. package/dist/ui/display/catalog.js +1 -0
  159. package/dist/ui/display/index.d.ts +2 -0
  160. package/dist/ui/display/index.js +1 -0
  161. package/dist/ui/forms/LoginForm.d.ts +1 -0
  162. package/dist/ui/forms/LoginForm.js +1 -0
  163. package/dist/ui/forms/SettingsContainer.d.ts +2 -1
  164. package/dist/ui/forms/SettingsContainer.js +2 -2
  165. package/dist/ui/forms/catalog.d.ts +1 -1
  166. package/dist/ui/index.d.ts +6 -1
  167. package/dist/ui/index.js +3 -1
  168. package/dist/ui/layout/BarLayout.d.ts +1 -1
  169. package/dist/ui/layout/FloatingLayout.d.ts +1 -1
  170. package/dist/ui/layout/InlineLayout.d.ts +1 -1
  171. package/dist/ui/layout/MountTitle.d.ts +2 -2
  172. package/dist/ui/layout/MountTitle.js +2 -2
  173. package/dist/ui/layout/RailLayout.d.ts +1 -1
  174. package/dist/ui/layout/SectionHeader.d.ts +2 -2
  175. package/dist/ui/layout/SectionHeader.js +4 -7
  176. package/dist/ui/layout/SingleLayout.d.ts +1 -1
  177. package/dist/ui/layout/SpatialCard.d.ts +2 -2
  178. package/dist/ui/layout/SpatialLayout.d.ts +1 -1
  179. package/dist/ui/layout/SplitLayout.d.ts +1 -1
  180. package/dist/ui/layout/StackHeader.d.ts +1 -1
  181. package/dist/ui/layout/StackLayout.d.ts +1 -1
  182. package/dist/ui/layout/TabLayout.d.ts +1 -1
  183. package/dist/ui/layout/TabPanelLayout.d.ts +2 -2
  184. package/dist/ui/layout/TabPanelLayout.js +1 -1
  185. package/dist/ui/layout/catalog.d.ts +1 -1
  186. package/dist/ui/layout/register.d.ts +2 -2
  187. package/dist/ui/layout/register.js +1 -1
  188. package/dist/ui/media/catalog.d.ts +1 -1
  189. package/dist/ui/menu/ActionList.d.ts +2 -2
  190. package/dist/ui/menu/ActionList.js +1 -1
  191. package/dist/ui/menu/ContainerMenu.d.ts +2 -2
  192. package/dist/ui/menu/ContextMenu.d.ts +2 -2
  193. package/dist/ui/menu/useChatPicker.d.ts +2 -2
  194. package/dist/ui/navigation/ActivityBarItem.css +81 -0
  195. package/dist/ui/navigation/ActivityBarItem.d.ts +61 -0
  196. package/dist/ui/navigation/ActivityBarItem.js +68 -0
  197. package/dist/ui/navigation/catalog.d.ts +1 -1
  198. package/dist/ui/navigation/catalog.js +1 -0
  199. package/dist/ui/navigation/index.d.ts +2 -0
  200. package/dist/ui/navigation/index.js +1 -0
  201. package/dist/ui/overlay/catalog.d.ts +1 -1
  202. package/dist/ui/register.d.ts +3 -3
  203. package/dist/ui/register.js +1 -1
  204. package/package.json +15 -7
  205. package/dist/controls/command.d.ts +0 -18
  206. package/dist/controls/keybinding.d.ts +0 -9
  207. package/dist/controls/layout.d.ts +0 -16
  208. package/dist/controls/manifest.d.ts +0 -21
  209. package/dist/controls/session.d.ts +0 -16
  210. package/dist/core/binding-resolver.d.ts +0 -7
  211. package/dist/core/converter-registry.d.ts +0 -2
  212. package/dist/core/label.d.ts +0 -2
  213. package/dist/core/mount-surface.d.ts +0 -15
  214. package/dist/runtime/builtins.d.ts +0 -3
  215. package/dist/types/disposable.d.ts +0 -3
  216. package/dist/types/disposable.js +0 -1
  217. package/dist/types/label.js +0 -1
  218. /package/dist/{controls → core/controls}/index.d.ts +0 -0
  219. /package/dist/{controls → core/controls}/index.js +0 -0
  220. /package/dist/{controls → core/controls}/storage/layout-local.js +0 -0
  221. /package/dist/{controls → core/controls}/storage/session-local.js +0 -0
  222. /package/dist/{converters → core/converters}/a2ui-v0.10.js +0 -0
  223. /package/dist/{converters → core/converters}/index.d.ts +0 -0
  224. /package/dist/{converters → core/converters}/index.js +0 -0
  225. /package/dist/core/{surface-presentation.js → graph/surface-presentation.js} +0 -0
  226. /package/dist/{i18n → core/i18n}/i18n-backend.js +0 -0
  227. /package/dist/{i18n → core/i18n}/registry.d.ts +0 -0
  228. /package/dist/{i18n → core/i18n}/registry.js +0 -0
  229. /package/dist/core/{path-resolver.js → resolve/path-resolver.js} +0 -0
  230. /package/dist/core/{permissions.js → resolve/permissions.js} +0 -0
  231. /package/dist/core/{backends → store/backends}/modus-backend.js +0 -0
  232. /package/dist/core/{backends → store/backends}/storage-backend.js +0 -0
  233. /package/dist/core/{backends → store/backends}/yjs-backend.js +0 -0
  234. /package/dist/core/{computed-dsl.d.ts → store/computed-dsl.d.ts} +0 -0
  235. /package/dist/core/{computed-dsl.js → store/computed-dsl.js} +0 -0
  236. /package/dist/{runtime → sdk}/args-schema.js +0 -0
  237. /package/dist/{types → sdk}/binding-resolver.d.ts +0 -0
  238. /package/dist/{types → sdk}/binding-resolver.js +0 -0
  239. /package/dist/{types → sdk}/colors.d.ts +0 -0
  240. /package/dist/{types → sdk}/colors.js +0 -0
  241. /package/dist/{types → sdk}/command.d.ts +0 -0
  242. /package/dist/{types → sdk}/command.js +0 -0
  243. /package/dist/{types → sdk}/component-graph.d.ts +0 -0
  244. /package/dist/{types → sdk}/component-graph.js +0 -0
  245. /package/dist/{types → sdk}/component-registry.d.ts +0 -0
  246. /package/dist/{types → sdk}/component-registry.js +0 -0
  247. /package/dist/{types → sdk}/converter-registry.d.ts +0 -0
  248. /package/dist/{types → sdk}/converter-registry.js +0 -0
  249. /package/dist/{core → sdk}/disposable.js +0 -0
  250. /package/dist/{types → sdk}/events.d.ts +0 -0
  251. /package/dist/{types → sdk}/events.js +0 -0
  252. /package/dist/{types → sdk}/host.d.ts +0 -0
  253. /package/dist/{types → sdk}/host.js +0 -0
  254. /package/dist/{types → sdk}/keybinding.d.ts +0 -0
  255. /package/dist/{types → sdk}/keybinding.js +0 -0
  256. /package/dist/{types → sdk}/layout.js +0 -0
  257. /package/dist/{types → sdk}/manifest.d.ts +0 -0
  258. /package/dist/{types → sdk}/manifest.js +0 -0
  259. /package/dist/{types → sdk}/mount-menu.d.ts +0 -0
  260. /package/dist/{types → sdk}/mount-menu.js +0 -0
  261. /package/dist/{types → sdk}/mount-surface.js +0 -0
  262. /package/dist/{types → sdk}/permissions.d.ts +0 -0
  263. /package/dist/{types → sdk}/permissions.js +0 -0
  264. /package/dist/{types → sdk}/query.d.ts +0 -0
  265. /package/dist/{types → sdk}/query.js +0 -0
  266. /package/dist/{types → sdk}/reactive-store.d.ts +0 -0
  267. /package/dist/{types → sdk}/reactive-store.js +0 -0
  268. /package/dist/{types → sdk}/scena.js +0 -0
  269. /package/dist/{types → sdk}/scope-backend.d.ts +0 -0
  270. /package/dist/{types → sdk}/scope-backend.js +0 -0
  271. /package/dist/{types → sdk}/session.d.ts +0 -0
  272. /package/dist/{types → sdk}/session.js +0 -0
  273. /package/dist/{types → sdk}/shell.d.ts +0 -0
  274. /package/dist/{types → sdk}/shell.js +0 -0
  275. /package/dist/{types → sdk}/when.d.ts +0 -0
  276. /package/dist/{types → sdk}/when.js +0 -0
@@ -1,3 +1,3 @@
1
- import { BindingPath } from '../../types/component-graph.js';
2
- import { Label } from '../../types/label.js';
1
+ import { BindingPath } from '../../sdk/component-graph.js';
2
+ import { Label } from '../../sdk/label.js';
3
3
  export declare function useStoreLabel(value: Label | undefined, fallback?: string, dataContext?: BindingPath): string;
@@ -1,4 +1,4 @@
1
- import { translate } from '../../i18n/registry.js';
1
+ import { translate } from '../../core/i18n/registry.js';
2
2
  import { useStore } from './useStore.js';
3
3
  const EMPTY_LABEL_PATH = '$/__label__/empty';
4
4
  export function useStoreLabel(value, fallback = '', dataContext) {
@@ -1,4 +1,4 @@
1
- import type { SurfaceName } from '../../types/mount-surface.js';
2
- import type { SurfacePresentation } from '../../types/layout.js';
3
- import { type PresentationPolicy } from '../../core/surface-presentation.js';
1
+ import type { SurfaceName } from '../../sdk/mount-surface.js';
2
+ import type { SurfacePresentation } from '../../sdk/layout.js';
3
+ import { type PresentationPolicy } from '../../core/graph/surface-presentation.js';
4
4
  export declare function useSurfacePresentation(surface: SurfaceName, policy?: PresentationPolicy): SurfacePresentation;
@@ -1,4 +1,4 @@
1
- import { resolveSurfacePresentation, } from '../../core/surface-presentation.js';
1
+ import { resolveSurfacePresentation, } from '../../core/graph/surface-presentation.js';
2
2
  import { useStore } from './useStore.js';
3
3
  // Reads `$/modus/class` and maps it to how this surface should occupy space.
4
4
  //
@@ -1,4 +1,4 @@
1
- import type { BindingPath } from '../types/component-graph.js';
1
+ import type { BindingPath } from '../sdk/component-graph.js';
2
2
  export declare const MountContext: import("react").Context<string | null>;
3
3
  export declare function useCurrentMountKey(): string | null;
4
4
  export declare const DataContextContext: import("react").Context<BindingPath | undefined>;
@@ -1,6 +1,6 @@
1
1
  import { type PointerEvent as ReactPointerEvent } from 'react';
2
- import type { SurfaceName } from '../types/mount-surface.js';
3
- import type { SurfacePresentation } from '../types/layout.js';
2
+ import type { SurfaceName } from '../sdk/mount-surface.js';
3
+ import type { SurfacePresentation } from '../sdk/layout.js';
4
4
  /**
5
5
  * Resizing a surface by its own edge, with no handle in the layout.
6
6
  *
@@ -1,3 +1,3 @@
1
- import type { Disposable } from '../types/disposable.js';
1
+ import type { Disposable } from '../sdk/disposable.js';
2
2
  export declare function registerClientHandler(name: string, handler: (args: Record<string, unknown>) => unknown | Promise<unknown>): Disposable;
3
3
  export declare function getClientHandler(name: string): ((args: Record<string, unknown>) => unknown | Promise<unknown>) | undefined;
@@ -1,5 +1,5 @@
1
- import type { Disposable } from '../types/disposable.js';
2
- import type { SocketBridge } from '../types/reactive-store.js';
1
+ import type { Disposable } from '../sdk/disposable.js';
2
+ import type { SocketBridge } from '../sdk/reactive-store.js';
3
3
  export interface InMemorySocket extends SocketBridge {
4
4
  dispatch(event: string, payload?: unknown): void;
5
5
  onOutgoing(event: string, fn: (payload: unknown) => void): Disposable;
@@ -1,10 +1,10 @@
1
- export { validateArgs, isPermissionPath } from './args-schema.js';
2
- export type { ValidateArgsResult } from './args-schema.js';
1
+ export { validateArgs, isPermissionPath } from '../sdk/args-schema.js';
2
+ export type { ValidateArgsResult } from '../sdk/args-schema.js';
3
3
  export { createSurfaceBridge } from './surface-bridge.js';
4
4
  export { registerClientHandler, getClientHandler, } from './client-handlers.js';
5
5
  export { createInMemorySocket } from './in-memory-socket.js';
6
6
  export type { InMemorySocket } from './in-memory-socket.js';
7
- export { registerBuiltinFunctions } from './builtins.js';
7
+ export { registerBuiltinFunctions } from '../core/builtins.js';
8
8
  export { registerLayoutCommands } from './layout-commands.js';
9
9
  export { registerOpenerCommands } from './opener-commands.js';
10
10
  export type { RegisterOpenerCommandsOptions } from './opener-commands.js';
@@ -1,7 +1,7 @@
1
- export { validateArgs, isPermissionPath } from './args-schema.js';
1
+ export { validateArgs, isPermissionPath } from '../sdk/args-schema.js';
2
2
  export { createSurfaceBridge } from './surface-bridge.js';
3
3
  export { registerClientHandler, getClientHandler, } from './client-handlers.js';
4
4
  export { createInMemorySocket } from './in-memory-socket.js';
5
- export { registerBuiltinFunctions } from './builtins.js';
5
+ export { registerBuiltinFunctions } from '../core/builtins.js';
6
6
  export { registerLayoutCommands } from './layout-commands.js';
7
7
  export { registerOpenerCommands } from './opener-commands.js';
@@ -1,5 +1,5 @@
1
- import type { Scena } from '../types/scena.js';
2
- import type { Disposable } from '../types/disposable.js';
3
- import type { ScenaLayout } from '../types/layout.js';
1
+ import type { Scena } from '../sdk/scena.js';
2
+ import type { Disposable } from '../sdk/disposable.js';
3
+ import type { ScenaLayout } from '../sdk/layout.js';
4
4
  export declare function registerLayoutCommands(scena: Scena): Disposable;
5
5
  export type { ScenaLayout };
@@ -1,5 +1,5 @@
1
- import { combineDisposables } from '../core/disposable.js';
2
- import { translate } from '../i18n/registry.js';
1
+ import { combineDisposables } from '../sdk/disposable.js';
2
+ import { translate } from '../core/i18n/registry.js';
3
3
  function joinAbs(root, rel) {
4
4
  if (rel.startsWith('$/'))
5
5
  return rel;
@@ -1,8 +1,8 @@
1
- import type { Scena } from '../types/scena.js';
2
- import type { Disposable } from '../types/disposable.js';
3
- import type { CommandContext } from '../types/command.js';
4
- import type { ComponentDefinition } from '../types/component-registry.js';
5
- import type { SurfaceName } from '../types/mount-surface.js';
1
+ import type { Scena } from '../sdk/scena.js';
2
+ import type { Disposable } from '../sdk/disposable.js';
3
+ import type { CommandContext } from '../sdk/command.js';
4
+ import type { ComponentDefinition } from '../sdk/component-registry.js';
5
+ import type { SurfaceName } from '../sdk/mount-surface.js';
6
6
  export interface RegisterOpenerCommandsOptions {
7
7
  resourceKind: string;
8
8
  slots?: string[];
@@ -1,6 +1,6 @@
1
- import { disposableFrom } from '../core/disposable.js';
2
- import { resolveLabel } from '../core/label.js';
3
- import { translate } from '../i18n/registry.js';
1
+ import { disposableFrom } from '../sdk/disposable.js';
2
+ import { resolveLabel } from '../sdk/label.js';
3
+ import { translate } from '../core/i18n/registry.js';
4
4
  export function registerOpenerCommands(scena, opts) {
5
5
  const slots = opts.slots ?? ['file:context'];
6
6
  const category = opts.category ?? 'Open with';
@@ -1,8 +1,8 @@
1
- import type { Disposable } from '../types/disposable.js';
2
- import type { EventBus } from '../types/events.js';
3
- import type { ReactiveStore, SocketBridge } from '../types/reactive-store.js';
4
- import type { MountSurfaceRegistry, SurfaceName } from '../types/mount-surface.js';
5
- import type { ConverterRegistry } from '../types/converter-registry.js';
1
+ import type { Disposable } from '../sdk/disposable.js';
2
+ import type { EventBus } from '../sdk/events.js';
3
+ import type { ReactiveStore, SocketBridge } from '../sdk/reactive-store.js';
4
+ import type { MountSurfaceRegistry, SurfaceName } from '../sdk/mount-surface.js';
5
+ import type { ConverterRegistry } from '../sdk/converter-registry.js';
6
6
  interface Deps {
7
7
  store: ReactiveStore;
8
8
  surfaces: MountSurfaceRegistry;
@@ -1,4 +1,4 @@
1
- import { combineDisposables } from '../core/disposable.js';
1
+ import { combineDisposables } from '../sdk/disposable.js';
2
2
  // Wires the socket bridge to scena's surface registry.
3
3
  //
4
4
  // Scena has no notion of "agent" — anyone (an agent, the user, a plugin, a
@@ -1,4 +1,4 @@
1
- import type { ArgsSchema, ArgType } from '../types/command.js';
1
+ import type { ArgsSchema, ArgType } from './command.js';
2
2
  export type ValidateArgsResult = {
3
3
  ok: true;
4
4
  value: Record<string, unknown>;
@@ -1,3 +1,5 @@
1
- import type { Disposable } from '../types/disposable.js';
1
+ export interface Disposable {
2
+ dispose(): void;
3
+ }
2
4
  export declare function combineDisposables(...disposables: (Disposable | undefined)[]): Disposable;
3
5
  export declare function disposableFrom(fn: () => void): Disposable;
@@ -13,6 +13,7 @@ export * from './converter-registry.js';
13
13
  export * from './permissions.js';
14
14
  export * from './events.js';
15
15
  export * from './command.js';
16
+ export * from './args-schema.js';
16
17
  export * from './colors.js';
17
18
  export * from './host.js';
18
19
  export * from './keybinding.js';
@@ -13,6 +13,7 @@ export * from './converter-registry.js';
13
13
  export * from './permissions.js';
14
14
  export * from './events.js';
15
15
  export * from './command.js';
16
+ export * from './args-schema.js';
16
17
  export * from './colors.js';
17
18
  export * from './host.js';
18
19
  export * from './keybinding.js';
@@ -7,3 +7,4 @@ export interface LabelResolveContext {
7
7
  get: (path: string) => unknown;
8
8
  translate: (key: string) => string;
9
9
  }
10
+ export declare function resolveLabel(label: Label | undefined, ctx: LabelResolveContext): string;
@@ -1,4 +1,3 @@
1
- // the useLabel hook (reactive).
2
1
  export function resolveLabel(label, ctx) {
3
2
  if (label == null)
4
3
  return '';
@@ -29,6 +29,31 @@ export interface TabPanelSplit {
29
29
  second: TabPanelNode;
30
30
  }
31
31
  export type SurfacePresentation = 'docked' | 'floating' | 'sheet' | 'bar';
32
+ /**
33
+ * Which edge of itself a surface closes on — the one facing `main`.
34
+ *
35
+ * Stamped by the shell, because only the shell knows its own arrangement: the
36
+ * same surface is `inline-end` in one app and `inline-start` in another, and a
37
+ * surface scena has never heard of has no name to look up.
38
+ *
39
+ * Logical rather than physical, so chrome flips under `dir="rtl"` without the
40
+ * shell restating it.
41
+ *
42
+ * This exists so scena's own CSS can stop matching surface NAMES. Rules keyed
43
+ * on `.oo-surface--sidebar-left` work only for the nine and silently skip
44
+ * whatever an app defined; rules keyed on `[data-surface-edge]` work for
45
+ * anything the shell places.
46
+ */
47
+ export type SurfaceEdge = 'inline-start' | 'inline-end' | 'block-start' | 'block-end';
48
+ /**
49
+ * What kind of region a surface is, for styling that is about the kind rather
50
+ * than the identity — a bar's buttons are small and quiet whether that bar is
51
+ * the title bar, the status bar, or an app's own `alert:top`.
52
+ *
53
+ * Also stamped by the shell. scena's CSS matches this; an APP's CSS is free to
54
+ * match `data-surface` by name, because an app does know its own surfaces.
55
+ */
56
+ export type SurfaceRole = 'bar' | 'rail' | 'panel' | 'main' | 'overlay';
32
57
  export interface SurfaceLayoutState {
33
58
  visible: boolean;
34
59
  size?: number;
@@ -3,7 +3,24 @@ import type { ComponentNode, DataBinding } from './component-graph.js';
3
3
  import type { WhenClause } from './when.js';
4
4
  import type { ResourceColor } from './colors.js';
5
5
  import type { Label } from './label.js';
6
- export type SurfaceName = 'titlebar' | 'activitybar' | 'sidebar:left' | 'sidebar:right' | 'main' | 'panel:bottom' | 'statusbar' | 'overlay' | 'detached';
6
+ /**
7
+ * Where something mounts.
8
+ *
9
+ * The nine below are the ones scena's own DefaultShell renders and the ones
10
+ * `layout` seeds defaults for — they are a convention, not the set. An app
11
+ * mounts to whatever names its shell draws: a second status bar, an
12
+ * `alert:top` band, four sidebars, or no sidebar at all.
13
+ *
14
+ * The runtime never had an opinion here — mounts, layout state and store paths
15
+ * are all keyed by the string — but this type used to say otherwise, which made
16
+ * the contract narrower than the thing it described. The `(string & {})` arm
17
+ * keeps editor completion for the nine while admitting any other name.
18
+ *
19
+ * Consequence for anything that sweeps surfaces: ask
20
+ * `surfaces.listSurfaces()`. A list of names written here cannot know what an
21
+ * app defined.
22
+ */
23
+ export type SurfaceName = 'titlebar' | 'activitybar' | 'sidebar:left' | 'sidebar:right' | 'main' | 'panel:bottom' | 'statusbar' | 'overlay' | 'detached' | (string & {});
7
24
  export type MountTarget = ComponentNode | DataBinding;
8
25
  export type EditTier = 'basic' | 'content' | 'binding' | 'structure' | 'schema';
9
26
  export interface MountPolicy {
@@ -67,6 +84,7 @@ export interface MountSurfaceRegistry {
67
84
  }): void;
68
85
  focus(key: string): void;
69
86
  listAt(surface: SurfaceName): ResolvedMount[];
87
+ listSurfaces(): SurfaceName[];
70
88
  move(opts: {
71
89
  key: string;
72
90
  toSurface: SurfaceName;
@@ -10,7 +10,7 @@ import type { PermissionEngine } from './permissions.js';
10
10
  import type { CommandRegistry } from './command.js';
11
11
  import type { KeybindingRegistry } from './keybinding.js';
12
12
  import type { ShellRegistry } from './shell.js';
13
- import type { LayoutAPI, LayoutRegistry, LayoutStorage, ScenaLayout } from './layout.js';
13
+ import type { SurfaceLayoutState, LayoutAPI, LayoutRegistry, LayoutStorage, ScenaLayout } from './layout.js';
14
14
  import type { SessionAPI, SessionStorage } from './session.js';
15
15
  import type { ManifestAPI } from './manifest.js';
16
16
  import type { EventBus } from './events.js';
@@ -45,6 +45,7 @@ export interface CreateScenaOptions {
45
45
  layoutStorage?: LayoutStorage;
46
46
  events?: EventBus;
47
47
  defaultSurface?: SurfaceName;
48
+ surfaceDefaults?: Partial<Record<SurfaceName, SurfaceLayoutState>>;
48
49
  initialLayout?: ScenaLayout;
49
50
  initialShellId?: string;
50
51
  backendFactories?: ScopeBackendFactory[];
@@ -1,7 +1,11 @@
1
- /* Bar layout: three slots (left | center | right) used by titlebar +
2
- * statusbar. Per-surface chrome (height, border-bottom vs border-top, bg)
3
- * lives on `.oo-surface--titlebar` / `.oo-surface--statusbar` so the
4
- * same bar layout can render in either bar. */
1
+ /* Bar layout: three slots (left | center | right), used by any surface a shell
2
+ * gives `role="bar"` -- the title bar and the status bar, and an app's own
3
+ * alert band just as well.
4
+ *
5
+ * Per-surface chrome (height, background) is the shell's or the app's, keyed on
6
+ * `[data-surface-role='bar']` for the kind or `[data-surface]` for one specific
7
+ * bar. The separator is handled by `[data-surface-edge]` in surface.css, which
8
+ * is why nothing here draws one. */
5
9
  .oo-layout--bar {
6
10
  display: flex;
7
11
  align-items: center;
@@ -1,5 +1,7 @@
1
1
  :root {
2
-
2
+ --oo-mono: ui-monospace, "Cascadia Code", "JetBrains Mono", "SF Mono", Consolas, monospace;
3
+ --oo-sans: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
4
+
3
5
  --input-padding-y: var(--oo-spacing-xs);
4
6
  --input-padding-x: var(--oo-spacing-sm);
5
7
  --input-background: var(--oo-color-canvas);
@@ -19,11 +21,11 @@
19
21
  --button-background: none;
20
22
  --button-background-hover: rgb(var(--oo-rgb-primary) / 0.88);
21
23
  --button-background-active: var(--oo-color-active);
22
- --button-text: inherit;
23
- --button-text-hover: var(--oo-color-hover);
24
+ --button-color: inherit;
25
+ --button-color-hover: var(--oo-color-hover);
24
26
  --button-border: var(--oo-color-border);
25
27
  --button-border-width: 1px;
26
- --button-radius: 0;
28
+ --button-border-radius: 0;
27
29
  --button-padding-y: var(--oo-spacing-xs);
28
30
  --button-padding-x: var(--oo-spacing-xs);
29
31
  --button-font-size: var(--oo-font-size-sm);
@@ -77,12 +79,12 @@ button {
77
79
  /* padding: var(--button-padding-y) var(--button-padding-x); */
78
80
  padding-inline: var(--button-padding-x);
79
81
  padding-block: var(--button-padding-y);
80
- border-radius: var(--button-radius);
82
+ border-radius: var(--button-border-radius);
81
83
  border-width: var(--button-border-width);
82
84
  border-style: solid;
83
85
  border-color: var(--button-border);
84
86
  background: var(--button-background);
85
- color: var(--button-text);
87
+ color: var(--button-color);
86
88
 
87
89
  cursor: pointer;
88
90
  font: inherit;
@@ -99,35 +101,35 @@ button {
99
101
 
100
102
  button[data-variant="primary"] {
101
103
  --button-background: none;
102
- --button-text: var(--oo-color-primary);
104
+ --button-color: var(--oo-color-primary);
103
105
  --button-border: var(--oo-color-primary);
104
- --button-text-hover: var(--oo-color-surface);
106
+ --button-color-hover: var(--oo-color-surface);
105
107
  --button-background-hover: rgb(var(--oo-rgb-primary) / 0.88);
106
108
  --button-background-active: rgb(var(--oo-rgb-primary) / 0.76);
107
109
  }
108
110
 
109
111
  button [data-variant="secondary"] {
110
112
  --button-background: none;
111
- --button-text: var(--oo-color-text);
113
+ --button-color: var(--oo-color-text);
112
114
  --button-border: var(--oo-color-border);
113
- --button-text-hover: var(--oo-color-surface);
115
+ --button-color-hover: var(--oo-color-surface);
114
116
  --button-background-hover: rgb(var(--oo-rgb-text) / 0.8);
115
117
  --button-background-active: rgb(var(--oo-rgb-text) / 0.76);
116
118
  }
117
119
 
118
120
  button[data-variant="danger"] {
119
121
  --button-background: none;
120
- --button-text: var(--oo-color-danger);
122
+ --button-color: var(--oo-color-danger);
121
123
  --button-border: var(--oo-color-danger);
122
- --button-text-hover: var(--oo-color-surface);
124
+ --button-color-hover: var(--oo-color-surface);
123
125
  --button-background-hover: rgb(var(--oo-rgb-danger) / 0.88);
124
126
  --button-background-active: rgb(var(--oo-rgb-danger) / 0.76);
125
127
  }
126
128
 
127
129
  button[data-variant="ghost"] {
128
130
  --button-background: none;
129
- --button-text: var(--oo-color-text);
130
- --button-text-hover: var(--oo-color-primary);
131
+ --button-color: var(--oo-color-text);
132
+ --button-color-hover: var(--oo-color-primary);
131
133
  --button-background-hover: none;
132
134
  --button-background-active: none;
133
135
  border: none;
@@ -136,7 +138,7 @@ button[data-variant="ghost"] {
136
138
 
137
139
  button[data-variant="borderless"] {
138
140
  --button-background: var(--oo-color-hover);
139
- --button-text: var(--oo-color-text);
141
+ --button-color: var(--oo-color-text);
140
142
  --button-border-width: 0;
141
143
  --button-background-hover: var(--oo-color-surface);
142
144
  --button-background-active: var(--oo-color-active);
@@ -161,7 +163,7 @@ button[data-disabled="true"] {
161
163
 
162
164
  button:hover {
163
165
  background: var(--button-background-hover);
164
- color: var(--button-text-hover);
166
+ color: var(--button-color-hover);
165
167
  }
166
168
 
167
169
  code,
@@ -0,0 +1,27 @@
1
+ import type { BindingPath } from '../sdk/component-graph.js';
2
+ import type { Disposable } from '../sdk/disposable.js';
3
+ import type { Scena } from '../sdk/scena.js';
4
+ import { type ThemeMode } from './index.js';
5
+ export declare const THEME_ID_PATH: BindingPath;
6
+ export declare const THEME_MODE_PATH: BindingPath;
7
+ export type ThemeModeChoice = ThemeMode | 'system';
8
+ export interface ThemeControllerOptions {
9
+ idKey?: string;
10
+ modeKey?: string;
11
+ defaultThemeId?: string;
12
+ defaultMode?: ThemeModeChoice;
13
+ root?: HTMLElement;
14
+ persist?: boolean;
15
+ }
16
+ export declare function resolveThemeMode(choice: ThemeModeChoice): ThemeMode;
17
+ /**
18
+ * Wires the two theme paths to the document, and keeps them there.
19
+ *
20
+ * Seeds the store from storage (falling back to whatever the entry already put
21
+ * on `<html>`, so there is no flash), applies on every change to either axis,
22
+ * and follows the OS while the mode is `system`.
23
+ *
24
+ * Call once, at boot. `ThemePicker` and `ThemeModeToggle` are views over the
25
+ * paths this owns and do no DOM or storage work of their own.
26
+ */
27
+ export declare function registerThemeController(scena: Scena, options?: ThemeControllerOptions): Disposable;
@@ -0,0 +1,74 @@
1
+ import { combineDisposables } from '../sdk/disposable.js';
2
+ import { applyTheme } from './index.js';
3
+ // The theme, as store state.
4
+ //
5
+ // A theme has two independent axes — the family (`default`, `solarized`, …)
6
+ // and the mode (light / dark / follow the OS) — and an app typically has more
7
+ // than one control over them: a picker in the title bar, a toggle beside it, a
8
+ // select in settings. Keeping both axes in the store is what lets those stay in
9
+ // agreement without talking to each other, and it is why `applyTheme` and the
10
+ // `localStorage` write happen in exactly one subscriber rather than in whoever
11
+ // was clicked.
12
+ //
13
+ // scena imports nothing here at runtime: `Scena` is a type, so `styles/`
14
+ // remains a leaf. That matters because an app entry imports this module before
15
+ // React renders, to avoid a flash of the wrong theme.
16
+ export const THEME_ID_PATH = '$/ui/theme/id';
17
+ export const THEME_MODE_PATH = '$/ui/theme/mode';
18
+ function isThemeChoice(v) {
19
+ return v === 'light' || v === 'dark' || v === 'system';
20
+ }
21
+ // Resolves `system` against the OS preference. Exported because a shell that
22
+ // needs the *effective* mode (to pick an asset, say) should not re-derive it.
23
+ export function resolveThemeMode(choice) {
24
+ if (choice !== 'system')
25
+ return choice;
26
+ if (typeof window === 'undefined' || !window.matchMedia)
27
+ return 'light';
28
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
29
+ }
30
+ /**
31
+ * Wires the two theme paths to the document, and keeps them there.
32
+ *
33
+ * Seeds the store from storage (falling back to whatever the entry already put
34
+ * on `<html>`, so there is no flash), applies on every change to either axis,
35
+ * and follows the OS while the mode is `system`.
36
+ *
37
+ * Call once, at boot. `ThemePicker` and `ThemeModeToggle` are views over the
38
+ * paths this owns and do no DOM or storage work of their own.
39
+ */
40
+ export function registerThemeController(scena, options = {}) {
41
+ const { idKey = 'scena.theme-id', modeKey = 'scena.theme-mode', defaultThemeId = 'default', defaultMode = 'system', persist = true, } = options;
42
+ const root = options.root ?? document.documentElement;
43
+ const storage = persist && typeof localStorage !== 'undefined' ? localStorage : null;
44
+ const savedId = storage?.getItem(idKey) ?? null;
45
+ const savedMode = storage?.getItem(modeKey) ?? null;
46
+ scena.store.patchMany({
47
+ [THEME_ID_PATH]: savedId ?? root.getAttribute('data-theme') ?? defaultThemeId,
48
+ [THEME_MODE_PATH]: isThemeChoice(savedMode) ? savedMode : defaultMode,
49
+ });
50
+ function apply() {
51
+ const id = scena.store.get(THEME_ID_PATH) ?? defaultThemeId;
52
+ const choice = scena.store.get(THEME_MODE_PATH) ?? defaultMode;
53
+ applyTheme(root, id, resolveThemeMode(choice));
54
+ storage?.setItem(idKey, id);
55
+ storage?.setItem(modeKey, choice);
56
+ }
57
+ apply();
58
+ const subs = [
59
+ scena.store.subscribe(THEME_ID_PATH, apply),
60
+ scena.store.subscribe(THEME_MODE_PATH, apply),
61
+ ];
62
+ // Only re-applies while the choice is `system`; a pinned light/dark ignores
63
+ // the OS entirely, which is the point of pinning it.
64
+ if (typeof window !== 'undefined' && window.matchMedia) {
65
+ const mq = window.matchMedia('(prefers-color-scheme: dark)');
66
+ const onSystemChange = () => {
67
+ if (scena.store.get(THEME_MODE_PATH) === 'system')
68
+ apply();
69
+ };
70
+ mq.addEventListener('change', onSystemChange);
71
+ subs.push({ dispose: () => mq.removeEventListener('change', onSystemChange) });
72
+ }
73
+ return combineDisposables(...subs);
74
+ }
@@ -0,0 +1,10 @@
1
+ .oo-settings {
2
+ --space-gap: var(--oo-spacing-md);
3
+ }
4
+
5
+ .oo-settings__body {
6
+ display: flex;
7
+ flex-direction: column;
8
+ gap: var(--space-gap);
9
+ /* padding: var(--space-gap); */
10
+ }
@@ -27,3 +27,5 @@ export interface AppearanceProps {
27
27
  export declare function appearance(base: string, opts?: AppearanceProps): string;
28
28
  export declare function resolveVariableSize(name: string): string;
29
29
  export declare function resolveVariableFontSize(name: string): string;
30
+ export { THEME_ID_PATH, THEME_MODE_PATH, resolveThemeMode, registerThemeController, } from './controller.js';
31
+ export type { ThemeModeChoice, ThemeControllerOptions } from './controller.js';
@@ -107,3 +107,6 @@ export function resolveVariableFontSize(name) {
107
107
  return `--oo-font-size-${name}`;
108
108
  return `--${name}`;
109
109
  }
110
+ // ── Theme as store state ─────────────────────────────────────────────────
111
+ // Re-exported here so an app has one import for everything theme-related.
112
+ export { THEME_ID_PATH, THEME_MODE_PATH, resolveThemeMode, registerThemeController, } from './controller.js';
@@ -14,11 +14,62 @@
14
14
 
15
15
  .oo-surface {
16
16
  --oo-surface-float-width: 17rem;
17
- --oo-surface-sheet-height: 55%;
17
+ --oo-surface-sheet-height: 85%;
18
18
  --oo-surface-bar-size: 2.75rem;
19
19
  --oo-surface-overlay-shadow: 0 0 28px rgb(0 0 0 / 0.32);
20
20
  }
21
21
 
22
+ /*
23
+ * Separators between surfaces.
24
+ *
25
+ * OFF by default: a shell that separates its regions by background alone is a
26
+ * legitimate design -- `paper` is exactly that -- and turning hairlines on for
27
+ * everyone would change every existing app's chrome. A theme opts in on the
28
+ * root:
29
+ *
30
+ * --oo-surface-border-width: 1px;
31
+ *
32
+ * Keyed on the EDGE the shell stamped, not on the surface's name. A rule
33
+ * per name works for the nine scena ships and silently skips whatever an app
34
+ * defined; a shell that places `alert:top` and says `edge="block-end"` gets a
35
+ * separator for free.
36
+ *
37
+ * The defaults are `var()` fallbacks rather than declarations on `.oo-surface`,
38
+ * and that is load-bearing: a custom property set ON the element beats the same
39
+ * property inherited from `<html>`, so declaring `--oo-surface-border-width: 0`
40
+ * here would silently override every theme that tried to turn borders on.
41
+ */
42
+ .oo-surface[data-surface-edge='inline-end'] {
43
+ border-inline-end:
44
+ var(--oo-surface-border-width, 0px) solid
45
+ var(--oo-surface-border, var(--oo-color-border));
46
+ }
47
+
48
+ .oo-surface[data-surface-edge='inline-start'] {
49
+ border-inline-start:
50
+ var(--oo-surface-border-width, 0px) solid
51
+ var(--oo-surface-border, var(--oo-color-border));
52
+ }
53
+
54
+ .oo-surface[data-surface-edge='block-end'] {
55
+ border-block-end:
56
+ var(--oo-surface-border-width, 0px) solid
57
+ var(--oo-surface-border, var(--oo-color-border));
58
+ }
59
+
60
+ .oo-surface[data-surface-edge='block-start'] {
61
+ border-block-start:
62
+ var(--oo-surface-border-width, 0px) solid
63
+ var(--oo-surface-border, var(--oo-color-border));
64
+ }
65
+
66
+ /* An overlaid surface is lifted out of the flow with its own shadow, so a
67
+ * border on the edge it no longer touches would draw a line into open space. */
68
+ .oo-surface[data-presentation='floating'],
69
+ .oo-surface[data-presentation='sheet'] {
70
+ border: 0;
71
+ }
72
+
22
73
  /* ── floating: lifted over `main`, consumes no width ─────────────────── */
23
74
  .oo-surface[data-presentation='floating'] {
24
75
  position: absolute;
@@ -30,11 +81,26 @@
30
81
  background: var(--oo-color-surface, var(--oo-color-canvas));
31
82
  }
32
83
 
33
- .oo-surface--sidebar-left[data-presentation='floating'] {
84
+ /* A floating surface anchors OPPOSITE the edge it closes on: one that closes
85
+ * on its inline-end lifts out of the start side of the viewport. */
86
+ .oo-surface[data-surface-edge='inline-end'][data-presentation='floating'] {
87
+ inset-inline-start: 0;
88
+ }
89
+
90
+ .oo-surface[data-surface-edge='inline-start'][data-presentation='floating'] {
91
+ inset-inline-end: 0;
92
+ }
93
+
94
+ /* Fallback for shells that place these two without stamping an edge -- the
95
+ * stamping is newer than they are, and a floating sidebar with no anchor sits
96
+ * wherever its static position left it, which is a visible break rather than
97
+ * a missing nicety. Physical properties on purpose: these two names encode a
98
+ * physical side, so honouring them under `dir="rtl"` would be a lie. */
99
+ .oo-surface--sidebar-left[data-presentation='floating']:not([data-surface-edge]) {
34
100
  left: 0;
35
101
  }
36
102
 
37
- .oo-surface--sidebar-right[data-presentation='floating'] {
103
+ .oo-surface--sidebar-right[data-presentation='floating']:not([data-surface-edge]) {
38
104
  right: 0;
39
105
  }
40
106
 
@@ -101,7 +101,7 @@
101
101
  --oo-rgb-danger: 204 0 0;
102
102
  --oo-rgb-success: 0 170 0;
103
103
  --oo-rgb-warning: 204 136 0;
104
- --oo-rgb-info: var(--oo-blue);
104
+ --oo-rgb-info: var(--oo-rgb-blue);
105
105
 
106
106
  /* ----------------------------------------
107
107
  * Resolved semantic colors