kiso 0.3.0.pre → 0.4.0.pre

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 (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -1
  3. data/README.md +16 -3
  4. data/app/assets/tailwind/kiso/engine.css +4 -3
  5. data/app/assets/tailwind/kiso/palettes/blue.css +65 -0
  6. data/app/assets/tailwind/kiso/palettes/green.css +65 -0
  7. data/app/assets/tailwind/kiso/palettes/orange.css +65 -0
  8. data/app/assets/tailwind/kiso/palettes/violet.css +65 -0
  9. data/app/assets/tailwind/kiso/palettes/zinc.css +65 -0
  10. data/app/helpers/kiso/app_component_helper.rb +53 -0
  11. data/app/helpers/kiso/component_helper.rb +110 -24
  12. data/app/helpers/kiso/ui_context_helper.rb +59 -0
  13. data/app/javascript/controllers/kiso/alert_controller.js +33 -0
  14. data/app/javascript/controllers/kiso/index.js +3 -0
  15. data/app/views/kiso/components/_alert.html.erb +19 -3
  16. data/app/views/kiso/components/_alert_dialog.html.erb +2 -2
  17. data/app/views/kiso/components/_app.html.erb +7 -0
  18. data/app/views/kiso/components/_avatar.html.erb +3 -3
  19. data/app/views/kiso/components/_breadcrumb.html.erb +1 -1
  20. data/app/views/kiso/components/_color_mode_button.html.erb +1 -1
  21. data/app/views/kiso/components/_color_mode_select.html.erb +4 -4
  22. data/app/views/kiso/components/_container.html.erb +7 -0
  23. data/app/views/kiso/components/_dashboard_sidebar.html.erb +1 -1
  24. data/app/views/kiso/components/_dialog.html.erb +2 -2
  25. data/app/views/kiso/components/_footer.html.erb +7 -0
  26. data/app/views/kiso/components/_header.html.erb +7 -0
  27. data/app/views/kiso/components/_main.html.erb +7 -0
  28. data/app/views/kiso/components/_page.html.erb +7 -0
  29. data/app/views/kiso/components/_page_body.html.erb +7 -0
  30. data/app/views/kiso/components/_page_card.html.erb +40 -0
  31. data/app/views/kiso/components/_page_grid.html.erb +7 -0
  32. data/app/views/kiso/components/_page_header.html.erb +38 -0
  33. data/app/views/kiso/components/_page_section.html.erb +11 -0
  34. data/app/views/kiso/components/_pagination.html.erb +1 -1
  35. data/app/views/kiso/components/_select_native.html.erb +3 -3
  36. data/app/views/kiso/components/_skeleton.html.erb +5 -0
  37. data/app/views/kiso/components/_slider.html.erb +4 -4
  38. data/app/views/kiso/components/_switch.html.erb +2 -2
  39. data/app/views/kiso/components/alert/_actions.html.erb +7 -0
  40. data/app/views/kiso/components/breadcrumb/_ellipsis.html.erb +1 -1
  41. data/app/views/kiso/components/combobox/_input.html.erb +1 -1
  42. data/app/views/kiso/components/combobox/_item.html.erb +2 -2
  43. data/app/views/kiso/components/combobox/_list.html.erb +2 -1
  44. data/app/views/kiso/components/command/_group.html.erb +2 -2
  45. data/app/views/kiso/components/command/_input.html.erb +3 -2
  46. data/app/views/kiso/components/command/_list.html.erb +2 -1
  47. data/app/views/kiso/components/dashboard_navbar/_toggle.html.erb +1 -1
  48. data/app/views/kiso/components/dashboard_sidebar/_collapse.html.erb +1 -1
  49. data/app/views/kiso/components/dashboard_sidebar/_toggle.html.erb +1 -1
  50. data/app/views/kiso/components/dialog/_close.html.erb +1 -1
  51. data/app/views/kiso/components/nav/_item.html.erb +2 -2
  52. data/app/views/kiso/components/nav/_section.html.erb +5 -5
  53. data/app/views/kiso/components/page/_center.html.erb +7 -0
  54. data/app/views/kiso/components/page/_left.html.erb +7 -0
  55. data/app/views/kiso/components/page/_right.html.erb +7 -0
  56. data/app/views/kiso/components/page_card/_body.html.erb +7 -0
  57. data/app/views/kiso/components/page_card/_description.html.erb +7 -0
  58. data/app/views/kiso/components/page_card/_footer.html.erb +7 -0
  59. data/app/views/kiso/components/page_card/_header.html.erb +7 -0
  60. data/app/views/kiso/components/page_card/_icon.html.erb +7 -0
  61. data/app/views/kiso/components/page_card/_title.html.erb +7 -0
  62. data/app/views/kiso/components/page_header/_description.html.erb +7 -0
  63. data/app/views/kiso/components/page_header/_headline.html.erb +7 -0
  64. data/app/views/kiso/components/page_header/_links.html.erb +7 -0
  65. data/app/views/kiso/components/page_header/_title.html.erb +7 -0
  66. data/app/views/kiso/components/page_section/_body.html.erb +7 -0
  67. data/app/views/kiso/components/page_section/_description.html.erb +7 -0
  68. data/app/views/kiso/components/page_section/_header.html.erb +7 -0
  69. data/app/views/kiso/components/page_section/_headline.html.erb +7 -0
  70. data/app/views/kiso/components/page_section/_links.html.erb +7 -0
  71. data/app/views/kiso/components/page_section/_title.html.erb +7 -0
  72. data/app/views/kiso/components/page_section/_wrapper.html.erb +7 -0
  73. data/app/views/kiso/components/pagination/_ellipsis.html.erb +1 -1
  74. data/app/views/kiso/components/pagination/_next.html.erb +2 -2
  75. data/app/views/kiso/components/pagination/_previous.html.erb +2 -2
  76. data/app/views/kiso/components/select/_item.html.erb +2 -2
  77. data/config/locales/en.yml +33 -0
  78. data/lib/generators/kiso/component/USAGE +35 -0
  79. data/lib/generators/kiso/component/component_generator.rb +104 -0
  80. data/lib/generators/kiso/component/templates/partial.html.erb.tt +7 -0
  81. data/lib/generators/kiso/component/templates/sub_part_partial.html.erb.tt +7 -0
  82. data/lib/generators/kiso/component/templates/sub_part_theme.rb.tt +21 -0
  83. data/lib/generators/kiso/component/templates/theme.rb.tt +21 -0
  84. data/lib/kiso/configuration.rb +40 -0
  85. data/lib/kiso/engine.rb +105 -1
  86. data/lib/kiso/presets/rounded.rb +136 -0
  87. data/lib/kiso/presets/sharp.rb +178 -0
  88. data/lib/kiso/presets.rb +49 -0
  89. data/lib/kiso/theme_overrides.rb +5 -1
  90. data/lib/kiso/themes/alert.rb +24 -11
  91. data/lib/kiso/themes/dashboard.rb +1 -1
  92. data/lib/kiso/themes/layout.rb +69 -0
  93. data/lib/kiso/themes/page.rb +295 -0
  94. data/lib/kiso/themes/skeleton.rb +16 -0
  95. data/lib/kiso/version.rb +1 -1
  96. data/lib/kiso.rb +7 -0
  97. metadata +63 -1
@@ -1,17 +1,17 @@
1
- <%# locals: (title: nil, open: true, collapsible: true, css_classes: "", **component_options) %>
1
+ <%# locals: (title: nil, open: true, collapsible: true, ui: {}, css_classes: "", **component_options) %>
2
2
  <% if title && collapsible %>
3
3
  <%= content_tag :details,
4
4
  class: Kiso::Themes::NavSection.render(class: css_classes),
5
5
  data: kiso_prepare_options(component_options, slot: "nav-section"),
6
6
  open: open,
7
7
  **component_options do %>
8
- <summary class="<%= Kiso::Themes::NavSectionTitle.render %>" data-slot="nav-section-title">
8
+ <summary class="<%= Kiso::Themes::NavSectionTitle.render(class: ui[:title]) %>" data-slot="nav-section-title">
9
9
  <span class="truncate"><%= title %></span>
10
10
  <span class="ml-auto" data-slot="nav-section-chevron">
11
11
  <%= kiso_component_icon(:chevron_down, class: "size-4") %>
12
12
  </span>
13
13
  </summary>
14
- <div data-slot="nav-section-content" class="<%= Kiso::Themes::NavSectionContent.render %>">
14
+ <div data-slot="nav-section-content" class="<%= Kiso::Themes::NavSectionContent.render(class: ui[:content]) %>">
15
15
  <%= yield %>
16
16
  </div>
17
17
  <% end %>
@@ -20,10 +20,10 @@
20
20
  class: Kiso::Themes::NavSection.render(class: css_classes),
21
21
  data: kiso_prepare_options(component_options, slot: "nav-section"),
22
22
  **component_options do %>
23
- <div class="<%= Kiso::Themes::NavSectionTitle.render %>" data-slot="nav-section-title">
23
+ <div class="<%= Kiso::Themes::NavSectionTitle.render(class: ui[:title]) %>" data-slot="nav-section-title">
24
24
  <span class="truncate"><%= title %></span>
25
25
  </div>
26
- <div data-slot="nav-section-content" class="<%= Kiso::Themes::NavSectionContent.render %>">
26
+ <div data-slot="nav-section-content" class="<%= Kiso::Themes::NavSectionContent.render(class: ui[:content]) %>">
27
27
  <%= yield %>
28
28
  </div>
29
29
  <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::PageCenter.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-center"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :aside,
3
+ class: Kiso::Themes::PageLeft.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-left"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :aside,
3
+ class: Kiso::Themes::PageRight.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-right"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::PageCardBody.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-card-body"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :p,
3
+ class: Kiso::Themes::PageCardDescription.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-card-description"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::PageCardFooter.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-card-footer"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::PageCardHeader.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-card-header"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::PageCardIcon.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-card-icon"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :p,
3
+ class: Kiso::Themes::PageCardTitle.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-card-title"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :p,
3
+ class: Kiso::Themes::PageHeaderDescription.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-header-description"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::PageHeaderHeadline.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-header-headline"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::PageHeaderLinks.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-header-links"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :h1,
3
+ class: Kiso::Themes::PageHeaderTitle.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-header-title"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::PageSectionBody.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-section-body"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (orientation: :horizontal, css_classes: "", **component_options) %>
2
+ <%= content_tag :p,
3
+ class: Kiso::Themes::PageSectionDescription.render(orientation: orientation, class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-section-description"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::PageSectionHeader.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-section-header"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (orientation: :horizontal, css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::PageSectionHeadline.render(orientation: orientation, class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-section-headline"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (orientation: :horizontal, css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::PageSectionLinks.render(orientation: orientation, class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-section-links"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (orientation: :horizontal, css_classes: "", **component_options) %>
2
+ <%= content_tag :h2,
3
+ class: Kiso::Themes::PageSectionTitle.render(orientation: orientation, class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-section-title"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%# locals: (order: :first, css_classes: "", **component_options) %>
2
+ <%= content_tag :div,
3
+ class: Kiso::Themes::PageSectionWrapper.render(order: order, class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "page-section-wrapper"),
5
+ **component_options do %>
6
+ <%= yield %>
7
+ <% end %>
@@ -5,5 +5,5 @@
5
5
  data: kiso_prepare_options(component_options, slot: "pagination-ellipsis"),
6
6
  **component_options do %>
7
7
  <%= kiso_component_icon(:ellipsis, size: :sm) %>
8
- <%= content_tag :span, "More pages", class: "sr-only" %>
8
+ <%= content_tag :span, t("kiso.pagination.more_pages"), class: "sr-only" %>
9
9
  <% end %>
@@ -1,5 +1,5 @@
1
1
  <%# locals: (href: "#", active: false, css_classes: "", **component_options) %>
2
- <% aria_attrs = {label: "Go to next page"}
2
+ <% aria_attrs = {label: t("kiso.pagination.next_page")}
3
3
  aria_attrs[:current] = "page" if active %>
4
4
  <%= content_tag :a,
5
5
  href: href,
@@ -7,6 +7,6 @@
7
7
  class: Kiso::Themes::PaginationNext.render(active: active, class: css_classes),
8
8
  data: kiso_prepare_options(component_options, slot: "pagination-next"),
9
9
  **component_options do %>
10
- <%= content_tag :span, "Next", class: "hidden sm:block" %>
10
+ <%= content_tag :span, t("kiso.pagination.next"), class: "hidden sm:block" %>
11
11
  <%= kiso_component_icon(:chevron_right) %>
12
12
  <% end %>
@@ -1,5 +1,5 @@
1
1
  <%# locals: (href: "#", active: false, css_classes: "", **component_options) %>
2
- <% aria_attrs = {label: "Go to previous page"}
2
+ <% aria_attrs = {label: t("kiso.pagination.previous_page")}
3
3
  aria_attrs[:current] = "page" if active %>
4
4
  <%= content_tag :a,
5
5
  href: href,
@@ -8,5 +8,5 @@
8
8
  data: kiso_prepare_options(component_options, slot: "pagination-previous"),
9
9
  **component_options do %>
10
10
  <%= kiso_component_icon(:chevron_left) %>
11
- <%= content_tag :span, "Previous", class: "hidden sm:block" %>
11
+ <%= content_tag :span, t("kiso.pagination.previous"), class: "hidden sm:block" %>
12
12
  <% end %>
@@ -1,4 +1,4 @@
1
- <%# locals: (value:, disabled: false, css_classes: "", **component_options) %>
1
+ <%# locals: (value:, disabled: false, ui: {}, css_classes: "", **component_options) %>
2
2
  <%= content_tag :div,
3
3
  class: Kiso::Themes::SelectItem.render(class: css_classes),
4
4
  role: "option",
@@ -10,7 +10,7 @@
10
10
  disabled: (disabled ? "true" : nil)),
11
11
  aria: {selected: false, disabled: (disabled || nil)},
12
12
  **component_options do %>
13
- <%= tag.span class: Kiso::Themes::SelectItemIndicator.render,
13
+ <%= tag.span class: Kiso::Themes::SelectItemIndicator.render(class: ui[:indicator]),
14
14
  data: { slot: "select-item-indicator", kiso__select_target: "indicator" },
15
15
  hidden: true do %>
16
16
  <%= kiso_component_icon(:check, class: "size-4") %>
@@ -0,0 +1,33 @@
1
+ en:
2
+ kiso:
3
+ alert:
4
+ dismiss: "Dismiss"
5
+ breadcrumb:
6
+ label: "breadcrumb"
7
+ more: "More"
8
+ color_mode_button:
9
+ toggle: "Toggle color mode"
10
+ color_mode_select:
11
+ theme: "Theme"
12
+ system: "System"
13
+ light: "Light"
14
+ dark: "Dark"
15
+ combobox:
16
+ toggle: "Toggle"
17
+ options: "Options"
18
+ command:
19
+ search: "Search"
20
+ suggestions: "Suggestions"
21
+ dashboard_sidebar:
22
+ label: "Sidebar navigation"
23
+ toggle: "Toggle sidebar"
24
+ collapse: "Collapse sidebar"
25
+ dialog:
26
+ close: "Close"
27
+ pagination:
28
+ label: "pagination"
29
+ more_pages: "More pages"
30
+ next: "Next"
31
+ next_page: "Go to next page"
32
+ previous: "Previous"
33
+ previous_page: "Go to previous page"
@@ -0,0 +1,35 @@
1
+ Description:
2
+ Scaffolds a component with a ClassVariants theme module and ERB partial.
3
+ Components are rendered using the appui() helper.
4
+
5
+ Theme files are placed in app/themes/<active_theme>/ (default: app/themes/default/).
6
+ The active theme is set via Kiso.config.app_theme.
7
+
8
+ Examples:
9
+ bin/rails generate kiso:component pricing_card
10
+
11
+ Creates:
12
+ app/themes/default/pricing_card.rb
13
+ app/views/components/_pricing_card.html.erb
14
+
15
+ bin/rails generate kiso:component pricing_card --sub-parts header footer
16
+
17
+ Creates:
18
+ app/themes/default/pricing_card.rb
19
+ app/themes/default/pricing_card_header.rb
20
+ app/themes/default/pricing_card_footer.rb
21
+ app/views/components/_pricing_card.html.erb
22
+ app/views/components/pricing_card/_header.html.erb
23
+ app/views/components/pricing_card/_footer.html.erb
24
+
25
+ bin/rails generate kiso:component pricing_card --theme modern
26
+
27
+ Creates theme files in app/themes/modern/ instead of app/themes/default/.
28
+
29
+ Usage:
30
+ appui(:pricing_card) { "Content" }
31
+
32
+ appui(:pricing_card) do
33
+ appui(:pricing_card, :header) { "Title" }
34
+ appui(:pricing_card, :footer) { "Actions" }
35
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kiso
4
+ module Generators
5
+ # Scaffolds a component with a ClassVariants theme module and ERB partial.
6
+ #
7
+ # Theme files are placed in +app/themes/<active_theme>/+ (default:
8
+ # +app/themes/default/+). The active theme is configured via
9
+ # +Kiso.config.app_theme+. Components are rendered using the +appui()+
10
+ # helper.
11
+ #
12
+ # @example Basic usage
13
+ # bin/rails generate kiso:component pricing_card
14
+ #
15
+ # @example With sub-parts
16
+ # bin/rails generate kiso:component pricing_card --sub-parts header footer
17
+ #
18
+ # @example With a custom theme
19
+ # bin/rails generate kiso:component pricing_card --theme modern
20
+ class ComponentGenerator < Rails::Generators::NamedBase
21
+ source_root File.expand_path("templates", __dir__)
22
+
23
+ class_option :sub_parts,
24
+ type: :array,
25
+ default: [],
26
+ desc: "Sub-part names to generate (e.g. --sub-parts header footer)"
27
+
28
+ class_option :theme,
29
+ type: :string,
30
+ default: nil,
31
+ desc: "Theme directory name (defaults to Kiso.config.app_theme, usually :default)"
32
+
33
+ def create_theme_file
34
+ template "theme.rb.tt", File.join(theme_dir, component_path_dir, "#{file_name}.rb")
35
+ end
36
+
37
+ def create_partial_file
38
+ template "partial.html.erb.tt",
39
+ File.join("app/views/components", component_path_dir, "_#{file_name}.html.erb")
40
+ end
41
+
42
+ def create_sub_part_files
43
+ options[:sub_parts].each do |part|
44
+ @current_part = part
45
+ template "sub_part_theme.rb.tt",
46
+ File.join(theme_dir, component_path_dir, "#{file_name}_#{part}.rb")
47
+ template "sub_part_partial.html.erb.tt",
48
+ File.join("app/views/components", component_path_dir, file_name, "_#{part}.html.erb")
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ # @return [String] the current sub-part name being generated
55
+ attr_reader :current_part
56
+
57
+ # @return [String] the theme directory path (e.g. "app/themes/default")
58
+ def theme_dir
59
+ name = (options[:theme] || Kiso.config.app_theme).to_s
60
+ File.join("app/themes", name)
61
+ end
62
+
63
+ # @return [String] the component name in PascalCase (e.g. "PricingCard")
64
+ def class_name_without_namespace
65
+ file_name.camelize
66
+ end
67
+
68
+ # @return [String] the kebab-case data-slot value (e.g. "pricing-card")
69
+ def slot_name
70
+ file_name.dasherize
71
+ end
72
+
73
+ # @return [String] the kebab-case data-slot value for a sub-part (e.g. "pricing-card-header")
74
+ def sub_part_slot_name
75
+ "#{slot_name}-#{current_part.dasherize}"
76
+ end
77
+
78
+ # @return [String] the PascalCase theme constant name for a sub-part (e.g. "PricingCardHeader")
79
+ def sub_part_class_name
80
+ "#{class_name_without_namespace}#{current_part.camelize}"
81
+ end
82
+
83
+ # @return [Array<String>] namespace segments from the name argument
84
+ def component_class_path
85
+ regular_class_path
86
+ end
87
+
88
+ # @return [String] namespace directory path (empty string for simple names)
89
+ def component_path_dir
90
+ component_class_path.join("/")
91
+ end
92
+
93
+ # @return [String] full module nesting prefix (e.g. "Admin::" for admin/pricing_card)
94
+ def module_prefix
95
+ component_class_path.map(&:camelize).join("::")
96
+ end
97
+
98
+ # @return [Boolean] whether the component has a namespace prefix (e.g. admin/pricing_card)
99
+ def has_namespace?
100
+ component_class_path.any?
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,7 @@
1
+ <%% # locals: (css_classes: "", **component_options) %>
2
+ <%%= content_tag :div,
3
+ class: AppThemes::<%= has_namespace? ? "#{module_prefix}::" : "" %><%= class_name_without_namespace %>.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "<%= slot_name %>"),
5
+ **component_options do %>
6
+ <%%= yield %>
7
+ <%% end %>
@@ -0,0 +1,7 @@
1
+ <%% # locals: (css_classes: "", **component_options) %>
2
+ <%%= content_tag :div,
3
+ class: AppThemes::<%= has_namespace? ? "#{module_prefix}::" : "" %><%= sub_part_class_name %>.render(class: css_classes),
4
+ data: kiso_prepare_options(component_options, slot: "<%= sub_part_slot_name %>"),
5
+ **component_options do %>
6
+ <%%= yield %>
7
+ <%% end %>
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ <% if has_namespace? -%>
4
+ <% component_class_path.each_with_index do |segment, i| -%>
5
+ <%= " " * i %>module AppThemes::<%= segment.camelize %>
6
+ <% end -%>
7
+ <%= " " * component_class_path.size %><%= sub_part_class_name %> = ClassVariants.build(
8
+ <%= " " * component_class_path.size %> base: "",
9
+ <%= " " * component_class_path.size %> variants: {},
10
+ <%= " " * component_class_path.size %> defaults: {}
11
+ <%= " " * component_class_path.size %>)
12
+ <% component_class_path.each_with_index do |_, i| -%>
13
+ <%= " " * (component_class_path.size - 1 - i) %>end
14
+ <% end -%>
15
+ <% else -%>
16
+ AppThemes::<%= sub_part_class_name %> = ClassVariants.build(
17
+ base: "",
18
+ variants: {},
19
+ defaults: {}
20
+ )
21
+ <% end -%>
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ <% if has_namespace? -%>
4
+ <% component_class_path.each_with_index do |segment, i| -%>
5
+ <%= " " * i %>module AppThemes::<%= segment.camelize %>
6
+ <% end -%>
7
+ <%= " " * component_class_path.size %><%= class_name_without_namespace %> = ClassVariants.build(
8
+ <%= " " * component_class_path.size %> base: "",
9
+ <%= " " * component_class_path.size %> variants: {},
10
+ <%= " " * component_class_path.size %> defaults: {}
11
+ <%= " " * component_class_path.size %>)
12
+ <% component_class_path.each_with_index do |_, i| -%>
13
+ <%= " " * (component_class_path.size - 1 - i) %>end
14
+ <% end -%>
15
+ <% else -%>
16
+ AppThemes::<%= class_name_without_namespace %> = ClassVariants.build(
17
+ base: "",
18
+ variants: {},
19
+ defaults: {}
20
+ )
21
+ <% end -%>
@@ -23,9 +23,49 @@ module Kiso
23
23
  # Applied once at boot by {ThemeOverrides.apply!}.
24
24
  attr_reader :theme
25
25
 
26
+ # @return [Symbol] the active app theme directory name.
27
+ # Theme files are loaded from +app/themes/<name>/+. Defaults to
28
+ # +:default+, meaning +app/themes/default/+.
29
+ #
30
+ # @example Switch to a custom theme
31
+ # Kiso.configure do |config|
32
+ # config.app_theme = :modern
33
+ # end
34
+ attr_accessor :app_theme
35
+
26
36
  def initialize
27
37
  @icons = default_icons
28
38
  @theme = {}
39
+ @app_theme = :default
40
+ end
41
+
42
+ # Resolves the active app theme directory path relative to the given root.
43
+ #
44
+ # @param app_root [Pathname] the Rails application root
45
+ # @return [Pathname] the active theme directory (e.g. +app/themes/default+)
46
+ def app_theme_path(app_root)
47
+ app_root.join("app/themes", app_theme.to_s)
48
+ end
49
+
50
+ # Applies a pre-built style preset to all components.
51
+ # Presets populate +@theme+ before {ThemeOverrides.apply!} runs,
52
+ # so host-app overrides set after this call take priority.
53
+ #
54
+ # @param name [Symbol, String] the preset name (e.g. +:rounded+, +:sharp+)
55
+ # @raise [ArgumentError] if the preset does not exist
56
+ # @return [void]
57
+ #
58
+ # @example
59
+ # Kiso.configure do |config|
60
+ # config.apply_preset(:rounded)
61
+ # # Per-component overrides still work on top of the preset:
62
+ # config.theme[:button] = { base: "shadow-lg" }
63
+ # end
64
+ def apply_preset(name)
65
+ preset = Kiso::Presets.load(name)
66
+ preset.each do |component, overrides|
67
+ @theme[component] = (@theme[component] || {}).merge(overrides)
68
+ end
29
69
  end
30
70
 
31
71
  private