@almadar/std 16.187.0 → 16.189.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/behaviors/lolo/ui/core/.hand-authored.json +4 -4
  2. package/behaviors/lolo/ui/core/atoms/std-board.lolo +138 -4
  3. package/behaviors/lolo/ui/core/atoms/std-browse.lolo +148 -8
  4. package/behaviors/lolo/ui/core/atoms/std-calendar.lolo +161 -11
  5. package/behaviors/lolo/ui/core/atoms/std-event-log.lolo +255 -2
  6. package/behaviors/lolo/ui/core/atoms/std-gallery.lolo +148 -1
  7. package/behaviors/lolo/ui/core/atoms/std-list.lolo +193 -1
  8. package/behaviors/lolo/ui/core/atoms/std-record-detail.lolo +731 -0
  9. package/behaviors/lolo/ui/core/atoms/std-related.lolo +5 -1
  10. package/behaviors/lolo/ui/core/atoms/std-selection.lolo +182 -1
  11. package/behaviors/lolo/ui/core/atoms/std-tree.lolo +113 -3
  12. package/behaviors/lolo/ui/core/atoms/std-version-history.lolo +1 -1
  13. package/behaviors/lolo/ui/core/molecules/ui-document-details.lolo +80 -0
  14. package/behaviors/lolo/ui/core/molecules/ui-document-panel.lolo +213 -0
  15. package/behaviors/lolo/ui/core/molecules/{ui-rich-block-editor.lolo → ui-rich-text-editor.lolo} +25 -25
  16. package/behaviors/lolo/ui/game/atoms/std-area-fill.lolo +93 -0
  17. package/behaviors/lolo/ui/game/atoms/std-choice-gate.lolo +100 -0
  18. package/behaviors/lolo/ui/game/atoms/std-coef-pad.lolo +114 -0
  19. package/behaviors/lolo/ui/game/atoms/std-curve-fog.lolo +50 -0
  20. package/behaviors/lolo/ui/game/atoms/std-loop-lock.lolo +79 -0
  21. package/behaviors/lolo/ui/game/atoms/std-pad-lock.lolo +97 -0
  22. package/behaviors/lolo/ui/game/atoms/std-patrol-hazard.lolo +14 -7
  23. package/behaviors/lolo/ui/game/atoms/std-platformer-body.lolo +48 -5
  24. package/behaviors/lolo/ui/game/atoms/std-velocity-gate.lolo +101 -0
  25. package/behaviors/lolo/ui/game/atoms/std-zone-card.lolo +95 -0
  26. package/behaviors/lolo/ui/game/organisms/std-platformer-board-2d.lolo +9 -0
  27. package/behaviors/registry/infra/atoms/std-approval-gate.orb +16 -8
  28. package/behaviors/registry/infra/atoms/std-cache-aside.orb +62 -31
  29. package/behaviors/registry/infra/atoms/std-circuit-breaker.orb +32 -16
  30. package/behaviors/registry/infra/atoms/std-data-erasure.orb +16 -8
  31. package/behaviors/registry/infra/atoms/std-mod-queue.orb +16 -8
  32. package/behaviors/registry/infra/atoms/std-rate-limiter.orb +28 -14
  33. package/behaviors/registry/infra/organisms/std-status-lifecycle-control.orb +2 -1
  34. package/behaviors/registry/ml/organisms/std-escalating-decision.orb +10 -5
  35. package/behaviors/registry/ml/organisms/std-knowledge-tracing.orb +4 -2
  36. package/behaviors/registry/ui/core/atoms/std-billable-hour.orb +2 -1
  37. package/behaviors/registry/ui/core/atoms/std-board.orb +355 -2
  38. package/behaviors/registry/ui/core/atoms/std-browse.orb +304 -31
  39. package/behaviors/registry/ui/core/atoms/std-calendar.orb +393 -25
  40. package/behaviors/registry/ui/core/atoms/std-dashboard-grid-embedded.orb +2 -1
  41. package/behaviors/registry/ui/core/atoms/std-esign-flow.orb +4 -2
  42. package/behaviors/registry/ui/core/atoms/std-esign-request.orb +6 -3
  43. package/behaviors/registry/ui/core/atoms/std-event-log.orb +773 -0
  44. package/behaviors/registry/ui/core/atoms/std-export.orb +4 -2
  45. package/behaviors/registry/ui/core/atoms/std-gallery.orb +390 -0
  46. package/behaviors/registry/ui/core/atoms/std-import.orb +4 -2
  47. package/behaviors/registry/ui/core/atoms/std-list.orb +451 -0
  48. package/behaviors/registry/ui/core/atoms/std-record-detail.orb +3360 -0
  49. package/behaviors/registry/ui/core/atoms/std-related.orb +23 -1
  50. package/behaviors/registry/ui/core/atoms/std-selection.orb +436 -0
  51. package/behaviors/registry/ui/core/atoms/std-tree.orb +292 -1
  52. package/behaviors/registry/ui/core/atoms/std-version-history.orb +1 -1
  53. package/behaviors/registry/ui/core/molecules/ui-document-details.orb +342 -0
  54. package/behaviors/registry/ui/core/molecules/ui-document-panel.orb +655 -0
  55. package/behaviors/registry/ui/core/molecules/{ui-rich-block-editor.orb → ui-rich-text-editor.orb} +84 -97
  56. package/behaviors/registry/ui/game/atoms/std-area-fill.orb +955 -0
  57. package/behaviors/registry/ui/game/atoms/std-choice-gate.orb +855 -0
  58. package/behaviors/registry/ui/game/atoms/std-coef-pad.orb +928 -0
  59. package/behaviors/registry/ui/game/atoms/std-curve-fog.orb +337 -0
  60. package/behaviors/registry/ui/game/atoms/std-fx-trail.orb +1 -1
  61. package/behaviors/registry/ui/game/atoms/std-gate-lock.orb +1 -1
  62. package/behaviors/registry/ui/game/atoms/std-lives.orb +1 -1
  63. package/behaviors/registry/ui/game/atoms/std-loop-lock.orb +785 -0
  64. package/behaviors/registry/ui/game/atoms/std-pad-lock.orb +933 -0
  65. package/behaviors/registry/ui/game/atoms/std-patrol-hazard.orb +190 -44
  66. package/behaviors/registry/ui/game/atoms/std-platformer-body.orb +1330 -653
  67. package/behaviors/registry/ui/game/atoms/std-velocity-gate.orb +1040 -0
  68. package/behaviors/registry/ui/game/atoms/std-zone-card.orb +642 -0
  69. package/behaviors/registry/ui/game/organisms/std-arcade-board-3d.orb +8 -4
  70. package/behaviors/registry/ui/game/organisms/std-crew-board-2d.orb +6 -3
  71. package/behaviors/registry/ui/game/organisms/std-dungeon-board-2d.orb +10 -5
  72. package/behaviors/registry/ui/game/organisms/std-market-board-3d.orb +8 -4
  73. package/behaviors/registry/ui/game/organisms/std-objective-board-3d.orb +8 -4
  74. package/behaviors/registry/ui/game/organisms/std-platformer-board-2d.orb +36 -1
  75. package/behaviors/registry/ui/game/organisms/std-survival-board-3d.orb +8 -4
  76. package/behaviors/registry/ui/game/organisms/std-tactics-board-2d.orb +12 -6
  77. package/behaviors/registry/ui/game/organisms/std-tactics-board-3d.orb +8 -4
  78. package/behaviors/registry/ui/game/organisms/std-worldmap-board-2d.orb +6 -3
  79. package/behaviors/registry/ui/learning/atoms/std-learn-slope-probe.orb +1 -1
  80. package/behaviors/registry/ui/marketing/atoms/std-marketing-article.orb +2 -1
  81. package/behaviors/registry/ui/marketing/atoms/std-marketing-footer.orb +2 -1
  82. package/behaviors/registry/ui/marketing/atoms/std-marketing-split.orb +2 -1
  83. package/behaviors/registry/ui/marketing/atoms/std-marketing-stats.orb +2 -1
  84. package/behaviors/registry/ui/marketing/atoms/std-marketing-steps.orb +2 -1
  85. package/behaviors/registry/ui/marketing/atoms/std-marketing-team.orb +2 -1
  86. package/dist/behaviors/exports-reader.js +10971 -6255
  87. package/dist/behaviors/functions/index.d.ts +1205 -256
  88. package/dist/behaviors/functions/index.js +10932 -6245
  89. package/dist/behaviors/index.d.ts +1 -1
  90. package/dist/behaviors/index.js +10972 -6256
  91. package/dist/behaviors/query.js +10971 -6255
  92. package/dist/behaviors-embeddings.hash.json +3 -3
  93. package/dist/behaviors-embeddings.json +485 -469
  94. package/dist/behaviors-registry.json +6125 -2940
  95. package/dist/index.d.ts +1 -1
  96. package/dist/index.js +10972 -6256
  97. package/dist/knob-embeddings.hash.json +3 -3
  98. package/dist/knob-embeddings.json +1 -1
  99. package/dist/registry/factory-signatures.json +1 -1
  100. package/package.json +4 -4
  101. package/behaviors/lolo/ui/core/atoms/std-rich-editor.lolo +0 -790
  102. package/behaviors/registry/ui/core/atoms/std-rich-editor.orb +0 -2225
