@almadar/std 16.235.0 → 16.236.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 (244) hide show
  1. package/behaviors/behaviors-registry.json +4402 -1898
  2. package/behaviors/lolo/infra/atoms/std-approval-gate.lolo +25 -41
  3. package/behaviors/lolo/infra/atoms/std-audit-capture.lolo +0 -5
  4. package/behaviors/lolo/infra/atoms/std-cache-aside.lolo +0 -24
  5. package/behaviors/lolo/infra/atoms/std-circuit-breaker.lolo +1 -17
  6. package/behaviors/lolo/infra/atoms/std-data-erasure.lolo +17 -24
  7. package/behaviors/lolo/infra/atoms/std-data-import.lolo +8 -11
  8. package/behaviors/lolo/infra/atoms/std-game-clock.lolo +2 -0
  9. package/behaviors/lolo/infra/atoms/std-knowledge-loop.lolo +0 -5
  10. package/behaviors/lolo/infra/atoms/std-lifecycle.lolo +3 -1
  11. package/behaviors/lolo/infra/atoms/std-mod-queue.lolo +40 -18
  12. package/behaviors/lolo/infra/atoms/std-notification-preferences.lolo +20 -11
  13. package/behaviors/lolo/infra/atoms/std-notify-on-event.lolo +0 -5
  14. package/behaviors/lolo/infra/atoms/std-permission-matrix.lolo +23 -11
  15. package/behaviors/lolo/infra/atoms/std-rate-limiter.lolo +84 -22
  16. package/behaviors/lolo/infra/atoms/std-status-lifecycle.lolo +1 -6
  17. package/behaviors/lolo/ml/atoms/std-graph-builder.lolo +3 -1
  18. package/behaviors/lolo/ml/atoms/std-ml-classify.lolo +0 -4
  19. package/behaviors/lolo/ml/atoms/std-ml-similarity.lolo +0 -4
  20. package/behaviors/lolo/ui/avl/atoms/ui-avl-state-machine.lolo +12 -0
  21. package/behaviors/lolo/ui/core/atoms/std-app-layout.lolo +55 -9
  22. package/behaviors/lolo/ui/core/atoms/std-app-search.lolo +6 -2
  23. package/behaviors/lolo/ui/core/atoms/std-billable-hour.lolo +19 -14
  24. package/behaviors/lolo/ui/core/atoms/std-board.lolo +77 -27
  25. package/behaviors/lolo/ui/core/atoms/std-browse.lolo +44 -28
  26. package/behaviors/lolo/ui/core/atoms/std-calendar.lolo +7 -3
  27. package/behaviors/lolo/ui/core/atoms/std-esign-flow.lolo +25 -13
  28. package/behaviors/lolo/ui/core/atoms/std-esign-request.lolo +5 -0
  29. package/behaviors/lolo/ui/core/atoms/std-event-log.lolo +0 -5
  30. package/behaviors/lolo/ui/core/atoms/std-export.lolo +0 -10
  31. package/behaviors/lolo/ui/core/atoms/std-file-store.lolo +7 -3
  32. package/behaviors/lolo/ui/core/atoms/std-form-advanced.lolo +1 -6
  33. package/behaviors/lolo/ui/core/atoms/std-geosearch.lolo +1 -0
  34. package/behaviors/lolo/ui/core/atoms/std-graphs.lolo +20 -4
  35. package/behaviors/lolo/ui/core/atoms/std-import.lolo +0 -5
  36. package/behaviors/lolo/ui/core/atoms/std-list.lolo +46 -32
  37. package/behaviors/lolo/ui/core/atoms/std-modal-editor.lolo +2 -2
  38. package/behaviors/lolo/ui/core/atoms/std-rating-review.lolo +12 -13
  39. package/behaviors/lolo/ui/core/atoms/std-record-detail.lolo +16 -12
  40. package/behaviors/lolo/ui/core/atoms/std-recurrence.lolo +10 -1
  41. package/behaviors/lolo/ui/core/atoms/std-role-gate.lolo +39 -0
  42. package/behaviors/lolo/ui/core/atoms/std-saved-search.lolo +78 -16
  43. package/behaviors/lolo/ui/core/atoms/std-selection.lolo +15 -10
  44. package/behaviors/lolo/ui/core/atoms/std-stats.lolo +5 -5
  45. package/behaviors/lolo/ui/core/atoms/std-tag-taxonomy.lolo +3 -0
  46. package/behaviors/lolo/ui/core/atoms/std-thread.lolo +41 -73
  47. package/behaviors/lolo/ui/core/atoms/std-version-history.lolo +20 -11
  48. package/behaviors/lolo/ui/core/atoms/std-vote.lolo +0 -4
  49. package/behaviors/lolo/ui/core/atoms/std-wizard.lolo +3 -3
  50. package/behaviors/lolo/ui/core/atoms/ui-presence.lolo +21 -0
  51. package/behaviors/lolo/ui/core/molecules/ui-breadcrumb.lolo +6 -1
  52. package/behaviors/lolo/ui/core/molecules/ui-chart.lolo +11 -1
  53. package/behaviors/lolo/ui/core/molecules/ui-code-block.lolo +13 -8
  54. package/behaviors/lolo/ui/core/molecules/ui-command-palette.lolo +7 -2
  55. package/behaviors/lolo/ui/core/molecules/ui-commit-row.lolo +2 -2
  56. package/behaviors/lolo/ui/core/molecules/ui-confirm-dialog.lolo +8 -0
  57. package/behaviors/lolo/ui/core/molecules/ui-data-grid.lolo +41 -3
  58. package/behaviors/lolo/ui/core/molecules/ui-data-list.lolo +41 -3
  59. package/behaviors/lolo/ui/core/molecules/ui-document-details.lolo +30 -9
  60. package/behaviors/lolo/ui/core/molecules/ui-document-panel.lolo +8 -3
  61. package/behaviors/lolo/ui/core/molecules/ui-document-viewer.lolo +6 -1
  62. package/behaviors/lolo/ui/core/molecules/ui-drawer.lolo +13 -0
  63. package/behaviors/lolo/ui/core/molecules/ui-floating-action-button.lolo +6 -1
  64. package/behaviors/lolo/ui/core/molecules/ui-floating-toolbar.lolo +6 -1
  65. package/behaviors/lolo/ui/core/molecules/ui-form-actions.lolo +6 -1
  66. package/behaviors/lolo/ui/core/molecules/ui-graph-canvas.lolo +6 -1
  67. package/behaviors/lolo/ui/core/molecules/ui-menu.lolo +6 -1
  68. package/behaviors/lolo/ui/core/molecules/ui-meter.lolo +6 -1
  69. package/behaviors/lolo/ui/core/molecules/ui-modal.lolo +5 -0
  70. package/behaviors/lolo/ui/core/molecules/ui-page-header.lolo +11 -1
  71. package/behaviors/lolo/ui/core/molecules/ui-page-transition.lolo +1 -1
  72. package/behaviors/lolo/ui/core/molecules/ui-swipeable-row.lolo +44 -15
  73. package/behaviors/lolo/ui/core/molecules/ui-table-view.lolo +41 -3
  74. package/behaviors/lolo/ui/core/molecules/ui-tabs.lolo +8 -2
  75. package/behaviors/lolo/ui/core/organisms/ui-detail-panel.lolo +66 -12
  76. package/behaviors/lolo/ui/core/organisms/ui-entity-cards.lolo +9 -3
  77. package/behaviors/lolo/ui/core/organisms/ui-entity-list.lolo +9 -3
  78. package/behaviors/lolo/ui/core/organisms/ui-entity-table.lolo +18 -9
  79. package/behaviors/lolo/ui/core/organisms/ui-form-section.lolo +55 -10
  80. package/behaviors/lolo/ui/core/organisms/ui-form.lolo +55 -10
  81. package/behaviors/lolo/ui/core/organisms/ui-media-gallery.lolo +8 -3
  82. package/behaviors/lolo/ui/core/organisms/ui-state-machine-view.lolo +12 -0
  83. package/behaviors/lolo/ui/core/organisms/ui-timeline.lolo +8 -3
  84. package/behaviors/lolo/ui/core/templates/ui-counter-template.lolo +2 -44
  85. package/behaviors/lolo/ui/core/templates/ui-dashboard-layout.lolo +6 -1
  86. package/behaviors/lolo/ui/core/templates/ui-generic-app-template.lolo +2 -37
  87. package/behaviors/lolo/ui/game/atoms/ui-game-menu.lolo +8 -2
  88. package/behaviors/lolo/ui/game/organisms/std-arcade-board-3d.lolo +2 -2
  89. package/behaviors/lolo/ui/game/organisms/std-crew-board-2d.lolo +0 -4
  90. package/behaviors/lolo/ui/game/organisms/std-platformer-puzzle.lolo +2 -66
  91. package/behaviors/lolo/ui/game/organisms/std-tactics-board-2d.lolo +0 -4
  92. package/behaviors/lolo/ui/game/organisms/std-worldmap-board-2d.lolo +0 -4
  93. package/behaviors/lolo/ui/learning/atoms/std-learn-stepper.lolo +6 -6
  94. package/behaviors/lolo-behavior-contracts.json +1 -1
  95. package/behaviors/registry/factory-signatures.json +1 -1
  96. package/behaviors/registry/infra/atoms/std-approval-gate.orb +124 -67
  97. package/behaviors/registry/infra/atoms/std-audit-capture.orb +0 -8
  98. package/behaviors/registry/infra/atoms/std-cache-aside.orb +0 -84
  99. package/behaviors/registry/infra/atoms/std-circuit-breaker.orb +1 -44
  100. package/behaviors/registry/infra/atoms/std-data-erasure.orb +124 -55
  101. package/behaviors/registry/infra/atoms/std-data-import.orb +12 -11
  102. package/behaviors/registry/infra/atoms/std-game-clock.orb +31 -0
  103. package/behaviors/registry/infra/atoms/std-knowledge-loop.orb +0 -57
  104. package/behaviors/registry/infra/atoms/std-lifecycle.orb +43 -0
  105. package/behaviors/registry/infra/atoms/std-mod-queue.orb +379 -103
  106. package/behaviors/registry/infra/atoms/std-notification-preferences.orb +126 -12
  107. package/behaviors/registry/infra/atoms/std-notify-on-event.orb +0 -11
  108. package/behaviors/registry/infra/atoms/std-permission-matrix.orb +128 -12
  109. package/behaviors/registry/infra/atoms/std-rate-limiter.orb +287 -72
  110. package/behaviors/registry/infra/atoms/std-status-lifecycle.orb +5 -8
  111. package/behaviors/registry/ml/atoms/std-graph-builder.orb +11 -0
  112. package/behaviors/registry/ml/atoms/std-ml-classify.orb +0 -7
  113. package/behaviors/registry/ml/atoms/std-ml-similarity.orb +0 -7
  114. package/behaviors/registry/ui/avl/atoms/ui-avl-state-machine.orb +82 -0
  115. package/behaviors/registry/ui/core/atoms/std-app-layout.orb +417 -9
  116. package/behaviors/registry/ui/core/atoms/std-app-search.orb +53 -1
  117. package/behaviors/registry/ui/core/atoms/std-billable-hour.orb +209 -19
  118. package/behaviors/registry/ui/core/atoms/std-board.orb +242 -61
  119. package/behaviors/registry/ui/core/atoms/std-browse.orb +295 -41
  120. package/behaviors/registry/ui/core/atoms/std-calendar.orb +96 -2
  121. package/behaviors/registry/ui/core/atoms/std-esign-flow.orb +122 -15
  122. package/behaviors/registry/ui/core/atoms/std-esign-request.orb +11 -0
  123. package/behaviors/registry/ui/core/atoms/std-event-log.orb +0 -8
  124. package/behaviors/registry/ui/core/atoms/std-export.orb +0 -16
  125. package/behaviors/registry/ui/core/atoms/std-file-store.orb +109 -2
  126. package/behaviors/registry/ui/core/atoms/std-form-advanced.orb +1 -43
  127. package/behaviors/registry/ui/core/atoms/std-geosearch.orb +5 -0
  128. package/behaviors/registry/ui/core/atoms/std-graphs.orb +173 -66
  129. package/behaviors/registry/ui/core/atoms/std-import.orb +0 -8
  130. package/behaviors/registry/ui/core/atoms/std-list.orb +226 -34
  131. package/behaviors/registry/ui/core/atoms/std-modal-editor.orb +10 -1
  132. package/behaviors/registry/ui/core/atoms/std-rating-review.orb +37 -19
  133. package/behaviors/registry/ui/core/atoms/std-record-detail.orb +204 -11
  134. package/behaviors/registry/ui/core/atoms/std-recurrence.orb +89 -4
  135. package/behaviors/registry/ui/core/atoms/std-role-gate.orb +217 -0
  136. package/behaviors/registry/ui/core/atoms/std-saved-search.orb +419 -19
  137. package/behaviors/registry/ui/core/atoms/std-selection.orb +140 -10
  138. package/behaviors/registry/ui/core/atoms/std-stats.orb +73 -1
  139. package/behaviors/registry/ui/core/atoms/std-tag-taxonomy.orb +3 -0
  140. package/behaviors/registry/ui/core/atoms/std-thread.orb +190 -115
  141. package/behaviors/registry/ui/core/atoms/std-version-history.orb +127 -13
  142. package/behaviors/registry/ui/core/atoms/std-vote.orb +0 -9
  143. package/behaviors/registry/ui/core/atoms/std-wizard.orb +33 -3
  144. package/behaviors/registry/ui/core/atoms/ui-presence.orb +59 -0
  145. package/behaviors/registry/ui/core/molecules/ui-breadcrumb.orb +53 -1
  146. package/behaviors/registry/ui/core/molecules/ui-chart.orb +68 -1
  147. package/behaviors/registry/ui/core/molecules/ui-code-block.orb +291 -8
  148. package/behaviors/registry/ui/core/molecules/ui-command-palette.orb +87 -2
  149. package/behaviors/registry/ui/core/molecules/ui-commit-row.orb +3 -2
  150. package/behaviors/registry/ui/core/molecules/ui-confirm-dialog.orb +32 -0
  151. package/behaviors/registry/ui/core/molecules/ui-data-grid.orb +189 -3
  152. package/behaviors/registry/ui/core/molecules/ui-data-list.orb +189 -3
  153. package/behaviors/registry/ui/core/molecules/ui-document-details.orb +81 -24
  154. package/behaviors/registry/ui/core/molecules/ui-document-panel.orb +121 -3
  155. package/behaviors/registry/ui/core/molecules/ui-document-viewer.orb +53 -1
  156. package/behaviors/registry/ui/core/molecules/ui-drawer.orb +40 -0
  157. package/behaviors/registry/ui/core/molecules/ui-floating-action-button.orb +53 -1
  158. package/behaviors/registry/ui/core/molecules/ui-floating-toolbar.orb +53 -1
  159. package/behaviors/registry/ui/core/molecules/ui-form-actions.orb +53 -1
  160. package/behaviors/registry/ui/core/molecules/ui-graph-canvas.orb +53 -1
  161. package/behaviors/registry/ui/core/molecules/ui-menu.orb +57 -1
  162. package/behaviors/registry/ui/core/molecules/ui-meter.orb +53 -1
  163. package/behaviors/registry/ui/core/molecules/ui-modal.orb +8 -0
  164. package/behaviors/registry/ui/core/molecules/ui-page-header.orb +60 -1
  165. package/behaviors/registry/ui/core/molecules/ui-page-transition.orb +1 -1
  166. package/behaviors/registry/ui/core/molecules/ui-swipeable-row.orb +393 -23
  167. package/behaviors/registry/ui/core/molecules/ui-table-view.orb +189 -3
  168. package/behaviors/registry/ui/core/molecules/ui-tabs.orb +99 -2
  169. package/behaviors/registry/ui/core/organisms/ui-detail-panel.orb +282 -20
  170. package/behaviors/registry/ui/core/organisms/ui-entity-cards.orb +130 -3
  171. package/behaviors/registry/ui/core/organisms/ui-entity-list.orb +130 -3
  172. package/behaviors/registry/ui/core/organisms/ui-entity-table.orb +367 -9
  173. package/behaviors/registry/ui/core/organisms/ui-form-section.orb +104 -13
  174. package/behaviors/registry/ui/core/organisms/ui-form.orb +104 -13
  175. package/behaviors/registry/ui/core/organisms/ui-media-gallery.orb +121 -3
  176. package/behaviors/registry/ui/core/organisms/ui-state-machine-view.orb +82 -0
  177. package/behaviors/registry/ui/core/organisms/ui-timeline.orb +121 -3
  178. package/behaviors/registry/ui/core/templates/ui-counter-template.orb +1 -172
  179. package/behaviors/registry/ui/core/templates/ui-dashboard-layout.orb +53 -1
  180. package/behaviors/registry/ui/core/templates/ui-generic-app-template.orb +1 -116
  181. package/behaviors/registry/ui/game/atoms/ui-game-menu.orb +99 -2
  182. package/behaviors/registry/ui/game/organisms/std-arcade-board-3d.orb +10 -0
  183. package/behaviors/registry/ui/game/organisms/std-crew-board-2d.orb +0 -7
  184. package/behaviors/registry/ui/game/organisms/std-platformer-puzzle.orb +1 -807
  185. package/behaviors/registry/ui/game/organisms/std-tactics-board-2d.orb +0 -7
  186. package/behaviors/registry/ui/game/organisms/std-worldmap-board-2d.orb +0 -7
  187. package/behaviors/registry/ui/learning/atoms/std-learn-stepper.orb +6 -0
  188. package/canonical-operators.json +18 -1
  189. package/dist/behaviors/exports-reader.js +7662 -3762
  190. package/dist/behaviors/functions/index.d.ts +309 -104
  191. package/dist/behaviors/functions/index.js +7651 -3762
  192. package/dist/behaviors/index.d.ts +1 -1
  193. package/dist/behaviors/index.js +7663 -3763
  194. package/dist/behaviors/query.js +7662 -3762
  195. package/dist/behaviors-embeddings.hash.json +3 -3
  196. package/dist/behaviors-embeddings.json +35 -27
  197. package/dist/behaviors-registry.json +4402 -1898
  198. package/dist/index.d.ts +3 -3
  199. package/dist/index.js +7680 -3763
  200. package/dist/knob-embeddings.hash.json +3 -3
  201. package/dist/knob-embeddings.json +612 -352
  202. package/dist/modules/anim.d.ts +1 -1
  203. package/dist/modules/array.d.ts +1 -1
  204. package/dist/modules/array.js +15 -0
  205. package/dist/modules/async.d.ts +1 -1
  206. package/dist/modules/behavior.d.ts +1 -1
  207. package/dist/modules/browser.d.ts +1 -1
  208. package/dist/modules/composition.d.ts +1 -1
  209. package/dist/modules/contract.d.ts +1 -1
  210. package/dist/modules/core.d.ts +1 -1
  211. package/dist/modules/core.js +2 -0
  212. package/dist/modules/data.d.ts +1 -1
  213. package/dist/modules/ease.d.ts +1 -1
  214. package/dist/modules/format.d.ts +1 -1
  215. package/dist/modules/geo.d.ts +1 -1
  216. package/dist/modules/graph.d.ts +1 -1
  217. package/dist/modules/grid.d.ts +1 -1
  218. package/dist/modules/index.d.ts +1 -1
  219. package/dist/modules/index.js +17 -0
  220. package/dist/modules/integration.d.ts +1 -1
  221. package/dist/modules/json.d.ts +1 -1
  222. package/dist/modules/llm.d.ts +1 -1
  223. package/dist/modules/math.d.ts +1 -1
  224. package/dist/modules/memory.d.ts +1 -1
  225. package/dist/modules/nn.d.ts +1 -1
  226. package/dist/modules/noise.d.ts +1 -1
  227. package/dist/modules/object.d.ts +1 -1
  228. package/dist/modules/os.d.ts +1 -1
  229. package/dist/modules/path.d.ts +1 -1
  230. package/dist/modules/prob.d.ts +1 -1
  231. package/dist/modules/session.d.ts +1 -1
  232. package/dist/modules/str.d.ts +1 -1
  233. package/dist/modules/tensor.d.ts +1 -1
  234. package/dist/modules/time.d.ts +1 -1
  235. package/dist/modules/trace.d.ts +1 -1
  236. package/dist/modules/train.d.ts +1 -1
  237. package/dist/modules/validate.d.ts +1 -1
  238. package/dist/modules/vector.d.ts +1 -1
  239. package/dist/modules/workspace.d.ts +1 -1
  240. package/dist/registry/factory-signatures.json +1 -1
  241. package/dist/registry.d.ts +2 -2
  242. package/dist/registry.js +17 -0
  243. package/dist/{types-Ggla7OK7.d.ts → types-DLx38UFZ.d.ts} +23 -3
  244. package/package.json +2 -2
