@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
@@ -2,13 +2,15 @@ app ui-swipeable-row "1.0.0"
2
2
  "SwipeableRow — UI factory (1:1 with the @almadar/ui swipeable-row pattern)."
3
3
  ;; @pattern "swipeable-row"
4
4
  orbital SwipeableRowOrbital {
5
- type SwipeableRowLoaded = Event { data : [SwipeableRowItem] } "SwipeableRow rows finished loading; payload.data holds the collection"
5
+ type SwipeableRowLoaded = Event { data : SwipeableRowItem } "SwipeableRow row finished loading; payload.data holds the single row"
6
6
  type SwipeableRowLeftActionsItem = {
7
7
  label : string!
8
8
  icon : icon
9
9
  variant : "primary" | "secondary" | "danger" | "ghost"
10
10
  event : event!
11
11
  eventPayload : @payload event
12
+ when : SExpr
13
+ roles : [string]
12
14
  }
13
15
  type SwipeableRowRightActionsItem = {
14
16
  label : string!
@@ -16,6 +18,8 @@ orbital SwipeableRowOrbital {
16
18
  variant : "primary" | "secondary" | "danger" | "ghost"
17
19
  event : event!
18
20
  eventPayload : @payload event
21
+ when : SExpr
22
+ roles : [string]
19
23
  }
20
24
 
21
25
  entity SwipeableRowItem [runtime] {
@@ -23,24 +27,37 @@ orbital SwipeableRowOrbital {
23
27
  }
24
28
 
25
29
  trait SwipeableRowRender -> @rebindable SwipeableRowItem [interaction, instance] {
26
- initial: idle
30
+ initial: resolving
27
31
 
28
- state idle {
29
- INIT -> idle when @config.selfFetch
30
- (fetch SwipeableRowItem { emit: { success: SwipeableRowLoaded } })
32
+ state resolving {
33
+ INIT -> idle when (and @config.selfFetch (!= (str/default ?id "") ""))
34
+ (fetch SwipeableRowItem { id: ?id, emit: { success: SwipeableRowLoaded } })
35
+ (render-ui main {
36
+ leftActions: (array/filter @config.leftActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
37
+ rightActions: (array/filter @config.rightActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
38
+ threshold: @config.threshold
39
+ children: @config.children
40
+ itemData: @entity
41
+ className: @config.className
42
+ type: swipeable-row
43
+ })
44
+ INIT -> idle when (not (and @config.selfFetch (!= (str/default ?id "") "")))
31
45
  (render-ui main {
32
- leftActions: @config.leftActions
33
- rightActions: @config.rightActions
46
+ leftActions: (array/filter @config.leftActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
47
+ rightActions: (array/filter @config.rightActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
34
48
  threshold: @config.threshold
35
49
  children: @config.children
36
50
  itemData: @entity
37
51
  className: @config.className
38
52
  type: swipeable-row
39
53
  })
40
- INIT -> idle when (not @config.selfFetch)
54
+ }
55
+
56
+ state idle {
57
+ INIT -> idle
41
58
  (render-ui main {
42
- leftActions: @config.leftActions
43
- rightActions: @config.rightActions
59
+ leftActions: (array/filter @config.leftActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
60
+ rightActions: (array/filter @config.rightActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
44
61
  threshold: @config.threshold
45
62
  children: @config.children
46
63
  itemData: @entity
@@ -49,8 +66,8 @@ orbital SwipeableRowOrbital {
49
66
  })
50
67
  SwipeableRowLoaded -> idle
51
68
  (render-ui main {
52
- leftActions: @config.leftActions
53
- rightActions: @config.rightActions
69
+ leftActions: (array/filter @config.leftActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
70
+ rightActions: (array/filter @config.rightActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
54
71
  threshold: @config.threshold
55
72
  children: @config.children
56
73
  itemData: @payload.data
@@ -61,11 +78,19 @@ orbital SwipeableRowOrbital {
61
78
 
62
79
  emits {
63
80
  SwipeableRowLoaded
64
- @description "SwipeableRow rows finished loading; payload.data holds the collection."
81
+ @description "SwipeableRow row finished loading; payload.data holds the single row."
65
82
  @synonyms "loaded, fetched, retrieved"
66
83
  @tier "essential"
67
84
  }
68
85
 
86
+ listens {
87
+ INIT {
88
+ id : string
89
+ }
90
+ @description "Mount payload; a host that routes to this panel by id (a :id page param) passes it here."
91
+ @tier "internal"
92
+ }
93
+
69
94
  config {
70
95
  leftActions : [SwipeableRowLeftActionsItem] = []
71
96
  @label "Left Actions"
@@ -87,9 +112,13 @@ orbital SwipeableRowOrbital {
87
112
  @label "Class Name"
88
113
  @description "className prop"
89
114
  @tier "presentation"
115
+ viewerRole : string = ""
116
+ @label "Viewer's role"
117
+ @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."
118
+ @tier "policy"
90
119
  selfFetch : boolean = true
91
- @label "Fetch its own rows on mount?"
92
- @description "true (default) = standalone mount self-populates on INIT. false = a composing atom owns the fetch and routes its loaded event here — suppresses the wrapper's own un-hydrated fetch so it cannot race the composer's."
120
+ @label "Fetch its own row on mount?"
121
+ @description "true (default) = a mount that carries an id loads that one row (never the collection); a create-mode mount skips the load. false = a composing atom owns the load."
93
122
  @tier "internal"
94
123
  }
95
124
  }
@@ -4,6 +4,10 @@ app ui-table-view "1.0.0"
4
4
  ;; @pattern "table-view"
5
5
  orbital TableViewOrbital {
6
6
  type TableViewLoaded = Event { data : [TableViewItem] } "TableView rows finished loading; payload.data holds the collection"
7
+ type TableViewEmptyAction = {
8
+ label : string!
9
+ event : event
10
+ }
7
11
  type TableViewColumnsItem = {
8
12
  key : string!
9
13
  field : string
@@ -35,6 +39,8 @@ orbital TableViewOrbital {
35
39
  event : event!
36
40
  icon : icon
37
41
  variant : "primary" | "secondary" | "ghost" | "danger"
42
+ when : SExpr
43
+ roles : [string]
38
44
  }
39
45
  type TableViewError = {
40
46
  message : string!
@@ -68,10 +74,14 @@ orbital TableViewOrbital {
68
74
  positionEvent: @config.positionEvent
69
75
  dndItemIdField: @config.dndItemIdField
70
76
  dndRoot: @config.dndRoot
77
+ emptyIcon: @config.emptyIcon
78
+ emptyTitle: @config.emptyTitle
79
+ emptyDescription: @config.emptyDescription
80
+ emptyAction: @config.emptyAction
71
81
  entity: @entity
72
82
  columns: @config.columns
73
83
  fields: @config.fields
74
- itemActions: @config.itemActions
84
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
75
85
  maxInlineActions: @config.maxInlineActions
76
86
  itemClickEvent: @config.itemClickEvent
77
87
  selectable: @config.selectable
@@ -100,10 +110,14 @@ orbital TableViewOrbital {
100
110
  positionEvent: @config.positionEvent
101
111
  dndItemIdField: @config.dndItemIdField
102
112
  dndRoot: @config.dndRoot
113
+ emptyIcon: @config.emptyIcon
114
+ emptyTitle: @config.emptyTitle
115
+ emptyDescription: @config.emptyDescription
116
+ emptyAction: @config.emptyAction
103
117
  entity: @entity
104
118
  columns: @config.columns
105
119
  fields: @config.fields
106
- itemActions: @config.itemActions
120
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
107
121
  maxInlineActions: @config.maxInlineActions
108
122
  itemClickEvent: @config.itemClickEvent
109
123
  selectable: @config.selectable
@@ -132,10 +146,14 @@ orbital TableViewOrbital {
132
146
  positionEvent: @config.positionEvent
133
147
  dndItemIdField: @config.dndItemIdField
134
148
  dndRoot: @config.dndRoot
149
+ emptyIcon: @config.emptyIcon
150
+ emptyTitle: @config.emptyTitle
151
+ emptyDescription: @config.emptyDescription
152
+ emptyAction: @config.emptyAction
135
153
  entity: @payload.data
136
154
  columns: @config.columns
137
155
  fields: @config.fields
138
- itemActions: @config.itemActions
156
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
139
157
  maxInlineActions: @config.maxInlineActions
140
158
  itemClickEvent: @config.itemClickEvent
141
159
  selectable: @config.selectable
@@ -213,6 +231,22 @@ orbital TableViewOrbital {
213
231
  @label "Dnd Root"
214
232
  @description "Mark this container as the DnD root for its subtree — descendant zones share one DndContext (cross-container drag). Use on an outer container whose own items are not draggable."
215
233
  @tier "presentation"
234
+ emptyIcon : icon
235
+ @label "Empty Icon"
236
+ @description "Domain icon for the empty state."
237
+ @tier "presentation"
238
+ emptyTitle : string
239
+ @label "Empty Title"
240
+ @description "Specific title ('No orders yet')."
241
+ @tier "presentation"
242
+ emptyDescription : string
243
+ @label "Empty Description"
244
+ @description "What will appear here once rows exist."
245
+ @tier "presentation"
246
+ emptyAction : TableViewEmptyAction
247
+ @label "Empty Action"
248
+ @description "Create-the-first-item action."
249
+ @tier "presentation"
216
250
  columns : [TableViewColumnsItem] = []
217
251
  @label "Columns"
218
252
  @description "Column definitions. The compiler emits `columns`; `fields` is the alias."
@@ -289,6 +323,10 @@ orbital TableViewOrbital {
289
323
  @label "Relations Data"
290
324
  @description "Relation display data: { fieldName: [{value, label}] } — injected server-side by the runtime (relation-option injection) or bound by compiled codegen; resolves stored foreign ids to display names for a column whose field is relation-typed. Same contract DetailPanel takes."
291
325
  @tier "presentation"
326
+ viewerRole : string = ""
327
+ @label "Viewer's role"
328
+ @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."
329
+ @tier "policy"
292
330
  selfFetch : boolean = true
293
331
  @label "Fetch its own rows on mount?"
294
332
  @description "true (default) = standalone mount self-populates on INIT. false = a composing atom owns the fetch and routes its loaded event here — suppresses the wrapper's own un-hydrated fetch so it cannot race the composer's."
@@ -13,6 +13,7 @@ orbital TabsOrbital {
13
13
  disabled : boolean
14
14
  event : event
15
15
  active : boolean
16
+ roles : [string]
16
17
  }
17
18
  type TabsItemsItemIconAsset = {
18
19
  url : asset!
@@ -39,6 +40,7 @@ orbital TabsOrbital {
39
40
  disabled : boolean
40
41
  event : event
41
42
  active : boolean
43
+ roles : [string]
42
44
  }
43
45
  type TabsTabsItemIconAsset = {
44
46
  url : asset!
@@ -65,8 +67,8 @@ orbital TabsOrbital {
65
67
  state idle {
66
68
  INIT -> idle
67
69
  (render-ui main {
68
- items: @config.items
69
- tabs: @config.tabs
70
+ items: (array/filter @config.items (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
71
+ tabs: (array/filter @config.tabs (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
70
72
  defaultActiveTab: @config.defaultActiveTab
71
73
  activeTab: @config.activeTab
72
74
  onTabChange: @config.onTabChange
@@ -123,6 +125,10 @@ orbital TabsOrbital {
123
125
  @label "Class Name"
124
126
  @description "Additional CSS classes"
125
127
  @tier "presentation"
128
+ viewerRole : string = ""
129
+ @label "Viewer's role"
130
+ @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."
131
+ @tier "policy"
126
132
  }
127
133
  }
128
134
 
@@ -2,7 +2,7 @@ app ui-detail-panel "1.0.0"
2
2
  "DetailPanel — UI factory (1:1 with the @almadar/ui detail-panel pattern)."
3
3
  ;; @pattern "detail-panel"
4
4
  orbital DetailPanelOrbital {
5
- type DetailPanelLoaded = Event { data : [DetailPanelItem] } "DetailPanel rows finished loading; payload.data holds the collection"
5
+ type DetailPanelLoaded = Event { data : DetailPanelItem } "DetailPanel row finished loading; payload.data holds the single row"
6
6
  type DetailPanelError = {
7
7
  message : string!
8
8
  name : string
@@ -29,6 +29,8 @@ orbital DetailPanelOrbital {
29
29
  event : event
30
30
  navigatesTo : string
31
31
  variant : "primary" | "secondary" | "ghost" | "danger"
32
+ when : SExpr
33
+ roles : [string]
32
34
  }
33
35
  type DetailPanelBackAction = {
34
36
  label : string!
@@ -36,6 +38,7 @@ orbital DetailPanelOrbital {
36
38
  event : event
37
39
  navigatesTo : string
38
40
  variant : "primary" | "secondary" | "ghost" | "danger"
41
+ when : SExpr
39
42
  }
40
43
  type DetailPanelFieldsItem = {
41
44
  key : string!
@@ -60,11 +63,11 @@ orbital DetailPanelOrbital {
60
63
  }
61
64
 
62
65
  trait DetailPanelRender -> @rebindable DetailPanelItem [interaction, instance] {
63
- initial: idle
66
+ initial: resolving
64
67
 
65
- state idle {
66
- INIT -> idle when @config.selfFetch
67
- (fetch DetailPanelItem { emit: { success: DetailPanelLoaded } })
68
+ state resolving {
69
+ INIT -> idle when (and @config.selfFetch (!= (str/default ?id "") "") (!= @config.mode "create"))
70
+ (fetch DetailPanelItem { id: ?id, emit: { success: DetailPanelLoaded } })
68
71
  (render-ui main {
69
72
  className: @config.className
70
73
  isLoading: @config.isLoading
@@ -84,7 +87,7 @@ orbital DetailPanelOrbital {
84
87
  status: @config.status
85
88
  avatar: @config.avatar
86
89
  sections: @config.sections
87
- actions: @config.actions
90
+ actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
88
91
  maxInlineActions: @config.maxInlineActions
89
92
  backAction: @config.backAction
90
93
  footer: @config.footer
@@ -100,7 +103,7 @@ orbital DetailPanelOrbital {
100
103
  relationsData: @config.relationsData
101
104
  type: detail-panel
102
105
  })
103
- INIT -> idle when (not @config.selfFetch)
106
+ INIT -> idle when (not (and @config.selfFetch (!= (str/default ?id "") "") (!= @config.mode "create")))
104
107
  (render-ui main {
105
108
  className: @config.className
106
109
  isLoading: @config.isLoading
@@ -120,7 +123,46 @@ orbital DetailPanelOrbital {
120
123
  status: @config.status
121
124
  avatar: @config.avatar
122
125
  sections: @config.sections
123
- actions: @config.actions
126
+ actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
127
+ maxInlineActions: @config.maxInlineActions
128
+ backAction: @config.backAction
129
+ footer: @config.footer
130
+ slideOver: @config.slideOver
131
+ fields: @config.fields
132
+ fieldNames: @config.fieldNames
133
+ initialData: @entity
134
+ mode: @config.mode
135
+ position: @config.position
136
+ width: @config.width
137
+ displayFields: @config.displayFields
138
+ showActions: @config.showActions
139
+ relationsData: @config.relationsData
140
+ type: detail-panel
141
+ })
142
+ }
143
+
144
+ state idle {
145
+ INIT -> idle
146
+ (render-ui main {
147
+ className: @config.className
148
+ isLoading: @config.isLoading
149
+ error: @config.error
150
+ sortBy: @config.sortBy
151
+ sortDirection: @config.sortDirection
152
+ searchValue: @config.searchValue
153
+ page: @config.pageProp
154
+ pageSize: @config.pageSize
155
+ totalCount: @config.totalCount
156
+ activeFilters: @config.activeFilters
157
+ selectedIds: @config.selectedIds
158
+ entity: @entity
159
+ title: @config.title
160
+ onTitleCommit: @config.onTitleCommit
161
+ subtitle: @config.subtitle
162
+ status: @config.status
163
+ avatar: @config.avatar
164
+ sections: @config.sections
165
+ actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
124
166
  maxInlineActions: @config.maxInlineActions
125
167
  backAction: @config.backAction
126
168
  footer: @config.footer
@@ -156,7 +198,7 @@ orbital DetailPanelOrbital {
156
198
  status: @config.status
157
199
  avatar: @config.avatar
158
200
  sections: @config.sections
159
- actions: @config.actions
201
+ actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
160
202
  maxInlineActions: @config.maxInlineActions
161
203
  backAction: @config.backAction
162
204
  footer: @config.footer
@@ -176,11 +218,19 @@ orbital DetailPanelOrbital {
176
218
 
177
219
  emits {
178
220
  DetailPanelLoaded
179
- @description "DetailPanel rows finished loading; payload.data holds the collection."
221
+ @description "DetailPanel row finished loading; payload.data holds the single row."
180
222
  @synonyms "loaded, fetched, retrieved"
181
223
  @tier "essential"
182
224
  }
183
225
 
226
+ listens {
227
+ INIT {
228
+ id : string
229
+ }
230
+ @description "Mount payload; a host that routes to this panel by id (a :id page param) passes it here."
231
+ @tier "internal"
232
+ }
233
+
184
234
  config {
185
235
  className : string
186
236
  @label "Class Name"
@@ -303,9 +353,13 @@ orbital DetailPanelOrbital {
303
353
  @label "Relations Data"
304
354
  @description "Relation display data: { fieldName: [{value, label}] } — injected server-side by the runtime (relation-option injection) or bound by compiled codegen; resolves stored foreign ids to display names."
305
355
  @tier "presentation"
356
+ viewerRole : string = ""
357
+ @label "Viewer's role"
358
+ @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."
359
+ @tier "policy"
306
360
  selfFetch : boolean = true
307
- @label "Fetch its own rows on mount?"
308
- @description "true (default) = standalone mount self-populates on INIT. false = a composing atom owns the fetch and routes its loaded event here — suppresses the wrapper's own un-hydrated fetch so it cannot race the composer's."
361
+ @label "Fetch its own row on mount?"
362
+ @description "true (default) = a mount that carries an id loads that one row (never the collection); a create-mode mount skips the load. false = a composing atom owns the load."
309
363
  @tier "internal"
310
364
  }
311
365
  }
@@ -27,6 +27,8 @@ orbital EntityCardsOrbital {
27
27
  navigatesTo : string
28
28
  placement : string
29
29
  variant : string
30
+ when : SExpr
31
+ roles : [string]
30
32
  }
31
33
 
32
34
  entity EntityCardsItem [runtime] {
@@ -60,7 +62,7 @@ orbital EntityCardsOrbital {
60
62
  fields: @config.fields
61
63
  fieldNames: @config.fieldNames
62
64
  columns: @config.columns
63
- itemActions: @config.itemActions
65
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
64
66
  showTotal: @config.showTotal
65
67
  showAvatar: @config.showAvatar
66
68
  variant: @config.variant
@@ -89,7 +91,7 @@ orbital EntityCardsOrbital {
89
91
  fields: @config.fields
90
92
  fieldNames: @config.fieldNames
91
93
  columns: @config.columns
92
- itemActions: @config.itemActions
94
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
93
95
  showTotal: @config.showTotal
94
96
  showAvatar: @config.showAvatar
95
97
  variant: @config.variant
@@ -118,7 +120,7 @@ orbital EntityCardsOrbital {
118
120
  fields: @config.fields
119
121
  fieldNames: @config.fieldNames
120
122
  columns: @config.columns
121
- itemActions: @config.itemActions
123
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
122
124
  showTotal: @config.showTotal
123
125
  showAvatar: @config.showAvatar
124
126
  variant: @config.variant
@@ -238,6 +240,10 @@ orbital EntityCardsOrbital {
238
240
  @label "Image Field"
239
241
  @description "Entity field name containing an image URL to display as card thumbnail"
240
242
  @tier "presentation"
243
+ viewerRole : string = ""
244
+ @label "Viewer's role"
245
+ @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."
246
+ @tier "policy"
241
247
  selfFetch : boolean = true
242
248
  @label "Fetch its own rows on mount?"
243
249
  @description "true (default) = standalone mount self-populates on INIT. false = a composing atom owns the fetch and routes its loaded event here — suppresses the wrapper's own un-hydrated fetch so it cannot race the composer's."
@@ -21,6 +21,8 @@ orbital EntityListOrbital {
21
21
  navigatesTo : string
22
22
  placement : string
23
23
  variant : "primary" | "secondary" | "ghost" | "danger" | "default"
24
+ when : SExpr
25
+ roles : [string]
24
26
  }
25
27
 
26
28
  entity EntityListItem [runtime] {
@@ -48,7 +50,7 @@ orbital EntityListOrbital {
48
50
  entity: @entity
49
51
  entityType: @config.entityType
50
52
  selectable: @config.selectable
51
- itemActions: @config.itemActions
53
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
52
54
  showDividers: @config.showDividers
53
55
  variant: @config.variant
54
56
  emptyMessage: @config.emptyMessage
@@ -73,7 +75,7 @@ orbital EntityListOrbital {
73
75
  entity: @entity
74
76
  entityType: @config.entityType
75
77
  selectable: @config.selectable
76
- itemActions: @config.itemActions
78
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
77
79
  showDividers: @config.showDividers
78
80
  variant: @config.variant
79
81
  emptyMessage: @config.emptyMessage
@@ -98,7 +100,7 @@ orbital EntityListOrbital {
98
100
  entity: @payload.data
99
101
  entityType: @config.entityType
100
102
  selectable: @config.selectable
101
- itemActions: @config.itemActions
103
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
102
104
  showDividers: @config.showDividers
103
105
  variant: @config.variant
104
106
  emptyMessage: @config.emptyMessage
@@ -207,6 +209,10 @@ orbital EntityListOrbital {
207
209
  @label "Field Names"
208
210
  @description "Alias for fields - backwards compatibility"
209
211
  @tier "presentation"
212
+ viewerRole : string = ""
213
+ @label "Viewer's role"
214
+ @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."
215
+ @tier "policy"
210
216
  selfFetch : boolean = true
211
217
  @label "Fetch its own rows on mount?"
212
218
  @description "true (default) = standalone mount self-populates on INIT. false = a composing atom owns the fetch and routes its loaded event here — suppresses the wrapper's own un-hydrated fetch so it cannot race the composer's."
@@ -32,6 +32,8 @@ orbital EntityTableOrbital {
32
32
  placement : string
33
33
  icon : icon
34
34
  variant : string
35
+ when : SExpr
36
+ roles : [string]
35
37
  }
36
38
  type EntityTableEmptyAction = {
37
39
  label : string!
@@ -42,12 +44,15 @@ orbital EntityTableOrbital {
42
44
  icon : icon
43
45
  variant : "default" | "danger"
44
46
  event : event
47
+ when : SExpr
48
+ roles : [string]
45
49
  }
46
50
  type EntityTableBulkActionsItem = {
47
51
  label : string!
48
52
  icon : icon
49
53
  variant : "default" | "danger"
50
54
  event : event
55
+ roles : [string]
51
56
  }
52
57
  type EntityTableRelationsDataValueItem = {
53
58
  value : string!
@@ -81,7 +86,7 @@ orbital EntityTableOrbital {
81
86
  entity: @entity
82
87
  fields: @config.fields
83
88
  columns: @config.columns
84
- itemActions: @config.itemActions
89
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
85
90
  emptyIcon: @config.emptyIcon
86
91
  emptyTitle: @config.emptyTitle
87
92
  emptyDescription: @config.emptyDescription
@@ -89,8 +94,8 @@ orbital EntityTableOrbital {
89
94
  selectable: @config.selectable
90
95
  searchable: @config.searchable
91
96
  searchPlaceholder: @config.searchPlaceholder
92
- rowActions: @config.rowActions
93
- bulkActions: @config.bulkActions
97
+ rowActions: (array/filter @config.rowActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
98
+ bulkActions: (array/filter @config.bulkActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
94
99
  headerActions: @config.headerActions
95
100
  showTotal: @config.showTotal
96
101
  look: @config.look
@@ -113,7 +118,7 @@ orbital EntityTableOrbital {
113
118
  entity: @entity
114
119
  fields: @config.fields
115
120
  columns: @config.columns
116
- itemActions: @config.itemActions
121
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
117
122
  emptyIcon: @config.emptyIcon
118
123
  emptyTitle: @config.emptyTitle
119
124
  emptyDescription: @config.emptyDescription
@@ -121,8 +126,8 @@ orbital EntityTableOrbital {
121
126
  selectable: @config.selectable
122
127
  searchable: @config.searchable
123
128
  searchPlaceholder: @config.searchPlaceholder
124
- rowActions: @config.rowActions
125
- bulkActions: @config.bulkActions
129
+ rowActions: (array/filter @config.rowActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
130
+ bulkActions: (array/filter @config.bulkActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
126
131
  headerActions: @config.headerActions
127
132
  showTotal: @config.showTotal
128
133
  look: @config.look
@@ -145,7 +150,7 @@ orbital EntityTableOrbital {
145
150
  entity: @payload.data
146
151
  fields: @config.fields
147
152
  columns: @config.columns
148
- itemActions: @config.itemActions
153
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
149
154
  emptyIcon: @config.emptyIcon
150
155
  emptyTitle: @config.emptyTitle
151
156
  emptyDescription: @config.emptyDescription
@@ -153,8 +158,8 @@ orbital EntityTableOrbital {
153
158
  selectable: @config.selectable
154
159
  searchable: @config.searchable
155
160
  searchPlaceholder: @config.searchPlaceholder
156
- rowActions: @config.rowActions
157
- bulkActions: @config.bulkActions
161
+ rowActions: (array/filter @config.rowActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
162
+ bulkActions: (array/filter @config.bulkActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
158
163
  headerActions: @config.headerActions
159
164
  showTotal: @config.showTotal
160
165
  look: @config.look
@@ -286,6 +291,10 @@ orbital EntityTableOrbital {
286
291
  @label "Relations Data"
287
292
  @description "Relation display data: { fieldName: [{value, label}] } — injected server-side by the runtime (relation-option injection) or bound by compiled codegen; resolves stored foreign ids to display names for a column whose field is relation-typed. Same contract DetailPanel takes."
288
293
  @tier "presentation"
294
+ viewerRole : string = ""
295
+ @label "Viewer's role"
296
+ @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."
297
+ @tier "policy"
289
298
  selfFetch : boolean = true
290
299
  @label "Fetch its own rows on mount?"
291
300
  @description "true (default) = standalone mount self-populates on INIT. false = a composing atom owns the fetch and routes its loaded event here — suppresses the wrapper's own un-hydrated fetch so it cannot race the composer's."