@almadar/std 16.200.0 → 16.202.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/behaviors/lolo/ui/core/molecules/ui-command-palette.lolo +116 -0
  2. package/behaviors/lolo/ui/core/molecules/ui-file-tree.lolo +5 -0
  3. package/behaviors/lolo/ui/core/molecules/ui-floating-toolbar.lolo +55 -0
  4. package/behaviors/lolo/ui/core/organisms/ui-dock-layout.lolo +186 -0
  5. package/behaviors/lolo/ui/core/organisms/ui-split-pane.lolo +37 -1
  6. package/behaviors/lolo/ui/game/atoms/std-audio-cue.lolo +138 -0
  7. package/behaviors/lolo/ui/game/atoms/std-camera-rig.lolo +158 -0
  8. package/behaviors/lolo/ui/game/atoms/std-coef-pad.lolo +5 -3
  9. package/behaviors/lolo/ui/game/atoms/std-platformer-body.lolo +14 -5
  10. package/behaviors/lolo/ui/game/atoms/ui-canvas-2d.lolo +42 -0
  11. package/behaviors/lolo/ui/game/atoms/ui-canvas.lolo +42 -0
  12. package/behaviors/lolo/ui/game/atoms/ui-game-audio-cue.lolo +68 -0
  13. package/behaviors/lolo/ui/game/atoms/ui-game-audio-toggle.lolo +13 -0
  14. package/behaviors/lolo/ui/learning/atoms/ui-algo-graph-canvas.lolo +1 -0
  15. package/behaviors/lolo/ui/learning/atoms/ui-algorithm-canvas.lolo +1 -0
  16. package/behaviors/lolo/ui/learning/atoms/ui-biology-canvas.lolo +1 -0
  17. package/behaviors/lolo/ui/learning/atoms/ui-chemistry-canvas.lolo +1 -0
  18. package/behaviors/lolo/ui/learning/atoms/ui-learning-canvas.lolo +7 -0
  19. package/behaviors/lolo/ui/learning/atoms/ui-math-canvas.lolo +19 -0
  20. package/behaviors/lolo/ui/learning/atoms/ui-physics-canvas.lolo +1 -0
  21. package/behaviors/registry/infra/atoms/std-approval-gate.orb +20 -10
  22. package/behaviors/registry/infra/atoms/std-cache-aside.orb +62 -31
  23. package/behaviors/registry/infra/atoms/std-circuit-breaker.orb +32 -16
  24. package/behaviors/registry/infra/atoms/std-data-erasure.orb +16 -8
  25. package/behaviors/registry/infra/atoms/std-mod-queue.orb +16 -8
  26. package/behaviors/registry/infra/atoms/std-rate-limiter.orb +28 -14
  27. package/behaviors/registry/infra/organisms/std-status-lifecycle-control.orb +2 -1
  28. package/behaviors/registry/ml/organisms/std-escalating-decision.orb +10 -5
  29. package/behaviors/registry/ml/organisms/std-knowledge-tracing.orb +4 -2
  30. package/behaviors/registry/ui/core/atoms/std-billable-hour.orb +2 -1
  31. package/behaviors/registry/ui/core/atoms/std-browse.orb +6 -3
  32. package/behaviors/registry/ui/core/atoms/std-dashboard-grid-embedded.orb +2 -1
  33. package/behaviors/registry/ui/core/atoms/std-esign-flow.orb +4 -2
  34. package/behaviors/registry/ui/core/atoms/std-esign-request.orb +6 -3
  35. package/behaviors/registry/ui/core/atoms/std-export.orb +4 -2
  36. package/behaviors/registry/ui/core/atoms/std-gallery.orb +18 -9
  37. package/behaviors/registry/ui/core/atoms/std-import.orb +4 -2
  38. package/behaviors/registry/ui/core/atoms/std-list.orb +6 -3
  39. package/behaviors/registry/ui/core/molecules/ui-command-palette.orb +589 -0
  40. package/behaviors/registry/ui/core/molecules/ui-file-tree.orb +8 -0
  41. package/behaviors/registry/ui/core/molecules/ui-floating-toolbar.orb +285 -0
  42. package/behaviors/registry/ui/core/organisms/ui-dock-layout.orb +521 -0
  43. package/behaviors/registry/ui/core/organisms/ui-split-pane.orb +109 -2
  44. package/behaviors/registry/ui/game/atoms/std-audio-cue.orb +653 -0
  45. package/behaviors/registry/ui/game/atoms/std-camera-rig.orb +813 -0
  46. package/behaviors/registry/ui/game/atoms/std-coef-pad.orb +170 -4
  47. package/behaviors/registry/ui/game/atoms/std-platformer-body.orb +84 -7
  48. package/behaviors/registry/ui/game/atoms/ui-canvas-2d.orb +135 -0
  49. package/behaviors/registry/ui/game/atoms/ui-canvas.orb +134 -0
  50. package/behaviors/registry/ui/game/atoms/ui-game-audio-cue.orb +258 -0
  51. package/behaviors/registry/ui/game/atoms/ui-game-audio-toggle.orb +48 -0
  52. package/behaviors/registry/ui/game/organisms/std-arcade-board-3d.orb +8 -4
  53. package/behaviors/registry/ui/game/organisms/std-crew-board-2d.orb +6 -3
  54. package/behaviors/registry/ui/game/organisms/std-dungeon-board-2d.orb +10 -5
  55. package/behaviors/registry/ui/game/organisms/std-market-board-3d.orb +8 -4
  56. package/behaviors/registry/ui/game/organisms/std-objective-board-3d.orb +8 -4
  57. package/behaviors/registry/ui/game/organisms/std-platformer-board-2d.orb +6 -3
  58. package/behaviors/registry/ui/game/organisms/std-survival-board-3d.orb +8 -4
  59. package/behaviors/registry/ui/game/organisms/std-tactics-board-2d.orb +12 -6
  60. package/behaviors/registry/ui/game/organisms/std-tactics-board-3d.orb +8 -4
  61. package/behaviors/registry/ui/game/organisms/std-worldmap-board-2d.orb +6 -3
  62. package/behaviors/registry/ui/learning/atoms/ui-algo-graph-canvas.orb +9 -0
  63. package/behaviors/registry/ui/learning/atoms/ui-algorithm-canvas.orb +13 -0
  64. package/behaviors/registry/ui/learning/atoms/ui-biology-canvas.orb +13 -0
  65. package/behaviors/registry/ui/learning/atoms/ui-chemistry-canvas.orb +13 -0
  66. package/behaviors/registry/ui/learning/atoms/ui-learning-canvas.orb +21 -0
  67. package/behaviors/registry/ui/learning/atoms/ui-math-canvas.orb +39 -0
  68. package/behaviors/registry/ui/learning/atoms/ui-physics-canvas.orb +13 -0
  69. package/behaviors/registry/ui/marketing/atoms/std-marketing-article.orb +2 -1
  70. package/behaviors/registry/ui/marketing/atoms/std-marketing-footer.orb +2 -1
  71. package/behaviors/registry/ui/marketing/atoms/std-marketing-split.orb +2 -1
  72. package/behaviors/registry/ui/marketing/atoms/std-marketing-stats.orb +2 -1
  73. package/behaviors/registry/ui/marketing/atoms/std-marketing-steps.orb +2 -1
  74. package/behaviors/registry/ui/marketing/atoms/std-marketing-team.orb +2 -1
  75. package/dist/behaviors/exports-reader.js +3668 -2878
  76. package/dist/behaviors/functions/index.d.ts +673 -6
  77. package/dist/behaviors/functions/index.js +3650 -2879
  78. package/dist/behaviors/index.d.ts +2 -2
  79. package/dist/behaviors/index.js +3679 -2879
  80. package/dist/behaviors/query.d.ts +88 -4
  81. package/dist/behaviors/query.js +3679 -2879
  82. package/dist/behaviors-embeddings.hash.json +3 -3
  83. package/dist/behaviors-embeddings.json +33 -9
  84. package/dist/behaviors-registry.json +125308 -3773
  85. package/dist/index.d.ts +2 -2
  86. package/dist/index.js +3679 -2879
  87. package/dist/knob-embeddings.hash.json +3 -3
  88. package/dist/knob-embeddings.json +1 -1
  89. package/dist/registry/factory-signatures.json +1 -1
  90. package/package.json +3 -3
