stimulus_plumbers_tailwind 0.4.4 → 0.4.8

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cc13ebbc0d54b3d0b83fe52d34b67c051244438358d02102cc8337d39c8a7916
4
- data.tar.gz: f34456ae1ab6b932d27df84124d3c4c2e40a1bcecd42a103be8894a6983951aa
3
+ metadata.gz: f570868b6706fa7a6b460b6bf78361957e3ed8a7ed3592bca0a2587966efbafe
4
+ data.tar.gz: 3ec048b9fef9972184db57cb95a121408ef3269134c4351c7f97a808f523d24e
5
5
  SHA512:
6
- metadata.gz: 071bf0b4b5d77db471480274eb802aa6cf1e429a2163393953ad94bcd4afa7d62ffc8b45b83c0ff132dd352f78e2f295990fd0d74d80c15a139369e2943557e0
7
- data.tar.gz: 5e34b159bd66b6caa3307e3dd8ec3c1f7083f992c4d8c4d5100f25a8bdb62869283a75eea332878deaee07de8edcdf3a22d2b0a5cb88dfd909a5dd36a6e89189
6
+ metadata.gz: 822d92416d88670f4c77c802cc87bd9c16b89cd17007f14a76d122cdcd9cbe7eb8224bf10ac6fbdb8d3f5c09abd9bec627633b78e43b880b5fcbd0ddcea16422
7
+ data.tar.gz: 1dda3a7595075605a20dd5739d42e39a74b1a0c3535e8c7af33ba7f85ddb2b603914b13da493ad7bd4605502e4afd0ae22eff30824eb736bbbe06c075bae314b
data/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [conventional commits](https://www.conventionalcommits.org/) for commit guidelines.
4
4
 
5
+ ---
6
+ ## [0.4.4](https://github.com/ryancyq/stimulus-plumbers/compare/stimulus-plumbers-tailwind/v0.4.3..stimulus-plumbers-tailwind/v0.4.4) - 2026-06-30
7
+
8
+ ### Dependencies
9
+
10
+ - update npm package dist to have both es + umd + source map - ([64ec309](https://github.com/ryancyq/stimulus-plumbers/commit/64ec309ca171584d1604e4e7d3d3533878ebed7a)) - Ryan Chang
11
+
5
12
  ---
6
13
  ## [0.4.3](https://github.com/ryancyq/stimulus-plumbers/compare/stimulus-plumbers-tailwind/v0.4.2..stimulus-plumbers-tailwind/v0.4.3) - 2026-06-30
7
14
 
data/README.md CHANGED
@@ -6,6 +6,8 @@
6
6
 
7
7
  Tailwind CSS v4 theme for [`stimulus_plumbers`](../stimulus-plumbers-rails). Extends the base theme with utility classes for all components.
8
8
 
9
+ See [docs/guide.md](docs/guide.md) for a quick setup/theming guide.
10
+
9
11
  ## Requirements
10
12
 
11
13
  - Ruby >= 3.0
@@ -23,7 +25,7 @@ gem "stimulus_plumbers_tailwind"
23
25
  bundle install
24
26
  ```
25
27
 
26
- Activate the theme in an initializer or `config/application.rb`:
28
+ In a Rails app, the theme registers and activates automatically — no config needed. Outside Rails, it only registers; activate it explicitly:
27
29
 
28
30
  ```ruby
29
31
  StimulusPlumbers.configure do |config|
@@ -31,10 +33,10 @@ StimulusPlumbers.configure do |config|
31
33
  end
32
34
  ```
33
35
 
34
- Run the install generator once to inject the required `@source` directive into your Tailwind CSS entry file:
36
+ Run the install generator once to inject the required `@source` directive (and the `stimulus_plumbers` tokens.css import) into your Tailwind CSS entry file:
35
37
 
36
38
  ```bash
37
- bin/rails generate stimulus_plumbers_tailwind:install
39
+ bin/rails generate stimulus_plumbers:tailwind:install
38
40
  ```
39
41
 
40
42
  The generator checks these files in order:
@@ -45,7 +47,7 @@ The generator checks these files in order:
45
47
 
46
48
  Override the detected file for both the generator and rake task with `TAILWIND_CSS_FILE=/path/to/entry.css`.
47
49
 
48
- After the initial install, the `@source` path is kept current automatically — no manual re-run needed after `bundle update`. The engine hooks `stimulus_plumbers_tailwind:install` as a prerequisite of:
50
+ After the initial install, the `@source` path is kept current automatically — no manual re-run needed after `bundle update`. The engine hooks `stimulus_plumbers:tailwind:install` as a prerequisite of:
49
51
 
50
52
  - `assets:precompile` (Sprockets and Propshaft both define this task)
51
53
  - `tailwindcss:build` (when `tailwindcss-rails` is present)
@@ -53,7 +55,7 @@ After the initial install, the `@source` path is kept current automatically —
53
55
  To trigger an update manually without a full compile (useful for debugging or after `bundle update`):
54
56
 
55
57
  ```bash
56
- bin/rails stimulus_plumbers_tailwind:install
58
+ bin/rails stimulus_plumbers:tailwind:install
57
59
  ```
58
60
 
59
61
  ## Theming
@@ -0,0 +1,50 @@
1
+ # Tailwind Theme Architecture
2
+
3
+ ## Module Layout
4
+
5
+ `TailwindTheme` extends `Base` and is split into concern modules under `StimulusPlumbers::Themes::Tailwind::*`. Each module provides CSS class resolution for one component family. The `Icon` module also owns the icon registry (`icons/`).
6
+
7
+ ## Constant Ownership Rules
8
+
9
+ - **No local aliases** — never re-export another module's constant (e.g. `MY_CONST = Other::CONST`). Reference the constant directly at the call site.
10
+ - **No prefix redundancy** — name constants after what they represent, not where they live. `Button::VARIANTS` not `Button::BUTTON_VARIANTS`; `Card::VARIANTS` not `Card::CARD_VARIANTS`.
11
+ - **Remove unused constants** — if a constant has no call sites in `schema.rb`, delete it.
12
+
13
+ ## Shared Interactive Foundation — `Control::BASE`
14
+
15
+ `Control::BASE` holds CSS shared by all focusable, disableable controls: font weight, transition, focus ring tokens, `disabled:*` states. Components include it via array splat and add their own ring color variable on top.
16
+
17
+ ```ruby
18
+ # Composition — correct
19
+ [*Control::BASE, *Button::BASE, "extra-class"].freeze
20
+
21
+ # Duplication — wrong
22
+ ["font-medium", "transition-colors", "extra-class"].freeze
23
+ ```
24
+
25
+ `Control::BASE` is always included first; never duplicate its classes in component constants.
26
+
27
+ ## Icon-Only Square Pattern
28
+
29
+ The core gem wraps button/link text in `<span>`. Icon-only renders no `<span>`. The theme detects this via CSS:
30
+
31
+ - `Button::LAYOUT` carries `[&:not(:has(>span))]:aspect-square [&:not(:has(>span))]:px-0`
32
+ - `Link::BUTTON` carries the same two classes
33
+ - `fab`/`fab_outline` types become circles via this mechanism
34
+
35
+ **Do not change the Ruby renderer's `<span>` wrapping contract without updating these theme constants.**
36
+
37
+ ## Card Style Pattern
38
+
39
+ Button, Link, Checkbox, and Radio all share a unified card style via the `--card-ring` CSS variable.
40
+
41
+ - `Card::VARIANTS` maps `:default/:success/:destructive/:warning/:info` to `--sp-color-*` values
42
+ - All card-type components reference `Card::VARIANTS.fetch(variant, Card::VARIANTS[:default])`
43
+ - **Button card** (`type: :card`) — `Button::BASE + Button::CARD + Button::TYPES[:card]`; `size:` ignored
44
+ - **Link card** — `Link::CARD` composes `Control::BASE + Card::BASE + Button::CARD`
45
+ - **Checkbox card** — input visible; label uses `has-[:checked]:border-(--card-ring)`
46
+ - **Radio card/button** — input is `hidden peer`; label uses `peer-checked:border-(--card-ring)`
47
+
48
+ ## Floating Field Key Ownership
49
+
50
+ Floating-label theme keys (`form_field_floating`, `form_field_floating_group`, `form_field_floating_label`) and their constants (`FLOATING_INPUT_*`, `FLOATING_GROUP_TYPES`, `FLOATING_LABEL_*`) live in `Form::Field` (`form/field.rb`), **not** `Form::Input`. Floating is a field-layout concern, not an input-element concern.
data/docs/guide.md ADDED
@@ -0,0 +1,22 @@
1
+ # Guide
2
+
3
+ Adding this gem registers and activates the Tailwind theme automatically in Rails — no config
4
+ needed. Outside Rails, activate it explicitly with `config.theme.use(:tailwind)`.
5
+
6
+ Run the install generator once to wire the required `@source` directive into your Tailwind CSS
7
+ entry file:
8
+
9
+ ```bash
10
+ bin/rails generate stimulus_plumbers:tailwind:install
11
+ ```
12
+
13
+ It re-runs automatically on `assets:precompile`/`tailwindcss:build` after that — see
14
+ [README.md](../README.md#installation) for file-detection order and the `TAILWIND_CSS_FILE`
15
+ override.
16
+
17
+ Icons: pass a kebab-case name to `sp_icon` or any `icon_leading:`/`icon_trailing:` option (append
18
+ `/solid` for the filled variant) — see [README.md](../README.md#icons) for aliases and the
19
+ optional `heroicons` gem.
20
+
21
+ To implement a custom theme instead of/alongside Tailwind, see
22
+ [stimulus-plumbers-rails/docs/component/theme.md](../../stimulus-plumbers-rails/docs/component/theme.md).
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "stimulus_plumbers/generators/css_entrypoint"
5
+ require "stimulus_plumbers/generators/tokens_directive"
6
+
7
+ module StimulusPlumbers
8
+ module Tailwind
9
+ module Generators
10
+ class InstallGenerator < Rails::Generators::Base
11
+ include StimulusPlumbers::Generators::CssEntrypoint
12
+
13
+ GEM_NAME = "stimulus_plumbers_tailwind"
14
+ LIB_DIR = File.expand_path("../../../..", __dir__)
15
+ TAILWIND_CSS_FILE = "TAILWIND_CSS_FILE"
16
+ CSS_CANDIDATES = %w[
17
+ app/assets/stylesheets/application.tailwind.css
18
+ app/assets/stylesheets/application.css
19
+ app/javascript/entrypoints/application.css
20
+ ].freeze
21
+
22
+ def install
23
+ css_file = entry_css_file(**css_file_lookup_options)
24
+ return warn_entry_css_not_found(label: "Tailwind CSS", **css_file_lookup_options) unless css_file
25
+
26
+ apply_edit(
27
+ css_file,
28
+ StimulusPlumbers::Generators::TokensDirective.directive,
29
+ stale_pattern: StimulusPlumbers::Generators::TokensDirective.stale_pattern
30
+ )
31
+ apply_edit(
32
+ css_file,
33
+ source_directive,
34
+ anchor_pattern: source_anchor_pattern,
35
+ stale_pattern: source_stale_pattern
36
+ )
37
+ end
38
+
39
+ private
40
+
41
+ def css_file_lookup_options
42
+ {
43
+ candidates: CSS_CANDIDATES,
44
+ env_var: TAILWIND_CSS_FILE,
45
+ fallback_env_var: StimulusPlumbers::Generators::CssEntrypoint::STIMULUS_PLUMBERS_CSS_FILE
46
+ }
47
+ end
48
+
49
+ def source_directive
50
+ %(@source "#{LIB_DIR}/**/*.rb";)
51
+ end
52
+
53
+ def source_anchor_pattern
54
+ %r{@import "tailwindcss"[^;]*;}
55
+ end
56
+
57
+ def source_stale_pattern
58
+ %r{@source "[^"]*#{Regexp.escape(GEM_NAME)}[^"]*";}
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StimulusPlumbers
4
+ module Tailwind
5
+ class Engine < ::Rails::Engine
6
+ initializer "stimulus_plumbers_tailwind.register_theme" do
7
+ StimulusPlumbers.configure do |c|
8
+ c.theme.register(:tailwind, StimulusPlumbers::Themes::TailwindTheme)
9
+ c.theme.use(:tailwind)
10
+ end
11
+ end
12
+
13
+ rake_tasks do
14
+ load File.join(__dir__, "../../tasks/stimulus_plumbers_tailwind.rake")
15
+ end
16
+ end
17
+ end
18
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module StimulusPlumbers
4
4
  module Tailwind
5
- VERSION = "0.4.4"
5
+ VERSION = "0.4.8"
6
6
  end
7
7
  end
@@ -6,7 +6,7 @@ require_relative "stimulus_plumbers/tailwind/version"
6
6
  require_relative "stimulus_plumbers/themes/tailwind_theme"
7
7
 
8
8
  if defined?(Rails::Engine)
9
- require_relative "stimulus_plumbers_tailwind/engine"
9
+ require_relative "stimulus_plumbers/tailwind/engine"
10
10
  else
11
11
  StimulusPlumbers.configure do |c|
12
12
  c.theme.register(:tailwind, StimulusPlumbers::Themes::TailwindTheme)
@@ -1,15 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- namespace :stimulus_plumbers_tailwind do
4
- desc "Add @source directive for stimulus_plumbers_tailwind into Tailwind CSS entry file"
5
- task install: :environment do
6
- require "generators/stimulus_plumbers_tailwind/install/install_generator"
7
- StimulusPlumbersTailwind::Generators::InstallGenerator.new(
8
- [], {}, { destination_root: Rails.root.to_s }
9
- ).invoke_all
3
+ namespace :stimulus_plumbers do
4
+ namespace :tailwind do
5
+ desc "Add @source directive for stimulus_plumbers_tailwind into Tailwind CSS entry file"
6
+ task(:install) do
7
+ unless ENV["STIMULUS_PLUMBERS_SKIP_INSTALL"]
8
+ require "generators/stimulus_plumbers/tailwind/install/install_generator"
9
+ StimulusPlumbers::Tailwind::Generators::InstallGenerator.new(
10
+ [], {}, { destination_root: Rails.root.to_s }
11
+ ).invoke_all
12
+ end
13
+ end
10
14
  end
11
15
  end
12
16
 
13
- Rake::Task["assets:precompile"].enhance(["stimulus_plumbers_tailwind:install"]) if Rake::Task.task_defined?("assets:precompile")
17
+ Rake::Task["stimulus_plumbers:tailwind:install"].enhance(["environment"]) unless ENV["STIMULUS_PLUMBERS_SKIP_INSTALL"]
14
18
 
15
- Rake::Task["tailwindcss:build"].enhance(["stimulus_plumbers_tailwind:install"]) if Rake::Task.task_defined?("tailwindcss:build")
19
+ # Hooks into these tasks as a prerequisite; Rake merges rather than overwrites, so order-independent.
20
+ task "assets:precompile" => ["stimulus_plumbers:tailwind:install"]
21
+ task "tailwindcss:build" => ["stimulus_plumbers:tailwind:install"]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stimulus_plumbers_tailwind
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: 0.4.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Chang
@@ -33,7 +33,10 @@ files:
33
33
  - CHANGELOG.md
34
34
  - LICENSE-DEPENDENCIES
35
35
  - README.md
36
- - lib/generators/stimulus_plumbers_tailwind/install/install_generator.rb
36
+ - docs/architecture.md
37
+ - docs/guide.md
38
+ - lib/generators/stimulus_plumbers/tailwind/install/install_generator.rb
39
+ - lib/stimulus_plumbers/tailwind/engine.rb
37
40
  - lib/stimulus_plumbers/tailwind/version.rb
38
41
  - lib/stimulus_plumbers/themes/tailwind/avatar.rb
39
42
  - lib/stimulus_plumbers/themes/tailwind/button.rb
@@ -704,7 +707,6 @@ files:
704
707
  - lib/stimulus_plumbers/themes/tailwind/timeline/group.rb
705
708
  - lib/stimulus_plumbers/themes/tailwind_theme.rb
706
709
  - lib/stimulus_plumbers_tailwind.rb
707
- - lib/stimulus_plumbers_tailwind/engine.rb
708
710
  - lib/tasks/stimulus_plumbers_tailwind.rake
709
711
  homepage: https://github.com/ryancyq/stimulus-plumbers
710
712
  licenses:
@@ -1,78 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rails/generators"
4
-
5
- module StimulusPlumbersTailwind
6
- module Generators
7
- class InstallGenerator < Rails::Generators::Base
8
- GEM_NAME = "stimulus_plumbers_tailwind"
9
- TAILWIND_CSS_FILE = "TAILWIND_CSS_FILE"
10
- CSS_CANDIDATES = %w[
11
- app/assets/stylesheets/application.tailwind.css
12
- app/assets/stylesheets/application.css
13
- app/javascript/entrypoints/application.css
14
- ].freeze
15
-
16
- def install
17
- css_file = entry_css_file
18
- return warn_entry_css_not_found unless css_file
19
-
20
- apply_edit(css_file)
21
- end
22
-
23
- private
24
-
25
- def warn_entry_css_not_found
26
- tried = CSS_CANDIDATES.map { |c| File.join(destination_root, c) }
27
- tried.unshift(File.expand_path(ENV[TAILWIND_CSS_FILE])) if ENV[TAILWIND_CSS_FILE]
28
- say "Could not find a Tailwind CSS entry file. Tried: #{tried.join(", ")}. " \
29
- "Set #{TAILWIND_CSS_FILE}=/path/to/entry.css and re-run.",
30
- :red
31
- end
32
-
33
- def apply_edit(css_file)
34
- content = File.read(css_file)
35
- new_content, status = content_edit(content, source_directive)
36
-
37
- if new_content
38
- File.write(css_file, new_content)
39
- say_status status, relative_to_destination(css_file), :green
40
- else
41
- say_status :identical, relative_to_destination(css_file)
42
- end
43
- end
44
-
45
- def content_edit(content, source_line)
46
- if content.include?(source_line)
47
- nil
48
- elsif (existing = content.match(%r{@source "[^"]*#{Regexp.escape(GEM_NAME)}[^"]*";}))
49
- [content.sub(existing[0], source_line), :update]
50
- elsif (import_line = content.match(%r{@import "tailwindcss"[^;]*;}))
51
- [content.sub(import_line[0], "#{import_line[0]}\n#{source_line}"), :insert]
52
- else
53
- ["#{content.rstrip}\n#{source_line}\n", :append]
54
- end
55
- end
56
-
57
- def source_directive
58
- spec = Gem.loaded_specs[GEM_NAME]
59
- %(@source "#{spec.gem_dir}/lib/**/*.rb";)
60
- end
61
-
62
- def entry_css_file
63
- if ENV[TAILWIND_CSS_FILE]
64
- path = File.expand_path(ENV[TAILWIND_CSS_FILE])
65
- return path if File.exist?(path)
66
- end
67
-
68
- CSS_CANDIDATES
69
- .map { |c| File.join(destination_root, c) }
70
- .find { |f| File.exist?(f) }
71
- end
72
-
73
- def relative_to_destination(path)
74
- path.delete_prefix("#{destination_root}/")
75
- end
76
- end
77
- end
78
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StimulusPlumbersTailwind
4
- class Engine < ::Rails::Engine
5
- initializer "stimulus_plumbers_tailwind.register_theme" do
6
- StimulusPlumbers.configure do |c|
7
- c.theme.register(:tailwind, StimulusPlumbers::Themes::TailwindTheme)
8
- end
9
- end
10
-
11
- rake_tasks do
12
- load File.join(__dir__, "../tasks/stimulus_plumbers_tailwind.rake")
13
- end
14
- end
15
- end