daisyui_on_phlex 0.1.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.
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaisyuiOnPhlex
4
+ module Components
5
+ class Alert < DaisyuiOnPhlex::Base
6
+ def initialize(
7
+ variant: :info,
8
+ **attributes
9
+ )
10
+ @variant = variant
11
+ @attributes = attributes
12
+ end
13
+
14
+ def view_template(&block)
15
+ div(
16
+ class: alert_classes,
17
+ **@attributes
18
+ ) do
19
+ render_icon if icon_for_variant
20
+ div(&block) if block_given?
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def alert_classes
27
+ classes = ["alert"]
28
+
29
+ case @variant
30
+ when :info then classes << "alert-info"
31
+ when :success then classes << "alert-success"
32
+ when :warning then classes << "alert-warning"
33
+ when :error then classes << "alert-error"
34
+ end
35
+
36
+ merge_classes(*classes)
37
+ end
38
+
39
+ def icon_for_variant
40
+ case @variant
41
+ when :info then "info"
42
+ when :success then "check"
43
+ when :warning then "warning"
44
+ when :error then "error"
45
+ end
46
+ end
47
+
48
+ def render_icon
49
+ render_svg_icon
50
+ end
51
+
52
+ def render_svg_icon
53
+ svg(
54
+ xmlns: "http://www.w3.org/2000/svg",
55
+ class: "h-6 w-6 shrink-0 stroke-current",
56
+ fill: "none",
57
+ viewBox: "0 0 24 24"
58
+ ) do
59
+ render_svg_path
60
+ end
61
+ end
62
+
63
+ def render_svg_path
64
+ case @variant
65
+ when :info
66
+ unsafe_raw '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>'
67
+ when :success
68
+ unsafe_raw '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>'
69
+ when :warning
70
+ unsafe_raw '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"></path>'
71
+ when :error
72
+ unsafe_raw '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"></path>'
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaisyuiOnPhlex
4
+ module Components
5
+ class Badge < DaisyuiOnPhlex::Base
6
+ def initialize(
7
+ variant: :neutral,
8
+ size: :md,
9
+ outline: false,
10
+ **attributes
11
+ )
12
+ @variant = variant
13
+ @size = size
14
+ @outline = outline
15
+ @attributes = attributes
16
+ end
17
+
18
+ def view_template(&block)
19
+ span(
20
+ class: badge_classes,
21
+ **@attributes,
22
+ &block
23
+ )
24
+ end
25
+
26
+ private
27
+
28
+ def badge_classes
29
+ classes = ["badge"]
30
+
31
+ # Variant classes
32
+ case @variant
33
+ when :primary then classes << "badge-primary"
34
+ when :secondary then classes << "badge-secondary"
35
+ when :accent then classes << "badge-accent"
36
+ when :neutral then classes << "badge-neutral"
37
+ when :info then classes << "badge-info"
38
+ when :success then classes << "badge-success"
39
+ when :warning then classes << "badge-warning"
40
+ when :error then classes << "badge-error"
41
+ when :ghost then classes << "badge-ghost"
42
+ end
43
+
44
+ # Size classes
45
+ case @size
46
+ when :xs then classes << "badge-xs"
47
+ when :sm then classes << "badge-sm"
48
+ when :md then # default, no class needed
49
+ when :lg then classes << "badge-lg"
50
+ end
51
+
52
+ # Modifier classes
53
+ classes << "badge-outline" if @outline
54
+
55
+ merge_classes(*classes)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaisyuiOnPhlex
4
+ module Components
5
+ class Button < DaisyuiOnPhlex::Base
6
+ def initialize(
7
+ variant: :primary,
8
+ size: :md,
9
+ outline: false,
10
+ ghost: false,
11
+ link: false,
12
+ active: false,
13
+ disabled: false,
14
+ loading: false,
15
+ wide: false,
16
+ block: false,
17
+ circle: false,
18
+ square: false,
19
+ glass: false,
20
+ no_animation: false,
21
+ **attributes
22
+ )
23
+ @variant = variant
24
+ @size = size
25
+ @outline = outline
26
+ @ghost = ghost
27
+ @link = link
28
+ @active = active
29
+ @disabled = disabled
30
+ @loading = loading
31
+ @wide = wide
32
+ @block = block
33
+ @circle = circle
34
+ @square = square
35
+ @glass = glass
36
+ @no_animation = no_animation
37
+ @attributes = attributes
38
+ end
39
+
40
+ def view_template(&block)
41
+ button(
42
+ class: button_classes,
43
+ disabled: @disabled,
44
+ **@attributes,
45
+ &block
46
+ )
47
+ end
48
+
49
+ private
50
+
51
+ def button_classes
52
+ classes = ["btn"]
53
+
54
+ # Variant classes
55
+ case @variant
56
+ when :primary then classes << "btn-primary"
57
+ when :secondary then classes << "btn-secondary"
58
+ when :accent then classes << "btn-accent"
59
+ when :neutral then classes << "btn-neutral"
60
+ when :info then classes << "btn-info"
61
+ when :success then classes << "btn-success"
62
+ when :warning then classes << "btn-warning"
63
+ when :error then classes << "btn-error"
64
+ when :ghost then classes << "btn-ghost"
65
+ when :link then classes << "btn-link"
66
+ end
67
+
68
+ # Size classes
69
+ case @size
70
+ when :xs then classes << "btn-xs"
71
+ when :sm then classes << "btn-sm"
72
+ when :md then # default, no class needed
73
+ when :lg then classes << "btn-lg"
74
+ end
75
+
76
+ # Modifier classes
77
+ classes << "btn-outline" if @outline
78
+ classes << "btn-ghost" if @ghost
79
+ classes << "btn-link" if @link
80
+ classes << "btn-active" if @active
81
+ classes << "btn-disabled" if @disabled
82
+ classes << "loading" if @loading
83
+ classes << "btn-wide" if @wide
84
+ classes << "btn-block" if @block
85
+ classes << "btn-circle" if @circle
86
+ classes << "btn-square" if @square
87
+ classes << "glass" if @glass
88
+ classes << "no-animation" if @no_animation
89
+
90
+ merge_classes(*classes)
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaisyuiOnPhlex
4
+ module Components
5
+ class Card < DaisyuiOnPhlex::Base
6
+ def initialize(
7
+ compact: false,
8
+ bordered: false,
9
+ image_full: false,
10
+ side: false,
11
+ **attributes
12
+ )
13
+ @compact = compact
14
+ @bordered = bordered
15
+ @image_full = image_full
16
+ @side = side
17
+ @attributes = attributes
18
+ end
19
+
20
+ def view_template(&block)
21
+ div(
22
+ class: card_classes,
23
+ **@attributes,
24
+ &block
25
+ )
26
+ end
27
+
28
+ def body(css_class: nil, **attributes, &block)
29
+ div(
30
+ class: merge_classes("card-body", css_class),
31
+ **attributes,
32
+ &block
33
+ )
34
+ end
35
+
36
+ def title(css_class: nil, **attributes, &block)
37
+ h2(
38
+ class: merge_classes("card-title", css_class),
39
+ **attributes,
40
+ &block
41
+ )
42
+ end
43
+
44
+ def actions(css_class: nil, **attributes, &block)
45
+ div(
46
+ class: merge_classes("card-actions", css_class),
47
+ **attributes,
48
+ &block
49
+ )
50
+ end
51
+
52
+ def figure(css_class: nil, **attributes, &block)
53
+ figure_tag(
54
+ class: merge_classes("", css_class),
55
+ **attributes,
56
+ &block
57
+ )
58
+ end
59
+
60
+ private
61
+
62
+ def figure_tag(...)
63
+ public_send(:figure, ...)
64
+ end
65
+
66
+ def card_classes
67
+ classes = ["card"]
68
+
69
+ classes << "card-compact" if @compact
70
+ classes << "card-bordered" if @bordered
71
+ classes << "image-full" if @image_full
72
+ classes << "card-side" if @side
73
+
74
+ merge_classes(*classes)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaisyuiOnPhlex
4
+ module Components
5
+ class Input < DaisyuiOnPhlex::Base
6
+ def initialize(
7
+ type: :text,
8
+ size: :md,
9
+ variant: nil,
10
+ bordered: true,
11
+ ghost: false,
12
+ **attributes
13
+ )
14
+ @type = type
15
+ @size = size
16
+ @variant = variant
17
+ @bordered = bordered
18
+ @ghost = ghost
19
+ @attributes = attributes
20
+ end
21
+
22
+ def view_template
23
+ input(
24
+ type: @type,
25
+ class: input_classes,
26
+ **@attributes
27
+ )
28
+ end
29
+
30
+ private
31
+
32
+ def input_classes
33
+ classes = ["input"]
34
+
35
+ # Base styling
36
+ classes << "input-bordered" if @bordered
37
+ classes << "input-ghost" if @ghost
38
+
39
+ # Size classes
40
+ case @size
41
+ when :xs then classes << "input-xs"
42
+ when :sm then classes << "input-sm"
43
+ when :md then # default, no class needed
44
+ when :lg then classes << "input-lg"
45
+ end
46
+
47
+ # Variant classes
48
+ case @variant
49
+ when :primary then classes << "input-primary"
50
+ when :secondary then classes << "input-secondary"
51
+ when :accent then classes << "input-accent"
52
+ when :info then classes << "input-info"
53
+ when :success then classes << "input-success"
54
+ when :warning then classes << "input-warning"
55
+ when :error then classes << "input-error"
56
+ end
57
+
58
+ merge_classes(*classes)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaisyuiOnPhlex
4
+ module Components
5
+ class Modal < DaisyuiOnPhlex::Base
6
+ def initialize(
7
+ id:,
8
+ open: false,
9
+ **attributes
10
+ )
11
+ @id = id
12
+ @open = open
13
+ @attributes = attributes
14
+ end
15
+
16
+ def view_template(&block)
17
+ # Modal trigger (checkbox for CSS-only modal)
18
+ input(
19
+ type: "checkbox",
20
+ id: @id,
21
+ class: "modal-toggle",
22
+ checked: @open
23
+ )
24
+
25
+ # Modal
26
+ div(
27
+ class: "modal",
28
+ role: "dialog"
29
+ ) do
30
+ div(
31
+ class: "modal-box",
32
+ **@attributes,
33
+ &block
34
+ )
35
+
36
+ # Close modal when clicking outside
37
+ label(
38
+ class: "modal-backdrop",
39
+ for: @id
40
+ )
41
+ end
42
+ end
43
+
44
+ def title(css_class: nil, **attributes, &block)
45
+ h3(
46
+ class: merge_classes("text-lg font-bold", css_class),
47
+ **attributes,
48
+ &block
49
+ )
50
+ end
51
+
52
+ def action(**attributes, &block)
53
+ div(
54
+ class: "modal-action",
55
+ **attributes,
56
+ &block
57
+ )
58
+ end
59
+
60
+ def close_button(text = "Close", **attributes)
61
+ label(
62
+ for: @id,
63
+ class: merge_classes("btn", attributes[:class]),
64
+ **attributes.except(:class)
65
+ ) { text }
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/base"
4
+
5
+ module DaisyuiOnPhlex
6
+ module Generators
7
+ class InstallGenerator < Rails::Generators::Base
8
+ desc "Install DaisyUI On Phlex"
9
+ source_root File.expand_path("templates", __dir__)
10
+
11
+ def copy_daisyui_files
12
+ say "Installing DaisyUI files...", :green
13
+
14
+ # Download DaisyUI files
15
+ run "curl -sLo app/assets/tailwind/daisyui.js https://github.com/saadeghi/daisyui/releases/latest/download/daisyui.js" rescue nil
16
+ run "curl -sLo app/assets/tailwind/daisyui-theme.js https://github.com/saadeghi/daisyui/releases/latest/download/daisyui-theme.js" rescue nil
17
+ end
18
+
19
+ def update_tailwind_config
20
+ tailwind_config_path = "app/assets/tailwind/application.css"
21
+
22
+ if File.exist?(tailwind_config_path)
23
+ say "Updating Tailwind CSS configuration...", :green
24
+
25
+ content = File.read(tailwind_config_path)
26
+
27
+ unless content.include?("@plugin \"./daisyui.js\"")
28
+ # Add DaisyUI plugin line after @import "tailwindcss"
29
+ updated_content = content.gsub(
30
+ /@import "tailwindcss" source\(none\);/,
31
+ "@import \"tailwindcss\" source(none);\n@plugin \"./daisyui.js\";"
32
+ )
33
+
34
+ File.write(tailwind_config_path, updated_content)
35
+ say "Added DaisyUI plugin to Tailwind CSS configuration", :green
36
+ else
37
+ say "DaisyUI plugin already configured in Tailwind CSS", :yellow
38
+ end
39
+ else
40
+ say "Tailwind CSS configuration not found. Please add @plugin \"./daisyui.js\"; to your Tailwind CSS configuration manually.", :yellow
41
+ end
42
+ end
43
+
44
+ def show_readme
45
+ say <<~TEXT, :green
46
+
47
+ DaisyUI On Phlex has been installed! 🎉
48
+
49
+ You can now use DaisyUI components in your Phlex views:
50
+
51
+ # In your Phlex view
52
+ class MyView < Phlex::HTML
53
+ def view_template
54
+ render DaisyuiOnPhlex::Components::Button.new(variant: :primary) do
55
+ "Click me!"
56
+ end
57
+
58
+ render DaisyuiOnPhlex::Components::Alert.new(variant: :success) do
59
+ "Success message"
60
+ end
61
+ end
62
+ end
63
+
64
+ Available components:
65
+ - Button
66
+ - Alert
67
+ - Card
68
+ - Badge
69
+ - Modal
70
+ - Input
71
+ - And more coming soon...
72
+
73
+ For more information, visit: https://github.com/jacob/daisyui-on-phlex
74
+
75
+ TEXT
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/railtie"
4
+
5
+ module DaisyuiOnPhlex
6
+ class Railtie < Rails::Railtie
7
+ initializer "daisyui_on_phlex.setup" do |app|
8
+ # Add any Rails-specific setup here
9
+ if defined?(Phlex::Rails)
10
+ # Ensure Phlex can find our components
11
+ app.config.autoload_paths += %W[
12
+ #{File.join(__dir__, "components")}
13
+ ]
14
+ end
15
+ end
16
+
17
+ generators do
18
+ require_relative "generators/install_generator"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,116 @@
1
+ /**
2
+ * DaisyUI on Phlex - Main CSS file
3
+ *
4
+ * This file provides the essential DaisyUI setup for Phlex components.
5
+ * Import this file in your application.css after importing Tailwind CSS.
6
+ *
7
+ * Usage:
8
+ * @import "tailwindcss";
9
+ * @import "daisyui_on_phlex/stylesheets/daisyui_on_phlex.css";
10
+ */
11
+
12
+ /* DaisyUI Plugin Configuration */
13
+ @plugin "daisyui" {
14
+ /* Enable commonly used themes with sensible defaults */
15
+ /* themes: light --default, dark --prefersdark, cupcake, dracula, emerald, corporate, synthwave, retro, cyberpunk, valentine, halloween, garden, forest, aqua, lofi, pastel, fantasy, wireframe, black, luxury, autumn, business, acid, lemonade, night, coffee, winter, dim, nord, sunset; */
16
+ themes: light --default, dark --prefersdark;
17
+
18
+ /* Disable logs in production for cleaner console output */
19
+ logs: false;
20
+ }
21
+
22
+ /* Base Styles for Better Component Integration */
23
+ :root {
24
+ /* Ensure smooth theme transitions */
25
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
26
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
27
+ transition-duration: 200ms;
28
+ }
29
+
30
+ /* Theme-aware focus styles for better accessibility */
31
+ *:focus-visible {
32
+ @apply outline-2 outline-offset-2 outline-primary;
33
+ }
34
+
35
+ /* Enhanced scrollbar styling using DaisyUI color variables */
36
+ * {
37
+ scrollbar-width: thin;
38
+ scrollbar-color: hsl(var(--color-base-content) / 0.2) transparent;
39
+ }
40
+
41
+ *::-webkit-scrollbar {
42
+ width: 8px;
43
+ height: 8px;
44
+ }
45
+
46
+ *::-webkit-scrollbar-track {
47
+ background: transparent;
48
+ }
49
+
50
+ *::-webkit-scrollbar-thumb {
51
+ background: hsl(var(--color-base-content) / 0.2);
52
+ border-radius: 0.25rem;
53
+ }
54
+
55
+ *::-webkit-scrollbar-thumb:hover {
56
+ background: hsl(var(--color-base-content) / 0.3);
57
+ }
58
+
59
+ /* Component-specific enhancements */
60
+
61
+ /* Ensure proper text wrapping in cards */
62
+ .card-body {
63
+ word-wrap: break-word;
64
+ overflow-wrap: break-word;
65
+ }
66
+
67
+ /* Better modal backdrop behavior */
68
+ .modal {
69
+ backdrop-filter: blur(4px);
70
+ }
71
+
72
+ /* Enhanced button states */
73
+ .btn:disabled {
74
+ @apply opacity-50 cursor-not-allowed;
75
+ }
76
+
77
+ /* Alert icon spacing */
78
+ .alert svg {
79
+ @apply shrink-0;
80
+ }
81
+
82
+ /* Badge content alignment */
83
+ .badge {
84
+ @apply inline-flex items-center justify-center;
85
+ }
86
+
87
+ /* Theme transition for all elements */
88
+ [data-theme] {
89
+ transition: color 200ms ease-in-out, background-color 200ms ease-in-out, border-color 200ms ease-in-out;
90
+ }
91
+
92
+ /* Reduced motion preferences */
93
+ @media (prefers-reduced-motion: reduce) {
94
+ *,
95
+ *::before,
96
+ *::after {
97
+ animation-duration: 0.01ms !important;
98
+ animation-iteration-count: 1 !important;
99
+ transition-duration: 0.01ms !important;
100
+ }
101
+ }
102
+
103
+ /* Print styles - ensure readability when printing */
104
+ @media print {
105
+ .modal,
106
+ .drawer,
107
+ .dropdown-content {
108
+ display: none !important;
109
+ }
110
+
111
+ .btn,
112
+ .card,
113
+ .alert {
114
+ break-inside: avoid;
115
+ }
116
+ }
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaisyuiOnPhlex
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tailwind_merge"
4
+ require_relative "daisyui_on_phlex/version"
5
+ require_relative "daisyui_on_phlex/base"
6
+ require_relative "daisyui_on_phlex/railtie" if defined?(Rails)
7
+
8
+ # Load all component files
9
+ Dir[File.join(__dir__, "daisyui_on_phlex", "components", "*.rb")].each { |file| require file }
10
+
11
+ module DaisyuiOnPhlex
12
+ class Error < StandardError; end
13
+ end
@@ -0,0 +1,4 @@
1
+ module DaisyuiOnPhlex
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end