@almadar/std 16.236.0 → 16.237.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 (115) hide show
  1. package/behaviors/behaviors-registry.json +1389 -265
  2. package/behaviors/lolo/infra/atoms/std-approval-gate.lolo +7 -0
  3. package/behaviors/lolo/infra/atoms/std-migration-job.lolo +2 -2
  4. package/behaviors/lolo/infra/atoms/std-notification-preferences.lolo +5 -0
  5. package/behaviors/lolo/infra/atoms/std-permission-matrix.lolo +5 -0
  6. package/behaviors/lolo/ui/core/atoms/std-browse.lolo +32 -5
  7. package/behaviors/lolo/ui/core/atoms/std-event-log.lolo +32 -0
  8. package/behaviors/lolo/ui/core/atoms/std-file-store.lolo +8 -1
  9. package/behaviors/lolo/ui/core/atoms/std-gantt-schedule.lolo +8 -1
  10. package/behaviors/lolo/ui/core/atoms/std-image-upload-multi.lolo +2 -2
  11. package/behaviors/lolo/ui/core/atoms/std-list.lolo +7 -0
  12. package/behaviors/lolo/ui/core/atoms/std-multi-party-flow.lolo +24 -0
  13. package/behaviors/lolo/ui/core/atoms/std-record-detail.lolo +13 -1
  14. package/behaviors/lolo/ui/core/atoms/std-recurrence.lolo +4 -0
  15. package/behaviors/lolo/ui/core/atoms/std-saved-search.lolo +6 -0
  16. package/behaviors/lolo/ui/core/atoms/std-selection.lolo +7 -0
  17. package/behaviors/lolo/ui/core/atoms/std-version-history.lolo +7 -1
  18. package/behaviors/lolo/ui/core/atoms/ui-time-slot-cell.lolo +36 -0
  19. package/behaviors/lolo/ui/core/atoms/ui-typography.lolo +5 -0
  20. package/behaviors/lolo/ui/core/molecules/ui-alert.lolo +5 -0
  21. package/behaviors/lolo/ui/core/molecules/ui-animated-counter.lolo +1 -1
  22. package/behaviors/lolo/ui/core/molecules/ui-command-palette.lolo +4 -4
  23. package/behaviors/lolo/ui/core/molecules/ui-data-grid.lolo +19 -2
  24. package/behaviors/lolo/ui/core/molecules/ui-data-list.lolo +6 -0
  25. package/behaviors/lolo/ui/core/molecules/ui-date-range-picker.lolo +3 -3
  26. package/behaviors/lolo/ui/core/molecules/ui-document-details.lolo +1 -0
  27. package/behaviors/lolo/ui/core/molecules/ui-emoji-picker.lolo +1 -1
  28. package/behaviors/lolo/ui/core/molecules/ui-feature-card.lolo +1 -1
  29. package/behaviors/lolo/ui/core/molecules/ui-gantt.lolo +9 -1
  30. package/behaviors/lolo/ui/core/molecules/ui-import-preview-tree.lolo +3 -2
  31. package/behaviors/lolo/ui/core/molecules/ui-likert-scale.lolo +1 -1
  32. package/behaviors/lolo/ui/core/molecules/ui-menu.lolo +1 -0
  33. package/behaviors/lolo/ui/core/molecules/ui-table-view.lolo +16 -2
  34. package/behaviors/lolo/ui/core/organisms/ui-detail-panel.lolo +21 -4
  35. package/behaviors/lolo/ui/core/organisms/ui-entity-cards.lolo +28 -7
  36. package/behaviors/lolo/ui/core/organisms/ui-entity-list.lolo +37 -5
  37. package/behaviors/lolo/ui/core/organisms/ui-entity-table.lolo +18 -1
  38. package/behaviors/lolo/ui/core/organisms/ui-form-section.lolo +2 -0
  39. package/behaviors/lolo/ui/core/organisms/ui-form.lolo +2 -0
  40. package/behaviors/lolo/ui/core/organisms/ui-media-gallery.lolo +14 -0
  41. package/behaviors/lolo/ui/core/organisms/ui-stat-card.lolo +6 -0
  42. package/behaviors/lolo/ui/core/organisms/ui-timeline.lolo +30 -2
  43. package/behaviors/lolo/ui/core/templates/ui-auth-layout.lolo +1 -1
  44. package/behaviors/lolo/ui/core/templates/ui-counter-template.lolo +1 -1
  45. package/behaviors/lolo/ui/core/templates/ui-dashboard-layout.lolo +1 -1
  46. package/behaviors/lolo/ui/game/.hand-authored.json +2 -2
  47. package/behaviors/lolo/ui/game/atoms/ui-choice-button.lolo +1 -1
  48. package/behaviors/lolo/ui/game/atoms/ui-dialogue-bubble.lolo +2 -2
  49. package/behaviors/lolo/ui/game/atoms/ui-game-menu.lolo +1 -1
  50. package/behaviors/lolo/ui/game/atoms/ui-score-display.lolo +1 -1
  51. package/behaviors/lolo-behavior-contracts.json +1 -1
  52. package/behaviors/registry/factory-signatures.json +1 -1
  53. package/behaviors/registry/infra/atoms/std-approval-gate.orb +70 -0
  54. package/behaviors/registry/infra/atoms/std-migration-job.orb +26 -1
  55. package/behaviors/registry/infra/atoms/std-notification-preferences.orb +9 -0
  56. package/behaviors/registry/infra/atoms/std-permission-matrix.orb +9 -0
  57. package/behaviors/registry/ui/core/atoms/std-browse.orb +204 -8
  58. package/behaviors/registry/ui/core/atoms/std-event-log.orb +44 -0
  59. package/behaviors/registry/ui/core/atoms/std-file-store.orb +12 -1
  60. package/behaviors/registry/ui/core/atoms/std-gantt-schedule.orb +25 -1
  61. package/behaviors/registry/ui/core/atoms/std-image-upload-multi.orb +4 -0
  62. package/behaviors/registry/ui/core/atoms/std-list.orb +11 -0
  63. package/behaviors/registry/ui/core/atoms/std-multi-party-flow.orb +24 -0
  64. package/behaviors/registry/ui/core/atoms/std-record-detail.orb +71 -3
  65. package/behaviors/registry/ui/core/atoms/std-recurrence.orb +4 -0
  66. package/behaviors/registry/ui/core/atoms/std-saved-search.orb +54 -0
  67. package/behaviors/registry/ui/core/atoms/std-selection.orb +39 -0
  68. package/behaviors/registry/ui/core/atoms/std-version-history.orb +11 -1
  69. package/behaviors/registry/ui/core/atoms/ui-time-slot-cell.orb +132 -0
  70. package/behaviors/registry/ui/core/atoms/ui-typography.orb +7 -0
  71. package/behaviors/registry/ui/core/molecules/ui-alert.orb +7 -0
  72. package/behaviors/registry/ui/core/molecules/ui-animated-counter.orb +1 -1
  73. package/behaviors/registry/ui/core/molecules/ui-command-palette.orb +2 -4
  74. package/behaviors/registry/ui/core/molecules/ui-data-grid.orb +108 -2
  75. package/behaviors/registry/ui/core/molecules/ui-data-list.orb +72 -0
  76. package/behaviors/registry/ui/core/molecules/ui-date-range-picker.orb +1 -3
  77. package/behaviors/registry/ui/core/molecules/ui-document-details.orb +12 -0
  78. package/behaviors/registry/ui/core/molecules/ui-emoji-picker.orb +0 -1
  79. package/behaviors/registry/ui/core/molecules/ui-feature-card.orb +0 -1
  80. package/behaviors/registry/ui/core/molecules/ui-gantt.orb +28 -1
  81. package/behaviors/registry/ui/core/molecules/ui-import-preview-tree.orb +9 -2
  82. package/behaviors/registry/ui/core/molecules/ui-likert-scale.orb +1 -1
  83. package/behaviors/registry/ui/core/molecules/ui-menu.orb +17 -0
  84. package/behaviors/registry/ui/core/molecules/ui-table-view.orb +148 -2
  85. package/behaviors/registry/ui/core/organisms/ui-detail-panel.orb +133 -13
  86. package/behaviors/registry/ui/core/organisms/ui-entity-cards.orb +210 -26
  87. package/behaviors/registry/ui/core/organisms/ui-entity-list.orb +166 -17
  88. package/behaviors/registry/ui/core/organisms/ui-entity-table.orb +122 -0
  89. package/behaviors/registry/ui/core/organisms/ui-form-section.orb +28 -0
  90. package/behaviors/registry/ui/core/organisms/ui-form.orb +28 -0
  91. package/behaviors/registry/ui/core/organisms/ui-media-gallery.orb +20 -0
  92. package/behaviors/registry/ui/core/organisms/ui-stat-card.orb +58 -0
  93. package/behaviors/registry/ui/core/organisms/ui-timeline.orb +38 -5
  94. package/behaviors/registry/ui/core/templates/ui-auth-layout.orb +0 -1
  95. package/behaviors/registry/ui/core/templates/ui-counter-template.orb +0 -1
  96. package/behaviors/registry/ui/core/templates/ui-dashboard-layout.orb +0 -1
  97. package/behaviors/registry/ui/game/atoms/ui-choice-button.orb +1 -1
  98. package/behaviors/registry/ui/game/atoms/ui-dialogue-bubble.orb +1 -2
  99. package/behaviors/registry/ui/game/atoms/ui-game-menu.orb +1 -1
  100. package/behaviors/registry/ui/game/atoms/ui-score-display.orb +0 -1
  101. package/dist/behaviors/exports-reader.js +1157 -61
  102. package/dist/behaviors/functions/index.d.ts +114 -32
  103. package/dist/behaviors/functions/index.js +1157 -61
  104. package/dist/behaviors/index.d.ts +1 -1
  105. package/dist/behaviors/index.js +1157 -61
  106. package/dist/behaviors/query.js +1157 -61
  107. package/dist/behaviors-embeddings.hash.json +3 -3
  108. package/dist/behaviors-embeddings.json +15 -15
  109. package/dist/behaviors-registry.json +1389 -265
  110. package/dist/index.d.ts +1 -1
  111. package/dist/index.js +1157 -61
  112. package/dist/knob-embeddings.hash.json +3 -3
  113. package/dist/knob-embeddings.json +165 -25
  114. package/dist/registry/factory-signatures.json +1 -1
  115. package/package.json +3 -3
