@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,5 +1,5 @@
1
1
  import type { CSSProperties } from 'react';
2
- import type { Label } from '../types/label.js';
2
+ import type { Label } from '../sdk/label.js';
3
3
  export declare function labelText(label?: Label): string;
4
4
  export type StyleJustify = 'start' | 'center' | 'end' | 'spaceAround' | 'spaceBetween' | 'spaceEvenly' | 'stretch' | 'space-around' | 'space-between';
5
5
  export type StyleAlign = 'start' | 'center' | 'end' | 'stretch';
package/dist/ui/_utils.js CHANGED
@@ -1,5 +1,5 @@
1
- import { resolveLabel } from '../core/label.js';
2
- import { translate } from '../i18n/registry.js';
1
+ import { resolveLabel } from '../sdk/label.js';
2
+ import { translate } from '../core/i18n/registry.js';
3
3
  // Resolve a Label (string | { t }) to a plain string for non-reactive contexts.
4
4
  // `{ path }` titles are resolved reactively by the layout headers via
5
5
  // MountTitle / useMountTitle (which descend + subscribe against the mount's
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useSyncExternalStore } from 'react';
3
3
  import { useCampus } from './context.js';
4
- import { resolveColorAlpha } from '../../types/colors.js';
4
+ import { resolveColorAlpha } from '../../sdk/colors.js';
5
5
  const DEFAULT_W = 160;
6
6
  const DEFAULT_H = 110;
7
7
  const DEFAULT_PADDING = 12;
@@ -1,2 +1,2 @@
1
- import type { ComponentDefinition } from '../../types/component-registry.js';
1
+ import type { ComponentDefinition } from '../../sdk/component-registry.js';
2
2
  export declare const CATALOG_CHART_MAP: ComponentDefinition[];
