lightning_ui_kit 0.2.5 → 0.3.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/Rakefile +2 -9
  4. data/app/assets/builds/lightning_ui_kit.css +31 -588
  5. data/app/assets/builds/lightning_ui_kit.js +2 -9
  6. data/app/assets/builds/lightning_ui_kit.js.map +4 -4
  7. data/app/assets/vendor/lightning_ui_kit.css +88 -582
  8. data/app/assets/vendor/lightning_ui_kit.js +2 -9
  9. data/app/components/lightning_ui_kit/button_component.html.erb +0 -4
  10. data/app/components/lightning_ui_kit/button_component.rb +3 -24
  11. data/app/components/lightning_ui_kit/checkbox_component.html.erb +7 -2
  12. data/app/components/lightning_ui_kit/checkbox_component.rb +0 -13
  13. data/app/components/lightning_ui_kit/dropdown_component.html.erb +1 -1
  14. data/app/components/lightning_ui_kit/dropdown_component.rb +1 -1
  15. data/app/components/lightning_ui_kit/dropzone_component.html.erb +38 -13
  16. data/app/components/lightning_ui_kit/dropzone_component.rb +16 -43
  17. data/app/components/lightning_ui_kit/file_input_component.html.erb +34 -4
  18. data/app/components/lightning_ui_kit/file_input_component.rb +20 -54
  19. data/app/components/lightning_ui_kit/input_component.html.erb +98 -14
  20. data/app/components/lightning_ui_kit/input_component.rb +19 -154
  21. data/app/components/lightning_ui_kit/modal_component.html.erb +2 -2
  22. data/app/components/lightning_ui_kit/select_component.html.erb +27 -6
  23. data/app/components/lightning_ui_kit/select_component.rb +23 -65
  24. data/app/components/lightning_ui_kit/textarea_component.html.erb +37 -5
  25. data/app/components/lightning_ui_kit/textarea_component.rb +17 -50
  26. data/app/javascript/lightning_ui_kit/controllers/modal_controller.js +1 -7
  27. data/app/javascript/lightning_ui_kit/index.js +0 -8
  28. data/config/deploy.yml +5 -2
  29. data/lib/lightning_ui_kit/engine.rb +6 -1
  30. data/lib/lightning_ui_kit/version.rb +1 -1
  31. metadata +17 -17
  32. data/app/components/lightning_ui_kit/combobox_component.html.erb +0 -137
  33. data/app/components/lightning_ui_kit/combobox_component.rb +0 -205
  34. data/app/components/lightning_ui_kit/layout_component.html.erb +0 -118
  35. data/app/components/lightning_ui_kit/layout_component.rb +0 -26
  36. data/app/components/lightning_ui_kit/sidebar_link_component.html.erb +0 -6
  37. data/app/components/lightning_ui_kit/sidebar_link_component.rb +0 -33
  38. data/app/components/lightning_ui_kit/sidebar_section_component.html.erb +0 -8
  39. data/app/components/lightning_ui_kit/sidebar_section_component.rb +0 -18
  40. data/app/components/lightning_ui_kit/tooltip_component.html.erb +0 -15
  41. data/app/components/lightning_ui_kit/tooltip_component.rb +0 -26
  42. data/app/javascript/lightning_ui_kit/controllers/combobox_controller.js +0 -704
  43. data/app/javascript/lightning_ui_kit/controllers/field_controller.js +0 -23
  44. data/app/javascript/lightning_ui_kit/controllers/layout_controller.js +0 -19
  45. data/app/javascript/lightning_ui_kit/controllers/tooltip_controller.js +0 -235