@@ -189,10 +189,12 @@ orbital ApprovalGateOrbital {
189
189
  variant: caption
190
190
  }, {
191
191
  label: Requested
192
+ format: date
192
193
  name: requestedAt
193
194
  variant: caption
194
195
  }]
195
196
  gap: sm
197
+ itemClickEvent: @config.itemClickEvent
196
198
  itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
197
199
  look: @config.tableLook
198
200
  type: data-grid
@@ -337,6 +339,7 @@ orbital ApprovalGateOrbital {
337
339
  @tier "domain"
338
340
  OPEN_SUBJECT -> external {
339
341
  id : string!
342
+ row : ApprovalRequest
340
343
  subjectId : string
341
344
  subjectLabel : string
342
345
  }
@@ -496,6 +499,10 @@ orbital ApprovalGateOrbital {
496
499
  @label "Review slot"
497
500
  @description "UI slot the review queue renders into. Defaults to the modal overlay so the queue never seizes the host's main content; summoned via OPEN, cleared via CLOSE."
498
501
  @tier "internal"
502
+ itemClickEvent : event = OPEN_SUBJECT
503
+ @label "Row click"
504
+ @description "Event emitted when a row is clicked; opens the subject under review. Empty disables the row click."
505
+ @tier "presentation"
499
506
  itemActions : [ItemAction] = [{
500
507
  event: OPEN_SUBJECT
501
508
  icon: eye
@@ -4,7 +4,7 @@ orbital MigrationJobOrbital {
4
4
 
5
5
  type MigrationFile = { name : string, size : number, type : string, lastModified : number }
6
6
  type ImportSourceOption = { id : string!, kind : string!, label : string!, event : string }
7
- type ImportUnit = { ref : string!, targetEntity : string!, fields : Map string scalar, parentRef : string }
7
+ type ImportUnit = { ref : string!, targetEntity : string!, title : string, fields : Map string scalar, parentRef : string }
8
8
  type ImportSkip = { ref : string!, reason : string! }
9
9
  type MigrationStats = { committed : number, failed : [Map string scalar] }
10
10
 
@@ -17,7 +17,7 @@ orbital MigrationJobOrbital {
17
17
  documents : [Map string scalar] @description "Document metadata listed from the source — migration.listDocuments service result, never destructured by the atom." = []
18
18
  document : Map string scalar @description "Most recently fetched document content — migration.fetchDocument service result, never destructured by the atom." = {}
19
19
  stats : MigrationStats @description "Staged/committed/failed/skipped counts — merged from host staging and migration.commit service results, never destructured by the atom." = {}
20
- units : [ImportUnit] @description "Staged ImportUnits ready for review (ref/targetEntity/fields/parentRef), when the host stages the full rows rather than aggregate stats only." @synonyms "staged units, preview rows, import rows, staged rows" = []
20
+ units : [ImportUnit] @description "Staged ImportUnits ready for review (ref/targetEntity/title/fields/parentRef), when the host stages the full rows rather than aggregate stats only." @synonyms "staged units, preview rows, import rows, staged rows" = []
21
21
  skipped : [ImportSkip] @description "Source elements skipped during staging with a reason each, when the host stages the full rows rather than aggregate stats only." @synonyms "skipped rows, skipped elements, staging skips" = []
22
22
  validationErrors : [Map string scalar] @description "Validation errors surfaced during staging, when the host stages the full rows rather than aggregate stats only." @synonyms "staging errors, validation issues, import errors" = []
23
23
  error : string @description "Failure detail when status is failed." = ""
@@ -103,6 +103,7 @@ orbital NotificationPreferencesOrbital {
103
103
  variant: caption
104
104
  }]
105
105
  gap: sm
106
+ itemClickEvent: @config.itemClickEvent
106
107
  itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
107
108
  look: @config.tableLook
108
109
  type: data-grid
@@ -333,6 +334,10 @@ orbital NotificationPreferencesOrbital {
333
334
  @label "Table look"
334
335
  @description "Layer 2 visual treatment for the preference data table rendered by this atom."
335
336
  @tier "presentation"
337
+ itemClickEvent : event = EDIT
338
+ @label "Row click"
339
+ @description "Event emitted when a row is clicked; opens the preference for editing. Empty disables the row click."
340
+ @tier "presentation"
336
341
  itemActions : [ItemAction] = [{
337
342
  event: EDIT
338
343
  icon: pencil
@@ -162,6 +162,7 @@ orbital PermissionMatrixOrbital {
162
162
  variant: caption
163
163
  }]
164
164
  gap: sm
165
+ itemClickEvent: @config.itemClickEvent
165
166
  itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
166
167
  type: data-grid
167
168
  }]
@@ -248,6 +249,10 @@ orbital PermissionMatrixOrbital {
248
249
  config {}
249
250
 
250
251
  config {
252
+ itemClickEvent : event = EDIT
253
+ @label "Row click"
254
+ @description "Event emitted when a row is clicked; opens the grant for editing. Empty disables the row click."
255
+ @tier "presentation"
251
256
  itemActions : [ItemAction] = [{
252
257
  event: EDIT
253
258
  icon: pencil
@@ -1,8 +1,9 @@
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
- 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 }
3
+ type BadgeColor = "default" | "primary" | "secondary" | "success" | "warning" | "danger" | "error" | "info" | "neutral" | "destructive"
4
+ 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, colorMap : Map string BadgeColor, labels : Map string string }
4
5
  type ItemAction = { label : string!, event : event, navigatesTo : string, variant : primary | secondary | ghost | danger, icon : string, roles : [string], when : SExpr }
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
+ 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, colorMap : Map string BadgeColor, labels : Map string string, variant : h3 | h4 }
6
7
  type FilterSpec = { field : string!, label : string, options : [string] }
7
8
  orbital BrowseItemOrbital {
8
9
  type BrowseDetailAction = {
@@ -406,11 +407,32 @@ orbital BrowseItemOrbital {
406
407
  @label "Browse look"
407
408
  @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."
408
409
  @tier "presentation"
409
- detailFields : [string] = [name, description, status, createdAt]
410
+ detailFields : [FieldSpec] = [{
411
+ label: Name
412
+ name: name
413
+ variant: h4
414
+ }, {
415
+ label: Description
416
+ name: description
417
+ variant: body
418
+ }, {
419
+ label: Status
420
+ name: status
421
+ variant: badge
422
+ }, {
423
+ format: date
424
+ label: Created
425
+ name: createdAt
426
+ }]
410
427
  @label "Which fields appear in the master-detail record pane?"
411
- @description "Field names shown in the detail panel when browseLook = master-detail; the first entry doubles as the pane title. Consumers overriding columns/fields should override this list to match their entity."
428
+ @description "Fields shown in the detail panel when browseLook = master-detail; the field declared variant h3/h4 is the pane title. Consumers overriding columns/fields should override this list to match their entity."
412
429
  @synonyms "detail columns, record fields, detail pane fields"
413
430
  @tier "presentation"
431
+ detailCloseEvent : event = CLOSE
432
+ @label "Which pane action closes the record?"
433
+ @description "The detailActions entry whose event matches renders as the pane's close (×) button."
434
+ @synonyms "close event, dismiss event, pane close"
435
+ @tier "presentation"
414
436
  detailActions : [BrowseDetailAction] = [{ event: CLOSE, label: Close }]
415
437
  @label "Master-detail record pane actions"
416
438
  @description "Action buttons on the master-detail record pane (detail-panel `actions` descriptors: label/event/icon/variant). Consumers add their own record actions (Edit/Delete/…) alongside or instead of Close."
@@ -453,6 +475,7 @@ orbital BrowseItemOrbital {
453
475
  fields: @config.fields
454
476
  gap: @config.gap
455
477
  imageField: @config.imageField
478
+ itemClickEvent: @config.itemClickEvent
456
479
  itemActions: (array/filter @config.itemActions (fn item (or (= (array/len (object/get @item roles [])) 0) (array/includes (object/get @item roles []) @config.viewerRole))))
457
480
  maxInlineActions: @config.maxInlineActions
458
481
  pageSize: @config.displayPageSize
@@ -566,6 +589,7 @@ orbital BrowseItemOrbital {
566
589
  entity: ?data
567
590
  fields: []
568
591
  gap: md
592
+ itemClickEvent: @config.itemClickEvent
569
593
  itemActions: (array/filter @config.itemActions (fn item (or (= (array/len (object/get @item roles [])) 0) (array/includes (object/get @item roles []) @config.viewerRole))))
570
594
  renderItem: (fn item {
571
595
  children: [{
@@ -688,6 +712,7 @@ orbital BrowseItemOrbital {
688
712
  fields: @config.fields
689
713
  gap: lg
690
714
  imageField: @config.imageField
715
+ itemClickEvent: @config.itemClickEvent
691
716
  itemActions: (array/filter @config.itemActions (fn item (or (= (array/len (object/get @item roles [])) 0) (array/includes (object/get @item roles []) @config.viewerRole))))
692
717
  maxInlineActions: @config.maxInlineActions
693
718
  minCardWidth: 260
@@ -741,6 +766,7 @@ orbital BrowseItemOrbital {
741
766
  children: [{
742
767
  entity: ?data
743
768
  fields: @config.fields
769
+ itemClickEvent: @config.itemClickEvent
744
770
  itemActions: (array/filter @config.itemActions (fn item (or (= (array/len (object/get @item roles [])) 0) (array/includes (object/get @item roles []) @config.viewerRole))))
745
771
  maxInlineActions: @config.maxInlineActions
746
772
  emptyDescription: @config.emptyDescription
@@ -861,7 +887,8 @@ orbital BrowseItemOrbital {
861
887
  }), {
862
888
  detail: {
863
889
  actions: (array/filter @config.detailActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
864
- fieldNames: @config.detailFields
890
+ fields: @config.detailFields
891
+ closeEvent: @config.detailCloseEvent
865
892
  initialData: ?row
866
893
  showActions: true
867
894
  type: detail-panel
@@ -128,6 +128,10 @@ orbital EventLogOrbital {
128
128
  }, {
129
129
  entity: @entity.entries
130
130
  fields: (title description date status)
131
+ titleField: @config.titleField
132
+ descriptionField: @config.descriptionField
133
+ dateField: @config.dateField
134
+ statusField: @config.statusField
131
135
  look: @config.timelineLook
132
136
  type: timeline
133
137
  }]
@@ -224,6 +228,10 @@ orbital EventLogOrbital {
224
228
  }, {
225
229
  entity: @entity.entries
226
230
  fields: (title description date status)
231
+ titleField: @config.titleField
232
+ descriptionField: @config.descriptionField
233
+ dateField: @config.dateField
234
+ statusField: @config.statusField
227
235
  look: @config.timelineLook
228
236
  type: timeline
229
237
  }]
@@ -339,6 +347,10 @@ orbital EventLogOrbital {
339
347
  }, {
340
348
  entity: @entity.entries
341
349
  fields: (title description date status)
350
+ titleField: @config.titleField
351
+ descriptionField: @config.descriptionField
352
+ dateField: @config.dateField
353
+ statusField: @config.statusField
342
354
  look: @config.timelineLook
343
355
  type: timeline
344
356
  }]
@@ -451,6 +463,10 @@ orbital EventLogOrbital {
451
463
  }, {
452
464
  entity: @entity.entries
453
465
  fields: (title description date status)
466
+ titleField: @config.titleField
467
+ descriptionField: @config.descriptionField
468
+ dateField: @config.dateField
469
+ statusField: @config.statusField
454
470
  look: @config.timelineLook
455
471
  type: timeline
456
472
  }]
@@ -630,6 +646,22 @@ orbital EventLogOrbital {
630
646
  @label "Card look"
631
647
  @description "Layer 2 visual treatment for cards rendered by this atom."
632
648
  @tier "presentation"
649
+ titleField : string = "title"
650
+ @label "Title field"
651
+ @description "Entity field holding each event's title."
652
+ @tier "presentation"
653
+ descriptionField : string = "description"
654
+ @label "Description field"
655
+ @description "Entity field holding each event's description."
656
+ @tier "presentation"
657
+ dateField : string = "date"
658
+ @label "Date field"
659
+ @description "Entity field holding each event's date."
660
+ @tier "presentation"
661
+ statusField : string = "status"
662
+ @label "Status field"
663
+ @description "Entity field holding each event's status (complete | active | pending | error)."
664
+ @tier "presentation"
633
665
  timelineLook : "vertical-compact" | "vertical-spacious" | "horizontal" | "swimlane" = vertical-spacious
634
666
  @label "Timeline look"
635
667
  @description "Layer 2 visual treatment for the timeline."
@@ -63,6 +63,7 @@ orbital StoredFileOrbital {
63
63
  entity: ?data
64
64
  fields: @config.fields
65
65
  gap: sm
66
+ itemClickEvent: @config.itemClickEvent
66
67
  itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
67
68
  look: @config.tableLook
68
69
  reorderEvent: REORDER
@@ -385,7 +386,7 @@ orbital StoredFileOrbital {
385
386
  fields : [FieldSpec] = [{
386
387
  label: Name
387
388
  name: name
388
- variant: caption
389
+ variant: h4
389
390
  }, {
390
391
  label: Folder
391
392
  name: folder
@@ -399,6 +400,7 @@ orbital StoredFileOrbital {
399
400
  name: sizeBytes
400
401
  variant: caption
401
402
  }, {
403
+ format: date
402
404
  label: Uploaded
403
405
  name: uploadedAt
404
406
  variant: caption
@@ -406,6 +408,11 @@ orbital StoredFileOrbital {
406
408
  @label "Columns to show"
407
409
  @description "Each column maps to one field on the linked entity"
408
410
  @tier "presentation"
411
+ itemClickEvent : event = OPEN_FILE
412
+ @label "Which event does clicking a row fire?"
413
+ @description "Row-click channel; empty = rows are not clickable."
414
+ @synonyms "row click event, item click, open event"
415
+ @tier "presentation"
409
416
  itemActions : [ItemAction] = [{
410
417
  event: OPEN_FILE
411
418
  icon: arrow-right
@@ -2,6 +2,7 @@ app std-gantt-schedule "1.0.0"
2
2
  "std-gantt-schedule — GENERIC view-only Gantt/timeline atom: fetches a task collection on INIT and renders it as bars on a day-scale axis via the gantt pattern, with group headers, dependency arrows, and a today marker. Fully rebindable: a host overrides the linked entity and points the field-mapping configs (labelField/startField/endField/durationField/statusField/groupField) at its own columns; clicking a bar emits the config-named onBarClick event with the row id. No drag-edit, no zoom — schedule viewing only."
3
3
  type GanttLinkSpec = { from : string!, to : string! }
4
4
  orbital GanttScheduleOrbital {
5
+ type BarColor = "default" | "primary" | "secondary" | "success" | "warning" | "danger" | "error" | "info" | "neutral" | "destructive"
5
6
  type TaskLoaded = Event { data : [Task] } "Fired when Task finishes loading; payload.data holds the tasks"
6
7
 
7
8
  type TaskLoadFailed = Event { error : string, code : string } "Fired when Task fails to load"
@@ -61,6 +62,7 @@ orbital GanttScheduleOrbital {
61
62
  showToday: @config.showToday
62
63
  startField: @config.startField
63
64
  statusField: @config.statusField
65
+ statusColorMap: @config.statusColorMap
64
66
  tasks: ?data
65
67
  titleField: @config.labelField
66
68
  type: gantt
@@ -167,9 +169,14 @@ orbital GanttScheduleOrbital {
167
169
  @tier "presentation"
168
170
  statusField : string = "status"
169
171
  @label "Status field"
170
- @description "Row column holding the status value that drives bar colour."
172
+ @description "Row column holding each bar's status value."
171
173
  @synonyms "status column, state field, stage field"
172
174
  @tier "presentation"
175
+ statusColorMap : Map string BarColor = {}
176
+ @label "Bar colour per status"
177
+ @description "Bar colour for each exact status value, e.g. {blocked: danger, complete: success}. Unmapped statuses are primary bars."
178
+ @synonyms "status colours, bar colours, colour map"
179
+ @tier "presentation"
173
180
  groupField : string = ""
174
181
  @label "Group field"
175
182
  @description "Row column rows are grouped under header rows by (e.g. team, project). Empty (default) = flat list, no group headers."
@@ -68,7 +68,7 @@ orbital UploadedImageOrbital {
68
68
  maxFiles: @config.maxImages
69
69
  maxSize: @config.maxBytesPerImage
70
70
  type: upload-drop-zone
71
- }, { entity: ?data, type: media-gallery }]
71
+ }, { captionField: name, entity: ?data, srcField: url, type: media-gallery }]
72
72
  direction: vertical
73
73
  gap: md
74
74
  type: stack
@@ -199,7 +199,7 @@ orbital UploadedImageOrbital {
199
199
  maxFiles: @config.maxImages
200
200
  maxSize: @config.maxBytesPerImage
201
201
  type: upload-drop-zone
202
- }, { entity: ?data, type: media-gallery }]
202
+ }, { captionField: name, entity: ?data, srcField: url, type: media-gallery }]
203
203
  direction: vertical
204
204
  gap: md
205
205
  type: stack
@@ -117,6 +117,7 @@ orbital ListItemOrbital {
117
117
  name: status
118
118
  variant: badge
119
119
  }]
120
+ itemClickEvent: @config.itemClickEvent
120
121
  itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
121
122
  pageSize: @config.displayPageSize
122
123
  type: data-grid
@@ -250,6 +251,7 @@ orbital ListItemOrbital {
250
251
  name: status
251
252
  variant: badge
252
253
  }]
254
+ itemClickEvent: @config.itemClickEvent
253
255
  itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
254
256
  pageSize: @config.displayPageSize
255
257
  type: data-grid
@@ -369,6 +371,11 @@ orbital ListItemOrbital {
369
371
  @description "Rows visible per page before the data-grid's own pagination control appears — 20 matches the CRUD-list density sweet spot (Miller's law, 10-25 rows)."
370
372
  @synonyms "visible rows, items per page, display limit, show per page"
371
373
  @tier "presentation"
374
+ itemClickEvent : event = EDIT
375
+ @label "Which event does clicking a row fire?"
376
+ @description "Row-click channel; empty = rows are not clickable."
377
+ @synonyms "row click event, item click, open event"
378
+ @tier "presentation"
372
379
  itemActions : [ItemAction] = [{
373
380
  event: EDIT
374
381
  label: Edit
@@ -259,6 +259,10 @@ orbital MultiPartyFlowOrbital {
259
259
  }, {
260
260
  entity: @entity.audit
261
261
  fields: (title description timestamp status)
262
+ titleField: "title"
263
+ descriptionField: "description"
264
+ dateField: "timestamp"
265
+ statusField: "status"
262
266
  look: @config.timelineLook
263
267
  type: timeline
264
268
  }, { type: divider }, {
@@ -508,6 +512,10 @@ orbital MultiPartyFlowOrbital {
508
512
  }, {
509
513
  entity: @entity.audit
510
514
  fields: (title description timestamp status)
515
+ titleField: "title"
516
+ descriptionField: "description"
517
+ dateField: "timestamp"
518
+ statusField: "status"
511
519
  look: @config.timelineLook
512
520
  type: timeline
513
521
  }, { type: divider }, {
@@ -671,6 +679,10 @@ orbital MultiPartyFlowOrbital {
671
679
  }, {
672
680
  entity: @entity.audit
673
681
  fields: (title description timestamp status)
682
+ titleField: "title"
683
+ descriptionField: "description"
684
+ dateField: "timestamp"
685
+ statusField: "status"
674
686
  look: @config.timelineLook
675
687
  type: timeline
676
688
  }]
@@ -827,6 +839,10 @@ orbital MultiPartyFlowOrbital {
827
839
  }, {
828
840
  entity: @entity.audit
829
841
  fields: (title description timestamp status)
842
+ titleField: "title"
843
+ descriptionField: "description"
844
+ dateField: "timestamp"
845
+ statusField: "status"
830
846
  look: @config.timelineLook
831
847
  type: timeline
832
848
  }, {
@@ -905,6 +921,10 @@ orbital MultiPartyFlowOrbital {
905
921
  }, {
906
922
  entity: @entity.audit
907
923
  fields: (title description timestamp status)
924
+ titleField: "title"
925
+ descriptionField: "description"
926
+ dateField: "timestamp"
927
+ statusField: "status"
908
928
  look: @config.timelineLook
909
929
  type: timeline
910
930
  }, {
@@ -989,6 +1009,10 @@ orbital MultiPartyFlowOrbital {
989
1009
  }, {
990
1010
  entity: @entity.audit
991
1011
  fields: (title description timestamp status)
1012
+ titleField: "title"
1013
+ descriptionField: "description"
1014
+ dateField: "timestamp"
1015
+ statusField: "status"
992
1016
  look: @config.timelineLook
993
1017
  type: timeline
994
1018
  }, {
@@ -3,7 +3,8 @@ app std-record-detail "1.0.0"
3
3
  ;; @capabilities "record detail, single record view, entity detail panel, drill-down record, show one record, record profile, detail page, view details, document editor, wiki page, note taking, article body, rich text editing, write and edit content"
4
4
  orbital RecordItemOrbital {
5
5
  type RecordAction = { label : string!, event : event!, icon : string, variant : primary | secondary | ghost | danger, roles : [string], when : SExpr }
6
- type RecordFieldSpec = { key : string!, header : string, format : date | currency | number | boolean | percent }
6
+ type BadgeColor = "default" | "primary" | "secondary" | "success" | "warning" | "danger" | "error" | "info" | "neutral" | "destructive"
7
+ type RecordFieldSpec = { key : string!, header : string, format : date | currency | number | boolean | percent, variant : h3 | h4 | body | caption | badge | small | progress, colorMap : Map string BadgeColor, labels : Map string string }
7
8
  type MetaFieldSpec = { key : string!, label : string, kind : text | boolean | select | readonly, options : [string], icon : string, format : date | currency | number | boolean | percent }
8
9
  type RecordSection = { title : string!, fields : [string] }
9
10
 
@@ -448,12 +449,15 @@ orbital RecordItemOrbital {
448
449
  fields : [RecordFieldSpec] = [{
449
450
  header: Name
450
451
  key: name
452
+ variant: h4
451
453
  }, {
452
454
  header: Description
453
455
  key: description
456
+ variant: body
454
457
  }, {
455
458
  header: Status
456
459
  key: status
460
+ variant: badge
457
461
  }, {
458
462
  format: date
459
463
  header: Created
@@ -463,6 +467,11 @@ orbital RecordItemOrbital {
463
467
  @description "Each entry maps one entity field to a labelled row in the panel. Unlike a list row, a detail panel SHOULD label every field — the value stands alone here with no column header or repeated row position to name it."
464
468
  @synonyms "detail fields, record fields, panel fields, shown fields"
465
469
  @tier "presentation"
470
+ closeEvent : event = ""
471
+ @label "Which action closes the record?"
472
+ @description "The `actions` entry whose event matches renders as the panel's close (×) button. Empty = no close button (a routed detail page navigates back instead)."
473
+ @synonyms "close event, dismiss event, close button"
474
+ @tier "presentation"
466
475
  sections : [RecordSection] = []
467
476
  @label "How should the fields be grouped?"
468
477
  @description "Optional titled groups over `fields`, e.g. [{title: Contact, fields: [email, phone]}]. Group into sections of 3-5 once a record carries more than about seven fields — a flat list past that is the cognitive-load problem Almadar_UX.md §1.4 (Miller) describes. Empty = one ungrouped list, the default."
@@ -567,6 +576,7 @@ orbital RecordItemOrbital {
567
576
  actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
568
577
  entity: @entity.loadedRow
569
578
  fields: @config.fields
579
+ closeEvent: @config.closeEvent
570
580
  initialData: @entity.loadedRow
571
581
  maxInlineActions: @config.maxInlineActions
572
582
  sections: @config.sections
@@ -587,6 +597,7 @@ orbital RecordItemOrbital {
587
597
  actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
588
598
  entity: @entity.loadedRow
589
599
  fields: @config.fields
600
+ closeEvent: @config.closeEvent
590
601
  initialData: @entity.loadedRow
591
602
  maxInlineActions: @config.maxInlineActions
592
603
  sections: @config.sections
@@ -608,6 +619,7 @@ orbital RecordItemOrbital {
608
619
  actions: (array/filter @config.actions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
609
620
  entity: @entity.loadedRow
610
621
  fields: @config.fields
622
+ closeEvent: @config.closeEvent
611
623
  initialData: @entity.loadedRow
612
624
  maxInlineActions: @config.maxInlineActions
613
625
  sections: @config.sections
@@ -140,6 +140,10 @@ orbital RecurrenceOrbital {
140
140
  }, {
141
141
  entity: @entity.occurrences
142
142
  fields: (title description date status)
143
+ titleField: "title"
144
+ descriptionField: "description"
145
+ dateField: "date"
146
+ statusField: "status"
143
147
  itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
144
148
  look: @config.timelineLook
145
149
  type: timeline
@@ -77,6 +77,7 @@ orbital SavedSearchOrbital {
77
77
  variant: badge
78
78
  }]
79
79
  gap: sm
80
+ itemClickEvent: @config.itemClickEvent
80
81
  itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
81
82
  look: @config.tableLook
82
83
  type: data-grid
@@ -253,6 +254,7 @@ orbital SavedSearchOrbital {
253
254
  @tier "presentation"
254
255
  EDIT {
255
256
  id : string!
257
+ row : SavedSearch
256
258
  }
257
259
  @description "Indicates a saved search is being modified."
258
260
  @synonyms "modify, update, change"
@@ -405,6 +407,10 @@ orbital SavedSearchOrbital {
405
407
  @label "Default saved-search name"
406
408
  @description "Name given to a saved search when the current search has no query text (filters only). Renamable afterwards."
407
409
  @tier "presentation"
410
+ itemClickEvent : event = EDIT
411
+ @label "Row click"
412
+ @description "Event emitted when a row is clicked; opens the saved search for editing. Empty disables the row click."
413
+ @tier "presentation"
408
414
  itemActions : [ItemAction] = [{
409
415
  event: TOGGLE_ALERT
410
416
  icon: bell
@@ -87,6 +87,7 @@ orbital SelectableItemOrbital {
87
87
  className: "transition-shadow hover:shadow-md cursor-pointer"
88
88
  entity: ?data
89
89
  fields: []
90
+ itemClickEvent: @config.itemClickEvent
90
91
  itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
91
92
  look: @config.tableLook
92
93
  pageSize: @config.displayPageSize
@@ -217,6 +218,7 @@ orbital SelectableItemOrbital {
217
218
  className: "transition-shadow hover:shadow-md cursor-pointer"
218
219
  entity: ?data
219
220
  fields: []
221
+ itemClickEvent: @config.itemClickEvent
220
222
  itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
221
223
  look: @config.tableLook
222
224
  pageSize: @config.displayPageSize
@@ -380,6 +382,7 @@ orbital SelectableItemOrbital {
380
382
  listens {
381
383
  SELECT {
382
384
  id : string!
385
+ row : SelectableItem
383
386
  }
384
387
  @description "Indicates an item has been chosen."
385
388
  @synonyms "chosen, picked, highlighted"
@@ -460,6 +463,10 @@ orbital SelectableItemOrbital {
460
463
  @description "Rows visible per page before the data-grid's own pagination control appears — 20 matches the pick-list density sweet spot (Miller's law, 10-25 rows)."
461
464
  @synonyms "visible rows, items per page, display limit, show per page"
462
465
  @tier "presentation"
466
+ itemClickEvent : event = SELECT
467
+ @label "Row click"
468
+ @description "Event emitted when a row is clicked; clicking a row selects it. Empty disables the row click."
469
+ @tier "presentation"
463
470
  itemActions : [ItemAction] = [{
464
471
  event: SELECT
465
472
  icon: check
@@ -73,13 +73,15 @@ orbital RevisionOrbital {
73
73
  }, {
74
74
  label: Summary
75
75
  name: summary
76
- variant: caption
76
+ variant: h4
77
77
  }, {
78
78
  label: Saved
79
+ format: date
79
80
  name: createdAt
80
81
  variant: caption
81
82
  }]
82
83
  gap: sm
84
+ itemClickEvent: @config.itemClickEvent
83
85
  itemActions: (array/filter @config.itemActions (fn action (or (= (array/len (object/get @action roles [])) 0) (array/includes (object/get @action roles []) @config.viewerRole))))
84
86
  look: @config.tableLook
85
87
  type: data-grid
@@ -591,6 +593,10 @@ orbital RevisionOrbital {
591
593
  @label "Scope field"
592
594
  @description "Revision entity field holding the parent document's id. When set, a page-mounted {id} route param scopes INIT's fetch, and a SHOW_HISTORY { key } event rescopes the feed, to rows whose scopeField equals the id/key; rollback and retry refetches stay scoped too. Empty (default) or no id = unfiltered global feed, unchanged from prior behavior."
593
595
  @tier "domain"
596
+ itemClickEvent : event = OPEN_REVISION
597
+ @label "Row click"
598
+ @description "Event emitted when a row is clicked; opens the revision. Empty disables the row click."
599
+ @tier "presentation"
594
600
  itemActions : [ItemAction] = [{
595
601
  event: OPEN_REVISION
596
602
  icon: arrow-right