@@ -0,0 +1,61 @@
1
+ .oo-button-bar {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: var(--oo-spacing-xs);
5
+ height: var(--oo-button-bar-height, 22px);
6
+ padding: 0 var(--oo-spacing-sm);
7
+ border: none;
8
+ border-radius: var(--oo-radius-sm);
9
+ background: transparent;
10
+ color: inherit;
11
+ font: inherit;
12
+ font-size: var(--oo-font-size-xs);
13
+ line-height: 1;
14
+ white-space: nowrap;
15
+ cursor: default;
16
+ }
17
+
18
+ .oo-button-bar[data-interactive='true'] { cursor: pointer; }
19
+ .oo-button-bar[data-interactive='true']:hover { background: var(--oo-color-hover); }
20
+ .oo-button-bar[data-interactive='true']:active { background: var(--oo-color-active); }
21
+
22
+ .oo-button-bar:focus-visible {
23
+ outline: 1px solid var(--oo-color-accent);
24
+ outline-offset: -1px;
25
+ }
26
+
27
+ .oo-button-bar[disabled] { opacity: 0.5; cursor: default; }
28
+ .oo-button-bar[data-active='true'] {
29
+ background: var(--oo-color-active);
30
+ color: var(--oo-color-accent);
31
+ }
32
+
33
+ .oo-button-bar[data-tone='accent'] { color: var(--oo-color-accent); }
34
+ .oo-button-bar[data-tone='danger'] { color: var(--oo-color-danger); }
35
+ .oo-button-bar[data-tone='warning'] { color: var(--oo-color-warning); }
36
+ .oo-button-bar[data-tone='success'] { color: var(--oo-color-success); }
37
+ .oo-button-bar[data-tone='muted'] { color: var(--oo-color-muted); }
38
+
39
+ .oo-button-bar__value { font-weight: 600; }
40
+
41
+ /* In a bar, quieter and smaller -- keyed on the ROLE the shell stamped, not on
42
+ * a surface name, so an app's own `alert:top` gets the same treatment without
43
+ * scena having heard of it.
44
+ *
45
+ * It deliberately does NOT distinguish the title bar from the status bar. That
46
+ * difference is real in most editors, but it is an app's opinion about its own
47
+ * two bars, and an app can express it in one rule keyed on `data-surface`,
48
+ * which it is free to do because it knows its own surface names. scena styling
49
+ * the kind, apps styling the identity, is the line.
50
+ *
51
+ * The attribute plus the class beats `.oo-bar__slot button` in bar.css (one
52
+ * class + one type) rather than tying on specificity and losing to source
53
+ * order. */
54
+ [data-surface-role='bar'] .oo-button-bar {
55
+ height: var(--oo-button-bar-height-sm, 20px);
56
+ color: var(--oo-color-muted);
57
+ }
58
+
59
+ [data-surface-role='bar'] .oo-button-bar[data-interactive='true']:hover {
60
+ color: var(--oo-color-text);
61
+ }
@@ -0,0 +1,36 @@
1
+ import type { CSSProperties, ReactNode } from 'react';
2
+ import type { BindingPath } from '../../sdk/component-graph.js';
3
+ import './ButtonBar.css';
4
+ export type ButtonBarTone = 'default' | 'accent' | 'danger' | 'warning' | 'success' | 'muted';
5
+ export interface ButtonBarProps {
6
+ icon?: string;
7
+ label?: string;
8
+ value?: string | number;
9
+ valuePath?: BindingPath;
10
+ command?: string;
11
+ args?: Record<string, unknown>;
12
+ onClick?: () => void;
13
+ tone?: ButtonBarTone;
14
+ active?: boolean;
15
+ disabled?: boolean;
16
+ title?: string;
17
+ className?: string;
18
+ style?: CSSProperties;
19
+ }
20
+ /**
21
+ * The button that goes in a bar.
22
+ *
23
+ * One component for the title bar and the status bar rather than two, because
24
+ * the difference between them is entirely presentational — the status bar is
25
+ * smaller and quieter — and that difference is carried by the surrounding
26
+ * `.oo-bar` context in CSS, not by a prop. A caller that wants the status-bar
27
+ * treatment puts it in the status bar.
28
+ *
29
+ * Both apps grew a near-identical `CommandButton` for this; the useful part is
30
+ * the parts they each got slightly wrong. It renders nothing when there is
31
+ * nothing to show, it does not swallow a click while a command is missing, and
32
+ * `title` falls back to the label so an icon-only button is never unlabelled
33
+ * for a screen reader.
34
+ */
35
+ export declare function ButtonBar({ icon, label, value, valuePath, command, args, onClick, tone, active, disabled, title, className, style, }: ButtonBarProps): ReactNode;
36
+ export default ButtonBar;
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useScena } from '../../react/ScenaProvider.js';
3
+ import { useStore } from '../../react/hooks/useStore.js';
4
+ import './ButtonBar.css';
5
+ /**
6
+ * The button that goes in a bar.
7
+ *
8
+ * One component for the title bar and the status bar rather than two, because
9
+ * the difference between them is entirely presentational — the status bar is
10
+ * smaller and quieter — and that difference is carried by the surrounding
11
+ * `.oo-bar` context in CSS, not by a prop. A caller that wants the status-bar
12
+ * treatment puts it in the status bar.
13
+ *
14
+ * Both apps grew a near-identical `CommandButton` for this; the useful part is
15
+ * the parts they each got slightly wrong. It renders nothing when there is
16
+ * nothing to show, it does not swallow a click while a command is missing, and
17
+ * `title` falls back to the label so an icon-only button is never unlabelled
18
+ * for a screen reader.
19
+ */
20
+ export function ButtonBar({ icon, label, value, valuePath, command, args, onClick, tone = 'default', active, disabled, title, className, style, }) {
21
+ const scena = useScena();
22
+ const bound = useStore(valuePath);
23
+ const shown = valuePath ? bound : value;
24
+ // Nothing to render is not an error, but an empty button is a dead 24px of
25
+ // bar that still takes a click.
26
+ if (icon === undefined && label === undefined && shown === undefined)
27
+ return null;
28
+ const accessible = title ?? label ?? command;
29
+ function handleClick() {
30
+ if (disabled)
31
+ return;
32
+ if (onClick) {
33
+ onClick();
34
+ return;
35
+ }
36
+ if (command)
37
+ void scena.commands.execute(command, args);
38
+ }
39
+ const interactive = !disabled && (onClick !== undefined || command !== undefined);
40
+ return (_jsxs("button", { type: "button", className: ['oo-button-bar', className].filter(Boolean).join(' '), style: style, "data-tone": tone, "data-active": active ?? undefined, "data-interactive": interactive, disabled: disabled, title: accessible, "aria-label": accessible, "aria-pressed": active, onClick: handleClick, children: [icon !== undefined ? (_jsx("span", { className: "oo-button-bar__icon", "aria-hidden": "true", children: icon })) : null, label !== undefined ? _jsx("span", { className: "oo-button-bar__label", children: label }) : null, shown !== undefined ? _jsx("span", { className: "oo-button-bar__value", children: shown }) : null] }));
41
+ }
42
+ export default ButtonBar;
@@ -0,0 +1,22 @@
1
+ .oo-theme-mode-toggle {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: var(--oo-spacing-xs);
5
+ height: 22px;
6
+ padding: 0 var(--oo-spacing-sm);
7
+ border: none;
8
+ border-radius: var(--oo-radius-sm);
9
+ background: transparent;
10
+ color: inherit;
11
+ font: inherit;
12
+ font-size: var(--oo-font-size-xs);
13
+ line-height: 1;
14
+ cursor: pointer;
15
+ }
16
+
17
+ .oo-theme-mode-toggle:hover { background: var(--oo-color-hover); }
18
+ .oo-theme-mode-toggle:focus-visible {
19
+ outline: 1px solid var(--oo-color-accent);
20
+ outline-offset: -1px;
21
+ }
22
+ .oo-theme-mode-toggle[data-mode='system'] { color: var(--oo-color-muted); }
@@ -0,0 +1,20 @@
1
+ import type { CSSProperties, ReactNode } from 'react';
2
+ import { type ThemeModeChoice } from '../../styles/controller.js';
3
+ import './ThemeModeToggle.css';
4
+ export interface ThemeModeToggleProps {
5
+ modes?: ThemeModeChoice[];
6
+ display?: 'icon' | 'text' | 'both';
7
+ className?: string;
8
+ style?: CSSProperties;
9
+ }
10
+ /**
11
+ * Cycles the theme mode. A view over `$/ui/theme/mode` — it writes the store
12
+ * and nothing else, so `registerThemeController` stays the only thing that
13
+ * touches the DOM or localStorage, and any other control over the same path
14
+ * (a settings select, say) stays in agreement with it for free.
15
+ *
16
+ * Requires `registerThemeController`; without it the path is never applied and
17
+ * clicking appears to do nothing.
18
+ */
19
+ export declare function ThemeModeToggle({ modes, display, className, style, }: ThemeModeToggleProps): ReactNode;
20
+ export default ThemeModeToggle;
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useStore, useStoreSetter } from '../../react/hooks/useStore.js';
3
+ import { THEME_MODE_PATH } from '../../styles/controller.js';
4
+ import './ThemeModeToggle.css';
5
+ const ORDER = ['light', 'dark', 'system'];
6
+ const ICON = {
7
+ light: '☀︎',
8
+ dark: '☾︎',
9
+ system: '◐︎',
10
+ };
11
+ const TITLE = {
12
+ light: 'Light',
13
+ dark: 'Dark',
14
+ system: 'Follow system',
15
+ };
16
+ /**
17
+ * Cycles the theme mode. A view over `$/ui/theme/mode` — it writes the store
18
+ * and nothing else, so `registerThemeController` stays the only thing that
19
+ * touches the DOM or localStorage, and any other control over the same path
20
+ * (a settings select, say) stays in agreement with it for free.
21
+ *
22
+ * Requires `registerThemeController`; without it the path is never applied and
23
+ * clicking appears to do nothing.
24
+ */
25
+ export function ThemeModeToggle({ modes = ORDER, display = 'icon', className, style, }) {
26
+ const mode = useStore(THEME_MODE_PATH) ?? 'system';
27
+ const setStore = useStoreSetter();
28
+ const index = modes.indexOf(mode);
29
+ // An unlisted current mode would make indexOf return -1 and the first click
30
+ // land on modes[0] — which is the right recovery, so it is left alone.
31
+ const next = modes[(index + 1) % modes.length] ?? modes[0];
32
+ return (_jsxs("button", { type: "button", className: ['oo-theme-mode-toggle', className].filter(Boolean).join(' '), style: style, "data-mode": mode, title: `${TITLE[mode]} — click for ${TITLE[next].toLowerCase()}`, "aria-label": `Theme mode: ${TITLE[mode]}`, onClick: () => setStore(THEME_MODE_PATH, next), children: [display !== 'text' ? _jsx("span", { "aria-hidden": "true", children: ICON[mode] }) : null, display !== 'icon' ? _jsx("span", { children: TITLE[mode] }) : null] }));
33
+ }
34
+ export default ThemeModeToggle;
@@ -0,0 +1,24 @@
1
+ .oo-theme-picker {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: var(--oo-spacing-xs);
5
+ font-size: var(--oo-font-size-xs);
6
+ }
7
+
8
+ .oo-theme-picker__label { color: var(--oo-color-muted); }
9
+
10
+ .oo-theme-picker__select {
11
+ height: 22px;
12
+ padding: 0 var(--oo-spacing-xs);
13
+ border: 1px solid var(--oo-input-border);
14
+ border-radius: var(--oo-radius-sm);
15
+ background: var(--oo-input-bg);
16
+ color: var(--oo-input-fg);
17
+ font: inherit;
18
+ font-size: var(--oo-font-size-xs);
19
+ }
20
+
21
+ .oo-theme-picker__select:focus-visible {
22
+ outline: 1px solid var(--oo-color-accent);
23
+ outline-offset: -1px;
24
+ }
@@ -0,0 +1,27 @@
1
+ import type { CSSProperties, ReactNode } from 'react';
2
+ import './ThemePicker.css';
3
+ export interface ThemePickerProps {
4
+ themes?: string[];
5
+ label?: string;
6
+ compact?: boolean;
7
+ className?: string;
8
+ style?: CSSProperties;
9
+ }
10
+ /**
11
+ * Picks the theme family. A view over `$/ui/theme/id`, same contract as
12
+ * `ThemeModeToggle`: it writes the store and `registerThemeController` does
13
+ * the applying.
14
+ *
15
+ * The options come from the theme registry rather than from a prop, so a theme
16
+ * registered later — by an extension, or lazily — appears here without this
17
+ * component knowing anything about it. That is also why it reads the registry
18
+ * on render instead of caching: `registerTheme` has no change event, and the
19
+ * list is short enough that it does not matter.
20
+ *
21
+ * Renders nothing below two choices. One theme is not a choice, and a select
22
+ * with a single option is a control that cannot do anything — an app that ships
23
+ * only the built-in theme can mount this unconditionally and it stays out of
24
+ * the way until a second theme is registered.
25
+ */
26
+ export declare function ThemePicker({ themes, label, compact, className, style, }: ThemePickerProps): ReactNode;
27
+ export default ThemePicker;
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useStore, useStoreSetter } from '../../react/hooks/useStore.js';
3
+ import { listThemes } from '../../styles/index.js';
4
+ import { THEME_ID_PATH } from '../../styles/controller.js';
5
+ import './ThemePicker.css';
6
+ /**
7
+ * Picks the theme family. A view over `$/ui/theme/id`, same contract as
8
+ * `ThemeModeToggle`: it writes the store and `registerThemeController` does
9
+ * the applying.
10
+ *
11
+ * The options come from the theme registry rather than from a prop, so a theme
12
+ * registered later — by an extension, or lazily — appears here without this
13
+ * component knowing anything about it. That is also why it reads the registry
14
+ * on render instead of caching: `registerTheme` has no change event, and the
15
+ * list is short enough that it does not matter.
16
+ *
17
+ * Renders nothing below two choices. One theme is not a choice, and a select
18
+ * with a single option is a control that cannot do anything — an app that ships
19
+ * only the built-in theme can mount this unconditionally and it stays out of
20
+ * the way until a second theme is registered.
21
+ */
22
+ export function ThemePicker({ themes, label = 'Theme', compact = false, className, style, }) {
23
+ const current = useStore(THEME_ID_PATH) ?? 'default';
24
+ const setStore = useStoreSetter();
25
+ const all = listThemes();
26
+ const items = themes
27
+ ? themes.map((id) => all.find((t) => t.id === id)).filter((t) => t !== undefined)
28
+ : all;
29
+ if (items.length < 2)
30
+ return null;
31
+ return (_jsxs("label", { className: ['oo-theme-picker', className].filter(Boolean).join(' '), style: style, title: label, children: [compact ? null : _jsx("span", { className: "oo-theme-picker__label", children: label }), _jsx("select", { className: "oo-theme-picker__select", value: current, "aria-label": label, onChange: (e) => setStore(THEME_ID_PATH, e.currentTarget.value), children: items.map((theme) => (_jsx("option", { value: theme.id, children: theme.label }, theme.id))) })] }));
32
+ }
33
+ export default ThemePicker;
@@ -1,2 +1,2 @@
1
- import type { ComponentDefinition } from '../../types/component-registry.js';
1
+ import type { ComponentDefinition } from '../../sdk/component-registry.js';
2
2
  export declare const CATALOG_CONTROLS_MAP: ComponentDefinition[];