@@ -1,6 +1,7 @@
1
1
  app std-selection "1.0.0"
2
2
  "std-selection as a Function"
3
3
  type FilterSpec = { field : string!, label : string, options : [string] }
4
+ type ItemAction = { label : string!, event : event, icon : string, roles : [string], when : SExpr }
4
5
  orbital SelectableItemOrbital {
5
6
  type SelectableItemLoaded = Event { data : [SelectableItem] } "Fired when SelectableItem finishes loading; payload.data holds the list"
6
7
 
@@ -86,11 +87,7 @@ orbital SelectableItemOrbital {
86
87
  className: "transition-shadow hover:shadow-md cursor-pointer"
87
88
  entity: ?data
88
89
  fields: []
89
- itemActions: [{
90
- event: SELECT
91
- icon: check
92
- label: Select
93
- }]
90
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
94
91
  look: @config.tableLook
95
92
  pageSize: @config.displayPageSize
96
93
  renderItem: (fn item {
@@ -220,11 +217,7 @@ orbital SelectableItemOrbital {
220
217
  className: "transition-shadow hover:shadow-md cursor-pointer"
221
218
  entity: ?data
222
219
  fields: []
223
- itemActions: [{
224
- event: SELECT
225
- icon: check
226
- label: Select
227
- }]
220
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
228
221
  look: @config.tableLook
229
222
  pageSize: @config.displayPageSize
230
223
  renderItem: (fn item {
@@ -467,6 +460,18 @@ orbital SelectableItemOrbital {
467
460
  @description "Rows visible per page before the data-grid's own pagination control appears — 20 matches the pick-list density sweet spot (Miller's law, 10-25 rows)."
468
461
  @synonyms "visible rows, items per page, display limit, show per page"
469
462
  @tier "presentation"
463
+ itemActions : [ItemAction] = [{
464
+ event: SELECT
465
+ icon: check
466
+ label: Select
467
+ }]
468
+ @label "Row actions"
469
+ @description "Actions offered on each row; give an item `roles` to show it only to those viewer roles."
470
+ @tier "presentation"
471
+ viewerRole : string = ""
472
+ @label "Viewer's role"
473
+ @description "The signed-in viewer's role that each action's `roles` is checked against. Bind it explicitly at the call site (e.g. `viewerRole: @user.role`) in an app whose identity carries a role; left empty, only actions with no `roles` show."
474
+ @tier "policy"
470
475
  }
471
476
  }
472
477
 
@@ -115,7 +115,7 @@ orbital StatsItemOrbital {
115
115
  @description "One stat card per entry; declares aggregation, format, and styling"
116
116
  @synonyms "list of KPI cards / stat tiles / metric cards. each entry has label / value / format / icon / variant / aggregation. user phrases: 'replace metrics with X, Y, Z' -> rewrite array; 'add Revenue tile' -> append entry; 'change KPIs to X' -> rewrite array"
117
117
  @tier "presentation"
118
- title : string = Summary
118
+ title : string = ""
119
119
  @label "Section title"
120
120
  @description "Heading shown above the stat-card grid"
121
121
  @synonyms "the section header text. user phrases: 'rename section to X' / 'title the KPIs X' / 'change section title to X' -> X"
@@ -137,7 +137,7 @@ orbital StatsItemOrbital {
137
137
  @label "Stats look"
138
138
  @description "Layer 3 body layout: default per-metric stat-card grid ('cards'), Stripe-dashboard KPI tile row ('kpi-tiles'), single oversize hero number ('hero-metric'), or chart-first sparkline tile grid ('sparkline-row')."
139
139
  @tier "presentation"
140
- bodyContent : render-ui = { data-theme: @config.theme, type: box, children: [{
140
+ bodyContent : render-ui = { data-theme: @config.theme, type: box, children: [(if ["!=", @config.title, ""] { content: @config.title, type: typography, variant: h3 } { children: [], gap: none, type: stack }), {
141
141
  entity: @entity.cards
142
142
  fields: []
143
143
  renderItem: (fn card {
@@ -163,7 +163,7 @@ orbital StatsItemOrbital {
163
163
  @label "Body content tree"
164
164
  @description "Render-ui SExpr rendered after metrics aggregate for statsLook='cards' — the canonical data-grid call mapping @entity.cards through stat-display. Other statsLook values render kpiTilesBodyContent / heroMetricBodyContent / sparklineRowBodyContent instead; all four share this trait's state machine, aggregation pipeline, and listens."
165
165
  @tier "internal"
166
- kpiTilesBodyContent : render-ui = { data-theme: @config.theme, type: box, children: [{
166
+ kpiTilesBodyContent : render-ui = { data-theme: @config.theme, type: box, children: [(if ["!=", @config.title, ""] { content: @config.title, type: typography, variant: h3 } { children: [], gap: none, type: stack }), {
167
167
  className: w-full
168
168
  entity: @entity.cards
169
169
  fields: []
@@ -239,7 +239,7 @@ orbital StatsItemOrbital {
239
239
  @label "KPI tiles body content tree"
240
240
  @description "Render-ui SExpr for statsLook='kpi-tiles' — Stripe-dashboard style tile grid: huge typography number, label, trend indicator, sparkline hint."
241
241
  @tier "internal"
242
- heroMetricBodyContent : render-ui = { data-theme: @config.theme, type: box, children: [{
242
+ heroMetricBodyContent : render-ui = { data-theme: @config.theme, type: box, children: [(if ["!=", @config.title, ""] { content: @config.title, type: typography, variant: h3 } { children: [], gap: none, type: stack }), {
243
243
  entity: @entity.cards
244
244
  fields: []
245
245
  gap: none
@@ -324,7 +324,7 @@ orbital StatsItemOrbital {
324
324
  @label "Hero metric body content tree"
325
325
  @description "Render-ui SExpr for statsLook='hero-metric' — one elevated card, one oversize number, background sparkline."
326
326
  @tier "internal"
327
- sparklineRowBodyContent : render-ui = { data-theme: @config.theme, type: box, children: [{
327
+ sparklineRowBodyContent : render-ui = { data-theme: @config.theme, type: box, children: [(if ["!=", @config.title, ""] { content: @config.title, type: typography, variant: h3 } { children: [], gap: none, type: stack }), {
328
328
  className: w-full
329
329
  entity: @entity.cards
330
330
  fields: []
@@ -126,6 +126,7 @@ orbital TagTaxonomyOrbital {
126
126
  padding: sm
127
127
  type: card
128
128
  })
129
+ look: @config.tableLook
129
130
  type: data-grid
130
131
  }]
131
132
  direction: vertical
@@ -278,6 +279,7 @@ orbital TagTaxonomyOrbital {
278
279
  padding: sm
279
280
  type: card
280
281
  })
282
+ look: @config.tableLook
281
283
  type: data-grid
282
284
  }]
283
285
  direction: vertical
@@ -490,6 +492,7 @@ orbital TagTaxonomyOrbital {
490
492
  padding: sm
491
493
  type: card
492
494
  })
495
+ look: @config.tableLook
493
496
  type: data-grid
494
497
  }]
495
498
  direction: vertical
@@ -1,6 +1,11 @@
1
1
  app std-thread "1.3.0"
2
- "std-thread — forum-style nested replies with collapse + flat-mode toggle. Owns ThreadPost (persistent). flat:true covers 1:1 linear inquiry threads; flat:false renders forum-style nested. INIT fetches, scoped by @config.threadRootId when set (blank = every root, the default). REPLY persists a child post under @payload.parentId, stamped with the real @user identity. A consumer that mounts this as page comments forwards its own document-opened signal to SET_THREAD_ROOT { rootId }, which stamps @entity.replyRootId (scratch — the persisted threadRootId column is written only by the reply persist create) and refetches filtered by the payload; a plain INIT re-entry now also falls back through @entity.replyRootId before @config.threadRootId, so it stays scoped to the last SET_THREAD_ROOT instead of re-widening — only the after-create/after-select refetches still scope directly off their own event payload. Layer 3 variants override `bodyContent` to deliver chat-bubble, email-threaded, or linear-comments UX while inheriting the same trait, state machine, emits, and listens. A non-empty sectionTitle switches the default bodyContent into titled-comments mode: header + post list + a standalone composer button (without it an empty thread has no REPLY emitter at all — the affordance only existed per-row)."
2
+ "std-thread — forum-style nested replies with collapse. Owns ThreadPost (persistent). INIT fetches, scoped by @config.threadRootId when set (blank = every root, the default). REPLY persists a child post under @payload.parentId, stamped with the real @user identity. A consumer that mounts this as page comments forwards its own document-opened signal to SET_THREAD_ROOT { rootId }, which stamps @entity.replyRootId (scratch — the persisted threadRootId column is written only by the reply persist create) and refetches filtered by the payload; a plain INIT re-entry now also falls back through @entity.replyRootId before @config.threadRootId, so it stays scoped to the last SET_THREAD_ROOT instead of re-widening — only the after-create/after-select refetches still scope directly off their own event payload. Layer 3 variants override `bodyContent` to deliver chat-bubble, email-threaded, or linear-comments UX while inheriting the same trait, state machine, emits, and listens. A non-empty sectionTitle switches the default bodyContent into titled-comments mode: header + post list + a standalone composer button (without it an empty thread has no REPLY emitter at all — the affordance only existed per-row)."
3
+ type ItemAction = { label : string!, event : event, icon : string, roles : [string], when : SExpr }
3
4
  orbital ThreadPostOrbital {
5
+ uses RoleGate from "std/behaviors/std-role-gate"
6
+
7
+ uses Button from "std/behaviors/ui-button"
8
+
4
9
  ;; Forward relation: array of child ThreadPost IDs whose parentId === this.id.
5
10
  ;; Lowers to `type: "relation", cardinality: "many"` (orbital-lolo lower.rs).
6
11
  ;; @rebindable rewrites the target to the rebound entity in variant atoms.
@@ -381,10 +386,6 @@ orbital ThreadPostOrbital {
381
386
  }
382
387
 
383
388
  config {
384
- flat : boolean = false
385
- @label "Flat thread"
386
- @description "Render replies as a linear list instead of nested tree"
387
- @tier "presentation"
388
389
  threadRootId : string = ""
389
390
  @label "Root post id"
390
391
  @description "Top-level post whose descendants are loaded, filters every fetch and defaults new top-level replies' threadRootId (blank = all roots, unfiltered)"
@@ -394,10 +395,6 @@ orbital ThreadPostOrbital {
394
395
  @label "Table look"
395
396
  @description "Layer 2 visual treatment for the data table rendered by this atom."
396
397
  @tier "presentation"
397
- recipientName : string = Conversation
398
- @label "recipientName"
399
- @description "Header/recipient label for chat-style threads."
400
- @tier "presentation"
401
398
  sectionTitle : string = ""
402
399
  @label "sectionTitle"
403
400
  @description "Section header rendered by the default bodyContent when non-empty, along with a standalone composer button — the only REPLY affordance an empty thread has. Blank (the default) keeps the bare post list for embedded threads that bring their own chrome (chat rails, custom comment sections)."
@@ -408,58 +405,6 @@ orbital ThreadPostOrbital {
408
405
  @description "Label of the standalone composer button rendered under the post list when sectionTitle is non-empty."
409
406
  @synonyms "reply label, comment button, add comment"
410
407
  @tier "presentation"
411
- emailAuthorBinding : string = @item.authorName
412
- @label "emailAuthorBinding"
413
- @description "List-pane binding for the message author."
414
- @tier "presentation"
415
- emailSubjectBinding : string = @item.subject
416
- @label "emailSubjectBinding"
417
- @description "List-pane binding for the message subject."
418
- @tier "presentation"
419
- emailPreviewBinding : string = @item.preview
420
- @label "emailPreviewBinding"
421
- @description "List-pane binding for the message preview text."
422
- @tier "presentation"
423
- detailSubjectBinding : string = @entity.focusedRow.subject
424
- @label "detailSubjectBinding"
425
- @description "Detail-pane binding for the focused message subject."
426
- @tier "presentation"
427
- detailAuthorBinding : string = @entity.focusedRow.authorName
428
- @label "detailAuthorBinding"
429
- @description "Detail-pane binding for the focused message author."
430
- @tier "presentation"
431
- detailFromBinding : string = @entity.focusedRow.fromAddress
432
- @label "detailFromBinding"
433
- @description "Detail-pane binding for the From address."
434
- @tier "presentation"
435
- detailToBinding : string = @entity.focusedRow.toAddress
436
- @label "detailToBinding"
437
- @description "Detail-pane binding for the To address."
438
- @tier "presentation"
439
- detailDateBinding : string = @entity.focusedRow.createdAt
440
- @label "detailDateBinding"
441
- @description "Detail-pane binding for the timestamp."
442
- @tier "presentation"
443
- detailContentBinding : string = @entity.focusedRow.content
444
- @label "detailContentBinding"
445
- @description "Detail-pane binding for the message body."
446
- @tier "presentation"
447
- replyAuthorBinding : string = @reply.authorName
448
- @label "replyAuthorBinding"
449
- @description "Reply binding for the reply author."
450
- @tier "presentation"
451
- replyFromBinding : string = @reply.fromAddress
452
- @label "replyFromBinding"
453
- @description "Reply binding for the reply From address."
454
- @tier "presentation"
455
- replyDateBinding : string = @reply.createdAt
456
- @label "replyDateBinding"
457
- @description "Reply binding for the reply timestamp."
458
- @tier "presentation"
459
- replyContentBinding : string = @reply.content
460
- @label "replyContentBinding"
461
- @description "Reply binding for the reply body."
462
- @tier "presentation"
463
408
  bodyContent : render-ui = {
464
409
  children: [(if ["!=", @config.sectionTitle, ""] {
465
410
  content: @config.sectionTitle
@@ -485,21 +430,11 @@ orbital ThreadPostOrbital {
485
430
  variant: caption
486
431
  }]
487
432
  gap: sm
488
- itemActions: [{
489
- event: REPLY
490
- icon: message-square
491
- label: Reply
492
- }]
433
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
493
434
  look: @config.tableLook
494
435
  type: data-list
495
436
  variant: card
496
- }, (if ["!=", @config.sectionTitle, ""] {
497
- action: REPLY
498
- icon: message-square
499
- label: @config.composerLabel
500
- type: button
501
- variant: secondary
502
- } {
437
+ }, (if ["!=", @config.sectionTitle, ""] <trait.ThreadReplyGate /> {
503
438
  children: []
504
439
  gap: none
505
440
  type: stack
@@ -511,6 +446,39 @@ orbital ThreadPostOrbital {
511
446
  @label "Body content tree"
512
447
  @description "Render-ui SExpr rendered after thread posts load. Default is the canonical forum-style data-list. Layer 3 variants override this with their own tree (chat bubbles, email-threaded cards, linear comment stacks, etc.) to deliver entirely different thread UX while inheriting the same trait, state machine, emits, and listens."
513
448
  @tier "internal"
449
+ itemActions : [ItemAction] = [{
450
+ event: REPLY
451
+ icon: message-square
452
+ label: Reply
453
+ }]
454
+ @label "Row actions"
455
+ @description "Actions offered on each row; give an item `roles` to show it only to those viewer roles."
456
+ @tier "presentation"
457
+ viewerRole : string = ""
458
+ @label "Viewer's role"
459
+ @description "The signed-in viewer's role that each action's `roles` is checked against. Bind it explicitly at the call site (e.g. `viewerRole: @user.role`) in an app whose identity carries a role; left empty, only actions with no `roles` show."
460
+ @tier "policy"
461
+ replyRoles : [string] = []
462
+ @label "Roles that can reply"
463
+ @description "Roles (matched against viewerRole) that see the thread's Reply button. Empty = everyone."
464
+ @tier "policy"
465
+ }
466
+ }
467
+
468
+ trait ThreadReplyButton = Button.traits.ButtonRender {
469
+ config {
470
+ action: REPLY
471
+ icon: message-square
472
+ label: @config.composerLabel
473
+ variant: secondary
474
+ }
475
+ }
476
+
477
+ trait ThreadReplyGate = RoleGate.traits.RoleGate {
478
+ config {
479
+ roles: @config.replyRoles
480
+ viewerRole: @config.viewerRole
481
+ content: <trait.ThreadReplyButton />
514
482
  }
515
483
  }
516
484
 
@@ -1,5 +1,6 @@
1
1
  app std-version-history "1.0.0"
2
2
  "std-version-history — wiki/CMS revision history with diff + rollback. Browses revisions; opens detail in `viewing_single`; compares the opened revision with the newest in `comparing`; Rollback emits RevisionRolledBack { row } for the consumer to restore onto its source document. `RevisionManage` is a rebindable single-entity trait: a consumer rebinds it to its own entity via `linkedEntity`. `config.scopeField` names the Revision field holding the parent document id; a page-mounted `{id}` route param scopes INIT's own fetch, and a consumer forwards SHOW_HISTORY { key } (via a `listens` override) to rescope the feed to one document — empty scopeField (default) or no id keeps today's unfiltered global feed. Rollback and retry refetches stay scoped."
3
+ type ItemAction = { label : string!, event : event, variant : string, icon : string, roles : [string], when : SExpr }
3
4
  orbital RevisionOrbital {
4
5
  type RevisionLoaded = Event { data : [Revision] } "Fired when the revision collection finishes loading"
5
6
 
@@ -79,17 +80,7 @@ orbital RevisionOrbital {
79
80
  variant: caption
80
81
  }]
81
82
  gap: sm
82
- itemActions: [{
83
- event: OPEN_REVISION
84
- icon: arrow-right
85
- label: Open
86
- variant: ghost
87
- }, {
88
- event: ROLLBACK
89
- icon: rotate-ccw
90
- label: Rollback
91
- variant: danger
92
- }]
83
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
93
84
  look: @config.tableLook
94
85
  type: data-grid
95
86
  }]
@@ -600,6 +591,24 @@ orbital RevisionOrbital {
600
591
  @label "Scope field"
601
592
  @description "Revision entity field holding the parent document's id. When set, a page-mounted {id} route param scopes INIT's fetch, and a SHOW_HISTORY { key } event rescopes the feed, to rows whose scopeField equals the id/key; rollback and retry refetches stay scoped too. Empty (default) or no id = unfiltered global feed, unchanged from prior behavior."
602
593
  @tier "domain"
594
+ itemActions : [ItemAction] = [{
595
+ event: OPEN_REVISION
596
+ icon: arrow-right
597
+ label: Open
598
+ variant: ghost
599
+ }, {
600
+ event: ROLLBACK
601
+ icon: rotate-ccw
602
+ label: Rollback
603
+ variant: danger
604
+ }]
605
+ @label "Row actions"
606
+ @description "Actions offered on each row; give an item `roles` to show it only to those viewer roles."
607
+ @tier "presentation"
608
+ viewerRole : string = ""
609
+ @label "Viewer's role"
610
+ @description "The signed-in viewer's role that each action's `roles` is checked against. Bind it explicitly at the call site (e.g. `viewerRole: @user.role`) in an app whose identity carries a role; left empty, only actions with no `roles` show."
611
+ @tier "policy"
603
612
  }
604
613
  }
605
614
 
@@ -235,10 +235,6 @@ orbital VoteOrbital {
235
235
  }
236
236
 
237
237
  config {
238
- allowDown : boolean = true
239
- @label "Allow downvotes"
240
- @description "Show the downvote arrow alongside the upvote"
241
- @tier "domain"
242
238
  }
243
239
  }
244
240
 
@@ -109,7 +109,7 @@ orbital WizardOrbital {
109
109
  }, { type: divider }, {
110
110
  cancelEvent: CANCEL
111
111
  entity: @entity
112
- fields: @entity.currentFields
112
+ fields: (array/map @entity.currentFields (fn f { name: @f }))
113
113
  mode: edit
114
114
  showCancel: false
115
115
  showSubmit: false
@@ -232,7 +232,7 @@ orbital WizardOrbital {
232
232
  }, { type: divider }, {
233
233
  cancelEvent: CANCEL
234
234
  entity: @entity
235
- fields: @entity.currentFields
235
+ fields: (array/map @entity.currentFields (fn f { name: @f }))
236
236
  mode: edit
237
237
  showCancel: false
238
238
  showSubmit: false
@@ -368,7 +368,7 @@ orbital WizardOrbital {
368
368
  }, { type: divider }, {
369
369
  cancelEvent: CANCEL
370
370
  entity: @entity
371
- fields: @entity.currentFields
371
+ fields: (array/map @entity.currentFields (fn f { name: @f }))
372
372
  mode: edit
373
373
  showCancel: false
374
374
  showSubmit: false
@@ -12,6 +12,9 @@ orbital PresenceOrbital {
12
12
  state idle {
13
13
  INIT -> idle
14
14
  (render-ui main {
15
+ animation: @config.animation
16
+ animate: @config.animate
17
+ onExited: @config.onExited
15
18
  show: @config.show
16
19
  className: @config.className
17
20
  children: @config.children
@@ -19,7 +22,25 @@ orbital PresenceOrbital {
19
22
  })
20
23
  }
21
24
 
25
+ emits {
26
+ @config.onExited -> external { }
27
+ @description "Fired after the exit animation completes (before unmount)."
28
+ @tier "essential"
29
+ }
30
+
22
31
  config {
32
+ animation : "modal" | "overlay" | "slide-up" | "drawer" | "popover" | "toast" | "fade" | "page" = modal
33
+ @label "Animation"
34
+ @description "Which motion preset to use (maps to `animate-<name>-in/out`)."
35
+ @tier "presentation"
36
+ animate : boolean
37
+ @label "Animate"
38
+ @description "Per-instance opt-out. Global opt-out is `--motion-enable` / reduced-motion. @default true"
39
+ @tier "presentation"
40
+ onExited : event = "EXITED"
41
+ @label "On Exited"
42
+ @description "Fired after the exit animation completes (before unmount)."
43
+ @tier "presentation"
23
44
  show : boolean = false
24
45
  @label "Show"
25
46
  @description "When false, the exit animation runs, then children unmount."
@@ -9,6 +9,7 @@ orbital BreadcrumbOrbital {
9
9
  icon : icon
10
10
  isCurrent : boolean
11
11
  event : event
12
+ roles : [string]
12
13
  }
13
14
 
14
15
  entity BreadcrumbItem [runtime] {
@@ -21,7 +22,7 @@ orbital BreadcrumbOrbital {
21
22
  state idle {
22
23
  INIT -> idle
23
24
  (render-ui main {
24
- items: @config.items
25
+ items: (array/filter @config.items (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
25
26
  fromNavStack: @config.fromNavStack
26
27
  itemEvent: @config.itemEvent
27
28
  separator: @config.separator
@@ -66,6 +67,10 @@ orbital BreadcrumbOrbital {
66
67
  @label "Class Name"
67
68
  @description "Additional CSS classes"
68
69
  @tier "presentation"
70
+ viewerRole : string = ""
71
+ @label "Viewer's role"
72
+ @description "The viewer's role that each action's `roles` is checked against; bind it at the call site (e.g. `viewerRole: @user.role`). Empty = only actions with no `roles` show."
73
+ @tier "policy"
69
74
  }
70
75
  }
71
76
 
@@ -30,6 +30,7 @@ orbital ChartOrbital {
30
30
  event : event
31
31
  navigatesTo : string
32
32
  variant : "primary" | "secondary" | "ghost"
33
+ roles : [string]
33
34
  }
34
35
  type ChartError = {
35
36
  message : string!
@@ -60,8 +61,9 @@ orbital ChartOrbital {
60
61
  showValues: @config.showValues
61
62
  stack: @config.stack
62
63
  timeAxis: @config.timeAxis
64
+ period: @config.period
63
65
  drillEvent: @config.drillEvent
64
- actions: @config.actions
66
+ actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
65
67
  isLoading: @config.isLoading
66
68
  error: @config.error
67
69
  className: @config.className
@@ -120,6 +122,10 @@ orbital ChartOrbital {
120
122
  @label "Time Axis"
121
123
  @description "Format X-axis labels as time (ISO date in → 'Mar 2026'-style label out)"
122
124
  @tier "presentation"
125
+ period : "day" | "week" | "month" | "quarter" | "year" = day
126
+ @label "Period"
127
+ @description "Bucket granularity of a time axis — labels read 'Oct 2', 'Week of Sep 28', 'Oct 2026', 'Q4 2026' or '2026'"
128
+ @tier "presentation"
123
129
  drillEvent : string
124
130
  @label "Drill Event"
125
131
  @description "Event name emitted as `UI:{drillEvent}` with `{ label, value, seriesLabel? }` on data-point click"
@@ -140,6 +146,10 @@ orbital ChartOrbital {
140
146
  @label "Class Name"
141
147
  @description "Additional CSS classes"
142
148
  @tier "presentation"
149
+ viewerRole : string = ""
150
+ @label "Viewer's role"
151
+ @description "The viewer's role that each action's `roles` is checked against; bind it at the call site (e.g. `viewerRole: @user.role`). Empty = only actions with no `roles` show."
152
+ @tier "policy"
143
153
  }
144
154
  }
145
155
 
@@ -18,6 +18,7 @@ orbital CodeBlockOrbital {
18
18
  event : event
19
19
  navigatesTo : string
20
20
  variant : "primary" | "secondary" | "ghost"
21
+ roles : [string]
21
22
  }
22
23
  type CodeBlockError = {
23
24
  message : string!
@@ -66,7 +67,7 @@ orbital CodeBlockOrbital {
66
67
  showLineNumbers: @config.showLineNumbers
67
68
  wordWrap: @config.wordWrap
68
69
  files: @config.files
69
- actions: @config.actions
70
+ actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
70
71
  isLoading: @config.isLoading
71
72
  error: @config.error
72
73
  showCopy: @config.showCopy
@@ -106,7 +107,7 @@ orbital CodeBlockOrbital {
106
107
  showLineNumbers: @config.showLineNumbers
107
108
  wordWrap: @config.wordWrap
108
109
  files: @config.files
109
- actions: @config.actions
110
+ actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
110
111
  isLoading: @config.isLoading
111
112
  error: @config.error
112
113
  showCopy: @config.showCopy
@@ -146,7 +147,7 @@ orbital CodeBlockOrbital {
146
147
  showLineNumbers: @config.showLineNumbers
147
148
  wordWrap: @config.wordWrap
148
149
  files: @config.files
149
- actions: @config.actions
150
+ actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
150
151
  isLoading: @config.isLoading
151
152
  error: @config.error
152
153
  showCopy: @config.showCopy
@@ -186,7 +187,7 @@ orbital CodeBlockOrbital {
186
187
  showLineNumbers: @config.showLineNumbers
187
188
  wordWrap: @config.wordWrap
188
189
  files: @config.files
189
- actions: @config.actions
190
+ actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
190
191
  isLoading: @config.isLoading
191
192
  error: @config.error
192
193
  showCopy: @config.showCopy
@@ -226,7 +227,7 @@ orbital CodeBlockOrbital {
226
227
  showLineNumbers: @config.showLineNumbers
227
228
  wordWrap: @config.wordWrap
228
229
  files: @config.files
229
- actions: @config.actions
230
+ actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
230
231
  isLoading: @config.isLoading
231
232
  error: @config.error
232
233
  showCopy: @config.showCopy
@@ -266,7 +267,7 @@ orbital CodeBlockOrbital {
266
267
  showLineNumbers: @config.showLineNumbers
267
268
  wordWrap: @config.wordWrap
268
269
  files: @config.files
269
- actions: @config.actions
270
+ actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
270
271
  isLoading: @config.isLoading
271
272
  error: @config.error
272
273
  showCopy: @config.showCopy
@@ -306,7 +307,7 @@ orbital CodeBlockOrbital {
306
307
  showLineNumbers: @config.showLineNumbers
307
308
  wordWrap: @config.wordWrap
308
309
  files: @config.files
309
- actions: @config.actions
310
+ actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
310
311
  isLoading: @config.isLoading
311
312
  error: @config.error
312
313
  showCopy: @config.showCopy
@@ -346,7 +347,7 @@ orbital CodeBlockOrbital {
346
347
  showLineNumbers: @config.showLineNumbers
347
348
  wordWrap: @config.wordWrap
348
349
  files: @config.files
349
- actions: @config.actions
350
+ actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
350
351
  isLoading: @config.isLoading
351
352
  error: @config.error
352
353
  showCopy: @config.showCopy
@@ -564,6 +565,10 @@ orbital CodeBlockOrbital {
564
565
  @label "Line Numbers"
565
566
  @description "Editable only: number the lines in a gutter (lines with errors in red). Default on."
566
567
  @tier "presentation"
568
+ viewerRole : string = ""
569
+ @label "Viewer's role"
570
+ @description "The viewer's role that each action's `roles` is checked against; bind it at the call site (e.g. `viewerRole: @user.role`). Empty = only actions with no `roles` show."
571
+ @tier "policy"
567
572
  }
568
573
  }
569
574
 
@@ -13,6 +13,7 @@ orbital CommandPaletteOrbital {
13
13
  event : event
14
14
  action : event
15
15
  actionPayload : @payload action
16
+ roles : [string]
16
17
  }
17
18
  type CommandPaletteSELECTCommand = {
18
19
  id : string!
@@ -41,7 +42,7 @@ orbital CommandPaletteOrbital {
41
42
  (render-ui main {
42
43
  open: @entity.open
43
44
  onOpenChange: @config.onOpenChange
44
- commands: @config.commands
45
+ commands: (array/filter @config.commands (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
45
46
  onSelect: @config.onSelect
46
47
  placeholder: @config.placeholder
47
48
  emptyLabel: @config.emptyLabel
@@ -53,7 +54,7 @@ orbital CommandPaletteOrbital {
53
54
  (render-ui main {
54
55
  open: @entity.open
55
56
  onOpenChange: @config.onOpenChange
56
- commands: @config.commands
57
+ commands: (array/filter @config.commands (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
57
58
  onSelect: @config.onSelect
58
59
  placeholder: @config.placeholder
59
60
  emptyLabel: @config.emptyLabel
@@ -110,6 +111,10 @@ orbital CommandPaletteOrbital {
110
111
  @label "Class Name"
111
112
  @description "Additional CSS classes on the overlay's dialog"
112
113
  @tier "presentation"
114
+ viewerRole : string = ""
115
+ @label "Viewer's role"
116
+ @description "The viewer's role that each action's `roles` is checked against; bind it at the call site (e.g. `viewerRole: @user.role`). Empty = only actions with no `roles` show."
117
+ @tier "policy"
113
118
  }
114
119
  }
115
120
 
@@ -104,9 +104,9 @@ orbital CommitRowOrbital {
104
104
  @label "Timestamp"
105
105
  @description "Display time (already formatted, e.g. '2 min ago')."
106
106
  @tier "presentation"
107
- kind : "user" | "agent" | "restore" | "undo" | "redo" | "snapshot" = user
107
+ kind : "user" | "agent" | "restore" | "undo" | "redo" | "snapshot" | "merge" = user
108
108
  @label "Kind"
109
- @description "What made this version (a user save, an agent turn, a restore, an undo/redo, a snapshot)."
109
+ @description "What made this version (a user save, an agent turn, a restore, an undo/redo, a snapshot, a merge of a teammate's work)."
110
110
  @tier "presentation"
111
111
  additions : number
112
112
  @label "Additions"
@@ -27,6 +27,7 @@ orbital ConfirmDialogOrbital {
27
27
  (render-ui modal {
28
28
  isOpen: @config.isOpen
29
29
  onClose: @config.onClose
30
+ onExited: @config.onExited
30
31
  onConfirm: @config.onConfirm
31
32
  title: @config.title
32
33
  message: @config.message
@@ -58,6 +59,9 @@ orbital ConfirmDialogOrbital {
58
59
  @config.onClose -> external { }
59
60
  @description "Callback when dialog is closed (injected by slot wrapper)"
60
61
  @tier "essential"
62
+ @config.onExited -> external { }
63
+ @description "Fires after the exit animation completes (the dialog is about to unmount)."
64
+ @tier "essential"
61
65
  @config.onConfirm -> external { }
62
66
  @description "Callback when action is confirmed (injected by slot wrapper)"
63
67
  @tier "essential"
@@ -77,6 +81,10 @@ orbital ConfirmDialogOrbital {
77
81
  @label "On Close"
78
82
  @description "Callback when dialog is closed (injected by slot wrapper)"
79
83
  @tier "presentation"
84
+ onExited : event = "EXITED"
85
+ @label "On Exited"
86
+ @description "Fires after the exit animation completes (the dialog is about to unmount)."
87
+ @tier "presentation"
80
88
  onConfirm : event = "CONFIRM"
81
89
  @label "On Confirm"
82
90
  @description "Callback when action is confirmed (injected by slot wrapper)"