openuispec 0.1.45 → 0.1.47

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 (138) hide show
  1. package/README.md +17 -5
  2. package/cli/init.ts +21 -3
  3. package/examples/social-app/.mcp.json +10 -0
  4. package/examples/social-app/AGENTS.md +114 -0
  5. package/examples/social-app/CLAUDE.md +114 -0
  6. package/examples/social-app/README.md +19 -0
  7. package/examples/social-app/backend/.gitkeep +1 -0
  8. package/examples/social-app/generated/android/social-app/app/build.gradle.kts +92 -0
  9. package/examples/social-app/generated/android/social-app/app/src/main/AndroidManifest.xml +26 -0
  10. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/AppContainer.kt +20 -0
  11. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/MainActivity.kt +35 -0
  12. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/SocialAppApplication.kt +13 -0
  13. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/data/MockData.kt +98 -0
  14. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/data/preferences/AppPreferences.kt +19 -0
  15. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/data/preferences/DataStorePreferencesRepository.kt +68 -0
  16. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/data/preferences/PreferencesRepository.kt +15 -0
  17. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/model/Models.kt +34 -0
  18. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/MainShell.kt +390 -0
  19. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/components/Components.kt +234 -0
  20. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/components/ContractPrimitives.kt +641 -0
  21. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/navigation/RootComponent.kt +113 -0
  22. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/ChatDetailScreen.kt +212 -0
  23. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/CreatePostScreen.kt +113 -0
  24. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/DiscoverScreen.kt +137 -0
  25. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/EditProfileScreen.kt +180 -0
  26. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/HomeFeedScreen.kt +157 -0
  27. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/MessagesInboxScreen.kt +85 -0
  28. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/NotificationsScreen.kt +74 -0
  29. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/PostDetailScreen.kt +293 -0
  30. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/ProfileSelfScreen.kt +116 -0
  31. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/SearchResultsScreen.kt +161 -0
  32. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/SettingsScreen.kt +164 -0
  33. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/SettingsStore.kt +95 -0
  34. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/screens/UserProfileScreen.kt +123 -0
  35. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Color.kt +33 -0
  36. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Shape.kt +41 -0
  37. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Spacing.kt +20 -0
  38. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Theme.kt +82 -0
  39. package/examples/social-app/generated/android/social-app/app/src/main/java/com/social/app/ui/theme/Type.kt +60 -0
  40. package/examples/social-app/generated/android/social-app/app/src/main/res/drawable/ic_launcher_foreground.xml +9 -0
  41. package/examples/social-app/generated/android/social-app/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +5 -0
  42. package/examples/social-app/generated/android/social-app/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +5 -0
  43. package/examples/social-app/generated/android/social-app/app/src/main/res/values/strings.xml +91 -0
  44. package/examples/social-app/generated/android/social-app/app/src/main/res/values/themes.xml +10 -0
  45. package/examples/social-app/generated/android/social-app/app/src/main/res/values-ru/strings.xml +79 -0
  46. package/examples/social-app/generated/android/social-app/app/src/main/res/values-uz/strings.xml +79 -0
  47. package/examples/social-app/generated/android/social-app/app/src/main/xml/AndroidManifest.xml +23 -0
  48. package/examples/social-app/generated/android/social-app/build.gradle.kts +6 -0
  49. package/examples/social-app/generated/android/social-app/gradle/libs.versions.toml +48 -0
  50. package/examples/social-app/generated/android/social-app/gradle/wrapper/gradle-wrapper.properties +8 -0
  51. package/examples/social-app/generated/android/social-app/gradle.properties +11 -0
  52. package/examples/social-app/generated/android/social-app/gradlew +25 -0
  53. package/examples/social-app/generated/android/social-app/settings.gradle.kts +23 -0
  54. package/examples/social-app/generated/web/social-app/index.html +12 -0
  55. package/examples/social-app/generated/web/social-app/package-lock.json +2517 -0
  56. package/examples/social-app/generated/web/social-app/package.json +27 -0
  57. package/examples/social-app/generated/web/social-app/src/app/App.tsx +58 -0
  58. package/examples/social-app/generated/web/social-app/src/components/Shell.tsx +259 -0
  59. package/examples/social-app/generated/web/social-app/src/components/cards.tsx +317 -0
  60. package/examples/social-app/generated/web/social-app/src/components/ui.tsx +340 -0
  61. package/examples/social-app/generated/web/social-app/src/flows/CreatePostFlow.tsx +86 -0
  62. package/examples/social-app/generated/web/social-app/src/i18n.tsx +59 -0
  63. package/examples/social-app/generated/web/social-app/src/lib/icons.tsx +85 -0
  64. package/examples/social-app/generated/web/social-app/src/lib/tokens.ts +70 -0
  65. package/examples/social-app/generated/web/social-app/src/lib/utils.ts +97 -0
  66. package/examples/social-app/generated/web/social-app/src/locales/en.json +67 -0
  67. package/examples/social-app/generated/web/social-app/src/locales/ru.json +67 -0
  68. package/examples/social-app/generated/web/social-app/src/locales/uz.json +67 -0
  69. package/examples/social-app/generated/web/social-app/src/main.tsx +16 -0
  70. package/examples/social-app/generated/web/social-app/src/screens/ChatDetailScreen.tsx +90 -0
  71. package/examples/social-app/generated/web/social-app/src/screens/DiscoverScreen.tsx +86 -0
  72. package/examples/social-app/generated/web/social-app/src/screens/EditProfileScreen.tsx +57 -0
  73. package/examples/social-app/generated/web/social-app/src/screens/HomeFeedScreen.tsx +103 -0
  74. package/examples/social-app/generated/web/social-app/src/screens/MessagesInboxScreen.tsx +52 -0
  75. package/examples/social-app/generated/web/social-app/src/screens/NotificationsScreen.tsx +41 -0
  76. package/examples/social-app/generated/web/social-app/src/screens/PostDetailScreen.tsx +115 -0
  77. package/examples/social-app/generated/web/social-app/src/screens/ProfileSelfScreen.tsx +57 -0
  78. package/examples/social-app/generated/web/social-app/src/screens/ProfileUserScreen.tsx +76 -0
  79. package/examples/social-app/generated/web/social-app/src/screens/SearchResultsScreen.tsx +96 -0
  80. package/examples/social-app/generated/web/social-app/src/screens/SettingsScreen.tsx +79 -0
  81. package/examples/social-app/generated/web/social-app/src/state/store.ts +592 -0
  82. package/examples/social-app/generated/web/social-app/src/styles.css +124 -0
  83. package/examples/social-app/generated/web/social-app/src/vite-env.d.ts +1 -0
  84. package/examples/social-app/generated/web/social-app/tsconfig.json +22 -0
  85. package/examples/social-app/generated/web/social-app/tsconfig.node.json +13 -0
  86. package/examples/social-app/generated/web/social-app/tsconfig.node.tsbuildinfo +1 -0
  87. package/examples/social-app/generated/web/social-app/tsconfig.tsbuildinfo +1 -0
  88. package/examples/social-app/generated/web/social-app/vite.config.d.ts +2 -0
  89. package/examples/social-app/generated/web/social-app/vite.config.js +6 -0
  90. package/examples/social-app/generated/web/social-app/vite.config.ts +7 -0
  91. package/examples/social-app/openuispec/README.md +56 -0
  92. package/examples/social-app/openuispec/contracts/.gitkeep +0 -0
  93. package/examples/social-app/openuispec/contracts/action_trigger.yaml +104 -0
  94. package/examples/social-app/openuispec/contracts/collection.yaml +43 -0
  95. package/examples/social-app/openuispec/contracts/data_display.yaml +47 -0
  96. package/examples/social-app/openuispec/contracts/feedback.yaml +49 -0
  97. package/examples/social-app/openuispec/contracts/input_field.yaml +41 -0
  98. package/examples/social-app/openuispec/contracts/nav_container.yaml +34 -0
  99. package/examples/social-app/openuispec/contracts/surface.yaml +41 -0
  100. package/examples/social-app/openuispec/flows/.gitkeep +0 -0
  101. package/examples/social-app/openuispec/flows/create_post.yaml +66 -0
  102. package/examples/social-app/openuispec/locales/.gitkeep +0 -0
  103. package/examples/social-app/openuispec/locales/en.json +67 -0
  104. package/examples/social-app/openuispec/locales/ru.json +67 -0
  105. package/examples/social-app/openuispec/locales/uz.json +67 -0
  106. package/examples/social-app/openuispec/openuispec.yaml +214 -0
  107. package/examples/social-app/openuispec/platform/.gitkeep +0 -0
  108. package/examples/social-app/openuispec/platform/android.yaml +30 -0
  109. package/examples/social-app/openuispec/platform/ios.yaml +19 -0
  110. package/examples/social-app/openuispec/platform/web.yaml +23 -0
  111. package/examples/social-app/openuispec/screens/.gitkeep +0 -0
  112. package/examples/social-app/openuispec/screens/chat_detail.yaml +53 -0
  113. package/examples/social-app/openuispec/screens/discover.yaml +78 -0
  114. package/examples/social-app/openuispec/screens/edit_profile.yaml +78 -0
  115. package/examples/social-app/openuispec/screens/home_feed.yaml +138 -0
  116. package/examples/social-app/openuispec/screens/messages_inbox.yaml +43 -0
  117. package/examples/social-app/openuispec/screens/notifications.yaml +29 -0
  118. package/examples/social-app/openuispec/screens/post_detail.yaml +86 -0
  119. package/examples/social-app/openuispec/screens/profile_self.yaml +53 -0
  120. package/examples/social-app/openuispec/screens/profile_user.yaml +60 -0
  121. package/examples/social-app/openuispec/screens/search_results.yaml +62 -0
  122. package/examples/social-app/openuispec/screens/settings.yaml +99 -0
  123. package/examples/social-app/openuispec/tokens/.gitkeep +0 -0
  124. package/examples/social-app/openuispec/tokens/color.yaml +76 -0
  125. package/examples/social-app/openuispec/tokens/elevation.yaml +31 -0
  126. package/examples/social-app/openuispec/tokens/icons.yaml +147 -0
  127. package/examples/social-app/openuispec/tokens/layout.yaml +37 -0
  128. package/examples/social-app/openuispec/tokens/motion.yaml +28 -0
  129. package/examples/social-app/openuispec/tokens/spacing.yaml +19 -0
  130. package/examples/social-app/openuispec/tokens/themes.yaml +31 -0
  131. package/examples/social-app/openuispec/tokens/typography.yaml +50 -0
  132. package/examples/social-app/package.json +12 -0
  133. package/examples/taskflow/openuispec/openuispec.yaml +2 -0
  134. package/examples/todo-orbit/openuispec/openuispec.yaml +2 -0
  135. package/mcp-server/index.ts +200 -10
  136. package/package.json +1 -1
  137. package/schema/openuispec.schema.json +7 -0
  138. package/spec/openuispec-v0.1.md +13 -0
