kasy-cli 1.21.9 → 1.22.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 (267) hide show
  1. package/lib/commands/add.js +93 -80
  2. package/lib/commands/configure.js +100 -32
  3. package/lib/commands/doctor.js +28 -2
  4. package/lib/commands/new.js +80 -37
  5. package/lib/commands/notifications.js +1 -1
  6. package/lib/commands/remove.js +43 -15
  7. package/lib/commands/run.js +2 -2
  8. package/lib/commands/update.js +2 -2
  9. package/lib/scaffold/CHANGELOG.json +14 -0
  10. package/lib/scaffold/backends/api/generator.js +14 -14
  11. package/lib/scaffold/backends/api/patch/README.md +83 -0
  12. package/lib/scaffold/backends/api/patch/lib/core/data/api/storage_api.dart +1 -1
  13. package/lib/scaffold/backends/api/patch/lib/core/data/entities/user_entity.dart +5 -0
  14. package/lib/scaffold/backends/api/patch/lib/{environnements.dart → environments.dart} +3 -11
  15. package/lib/scaffold/backends/api/patch/lib/features/ai_chat/api/ai_chat_api.dart +108 -0
  16. package/lib/scaffold/backends/api/patch/lib/features/ai_chat/api/ai_chat_conversation_entity.dart +51 -0
  17. package/lib/scaffold/backends/api/patch/lib/features/{llm_chat/api/llm_chat_message_entity.dart → ai_chat/api/ai_chat_message_entity.dart} +5 -5
  18. package/lib/scaffold/backends/api/patch/lib/features/{llm_chat/providers/llm_chat_notifier.dart → ai_chat/providers/ai_chat_notifier.dart} +71 -38
  19. package/lib/scaffold/backends/api/patch/lib/features/authentication/api/authentication_api.dart +2 -2
  20. package/lib/scaffold/backends/api/patch/lib/features/feedbacks/api/feature_request_api.dart +54 -0
  21. package/lib/scaffold/backends/api/patch/lib/features/onboarding/models/user_info.dart +16 -16
  22. package/lib/scaffold/backends/api/patch/lib/features/onboarding/ui/components/onboarding_att_setup.dart +4 -3
  23. package/lib/scaffold/backends/api/patch/lib/features/onboarding/ui/widgets/onboarding_radio_question.dart +38 -28
  24. package/lib/scaffold/backends/api/patch/lib/features/settings/ui/components/admin/admin_users_api.dart +100 -0
  25. package/lib/scaffold/backends/api/patch/lib/features/{subscription → subscriptions}/api/entities/subscription_entity.dart +13 -0
  26. package/lib/scaffold/backends/api/patch/lib/features/subscriptions/api/stripe_backend_api.dart +60 -0
  27. package/lib/scaffold/backends/api/patch/lib/features/{subscription → subscriptions}/api/subscription_api.dart +1 -1
  28. package/lib/scaffold/backends/api/pubspec.yaml.tpl +4 -5
  29. package/lib/scaffold/backends/firebase/deploy.js +87 -13
  30. package/lib/scaffold/backends/firebase/generator.js +5 -5
  31. package/lib/scaffold/backends/firebase/tokens.js +4 -4
  32. package/lib/scaffold/backends/supabase/deploy.js +63 -11
  33. package/lib/scaffold/backends/supabase/edge-functions/admin-list-users/index.ts +149 -0
  34. package/lib/scaffold/backends/supabase/edge-functions/{llm-chat → ai-chat}/index.ts +19 -19
  35. package/lib/scaffold/backends/supabase/edge-functions/revenuecat-webhook/index.ts +2 -0
  36. package/lib/scaffold/backends/supabase/edge-functions/stripe-create-checkout-session/index.ts +123 -0
  37. package/lib/scaffold/backends/supabase/edge-functions/stripe-create-portal-session/index.ts +97 -0
  38. package/lib/scaffold/backends/supabase/edge-functions/stripe-list-prices/index.ts +83 -0
  39. package/lib/scaffold/backends/supabase/edge-functions/stripe-webhook/index.ts +138 -0
  40. package/lib/scaffold/backends/supabase/generator.js +17 -17
  41. package/lib/scaffold/backends/supabase/migrations/20240101000009_ai_messages.sql +50 -0
  42. package/lib/scaffold/backends/supabase/migrations/20240101000012_stripe_customers.sql +36 -0
  43. package/lib/scaffold/backends/supabase/migrations/20240101000013_admin_role.sql +62 -0
  44. package/lib/scaffold/backends/supabase/patch/lib/core/data/entities/user_entity.dart +4 -0
  45. package/lib/scaffold/backends/supabase/patch/lib/{environnements.dart → environments.dart} +3 -13
  46. package/lib/scaffold/backends/supabase/patch/lib/features/ai_chat/api/ai_chat_api.dart +95 -0
  47. package/lib/scaffold/backends/supabase/patch/lib/features/ai_chat/api/ai_chat_conversation_entity.dart +52 -0
  48. package/lib/scaffold/backends/supabase/patch/lib/features/{llm_chat/api/llm_chat_message_entity.dart → ai_chat/api/ai_chat_message_entity.dart} +6 -6
  49. package/lib/scaffold/backends/supabase/patch/lib/features/{llm_chat/providers/llm_chat_notifier.dart → ai_chat/providers/ai_chat_notifier.dart} +63 -35
  50. package/lib/scaffold/backends/supabase/patch/lib/features/authentication/api/authentication_api.dart +1 -1
  51. package/lib/scaffold/backends/supabase/patch/lib/features/feedbacks/api/feature_request_api.dart +46 -0
  52. package/lib/scaffold/backends/supabase/patch/lib/features/onboarding/models/user_info.dart +16 -16
  53. package/lib/scaffold/backends/supabase/patch/lib/features/onboarding/ui/components/onboarding_att_setup.dart +4 -3
  54. package/lib/scaffold/backends/supabase/patch/lib/features/onboarding/ui/widgets/onboarding_radio_question.dart +38 -28
  55. package/lib/scaffold/backends/supabase/patch/lib/features/settings/ui/components/admin/admin_users_api.dart +93 -0
  56. package/lib/scaffold/backends/supabase/patch/lib/features/{subscription → subscriptions}/api/entities/subscription_entity.dart +13 -0
  57. package/lib/scaffold/backends/supabase/patch/lib/features/subscriptions/api/stripe_backend_api.dart +52 -0
  58. package/lib/scaffold/backends/supabase/patch/lib/features/{subscription → subscriptions}/api/subscription_api.dart +1 -1
  59. package/lib/scaffold/backends/supabase/pubspec.yaml.tpl +4 -5
  60. package/lib/scaffold/backends/supabase/tokens.js +3 -3
  61. package/lib/scaffold/catalog.js +9 -11
  62. package/lib/scaffold/generate.js +45 -31
  63. package/lib/scaffold/shared/generator-utils.js +188 -81
  64. package/lib/scaffold/shared/sort-imports.js +191 -0
  65. package/lib/scaffold/shared/template-strings.js +3 -3
  66. package/lib/utils/checks.js +2 -2
  67. package/lib/utils/i18n/messages-en.js +50 -35
  68. package/lib/utils/i18n/messages-es.js +50 -35
  69. package/lib/utils/i18n/messages-pt.js +52 -37
  70. package/lib/utils/updates.js +15 -15
  71. package/package.json +1 -1
  72. package/templates/firebase/.env.example +2 -2
  73. package/templates/firebase/android/app/src/main/res/drawable/background.png +0 -0
  74. package/templates/firebase/android/app/src/main/res/drawable-night/background.png +0 -0
  75. package/templates/firebase/android/app/src/main/res/drawable-night-v21/background.png +0 -0
  76. package/templates/firebase/android/app/src/main/res/drawable-v21/background.png +0 -0
  77. package/templates/firebase/android/app/src/main/res/values-night-v31/styles.xml +1 -1
  78. package/templates/firebase/android/app/src/main/res/values-v31/styles.xml +1 -1
  79. package/templates/firebase/assets/images/logo_wordmark_dark.png +0 -0
  80. package/templates/firebase/assets/images/logo_wordmark_light.png +0 -0
  81. package/templates/firebase/docs/revenuecat-setup.es.md +1 -1
  82. package/templates/firebase/docs/revenuecat-setup.pt.md +1 -1
  83. package/templates/firebase/firestore.rules +24 -5
  84. package/templates/firebase/functions/package-lock.json +22 -1
  85. package/templates/firebase/functions/package.json +2 -1
  86. package/templates/firebase/functions/src/admin/functions.ts +113 -0
  87. package/templates/firebase/functions/src/{llm_chat → ai_chat}/index.ts +16 -16
  88. package/templates/firebase/functions/src/index.ts +8 -2
  89. package/templates/firebase/functions/src/notifications/device_triggers.ts +2 -2
  90. package/templates/firebase/functions/src/notifications/triggers.ts +3 -3
  91. package/templates/firebase/functions/src/subscriptions/models/subscription_status.ts +2 -0
  92. package/templates/firebase/functions/src/subscriptions/stripe_functions.ts +222 -0
  93. package/templates/firebase/functions/src/subscriptions/subscriptions_functions.ts +2 -2
  94. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png +0 -0
  95. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png +0 -0
  96. package/templates/firebase/lib/components/components.dart +4 -1
  97. package/templates/firebase/lib/components/kasy_app_bar.dart +22 -7
  98. package/templates/firebase/lib/components/kasy_avatar.dart +7 -6
  99. package/templates/firebase/lib/components/kasy_button.dart +23 -99
  100. package/templates/firebase/lib/components/kasy_dialog.dart +11 -11
  101. package/templates/firebase/lib/components/kasy_image_viewer.dart +84 -0
  102. package/templates/firebase/lib/components/{kasy_sidebar_pro.dart → kasy_sidebar.dart} +692 -425
  103. package/templates/firebase/lib/components/kasy_status_tag.dart +91 -0
  104. package/templates/firebase/lib/components/kasy_text_area.dart +1 -3
  105. package/templates/firebase/lib/components/kasy_text_field.dart +5 -6
  106. package/templates/firebase/lib/components/kasy_text_field_otp.dart +1 -3
  107. package/templates/firebase/lib/components/kasy_toast.dart +2 -2
  108. package/templates/firebase/lib/components/kasy_web_header.dart +209 -0
  109. package/templates/firebase/lib/core/ads/ads_provider.dart +1 -1
  110. package/templates/firebase/lib/core/bottom_menu/bottom_menu.dart +57 -4
  111. package/templates/firebase/lib/core/bottom_menu/bottom_router.dart +19 -91
  112. package/templates/firebase/lib/core/bottom_menu/kasy_bottom_bar_factory.dart +196 -96
  113. package/templates/firebase/lib/core/bottom_menu/web_content_wrapper.dart +41 -0
  114. package/templates/firebase/lib/core/config/app_env.dart +5 -11
  115. package/templates/firebase/lib/core/config/features.dart +5 -4
  116. package/templates/firebase/lib/core/data/api/analytics_api.dart +1 -1
  117. package/templates/firebase/lib/core/data/api/http_client.dart +1 -1
  118. package/templates/firebase/lib/core/data/entities/user_entity.dart +3 -0
  119. package/templates/firebase/lib/core/data/models/entitlement.dart +35 -0
  120. package/templates/firebase/lib/core/data/models/subscription.dart +13 -186
  121. package/templates/firebase/lib/core/data/models/user.dart +11 -0
  122. package/templates/firebase/lib/core/data/repositories/user_repository.dart +1 -1
  123. package/templates/firebase/lib/core/home_widgets/home_widget_background_task.dart +1 -1
  124. package/templates/firebase/lib/core/home_widgets/home_widget_mywidget_service.dart +1 -1
  125. package/templates/firebase/lib/core/icons/kasy_icons.dart +31 -1
  126. package/templates/firebase/lib/core/rating/api/rating_api.dart +2 -2
  127. package/templates/firebase/lib/core/states/logout_action.dart +25 -0
  128. package/templates/firebase/lib/core/states/user_state_notifier.dart +3 -3
  129. package/templates/firebase/lib/core/theme/colors.dart +488 -188
  130. package/templates/firebase/lib/core/theme/radius.dart +22 -11
  131. package/templates/firebase/lib/core/theme/shadows.dart +66 -0
  132. package/templates/firebase/lib/core/theme/texts.dart +75 -41
  133. package/templates/firebase/lib/core/theme/universal_theme.dart +9 -4
  134. package/templates/firebase/lib/core/web_device_preview/web_device_preview.dart +5 -4
  135. package/templates/firebase/lib/core/web_viewport_scale.dart +52 -0
  136. package/templates/firebase/lib/core/widgets/kasy_brand_badge.dart +118 -0
  137. package/templates/firebase/lib/core/widgets/kasy_brand_logo.dart +40 -0
  138. package/templates/firebase/lib/core/widgets/kasy_focus_ring.dart +125 -0
  139. package/templates/firebase/lib/core/widgets/kasy_hover.dart +33 -13
  140. package/templates/firebase/lib/core/widgets/kasy_pressable_depth.dart +18 -13
  141. package/templates/firebase/lib/{environnements.dart → environments.dart} +3 -14
  142. package/templates/firebase/lib/features/ai_chat/ai_chat_page.dart +159 -0
  143. package/templates/firebase/lib/features/ai_chat/api/ai_chat_api.dart +107 -0
  144. package/templates/firebase/lib/features/ai_chat/api/ai_chat_conversation_entity.dart +64 -0
  145. package/templates/firebase/lib/features/{llm_chat/api/llm_chat_message_entity.dart → ai_chat/api/ai_chat_message_entity.dart} +6 -6
  146. package/templates/firebase/lib/features/{llm_chat/providers/llm_chat_notifier.dart → ai_chat/providers/ai_chat_notifier.dart} +73 -38
  147. package/templates/firebase/lib/features/ai_chat/providers/ai_conversations_notifier.dart +103 -0
  148. package/templates/firebase/lib/features/{llm_chat/ui/widgets/llm_chat_avatars.dart → ai_chat/ui/widgets/ai_chat_avatars.dart} +13 -13
  149. package/templates/firebase/lib/features/{llm_chat/ui/widgets/llm_chat_composer.dart → ai_chat/ui/widgets/ai_chat_composer.dart} +10 -10
  150. package/templates/firebase/lib/features/{llm_chat/llm_chat_page.dart → ai_chat/ui/widgets/ai_chat_conversation_view.dart} +80 -67
  151. package/templates/firebase/lib/features/ai_chat/ui/widgets/ai_conversation_list.dart +285 -0
  152. package/templates/firebase/lib/features/ai_chat/ui/widgets/ai_conversation_tile.dart +163 -0
  153. package/templates/firebase/lib/features/authentication/api/authentication_api.dart +52 -13
  154. package/templates/firebase/lib/features/authentication/api/popup_dismiss_watcher.dart +12 -0
  155. package/templates/firebase/lib/features/authentication/api/popup_dismiss_watcher_web.dart +35 -0
  156. package/templates/firebase/lib/features/authentication/ui/recover_password_page.dart +108 -68
  157. package/templates/firebase/lib/features/authentication/ui/signin_page.dart +38 -51
  158. package/templates/firebase/lib/features/authentication/ui/signup_page.dart +38 -51
  159. package/templates/firebase/lib/features/authentication/ui/widgets/auth_card_scaffold.dart +118 -0
  160. package/templates/firebase/lib/features/authentication/ui/widgets/recover_password_result.dart +61 -44
  161. package/templates/firebase/lib/features/feedbacks/api/feature_request_api.dart +32 -0
  162. package/templates/firebase/lib/features/feedbacks/models/feedback_state.dart +5 -5
  163. package/templates/firebase/lib/features/feedbacks/providers/feedback_page_notifier.dart +2 -2
  164. package/templates/firebase/lib/features/home/design_system_page.dart +808 -170
  165. package/templates/firebase/lib/features/home/home_components_page.dart +6 -3
  166. package/templates/firebase/lib/features/home/home_components_preview_page.dart +6 -6
  167. package/templates/firebase/lib/features/home/home_components_preview_registry.dart +325 -186
  168. package/templates/firebase/lib/features/home/home_feed.dart +289 -0
  169. package/templates/firebase/lib/features/home/home_image_grid.dart +355 -0
  170. package/templates/firebase/lib/features/home/home_page.dart +11 -250
  171. package/templates/firebase/lib/features/{local_reminder → local_reminders}/providers/reminder_notifier.dart +1 -1
  172. package/templates/firebase/lib/features/{local_reminder → local_reminders}/ui/reminder_page.dart +2 -2
  173. package/templates/firebase/lib/features/notifications/shared/att_permission.dart +1 -1
  174. package/templates/firebase/lib/features/notifications/ui/request_notification_permission.dart +25 -61
  175. package/templates/firebase/lib/features/notifications/ui/widgets/permission_request_view.dart +117 -0
  176. package/templates/firebase/lib/features/onboarding/models/user_info.dart +16 -16
  177. package/templates/firebase/lib/features/onboarding/ui/components/onboarding_att_setup.dart +4 -3
  178. package/templates/firebase/lib/features/onboarding/ui/components/onboarding_features.dart +7 -9
  179. package/templates/firebase/lib/features/onboarding/ui/components/onboarding_loader.dart +71 -48
  180. package/templates/firebase/lib/features/onboarding/ui/components/onboarding_notifications_setup.dart +3 -2
  181. package/templates/firebase/lib/features/onboarding/ui/components/onboarding_questions.dart +5 -5
  182. package/templates/firebase/lib/features/onboarding/ui/onboarding_page.dart +4 -4
  183. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_background.dart +4 -2
  184. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_feature.dart +39 -121
  185. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_illustration_scaffold.dart +105 -70
  186. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_module_mockups.dart +639 -0
  187. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_progress.dart +62 -50
  188. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_radio_question.dart +38 -28
  189. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_step_header.dart +75 -0
  190. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_sticky_footer.dart +16 -5
  191. package/templates/firebase/lib/features/onboarding/ui/widgets/selectable_row_tile.dart +26 -22
  192. package/templates/firebase/lib/features/settings/settings_page.dart +601 -90
  193. package/templates/firebase/lib/features/settings/ui/components/admin/admin_page.dart +1193 -0
  194. package/templates/firebase/lib/features/settings/ui/components/admin/admin_paywalls.dart +1 -1
  195. package/templates/firebase/lib/features/settings/ui/components/admin/admin_routes.dart +2 -3
  196. package/templates/firebase/lib/features/settings/ui/components/admin/admin_users_api.dart +86 -0
  197. package/templates/firebase/lib/features/settings/ui/components/admin/admin_users_tab.dart +1215 -0
  198. package/templates/firebase/lib/features/settings/ui/components/admin/send_push_notification_page.dart +236 -0
  199. package/templates/firebase/lib/features/settings/ui/components/avatar_component.dart +3 -3
  200. package/templates/firebase/lib/features/settings/ui/widgets/kasy_user_avatar.dart +77 -0
  201. package/templates/firebase/lib/features/settings/ui/widgets/settings_tile.dart +1 -0
  202. package/templates/firebase/lib/features/{subscription → subscriptions}/api/entities/subscription_entity.dart +17 -0
  203. package/templates/firebase/lib/features/{subscription → subscriptions}/api/inapp_subscription_api.dart +67 -46
  204. package/templates/firebase/lib/features/subscriptions/api/revenuecat_product.dart +189 -0
  205. package/templates/firebase/lib/features/subscriptions/api/stripe_backend_api.dart +55 -0
  206. package/templates/firebase/lib/features/subscriptions/api/stripe_payment_api.dart +82 -0
  207. package/templates/firebase/lib/features/subscriptions/api/stripe_product.dart +178 -0
  208. package/templates/firebase/lib/features/{subscription → subscriptions}/api/subscription_api.dart +1 -1
  209. package/templates/firebase/lib/features/subscriptions/api/subscription_payment_api.dart +53 -0
  210. package/templates/firebase/lib/features/subscriptions/api/subscription_payment_api_provider.dart +21 -0
  211. package/templates/firebase/lib/features/{subscription → subscriptions}/providers/premium_page_provider.dart +9 -6
  212. package/templates/firebase/lib/features/{subscription → subscriptions}/repositories/subscription_repository.dart +26 -30
  213. package/{lib/scaffold/backends/supabase/patch/lib/features/subscription → templates/firebase/lib/features/subscriptions}/shared/maybeshow_premium.dart +0 -2
  214. package/templates/firebase/lib/features/subscriptions/shared/subscription_management.dart +45 -0
  215. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/component/active_premium_content.dart +28 -4
  216. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/component/paywall_minimal.dart +7 -7
  217. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/component/paywall_row.dart +8 -8
  218. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/component/paywall_with_switch.dart +7 -7
  219. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/component/premium_content.dart +7 -7
  220. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/component/premium_page_factory.dart +5 -5
  221. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/premium_page.dart +5 -5
  222. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/comparison_table.dart +1 -1
  223. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/paywall_empty_state.dart +4 -4
  224. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/premium_bottom_menu.dart +3 -4
  225. package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/selectable_col.dart +1 -1
  226. package/templates/firebase/lib/i18n/en.i18n.json +171 -46
  227. package/templates/firebase/lib/i18n/es.i18n.json +175 -50
  228. package/templates/firebase/lib/i18n/pt.i18n.json +166 -41
  229. package/templates/firebase/lib/main.dart +6 -3
  230. package/templates/firebase/lib/router.dart +15 -23
  231. package/templates/firebase/pubspec.yaml +4 -5
  232. package/templates/firebase/test/core/data/repositories/user_repository_test.dart +3 -3
  233. package/templates/firebase/test/core/states/user_state_notifier_test.dart +4 -4
  234. package/templates/firebase/test/core/widgets/focus_ring_shape_test.dart +55 -0
  235. package/templates/firebase/test/features/{subscription → subscriptions}/api/fake_inapp_subscription_api.dart +11 -4
  236. package/templates/firebase/test/features/{subscription → subscriptions}/api/fake_revenuecat_product.dart +1 -0
  237. package/templates/firebase/test/features/{subscription → subscriptions}/api/fake_subscription_api.dart +2 -2
  238. package/templates/firebase/test/features/{subscription → subscriptions}/subscription_page_test.dart +4 -4
  239. package/templates/firebase/test/test_utils.dart +6 -6
  240. package/templates/firebase/web/index.html +5 -2
  241. package/lib/scaffold/backends/api/patch/lib/features/llm_chat/api/llm_chat_api.dart +0 -58
  242. package/lib/scaffold/backends/api/patch/lib/features/subscription/shared/maybeshow_premium.dart +0 -86
  243. package/lib/scaffold/backends/supabase/migrations/20240101000009_llm_messages.sql +0 -22
  244. package/lib/scaffold/backends/supabase/patch/lib/features/llm_chat/api/llm_chat_api.dart +0 -47
  245. package/templates/firebase/assets/images/onboarding/authentication-login-template.jpg +0 -0
  246. package/templates/firebase/assets/images/onboarding/img2.jpg +0 -0
  247. package/templates/firebase/assets/images/onboarding/img3.jpg +0 -0
  248. package/templates/firebase/assets/images/onboarding/notifications.png +0 -0
  249. package/templates/firebase/assets/images/onboarding/purchase.png +0 -0
  250. package/templates/firebase/lib/core/sidebar/kasy_sidebar.dart +0 -2021
  251. package/templates/firebase/lib/features/authentication/ui/widgets/auth_brand.dart +0 -35
  252. package/templates/firebase/lib/features/home/home_features_page.dart +0 -207
  253. package/templates/firebase/lib/features/llm_chat/api/llm_chat_api.dart +0 -50
  254. package/templates/firebase/lib/features/settings/ui/components/admin/admin_bottom_sheet.dart +0 -316
  255. package/templates/firebase/lib/features/subscription/shared/maybeshow_premium.dart +0 -85
  256. /package/templates/firebase/lib/features/{local_reminder → local_reminders}/repositories/reminder_preferences.dart +0 -0
  257. /package/templates/firebase/lib/features/{subscription → subscriptions}/providers/models/premium_state.dart +0 -0
  258. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/feature_line.dart +0 -0
  259. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/premium_background.dart +0 -0
  260. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/premium_background_gradient.dart +0 -0
  261. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/premium_banner.dart +0 -0
  262. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/premium_card.dart +0 -0
  263. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/premium_close_button.dart +0 -0
  264. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/premium_feature.dart +0 -0
  265. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/selectable_row.dart +0 -0
  266. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/trial_switcher.dart +0 -0
  267. /package/templates/firebase/lib/features/{subscription → subscriptions}/ui/widgets/unsubscribe_feedback_popup.dart +0 -0
