ariadne_view_components 0.0.84 → 0.0.86

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/app/assets/javascripts/ariadne_view_components.js +7 -7
  4. data/app/assets/javascripts/ariadne_view_components.js.br +0 -0
  5. data/app/assets/javascripts/ariadne_view_components.js.gz +0 -0
  6. data/app/assets/javascripts/ariadne_view_components.js.map +1 -1
  7. data/app/assets/stylesheets/ariadne_view_components.css +1 -1
  8. data/app/assets/stylesheets/ariadne_view_components.css.br +0 -0
  9. data/app/assets/stylesheets/ariadne_view_components.css.gz +0 -0
  10. data/app/components/ariadne/base_component.rb +15 -5
  11. data/app/components/ariadne/form/base_component.rb +1 -1
  12. data/app/components/ariadne/form/checkbox/component.html.erb +1 -1
  13. data/app/components/ariadne/form/checkbox/component.rb +15 -3
  14. data/app/components/ariadne/form/radio_button/component.html.erb +1 -3
  15. data/app/components/ariadne/form/select/component.html.erb +4 -2
  16. data/app/components/ariadne/form/select/component.rb +50 -2
  17. data/app/components/ariadne/form/toggle_group/component.html.erb +7 -0
  18. data/app/components/ariadne/form/toggle_group/component.rb +35 -0
  19. data/app/components/ariadne/form/toggle_group/option/component.html.erb +8 -0
  20. data/app/components/ariadne/form/toggle_group/option/component.rb +46 -0
  21. data/app/components/ariadne/layout/label_block/component.html.erb +12 -0
  22. data/app/components/ariadne/layout/label_block/component.rb +39 -0
  23. data/app/components/ariadne/layout/nav_bar/component.rb +4 -4
  24. data/app/components/ariadne/layout/section_block/component.html.erb +4 -0
  25. data/app/components/ariadne/layout/section_block/component.rb +12 -0
  26. data/app/components/ariadne/layout/section_block/header/component.html.erb +4 -0
  27. data/app/components/ariadne/layout/section_block/header/component.rb +14 -0
  28. data/app/components/ariadne/ui/avatar/component.html.erb +7 -0
  29. data/app/components/ariadne/ui/avatar/component.rb +54 -0
  30. data/app/components/ariadne/ui/badge/component.rb +8 -0
  31. data/app/components/ariadne/ui/card/body/component.html.erb +3 -0
  32. data/app/components/ariadne/ui/card/body/component.rb +25 -0
  33. data/app/components/ariadne/ui/card/component.html.erb +2 -6
  34. data/app/components/ariadne/ui/card/component.rb +1 -0
  35. data/app/components/ariadne/ui/combobox/component.rb +2 -0
  36. data/app/components/ariadne/ui/list/component.html.erb +2 -2
  37. data/app/components/ariadne/ui/list/component.rb +4 -3
  38. data/app/components/ariadne/ui/pagination/component.html.erb +29 -0
  39. data/app/components/ariadne/ui/pagination/component.rb +30 -0
  40. data/app/components/ariadne/ui/stats_panel/component.html.erb +7 -0
  41. data/app/components/ariadne/ui/stats_panel/component.rb +12 -0
  42. data/app/components/ariadne/ui/stats_panel/item/component.html.erb +4 -0
  43. data/app/components/ariadne/ui/stats_panel/item/component.rb +27 -0
  44. data/app/components/ariadne/ui/time_ago/component.html.erb +1 -0
  45. data/app/components/ariadne/ui/time_ago/component.rb +155 -0
  46. data/app/components/ariadne/ui/time_ago/en.yml +12 -0
  47. data/app/components/ariadne/ui/toggle/component.html.erb +7 -0
  48. data/app/components/ariadne/ui/toggle/component.rb +124 -0
  49. data/app/components/ariadne/ui/toggle/component.ts +133 -0
  50. data/app/lib/ariadne/fetch_or_fallback_helper.rb +23 -0
  51. data/lib/ariadne/view_components/engine.rb +4 -0
  52. data/lib/ariadne/view_components/version.rb +1 -1
  53. metadata +28 -2
