phlex_ui 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/phlex_ui/alert/description.rb +17 -0
- data/lib/phlex_ui/alert/title.rb +17 -0
- data/lib/phlex_ui/alert.rb +36 -0
- data/lib/phlex_ui/alert_dialog/action.rb +17 -0
- data/lib/phlex_ui/alert_dialog/cancel.rb +21 -0
- data/lib/phlex_ui/alert_dialog/content.rb +45 -0
- data/lib/phlex_ui/alert_dialog/description.rb +17 -0
- data/lib/phlex_ui/alert_dialog/footer.rb +17 -0
- data/lib/phlex_ui/alert_dialog/header.rb +17 -0
- data/lib/phlex_ui/alert_dialog/title.rb +17 -0
- data/lib/phlex_ui/alert_dialog/trigger.rb +18 -0
- data/lib/phlex_ui/alert_dialog.rb +26 -0
- data/lib/phlex_ui/aspect_ratio.rb +33 -0
- data/lib/phlex_ui/avatar/fallback.rb +17 -0
- data/lib/phlex_ui/avatar/image.rb +26 -0
- data/lib/phlex_ui/avatar.rb +49 -0
- data/lib/phlex_ui/badge.rb +46 -62
- data/lib/phlex_ui/button.rb +86 -63
- data/lib/phlex_ui/card/content.rb +17 -0
- data/lib/phlex_ui/card/description.rb +17 -0
- data/lib/phlex_ui/card/footer.rb +17 -0
- data/lib/phlex_ui/card/header.rb +17 -0
- data/lib/phlex_ui/card/title.rb +17 -0
- data/lib/phlex_ui/card.rb +17 -0
- data/lib/phlex_ui/checkbox.rb +18 -0
- data/lib/phlex_ui/clipboard/popover.rb +36 -0
- data/lib/phlex_ui/clipboard/source.rb +19 -0
- data/lib/phlex_ui/clipboard/trigger.rb +20 -0
- data/lib/phlex_ui/clipboard.rb +39 -0
- data/lib/phlex_ui/codeblock.rb +105 -0
- data/lib/phlex_ui/collapsible/content.rb +18 -0
- data/lib/phlex_ui/collapsible/trigger.rb +19 -0
- data/lib/phlex_ui/collapsible.rb +25 -0
- data/lib/phlex_ui/context_menu/content.rb +25 -0
- data/lib/phlex_ui/context_menu/item.rb +66 -0
- data/lib/phlex_ui/context_menu/label.rb +24 -0
- data/lib/phlex_ui/context_menu/separator.rb +19 -0
- data/lib/phlex_ui/context_menu/trigger.rb +20 -0
- data/lib/phlex_ui/context_menu.rb +26 -0
- data/lib/phlex_ui/dialog/content.rb +78 -0
- data/lib/phlex_ui/dialog/description.rb +17 -0
- data/lib/phlex_ui/dialog/footer.rb +17 -0
- data/lib/phlex_ui/dialog/header.rb +17 -0
- data/lib/phlex_ui/dialog/middle.rb +17 -0
- data/lib/phlex_ui/dialog/title.rb +17 -0
- data/lib/phlex_ui/dialog/trigger.rb +19 -0
- data/lib/phlex_ui/dialog.rb +25 -0
- data/lib/phlex_ui/dropdown_menu/content.rb +22 -0
- data/lib/phlex_ui/dropdown_menu/item.rb +28 -0
- data/lib/phlex_ui/dropdown_menu/label.rb +17 -0
- data/lib/phlex_ui/dropdown_menu/separator.rb +19 -0
- data/lib/phlex_ui/dropdown_menu/trigger.rb +17 -0
- data/lib/phlex_ui/dropdown_menu.rb +26 -0
- data/lib/phlex_ui/form/item.rb +17 -0
- data/lib/phlex_ui/form/spacer.rb +17 -0
- data/lib/phlex_ui/form.rb +34 -0
- data/lib/phlex_ui/hint.rb +17 -0
- data/lib/phlex_ui/hover_card/content.rb +22 -0
- data/lib/phlex_ui/hover_card/trigger.rb +19 -0
- data/lib/phlex_ui/hover_card.rb +27 -0
- data/lib/phlex_ui/input.rb +29 -0
- data/lib/phlex_ui/input_error.rb +17 -0
- data/lib/phlex_ui/label.rb +17 -0
- data/lib/phlex_ui/link.rb +97 -0
- data/lib/phlex_ui/popover/content.rb +22 -0
- data/lib/phlex_ui/popover/trigger.rb +19 -0
- data/lib/phlex_ui/popover.rb +25 -0
- data/lib/phlex_ui/shortcut_key.rb +17 -0
- data/lib/phlex_ui/table/body.rb +17 -0
- data/lib/phlex_ui/table/builder.rb +77 -0
- data/lib/phlex_ui/table/caption.rb +17 -0
- data/lib/phlex_ui/table/cell.rb +17 -0
- data/lib/phlex_ui/table/footer.rb +17 -0
- data/lib/phlex_ui/table/head.rb +17 -0
- data/lib/phlex_ui/table/header.rb +17 -0
- data/lib/phlex_ui/table/row.rb +17 -0
- data/lib/phlex_ui/table.rb +19 -0
- data/lib/phlex_ui/tabs/content.rb +26 -0
- data/lib/phlex_ui/tabs/list.rb +17 -0
- data/lib/phlex_ui/tabs/trigger.rb +28 -0
- data/lib/phlex_ui/tabs.rb +25 -0
- data/lib/phlex_ui/theme_toggle.rb +41 -0
- data/lib/phlex_ui/tooltip/content.rb +22 -0
- data/lib/phlex_ui/tooltip/trigger.rb +17 -0
- data/lib/phlex_ui/tooltip.rb +25 -0
- data/lib/phlex_ui/typography/blockquote.rb +17 -0
- data/lib/phlex_ui/typography/h1.rb +17 -0
- data/lib/phlex_ui/typography/h2.rb +17 -0
- data/lib/phlex_ui/typography/h3.rb +17 -0
- data/lib/phlex_ui/typography/h4.rb +17 -0
- data/lib/phlex_ui/typography/inline_code.rb +17 -0
- data/lib/phlex_ui/typography/large.rb +17 -0
- data/lib/phlex_ui/typography/lead.rb +17 -0
- data/lib/phlex_ui/typography/list.rb +47 -0
- data/lib/phlex_ui/typography/list_item.rb +17 -0
- data/lib/phlex_ui/typography/muted.rb +17 -0
- data/lib/phlex_ui/typography/p.rb +17 -0
- data/lib/phlex_ui/typography/small.rb +17 -0
- metadata +112 -2
data/lib/phlex_ui/button.rb
CHANGED
@@ -1,73 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module PhlexUI
|
2
4
|
class Button < Base
|
3
|
-
def initialize(**
|
4
|
-
@variant =
|
5
|
-
@size =
|
6
|
-
@
|
7
|
-
|
5
|
+
def initialize(variant: :primary, size: :md, icon: false, **attrs)
|
6
|
+
@variant = variant.to_sym
|
7
|
+
@size = size.to_sym
|
8
|
+
@icon = icon
|
9
|
+
super(**attrs)
|
8
10
|
end
|
9
11
|
|
10
12
|
def template(&)
|
13
|
+
button(**attrs, &)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def size_classes
|
19
|
+
if @icon
|
20
|
+
case @size
|
21
|
+
when :sm then "h-6 w-6"
|
22
|
+
when :md then "h-9 w-9"
|
23
|
+
when :lg then "h-10 w-10"
|
24
|
+
when :xl then "h-12 w-12"
|
25
|
+
end
|
26
|
+
else
|
27
|
+
case @size
|
28
|
+
when :sm then "px-3 py-1.5 h-8 text-xs"
|
29
|
+
when :md then "px-4 py-2 h-9 text-sm"
|
30
|
+
when :lg then "px-4 py-2 h-10 text-base"
|
31
|
+
when :xl then "px-6 py-3 h-12 text-base"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def primary_classes
|
37
|
+
tokens(
|
38
|
+
"whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-text shadow hover:bg-primary/90",
|
39
|
+
size_classes
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
def link_classes
|
44
|
+
tokens(
|
45
|
+
"whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 text-primary underline-offset-4 hover:underline",
|
46
|
+
size_classes
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
def secondary_classes
|
51
|
+
tokens(
|
52
|
+
"whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-muted-background text-text shadow-sm hover:bg-opacity-80",
|
53
|
+
size_classes
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
def destructive_classes
|
58
|
+
tokens(
|
59
|
+
"whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-destructive text-white shadow-sm hover:bg-destructive/90",
|
60
|
+
size_classes
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
def outline_classes
|
65
|
+
tokens(
|
66
|
+
"whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border border-input bg-background shadow-sm hover:bg-accent-background hover:text-accent-text",
|
67
|
+
size_classes
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
def ghost_classes
|
72
|
+
tokens(
|
73
|
+
"whitespace-nowrap inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 hover:bg-accent-background hover:text-accent-text",
|
74
|
+
size_classes
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
def default_classes
|
11
79
|
case @variant
|
12
|
-
when :primary
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
-> { @size.nil? } => "px-4 py-2",
|
19
|
-
-> { @kwargs[:class] } => @kwargs[:class]
|
20
|
-
),
|
21
|
-
&)
|
22
|
-
when :link
|
23
|
-
button(
|
24
|
-
**@kwargs,
|
25
|
-
class: tokens(
|
26
|
-
"whitespace-nowrap inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 text-primary-600 dark:text-primary-400 underline-offset-4 hover:underline h-9 px-4 py-2",
|
27
|
-
-> { @kwargs[:class] } => @kwargs[:class]
|
28
|
-
),
|
29
|
-
&)
|
30
|
-
when :secondary
|
31
|
-
button(
|
32
|
-
**@kwargs,
|
33
|
-
class: tokens(
|
34
|
-
"whitespace-nowrap inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-primary-100 dark:bg-accent text-primary-600 dark:text-white shadow-sm hover:bg-primary-200 hover:text-primary-700 dark:hover:bg-opacity-10 h-9",
|
35
|
-
-> { @size == :icon } => "h-9 w-9 justify-center",
|
36
|
-
-> { @size.nil? } => "px-4 py-2",
|
37
|
-
-> { @kwargs[:class] } => @kwargs[:class]
|
38
|
-
),
|
39
|
-
&)
|
40
|
-
when :destructive
|
41
|
-
button(
|
42
|
-
**@kwargs,
|
43
|
-
class: tokens(
|
44
|
-
"whitespace-nowrap inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-destructive-600 hover:bg-destructive-700 dark:bg-destructive-500 dark:hover:bg-destructive-600 text-white shadow-sm h-9",
|
45
|
-
-> { @size == :icon } => "h-9 w-9 justify-center",
|
46
|
-
-> { @size.nil? } => "px-4 py-2",
|
47
|
-
-> { @kwargs[:class] } => @kwargs[:class]
|
48
|
-
),
|
49
|
-
&)
|
50
|
-
when :outline
|
51
|
-
button(
|
52
|
-
**@kwargs,
|
53
|
-
class: tokens(
|
54
|
-
"whitespace-nowrap inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border bg-transparent shadow-sm hover:bg-accent h-9",
|
55
|
-
-> { @size == :icon } => "h-9 w-9 justify-center",
|
56
|
-
-> { @size.nil? } => "px-4 py-2",
|
57
|
-
-> { @kwargs[:class] } => @kwargs[:class]
|
58
|
-
),
|
59
|
-
&)
|
60
|
-
when :ghost
|
61
|
-
button(
|
62
|
-
**@kwargs,
|
63
|
-
class: tokens(
|
64
|
-
"whitespace-nowrap inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 hover:bg-accent h-9",
|
65
|
-
-> { @size == :icon } => "h-9 w-9 justify-center",
|
66
|
-
-> { @size.nil? } => "px-4 py-2",
|
67
|
-
-> { @kwargs[:class] } => @kwargs[:class]
|
68
|
-
),
|
69
|
-
&)
|
80
|
+
when :primary then primary_classes
|
81
|
+
when :link then link_classes
|
82
|
+
when :secondary then secondary_classes
|
83
|
+
when :destructive then destructive_classes
|
84
|
+
when :outline then outline_classes
|
85
|
+
when :ghost then ghost_classes
|
70
86
|
end
|
71
87
|
end
|
88
|
+
|
89
|
+
def default_attrs
|
90
|
+
{
|
91
|
+
type: "button",
|
92
|
+
class: default_classes,
|
93
|
+
}
|
94
|
+
end
|
72
95
|
end
|
73
96
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhlexUI
|
4
|
+
class Checkbox < Base
|
5
|
+
def template
|
6
|
+
input(**attrs)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def default_attrs
|
12
|
+
{
|
13
|
+
type: "checkbox",
|
14
|
+
class: "peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 accent-primary"
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhlexUI
|
4
|
+
class Clipboard::Popover < Base
|
5
|
+
def initialize(type:, **attrs)
|
6
|
+
@type = type
|
7
|
+
super(**attrs)
|
8
|
+
end
|
9
|
+
|
10
|
+
def template(&)
|
11
|
+
template_tag(data: { clipboard_target: clipboard_target }) do
|
12
|
+
div(**attrs, &)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def clipboard_target
|
19
|
+
case @type
|
20
|
+
when :success
|
21
|
+
"successPopover"
|
22
|
+
when :error
|
23
|
+
"errorPopover"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def default_attrs
|
28
|
+
{
|
29
|
+
data: {
|
30
|
+
state: :open
|
31
|
+
},
|
32
|
+
class: "z-50 rounded-md text-sm border bg-background px-2 py-0.5 text-text shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhlexUI
|
4
|
+
class Clipboard::Trigger < Base
|
5
|
+
def template(&)
|
6
|
+
div(**attrs, &)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def default_attrs
|
12
|
+
{
|
13
|
+
data: {
|
14
|
+
clipboard_target: "trigger",
|
15
|
+
action: "click->clipboard#copy",
|
16
|
+
}
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhlexUI
|
4
|
+
class Clipboard < Base
|
5
|
+
def initialize(success: "Copied!", error: "Copy Failed!", **attrs)
|
6
|
+
@success = success
|
7
|
+
@error = error
|
8
|
+
super(**attrs)
|
9
|
+
end
|
10
|
+
|
11
|
+
def template(&)
|
12
|
+
div(**attrs) do
|
13
|
+
div(&)
|
14
|
+
success_popover
|
15
|
+
error_popover
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def success_popover
|
22
|
+
render Clipboard::Popover.new(type: :success) { @success }
|
23
|
+
end
|
24
|
+
|
25
|
+
def error_popover
|
26
|
+
render Clipboard::Popover.new(type: :error) { @error }
|
27
|
+
end
|
28
|
+
|
29
|
+
def default_attrs
|
30
|
+
{
|
31
|
+
data: {
|
32
|
+
controller: "clipboard",
|
33
|
+
clipboard_success_value: @success,
|
34
|
+
clipboard_error_value: @error,
|
35
|
+
}
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rouge"
|
4
|
+
|
5
|
+
module PhlexUI
|
6
|
+
class Codeblock < Base
|
7
|
+
FORMATTER = ::Rouge::Formatters::HTML.new
|
8
|
+
ROUGE_CSS = Rouge::Themes::Github.mode(:dark).render(scope: '.highlight') # See themes here: https://rouge-ruby.github.io/docs/Rouge/CSSTheme.html
|
9
|
+
|
10
|
+
def initialize(code, syntax:, clipboard: true, clipboard_success: "Copied!", clipboard_error: "Copy failed!", **attrs)
|
11
|
+
@code = code
|
12
|
+
@syntax = syntax.to_sym
|
13
|
+
@clipboard = clipboard
|
14
|
+
@clipboard_success = clipboard_success
|
15
|
+
@clipboard_error = clipboard_error
|
16
|
+
|
17
|
+
if @syntax == :ruby || @syntax == :html
|
18
|
+
@code = @code.gsub(/(?:^|\G) {2}/m, " ")
|
19
|
+
end
|
20
|
+
|
21
|
+
super(**attrs)
|
22
|
+
end
|
23
|
+
|
24
|
+
def template
|
25
|
+
style { ROUGE_CSS.html_safe } # For faster load times, move this to the head of your document. (Also move ROUGE_CSS value to head of document)
|
26
|
+
if @clipboard
|
27
|
+
with_clipboard
|
28
|
+
else
|
29
|
+
codeblock
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def default_attrs
|
36
|
+
{
|
37
|
+
class: "highlight text-sm max-h-[350px] after:content-none flex font-mono overflow-auto overflow-x rounded-md border !bg-stone-900 [&_pre]:p-4"
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def with_clipboard
|
42
|
+
render PhlexUI::Clipboard.new(success: @clipboard_success, error: @clipboard_error, class: 'relative') do
|
43
|
+
render PhlexUI::Clipboard::Source.new do
|
44
|
+
codeblock
|
45
|
+
end
|
46
|
+
div(class: "absolute top-2 right-2") do
|
47
|
+
render PhlexUI::Clipboard::Trigger.new do
|
48
|
+
render PhlexUI::Button.new(variant: :ghost, size: :sm, icon: true, class: 'text-white hover:text-white hover:bg-white/20') { clipboard_icon }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def codeblock
|
55
|
+
div(**attrs) do
|
56
|
+
div(class: "after:content-none") do
|
57
|
+
pre do
|
58
|
+
unsafe_raw FORMATTER.format(
|
59
|
+
lexer.lex(@code)
|
60
|
+
)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def lexer
|
67
|
+
Rouge::Lexer.find(@syntax)
|
68
|
+
end
|
69
|
+
|
70
|
+
def clipboard_icon
|
71
|
+
svg(
|
72
|
+
xmlns: "http://www.w3.org/2000/svg",
|
73
|
+
fill: "none",
|
74
|
+
viewbox: "0 0 24 24",
|
75
|
+
stroke_width: "1.5",
|
76
|
+
stroke: "currentColor",
|
77
|
+
class: "w-4 h-4"
|
78
|
+
) do |s|
|
79
|
+
s.path(
|
80
|
+
stroke_linecap: "round",
|
81
|
+
stroke_linejoin: "round",
|
82
|
+
d:
|
83
|
+
"M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"
|
84
|
+
)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def check_icon
|
89
|
+
svg(
|
90
|
+
xmlns: "http://www.w3.org/2000/svg",
|
91
|
+
fill: "none",
|
92
|
+
viewbox: "0 0 24 24",
|
93
|
+
stroke_width: "1.5",
|
94
|
+
stroke: "currentColor",
|
95
|
+
class: "w-4 h-4"
|
96
|
+
) do |s|
|
97
|
+
s.path(
|
98
|
+
stroke_linecap: "round",
|
99
|
+
stroke_linejoin: "round",
|
100
|
+
d: "M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
101
|
+
)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhlexUI
|
4
|
+
class Collapsible::Content < Base
|
5
|
+
def template(&)
|
6
|
+
div(**attrs, &)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def default_attrs
|
12
|
+
{
|
13
|
+
data: { collapsible_target: "content" },
|
14
|
+
class: 'overflow-y-hidden'
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhlexUI
|
4
|
+
class Collapsible::Trigger < Base
|
5
|
+
def template(&)
|
6
|
+
div(**attrs, &)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def default_attrs
|
12
|
+
{
|
13
|
+
data: {
|
14
|
+
action: "click->collapsible#toggle"
|
15
|
+
}
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhlexUI
|
4
|
+
class Collapsible < Base
|
5
|
+
def initialize(open: false, **attrs)
|
6
|
+
@open = open
|
7
|
+
super(**attrs)
|
8
|
+
end
|
9
|
+
|
10
|
+
def template(&)
|
11
|
+
div(**attrs, &)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def default_attrs
|
17
|
+
{
|
18
|
+
data: {
|
19
|
+
controller: 'collapsible',
|
20
|
+
collapsible_open_value: @open
|
21
|
+
}
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhlexUI
|
4
|
+
class ContextMenu::Content < Base
|
5
|
+
def template(&)
|
6
|
+
template_tag(data: { popover_target: "content" }) do
|
7
|
+
div(**attrs, &)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def default_attrs
|
14
|
+
{
|
15
|
+
role: "menu",
|
16
|
+
aria_orientation: "vertical",
|
17
|
+
data_state: "open",
|
18
|
+
class:
|
19
|
+
"z-50 min-w-[8rem] outline-none pointer-events-auto overflow-hidden rounded-md border bg-background p-1 text-text shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
20
|
+
tabindex: "-1",
|
21
|
+
data_orientation: "vertical",
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhlexUI
|
4
|
+
class ContextMenu::Item < Base
|
5
|
+
def initialize(href: "#", checked: false, shortcut: nil, disabled: false, **attrs)
|
6
|
+
@href = href
|
7
|
+
@checked = checked
|
8
|
+
@shortcut = shortcut
|
9
|
+
@disabled = disabled
|
10
|
+
|
11
|
+
super(**attrs)
|
12
|
+
end
|
13
|
+
|
14
|
+
def template(&)
|
15
|
+
a(**attrs) do
|
16
|
+
render_checkmark if @checked
|
17
|
+
yield
|
18
|
+
render_shortcut if @shortcut
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def render_checkmark
|
25
|
+
span(class: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center") do
|
26
|
+
span(data_state: "checked") do
|
27
|
+
svg(
|
28
|
+
width: "15",
|
29
|
+
height: "15",
|
30
|
+
viewbox: "0 0 15 15",
|
31
|
+
fill: "none",
|
32
|
+
xmlns: "http://www.w3.org/2000/svg",
|
33
|
+
class: "h-4 w-4"
|
34
|
+
) do |s|
|
35
|
+
s.path(
|
36
|
+
d:
|
37
|
+
"M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z",
|
38
|
+
fill: "currentColor",
|
39
|
+
fill_rule: "evenodd",
|
40
|
+
clip_rule: "evenodd"
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def render_shortcut
|
48
|
+
span(class: "ml-auto text-xs tracking-widest text-muted-text") { @shortcut }
|
49
|
+
end
|
50
|
+
|
51
|
+
def default_attrs
|
52
|
+
{
|
53
|
+
href: @href,
|
54
|
+
role: "menuitem",
|
55
|
+
class:
|
56
|
+
"relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent-background hover:text-accent-text focus:bg-accent-background focus:text-accent-text aria-selected:bg-accent-background aria-selected:text-accent-text data-[disabled]:pointer-events-none data-[disabled]:opacity-50 pl-8",
|
57
|
+
tabindex: "-1",
|
58
|
+
data_orientation: "vertical",
|
59
|
+
data_action: "click->popover#close",
|
60
|
+
data_popover_target: "menuItem",
|
61
|
+
data_disabled: @disabled,
|
62
|
+
disabled: @disabled
|
63
|
+
}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|