@almadar/std 16.230.0 → 16.232.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 (46) hide show
  1. package/behaviors/behaviors-registry.json +5214 -970
  2. package/behaviors/lolo/ui/core/atoms/std-form-advanced.lolo +36 -3
  3. package/behaviors/lolo/ui/core/atoms/std-language-picker.lolo +52 -0
  4. package/behaviors/lolo/ui/core/atoms/std-site-header.lolo +77 -15
  5. package/behaviors/lolo/ui/core/atoms/std-step-flow.lolo +1 -0
  6. package/behaviors/lolo/ui/core/atoms/std-version-history.lolo +38 -65
  7. package/behaviors/lolo/ui/core/molecules/ui-change-list.lolo +57 -0
  8. package/behaviors/lolo/ui/core/molecules/ui-commit-row.lolo +143 -0
  9. package/behaviors/lolo/ui/core/molecules/ui-header.lolo +1 -0
  10. package/behaviors/lolo/ui/core/molecules/ui-icon-button.lolo +105 -0
  11. package/behaviors/lolo/ui/core/molecules/ui-menu.lolo +1 -0
  12. package/behaviors/lolo/ui/core/molecules/ui-top-nav-item.lolo +53 -0
  13. package/behaviors/lolo/ui/core/molecules/ui-version-diff.lolo +19 -3
  14. package/behaviors/lolo/ui/core/organisms/ui-dock-layout.lolo +35 -5
  15. package/behaviors/lolo/ui/game/atoms/ui-canvas.lolo +1 -0
  16. package/behaviors/lolo-behavior-contracts.json +1 -1
  17. package/behaviors/registry/factory-signatures.json +1 -1
  18. package/behaviors/registry/ui/core/atoms/std-form-advanced.orb +52 -3
  19. package/behaviors/registry/ui/core/atoms/std-language-picker.orb +285 -0
  20. package/behaviors/registry/ui/core/atoms/std-site-header.orb +348 -74
  21. package/behaviors/registry/ui/core/atoms/std-step-flow.orb +2 -1
  22. package/behaviors/registry/ui/core/atoms/std-version-history.orb +470 -346
  23. package/behaviors/registry/ui/core/molecules/ui-change-list.orb +290 -0
  24. package/behaviors/registry/ui/core/molecules/ui-commit-row.orb +441 -0
  25. package/behaviors/registry/ui/core/molecules/ui-header.orb +43 -0
  26. package/behaviors/registry/ui/core/molecules/ui-icon-button.orb +418 -0
  27. package/behaviors/registry/ui/core/molecules/ui-menu.orb +13 -0
  28. package/behaviors/registry/ui/core/molecules/ui-top-nav-item.orb +277 -0
  29. package/behaviors/registry/ui/core/molecules/ui-version-diff.orb +109 -18
  30. package/behaviors/registry/ui/core/organisms/ui-dock-layout.orb +43 -5
  31. package/behaviors/registry/ui/game/atoms/ui-canvas.orb +8 -0
  32. package/dist/behaviors/exports-reader.js +3116 -2657
  33. package/dist/behaviors/functions/index.d.ts +437 -35
  34. package/dist/behaviors/functions/index.js +3100 -2657
  35. package/dist/behaviors/index.d.ts +1 -1
  36. package/dist/behaviors/index.js +3117 -2658
  37. package/dist/behaviors/query.js +3116 -2657
  38. package/dist/behaviors-embeddings.hash.json +3 -3
  39. package/dist/behaviors-embeddings.json +39 -7
  40. package/dist/behaviors-registry.json +5214 -970
  41. package/dist/index.d.ts +1 -1
  42. package/dist/index.js +3117 -2658
  43. package/dist/knob-embeddings.hash.json +3 -3
  44. package/dist/knob-embeddings.json +217 -13
  45. package/dist/registry/factory-signatures.json +1 -1
  46. package/package.json +2 -2