@@ -0,0 +1,124 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ module Ariadne
5
+ module UI
6
+ module Toggle
7
+ class Component < Ariadne::BaseComponent
8
+ option :size, default: proc { :md }
9
+ option :reversed, default: proc { false }
10
+
11
+ # @param form_url [String] The URL to POST to when the toggle switch is toggled. If `nil`, the toggle switch will not make any requests.
12
+ # @param csrf_token [String] A CSRF token that will be sent to the server as "authenticity_token" when the toggle switch is toggled. Unused if `src` is `nil`.
13
+ # @param checked [Boolean] Whether the toggle switch is on or off.
14
+ # @param enabled [Boolean] Whether or not the toggle switch responds to user input.
15
+ option :form_url, default: proc { nil }
16
+ option :form_method, default: proc { :post }
17
+ option :checked, default: proc { false }
18
+ option :enabled, default: proc { true }
19
+
20
+ accepts_html_attributes do |html_attrs|
21
+ html_attrs[:class] = Ariadne::ViewComponents.tailwind_merger.merge([style(size:), html_attrs[:class]].join(" "))
22
+
23
+ if @checked
24
+ html_attrs[:checked] = @checked
25
+ html_attrs["aria-pressed"] = @checked
26
+ end
27
+
28
+ html_attrs[:data] ||= {}
29
+ html_attrs[:data] = {
30
+ controller: "#{stimulus_name} #{html_attrs[:data].delete(:controller)}".strip,
31
+ "#{stimulus_name}-target": "toggle",
32
+ action: "click->#{stimulus_name}#toggle #{html_attrs[:data].delete(:action)}".strip,
33
+ }.merge(html_attrs[:data])
34
+ end
35
+
36
+ def before_render
37
+ @label_id = ::Ariadne::ViewHelper.generate_id
38
+
39
+ if @form_url.present?
40
+ csrf_token = view_context.form_authenticity_token(
41
+ form_options: {
42
+ method: @form_method,
43
+ action: @form_url,
44
+ },
45
+ )
46
+
47
+ form_values = {
48
+ "#{stimulus_name}-csrf-token-value": csrf_token,
49
+ "#{stimulus_name}-form-method-value": @form_method,
50
+ "#{stimulus_name}-form-url-value": @form_url,
51
+ }
52
+ html_attrs[:data] = html_attrs[:data].merge(form_values)
53
+ end
54
+ end
55
+
56
+ style do
57
+ base do
58
+ [
59
+ "ariadne-peer",
60
+ "ariadne-relative",
61
+ "ariadne-rounded-full",
62
+ "peer-focus:ariadne-ring-2",
63
+ "ariadne-bg-zinc-200",
64
+ "dark:ariadne-bg-zinc-700",
65
+ "peer-checked:ariadne-bg-indigo-500",
66
+
67
+ "after:ariadne-absolute",
68
+ "after:ariadne-content-['']",
69
+ "after:ariadne-start-0.5",
70
+ "after:ariadne-top-0.5",
71
+ "after:ariadne-rounded-full",
72
+ "after:ariadne-transition-all",
73
+ "after:ariadne-bg-white",
74
+ "peer-checked:after:ariadne-translate-x-full",
75
+ ]
76
+ end
77
+
78
+ variants do
79
+ size do
80
+ sm do
81
+ [
82
+ "ariadne-w-7",
83
+ "ariadne-h-4",
84
+ "after:ariadne-h-3",
85
+ "after:ariadne-w-3",
86
+ ]
87
+ end
88
+ md do
89
+ [
90
+ "ariadne-w-9",
91
+ "ariadne-h-5",
92
+ "after:ariadne-h-4",
93
+ "after:ariadne-w-4",
94
+ ]
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ style(:label) do
101
+ base do
102
+ [
103
+ "ariadne-relative",
104
+ "ariadne-inline-flex",
105
+ "ariadne-gap-3",
106
+ "ariadne-items-center",
107
+ "ariadne-cursor-pointer",
108
+ ]
109
+ end
110
+
111
+ variants do
112
+ reversed do
113
+ yes do
114
+ ["ariadne-flex-row-reverse"]
115
+ end
116
+ no do
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,133 @@
1
+ import {controllerFactory} from '@utils/createController'
2
+
3
+ export default class ToggleController extends controllerFactory<HTMLInputElement>()({
4
+ targets: {
5
+ toggle: HTMLInputElement,
6
+ },
7
+ values: {
8
+ formMethod: String,
9
+ formUrl: String,
10
+ csrfToken: String,
11
+ },
12
+ }) {
13
+ connect() {
14
+ this.toggling = false
15
+ }
16
+
17
+ requiresFormSubmit(): boolean {
18
+ return this.formUrlValue != null
19
+ }
20
+
21
+ async toggle() {
22
+ if (this.toggling) return
23
+
24
+ this.toggling = true
25
+
26
+ if (this.isDisabled()) {
27
+ return
28
+ }
29
+
30
+ if (!this.requiresFormSubmit()) {
31
+ this.performToggle()
32
+ this.toggling = false
33
+ return
34
+ }
35
+
36
+ // toggle immediately to tell screen readers the switch was clicked
37
+ this.performToggle()
38
+
39
+ try {
40
+ await this.submitForm()
41
+ } catch (error) {
42
+ if (error instanceof Error) {
43
+ // because we toggle immediately when the switch is clicked, toggle back to the
44
+ // old state on failure
45
+ // this.setErrorState(error.message || 'An error occurred, please try again.')
46
+ this.performToggle()
47
+ }
48
+
49
+ return
50
+ } finally {
51
+ this.toggling = false
52
+ }
53
+
54
+ // this.setSuccessState()
55
+ }
56
+
57
+ performToggle(): void {
58
+ if (this.isOn()) {
59
+ this.turnOff()
60
+ } else {
61
+ this.turnOn()
62
+ }
63
+ }
64
+
65
+ turnOn(): void {
66
+ if (this.isDisabled()) {
67
+ return
68
+ }
69
+
70
+ this.toggleTarget.setAttribute('aria-pressed', 'true')
71
+ }
72
+
73
+ turnOff(): void {
74
+ if (this.isDisabled()) {
75
+ return
76
+ }
77
+
78
+ this.toggleTarget.setAttribute('aria-pressed', 'false')
79
+ }
80
+
81
+ isOn(): boolean {
82
+ return this.toggleTarget.getAttribute('aria-pressed') === 'true'
83
+ }
84
+
85
+ isOff(): boolean {
86
+ return !this.isOn()
87
+ }
88
+
89
+ isDisabled(): boolean {
90
+ return this.toggleTarget.getAttribute('disabled') != null
91
+ }
92
+
93
+ private async submitForm() {
94
+ const body = new FormData()
95
+
96
+ const csrfToken = this.documentCsrfToken() || this.csrfTokenValue
97
+ if (csrfToken) {
98
+ body.append(this.csrfField(), csrfToken)
99
+ }
100
+
101
+ body.append(this.toggleTarget.name, this.isOn() ? 'true' : 'false')
102
+
103
+ if (!this.formUrlValue) throw new Error('invalid src')
104
+
105
+ let response
106
+
107
+ try {
108
+ response = await fetch(this.formUrlValue, {
109
+ credentials: 'same-origin',
110
+ method: this.formMethodValue,
111
+ headers: {
112
+ 'Requested-With': 'XMLHttpRequest',
113
+ },
114
+ body,
115
+ })
116
+ } catch (error) {
117
+ throw new Error('A network error occurred, please try again.')
118
+ }
119
+
120
+ if (!response.ok) {
121
+ throw new Error(await response.text())
122
+ }
123
+ }
124
+
125
+ // the authenticity token is passed into the element and is not generated in js land
126
+ private csrfField(): string {
127
+ return this.toggleTarget.getAttribute('csrf-field') || 'authenticity_token'
128
+ }
129
+ private documentCsrfToken(): string | null {
130
+ const meta = document.querySelector('meta[name=csrf-token]')
131
+ return meta && meta.getAttribute('content')
132
+ }
133
+ }
@@ -26,6 +26,29 @@ module Ariadne
26
26
 
