turbo_material 0.1.1

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 (52) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +247 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/turbo_material_manifest.js +3 -0
  6. data/app/assets/dist/turbo_material/tailwind.css +1 -0
  7. data/app/assets/javascripts/turbo_material/material_checkbox_controller.js +12 -0
  8. data/app/assets/javascripts/turbo_material/material_chips_input_controller.js +140 -0
  9. data/app/assets/javascripts/turbo_material/material_chips_select_controller.js +111 -0
  10. data/app/assets/javascripts/turbo_material/material_dialog_controller.js +27 -0
  11. data/app/assets/javascripts/turbo_material/material_input_controller.js +10 -0
  12. data/app/assets/javascripts/turbo_material/material_list_controller.js +57 -0
  13. data/app/assets/javascripts/turbo_material/material_menu_surface_controller.js +11 -0
  14. data/app/assets/javascripts/turbo_material/material_radio_controller.js +10 -0
  15. data/app/assets/javascripts/turbo_material/material_ripple_controller.js +10 -0
  16. data/app/assets/javascripts/turbo_material/material_select_controller.js +10 -0
  17. data/app/assets/javascripts/turbo_material/material_switch_controller.js +14 -0
  18. data/app/assets/stylesheets/turbo_material/application.css +15 -0
  19. data/app/assets/stylesheets/turbo_material/application.tailwind.css +3 -0
  20. data/app/controllers/turbo_material/application_controller.rb +4 -0
  21. data/app/helpers/turbo_material/application_helper.rb +7 -0
  22. data/app/helpers/turbo_material/checkbox_helper.rb +7 -0
  23. data/app/helpers/turbo_material/chips_input_helper.rb +7 -0
  24. data/app/helpers/turbo_material/chips_select_helper.rb +7 -0
  25. data/app/helpers/turbo_material/input_helper.rb +7 -0
  26. data/app/helpers/turbo_material/modal_helper.rb +7 -0
  27. data/app/helpers/turbo_material/radio_helper.rb +7 -0
  28. data/app/helpers/turbo_material/select_helper.rb +7 -0
  29. data/app/helpers/turbo_material/switch_helper.rb +7 -0
  30. data/app/helpers/turbo_material/textarea_helper.rb +7 -0
  31. data/app/jobs/turbo_material/application_job.rb +4 -0
  32. data/app/mailers/turbo_material/application_mailer.rb +6 -0
  33. data/app/models/turbo_material/application_record.rb +5 -0
  34. data/app/views/components/_checkbox.html.erb +25 -0
  35. data/app/views/components/_chips_input.html.erb +36 -0
  36. data/app/views/components/_chips_input_options.html.erb +20 -0
  37. data/app/views/components/_chips_select.html.erb +56 -0
  38. data/app/views/components/_input.html.erb +32 -0
  39. data/app/views/components/_modal.html.erb +37 -0
  40. data/app/views/components/_radio.html.erb +28 -0
  41. data/app/views/components/_select.html.erb +67 -0
  42. data/app/views/components/_switch.html.erb +34 -0
  43. data/app/views/components/_textarea.html.erb +30 -0
  44. data/app/views/layouts/turbo_material/application.html.erb +21 -0
  45. data/config/importmap.rb +4 -0
  46. data/config/routes.rb +2 -0
  47. data/config/tailwind.config.js +26 -0
  48. data/lib/tasks/turbo_material_tasks.rake +4 -0
  49. data/lib/turbo_material/engine.rb +44 -0
  50. data/lib/turbo_material/version.rb +3 -0
  51. data/lib/turbo_material.rb +6 -0
  52. metadata +164 -0
