@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,6 +2,7 @@ app std-board "1.3.0"
2
2
  "std-board — generic N-column board primitive. `config.columns` is an array of column definitions ({ key, label, icon, variant }); the trait `array/map`s them on `BoardItemsLoaded` into `@entity.boards` where each board carries its filtered items + a count. The render is a `data-grid` over `@entity.boards` (one card per column) whose `renderItem` lambda nests a `data-list` over `@col.items` (the cards in that stage). N is config-driven — pass any number of columns; the outer `data-grid`'s `cols` is bound to `@config.gridCols` so the grid wraps if you exceed it. Topology = loading / viewing_board / viewing_card / adding / error — distinct from the cookie-cutter `loading/browsing/viewing_single/error` CRUD shape. App-level atoms (e.g. std-pipeline) compose std-board via `uses` and add a sibling persistor + extended source entity. `config.boardLook` switches the board body between the default N-column grid ('columns') and a Trello-style wide-column kanban ('kanban-classic'). `viewing_board` listens for REFETCH_QUERY/REFETCH_FILTER/REFETCH_PAGE (the std-search/std-filter/std-pagination wiring targets, no render on refetch — @entity.boards is bound reactively) and can optionally render its own search box (config.bodySearch, default false) and filter bar (config.filters, default []); no pagination control is rendered — a board's columns are not a paged list."
3
3
  type ObjectSpec = { id : string, label : string, value : string }
4
4
  type ColumnSpec = { key : string!, label : string!, icon : string, variant : string }
5
+ type ItemAction = { label : string!, event : event, variant : primary | secondary | ghost | danger, icon : string, roles : [string] }
5
6
  type FilterSpec = { field : string!, label : string, options : [string] }
