baldur 0.1.1

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 (164) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE +21 -0
  4. data/README.md +318 -0
  5. data/TODO.md +6 -0
  6. data/app/assets/javascripts/baldur/controllers/accordion_controller.js +148 -0
  7. data/app/assets/javascripts/baldur/controllers/alert_controller.js +209 -0
  8. data/app/assets/javascripts/baldur/controllers/date_field_controller.js +558 -0
  9. data/app/assets/javascripts/baldur/controllers/details_menu_controller.js +30 -0
  10. data/app/assets/javascripts/baldur/controllers/form_submit_controller.js +7 -0
  11. data/app/assets/javascripts/baldur/controllers/marketing_pricing_controller.js +47 -0
  12. data/app/assets/javascripts/baldur/controllers/marketing_tabs_controller.js +118 -0
  13. data/app/assets/javascripts/baldur/controllers/menu_select_controller.js +401 -0
  14. data/app/assets/javascripts/baldur/controllers/mobile_sidebar_controller.js +13 -0
  15. data/app/assets/javascripts/baldur/controllers/modal_controller.js +149 -0
  16. data/app/assets/javascripts/baldur/controllers/panel_right_controller.js +1 -0
  17. data/app/assets/javascripts/baldur/controllers/panel_secondary_controller.js +129 -0
  18. data/app/assets/javascripts/baldur/controllers/segmented_tabs_controller.js +38 -0
  19. data/app/assets/javascripts/baldur/controllers/sidebar_controller.js +77 -0
  20. data/app/assets/javascripts/baldur/controllers/smooth_scroll_controller.js +29 -0
  21. data/app/assets/javascripts/baldur/controllers/snackbar_controller.js +158 -0
  22. data/app/assets/javascripts/baldur/controllers/table_disclosure_controller.js +46 -0
  23. data/app/assets/javascripts/baldur/controllers/theme_controller.js +90 -0
  24. data/app/assets/javascripts/baldur/controllers/tooltip_controller.js +136 -0
  25. data/app/assets/javascripts/baldur/lib/animation-helpers.js +56 -0
  26. data/app/assets/javascripts/baldur/lib/dom-helpers.js +80 -0
  27. data/app/assets/javascripts/baldur/lib/field-validation-helpers.js +36 -0
  28. data/app/assets/javascripts/baldur/lib/focus-management.js +89 -0
  29. data/app/assets/javascripts/baldur/lib/formatting-helpers.js +100 -0
  30. data/app/assets/javascripts/baldur/lib/lucide.js +20 -0
  31. data/app/assets/javascripts/baldur/lib/snackbar.js +50 -0
  32. data/app/assets/javascripts/baldur/lib/storage-helpers.js +50 -0
  33. data/app/assets/stylesheets/baldur/application/components/alert.css +226 -0
  34. data/app/assets/stylesheets/baldur/application/components/app_bar.css +41 -0
  35. data/app/assets/stylesheets/baldur/application/components/button.css +173 -0
  36. data/app/assets/stylesheets/baldur/application/components/card.css +63 -0
  37. data/app/assets/stylesheets/baldur/application/components/chart.css +40 -0
  38. data/app/assets/stylesheets/baldur/application/components/chip.css +51 -0
  39. data/app/assets/stylesheets/baldur/application/components/dialog.css +81 -0
  40. data/app/assets/stylesheets/baldur/application/components/forms.css +624 -0
  41. data/app/assets/stylesheets/baldur/application/components/layout.css +2 -0
  42. data/app/assets/stylesheets/baldur/application/components/list.css +15 -0
  43. data/app/assets/stylesheets/baldur/application/components/menu.css +300 -0
  44. data/app/assets/stylesheets/baldur/application/components/panel-right.css +1 -0
  45. data/app/assets/stylesheets/baldur/application/components/panel-secondary.css +71 -0
  46. data/app/assets/stylesheets/baldur/application/components/progress.css +84 -0
  47. data/app/assets/stylesheets/baldur/application/components/segmented-buttons.css +117 -0
  48. data/app/assets/stylesheets/baldur/application/components/settings-nav.css +84 -0
  49. data/app/assets/stylesheets/baldur/application/components/sidebar.css +123 -0
  50. data/app/assets/stylesheets/baldur/application/components/snackbar.css +179 -0
  51. data/app/assets/stylesheets/baldur/application/components/stepper.css +124 -0
  52. data/app/assets/stylesheets/baldur/application/components/switch.css +105 -0
  53. data/app/assets/stylesheets/baldur/application/components/table.css +331 -0
  54. data/app/assets/stylesheets/baldur/application/components/timeline.css +184 -0
  55. data/app/assets/stylesheets/baldur/application/components/utilities.css +180 -0
  56. data/app/assets/stylesheets/baldur/application/global.css +125 -0
  57. data/app/assets/stylesheets/baldur/application/marketing/layout.css +36 -0
  58. data/app/assets/stylesheets/baldur/application/motion.css +125 -0
  59. data/app/assets/stylesheets/baldur/application/theme.css +329 -0
  60. data/app/assets/stylesheets/baldur/theme/dark.css +90 -0
  61. data/app/assets/stylesheets/baldur/theme/light.css +82 -0
  62. data/app/assets/stylesheets/baldur.css +27 -0
  63. data/app/assets/stylesheets/baldur_panel_right.css +1 -0
  64. data/app/assets/stylesheets/baldur_panel_secondary.css +1 -0
  65. data/app/assets/tailwind/baldur/engine.css +5 -0
  66. data/app/helpers/baldur/compatibility/ui_aliases.rb +7 -0
  67. data/app/helpers/baldur/marketing_helper.rb +121 -0
  68. data/app/helpers/baldur/optional/auth_page_helper.rb +17 -0
  69. data/app/helpers/baldur/optional/google_auth_helper.rb +16 -0
  70. data/app/helpers/baldur/optional/panel_right_helper.rb +7 -0
  71. data/app/helpers/baldur/optional/panel_secondary_helper.rb +26 -0
  72. data/app/helpers/baldur/render_helper.rb +13 -0
  73. data/app/helpers/baldur/ui_helper.rb +217 -0
  74. data/app/helpers/baldur/ui_helper_feedback.rb +93 -0
  75. data/app/helpers/baldur/ui_helper_forms.rb +230 -0
  76. data/app/helpers/baldur/ui_helper_unavailable.rb +98 -0
  77. data/app/views/baldur/components/_accordion.html.erb +30 -0
  78. data/app/views/baldur/components/_action_row.html.erb +6 -0
  79. data/app/views/baldur/components/_alert.html.erb +61 -0
  80. data/app/views/baldur/components/_badge.html.erb +25 -0
  81. data/app/views/baldur/components/_button.html.erb +81 -0
  82. data/app/views/baldur/components/_card.html.erb +40 -0
  83. data/app/views/baldur/components/_chart_card.html.erb +42 -0
  84. data/app/views/baldur/components/_checkbox.html.erb +27 -0
  85. data/app/views/baldur/components/_date_field.html.erb +43 -0
  86. data/app/views/baldur/components/_google_sign_in_button.html.erb +1 -0
  87. data/app/views/baldur/components/_kebab_menu.html.erb +36 -0
  88. data/app/views/baldur/components/_kpi.html.erb +45 -0
  89. data/app/views/baldur/components/_menu_select.html.erb +78 -0
  90. data/app/views/baldur/components/_modal.html.erb +54 -0
  91. data/app/views/baldur/components/_pagination.html.erb +61 -0
  92. data/app/views/baldur/components/_segmented_buttons.html.erb +51 -0
  93. data/app/views/baldur/components/_settings_nav.html.erb +41 -0
  94. data/app/views/baldur/components/_snackbar.html.erb +42 -0
  95. data/app/views/baldur/components/_snackbar_stack.html.erb +13 -0
  96. data/app/views/baldur/components/_stepper.html.erb +39 -0
  97. data/app/views/baldur/components/_table.html.erb +117 -0
  98. data/app/views/baldur/components/_table_card.html.erb +86 -0
  99. data/app/views/baldur/components/_table_footer.html.erb +68 -0
  100. data/app/views/baldur/components/_text_field.html.erb +33 -0
  101. data/app/views/baldur/components/_tooltip.html.erb +73 -0
  102. data/app/views/baldur/marketing/_cta_banner.html.erb +20 -0
  103. data/app/views/baldur/marketing/_faq_section.html.erb +37 -0
  104. data/app/views/baldur/marketing/_features_section.html.erb +67 -0
  105. data/app/views/baldur/marketing/_footer.html.erb +38 -0
  106. data/app/views/baldur/marketing/_hero_section.html.erb +259 -0
  107. data/app/views/baldur/marketing/_pricing_tables.html.erb +99 -0
  108. data/app/views/baldur/marketing/_testimonials_section.html.erb +80 -0
  109. data/app/views/baldur/marketing/_top_nav.html.erb +28 -0
  110. data/app/views/baldur/optional/_auth_page.html.erb +21 -0
  111. data/app/views/baldur/optional/_google_sign_in_button.html.erb +19 -0
  112. data/app/views/baldur/optional/_panel_right.html.erb +1 -0
  113. data/app/views/baldur/optional/_panel_secondary.html.erb +34 -0
  114. data/baldur.gemspec +30 -0
  115. data/config/importmap.rb +2 -0
  116. data/lib/baldur/configuration.rb +24 -0
  117. data/lib/baldur/engine.rb +10 -0
  118. data/lib/baldur/version.rb +3 -0
  119. data/lib/baldur.rb +17 -0
  120. data/lib/generators/baldur/install/install_generator.rb +113 -0
  121. data/lib/generators/baldur/install/templates/baldur_initializer.rb +19 -0
  122. data/lib/generators/baldur/install/templates/fonts.css +14 -0
  123. data/lib/generators/baldur/install/templates/theme.css +27 -0
  124. data/lib/generators/baldur/install/templates/ui_helper.rb +4 -0
  125. data/lib/generators/baldur/install_google_auth/install_google_auth_generator.rb +15 -0
  126. data/lib/generators/baldur/install_panel_right/install_panel_right_generator.rb +9 -0
  127. data/lib/generators/baldur/install_panel_secondary/install_panel_secondary_generator.rb +21 -0
  128. data/script/verify_host_install +111 -0
  129. data/test/gemspec_test.rb +11 -0
  130. data/test/install_generator_test.rb +35 -0
  131. data/test/install_panel_secondary_generator_test.rb +21 -0
  132. data/test/marketing_helper_test.rb +38 -0
  133. data/test/run_all.rb +3 -0
  134. data/test/test_helper.rb +9 -0
  135. data/test/tmp/install_generator/app/assets/stylesheets/fonts.css +14 -0
  136. data/test/tmp/install_generator/app/assets/stylesheets/theme.css +27 -0
  137. data/test/tmp/install_generator/app/assets/tailwind/application.css +4 -0
  138. data/test/tmp/install_generator/app/helpers/ui_helper.rb +4 -0
  139. data/test/tmp/install_generator/app/javascript/controllers/accordion_controller.js +1 -0
  140. data/test/tmp/install_generator/app/javascript/controllers/date_field_controller.js +1 -0
  141. data/test/tmp/install_generator/app/javascript/controllers/details_menu_controller.js +1 -0
  142. data/test/tmp/install_generator/app/javascript/controllers/form_submit_controller.js +1 -0
  143. data/test/tmp/install_generator/app/javascript/controllers/marketing_pricing_controller.js +1 -0
  144. data/test/tmp/install_generator/app/javascript/controllers/marketing_tabs_controller.js +1 -0
  145. data/test/tmp/install_generator/app/javascript/controllers/menu_select_controller.js +1 -0
  146. data/test/tmp/install_generator/app/javascript/controllers/modal_controller.js +1 -0
  147. data/test/tmp/install_generator/app/javascript/controllers/segmented_tabs_controller.js +1 -0
  148. data/test/tmp/install_generator/app/javascript/controllers/sidebar_controller.js +1 -0
  149. data/test/tmp/install_generator/app/javascript/controllers/smooth_scroll_controller.js +1 -0
  150. data/test/tmp/install_generator/app/javascript/controllers/snackbar_controller.js +1 -0
  151. data/test/tmp/install_generator/app/javascript/controllers/theme_controller.js +1 -0
  152. data/test/tmp/install_generator/app/javascript/controllers/tooltip_controller.js +1 -0
  153. data/test/tmp/install_generator/app/javascript/lib/animation-helpers.js +1 -0
  154. data/test/tmp/install_generator/app/javascript/lib/dom-helpers.js +1 -0
  155. data/test/tmp/install_generator/app/javascript/lib/field-validation-helpers.js +1 -0
  156. data/test/tmp/install_generator/app/javascript/lib/focus-management.js +1 -0
  157. data/test/tmp/install_generator/app/javascript/lib/formatting-helpers.js +1 -0
  158. data/test/tmp/install_generator/app/javascript/lib/snackbar.js +1 -0
  159. data/test/tmp/install_generator/app/javascript/lib/storage-helpers.js +1 -0
  160. data/test/tmp/install_generator/config/initializers/baldur.rb +19 -0
  161. data/test/tmp/install_panel_secondary_generator/app/assets/tailwind/application.css +2 -0
  162. data/test/tmp/install_panel_secondary_generator/app/helpers/panel_secondary_helper.rb +3 -0
  163. data/test/tmp/install_panel_secondary_generator/app/javascript/controllers/panel_secondary_controller.js +1 -0
  164. metadata +259 -0