@@ -1,10 +1,14 @@
1
+ import { Button } from './Button.js';
1
2
  // Catalog registration for control components (dynamic import — no eager load).
2
3
  export const CATALOG_CONTROLS_MAP = [
3
- { component: 'Button', category: 'inline', renderer: { kind: 'react', load: () => import('./Button.js').then((m) => ({ default: m.Button })) } },
4
+ { component: 'Button', category: 'inline', renderer: { kind: 'react', load: async () => ({ default: Button }) } },
4
5
  { component: 'TextField', category: 'inline', renderer: { kind: 'react', load: () => import('./TextField.js').then((m) => ({ default: m.TextField })) } },
5
6
  { component: 'CheckBox', category: 'inline', renderer: { kind: 'react', load: () => import('./CheckBox.js').then((m) => ({ default: m.CheckBox })) } },
6
7
  { component: 'ChoicePicker', category: 'inline', renderer: { kind: 'react', load: () => import('./ChoicePicker.js').then((m) => ({ default: m.ChoicePicker })) } },
7
8
  { component: 'Slider', category: 'inline', renderer: { kind: 'react', load: () => import('./Slider.js').then((m) => ({ default: m.Slider })) } },
8
9
  { component: 'DateTimeInput', category: 'inline', renderer: { kind: 'react', load: () => import('./DateTimeInput.js').then((m) => ({ default: m.DateTimeInput })) } },
9
10
  { component: 'LocaleToggle', category: 'inline', renderer: { kind: 'react', load: () => import('./LocaleToggle.js').then((m) => ({ default: m.LocaleToggle })) } },
11
+ { component: 'ButtonBar', category: 'inline', renderer: { kind: 'react', load: () => import('./ButtonBar.js').then((m) => ({ default: m.ButtonBar })) } },
12
+ { component: 'ThemePicker', category: 'inline', renderer: { kind: 'react', load: () => import('./ThemePicker.js').then((m) => ({ default: m.ThemePicker })) } },
13
+ { component: 'ThemeModeToggle', category: 'inline', renderer: { kind: 'react', load: () => import('./ThemeModeToggle.js').then((m) => ({ default: m.ThemeModeToggle })) } },
10
14
  ];
