@almadar/std 16.188.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.
- package/behaviors/lolo/ui/core/.hand-authored.json +0 -4
- package/behaviors/lolo/ui/core/atoms/std-calendar.lolo +20 -8
- package/behaviors/lolo/ui/core/atoms/std-record-detail.lolo +428 -26
- package/behaviors/lolo/ui/core/atoms/std-related.lolo +5 -1
- package/behaviors/lolo/ui/core/atoms/std-version-history.lolo +1 -1
- package/behaviors/lolo/ui/core/molecules/ui-document-details.lolo +80 -0
- package/behaviors/lolo/ui/core/molecules/ui-document-panel.lolo +213 -0
- package/behaviors/lolo/ui/core/molecules/{ui-rich-block-editor.lolo → ui-rich-text-editor.lolo} +25 -25
- package/behaviors/lolo/ui/game/atoms/std-choice-gate.lolo +100 -0
- package/behaviors/lolo/ui/game/atoms/std-coef-pad.lolo +114 -0
- package/behaviors/lolo/ui/game/atoms/std-curve-fog.lolo +50 -0
- package/behaviors/lolo/ui/game/atoms/std-pad-lock.lolo +5 -1
- package/behaviors/lolo/ui/game/atoms/std-platformer-body.lolo +29 -3
- package/behaviors/lolo/ui/game/atoms/std-zone-card.lolo +95 -0
- package/behaviors/lolo/ui/game/organisms/std-platformer-board-2d.lolo +9 -0
- package/behaviors/registry/ui/core/atoms/std-calendar.orb +51 -27
- package/behaviors/registry/ui/core/atoms/std-record-detail.orb +2399 -180
- package/behaviors/registry/ui/core/atoms/std-related.orb +23 -1
- package/behaviors/registry/ui/core/atoms/std-version-history.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-document-details.orb +342 -0
- package/behaviors/registry/ui/core/molecules/ui-document-panel.orb +655 -0
- package/behaviors/registry/ui/core/molecules/{ui-rich-block-editor.orb → ui-rich-text-editor.orb} +84 -97
- package/behaviors/registry/ui/game/atoms/std-choice-gate.orb +855 -0
- package/behaviors/registry/ui/game/atoms/std-coef-pad.orb +928 -0
- package/behaviors/registry/ui/game/atoms/std-curve-fog.orb +337 -0
- package/behaviors/registry/ui/game/atoms/std-pad-lock.orb +31 -1
- package/behaviors/registry/ui/game/atoms/std-platformer-body.orb +847 -401
- package/behaviors/registry/ui/game/atoms/std-zone-card.orb +642 -0
- package/behaviors/registry/ui/game/organisms/std-platformer-board-2d.orb +38 -6
- package/dist/behaviors/exports-reader.js +6491 -6163
- package/dist/behaviors/functions/index.d.ts +669 -300
- package/dist/behaviors/functions/index.js +6469 -6152
- package/dist/behaviors/index.d.ts +1 -1
- package/dist/behaviors/index.js +6492 -6164
- package/dist/behaviors/query.js +6491 -6163
- package/dist/behaviors-embeddings.hash.json +3 -3
- package/dist/behaviors-embeddings.json +367 -375
- package/dist/behaviors-registry.json +4104 -2597
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6492 -6164
- package/dist/knob-embeddings.hash.json +3 -3
- package/dist/knob-embeddings.json +1 -1
- package/dist/registry/factory-signatures.json +1 -1
- package/package.json +4 -4
- package/behaviors/lolo/ui/core/atoms/std-rich-editor.lolo +0 -790
- 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
|
-
}
|