@@ -49,9 +49,12 @@ orbital FormEntryOrbital {
49
49
  type: stack
50
50
  }, { type: divider }, {
51
51
  cancelEvent: CANCEL
52
+ cancelLabel: @config.cancelLabel
52
53
  fields: @config.fields
53
54
  mode: create
55
+ showCancel: @config.showCancel
54
56
  submitEvent: SUBMIT
57
+ submitLabel: @config.submitLabel
55
58
  type: form-section
56
59
  }]
57
60
  direction: vertical
@@ -75,9 +78,12 @@ orbital FormEntryOrbital {
75
78
  type: stack
76
79
  }, { type: divider }, {
77
80
  cancelEvent: CANCEL
81
+ cancelLabel: @config.cancelLabel
78
82
  fields: @config.fields
79
83
  mode: create
84
+ showCancel: @config.showCancel
80
85
  submitEvent: SUBMIT
86
+ submitLabel: @config.submitLabel
81
87
  type: form-section
82
88
  }]
83
89
  direction: vertical
@@ -91,17 +97,17 @@ orbital FormEntryOrbital {
91
97
  (render-ui main {
92
98
  align: center
93
99
  children: [{ name: check-circle, size: xl, type: icon }, {
94
- content: "Form Submitted"
100
+ content: @config.successTitle
95
101
  type: typography
96
102
  variant: h2
97
103
  }, {
98
- message: "Your form has been submitted successfully."
104
+ message: @config.successMessage
99
105
  type: alert
100
106
  variant: success
101
107
  }, {
102
108
  action: RESET
103
109
  icon: plus
104
- label: "New Entry"
110
+ label: @config.newEntryLabel
105
111
  type: button
106
112
  variant: primary
107
113
  }]
@@ -137,9 +143,12 @@ orbital FormEntryOrbital {
137
143
  type: stack
138
144
  }, { type: divider }, {
139
145
  cancelEvent: CANCEL
146
+ cancelLabel: @config.cancelLabel
140
147
  fields: @config.fields
141
148
  mode: create
149
+ showCancel: @config.showCancel
142
150
  submitEvent: SUBMIT
151
+ submitLabel: @config.submitLabel
143
152
  type: form-section
144
153
  }]
145
154
  direction: vertical
@@ -246,6 +255,30 @@ orbital FormEntryOrbital {
246
255
  @label "Field validation"
247
256
  @description "Per-field rules (format, regex, length) shown inline on submit"
248
257
  @tier "domain"
258
+ submitLabel : string
259
+ @label "Submit button"
260
+ @description "Label on the submit button; unset keeps the translated Save"
261
+ @tier "presentation"
262
+ cancelLabel : string
263
+ @label "Cancel button"
264
+ @description "Label on the cancel button; unset keeps the translated Cancel"
265
+ @tier "presentation"
266
+ showCancel : boolean = true
267
+ @label "Show cancel"
268
+ @description "Whether the form shows a cancel button"
269
+ @tier "presentation"
270
+ successTitle : string = "Form Submitted"
271
+ @label "Confirmation title"
272
+ @description "Heading shown after a successful submit"
273
+ @tier "presentation"
274
+ successMessage : string = "Your form has been submitted successfully."
275
+ @label "Confirmation message"
276
+ @description "Message shown after a successful submit"
277
+ @tier "presentation"
278
+ newEntryLabel : string = "New Entry"
279
+ @label "New entry button"
280
+ @description "Label on the button that starts another entry after a submit"
281
+ @tier "presentation"
249
282
  }
250
283
  }
251
284
 
@@ -0,0 +1,52 @@
1
+ app std-language-picker "1.0.0"
2
+ "std-language-picker — the language switcher of a multilingual site or app: a globe button showing the current language code that opens a menu listing every language in its own name, with the current one ticked. Each entry links to the same page in that language. Routing convention: the default language lives at the root and every other language under a `/<code>/` prefix (`/pricing`, `/ar/pricing`, `/sl/pricing`), so each language has its own stable URL that can be linked from outside and indexed by search engines. Pick for public websites and app chrome that serve more than one language; std-site-header embeds it."
3
+ type SiteLanguage = { code : string!, label : string!, href : string! }
4
+ orbital LanguagePickerOrbital {
5
+ entity LanguagePickerView [runtime] {
6
+ id : string!
7
+ }
8
+
9
+ trait LanguagePickerRender -> @rebindable LanguagePickerView [interaction, instance] {
10
+ initial: idle
11
+
12
+ state idle {
13
+ INIT -> idle
14
+ (render-ui main @config.pickerContent)
15
+ }
16
+
17
+ config {
18
+ languages : [SiteLanguage] = [{ code: "en", label: "English", href: "/" }, { code: "ar", label: "العربية", href: "/ar/" }, { code: "sl", label: "Slovenščina", href: "/sl/" }]
19
+ @label "Languages"
20
+ @description "Every language this page exists in, each named in its own language, with the href of THIS page in that language. The default language's href has no prefix; the others start with /<code>/."
21
+ @synonyms "locales, translations, language list, language switcher, i18n"
22
+ @tier "presentation"
23
+ currentLanguage : string = "en"
24
+ @label "Current language"
25
+ @description "The code of the language this page is in; shown on the button and ticked in the menu"
26
+ @synonyms "locale, active language, page language"
27
+ @tier "presentation"
28
+ pickerContent : render-ui = {
29
+ type: menu
30
+ position: bottom-end
31
+ className: (if (== (array/len @config.languages) 0) hidden "")
32
+ trigger: {
33
+ type: button
34
+ variant: ghost
35
+ size: sm
36
+ icon: globe
37
+ label: (str/upper @config.currentLanguage)
38
+ }
39
+ items: (array/map @config.languages (fn entry {
40
+ id: (object/get @entry code "")
41
+ label: (object/get @entry label "")
42
+ href: (object/get @entry href "")
43
+ icon: (if (== (object/get @entry code "") @config.currentLanguage) check "")
44
+ }))
45
+ }
46
+ @label "Picker body"
47
+ @tier "internal"
48
+ }
49
+ }
50
+
51
+ page "/language-picker" as LanguagePickerPage -> LanguagePickerRender
52
+ }
@@ -1,7 +1,10 @@
1
1
  app std-site-header "1.0.0"
2
- "std-site-header — the sticky top bar of a public website: brand (logo + name), navigation links with the current page marked, and an optional call-to-action button. On small screens the links fold into a menu opened by a toggle. Links follow `href` (in-app path, #anchor, or absolute URL); the header action and the small-screen menu links also emit NAV_CLICKED { href, label }. Pick for marketing sites, docs portals and product websites; for signed-in app chrome use std-app-layout."
3
- type SiteNavLink = { label : string!, href : string! }
2
+ "std-site-header — the sticky top bar of a public website: brand (logo + name), navigation links with the current page marked (a link with children opens a dropdown), an optional language picker (std-language-picker: the same page in each language, default language at the root and the others under /<code>/), and an optional call-to-action button. On small screens the links fold into a menu opened by a toggle, with child links indented under their parent and the call-to-action button at the bottom. Links follow `href` (in-app path, #anchor, or absolute URL); the header action and the small-screen menu links also emit NAV_CLICKED { href, label }. Pick for marketing sites, docs portals and product websites; for signed-in app chrome use std-app-layout."
3
+ type SiteNavLink = { label : string!, href : string!, children : [SiteNavLink] }
4
+ type SiteLanguage = { code : string!, label : string!, href : string! }
4
5
  orbital SiteHeaderOrbital {
6
+ uses LanguagePicker from "std/behaviors/std-language-picker"
7
+
5
8
  entity SiteHeaderView [runtime] {
6
9
  id : string!
7
10
  menuOpen : boolean = false
@@ -59,6 +62,16 @@ orbital SiteHeaderOrbital {
59
62
  @label "Current page path"
60
63
  @description "Marks the matching link as active"
61
64
  @tier "presentation"
65
+ languages : [SiteLanguage] = []
66
+ @label "Languages"
67
+ @description "Every language this page exists in, each named in its own language, with the href of THIS page in that language (default language at the root, others under /<code>/). Empty hides the language picker."
68
+ @synonyms "locales, translations, language switcher, i18n"
69
+ @tier "presentation"
70
+ currentLanguage : string = "en"
71
+ @label "Current language"
72
+ @description "The code of the language this page is in"
73
+ @synonyms "locale, active language, page language"
74
+ @tier "presentation"
62
75
  actionLabel : string = ""
63
76
  @label "Header action label"
64
77
  @description "Call-to-action button at the right; empty hides it"
@@ -79,13 +92,18 @@ orbital SiteHeaderOrbital {
79
92
  showMenuToggle: false
80
93
  brandName: @config.brandName
81
94
  logoSrc: @config.logoSrc
82
- className: "hidden md:flex"
95
+ className: "hidden lg:flex"
83
96
  navigationItems: (array/map @config.links (fn entry {
84
97
  label: (object/get @entry label "")
85
98
  href: (object/get @entry href "")
86
99
  active: (== (object/get @entry href "") @config.currentPath)
100
+ children: (array/map (object/get @entry children []) (fn child {
101
+ label: (object/get @child label "")
102
+ href: (object/get @child href "")
103
+ active: (== (object/get @child href "") @config.currentPath)
104
+ }))
87
105
  }))
88
- actions: {
106
+ actions: [@trait.SiteHeaderLanguages, {
89
107
  type: button
90
108
  label: @config.actionLabel
91
109
  href: @config.actionHref
@@ -94,7 +112,7 @@ orbital SiteHeaderOrbital {
94
112
  action: NAV_LINK
95
113
  actionPayload: { href: @config.actionHref, label: @config.actionLabel }
96
114
  className: (if (== @config.actionLabel "") hidden "")
97
- }
115
+ }]
98
116
  }, {
99
117
  type: header
100
118
  variant: mobile
@@ -104,22 +122,59 @@ orbital SiteHeaderOrbital {
104
122
  onMenuToggle: MENU_TOGGLE
105
123
  brandName: @config.brandName
106
124
  logoSrc: @config.logoSrc
107
- className: "md:hidden"
125
+ className: "lg:hidden"
126
+ actions: [@trait.SiteHeaderLanguages]
108
127
  }, {
109
128
  type: stack
110
129
  direction: vertical
111
130
  gap: xs
112
131
  align: stretch
113
- className: (if @entity.menuOpen "md:hidden border-b border-border bg-card px-4 py-3" hidden)
114
- children: (array/map @config.links (fn entry {
132
+ className: (if @entity.menuOpen "lg:hidden border-b border-border bg-card px-4 py-3" hidden)
133
+ children: [{
134
+ type: stack
135
+ direction: vertical
136
+ gap: xs
137
+ align: stretch
138
+ children: (array/map @config.links (fn (entry) {
139
+ type: stack
140
+ direction: vertical
141
+ gap: xs
142
+ align: stretch
143
+ children: [{
144
+ type: button
145
+ variant: (if (== (object/get @entry href "") @config.currentPath) secondary ghost)
146
+ label: (object/get @entry label "")
147
+ href: (object/get @entry href "")
148
+ action: NAV_LINK
149
+ actionPayload: { href: (object/get @entry href ""), label: (object/get @entry label "") }
150
+ className: "justify-start"
151
+ }, {
152
+ type: stack
153
+ direction: vertical
154
+ gap: xs
155
+ align: stretch
156
+ className: "ps-6"
157
+ children: (array/map (object/get @entry children []) (fn (child) {
158
+ type: button
159
+ variant: (if (== (object/get @child href "") @config.currentPath) secondary ghost)
160
+ label: (object/get @child label "")
161
+ href: (object/get @child href "")
162
+ action: NAV_LINK
163
+ actionPayload: { href: (object/get @child href ""), label: (object/get @child label "") }
164
+ className: "justify-start"
165
+ }))
166
+ }]
167
+ }))
168
+ }, {
115
169
  type: button
116
- variant: (if (== (object/get @entry href "") @config.currentPath) secondary ghost)
117
- label: (object/get @entry label "")
118
- href: (object/get @entry href "")
170
+ label: @config.actionLabel
171
+ href: @config.actionHref
172
+ variant: primary
173
+ size: md
119
174
  action: NAV_LINK
120
- actionPayload: { href: (object/get @entry href ""), label: (object/get @entry label "") }
121
- className: "justify-start"
122
- }))
175
+ actionPayload: { href: @config.actionHref, label: @config.actionLabel }
176
+ className: (if (== @config.actionLabel "") hidden "mt-2 w-full")
177
+ }]
123
178
  }]
124
179
  }
125
180
  @label "Header body"
@@ -127,5 +182,12 @@ orbital SiteHeaderOrbital {
127
182
  }
128
183
  }
129
184
 
130
- page "/site-header" as SiteHeaderPage -> SiteHeaderRender
185
+ trait SiteHeaderLanguages = LanguagePicker.traits.LanguagePickerRender -> SiteHeaderView {
186
+ config {
187
+ languages: @config.languages
188
+ currentLanguage: @config.currentLanguage
189
+ }
190
+ }
191
+
192
+ page "/site-header" as SiteHeaderPage -> SiteHeaderRender, SiteHeaderLanguages
131
193
  }
@@ -530,6 +530,7 @@ orbital StepFlowOrbital {
530
530
  variant: primary
531
531
  }]
532
532
  direction: horizontal
533
+ wrap: true
533
534
  gap: sm
534
535
  type: stack
535
536
  }]