@@ -0,0 +1,116 @@
1
+ app ui-command-palette "1.0.0"
2
+ "CommandPalette — UI factory (1:1 with the @almadar/ui command-palette pattern)."
3
+ orbital CommandPaletteOrbital {
4
+ type CommandPaletteCommandsItem = {
5
+ id : string!
6
+ label : string!
7
+ icon : icon
8
+ shortcut : string
9
+ keywords : [string]
10
+ group : string
11
+ disabled : boolean
12
+ event : string
13
+ action : string
14
+ actionPayload : Map string scalar
15
+ }
16
+ type CommandPaletteSELECTCommand = {
17
+ id : string!
18
+ label : string!
19
+ icon : icon
20
+ shortcut : string
21
+ keywords : [string]
22
+ group : string
23
+ disabled : boolean
24
+ event : string
25
+ action : string
26
+ actionPayload : Map string scalar
27
+ }
28
+
29
+ entity CommandPaletteItem [runtime] {
30
+ id : string!
31
+ open : boolean = false
32
+ }
33
+
34
+ trait CommandPaletteRender -> @rebindable CommandPaletteItem [interaction, instance] {
35
+ initial: idle
36
+
37
+ state idle {
38
+ INIT -> idle
39
+ (set @entity.open @config.open)
40
+ (render-ui main {
41
+ open: @entity.open
42
+ onOpenChange: @config.onOpenChange
43
+ commands: @config.commands
44
+ onSelect: @config.onSelect
45
+ placeholder: @config.placeholder
46
+ emptyLabel: @config.emptyLabel
47
+ className: @config.className
48
+ type: command-palette
49
+ })
50
+ OPEN_CHANGE -> idle
51
+ (set @entity.open ?open)
52
+ (render-ui main {
53
+ open: @entity.open
54
+ onOpenChange: @config.onOpenChange
55
+ commands: @config.commands
56
+ onSelect: @config.onSelect
57
+ placeholder: @config.placeholder
58
+ emptyLabel: @config.emptyLabel
59
+ className: @config.className
60
+ type: command-palette
61
+ })
62
+ }
63
+
64
+ emits {
65
+ @config.onOpenChange -> external {
66
+ open : boolean
67
+ }
68
+ @description "Called to open/close the overlay (Escape, overlay click, or a selection)"
69
+ @tier "essential"
70
+ @config.onSelect -> external {
71
+ command : CommandPaletteSELECTCommand
72
+ }
73
+ @description "Called with the selected command (click, or Enter on the highlighted row)"
74
+ @tier "essential"
75
+ }
76
+
77
+ listens {
78
+ OPEN_CHANGE {
79
+ open : boolean
80
+ }
81
+ }
82
+
83
+ config {
84
+ open : boolean = false
85
+ @label "Open"
86
+ @description "Whether the palette overlay is open"
87
+ @tier "presentation"
88
+ onOpenChange : event = "OPEN_CHANGE"
89
+ @label "On Open Change"
90
+ @description "Called to open/close the overlay (Escape, overlay click, or a selection)"
91
+ @tier "presentation"
92
+ commands : [CommandPaletteCommandsItem] = [{ id: "Id", label: "Label", icon: "circle", shortcut: "Shortcut", keywords: ["Item", "Item 2"], group: "Group", disabled: false, action: "Action" }, { id: "Id 2", label: "Label 2", icon: "circle", shortcut: "Shortcut 2", keywords: ["Item", "Item 2"], group: "Group 2", disabled: true, action: "Action 2" }]
93
+ @label "Commands"
94
+ @description "Commands listed in the palette, filtered as the user types"
95
+ @tier "presentation"
96
+ onSelect : event = "SELECT"
97
+ @label "On Select"
98
+ @description "Called with the selected command (click, or Enter on the highlighted row)"
99
+ @tier "presentation"
100
+ placeholder : string = "Type a command..."
101
+ @label "Placeholder"
102
+ @description "Search field placeholder. Consumers own i18n — plain string prop, no package-internal translation (matches FloatingToolbar's convention)."
103
+ @tier "presentation"
104
+ emptyLabel : string = "No matching commands"
105
+ @label "Empty Label"
106
+ @description "Label shown when no command matches the query"
107
+ @tier "presentation"
108
+ className : string
109
+ @label "Class Name"
110
+ @description "Additional CSS classes on the overlay's dialog"
111
+ @tier "presentation"
112
+ }
113
+ }
114
+
115
+ page "/command-palette" as CommandPalettePage -> CommandPaletteRender
116
+ }
@@ -36,6 +36,7 @@ orbital FileTreeOrbital {
36
36
  onNodeAction: @config.onNodeAction
37
37
  nodeActionIcon: @config.nodeActionIcon
38
38
  nodeActionLabel: @config.nodeActionLabel
39
+ onNodeReorder: @config.onNodeReorder
39
40
  className: @config.className
40
41
  indent: @config.indent
41
42
  type: file-tree
@@ -91,6 +92,10 @@ orbital FileTreeOrbital {
91
92
  @label "Node Action Label"
92
93
  @description "Accessible label/tooltip for the row hover action."
93
94
  @tier "presentation"
95
+ onNodeReorder : event = ""
96
+ @label "On Node Reorder"
97
+ @description "Called when a row is dropped onto another, in flat `items` mode; carries the moved node's id, its new parent id (`null` for a root drop), and its index within the new parent's children. Presence-gated: binding this prop is what turns on row dragging."
98
+ @tier "presentation"
94
99
  className : string
95
100
  @label "Class Name"
96
101
  @description "CSS class"
@@ -0,0 +1,55 @@
1
+ app ui-floating-toolbar "1.0.0"
2
+ "FloatingToolbar — UI factory (1:1 with the @almadar/ui floating-toolbar pattern)."
3
+ orbital FloatingToolbarOrbital {
4
+ type FloatingToolbarItemsItem = {
5
+ id : string!
6
+ icon : icon!
7
+ label : string!
8
+ event : string
9
+ action : string
10
+ actionPayload : Map string scalar
11
+ active : boolean
12
+ disabled : boolean
13
+ testId : string
14
+ }
15
+
16
+ entity FloatingToolbarItem [runtime] {
17
+ id : string!
18
+ }
19
+
20
+ trait FloatingToolbarRender -> @rebindable FloatingToolbarItem [interaction, instance] {
21
+ initial: idle
22
+
23
+ state idle {
24
+ INIT -> idle
25
+ (render-ui main {
26
+ items: @config.items
27
+ position: @config.position
28
+ children: @config.children
29
+ className: @config.className
30
+ type: floating-toolbar
31
+ })
32
+ }
33
+
34
+ config {
35
+ items : [FloatingToolbarItemsItem] = [{ id: "Id", icon: "circle", label: "Label", action: "Action", active: false, disabled: false, testId: "Test Id" }, { id: "Id 2", icon: "circle", label: "Label 2", action: "Action 2", active: true, disabled: true, testId: "Test Id 2" }]
36
+ @label "Items"
37
+ @description "Tool items rendered as icon buttons"
38
+ @tier "presentation"
39
+ position : "bottom-center" | "bottom-left" | "bottom-right" = "bottom-center"
40
+ @label "Position"
41
+ @description "Strip position within the app frame."
42
+ @tier "presentation"
43
+ children : node
44
+ @label "Children"
45
+ @description "Custom cells appended after the items, separated by a divider"
46
+ @tier "presentation"
47
+ className : string
48
+ @label "Class Name"
49
+ @description "Additional CSS classes on the positioned root"
50
+ @tier "presentation"
51
+ }
52
+ }
53
+
54
+ page "/floating-toolbar" as FloatingToolbarPage -> FloatingToolbarRender
55
+ }
@@ -0,0 +1,186 @@
1
+ app ui-dock-layout "1.0.0"
2
+ "DockLayout — UI factory (1:1 with the @almadar/ui dock-layout pattern)."
3
+ orbital DockLayoutOrbital {
4
+ entity DockLayoutItem [runtime] {
5
+ id : string!
6
+ }
7
+
8
+ trait DockLayoutRender -> @rebindable DockLayoutItem [interaction, instance] {
9
+ initial: idle
10
+
11
+ state idle {
12
+ INIT -> idle
13
+ (render-ui main {
14
+ rail: @config.rail
15
+ sidebar: @config.sidebar
16
+ main: @config.main
17
+ bottomPanel: @config.bottomPanel
18
+ statusBar: @config.statusBar
19
+ secondarySidebar: @config.secondarySidebar
20
+ railWidth: @config.railWidth
21
+ secondarySidebarWidth: @config.secondarySidebarWidth
22
+ sidebarCollapsed: @config.sidebarCollapsed
23
+ onSidebarCollapsedChange: @config.onSidebarCollapsedChange
24
+ sidebarWidth: @config.sidebarWidth
25
+ onSidebarWidthChange: @config.onSidebarWidthChange
26
+ sidebarMinSize: @config.sidebarMinSize
27
+ bottomPanelCollapsed: @config.bottomPanelCollapsed
28
+ onBottomPanelCollapsedChange: @config.onBottomPanelCollapsedChange
29
+ bottomPanelHeight: @config.bottomPanelHeight
30
+ onBottomPanelHeightChange: @config.onBottomPanelHeightChange
31
+ bottomPanelMinSize: @config.bottomPanelMinSize
32
+ secondarySidebarCollapsed: @config.secondarySidebarCollapsed
33
+ onSecondarySidebarCollapsedChange: @config.onSecondarySidebarCollapsedChange
34
+ className: @config.className
35
+ railClassName: @config.railClassName
36
+ sidebarClassName: @config.sidebarClassName
37
+ mainClassName: @config.mainClassName
38
+ bottomPanelClassName: @config.bottomPanelClassName
39
+ statusBarClassName: @config.statusBarClassName
40
+ secondarySidebarClassName: @config.secondarySidebarClassName
41
+ type: dock-layout
42
+ })
43
+ }
44
+
45
+ emits {
46
+ @config.onSidebarCollapsedChange -> external {
47
+ collapsed : boolean
48
+ }
49
+ @description "onSidebarCollapsedChange prop"
50
+ @tier "essential"
51
+ @config.onSidebarWidthChange -> external {
52
+ width : number
53
+ }
54
+ @description "onSidebarWidthChange prop"
55
+ @tier "essential"
56
+ @config.onBottomPanelCollapsedChange -> external {
57
+ collapsed : boolean
58
+ }
59
+ @description "onBottomPanelCollapsedChange prop"
60
+ @tier "essential"
61
+ @config.onBottomPanelHeightChange -> external {
62
+ height : number
63
+ }
64
+ @description "onBottomPanelHeightChange prop"
65
+ @tier "essential"
66
+ @config.onSecondarySidebarCollapsedChange -> external {
67
+ collapsed : boolean
68
+ }
69
+ @description "onSecondarySidebarCollapsedChange prop"
70
+ @tier "essential"
71
+ }
72
+
73
+ config {
74
+ rail : node
75
+ @label "Rail"
76
+ @description "Fixed-width far-left vertical strip (e.g. an icon nav rail)."
77
+ @tier "presentation"
78
+ sidebar : node
79
+ @label "Sidebar"
80
+ @description "Collapsible, resizable left sidebar."
81
+ @tier "presentation"
82
+ main : node = []
83
+ @label "Main"
84
+ @description "Required center region."
85
+ @tier "presentation"
86
+ bottomPanel : node
87
+ @label "Bottom Panel"
88
+ @description "Collapsible, resizable-height bottom panel."
89
+ @tier "presentation"
90
+ statusBar : node
91
+ @label "Status Bar"
92
+ @description "Slim strip pinned to the bottom of the frame, below the bottom panel."
93
+ @tier "presentation"
94
+ secondarySidebar : node
95
+ @label "Secondary Sidebar"
96
+ @description "Collapsible right sidebar."
97
+ @tier "presentation"
98
+ railWidth : number = 56
99
+ @label "Rail Width"
100
+ @description "Width of `rail` in pixels. @default 56"
101
+ @tier "presentation"
102
+ secondarySidebarWidth : number = 280
103
+ @label "Secondary Sidebar Width"
104
+ @description "Width of `secondarySidebar` in pixels (fixed — not resizable). @default 280"
105
+ @tier "presentation"
106
+ sidebarCollapsed : boolean = false
107
+ @label "Sidebar Collapsed"
108
+ @description "Whether `sidebar` is collapsed. @default false"
109
+ @tier "presentation"
110
+ onSidebarCollapsedChange : event = "SIDEBAR_COLLAPSED_CHANGE"
111
+ @label "On Sidebar Collapsed Change"
112
+ @description "onSidebarCollapsedChange prop"
113
+ @tier "presentation"
114
+ sidebarWidth : number = 20
115
+ @label "Sidebar Width"
116
+ @description "Sidebar size as a SplitPane ratio (0-100, percentage of the sidebar/main split). @default 20"
117
+ @tier "presentation"
118
+ onSidebarWidthChange : event = "SIDEBAR_WIDTH_CHANGE"
119
+ @label "On Sidebar Width Change"
120
+ @description "onSidebarWidthChange prop"
121
+ @tier "presentation"
122
+ sidebarMinSize : number = 160
123
+ @label "Sidebar Min Size"
124
+ @description "Minimum sidebar size in pixels, forwarded to SplitPane's `minSize`. @default 160"
125
+ @tier "presentation"
126
+ bottomPanelCollapsed : boolean = false
127
+ @label "Bottom Panel Collapsed"
128
+ @description "Whether `bottomPanel` is collapsed. @default false"
129
+ @tier "presentation"
130
+ onBottomPanelCollapsedChange : event = "BOTTOM_PANEL_COLLAPSED_CHANGE"
131
+ @label "On Bottom Panel Collapsed Change"
132
+ @description "onBottomPanelCollapsedChange prop"
133
+ @tier "presentation"
134
+ bottomPanelHeight : number = 30
135
+ @label "Bottom Panel Height"
136
+ @description "Bottom panel size as a SplitPane ratio (0-100, percentage given to the panel). @default 30"
137
+ @tier "presentation"
138
+ onBottomPanelHeightChange : event = "BOTTOM_PANEL_HEIGHT_CHANGE"
139
+ @label "On Bottom Panel Height Change"
140
+ @description "onBottomPanelHeightChange prop"
141
+ @tier "presentation"
142
+ bottomPanelMinSize : number = 120
143
+ @label "Bottom Panel Min Size"
144
+ @description "Minimum bottom panel size in pixels, forwarded to SplitPane's `minSize`. @default 120"
145
+ @tier "presentation"
146
+ secondarySidebarCollapsed : boolean = false
147
+ @label "Secondary Sidebar Collapsed"
148
+ @description "Whether `secondarySidebar` is collapsed. @default false"
149
+ @tier "presentation"
150
+ onSecondarySidebarCollapsedChange : event = "SECONDARY_SIDEBAR_COLLAPSED_CHANGE"
151
+ @label "On Secondary Sidebar Collapsed Change"
152
+ @description "onSecondarySidebarCollapsedChange prop"
153
+ @tier "presentation"
154
+ className : string
155
+ @label "Class Name"
156
+ @description "Additional CSS classes on the root frame."
157
+ @tier "presentation"
158
+ railClassName : string
159
+ @label "Rail Class Name"
160
+ @description "railClassName prop"
161
+ @tier "presentation"
162
+ sidebarClassName : string
163
+ @label "Sidebar Class Name"
164
+ @description "sidebarClassName prop"
165
+ @tier "presentation"
166
+ mainClassName : string
167
+ @label "Main Class Name"
168
+ @description "mainClassName prop"
169
+ @tier "presentation"
170
+ bottomPanelClassName : string
171
+ @label "Bottom Panel Class Name"
172
+ @description "bottomPanelClassName prop"
173
+ @tier "presentation"
174
+ statusBarClassName : string
175
+ @label "Status Bar Class Name"
176
+ @description "statusBarClassName prop"
177
+ @tier "presentation"
178
+ secondarySidebarClassName : string
179
+ @label "Secondary Sidebar Class Name"
180
+ @description "secondarySidebarClassName prop"
181
+ @tier "presentation"
182
+ }
183
+ }
184
+
185
+ page "/dock-layout" as DockLayoutPage -> DockLayoutRender
186
+ }
@@ -3,6 +3,7 @@ app ui-split-pane "1.0.0"
3
3
  orbital SplitPaneOrbital {
4
4
  entity SplitPaneItem [runtime] {
5
5
  id : string!
6
+ ratio : number
6
7
  }
7
8
 
8
9
  trait SplitPaneRender -> @rebindable SplitPaneItem [interaction, instance] {
@@ -10,9 +11,10 @@ orbital SplitPaneOrbital {
10
11
 
11
12
  state idle {
12
13
  INIT -> idle
14
+ (set @entity.ratio @config.ratio)
13
15
  (render-ui main {
14
16
  direction: @config.direction
15
- ratio: @config.ratio
17
+ ratio: @entity.ratio
16
18
  minSize: @config.minSize
17
19
  resizable: @config.resizable
18
20
  left: @config.left
@@ -20,8 +22,38 @@ orbital SplitPaneOrbital {
20
22
  className: @config.className
21
23
  leftClassName: @config.leftClassName
22
24
  rightClassName: @config.rightClassName
25
+ onRatioChange: @config.onRatioChange
23
26
  type: split-pane
24
27
  })
28
+ RATIO_CHANGE -> idle
29
+ (set @entity.ratio ?ratio)
30
+ (render-ui main {
31
+ direction: @config.direction
32
+ ratio: @entity.ratio
33
+ minSize: @config.minSize
34
+ resizable: @config.resizable
35
+ left: @config.left
36
+ right: @config.right
37
+ className: @config.className
38
+ leftClassName: @config.leftClassName
39
+ rightClassName: @config.rightClassName
40
+ onRatioChange: @config.onRatioChange
41
+ type: split-pane
42
+ })
43
+ }
44
+
45
+ emits {
46
+ @config.onRatioChange -> external {
47
+ ratio : number
48
+ }
49
+ @description "Called with the new ratio while dragging. Providing this makes `ratio` controlled — the rendered split always tracks the prop instead of internal state, mirroring a controlled input. Omit for uncontrolled (self-tracked) behavior."
50
+ @tier "essential"
51
+ }
52
+
53
+ listens {
54
+ RATIO_CHANGE {
55
+ ratio : number
56
+ }
25
57
  }
26
58
 
27
59
  config {
@@ -61,6 +93,10 @@ orbital SplitPaneOrbital {
61
93
  @label "Right Class Name"
62
94
  @description "Class for right/bottom pane"
63
95
  @tier "presentation"
96
+ onRatioChange : event = "RATIO_CHANGE"
97
+ @label "On Ratio Change"
98
+ @description "Called with the new ratio while dragging. Providing this makes `ratio` controlled — the rendered split always tracks the prop instead of internal state, mirroring a controlled input. Omit for uncontrolled (self-tracked) behavior."
99
+ @tier "presentation"
64
100
  }
65
101
  }
66
102
 
@@ -0,0 +1,138 @@
1
+ app std-audio-cue "1.0.0"
2
+ "Headless-ish sound driver: the SOLE writer of cue/cueSeq/music/muted/volume, rendered through the game-audio-cue atom which mounts @almadar/ui's useGameAudio hook. Intents: CUE plays a one-shot SFX by manifest key (cueSeq increments so the same key can re-fire), MUSIC crossfades to a looping track by key, STOP_MUSIC fades it out, MUTE/UNMUTE/TOGGLE_MUTE flip playback and emit AUDIO_MUTED, SET_VOLUME sets master volume, RESTART reseeds from config. The manifest and baseUrl are config, not runtime state — swap them per game by rebinding this atom's config, never by hand-authoring a second audio layer."
3
+ orbital AudioCueOrbital {
4
+ type SoundEntry = {
5
+ path : string
6
+ volume : number
7
+ loop : boolean
8
+ poolSize : number
9
+ autostart : boolean
10
+ crossfade : boolean
11
+ crossfadeDurationMs : number
12
+ }
13
+
14
+ entity AudioState [runtime, shared] {
15
+ id : string!
16
+ cue : string = ""
17
+ cueSeq : number = 0
18
+ music : string = ""
19
+ muted : boolean = false
20
+ volume : number = 1
21
+ }
22
+
23
+ trait AudioCue -> @rebindable AudioState [lifecycle] {
24
+ initial: active
25
+
26
+ state active {
27
+ INIT -> active
28
+ (set @entity.cue "")
29
+ (set @entity.cueSeq 0)
30
+ (set @entity.music @config.initialMusic)
31
+ (set @entity.muted @config.initialMuted)
32
+ (set @entity.volume @config.initialVolume)
33
+ (render-ui main {
34
+ cue: @entity.cue
35
+ cueSeq: @entity.cueSeq
36
+ music: @entity.music
37
+ muted: @entity.muted
38
+ volume: @entity.volume
39
+ manifest: @config.manifest
40
+ baseUrl: @config.baseUrl
41
+ type: game-audio-cue
42
+ })
43
+
44
+ CUE -> active
45
+ (set @entity.cue ?key)
46
+ (set @entity.cueSeq (+ @entity.cueSeq 1))
47
+
48
+ MUSIC -> active
49
+ (set @entity.music ?key)
50
+
51
+ STOP_MUSIC -> active
52
+ (set @entity.music "")
53
+
54
+ MUTE -> active
55
+ (set @entity.muted true)
56
+ (emit AUDIO_MUTED { muted: true })
57
+
58
+ UNMUTE -> active
59
+ (set @entity.muted false)
60
+ (emit AUDIO_MUTED { muted: false })
61
+
62
+ TOGGLE_MUTE -> active
63
+ (set @entity.muted (not @entity.muted))
64
+ (emit AUDIO_MUTED { muted: @entity.muted })
65
+
66
+ SET_VOLUME -> active
67
+ (set @entity.volume ?volume)
68
+
69
+ RESTART -> active
70
+ (set @entity.cue "")
71
+ (set @entity.cueSeq 0)
72
+ (set @entity.music @config.initialMusic)
73
+ (set @entity.muted @config.initialMuted)
74
+ (set @entity.volume @config.initialVolume)
75
+ }
76
+
77
+ emits {
78
+ AUDIO_MUTED -> external {
79
+ muted : boolean!
80
+ }
81
+ @description "Mute state changed via MUTE/UNMUTE/TOGGLE_MUTE."
82
+ @synonyms "mute-changed, sound-toggled"
83
+ @tier "domain"
84
+ }
85
+
86
+ listens {
87
+ CUE { key : string! }
88
+ @description "Play a one-shot SFX by manifest key; re-fires even when key repeats."
89
+ @tier "domain"
90
+ MUSIC { key : string! }
91
+ @description "Crossfade to a looping background track by manifest key."
92
+ @tier "domain"
93
+ STOP_MUSIC
94
+ @description "Fade out and stop the current music."
95
+ @tier "domain"
96
+ MUTE
97
+ @description "Mute all playback."
98
+ @tier "domain"
99
+ UNMUTE
100
+ @description "Unmute playback."
101
+ @tier "domain"
102
+ TOGGLE_MUTE
103
+ @description "Flip the current mute state."
104
+ @tier "domain"
105
+ SET_VOLUME { volume : number! }
106
+ @description "Set master volume 0-1."
107
+ @tier "domain"
108
+ RESTART
109
+ @description "Reseed cue/music/muted/volume from config."
110
+ @tier "domain"
111
+ }
112
+
113
+ config {
114
+ manifest : Map string SoundEntry = {}
115
+ @label "Manifest"
116
+ @description "Sound definitions keyed by logical name — path(s), volume, loop, pooling, autostart, crossfade."
117
+ @tier "domain"
118
+ baseUrl : string = ""
119
+ @label "Base Url"
120
+ @description "Prefix prepended to every manifest path."
121
+ @tier "infra"
122
+ initialMuted : boolean = false
123
+ @label "Initial Muted"
124
+ @description "Muted state seeded on INIT/RESTART."
125
+ @tier "presentation"
126
+ initialVolume : number = 1
127
+ @label "Initial Volume"
128
+ @description "Master volume 0-1 seeded on INIT/RESTART."
129
+ @tier "presentation"
130
+ initialMusic : string = ""
131
+ @label "Initial Music"
132
+ @description "Manifest key auto-played as looping music on INIT/RESTART; empty plays none."
133
+ @tier "presentation"
134
+ }
135
+ }
136
+
137
+ page "/audio-cue" as AudioCuePage -> AudioCue
138
+ }