@@ -0,0 +1,113 @@
1
+ require "rails/generators"
2
+
3
+ module Baldur
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("templates", __dir__)
7
+
8
+ CORE_CONTROLLERS = %w[
9
+ accordion
10
+ date_field
11
+ details_menu
12
+ form_submit
13
+ menu_select
14
+ modal
15
+ marketing_pricing
16
+ marketing_tabs
17
+ segmented_tabs
18
+ sidebar
19
+ smooth_scroll
20
+ snackbar
21
+ theme
22
+ tooltip
23
+ ].freeze
24
+
25
+ CORE_LIBS = %w[
26
+ animation-helpers
27
+ dom-helpers
28
+ field-validation-helpers
29
+ focus-management
30
+ formatting-helpers
31
+ snackbar
32
+ storage-helpers
33
+ ].freeze
34
+
35
+ def create_ui_helper
36
+ template "ui_helper.rb", "app/helpers/ui_helper.rb"
37
+ end
38
+
39
+ def create_initializer
40
+ template "baldur_initializer.rb", "config/initializers/baldur.rb"
41
+ end
42
+
43
+ def create_theme_override
44
+ template "theme.css", "app/assets/stylesheets/theme.css"
45
+ end
46
+
47
+ def create_fonts_override
48
+ template "fonts.css", "app/assets/stylesheets/fonts.css"
49
+ end
50
+
51
+ def create_controller_shims
52
+ CORE_CONTROLLERS.each do |name|
53
+ create_file "app/javascript/controllers/#{name}_controller.js", <<~JS
54
+ export { default } from "baldur/controllers/#{name}_controller"
55
+ JS
56
+ end
57
+ end
58
+
59
+ def create_lib_shims
60
+ CORE_LIBS.each do |name|
61
+ create_file "app/javascript/lib/#{name}.js", <<~JS
62
+ export * from "baldur/lib/#{name}"
63
+ JS
64
+ end
65
+ end
66
+
67
+ def add_stylesheet_import
68
+ return unless File.exist?(tailwind_entrypoint_path)
69
+
70
+ append_unique_line tailwind_entrypoint_path, "@import \"../stylesheets/fonts.css\";"
71
+ append_unique_line tailwind_entrypoint_path, "@import \"../builds/tailwind/baldur.css\";"
72
+ append_unique_line tailwind_entrypoint_path, "@import \"../stylesheets/theme.css\";"
73
+ ensure_stylesheet_import_order
74
+ end
75
+
76
+ private
77
+
78
+ def append_unique_line(path, line)
79
+ append_to_file path, "#{line}\n" unless File.read(path).include?(line)
80
+ end
81
+
82
+ def ensure_stylesheet_import_order
83
+ source = File.read(tailwind_entrypoint_path)
84
+ fonts_import = "@import \"../stylesheets/fonts.css\";"
85
+ tailwind_import = "@import \"tailwindcss\";"
86
+ baldur_import = "@import \"../builds/tailwind/baldur.css\";"
87
+ theme_import = "@import \"../stylesheets/theme.css\";"
88
+ normalized = source.lines.reject { |line| line.strip == fonts_import }.join
89
+ normalized = if normalized.include?(tailwind_import)
90
+ normalized.sub("#{tailwind_import}\n", "#{fonts_import}\n#{tailwind_import}\n")
91
+ else
92
+ "#{fonts_import}\n#{normalized}"
93
+ end
94
+
95
+ if normalized.include?(baldur_import) && normalized.include?(theme_import) &&
96
+ normalized.index(baldur_import) > normalized.index(theme_import)
97
+ normalized = normalized.lines.reject { |line| line.strip == theme_import }.join
98
+ normalized = normalized.sub("#{baldur_import}\n", "#{baldur_import}\n#{theme_import}\n")
99
+ end
100
+
101
+ File.write(tailwind_entrypoint_path, normalized)
102
+ end
103
+
104
+ def tailwind_entrypoint_path
105
+ File.join(destination_root, tailwind_entrypoint)
106
+ end
107
+
108
+ def tailwind_entrypoint
109
+ "app/assets/tailwind/application.css"
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,19 @@
1
+ require "baldur"
2
+
3
+ Baldur.configure do |config|
4
+ config.unavailable_fallback_message = "Missing metric or raw data required to compute this value."
5
+ config.theme_storage_key = "baldur.theme"
6
+ config.marketing_brand = {
7
+ name: "Your Brand",
8
+ wordmark: "Your Brand",
9
+ logo_src: "/icon.png",
10
+ logo_alt: "Your Brand logo"
11
+ }
12
+
13
+ # Supply host-specific lookups when using unavailable dependency helpers.
14
+ config.warning_dependency_resolver = ->(_warning_keys) { [] }
15
+ config.dependency_dataset_name_resolver = ->(dataset_key) { dataset_key.to_s.humanize }
16
+
17
+ # Optional integrations.
18
+ config.default_google_sign_in_path = nil
19
+ end
@@ -0,0 +1,14 @@
1
+ /*
2
+ * Host font loading overrides.
3
+ *
4
+ * Load the font families your app needs here using either `@import` or
5
+ * `@font-face`. Baldur does not load web fonts directly.
6
+ *
7
+ * Default:
8
+ * - Geist for body, headings, and UI surfaces
9
+ *
10
+ * Example:
11
+ * @import url("https://fonts.googleapis.com/css2?family=Geist:wght@100..900&family=JetBrains+Mono:wght@100..800&display=swap");
12
+ */
13
+
14
+ @import url("https://fonts.googleapis.com/css2?family=Geist:wght@100..900&display=swap");
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Host theme overrides.
3
+ *
4
+ * Override only the base palette inputs below. Baldur remains the source of
5
+ * truth for semantic tokens, light/dark role mapping, and component styling.
6
+ * Use `fonts.css` to load font files, then map those loaded families to the
7
+ * font tokens below.
8
+ *
9
+ * Example:
10
+ * :root {
11
+ * --_primary-base: oklch(0.68 0.16 27);
12
+ * --_secondary-base: oklch(0.30 0.04 195);
13
+ * --_accent-base: oklch(0.48 0.07 92);
14
+ * --_neutral-base: oklch(0.87 0 0);
15
+ * --font-body: "Geist", "Inter", "Segoe UI", "Helvetica Neue", Arial, system-ui, -apple-system, sans-serif;
16
+ * --font-heading: var(--font-body);
17
+ * --font-ui: var(--font-body);
18
+ * }
19
+ */
20
+
21
+ :root {
22
+ --font-body: "Geist", "Inter", "Segoe UI", "Helvetica Neue", Arial, system-ui, -apple-system, sans-serif;
23
+ --font-heading: var(--font-body);
24
+ --font-ui: var(--font-body);
25
+ --font-family: var(--font-body);
26
+ --font-sans: var(--font-body);
27
+ }
@@ -0,0 +1,4 @@
1
+ module UiHelper
2
+ include Baldur::Compatibility::UiAliases
3
+ include Baldur::MarketingHelper
4
+ end
@@ -0,0 +1,15 @@
1
+ require "rails/generators"
2
+
3
+ module Baldur
4
+ module Generators
5
+ class InstallGoogleAuthGenerator < Rails::Generators::Base
6
+ def create_helper
7
+ create_file "app/helpers/google_auth_helper.rb", <<~RUBY
8
+ module GoogleAuthHelper
9
+ include Baldur::Optional::GoogleAuthHelper
10
+ end
11
+ RUBY
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ require "rails/generators"
2
+ require_relative "../install_panel_secondary/install_panel_secondary_generator"
3
+
4
+ module Baldur
5
+ module Generators
6
+ class InstallPanelRightGenerator < InstallPanelSecondaryGenerator
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ require "rails/generators"
2
+
3
+ module Baldur
4
+ module Generators
5
+ class InstallPanelSecondaryGenerator < Rails::Generators::Base
6
+ def create_helper
7
+ create_file "app/helpers/panel_secondary_helper.rb", <<~RUBY
8
+ module PanelSecondaryHelper
9
+ include Baldur::Optional::PanelSecondaryHelper
10
+ end
11
+ RUBY
12
+ end
13
+
14
+ def create_controller_shim
15
+ create_file "app/javascript/controllers/panel_secondary_controller.js", <<~JS
16
+ export { default } from "baldur/controllers/panel_secondary_controller"
17
+ JS
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ ENV["RAILS_ENV"] ||= "development"
5
+
6
+ require File.expand_path("../../../config/environment", __dir__)
7
+
8
+ def assert!(message)
9
+ raise message unless yield
10
+ end
11
+
12
+ def tailwind_entrypoint
13
+ Rails.root.join("app/assets/tailwind/application.css")
14
+ end
15
+
16
+ puts "Baldur host install smoke check"
17
+ puts "Rails root: #{Rails.root}"
18
+ puts "Baldur root: #{Baldur::Engine.root}"
19
+
20
+ assert!("Expected Baldur importmap path to be registered") do
21
+ Rails.application.config.importmap.paths.any? { |path| path.to_s.end_with?("/config/importmap.rb") && path.to_s.include?("/baldur/") }
22
+ end
23
+
24
+ %w[
25
+ app/javascript/controllers/sidebar_controller.js
26
+ app/javascript/controllers/mobile_sidebar_controller.js
27
+ app/javascript/controllers/theme_controller.js
28
+ app/javascript/controllers/modal_controller.js
29
+ app/javascript/controllers/marketing_tabs_controller.js
30
+ app/javascript/controllers/marketing_pricing_controller.js
31
+ ].each do |relative_path|
32
+ path = Rails.root.join(relative_path)
33
+ assert!("Missing generated shim: #{relative_path}") { path.exist? }
34
+ end
35
+
36
+ assert!("Expected ui_button helper to be available") do
37
+ ApplicationController.helpers.respond_to?(:ui_button)
38
+ end
39
+
40
+ button_html = ApplicationController.helpers.ui_button(label: "Verify", href: "/")
41
+ assert!("ui_button did not render expected markup") do
42
+ button_html.include?("button") || button_html.include?("<a")
43
+ end
44
+
45
+ modal_html = ApplicationController.helpers.ui_modal(id: "verify-modal", title: "Verify") { "Body".html_safe }
46
+ assert!("ui_modal did not render expected markup") do
47
+ modal_html.include?("dialog") || modal_html.include?("modal")
48
+ end
49
+ assert!("ui_modal did not render body content") do
50
+ modal_html.include?("Body")
51
+ end
52
+
53
+ card_html = ApplicationController.helpers.ui_card(title: "Verify", body: "Card body")
54
+ assert!("ui_card did not render body content") do
55
+ card_html.include?("Card body")
56
+ end
57
+
58
+ top_nav_html = ApplicationController.helpers.ui_marketing_top_nav(
59
+ links: [ { label: "Pricing", href: "/pricing", class: "nav-link" } ],
60
+ primary_action: { label: "Verify", href: "/", variant: :primary }
61
+ )
62
+ assert!("ui_marketing_top_nav did not render expected markup") do
63
+ top_nav_html.include?("marketing-top-nav") && top_nav_html.include?("Pricing")
64
+ end
65
+
66
+ assert!("Expected Tailwind entrypoint at #{tailwind_entrypoint}") do
67
+ tailwind_entrypoint.exist?
68
+ end
69
+
70
+ tailwind_source = tailwind_entrypoint.read
71
+
72
+ [
73
+ '@import "../stylesheets/fonts.css";',
74
+ '@import "../builds/tailwind/baldur.css";',
75
+ '@import "../stylesheets/theme.css";'
76
+ ].each do |line|
77
+ assert!("Missing Tailwind integration line: #{line}") { tailwind_source.include?(line) }
78
+ end
79
+
80
+ host_fonts = Rails.root.join("app/assets/stylesheets/fonts.css")
81
+ assert!("Expected host font override scaffold at #{host_fonts}") do
82
+ host_fonts.exist?
83
+ end
84
+
85
+ host_theme = Rails.root.join("app/assets/stylesheets/theme.css")
86
+ assert!("Expected host theme override scaffold at #{host_theme}") do
87
+ host_theme.exist?
88
+ end
89
+
90
+ assert!("Expected host fonts import before Tailwind in the entrypoint") do
91
+ tailwind_source.index('@import "../stylesheets/fonts.css";') <
92
+ tailwind_source.index('@import "tailwindcss";')
93
+ end
94
+
95
+ assert!("Expected host theme override import after the Baldur import") do
96
+ tailwind_source.index('@import "../builds/tailwind/baldur.css";') <
97
+ tailwind_source.index('@import "../stylesheets/theme.css";')
98
+ end
99
+
100
+ assert!("Expected Tailwind entrypoint to stop hard-coding Geist font imports") do
101
+ !tailwind_source.include?('family=Geist:wght@100..900')
102
+ end
103
+
104
+ if ApplicationController.helpers.respond_to?(:ui_panel_secondary)
105
+ panel_html = ApplicationController.helpers.ui_panel_secondary(id: "verify-panel", title: "Panel", trigger_label: "Open") { "Body".html_safe }
106
+ assert!("ui_panel_secondary did not render expected markup") do
107
+ panel_html.include?("panel-secondary")
108
+ end
109
+ end
110
+
111
+ puts "Smoke check passed"
@@ -0,0 +1,11 @@
1
+ require_relative "test_helper"
2
+
3
+ class BaldurGemspecTest < Minitest::Test
4
+ def test_gemspec_lists_only_files
5
+ spec = Gem::Specification.load(File.expand_path("../baldur.gemspec", __dir__))
6
+
7
+ assert spec.files.any?, "expected gemspec to include files"
8
+ assert spec.files.all? { |path| File.file?(File.expand_path("../#{path}", __dir__)) }, "expected spec.files to contain only files"
9
+ assert_includes spec.files, "app/assets/tailwind/baldur/engine.css"
10
+ end
11
+ end
@@ -0,0 +1,35 @@
1
+ require_relative "test_helper"
2
+ require_relative "../lib/generators/baldur/install/install_generator"
3
+
4
+ class BaldurInstallGeneratorTest < Rails::Generators::TestCase
5
+ tests Baldur::Generators::InstallGenerator
6
+ destination File.expand_path("tmp/install_generator", __dir__)
7
+ setup :prepare_destination
8
+
9
+ setup do
10
+ FileUtils.mkdir_p File.join(destination_root, "app/assets/tailwind")
11
+ File.write(File.join(destination_root, "app/assets/tailwind/application.css"), "@import \"tailwindcss\";\n")
12
+ end
13
+
14
+ test "installs path agnostic tailwind integration and helper shims" do
15
+ run_generator
16
+
17
+ tailwind_entrypoint = File.join(destination_root, "app/assets/tailwind/application.css")
18
+ tailwind_source = File.read(tailwind_entrypoint)
19
+
20
+ assert_includes tailwind_source, "@import \"../stylesheets/fonts.css\";"
21
+ assert_includes tailwind_source, "@import \"../builds/tailwind/baldur.css\";"
22
+ assert_includes tailwind_source, "@import \"../stylesheets/theme.css\";"
23
+ refute_includes tailwind_source, "gems/baldur"
24
+
25
+ assert_operator tailwind_source.index("@import \"../stylesheets/fonts.css\";"), :<, tailwind_source.index("@import \"tailwindcss\";")
26
+ assert_operator tailwind_source.index("@import \"../builds/tailwind/baldur.css\";"), :<, tailwind_source.index("@import \"../stylesheets/theme.css\";")
27
+
28
+ assert_file "app/helpers/ui_helper.rb"
29
+ assert_file "config/initializers/baldur.rb"
30
+ assert_file "app/assets/stylesheets/fonts.css"
31
+ assert_file "app/assets/stylesheets/theme.css"
32
+ assert_file "app/javascript/controllers/sidebar_controller.js", /export \{ default \} from "baldur\/controllers\/sidebar_controller"/
33
+ assert_file "app/javascript/lib/snackbar.js", /export \* from "baldur\/lib\/snackbar"/
34
+ end
35
+ end
@@ -0,0 +1,21 @@
1
+ require_relative "test_helper"
2
+ require_relative "../lib/generators/baldur/install_panel_secondary/install_panel_secondary_generator"
3
+
4
+ class BaldurInstallPanelSecondaryGeneratorTest < Rails::Generators::TestCase
5
+ tests Baldur::Generators::InstallPanelSecondaryGenerator
6
+ destination File.expand_path("tmp/install_panel_secondary_generator", __dir__)
7
+ setup :prepare_destination
8
+
9
+ setup do
10
+ FileUtils.mkdir_p File.join(destination_root, "app/assets/tailwind")
11
+ File.write(File.join(destination_root, "app/assets/tailwind/application.css"), "@import \"tailwindcss\";\n@import \"../builds/tailwind/baldur.css\";\n")
12
+ end
13
+
14
+ test "adds helper and controller without touching the tailwind contract" do
15
+ run_generator
16
+
17
+ assert_file "app/helpers/panel_secondary_helper.rb", /include Baldur::Optional::PanelSecondaryHelper/
18
+ assert_file "app/javascript/controllers/panel_secondary_controller.js", /export \{ default \} from "baldur\/controllers\/panel_secondary_controller"/
19
+ assert_equal "@import \"tailwindcss\";\n@import \"../builds/tailwind/baldur.css\";\n", File.read(File.join(destination_root, "app/assets/tailwind/application.css"))
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ require_relative "test_helper"
2
+
3
+ class BaldurMarketingHelperTest < Minitest::Test
4
+ HelperHost = Struct.new(:config) do
5
+ include Baldur::MarketingHelper
6
+ end
7
+
8
+ def setup
9
+ @original_brand = Baldur.config.marketing_brand
10
+ end
11
+
12
+ def teardown
13
+ Baldur.config.marketing_brand = @original_brand
14
+ end
15
+
16
+ def test_uses_configured_brand_without_host_helper_fallback
17
+ Baldur.config.marketing_brand = {
18
+ name: "Standalone",
19
+ wordmark: "Standalone UI",
20
+ logo_src: "/standalone-logo.svg"
21
+ }
22
+
23
+ helper = HelperHost.new(Baldur.config)
24
+ resolved = helper.send(:ui_marketing_configured_brand)
25
+
26
+ assert_equal "Standalone", resolved[:name]
27
+ assert_equal "Standalone UI", resolved[:wordmark]
28
+ assert_equal "/standalone-logo.svg", resolved[:logo_src]
29
+ end
30
+
31
+ def test_returns_empty_brand_hash_when_no_brand_is_configured
32
+ Baldur.config.marketing_brand = nil
33
+
34
+ helper = HelperHost.new(Baldur.config)
35
+
36
+ assert_equal({}, helper.send(:ui_marketing_configured_brand))
37
+ end
38
+ end
data/test/run_all.rb ADDED
@@ -0,0 +1,3 @@
1
+ Dir[File.expand_path("*_test.rb", __dir__)].sort.each do |path|
2
+ require path
3
+ end
@@ -0,0 +1,9 @@
1
+ ENV["MT_NO_PLUGINS"] = "1"
2
+
3
+ require "bundler/setup"
4
+ require "minitest/autorun"
5
+ require "rails/generators/test_case"
6
+
7
+ require_relative "../lib/baldur"
8
+ require_relative "../app/helpers/baldur/render_helper"
9
+ require_relative "../app/helpers/baldur/marketing_helper"
@@ -0,0 +1,14 @@
1
+ /*
2
+ * Host font loading overrides.
3
+ *
4
+ * Load the font families your app needs here using either `@import` or
5
+ * `@font-face`. Baldur does not load web fonts directly.
6
+ *
7
+ * Default:
8
+ * - Geist for body, headings, and UI surfaces
9
+ *
10
+ * Example:
11
+ * @import url("https://fonts.googleapis.com/css2?family=Geist:wght@100..900&family=JetBrains+Mono:wght@100..800&display=swap");
12
+ */
13
+
14
+ @import url("https://fonts.googleapis.com/css2?family=Geist:wght@100..900&display=swap");
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Host theme overrides.
3
+ *
4
+ * Override only the base palette inputs below. Baldur remains the source of
5
+ * truth for semantic tokens, light/dark role mapping, and component styling.
6
+ * Use `fonts.css` to load font files, then map those loaded families to the
7
+ * font tokens below.
8
+ *
9
+ * Example:
10
+ * :root {
11
+ * --_primary-base: oklch(0.68 0.16 27);
12
+ * --_secondary-base: oklch(0.30 0.04 195);
13
+ * --_accent-base: oklch(0.48 0.07 92);
14
+ * --_neutral-base: oklch(0.87 0 0);
15
+ * --font-body: "Geist", "Inter", "Segoe UI", "Helvetica Neue", Arial, system-ui, -apple-system, sans-serif;
16
+ * --font-heading: var(--font-body);
17
+ * --font-ui: var(--font-body);
18
+ * }
19
+ */
20
+
21
+ :root {
22
+ --font-body: "Geist", "Inter", "Segoe UI", "Helvetica Neue", Arial, system-ui, -apple-system, sans-serif;
23
+ --font-heading: var(--font-body);
24
+ --font-ui: var(--font-body);
25
+ --font-family: var(--font-body);
26
+ --font-sans: var(--font-body);
27
+ }
@@ -0,0 +1,4 @@
1
+ @import "../stylesheets/fonts.css";
2
+ @import "tailwindcss";
3
+ @import "../builds/tailwind/baldur.css";
4
+ @import "../stylesheets/theme.css";
@@ -0,0 +1,4 @@
1
+ module UiHelper
2
+ include Baldur::Compatibility::UiAliases
3
+ include Baldur::MarketingHelper
4
+ end
@@ -0,0 +1 @@
1
+ export { default } from "baldur/controllers/accordion_controller"
@@ -0,0 +1 @@
1
+ export { default } from "baldur/controllers/date_field_controller"
@@ -0,0 +1 @@
1
+ export { default } from "baldur/controllers/details_menu_controller"
@@ -0,0 +1 @@
1
+ export { default } from "baldur/controllers/form_submit_controller"
@@ -0,0 +1 @@
1
+ export { default } from "baldur/controllers/marketing_pricing_controller"
@@ -0,0 +1 @@
1
+ export { default } from "baldur/controllers/marketing_tabs_controller"
@@ -0,0 +1 @@
1
+ export { default } from "baldur/controllers/menu_select_controller"
@@ -0,0 +1 @@
1
+ export { default } from "baldur/controllers/modal_controller"
@@ -0,0 +1 @@
1
+ export { default } from "baldur/controllers/segmented_tabs_controller"
@@ -0,0 +1 @@
1
+ export { default } from "baldur/controllers/sidebar_controller"
@@ -0,0 +1 @@
1
+ export { default } from "baldur/controllers/smooth_scroll_controller"
@@ -0,0 +1 @@
1
+ export { default } from "baldur/controllers/snackbar_controller"
@@ -0,0 +1 @@
1
+ export { default } from "baldur/controllers/theme_controller"
@@ -0,0 +1 @@
1
+ export { default } from "baldur/controllers/tooltip_controller"
@@ -0,0 +1 @@
1
+ export * from "baldur/lib/animation-helpers"
@@ -0,0 +1 @@
1
+ export * from "baldur/lib/dom-helpers"
@@ -0,0 +1 @@
1
+ export * from "baldur/lib/field-validation-helpers"
@@ -0,0 +1 @@
1
+ export * from "baldur/lib/focus-management"
@@ -0,0 +1 @@
1
+ export * from "baldur/lib/formatting-helpers"
@@ -0,0 +1 @@
1
+ export * from "baldur/lib/snackbar"
@@ -0,0 +1 @@
1
+ export * from "baldur/lib/storage-helpers"
@@ -0,0 +1,19 @@
1
+ require "baldur"
2
+
3
+ Baldur.configure do |config|
4
+ config.unavailable_fallback_message = "Missing metric or raw data required to compute this value."
5
+ config.theme_storage_key = "baldur.theme"
6
+ config.marketing_brand = {
7
+ name: "Your Brand",
8
+ wordmark: "Your Brand",
9
+ logo_src: "/icon.png",
10
+ logo_alt: "Your Brand logo"
11
+ }
12
+
13
+ # Supply host-specific lookups when using unavailable dependency helpers.
14
+ config.warning_dependency_resolver = ->(_warning_keys) { [] }
15
+ config.dependency_dataset_name_resolver = ->(dataset_key) { dataset_key.to_s.humanize }
16
+
17
+ # Optional integrations.
18
+ config.default_google_sign_in_path = nil
19
+ end
@@ -0,0 +1,2 @@
1
+ @import "tailwindcss";
2
+ @import "../builds/tailwind/baldur.css";
@@ -0,0 +1,3 @@
1
+ module PanelSecondaryHelper
2
+ include Baldur::Optional::PanelSecondaryHelper
3
+ end
@@ -0,0 +1 @@
1
+ export { default } from "baldur/controllers/panel_secondary_controller"