@@ -0,0 +1,78 @@
1
+ discover:
2
+ semantic: "Discover screen with search, trending topics, and suggested creators"
3
+ status: draft
4
+
5
+ data:
6
+ creators:
7
+ source: "api.discover.creators"
8
+ loading: { skeleton: true, count: 6 }
9
+ trends:
10
+ source: "api.discover.trends"
11
+ loading: { skeleton: true, count: 5 }
12
+ tags:
13
+ source: "api.discover.tags"
14
+ loading: { skeleton: true, count: 10 }
15
+
16
+ state:
17
+ search_query: { type: string, default: "" }
18
+
19
+ layout:
20
+ type: scroll_vertical
21
+ sections:
22
+ - id: search_bar
23
+ contract: input_field
24
+ input_type: text
25
+ props:
26
+ label: "$t:discover.search_placeholder"
27
+ value: "state.search_query"
28
+ icon: "search"
29
+ action:
30
+ type: navigate
31
+ destination: "screens/search_results"
32
+ params: { query: "state.search_query" }
33
+
34
+ - id: trending_section
35
+ header: "$t:discover.trending"
36
+ contract: collection
37
+ variant: list
38
+ props:
39
+ data: "trends"
40
+ item_contract: data_display
41
+ item_props_map:
42
+ title: "item.label"
43
+ subtitle: "{item.post_count | format:number}"
44
+ action:
45
+ type: navigate
46
+ destination: "screens/search_results"
47
+ params: { query: "{item.label}", tab: "posts" }
48
+
49
+ - id: tags_section
50
+ header: "$t:discover.popular_tags"
51
+ contract: collection
52
+ variant: chip_row
53
+ props:
54
+ data: "tags"
55
+ item_contract: action_trigger
56
+ item_props_map:
57
+ label: "#{item.name}"
58
+ action:
59
+ type: navigate
60
+ destination: "screens/search_results"
61
+ params: { query: "#{item.name}", tab: "posts" }
62
+
63
+ - id: creators_section
64
+ header: "$t:discover.suggested_creators"
65
+ contract: collection
66
+ variant: horizontal_scroll
67
+ props:
68
+ data: "creators"
69
+ item_contract: data_display
70
+ item_props_map:
71
+ title: "item.display_name"
72
+ subtitle: "@{item.handle}"
73
+ body: "item.bio"
74
+ leading: "item.avatar_url"
75
+ action:
76
+ type: navigate
77
+ destination: "screens/profile_user"
78
+ params: { user_id: "{item.id}" }
@@ -0,0 +1,78 @@
1
+ edit_profile:
2
+ semantic: "Edit current user's profile fields"
3
+ status: draft
4
+
5
+ data:
6
+ profile:
7
+ source: "api.profiles.me"
8
+
9
+ state:
10
+ display_name: { type: string, default: "{profile.display_name}" }
11
+ handle: { type: string, default: "{profile.handle}" }
12
+ bio: { type: string, default: "{profile.bio}" }
13
+ website: { type: string, default: "{profile.website}" }
14
+
15
+ layout:
16
+ type: scroll_vertical
17
+ sections:
18
+ - id: avatar_section
19
+ contract: data_display
20
+ variant: card
21
+ props:
22
+ title: "$t:edit_profile.avatar"
23
+ media: "{profile.avatar_url}"
24
+
25
+ - id: form
26
+ form_id: "profile_form"
27
+ children:
28
+ - contract: input_field
29
+ input_type: text
30
+ props:
31
+ label: "$t:edit_profile.display_name"
32
+ value: "state.display_name"
33
+ required: true
34
+ data_binding: "form.display_name"
35
+
36
+ - contract: input_field
37
+ input_type: text
38
+ props:
39
+ label: "$t:edit_profile.handle"
40
+ value: "state.handle"
41
+ required: true
42
+ data_binding: "form.handle"
43
+
44
+ - contract: input_field
45
+ input_type: text
46
+ props:
47
+ label: "$t:edit_profile.bio"
48
+ value: "state.bio"
49
+ multiline: true
50
+ max_length: 160
51
+ data_binding: "form.bio"
52
+
53
+ - contract: input_field
54
+ input_type: text
55
+ props:
56
+ label: "$t:edit_profile.website"
57
+ value: "state.website"
58
+ keyboard: url
59
+ data_binding: "form.website"
60
+
61
+ - id: save_button
62
+ contract: action_trigger
63
+ variant: primary
64
+ props:
65
+ label: "$t:edit_profile.save"
66
+ full_width: true
67
+ action:
68
+ type: sequence
69
+ actions:
70
+ - type: api_call
71
+ endpoint: "api.profiles.updateMe"
72
+ body:
73
+ display_name: "state.display_name"
74
+ handle: "state.handle"
75
+ bio: "state.bio"
76
+ website: "state.website"
77
+ - { type: feedback, variant: toast, message: "$t:edit_profile.saved" }
78
+ - { type: dismiss }
@@ -0,0 +1,138 @@
1
+ home_feed:
2
+ semantic: "Main feed with stories carousel, post list, and create post action"
3
+ status: draft
4
+
5
+ data:
6
+ feed:
7
+ source: "api.feed.list"
8
+ params:
9
+ filter: "state.active_filter"
10
+ search: "state.search_query"
11
+ cursor: "state.cursor"
12
+ loading: { skeleton: true, count: 5 }
13
+ empty: { message: "$t:home.empty_feed" }
14
+ stories:
15
+ source: "api.feed.stories"
16
+ loading: { skeleton: true, count: 8 }
17
+
18
+ state:
19
+ active_filter:
20
+ type: enum
21
+ values: [all, following, popular]
22
+ default: all
23
+ search_query: { type: string, default: "" }
24
+ cursor: { type: string, default: "" }
25
+
26
+ navigation:
27
+ contract: nav_container
28
+ props:
29
+ items:
30
+ - id: "home"
31
+ label: "$t:nav.home"
32
+ icon: "home"
33
+ destination: "screens/home_feed"
34
+ - id: "discover"
35
+ label: "$t:nav.discover"
36
+ icon: "discover"
37
+ destination: "screens/discover"
38
+ - id: "notifications"
39
+ label: "$t:nav.notifications"
40
+ icon: "notifications"
41
+ destination: "screens/notifications"
42
+ badge:
43
+ count: "api.notifications.unreadCount"
44
+ - id: "profile"
45
+ label: "$t:nav.profile"
46
+ icon: "profile"
47
+ destination: "screens/profile_self"
48
+ adaptive:
49
+ compact: { variant: tab_bar }
50
+ expanded: { variant: sidebar }
51
+
52
+ layout:
53
+ type: scroll_vertical
54
+ sections:
55
+ - id: stories_bar
56
+ contract: collection
57
+ variant: horizontal_scroll
58
+ props:
59
+ data: "stories"
60
+ item_contract: data_display
61
+ item_props_map:
62
+ title: "item.author.display_name"
63
+ media: "item.preview_url"
64
+ action:
65
+ type: navigate
66
+ destination: "screens/post_detail"
67
+ params: { post_id: "{item.id}" }
68
+
69
+ - id: filter_chips
70
+ contract: collection
71
+ variant: chip_row
72
+ props:
73
+ data: "state.active_filter"
74
+ item_contract: action_trigger
75
+ item_props_map:
76
+ label: "item.label"
77
+ options:
78
+ - { value: "all", label: "$t:home.filter_all" }
79
+ - { value: "following", label: "$t:home.filter_following" }
80
+ - { value: "popular", label: "$t:home.filter_popular" }
81
+
82
+ - id: post_list
83
+ contract: collection
84
+ variant: list
85
+ props:
86
+ data: "feed"
87
+ item_contract: data_display
88
+ item_props_map:
89
+ title: "item.author.display_name"
90
+ subtitle: "@{item.author.handle}"
91
+ body: "item.body"
92
+ media: "item.media_url"
93
+ leading: "item.author.avatar_url"
94
+ metadata:
95
+ like_count: "{item.like_count | format:number}"
96
+ comment_count: "{item.comment_count | format:number}"
97
+ timestamp: "{item.published_at | format:date_relative}"
98
+ item_actions:
99
+ - id: like
100
+ icon: "like"
101
+ icon_active: "like_fill"
102
+ action: { type: api_call, endpoint: "api.posts.toggleLike", params: { id: "{item.id}" } }
103
+ - id: comment
104
+ icon: "comment"
105
+ action: { type: navigate, destination: "screens/post_detail", params: { post_id: "{item.id}" } }
106
+ - id: share
107
+ icon: "share"
108
+ action: { type: share, content: "{item.body}" }
109
+ - id: save
110
+ icon: "bookmark"
111
+ icon_active: "bookmark_fill"
112
+ action: { type: api_call, endpoint: "api.posts.save", params: { id: "{item.id}" } }
113
+ action:
114
+ type: navigate
115
+ destination: "screens/post_detail"
116
+ params: { post_id: "{item.id}" }
117
+ pagination:
118
+ type: infinite_scroll
119
+ cursor_field: "cursor"
120
+
121
+ - id: create_fab
122
+ contract: action_trigger
123
+ variant: fab
124
+ position: "floating"
125
+ props:
126
+ icon: "create_post"
127
+ label: "$t:nav.create"
128
+ aria_label: "$t:nav.create"
129
+ action:
130
+ type: navigate
131
+ destination: "flows/create_post"
132
+ adaptive:
133
+ compact:
134
+ position: "bottom-right"
135
+ inset: { bottom: 80, right: 16 }
136
+ expanded:
137
+ position: "bottom-right"
138
+ inset: { bottom: 32, right: 32 }
@@ -0,0 +1,43 @@
1
+ messages_inbox:
2
+ semantic: "Conversations list with search and unread indicators"
3
+ status: draft
4
+
5
+ data:
6
+ conversations:
7
+ source: "api.messages.list"
8
+ params:
9
+ search: "state.search_query"
10
+ loading: { skeleton: true, count: 6 }
11
+ empty: { message: "$t:messages.empty_inbox" }
12
+
13
+ state:
14
+ search_query: { type: string, default: "" }
15
+
16
+ layout:
17
+ type: scroll_vertical
18
+ sections:
19
+ - id: search
20
+ contract: input_field
21
+ input_type: text
22
+ props:
23
+ label: "$t:messages.search_placeholder"
24
+ value: "state.search_query"
25
+ icon: "search"
26
+
27
+ - id: conversation_list
28
+ contract: collection
29
+ variant: list
30
+ props:
31
+ data: "conversations"
32
+ item_contract: data_display
33
+ item_props_map:
34
+ title: "item.participant.display_name"
35
+ subtitle: "item.last_message.body"
36
+ leading: "item.participant.avatar_url"
37
+ metadata:
38
+ timestamp: "{item.last_message.created_at | format:date_relative}"
39
+ unread_count: "{item.unread_count}"
40
+ action:
41
+ type: navigate
42
+ destination: "screens/chat_detail"
43
+ params: { conversation_id: "{item.id}" }
@@ -0,0 +1,29 @@
1
+ notifications:
2
+ semantic: "Notification list with mark-as-read"
3
+ status: draft
4
+
5
+ data:
6
+ notifications:
7
+ source: "api.notifications.list"
8
+ loading: { skeleton: true, count: 8 }
9
+ empty: { message: "$t:notifications.empty" }
10
+
11
+ layout:
12
+ type: scroll_vertical
13
+ sections:
14
+ - id: notification_list
15
+ contract: collection
16
+ variant: list
17
+ props:
18
+ data: "notifications"
19
+ item_contract: data_display
20
+ item_props_map:
21
+ title: "item.actor.display_name"
22
+ subtitle: "item.message"
23
+ leading: "item.actor.avatar_url"
24
+ metadata:
25
+ timestamp: "{item.created_at | format:date_relative}"
26
+ action:
27
+ type: api_call
28
+ endpoint: "api.notifications.markRead"
29
+ params: { id: "{item.id}" }
@@ -0,0 +1,86 @@
1
+ post_detail:
2
+ semantic: "Full post view with comments thread and interaction actions"
3
+ status: draft
4
+
5
+ params:
6
+ post_id: { type: string, required: true }
7
+
8
+ data:
9
+ post:
10
+ source: "api.posts.getById"
11
+ params: { id: "params.post_id" }
12
+ loading: { skeleton: true }
13
+ comments:
14
+ source: "api.posts.comments"
15
+ params: { id: "params.post_id" }
16
+ loading: { skeleton: true, count: 3 }
17
+ empty: { message: "$t:post.no_comments" }
18
+
19
+ state:
20
+ comment_text: { type: string, default: "" }
21
+
22
+ layout:
23
+ type: scroll_vertical
24
+ sections:
25
+ - id: post_content
26
+ contract: data_display
27
+ variant: hero
28
+ props:
29
+ title: "{post.author.display_name}"
30
+ subtitle: "@{post.author.handle}"
31
+ body: "{post.body}"
32
+ media: "{post.media_url}"
33
+ leading: "{post.author.avatar_url}"
34
+ metadata:
35
+ like_count: "{post.like_count | format:number}"
36
+ comment_count: "{post.comment_count | format:number}"
37
+ timestamp: "{post.published_at | format:date}"
38
+ action:
39
+ type: navigate
40
+ destination: "screens/profile_user"
41
+ params: { user_id: "{post.author_id}" }
42
+
43
+ - id: post_actions
44
+ contract: action_trigger
45
+ variant: secondary
46
+ props:
47
+ label: "$t:post.like_action"
48
+ icon: "like"
49
+ action:
50
+ type: api_call
51
+ endpoint: "api.posts.toggleLike"
52
+ params: { id: "params.post_id" }
53
+
54
+ - id: comments_list
55
+ header: "$t:post.comments_header"
56
+ contract: collection
57
+ variant: list
58
+ props:
59
+ data: "comments"
60
+ item_contract: data_display
61
+ item_props_map:
62
+ title: "item.author.display_name"
63
+ body: "item.body"
64
+ leading: "item.author.avatar_url"
65
+ metadata:
66
+ timestamp: "{item.created_at | format:date_relative}"
67
+ action:
68
+ type: navigate
69
+ destination: "screens/profile_user"
70
+ params: { user_id: "{item.author_id}" }
71
+
72
+ - id: comment_input
73
+ contract: input_field
74
+ input_type: text
75
+ props:
76
+ label: "$t:post.comment_placeholder"
77
+ value: "state.comment_text"
78
+ multiline: true
79
+ trailing_action:
80
+ icon: "send"
81
+ action:
82
+ type: sequence
83
+ actions:
84
+ - { type: api_call, endpoint: "api.posts.comments", method: POST, body: { body: "state.comment_text", post_id: "params.post_id" } }
85
+ - { type: set_state, key: "comment_text", value: "" }
86
+ - { type: feedback, variant: toast, message: "$t:post.comment_sent" }
@@ -0,0 +1,53 @@
1
+ profile_self:
2
+ semantic: "Current user's own profile with posts, stats, and edit action"
3
+ status: draft
4
+
5
+ data:
6
+ profile:
7
+ source: "api.profiles.me"
8
+ loading: { skeleton: true }
9
+ posts:
10
+ source: "api.profiles.myPosts"
11
+ loading: { skeleton: true, count: 3 }
12
+ empty: { message: "$t:profile.no_posts_self" }
13
+
14
+ layout:
15
+ type: scroll_vertical
16
+ sections:
17
+ - id: profile_header
18
+ contract: data_display
19
+ variant: hero
20
+ props:
21
+ title: "{profile.display_name}"
22
+ subtitle: "@{profile.handle}"
23
+ body: "{profile.bio}"
24
+ leading: "{profile.avatar_url}"
25
+ trailing:
26
+ contract: action_trigger
27
+ variant: secondary
28
+ props:
29
+ label: "$t:profile.edit_button"
30
+ icon: "edit"
31
+ action:
32
+ type: navigate
33
+ destination: "screens/edit_profile"
34
+
35
+ - id: user_posts
36
+ header: "$t:profile.posts_header"
37
+ contract: collection
38
+ variant: list
39
+ props:
40
+ data: "posts"
41
+ item_contract: data_display
42
+ item_props_map:
43
+ title: "item.author.display_name"
44
+ body: "item.body"
45
+ media: "item.media_url"
46
+ metadata:
47
+ like_count: "{item.like_count | format:number}"
48
+ comment_count: "{item.comment_count | format:number}"
49
+ timestamp: "{item.published_at | format:date_relative}"
50
+ action:
51
+ type: navigate
52
+ destination: "screens/post_detail"
53
+ params: { post_id: "{item.id}" }
@@ -0,0 +1,60 @@
1
+ profile_user:
2
+ semantic: "Another user's profile with their posts and follow action"
3
+ status: draft
4
+
5
+ params:
6
+ user_id: { type: string, required: true }
7
+
8
+ data:
9
+ profile:
10
+ source: "api.profiles.getById"
11
+ params: { id: "params.user_id" }
12
+ loading: { skeleton: true }
13
+ posts:
14
+ source: "api.profiles.posts"
15
+ params: { id: "params.user_id" }
16
+ loading: { skeleton: true, count: 3 }
17
+ empty: { message: "$t:profile.no_posts_user" }
18
+
19
+ layout:
20
+ type: scroll_vertical
21
+ sections:
22
+ - id: profile_header
23
+ contract: data_display
24
+ variant: hero
25
+ props:
26
+ title: "{profile.display_name}"
27
+ subtitle: "@{profile.handle}"
28
+ body: "{profile.bio}"
29
+ leading: "{profile.avatar_url}"
30
+ trailing:
31
+ contract: action_trigger
32
+ variant: primary
33
+ props:
34
+ label: "$t:profile.follow_button"
35
+ action:
36
+ type: api_call
37
+ endpoint: "api.profiles.follow"
38
+ params: { id: "params.user_id" }
39
+
40
+ - id: user_posts
41
+ header: "$t:profile.posts_header"
42
+ contract: collection
43
+ variant: list
44
+ props:
45
+ data: "posts"
46
+ item_contract: data_display
47
+ item_props_map:
48
+ title: "item.author.display_name"
49
+ subtitle: "@{item.author.handle}"
50
+ body: "item.body"
51
+ media: "item.media_url"
52
+ leading: "item.author.avatar_url"
53
+ metadata:
54
+ like_count: "{item.like_count | format:number}"
55
+ comment_count: "{item.comment_count | format:number}"
56
+ timestamp: "{item.published_at | format:date_relative}"
57
+ action:
58
+ type: navigate
59
+ destination: "screens/post_detail"
60
+ params: { post_id: "{item.id}" }
@@ -0,0 +1,62 @@
1
+ search_results:
2
+ semantic: "Search results with tabbed views for posts, people, and tags"
3
+ status: draft
4
+
5
+ params:
6
+ query: { type: string, required: true }
7
+ tab: { type: string, default: "posts" }
8
+
9
+ data:
10
+ results:
11
+ source: "api.discover.search"
12
+ params:
13
+ query: "params.query"
14
+ tab: "state.active_tab"
15
+ loading: { skeleton: true, count: 5 }
16
+ empty: { message: "$t:search.no_results" }
17
+
18
+ state:
19
+ active_tab:
20
+ type: enum
21
+ values: [posts, people, tags]
22
+ default: "params.tab"
23
+
24
+ layout:
25
+ type: scroll_vertical
26
+ sections:
27
+ - id: search_bar
28
+ contract: input_field
29
+ input_type: text
30
+ props:
31
+ label: "$t:search.placeholder"
32
+ value: "params.query"
33
+ icon: "search"
34
+
35
+ - id: tab_bar
36
+ contract: collection
37
+ variant: chip_row
38
+ props:
39
+ data: "state.active_tab"
40
+ item_contract: action_trigger
41
+ item_props_map:
42
+ label: "item.label"
43
+ options:
44
+ - { value: "posts", label: "$t:search.tab_posts" }
45
+ - { value: "people", label: "$t:search.tab_people" }
46
+ - { value: "tags", label: "$t:search.tab_tags" }
47
+
48
+ - id: results_list
49
+ contract: collection
50
+ variant: list
51
+ props:
52
+ data: "results"
53
+ item_contract: data_display
54
+ item_props_map:
55
+ title: "item.title"
56
+ subtitle: "item.subtitle"
57
+ body: "item.body"
58
+ leading: "item.avatar_url"
59
+ action:
60
+ type: navigate
61
+ destination: "screens/post_detail"
62
+ params: { post_id: "{item.id}" }