@almadar/std 16.187.0 → 16.189.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 (102) hide show
  1. package/behaviors/lolo/ui/core/.hand-authored.json +4 -4
  2. package/behaviors/lolo/ui/core/atoms/std-board.lolo +138 -4
  3. package/behaviors/lolo/ui/core/atoms/std-browse.lolo +148 -8
  4. package/behaviors/lolo/ui/core/atoms/std-calendar.lolo +161 -11
  5. package/behaviors/lolo/ui/core/atoms/std-event-log.lolo +255 -2
  6. package/behaviors/lolo/ui/core/atoms/std-gallery.lolo +148 -1
  7. package/behaviors/lolo/ui/core/atoms/std-list.lolo +193 -1
  8. package/behaviors/lolo/ui/core/atoms/std-record-detail.lolo +731 -0
  9. package/behaviors/lolo/ui/core/atoms/std-related.lolo +5 -1
  10. package/behaviors/lolo/ui/core/atoms/std-selection.lolo +182 -1
  11. package/behaviors/lolo/ui/core/atoms/std-tree.lolo +113 -3
  12. package/behaviors/lolo/ui/core/atoms/std-version-history.lolo +1 -1
  13. package/behaviors/lolo/ui/core/molecules/ui-document-details.lolo +80 -0
  14. package/behaviors/lolo/ui/core/molecules/ui-document-panel.lolo +213 -0
  15. package/behaviors/lolo/ui/core/molecules/{ui-rich-block-editor.lolo → ui-rich-text-editor.lolo} +25 -25
  16. package/behaviors/lolo/ui/game/atoms/std-area-fill.lolo +93 -0
  17. package/behaviors/lolo/ui/game/atoms/std-choice-gate.lolo +100 -0
  18. package/behaviors/lolo/ui/game/atoms/std-coef-pad.lolo +114 -0
  19. package/behaviors/lolo/ui/game/atoms/std-curve-fog.lolo +50 -0
  20. package/behaviors/lolo/ui/game/atoms/std-loop-lock.lolo +79 -0
  21. package/behaviors/lolo/ui/game/atoms/std-pad-lock.lolo +97 -0
  22. package/behaviors/lolo/ui/game/atoms/std-patrol-hazard.lolo +14 -7
  23. package/behaviors/lolo/ui/game/atoms/std-platformer-body.lolo +48 -5
  24. package/behaviors/lolo/ui/game/atoms/std-velocity-gate.lolo +101 -0
  25. package/behaviors/lolo/ui/game/atoms/std-zone-card.lolo +95 -0
  26. package/behaviors/lolo/ui/game/organisms/std-platformer-board-2d.lolo +9 -0
  27. package/behaviors/registry/infra/atoms/std-approval-gate.orb +16 -8
  28. package/behaviors/registry/infra/atoms/std-cache-aside.orb +62 -31
  29. package/behaviors/registry/infra/atoms/std-circuit-breaker.orb +32 -16
  30. package/behaviors/registry/infra/atoms/std-data-erasure.orb +16 -8
  31. package/behaviors/registry/infra/atoms/std-mod-queue.orb +16 -8
  32. package/behaviors/registry/infra/atoms/std-rate-limiter.orb +28 -14
  33. package/behaviors/registry/infra/organisms/std-status-lifecycle-control.orb +2 -1
  34. package/behaviors/registry/ml/organisms/std-escalating-decision.orb +10 -5
  35. package/behaviors/registry/ml/organisms/std-knowledge-tracing.orb +4 -2
  36. package/behaviors/registry/ui/core/atoms/std-billable-hour.orb +2 -1
  37. package/behaviors/registry/ui/core/atoms/std-board.orb +355 -2
  38. package/behaviors/registry/ui/core/atoms/std-browse.orb +304 -31
  39. package/behaviors/registry/ui/core/atoms/std-calendar.orb +393 -25
  40. package/behaviors/registry/ui/core/atoms/std-dashboard-grid-embedded.orb +2 -1
  41. package/behaviors/registry/ui/core/atoms/std-esign-flow.orb +4 -2
  42. package/behaviors/registry/ui/core/atoms/std-esign-request.orb +6 -3
  43. package/behaviors/registry/ui/core/atoms/std-event-log.orb +773 -0
  44. package/behaviors/registry/ui/core/atoms/std-export.orb +4 -2
  45. package/behaviors/registry/ui/core/atoms/std-gallery.orb +390 -0
  46. package/behaviors/registry/ui/core/atoms/std-import.orb +4 -2
  47. package/behaviors/registry/ui/core/atoms/std-list.orb +451 -0
  48. package/behaviors/registry/ui/core/atoms/std-record-detail.orb +3360 -0
  49. package/behaviors/registry/ui/core/atoms/std-related.orb +23 -1
  50. package/behaviors/registry/ui/core/atoms/std-selection.orb +436 -0
  51. package/behaviors/registry/ui/core/atoms/std-tree.orb +292 -1
  52. package/behaviors/registry/ui/core/atoms/std-version-history.orb +1 -1
  53. package/behaviors/registry/ui/core/molecules/ui-document-details.orb +342 -0
  54. package/behaviors/registry/ui/core/molecules/ui-document-panel.orb +655 -0
  55. package/behaviors/registry/ui/core/molecules/{ui-rich-block-editor.orb → ui-rich-text-editor.orb} +84 -97
  56. package/behaviors/registry/ui/game/atoms/std-area-fill.orb +955 -0
  57. package/behaviors/registry/ui/game/atoms/std-choice-gate.orb +855 -0
  58. package/behaviors/registry/ui/game/atoms/std-coef-pad.orb +928 -0
  59. package/behaviors/registry/ui/game/atoms/std-curve-fog.orb +337 -0
  60. package/behaviors/registry/ui/game/atoms/std-fx-trail.orb +1 -1
  61. package/behaviors/registry/ui/game/atoms/std-gate-lock.orb +1 -1
  62. package/behaviors/registry/ui/game/atoms/std-lives.orb +1 -1
  63. package/behaviors/registry/ui/game/atoms/std-loop-lock.orb +785 -0
  64. package/behaviors/registry/ui/game/atoms/std-pad-lock.orb +933 -0
  65. package/behaviors/registry/ui/game/atoms/std-patrol-hazard.orb +190 -44
  66. package/behaviors/registry/ui/game/atoms/std-platformer-body.orb +1330 -653
  67. package/behaviors/registry/ui/game/atoms/std-velocity-gate.orb +1040 -0
  68. package/behaviors/registry/ui/game/atoms/std-zone-card.orb +642 -0
  69. package/behaviors/registry/ui/game/organisms/std-arcade-board-3d.orb +8 -4
  70. package/behaviors/registry/ui/game/organisms/std-crew-board-2d.orb +6 -3
  71. package/behaviors/registry/ui/game/organisms/std-dungeon-board-2d.orb +10 -5
  72. package/behaviors/registry/ui/game/organisms/std-market-board-3d.orb +8 -4
  73. package/behaviors/registry/ui/game/organisms/std-objective-board-3d.orb +8 -4
  74. package/behaviors/registry/ui/game/organisms/std-platformer-board-2d.orb +36 -1
  75. package/behaviors/registry/ui/game/organisms/std-survival-board-3d.orb +8 -4
  76. package/behaviors/registry/ui/game/organisms/std-tactics-board-2d.orb +12 -6
  77. package/behaviors/registry/ui/game/organisms/std-tactics-board-3d.orb +8 -4
  78. package/behaviors/registry/ui/game/organisms/std-worldmap-board-2d.orb +6 -3
  79. package/behaviors/registry/ui/learning/atoms/std-learn-slope-probe.orb +1 -1
  80. package/behaviors/registry/ui/marketing/atoms/std-marketing-article.orb +2 -1
  81. package/behaviors/registry/ui/marketing/atoms/std-marketing-footer.orb +2 -1
  82. package/behaviors/registry/ui/marketing/atoms/std-marketing-split.orb +2 -1
  83. package/behaviors/registry/ui/marketing/atoms/std-marketing-stats.orb +2 -1
  84. package/behaviors/registry/ui/marketing/atoms/std-marketing-steps.orb +2 -1
  85. package/behaviors/registry/ui/marketing/atoms/std-marketing-team.orb +2 -1
  86. package/dist/behaviors/exports-reader.js +10971 -6255
  87. package/dist/behaviors/functions/index.d.ts +1205 -256
  88. package/dist/behaviors/functions/index.js +10932 -6245
  89. package/dist/behaviors/index.d.ts +1 -1
  90. package/dist/behaviors/index.js +10972 -6256
  91. package/dist/behaviors/query.js +10971 -6255
  92. package/dist/behaviors-embeddings.hash.json +3 -3
  93. package/dist/behaviors-embeddings.json +485 -469
  94. package/dist/behaviors-registry.json +6125 -2940
  95. package/dist/index.d.ts +1 -1
  96. package/dist/index.js +10972 -6256
  97. package/dist/knob-embeddings.hash.json +3 -3
  98. package/dist/knob-embeddings.json +1 -1
  99. package/dist/registry/factory-signatures.json +1 -1
  100. package/package.json +4 -4
  101. package/behaviors/lolo/ui/core/atoms/std-rich-editor.lolo +0 -790
  102. package/behaviors/registry/ui/core/atoms/std-rich-editor.orb +0 -2225