@@ -11,3 +11,9 @@ export { Checks } from './Checks.js';
11
11
  export type { CheckRuleResolved, ChecksProps } from './Checks.js';
12
12
  export { LocaleToggle } from './LocaleToggle.js';
13
13
  export type { LocaleToggleProps, LocaleToggleDisplay } from './LocaleToggle.js';
14
+ export { ButtonBar } from './ButtonBar.js';
15
+ export type { ButtonBarProps, ButtonBarTone } from './ButtonBar.js';
16
+ export { ThemePicker } from './ThemePicker.js';
17
+ export type { ThemePickerProps } from './ThemePicker.js';
18
+ export { ThemeModeToggle } from './ThemeModeToggle.js';
19
+ export type { ThemeModeToggleProps } from './ThemeModeToggle.js';
@@ -9,3 +9,6 @@ export { Slider } from './Slider.js';
9
9
  export { DateTimeInput } from './DateTimeInput.js';
10
10
  export { Checks } from './Checks.js';
11
11
  export { LocaleToggle } from './LocaleToggle.js';
12
+ export { ButtonBar } from './ButtonBar.js';
13
+ export { ThemePicker } from './ThemePicker.js';
14
+ export { ThemeModeToggle } from './ThemeModeToggle.js';
@@ -1,5 +1,5 @@
1
1
  import type { ReactNode } from 'react';