@@ -0,0 +1,27 @@
1
+ import { Controller } from "@hotwired/stimulus";
2
+
3
+ export default class extends Controller {
4
+ dialog = undefined;
5
+
6
+ static values = {
7
+ opened: Boolean
8
+ }
9
+
10
+ connect() {
11
+ this.dialog = mdc.dialog.MDCDialog.attachTo(this.element);
12
+ if (this.openedValue) {
13
+ this.dialog.open();
14
+ }
15
+ }
16
+
17
+ close() {
18
+ this.dialog.close();
19
+ }
20
+
21
+ open() {
22
+ this.dialog.open();
23
+ }
24
+
25
+ disconnect() {
26
+ }
27
+ }
@@ -0,0 +1,10 @@
1
+ import { Controller } from "@hotwired/stimulus";
2
+
3
+ export default class extends Controller {
4
+ connect() {
5
+ mdc.textField.MDCTextField.attachTo(this.element);
6
+ }
7
+
8
+ disconnect() {
9
+ }
10
+ }
@@ -0,0 +1,57 @@
1
+ import { Controller } from "@hotwired/stimulus";
2
+
3
+ export default class extends Controller {
4
+ connect() {
5
+ this.list = mdc.list.MDCList.attachTo(this.element);
6
+ this.list.listen('MDCList:action', (event) => {
7
+ this.focusElement(event.detail.index);
8
+ this.element.dispatchEvent(new CustomEvent('country-select-focus', {
9
+ bubbles: true,
10
+ cancelable: true,
11
+ detail: {
12
+ index: event.detail.index
13
+ }
14
+ }));
15
+ });
16
+ }
17
+
18
+ selected() {
19
+ return this.list.listElements[this.list.selectedIndex];
20
+ }
21
+
22
+ focusNext() {
23
+ if (this.list.selectedIndex === undefined ) {
24
+ this.list.selectedIndex = 0;
25
+ } else if (this.list.selectedIndex < this.list.listElements.length - 1) {
26
+ this.list.selectedIndex++;
27
+ } else {
28
+ this.list.selectedIndex = 0;
29
+ }
30
+ this.element.querySelector(".mdc-deprecated-list-item--selected").scrollIntoView({
31
+ behavior: 'smooth'
32
+ });
33
+ }
34
+
35
+ focusPrevious() {
36
+ if (this.list.selectedIndex === undefined ) {
37
+ this.list.selectedIndex = this.list.listElements.length - 1;
38
+ } else if (this.list.selectedIndex > 0) {
39
+ this.list.selectedIndex--;
40
+ } else {
41
+ this.list.selectedIndex = this.list.listElements.length - 1;
42
+ }
43
+ this.element.querySelector(".mdc-deprecated-list-item--selected").scrollIntoView({
44
+ behavior: 'smooth'
45
+ });
46
+ }
47
+
48
+ focusElement(index) {
49
+ this.list.selectedIndex = index;
50
+ this.element.querySelector(".mdc-deprecated-list-item--selected").scrollIntoView({
51
+ behavior: 'smooth'
52
+ });
53
+ }
54
+
55
+ disconnect() {
56
+ }
57
+ }
@@ -0,0 +1,11 @@
1
+ import { Controller } from "@hotwired/stimulus";
2
+
3
+ export default class extends Controller {
4
+
5
+ connect() {
6
+ this.menuSurface = new mdc.menuSurface.MDCMenuSurface.attachTo(this.element);
7
+ }
8
+
9
+ disconnect() {
10
+ }
11
+ }
@@ -0,0 +1,10 @@
1
+ import { Controller } from "@hotwired/stimulus";
2
+
3
+ export default class extends Controller {
4
+ connect() {
5
+ const select = mdc.radio.MDCRadio.attachTo(this.element);
6
+ }
7
+
8
+ disconnect() {
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ import { Controller } from "@hotwired/stimulus";
2
+
3
+ export default class extends Controller {
4
+ connect() {
5
+ mdc.ripple.MDCRipple.attachTo(this.element);
6
+ }
7
+
8
+ disconnect() {
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ import { Controller } from "@hotwired/stimulus";
2
+
3
+ export default class extends Controller {
4
+ connect() {
5
+ const select = mdc.select.MDCSelect.attachTo(this.element)
6
+ }
7
+
8
+ disconnect() {
9
+ }
10
+ }
@@ -0,0 +1,14 @@
1
+ import { Controller } from "@hotwired/stimulus";
2
+
3
+ export default class extends Controller {
4
+ connect() {
5
+ const switchControl = mdc.switchControl.MDCSwitch.attachTo(this.element.querySelector('.mdc-switch'));
6
+ const hidden = this.element.querySelector('input[type=hidden]');
7
+ switchControl.listen('click', () => {
8
+ hidden.value = switchControl.selected;
9
+ });
10
+ }
11
+
12
+ disconnect() {
13
+ }
14
+ }
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,3 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
@@ -0,0 +1,4 @@
1
+ module TurboMaterial
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ module TurboMaterial
2
+ module ApplicationHelper
3
+ def cast_boolean(param)
4
+ ActiveRecord::Type::Boolean.new.cast(param)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module TurboMaterial
2
+ module CheckboxHelper
3
+ def material_checkbox(kwargs = {})
4
+ render "components/checkbox", **kwargs
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module TurboMaterial
2
+ module ChipsInputHelper
3
+ def material_chips_input(kwargs = {})
4
+ render "components/chips_input", **kwargs
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module TurboMaterial
2
+ module ChipsSelectHelper
3
+ def material_chips_select(kwargs = {})
4
+ render "components/chips_select", **kwargs
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module TurboMaterial
2
+ module InputHelper
3
+ def material_input(kwargs = {})
4
+ render "components/input", **kwargs
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module TurboMaterial
2
+ module ModalHelper
3
+ def material_modal(kwargs = {})
4
+ render "components/modal", **kwargs
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module TurboMaterial
2
+ module RadioHelper
3
+ def material_radio(kwargs = {})
4
+ render "components/radio", **kwargs
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module TurboMaterial
2
+ module SelectHelper
3
+ def material_select(kwargs = {})
4
+ render "components/select", **kwargs
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module TurboMaterial
2
+ module SwitchHelper
3
+ def material_switch(kwargs = {})
4
+ render "components/switch", **kwargs
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module TurboMaterial
2
+ module TextareaHelper
3
+ def material_textarea(kwargs = {})
4
+ render "components/textarea", **kwargs
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ module TurboMaterial
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module TurboMaterial
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: "from@example.com"
4
+ layout "mailer"
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module TurboMaterial
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,25 @@
1
+ <%# locals: (form:, disabled: false, name:, label: nil, id:, checked: false, checked_value: '1', unchecked_value: '0', frame: nil, source_override: nil) %>
2
+ <div class="mdc-form-field" data-controller="material-checkbox">
3
+ <div class="mdc-checkbox <%= disabled ? 'mdc-checkbox--disabled' : '' %>">
4
+ <%= form.check_box name.to_sym, {
5
+ id: id, class: "mdc-checkbox__native-control",
6
+ disabled: disabled,
7
+ checked: checked || form&.object&.[](source_override || name.to_sym),
8
+ data: { frame: frame }.compact
9
+ }, checked_value, unchecked_value %>
10
+ <div class="mdc-checkbox__background">
11
+ <svg class="mdc-checkbox__checkmark"
12
+ viewBox="0 0 24 24">
13
+ <path class="mdc-checkbox__checkmark-path"
14
+ fill="none"
15
+ d="M1.73,12.91 8.1,19.28 22.79,4.59"/>
16
+ </svg>
17
+ <div class="mdc-checkbox__mixedmark"></div>
18
+ </div>
19
+ <div class="mdc-checkbox__ripple"></div>
20
+ <div class="mdc-checkbox__focus-ring"></div>
21
+ </div>
22
+ <label for="<%= id %>">
23
+ <%= label || name.capitalize %>
24
+ </label>
25
+ </div>
@@ -0,0 +1,36 @@
1
+ <%# locals: (form:, disabled: false, required: false, name:, label: nil, id:, frame: nil, suffix: nil, type: 'text', url: nil, selected: [], options: [], value: nil) %>
2
+ <%- id = [name, suffix].compact_blank.join('-') -%>
3
+ <div data-controller="material-chips-input"
4
+ data-material-chips-input-url-value="<%= url %>"
5
+ data-material-chips-input-name-value="<%= name %>"
6
+ data-material-chips-input-material-list-outlet="#<%= "#{id}-list" %>"
7
+ <% if suffix.present? %>data-material-chips-input-suffix-value="<%= suffix %>"<% end %>
8
+ data-action="keydown.esc->material-chips-input#close keydown.enter->prevent-default country-select-focus->material-chips-input#confirmSelection"
9
+ >
10
+ <label class="mdc-text-field mdc-text-field--filled w-full !h-max !h-full">
11
+ <span class="mdc-text-field__ripple"></span>
12
+ <span class="mdc-floating-label !top-6"><%= label %></span>
13
+ <div class="mdc-chip-set mdc-chip-set--input !pt-8 w-full" role="grid">
14
+ <%- selected.each do |chip| -%>
15
+ <div class="mdc-chip">
16
+ <div class="mdc-chip__text"><%= chip[:label] %></div>
17
+ <!-- <i class="material-icons mdc-chip__icon mdc-chip__icon--trailing" tabindex="0" role="button">cancel</i>-->
18
+ </div>
19
+ <%- end -%>
20
+ <%= form.hidden_field name.to_sym, value: value, data: { 'material-chips-input-target': 'hidden' } %>
21
+ <%= form.text_field "#{name}_".to_sym,
22
+ class: 'mdc-text-field__input', value: value || form&.object&.[](name.to_sym),
23
+ id: id, 'aria-labelledby' => id + '-label',
24
+ required: required,
25
+ disabled: disabled,
26
+ type: type, autocomplete: "off",
27
+ data: { 'material-chips-input-target': 'input',
28
+ action: 'input->material-chips-input#search mousedown->material-chips-input#toggle keydown.down->material-chips-input#focusNext keydown.up->material-chips-input#focusPrevious keydown.enter->material-chips-input#confirmSelection keydown->material-chips-input#open' }
29
+ %>
30
+ </div>
31
+ <span class="mdc-line-ripple"></span>
32
+ </label>
33
+ <div class="mdc-menu-surface--anchor">
34
+ <%= render partial: 'components/chips_input_options', locals: { options: options, suffix: suffix, name: name, label: label } %>
35
+ </div>
36
+ </div>
@@ -0,0 +1,20 @@
1
+ <%# locals: (suffix:, options: [], label:, name:, opened: 'false') %>
2
+ <%- id = [name, suffix].compact_blank.join('-') -%>
3
+ <div id="<%= "#{id}-panel" %>"
4
+ class="mdc-menu-surface <%= (opened != 'true' || options.size.zero?) ? '' : 'mdc-menu-surface--open' %> !z-100 mdc-menu-surface--fullwidth"
5
+ data-controller="material-menu-surface"
6
+ data-material-chips-input-target="panel" data-size="<%= options.size %>">
7
+ <ul class="mdc-deprecated-list max-h-64 overflow-y-auto"
8
+ id="<%= "#{id}-list" %>"
9
+ role="listbox"
10
+ aria-label="<%= label %>"
11
+ data-controller="material-list"
12
+ >
13
+ <%- options.each_with_index do |option, idx| -%>
14
+ <li class="mdc-deprecated-list-item" data-value="<%= option[:id] %>" data-name="<%= option[:label] %>" <% if idx.zero? %> tabindex="0"<% end %>>
15
+ <span class="mdc-deprecated-list-item__ripple"></span>
16
+ <span class="mdc-deprecated-list-item__text"><%= option[:label] %></span>
17
+ </li>
18
+ <%- end -%>
19
+ </ul>
20
+ </div>
@@ -0,0 +1,56 @@
1
+ <%# locals: (form:, disabled: false, required: false, name:, label: nil, id:, value: nil, url: nil, frame: nil, source_override: nil, options: [], confirmable: false, query_string: nil, modal_name: nil, modal_url: nil, chip_css: nil, fixed: false) %>
2
+ <div class="mdc-select mdc-select--filled w-full"
3
+ data-controller="material-chips-select"
4
+ data-material-chips-select-selected-value="<%= value %>"
5
+ data-material-chips-select-url-value="<%= url %>"
6
+ data-material-chips-select-confirmable-value="<%= confirmable %>"
7
+ data-material-chips-select-query-string-value="<%= query_string %>"
8
+ data-material-chips-select-modal-name-value="<%= modal_name %>"
9
+ data-material-chips-select-modal-url-value="<%= modal_url %>"
10
+ data-material-chips-select-chip-css-value="<%= chip_css %>"
11
+ >
12
+ <div class="mdc-select__anchor"
13
+ role="button"
14
+ aria-haspopup="listbox"
15
+ aria-expanded="false"
16
+ aria-expanded="false"
17
+ aria-labelledby="<%= id %>-label <%= id %>-selected-text"
18
+ <% if disabled %>aria-disabled="true"<% end %>
19
+ <% if required %>aria-required="true"<% end %>
20
+ >
21
+ <span class="mdc-select__ripple"></span>
22
+ <span id="<%= id %>-label" class="mdc-floating-label pb-1"><%= label || name.capitalize %></span>
23
+ <div class="mdc-chip-set mdc-chip-set--input"></div>
24
+ <span class="mdc-select__selected-text-container"><span id="<%= id %>-selected-text" class="mdc-select__selected-text !hidden"></span></span>
25
+ <span class="mdc-select__dropdown-icon">
26
+ <svg
27
+ class="mdc-select__dropdown-icon-graphic"
28
+ viewBox="7 10 10 5" focusable="false">
29
+ <polygon
30
+ class="mdc-select__dropdown-icon-inactive"
31
+ stroke="none"
32
+ fill-rule="evenodd"
33
+ points="7 10 12 15 17 10">
34
+ </polygon>
35
+ <polygon
36
+ class="mdc-select__dropdown-icon-active"
37
+ stroke="none"
38
+ fill-rule="evenodd"
39
+ points="7 15 12 10 17 15">
40
+ </polygon>
41
+ </svg>
42
+ </span>
43
+ <span class="mdc-line-ripple"></span>
44
+ </div>
45
+ <%= form.hidden_field name.to_sym, value: value, data: { 'material-chips-select-target': 'hidden' } if form %>
46
+ <div class="mdc-select__menu mdc-menu mdc-menu-surface <%= fixed ? 'mdc-menu-surface--fixed' : 'mdc-menu-surface--fullwidth' %>">
47
+ <ul class="mdc-deprecated-list" role="listbox" aria-label="<%= label %> listbox">
48
+ <% options.each do |option| %>
49
+ <li class="mdc-deprecated-list-item" aria-selected="false" data-value="<%= option[:value] %>" data-label="<%= option[:label] %>" <% if option[:confirmed].in? [true, false] %>data-confirmed="<%= option[:confirmed] %>"<% end %> role="option">
50
+ <span class="mdc-deprecated-list-item__ripple"></span>
51
+ <span class="mdc-deprecated-list-item__text"><%= option[:label] %></span>
52
+ </li>
53
+ <% end %>
54
+ </ul>
55
+ </div>
56
+ </div>
@@ -0,0 +1,32 @@
1
+ <%# locals: (form:, custom_controller: nil, custom_css: nil, disabled: false, required: false, name:, label: nil, id:, checked: false, frame: nil, provide_hidden: false, value: nil, type: 'text', data: {}, min: nil, max: nil, helper: nil, parent: nil) %>
2
+ <label class="mdc-text-field mdc-text-field--filled w-full <%= custom_css %>"
3
+ data-controller="<%= custom_controller || 'material-input' %>" <% if frame %>data-frame="<%= frame %>"<% end %>>
4
+ <span class="mdc-text-field__ripple"></span>
5
+ <span class="mdc-floating-label" id="<%= id %>-label">
6
+ <%= label || name.capitalize %>
7
+ </span>
8
+ <%= form.text_field provide_hidden ? "#{name}_".to_sym : name.to_sym,
9
+ class: 'mdc-text-field__input', value: value || form&.object&.[](name.to_sym),
10
+ id: id, 'aria-labelledby' => id + '-label',
11
+ required: required, disabled: disabled,
12
+ type: type, autocomplete: "off", data: { frame: frame, **(data) }.compact,
13
+ min: min, max: max
14
+ %>
15
+ <span class="mdc-line-ripple"></span>
16
+ <%- if provide_hidden -%>
17
+ <%= form.hidden_field name.to_sym, value: value, data: { frame: frame }.compact %>
18
+ <%- end -%>
19
+ </label>
20
+ <div class="mdc-text-field-helper-line">
21
+ <%- if helper -%>
22
+ <div class="mdc-text-field-helper-text" aria-hidden="true"><%= helper %></div>
23
+ <%- end -%>
24
+ <div class="mdc-text-field-helper-text--validation-msg text-sm text-red-500 hidden jserror">
25
+ </div>
26
+ <%- parent&.errors&.[](name.to_sym)&.each do |msg| -%>
27
+ <div class="mdc-text-field-helper-text--validation-msg text-sm text-red-500"
28
+ aria-hidden="true">
29
+ <%= msg %>
30
+ </div>
31
+ <%- end -%>
32
+ </div>
@@ -0,0 +1,37 @@
1
+ <%# locals: (title:) %>
2
+ <turbo-frame id="modal">
3
+ <div class="mdc-dialog" data-controller="material-dialog" data-material-dialog-opened-value="true">
4
+ <div class="mdc-dialog__container">
5
+ <div class="mdc-dialog__surface !min-w-[36rem] !min-h-[14rem]"
6
+ role="alertdialog"
7
+ aria-modal="true"
8
+ aria-labelledby="my-dialog-title"
9
+ aria-describedby="my-dialog-content">
10
+ <h2 class="mdc-dialog__title">
11
+ <div class="flex items-center justify-between">
12
+ <span><%= title %></span>
13
+ <button type="button" class="mdc-icon-button mdc-dialog__close" data-mdc-ripple-is-unbounded data-action="click->material-dialog#close">
14
+ <div class="mdc-icon-button__ripple"></div>
15
+ <span class="mdc-icon-button__focus-ring"></span>
16
+ <i class="material-icons !text-white">close</i>
17
+ </button>
18
+ </div>
19
+ </h2>
20
+ <div class="mdc-dialog__content">
21
+ Contents
22
+ </div>
23
+ <div class="mdc-dialog__actions">
24
+ <button type="button" class="mdc-button mdc-dialog__button mdc-dialog__close" data-action="click->material-dialog#close">
25
+ <div class="mdc-button__ripple"></div>
26
+ <span class="mdc-button__label">Cancel</span>
27
+ </button>
28
+ <button type="button" class="mdc-button mdc-dialog__button" data-controller="material-ripple">
29
+ <div class="mdc-button__ripple"></div>
30
+ <span class="mdc-button__label">OK</span>
31
+ </button>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ <div class="mdc-dialog__scrim"></div>
36
+ </div>
37
+ </turbo-frame>
@@ -0,0 +1,28 @@
1
+ <%# locals: (form:, disabled: false, required: false, name:, label: nil, id:, checked: false, value: nil, parent: nil) %>
2
+ <div class="mdc-form-field flex flex-col">
3
+ <label>
4
+ <%= label || name.capitalize %>
5
+ </label>
6
+ <div class="flex flex-row items-center w-full">
7
+ <div class="mdc-radio <%= disabled ? 'mdc-radio--disabled' : '' %>" data-controller="material-radio">
8
+ <%= form.radio_button name.to_sym, 'true', class: 'mdc-radio__native-control', id: id + '-1', checked: value, disabled: disabled %>
9
+ <div class="mdc-radio__background">
10
+ <div class="mdc-radio__outer-circle"></div>
11
+ <div class="mdc-radio__inner-circle"></div>
12
+ </div>
13
+ <div class="mdc-radio__ripple"></div>
14
+ <div class="mdc-radio__focus-ring"></div>
15
+ </div>
16
+ <label for="<%= id %>-1">Yes</label>
17
+ <div class="mdc-radio <%= disabled ? 'mdc-radio--disabled' : '' %>">
18
+ <%= form.radio_button name.to_sym, 'false', class: 'mdc-radio__native-control', id: id + '-2', checked: !value, disabled: disabled %>
19
+ <div class="mdc-radio__background">
20
+ <div class="mdc-radio__outer-circle"></div>
21
+ <div class="mdc-radio__inner-circle"></div>
22
+ </div>
23
+ <div class="mdc-radio__ripple"></div>
24
+ <div class="mdc-radio__focus-ring"></div>
25
+ </div>
26
+ <label for="<%= id %>-2">No</label>
27
+ </div>
28
+ </div>
@@ -0,0 +1,67 @@
1
+ <%# locals: (form:, disabled: false, required: false, name:, label: nil, id:, checked: false, value: nil, parent: nil, frame: nil, selected_text: nil, fixed: false, options: [], hint: nil, helper: nil) %>
2
+ <div class="mdc-select mdc-select--filled w-full<%= disabled ? ' mdc-select--disabled' : '' %><%= required ? ' mdc-select--required' : '' %>"
3
+ data-controller="material-select" <% if frame %> data-frame="<%= frame %>"<% end %> id="<%= id %>">
4
+ <%= form.hidden_field name.to_sym, value: value %>
5
+ <div class="mdc-select__anchor"
6
+ role="button"
7
+ aria-haspopup="listbox"
8
+ aria-expanded="false"
9
+ aria-labelledby="<%= id %>-label <%= id %>-selected-text"
10
+ <% if disabled %>aria-disabled="true"<% end %>
11
+ <% if required %>aria-required="true"<% end %>
12
+ >
13
+ <span class="mdc-select__ripple"></span>
14
+ <span id="<%= id %>-label" class="mdc-floating-label"><%= label || name.capitalize %></span>
15
+ <span class="mdc-select__selected-text-container">
16
+ <span id="<%= id %>-selected-text" class="mdc-select__selected-text">
17
+ <%= selected_text || value %>
18
+ </span>
19
+ </span>
20
+ <span class="mdc-select__dropdown-icon">
21
+ <svg
22
+ class="mdc-select__dropdown-icon-graphic"
23
+ viewBox="7 10 10 5" focusable="false">
24
+ <polygon
25
+ class="mdc-select__dropdown-icon-inactive"
26
+ stroke="none"
27
+ fill-rule="evenodd"
28
+ points="7 10 12 15 17 10">
29
+ </polygon>
30
+ <polygon
31
+ class="mdc-select__dropdown-icon-active"
32
+ stroke="none"
33
+ fill-rule="evenodd"
34
+ points="7 15 12 10 17 15">
35
+ </polygon>
36
+ </svg>
37
+ </span>
38
+ <span class="mdc-line-ripple"></span>
39
+ </div>
40
+
41
+ <div class="mdc-select__menu mdc-menu mdc-menu-surface !z-100 <%= fixed ? 'mdc-menu-surface--fixed' : 'mdc-menu-surface--fullwidth' %>" id="<%= id %>-surface">
42
+ <ul class="mdc-deprecated-list" role="listbox" aria-label="<%= label %> listbox">
43
+ <% options.each do |option| %>
44
+ <li class="mdc-deprecated-list-item<%= value == option[:value] ? ' mdc-deprecated-list-item--selected' : '' %>" aria-selected="<%= (value == option[:value]).to_s %>" data-value="<%= option[:value] %>" role="option">
45
+ <span class="mdc-deprecated-list-item__ripple"></span>
46
+ <span class="mdc-deprecated-list-item__text"><%= option[:label] %></span>
47
+ </li>
48
+ <% end %>
49
+ </ul>
50
+ </div>
51
+ </div>
52
+ <%- if hint.present? -%>
53
+ <div class="font-sans text-xs p-2"><%= hint %></div>
54
+ <%- end -%>
55
+ <%- if helper.present? || parent&.errors.present? -%>
56
+ <div class="mdc-text-field-helper-line">
57
+ <%- if helper -%>
58
+ <div class="mdc-text-field-helper-text" aria-hidden="true"><%= helper %></div>
59
+ <%- end -%>
60
+ <%- parent&.errors&.[](name.to_sym)&.each do |msg| -%>
61
+ <div class="mdc-text-field-helper-text--validation-msg text-sm text-red-500"
62
+ aria-hidden="true">
63
+ <%= msg %>
64
+ </div>
65
+ <%- end -%>
66
+ </div>
67
+ <%- end -%>
@@ -0,0 +1,34 @@
1
+ <%# locals: (form:, disabled: false, name:, label: nil, id:, value: nil, true_label: nil, false_label: nil, frame: nil) %>
2
+ <div data-controller="material-switch" <% if frame %> data-frame="<%= frame %>"<% end %>>
3
+ <button id="selected-switch" class="mdc-switch <%= cast_boolean(value) ? 'mdc-switch--selected' : '' %>"
4
+ type="button" role="switch" aria-checked="<%= cast_boolean(value) ? 'true' : 'false' %>" <% if disabled %>disabled<% end %>>
5
+ <div class="mdc-switch__track"></div>
6
+ <div class="mdc-switch__handle-track">
7
+ <div class="mdc-switch__handle">
8
+ <div class="mdc-switch__shadow">
9
+ <div class="mdc-elevation-overlay"></div>
10
+ </div>
11
+ <div class="mdc-switch__ripple"></div>
12
+ <div class="mdc-switch__icons">
13
+ <svg class="mdc-switch__icon mdc-switch__icon--on" viewBox="0 0 24 24">
14
+ <path d="M19.69,5.23L8.96,15.96l-4.23-4.23L2.96,13.5l6,6L21.46,7L19.69,5.23z"/>
15
+ </svg>
16
+ <svg class="mdc-switch__icon mdc-switch__icon--off" viewBox="0 0 24 24">
17
+ <path d="M20 13H4v-2h16v2z"/>
18
+ </svg>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ <span class="mdc-switch__focus-ring-wrapper">
23
+ <div class="mdc-switch__focus-ring"></div>
24
+ </span>
25
+ </button>
26
+ <label for="selected-switch">
27
+ <% if cast_boolean(value) %>
28
+ <%= true_label || label %>
29
+ <% else %>
30
+ <%= false_label || label %>
31
+ <% end %>
32
+ </label>
33
+ <%= form.hidden_field name.to_sym, value: value %>
34
+ </div>