المسارات، وكيف تتشارك السمات على المسار نفسه الشاشة.
الصفحة مسار والسمات التي تعمل عليه. حين يُفتح المسار تتلقى كل سمة INIT مرة واحدة، وحين يُغلق تُحرَّر السمات.
page "/notes" -> NoteList, NoteForm
page "/notes/:id" as NoteDetail -> NoteView
page "/" -> Home [initial]:id معامل مسار، يصل في حمولة INIT للصفحة على شكل ?id.as Name يعطي الصفحة اسمًا تشير إليه المداريّات الأخرى والوكلاء.[initial] يحدد صفحة البداية.يجب أن تكون كل صفحة قابلة للوصول: رابط أو عنصر تنقل أو تأثير navigate يقود إليها، وإلا أبلغ عنها orb validate.
سمتان ترسمان كلتاهما في main تكدّسان جسمين في صفحة واحدة، وهذا ما يرفضه المدقق. ركّبهما بدلًا من ذلك: سمة الصفحة ترسم تخطيطًا وتضمّن الأخريات بـ @trait.Name:
1trait LibraryPage -> LibraryView [interaction, instance] {
2 initial: idle
3 state idle {
4 INIT -> idle
5 (render-ui main { type: stack, direction: vertical, gap: lg, children: [@trait.BookFacts, @trait.BookShelf] })
6 }
7}
8
9page "/library" -> LibraryPageتحتفظ كل سمة مضمَّنة بآلة حالاتها وتحديثاتها، وسمة الصفحة تقرر مكانها فقط.
LibraryPage
on LibraryView · states: 1 · transitions: 0BookShelf
on Book · states: 3 · transitions: 9BookFacts
on LibraryView · states: 1 · transitions: 0MasterListView
on Book · states: 1 · transitions: 1books
on loan
Abelson and Sussman
Hoare
Knuth
1app std-orb-docex-library "1.0.0"
2"std-orb-docex-library — composition: two standard behaviors bound to a local entity and configured at the call site, with no state machine written by hand."
3orbital LibraryOrbital {
4 uses Browse from "std/behaviors/std-browse"
5 uses StatBand from "std/behaviors/std-stat-band"
6
7 entity Book [persistent: docex_books, local] {
8 id : string!
9 name : string!
10 author : string = ""
11 status : "active" | "pending" | "inactive" = active
12 instances [
13 { id: "B-1", name: "Structure and Interpretation", author: "Abelson and Sussman", status: active },
14 { id: "B-2", name: "Communicating Sequential Processes", author: "Hoare", status: pending },
15 { id: "B-3", name: "The Art of Computer Programming", author: "Knuth", status: active }
16 ]
17 }
18
19 entity LibraryView [runtime] {
20 id : string!
21 }
22
23 trait LibraryPage -> LibraryView [interaction, instance] {
24 initial: idle
25
26 state idle {
27 INIT -> idle
28 (render-ui main { type: stack, direction: vertical, gap: lg, children: [@trait.BookFacts, @trait.BookShelf] })
29 }
30 }
31
32 trait BookShelf = Browse.traits.BrowseItemBrowse -> Book {
33 config {
34 browseLook: feed
35 bodySearch: false
36 fields: [{ name: "name", label: "Title", variant: h4 }, { name: "author", label: "Author", variant: caption }, { name: "status", label: "Status", variant: badge, labels: { active: "On the shelf", pending: "On loan", inactive: "Lost" } }]
37 }
38 }
39
40 trait BookFacts = StatBand.traits.StatBandRender -> LibraryView {
41 config {
42 heading: "The shelf at a glance"
43 items: [{ value: "3", label: "books" }, { value: "1", label: "on loan" }]
44 }
45 }
46
47 page "/library" -> LibraryPage
48}يرسم render-ui في خانة مسماة. main هو جسم الصفحة. modal وdrawer وdock طبقات فوقها: ما يفتحها يجب أن يفرغها ((render-ui modal null)) في كل مسار يغادر الحالة التي فتحتها، والمدقق يتحقق من ذلك. toast يعرض الإشعارات، وfloating يظهر في كل صفحة.
الدائرة المغلقة تربط الأحداث والحالات والشاشات معًا.