phlex_kit 0.2.2 → 0.4.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -5
  3. data/app/components/phlex_kit/sidebar/sidebar.css +57 -0
  4. data/app/components/phlex_kit/sidebar/sidebar.rb +5 -5
  5. data/app/components/phlex_kit/sidebar/sidebar_controller.js +24 -0
  6. data/app/components/phlex_kit/sidebar/sidebar_trigger.rb +23 -0
  7. data/app/components/phlex_kit/sidebar/sidebar_wrapper.rb +37 -2
  8. data/app/javascript/phlex_kit/controllers/index.js +2 -0
  9. data/config/importmap.rb +17 -3
  10. data/lib/generators/phlex_kit/component/component_generator.rb +42 -10
  11. data/lib/phlex_kit/engine.rb +7 -2
  12. data/lib/phlex_kit/version.rb +1 -1
  13. metadata +41 -39
  14. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/accordion}/accordion_controller.js +0 -0
  15. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/alert_dialog}/alert_dialog_controller.js +0 -0
  16. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/attachment}/scroll_fade_controller.js +0 -0
  17. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/avatar}/avatar_controller.js +0 -0
  18. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/calendar}/calendar_controller.js +0 -0
  19. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/calendar}/calendar_input_controller.js +0 -0
  20. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/carousel}/carousel_controller.js +0 -0
  21. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/chart}/chart_controller.js +0 -0
  22. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/clipboard}/clipboard_controller.js +0 -0
  23. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/collapsible}/collapsible_controller.js +0 -0
  24. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/combobox}/combobox_controller.js +0 -0
  25. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/command}/command_controller.js +0 -0
  26. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/command}/command_dialog_controller.js +0 -0
  27. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/context_menu}/context_menu_controller.js +0 -0
  28. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/data_table}/data_table_column_visibility_controller.js +0 -0
  29. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/data_table}/data_table_controller.js +0 -0
  30. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/data_table}/data_table_search_controller.js +0 -0
  31. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/dialog}/dialog_controller.js +0 -0
  32. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/dropdown_menu}/dropdown_menu_controller.js +0 -0
  33. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/form_field}/form_field_controller.js +0 -0
  34. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/hover_card}/hover_card_controller.js +0 -0
  35. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/input_otp}/input_otp_controller.js +0 -0
  36. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/masked_input}/masked_input_controller.js +0 -0
  37. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/menubar}/menubar_controller.js +0 -0
  38. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/message_scroller}/message_scroller_controller.js +0 -0
  39. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/popover}/popover_controller.js +0 -0
  40. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/resizable}/resizable_controller.js +0 -0
  41. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/select}/select_controller.js +0 -0
  42. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/select}/select_item_controller.js +0 -0
  43. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/sheet}/sheet_content_controller.js +0 -0
  44. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/sheet}/sheet_controller.js +0 -0
  45. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/slider}/slider_controller.js +0 -0
  46. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/tabs}/tabs_controller.js +0 -0
  47. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/theme_toggle}/theme_toggle_controller.js +0 -0
  48. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/toast}/toast_controller.js +0 -0
  49. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/toast}/toaster_controller.js +0 -0
  50. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/toggle}/toggle_controller.js +0 -0
  51. /data/app/{javascript/phlex_kit/controllers → components/phlex_kit/toggle_group}/toggle_group_controller.js +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f6988a4f8e3f47462f9f83824ed6542cafded9d656adb10340e7eb618156063
4
- data.tar.gz: ca293b01074cfa84962df3c80683e3df5ae36cf5a919b1e8c0bcd1861948b52c
3
+ metadata.gz: dabd58e18372455c16ef319dc2f6270469ea2bbacfa42f2418f1e82f127d57cb
4
+ data.tar.gz: 04b6f68484015c542bfb65d24322c9342ec029d4d3d322f80dca0f571bbdcba0
5
5
  SHA512:
6
- metadata.gz: fd26ed3b6aef6bf015c7fbdf574516a68e8eb10fe1cfe1356a4292420d01917977428d2b35a301b65e6a8ff19c73daf5ac9ffdfb9af6abae6f96afd4818d7c81
7
- data.tar.gz: 6d6c3d42730c2ce500a6f8c8e49afab8e11ec192f87bf9d87434761d334b40e1a762cc157ad7b38b2914edbffeae9fea501235f1cdc0ec6937c88a8f843399fa
6
+ metadata.gz: d7ffa228298fa3583da83586982aa28404e1c87979b5c839123c6f493da0e6ce8502b9df6a40b58ba73cd11276a06c3e2c96a081bd82057b903dfd5f9d4dddab
7
+ data.tar.gz: fee2a8edf8f4ad0da4ab8ee42da82316ee0a6674f689f9f1c6025b7efd097c4a557e788dbe725683c5ecdbe49635735cab086a798c39d104550bc17dbb017b70
data/README.md CHANGED
@@ -9,6 +9,16 @@ instead of Tailwind**. The full [ruby_ui](https://ruby-ui.com) catalog plus
9
9
  shadcn's own additions — 70 component families, 38 Stimulus controllers —
10
10
  with the default theme lifted verbatim from shadcn/ui's current token system.
11
11
 
12
+ <picture>
13
+ <source media="(prefers-color-scheme: dark)" srcset="docs/images/create-page-dark.png">
14
+ <source media="(prefers-color-scheme: light)" srcset="docs/images/create-page-light.png">
15
+ <img alt="The docs site's /create page — shadcn/ui's theme-builder demo rebuilt entirely from PhlexKit components" src="docs/images/create-page-light.png">
16
+ </picture>
17
+
18
+ *Every pixel above is PhlexKit: [shadcn's /create demo](https://ui.shadcn.com/create)
19
+ rebuilt in the dummy app from kit components — cards, charts, sliders,
20
+ switches, nav menu, command palette — at `/create` in [the docs site](#the-docs-site).*
21
+
12
22
  - **No build step.** Components are plain Ruby classes with co-located vanilla
13
23
  CSS, served precompiled-static through Propshaft. No Tailwind, no Node, no
14
24
  PostCSS.
@@ -52,6 +62,11 @@ registerPhlexKitControllers(application)
52
62
 
53
63
  That's it — no Tailwind config, no content globs, no bundler.
54
64
 
65
+ For a full step-by-step walkthrough on the default Propshaft + importmap stack —
66
+ including how the `@import` chain and the Stimulus registration wire up, and how
67
+ to verify the install — see
68
+ [docs/05-PROPSHAFT-INSTALL.md](docs/05-PROPSHAFT-INSTALL.md).
69
+
55
70
  ## Usage
56
71
 
57
72
  ```ruby
@@ -136,7 +151,11 @@ stylesheet_link_tag "phlex_kit/themes/neutral"
136
151
 
137
152
  The three knobs from ui.shadcn.com/create map directly: **Radius** →
138
153
  `--pk-radius`; **Icon Library** → `PhlexKit.config.icon_library` (see Icons
139
- below); **Menu** → `PhlexKit::Sidebar.new(menu: :default | :solid)`.
154
+ below); **Menu** → `PhlexKit::Sidebar.new(menu: :default | :solid)`. For an
155
+ off-canvas sidebar, `PhlexKit::SidebarWrapper.new(collapsible: :offcanvas)` +
156
+ a `PhlexKit::SidebarTrigger` anywhere inside it: desktop slides the rail out
157
+ of the layout, below 768px it overlays as a drawer behind a scrim (Escape /
158
+ scrim-click closes; state is DOM-only so Turbo caches restore closed).
140
159
 
141
160
  ## Icons
142
161
 
@@ -184,6 +203,11 @@ render PhlexKit::Chart.new(options: {
184
203
  No `window.Chart`? The controller dispatches `phlex-kit--chart:connect` with
185
204
  `{ canvas, options }` so you can drive any other library.
186
205
 
206
+ For the full walkthrough — pinning Chart.js through **importmap** (and the
207
+ gotcha that makes the obvious `bin/importmap pin chart.js` fail), the UMD
208
+ alternative, and end-to-end verification — see
209
+ [docs/06-CHARTS.md](docs/06-CHARTS.md).
210
+
187
211
  ## phlex-reactive (optional)
188
212
 
189
213
  For components that own server-state behavior, add phlex-reactive and include
@@ -207,8 +231,14 @@ Want to own and edit a component's source? Eject it into your app:
207
231
  bin/rails g phlex_kit:component button
208
232
  ```
209
233
 
210
- This copies `button.rb` + `button.css` into `app/components/phlex_kit/button/`
211
- and wires its `@import`. Your copy shadows the gem's.
234
+ This copies the whole component folder — `button.rb` (+ any parts), `button.css`,
235
+ and, for interactive components, `button_controller.js` into
236
+ `app/components/phlex_kit/button/`, prepends its `@import`, and wires
237
+ `config/application.rb` once so your copy fully shadows the gem's — **Ruby, CSS,
238
+ and JS**. (It Zeitwerk-collapses the folder so `button/button.rb` autoloads as
239
+ `PhlexKit::Button`, and puts `app/components` ahead of the gem on Propshaft's
240
+ asset path so the ejected CSS/JS resolve to your copy, not the gem's.) Re-running
241
+ for another component reuses the same wiring — it's injected only once.
212
242
 
213
243
  ## The docs site
214
244
 
@@ -278,8 +308,9 @@ fully mirrored overlay alignment in RTL may need small host-side overrides.
278
308
  Four engine initializers make the zero-build story hold:
279
309
 
280
310
  1. `app/components`, the stylesheet dir, and `app/javascript` go on
281
- Propshaft's load path, so CSS sits beside each `.rb` and the importmap pins
282
- resolve.
311
+ Propshaft's load path, so each component's `.css` and `_controller.js` sit
312
+ beside its `.rb` and the importmap pins resolve (`app/javascript` still serves
313
+ the central `controllers/index.js` registry).
283
314
  2. Component folders are Zeitwerk-`collapse`d, so `button/button.rb` is
284
315
  `PhlexKit::Button` and `card/card_header.rb` is `PhlexKit::CardHeader`.
285
316
  3. A guard keeps Propshaft from serving Ruby source out of `public/assets/`.
@@ -158,3 +158,60 @@
158
158
  .pk-input.pk-sidebar-input { height: 2rem; width: 100%; background: var(--pk-bg); box-shadow: none; }
159
159
 
160
160
  .pk-sidebar-inset { flex: 1; min-width: 0; }
161
+
162
+ /* --- Offcanvas mode (SidebarWrapper collapsible: :offcanvas) ---------------
163
+ Desktop: the rail slides out of the layout (data-collapsed on the wrapper).
164
+ Mobile (<768px): the rail is a fixed overlay drawer behind a scrim
165
+ (data-open). The trigger only shows inside an offcanvas wrapper. The 767px
166
+ cutoff matches sidebar_controller.js. */
167
+ .pk-sidebar-wrapper.collapsible-offcanvas .pk-sidebar {
168
+ transition: margin-left .2s ease, transform .2s ease;
169
+ }
170
+ .pk-sidebar-wrapper.collapsible-offcanvas[data-collapsed] .pk-sidebar { margin-left: -16rem; }
171
+
172
+ .pk-sidebar-trigger {
173
+ display: none;
174
+ align-items: center;
175
+ justify-content: center;
176
+ width: 2rem;
177
+ height: 2rem;
178
+ border: 0;
179
+ border-radius: calc(var(--pk-radius) - 2px);
180
+ background: transparent;
181
+ color: inherit;
182
+ padding: 0;
183
+ cursor: pointer;
184
+ }
185
+ .pk-sidebar-trigger:hover { background: var(--pk-accent); }
186
+ .pk-sidebar-trigger svg { width: 1rem; height: 1rem; }
187
+ .collapsible-offcanvas .pk-sidebar-trigger { display: inline-flex; }
188
+
189
+ .pk-sidebar-scrim { display: none; }
190
+
191
+ @media (max-width: 767px) {
192
+ .pk-sidebar-wrapper.collapsible-offcanvas .pk-sidebar {
193
+ position: fixed;
194
+ inset-block: 0;
195
+ left: 0;
196
+ z-index: 50;
197
+ height: 100dvh;
198
+ margin-left: 0;
199
+ transform: translateX(-100%);
200
+ box-shadow: 0 8px 30px rgb(0 0 0 / .35);
201
+ }
202
+ .pk-sidebar-wrapper.collapsible-offcanvas[data-open] .pk-sidebar { transform: none; }
203
+ .pk-sidebar-wrapper.collapsible-offcanvas[data-open] .pk-sidebar-scrim {
204
+ display: block;
205
+ position: fixed;
206
+ inset: 0;
207
+ z-index: 49;
208
+ background: rgb(0 0 0 / .5);
209
+ border: 0;
210
+ padding: 0;
211
+ cursor: default;
212
+ }
213
+ }
214
+
215
+ @media (prefers-reduced-motion: reduce) {
216
+ .pk-sidebar-wrapper.collapsible-offcanvas .pk-sidebar { transition: none; }
217
+ }
@@ -1,9 +1,9 @@
1
1
  module PhlexKit
2
- # Sidebar shell, ported from ruby_ui's RubyUI::Sidebar at `collapsible: :none`
3
- # (the NonCollapsibleSidebar path): a static flex-column rail. Deliberately
4
- # WITHOUT ruby_ui's collapsible/offcanvas Stimulus controller + cookie state +
5
- # mobile Sheet (the admin sidebar is static) those can be added later if a
6
- # collapsible chrome is wanted. The static part set matches shadcn/ui's Sidebar:
2
+ # Sidebar shell, ported from ruby_ui's RubyUI::Sidebar: a flex-column rail.
3
+ # Static by default; SidebarWrapper(collapsible: :offcanvas) + SidebarTrigger
4
+ # give it shadcn's offcanvas behavior (desktop slide-away, mobile overlay
5
+ # drawer with scrimsee sidebar_wrapper.rb / sidebar_controller.js).
6
+ # The part set matches shadcn/ui's Sidebar:
7
7
  # compose with SidebarWrapper (the page root) + SidebarHeader / SidebarContent /
8
8
  # SidebarGroup (+ Label / Content / Action) / SidebarMenu (+ Item / Button /
9
9
  # Action / Badge / Skeleton / Sub / SubItem / SubButton) / SidebarSeparator /
@@ -0,0 +1,24 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ // Connects to data-controller="phlex-kit--sidebar" — set by SidebarWrapper when
4
+ // collapsible: :offcanvas. One attribute per surface, both DOM-only so Turbo's
5
+ // page cache never restores an open drawer (the wrapper also closes on
6
+ // turbo:before-cache): `data-open` shows the mobile overlay drawer,
7
+ // `data-collapsed` slides the desktop rail out of the layout. The 767px cutoff
8
+ // matches sidebar.css's offcanvas media query.
9
+ export default class extends Controller {
10
+ static MOBILE = "(max-width: 767px)"
11
+
12
+ toggle() {
13
+ if (this.mobile) this.element.toggleAttribute("data-open")
14
+ else this.element.toggleAttribute("data-collapsed")
15
+ }
16
+
17
+ closeMobile() {
18
+ this.element.removeAttribute("data-open")
19
+ }
20
+
21
+ get mobile() {
22
+ return window.matchMedia(this.constructor.MOBILE).matches
23
+ }
24
+ }
@@ -0,0 +1,23 @@
1
+ module PhlexKit
2
+ # The hamburger that toggles an offcanvas sidebar, ported from shadcn/ui's
3
+ # SidebarTrigger. Place it anywhere inside a
4
+ # SidebarWrapper(collapsible: :offcanvas) — typically at the top of the
5
+ # SidebarInset. Renders the :menu icon unless a block supplies its own
6
+ # content. Hidden by CSS unless the wrapper is offcanvas. See sidebar.rb.
7
+ class SidebarTrigger < BaseComponent
8
+ def initialize(**attrs)
9
+ @attrs = attrs
10
+ end
11
+
12
+ def view_template(&block)
13
+ button(**mix({
14
+ type: :button,
15
+ class: "pk-sidebar-trigger",
16
+ aria_label: "Toggle sidebar",
17
+ data: { action: "click->phlex-kit--sidebar#toggle" }
18
+ }, @attrs)) do
19
+ block ? yield : render(Icon.new(:menu, size: nil))
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,13 +1,48 @@
1
1
  module PhlexKit
2
2
  # The page-level flex row that holds a PhlexKit::Sidebar + a PhlexKit::SidebarInset.
3
+ #
4
+ # `collapsible:` (shadcn/ui's Sidebar `collapsible` prop, held here because the
5
+ # wrapper is the Stimulus scope shared by rail, trigger and scrim):
6
+ # :none — static rail (default).
7
+ # :offcanvas — the rail hides/reveals via a PhlexKit::SidebarTrigger. On
8
+ # desktop it slides out of the layout; below 768px it overlays
9
+ # as a fixed drawer behind a click-to-close scrim, closed by
10
+ # Escape and before Turbo caches the page. State is DOM-only:
11
+ # `data-collapsed` (desktop) / `data-open` (mobile drawer).
3
12
  # See sidebar.rb.
4
13
  class SidebarWrapper < BaseComponent
5
- def initialize(**attrs)
14
+ COLLAPSIBLE = { none: nil, offcanvas: "collapsible-offcanvas" }.freeze
15
+
16
+ def initialize(collapsible: :none, **attrs)
17
+ @collapsible = collapsible.to_sym
6
18
  @attrs = attrs
7
19
  end
8
20
 
9
21
  def view_template(&block)
10
- div(**mix({ class: "pk-sidebar-wrapper" }, @attrs), &block)
22
+ unless offcanvas?
23
+ return div(**mix({ class: classes }, @attrs), &block)
24
+ end
25
+
26
+ div(**mix({
27
+ class: classes,
28
+ data: {
29
+ controller: "phlex-kit--sidebar",
30
+ action: "keydown.esc@window->phlex-kit--sidebar#closeMobile " \
31
+ "turbo:before-cache@window->phlex-kit--sidebar#closeMobile"
32
+ }
33
+ }, @attrs)) do
34
+ yield if block
35
+ button(type: :button, class: "pk-sidebar-scrim", aria_label: "Close sidebar",
36
+ tabindex: "-1", data: { action: "click->phlex-kit--sidebar#closeMobile" })
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def offcanvas? = @collapsible == :offcanvas
43
+
44
+ def classes
45
+ [ "pk-sidebar-wrapper", COLLAPSIBLE.fetch(@collapsible) ].compact.join(" ")
11
46
  end
12
47
  end
13
48
  end
@@ -39,6 +39,7 @@ import SelectController from "phlex_kit/controllers/select_controller"
39
39
  import SelectItemController from "phlex_kit/controllers/select_item_controller"
40
40
  import SheetController from "phlex_kit/controllers/sheet_controller"
41
41
  import SheetContentController from "phlex_kit/controllers/sheet_content_controller"
42
+ import SidebarController from "phlex_kit/controllers/sidebar_controller"
42
43
  import SliderController from "phlex_kit/controllers/slider_controller"
43
44
  import TabsController from "phlex_kit/controllers/tabs_controller"
44
45
  import ThemeToggleController from "phlex_kit/controllers/theme_toggle_controller"
@@ -79,6 +80,7 @@ export function registerPhlexKitControllers(application) {
79
80
  application.register("phlex-kit--select-item", SelectItemController)
80
81
  application.register("phlex-kit--sheet", SheetController)
81
82
  application.register("phlex-kit--sheet-content", SheetContentController)
83
+ application.register("phlex-kit--sidebar", SidebarController)
82
84
  application.register("phlex-kit--slider", SliderController)
83
85
  application.register("phlex-kit--tabs", TabsController)
84
86
  application.register("phlex-kit--theme-toggle", ThemeToggleController)
data/config/importmap.rb CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  # Pins the PhlexKit Stimulus controllers so importmap-rails hosts can register
4
4
  # them. The engine appends this file to the host's importmap paths.
5
- pin_all_from PhlexKit::Engine.root.join("app/javascript/phlex_kit/controllers"),
6
- under: "phlex_kit/controllers",
7
- to: "phlex_kit/controllers"
5
+ #
6
+ # Each controller is co-located with its component under
7
+ # app/components/phlex_kit/<name>/<name>_controller.js, but we keep the flat
8
+ # `phlex_kit/controllers/*` module namespace stable so index.js imports and the
9
+ # host-facing API (`import … from "phlex_kit/controllers"`) never change. Basenames
10
+ # are globally unique, so the flat module IDs don't collide. app/components is
11
+ # already on the asset path (see Engine), so these logical paths resolve and
12
+ # get fingerprinted.
13
+ components_root = PhlexKit::Engine.root.join("app/components")
14
+ Dir.glob(components_root.join("phlex_kit/*/*_controller.js")).sort.each do |path|
15
+ name = File.basename(path, ".js") # e.g. "button_controller"
16
+ logical = path.sub("#{components_root}/", "") # e.g. "phlex_kit/button/button_controller.js"
17
+ pin "phlex_kit/controllers/#{name}", to: logical
18
+ end
19
+
20
+ # The aggregator that hosts import from ("phlex_kit/controllers"); stays central.
21
+ pin "phlex_kit/controllers", to: "phlex_kit/controllers/index.js"
@@ -5,13 +5,17 @@ require "rails/generators/named_base"
5
5
  module PhlexKit
6
6
  module Generators
7
7
  # `rails g phlex_kit:component button` — the shadcn-style "eject": copies a
8
- # component's folder (.rb parts + co-located .css) out of the gem and into the
9
- # host app so the team owns and can edit the source. Appends its @import to
10
- # application.css. The ejected copy keeps the PhlexKit namespace; the host's
11
- # copy shadows the gem's via Zeitwerk load-path order.
8
+ # component's folder (.rb parts + co-located .css + _controller.js) out of the
9
+ # gem and into the host app so the team owns and can edit the source. Appends
10
+ # its @import to application.css and wires config/application.rb (once) so the
11
+ # ejected copy fully shadows the gem's Ruby, CSS, and JS alike.
12
12
  class ComponentGenerator < Rails::Generators::NamedBase
13
13
  source_root PhlexKit::Engine.root.join("app/components/phlex_kit").to_s
14
14
 
15
+ # Marker that `wire_host_app` is idempotent against — presence means an
16
+ # earlier eject already wired config/application.rb.
17
+ COLLAPSE_LINE = %(Rails.autoloaders.main.collapse(Rails.root.join("app/components/phlex_kit/*")))
18
+
15
19
  def eject_component
16
20
  unless File.directory?(File.join(self.class.source_root, file_name))
17
21
  say_status :error, "no PhlexKit component named '#{file_name}'", :red
@@ -27,14 +31,42 @@ module PhlexKit
27
31
  prepend_to_file(css, line) unless File.read(css).include?(line.strip)
28
32
  end
29
33
 
30
- def remind_collapse
31
- say <<~MSG
32
- Ejected phlex_kit/#{file_name}. Ensure your app collapses ejected
33
- component folders (config/application.rb):
34
+ # Make an ejected component fully editable, in one step. Two things are
35
+ # needed and neither is on by default in a host app:
36
+ # 1. Zeitwerk collapse so app/components/phlex_kit/button/button.rb
37
+ # autoloads as PhlexKit::Button (not ::Button::Button). Fixes Ruby.
38
+ # 2. Host app/components ahead of the gem on Propshaft's asset path — so
39
+ # the ejected <name>.css and <name>_controller.js resolve to the host
40
+ # copy instead of the gem's. Without this the Ruby shadows but the CSS
41
+ # and JS silently keep serving the gem's originals.
42
+ # Injected once (idempotent) right after config.load_defaults, where
43
+ # config.assets is available.
44
+ def wire_host_app
45
+ app_rb = "config/application.rb"
46
+ unless File.exist?(app_rb)
47
+ say_status :skip, "#{app_rb} not found — wire ejected components manually (see docs/05-PROPSHAFT-INSTALL.md)", :yellow
48
+ return
49
+ end
50
+ if File.read(app_rb).include?(COLLAPSE_LINE)
51
+ say_status :identical, "#{app_rb} already wired for ejected components", :blue
52
+ return
53
+ end
54
+ inject_into_file app_rb, after: /^\s*config\.load_defaults.*\n/ do
55
+ # Indent only non-empty lines so the blank separator carries no trailing space.
56
+ <<~RUBY.gsub(/^(?=.)/, " ")
34
57
 
35
- Rails.autoloaders.main.collapse("app/components/phlex_kit/*")
58
+ # PhlexKit: make ejected components under app/components/phlex_kit/
59
+ # fully editable — collapse so <name>/<name>.rb autoloads as
60
+ # PhlexKit::<Name>, and put the dir ahead of the gem on the asset path
61
+ # so the ejected <name>.css and <name>_controller.js shadow the gem's.
62
+ #{COLLAPSE_LINE}
63
+ config.assets.paths.unshift(Rails.root.join("app/components"))
64
+ RUBY
65
+ end
66
+ end
36
67
 
37
- MSG
68
+ def confirm
69
+ say_status :phlex_kit, "ejected phlex_kit/#{file_name} — your copy now shadows the gem (Ruby, CSS, JS)", :green
38
70
  end
39
71
  end
40
72
  end
@@ -14,8 +14,10 @@ module PhlexKit
14
14
  if app.config.respond_to?(:assets)
15
15
  app.config.assets.paths << root.join("app/components")
16
16
  app.config.assets.paths << root.join("app/assets/stylesheets")
17
- # The Stimulus controllers must be servable too, or every importmap pin
18
- # from (4) resolves to a missing asset and gets silently skipped.
17
+ # The Stimulus controllers are co-located under app/components (served via
18
+ # the path above); this keeps the central registry (controllers/index.js)
19
+ # servable too, or the "phlex_kit/controllers" pin from (4) resolves to a
20
+ # missing asset and gets silently skipped.
19
21
  app.config.assets.paths << root.join("app/javascript")
20
22
  end
21
23
  end
@@ -38,6 +40,9 @@ module PhlexKit
38
40
  initializer "phlex_kit.importmap", before: "importmap" do |app|
39
41
  if app.respond_to?(:config) && app.config.respond_to?(:importmap)
40
42
  app.config.importmap.paths << root.join("config/importmap.rb")
43
+ # Colocated controllers change under app/components; the central registry
44
+ # lives under app/javascript. Sweep both so edits bust the importmap cache.
45
+ app.config.importmap.cache_sweepers << root.join("app/components")
41
46
  app.config.importmap.cache_sweepers << root.join("app/javascript")
42
47
  end
43
48
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PhlexKit
4
- VERSION = "0.2.2"
4
+ VERSION = "0.4.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phlex_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Kennedy
@@ -126,6 +126,7 @@ files:
126
126
  - app/components/phlex_kit/accordion/accordion.css
127
127
  - app/components/phlex_kit/accordion/accordion.rb
128
128
  - app/components/phlex_kit/accordion/accordion_content.rb
129
+ - app/components/phlex_kit/accordion/accordion_controller.js
129
130
  - app/components/phlex_kit/accordion/accordion_default_content.rb
130
131
  - app/components/phlex_kit/accordion/accordion_default_trigger.rb
131
132
  - app/components/phlex_kit/accordion/accordion_icon.rb
@@ -140,6 +141,7 @@ files:
140
141
  - app/components/phlex_kit/alert_dialog/alert_dialog_action.rb
141
142
  - app/components/phlex_kit/alert_dialog/alert_dialog_cancel.rb
142
143
  - app/components/phlex_kit/alert_dialog/alert_dialog_content.rb
144
+ - app/components/phlex_kit/alert_dialog/alert_dialog_controller.js
143
145
  - app/components/phlex_kit/alert_dialog/alert_dialog_description.rb
144
146
  - app/components/phlex_kit/alert_dialog/alert_dialog_footer.rb
145
147
  - app/components/phlex_kit/alert_dialog/alert_dialog_header.rb
@@ -158,8 +160,10 @@ files:
158
160
  - app/components/phlex_kit/attachment/attachment_media.rb
159
161
  - app/components/phlex_kit/attachment/attachment_title.rb
160
162
  - app/components/phlex_kit/attachment/attachment_trigger.rb
163
+ - app/components/phlex_kit/attachment/scroll_fade_controller.js
161
164
  - app/components/phlex_kit/avatar/avatar.css
162
165
  - app/components/phlex_kit/avatar/avatar.rb
166
+ - app/components/phlex_kit/avatar/avatar_controller.js
163
167
  - app/components/phlex_kit/avatar/avatar_fallback.rb
164
168
  - app/components/phlex_kit/avatar/avatar_group.rb
165
169
  - app/components/phlex_kit/avatar/avatar_image.rb
@@ -185,8 +189,10 @@ files:
185
189
  - app/components/phlex_kit/calendar/calendar.css
186
190
  - app/components/phlex_kit/calendar/calendar.rb
187
191
  - app/components/phlex_kit/calendar/calendar_body.rb
192
+ - app/components/phlex_kit/calendar/calendar_controller.js
188
193
  - app/components/phlex_kit/calendar/calendar_days.rb
189
194
  - app/components/phlex_kit/calendar/calendar_header.rb
195
+ - app/components/phlex_kit/calendar/calendar_input_controller.js
190
196
  - app/components/phlex_kit/calendar/calendar_next.rb
191
197
  - app/components/phlex_kit/calendar/calendar_prev.rb
192
198
  - app/components/phlex_kit/calendar/calendar_title.rb
@@ -202,15 +208,18 @@ files:
202
208
  - app/components/phlex_kit/carousel/carousel.css
203
209
  - app/components/phlex_kit/carousel/carousel.rb
204
210
  - app/components/phlex_kit/carousel/carousel_content.rb
211
+ - app/components/phlex_kit/carousel/carousel_controller.js
205
212
  - app/components/phlex_kit/carousel/carousel_item.rb
206
213
  - app/components/phlex_kit/carousel/carousel_next.rb
207
214
  - app/components/phlex_kit/carousel/carousel_previous.rb
208
215
  - app/components/phlex_kit/chart/chart.css
209
216
  - app/components/phlex_kit/chart/chart.rb
217
+ - app/components/phlex_kit/chart/chart_controller.js
210
218
  - app/components/phlex_kit/checkbox/checkbox.css
211
219
  - app/components/phlex_kit/checkbox/checkbox.rb
212
220
  - app/components/phlex_kit/clipboard/clipboard.css
213
221
  - app/components/phlex_kit/clipboard/clipboard.rb
222
+ - app/components/phlex_kit/clipboard/clipboard_controller.js
214
223
  - app/components/phlex_kit/clipboard/clipboard_popover.rb
215
224
  - app/components/phlex_kit/clipboard/clipboard_source.rb
216
225
  - app/components/phlex_kit/clipboard/clipboard_trigger.rb
@@ -219,6 +228,7 @@ files:
219
228
  - app/components/phlex_kit/collapsible/collapsible.css
220
229
  - app/components/phlex_kit/collapsible/collapsible.rb
221
230
  - app/components/phlex_kit/collapsible/collapsible_content.rb
231
+ - app/components/phlex_kit/collapsible/collapsible_controller.js
222
232
  - app/components/phlex_kit/collapsible/collapsible_trigger.rb
223
233
  - app/components/phlex_kit/combobox/combobox.css
224
234
  - app/components/phlex_kit/combobox/combobox.rb
@@ -226,6 +236,7 @@ files:
226
236
  - app/components/phlex_kit/combobox/combobox_badge_trigger.rb
227
237
  - app/components/phlex_kit/combobox/combobox_checkbox.rb
228
238
  - app/components/phlex_kit/combobox/combobox_clear_button.rb
239
+ - app/components/phlex_kit/combobox/combobox_controller.js
229
240
  - app/components/phlex_kit/combobox/combobox_empty_state.rb
230
241
  - app/components/phlex_kit/combobox/combobox_input_trigger.rb
231
242
  - app/components/phlex_kit/combobox/combobox_item.rb
@@ -239,8 +250,10 @@ files:
239
250
  - app/components/phlex_kit/combobox/combobox_trigger.rb
240
251
  - app/components/phlex_kit/command/command.css
241
252
  - app/components/phlex_kit/command/command.rb
253
+ - app/components/phlex_kit/command/command_controller.js
242
254
  - app/components/phlex_kit/command/command_dialog.rb
243
255
  - app/components/phlex_kit/command/command_dialog_content.rb
256
+ - app/components/phlex_kit/command/command_dialog_controller.js
244
257
  - app/components/phlex_kit/command/command_dialog_trigger.rb
245
258
  - app/components/phlex_kit/command/command_empty.rb
246
259
  - app/components/phlex_kit/command/command_group.rb
@@ -250,6 +263,7 @@ files:
250
263
  - app/components/phlex_kit/context_menu/context_menu.css
251
264
  - app/components/phlex_kit/context_menu/context_menu.rb
252
265
  - app/components/phlex_kit/context_menu/context_menu_content.rb
266
+ - app/components/phlex_kit/context_menu/context_menu_controller.js
253
267
  - app/components/phlex_kit/context_menu/context_menu_item.rb
254
268
  - app/components/phlex_kit/context_menu/context_menu_label.rb
255
269
  - app/components/phlex_kit/context_menu/context_menu_separator.rb
@@ -258,6 +272,8 @@ files:
258
272
  - app/components/phlex_kit/data_table/data_table.rb
259
273
  - app/components/phlex_kit/data_table/data_table_bulk_actions.rb
260
274
  - app/components/phlex_kit/data_table/data_table_column_toggle.rb
275
+ - app/components/phlex_kit/data_table/data_table_column_visibility_controller.js
276
+ - app/components/phlex_kit/data_table/data_table_controller.js
261
277
  - app/components/phlex_kit/data_table/data_table_expand_toggle.rb
262
278
  - app/components/phlex_kit/data_table/data_table_form.rb
263
279
  - app/components/phlex_kit/data_table/data_table_kaminari_adapter.rb
@@ -268,6 +284,7 @@ files:
268
284
  - app/components/phlex_kit/data_table/data_table_per_page_select.rb
269
285
  - app/components/phlex_kit/data_table/data_table_row_checkbox.rb
270
286
  - app/components/phlex_kit/data_table/data_table_search.rb
287
+ - app/components/phlex_kit/data_table/data_table_search_controller.js
271
288
  - app/components/phlex_kit/data_table/data_table_select_all_checkbox.rb
272
289
  - app/components/phlex_kit/data_table/data_table_selection_summary.rb
273
290
  - app/components/phlex_kit/data_table/data_table_sort_head.rb
@@ -277,6 +294,7 @@ files:
277
294
  - app/components/phlex_kit/dialog/dialog.css
278
295
  - app/components/phlex_kit/dialog/dialog.rb
279
296
  - app/components/phlex_kit/dialog/dialog_content.rb
297
+ - app/components/phlex_kit/dialog/dialog_controller.js
280
298
  - app/components/phlex_kit/dialog/dialog_description.rb
281
299
  - app/components/phlex_kit/dialog/dialog_footer.rb
282
300
  - app/components/phlex_kit/dialog/dialog_header.rb
@@ -296,6 +314,7 @@ files:
296
314
  - app/components/phlex_kit/dropdown_menu/dropdown_menu.rb
297
315
  - app/components/phlex_kit/dropdown_menu/dropdown_menu_checkbox_item.rb
298
316
  - app/components/phlex_kit/dropdown_menu/dropdown_menu_content.rb
317
+ - app/components/phlex_kit/dropdown_menu/dropdown_menu_controller.js
299
318
  - app/components/phlex_kit/dropdown_menu/dropdown_menu_group.rb
300
319
  - app/components/phlex_kit/dropdown_menu/dropdown_menu_item.rb
301
320
  - app/components/phlex_kit/dropdown_menu/dropdown_menu_label.rb
@@ -318,12 +337,14 @@ files:
318
337
  - app/components/phlex_kit/form/form.rb
319
338
  - app/components/phlex_kit/form_field/form_field.css
320
339
  - app/components/phlex_kit/form_field/form_field.rb
340
+ - app/components/phlex_kit/form_field/form_field_controller.js
321
341
  - app/components/phlex_kit/form_field/form_field_error.rb
322
342
  - app/components/phlex_kit/form_field/form_field_hint.rb
323
343
  - app/components/phlex_kit/form_field/form_field_label.rb
324
344
  - app/components/phlex_kit/hover_card/hover_card.css
325
345
  - app/components/phlex_kit/hover_card/hover_card.rb
326
346
  - app/components/phlex_kit/hover_card/hover_card_content.rb
347
+ - app/components/phlex_kit/hover_card/hover_card_controller.js
327
348
  - app/components/phlex_kit/hover_card/hover_card_trigger.rb
328
349
  - app/components/phlex_kit/icon/icon.rb
329
350
  - app/components/phlex_kit/input/input.css
@@ -334,6 +355,7 @@ files:
334
355
  - app/components/phlex_kit/input_group/input_group_text.rb
335
356
  - app/components/phlex_kit/input_otp/input_otp.css
336
357
  - app/components/phlex_kit/input_otp/input_otp.rb
358
+ - app/components/phlex_kit/input_otp/input_otp_controller.js
337
359
  - app/components/phlex_kit/input_otp/input_otp_group.rb
338
360
  - app/components/phlex_kit/input_otp/input_otp_separator.rb
339
361
  - app/components/phlex_kit/input_otp/input_otp_slot.rb
@@ -357,9 +379,11 @@ files:
357
379
  - app/components/phlex_kit/marker/marker_content.rb
358
380
  - app/components/phlex_kit/marker/marker_icon.rb
359
381
  - app/components/phlex_kit/masked_input/masked_input.rb
382
+ - app/components/phlex_kit/masked_input/masked_input_controller.js
360
383
  - app/components/phlex_kit/menubar/menubar.css
361
384
  - app/components/phlex_kit/menubar/menubar.rb
362
385
  - app/components/phlex_kit/menubar/menubar_content.rb
386
+ - app/components/phlex_kit/menubar/menubar_controller.js
363
387
  - app/components/phlex_kit/menubar/menubar_item.rb
364
388
  - app/components/phlex_kit/menubar/menubar_menu.rb
365
389
  - app/components/phlex_kit/menubar/menubar_separator.rb
@@ -373,6 +397,7 @@ files:
373
397
  - app/components/phlex_kit/message/message_header.rb
374
398
  - app/components/phlex_kit/message_scroller/message_scroller.css
375
399
  - app/components/phlex_kit/message_scroller/message_scroller.rb
400
+ - app/components/phlex_kit/message_scroller/message_scroller_controller.js
376
401
  - app/components/phlex_kit/native_select/native_select.css
377
402
  - app/components/phlex_kit/native_select/native_select.rb
378
403
  - app/components/phlex_kit/native_select/native_select_group.rb
@@ -393,6 +418,7 @@ files:
393
418
  - app/components/phlex_kit/popover/popover.css
394
419
  - app/components/phlex_kit/popover/popover.rb
395
420
  - app/components/phlex_kit/popover/popover_content.rb
421
+ - app/components/phlex_kit/popover/popover_controller.js
396
422
  - app/components/phlex_kit/popover/popover_trigger.rb
397
423
  - app/components/phlex_kit/progress/progress.css
398
424
  - app/components/phlex_kit/progress/progress.rb
@@ -401,6 +427,7 @@ files:
401
427
  - app/components/phlex_kit/radio_group/radio_group.css
402
428
  - app/components/phlex_kit/radio_group/radio_group.rb
403
429
  - app/components/phlex_kit/resizable/resizable.css
430
+ - app/components/phlex_kit/resizable/resizable_controller.js
404
431
  - app/components/phlex_kit/resizable/resizable_handle.rb
405
432
  - app/components/phlex_kit/resizable/resizable_panel.rb
406
433
  - app/components/phlex_kit/resizable/resizable_panel_group.rb
@@ -409,9 +436,11 @@ files:
409
436
  - app/components/phlex_kit/select/select.css
410
437
  - app/components/phlex_kit/select/select.rb
411
438
  - app/components/phlex_kit/select/select_content.rb
439
+ - app/components/phlex_kit/select/select_controller.js
412
440
  - app/components/phlex_kit/select/select_group.rb
413
441
  - app/components/phlex_kit/select/select_input.rb
414
442
  - app/components/phlex_kit/select/select_item.rb
443
+ - app/components/phlex_kit/select/select_item_controller.js
415
444
  - app/components/phlex_kit/select/select_label.rb
416
445
  - app/components/phlex_kit/select/select_trigger.rb
417
446
  - app/components/phlex_kit/select/select_value.rb
@@ -420,6 +449,8 @@ files:
420
449
  - app/components/phlex_kit/sheet/sheet.css
421
450
  - app/components/phlex_kit/sheet/sheet.rb
422
451
  - app/components/phlex_kit/sheet/sheet_content.rb
452
+ - app/components/phlex_kit/sheet/sheet_content_controller.js
453
+ - app/components/phlex_kit/sheet/sheet_controller.js
423
454
  - app/components/phlex_kit/sheet/sheet_description.rb
424
455
  - app/components/phlex_kit/sheet/sheet_footer.rb
425
456
  - app/components/phlex_kit/sheet/sheet_header.rb
@@ -431,6 +462,7 @@ files:
431
462
  - app/components/phlex_kit/sidebar/sidebar.css
432
463
  - app/components/phlex_kit/sidebar/sidebar.rb
433
464
  - app/components/phlex_kit/sidebar/sidebar_content.rb
465
+ - app/components/phlex_kit/sidebar/sidebar_controller.js
434
466
  - app/components/phlex_kit/sidebar/sidebar_footer.rb
435
467
  - app/components/phlex_kit/sidebar/sidebar_group.rb
436
468
  - app/components/phlex_kit/sidebar/sidebar_group_action.rb
@@ -449,11 +481,13 @@ files:
449
481
  - app/components/phlex_kit/sidebar/sidebar_menu_sub_button.rb
450
482
  - app/components/phlex_kit/sidebar/sidebar_menu_sub_item.rb
451
483
  - app/components/phlex_kit/sidebar/sidebar_separator.rb
484
+ - app/components/phlex_kit/sidebar/sidebar_trigger.rb
452
485
  - app/components/phlex_kit/sidebar/sidebar_wrapper.rb
453
486
  - app/components/phlex_kit/skeleton/skeleton.css
454
487
  - app/components/phlex_kit/skeleton/skeleton.rb
455
488
  - app/components/phlex_kit/slider/slider.css
456
489
  - app/components/phlex_kit/slider/slider.rb
490
+ - app/components/phlex_kit/slider/slider_controller.js
457
491
  - app/components/phlex_kit/spinner/spinner.css
458
492
  - app/components/phlex_kit/spinner/spinner.rb
459
493
  - app/components/phlex_kit/switch/switch.css
@@ -470,25 +504,31 @@ files:
470
504
  - app/components/phlex_kit/tabs/tabs.css
471
505
  - app/components/phlex_kit/tabs/tabs.rb
472
506
  - app/components/phlex_kit/tabs/tabs_content.rb
507
+ - app/components/phlex_kit/tabs/tabs_controller.js
473
508
  - app/components/phlex_kit/tabs/tabs_list.rb
474
509
  - app/components/phlex_kit/tabs/tabs_trigger.rb
475
510
  - app/components/phlex_kit/textarea/textarea.css
476
511
  - app/components/phlex_kit/textarea/textarea.rb
477
512
  - app/components/phlex_kit/theme_toggle/theme_toggle.rb
513
+ - app/components/phlex_kit/theme_toggle/theme_toggle_controller.js
478
514
  - app/components/phlex_kit/toast/toast.css
479
515
  - app/components/phlex_kit/toast/toast.rb
480
516
  - app/components/phlex_kit/toast/toast_action.rb
481
517
  - app/components/phlex_kit/toast/toast_cancel.rb
482
518
  - app/components/phlex_kit/toast/toast_close.rb
519
+ - app/components/phlex_kit/toast/toast_controller.js
483
520
  - app/components/phlex_kit/toast/toast_description.rb
484
521
  - app/components/phlex_kit/toast/toast_icon.rb
485
522
  - app/components/phlex_kit/toast/toast_item.rb
486
523
  - app/components/phlex_kit/toast/toast_region.rb
487
524
  - app/components/phlex_kit/toast/toast_title.rb
525
+ - app/components/phlex_kit/toast/toaster_controller.js
488
526
  - app/components/phlex_kit/toggle/toggle.css
489
527
  - app/components/phlex_kit/toggle/toggle.rb
528
+ - app/components/phlex_kit/toggle/toggle_controller.js
490
529
  - app/components/phlex_kit/toggle_group/toggle_group.css
491
530
  - app/components/phlex_kit/toggle_group/toggle_group.rb
531
+ - app/components/phlex_kit/toggle_group/toggle_group_controller.js
492
532
  - app/components/phlex_kit/toggle_group/toggle_group_item.rb
493
533
  - app/components/phlex_kit/tooltip/tooltip.css
494
534
  - app/components/phlex_kit/tooltip/tooltip.rb
@@ -500,45 +540,7 @@ files:
500
540
  - app/components/phlex_kit/typography/inline_link.rb
501
541
  - app/components/phlex_kit/typography/text.rb
502
542
  - app/components/phlex_kit/typography/typography.css
503
- - app/javascript/phlex_kit/controllers/accordion_controller.js
504
- - app/javascript/phlex_kit/controllers/alert_dialog_controller.js
505
- - app/javascript/phlex_kit/controllers/avatar_controller.js
506
- - app/javascript/phlex_kit/controllers/calendar_controller.js
507
- - app/javascript/phlex_kit/controllers/calendar_input_controller.js
508
- - app/javascript/phlex_kit/controllers/carousel_controller.js
509
- - app/javascript/phlex_kit/controllers/chart_controller.js
510
- - app/javascript/phlex_kit/controllers/clipboard_controller.js
511
- - app/javascript/phlex_kit/controllers/collapsible_controller.js
512
- - app/javascript/phlex_kit/controllers/combobox_controller.js
513
- - app/javascript/phlex_kit/controllers/command_controller.js
514
- - app/javascript/phlex_kit/controllers/command_dialog_controller.js
515
- - app/javascript/phlex_kit/controllers/context_menu_controller.js
516
- - app/javascript/phlex_kit/controllers/data_table_column_visibility_controller.js
517
- - app/javascript/phlex_kit/controllers/data_table_controller.js
518
- - app/javascript/phlex_kit/controllers/data_table_search_controller.js
519
- - app/javascript/phlex_kit/controllers/dialog_controller.js
520
- - app/javascript/phlex_kit/controllers/dropdown_menu_controller.js
521
- - app/javascript/phlex_kit/controllers/form_field_controller.js
522
- - app/javascript/phlex_kit/controllers/hover_card_controller.js
523
543
  - app/javascript/phlex_kit/controllers/index.js
524
- - app/javascript/phlex_kit/controllers/input_otp_controller.js
525
- - app/javascript/phlex_kit/controllers/masked_input_controller.js
526
- - app/javascript/phlex_kit/controllers/menubar_controller.js
527
- - app/javascript/phlex_kit/controllers/message_scroller_controller.js
528
- - app/javascript/phlex_kit/controllers/popover_controller.js
529
- - app/javascript/phlex_kit/controllers/resizable_controller.js
530
- - app/javascript/phlex_kit/controllers/scroll_fade_controller.js
531
- - app/javascript/phlex_kit/controllers/select_controller.js
532
- - app/javascript/phlex_kit/controllers/select_item_controller.js
533
- - app/javascript/phlex_kit/controllers/sheet_content_controller.js
534
- - app/javascript/phlex_kit/controllers/sheet_controller.js
535
- - app/javascript/phlex_kit/controllers/slider_controller.js
536
- - app/javascript/phlex_kit/controllers/tabs_controller.js
537
- - app/javascript/phlex_kit/controllers/theme_toggle_controller.js
538
- - app/javascript/phlex_kit/controllers/toast_controller.js
539
- - app/javascript/phlex_kit/controllers/toaster_controller.js
540
- - app/javascript/phlex_kit/controllers/toggle_controller.js
541
- - app/javascript/phlex_kit/controllers/toggle_group_controller.js
542
544
  - config/importmap.rb
543
545
  - lib/generators/phlex_kit/component/component_generator.rb
544
546
  - lib/generators/phlex_kit/install/install_generator.rb