@almadar/std 16.209.0 → 16.211.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 (113) hide show
  1. package/behaviors/lolo/infra/atoms/std-approval-gate.lolo +2 -2
  2. package/behaviors/lolo/infra/atoms/std-calendar-sync.lolo +5 -5
  3. package/behaviors/lolo/infra/atoms/std-cascade-on-delete.lolo +7 -1
  4. package/behaviors/lolo/infra/atoms/std-circuit-breaker.lolo +3 -3
  5. package/behaviors/lolo/ui/core/atoms/std-app-layout.lolo +1 -0
  6. package/behaviors/lolo/ui/core/atoms/std-browse.lolo +40 -41
  7. package/behaviors/lolo/ui/core/atoms/std-calendar.lolo +25 -19
  8. package/behaviors/lolo/ui/core/atoms/std-confirmation.lolo +2 -0
  9. package/behaviors/lolo/ui/core/atoms/std-esign-request.lolo +2 -2
  10. package/behaviors/lolo/ui/core/atoms/std-graphs.lolo +1 -1
  11. package/behaviors/lolo/ui/core/atoms/std-modal.lolo +3 -1
  12. package/behaviors/lolo/ui/core/atoms/std-stats.lolo +1 -1
  13. package/behaviors/lolo/ui/core/atoms/std-step-flow.lolo +4 -3
  14. package/behaviors/lolo/ui/core/atoms/std-tag-taxonomy.lolo +1 -4
  15. package/behaviors/lolo/ui/core/atoms/std-thread.lolo +33 -30
  16. package/behaviors/lolo/ui/core/atoms/std-version-history.lolo +1 -1
  17. package/behaviors/lolo/ui/core/atoms/ui-radio.lolo +1 -1
  18. package/behaviors/lolo/ui/core/atoms/ui-range-slider.lolo +1 -1
  19. package/behaviors/lolo/ui/core/atoms/ui-switch.lolo +1 -1
  20. package/behaviors/lolo/ui/core/atoms/ui-text-highlight.lolo +1 -1
  21. package/behaviors/lolo/ui/core/atoms/ui-time-slot-cell.lolo +1 -1
  22. package/behaviors/lolo/ui/core/molecules/ui-code-block.lolo +2 -2
  23. package/behaviors/lolo/ui/core/molecules/ui-command-palette.lolo +1 -1
  24. package/behaviors/lolo/ui/core/molecules/ui-date-range-picker.lolo +2 -2
  25. package/behaviors/lolo/ui/core/molecules/ui-document-panel.lolo +2 -2
  26. package/behaviors/lolo/ui/core/molecules/ui-filter-group.lolo +1 -1
  27. package/behaviors/lolo/ui/core/molecules/ui-number-stepper.lolo +1 -1
  28. package/behaviors/lolo/ui/core/molecules/ui-pagination.lolo +1 -1
  29. package/behaviors/lolo/ui/core/molecules/ui-popover.lolo +1 -1
  30. package/behaviors/lolo/ui/core/molecules/ui-relation-select.lolo +1 -1
  31. package/behaviors/lolo/ui/core/molecules/ui-rich-text-editor.lolo +1 -1
  32. package/behaviors/lolo/ui/core/molecules/ui-search-input.lolo +1 -1
  33. package/behaviors/lolo/ui/core/molecules/ui-sidebar.lolo +1 -1
  34. package/behaviors/lolo/ui/core/molecules/ui-star-rating.lolo +1 -1
  35. package/behaviors/lolo/ui/core/molecules/ui-wizard-navigation.lolo +2 -2
  36. package/behaviors/lolo/ui/core/organisms/ui-split-pane.lolo +1 -1
  37. package/behaviors/lolo/ui/game/atoms/ui-draw-skinned-mesh.lolo +126 -0
  38. package/behaviors/lolo/ui/game/atoms/ui-trait-slot.lolo +1 -1
  39. package/behaviors/lolo/ui/game/organisms/std-arcade-board-3d.lolo +10 -10
  40. package/behaviors/lolo/ui/game/organisms/std-crew-board-2d.lolo +10 -10
  41. package/behaviors/lolo/ui/game/organisms/std-dungeon-board-2d.lolo +36 -36
  42. package/behaviors/lolo/ui/game/organisms/std-market-board-3d.lolo +36 -36
  43. package/behaviors/lolo/ui/game/organisms/std-objective-board-3d.lolo +34 -34
  44. package/behaviors/lolo/ui/game/organisms/std-survival-board-3d.lolo +10 -10
  45. package/behaviors/lolo/ui/game/organisms/std-tactics-board-2d.lolo +12 -12
  46. package/behaviors/lolo/ui/game/organisms/std-tactics-board-3d.lolo +12 -12
  47. package/behaviors/lolo/ui/game/organisms/std-worldmap-board-2d.lolo +20 -20
  48. package/behaviors/registry/infra/atoms/std-approval-gate.orb +20 -9
  49. package/behaviors/registry/infra/atoms/std-calendar-sync.orb +5 -0
  50. package/behaviors/registry/infra/atoms/std-cascade-on-delete.orb +28 -0
  51. package/behaviors/registry/infra/atoms/std-circuit-breaker.orb +3 -0
  52. package/behaviors/registry/infra/atoms/std-notification-center.orb +56 -24
  53. package/behaviors/registry/infra/atoms/std-notify-on-event.orb +12 -6
  54. package/behaviors/registry/ui/core/atoms/std-app-layout.orb +20 -0
  55. package/behaviors/registry/ui/core/atoms/std-browse.orb +51 -137
  56. package/behaviors/registry/ui/core/atoms/std-calendar.orb +101 -24
  57. package/behaviors/registry/ui/core/atoms/std-confirmation.orb +44 -18
  58. package/behaviors/registry/ui/core/atoms/std-esign-flow.orb +44 -18
  59. package/behaviors/registry/ui/core/atoms/std-esign-request.orb +19 -8
  60. package/behaviors/registry/ui/core/atoms/std-form-advanced.orb +20 -9
  61. package/behaviors/registry/ui/core/atoms/std-graphs.orb +1 -0
  62. package/behaviors/registry/ui/core/atoms/std-modal.orb +52 -24
  63. package/behaviors/registry/ui/core/atoms/std-stats.orb +1 -0
  64. package/behaviors/registry/ui/core/atoms/std-step-flow.orb +0 -3
  65. package/behaviors/registry/ui/core/atoms/std-tag-taxonomy.orb +2 -9
  66. package/behaviors/registry/ui/core/atoms/std-thread.orb +134 -40
  67. package/behaviors/registry/ui/core/atoms/std-version-history.orb +1 -0
  68. package/behaviors/registry/ui/core/atoms/ui-radio.orb +1 -0
  69. package/behaviors/registry/ui/core/atoms/ui-range-slider.orb +1 -0
  70. package/behaviors/registry/ui/core/atoms/ui-switch.orb +1 -0
  71. package/behaviors/registry/ui/core/atoms/ui-text-highlight.orb +1 -0
  72. package/behaviors/registry/ui/core/atoms/ui-time-slot-cell.orb +1 -0
  73. package/behaviors/registry/ui/core/molecules/ui-code-block.orb +2 -0
  74. package/behaviors/registry/ui/core/molecules/ui-command-palette.orb +1 -0
  75. package/behaviors/registry/ui/core/molecules/ui-date-range-picker.orb +2 -0
  76. package/behaviors/registry/ui/core/molecules/ui-document-panel.orb +2 -0
  77. package/behaviors/registry/ui/core/molecules/ui-filter-group.orb +1 -0
  78. package/behaviors/registry/ui/core/molecules/ui-number-stepper.orb +1 -0
  79. package/behaviors/registry/ui/core/molecules/ui-pagination.orb +1 -0
  80. package/behaviors/registry/ui/core/molecules/ui-popover.orb +1 -0
  81. package/behaviors/registry/ui/core/molecules/ui-relation-select.orb +1 -0
  82. package/behaviors/registry/ui/core/molecules/ui-rich-text-editor.orb +1 -0
  83. package/behaviors/registry/ui/core/molecules/ui-search-input.orb +1 -0
  84. package/behaviors/registry/ui/core/molecules/ui-sidebar.orb +1 -0
  85. package/behaviors/registry/ui/core/molecules/ui-star-rating.orb +1 -0
  86. package/behaviors/registry/ui/core/molecules/ui-wizard-navigation.orb +2 -0
  87. package/behaviors/registry/ui/core/organisms/ui-split-pane.orb +1 -0
  88. package/behaviors/registry/ui/game/atoms/ui-draw-skinned-mesh.orb +687 -0
  89. package/behaviors/registry/ui/game/atoms/ui-trait-slot.orb +1 -0
  90. package/behaviors/registry/ui/game/organisms/std-arcade-board-3d.orb +10 -30
  91. package/behaviors/registry/ui/game/organisms/std-crew-board-2d.orb +10 -30
  92. package/behaviors/registry/ui/game/organisms/std-dungeon-board-2d.orb +36 -108
  93. package/behaviors/registry/ui/game/organisms/std-market-board-3d.orb +36 -108
  94. package/behaviors/registry/ui/game/organisms/std-objective-board-3d.orb +34 -102
  95. package/behaviors/registry/ui/game/organisms/std-survival-board-3d.orb +10 -30
  96. package/behaviors/registry/ui/game/organisms/std-tactics-board-2d.orb +12 -36
  97. package/behaviors/registry/ui/game/organisms/std-tactics-board-3d.orb +12 -36
  98. package/behaviors/registry/ui/game/organisms/std-worldmap-board-2d.orb +20 -60
  99. package/dist/behaviors/exports-reader.js +2147 -2212
  100. package/dist/behaviors/functions/index.d.ts +111 -34
  101. package/dist/behaviors/functions/index.js +2145 -2211
  102. package/dist/behaviors/index.d.ts +1 -1
  103. package/dist/behaviors/index.js +2148 -2213
  104. package/dist/behaviors/query.js +2147 -2212
  105. package/dist/behaviors-embeddings.hash.json +3 -3
  106. package/dist/behaviors-embeddings.json +11 -7
  107. package/dist/behaviors-registry.json +997 -759
  108. package/dist/index.d.ts +1 -1
  109. package/dist/index.js +2148 -2213
  110. package/dist/knob-embeddings.hash.json +3 -3
  111. package/dist/knob-embeddings.json +1 -1
  112. package/dist/registry/factory-signatures.json +1 -1
  113. package/package.json +3 -3