@@ -1,19 +1,17 @@
1
- import 'package:bart/bart/bart_model.dart';
2
1
  import 'package:flutter/foundation.dart' show kIsWeb;
3
2
  import 'package:flutter/material.dart';
4
3
  import 'package:flutter/services.dart';
5
4
  import 'package:kasy_kit/components/components.dart';
6
- import 'package:kasy_kit/components/kasy_sidebar_pro.dart';
7
5
  import 'package:kasy_kit/core/haptics/kasy_haptics.dart';
8
6
  import 'package:kasy_kit/core/theme/theme.dart';
9
7
  import 'package:kasy_kit/core/widgets/kasy_hover.dart';
10
8
  import 'package:kasy_kit/features/home/home_components_preview_page.dart';
11
9
 
12
- /// Previews instanciam os widgets públicos do kit (`components.dart` +
13
- /// tema). Rows / scroll / espaçamentos são apenas layout da vitrine —
14
- /// comportamento visual vem das props do componente (ex.: `KasyAccordion.surfaceRadius`,
15
- /// `KasyButton.borderRadius`). Presets opcionais: [KasyAvatarGradients],
16
- /// [KasyAvatarDemoPhotos] (pacote avatar).
10
+ /// Previews only instantiate the kit's public widgets (`components.dart` +
11
+ /// theme). Rows / scroll / spacing are just showcase layout;
12
+ /// visual behavior comes from the component's props (e.g. `KasyAccordion.surfaceRadius`,
13
+ /// `KasyButton.borderRadius`). Optional presets: [KasyAvatarGradients],
14
+ /// [KasyAvatarDemoPhotos] (avatar package).
17
15
  class ComponentPreviewDefinition {
18
16
  final String title;
19
17
  final List<ComponentPreviewVariant> variants;
@@ -86,6 +84,24 @@ ComponentPreviewDefinition? getComponentPreviewDefinition(
86
84
  ),
87
85
  ],