27
27
  INTEGER_TYPES = Set.new(["Integer"]).freeze
28
28
 
29
+ def fetch_or_fallback(allowed_values, given_value, fallback = nil, deprecated_values: nil)
30
+ if allowed_values.include?(given_value)
31
+ given_value
32
+ elsif deprecated_values&.include?(given_value)
33
+ ::Ariadne::ViewComponents.deprecation.warn("#{given_value} is deprecated and will be removed in a future version.") unless Rails.env.production? || silence_deprecations?
34
+
35
+ given_value
36
+ else
37
+ if fallback_raises && ENV["RAILS_ENV"] != "production"
38
+ raise InvalidValueError, <<~MSG
39
+ fetch_or_fallback was called with an invalid value.
40
+
41
+ Expected one of: #{allowed_values.inspect}
42
+ Got: #{given_value.inspect}
43
+
44
+ This will not raise in production, but will instead fallback to: #{fallback.inspect}
45
+ MSG
46
+ end
47
+
48
+ fallback
49
+ end
50
+ end
51
+
29
52
  def fetch_or_raise(allowed_values, given_value, against: nil)
30
53
  if !allowed_values.is_a?(Array) && !allowed_values.is_a?(Set)
31
54
  raise ArgumentError, "allowed_values must be an array or a set; it was #{allowed_values.class}"
