@almadar/std 16.187.0 → 16.188.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.
- package/behaviors/lolo/ui/core/.hand-authored.json +4 -0
- package/behaviors/lolo/ui/core/atoms/std-board.lolo +138 -4
- package/behaviors/lolo/ui/core/atoms/std-browse.lolo +148 -8
- package/behaviors/lolo/ui/core/atoms/std-calendar.lolo +141 -3
- package/behaviors/lolo/ui/core/atoms/std-event-log.lolo +255 -2
- package/behaviors/lolo/ui/core/atoms/std-gallery.lolo +148 -1
- package/behaviors/lolo/ui/core/atoms/std-list.lolo +193 -1
- package/behaviors/lolo/ui/core/atoms/std-record-detail.lolo +329 -0
- package/behaviors/lolo/ui/core/atoms/std-selection.lolo +182 -1
- package/behaviors/lolo/ui/core/atoms/std-tree.lolo +113 -3
- package/behaviors/lolo/ui/game/atoms/std-area-fill.lolo +93 -0
- package/behaviors/lolo/ui/game/atoms/std-loop-lock.lolo +79 -0
- package/behaviors/lolo/ui/game/atoms/std-pad-lock.lolo +93 -0
- package/behaviors/lolo/ui/game/atoms/std-patrol-hazard.lolo +14 -7
- package/behaviors/lolo/ui/game/atoms/std-platformer-body.lolo +21 -4
- package/behaviors/lolo/ui/game/atoms/std-velocity-gate.lolo +101 -0
- package/behaviors/registry/infra/atoms/std-approval-gate.orb +16 -8
- package/behaviors/registry/infra/atoms/std-cache-aside.orb +62 -31
- package/behaviors/registry/infra/atoms/std-circuit-breaker.orb +32 -16
- package/behaviors/registry/infra/atoms/std-data-erasure.orb +16 -8
- package/behaviors/registry/infra/atoms/std-mod-queue.orb +16 -8
- package/behaviors/registry/infra/atoms/std-rate-limiter.orb +28 -14
- package/behaviors/registry/infra/organisms/std-status-lifecycle-control.orb +2 -1
- package/behaviors/registry/ml/organisms/std-escalating-decision.orb +10 -5
- package/behaviors/registry/ml/organisms/std-knowledge-tracing.orb +4 -2
- package/behaviors/registry/ui/core/atoms/std-billable-hour.orb +2 -1
- package/behaviors/registry/ui/core/atoms/std-board.orb +355 -2
- package/behaviors/registry/ui/core/atoms/std-browse.orb +304 -31
- package/behaviors/registry/ui/core/atoms/std-calendar.orb +344 -0
- package/behaviors/registry/ui/core/atoms/std-dashboard-grid-embedded.orb +2 -1
- package/behaviors/registry/ui/core/atoms/std-esign-flow.orb +4 -2
- package/behaviors/registry/ui/core/atoms/std-esign-request.orb +6 -3
- package/behaviors/registry/ui/core/atoms/std-event-log.orb +773 -0
- package/behaviors/registry/ui/core/atoms/std-export.orb +4 -2
- package/behaviors/registry/ui/core/atoms/std-gallery.orb +390 -0
- package/behaviors/registry/ui/core/atoms/std-import.orb +4 -2
- package/behaviors/registry/ui/core/atoms/std-list.orb +451 -0
- package/behaviors/registry/ui/core/atoms/std-record-detail.orb +1141 -0
- package/behaviors/registry/ui/core/atoms/std-selection.orb +436 -0
- package/behaviors/registry/ui/core/atoms/std-tree.orb +292 -1
- package/behaviors/registry/ui/game/atoms/std-area-fill.orb +955 -0
- package/behaviors/registry/ui/game/atoms/std-fx-trail.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-gate-lock.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-lives.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-loop-lock.orb +785 -0
- package/behaviors/registry/ui/game/atoms/std-pad-lock.orb +903 -0
- package/behaviors/registry/ui/game/atoms/std-patrol-hazard.orb +190 -44
- package/behaviors/registry/ui/game/atoms/std-platformer-body.orb +868 -637
- package/behaviors/registry/ui/game/atoms/std-velocity-gate.orb +1040 -0
- package/behaviors/registry/ui/game/organisms/std-arcade-board-3d.orb +8 -4
- package/behaviors/registry/ui/game/organisms/std-crew-board-2d.orb +6 -3
- package/behaviors/registry/ui/game/organisms/std-dungeon-board-2d.orb +10 -5
- package/behaviors/registry/ui/game/organisms/std-market-board-3d.orb +8 -4
- package/behaviors/registry/ui/game/organisms/std-objective-board-3d.orb +8 -4
- package/behaviors/registry/ui/game/organisms/std-platformer-board-2d.orb +7 -4
- package/behaviors/registry/ui/game/organisms/std-survival-board-3d.orb +8 -4
- package/behaviors/registry/ui/game/organisms/std-tactics-board-2d.orb +12 -6
- package/behaviors/registry/ui/game/organisms/std-tactics-board-3d.orb +8 -4
- package/behaviors/registry/ui/game/organisms/std-worldmap-board-2d.orb +6 -3
- package/behaviors/registry/ui/learning/atoms/std-learn-slope-probe.orb +1 -1
- package/behaviors/registry/ui/marketing/atoms/std-marketing-article.orb +2 -1
- package/behaviors/registry/ui/marketing/atoms/std-marketing-footer.orb +2 -1
- package/behaviors/registry/ui/marketing/atoms/std-marketing-split.orb +2 -1
- package/behaviors/registry/ui/marketing/atoms/std-marketing-stats.orb +2 -1
- package/behaviors/registry/ui/marketing/atoms/std-marketing-steps.orb +2 -1
- package/behaviors/registry/ui/marketing/atoms/std-marketing-team.orb +2 -1
- package/dist/behaviors/exports-reader.js +7541 -3153
- package/dist/behaviors/functions/index.d.ts +598 -18
- package/dist/behaviors/functions/index.js +7524 -3154
- package/dist/behaviors/index.d.ts +1 -1
- package/dist/behaviors/index.js +7542 -3154
- package/dist/behaviors/query.js +7541 -3153
- package/dist/behaviors-embeddings.hash.json +3 -3
- package/dist/behaviors-embeddings.json +485 -461
- package/dist/behaviors-registry.json +2612 -934
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7542 -3154
- package/dist/knob-embeddings.hash.json +3 -3
- package/dist/knob-embeddings.json +1 -1
- package/dist/registry/factory-signatures.json +1 -1
- package/package.json +1 -1
|
@@ -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"
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
app std-board "1.
|
|
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
|
|
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: [@
|
|
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).
|
|
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
|
|
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
|
|
@@ -1,6 +1,7 @@
|
|
|
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
3
|
type ItemAction = { label : string!, event : string, navigatesTo : string, variant : primary | secondary | ghost | danger, icon : string }
|
|
4
|
+
type FilterSpec = { field : string!, label : string, options : [string] }
|
|
4
5
|
orbital CalendarEventOrbital {
|
|
5
6
|
type CalendarEventLoaded = Event { data : [CalendarEvent] } "Fired when CalendarEvent finishes loading; payload.data holds the events"
|
|
6
7
|
|
|
@@ -101,6 +102,20 @@ orbital CalendarEventOrbital {
|
|
|
101
102
|
(fetch CalendarEvent {
|
|
102
103
|
emit: { failure: CalendarEventLoadFailed, success: CalendarEventLoaded }
|
|
103
104
|
})
|
|
105
|
+
;; Same no-render-ui shape as SELECT_DAY/CALENDAR_*_WEEK above: transition
|
|
106
|
+
;; to `loading` without repainting, so the current grid/agenda/timeline
|
|
107
|
+
;; stays mounted until CalendarEventLoaded's own render-ui fires — a
|
|
108
|
+
;; repaint here would flicker the toolbar's search-input every keystroke.
|
|
109
|
+
REFETCH_QUERY -> loading
|
|
110
|
+
(fetch CalendarEvent {
|
|
111
|
+
emit: { failure: CalendarEventLoadFailed, success: CalendarEventLoaded }
|
|
112
|
+
filter: (or ["=", ?searchTerm, ""] (str/includes (object/get @entity name) ?searchTerm))
|
|
113
|
+
})
|
|
114
|
+
REFETCH_FILTER -> loading
|
|
115
|
+
(fetch CalendarEvent {
|
|
116
|
+
emit: { failure: CalendarEventLoadFailed, success: CalendarEventLoaded }
|
|
117
|
+
filter: (or ["=", ?value, ""] ["=", (object/get @entity ?field), ?value])
|
|
118
|
+
})
|
|
104
119
|
}
|
|
105
120
|
|
|
106
121
|
state error {
|
|
@@ -162,6 +177,19 @@ orbital CalendarEventOrbital {
|
|
|
162
177
|
@description "Move the week timeline one week later."
|
|
163
178
|
@synonyms "next week, forward a week, later week, following week"
|
|
164
179
|
@tier "domain"
|
|
180
|
+
REFETCH_QUERY {
|
|
181
|
+
searchTerm : string!
|
|
182
|
+
}
|
|
183
|
+
@description "Triggers a data refresh based on the current query."
|
|
184
|
+
@synonyms "refresh, reload, update, re-query"
|
|
185
|
+
@tier "domain"
|
|
186
|
+
REFETCH_FILTER {
|
|
187
|
+
field : string!
|
|
188
|
+
value : string!
|
|
189
|
+
}
|
|
190
|
+
@description "Triggers a data refresh based on current filter criteria."
|
|
191
|
+
@synonyms "refresh, filter, update, reload"
|
|
192
|
+
@tier "domain"
|
|
165
193
|
}
|
|
166
194
|
|
|
167
195
|
config {
|
|
@@ -213,6 +241,26 @@ orbital CalendarEventOrbital {
|
|
|
213
241
|
@description "Row field the agenda list groups its day sections by. Rebound hosts point this at their own timestamp column (e.g. startTime, scheduledAt)."
|
|
214
242
|
@synonyms "group field, section field, day field"
|
|
215
243
|
@tier "presentation"
|
|
244
|
+
bodySearch : boolean = false
|
|
245
|
+
@label "Show the calendar's own search box?"
|
|
246
|
+
@description "Embeds a title search box in the toolbar above the calendar body (all three calendarLook trees). Defaults false: std-calendar has never had a search box, so an untouched consumer's surface is unchanged; the primary path is composing std-search beside this atom and wiring XSearch.SEARCH -> REFETCH_QUERY. Set true only for a standalone calendar with no page-level search affordance."
|
|
247
|
+
@synonyms "inline search, calendar search, built-in search, show search, duplicate search"
|
|
248
|
+
@tier "presentation"
|
|
249
|
+
searchPlaceholder : string = "Search…"
|
|
250
|
+
@label "Search box placeholder text"
|
|
251
|
+
@description "Hint text inside the calendar's search box (e.g. 'Search events…')."
|
|
252
|
+
@synonyms "search hint, placeholder, search box text, search label"
|
|
253
|
+
@tier "presentation"
|
|
254
|
+
filters : [FilterSpec] = []
|
|
255
|
+
@label "Which filters should appear above the calendar?"
|
|
256
|
+
@description "Dropdown filter facets by field, rendered as an embedded filter bar above the calendar body (all three calendarLook trees); 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 calendar and routes XFilter.FILTER -> REFETCH_FILTER — that is the wired owner and remains the primary path. Use this knob only for a standalone calendar with no page-level filter affordance."
|
|
257
|
+
@synonyms "filter bar, faceted filters, field filters, dropdowns"
|
|
258
|
+
@tier "presentation"
|
|
259
|
+
filterBarLook : "toolbar" | "chips" | "pills" | "popover-trigger" | "inline-column-header" = toolbar
|
|
260
|
+
@label "Filter bar look"
|
|
261
|
+
@description "Visual treatment for the embedded filter bar, mirroring std-filter's own enum. Only applies when `filters` is non-empty."
|
|
262
|
+
@synonyms "filter bar style, facet style, chips, pills"
|
|
263
|
+
@tier "presentation"
|
|
216
264
|
bodyContent : render-ui = {
|
|
217
265
|
children: [{
|
|
218
266
|
align: center
|
|
@@ -235,7 +283,37 @@ orbital CalendarEventOrbital {
|
|
|
235
283
|
gap: md
|
|
236
284
|
justify: between
|
|
237
285
|
type: stack
|
|
238
|
-
},
|
|
286
|
+
}, (if @config.bodySearch {
|
|
287
|
+
children: [{
|
|
288
|
+
className: "w-full max-w-md"
|
|
289
|
+
clearable: true
|
|
290
|
+
event: REFETCH_QUERY
|
|
291
|
+
placeholder: @config.searchPlaceholder
|
|
292
|
+
type: search-input
|
|
293
|
+
}]
|
|
294
|
+
direction: horizontal
|
|
295
|
+
gap: sm
|
|
296
|
+
type: stack
|
|
297
|
+
} {
|
|
298
|
+
children: []
|
|
299
|
+
gap: none
|
|
300
|
+
type: stack
|
|
301
|
+
}), (if [">", (array/len @config.filters), 0] {
|
|
302
|
+
children: [{
|
|
303
|
+
entity: CalendarEvent
|
|
304
|
+
event: REFETCH_FILTER
|
|
305
|
+
filters: @config.filters
|
|
306
|
+
look: @config.filterBarLook
|
|
307
|
+
type: filter-group
|
|
308
|
+
}]
|
|
309
|
+
direction: horizontal
|
|
310
|
+
gap: sm
|
|
311
|
+
type: stack
|
|
312
|
+
} {
|
|
313
|
+
children: []
|
|
314
|
+
gap: none
|
|
315
|
+
type: stack
|
|
316
|
+
}), { type: divider }, {
|
|
239
317
|
events: ?data
|
|
240
318
|
onEventClick: @config.onEventClick
|
|
241
319
|
renderItem: (fn item {
|
|
@@ -307,7 +385,37 @@ orbital CalendarEventOrbital {
|
|
|
307
385
|
gap: md
|
|
308
386
|
justify: between
|
|
309
387
|
type: stack
|
|
310
|
-
},
|
|
388
|
+
}, (if @config.bodySearch {
|
|
389
|
+
children: [{
|
|
390
|
+
className: "w-full max-w-md"
|
|
391
|
+
clearable: true
|
|
392
|
+
event: REFETCH_QUERY
|
|
393
|
+
placeholder: @config.searchPlaceholder
|
|
394
|
+
type: search-input
|
|
395
|
+
}]
|
|
396
|
+
direction: horizontal
|
|
397
|
+
gap: sm
|
|
398
|
+
type: stack
|
|
399
|
+
} {
|
|
400
|
+
children: []
|
|
401
|
+
gap: none
|
|
402
|
+
type: stack
|
|
403
|
+
}), (if [">", (array/len @config.filters), 0] {
|
|
404
|
+
children: [{
|
|
405
|
+
entity: CalendarEvent
|
|
406
|
+
event: REFETCH_FILTER
|
|
407
|
+
filters: @config.filters
|
|
408
|
+
look: @config.filterBarLook
|
|
409
|
+
type: filter-group
|
|
410
|
+
}]
|
|
411
|
+
direction: horizontal
|
|
412
|
+
gap: sm
|
|
413
|
+
type: stack
|
|
414
|
+
} {
|
|
415
|
+
children: []
|
|
416
|
+
gap: none
|
|
417
|
+
type: stack
|
|
418
|
+
}), { type: divider }, {
|
|
311
419
|
entity: ?data
|
|
312
420
|
fields: []
|
|
313
421
|
gap: md
|
|
@@ -429,7 +537,37 @@ orbital CalendarEventOrbital {
|
|
|
429
537
|
gap: md
|
|
430
538
|
justify: between
|
|
431
539
|
type: stack
|
|
432
|
-
},
|
|
540
|
+
}, (if @config.bodySearch {
|
|
541
|
+
children: [{
|
|
542
|
+
className: "w-full max-w-md"
|
|
543
|
+
clearable: true
|
|
544
|
+
event: REFETCH_QUERY
|
|
545
|
+
placeholder: @config.searchPlaceholder
|
|
546
|
+
type: search-input
|
|
547
|
+
}]
|
|
548
|
+
direction: horizontal
|
|
549
|
+
gap: sm
|
|
550
|
+
type: stack
|
|
551
|
+
} {
|
|
552
|
+
children: []
|
|
553
|
+
gap: none
|
|
554
|
+
type: stack
|
|
555
|
+
}), (if [">", (array/len @config.filters), 0] {
|
|
556
|
+
children: [{
|
|
557
|
+
entity: CalendarEvent
|
|
558
|
+
event: REFETCH_FILTER
|
|
559
|
+
filters: @config.filters
|
|
560
|
+
look: @config.filterBarLook
|
|
561
|
+
type: filter-group
|
|
562
|
+
}]
|
|
563
|
+
direction: horizontal
|
|
564
|
+
gap: sm
|
|
565
|
+
type: stack
|
|
566
|
+
} {
|
|
567
|
+
children: []
|
|
568
|
+
gap: none
|
|
569
|
+
type: stack
|
|
570
|
+
}), { type: divider }, {
|
|
433
571
|
className: w-full
|
|
434
572
|
dayWindow: 7
|
|
435
573
|
events: ?data
|