@@ -1,205 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class LightningUiKit::ComboboxComponent < LightningUiKit::BaseComponent
4
- include LightningUiKit::Errors
5
-
6
- def initialize(
7
- name: nil,
8
- form: nil,
9
- label: nil,
10
- description: nil,
11
- placeholder: nil,
12
- disabled: false,
13
- error: nil,
14
- multiple: false,
15
- allow_custom: false,
16
- options: [],
17
- selected: nil,
18
- url: nil,
19
- min_chars: 0,
20
- debounce: 300,
21
- association: nil,
22
- foreign_key: nil,
23
- nested_model: nil,
24
- collection: nil,
25
- label_method: :to_s,
26
- value_method: :id,
27
- **options_hash
28
- )
29
- @form = form
30
- @label = label
31
- @description = description
32
- @placeholder = placeholder
33
- @disabled = disabled
34
- @error = error
35
- @allow_custom = allow_custom
36
- @url = url
37
- @min_chars = min_chars
38
- @debounce = debounce
39
- @options_hash = options_hash
40
-
41
- @association = association
42
- @foreign_key = foreign_key
43
- @nested_model = nested_model
44
- @collection = collection
45
- @label_method = label_method
46
- @value_method = value_method
47
-
48
- if association_mode?
49
- @name = nested_attributes_name
50
- @multiple = true
51
- @options = derive_options_from_collection if @collection
52
- @selected = derive_selected_from_association if @form&.object
53
- else
54
- @name = name
55
- @multiple = multiple
56
- @options = options
57
- @selected = selected
58
- end
59
- end
60
-
61
- def classes
62
- merge_classes([
63
- "lui:[&>[data-slot=label]+[data-slot=control]]:mt-3",
64
- "lui:[&>[data-slot=label]+[data-slot=description]]:mt-1",
65
- "lui:[&>[data-slot=description]+[data-slot=control]]:mt-3",
66
- "lui:[&>[data-slot=control]+[data-slot=description]]:mt-3",
67
- "lui:[&>[data-slot=control]+[data-slot=error]]:mt-3",
68
- "lui:*:data-[slot=label]:font-medium",
69
- @options_hash[:class]
70
- ].compact.join(" "))
71
- end
72
-
73
- def data
74
- default_data = {
75
- controller: "lui-combobox",
76
- action: "click@window->lui-combobox#clickOutside"
77
- }
78
- default_data.merge(@options_hash[:data] || {}).merge(combobox_values)
79
- end
80
-
81
- def combobox_values
82
- base = {
83
- "lui-combobox-multiple-value" => @multiple,
84
- "lui-combobox-allow-custom-value" => @allow_custom,
85
- "lui-combobox-url-value" => @url,
86
- "lui-combobox-min-chars-value" => @min_chars,
87
- "lui-combobox-debounce-value" => @debounce,
88
- "lui-combobox-options-value" => options_json,
89
- "lui-combobox-selected-value" => selected_json
90
- }
91
-
92
- if association_mode?
93
- base["lui-combobox-foreign-key-value"] = @foreign_key.to_s
94
- base["lui-combobox-nested-model-value"] = @nested_model.to_s if @nested_model
95
- end
96
-
97
- base.compact
98
- end
99
-
100
- def association_mode?
101
- @association.present? && @foreign_key.present?
102
- end
103
-
104
- def input_data
105
- {
106
- "lui-combobox-target" => "input",
107
- :action => "input->lui-combobox#onInput focus->lui-combobox#onFocus keydown->lui-combobox#onKeydown"
108
- }.tap do |d|
109
- d[:invalid] = "true" if has_errors?
110
- end
111
- end
112
-
113
- def input_classes
114
- merge_classes([
115
- "lui:relative lui:block lui:w-full lui:appearance-none lui:rounded-lg",
116
- "lui:px-[calc(--spacing(3.5)-1px)] lui:py-[calc(--spacing(2.5)-1px)]",
117
- "lui:sm:px-[calc(--spacing(3)-1px)] lui:sm:py-[calc(--spacing(1.5)-1px)]",
118
- "lui:text-base/6 lui:text-zinc-950 lui:placeholder:text-zinc-500 lui:sm:text-sm/6",
119
- "lui:border lui:border-zinc-950/10 lui:data-[hover]:border-zinc-950/20",
120
- "lui:bg-transparent lui:focus:outline-hidden",
121
- "lui:data-invalid:border-red-500 lui:data-invalid:data-[hover]:border-red-500/60",
122
- "lui:data-disabled:border-zinc-950/20",
123
- "lui:pr-10"
124
- ].join(" "))
125
- end
126
-
127
- def label_data
128
- {slot: "label"}.merge(@options_hash[:label_data] || {}).tap do |data|
129
- data[:disabled] = "true" if @disabled
130
- end
131
- end
132
-
133
- def description_data
134
- {slot: "description"}.merge(@options_hash[:description_data] || {}).tap do |data|
135
- data[:disabled] = "true" if @disabled
136
- end
137
- end
138
-
139
- def error_data
140
- {slot: "error"}.merge(@options_hash[:error_data] || {}).tap do |data|
141
- data[:disabled] = "true" if @disabled
142
- end
143
- end
144
-
145
- def hidden_field_name
146
- base_name = scoped_field_name
147
-
148
- if association_mode?
149
- base_name
150
- elsif @multiple
151
- "#{base_name}[]"
152
- else
153
- base_name
154
- end
155
- end
156
-
157
- def scoped_field_name
158
- if @form
159
- "#{@form.object_name}[#{@name}]"
160
- else
161
- @name.to_s
162
- end
163
- end
164
-
165
- private
166
-
167
- def nested_attributes_name
168
- "#{@association}_attributes"
169
- end
170
-
171
- def derive_options_from_collection
172
- return [] unless @collection
173
-
174
- @collection.map do |item|
175
- {value: item.public_send(@value_method), label: item.public_send(@label_method)}
176
- end
177
- end
178
-
179
- def derive_selected_from_association
180
- return [] unless @form&.object&.respond_to?(@association)
181
-
182
- @form.object.public_send(@association).map do |join_record|
183
- {
184
- join_id: join_record.id,
185
- value: join_record.public_send(@foreign_key)
186
- }
187
- end
188
- end
189
-
190
- def options_json
191
- @options.to_json
192
- end
193
-
194
- def selected_json
195
- return [].to_json if @selected.nil?
196
-
197
- if association_mode?
198
- @selected.to_json
199
- elsif @selected.is_a?(Array)
200
- @selected.to_json
201
- else
202
- [@selected].to_json
203
- end
204
- end
205
- end
@@ -1,118 +0,0 @@
1
- <div class="lui:relative lui:isolate lui:flex lui:h-screen lui:w-full lui:bg-white lui:max-lg:flex-col lui:max-lg:h-auto lui:max-lg:min-h-screen lui:lg:bg-zinc-100 lui:overflow-hidden" data-controller="lui-layout">
2
- <%# Desktop Sidebar (fixed, hidden on mobile) %>
3
- <div class="lui:fixed lui:inset-y-0 lui:left-0 <%= sidebar_width_class %> lui:max-lg:hidden lui:z-10">
4
- <nav class="lui:flex lui:h-full lui:min-h-0 lui:flex-col">
5
- <%# Sidebar content %>
6
- <div class="lui:flex lui:flex-1 lui:flex-col lui:overflow-y-auto lui:p-4">
7
- <% if header? %>
8
- <div class="lui:mb-4">
9
- <%= header %>
10
- </div>
11
- <% end %>
12
- <% if sections? %>
13
- <div class="lui:space-y-6">
14
- <% sections.each do |section| %>
15
- <%= section %>
16
- <% end %>
17
- </div>
18
- <% end %>
19
- <%= sidebar %>
20
- </div>
21
-
22
- <%# Footer at bottom of sidebar %>
23
- <% if footer? %>
24
- <div class="lui:border-t lui:border-zinc-950/5">
25
- <%= footer %>
26
- </div>
27
- <% end %>
28
- </nav>
29
- </div>
30
-
31
- <%# Mobile Header (hidden on desktop) %>
32
- <header class="lui:flex lui:items-center lui:px-4 lui:lg:hidden">
33
- <div class="lui:py-2.5">
34
- <button
35
- type="button"
36
- aria-label="Open navigation"
37
- class="lui:cursor-pointer lui:relative lui:flex lui:min-w-0 lui:items-center lui:gap-3 lui:rounded-lg lui:p-2 lui:text-left lui:text-base/6 lui:font-medium lui:text-zinc-950 lui:sm:text-sm/5 lui:hover:bg-zinc-950/5"
38
- data-action="lui-layout#openSidebar"
39
- >
40
- <span class="lui:absolute lui:top-1/2 lui:left-1/2 lui:size-[max(100%,2.75rem)] lui:-translate-x-1/2 lui:-translate-y-1/2 [@media(pointer:fine)]:lui:hidden" aria-hidden="true"></span>
41
- <svg class="lui:size-6 lui:shrink-0 lui:fill-zinc-500 lui:sm:size-5" viewBox="0 0 20 20" aria-hidden="true">
42
- <path d="M2 6.75C2 6.33579 2.33579 6 2.75 6H17.25C17.6642 6 18 6.33579 18 6.75C18 7.16421 17.6642 7.5 17.25 7.5H2.75C2.33579 7.5 2 7.16421 2 6.75ZM2 13.25C2 12.8358 2.33579 12.5 2.75 12.5H17.25C17.6642 12.5 18 12.8358 18 13.25C18 13.6642 17.6642 14 17.25 14H2.75C2.33579 14 2 13.6642 2 13.25Z"></path>
43
- </svg>
44
- </button>
45
- </div>
46
- <div class="lui:min-w-0 lui:flex-1">
47
- <nav class="lui:flex lui:flex-1 lui:items-center lui:gap-4 lui:py-2.5">
48
- <% if mobile_header? %>
49
- <%= mobile_header %>
50
- <% end %>
51
- </nav>
52
- </div>
53
- </header>
54
-
55
- <%# Mobile Sidebar Overlay %>
56
- <div
57
- class="lui:group lui:fixed lui:inset-0 lui:z-50 lui:invisible lui:data-[open]:visible"
58
- data-lui-layout-target="overlay"
59
- >
60
- <%# Backdrop %>
61
- <div
62
- class="lui:fixed lui:inset-0 lui:bg-zinc-950/25 lui:opacity-0 lui:transition-opacity lui:duration-300 lui:group-data-[open]:opacity-100"
63
- data-action="click->lui-layout#closeSidebar"
64
- ></div>
65
-
66
- <%# Mobile Sidebar Panel %>
67
- <div class="lui:fixed lui:inset-y-0 lui:left-0 <%= sidebar_width_class %> lui:bg-white lui:-translate-x-full lui:transition-transform lui:duration-300 lui:ease-out lui:shadow-xl lui:group-data-[open]:translate-x-0">
68
- <nav class="lui:flex lui:h-full lui:min-h-0 lui:flex-col">
69
- <%# Close button %>
70
- <div class="lui:flex lui:items-center lui:justify-end lui:p-4">
71
- <button
72
- type="button"
73
- aria-label="Close navigation"
74
- class="lui:cursor-pointer lui:rounded-lg lui:p-2 lui:hover:bg-zinc-950/5"
75
- data-action="lui-layout#closeSidebar"
76
- >
77
- <svg class="lui:size-6 lui:fill-zinc-500" viewBox="0 0 20 20" aria-hidden="true">
78
- <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
79
- </svg>
80
- </button>
81
- </div>
82
-
83
- <%# Sidebar content %>
84
- <div class="lui:flex lui:flex-1 lui:flex-col lui:overflow-y-auto lui:p-4">
85
- <% if header? %>
86
- <div class="lui:mb-4">
87
- <%= header %>
88
- </div>
89
- <% end %>
90
- <% if sections? %>
91
- <div class="lui:space-y-6">
92
- <% sections.each do |section| %>
93
- <%= section %>
94
- <% end %>
95
- </div>
96
- <% end %>
97
- <%= sidebar %>
98
- </div>
99
-
100
- <%# Footer %>
101
- <% if footer? %>
102
- <div class="lui:border-t lui:border-zinc-950/5">
103
- <%= footer %>
104
- </div>
105
- <% end %>
106
- </nav>
107
- </div>
108
- </div>
109
-
110
- <%# Main Content Area %>
111
- <main class="lui:flex lui:flex-1 lui:flex-col lui:min-h-0 lui:pb-4 lui:lg:min-w-0 lui:lg:pt-4 lui:lg:pr-4 <%= main_padding_class %>">
112
- <div class="lui:flex-1 lui:min-h-0 lui:p-6 lui:lg:rounded-lg lui:lg:bg-white lui:lg:p-10 lui:lg:shadow-xs lui:lg:ring-1 lui:lg:ring-zinc-950/5 lui:lg:overflow-y-auto">
113
- <div class="lui:mx-auto lui:max-w-6xl">
114
- <%= content %>
115
- </div>
116
- </div>
117
- </main>
118
- </div>
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class LightningUiKit::LayoutComponent < LightningUiKit::BaseComponent
4
- renders_one :sidebar
5
- renders_one :header
6
- renders_many :sections, LightningUiKit::SidebarSectionComponent
7
- renders_one :footer
8
- renders_one :mobile_header
9
-
10
- def initialize(sidebar_width: "w-64", **options)
11
- @sidebar_width = sidebar_width
12
- @options = options
13
- end
14
-
15
- def sidebar_width_class
16
- if @sidebar_width == "w-64"
17
- "lui:lg:w-64"
18
- else
19
- "lui:lg:#{@sidebar_width}"
20
- end
21
- end
22
-
23
- def main_padding_class
24
- "lui:lg:pl-64"
25
- end
26
- end
@@ -1,6 +0,0 @@
1
- <%= link_to @url, class: classes, data: data do %>
2
- <% if @icon %>
3
- <%= heroicon(@icon, options: { class: icon_classes }) %>
4
- <% end %>
5
- <span><%= @title %></span>
6
- <% end %>
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class LightningUiKit::SidebarLinkComponent < LightningUiKit::BaseComponent
4
- def initialize(title:, url:, icon: nil, current: false, **options)
5
- @title = title
6
- @url = url
7
- @icon = icon
8
- @current = current
9
- @options = options
10
- end
11
-
12
- def classes
13
- base_classes = "lui:flex lui:items-center lui:gap-3 lui:rounded-lg lui:px-3 lui:py-2 lui:text-sm lui:transition-colors"
14
-
15
- if @current
16
- merge_classes([base_classes, "lui:bg-zinc-950/5 lui:text-zinc-950 lui:font-semibold", @options[:class]].compact.join(" "))
17
- else
18
- merge_classes([base_classes, "lui:text-zinc-600 lui:hover:bg-zinc-950/5 lui:hover:text-zinc-950", @options[:class]].compact.join(" "))
19
- end
20
- end
21
-
22
- def icon_classes
23
- if @current
24
- "lui:size-5 lui:shrink-0 lui:text-zinc-600"
25
- else
26
- "lui:size-5 lui:shrink-0 lui:text-zinc-400"
27
- end
28
- end
29
-
30
- def data
31
- @options[:data] || {}
32
- end
33
- end
@@ -1,8 +0,0 @@
1
- <div class="<%= classes %>">
2
- <% if @title %>
3
- <h3 class="<%= title_classes %>"><%= @title %></h3>
4
- <% end %>
5
- <% links.each do |link| %>
6
- <%= link %>
7
- <% end %>
8
- </div>
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class LightningUiKit::SidebarSectionComponent < LightningUiKit::BaseComponent
4
- renders_many :links, LightningUiKit::SidebarLinkComponent
5
-
6
- def initialize(title: nil, **options)
7
- @title = title
8
- @options = options
9
- end
10
-
11
- def classes
12
- merge_classes(["lui:space-y-1", @options[:class]].compact.join(" "))
13
- end
14
-
15
- def title_classes
16
- "lui:px-3 lui:py-2 lui:text-xs lui:font-medium lui:text-zinc-400 lui:uppercase lui:tracking-wider"
17
- end
18
- end
@@ -1,15 +0,0 @@
1
- <%= tag.div(
2
- data: data.merge({
3
- "lui-tooltip-active-value" => @active,
4
- "lui-tooltip-position-value" => @position
5
- }),
6
- class: "lui:inline-block") do %>
7
- <%= content %>
8
-
9
- <%= tag.div(data: { "lui-tooltip-target" => "template" }, class: "lui:hidden") do %>
10
- <%= tag.div( class: "lui:absolute lui:z-50 lui:px-3 lui:py-2 lui:text-sm lui:font-medium lui:text-white lui:bg-zinc-800 lui:rounded-lg lui:shadow-sm lui:opacity-0 lui:transition-opacity lui:duration-200 lui:ease-in-out") do %>
11
- <%= @text %>
12
- <%= tag.div( class: "tooltip-arrow lui:absolute lui:w-2 lui:h-2 lui:bg-zinc-800 lui:transform lui:rotate-45", data: { "tooltip-arrow" => "true" }) %>
13
- <% end %>
14
- <% end %>
15
- <% end %>
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class LightningUiKit::TooltipComponent < LightningUiKit::BaseComponent
4
- POSITION_OPTIONS = [:top, :bottom, :left, :right]
5
- DEFAULT_POSITION = :bottom
6
-
7
- def initialize(text: nil, position: DEFAULT_POSITION, active: true, **options)
8
- @text = text
9
- @position = position || DEFAULT_POSITION
10
- @active = active
11
- @options = options
12
- end
13
-
14
- def classes
15
- merge_classes(["lui:w-full lui:flex lui:justify-center lui:fixed lui:bottom-5", @options[:class]].compact.join(" "))
16
- end
17
-
18
- def data
19
- default_data = {
20
- controller: "lui-tooltip",
21
- action: "mouseenter->lui-tooltip#show mouseleave->lui-tooltip#hide focus->lui-tooltip#show blur->lui-tooltip#hide"
22
- }
23
-
24
- default_data.merge(@options[:data] || {})
25
- end
26
- end