88
86
  );
87
+ case 'Web Header':
88
+ return const ComponentPreviewDefinition(
89
+ title: 'Web Header',
90
+ variants: [
91
+ ComponentPreviewVariant(
92
+ label: 'Default',
93
+ builder: _buildWebHeaderDefaultVariant,
94
+ ),
95
+ ComponentPreviewVariant(
96
+ label: 'With notification',
97
+ builder: _buildWebHeaderBadgeVariant,
98
+ ),
99
+ ComponentPreviewVariant(
100
+ label: 'Without avatar',
101
+ builder: _buildWebHeaderNoAvatarVariant,
102
+ ),
103
+ ],
104
+ );
89
105
  case 'Button':
90
106
  return const ComponentPreviewDefinition(
91
107
  title: 'Button',
@@ -313,6 +329,24 @@ ComponentPreviewDefinition? getComponentPreviewDefinition(
313
329
  ),
314
330
  ],
315
331
  );
332
+ case 'Status Tag':
333
+ return const ComponentPreviewDefinition(
334
+ title: 'Status Tag',
335
+ variants: [
336
+ ComponentPreviewVariant(
337
+ label: 'Tones',
338
+ builder: _buildStatusTagTones,
339
+ ),
340
+ ComponentPreviewVariant(
341
+ label: 'Without dot',
342
+ builder: _buildStatusTagNoDot,
343
+ ),
344
+ ComponentPreviewVariant(
345
+ label: 'In a row',
346
+ builder: _buildStatusTagInRow,
347
+ ),
348
+ ],
349
+ );
316
350
  case 'TextField':