@@ -61,6 +61,10 @@ module Ariadne
61
61
  end
62
62
  end
63
63
 
64
+ initializer "i18n.load_path" do
65
+ config.i18n.load_path.concat(Dir[Engine.root.join.join("app", "components", "**", "*.yml")])
66
+ end
67
+
64
68
  config.after_initialize do |_app|
65
69
  Ariadne::ViewComponents.tailwind_merger = TailwindMerge::Merger.new(config: { prefix: "ariadne-" })
66
70
  end
@@ -3,6 +3,6 @@
3
3
  # :nocov:
4
4
  module Ariadne
5
5
  module ViewComponents
6
- VERSION = "0.0.84"
6
+ VERSION = "0.0.86"
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ariadne_view_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.84
4
+ version: 0.0.86
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garen J. Torikian
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-12 00:00:00.000000000 Z
11
+ date: 2024-08-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tailwind_merge
@@ -157,17 +157,27 @@ files:
157
157
  - app/components/ariadne/form/separator/component.rb
158
158
  - app/components/ariadne/form/text_field/component.html.erb
159
159
  - app/components/ariadne/form/text_field/component.rb
160
+ - app/components/ariadne/form/toggle_group/component.html.erb
161
+ - app/components/ariadne/form/toggle_group/component.rb
162
+ - app/components/ariadne/form/toggle_group/option/component.html.erb
163
+ - app/components/ariadne/form/toggle_group/option/component.rb
160
164
  - app/components/ariadne/form/validation_message/component.html.erb
161
165
  - app/components/ariadne/form/validation_message/component.rb
162
166
  - app/components/ariadne/layout/grid/component.html.erb
163
167
  - app/components/ariadne/layout/grid/component.rb
164
168
  - app/components/ariadne/layout/grid/item/component.html.erb
165
169
  - app/components/ariadne/layout/grid/item/component.rb
170
+ - app/components/ariadne/layout/label_block/component.html.erb
171
+ - app/components/ariadne/layout/label_block/component.rb
166
172
  - app/components/ariadne/layout/narrow/component.html.erb
167
173
  - app/components/ariadne/layout/narrow/component.rb
