@almadar/std 16.228.0 → 16.230.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 (170) hide show
  1. package/behaviors/behaviors-registry.json +97602 -98073
  2. package/behaviors/lolo/infra/atoms/std-notify-on-event.lolo +2 -2
  3. package/behaviors/lolo/ui/core/atoms/std-book-reader.lolo +316 -0
  4. package/behaviors/lolo/ui/core/atoms/std-card-grid.lolo +172 -0
  5. package/behaviors/lolo/ui/core/atoms/std-hero.lolo +247 -0
  6. package/behaviors/lolo/ui/core/atoms/std-media-section.lolo +154 -0
  7. package/behaviors/lolo/ui/core/atoms/std-pricing.lolo +177 -0
  8. package/behaviors/lolo/ui/core/atoms/std-prose.lolo +85 -0
  9. package/behaviors/lolo/ui/core/atoms/std-site-footer.lolo +159 -0
  10. package/behaviors/lolo/ui/core/atoms/std-site-header.lolo +131 -0
  11. package/behaviors/lolo/ui/core/atoms/std-stat-band.lolo +83 -0
  12. package/behaviors/lolo/ui/core/atoms/std-stats.lolo +4 -5
  13. package/behaviors/lolo/ui/core/atoms/std-steps.lolo +124 -0
  14. package/behaviors/lolo/ui/core/atoms/ui-box.lolo +5 -0
  15. package/behaviors/lolo/ui/core/atoms/ui-button.lolo +6 -1
  16. package/behaviors/lolo/ui/core/atoms/ui-image.lolo +64 -0
  17. package/behaviors/lolo/ui/{marketing/atoms → core/molecules}/ui-animated-counter.lolo +11 -6
  18. package/behaviors/lolo/ui/core/organisms/ui-chat-bar.lolo +5 -0
  19. package/behaviors/lolo/ui/game/atoms/ui-canvas-2d.lolo +1 -1
  20. package/behaviors/lolo-behavior-contracts.json +1 -1
  21. package/behaviors/registry/factory-signatures.json +1 -1
  22. package/behaviors/registry/infra/atoms/std-notify-on-event.orb +45 -9
  23. package/behaviors/registry/ui/core/atoms/std-book-reader.orb +1269 -0
  24. package/behaviors/registry/ui/core/atoms/std-card-grid.orb +826 -0
  25. package/behaviors/registry/ui/core/atoms/std-hero.orb +811 -0
  26. package/behaviors/registry/ui/core/atoms/std-media-section.orb +740 -0
  27. package/behaviors/registry/ui/core/atoms/std-pricing.orb +751 -0
  28. package/behaviors/registry/ui/core/atoms/std-prose.orb +264 -0
  29. package/behaviors/registry/ui/core/atoms/std-site-footer.orb +589 -0
  30. package/behaviors/registry/ui/core/atoms/std-site-header.orb +530 -0
  31. package/behaviors/registry/ui/core/atoms/std-stat-band.orb +311 -0
  32. package/behaviors/registry/ui/core/atoms/std-stats.orb +4 -5
  33. package/behaviors/registry/ui/core/atoms/std-steps.orb +532 -0
  34. package/behaviors/registry/ui/{marketing → core}/atoms/ui-animated-graphic.orb +20 -20
  35. package/behaviors/registry/ui/{marketing → core}/atoms/ui-animated-reveal.orb +20 -20
  36. package/behaviors/registry/ui/core/atoms/ui-box.orb +7 -0
  37. package/behaviors/registry/ui/core/atoms/ui-button.orb +9 -1
  38. package/behaviors/registry/ui/core/atoms/ui-image.orb +231 -0
  39. package/behaviors/registry/ui/{marketing → core}/atoms/ui-pattern-tile.orb +20 -20
  40. package/behaviors/registry/ui/{marketing/atoms → core/molecules}/ui-animated-counter.orb +33 -26
  41. package/behaviors/registry/ui/{marketing/atoms → core/molecules}/ui-feature-card.orb +20 -20
  42. package/behaviors/registry/ui/{marketing/atoms → core/molecules}/ui-geometric-pattern.orb +20 -20
  43. package/behaviors/registry/ui/core/organisms/ui-chat-bar.orb +7 -0
  44. package/behaviors/registry/ui/{marketing → core}/templates/ui-auth-layout.orb +20 -20
  45. package/behaviors/registry/ui/game/atoms/ui-canvas-2d.orb +1 -1
  46. package/behaviors/signatures.lolo +1070 -2984
  47. package/canonical-operators.json +3 -3
  48. package/dist/behaviors/exports-reader.js +3818 -10339
  49. package/dist/behaviors/functions/index.d.ts +3965 -6984
  50. package/dist/behaviors/functions/index.js +3786 -10195
  51. package/dist/behaviors/index.d.ts +1 -1
  52. package/dist/behaviors/index.js +3819 -10340
  53. package/dist/behaviors/query.js +3818 -10339
  54. package/dist/behaviors-embeddings.hash.json +3 -3
  55. package/dist/behaviors-embeddings.json +77 -237
  56. package/dist/behaviors-registry.json +97602 -98073
  57. package/dist/index.d.ts +1 -1
  58. package/dist/index.js +3821 -10342
  59. package/dist/knob-embeddings.hash.json +3 -3
  60. package/dist/knob-embeddings.json +352 -1212
  61. package/dist/modules/core.js +2 -2
  62. package/dist/modules/index.js +2 -2
  63. package/dist/registry/factory-signatures.json +1 -1
  64. package/dist/registry.js +2 -2
  65. package/i18n/ar.json +8 -4
  66. package/i18n/en.json +4 -0
  67. package/i18n/sl.json +8 -4
  68. package/package.json +4 -6
  69. package/behaviors/lolo/ui/marketing/atoms/std-marketing-article.lolo +0 -31
  70. package/behaviors/lolo/ui/marketing/atoms/std-marketing-cta.lolo +0 -93
  71. package/behaviors/lolo/ui/marketing/atoms/std-marketing-features.lolo +0 -83
  72. package/behaviors/lolo/ui/marketing/atoms/std-marketing-footer.lolo +0 -72
  73. package/behaviors/lolo/ui/marketing/atoms/std-marketing-hero.lolo +0 -131
  74. package/behaviors/lolo/ui/marketing/atoms/std-marketing-nav.lolo +0 -86
  75. package/behaviors/lolo/ui/marketing/atoms/std-marketing-pricing.lolo +0 -85
  76. package/behaviors/lolo/ui/marketing/atoms/std-marketing-showcase.lolo +0 -87
  77. package/behaviors/lolo/ui/marketing/atoms/std-marketing-split.lolo +0 -50
  78. package/behaviors/lolo/ui/marketing/atoms/std-marketing-stats.lolo +0 -43
  79. package/behaviors/lolo/ui/marketing/atoms/std-marketing-steps.lolo +0 -48
  80. package/behaviors/lolo/ui/marketing/atoms/std-marketing-team.lolo +0 -51
  81. package/behaviors/lolo/ui/marketing/atoms/ui-article-section.lolo +0 -44
  82. package/behaviors/lolo/ui/marketing/atoms/ui-case-study-card.lolo +0 -60
  83. package/behaviors/lolo/ui/marketing/atoms/ui-community-links.lolo +0 -67
  84. package/behaviors/lolo/ui/marketing/atoms/ui-content-section.lolo +0 -44
  85. package/behaviors/lolo/ui/marketing/atoms/ui-cta-banner.lolo +0 -68
  86. package/behaviors/lolo/ui/marketing/atoms/ui-hero-section.lolo +0 -112
  87. package/behaviors/lolo/ui/marketing/atoms/ui-install-box.lolo +0 -39
  88. package/behaviors/lolo/ui/marketing/atoms/ui-marketing-footer.lolo +0 -58
  89. package/behaviors/lolo/ui/marketing/atoms/ui-marketing-stat-card.lolo +0 -45
  90. package/behaviors/lolo/ui/marketing/atoms/ui-pricing-card.lolo +0 -70
  91. package/behaviors/lolo/ui/marketing/atoms/ui-pricing-grid.lolo +0 -49
  92. package/behaviors/lolo/ui/marketing/atoms/ui-pull-quote.lolo +0 -34
  93. package/behaviors/lolo/ui/marketing/atoms/ui-service-catalog.lolo +0 -40
  94. package/behaviors/lolo/ui/marketing/atoms/ui-showcase-card.lolo +0 -64
  95. package/behaviors/lolo/ui/marketing/atoms/ui-split-section.lolo +0 -69
  96. package/behaviors/lolo/ui/marketing/atoms/ui-stats-grid.lolo +0 -44
  97. package/behaviors/lolo/ui/marketing/atoms/ui-step-flow.lolo +0 -51
  98. package/behaviors/lolo/ui/marketing/atoms/ui-tag-cloud.lolo +0 -45
  99. package/behaviors/lolo/ui/marketing/atoms/ui-team-card.lolo +0 -54
  100. package/behaviors/lolo/ui/marketing/organisms/ui-book-chapter-view.lolo +0 -63
  101. package/behaviors/lolo/ui/marketing/organisms/ui-book-cover-page.lolo +0 -54
  102. package/behaviors/lolo/ui/marketing/organisms/ui-book-nav-bar.lolo +0 -49
  103. package/behaviors/lolo/ui/marketing/organisms/ui-book-table-of-contents.lolo +0 -70
  104. package/behaviors/lolo/ui/marketing/organisms/ui-book-viewer.lolo +0 -161
  105. package/behaviors/lolo/ui/marketing/organisms/ui-case-study-organism.lolo +0 -153
  106. package/behaviors/lolo/ui/marketing/organisms/ui-feature-grid-organism.lolo +0 -159
  107. package/behaviors/lolo/ui/marketing/organisms/ui-hero-organism.lolo +0 -162
  108. package/behaviors/lolo/ui/marketing/organisms/ui-pricing-organism.lolo +0 -155
  109. package/behaviors/lolo/ui/marketing/organisms/ui-showcase-organism.lolo +0 -164
  110. package/behaviors/lolo/ui/marketing/organisms/ui-stats-organism.lolo +0 -142
  111. package/behaviors/lolo/ui/marketing/organisms/ui-step-flow-organism.lolo +0 -165
  112. package/behaviors/lolo/ui/marketing/organisms/ui-team-organism.lolo +0 -152
  113. package/behaviors/lolo/ui/marketing/templates/ui-about-page-template.lolo +0 -105
  114. package/behaviors/lolo/ui/marketing/templates/ui-feature-detail-page-template.lolo +0 -93
  115. package/behaviors/lolo/ui/marketing/templates/ui-landing-page-template.lolo +0 -144
  116. package/behaviors/lolo/ui/marketing/templates/ui-pricing-page-template.lolo +0 -89
  117. package/behaviors/registry/ui/marketing/atoms/std-marketing-article.orb +0 -121
  118. package/behaviors/registry/ui/marketing/atoms/std-marketing-cta.orb +0 -360
  119. package/behaviors/registry/ui/marketing/atoms/std-marketing-features.orb +0 -305
  120. package/behaviors/registry/ui/marketing/atoms/std-marketing-footer.orb +0 -265
  121. package/behaviors/registry/ui/marketing/atoms/std-marketing-hero.orb +0 -424
  122. package/behaviors/registry/ui/marketing/atoms/std-marketing-nav.orb +0 -288
  123. package/behaviors/registry/ui/marketing/atoms/std-marketing-pricing.orb +0 -366
  124. package/behaviors/registry/ui/marketing/atoms/std-marketing-showcase.orb +0 -415
  125. package/behaviors/registry/ui/marketing/atoms/std-marketing-split.orb +0 -152
  126. package/behaviors/registry/ui/marketing/atoms/std-marketing-stats.orb +0 -151
  127. package/behaviors/registry/ui/marketing/atoms/std-marketing-steps.orb +0 -221
  128. package/behaviors/registry/ui/marketing/atoms/std-marketing-team.orb +0 -239
  129. package/behaviors/registry/ui/marketing/atoms/ui-article-section.orb +0 -176
  130. package/behaviors/registry/ui/marketing/atoms/ui-case-study-card.orb +0 -195
  131. package/behaviors/registry/ui/marketing/atoms/ui-community-links.orb +0 -254
  132. package/behaviors/registry/ui/marketing/atoms/ui-content-section.orb +0 -182
  133. package/behaviors/registry/ui/marketing/atoms/ui-cta-banner.orb +0 -254
  134. package/behaviors/registry/ui/marketing/atoms/ui-hero-section.orb +0 -345
  135. package/behaviors/registry/ui/marketing/atoms/ui-install-box.orb +0 -163
  136. package/behaviors/registry/ui/marketing/atoms/ui-marketing-footer.orb +0 -298
  137. package/behaviors/registry/ui/marketing/atoms/ui-marketing-stat-card.orb +0 -177
  138. package/behaviors/registry/ui/marketing/atoms/ui-pricing-card.orb +0 -237
  139. package/behaviors/registry/ui/marketing/atoms/ui-pricing-grid.orb +0 -313
  140. package/behaviors/registry/ui/marketing/atoms/ui-pull-quote.orb +0 -156
  141. package/behaviors/registry/ui/marketing/atoms/ui-service-catalog.orb +0 -205
  142. package/behaviors/registry/ui/marketing/atoms/ui-showcase-card.orb +0 -221
  143. package/behaviors/registry/ui/marketing/atoms/ui-split-section.orb +0 -239
  144. package/behaviors/registry/ui/marketing/atoms/ui-stats-grid.orb +0 -202
  145. package/behaviors/registry/ui/marketing/atoms/ui-step-flow.orb +0 -236
  146. package/behaviors/registry/ui/marketing/atoms/ui-tag-cloud.orb +0 -217
  147. package/behaviors/registry/ui/marketing/atoms/ui-team-card.orb +0 -186
  148. package/behaviors/registry/ui/marketing/organisms/ui-book-chapter-view.orb +0 -277
  149. package/behaviors/registry/ui/marketing/organisms/ui-book-cover-page.orb +0 -190
  150. package/behaviors/registry/ui/marketing/organisms/ui-book-nav-bar.orb +0 -183
  151. package/behaviors/registry/ui/marketing/organisms/ui-book-table-of-contents.orb +0 -286
  152. package/behaviors/registry/ui/marketing/organisms/ui-book-viewer.orb +0 -553
  153. package/behaviors/registry/ui/marketing/organisms/ui-case-study-organism.orb +0 -507
  154. package/behaviors/registry/ui/marketing/organisms/ui-feature-grid-organism.orb +0 -504
  155. package/behaviors/registry/ui/marketing/organisms/ui-hero-organism.orb +0 -635
  156. package/behaviors/registry/ui/marketing/organisms/ui-pricing-organism.orb +0 -539
  157. package/behaviors/registry/ui/marketing/organisms/ui-showcase-organism.orb +0 -542
  158. package/behaviors/registry/ui/marketing/organisms/ui-stats-organism.orb +0 -447
  159. package/behaviors/registry/ui/marketing/organisms/ui-step-flow-organism.orb +0 -505
  160. package/behaviors/registry/ui/marketing/organisms/ui-team-organism.orb +0 -494
  161. package/behaviors/registry/ui/marketing/templates/ui-about-page-template.orb +0 -752
  162. package/behaviors/registry/ui/marketing/templates/ui-feature-detail-page-template.orb +0 -638
  163. package/behaviors/registry/ui/marketing/templates/ui-landing-page-template.orb +0 -1028
  164. package/behaviors/registry/ui/marketing/templates/ui-pricing-page-template.orb +0 -603
  165. /package/behaviors/lolo/ui/{marketing → core}/atoms/ui-animated-graphic.lolo +0 -0
  166. /package/behaviors/lolo/ui/{marketing → core}/atoms/ui-animated-reveal.lolo +0 -0
  167. /package/behaviors/lolo/ui/{marketing → core}/atoms/ui-pattern-tile.lolo +0 -0
  168. /package/behaviors/lolo/ui/{marketing/atoms → core/molecules}/ui-feature-card.lolo +0 -0
  169. /package/behaviors/lolo/ui/{marketing/atoms → core/molecules}/ui-geometric-pattern.lolo +0 -0
  170. /package/behaviors/lolo/ui/{marketing → core}/templates/ui-auth-layout.lolo +0 -0