317
351
  return const ComponentPreviewDefinition(
318
352
  title: 'TextField',
@@ -510,24 +544,18 @@ ComponentPreviewDefinition? getComponentPreviewDefinition(
510
544
  case 'Sidebar':
511
545
  return const ComponentPreviewDefinition(
512
546
  title: 'Sidebar',
513
- variants: [
514
- ComponentPreviewVariant(
515
- label: 'Drawer demo',
516
- builder: _buildSidebarVariant,
517
- ),
518
- ],
519
- );
520
- case 'Sidebar Pro':
521
- return const ComponentPreviewDefinition(
522
- title: 'Sidebar Pro',
523
547
  variants: [
524
548
  ComponentPreviewVariant(
525
549
  label: 'Expanded',
526
- builder: _buildSidebarProExpanded,
550
+ builder: _buildSidebarExpanded,
527
551
  ),
528
552
  ComponentPreviewVariant(
529
553
  label: 'Collapsed',
530
- builder: _buildSidebarProCollapsed,
554
+ builder: _buildSidebarCollapsed,
555
+ ),
556
+ ComponentPreviewVariant(
557
+ label: 'Without profile',
558
+ builder: _buildSidebarNoProfile,
531
559
  ),
532
560
  ],
533
561
  );
@@ -581,142 +609,26 @@ ComponentPreviewDefinition? getComponentPreviewDefinition(
581
609
  }
582
610
 
583
611
  // ─────────────────────────────────────────────────────────────────────────────
584
- // Sidebar — drawer demo
612
+ // Sidebar — interactive preview
585
613
  // ─────────────────────────────────────────────────────────────────────────────
586
614
 
587
- Widget _buildSidebarVariant(BuildContext context) => const _SidebarPreview();
615
+ Widget _buildSidebarExpanded(BuildContext context) =>
616
+ const _SidebarPreview(initiallyCollapsed: false);
588
617
 
589
- final List<BartMenuRoute> _kSidebarMockRoutes = [
590
- BartMenuRoute.bottomBar(
591
- label: 'Home',
592
- icon: KasyIcons.home,
593
- path: '/home',
594
- pageBuilder: (parentCtx, tabCtx, settings) => const SizedBox.shrink(),
595
- ),
596
- BartMenuRoute.bottomBar(
597
- label: 'Notifications',
598
- icon: KasyIcons.notification,
599
- path: '/notifications',
600
- pageBuilder: (parentCtx, tabCtx, settings) => const SizedBox.shrink(),
601
- ),
602
- BartMenuRoute.bottomBar(
603
- label: 'Profile',
604
- icon: KasyIcons.person,
605
- path: '/profile',
606
- pageBuilder: (parentCtx, tabCtx, settings) => const SizedBox.shrink(),
607
- ),
608
- BartMenuRoute.bottomBar(
609
- label: 'Settings',
610
- icon: KasyIcons.settings,
611
- path: '/settings',
612
- pageBuilder: (parentCtx, tabCtx, settings) => const SizedBox.shrink(),
613
- ),
614
- ];
615
-
616
- class _SidebarPreview extends StatefulWidget {
617
- const _SidebarPreview();
618
-
619
- @override
620
- State<_SidebarPreview> createState() => _SidebarPreviewState();
621
- }
622
-
623
- class _SidebarPreviewState extends State<_SidebarPreview> {
624
- final ValueNotifier<int> _currentItem = ValueNotifier(0);
618
+ Widget _buildSidebarCollapsed(BuildContext context) =>
619
+ const _SidebarPreview(initiallyCollapsed: true);
625
620
 
626
- @override
627
- void dispose() {
628
- _currentItem.dispose();
629
- super.dispose();
630
- }
621
+ Widget _buildSidebarNoProfile(BuildContext context) =>
622
+ const _SidebarPreview(initiallyCollapsed: false, showProfile: false);
631
623
 
632
- void _openDrawer(BuildContext context, {required bool fromEnd}) {
633
- final routes = _kSidebarMockRoutes;
634
- showGeneralDialog<void>(
635
- context: context,
636
- barrierDismissible: true,
637
- barrierLabel: 'Dismiss',
638
- barrierColor: Colors.black.withValues(alpha: 0.42),
639
- transitionDuration: const Duration(milliseconds: 290),
640
- pageBuilder: (ctx, anim, secAnim) => Align(
641
- alignment:
642
- fromEnd ? Alignment.centerRight : Alignment.centerLeft,
643
- child: SizedBox(
644
- height: double.infinity,
645
- child: ValueListenableBuilder<int>(
646
- valueListenable: _currentItem,
647
- builder: (builderCtx, currentIndex, child) =>
648
- kasySidebarBuilder(routes, (i) {
649
- _currentItem.value = i;
650
- }, _currentItem),
651
- ),
652
- ),
653
- ),
654
- transitionBuilder: (ctx, anim, secAnim, child) {
655
- final curved = CurvedAnimation(
656
- parent: anim,
657
- curve: Curves.easeOutCubic,
658
- );
659
- return SlideTransition(
660
- position: Tween<Offset>(
661
- begin: Offset(fromEnd ? 1.0 : -1.0, 0),
662
- end: Offset.zero,
663
- ).animate(curved),
664
- child: FadeTransition(
665
- opacity: Tween<double>(begin: 0.85, end: 1.0).animate(curved),
666
- child: child,
667
- ),
668
- );
669
- },
670
- );
671
- }
672
-
673
- @override
674
- Widget build(BuildContext context) {
675
- return Column(
676
- mainAxisSize: MainAxisSize.min,
677
- crossAxisAlignment: CrossAxisAlignment.stretch,
678
- children: [
679
- Padding(
680
- padding: const EdgeInsets.symmetric(horizontal: KasySpacing.md),
681
- child: _previewIntrinsicLaunch(
682
- KasyButton(
683
- label: 'Open Left',
684
- variant: KasyButtonVariant.soft,
685
- onPressed: () => _openDrawer(context, fromEnd: false),
686
- ),
687
- ),
688
- ),
689
- const SizedBox(height: KasySpacing.sm),
690
- Padding(
691
- padding: const EdgeInsets.symmetric(horizontal: KasySpacing.md),
692
- child: _previewIntrinsicLaunch(
693
- KasyButton(
694
- label: 'Open Right',
695
- variant: KasyButtonVariant.soft,
696
- onPressed: () => _openDrawer(context, fromEnd: true),
697
- ),
698
- ),
699
- ),
700
- ],
701
- );
702
- }
703
- }
704
-
705
-
706
- // ─────────────────────────────────────────────────────────────────────────────
707
- // Sidebar Pro — interactive preview
708
- // ─────────────────────────────────────────────────────────────────────────────
709
-
710
- Widget _buildSidebarProExpanded(BuildContext context) =>
711
- const _SidebarProPreview(initiallyCollapsed: false);
712
-
713
- Widget _buildSidebarProCollapsed(BuildContext context) =>
714
- const _SidebarProPreview(initiallyCollapsed: true);
715
-
716
- class _SidebarProPreview extends StatelessWidget {
717
- const _SidebarProPreview({required this.initiallyCollapsed});
624
+ class _SidebarPreview extends StatelessWidget {
625
+ const _SidebarPreview({
626
+ required this.initiallyCollapsed,
627
+ this.showProfile = true,
628
+ });
718
629
 
719
630
  final bool initiallyCollapsed;
631
+ final bool showProfile;
720
632
 
721
633
  void _open(BuildContext context, {required bool fromEnd}) {
722
634
  showGeneralDialog<void>(
@@ -729,11 +641,12 @@ class _SidebarProPreview extends StatelessWidget {
729
641
  alignment: fromEnd ? Alignment.centerRight : Alignment.centerLeft,
730
642
  child: SizedBox(
731
643
  height: double.infinity,
732
- child: KasySidebarPro(
644
+ child: KasySidebar(
733
645
  initiallyCollapsed: initiallyCollapsed,
646
+ showProfile: showProfile,
734
647
  side: fromEnd
735
- ? KasySidebarProSide.right
736
- : KasySidebarProSide.left,
648
+ ? KasySidebarSide.right
649
+ : KasySidebarSide.left,
737
650
  ),
738
651
  ),
739
652
  ),
@@ -1864,6 +1777,18 @@ Widget _buildAppBarSubpageActionsVariant(BuildContext context) {
1864
1777
  return const _AppBarPreview(variant: KasyAppBarStyle.subpageActions);
1865
1778
  }
1866
1779
 
1780
+ Widget _buildWebHeaderDefaultVariant(BuildContext context) {
1781
+ return const _WebHeaderPreview();
1782
+ }
1783
+
1784
+ Widget _buildWebHeaderBadgeVariant(BuildContext context) {
1785
+ return const _WebHeaderPreview(showBadge: true);
1786
+ }
1787
+
1788
+ Widget _buildWebHeaderNoAvatarVariant(BuildContext context) {
1789
+ return const _WebHeaderPreview(showAvatar: false);
1790
+ }
1791
+
1867
1792
  Widget _buildButtonSizesVariant(BuildContext context) {
1868
1793
  return const _ButtonSizesPreview();
1869
1794
  }
@@ -2643,6 +2568,59 @@ Widget _buildBadgeDefault(BuildContext context) {
2643
2568
  );
2644
2569
  }
2645
2570
 
2571
+ // ── Status Tag previews ──────────────────────────────────────────────────────
2572
+
2573
+ Widget _buildStatusTagTones(BuildContext context) {
2574
+ return const Center(
2575
+ child: Wrap(
2576
+ spacing: KasySpacing.sm,
2577
+ runSpacing: KasySpacing.sm,
2578
+ alignment: WrapAlignment.center,
2579
+ children: [
2580
+ KasyStatusTag(label: 'Active', tone: KasyStatusTagTone.success),
2581
+ KasyStatusTag(label: 'Subscriber', tone: KasyStatusTagTone.primary),
2582
+ KasyStatusTag(label: 'Pending', tone: KasyStatusTagTone.warning),
2583
+ KasyStatusTag(label: 'Blocked', tone: KasyStatusTagTone.danger),
2584
+ KasyStatusTag(label: 'Inactive'),
2585
+ ],
2586
+ ),
2587
+ );
2588
+ }
2589
+
2590
+ Widget _buildStatusTagNoDot(BuildContext context) {
2591
+ return const Center(
2592
+ child: Wrap(
2593
+ spacing: KasySpacing.sm,
2594
+ runSpacing: KasySpacing.sm,
2595
+ alignment: WrapAlignment.center,
2596
+ children: [
2597
+ KasyStatusTag(
2598
+ label: 'Visible',
2599
+ tone: KasyStatusTagTone.success,
2600
+ showDot: false,
2601
+ ),
2602
+ KasyStatusTag(
2603
+ label: 'Hidden',
2604
+ showDot: false,
2605
+ ),
2606
+ ],
2607
+ ),
2608
+ );
2609
+ }
2610
+
2611
+ Widget _buildStatusTagInRow(BuildContext context) {
2612
+ return const Center(
2613
+ child: Row(
2614
+ mainAxisSize: MainAxisSize.min,
2615
+ children: [
2616
+ KasyStatusTag(label: 'Active', tone: KasyStatusTagTone.success),
2617
+ SizedBox(width: KasySpacing.sm),
2618
+ KasyStatusTag(label: 'Subscriber', tone: KasyStatusTagTone.primary),
2619
+ ],
2620
+ ),
2621
+ );
2622
+ }
2623
+
2646
2624
  Widget _buildBadgeColors(BuildContext context) {
2647
2625
  return const _BadgeColorsPreview();
2648
2626
  }
@@ -3321,7 +3299,7 @@ class _ToastVariantsPreview extends StatelessWidget {
3321
3299
  context,
3322
3300
  title: 'Join a team',
3323
3301
  message:
3324
- 'Junior Garcia sent you an invitation to join HeroUI team!',
3302
+ 'You have been invited to join the team!',
3325
3303
  icon: _logoChip(context),
3326
3304
  ),
3327
3305
  ),
@@ -3440,7 +3418,7 @@ class _ToastStaticPreviewState extends State<_ToastStaticPreview> {
3440
3418
  KasyToast(
3441
3419
  title: 'Join a team',
3442
3420
  message:
3443
- 'Junior Garcia sent you an invitation to join HeroUI team!',
3421
+ 'You have been invited to join the team!',
3444
3422
  icon: _logoChip(),
3445
3423
  onClose: () => setState(() => _dismissed.add(0)),
3446
3424
  ),
@@ -3725,6 +3703,161 @@ class _AccordionPreviewState extends State<_AccordionPreview> {
3725
3703
  }
3726
3704
  }
3727
3705
 
3706
+ /// Presents [KasyWebHeader] inside a desktop browser-window mock (title bar +
3707
+ /// faux sidebar + content) so the preview reads as the web/desktop chrome it is.
3708
+ class _WebHeaderPreview extends StatelessWidget {
3709
+ final bool showBadge;
3710
+ final bool showAvatar;
3711
+
3712
+ const _WebHeaderPreview({this.showBadge = false, this.showAvatar = true});
3713
+
3714
+ @override
3715
+ Widget build(BuildContext context) {
3716
+ final KasyColors c = context.colors;
3717
+ return DecoratedBox(
3718
+ decoration: BoxDecoration(
3719
+ color: c.surface,
3720
+ borderRadius: BorderRadius.circular(KasyRadius.lg),
3721
+ border: Border.all(color: c.onSurface.withValues(alpha: 0.10)),
3722
+ boxShadow: [KasyShadows.component(context)],
3723
+ ),
3724
+ child: ClipRRect(
3725
+ borderRadius: BorderRadius.circular(KasyRadius.lg),
3726
+ child: Column(
3727
+ mainAxisSize: MainAxisSize.min,
3728
+ children: [
3729
+ const _BrowserTopBar(),
3730
+ // The real header, flush — no corner radius of its own.
3731
+ KasyWebHeader(
3732
+ showNotificationBadge: showBadge,
3733
+ showAvatar: showAvatar,
3734
+ onNotifications: () {},
3735
+ onCreate: () {},
3736
+ onAvatarTap: () {},
3737
+ ),
3738
+ const SizedBox(
3739
+ height: 150,
3740
+ child: Row(
3741
+ crossAxisAlignment: CrossAxisAlignment.stretch,
3742
+ children: [
3743
+ _DesktopMockSidebar(),
3744
+ Expanded(child: _DesktopMockContent()),
3745
+ ],
3746
+ ),
3747
+ ),
3748
+ ],
3749
+ ),
3750
+ ),
3751
+ );
3752
+ }
3753
+ }
3754
+
3755
+ /// macOS-style window chrome: traffic-light dots + an address pill.
3756
+ class _BrowserTopBar extends StatelessWidget {
3757
+ const _BrowserTopBar();
3758
+
3759
+ @override
3760
+ Widget build(BuildContext context) {
3761
+ final KasyColors c = context.colors;
3762
+ return Container(
3763
+ height: 36,
3764
+ padding: const EdgeInsets.symmetric(horizontal: 14),
3765
+ decoration: BoxDecoration(
3766
+ color: c.surfaceNeutralSoft,
3767
+ border: Border(
3768
+ bottom: BorderSide(color: c.onSurface.withValues(alpha: 0.08)),
3769
+ ),
3770
+ ),
3771
+ child: Row(
3772
+ children: [
3773
+ _trafficDot(const Color(0xFFFF5F57)),
3774
+ const SizedBox(width: 8),
3775
+ _trafficDot(const Color(0xFFFEBC2E)),
3776
+ const SizedBox(width: 8),
3777
+ _trafficDot(const Color(0xFF28C840)),
3778
+ const SizedBox(width: 16),
3779
+ Expanded(
3780
+ child: Container(
3781
+ height: 18,
3782
+ decoration: BoxDecoration(
3783
+ color: c.surface,
3784
+ borderRadius: BorderRadius.circular(KasyRadius.full),
3785
+ border: Border.all(
3786
+ color: c.onSurface.withValues(alpha: 0.08),
3787
+ ),
3788
+ ),
3789
+ ),
3790
+ ),
3791
+ ],
3792
+ ),
3793
+ );
3794
+ }
3795
+
3796
+ Widget _trafficDot(Color color) => Container(
3797
+ width: 11,
3798
+ height: 11,
3799
+ decoration: BoxDecoration(color: color, shape: BoxShape.circle),
3800
+ );
3801
+ }
3802
+
3803
+ /// Narrow faux navigation rail to the left of the content area.
3804
+ class _DesktopMockSidebar extends StatelessWidget {
3805
+ const _DesktopMockSidebar();
3806
+
3807
+ @override
3808
+ Widget build(BuildContext context) {
3809
+ final KasyColors c = context.colors;
3810
+ return Container(
3811
+ width: 76,
3812
+ decoration: BoxDecoration(
3813
+ color: c.surface,
3814
+ border: Border(
3815
+ right: BorderSide(color: c.onSurface.withValues(alpha: 0.08)),
3816
+ ),
3817
+ ),
3818
+ child: const Padding(
3819
+ padding: EdgeInsets.all(KasySpacing.smd),
3820
+ child: Column(
3821
+ crossAxisAlignment: CrossAxisAlignment.stretch,
3822
+ children: <Widget>[
3823
+ _AppBarBodyLine(widthFactor: 1),
3824
+ SizedBox(height: KasySpacing.sm),
3825
+ _AppBarBodyLine(widthFactor: 0.8),
3826
+ SizedBox(height: KasySpacing.sm),
3827
+ _AppBarBodyLine(widthFactor: 0.9),
3828
+ SizedBox(height: KasySpacing.sm),
3829
+ _AppBarBodyLine(widthFactor: 0.7),
3830
+ ],
3831
+ ),
3832
+ ),
3833
+ );
3834
+ }
3835
+ }
3836
+
3837
+ /// Faux content area shown under the header in the desktop mock.
3838
+ class _DesktopMockContent extends StatelessWidget {
3839
+ const _DesktopMockContent();
3840
+
3841
+ @override
3842
+ Widget build(BuildContext context) {
3843
+ return const Padding(
3844
+ padding: EdgeInsets.all(KasySpacing.md),
3845
+ child: Column(
3846
+ crossAxisAlignment: CrossAxisAlignment.stretch,
3847
+ children: <Widget>[
3848
+ _AppBarBodyLine(widthFactor: 0.4),
3849
+ SizedBox(height: KasySpacing.md),
3850
+ _AppBarBodyLine(widthFactor: 0.95),
3851
+ SizedBox(height: KasySpacing.sm),
3852
+ _AppBarBodyLine(widthFactor: 0.85),
3853
+ SizedBox(height: KasySpacing.sm),
3854
+ _AppBarBodyLine(widthFactor: 0.9),
3855
+ ],
3856
+ ),
3857
+ );
3858
+ }
3859
+ }
3860
+
3728
3861
  class _AppBarPreview extends StatelessWidget {
3729
3862
  final KasyAppBarStyle variant;
3730
3863
 
@@ -3740,38 +3873,44 @@ class _AppBarPreview extends StatelessWidget {
3740
3873
  tooltip: 'More',
3741
3874
  onPressed: () {},
3742
3875
  );
3743
- return DecoratedBox(
3744
- decoration: BoxDecoration(
3745
- color: context.colors.surface,
3746
- borderRadius: BorderRadius.circular(KasyRadius.xl),
3747
- border: Border.all(
3748
- color: context.colors.outline.withValues(alpha: 0.3),
3749
- ),
3750
- boxShadow: [KasyShadows.component(context)],
3751
- ),
3752
- child: ClipRRect(
3753
- borderRadius: BorderRadius.circular(KasyRadius.xl),
3754
- child: SizedBox(
3755
- height: 236,
3756
- child: Stack(
3757
- fit: StackFit.expand,
3758
- children: [
3759
- const _AppBarMockBody(),
3760
- Positioned(
3761
- top: 0,
3762
- left: 0,
3763
- right: 0,
3764
- child: KasyAppBar(
3765
- useSafeArea: false,
3766
- title: 'Preview',
3767
- style: variant,
3768
- onBack: () {},
3769
- trailing: variant == KasyAppBarStyle.subpageActions
3770
- ? trailing
3771
- : null,
3876
+ final KasyColors c = context.colors;
3877
+ // KasyAppBar hides itself at desktop width; the preview must always show it,
3878
+ // so pin a phone-sized MediaQuery just for the bar's own width check.
3879
+ return MediaQuery(
3880
+ data: MediaQuery.of(context).copyWith(size: const Size(390, 844)),
3881
+ child: DecoratedBox(
3882
+ decoration: BoxDecoration(
3883
+ color: c.surface,
3884
+ borderRadius: BorderRadius.circular(KasyRadius.xl),
3885
+ border: Border.all(
3886
+ color: c.outline.withValues(alpha: 0.3),
3887
+ ),
3888
+ boxShadow: [KasyShadows.component(context)],
3889
+ ),
3890
+ child: ClipRRect(
3891
+ borderRadius: BorderRadius.circular(KasyRadius.xl),
3892
+ child: SizedBox(
3893
+ height: 236,
3894
+ child: Stack(
3895
+ fit: StackFit.expand,
3896
+ children: [
3897
+ const _AppBarMockBody(),
3898
+ Positioned(
3899
+ top: 0,
3900
+ left: 0,
3901
+ right: 0,
3902
+ child: KasyAppBar(
3903
+ useSafeArea: false,
3904
+ title: 'Preview',
3905
+ style: variant,
3906
+ onBack: () {},
3907
+ trailing: variant == KasyAppBarStyle.subpageActions
3908
+ ? trailing
3909
+ : null,
3910
+ ),
3772
3911
  ),
3773
- ),
3774
- ],
3912
+ ],
3913
+ ),
3775
3914
  ),
3776
3915
  ),
3777
3916
  ),
@@ -5030,8 +5169,8 @@ void _noop() {}
5030
5169
 
5031
5170
  void _triggerTapFeedback() {}
5032
5171
 
5033
- /// Os hosts de preview aplicam largura máxima ao conteúdo; uma [Row] centralizada
5034
- /// mantém [KasyButton] sem `expand` com largura intrínseca ao rótulo.
5172
+ /// Preview hosts apply a maximum width to the content; a centered [Row]
5173
+ /// keeps [KasyButton] without `expand` at its label's intrinsic width.
5035
5174
  Widget _previewIntrinsicLaunch(Widget child) {
5036
5175
  return Row(
5037
5176
  mainAxisAlignment: MainAxisAlignment.center,