@@ -1,13 +1,11 @@
1
1
  app std-version-history "1.0.0"
2
- "std-version-history — wiki/CMS revision history with diff + rollback. Browses revisions; opens detail in `viewing_single`; compares two revisions in `comparing` with intrinsic version-diff; persists rollback. `RevisionManage` is a rebindable single-entity trait: a consumer rebinds it to its own entity via `linkedEntity`. `config.scopeField` names the Revision field holding the parent document id; a page-mounted `{id}` route param scopes INIT's own fetch, and a consumer forwards SHOW_HISTORY { key } (via a `listens` override) to rescope the feed to one document — empty scopeField (default) or no id keeps today's unfiltered global feed. Rollback and retry refetches stay scoped."
2
+ "std-version-history — wiki/CMS revision history with diff + rollback. Browses revisions; opens detail in `viewing_single`; compares the opened revision with the newest in `comparing`; Rollback emits RevisionRolledBack { row } for the consumer to restore onto its source document. `RevisionManage` is a rebindable single-entity trait: a consumer rebinds it to its own entity via `linkedEntity`. `config.scopeField` names the Revision field holding the parent document id; a page-mounted `{id}` route param scopes INIT's own fetch, and a consumer forwards SHOW_HISTORY { key } (via a `listens` override) to rescope the feed to one document — empty scopeField (default) or no id keeps today's unfiltered global feed. Rollback and retry refetches stay scoped."
3
3
  orbital RevisionOrbital {
4
4
  type RevisionLoaded = Event { data : [Revision] } "Fired when the revision collection finishes loading"
5
5
 
6
6
  type RevisionLoadFailed = Event { error : string, code : string } "Fired when the revision collection fails to load"
7
7
 
8
- type RevisionRolledBack = Event Revision "Fired after a rollback persists successfully on the source document"
9
-
10
- type RevisionRollbackFailed = Event { error : string, code : string } "Fired when a rollback fails to persist"
8
+ type RevisionRolledBack = Event { row : Revision! } "The revision to roll back to: the consumer restores row.content onto its source document (listen for it)"
11
9
 
12
10
  entity Revision [persistent: revisions] {
13
11
  id : string!
@@ -16,11 +14,12 @@ orbital RevisionOrbital {
16
14
  versionNumber : number! @description "A sequential identifier representing the revision's order." @synonyms "sequence, order, iteration"
17
15
  authorId : string @description "Unique identifier for the user who made the change." @synonyms "user identifier, creator, contributor"
18
16
  authorName : string @description "The name of the user who made the change." @synonyms "user, contributor, owner"
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"
17
+ content : string @description "The snapshotted body of the revision — plain text or the rich-text HTML a document-look record carries. Rollback emits RevisionRolledBack { row }; the consumer restores row.content onto its source document." @synonyms "text, body, data, value"
20
18
  summary : string @description "A brief explanation of the revision's changes." @synonyms "description, note, comment, explanation"
21
19
  searchTerm : string @intrinsic @description "The current search query the user submitted." @synonyms "query, term, q" = ""
22
20
  createdAt : string
23
21
  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" = ""
22
+ revisions : [Revision] @intrinsic @description "The loaded revisions, newest first — what Compare diffs against." @synonyms "versions, history" = []
24
23
  }
25
24
 
26
25
  trait RevisionManage -> @rebindable Revision [interaction, collection] {
@@ -47,6 +46,7 @@ orbital RevisionOrbital {
47
46
  type: stack
48
47
  })
49
48
  RevisionLoaded -> browsing
49
+ (set @entity.revisions (array/sort ?data "versionNumber" "desc"))
50
50
  (render-ui main {
51
51
  children: [{
52
52
  align: center
@@ -97,18 +97,6 @@ orbital RevisionOrbital {
97
97
  gap: md
98
98
  type: stack
99
99
  })
100
- RevisionRolledBack -> loading
101
- (set @entity.scopeKey (object/get @payload @config.scopeField ""))
102
- (fetch Revision {
103
- filter: (or ["=", @config.scopeField, ""] ["=", (object/get @payload @config.scopeField ""), ""] ["=", (object/get @entity @config.scopeField), (object/get @payload @config.scopeField "")])
104
- emit: { failure: RevisionLoadFailed, success: RevisionLoaded }
105
- })
106
- RevisionRollbackFailed -> error
107
- (render-ui main {
108
- message: ?error
109
- type: alert
110
- variant: error
111
- })
112
100
  RevisionLoadFailed -> error
113
101
  (render-ui main {
114
102
  message: ?error
@@ -267,7 +255,7 @@ orbital RevisionOrbital {
267
255
  variant: secondary
268
256
  }, {
269
257
  action: ROLLBACK
270
- actionPayload: { id: @entity.id }
258
+ actionPayload: { row: @entity }
271
259
  label: Rollback
272
260
  type: button
273
261
  variant: danger
@@ -281,9 +269,11 @@ orbital RevisionOrbital {
281
269
  type: stack
282
270
  })
283
271
  ROLLBACK -> loading
284
- (set @entity.id ?id)
285
- (persist update Revision @entity {
286
- emit: { failure: RevisionRollbackFailed, success: RevisionRolledBack }
272
+ (emit RevisionRolledBack { row: ?row })
273
+ (set @entity.scopeKey (object/get ?row @config.scopeField ""))
274
+ (fetch Revision {
275
+ filter: (or ["=", @config.scopeField, ""] ["=", (object/get ?row @config.scopeField ""), ""] ["=", (object/get @entity @config.scopeField), (object/get ?row @config.scopeField "")])
276
+ emit: { failure: RevisionLoadFailed, success: RevisionLoaded }
287
277
  })
288
278
  (render-ui main {
289
279
  align: center
@@ -322,6 +312,7 @@ orbital RevisionOrbital {
322
312
  state viewing_single {
323
313
  CLOSE_VIEW -> loading
324
314
  (fetch Revision {
315
+ filter: (or ["=", @config.scopeField, ""] ["=", @entity.scopeKey, ""] ["=", (object/get @entity @config.scopeField), @entity.scopeKey])
325
316
  emit: { failure: RevisionLoadFailed, success: RevisionLoaded }
326
317
  })
327
318
  (render-ui main {
@@ -356,17 +347,16 @@ orbital RevisionOrbital {
356
347
  gap: sm
357
348
  type: stack
358
349
  }, { type: divider }, {
359
- afterId: ?afterId
360
- beforeId: ?beforeId
361
- onRevert: ROLLBACK
362
- revisions: ?revisions
350
+ afterId: (object/get (array/first @entity.revisions) "id" "")
351
+ beforeId: @entity.id
352
+ revisions: (array/map @entity.revisions (fn r { id: @r.id, label: (str/concat "v" (str/default @r.versionNumber "")), author: @r.authorName, timestamp: @r.createdAt, content: @r.content }))
363
353
  type: version-diff
364
354
  view: side-by-side
365
355
  }, {
366
356
  align: center
367
357
  children: [{
368
358
  action: ROLLBACK
369
- actionPayload: { id: @entity.id }
359
+ actionPayload: { row: @entity }
370
360
  label: Rollback
371
361
  type: button
372
362
  variant: danger
@@ -380,9 +370,11 @@ orbital RevisionOrbital {
380
370
  type: stack
381
371
  })
382
372
  ROLLBACK -> loading
383
- (set @entity.id ?id)
384
- (persist update Revision @entity {
385
- emit: { failure: RevisionRollbackFailed, success: RevisionRolledBack }
373
+ (emit RevisionRolledBack { row: ?row })
374
+ (set @entity.scopeKey (object/get ?row @config.scopeField ""))
375
+ (fetch Revision {
376
+ filter: (or ["=", @config.scopeField, ""] ["=", (object/get ?row @config.scopeField ""), ""] ["=", (object/get @entity @config.scopeField), (object/get ?row @config.scopeField "")])
377
+ emit: { failure: RevisionLoadFailed, success: RevisionLoaded }
386
378
  })
387
379
  (render-ui main {
388
380
  align: center
@@ -421,6 +413,7 @@ orbital RevisionOrbital {
421
413
  state comparing {
422
414
  CLOSE_VIEW -> loading
423
415
  (fetch Revision {
416
+ filter: (or ["=", @config.scopeField, ""] ["=", @entity.scopeKey, ""] ["=", (object/get @entity @config.scopeField), @entity.scopeKey])
424
417
  emit: { failure: RevisionLoadFailed, success: RevisionLoaded }
425
418
  })
426
419
  (render-ui main {
@@ -437,9 +430,11 @@ orbital RevisionOrbital {
437
430
  type: stack
438
431
  })
439
432
  ROLLBACK -> loading
440
- (set @entity.id ?id)
441
- (persist update Revision @entity {
442
- emit: { failure: RevisionRollbackFailed, success: RevisionRolledBack }
433
+ (emit RevisionRolledBack { row: ?row })
434
+ (set @entity.scopeKey (object/get ?row @config.scopeField ""))
435
+ (fetch Revision {
436
+ filter: (or ["=", @config.scopeField, ""] ["=", (object/get ?row @config.scopeField ""), ""] ["=", (object/get @entity @config.scopeField), (object/get ?row @config.scopeField "")])
437
+ emit: { failure: RevisionLoadFailed, success: RevisionLoaded }
443
438
  })
444
439
  (render-ui main {
445
440
  align: center
@@ -506,17 +501,14 @@ orbital RevisionOrbital {
506
501
  @tier "domain"
507
502
  COMPARE {
508
503
  id : string!
509
- beforeId : string!
510
- afterId : string!
511
- revisions : [Revision]
512
504
  }
513
- @description "Signals a request to compare two versions."
505
+ @description "Signals a request to compare the opened revision with the newest one."
514
506
  @synonyms "compare, diff, contrast"
515
507
  @tier "presentation"
516
508
  ROLLBACK {
517
- id : string!
509
+ row : Revision!
518
510
  }
519
- @description "Indicates a revision has been successfully reverted."
511
+ @description "Requests a rollback to this revision."
520
512
  @synonyms "reverted, undone, restored"
521
513
  @tier "domain"
522
514
  RevisionLoaded {
@@ -532,17 +524,12 @@ orbital RevisionOrbital {
532
524
  @description "Indicates a failure to load revision data."
533
525
  @synonyms "error, fail, problem, unsuccessful"
534
526
  @tier "internal"
535
- RevisionRolledBack
536
- @description "Indicates a revision has been successfully restored to a previous state."
537
- @synonyms "restored, reverted, undone"
538
- @tier "presentation"
539
- RevisionRollbackFailed {
540
- error : string
541
- code : string
527
+ RevisionRolledBack -> external {
528
+ row : Revision!
542
529
  }
543
- @description "Indicates that a revision rollback operation was unsuccessful."
544
- @synonyms "rollback failed, revert error, undo failure"
545
- @tier "internal"
530
+ @description "The revision to roll back to; the consumer restores row.content onto its source document."
531
+ @synonyms "restored, reverted, undone"
532
+ @tier "domain"
546
533
  }
547
534
 
548
535
  listens {
@@ -565,17 +552,14 @@ orbital RevisionOrbital {
565
552
  @tier "domain"
566
553
  COMPARE {
567
554
  id : string!
568
- beforeId : string!
569
- afterId : string!
570
- revisions : [Revision]
571
555
  }
572
- @description "Indicates a request to compare two versions."
556
+ @description "Indicates a request to compare the opened revision with the newest one."
573
557
  @synonyms "diff, compare, contrast"
574
558
  @tier "presentation"
575
559
  ROLLBACK {
576
- id : string!
560
+ row : Revision!
577
561
  }
578
- @description "A revision has been successfully reverted to a previous state."
562
+ @description "A rollback to this revision was requested."
579
563
  @synonyms "reverted, undone, restored"
580
564
  @tier "domain"
581
565
  RevisionLoaded {
@@ -591,17 +575,6 @@ orbital RevisionOrbital {
591
575
  @description "Indicates a failure to retrieve revision data."
592
576
  @synonyms "error, failure, problem, fetch failed"
593
577
  @tier "internal"
594
- RevisionRolledBack
595
- @description "Indicates a revision has been successfully reverted."
596
- @synonyms "reverted, undone, restored"
597
- @tier "internal"
598
- RevisionRollbackFailed {
599
- error : string
600
- code : string
601
- }
602
- @description "Indicates that a revision rollback operation has failed."
603
- @synonyms "rollback error, revert failure, undo failed"
604
- @tier "internal"
605
578
  SHOW_HISTORY {
606
579
  key : string!
607
580
  }
@@ -0,0 +1,57 @@
1
+ app ui-change-list "1.0.0"
2
+ "The plain-language changes in one version (added / modified / removed). — UI factory (1:1 with the @almadar/ui change-list pattern)."
3
+ ;; @capabilities "change summary, what changed, version changes, diff summary, release notes list, modification list"
4
+ ;; @pattern "change-list"
5
+ orbital ChangeListOrbital {
6
+ type ChangeListChangesItem = {
7
+ type : "added" | "modified" | "removed"!
8
+ title : string!
9
+ description : string
10
+ before : string
11
+ after : string
12
+ }
13
+
14
+ entity ChangeListItem [runtime] {
15
+ id : string!
16
+ }
17
+
18
+ trait ChangeListRender -> @rebindable ChangeListItem [interaction, instance] {
19
+ initial: idle
20
+
21
+ state idle {
22
+ INIT -> idle
23
+ (render-ui main {
24
+ changes: @config.changes
25
+ inspectEvent: @config.inspectEvent
26
+ className: @config.className
27
+ type: change-list
28
+ })
29
+ }
30
+
31
+ emits {
32
+ @config.inspectEvent -> external {
33
+ title : string!
34
+ type : "added" | "modified" | "removed"!
35
+ }
36
+ @description "Emitted by a change's Inspect button. Payload: { title, type }."
37
+ @tier "essential"
38
+ }
39
+
40
+ config {
41
+ changes : [ChangeListChangesItem] = [{ type: added, title: "Title", description: "Description", before: "Before", after: "After" }, { type: modified, title: "Title 2", description: "Description 2", before: "Before 2", after: "After 2" }]
42
+ @label "Changes"
43
+ @description "The changes. Accepts a typed list or a render-ui payload binding."
44
+ @tier "presentation"
45
+ inspectEvent : event = "INSPECT"
46
+ @label "Inspect Event"
47
+ @description "Emitted by a change's Inspect button. Payload: { title, type }."
48
+ @tier "presentation"
49
+ className : string
50
+ @label "Class Name"
51
+ @description "className prop"
52
+ @tier "presentation"
53
+ }
54
+ }
55
+
56
+ page "/change-list" as ChangeListPage -> ChangeListRender
57
+ }