@@ -136,7 +136,7 @@ orbital ApprovalGateOrbital {
136
136
  (persist update ApprovalRequest @entity {
137
137
  emit: { failure: ApprovalRequestReviewFailed, success: ApprovalRequestReviewed }
138
138
  })
139
- (notify "Approval could not be applied — the request was reopened." error)
139
+ (notify error "Approval could not be applied — the request was reopened.")
140
140
  OPEN -> loading when @config.enabled
141
141
  (fetch ApprovalRequest {
142
142
  filter: ["=", (object/get @entity status), "pending"]
@@ -282,7 +282,7 @@ orbital ApprovalGateOrbital {
282
282
  (persist update ApprovalRequest @entity {
283
283
  emit: { failure: ApprovalRequestReviewFailed, success: ApprovalRequestReviewed }
284
284
  })
285
- (notify "Approval could not be applied — the request was reopened." error)
285
+ (notify error "Approval could not be applied — the request was reopened.")
286
286
  CLOSE -> idle
287
287
  (render-ui @config.reviewSlot null)
288
288
  }
@@ -7,11 +7,11 @@ orbital CalendarSyncOrbital {
7
7
 
8
8
  entity CalendarSyncRun [persistent: calendarSyncState] {
9
9
  id : string!
10
- syncToken : string @description "Scratch: Google incremental-sync token from the last listEvents; in-memory per instance — a restart falls back to a full list." @synonyms "sync cursor, next token" = ""
11
- lastSyncedAt : number @description "When the last full push+pull cycle completed; 0 = never." @synonyms "last sync time" = 0
12
- headId : string @description "Scratch: id of the target row the push loop is currently exporting." @synonyms "cursor, current row" = ""
13
- pending : [RemoteEvent] @description "Scratch: remote events remaining in the current pull-upsert loop." @synonyms "pull queue, remaining events" = []
14
- lastError : string @description "Last sync failure detail; blank = none." @synonyms "sync error, failure" = ""
10
+ syncToken : string @intrinsic @description "Scratch: Google incremental-sync token from the last listEvents; in-memory per instance — a restart falls back to a full list." @synonyms "sync cursor, next token" = ""
11
+ lastSyncedAt : number @intrinsic @description "When the last full push+pull cycle completed; 0 = never." @synonyms "last sync time" = 0
12
+ headId : string @intrinsic @description "Scratch: id of the target row the push loop is currently exporting." @synonyms "cursor, current row" = ""
13
+ pending : [RemoteEvent] @intrinsic @description "Scratch: remote events remaining in the current pull-upsert loop." @synonyms "pull queue, remaining events" = []
14
+ lastError : string @intrinsic @description "Last sync failure detail; blank = none." @synonyms "sync error, failure" = ""
15
15
  }
16
16
 
17
17
  entity CalendarEvent [persistent: calendarEvents] {
@@ -18,7 +18,7 @@ orbital CascadeOnDeleteOrbital {
18
18
  parentId : string @description "Identifier of the deleted parent the cascade is clearing dependents for." @synonyms "parent, source, origin" = ""
19
19
  parentEntity : string @description "Identifies the parent entity of the cascade." @synonyms "related entity, source entity, parent" = ""
20
20
  rowCount : number @description "The number of rows deleted by the cascade." @synonyms "count, size, quantity" = 0
21
- headId : string @description "Scratch: id of the dependent row the loop is currently deleting." @synonyms "current id, cursor" = ""
21
+ headId : string @intrinsic @description "Scratch: id of the dependent row the loop is currently deleting." @synonyms "current id, cursor" = ""
22
22
  }
23
23
 
24
24
  trait CascadeOnDeleteGate -> CascadeLog [lifecycle, instance, cascade-delete] {
@@ -43,7 +43,13 @@ orbital CascadeOnDeleteOrbital {
43
43
  })
44
44
  DepsLoaded -> idle when ["=", (array/len (array/filter ?data (fn row ["=", (object/get @row @config.foreignKeyField), @entity.parentId]))), 0]
45
45
  (emit CascadeCompleted { parentId: @entity.parentId })
46
+ (persist create CascadeLog {
47
+ parentId: @entity.parentId
48
+ parentEntity: @entity.parentEntity
49
+ rowCount: @entity.rowCount
50
+ })
46
51
  CascadeStepped -> scanning
52
+ (set @entity.rowCount (+ @entity.rowCount 1))
47
53
  (fetch @config.dependentEntity {
48
54
  emit: { failure: CascadeFailed, success: DepsLoaded }
49
55
  })
@@ -21,9 +21,9 @@ orbital ServiceNodeOrbital {
21
21
  description : string @description "A textual explanation of the service node's function." @synonyms "explanation, details, notes, information"
22
22
  status : "active" | "inactive" | "pending" @description "Current operational state of the component." @synonyms "state, condition, operationalStatus" = active
23
23
  createdAt : string
24
- failureCount : number @description "The number of times the circuit breaker has failed." @synonyms "error count, failures, error occurrences" = 0
25
- successCount : number @description "Number of successful operations." @synonyms "successes, hits, completions" = 0
26
- threshold : number @description "Maximum value before triggering an action." @synonyms "limit, cap, boundary" = 5
24
+ failureCount : number @intrinsic @description "The number of times the circuit breaker has failed." @synonyms "error count, failures, error occurrences" = 0
25
+ successCount : number @intrinsic @description "Number of successful operations." @synonyms "successes, hits, completions" = 0
26
+ threshold : number @intrinsic @description "Maximum value before triggering an action." @synonyms "limit, cap, boundary" = 5
27
27
  }
28
28
 
29
29
  trait ShieldIcon = Icon.traits.IconRender -> ServiceNode {
@@ -49,6 +49,7 @@ orbital AppLayoutOrbital {
49
49
  })
50
50
  AppLayoutStateLoaded -> composing
51
51
  AppLayoutStateLoadFailed -> composing
52
+ (notify error (str/concat "Couldn't load the layout — " ?error))
52
53
  SEARCH -> composing
53
54
  NOTIFY_CLICK -> composing
54
55
  }
@@ -25,44 +25,19 @@ orbital BrowseItemOrbital {
25
25
  }
26
26
 
27
27
  uses Typography from "std/behaviors/ui-typography"
28
- uses DataGrid from "std/behaviors/ui-data-grid"
29
- uses TableView from "std/behaviors/ui-table-view"
30
28
  uses DataList from "std/behaviors/ui-data-list"
31
29
 
32
- trait DataGrid1 = DataGrid.traits.DataGridRender -> BrowseItem {
33
- config {
34
- cols: @config.cols
35
- fields: @config.fields
36
- gap: @config.gap
37
- imageField: @config.imageField
38
- itemActions: @config.itemActions
39
- maxInlineActions: @config.maxInlineActions
40
- pageSize: @config.displayPageSize
41
- selfFetch: false
42
- }
43
-
44
- listens {
45
- BrowseItemBrowse.BrowseItemLoaded -> DataGridLoaded
46
- }
47
- }
48
-
49
- trait DenseTableView = TableView.traits.TableViewRender -> BrowseItem {
50
- config {
51
- columns: @config.columns
52
- emptyMessage: "No records"
53
- itemActions: @config.itemActions
54
- itemClickEvent: @config.itemClickEvent
55
- look: dense
56
- maxInlineActions: @config.maxInlineActions
57
- pageSize: @config.displayPageSize
58
- selectable: @config.selectable
59
- selfFetch: false
60
- }
61
-
62
- listens {
63
- BrowseItemBrowse.BrowseItemLoaded -> TableViewLoaded
64
- }
65
- }
30
+ ;; table-default and dense looks used to compose separately-listening
31
+ ;; sibling traits (DataGrid1/DenseTableView) here, same shape as
32
+ ;; MasterListView below. Both re-render fully on every BrowseItemLoaded
33
+ ;; (unlike master-detail's VIEW/CLOSE, which doesn't carry `.data`), so
34
+ ;; unlike MasterListView they had no reason to be persistent components —
35
+ ;; inlined into denseBodyContent/bodyContent directly 2026-09-08, matching
36
+ ;; feed/gallery/triage's existing inline shape. A separately-listening
37
+ ;; sibling fires unconditionally regardless of browseLook (a listens guard
38
+ ;; can't gate on @config — both the Rust interpreter and the TS codegen
39
+ ;; path restrict a listens guard's context to @payload only), so all three
40
+ ;; used to race for slot main on every load.
66
41
 
67
42
  trait MasterListView = DataList.traits.DataListRender -> BrowseItem {
68
43
  config {
@@ -171,6 +146,10 @@ orbital BrowseItemOrbital {
171
146
  (if ["=", @config.browseLook, triage]
172
147
  (render-ui main @config.triageBodyContent)
173
148
  (render-ui main @config.bodyContent))))))
149
+ ;; A refetch keeps the populated body on screen; only the failure
150
+ ;; itself has to reach the user.
151
+ BrowseItemLoadFailed -> browsing
152
+ (notify error (str/concat "Couldn't refresh the list — " ?error))
174
153
  }
175
154
 
176
155
  state error {
@@ -461,14 +440,23 @@ orbital BrowseItemOrbital {
461
440
  children: []
462
441
  gap: none
463
442
  type: stack
464
- }), @trait.DataGrid1]
443
+ }), {
444
+ cols: @config.cols
445
+ entity: ?data
446
+ fields: @config.fields
447
+ gap: @config.gap
448
+ imageField: @config.imageField
449
+ itemActions: @config.itemActions
450
+ maxInlineActions: @config.maxInlineActions
451
+ pageSize: @config.displayPageSize
452
+ type: data-grid
453
+ }]
465
454
  direction: vertical