@@ -99,6 +99,10 @@
99
99
  "signature": "33fcd927eb0bb9b7",
100
100
  "board": "packages/almadar-std/behaviors/lolo/ui/core/atoms/std-rating-review.lolo"
101
101
  },
102
+ "std-record-detail": {
103
+ "signature": "2d1e4a89d0de6e94",
104
+ "board": "packages/almadar-std/behaviors/lolo/ui/core/atoms/std-record-detail.lolo"
105
+ },
102
106
  "std-recurrence": {
103
107
  "signature": "56693212f7a2f8bc",
104
108
  "board": "packages/almadar-std/behaviors/lolo/ui/core/atoms/std-recurrence.lolo"
@@ -107,10 +111,6 @@
107
111
  "signature": "d11c4e5a26b3779d",
108
112
  "board": "packages/almadar-std/behaviors/lolo/ui/core/atoms/std-related.lolo"
109
113
  },
110
- "std-rich-editor": {
111
- "signature": "2ff1a9ef3cc7e487",
112
- "board": "packages/almadar-std/behaviors/lolo/ui/core/atoms/std-rich-editor.lolo"
113
- },
114
114
  "std-saved-search": {
115
115
  "signature": "e687e5294aaae0cc",
116
116
  "board": "packages/almadar-std/behaviors/lolo/ui/core/atoms/std-saved-search.lolo"
@@ -1,7 +1,8 @@
1
- app std-board "1.2.0"
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')."
1
+ app std-board "1.3.0"
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 FilterSpec = { field : string!, label : string, options : [string] }
5
6
  orbital BoardOrbital {
6
7
  type BoardItem = { id : string!, title : string, description : string, stage : string, notes : string, position : number }
7
8
 
@@ -219,6 +220,33 @@ orbital BoardOrbital {
219
220
  (fetch BoardView {
220
221
  emit: { failure: BoardItemsLoadFailed, success: BoardItemsLoaded }
221
222
  })
223
+ ;; REFETCH_* stay in viewing_board and issue no render-ui, matching
224
+ ;; std-browse's REFETCH_QUERY/REFETCH_FILTER/REFETCH_PAGE: a render here
225
+ ;; would swap the whole board tree on every keystroke. The fetch runs in
226
+ ;; the background; the BoardItemsLoaded arm below already recomputes
227
+ ;; @entity.boards, which the mounted data-grid is bound to, so the grid
228
+ ;; updates in place with no unmount/flicker.
229
+ REFETCH_QUERY -> viewing_board
230
+ (fetch BoardView {
231
+ emit: { failure: BoardItemsLoadFailed, success: BoardItemsLoaded }
232
+ filter: (or ["=", ?searchTerm, ""] (str/includes (object/get @entity title) ?searchTerm))
233
+ })
234
+ REFETCH_FILTER -> viewing_board
235
+ (fetch BoardView {
236
+ emit: { failure: BoardItemsLoadFailed, success: BoardItemsLoaded }
237
+ filter: (or ["=", ?value, ""] ["=", (object/get @entity ?field), ?value])
238
+ })
239
+ ;; A board's columns are not a paged list — paging the underlying fetch
240
+ ;; would show only one page's worth of items spread across all columns,
241
+ ;; which is wrong kanban UX. This arm exists so a consumer CAN wire
242
+ ;; std-pagination if they have a reason to; std-board itself never
243
+ ;; renders a pagination control (see bodyContent/kanbanClassicBodyContent).
244
+ REFETCH_PAGE -> viewing_board
245
+ (fetch BoardView {
246
+ emit: { failure: BoardItemsLoadFailed, success: BoardItemsLoaded }
247
+ limit: @config.pageSize
248
+ offset: ["*", ["-", ?page, 1], @config.pageSize]
249
+ })
222
250
  BoardItemsLoaded -> viewing_board
223
251
  (set @entity.boards (array/map @config.columns (fn col {
224
252
  count: (array/len (array/filter ?data (fn item ["=", (object/get @item @config.groupByField), (object/get @col key)])))
@@ -422,6 +450,25 @@ orbital BoardOrbital {
422
450
  @description "Indicates a board card has been removed."
423
451
  @synonyms "remove, discard, delete"
424
452
  @tier "presentation"
453
+ REFETCH_QUERY {
454
+ searchTerm : string!
455
+ }
456
+ @description "Triggers a board refresh based on the current search query."
457
+ @synonyms "refresh, reload, update, re-query"
458
+ @tier "domain"
459
+ REFETCH_FILTER {
460
+ field : string!
461
+ value : string!
462
+ }
463
+ @description "Triggers a board refresh based on current filter criteria."
464
+ @synonyms "refresh, filter, update, reload"
465
+ @tier "domain"
466
+ REFETCH_PAGE {
467
+ page : number!
468
+ }
469
+ @description "Triggers a board refresh for a given page. std-board itself renders no pagination control; this exists so a composed std-pagination can drive one."
470
+ @synonyms "reload, refresh, update, paginate"
471
+ @tier "domain"
425
472
  BoardItemsLoaded {
426
473
  data : [ObjectSpec]
427
474
  }
@@ -508,6 +555,31 @@ orbital BoardOrbital {
508
555
  @label "Board look"
509
556
  @description "Layer 3 body layout: default N-column data-grid ('columns'), or a Trello-style wide-column kanban with sticky column headers ('kanban-classic')."
510
557
  @tier "presentation"
558
+ bodySearch : boolean = false
559
+ @label "Show the board's own search box?"
560
+ @description "Renders an inline search box above the columns. Defaults false: unlike std-browse, std-board has never had a search box, so defaulting this true would silently add one to every existing consumer. The wired path — composing std-search beside the board and routing its FILTER/SEARCH event to REFETCH_QUERY — works regardless of this knob; set true only for a standalone board with no page-level search affordance."
561
+ @synonyms "inline search, board search, built-in search, show search, duplicate search"
562
+ @tier "presentation"
563
+ searchPlaceholder : string = "Search…"
564
+ @label "Search box placeholder text"
565
+ @description "Hint text inside the board's embedded search box (e.g. 'Search cards…'). Only shown when bodySearch is true."
566
+ @synonyms "search hint, placeholder, search box text, search label"
567
+ @tier "presentation"
568
+ filters : [FilterSpec] = []
569
+ @label "Which filters should appear above the board?"
570
+ @description "Dropdown filter facets by field, rendered as an embedded filter bar above the columns; each selection fires REFETCH_FILTER on this trait. Empty (the default) = no filter bar, which is the right setting whenever the page already composes std-filter beside this board and routes its FILTER event to REFETCH_FILTER — that is the wired owner and remains the primary path. Use this knob only for a standalone board with no page-level filter affordance."
571
+ @synonyms "filter bar, faceted filters, field filters, column filters, dropdowns"
572
+ @tier "presentation"
573
+ filterBarLook : "toolbar" | "chips" | "pills" | "popover-trigger" | "inline-column-header" = toolbar
574
+ @label "Filter bar look"
575
+ @description "Visual treatment for the embedded filter bar, mirroring std-filter's own enum. Only applies when `filters` is non-empty."
576
+ @synonyms "filter bar style, facet style, chips, pills"
577
+ @tier "presentation"
578
+ pageSize : number = 10
579
+ @label "Fetch page size"
580
+ @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."
581
+ @synonyms "fetch limit, records per page, batch size, page limit"
582
+ @tier "presentation"
511
583
  cardActionsContent : render-ui = {
512
584
  align: center
513
585
  children: [{
@@ -536,7 +608,37 @@ orbital BoardOrbital {
536
608
  direction: horizontal
537
609
  gap: sm
538
610
  type: stack
539
- }, { type: divider }, {
611
+ }, { type: divider }, (if @config.bodySearch {
612
+ children: [{
613
+ className: "w-full max-w-md"
614
+ clearable: true
615
+ event: REFETCH_QUERY
616
+ placeholder: @config.searchPlaceholder
617
+ type: search-input
618
+ }]
619
+ direction: horizontal
620
+ gap: sm
621
+ type: stack
622
+ } {
623
+ children: []
624
+ gap: none
625
+ type: stack
626
+ }), (if [">", (array/len @config.filters), 0] {
627
+ children: [{
628
+ entity: BoardView
629
+ event: REFETCH_FILTER
630
+ filters: @config.filters
631
+ look: @config.filterBarLook
632
+ type: filter-group
633
+ }]
634
+ direction: horizontal
635
+ gap: sm
636
+ type: stack
637
+ } {
638
+ children: []
639
+ gap: none
640
+ type: stack
641
+ }), {
540
642
  cols: @config.gridCols
541
643
  dndRoot: true
542
644
  entity: @entity.boards
@@ -636,7 +738,39 @@ orbital BoardOrbital {
636
738
  direction: horizontal
637
739
  gap: sm
638
740
  type: stack
639
- }, { type: divider }, {
741
+ }, { type: divider }, (if @config.bodySearch {
742
+ children: [{
743
+ className: "w-full max-w-md"
744
+ clearable: true
745
+ event: REFETCH_QUERY
746
+ placeholder: @config.searchPlaceholder
747
+ type: search-input
748
+ }]
749
+ className: px-card-md
750
+ direction: horizontal
751
+ gap: sm
752
+ type: stack
753
+ } {
754
+ children: []
755
+ gap: none
756
+ type: stack
757
+ }), (if [">", (array/len @config.filters), 0] {
758
+ children: [{
759
+ entity: BoardView
760
+ event: REFETCH_FILTER
761
+ filters: @config.filters
762
+ look: @config.filterBarLook
763
+ type: filter-group
764
+ }]
765
+ className: px-card-md
766
+ direction: horizontal
767
+ gap: sm
768
+ type: stack
769
+ } {
770
+ children: []
771
+ gap: none
772
+ type: stack
773
+ }), {
640
774
  className: "w-full pb-2"
641
775
  dndRoot: true
642
776
  entity: @entity.boards
@@ -359,7 +359,7 @@ orbital BrowseItemOrbital {
359
359
  @tier "internal"
360
360
  filters : [FilterSpec] = []
361
361
  @label "Which filters should appear above the list?"
362
- @description "Dropdown filter facets by field. Each fires a refetch when the user changes the selection. Empty = no filter bar."
362
+ @description "Dropdown filter facets by field, rendered as an embedded filter bar above the rows; each selection fires REFETCH_FILTER on this trait. Empty (the default) = no filter bar, which is the right setting whenever the page already composes std-filter beside this list and routes `XFilter.FILTER -> REFETCH_FILTER` — that is the wired owner and remains the primary path. Use this knob only for a standalone list with no page-level filter affordance, so the surface shows one filter bar instead of two."
363
363
  @synonyms "filter bar, faceted filters, field filters, column filters, dropdowns"
364
364
  @tier "presentation"
365
365
  maxInlineActions : number = 3
@@ -402,6 +402,11 @@ orbital BrowseItemOrbital {
402
402
  @description "Hint text inside the list search box (e.g. 'Search orders…')."
403
403
  @synonyms "search hint, placeholder, search box text, search label"
404
404
  @tier "presentation"
405
+ filterBarLook : "toolbar" | "chips" | "pills" | "popover-trigger" | "inline-column-header" = toolbar
406
+ @label "Filter bar look"
407
+ @description "Visual treatment for the embedded filter bar, mirroring std-filter's own enum. Only applies when `filters` is non-empty."
408
+ @synonyms "filter bar style, facet style, chips, pills"
409
+ @tier "presentation"
405
410
  viewPattern : pattern = data-grid
406
411
  @label "Render pattern"
407
412
  @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."
@@ -421,12 +426,43 @@ orbital BrowseItemOrbital {
421
426
  @synonyms "record actions, detail actions, pane actions"
422
427
  @tier "presentation"
423
428
  bodyContent : render-ui = {
424
- children: [@trait.DataGrid1]
429
+ children: [(if @config.bodySearch {
430
+ children: [{
431
+ className: "w-full max-w-md"
432
+ clearable: true
433
+ event: REFETCH_QUERY
434
+ placeholder: @config.searchPlaceholder
435
+ type: search-input
436
+ }]
437
+ direction: horizontal
438
+ gap: sm
439
+ type: stack
440
+ } {
441
+ children: []
442
+ gap: none
443
+ type: stack
444
+ }), (if [">", (array/len @config.filters), 0] {
445
+ children: [{
446
+ entity: BrowseItem
447
+ event: REFETCH_FILTER
448
+ filters: @config.filters
449
+ look: @config.filterBarLook
450
+ type: filter-group
451
+ }]
452
+ direction: horizontal
453
+ gap: sm
454
+ type: stack
455
+ } {
456
+ children: []
457
+ gap: none
458
+ type: stack
459
+ }), @trait.DataGrid1]
425
460
  direction: vertical
461
+ gap: md
426
462
  type: stack
427
463
  }
428
464
  @label "Body content tree"
429
- @description "Render-ui SExpr rendered after rows load when browseLook = table (the default). Composes the canonical data-grid call wrapped in a stack. See denseBodyContent/feedBodyContent/galleryBodyContent for the other browseLook bodies; any may be overridden directly while inheriting the same trait, state machine, emits, and listens."
465
+ @description "Render-ui SExpr rendered after rows load when browseLook = table (the default). Toolbar (search when bodySearch, filter bar when filters is non-empty) above the canonical data-grid call. Until 2026-08-27 this was the only one of the six looks with no search affordance at all. See denseBodyContent/feedBodyContent/galleryBodyContent for the other browseLook bodies; any may be overridden directly while inheriting the same trait, state machine, emits, and listens."
430
466
  @tier "internal"
431
467
  denseBodyContent : render-ui = {
432
468
  children: [(if @config.bodySearch {
@@ -445,6 +481,22 @@ orbital BrowseItemOrbital {
445
481
  children: []
446
482
  gap: none
447
483
  type: stack
484
+ }), (if [">", (array/len @config.filters), 0] {
485
+ children: [{
486
+ entity: BrowseItem
487
+ event: REFETCH_FILTER
488
+ filters: @config.filters
489
+ look: @config.filterBarLook
490
+ type: filter-group
491
+ }]
492
+ className: "px-card-md py-card-sm border-b border-[var(--color-border)]"
493
+ direction: horizontal
494
+ gap: sm
495
+ type: stack
496
+ } {
497
+ children: []
498
+ gap: none
499
+ type: stack
448
500
  }), {
449
501
  children: [@trait.DenseTableView]
450
502
  className: overflow-x-auto
@@ -478,6 +530,22 @@ orbital BrowseItemOrbital {
478
530
  children: []
479
531
  gap: none
480
532
  type: stack
533
+ }), (if [">", (array/len @config.filters), 0] {
534
+ children: [{
535
+ entity: BrowseItem
536
+ event: REFETCH_FILTER
537
+ filters: @config.filters
538
+ look: @config.filterBarLook
539
+ type: filter-group
540
+ }]
541
+ className: w-full
542
+ direction: horizontal
543
+ gap: sm
544
+ type: stack
545
+ } {
546
+ children: []
547
+ gap: none
548
+ type: stack
481
549
  }), {
482
550
  entity: ?data
483
551
  fields: []
@@ -579,6 +647,22 @@ orbital BrowseItemOrbital {
579
647
  children: []
580
648
  gap: none
581
649
  type: stack
650
+ }), (if [">", (array/len @config.filters), 0] {
651
+ children: [{
652
+ entity: BrowseItem
653
+ event: REFETCH_FILTER
654
+ filters: @config.filters
655
+ look: @config.filterBarLook
656
+ type: filter-group
657
+ }]
658
+ className: w-full
659
+ direction: horizontal
660
+ gap: sm
661
+ type: stack
662
+ } {
663
+ children: []
664
+ gap: none
665
+ type: stack
582
666
  }), {
583
667
  className: w-full
584
668
  entity: ?data
@@ -615,6 +699,22 @@ orbital BrowseItemOrbital {
615
699
  children: []
616
700
  gap: none
617
701
  type: stack
702
+ }), (if [">", (array/len @config.filters), 0] {
703
+ children: [{
704
+ entity: BrowseItem
705
+ event: REFETCH_FILTER
706
+ filters: @config.filters
707
+ look: @config.filterBarLook
708
+ type: filter-group
709
+ }]
710
+ className: "px-card-md py-card-sm border-b border-[var(--color-border)]"
711
+ direction: horizontal
712
+ gap: sm
713
+ type: stack
714
+ } {
715
+ children: []
716
+ gap: none
717
+ type: stack
618
718
  }), {
619
719
  children: [{
620
720
  entity: ?data
@@ -638,7 +738,7 @@ orbital BrowseItemOrbital {
638
738
  @description "Render-ui SExpr rendered after rows load when browseLook = triage. Inbox-register queue: one surface with a toolbar search and compact list rows (title + badges + inline meta) built for keyboard-pace queue work; row actions collapse per maxInlineActions. Composes fields/itemActions/searchPlaceholder/bodySearch."
639
739
  @tier "internal"
640
740
  masterDetailBodyContent : render-ui = {
641
- children: [{
741
+ children: [(if @config.bodySearch {
642
742
  children: [{
643
743
  className: "w-full max-w-md"
644
744
  clearable: true
@@ -650,7 +750,27 @@ orbital BrowseItemOrbital {
650
750
  direction: horizontal
651
751
  gap: sm
652
752
  type: stack
653
- }, {
753
+ } {
754
+ children: []
755
+ gap: none
756
+ type: stack
757
+ }), (if [">", (array/len @config.filters), 0] {
758
+ children: [{
759
+ entity: BrowseItem
760
+ event: REFETCH_FILTER
761
+ filters: @config.filters
762
+ look: @config.filterBarLook
763
+ type: filter-group
764
+ }]
765
+ className: "px-card-md py-card-sm border-b border-[var(--color-border)]"
766
+ direction: horizontal
767
+ gap: sm
768
+ type: stack
769
+ } {
770
+ children: []
771
+ gap: none
772
+ type: stack
773
+ }), {
654
774
  detail: {
655
775
  children: []
656
776
  gap: none
@@ -678,10 +798,10 @@ orbital BrowseItemOrbital {
678
798
  type: stack
679
799
  }
680
800
  @label "Master-detail look body (no selection)"
681
- @description "Render-ui SExpr rendered after rows load when browseLook = master-detail: record-work split view — toolbar search, dense list left, empty-state pane right until a row is opened. Opening a row renders masterDetailRecordBodyContent. The toolbar is always present in this look (bodySearch does not apply)."
801
+ @description "Render-ui SExpr rendered after rows load when browseLook = master-detail: record-work split view — toolbar, dense list left, empty-state pane right until a row is opened. Opening a row renders masterDetailRecordBodyContent. The toolbar honours bodySearch and filters like every other look; it used to render its search box unconditionally, which put a second search box on any page that already composed std-search (observed in std-crm ContactOrbital)."
682
802
  @tier "internal"
683
803
  masterDetailRecordBodyContent : render-ui = {
684
- children: [{
804
+ children: [(if @config.bodySearch {
685
805
  children: [{
686
806
  className: "w-full max-w-md"
687
807
  clearable: true
@@ -693,7 +813,27 @@ orbital BrowseItemOrbital {
693
813
  direction: horizontal
694
814
  gap: sm
695
815
  type: stack
696
- }, {
816
+ } {
817
+ children: []
818
+ gap: none
819
+ type: stack
820
+ }), (if [">", (array/len @config.filters), 0] {
821
+ children: [{
822
+ entity: BrowseItem
823
+ event: REFETCH_FILTER
824
+ filters: @config.filters
825
+ look: @config.filterBarLook
826
+ type: filter-group
827
+ }]
828
+ className: "px-card-md py-card-sm border-b border-[var(--color-border)]"
829
+ direction: horizontal
830
+ gap: sm
831
+ type: stack
832
+ } {
833
+ children: []
834
+ gap: none
835
+ type: stack
836
+ }), {
697
837
  detail: {
698
838
  actions: @config.detailActions
699
839
  fieldNames: @config.detailFields