6
7
  orbital BoardOrbital {
7
8
  type BoardItem = { id : string!, title : string, description : string, stage : string, notes : string, position : number }
@@ -42,6 +43,7 @@ orbital BoardOrbital {
42
43
  INIT -> loading
43
44
  (fetch BoardView {
44
45
  emit: { failure: BoardItemsLoadFailed, success: BoardItemsLoaded }
46
+ include: @config.include
45
47
  })
46
48
  (render-ui main {
47
49
  title: "Loading board…"
@@ -72,6 +74,7 @@ orbital BoardOrbital {
72
74
  BoardItemsSaved -> loading
73
75
  (fetch BoardView {
74
76
  emit: { failure: BoardItemsLoadFailed, success: BoardItemsLoaded }
77
+ include: @config.include
75
78
  })
76
79
  (render-ui main {
77
80
  title: "Refreshing board…"
@@ -82,6 +85,7 @@ orbital BoardOrbital {
82
85
  BoardItemDeleted -> loading
83
86
  (fetch BoardView {
84
87
  emit: { failure: BoardItemsLoadFailed, success: BoardItemsLoaded }
88
+ include: @config.include
85
89
  })
86
90
  (render-ui main {
87
91
  title: "Refreshing board…"
@@ -100,6 +104,7 @@ orbital BoardOrbital {
100
104
  INIT -> loading
101
105
  (fetch BoardView {
102
106
  emit: { failure: BoardItemsLoadFailed, success: BoardItemsLoaded }
107
+ include: @config.include
103
108
  })
104
109
  (render-ui main {
105
110
  title: "Loading board…"
@@ -231,6 +236,7 @@ orbital BoardOrbital {
231
236
  BoardItemsSaved -> viewing_board
232
237
  (fetch BoardView {
233
238
  emit: { failure: BoardItemsLoadFailed, success: BoardItemsLoaded }
239
+ include: @config.include
234
240
  })
235
241
  ;; REFETCH_* stay in viewing_board and issue no render-ui, matching
236
242
  ;; std-browse's REFETCH_QUERY/REFETCH_FILTER/REFETCH_PAGE: a render here
@@ -241,11 +247,13 @@ orbital BoardOrbital {
241
247
  REFETCH_QUERY -> viewing_board
242
248
  (fetch BoardView {
243
249
  emit: { failure: BoardItemsLoadFailed, success: BoardItemsLoaded }
250
+ include: @config.include
244
251
  filter: (or ["=", ?searchTerm, ""] (str/includes (object/get @entity @config.searchField) ?searchTerm))
245
252
  })
246
253
  REFETCH_FILTER -> viewing_board
247
254
  (fetch BoardView {
248
255
  emit: { failure: BoardItemsLoadFailed, success: BoardItemsLoaded }
256
+ include: @config.include
249
257
  filter: (or ["=", ?value, ""] ["=", (object/get @entity ?field), ?value])
250
258
  })
251
259
  ;; A board's columns are not a paged list — paging the underlying fetch
@@ -256,6 +264,7 @@ orbital BoardOrbital {
256
264
  REFETCH_PAGE -> viewing_board
257
265
  (fetch BoardView {
258
266
  emit: { failure: BoardItemsLoadFailed, success: BoardItemsLoaded }
267
+ include: @config.include
259
268
  limit: @config.pageSize
260
269
  offset: ["*", ["-", ?page, 1], @config.pageSize]
261
270
  })
@@ -280,6 +289,7 @@ orbital BoardOrbital {
280
289
  CLOSE_CARD -> loading
281
290
  (fetch BoardView {
282
291
  emit: { failure: BoardItemsLoadFailed, success: BoardItemsLoaded }
292
+ include: @config.include
283
293
  })
284
294
  (render-ui main {
285
295
  title: "Refreshing board…"
@@ -531,6 +541,10 @@ orbital BoardOrbital {
531
541
  }
532
542
 
533
543
  config {
544
+ showHeader : boolean = true
545
+ @label "Show the board's own title row?"
546
+ @description "Off when the page already carries a page header naming the same thing, so the page shows one title."
547
+ @tier "presentation"
534
548
  title : string = Board
535
549
  @label "Board title"
536
550
  @description "Heading shown above the column board"
@@ -575,6 +589,11 @@ orbital BoardOrbital {
575
589
  @label "Card title binding"
576
590
  @description "Per-card binding for the title slot."
577
591
  @tier "presentation"
592
+ include : [string] = []
593
+ @label "Which relation fields to hydrate?"
594
+ @description "Entity relation field names to hydrate on fetch (e.g. an `assignee : TeamMember` field named `assignee`), so card bindings can use dot-paths like @item.assignee.name. Empty = no hydration, the default."
595
+ @synonyms "relation hydration, populate relations, joined fields, hydrate relations"
596
+ @tier "domain"
578
597
  cardDescriptionBinding : string = @item.description
579
598
  @label "Card description binding"
580
599
  @description "Per-card binding for the description slot."
@@ -624,16 +643,29 @@ orbital BoardOrbital {
624
643
  @description "Records fetched per REFETCH_PAGE request. std-board renders no pagination control itself — this only feeds the fetch limit/offset when a consumer wires a composed std-pagination to REFETCH_PAGE."
625
644
  @synonyms "fetch limit, records per page, batch size, page limit"
626
645
  @tier "presentation"
646
+ cardActions : [ItemAction] = [{
647
+ event: DELETE_CARD
648
+ icon: trash-2
649
+ label: Delete
650
+ variant: danger
651
+ }]
652
+ @label "Card panel action list"
653
+ @description "Buttons on the open-card panel's actions row, built by the default cardActionsContent. Give an item `roles` to show it only to those viewer roles."
654
+ @tier "presentation"
655
+ viewerRole : string = ""
656
+ @label "Viewer's role"
657
+ @description "The signed-in viewer's role that each card 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."
658
+ @tier "policy"
627
659
  cardActionsContent : render-ui = {
628
660
  align: center
629
- children: [{
630
- action: DELETE_CARD
661
+ children: (array/map (array/filter @config.cardActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole)))) (fn a {
662
+ action: @a.event
631
663
  actionPayload: { id: @entity.currentId }
632
- icon: trash-2
633
- label: Delete
664
+ icon: @a.icon
665
+ label: @a.label
634
666
  type: button
635
- variant: danger
636
- }]
667
+ variant: @a.variant
668
+ }))
637
669
  direction: horizontal
638
670
  gap: sm
639
671
  type: stack
@@ -642,17 +674,26 @@ orbital BoardOrbital {
642
674
  @description "Actions row of the open-card panel. Default is the Delete button only. Override to add consumer-wired actions — e.g. an Edit button with action: EDIT_CARD and actionPayload: { id: @entity.currentId, row: @entity.currentRow }, listened to by the organism's edit modal. Never leave a button here without a listener."
643
675
  @tier "presentation"
644
676
  bodyContent : render-ui = {
645
- children: [{
646
- align: center
647
- children: [{ name: kanban-square, size: lg, type: icon }, {
648
- content: @config.title
649
- type: typography
650
- variant: h3
651
- }]
652
- direction: horizontal
653
- gap: sm
677
+ children: [(if @config.showHeader {
678
+ children: [{
679
+ align: center
680
+ children: [{ name: kanban-square, size: lg, type: icon }, {
681
+ content: @config.title
682
+ type: typography
683
+ variant: h3
684
+ }]
685
+ direction: horizontal
686
+ gap: sm
687
+ type: stack
688
+ }, { type: divider }]
689
+ direction: vertical
690
+ gap: md
691
+ type: stack
692
+ } {
693
+ children: []
694
+ gap: none
654
695
  type: stack
655
- }, { type: divider }, (if @config.bodySearch {
696
+ }), (if @config.bodySearch {
656
697
  children: [{
657
698
  className: "w-full max-w-md"
658
699
  clearable: true
@@ -771,18 +812,27 @@ orbital BoardOrbital {
771
812
  @description "Render-ui SExpr rendered after the board loads for boardLook='columns' — the canonical column data-grid with nested per-column data-lists. boardLook='kanban-classic' renders kanbanClassicBodyContent instead; both share this trait's state machine, emits, and listens."
772
813
  @tier "internal"
773
814
  kanbanClassicBodyContent : render-ui = {
774
- children: [{
775
- align: center
776
- children: [{ name: kanban-square, size: xl, type: icon }, {
777
- content: @config.title
778
- type: typography
779
- variant: h2
780
- }]
781
- className: px-card-md
782
- direction: horizontal
783
- gap: sm
815
+ children: [(if @config.showHeader {
816
+ children: [{
817
+ align: center
818
+ children: [{ name: kanban-square, size: xl, type: icon }, {
819
+ content: @config.title
820
+ type: typography
821
+ variant: h2
822
+ }]
823
+ className: px-card-md
824
+ direction: horizontal
825
+ gap: sm
826
+ type: stack
827
+ }, { type: divider }]
828
+ direction: vertical
829
+ gap: md
830
+ type: stack
831
+ } {
832
+ children: []
833
+ gap: none
784
834
  type: stack
785
- }, { type: divider }, (if @config.bodySearch {
835
+ }), (if @config.bodySearch {
786
836
  children: [{
787
837
  className: "w-full max-w-md"
788
838
  clearable: true
@@ -1,7 +1,7 @@
1
1
  app std-browse "2.5.0"
2
2
  "std-browse as a Function — single primitive: data-grid. Owns the fetch + REFETCH (query/filter/page) state machine. Consumers configure fields/imageField/itemActions/cols/gap/variant; the atom renders the grid. Each `fields[]` entry accepts `{ name, label, variant }` plus optional `referenceEntity` + `displayField` to render a foreign-key column as the joined entity's display value (data-grid resolves @list[referenceEntity] at render time when both keys are present). `browseLook` (table default / dense / feed / gallery / master-detail / triage) selects one of six render bodies; dense/feed/gallery were folded in from std-browse-dense/-feed/-gallery (Phase 5.B); master-detail (split record view driven by the guarded VIEW/CLOSE self-transitions) and triage (inbox rows) were folded in 2026-07-26. Consumers retarget by setting browseLook."
3
3
  type FieldSpec = { name : string!, label : string, variant : h3 | h4 | body | caption | badge | small | progress, icon : string, format : date | currency | number | boolean | percent, key : string, header : string }
4
- type ItemAction = { label : string!, event : event, navigatesTo : string, variant : primary | secondary | ghost | danger, icon : string }
4
+ type ItemAction = { label : string!, event : event, navigatesTo : string, variant : primary | secondary | ghost | danger, icon : string, roles : [string], when : SExpr }
5
5
  type ColumnSpec = { key : string!, field : string, header : string, width : string, align : left | center | right, className : string, weight : normal | medium | semibold, format : badge | date | currency | number | percent | boolean, icon : string }
6
6
  type FilterSpec = { field : string!, label : string, options : [string] }
7
7
  orbital BrowseItemOrbital {
@@ -10,6 +10,8 @@ orbital BrowseItemOrbital {
10
10
  event : event!
11
11
  icon : string
12
12
  variant : string
13
+ roles : [string]
14
+ when : SExpr
13
15
  }
14
16
 
15
17
  type BrowseItemLoaded = Event { data : [BrowseItem], totalCount : number } "Fired when the BrowseItem collection finishes loading; payload.data holds the (possibly paginated) slice and totalCount holds the unsliced filter total. totalCount is optional so compiled-path emitters that haven't been migrated yet still validate"
@@ -43,6 +45,7 @@ orbital BrowseItemOrbital {
43
45
  config {
44
46
  fields: @config.fields
45
47
  itemActions: @config.itemActions
48
+ viewerRole: @config.viewerRole
46
49
  itemClickEvent: @config.itemClickEvent
47
50
  maxInlineActions: @config.maxInlineActions
48
51
  variant: compact
@@ -283,14 +286,6 @@ orbital BrowseItemOrbital {
283
286
  @label "Badge field binding"
284
287
  @description "Binding path for the status/badge slot."
285
288
  @tier "internal"
286
- imageLabelBinding : string = @item.thumbnailLabel
287
- @label "Image label binding"
288
- @description "Binding path for the image-area label slot."
289
- @tier "internal"
290
- priceBinding : string = @item.price
291
- @label "Price field binding"
292
- @description "Binding path for the price/amount overlay slot."
293
- @tier "internal"
294
289
  metaBinding : string = @item.createdAt
295
290
  @label "Meta field binding"
296
291
  @description "Binding path for the secondary meta slot (timestamp / category). Hosts binding a count or other non-date value should label it in the binding itself (e.g. (str/concat \"Vehicles: \" @item.vehicleCount)) and set metaFormat: none."
@@ -303,14 +298,6 @@ orbital BrowseItemOrbital {
303
298
  @label "Category field binding"
304
299
  @description "Binding path for the category/tag slot."
305
300
  @tier "internal"
306
- priorityBinding : string = @item.priority
307
- @label "Priority field binding"
308
- @description "Binding path for the priority slot."
309
- @tier "internal"
310
- assigneeBinding : string = @item.assignee
311
- @label "Assignee field binding"
312
- @description "Binding path for the assignee/owner slot."
313
- @tier "internal"
314
301
  itemActions : [ItemAction] = []
315
302
  @label "What actions can users take on each row?"
316
303
  @description "Buttons rendered on each row (e.g. Edit, Delete, View)."
@@ -361,6 +348,10 @@ orbital BrowseItemOrbital {
361
348
  @description "Name the field on this entity that holds the viewer's id (e.g. memberId, patientId, assignee). When set, the list loads ONLY rows whose that field equals @user.id — the 'my bookings' / 'my appointments' shape. Left blank the list loads every row, which is the default. Declared, never inferred: guessing the column from its name would silently scope the wrong one."
362
349
  @synonyms "owner field, my records, only mine, only my own, scope to user, per-user list, mine only, owned by me"
363
350
  @tier "policy"
351
+ viewerRole : string = ""
352
+ @label "Viewer's role"
353
+ @description "The signed-in viewer's role that each row 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."
354
+ @tier "policy"
364
355
  initialFilterField : string = ""
365
356
  @label "Which field does the first load filter on?"
366
357
  @description "Name the field the INITIAL load filters on, paired with initialFilterValue. This is the detail half of a list-detail pair: a thread that must wait for a conversation to be picked sets the field to its parent key and leaves the value blank, so the first load matches nothing and the empty state shows instead of every record in the table. REFETCH_FILTER then supplies the real selection. Left blank the first load is unfiltered, which is the default."
@@ -396,10 +387,21 @@ orbital BrowseItemOrbital {
396
387
  @description "Visual treatment for the embedded filter bar, mirroring std-filter's own enum. Only applies when `filters` is non-empty."
397
388
  @synonyms "filter bar style, facet style, chips, pills"
398
389
  @tier "presentation"
399
- viewPattern : pattern = data-grid
400
- @label "Render pattern"
401
- @description "UI pattern used to render the collection. Used by the default bodyContent tree; Layer 3 variants override bodyContent directly instead and may ignore this knob."
402
- @tier "internal"
390
+ emptyTitle : string = ""
391
+ @label "Empty-state title"
392
+ @description "Specific title shown when there are no rows (\"No orders yet\"). Left blank, a generic line shows."
393
+ @synonyms "empty title, no data title, empty heading"
394
+ @tier "presentation"
395
+ emptyDescription : string = ""
396
+ @label "Empty-state description"
397
+ @description "What will appear here once rows exist."
398
+ @synonyms "empty text, no data message, empty hint"
399
+ @tier "presentation"
400
+ emptyIcon : icon = inbox
401
+ @label "Empty-state icon"
402
+ @description "Domain icon shown when there are no rows."
403
+ @synonyms "empty icon, no data icon"
404
+ @tier "presentation"
403
405
  browseLook : "table" | "dense" | "feed" | "gallery" | "master-detail" | "triage" = table
404
406
  @label "Browse look"
405
407
  @description "Layer 2 visual treatment for the whole browse surface. table = the default data-grid (bodyContent); dense = spreadsheet-style table with toolbar search (denseBodyContent); feed = chronological card stream (feedBodyContent); gallery = image-first responsive card grid (galleryBodyContent); master-detail = record-work split view — dense list left, clicked record's detail right (masterDetailBodyContent); triage = inbox-register compact rows for queue work (triageBodyContent). Selecting a non-table look swaps which body tree renders after rows load; any body may still be overridden directly at the call site for a one-off layout."
@@ -451,9 +453,12 @@ orbital BrowseItemOrbital {
451
453
  fields: @config.fields
452
454
  gap: @config.gap
453
455
  imageField: @config.imageField
454
- itemActions: @config.itemActions
456
+ itemActions: (array/filter @config.itemActions (fn item (or (= (array/len (object/get @item roles [])) 0) (array/includes (object/get @item roles []) @config.viewerRole))))
455
457
  maxInlineActions: @config.maxInlineActions
456
458
  pageSize: @config.displayPageSize
459
+ emptyDescription: @config.emptyDescription
460
+ emptyIcon: @config.emptyIcon
461
+ emptyTitle: @config.emptyTitle
457
462
  type: data-grid
458
463
  }]
459
464
  direction: vertical
@@ -498,14 +503,16 @@ orbital BrowseItemOrbital {
498
503
  }), {
499
504
  children: [{
500
505
  columns: @config.columns
501
- emptyMessage: "No records"
502
506
  entity: ?data
503
- itemActions: @config.itemActions
507
+ itemActions: (array/filter @config.itemActions (fn item (or (= (array/len (object/get @item roles [])) 0) (array/includes (object/get @item roles []) @config.viewerRole))))
504
508
  itemClickEvent: @config.itemClickEvent
505
509
  look: dense
506
510
  maxInlineActions: @config.maxInlineActions
507
511
  pageSize: @config.displayPageSize
508
512
  selectable: @config.selectable
513
+ emptyDescription: @config.emptyDescription
514
+ emptyIcon: @config.emptyIcon
515
+ emptyTitle: @config.emptyTitle
509
516
  type: table-view
510
517
  }]
511
518
  className: overflow-x-auto
@@ -559,7 +566,7 @@ orbital BrowseItemOrbital {
559
566
  entity: ?data
560
567
  fields: []
561
568
  gap: md
562
- itemActions: @config.itemActions
569
+ itemActions: (array/filter @config.itemActions (fn item (or (= (array/len (object/get @item roles [])) 0) (array/includes (object/get @item roles []) @config.viewerRole))))
563
570
  renderItem: (fn item {
564
571
  children: [{
565
572
  align: start
@@ -627,6 +634,9 @@ orbital BrowseItemOrbital {
627
634
  padding: none
628
635
  type: card
629
636
  })
637
+ emptyDescription: @config.emptyDescription
638
+ emptyIcon: @config.emptyIcon
639
+ emptyTitle: @config.emptyTitle
630
640
  type: data-list
631
641
  variant: card
632
642
  }]
@@ -678,9 +688,12 @@ orbital BrowseItemOrbital {
678
688
  fields: @config.fields
679
689
  gap: lg
680
690
  imageField: @config.imageField
681
- itemActions: @config.itemActions
691
+ itemActions: (array/filter @config.itemActions (fn item (or (= (array/len (object/get @item roles [])) 0) (array/includes (object/get @item roles []) @config.viewerRole))))
682
692
  maxInlineActions: @config.maxInlineActions
683
693
  minCardWidth: 260
694
+ emptyDescription: @config.emptyDescription
695
+ emptyIcon: @config.emptyIcon
696
+ emptyTitle: @config.emptyTitle
684
697
  type: data-grid
685
698
  }]
686
699
  className: w-full
@@ -728,8 +741,11 @@ orbital BrowseItemOrbital {
728
741
  children: [{
729
742
  entity: ?data
730
743
  fields: @config.fields
731
- itemActions: @config.itemActions
744
+ itemActions: (array/filter @config.itemActions (fn item (or (= (array/len (object/get @item roles [])) 0) (array/includes (object/get @item roles []) @config.viewerRole))))
732
745
  maxInlineActions: @config.maxInlineActions
746
+ emptyDescription: @config.emptyDescription
747
+ emptyIcon: @config.emptyIcon
748
+ emptyTitle: @config.emptyTitle
733
749
  type: data-list
734
750
  variant: compact
735
751
  }]
@@ -844,7 +860,7 @@ orbital BrowseItemOrbital {
844
860
  type: stack
845
861
  }), {
846
862
  detail: {
847
- actions: @config.detailActions
863
+ actions: (array/filter @config.detailActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
848
864
  fieldNames: @config.detailFields
849
865
  initialData: ?row
850
866
  showActions: true
@@ -1,6 +1,6 @@
1
1
  app std-calendar "1.4.0"
2
2
  "std-calendar as a Function — owns the fetch + SELECT_DAY state machine; default bodyContent renders the month-grid + upcoming-events tree. `config.calendarLook` switches the body between the default month-grid ('month'), a day-grouped agenda list ('agenda-list'), and a 7-column week timeline ('week-timeline') while inheriting the same trait, state machine, emits, and listens."
3
- type ItemAction = { label : string!, event : event, navigatesTo : string, variant : primary | secondary | ghost | danger, icon : string }
3
+ type ItemAction = { label : string!, event : event, navigatesTo : string, variant : primary | secondary | ghost | danger, icon : string, roles : [string], when : SExpr }
4
4
  type FilterSpec = { field : string!, label : string, options : [string] }
5
5
  type FieldSpec = { name : string!, label : string, variant : h3 | h4 | body | caption | badge | small | progress, icon : string, format : date | currency | number | boolean | percent }
6
6
  orbital CalendarEventOrbital {
@@ -279,6 +279,10 @@ orbital CalendarEventOrbital {
279
279
  @description "Per-item action buttons on agenda-list rows — data-list itemActions descriptors (label/event/icon/variant). Consumers override to wire their own row actions (View/Edit/Delete) so agenda hosts never need a second table for actions."
280
280
  @synonyms "agenda actions, row actions, event actions, list actions"
281
281
  @tier "presentation"
282
+ viewerRole : string = ""
283
+ @label "Viewer's role"
284
+ @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."
285
+ @tier "policy"
282
286
  agendaGroupBy : string = date
283
287
  @label "Agenda group-by field"
284
288
  @description "Row field the agenda list groups its day sections by. Rebound hosts point this at their own timestamp column (e.g. startTime, scheduledAt)."
@@ -378,7 +382,7 @@ orbital CalendarEventOrbital {
378
382
  }, {
379
383
  entity: ?data
380
384
  fields: @config.fields
381
- itemActions: @config.agendaItemActions
385
+ itemActions: (array/filter @config.agendaItemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
382
386
  look: @config.tableLook
383
387
  type: data-list
384
388
  }]
@@ -446,7 +450,7 @@ orbital CalendarEventOrbital {
446
450
  fields: []
447
451
  gap: md
448
452
  groupBy: @config.agendaGroupBy
449
- itemActions: @config.agendaItemActions
453
+ itemActions: (array/filter @config.agendaItemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
450
454
  renderItem: (fn item {
451
455
  children: [{
452
456
  align: start
@@ -1,5 +1,6 @@
1
1
  app std-esign-flow "1.2.0"
2
2
  "std-esign-flow — the send-for-signature flow: list signature requests, create one (pick document + recipient), resend or cancel, track status. Composes std-file-store + std-esign-request; no document-rendering or code-preview chrome. v1.2 (W5): EnvelopeDispatcher wires sessions to the real `esign` service — SEND_ENVELOPE dispatches a DocuSign envelope (the document rides the event as an UploadDropZone-shaped file payload, since StoredFile rows are metadata-only) and stamps `envelopeId`/`sentAt`/status=sent; the browse grid's per-row \"Refresh status\" pulls getEnvelopeStatus and maps completed/delivered/declined onto signed/viewed/declined."
3
+ type ItemAction = { label : string!, event : event, variant : string, roles : [string], when : SExpr }
3
4
  orbital SignatureSessionOrbital {
4
5
  uses StoredFile from "std/behaviors/std-file-store"
5
6
 
@@ -95,19 +96,7 @@ orbital SignatureSessionOrbital {
95
96
  name: sentAt
96
97
  variant: caption
97
98
  }]
98
- itemActions: [{
99
- event: RESEND_REQUEST
100
- label: Resend
101
- variant: primary
102
- }, {
103
- event: REQUEST_DELETE
104
- label: Cancel
105
- variant: danger
106
- }, {
107
- event: CHECK_ENVELOPE_STATUS
108
- label: "Refresh status"
109
- variant: secondary
110
- }]
99
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
111
100
  type: data-grid
112
101
  }]
113
102
  direction: vertical
@@ -216,6 +205,29 @@ orbital SignatureSessionOrbital {
216
205
  SignatureSessionPersistor.SESSION_RESENT -> INIT
217
206
  SignatureSessionPersistor.SESSION_DELETED -> INIT
218
207
  }
208
+
209
+ config {
210
+ itemActions : [ItemAction] = [{
211
+ event: RESEND_REQUEST
212
+ label: Resend
213
+ variant: primary
214
+ }, {
215
+ event: REQUEST_DELETE
216
+ label: Cancel
217
+ variant: danger
218
+ }, {
219
+ event: CHECK_ENVELOPE_STATUS
220
+ label: "Refresh status"
221
+ variant: secondary
222
+ }]
223
+ @label "Row actions"
224
+ @description "Actions offered on each row; give an item `roles` to show it only to those viewer roles."
225
+ @tier "presentation"
226
+ viewerRole : string = ""
227
+ @label "Viewer's role"
228
+ @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."
229
+ @tier "policy"
230
+ }
219
231
  }
220
232
 
221
233
  trait SignatureSessionCreate = Modal.traits.ModalRecordModal -> SignatureSession {
@@ -61,6 +61,7 @@ orbital ESignRequestOrbital {
61
61
  label: Revoke
62
62
  variant: danger
63
63
  }]
64
+ viewerRole: @config.viewerRole
64
65
  look: @config.tableLook
65
66
  }
66
67
  }
@@ -178,6 +179,10 @@ orbital ESignRequestOrbital {
178
179
  @label "Table look"
179
180
  @description "Layer 2 visual treatment for the data table rendered by this atom."
180
181
  @tier "presentation"
182
+ viewerRole : string = ""
183
+ @label "Viewer's role"
184
+ @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."
185
+ @tier "policy"
181
186
  }
182
187
  }
183
188
 
@@ -659,11 +659,6 @@ orbital EventLogOrbital {
659
659
  @description "Records fetched from the server per REFETCH_PAGE request. The initial load and every search/kind/filter refetch stay unpaginated (load everything that matches) so the default unlimited activity feed is unchanged; only an explicit REFETCH_PAGE from a composed std-pagination control applies this limit."
660
660
  @synonyms "fetch limit, records per page, page limit"
661
661
  @tier "presentation"
662
- displayPageSize : number = 20
663
- @label "How many entries per page should a pager show?"
664
- @description "Page size a consumer-composed std-pagination control should use to compute total pages (e.g. from totalCount). This atom's own timeline pattern has no built-in pager UI, so this knob is informational for the composed control, not consumed by the timeline itself."
665
- @synonyms "visible rows, items per page, display limit"
666
- @tier "presentation"
667
662
  }
668
663
  }
669
664
 
@@ -59,16 +59,6 @@ orbital ExportOrbital {
59
59
  }
60
60
 
61
61
  config {
62
- tileId : string = ""
63
- @label "Tile id"
64
- @description "Identifier of the dashboard tile being exported"
65
- @synonyms "internal identifier — host orbital wires this; users rarely set it directly"
66
- @tier "internal"
67
- event : string = EXPORT_REQUESTED
68
- @label "Export event"
69
- @description "Event emitted when the user picks a format. Each entry in formats[] carries its own literal event field (no per-item templating in .lolo) — overriding this alone does not retarget the click; also set formats[].event to match."
70
- @synonyms "bus event name. internal wiring; users rarely target directly"
71
- @tier "internal"
72
62
  formats : [FormatOption] = [{
73
63
  event: EXPORT_REQUESTED
74
64
  format: csv
@@ -1,7 +1,7 @@
1
1
  app std-file-store "2.0.0"
2
2
  "std-file-store — the generic file/page tree primitive. A file-tree + config-driven data table over a hierarchical collection; opens a row in `viewing_single` with config-driven detail actions. Rebindable: pass `fields`/`itemActions`/`detailActions`/`tree` to retarget it at any hierarchical entity (files, wiki pages, note trees). Folds in the former std-page-tree via `reorderable` + a page field/action set."
3
3
  type FieldSpec = { name : string!, label : string, variant : "h3" | "h4" | "body" | "caption" | "badge" | "small" | "progress", icon : string, format : "date" | "currency" | "number" | "boolean" | "percent", key : string, header : string }
4
- type ItemAction = { label : string!, event : event!, variant : "primary" | "secondary" | "ghost" | "danger", icon : string }
4
+ type ItemAction = { label : string!, event : event!, variant : "primary" | "secondary" | "ghost" | "danger", icon : string, roles : [string], when : SExpr }
5
5
  type TreeNode = { name : string!, path : string!, type : "file" | "dir"!, children : [TreeNode] }
6
6
  orbital StoredFileOrbital {
7
7
  type StoredFileLoaded = Event { data : [StoredFile] } "Fired when the collection finishes loading"
@@ -63,7 +63,7 @@ orbital StoredFileOrbital {
63
63
  entity: ?data
64
64
  fields: @config.fields
65
65
  gap: sm
66
- itemActions: @config.itemActions
66
+ itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
67
67
  look: @config.tableLook
68
68
  reorderEvent: REORDER
69
69
  reorderable: @config.reorderable
@@ -154,7 +154,7 @@ orbital StoredFileOrbital {
154
154
  gap: sm
155
155
  type: stack
156
156
  }, { type: divider }, {
157
- entity: @config.detailActions
157
+ entity: (array/filter @config.detailActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
158
158
  fields: []
159
159
  gap: sm
160
160
  renderItem: (fn a {
@@ -431,6 +431,10 @@ orbital StoredFileOrbital {
431
431
  @label "Detail actions"
432
432
  @description "Buttons shown on the opened row's detail"
433
433
  @tier "presentation"
434
+ viewerRole : string = ""
435
+ @label "Viewer's role"
436
+ @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."
437
+ @tier "policy"
434
438
  tree : [TreeNode] = [{
435
439
  children: [{
436
440
  name: "Active.pdf"
@@ -1,7 +1,6 @@
1
1
  app std-form-advanced "1.2.0"
2
- "std-form-advanced — full-typed form-section primitive. Hosts the `editing` state with a configurable `fields` array (each entry mirrors @almadar/ui's `form-section` field schema: `{ name, label, type?, values?, relation?, required? }`). Field-level constraints live in `config.fieldValidation` as `[{ field, format?: 'email'|'url'|'phone', regex?, minLength?, maxLength?, message? }]` — form-section surfaces inline errors when a submit violates a declared constraint. Agents drive shape by overriding `config.fields` + `config.fieldValidation` per-call-site."
2
+ "std-form-advanced — full-typed form-section primitive. Hosts the `editing` state with a configurable `fields` array (each entry mirrors @almadar/ui's `form-section` field schema: `{ name, label, type?, values?, relation?, required? }`). Agents drive shape by overriding `config.fields` per-call-site."
3
3
  type FieldSpec = { name : string!, label : string, variant : string, icon : string, format : string, key : string, header : string }
4
- type ValidationSpec = { field : string!, rule : string, message : string }
5
4
  orbital FormEntryOrbital {
6
5
  type FormEntryLoaded = Event { data : [FormEntry] } "Fired when FormEntry finishes loading"
7
6
 
@@ -251,10 +250,6 @@ orbital FormEntryOrbital {
251
250
  @label "Form fields"
252
251
  @description "Inputs to render; each entry follows the form-section field schema"
253
252
  @tier "presentation"
254
- fieldValidation : [ValidationSpec] = []
255
- @label "Field validation"
256
- @description "Per-field rules (format, regex, length) shown inline on submit"
257
- @tier "domain"
258
253
  submitLabel : string
259
254
  @label "Submit button"
260
255
  @description "Label on the submit button; unset keeps the translated Save"
@@ -22,6 +22,7 @@ orbital GeoSearchResultOrbital {
22
22
 
23
23
  state idle {
24
24
  INIT -> idle
25
+ (set @entity.radiusKm @config.defaultRadiusKm)
25
26
  (render-ui main {
26
27
  children: [{
27
28
  event: @config.event