466
455
  gap: md
467
456
  type: stack
468
457
  }
469
458
  @label "Body content tree"
470
- @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."
471
- @tier "internal"
459
+ @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. Inlined directly (not via a composed sibling trait) 2026-09-08 — a separately-listening DataGrid1 sibling fired unconditionally on every BrowseItemLoaded regardless of browseLook, racing the correct body for slot main (a listens guard can't gate this: both the Rust interpreter and the TS codegen path restrict a listens guard's context to @payload only, so a browseLook config check there always evaluates undefined)."
472
460
  denseBodyContent : render-ui = {
473
461
  children: [(if @config.bodySearch {
474
462
  children: [{
@@ -503,7 +491,18 @@ orbital BrowseItemOrbital {
503
491
  gap: none
504
492
  type: stack
505
493
  }), {
506
- children: [@trait.DenseTableView]
494
+ children: [{
495
+ columns: @config.columns
496
+ emptyMessage: "No records"
497
+ entity: ?data
498
+ itemActions: @config.itemActions
499
+ itemClickEvent: @config.itemClickEvent
500
+ look: dense
501
+ maxInlineActions: @config.maxInlineActions
502
+ pageSize: @config.displayPageSize
503
+ selectable: @config.selectable
504
+ type: table-view
505
+ }]
507
506
  className: overflow-x-auto
508
507
  direction: vertical
509
508
  gap: none
@@ -515,7 +514,7 @@ orbital BrowseItemOrbital {
515
514
  type: stack
516
515
  }
517
516
  @label "Dense look body"
518
- @description "Render-ui SExpr rendered after rows load when browseLook = dense. Spreadsheet-style sticky-header data-table with a search bar; composes columns/itemActions/maxInlineActions/displayPageSize/searchPlaceholder. Folded from std-browse-dense (Phase 5.B)."
517
+ @description "Render-ui SExpr rendered after rows load when browseLook = dense. Spreadsheet-style sticky-header data-table with a search bar; composes columns/itemActions/maxInlineActions/displayPageSize/searchPlaceholder. Folded from std-browse-dense (Phase 5.B). Inlined directly (not via a composed sibling trait) 2026-09-08 — see the table-default body's note for why."
519
518
  @tier "internal"
520
519
  feedBodyContent : render-ui = {
521
520
  children: [(if @config.bodySearch {
@@ -2,6 +2,7 @@ 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 : event, navigatesTo : string, variant : primary | secondary | ghost | danger, icon : string }
4
4
  type FilterSpec = { field : string!, label : string, options : [string] }
5
+ type FieldSpec = { name : string!, label : string, variant : h3 | h4 | body | caption | badge | small | progress, icon : string, format : date | currency | number | boolean | percent }
5
6
  orbital CalendarEventOrbital {
6
7
  type CalendarEventLoaded = Event { data : [CalendarEvent] } "Fired when CalendarEvent finishes loading; payload.data holds the events"
7
8
 
@@ -226,6 +227,29 @@ orbital CalendarEventOrbital {
226
227
  @label "Description binding"
227
228
  @description "Per-row binding for the event description slot."
228
229
  @tier "presentation"
230
+ fields : [FieldSpec] = [{
231
+ icon: calendar
232
+ label: Event
233
+ name: name
234
+ variant: h4
235
+ }, {
236
+ label: Time
237
+ name: time
238
+ variant: badge
239
+ }, {
240
+ format: date
241
+ label: Date
242
+ name: date
243
+ variant: caption
244
+ }, {
245
+ label: Status
246
+ name: status
247
+ variant: badge
248
+ }]
249
+ @label "Upcoming-events columns"
250
+ @description "Row field descriptors for the 'Upcoming Events' data-list under calendarLook='month'. Rebound hosts must override this — it is a literal entity[field.name] lookup, unlike titleBinding/timeBinding/descriptionBinding (expression bindings), so it does not follow a rebind automatically."
251
+ @synonyms "upcoming events columns, month view fields, event list columns"
252
+ @tier "presentation"
229
253
  include : [string] = []
230
254
  @label "Which relation fields to hydrate?"
231
255
  @description "Entity relation field names to hydrate on fetch (e.g. a `category : Category` field named `category`), so chip bindings can use dot-paths like @item.category.name. Empty = no hydration, the default."
@@ -347,25 +371,7 @@ orbital CalendarEventOrbital {
347
371
  variant: h4
348
372
  }, {
349
373
  entity: ?data
350
- fields: [{
351
- icon: calendar
352
- label: Event
353
- name: name
354
- variant: h4
355
- }, {
356
- label: Time
357
- name: time
358
- variant: badge
359
- }, {
360
- format: date
361
- label: Date
362
- name: date
363
- variant: caption
364
- }, {
365
- label: Status
366
- name: status
367
- variant: badge
368
- }]
374
+ fields: @config.fields
369
375
  itemActions: @config.agendaItemActions
370
376
  look: @config.tableLook
371
377
  type: data-list
@@ -28,6 +28,8 @@ orbital ConfirmActionOrbital {
28
28
  (fetch ConfirmAction {
29
29
  emit: { failure: ConfirmActionLoadFailed, success: ConfirmActionLoaded }
30
30
  })
31
+ ConfirmActionLoadFailed -> idle
32
+ (notify error (str/concat "Couldn't load the item to confirm — " ?error))
31
33
  ;; Guard: REQUEST is rejected if no `row` payload was provided.
32
34
  ;; "Confirm an action against X" is meaningless without X — a
33
35
  ;; confirmation dialog with no entity to display is a precondition
@@ -99,10 +99,10 @@ orbital ESignRequestOrbital {
99
99
  state browsing {
100
100
  SEND_REQUEST -> browsing
101
101
  (set @entity.id ?id)
102
- (notify "Signature request sent" success)
102
+ (notify success "Signature request sent")
103
103
  REVOKE_REQUEST -> browsing
104
104
  (set @entity.id ?id)
105
- (notify "Signature request revoked" info)
105
+ (notify info "Signature request revoked")
106
106
  }
107
107
 
108
108
  state error {
@@ -8,7 +8,7 @@ orbital GraphItemOrbital {
8
8
 
9
9
  entity GraphItem [runtime] {
10
10
  id : string!
11
- chartData : [ChartPoint] @description "The data points used to render the chart." @synonyms "data, values, points" = []
11
+ chartData : [ChartPoint] @intrinsic @description "The data points used to render the chart." @synonyms "data, values, points" = []
12
12
  }
13
13
 
14
14
  trait GraphItemGraph -> @rebindable GraphItem [interaction, instance] {
@@ -36,6 +36,8 @@ orbital ModalRecordOrbital {
36
36
  (fetch ModalRecord {
37
37
  emit: { failure: ModalRecordLoadFailed, success: ModalRecordLoaded }
38
38
  })
39
+ ModalRecordLoadFailed -> closed
40
+ (notify error (str/concat "Couldn't load the record — " ?error))
39
41
  ;; stash only — a SEED never opens anything; OPEN reads it on demand
40
42
  SEED -> closed
41
43
  (set @entity.seedRow (object/merge ?row {}))
@@ -78,7 +80,7 @@ orbital ModalRecordOrbital {
78
80
  (set @entity.seedRow (object/merge ?row {}))
79
81
  CLOSE -> closed
80
82
  (render-ui @config.detailSlot null)
81
- (notify Cancelled info)
83
+ (notify info Cancelled)
82
84
  SAVE -> closed
83
85
  (render-ui @config.detailSlot null)
84
86
  }
@@ -15,7 +15,7 @@ orbital StatsItemOrbital {
15
15
 
16
16
  entity StatsItem [runtime] {
17
17
  id : string!
18
- cards : [StatCard] @description "A collection of statistical cards to display." @synonyms "statistics, items, displays" = []
18
+ cards : [StatCard] @intrinsic @description "A collection of statistical cards to display." @synonyms "statistics, items, displays" = []
19
19
  }
20
20
 
21
21
  trait StatsItemStats -> @rebindable StatsItem [interaction, instance] {
@@ -16,7 +16,8 @@ orbital StepFlowOrbital {
16
16
  entity StepFlowView [runtime] {
17
17
  id : string!
18
18
  wizardSteps : [WizardStep] @intrinsic = []
19
- currentStepIndex : number @intrinsic = 0
19
+ ;; Not @intrinsic: std-approval-chain's ApprovalRequest persists this as chain position.
20
+ currentStepIndex : number = 0
20
21
  totalSteps : number @intrinsic = 0
21
22
  currentStepLabel : string @intrinsic = ""
22
23
  currentStepDescription : string @intrinsic = ""
@@ -26,8 +27,8 @@ orbital StepFlowOrbital {
26
27
  primaryActionLabel : string @intrinsic = "Approve & Continue"
27
28
  primaryActionVariant : "primary" | "success" @intrinsic = primary
28
29
  primaryActionIcon : string @intrinsic = chevron-right
29
- finalStatus : "approved" | "rejected" | "escalated" | "" @intrinsic = ""
30
- rejectionReason : string @intrinsic = ""
30
+ finalStatus : "approved" | "rejected" | "escalated" | "" = ""
31
+ rejectionReason : string = ""
31
32
  errorMessage : string @intrinsic = ""
32
33
  }
33
34
 
@@ -537,10 +537,7 @@ orbital TagTaxonomyOrbital {
537
537
  @description "Signals a tag has been chosen for further exploration."
538
538
  @synonyms "chosen, picked, activated, highlighted"
539
539
  @tier "domain"
540
- NEW_TAG
541
- @description "Opens the create-tag form (rendered only when allowEdit is on); the creation lands at the level currently open."
542
- @synonyms "add tag, create category, new category"
543
- @tier "domain"
540
+ ;; NEW_TAG is self-consumed via listens, never an external emit.
544
541
  COMMIT_TAG {
545
542
  data : TagCommit
546
543
  }
@@ -1,5 +1,5 @@
1
1
  app std-thread "1.3.0"
2
- "std-thread — forum-style nested replies with collapse + flat-mode toggle. Owns ThreadPost (persistent). flat:true covers 1:1 linear inquiry threads; flat:false renders forum-style nested. INIT fetches, scoped by @config.threadRootId when set (blank = every root, the default). REPLY persists a child post under @payload.parentId, stamped with the real @user identity. A consumer that mounts this as page comments forwards its own document-opened signal to SET_THREAD_ROOT { rootId }, which stamps the frame and refetches filtered by the payload; the after-create and after-select refetch arms keep filtering by @config.threadRootId, so a mutation re-widens the panel until the consumer re-fires SET_THREAD_ROOT. Layer 3 variants override `bodyContent` to deliver chat-bubble, email-threaded, or linear-comments UX while inheriting the same trait, state machine, emits, and listens. A non-empty sectionTitle switches the default bodyContent into titled-comments mode: header + post list + a standalone composer button (without it an empty thread has no REPLY emitter at all — the affordance only existed per-row)."
2
+ "std-thread — forum-style nested replies with collapse + flat-mode toggle. Owns ThreadPost (persistent). flat:true covers 1:1 linear inquiry threads; flat:false renders forum-style nested. INIT fetches, scoped by @config.threadRootId when set (blank = every root, the default). REPLY persists a child post under @payload.parentId, stamped with the real @user identity. A consumer that mounts this as page comments forwards its own document-opened signal to SET_THREAD_ROOT { rootId }, which stamps @entity.replyRootId (scratch — the persisted threadRootId column is written only by the reply persist create) and refetches filtered by the payload; a plain INIT re-entry now also falls back through @entity.replyRootId before @config.threadRootId, so it stays scoped to the last SET_THREAD_ROOT instead of re-widening — only the after-create/after-select refetches still scope directly off their own event payload. Layer 3 variants override `bodyContent` to deliver chat-bubble, email-threaded, or linear-comments UX while inheriting the same trait, state machine, emits, and listens. A non-empty sectionTitle switches the default bodyContent into titled-comments mode: header + post list + a standalone composer button (without it an empty thread has no REPLY emitter at all — the affordance only existed per-row)."
3
3
  orbital ThreadPostOrbital {
4
4
  ;; Forward relation: array of child ThreadPost IDs whose parentId === this.id.
5
5
  ;; Lowers to `type: "relation", cardinality: "many"` (orbital-lolo lower.rs).
@@ -40,7 +40,10 @@ orbital ThreadPostOrbital {
40
40
  voteCount : number @description "The number of votes associated with this item." @synonyms "votes, rating, score" = 0
41
41
  replyCount : number @description "The number of replies to this post." @synonyms "count, number of replies, child posts" = 0
42
42
  replies : [ThreadPost] @description "A list of child ThreadPost entities." @synonyms "children, descendants, sub-posts"
43
- focusedRow : Map string scalar @description "The currently selected or active row within the thread." @synonyms "selection, active, current" = {}
43
+ focusedRow : Map string scalar @intrinsic @description "The currently selected or active row within the thread." @synonyms "selection, active, current" = {}
44
+ replyDraft : string @intrinsic @description "Reply text being composed." = ""
45
+ replyParentId : string @intrinsic @description "Post the reply being composed answers." = ""
46
+ replyRootId : string @intrinsic @description "Thread root the reply being composed belongs to." = ""
44
47
  }
45
48
 
46
49
  trait ThreadPostBrowse -> @rebindable ThreadPost [interaction, collection] {
@@ -50,7 +53,7 @@ orbital ThreadPostOrbital {
50
53
  INIT -> loading
51
54
  (fetch ThreadPost {
52
55
  emit: { failure: ThreadPostLoadFailed, success: ThreadPostLoaded }
53
- filter: (or ["=", @config.threadRootId, ""] ["=", (object/get @entity threadRootId), @config.threadRootId])
56
+ filter: (or ["=", (str/default @entity.replyRootId @config.threadRootId), ""] ["=", (object/get @entity threadRootId), (str/default @entity.replyRootId @config.threadRootId)])
54
57
  include: (replies)
55
58
  })
56
59
  (render-ui main { size: sm, type: spinner })
@@ -63,7 +66,7 @@ orbital ThreadPostOrbital {
63
66
  variant: error
64
67
  })
65
68
  SET_THREAD_ROOT -> loading
66
- (set @entity.threadRootId ?rootId)
69
+ (set @entity.replyRootId ?rootId)
67
70
  (fetch ThreadPost {
68
71
  emit: { failure: ThreadPostLoadFailed, success: ThreadPostLoaded }
69
72
  filter: (or ["=", ?rootId, ""] ["=", (object/get @entity threadRootId), ?rootId])
@@ -76,7 +79,7 @@ orbital ThreadPostOrbital {
76
79
  INIT -> loading
77
80
  (fetch ThreadPost {
78
81
  emit: { failure: ThreadPostLoadFailed, success: ThreadPostLoaded }
79
- filter: (or ["=", @config.threadRootId, ""] ["=", (object/get @entity threadRootId), @config.threadRootId])
82
+ filter: (or ["=", (str/default @entity.replyRootId @config.threadRootId), ""] ["=", (object/get @entity threadRootId), (str/default @entity.replyRootId @config.threadRootId)])
80
83
  include: (replies)
81
84
  })
82
85
  (render-ui main { size: sm, type: spinner })
@@ -91,14 +94,14 @@ orbital ThreadPostOrbital {
91
94
  authorName: @user.name
92
95
  content: ?content
93
96
  parentId: (str/default ?parentNodeId ?parentId)
94
- threadRootId: (str/default ?parentNodeId (str/default @entity.threadRootId (str/default @config.threadRootId root)))
97
+ threadRootId: (str/default ?parentNodeId (str/default @entity.replyRootId (str/default @config.threadRootId root)))
95
98
  } {
96
99
  emit: { failure: ThreadPostCreateFailed, success: ThreadPostCreated }
97
100
  })
98
101
  ;; Reply with no text yet (e.g. an email "Reply" button) opens the composer.
99
102
  REPLY -> replying when ["=", (str/default ?content ""), ""]
100
- (set @entity.parentId (str/default ?parentNodeId ?parentId))
101
- (set @entity.threadRootId (str/default ?parentNodeId (str/default @entity.threadRootId (str/default @config.threadRootId root))))
103
+ (set @entity.replyParentId (str/default ?parentNodeId ?parentId))
104
+ (set @entity.replyRootId (str/default ?parentNodeId (str/default @entity.replyRootId (str/default @config.threadRootId root))))
102
105
  (render-ui main {
103
106
  children: [{
104
107
  content: "Write a reply"
@@ -138,8 +141,8 @@ orbital ThreadPostOrbital {
138
141
  ;; ?row.threadRootId; ThreadPostCreated's payload is the created row
139
142
  ;; itself (see the type alias above), no `row` wrapper exists.
140
143
  ThreadPostCreated -> browsing
141
- (set @entity.content "")
142
- (set @entity.parentId "")
144
+ (set @entity.replyDraft "")
145
+ (set @entity.replyParentId "")
143
146
  (fetch ThreadPost {
144
147
  emit: { failure: ThreadPostLoadFailed, success: ThreadPostLoaded }
145
148
  filter: (or ["=", ?threadRootId, ""] ["=", (object/get @entity threadRootId), ?threadRootId])
@@ -159,20 +162,20 @@ orbital ThreadPostOrbital {
159
162
  ;; submit button) fire the composer triad while the trait sits in
160
163
  ;; browsing — without these arms every such click is swallowed.
161
164
  EDIT_REPLY -> browsing
162
- (set @entity.content ?value)
163
- SUBMIT_REPLY -> browsing when (not ["=", (str/default @entity.content ""), ""])
165
+ (set @entity.replyDraft ?value)
166
+ SUBMIT_REPLY -> browsing when (not ["=", (str/default @entity.replyDraft ""), ""])
164
167
  (persist create ThreadPost {
165
168
  authorId: @user.id
166
169
  authorName: @user.name
167
- content: @entity.content
168
- parentId: (str/default @entity.parentId "")
169
- threadRootId: (str/default @entity.threadRootId (str/default @config.threadRootId root))
170
+ content: @entity.replyDraft
171
+ parentId: (str/default @entity.replyParentId "")
172
+ threadRootId: (str/default @entity.replyRootId (str/default @config.threadRootId root))
170
173
  } {
171
174
  emit: { failure: ThreadPostCreateFailed, success: ThreadPostCreated }
172
175
  })
173
176
  CANCEL_REPLY -> browsing
174
- (set @entity.content "")
175
- (set @entity.parentId "")
177
+ (set @entity.replyDraft "")
178
+ (set @entity.replyParentId "")
176
179
  ;; replying.SUBMIT_REPLY -> browsing lands here before the persist
177
180
  ;; resolves; a failure must be caught here too, not just replying's twin arm.
178
181
  ThreadPostCreateFailed -> browsing
@@ -190,7 +193,7 @@ orbital ThreadPostOrbital {
190
193
  variant: error
191
194
  })
192
195
  SET_THREAD_ROOT -> loading
193
- (set @entity.threadRootId ?rootId)
196
+ (set @entity.replyRootId ?rootId)
194
197
  (fetch ThreadPost {
195
198
  emit: { failure: ThreadPostLoadFailed, success: ThreadPostLoaded }
196
199
  filter: (or ["=", ?rootId, ""] ["=", (object/get @entity threadRootId), ?rootId])
@@ -201,25 +204,25 @@ orbital ThreadPostOrbital {
201
204
 
202
205
  state replying {
203
206
  EDIT_REPLY -> replying
204
- (set @entity.content ?value)
205
- SUBMIT_REPLY -> browsing when (not ["=", (str/default @entity.content ""), ""])
207
+ (set @entity.replyDraft ?value)
208
+ SUBMIT_REPLY -> browsing when (not ["=", (str/default @entity.replyDraft ""), ""])
206
209
  (persist create ThreadPost {
207
210
  authorId: @user.id
208
211
  authorName: @user.name
209
- content: @entity.content
210
- parentId: (str/default @entity.parentId "")
211
- threadRootId: (str/default @entity.threadRootId (str/default @config.threadRootId root))
212
+ content: @entity.replyDraft
213
+ parentId: (str/default @entity.replyParentId "")
214
+ threadRootId: (str/default @entity.replyRootId (str/default @config.threadRootId root))
212
215
  } {
213
216
  emit: { failure: ThreadPostCreateFailed, success: ThreadPostCreated }
214
217
  })
215
218
  CANCEL_REPLY -> browsing
216
- (set @entity.content "")
217
- (set @entity.parentId "")
219
+ (set @entity.replyDraft "")
220
+ (set @entity.replyParentId "")
218
221
  ;; Scoped to the row just created (?threadRootId, flat) — see the twin
219
222
  ;; arm in `browsing` for why.
220
223
  ThreadPostCreated -> browsing
221
- (set @entity.content "")
222
- (set @entity.parentId "")
224
+ (set @entity.replyDraft "")
225
+ (set @entity.replyParentId "")
223
226
  (fetch ThreadPost {
224
227
  emit: { failure: ThreadPostLoadFailed, success: ThreadPostLoaded }
225
228
  filter: (or ["=", ?threadRootId, ""] ["=", (object/get @entity threadRootId), ?threadRootId])
@@ -232,7 +235,7 @@ orbital ThreadPostOrbital {
232
235
  variant: error
233
236
  })
234
237
  SET_THREAD_ROOT -> loading
235
- (set @entity.threadRootId ?rootId)
238
+ (set @entity.replyRootId ?rootId)
236
239
  (fetch ThreadPost {
237
240
  emit: { failure: ThreadPostLoadFailed, success: ThreadPostLoaded }
238
241
  filter: (or ["=", ?rootId, ""] ["=", (object/get @entity threadRootId), ?rootId])
@@ -245,12 +248,12 @@ orbital ThreadPostOrbital {
245
248
  INIT -> loading
246
249
  (fetch ThreadPost {
247
250
  emit: { failure: ThreadPostLoadFailed, success: ThreadPostLoaded }
248
- filter: (or ["=", @config.threadRootId, ""] ["=", (object/get @entity threadRootId), @config.threadRootId])
251
+ filter: (or ["=", (str/default @entity.replyRootId @config.threadRootId), ""] ["=", (object/get @entity threadRootId), (str/default @entity.replyRootId @config.threadRootId)])
249
252
  include: (replies)
250
253
  })
251
254
  (render-ui main { size: sm, type: spinner })
252
255
  SET_THREAD_ROOT -> loading
253
- (set @entity.threadRootId ?rootId)
256
+ (set @entity.replyRootId ?rootId)
254
257
  (fetch ThreadPost {
255
258
  emit: { failure: ThreadPostLoadFailed, success: ThreadPostLoaded }
256
259
  filter: (or ["=", ?rootId, ""] ["=", (object/get @entity threadRootId), ?rootId])
@@ -18,7 +18,7 @@ orbital RevisionOrbital {
18
18
  authorName : string @description "The name of the user who made the change." @synonyms "user, contributor, owner"
19
19
  content : string @description "The snapshotted body of the revision — plain text or the rich-text HTML a document-look record carries. Rollback hands the whole row back to the host, which restores content onto the source document." @synonyms "text, body, data, value"
20
20
  summary : string @description "A brief explanation of the revision's changes." @synonyms "description, note, comment, explanation"
21
- searchTerm : string @description "The current search query the user submitted." @synonyms "query, term, q" = ""
21
+ searchTerm : string @intrinsic @description "The current search query the user submitted." @synonyms "query, term, q" = ""
22
22
  createdAt : string
23
23
  scopeKey : string @intrinsic @description "The parent document id the feed is currently scoped to, set by SHOW_HISTORY. Empty when browsing the unfiltered global feed." @synonyms "scope, filter key, document scope" = ""
24
24
  }
@@ -3,7 +3,7 @@ app ui-radio "1.0.0"
3
3
  orbital RadioOrbital {
4
4
  entity RadioItem [runtime] {
5
5
  id : string!
6
- value : string
6
+ value : string @intrinsic
7
7
  }
8
8
 
9
9
  trait RadioRender -> @rebindable RadioItem [interaction, instance] {
@@ -3,7 +3,7 @@ app ui-range-slider "1.0.0"
3
3
  orbital RangeSliderOrbital {
4
4
  entity RangeSliderItem [runtime] {
5
5
  id : string!
6
- value : number = 0
6
+ value : number @intrinsic = 0
7
7
  }
8
8
 
9
9
  trait RangeSliderRender -> @rebindable RangeSliderItem [interaction, instance] {
@@ -3,7 +3,7 @@ app ui-switch "1.0.0"
3
3
  orbital SwitchOrbital {
4
4
  entity SwitchItem [runtime] {
5
5
  id : string!
6
- checked : boolean
6
+ checked : boolean @intrinsic
7
7
  }
8
8
 
9
9
  trait SwitchRender -> @rebindable SwitchItem [interaction, instance] {
@@ -3,7 +3,7 @@ app ui-text-highlight "1.0.0"
3
3
  orbital TextHighlightOrbital {
4
4
  entity TextHighlightItem [runtime] {
5
5
  id : string!
6
- annotationId : string
6
+ annotationId : string @intrinsic
7
7
  }
8
8
 
9
9
  trait TextHighlightRender -> @rebindable TextHighlightItem [interaction, instance] {
@@ -3,7 +3,7 @@ app ui-time-slot-cell "1.0.0"
3
3
  orbital TimeSlotCellOrbital {
4
4
  entity TimeSlotCellItem [runtime] {
5
5
  id : string!
6
- time : string = ""
6
+ time : string @intrinsic = ""
7
7
  }
8
8
 
9
9
  trait TimeSlotCellRender -> @rebindable TimeSlotCellItem [interaction, instance] {
@@ -27,8 +27,8 @@ orbital CodeBlockOrbital {
27
27
 
28
28
  entity CodeBlockItem [runtime] {
29
29
  id : string!
30
- code : string
31
- editorId : string
30
+ code : string @intrinsic
31
+ editorId : string @intrinsic
32
32
  }
33
33
 
34
34
  trait CodeBlockRender -> @rebindable CodeBlockItem [interaction, instance] {
@@ -28,7 +28,7 @@ orbital CommandPaletteOrbital {
28
28
 
29
29
  entity CommandPaletteItem [runtime] {
30
30
  id : string!
31
- open : boolean = false
31
+ open : boolean @intrinsic = false
32
32
  }
33
33
 
34
34
  trait CommandPaletteRender -> @rebindable CommandPaletteItem [interaction, instance] {