@@ -1,790 +0,0 @@
1
- app std-rich-editor "1.0.0"
2
- "std-rich-editor — wiki/CMS Notion-style block editor. Browses documents in `browsing`; opens the rich-block-editor on a selected row; persists block edits + publish status. `BlockEdit` is a rebindable single-row IN-PLACE body editor: an organism embeds it where the content belongs, rebinds it to its own entity (WikiPage, Note, …), hands it the row's id + blocksJson via OPEN, and routes the emitted BLOCKS_SAVED into its own persistor — this atom never fetches or persists. The read-only body is itself the edit affordance; an empty row paints an empty state that starts the first block; and OPEN_DRAFT opens straight into the authoring editor for a row that was just minted blank (document-first creation)."
3
- ;; @capabilities "notes app, note-taking, journal, personal journal entries, document editor, write and organize notes"
4
- type BlockSpec = { type : string!, content : string, id : string }
5
- type ObjectSpec = { id : string, label : string, value : string }
6
- orbital DocumentOrbital {
7
- type DocumentLoaded = Event { data : [Document] } "Fired when the documents collection finishes loading"
8
-
9
- type DocumentLoadFailed = Event { error : string, code : string } "Fired when the documents collection fails to load"
10
-
11
- type DocumentSaved = Event { row : Document } "Fired after a document's block content persists successfully"
12
-
13
- type DocumentPublished = Event { row : Document } "Fired after a document's status flips to published"
14
-
15
- type DocumentSaveFailed = Event { error : string, code : string } "Fired when persisting a document edit fails"
16
-
17
- entity Document [persistent: documents] {
18
- id : string!
19
- title : string! @description "The human-readable name of the document." @synonyms "name, heading, label"
20
- blocksJson : [BlockSpec] @description "Serialized representation of the document's content blocks." @synonyms "content, data, structure, blocks"
21
- authorId : string @description "Unique identifier of the user who created the document." @synonyms "creatorId, userId, ownerId"
22
- parentId : string @description "Reference to the parent document or container." @synonyms "parent, container, owner"
23
- kind : "page" | "doc" | "post" @description "Specifies the document type." @synonyms "type, documentType, category" = page
24
- status : "draft" | "published" | "archived" @description "Indicates the current state of the document." @synonyms "state, condition, lifecycle" = draft
25
- version : number @description "Represents the version number of the document." @synonyms "revision, release, iteration" = 1
26
- createdAt : string
27
- updatedAt : string
28
- }
29
-
30
- trait DocumentEdit -> Document [interaction, collection] {
31
- initial: loading
32
-
33
- state loading {
34
- INIT -> loading
35
- (fetch Document {
36
- emit: { failure: DocumentLoadFailed, success: DocumentLoaded }
37
- })
38
- (render-ui main {
39
- align: center
40
- children: [{ type: spinner }, {
41
- color: muted
42
- content: "Loading documents…"
43
- type: typography
44
- variant: caption
45
- }]
46
- className: py-12
47
- direction: vertical
48
- gap: md
49
- type: stack
50
- })
51
- DocumentLoaded -> browsing
52
- (render-ui main {
53
- children: [{
54
- align: center
55
- children: [{ name: file-text, type: icon }, {
56
- content: @config.title
57
- type: typography
58
- variant: h3
59
- }]
60
- direction: horizontal
61
- gap: sm
62
- type: stack
63
- }, { type: divider }, {
64
- cols: 1
65
- entity: ?data
66
- fields: [{
67
- label: Title
68
- name: title
69
- variant: caption
70
- }, {
71
- label: Kind
72
- name: kind
73
- variant: badge
74
- }, {
75
- label: Status
76
- name: status
77
- variant: badge
78
- }, {
79
- label: Version
80
- name: version
81
- variant: caption
82
- }, {
83
- format: date
84
- label: Updated
85
- name: updatedAt
86
- variant: caption
87
- }]
88
- gap: sm
89
- itemActions: [{
90
- event: OPEN
91
- icon: edit
92
- label: Open
93
- variant: primary
94
- }, {
95
- event: PUBLISH
96
- icon: send
97
- label: Publish
98
- variant: secondary
99
- }]
100
- look: @config.tableLook
101
- type: data-grid
102
- }]
103
- direction: vertical
104
- gap: md
105
- type: stack
106
- })
107
- DocumentSaved -> loading
108
- (fetch Document {
109
- emit: { failure: DocumentLoadFailed, success: DocumentLoaded }
110
- })
111
- DocumentPublished -> loading
112
- (fetch Document {
113
- emit: { failure: DocumentLoadFailed, success: DocumentLoaded }
114
- })
115
- DocumentSaveFailed -> error
116
- (render-ui main {
117
- message: ?error
118
- type: alert
119
- variant: error
120
- })
121
- DocumentLoadFailed -> error
122
- (render-ui main {
123
- message: ?error
124
- type: alert
125
- variant: error
126
- })
127
- }
128
-
129
- state browsing {
130
- ;; revisit re-fetches silently — landing state's own DocumentLoaded arm repaints
131
- INIT -> loading
132
- (fetch Document {
133
- emit: { failure: DocumentLoadFailed, success: DocumentLoaded }
134
- })
135
- OPEN -> editing
136
- (set @entity.id ?row.id)
137
- (set @entity.title ?row.title)
138
- (set @entity.blocksJson ?row.blocksJson)
139
- (set @entity.authorId ?row.authorId)
140
- (set @entity.parentId ?row.parentId)
141
- (set @entity.kind ?row.kind)
142
- (set @entity.status ?row.status)
143
- (set @entity.version ?row.version)
144
- (set @entity.createdAt ?row.createdAt)
145
- (set @entity.updatedAt ?row.updatedAt)
146
- (render-ui main {
147
- children: [{
148
- align: center
149
- children: [{
150
- action: CLOSE_VIEW
151
- label: Back
152
- type: button
153
- variant: ghost
154
- }, { name: file-text, type: icon }, {
155
- content: @entity.title
156
- type: typography
157
- variant: h3
158
- }, {
159
- label: @entity.status
160
- type: badge
161
- variant: secondary
162
- }]
163
- direction: horizontal
164
- gap: sm
165
- type: stack
166
- }, { type: divider }, {
167
- changeEvent: BLOCKS_CHANGE
168
- initialBlocks: @entity.blocksJson
169
- placeholder: "Start writing…"
170
- showToolbar: true
171
- type: rich-block-editor
172
- }, {
173
- align: center
174
- children: [{
175
- action: SAVE
176
- actionPayload: { id: @entity.id }
177
- label: Save
178
- type: button
179
- variant: primary
180
- }, {
181
- action: PUBLISH
182
- actionPayload: { id: @entity.id }
183
- label: Publish
184
- type: button
185
- variant: secondary
186
- }]
187
- direction: horizontal
188
- gap: sm
189
- type: stack
190
- }]
191
- direction: vertical
192
- gap: md
193
- type: stack
194
- })
195
- PUBLISH -> loading
196
- (set @entity.id ?id)
197
- (fetch Document {
198
- emit: { failure: DocumentLoadFailed, success: DocumentLoaded }
199
- })
200
- (render-ui main {
201
- align: center
202
- children: [{ type: spinner }, {
203
- color: muted
204
- content: "Publishing document…"
205
- type: typography
206
- variant: caption
207
- }]
208
- className: py-12
209
- direction: vertical
210
- gap: md
211
- type: stack
212
- })
213
- }
214
-
215
- state editing {
216
- BLOCKS_CHANGE -> editing
217
- (set @entity.blocksJson ?blocks)
218
- CLOSE_VIEW -> loading
219
- (fetch Document {
220
- emit: { failure: DocumentLoadFailed, success: DocumentLoaded }
221
- })
222
- (render-ui main {
223
- align: center
224
- children: [{ type: spinner }, {
225
- color: muted
226
- content: "Loading documents…"
227
- type: typography
228
- variant: caption
229
- }]
230
- className: py-12
231
- direction: vertical
232
- gap: md
233
- type: stack
234
- })
235
- SAVE -> loading
236
- (set @entity.id ?id)
237
- (persist update Document @entity {
238
- emit: { failure: DocumentSaveFailed, success: DocumentSaved }
239
- })
240
- (render-ui main {
241
- align: center
242
- children: [{ type: spinner }, {
243
- color: muted
244
- content: "Saving document…"
245
- type: typography
246
- variant: caption
247
- }]
248
- className: py-12
249
- direction: vertical
250
- gap: md
251
- type: stack
252
- })
253
- PUBLISH -> loading
254
- (set @entity.id ?id)
255
- (set @entity.status published)
256
- (persist update Document @entity {
257
- emit: { failure: DocumentSaveFailed, success: DocumentPublished }
258
- })
259
- (render-ui main {
260
- align: center
261
- children: [{ type: spinner }, {
262
- color: muted
263
- content: "Publishing document…"
264
- type: typography
265
- variant: caption
266
- }]
267
- className: py-12
268
- direction: vertical
269
- gap: md
270
- type: stack
271
- })
272
- }
273
-
274
- state error {
275
- INIT -> loading
276
- (fetch Document {
277
- emit: { failure: DocumentLoadFailed, success: DocumentLoaded }
278
- })
279
- (render-ui main { size: sm, type: spinner })
280
- }
281
-
282
- emits {
283
- OPEN {
284
- id : string!
285
- row : Document
286
- }
287
- @description "Signals the editor is being displayed."
288
- @synonyms "show, launch, reveal"
289
- @tier "domain"
290
- CLOSE_VIEW
291
- @description "Indicates the editor view is being closed."
292
- @synonyms "dismiss, hide, exit"
293
- @tier "domain"
294
- BLOCKS_CHANGE {
295
- blocks : [ObjectSpec]
296
- }
297
- @description "Signals that the content of a block has been modified."
298
- @synonyms "update, modify, changed, edit"
299
- @tier "domain"
300
- SAVE {
301
- id : string!
302
- }
303
- @description "Signals that changes have been saved."
304
- @synonyms "persist, update, commit"
305
- @tier "domain"
306
- PUBLISH {
307
- id : string!
308
- }
309
- @description "Signals that content has been published."
310
- @synonyms "publish, release, finalize"
311
- @tier "domain"
312
- DocumentLoaded {
313
- data : [Document]
314
- }
315
- @description "Signals that a document has been successfully loaded."
316
- @synonyms "loaded, fetched, retrieved"
317
- @tier "domain"
318
- DocumentLoadFailed {
319
- error : string
320
- code : string
321
- }
322
- @description "Indicates that loading a document failed."
323
- @synonyms "error, failure, problem, unsuccessful"
324
- @tier "internal"
325
- DocumentSaved {
326
- row : Document
327
- }
328
- @description "Signals that a document has been successfully saved."
329
- @synonyms "saved, persisted, updated"
330
- @tier "domain"
331
- DocumentPublished {
332
- row : Document
333
- }
334
- @description "Indicates a document has been successfully published."
335
- @synonyms "published, released, finalized"
336
- @tier "presentation"
337
- DocumentSaveFailed {
338
- error : string
339
- code : string
340
- }
341
- @description "Indicates that saving the document failed."
342
- @synonyms "error, failure, problem, unsuccessful"
343
- @tier "internal"
344
- }
345
-
346
- listens {
347
- OPEN {
348
- id : string!
349
- row : Document
350
- }
351
- @description "Indicates a rich editor view should be displayed."
352
- @synonyms "show, launch, reveal, display"
353
- @tier "domain"
354
- CLOSE_VIEW
355
- @description "Indicates the editor view is being dismissed."
356
- @synonyms "dismiss, hide, close, exit"
357
- @tier "domain"
358
- BLOCKS_CHANGE {
359
- blocks : [ObjectSpec]
360
- }
361
- @description "Indicates changes to the content of editable blocks."
362
- @synonyms "update, modify, edit"
363
- @tier "domain"
364
- SAVE {
365
- id : string!
366
- }
367
- @description "Indicates that changes have been saved."
368
- @synonyms "persist, update, commit"
369
- @tier "domain"
370
- PUBLISH {
371
- id : string!
372
- }
373
- @description "Indicates the document has been successfully published."
374
- @synonyms "publish, submit, finalize"
375
- @tier "domain"
376
- DocumentLoaded {
377
- data : [Document]
378
- }
379
- @description "Signals that a document has been successfully retrieved."
380
- @synonyms "loaded, fetched, retrieved"
381
- @tier "domain"
382
- DocumentLoadFailed {
383
- error : string
384
- code : string
385
- }
386
- @description "Indicates that loading a document failed."
387
- @synonyms "error, failure, problem, unsuccessful"
388
- @tier "internal"
389
- DocumentSaved {
390
- row : Document
391
- }
392
- @description "Indicates a document has been successfully saved."
393
- @synonyms "saved, updated, persisted"
394
- @tier "domain"
395
- DocumentPublished {
396
- row : Document
397
- }
398
- @description "Indicates a document has been successfully published."
399
- @synonyms "published, released, finalized"
400
- @tier "presentation"
401
- DocumentSaveFailed {
402
- error : string
403
- code : string
404
- }
405
- @description "Indicates a failure to save document changes."
406
- @synonyms "error, failure, problem, unsuccessful"
407
- @tier "internal"
408
- }
409
-
410
- config {
411
- title : string = Documents
412
- @label "Section title"
413
- @description "Heading shown above the document list"
414
- @tier "presentation"
415
- tableLook : "dense" | "spacious" | "striped" | "borderless" | "card-rows" = dense
416
- @label "Table look"
417
- @description "Layer 2 visual treatment for the data table rendered by this atom."
418
- @tier "presentation"
419
- }
420
- }
421
-
422
- ;; In-place body editor for one row. The composing organism embeds this
423
- ;; trait where the content belongs (`<trait.X />` inside its detail
424
- ;; render) and feeds it the loaded row through OPEN; the body paints
425
- ;; read-only AND is its own edit affordance — clicking it enters editing
426
- ;; with the authoring toolbar, and a row with no blocks yet paints an
427
- ;; empty state whose button starts the first one. OPEN_DRAFT is the
428
- ;; document-first entry: same payload, but it lands in the editor. SAVE
429
- ;; emits BLOCKS_SAVED for the host's persistor; this atom never fetches or
430
- ;; persists.
431
- trait BlockEdit -> @rebindable Document [interaction, instance] {
432
- initial: idle
433
-
434
- state idle {
435
- INIT -> idle
436
- OPEN -> viewing when [">", (array/len ?blocksJson), 0]
437
- (set @entity.id ?id)
438
- (set @entity.blocksJson ?blocksJson)
439
- (render-ui main {
440
- children: [{
441
- children: [{
442
- action: EDIT_BLOCKS
443
- icon: edit
444
- label: @config.editLabel
445
- type: button
446
- variant: secondary
447
- }]
448
- direction: horizontal
449
- gap: sm
450
- justify: end
451
- type: stack
452
- }, {
453
- action: EDIT_BLOCKS
454
- children: [{
455
- initialBlocks: @entity.blocksJson
456
- readOnly: true
457
- type: rich-block-editor
458
- }]
459
- className: "cursor-text rounded-md transition-colors hover:bg-muted/40"
460
- type: box
461
- }]
462
- direction: vertical
463
- gap: sm
464
- type: stack
465
- })
466
- OPEN -> viewing when ["=", (array/len ?blocksJson), 0]
467
- (set @entity.id ?id)
468
- (set @entity.blocksJson ?blocksJson)
469
- (render-ui main {
470
- actionEvent: EDIT_BLOCKS
471
- actionLabel: @config.emptyActionLabel
472
- description: @config.emptyDescription
473
- icon: file-text
474
- title: @config.emptyTitle
475
- type: empty-state
476
- })
477
- ;; Document-first entry: the row was just minted as a blank draft, so
478
- ;; the body opens ALREADY authoring instead of painting an empty state
479
- ;; the author has to click through. A distinct trigger, not a flag on
480
- ;; OPEN — the guard surface stays decidable.
481
- OPEN_DRAFT -> editing
482
- (set @entity.id ?id)
483
- (set @entity.blocksJson ?blocksJson)
484
- (render-ui main {
485
- children: [{
486
- align: center
487
- children: [{ name: file-text, type: icon }, {
488
- content: @config.title
489
- type: typography
490
- variant: h4
491
- }]
492
- direction: horizontal
493
- gap: sm
494
- type: stack
495
- }, {
496
- changeEvent: BLOCKS_CHANGE
497
- initialBlocks: @entity.blocksJson
498
- placeholder: @config.placeholder
499
- showToolbar: true
500
- type: rich-block-editor
501
- }, {
502
- children: [{
503
- action: SAVE_BLOCKS
504
- label: Save
505
- type: button
506
- variant: primary
507
- }, {
508
- action: CLOSE
509
- label: Cancel
510
- type: button
511
- variant: ghost
512
- }]
513
- direction: horizontal
514
- gap: sm
515
- justify: end
516
- type: stack
517
- }]
518
- direction: vertical
519
- gap: md
520
- type: stack
521
- })
522
- ;; self-loop on the external emit so the validator sees an in-atom
523
- ;; listener — the real consumer is the composing organism's persistor.
524
- BLOCKS_SAVED -> idle
525
- }
526
-
527
- state viewing {
528
- OPEN_DRAFT -> editing
529
- (set @entity.id ?id)
530
- (set @entity.blocksJson ?blocksJson)
531
- (render-ui main {
532
- children: [{
533
- align: center
534
- children: [{ name: file-text, type: icon }, {
535
- content: @config.title
536
- type: typography
537
- variant: h4
538
- }]
539
- direction: horizontal
540
- gap: sm
541
- type: stack
542
- }, {
543
- changeEvent: BLOCKS_CHANGE
544
- initialBlocks: @entity.blocksJson
545
- placeholder: @config.placeholder
546
- showToolbar: true
547
- type: rich-block-editor
548
- }, {
549
- children: [{
550
- action: SAVE_BLOCKS
551
- label: Save
552
- type: button
553
- variant: primary
554
- }, {
555
- action: CLOSE
556
- label: Cancel
557
- type: button
558
- variant: ghost
559
- }]
560
- direction: horizontal
561
- gap: sm
562
- justify: end
563
- type: stack
564
- }]
565
- direction: vertical
566
- gap: md
567
- type: stack
568
- })
569
- OPEN -> viewing when [">", (array/len ?blocksJson), 0]
570
- (set @entity.id ?id)
571
- (set @entity.blocksJson ?blocksJson)
572
- (render-ui main {
573
- children: [{
574
- children: [{
575
- action: EDIT_BLOCKS
576
- icon: edit
577
- label: @config.editLabel
578
- type: button
579
- variant: secondary
580
- }]
581
- direction: horizontal
582
- gap: sm
583
- justify: end
584
- type: stack
585
- }, {
586
- action: EDIT_BLOCKS
587
- children: [{
588
- initialBlocks: @entity.blocksJson
589
- readOnly: true
590
- type: rich-block-editor
591
- }]
592
- className: "cursor-text rounded-md transition-colors hover:bg-muted/40"
593
- type: box
594
- }]
595
- direction: vertical
596
- gap: sm
597
- type: stack
598
- })
599
- OPEN -> viewing when ["=", (array/len ?blocksJson), 0]
600
- (set @entity.id ?id)
601
- (set @entity.blocksJson ?blocksJson)
602
- (render-ui main {
603
- actionEvent: EDIT_BLOCKS
604
- actionLabel: @config.emptyActionLabel
605
- description: @config.emptyDescription
606
- icon: file-text
607
- title: @config.emptyTitle
608
- type: empty-state
609
- })
610
- EDIT_BLOCKS -> editing
611
- (render-ui main {
612
- children: [{
613
- align: center
614
- children: [{ name: file-text, type: icon }, {
615
- content: @config.title
616
- type: typography
617
- variant: h4
618
- }]
619
- direction: horizontal
620
- gap: sm
621
- type: stack
622
- }, {
623
- changeEvent: BLOCKS_CHANGE
624
- initialBlocks: @entity.blocksJson
625
- placeholder: @config.placeholder
626
- showToolbar: true
627
- type: rich-block-editor
628
- }, {
629
- children: [{
630
- action: SAVE_BLOCKS
631
- label: Save
632
- type: button
633
- variant: primary
634
- }, {
635
- action: CLOSE
636
- label: Cancel
637
- type: button
638
- variant: ghost
639
- }]
640
- direction: horizontal
641
- gap: sm
642
- justify: end
643
- type: stack
644
- }]
645
- direction: vertical
646
- gap: md
647
- type: stack
648
- })
649
- }
650
-
651
- state editing {
652
- BLOCKS_CHANGE -> editing
653
- (set @entity.blocksJson ?blocks)
654
- SAVE_BLOCKS -> viewing
655
- (emit BLOCKS_SAVED { id: @entity.id, blocksJson: @entity.blocksJson })
656
- (render-ui main {
657
- children: [{
658
- children: [{
659
- action: EDIT_BLOCKS
660
- icon: edit
661
- label: @config.editLabel
662
- type: button
663
- variant: secondary
664
- }]
665
- direction: horizontal
666
- gap: sm
667
- justify: end
668
- type: stack
669
- }, {
670
- action: EDIT_BLOCKS
671
- children: [{
672
- initialBlocks: @entity.blocksJson
673
- readOnly: true
674
- type: rich-block-editor
675
- }]
676
- className: "cursor-text rounded-md transition-colors hover:bg-muted/40"
677
- type: box
678
- }]
679
- direction: vertical
680
- gap: sm
681
- type: stack
682
- })
683
- CLOSE -> viewing
684
- (render-ui main {
685
- children: [{
686
- children: [{
687
- action: EDIT_BLOCKS
688
- icon: edit
689
- label: @config.editLabel
690
- type: button
691
- variant: secondary
692
- }]
693
- direction: horizontal
694
- gap: sm
695
- justify: end
696
- type: stack
697
- }, {
698
- action: EDIT_BLOCKS
699
- children: [{
700
- initialBlocks: @entity.blocksJson
701
- readOnly: true
702
- type: rich-block-editor
703
- }]
704
- className: "cursor-text rounded-md transition-colors hover:bg-muted/40"
705
- type: box
706
- }]
707
- direction: vertical
708
- gap: sm
709
- type: stack
710
- })
711
- }
712
-
713
- emits {
714
- BLOCKS_SAVED -> external {
715
- id : string!
716
- blocksJson : [BlockSpec]
717
- }
718
- @description "Signals a row's block content is ready to persist. This atom never persists — the composing organism routes BLOCKS_SAVED into its own persistor's update event."
719
- @synonyms "saved, persist, update, commit"
720
- @tier "domain"
721
- CLOSE
722
- @description "Leaves the editor without saving; the body returns to its read-only render."
723
- @synonyms "dismiss, hide, cancel, close"
724
- @tier "domain"
725
- BLOCKS_CHANGE {
726
- blocks : [BlockSpec]
727
- }
728
- @description "Signals that the content of a block has been modified while editing."
729
- @synonyms "update, modify, changed, edit"
730
- @tier "domain"
731
- }
732
-
733
- listens {
734
- OPEN {
735
- id : string!
736
- blocksJson : [BlockSpec]
737
- }
738
- @description "Hands the editor the row whose body it renders — the caller supplies the row's id and current blocks, since this trait never fetches them itself. Re-firing it repaints the body (e.g. after the host refetches a saved row)."
739
- @synonyms "show, launch, reveal, edit"
740
- @tier "domain"
741
- OPEN_DRAFT {
742
- id : string!
743
- blocksJson : [BlockSpec]
744
- }
745
- @description "Hands the editor a row that was just created as a blank draft: same payload as OPEN, but the body opens straight in the authoring editor instead of the read-only render, so a document-first 'New page' lands the author on a cursor rather than an empty state."
746
- @synonyms "new document, start writing, blank draft, compose"
747
- @tier "domain"
748
- BLOCKS_CHANGE {
749
- blocks : [BlockSpec]
750
- }
751
- @description "Indicates changes to the content of editable blocks while editing."
752
- @synonyms "update, modify, edit"
753
- @tier "domain"
754
- CLOSE
755
- @description "Leaves the editor without saving; the body returns to its read-only render."
756
- @synonyms "dismiss, hide, cancel, close"
757
- @tier "domain"
758
- }
759
-
760
- config {
761
- title : string = "Edit content"
762
- @label "Editor heading"
763
- @description "Heading shown above the editor while the body is being edited."
764
- @tier "presentation"
765
- placeholder : string = "Start writing…"
766
- @label "Placeholder text"
767
- @description "Placeholder shown in the block editor when it is empty."
768
- @tier "presentation"
769
- editLabel : string = "Edit content"
770
- @label "Edit button label"
771
- @description "Label of the button above the read-only body that opens the editor."
772
- @tier "presentation"
773
- emptyTitle : string = "Nothing written yet"
774
- @label "Empty heading"
775
- @description "Heading shown in place of the body when the row has no blocks yet."
776
- @tier "presentation"
777
- emptyDescription : string = "This page has no content yet. Start writing to fill it in."
778
- @label "Empty description"
779
- @description "Supporting line shown with the empty body state."
780
- @tier "presentation"
781
- emptyActionLabel : string = "Start writing"
782
- @label "Empty action label"
783
- @description "Label of the button that opens the editor from the empty body state."
784
- @tier "presentation"
785
- }
786
- }
787
-
788
- page "/documents/edit" as DocumentEditPage -> DocumentEdit
789
- page "/documents/block-edit" as BlockEditPage -> BlockEdit
790
- }