2
- import type { WhereOp } from '../../types/query.js';
2
+ import type { WhereOp } from '../../sdk/query.js';
3
3
  export interface FilterField {
4
4
  field: string;
5
5
  label?: string;
@@ -1,5 +1,5 @@
1
1
  import { type CSSProperties, type DragEvent as ReactDragEvent, type ReactNode } from 'react';
2
- import type { BindingPath } from '../../types/component-graph.js';
2
+ import type { BindingPath } from '../../sdk/component-graph.js';
3
3
  import './Listable.css';
4
4
  export interface ListableRenderContext {
5
5
  tableMode: boolean;
@@ -48,6 +48,7 @@ export interface ListableProps<T> {
48
48
  onSortChange?: (next: ListableSort | null) => void;
49
49
  tableBreakpoint?: number;
50
50
  renderListRow?: (item: T) => ReactNode;
51
+ getRowStyle?: (item: T, renderCtx: ListableRenderContext) => CSSProperties | undefined;
51
52
  contextMenuSlot?: string;
52
53
  contextFor?: (item: T) => Record<string, unknown>;
53
54
  contextDataContext?: BindingPath;
@@ -57,4 +58,4 @@ export interface ListableProps<T> {
57
58
  style?: CSSProperties;
58
59
  manageKeys?: boolean;
59
60
  }
60
- export declare function Listable<T>({ items, columns, getKey, title, toolbar, selectedKey, onSelect, onActivate, initialSort, sort, onSortChange, tableBreakpoint, renderListRow, contextMenuSlot, contextFor, contextDataContext, onRowDragStart, emptyState, className, style, manageKeys, }: ListableProps<T>): ReactNode;
61
+ export declare function Listable<T>({ items, columns, getKey, title, toolbar, selectedKey, onSelect, onActivate, initialSort, sort, onSortChange, tableBreakpoint, renderListRow, getRowStyle, contextMenuSlot, contextFor, contextDataContext, onRowDragStart, emptyState, className, style, manageKeys, }: ListableProps<T>): ReactNode;
@@ -33,7 +33,7 @@ function sortItems(items, columns, sort) {
33
33
  return [...items].sort((a, b) => sign * cmp(a, b));
34
34
  }
35
35
  const DEFAULT_TABLE_BREAKPOINT = 480;
36
- export function Listable({ items, columns, getKey, title, toolbar, selectedKey, onSelect, onActivate, initialSort, sort, onSortChange, tableBreakpoint = DEFAULT_TABLE_BREAKPOINT, renderListRow, contextMenuSlot, contextFor, contextDataContext, onRowDragStart, emptyState, className, style, manageKeys = false, }) {
36
+ export function Listable({ items, columns, getKey, title, toolbar, selectedKey, onSelect, onActivate, initialSort, sort, onSortChange, tableBreakpoint = DEFAULT_TABLE_BREAKPOINT, renderListRow, getRowStyle, contextMenuSlot, contextFor, contextDataContext, onRowDragStart, emptyState, className, style, manageKeys = false, }) {
37
37
  const rootRef = useRef(null);
38
38
  const [containerWidth, setContainerWidth] = useState(0);
39
39
  const [internalSort, setInternalSort] = useState(initialSort ?? null);
@@ -175,8 +175,10 @@ export function Listable({ items, columns, getKey, title, toolbar, selectedKey,
175
175
  function renderStackedRow(item) {
176
176
  const key = getKey(item);
177
177
  const selected = key === selectedKey;
178
+ const styleRow = getRowStyle ? getRowStyle(item, renderCtx) : undefined;
178
179
  return (_jsx("div", { role: "row", "data-key": key, "data-selected": selected ? 'true' : undefined, className: "oo-listable__item oo-listable__stack", draggable: onRowDragStart ? true : undefined, onDragStart: onRowDragStart ? (e) => onRowDragStart(e, item) : undefined, onClick: () => onSelect?.(item), onDoubleClick: () => onActivate?.(item), onContextMenu: (e) => openContextMenu(e, item), style: {
179
- cursor: onSelect ? 'pointer' : undefined
180
+ cursor: onSelect ? 'pointer' : undefined,
181
+ ...styleRow,
180
182
  }, children: renderListRow
181
183
  ? renderListRow(item)
182
184
  : visibleColumns.map((col) => {
@@ -1,5 +1,8 @@
1
1
  import type { ReactNode } from 'react';
2
2
  export interface PaginationProps {
3
3
  namespace: string;
4
+ count?: 'items' | 'pages';
5
+ pageSizes?: number[];
6
+ always?: boolean;
4
7
  }
5
- export declare function Pagination({ namespace }: PaginationProps): ReactNode;
8
+ export declare function Pagination({ namespace, count, pageSizes, always, }: PaginationProps): ReactNode;
@@ -4,23 +4,40 @@ import { useStore } from '../../react/hooks/useStore.js';
4
4
  import { useI18n } from '../../react/hooks/useI18n.js';
5
5
  // Generic pager bound to a resource's query/view. Writes `$/<ns>/query.page`;
6
6
  // the data provider re-resolves the view (server window or client slice).
7
- // Hidden when everything fits on one page.
8
- export function Pagination({ namespace }) {
7
+ export function Pagination({ namespace, count = 'items', pageSizes, always = false, }) {
9
8
  const scena = useScena();
10
9
  const { t } = useI18n('query');
11
10
  const view = useStore(`$/${namespace}/view`);
12
11
  const query = useStore(`$/${namespace}/query`);
13
12
  const total = view?.total ?? 0;
14
- const page = query?.page ?? 1;
15
13
  const pageSize = query?.pageSize ?? 50;
16
14
  const pages = Math.max(1, Math.ceil(total / pageSize));
17
- if (total <= pageSize)
15
+ // Clamped, because `total` can shrink under a reader - a filter narrowing,
16
+ // rows being deleted - and page 7 of a 2-page list renders as empty with
17
+ // both arrows disabled, which looks like a broken list rather than a stale
18
+ // page number.
19
+ const page = Math.min(Math.max(1, query?.page ?? 1), pages);
20
+ if (total <= pageSize && !always && !pageSizes?.length)
18
21
  return null;
19
- const setPage = (p) => scena.store.set(`$/${namespace}/query`, {
20
- ...query,
21
- page: Math.min(pages, Math.max(1, p)),
22
- });
23
- return (_jsxs("div", { style: bar, children: [_jsx("button", { style: btn, disabled: page <= 1, onClick: () => setPage(page - 1), "aria-label": "Previous", children: "\u2039" }), _jsx("span", { style: { fontSize: 12, color: 'var(--oo-color-muted, #8a8f98)' }, children: t('pageOf', { page, pages, fallback: '{page} / {pages}' }) }), _jsx("button", { style: btn, disabled: page >= pages, onClick: () => setPage(page + 1), "aria-label": "Next", children: "\u203A" })] }));
22
+ // The window this page actually covers. `first` is 0 only when there is
23
+ // nothing at all, which is the one case where "1 – 0 of 0" would be absurd.
24
+ const first = total === 0 ? 0 : (page - 1) * pageSize + 1;
25
+ const last = Math.min(page * pageSize, total);
26
+ const write = (next) => scena.store.set(`$/${namespace}/query`, { ...query, ...next });
27
+ const setPage = (p) => write({ page: Math.min(pages, Math.max(1, p)) });
28
+ const label = count === 'pages'
29
+ ? t('pageOf', { page, pages, fallback: '{page} / {pages}' })
30
+ : total === 0
31
+ ? t('noItems', { fallback: 'nothing' })
32
+ : t('itemRange', {
33
+ first,
34
+ last,
35
+ total,
36
+ fallback: '{first} – {last} of {total}',
37
+ });
38
+ return (_jsxs("div", { style: bar, children: [_jsx("button", { style: btn, disabled: page <= 1, onClick: () => setPage(page - 1), "aria-label": "Previous", children: "\u2039" }), _jsx("span", { style: { fontSize: 12, color: 'var(--oo-color-muted, #8a8f98)', fontVariantNumeric: 'tabular-nums' }, "aria-live": "polite", children: label }), _jsx("button", { style: btn, disabled: page >= pages, onClick: () => setPage(page + 1), "aria-label": "Next", children: "\u203A" }), pageSizes && pageSizes.length > 0 ? (_jsx("select", { style: select, value: pageSize, "aria-label": t('perPage', { fallback: 'Rows per page' }), onChange: (event) => write({ page: 1, pageSize: Number(event.currentTarget.value) }), children: [...new Set([...pageSizes, pageSize])]
39
+ .sort((a, b) => a - b)
40
+ .map((size) => (_jsx("option", { value: size, children: t('perPageOption', { size, fallback: '{size} / page' }) }, size))) })) : null] }));
24
41
  }
25
42
  const bar = {
26
43
  display: 'flex',
@@ -41,3 +58,14 @@ const btn = {
41
58
  height: 24,
42
59
  lineHeight: '20px',
43
60
  };
61
+ const select = {
62
+ appearance: 'none',
63
+ background: 'var(--oo-color-canvas, #14171c)',
64
+ border: '1px solid var(--oo-color-border, #2b2f37)',
65
+ borderRadius: 4,
66
+ color: 'var(--oo-color-muted, #8a8f98)',
67
+ cursor: 'pointer',
68
+ font: 'inherit',
69
+ fontSize: 11,
70
+ padding: '2px 4px',
71
+ };
@@ -1,6 +1,6 @@
1
1
  import { type ClipboardEvent as ReactClipboardEvent, type CSSProperties, type DragEvent as ReactDragEvent, type ReactNode } from 'react';
2
- import type { BindingPath } from '../../types/component-graph.js';
3
- import type { PickerAction } from '../../types/host.js';
2
+ import type { BindingPath } from '../../sdk/component-graph.js';
3
+ import type { PickerAction } from '../../sdk/host.js';
4
4
  import './Tree.css';
5
5
  export interface TreeNode<T = unknown> {
6
6
  key: string;
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
3
3
  import { ContextMenu } from '../menu/ContextMenu.js';
4
4
  import './Tree.css';
5
- import { resolveColorVar } from '../../types/colors.js';
5
+ import { resolveColorVar } from '../../sdk/colors.js';
6
6
  function flatten(nodes, expanded, depth = 0, parentKey = null, out = []) {
7
7
  for (const n of nodes) {
8
8
  const hasChildren = n.children !== undefined;
@@ -1,2 +1,2 @@
1
- import type { ComponentDefinition } from '../../types/component-registry.js';
1
+ import type { ComponentDefinition } from '../../sdk/component-registry.js';
2
2
  export declare const CATALOG_DATA_MAP: ComponentDefinition[];
@@ -1,19 +1,24 @@
1
1
  .oo-alert {
2
+ --oo-alert-rgb: var(--oo-rgb-blue);
3
+ --oo-alert-color: rgb(var(--oo-alert-rgb));
4
+ --oo-alert-spacing: var(--oo-spacing-sm);
5
+ --oo-alert-background: rgb(var(--oo-alert-rgb) / 0.1);
6
+ --oo-alert-border: rgb(var(--oo-alert-rgb) / 0.25);
2
7
  display: flex;
3
8
  align-items: flex-start;
4
- gap: var(--oo-spacing-sm);
5
- padding: var(--oo-spacing-md);
9
+ gap: var(--oo-alert-spacing);
10
+ padding: var(--oo-alert-spacing);
6
11
  border-radius: var(--oo-radius-md, 8px);
7
12
  font-size: var(--oo-font-size-sm);
8
13
  line-height: 1.5;
9
- background: rgb(var(--oo-color, var(--oo-color-blue)) / 0.1);
10
- color: rgb(var(--oo-color, var(--oo-color-blue)));
11
- border: 1px solid rgb(var(--oo-color, var(--oo-color-blue)) / 0.25);
14
+ background: var(--oo-alert-background);
15
+ color: var(--oo-alert-color);
16
+ border: 1px solid var(--oo-alert-border);
12
17
  }
13
- .oo-alert[data-tone='info'] { --oo-color: var(--oo-color-blue); }
14
- .oo-alert[data-tone='success'] { --oo-color: var(--oo-color-green); }
15
- .oo-alert[data-tone='warning'] { --oo-color: var(--oo-color-amber); }
16
- .oo-alert[data-tone='danger'] { --oo-color: var(--oo-color-red); }
18
+ .oo-alert[data-tone='info'] { --oo-alert-rgb: var(--oo-rgb-blue); }
19
+ .oo-alert[data-tone='success'] { --oo-alert-rgb: var(--oo-rgb-green); }
20
+ .oo-alert[data-tone='warning'] { --oo-alert-rgb: var(--oo-rgb-amber); }
21
+ .oo-alert[data-tone='danger'] { --oo-alert-rgb: var(--oo-rgb-red); }
17
22
  .oo-alert__icon {
18
23
  flex: 0 0 auto;
19
24
  margin-top: 2px;
@@ -27,7 +32,7 @@
27
32
  color: var(--oo-color-fg);
28
33
  }
29
34
  .oo-alert__title {
30
- color: rgb(var(--oo-color));
35
+ color: rgb(var(--oo-alert-rgb));
31
36
  }
32
37
  .oo-alert__close {
33
38
  background: none;
@@ -1,26 +1,34 @@
1
1
  .oo-badge {
2
+ --oo-badge-gap: 4px;
2
3
  --oo-badge-padding-y: 2px;
3
4
  --oo-badge-padding-x: 8px;
5
+ --oo-badge-font-size: var(--oo-font-size-xs);
6
+ --oo-badge-font-family: var(--oo-mono);
7
+ --oo-badge-font-weight: 500;
8
+ --oo-badge-line-height: 1.4;
9
+ --oo-badge-rgb: var(--oo-badge-color, var(--oo-rgb-muted));
10
+ --oo-badge-background: rgb(var(--oo-badge-rgb, var(--oo-rgb-muted)) / 0.15);
11
+ --oo-badge-color: rgb(var(--oo-badge-rgb, var(--oo-rgb-muted)));
12
+
4
13
  display: inline-flex;
5
14
  align-items: center;
6
- gap: 4px;
15
+ gap: var(--oo-badge-gap);
7
16
  padding: var(--oo-badge-padding-y) var(--oo-badge-padding-x);
17
+ font-size: var(--oo-badge-font-size);
18
+ font-family: var(--oo-badge-font-family);
19
+ font-weight: var(--oo-badge-font-weight);
20
+ line-height: var(--oo-badge-line-height);
21
+ background: var(--oo-badge-background);
22
+ color: var(--oo-badge-color);
8
23
  border-radius: 9999px;
9
- font-size: var(--oo-font-size-xs);
10
- font-weight: 500;
11
- line-height: 1.4;
12
- background: rgb(var(--oo-color, var(--oo-rgb-muted)) / 0.15);
13
- color: rgb(var(--oo-color, var(--oo-rgb-muted)));
14
24
  white-space: nowrap;
15
25
  }
16
- .oo-badge[data-variant='default'] {
17
- --oo-color: var(--oo-rgb-muted);
18
- }
19
- .oo-badge[data-variant='success'] { --oo-color: var(--oo-rgb-green); }
20
- .oo-badge[data-variant='warning'] { --oo-color: var(--oo-rgb-amber); }
21
- .oo-badge[data-variant='danger'] { --oo-color: var(--oo-rgb-red); }
22
- .oo-badge[data-variant='info'] { --oo-color: var(--oo-rgb-blue); }
26
+ .oo-badge[data-variant='default'] { --oo-badge-rgb: var(--oo-rgb-muted); }
27
+ .oo-badge[data-variant='success'] { --oo-badge-rgb: var(--oo-rgb-green); }
28
+ .oo-badge[data-variant='warning'] { --oo-badge-rgb: var(--oo-rgb-amber); }
29
+ .oo-badge[data-variant='danger'] { --oo-badge-rgb: var(--oo-rgb-red); }
30
+ .oo-badge[data-variant='info'] { --oo-badge-rgb: var(--oo-rgb-blue); }
23
31
  .oo-badge[data-outline='true'] {
24
32
  background: transparent;
25
- border: 1px solid rgb(var(--oo-color, var(--oo-rgb-muted)) / 0.5);
33
+ border: 1px solid rgb(var(--oo-badge-color, var(--oo-rgb-muted)) / 0.5);
26
34
  }