168
174
  - app/components/ariadne/layout/nav_bar/component.css
169
175
  - app/components/ariadne/layout/nav_bar/component.html.erb
170
176
  - app/components/ariadne/layout/nav_bar/component.rb
177
+ - app/components/ariadne/layout/section_block/component.html.erb
178
+ - app/components/ariadne/layout/section_block/component.rb
179
+ - app/components/ariadne/layout/section_block/header/component.html.erb
180
+ - app/components/ariadne/layout/section_block/header/component.rb
171
181
  - app/components/ariadne/layout/two_panel/component.html.erb
172
182
  - app/components/ariadne/layout/two_panel/component.rb
173
183
  - app/components/ariadne/layout/wide/component.html.erb
@@ -181,12 +191,16 @@ files:
181
191
  - app/components/ariadne/ui/accordion/component.ts
182
192
  - app/components/ariadne/ui/accordion/item/component.html.erb
183
193
  - app/components/ariadne/ui/accordion/item/component.rb
194
+ - app/components/ariadne/ui/avatar/component.html.erb
195
+ - app/components/ariadne/ui/avatar/component.rb
184
196
  - app/components/ariadne/ui/badge/component.html.erb
185
197
  - app/components/ariadne/ui/badge/component.rb
186
198
  - app/components/ariadne/ui/blankslate/component.html.erb
187
199
  - app/components/ariadne/ui/blankslate/component.rb
188
200
  - app/components/ariadne/ui/button/component.html.erb
189
201
  - app/components/ariadne/ui/button/component.rb
202
+ - app/components/ariadne/ui/card/body/component.html.erb
203
+ - app/components/ariadne/ui/card/body/component.rb
190
204
  - app/components/ariadne/ui/card/component.html.erb
191
205
  - app/components/ariadne/ui/card/component.rb
192
206
  - app/components/ariadne/ui/card/footer/component.html.erb
@@ -220,11 +234,17 @@ files:
220
234
  - app/components/ariadne/ui/overlay/component.html.erb
221
235
  - app/components/ariadne/ui/overlay/component.rb
222
236
  - app/components/ariadne/ui/overlay/component.ts
237
+ - app/components/ariadne/ui/pagination/component.html.erb
238
+ - app/components/ariadne/ui/pagination/component.rb
223
239
  - app/components/ariadne/ui/popover/component.html.erb
224
240
  - app/components/ariadne/ui/popover/component.rb
225
241
  - app/components/ariadne/ui/popover/component.ts
226
242
  - app/components/ariadne/ui/skeleton/component.html.erb
227
243
  - app/components/ariadne/ui/skeleton/component.rb
244
+ - app/components/ariadne/ui/stats_panel/component.html.erb
245
+ - app/components/ariadne/ui/stats_panel/component.rb
246
+ - app/components/ariadne/ui/stats_panel/item/component.html.erb
247
+ - app/components/ariadne/ui/stats_panel/item/component.rb
228
248
  - app/components/ariadne/ui/table/cell/component.html.erb
229
249
  - app/components/ariadne/ui/table/cell/component.rb
230
250
  - app/components/ariadne/ui/table/component.html.erb
@@ -235,6 +255,12 @@ files:
235
255
  - app/components/ariadne/ui/table/header/component.rb
236
256
  - app/components/ariadne/ui/table/row/component.html.erb
237
257
  - app/components/ariadne/ui/table/row/component.rb
258
+ - app/components/ariadne/ui/time_ago/component.html.erb
259
+ - app/components/ariadne/ui/time_ago/component.rb
260
+ - app/components/ariadne/ui/time_ago/en.yml
261
+ - app/components/ariadne/ui/toggle/component.html.erb
262
+ - app/components/ariadne/ui/toggle/component.rb
263
+ - app/components/ariadne/ui/toggle/component.ts
238
264
  - app/components/ariadne/ui/typography/component.html.erb
239
265
  - app/components/ariadne/ui/typography/component.rb
240
266
  - app/frontend/ariadne/index.ts