@@ -92,7 +92,7 @@ orbital NotifyOnEventOrbital {
92
92
  recipient: @entity.recipient
93
93
  recordedAt: @now
94
94
  severity: @entity.severity
95
- }) (if (and (str/includes @entity.prefQuietHours "-") ["!=", (str/slice (array/first (str/split @entity.prefQuietHours "-")) 0 2), (str/slice (array/nth (str/split @entity.prefQuietHours "-") 1) 0 2)] (if ["<", (str/slice (array/first (str/split @entity.prefQuietHours "-")) 0 2), (str/slice (array/nth (str/split @entity.prefQuietHours "-") 1) 0 2)] (and [">=", (time/hour @now), (str/slice (array/first (str/split @entity.prefQuietHours "-")) 0 2)] ["<", (time/hour @now), (str/slice (array/nth (str/split @entity.prefQuietHours "-") 1) 0 2)]) (or [">=", (time/hour @now), (str/slice (array/first (str/split @entity.prefQuietHours "-")) 0 2)] ["<", (time/hour @now), (str/slice (array/nth (str/split @entity.prefQuietHours "-") 1) 0 2)]))) (persist create NotificationRecord {
95
+ }) (if (and (str/includes @entity.prefQuietHours "-") ["!=", (str/slice (array/first (str/split @entity.prefQuietHours "-")) 0 2), (str/slice (array/nth (str/split @entity.prefQuietHours "-") 1) 0 2)] (if ["<", (str/slice (array/first (str/split @entity.prefQuietHours "-")) 0 2), (str/slice (array/nth (str/split @entity.prefQuietHours "-") 1) 0 2)] (and [">=", (str/padStart (str/concat "" (time/hour @now)) 2 "0"), (str/slice (array/first (str/split @entity.prefQuietHours "-")) 0 2)] ["<", (str/padStart (str/concat "" (time/hour @now)) 2 "0"), (str/slice (array/nth (str/split @entity.prefQuietHours "-") 1) 0 2)]) (or [">=", (str/padStart (str/concat "" (time/hour @now)) 2 "0"), (str/slice (array/first (str/split @entity.prefQuietHours "-")) 0 2)] ["<", (str/padStart (str/concat "" (time/hour @now)) 2 "0"), (str/slice (array/nth (str/split @entity.prefQuietHours "-") 1) 0 2)]))) (persist create NotificationRecord {
96
96
  channel: @entity.channel
97
97
  dispatched: false
98
98
  error: "quiet-hours"
@@ -427,7 +427,7 @@ orbital NotifyOnEventOrbital {
427
427
  @description "Signing secret forwarded to the webhook service so the receiving endpoint can verify the payload. Ignored when `webhookUrl` is blank."
428
428
  @synonyms "signing secret, hmac secret, webhook signature, shared secret"
429
429
  @tier "internal"
430
- template : string = ""
430
+ template : string = "You have a new notification"
431
431
  @label "Message template"
432
432
  @description "Text shown to the recipient; supports payload interpolation"
433
433
  @synonyms "notification text, message body, alert text"
@@ -0,0 +1,316 @@
1
+ app std-book-reader "1.0.0"
2
+ "std-book-reader — reads a multi-chapter book one chapter at a time. Opens on a cover (cover image, title, subtitle, author, a start button and the table of contents); reading shows a contents rail with the current chapter marked, the chapter title and progress, the chapter text (markdown) and previous/next buttons. Supports right-to-left books. Emits CHAPTER_OPENED on every chapter change. Pick for handbooks, manifestos, course readers and long-form guides."
3
+ type BookChapter = { title : string!, content : string! }
4
+ orbital BookReaderOrbital {
5
+
6
+ entity BookReaderView [runtime] {
7
+ id : string!
8
+ chapterIndex : number = 0
9
+ chapterTitle : string = ""
10
+ chapterContent : string = ""
11
+ progressLabel : string = ""
12
+ isFirst : boolean = true
13
+ isLast : boolean = false
14
+ }
15
+
16
+ trait BookReaderRead -> @rebindable BookReaderView [interaction, instance] {
17
+ initial: cover
18
+
19
+ state cover {
20
+ INIT -> cover
21
+ (render-ui main @config.coverContent)
22
+ START_READING -> reading
23
+ (set @entity.chapterIndex 0)
24
+ (set @entity.chapterTitle (object/get (array/nth @config.chapters 0) title ""))
25
+ (set @entity.chapterContent (object/get (array/nth @config.chapters 0) content ""))
26
+ (set @entity.isFirst true)
27
+ (set @entity.isLast (<= (array/len @config.chapters) 1))
28
+ (set @entity.progressLabel (str/concat "1 / " (array/len @config.chapters)))
29
+ (render-ui main @config.readingContent)
30
+ (emit CHAPTER_OPENED { index: 0, title: @entity.chapterTitle })
31
+ OPEN_CHAPTER -> reading
32
+ (set @entity.chapterIndex ?index)
33
+ (set @entity.chapterTitle (object/get (array/nth @config.chapters ?index) title ""))
34
+ (set @entity.chapterContent (object/get (array/nth @config.chapters ?index) content ""))
35
+ (set @entity.isFirst (== ?index 0))
36
+ (set @entity.isLast (>= ?index (- (array/len @config.chapters) 1)))
37
+ (set @entity.progressLabel (str/concat (+ ?index 1) " / " (array/len @config.chapters)))
38
+ (render-ui main @config.readingContent)
39
+ (emit CHAPTER_OPENED { index: ?index, title: @entity.chapterTitle })
40
+ }
41
+
42
+ state reading {
43
+ INIT -> reading
44
+ (render-ui main @config.readingContent)
45
+ OPEN_CHAPTER -> reading
46
+ (set @entity.chapterIndex ?index)
47
+ (set @entity.chapterTitle (object/get (array/nth @config.chapters ?index) title ""))
48
+ (set @entity.chapterContent (object/get (array/nth @config.chapters ?index) content ""))
49
+ (set @entity.isFirst (== ?index 0))
50
+ (set @entity.isLast (>= ?index (- (array/len @config.chapters) 1)))
51
+ (set @entity.progressLabel (str/concat (+ ?index 1) " / " (array/len @config.chapters)))
52
+ (render-ui main @config.readingContent)
53
+ (emit CHAPTER_OPENED { index: ?index, title: @entity.chapterTitle })
54
+ NEXT_CHAPTER -> reading when (not @entity.isLast)
55
+ (set @entity.chapterIndex (+ @entity.chapterIndex 1))
56
+ (set @entity.chapterTitle (object/get (array/nth @config.chapters @entity.chapterIndex) title ""))
57
+ (set @entity.chapterContent (object/get (array/nth @config.chapters @entity.chapterIndex) content ""))
58
+ (set @entity.isFirst false)
59
+ (set @entity.isLast (>= @entity.chapterIndex (- (array/len @config.chapters) 1)))
60
+ (set @entity.progressLabel (str/concat (+ @entity.chapterIndex 1) " / " (array/len @config.chapters)))
61
+ (render-ui main @config.readingContent)
62
+ (emit CHAPTER_OPENED { index: @entity.chapterIndex, title: @entity.chapterTitle })
63
+ PREV_CHAPTER -> reading when (not @entity.isFirst)
64
+ (set @entity.chapterIndex (- @entity.chapterIndex 1))
65
+ (set @entity.chapterTitle (object/get (array/nth @config.chapters @entity.chapterIndex) title ""))
66
+ (set @entity.chapterContent (object/get (array/nth @config.chapters @entity.chapterIndex) content ""))
67
+ (set @entity.isFirst (== @entity.chapterIndex 0))
68
+ (set @entity.isLast false)
69
+ (set @entity.progressLabel (str/concat (+ @entity.chapterIndex 1) " / " (array/len @config.chapters)))
70
+ (render-ui main @config.readingContent)
71
+ (emit CHAPTER_OPENED { index: @entity.chapterIndex, title: @entity.chapterTitle })
72
+ BACK_TO_COVER -> cover
73
+ (render-ui main @config.coverContent)
74
+ }
75
+
76
+ emits {
77
+ CHAPTER_OPENED -> external {
78
+ index : number
79
+ title : string
80
+ }
81
+ @description "The reader moved to a chapter; carries its index and title."
82
+ @synonyms "page turned, chapter changed, reading progress"
83
+ @tier "domain"
84
+ }
85
+
86
+ listens {
87
+ OPEN_CHAPTER {
88
+ index : number!
89
+ }
90
+ @description "Jump to a chapter from the table of contents."
91
+ @tier "internal"
92
+ }
93
+
94
+ config {
95
+ title : string = "Untitled book"
96
+ @label "Title"
97
+ @tier "presentation"
98
+ subtitle : string = ""
99
+ @label "Subtitle"
100
+ @tier "presentation"
101
+ author : string = ""
102
+ @label "Author"
103
+ @tier "presentation"
104
+ coverImage : string = ""
105
+ @label "Cover image"
106
+ @description "Cover image URL; empty hides it"
107
+ @tier "presentation"
108
+ direction : "ltr" | "rtl" = ltr
109
+ @label "Text direction"
110
+ @description "rtl for Arabic, Hebrew and other right-to-left books"
111
+ @synonyms "right to left, arabic book"
112
+ @tier "presentation"
113
+ chapters : [BookChapter] = [{ title: "Chapter one", content: "The first chapter's text, in **markdown**." }, { title: "Chapter two", content: "The second chapter's text." }]
114
+ @label "Chapters"
115
+ @description "Ordered chapters: a title and markdown content each"
116
+ @synonyms "sections, parts, pages, table of contents"
117
+ @tier "presentation"
118
+ startLabel : string = "Start reading"
119
+ @label "Start button label"
120
+ @tier "presentation"
121
+ contentsLabel : string = "Contents"
122
+ @label "Contents heading"
123
+ @tier "presentation"
124
+ previousLabel : string = "Previous"
125
+ @label "Previous button label"
126
+ @tier "presentation"
127
+ nextLabel : string = "Next"
128
+ @label "Next button label"
129
+ @tier "presentation"
130
+ coverLabel : string = "Cover"
131
+ @label "Back-to-cover label"
132
+ @tier "presentation"
133
+ coverContent : render-ui = {
134
+ type: box
135
+ paddingY: "2xl"
136
+ fullWidth: true
137
+ dir: @config.direction
138
+ children: [{
139
+ type: container
140
+ size: md
141
+ maxWidth: md
142
+ padding: lg
143
+ children: [{
144
+ type: stack
145
+ direction: vertical
146
+ gap: xl
147
+ children: [{
148
+ type: stack
149
+ direction: vertical
150
+ gap: md
151
+ align: center
152
+ children: [{
153
+ type: image
154
+ src: @config.coverImage
155
+ alt: @config.title
156
+ rounded: lg
157
+ bordered: true
158
+ loading: eager
159
+ className: "max-w-xs"
160
+ }, {
161
+ type: typography
162
+ content: @config.title
163
+ variant: h1
164
+ weight: bold
165
+ align: center
166
+ className: "tracking-tight text-balance"
167
+ }, {
168
+ type: typography
169
+ content: @config.subtitle
170
+ variant: large
171
+ color: muted
172
+ align: center
173
+ className: (if (== @config.subtitle "") hidden "text-pretty")
174
+ }, {
175
+ type: typography
176
+ content: @config.author
177
+ variant: label
178
+ color: muted
179
+ align: center
180
+ className: (if (== @config.author "") hidden "")
181
+ }, {
182
+ type: button
183
+ label: @config.startLabel
184
+ variant: primary
185
+ size: lg
186
+ action: START_READING
187
+ className: (if (== (array/len @config.chapters) 0) hidden "")
188
+ }]
189
+ }, {
190
+ type: stack
191
+ direction: vertical
192
+ gap: xs
193
+ className: (if (== (array/len @config.chapters) 0) hidden "")
194
+ children: [{
195
+ type: typography
196
+ content: @config.contentsLabel
197
+ variant: label
198
+ weight: semibold
199
+ }, {
200
+ type: stack
201
+ direction: vertical
202
+ gap: none
203
+ align: start
204
+ children: (array/map @config.chapters (fn chapter {
205
+ type: button
206
+ variant: link
207
+ label: (str/concat (+ @index 1) ". " (object/get @chapter title ""))
208
+ action: OPEN_CHAPTER
209
+ actionPayload: { index: @index }
210
+ }))
211
+ }]
212
+ }]
213
+ }]
214
+ }]
215
+ }
216
+ @label "Cover body"
217
+ @tier "internal"
218
+ readingContent : render-ui = {
219
+ type: box
220
+ paddingY: xl
221
+ fullWidth: true
222
+ dir: @config.direction
223
+ children: [{
224
+ type: container
225
+ size: xl
226
+ maxWidth: xl
227
+ padding: lg
228
+ children: [{
229
+ type: split
230
+ ratio: "1:3"
231
+ gap: xl
232
+ children: [{
233
+ type: stack
234
+ direction: vertical
235
+ gap: xs
236
+ align: start
237
+ className: "lg:sticky lg:top-6 self-start"
238
+ children: [{
239
+ type: button
240
+ variant: link
241
+ label: @config.coverLabel
242
+ leftIcon: book-open
243
+ action: BACK_TO_COVER
244
+ }, {
245
+ type: typography
246
+ content: @config.contentsLabel
247
+ variant: label
248
+ weight: semibold
249
+ className: "pt-2"
250
+ }, {
251
+ type: stack
252
+ direction: vertical
253
+ gap: none
254
+ align: start
255
+ children: (array/map @config.chapters (fn chapter {
256
+ type: button
257
+ variant: link
258
+ label: (object/get @chapter title "")
259
+ action: OPEN_CHAPTER
260
+ actionPayload: { index: @index }
261
+ className: (if (== @index @entity.chapterIndex) "text-foreground font-semibold" "")
262
+ }))
263
+ }]
264
+ }, {
265
+ type: stack
266
+ direction: vertical
267
+ gap: lg
268
+ children: [{
269
+ type: typography
270
+ content: @entity.progressLabel
271
+ variant: caption
272
+ color: muted
273
+ }, {
274
+ type: typography
275
+ content: @entity.chapterTitle
276
+ variant: h2
277
+ weight: bold
278
+ className: "tracking-tight"
279
+ }, {
280
+ type: markdown-content
281
+ content: @entity.chapterContent
282
+ direction: @config.direction
283
+ }, {
284
+ type: divider
285
+ }, {
286
+ type: stack
287
+ direction: horizontal
288
+ gap: md
289
+ justify: between
290
+ children: [{
291
+ type: button
292
+ variant: secondary
293
+ label: @config.previousLabel
294
+ leftIcon: (if (== @config.direction rtl) chevron-right chevron-left)
295
+ action: PREV_CHAPTER
296
+ disabled: @entity.isFirst
297
+ }, {
298
+ type: button
299
+ variant: primary
300
+ label: @config.nextLabel
301
+ rightIcon: (if (== @config.direction rtl) chevron-left chevron-right)
302
+ action: NEXT_CHAPTER
303
+ disabled: @entity.isLast
304
+ }]
305
+ }]
306
+ }]
307
+ }]
308
+ }]
309
+ }
310
+ @label "Reading body"
311
+ @tier "internal"
312
+ }
313
+ }
314
+
315
+ page "/book" as BookReaderPage -> BookReaderRead
316
+ }
@@ -0,0 +1,172 @@
1
+ app std-card-grid "1.0.0"
2
+ "std-card-grid — a titled grid of content cards from a config list. Each card can carry an image (screenshots, portfolio, case studies), a portrait (team members), an icon, a badge, a title, a description and a link. `look` picks media cards, centered profile cards, or plain text cards. Pick for showcases, team pages, case studies, service catalogs and testimonials."
3
+ type CardItem = { title : string!, description : string, image : string, imageAlt : string, avatar : string, icon : string, badge : string, meta : string, href : string, linkLabel : string }
4
+ orbital CardGridOrbital {
5
+
6
+ entity CardGridView [runtime] {
7
+ id : string!
8
+ }
9
+
10
+ trait CardGridRender -> @rebindable CardGridView [interaction, instance] {
11
+ initial: idle
12
+
13
+ state idle {
14
+ INIT -> idle
15
+ (render-ui main {
16
+ type: box
17
+ paddingY: xl
18
+ bg: (if (== @config.surface muted) muted transparent)
19
+ fullWidth: true
20
+ children: [{
21
+ type: container
22
+ size: xl
23
+ maxWidth: xl
24
+ padding: lg
25
+ children: [{ type: stack, direction: vertical, gap: xl, children: [{
26
+ type: stack
27
+ direction: vertical
28
+ gap: sm
29
+ align: (if (== @config.alignment center) center start)
30
+ className: (if (== @config.heading "") (if (== @config.lede "") hidden "") "")
31
+ children: [{
32
+ type: typography
33
+ content: @config.heading
34
+ variant: h2
35
+ weight: bold
36
+ align: (if (== @config.alignment center) center left)
37
+ className: (if (== @config.heading "") hidden "tracking-tight text-balance")
38
+ }, {
39
+ type: typography
40
+ content: @config.lede
41
+ variant: large
42
+ color: muted
43
+ align: (if (== @config.alignment center) center left)
44
+ className: (if (== @config.lede "") hidden "max-w-2xl text-pretty")
45
+ }]
46
+ }, {
47
+ type: simple-grid
48
+ cols: (math/min (math/max @config.columns 1) 6)
49
+ gap: lg
50
+ children: (array/map @config.items (fn item {
51
+ type: card
52
+ look: (if (== @config.look media) tile-image-first elevated)
53
+ padding: (if (== @config.look media) none md)
54
+ className: "h-full"
55
+ children: [{
56
+ type: image
57
+ src: (object/get @item image "")
58
+ alt: (object/get @item imageAlt (object/get @item title ""))
59
+ aspect: "16/9"
60
+ rounded: none
61
+ }, {
62
+ type: stack
63
+ direction: vertical
64
+ gap: sm
65
+ align: (if (== @config.look profile) center start)
66
+ className: (if (== @config.look media) "p-5" "")
67
+ children: [{
68
+ type: avatar
69
+ src: (object/get @item avatar "")
70
+ name: (object/get @item title "")
71
+ size: xl
72
+ className: (if (== (object/get @item avatar "") "") hidden "")
73
+ }, {
74
+ type: icon
75
+ name: (object/get @item icon "")
76
+ size: lg
77
+ className: (if (== (object/get @item icon "") "") hidden "text-primary")
78
+ }, {
79
+ type: badge
80
+ label: (object/get @item badge "")
81
+ variant: primary
82
+ }, {
83
+ type: typography
84
+ content: (object/get @item title "")
85
+ variant: h4
86
+ weight: semibold
87
+ align: (if (== @config.look profile) center left)
88
+ }, {
89
+ type: typography
90
+ content: (object/get @item meta "")
91
+ variant: caption
92
+ color: muted
93
+ align: (if (== @config.look profile) center left)
94
+ className: (if (== (object/get @item meta "") "") hidden "")
95
+ }, {
96
+ type: typography
97
+ content: (object/get @item description "")
98
+ variant: body
99
+ color: muted
100
+ align: (if (== @config.look profile) center left)
101
+ className: (if (== (object/get @item description "") "") hidden "text-pretty")
102
+ }, {
103
+ type: button
104
+ label: (object/get @item linkLabel "")
105
+ href: (object/get @item href "")
106
+ variant: link
107
+ rightIcon: arrow-right
108
+ action: CARD_OPEN
109
+ actionPayload: { href: (object/get @item href ""), title: (object/get @item title "") }
110
+ className: (if (== (object/get @item linkLabel "") "") hidden "")
111
+ }]
112
+ }]
113
+ }))
114
+ }] }]
115
+ }]
116
+ })
117
+ CARD_OPEN -> idle
118
+ (emit CARD_OPENED { href: ?href, title: ?title })
119
+ }
120
+
121
+ emits {
122
+ CARD_OPENED -> external {
123
+ href : string
124
+ title : string
125
+ }
126
+ @description "A card's link was clicked; carries its href and title."
127
+ @tier "domain"
128
+ }
129
+
130
+ listens {
131
+ CARD_OPEN {
132
+ href : string
133
+ title : string
134
+ }
135
+ @description "Card link click."
136
+ @tier "internal"
137
+ }
138
+
139
+ config {
140
+ heading : string = ""
141
+ @label "Heading"
142
+ @description "Section heading above the grid; empty hides it"
143
+ @synonyms "title"
144
+ @tier "presentation"
145
+ lede : string = ""
146
+ @label "Supporting text"
147
+ @description "Text under the heading; empty hides it"
148
+ @tier "presentation"
149
+ alignment : "center" | "start" = center
150
+ @label "Heading alignment"
151
+ @tier "presentation"
152
+ items : [CardItem] = [{ title: "First card", description: "What this card is about." }, { title: "Second card", description: "What this card is about." }, { title: "Third card", description: "What this card is about." }]
153
+ @label "Cards"
154
+ @description "One card per entry: title plus any of image, avatar, icon, badge, meta, description, href + linkLabel"
155
+ @synonyms "items, entries, showcase, portfolio, team members, case studies, services, testimonials"
156
+ @tier "presentation"
157
+ look : "media" | "profile" | "plain" = plain
158
+ @label "Card look"
159
+ @description "media = image-led cards, profile = centered portrait cards, plain = text cards"
160
+ @tier "presentation"
161
+ columns : number = 3
162
+ @label "Max columns"
163
+ @tier "presentation"
164
+ surface : "plain" | "muted" = plain
165
+ @label "Surface"
166
+ @description "Background behind the section"
167
+ @tier "presentation"
168
+ }
169
+ }
170
+
171
+ page "/card-grid" as CardGridPage -> CardGridRender
172
+ }