phlexy_ui 0.1.1 → 0.1.5
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 +4 -4
- data/lib/phlexy_ui/attribute_set.rb +28 -0
- data/lib/phlexy_ui/badge.rb +82 -0
- data/lib/phlexy_ui/base.rb +45 -31
- data/lib/phlexy_ui/button.rb +88 -7
- data/lib/phlexy_ui/card.rb +97 -21
- data/lib/phlexy_ui/class_list.rb +93 -0
- data/lib/phlexy_ui/collapsible_sub_menu.rb +53 -0
- data/lib/phlexy_ui/configurable.rb +24 -0
- data/lib/phlexy_ui/drawer.rb +75 -0
- data/lib/phlexy_ui/dropdown.rb +92 -0
- data/lib/phlexy_ui/link.rb +90 -0
- data/lib/phlexy_ui/loading.rb +98 -0
- data/lib/phlexy_ui/menu.rb +114 -0
- data/lib/phlexy_ui/menu_item.rb +50 -0
- data/lib/phlexy_ui/navbar.rb +32 -0
- data/lib/phlexy_ui/sub_menu.rb +37 -0
- data/lib/phlexy_ui/tab.rb +56 -0
- data/lib/phlexy_ui/tab_with_content.rb +50 -0
- data/lib/phlexy_ui/tab_without_content.rb +32 -0
- data/lib/phlexy_ui/tabs.rb +59 -0
- data/lib/phlexy_ui/tooltip.rb +77 -0
- data/lib/phlexy_ui/version.rb +1 -1
- data/lib/phlexy_ui.rb +1 -4
- metadata +45 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: da2c28aae3a33b6153c19f22a2d8845d1c92a7a94ad5f9ea0f326c22f419cd1d
|
4
|
+
data.tar.gz: 7fe16b4951c08d429c1e6c5848f7cab70bb3cfbc8170cfca56fccbddc1ddd3f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f10b63d841c5cec345f9a1da3e83ce402cd10924506a79820b6f115695d47db463e933d11943556754a88877645e6b8e05e8b4ceda64a92673bf74da967f65b
|
7
|
+
data.tar.gz: 37c963d0c597523910d93a7ba3a147663dd1dfcf980801ed52e2342eb53eb664ea2b898c85e083e8f8c45c56d4bad86b03d9d3e347df8a74dd9c274edcf41274
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module PhlexyUI
|
2
|
+
class AttributeSet
|
3
|
+
def initialize(base_modifiers, attributes_map)
|
4
|
+
@base_modifiers = base_modifiers
|
5
|
+
@attributes_map = attributes_map
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_h
|
9
|
+
attributes_modifiers.each_with_object({}) do |modifier, final_attributes_hash|
|
10
|
+
value = attributes_map[modifier]
|
11
|
+
|
12
|
+
if value.is_a?(Hash)
|
13
|
+
final_attributes_hash.merge!(value)
|
14
|
+
elsif value
|
15
|
+
final_attributes_hash[modifier] = value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :base_modifiers, :attributes_map
|
23
|
+
|
24
|
+
def attributes_modifiers
|
25
|
+
base_modifiers.select { |modifier| attributes_map.key?(modifier) }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhlexyUI
|
4
|
+
class Badge < Base
|
5
|
+
def initialize(*, as: :span, **)
|
6
|
+
super(*, **)
|
7
|
+
@as = as
|
8
|
+
end
|
9
|
+
|
10
|
+
def view_template(&)
|
11
|
+
generate_classes!(
|
12
|
+
component_html_class: :badge,
|
13
|
+
modifiers_map: BADGE_MODIFIERS_MAP,
|
14
|
+
base_modifiers:,
|
15
|
+
options:
|
16
|
+
).then do |classes|
|
17
|
+
public_send(as, class: classes, **options, &)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
BADGE_MODIFIERS_MAP = {
|
24
|
+
# "sm:badge-neutral"
|
25
|
+
# "md:badge-neutral"
|
26
|
+
# "lg:badge-neutral"
|
27
|
+
neutral: "badge-neutral",
|
28
|
+
# "sm:badge-primary"
|
29
|
+
# "md:badge-primary"
|
30
|
+
# "lg:badge-primary"
|
31
|
+
primary: "badge-primary",
|
32
|
+
# "sm:badge-secondary"
|
33
|
+
# "md:badge-secondary"
|
34
|
+
# "lg:badge-secondary"
|
35
|
+
secondary: "badge-secondary",
|
36
|
+
# "sm:badge-accent"
|
37
|
+
# "md:badge-accent"
|
38
|
+
# "lg:badge-accent"
|
39
|
+
accent: "badge-accent",
|
40
|
+
# "sm:badge-ghost"
|
41
|
+
# "md:badge-ghost"
|
42
|
+
# "lg:badge-ghost"
|
43
|
+
ghost: "badge-ghost",
|
44
|
+
# "sm:badge-info"
|
45
|
+
# "md:badge-info"
|
46
|
+
# "lg:badge-info"
|
47
|
+
info: "badge-info",
|
48
|
+
# "sm:badge-success"
|
49
|
+
# "md:badge-success"
|
50
|
+
# "lg:badge-success"
|
51
|
+
success: "badge-success",
|
52
|
+
# "sm:badge-warning"
|
53
|
+
# "md:badge-warning"
|
54
|
+
# "lg:badge-warning"
|
55
|
+
warning: "badge-warning",
|
56
|
+
# "sm:badge-error"
|
57
|
+
# "md:badge-error"
|
58
|
+
# "lg:badge-error"
|
59
|
+
error: "badge-error",
|
60
|
+
# "sm:badge-outline"
|
61
|
+
# "md:badge-outline"
|
62
|
+
# "lg:badge-outline"
|
63
|
+
outline: "badge-outline",
|
64
|
+
# "sm:badge-lg"
|
65
|
+
# "md:badge-lg"
|
66
|
+
# "lg:badge-lg"
|
67
|
+
lg: "badge-lg",
|
68
|
+
# "sm:badge-md"
|
69
|
+
# "md:badge-md"
|
70
|
+
# "lg:badge-md"
|
71
|
+
md: "badge-md",
|
72
|
+
# "sm:badge-sm"
|
73
|
+
# "md:badge-sm"
|
74
|
+
# "lg:badge-sm"
|
75
|
+
sm: "badge-sm",
|
76
|
+
# "sm:badge-xs"
|
77
|
+
# "md:badge-xs"
|
78
|
+
# "lg:badge-xs"
|
79
|
+
xs: "badge-xs"
|
80
|
+
}.freeze
|
81
|
+
end
|
82
|
+
end
|
data/lib/phlexy_ui/base.rb
CHANGED
@@ -2,47 +2,61 @@
|
|
2
2
|
|
3
3
|
module PhlexyUI
|
4
4
|
class Base < Phlex::HTML
|
5
|
-
def initialize(*
|
6
|
-
@
|
7
|
-
@sm_conditions = Array(sm)
|
8
|
-
@md_conditions = Array(md)
|
9
|
-
@lg_conditions = Array(lg)
|
5
|
+
def initialize(*base_modifiers, **options)
|
6
|
+
@base_modifiers = base_modifiers
|
10
7
|
@options = options
|
11
|
-
@data = options.delete(:data)
|
12
8
|
end
|
13
9
|
|
14
|
-
|
10
|
+
class << self
|
11
|
+
attr_reader :modifiers
|
12
|
+
|
13
|
+
private
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
:options,
|
21
|
-
:data,
|
22
|
-
:as
|
23
|
-
|
24
|
-
def classes
|
25
|
-
[
|
26
|
-
prefixed(self.class::BASE_HTML_CLASS),
|
27
|
-
*html_classes_for_conditions(normal_conditions),
|
28
|
-
*html_classes_for_conditions(sm_conditions, responsive_prefix: :sm),
|
29
|
-
*html_classes_for_conditions(md_conditions, responsive_prefix: :md),
|
30
|
-
*html_classes_for_conditions(lg_conditions, responsive_prefix: :lg)
|
31
|
-
]
|
15
|
+
def register_modifiers(modifiers)
|
16
|
+
@modifiers ||= {}
|
17
|
+
@modifiers.merge!(modifiers)
|
18
|
+
end
|
32
19
|
end
|
33
20
|
|
34
|
-
|
35
|
-
|
36
|
-
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :base_modifiers, :options, :as, :id
|
37
24
|
|
38
|
-
|
25
|
+
def modifiers
|
26
|
+
{
|
27
|
+
**self.class.modifiers,
|
28
|
+
**PhlexyUI.configuration.modifiers.for(component: self.class),
|
29
|
+
**PhlexyUI.configuration.modifiers.for(component: nil)
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def generate_classes!(
|
34
|
+
component_html_class: nil,
|
35
|
+
base_modifiers: [],
|
36
|
+
options: {},
|
37
|
+
modifiers_map: {}
|
38
|
+
)
|
39
|
+
ClassList.new(
|
40
|
+
component: self,
|
41
|
+
component_html_class:,
|
42
|
+
base_modifiers:,
|
43
|
+
options:,
|
44
|
+
modifiers_map:
|
45
|
+
).to_a.then do |classes|
|
46
|
+
classes.any? ? classes : nil
|
39
47
|
end
|
40
|
-
rescue KeyError => e
|
41
|
-
raise ArgumentError, "Condition `#{e.key}` is not defined for #{self.class}"
|
42
48
|
end
|
43
49
|
|
44
|
-
def
|
45
|
-
|
50
|
+
def generate_attributes(base_modifiers, attributes_map)
|
51
|
+
AttributeSet.new(base_modifiers, attributes_map).to_h
|
52
|
+
end
|
53
|
+
|
54
|
+
def render_as(*, as:, **, &)
|
55
|
+
if as.is_a?(Symbol)
|
56
|
+
render public_send(*, as:, **, &)
|
57
|
+
else
|
58
|
+
render as.new(*, **, &)
|
59
|
+
end
|
46
60
|
end
|
47
61
|
end
|
48
62
|
end
|
data/lib/phlexy_ui/button.rb
CHANGED
@@ -2,38 +2,119 @@
|
|
2
2
|
|
3
3
|
module PhlexyUI
|
4
4
|
class Button < Base
|
5
|
-
|
5
|
+
def initialize(*, as: :button, **)
|
6
|
+
super(*, **)
|
7
|
+
@as = as
|
8
|
+
end
|
9
|
+
|
10
|
+
def view_template(&)
|
11
|
+
generate_classes!(
|
12
|
+
component_html_class: :btn,
|
13
|
+
modifiers_map: BUTTON_MODIFIERS_MAP,
|
14
|
+
base_modifiers:,
|
15
|
+
options:
|
16
|
+
).then do |classes|
|
17
|
+
public_send(as, class: classes, **options, &)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
BUTTON_MODIFIERS_MAP = {
|
6
24
|
# Modifiers
|
25
|
+
# "sm:no-animation"
|
26
|
+
# "md:no-animation"
|
27
|
+
# "lg:no-animation"
|
7
28
|
no_animation: "no-animation",
|
29
|
+
# "sm:glass"
|
30
|
+
# "md:glass"
|
31
|
+
# "lg:glass"
|
8
32
|
glass: "glass",
|
33
|
+
# "sm:btn-ghost"
|
34
|
+
# "md:btn-ghost"
|
35
|
+
# "lg:btn-ghost"
|
9
36
|
ghost: "btn-ghost",
|
37
|
+
# "sm:btn-link"
|
38
|
+
# "md:btn-link"
|
39
|
+
# "lg:btn-link"
|
10
40
|
link: "btn-link",
|
41
|
+
# "sm:btn-outline"
|
42
|
+
# "md:btn-outline"
|
43
|
+
# "lg:btn-outline"
|
11
44
|
outline: "btn-outline",
|
45
|
+
# "sm:btn-active"
|
46
|
+
# "md:btn-active"
|
47
|
+
# "lg:btn-active"
|
12
48
|
active: "btn-active",
|
49
|
+
# "sm:btn-disabled"
|
50
|
+
# "md:btn-disabled"
|
51
|
+
# "lg:btn-disabled"
|
13
52
|
disabled: "btn-disabled",
|
53
|
+
# "sm:btn-lg"
|
54
|
+
# "md:btn-lg"
|
55
|
+
# "lg:btn-lg"
|
14
56
|
lg: "btn-lg",
|
57
|
+
# "sm:btn-md"
|
58
|
+
# "md:btn-md"
|
59
|
+
# "lg:btn-md"
|
15
60
|
md: "btn-md",
|
61
|
+
# "sm:btn-sm"
|
62
|
+
# "md:btn-sm"
|
63
|
+
# "lg:btn-sm"
|
16
64
|
sm: "btn-sm",
|
65
|
+
# "sm:btn-xs"
|
66
|
+
# "md:btn-xs"
|
67
|
+
# "lg:btn-xs"
|
17
68
|
xs: "btn-xs",
|
69
|
+
# "sm:btn-wide"
|
70
|
+
# "md:btn-wide"
|
71
|
+
# "lg:btn-wide"
|
18
72
|
wide: "btn-wide",
|
73
|
+
# "sm:btn-block"
|
74
|
+
# "md:btn-block"
|
75
|
+
# "lg:btn-block"
|
19
76
|
block: "btn-block",
|
77
|
+
# "sm:btn-circle"
|
78
|
+
# "md:btn-circle"
|
79
|
+
# "lg:btn-circle"
|
20
80
|
circle: "btn-circle",
|
81
|
+
# "sm:btn-square"
|
82
|
+
# "md:btn-square"
|
83
|
+
# "lg:btn-square"
|
21
84
|
square: "btn-square",
|
22
85
|
# Colors
|
86
|
+
# "sm:btn-neutral"
|
87
|
+
# "md:btn-neutral"
|
88
|
+
# "lg:btn-neutral"
|
23
89
|
neutral: "btn-neutral",
|
90
|
+
# "sm:btn-primary"
|
91
|
+
# "md:btn-primary"
|
92
|
+
# "lg:btn-primary"
|
24
93
|
primary: "btn-primary",
|
94
|
+
# "sm:btn-secondary"
|
95
|
+
# "md:btn-secondary"
|
96
|
+
# "lg:btn-secondary"
|
25
97
|
secondary: "btn-secondary",
|
98
|
+
# "sm:btn-accent"
|
99
|
+
# "md:btn-accent"
|
100
|
+
# "lg:btn-accent"
|
26
101
|
accent: "btn-accent",
|
102
|
+
# "sm:btn-info"
|
103
|
+
# "md:btn-info"
|
104
|
+
# "lg:btn-info"
|
27
105
|
info: "btn-info",
|
106
|
+
# "sm:btn-success"
|
107
|
+
# "md:btn-success"
|
108
|
+
# "lg:btn-success"
|
28
109
|
success: "btn-success",
|
110
|
+
# "sm:btn-warning"
|
111
|
+
# "md:btn-warning"
|
112
|
+
# "lg:btn-warning"
|
29
113
|
warning: "btn-warning",
|
114
|
+
# "sm:btn-error"
|
115
|
+
# "md:btn-error"
|
116
|
+
# "lg:btn-error"
|
30
117
|
error: "btn-error"
|
31
118
|
}.freeze
|
32
|
-
|
33
|
-
BASE_HTML_CLASS = "btn"
|
34
|
-
|
35
|
-
def view_template(&)
|
36
|
-
button(class: classes, data:, &)
|
37
|
-
end
|
38
119
|
end
|
39
120
|
end
|
data/lib/phlexy_ui/card.rb
CHANGED
@@ -2,42 +2,118 @@
|
|
2
2
|
|
3
3
|
module PhlexyUI
|
4
4
|
class Card < Base
|
5
|
-
CONDITIONS_CLASSES = {
|
6
|
-
# Modifiers
|
7
|
-
image_full: "image-full",
|
8
|
-
bordered: "card-bordered",
|
9
|
-
normal: "card-normal",
|
10
|
-
compact: "card-compact",
|
11
|
-
side: "card-side"
|
12
|
-
}.freeze
|
13
|
-
|
14
|
-
BASE_HTML_CLASS = "card"
|
15
|
-
|
16
5
|
def initialize(*, as: :section, **)
|
17
6
|
super(*, **)
|
18
7
|
@as = as
|
19
8
|
end
|
20
9
|
|
21
10
|
def view_template(&)
|
22
|
-
|
11
|
+
generate_classes!(
|
12
|
+
component_html_class: :card,
|
13
|
+
modifiers_map: modifiers,
|
14
|
+
base_modifiers:,
|
15
|
+
options:
|
16
|
+
).then do |classes|
|
17
|
+
public_send(as, class: classes, **options, &)
|
18
|
+
end
|
23
19
|
end
|
24
20
|
|
25
21
|
def body(**options, &)
|
26
|
-
|
27
|
-
|
28
|
-
|
22
|
+
generate_classes!(
|
23
|
+
component_html_class: :"card-body",
|
24
|
+
options:
|
25
|
+
).then do |classes|
|
26
|
+
div(class: classes, **options, &)
|
27
|
+
end
|
29
28
|
end
|
30
29
|
|
31
30
|
def title(**options, &)
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
generate_classes!(
|
32
|
+
component_html_class: :"card-title",
|
33
|
+
options:
|
34
|
+
).then do |classes|
|
35
|
+
header(class: classes, **options, &)
|
36
|
+
end
|
35
37
|
end
|
36
38
|
|
37
39
|
def actions(**options, &)
|
38
|
-
|
39
|
-
|
40
|
-
|
40
|
+
generate_classes!(
|
41
|
+
component_html_class: :"card-actions",
|
42
|
+
options:
|
43
|
+
).then do |classes|
|
44
|
+
footer(class: classes, **options, &)
|
45
|
+
end
|
41
46
|
end
|
47
|
+
|
48
|
+
register_modifiers(
|
49
|
+
# "sm:image-full"
|
50
|
+
# "md:image-full"
|
51
|
+
# "lg:image-full"
|
52
|
+
image_full: "image-full",
|
53
|
+
# "sm:card-bordered"
|
54
|
+
# "md:card-bordered"
|
55
|
+
# "lg:card-bordered"
|
56
|
+
bordered: "card-bordered",
|
57
|
+
# "sm:card-normal"
|
58
|
+
# "md:card-normal"
|
59
|
+
# "lg:card-normal"
|
60
|
+
normal: "card-normal",
|
61
|
+
# "sm:card-compact"
|
62
|
+
# "md:card-compact"
|
63
|
+
# "lg:card-compact"
|
64
|
+
compact: "card-compact",
|
65
|
+
# "sm:card-side"
|
66
|
+
# "md:card-side"
|
67
|
+
# "lg:card-side"
|
68
|
+
side: "card-side",
|
69
|
+
# "sm:glass"
|
70
|
+
# "md:glass"
|
71
|
+
# "lg:glass"
|
72
|
+
glass: "glass",
|
73
|
+
# "sm:bg-primary sm:text-primary-content"
|
74
|
+
# "md:bg-primary md:text-primary-content"
|
75
|
+
# "lg:bg-primary lg:text-primary-content"
|
76
|
+
primary: "bg-primary text-primary-content",
|
77
|
+
# "sm:bg-secondary sm:text-secondary-content"
|
78
|
+
# "md:bg-secondary md:text-secondary-content"
|
79
|
+
# "lg:bg-secondary lg:text-secondary-content"
|
80
|
+
secondary: "bg-secondary text-secondary-content",
|
81
|
+
# "sm:bg-accent sm:text-accent-content"
|
82
|
+
# "md:bg-accent md:text-accent-content"
|
83
|
+
# "lg:bg-accent lg:text-accent-content"
|
84
|
+
accent: "bg-accent text-accent-content",
|
85
|
+
# "sm:bg-neutral sm:text-neutral-content"
|
86
|
+
# "md:bg-neutral md:text-neutral-content"
|
87
|
+
# "lg:bg-neutral lg:text-neutral-content"
|
88
|
+
neutral: "bg-neutral text-neutral-content",
|
89
|
+
# "sm:bg-base-100 sm:text-base-content"
|
90
|
+
# "md:bg-base-100 md:text-base-content"
|
91
|
+
# "lg:bg-base-100 lg:text-base-content"
|
92
|
+
base_100: "bg-base-100 text-base-content",
|
93
|
+
# "sm:bg-base-200 sm:text-base-content"
|
94
|
+
# "md:bg-base-200 md:text-base-content"
|
95
|
+
# "lg:bg-base-200 lg:text-base-content"
|
96
|
+
base_200: "bg-base-200 text-base-content",
|
97
|
+
# "sm:bg-base-300 sm:text-base-content"
|
98
|
+
# "md:bg-base-300 md:text-base-content"
|
99
|
+
# "lg:bg-base-300 lg:text-base-content"
|
100
|
+
base_300: "bg-base-300 text-base-content",
|
101
|
+
# "sm:bg-info sm:text-info-content"
|
102
|
+
# "md:bg-info sm:text-info-content"
|
103
|
+
# "lg:bg-info sm:text-info-content"
|
104
|
+
info: "bg-info text-info-content",
|
105
|
+
# "sm:bg-success sm:text-success-content"
|
106
|
+
# "md:bg-success md:text-success-content"
|
107
|
+
# "lg:bg-success lg:text-success-content"
|
108
|
+
success: "bg-success text-success-content",
|
109
|
+
# "sm:bg-warning sm:text-warning-content"
|
110
|
+
# "md:bg-warning md:text-warning-content"
|
111
|
+
# "lg:bg-warning lg:text-warning-content"
|
112
|
+
warning: "bg-warning text-warning-content",
|
113
|
+
# "sm:bg-error sm:text-error-content"
|
114
|
+
# "md:bg-error md:text-error-content"
|
115
|
+
# "lg:bg-error lg:text-error-content"
|
116
|
+
error: "bg-error text-error-content"
|
117
|
+
)
|
42
118
|
end
|
43
119
|
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module PhlexyUI
|
2
|
+
class ClassList
|
3
|
+
RESPONSIVE_PREFIXES = %i[sm md lg xl].freeze
|
4
|
+
|
5
|
+
def initialize(
|
6
|
+
component:,
|
7
|
+
component_html_class: nil,
|
8
|
+
base_modifiers: [],
|
9
|
+
options: {},
|
10
|
+
modifiers_map: {}
|
11
|
+
)
|
12
|
+
@component_html_class = component_html_class
|
13
|
+
@base_modifiers = base_modifiers
|
14
|
+
@options = options
|
15
|
+
@modifiers_map = modifiers_map
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_a
|
19
|
+
classes = []
|
20
|
+
add_component_class(classes)
|
21
|
+
add_selected_modifiers_classes(classes)
|
22
|
+
add_responsive_modifiers_classes(classes)
|
23
|
+
add_class_option_classes(classes)
|
24
|
+
classes
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :component_html_class, :base_modifiers, :options, :modifiers_map
|
30
|
+
|
31
|
+
def selected_base_modifiers
|
32
|
+
base_modifiers.select { |modifier| modifiers_map.key?(modifier) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_component_class(classes)
|
36
|
+
return unless component_html_class
|
37
|
+
|
38
|
+
classes << with_config_prefix(component_html_class)
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_selected_modifiers_classes(classes)
|
42
|
+
classes.concat(
|
43
|
+
html_classes_for_modifiers(
|
44
|
+
selected_base_modifiers
|
45
|
+
)
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
def html_classes_for_modifiers(modifiers, responsive_prefix: nil)
|
50
|
+
modifiers.map do |modifier|
|
51
|
+
with_responsive_prefix(
|
52
|
+
with_config_prefix(
|
53
|
+
modifiers_map.fetch(modifier)
|
54
|
+
),
|
55
|
+
responsive_prefix
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_responsive_modifiers_classes(classes)
|
61
|
+
RESPONSIVE_PREFIXES.each do |responsive_prefix|
|
62
|
+
if (values = options.delete(responsive_prefix))
|
63
|
+
classes.concat(
|
64
|
+
html_classes_for_modifiers(
|
65
|
+
Array(values),
|
66
|
+
responsive_prefix:
|
67
|
+
)
|
68
|
+
)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_class_option_classes(classes)
|
74
|
+
classes << options.delete(:class) if options[:class]
|
75
|
+
end
|
76
|
+
|
77
|
+
def with_config_prefix(string)
|
78
|
+
string.to_s.split.map do |word|
|
79
|
+
"#{PhlexyUI.configuration.prefix}#{word}"
|
80
|
+
end.join(" ")
|
81
|
+
end
|
82
|
+
|
83
|
+
def with_responsive_prefix(string, responsive_prefix = nil)
|
84
|
+
string.split.map do |word|
|
85
|
+
if responsive_prefix
|
86
|
+
"#{responsive_prefix}:#{word}"
|
87
|
+
else
|
88
|
+
word
|
89
|
+
end
|
90
|
+
end.join(" ")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhlexyUI
|
4
|
+
# @private
|
5
|
+
class CollapsibleSubMenu < Base
|
6
|
+
include Phlex::DeferredRender
|
7
|
+
|
8
|
+
def initialize(*, **)
|
9
|
+
super
|
10
|
+
@items ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
def view_template(&)
|
14
|
+
attributes = generate_attributes(base_modifiers, ATTRIBUTES_MAP)
|
15
|
+
|
16
|
+
details(**attributes) do
|
17
|
+
if @title
|
18
|
+
summary do
|
19
|
+
render @title
|
20
|
+
end
|
21
|
+
else
|
22
|
+
raise ArgumentError, "A collapsible submenu requires a title"
|
23
|
+
end
|
24
|
+
|
25
|
+
if @items.any?
|
26
|
+
ul do
|
27
|
+
@items.each do |item|
|
28
|
+
render item
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def title(&block)
|
36
|
+
if @title
|
37
|
+
raise ArgumentError, "A collapsible submenu can only have one title"
|
38
|
+
else
|
39
|
+
@title = block
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def item(*, **, &)
|
44
|
+
@items << MenuItem.new(*, **, &)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
ATTRIBUTES_MAP = {
|
50
|
+
open: true
|
51
|
+
}.freeze
|
52
|
+
end
|
53
|
+
end
|
@@ -10,12 +10,36 @@ module PhlexyUI
|
|
10
10
|
@configuration ||= Configuration.new
|
11
11
|
end
|
12
12
|
|
13
|
+
class Modifiers
|
14
|
+
def initialize
|
15
|
+
@modifiers = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def add(modifier, classes:, component: nil)
|
19
|
+
@modifiers[component] ||= {}
|
20
|
+
@modifiers[component][modifier] = classes
|
21
|
+
end
|
22
|
+
|
23
|
+
def remove(modifier, component: nil)
|
24
|
+
@modifiers[component] ||= {}
|
25
|
+
@modifiers[component]&.delete(modifier)
|
26
|
+
end
|
27
|
+
|
28
|
+
def for(component: nil)
|
29
|
+
@modifiers[component] || {}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
13
33
|
class Configuration
|
14
34
|
attr_accessor :prefix
|
15
35
|
|
16
36
|
def initialize
|
17
37
|
@prefix = nil
|
18
38
|
end
|
39
|
+
|
40
|
+
def modifiers
|
41
|
+
@modifiers ||= Modifiers.new
|
42
|
+
end
|
19
43
|
end
|
20
44
|
end
|
21
45
|
end
|