ariadne_view_components 0.0.47-x86_64-darwin → 0.0.49-x86_64-darwin

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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -25
  3. data/app/assets/javascripts/ariadne_view_components.js +2 -2
  4. data/app/assets/javascripts/ariadne_view_components.js.map +1 -1
  5. data/app/assets/javascripts/components/ariadne/accumulator_controller/accumulator_controller.d.ts +22 -0
  6. data/app/assets/javascripts/components/ariadne/dropdown/menu_component.d.ts +1 -0
  7. data/app/assets/javascripts/components/ariadne/events_controller/events_controller.d.ts +4 -0
  8. data/app/assets/javascripts/components/ariadne/options_controller/options_controller.d.ts +40 -0
  9. data/app/assets/javascripts/components/ariadne/outlet_manager_controller/outlet_manager_controller.d.ts +42 -0
  10. data/app/assets/javascripts/components/ariadne/string_match_controller/string_match_controller.d.ts +27 -0
  11. data/app/assets/javascripts/components/ariadne/synced_boolean_attributes_controller/synced_boolean_attributes_controller.d.ts +44 -0
  12. data/app/assets/javascripts/components/ariadne/toggleable_controller/toggleable_controller.d.ts +34 -0
  13. data/app/assets/stylesheets/ariadne_view_components.css +3 -3
  14. data/app/components/ariadne/accumulator_controller/accumulator_controller.d.ts +22 -0
  15. data/app/components/ariadne/accumulator_controller/accumulator_controller.js +39 -0
  16. data/app/components/ariadne/accumulator_controller/accumulator_controller.ts +48 -0
  17. data/app/components/ariadne/action_card_component.html.erb +11 -0
  18. data/app/components/ariadne/action_card_component.rb +45 -0
  19. data/app/components/ariadne/ariadne.js +10 -0
  20. data/app/components/ariadne/ariadne.ts +10 -0
  21. data/app/components/ariadne/bottom_tab_component.html.erb +4 -0
  22. data/app/components/ariadne/bottom_tab_component.rb +44 -0
  23. data/app/components/ariadne/bottom_tab_nav_component.html.erb +5 -0
  24. data/app/components/ariadne/bottom_tab_nav_component.rb +33 -0
  25. data/app/components/ariadne/breadcrumbs_component.html.erb +13 -0
  26. data/app/components/ariadne/breadcrumbs_component.rb +31 -0
  27. data/app/components/ariadne/checkbox_component.html.erb +5 -0
  28. data/app/components/ariadne/checkbox_component.rb +43 -0
  29. data/app/components/ariadne/close_button_component.html.erb +4 -0
  30. data/app/components/ariadne/close_button_component.rb +33 -0
  31. data/app/components/ariadne/combobox_component.html.erb +14 -0
  32. data/app/components/ariadne/combobox_component.rb +76 -0
  33. data/app/components/ariadne/dropdown/menu_component.d.ts +1 -0
  34. data/app/components/ariadne/dropdown/menu_component.js +1 -0
  35. data/app/components/ariadne/events_controller/events_controller.d.ts +4 -0
  36. data/app/components/ariadne/events_controller/events_controller.js +6 -0
  37. data/app/components/ariadne/events_controller/events_controller.ts +7 -0
  38. data/app/components/ariadne/layout_component.html.erb +21 -0
  39. data/app/components/ariadne/layout_component.rb +69 -0
  40. data/app/components/ariadne/modal_component.html.erb +11 -0
  41. data/app/components/ariadne/modal_component.rb +88 -0
  42. data/app/components/ariadne/options_controller/options_controller.d.ts +40 -0
  43. data/app/components/ariadne/options_controller/options_controller.js +98 -0
  44. data/app/components/ariadne/options_controller/options_controller.ts +132 -0
  45. data/app/components/ariadne/outlet_manager_controller/outlet_manager_controller.d.ts +42 -0
  46. data/app/components/ariadne/outlet_manager_controller/outlet_manager_controller.js +237 -0
  47. data/app/components/ariadne/outlet_manager_controller/outlet_manager_controller.ts +278 -0
  48. data/app/components/ariadne/popover_component.html.erb +10 -0
  49. data/app/components/ariadne/popover_component.rb +81 -0
  50. data/app/components/ariadne/progress_bar_component.html.erb +5 -0
  51. data/app/components/ariadne/progress_bar_component.rb +63 -0
  52. data/app/components/ariadne/relative_time_component.html.erb +3 -0
  53. data/app/components/ariadne/relative_time_component.rb +61 -0
  54. data/app/components/ariadne/show_more_button_component.html.erb +11 -0
  55. data/app/components/ariadne/show_more_button_component.rb +47 -0
  56. data/app/components/ariadne/spinner_component.html.erb +16 -0
  57. data/app/components/ariadne/spinner_component.rb +45 -0
  58. data/app/components/ariadne/string_match_controller/string_match_controller.d.ts +27 -0
  59. data/app/components/ariadne/string_match_controller/string_match_controller.js +51 -0
  60. data/app/components/ariadne/string_match_controller/string_match_controller.ts +64 -0
  61. data/app/components/ariadne/subheader_component.html.erb +11 -0
  62. data/app/components/ariadne/subheader_component.rb +65 -0
  63. data/app/components/ariadne/synced_boolean_attributes_controller/synced_boolean_attributes_controller.d.ts +44 -0
  64. data/app/components/ariadne/synced_boolean_attributes_controller/synced_boolean_attributes_controller.js +153 -0
  65. data/app/components/ariadne/synced_boolean_attributes_controller/synced_boolean_attributes_controller.ts +192 -0
  66. data/app/components/ariadne/toggle_component/toggle_component.html.erb +15 -0
  67. data/app/components/ariadne/toggle_component.rb +95 -0
  68. data/app/components/ariadne/toggleable_controller/toggleable_controller.d.ts +34 -0
  69. data/app/components/ariadne/toggleable_controller/toggleable_controller.js +54 -0
  70. data/app/components/ariadne/toggleable_controller/toggleable_controller.ts +77 -0
  71. data/lib/ariadne/view_components/version.rb +1 -1
  72. data/static/arguments.yml +50 -0
  73. data/static/audited_at.json +17 -0
  74. data/static/classes.yml +209 -173
  75. data/static/constants.json +356 -0
  76. data/static/statuses.json +17 -0
  77. data/tailwind.config.js +7 -7
  78. metadata +75 -12
  79. /data/app/assets/javascripts/{ariadne-form.d.ts → components/ariadne/ariadne-form.d.ts} +0 -0
  80. /data/app/assets/javascripts/{ariadne.d.ts → components/ariadne/ariadne.d.ts} +0 -0
  81. /data/app/assets/javascripts/{clipboard_copy_component → components/ariadne/clipboard_copy_component}/clipboard-copy-component.d.ts +0 -0
  82. /data/app/assets/javascripts/{rich_text_area_component → components/ariadne/rich_text_area_component}/rich-text-area-component.d.ts +0 -0
  83. /data/app/assets/javascripts/{slideover_component → components/ariadne/slideover_component}/slideover-component.d.ts +0 -0
  84. /data/app/assets/javascripts/{tab_container_component → components/ariadne/tab_container_component}/tab-container-component.d.ts +0 -0
  85. /data/app/assets/javascripts/{tab_nav_component → components/ariadne/tab_nav_component}/tab-nav-component.d.ts +0 -0
  86. /data/app/assets/javascripts/{time_ago_component → components/ariadne/time_ago_component}/time-ago-component.d.ts +0 -0
  87. /data/app/assets/javascripts/{tooltip_component → components/ariadne/tooltip_component}/tooltip-component.d.ts +0 -0
@@ -0,0 +1,192 @@
1
+ import OutletManagerController from '../outlet_manager_controller/outlet_manager_controller'
2
+
3
+ export type TStimulusDispatchEvent<TDetails> = {
4
+ target?: Element | undefined
5
+ detail?: TDetails | undefined
6
+ prefix?: string | undefined
7
+ bubbles?: boolean | undefined
8
+ cancelable?: boolean | undefined
9
+ preventDefault: () => void
10
+ }
11
+
12
+ export type TBooleanValueDetail = {
13
+ value: boolean
14
+ }
15
+
16
+ export interface TSyncAttrDetail extends TBooleanValueDetail {
17
+ attr: string
18
+ }
19
+
20
+ /*
21
+ This class isn't used directly by itself because it has no functionality. What it does is establishes
22
+ "synced attrs" and "anti-attrs" so that other controllers can extend this one and not worry about
23
+ implementing the logic themselves (and thus have duplicate logic all over our controllers)
24
+
25
+ To implement this, extend your controller with "SyncedBooleanAttributesController" then spread its
26
+ values into your controllers then implement:
27
+
28
+ export default class MyNewController extends SyncedBooleanAttributesController {
29
+ static values = {
30
+ ...SyncedBooleanAttributesController.values,
31
+ myString: String,
32
+ }
33
+ }
34
+
35
+ Also, consider the functions defined here ABOVE the connection() function. Those functions will
36
+ give you control over how your controller can interact with other SyncedBooleanAttributeControllers.
37
+ Not every controller needs them but you should consider them (description can be found in the functions)
38
+
39
+ And don't forget that when you want to change an attr on an element, you should not do it manually.
40
+ Instead run:
41
+ this.updateAttributesForElement(element, value)
42
+ This will let you take advantage of the ecosystem created by this base controller without any additional work
43
+ */
44
+
45
+ export default class SyncedBooleanAttributesController<T> extends OutletManagerController<T> {
46
+ static values = {
47
+ ...OutletManagerController.values,
48
+ syncedAttrs: Array, // Set option target attrs to true/false in agreement with the option's selected state
49
+ antiAttrs: Array, // Set option target attrs to true/false opposite of the option's selected state
50
+ protectAttrs: Boolean, // If the controller should block other SyncedBooleanAttributesController from changing its defined attrs
51
+ }
52
+
53
+ declare readonly syncedAttrsValue: string[]
54
+ declare readonly hasSyncedAttrsValue: boolean
55
+ declare readonly antiAttrsValue: string[]
56
+ declare readonly hasAntiAttrsValue: boolean
57
+ declare readonly protectAttrsValue: boolean
58
+
59
+ // Some attributes are only false in HTML if they don't exist
60
+ // If included here, the property will be deleted on "false"
61
+ static removeOnFalseAttrs: {[k: string]: boolean} = {
62
+ checked: true,
63
+ }
64
+
65
+ syncedAttrsLookup: {[k: string]: boolean} | null = null
66
+ antiAttrsLookup: {[k: string]: boolean} | null = null
67
+
68
+ getValueForElement(element: Element): boolean | null {
69
+ // This function allows the base controller to access a given element's
70
+ // current status so the attributes can be set or compared. For example,
71
+ // you will want to make sure the attributes are added initially and are
72
+ // in sync with the controller's state. To ensure this, you can use the
73
+ // default connect() function or add "this.syncElementAttributes()" to your
74
+ // custom connect function. It'll look through your targets and get values for
75
+ // each then set the appropriate attrs and anti-attrs
76
+ return null
77
+ }
78
+
79
+ getElementsToSync(): Array<Element> | null | undefined {
80
+ // These are the elements your controller wants to keep in sync with the attrs
81
+ // Sometimes these are this.element, sometimes they're specific targets.
82
+ // Return them here so the base controller can automate some behaviors for you
83
+ return []
84
+ }
85
+
86
+ connect(): void {
87
+ // This function will sync attrs and anti-attrs when the controller connects.
88
+ // The logic is abstracted to a function so you can override this connect
89
+ // function in favor of your own without having to duplicate the sync logic
90
+ this.syncElementAttributes()
91
+ }
92
+
93
+ updateAttributesForElement(element: Element, value: boolean) {
94
+ // This is how you should update any synced or anti-synced attrs on your elements
95
+ // Do not do it manually unless you are very sure of what you're doing
96
+ if (this.hasSyncedAttrsValue) {
97
+ this.#setAttrs(element, this.syncedAttrsValue, value)
98
+ }
99
+
100
+ if (this.hasAntiAttrsValue) {
101
+ this.#setAttrs(element, this.antiAttrsValue, !value)
102
+ }
103
+ }
104
+
105
+ syncElementAttributes() {
106
+ this.syncOutlets()
107
+ // Essentially just a "sync attrs and anti-attrs on mount" function
108
+ const elements = this.getElementsToSync()
109
+
110
+ if (elements?.length) {
111
+ for (let index in elements) {
112
+ const element = elements[index]
113
+ const value = this.getValueForElement(element) ?? false
114
+ this.updateAttributesForElement(element, value)
115
+ }
116
+ }
117
+ }
118
+
119
+ validateAttrChange(dispatchEvent: TStimulusDispatchEvent<TSyncAttrDetail>) {
120
+ // If you protect your attrs, then this function will deny other controllers you specify from making changes to them.
121
+ // For example, if you want an item to disappear when it's selected, then your Options controller likely has an "aria-hidden"
122
+ // synced attr. If you use another attr to filter the list and then remove that filter, normally that would unhide your selected
123
+ // element. But if you have Options protect its attrs, the filter behavior won't be allowed to change it at any time and thus
124
+ // the element will remain hidden
125
+ const {target, detail} = dispatchEvent
126
+ if (target && detail) {
127
+ const currentValue = this.getValueForElement(target)
128
+ if (currentValue !== null && this.protectAttrsValue && this.#isAttr(detail.attr)) {
129
+ dispatchEvent.preventDefault()
130
+ }
131
+ }
132
+ }
133
+
134
+ #isSyncedAttr(attr: string) {
135
+ // Helper function to determine if the attr is synced
136
+ if (this.syncedAttrsLookup === null) {
137
+ this.syncedAttrsLookup = this.#getLookupForStringArray(this.syncedAttrsValue)
138
+ }
139
+
140
+ return this.syncedAttrsLookup[attr] ?? false
141
+ }
142
+
143
+ #isAntiAttr(attr: string) {
144
+ // Helper function to determine if the attr is anti-synced
145
+ if (this.antiAttrsLookup === null) {
146
+ this.antiAttrsLookup = this.#getLookupForStringArray(this.antiAttrsValue)
147
+ }
148
+
149
+ return this.antiAttrsLookup[attr] ?? false
150
+ }
151
+
152
+ #isAttr(attr: string) {
153
+ // Helper function to determine if an attr is known to a controller
154
+ return this.#isAntiAttr(attr) || this.#isSyncedAttr(attr)
155
+ }
156
+
157
+ #setAttrs(element: Element, attrs: string[], value: boolean) {
158
+ // Attempts to change the attr for an element. However, it'll dispatch an event
159
+ // first so other controllers get the opportunity to deny it
160
+ const attrState = JSON.stringify(value)
161
+ for (let index in attrs) {
162
+ const attr = attrs[index]
163
+
164
+ const dispatchEvent = this.dispatch('attrChange', {
165
+ target: element,
166
+ detail: {attr, value},
167
+ } as TStimulusDispatchEvent<TSyncAttrDetail>)
168
+
169
+ if (!dispatchEvent.defaultPrevented) {
170
+ if (attrState === 'false' && SyncedBooleanAttributesController.removeOnFalseAttrs[attr]) {
171
+ element.removeAttribute(attr)
172
+ } else {
173
+ element.setAttribute(attr, attrState)
174
+ }
175
+ }
176
+ }
177
+ }
178
+
179
+ #getLookupForStringArray(arr?: Array<string>) {
180
+ // Helper function to return an array of strings into an object for easy lookup
181
+ // While the arrays contained here are small, looking up attrs will happen often
182
+ // so I think it's worth the small sacrifice to memory
183
+ if (!arr?.length) {
184
+ return {}
185
+ }
186
+
187
+ return arr.reduce((acc, cur) => {
188
+ acc[cur] = true
189
+ return acc
190
+ }, {} as {[k: string]: boolean})
191
+ }
192
+ }
@@ -0,0 +1,15 @@
1
+ <%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do |wrapper| %>
2
+ <label class="ariadne-flex ariadne-w-fit ariadne-items-center <%= @label_classes %>">
3
+ <% if content? %>
4
+ <span class="group-data-[label-position=start]/wrapper:ariadne-mr-1.5 group-data-[label-position=end]/wrapper:ariadne-ml-1"><%= content %></span>
5
+ <% end %>
6
+ <%= render Ariadne::BaseComponent.new(tag: :button, classes: @button_classes, attributes: @button_attributes) do |button| %>
7
+ <span class="ariadne-sr-only ariadne-translate-x-3">Use setting</span>
8
+ <span aria-hidden="true" class="ariadne-pointer-events-none ariadne-absolute ariadne-h-full ariadne-w-full ariadne-rounded-md ariadne-bg-white"></span>
9
+ <span aria-hidden="true"
10
+ class="ariadne-bg-gray-200 ariadne-pointer-events-none ariadne-absolute ariadne-mx-auto ariadne-rounded-full ariadne-transition-colors ariadne-duration-200 ariadne-ease-in-out <%= @track_classes %>"></span>
11
+ <span aria-hidden="true"
12
+ class="ariadne-pointer-events-none ariadne-absolute ariadne-left-0 ariadne-inline-block ariadne-transform ariadne-rounded-full ariadne-border ariadne-border-gray-200 ariadne-bg-white ariadne-shadow ariadne-ring-0 ariadne-transition-transform ariadne-duration-200 ariadne-ease-in-out <%= @thumb_classes %>"></span>
13
+ <% end %>
14
+ </label>
15
+ <% end %>
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ariadne
4
+ # Simple toggle switch with on/off state. The logic is controlled by toggleable_controller and styles applied through
5
+ # tailwind's group+data attributes: https://tailwindcss.com/docs/hover-focus-and-other-states#data-attributes
6
+ class ToggleComponent < Ariadne::Component
7
+ DEFAULT_TAG = :div
8
+
9
+ DEFAULT_STATUS_LABEL_POSITION = :start
10
+ STATUS_LABEL_POSITION_MAPPINGS = {
11
+ start: "ariadne-flex-row",
12
+ end: "ariadne-flex-row-reverse",
13
+ }.freeze
14
+ STATUS_LABEL_POSITION_OPTIONS = STATUS_LABEL_POSITION_MAPPINGS.keys.freeze
15
+
16
+ DEFAULT_SIZE = :md
17
+ THUMB_SIZE_MAPPINGS = { sm: "ariadne-translate-x-0 ariadne-h-3 ariadne-w-3 group-aria-checked/toggle:ariadne-translate-x-3", md: "ariadne-translate-x-0 ariadne-h-5 ariadne-w-5 group-aria-checked/toggle:ariadne-translate-x-5" }.freeze
18
+ TRACK_SIZE_MAPPINGS = { sm: "ariadne-h-2 ariadne-w-4", md: "ariadne-h-4 ariadne-w-9" }.freeze
19
+ BUTTON_SIZE_MAPPINGS = { sm: "ariadne-h-3 ariadne-w-6", md: "ariadne-h-5 ariadne-w-10" }.freeze
20
+ LABEL_SIZE_MAPPINGS = { sm: "ariadne-text-xs", md: "ariadne-text-lg" }.freeze
21
+ SIZE_OPTIONS = THUMB_SIZE_MAPPINGS.keys.freeze
22
+
23
+ DEFAULT_CLASSES = {
24
+ wrapper: "ariadne-group/wrapper data-[disabled=true]:ariadne-opacity-50 data-[disabled=true]:ariadne-cursor-auto",
25
+ button: "ariadne-flex ariadne-justify-center ariadne-group/toggle ariadne-relative ariadne-inline-flex ariadne-flex-shrink-0 group-data-[disabled=false]/wrapper:ariadne-cursor-pointer ariadne-items-center ariadne-justify-center ariadne-rounded-full ariadne-focus:outline-none ariadne-focus:ring-2 ariadne-focus:ring-indigo-600 ariadne-focus:ring-offset-2 disabled:ariadne-cursor-auto",
26
+ }
27
+
28
+ DEFAULT_ATTRIBUTES = {
29
+ wrapper: {}.freeze,
30
+ button: {
31
+ role: "switch",
32
+ "data-controller": "toggleable",
33
+ "data-toggleable-synced-attrs-value": '["aria-checked"]',
34
+ "data-action": "click->toggleable#toggle",
35
+ },
36
+ }.freeze
37
+
38
+ DEFAULT_TRACK_COLOR = :indigo
39
+ TRACK_COLOR_MAPPINGS = {
40
+ white: "group-aria-checked/toggle:ariadne-bg-white",
41
+ green: "group-aria-checked/toggle:ariadne-bg-green-600",
42
+ blue: "group-aria-checked/toggle:ariadne-bg-blue-600",
43
+ billy_purple: "group-aria-checked/toggle:ariadne-bg-billy-purple",
44
+ indigo: "group-aria-checked/toggle:ariadne-bg-indigo-600",
45
+ }
46
+ TRACK_COLOR_OPTIONS = TRACK_COLOR_MAPPINGS.keys.freeze
47
+
48
+ # @example Default
49
+ #
50
+ # <%= render(Ariadne::ToggleComponent.new) { "Example" } %>
51
+ #
52
+ # @param classes [String] <%= link_to_classes_docs %>
53
+ # @param color [String] <%= link_to_classes_docs %>
54
+ # @param checked [Boolean] <%= link_to_classes_docs %>
55
+ # @param disabled [Boolean] <%= link_to_classes_docs %>
56
+ # @param size [String] <%= link_to_classes_docs %>
57
+ # @param label [String] <%= link_to_classes_docs %>
58
+ # @param status_label_position [String] <%= link_to_classes_docs %>
59
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
60
+ def initialize(
61
+ classes: nil,
62
+ checked: false,
63
+ disabled: false,
64
+ size: DEFAULT_SIZE,
65
+ color: DEFAULT_TRACK_COLOR,
66
+ status_label_position: DEFAULT_STATUS_LABEL_POSITION,
67
+ attributes: {}
68
+ )
69
+ @tag = DEFAULT_TAG
70
+ @size = fetch_or_raise(SIZE_OPTIONS, size)
71
+ @status_label_position = fetch_or_raise(STATUS_LABEL_POSITION_OPTIONS, status_label_position)
72
+ @color = fetch_or_raise(TRACK_COLOR_OPTIONS, color)
73
+ @classes = merge_class_names(DEFAULT_CLASSES[:wrapper], classes)
74
+ @checked = checked
75
+ @disabled = disabled
76
+ @attributes = DEFAULT_ATTRIBUTES[:wrapper].merge({ "data-label-position": @status_label_position, "data-disabled": @disabled }).merge(attributes)
77
+
78
+ @label_classes = merge_class_names(STATUS_LABEL_POSITION_MAPPINGS.fetch(@status_label_position), LABEL_SIZE_MAPPINGS.fetch(@size))
79
+
80
+ @button_classes = merge_class_names(DEFAULT_CLASSES[:button], BUTTON_SIZE_MAPPINGS.fetch(@size))
81
+ @button_attributes = DEFAULT_ATTRIBUTES[:button].merge({ "aria-checked": @checked, "data-toggleable-state-value": @checked, disabled: @disabled })
82
+
83
+ @thumb_classes = THUMB_SIZE_MAPPINGS.fetch(@size)
84
+ @track_classes = merge_class_names(TRACK_SIZE_MAPPINGS.fetch(@size), TRACK_COLOR_MAPPINGS.fetch(@color))
85
+ end
86
+
87
+ def on?
88
+ @checked
89
+ end
90
+
91
+ def disabled?
92
+ @disabled
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,34 @@
1
+ import type { TOutletChangeData } from '../outlet_manager_controller/outlet_manager_controller';
2
+ import SyncedBooleanAttributesController from '../synced_boolean_attributes_controller/synced_boolean_attributes_controller';
3
+ export interface ToggleableOutlet extends SyncedBooleanAttributesController<boolean> {
4
+ toggle: (event: Event, updateTo?: TOutletChangeData<boolean>) => void;
5
+ }
6
+ export default class ToggleableController extends SyncedBooleanAttributesController<boolean> implements ToggleableOutlet {
7
+ static outlets: string[];
8
+ static values: {
9
+ state: {
10
+ type: BooleanConstructor;
11
+ default: boolean;
12
+ };
13
+ closeOnOutsideClick: {
14
+ type: BooleanConstructor;
15
+ default: boolean;
16
+ };
17
+ syncedAttrs: ArrayConstructor;
18
+ antiAttrs: ArrayConstructor;
19
+ protectAttrs: BooleanConstructor;
20
+ outletEvents: ArrayConstructor;
21
+ };
22
+ stateValue: boolean;
23
+ readonly closeOnOutsideClickValue: boolean;
24
+ connect(): void;
25
+ toggle(event: Event, updateTo?: TOutletChangeData<boolean>): void;
26
+ on(event: Event): void;
27
+ off(event: Event): void;
28
+ clickOutside(event: Event): void;
29
+ getValueForElement(element: Element): boolean | null;
30
+ getElementsToSync(): Element[] | null | undefined;
31
+ getState(): boolean;
32
+ get event_key_postfix(): "on" | "off";
33
+ outletUpdate: (event: Event, updateTo?: TOutletChangeData<boolean>) => void;
34
+ }
@@ -0,0 +1,54 @@
1
+ import { useClickOutside } from 'stimulus-use';
2
+ import SyncedBooleanAttributesController from '../synced_boolean_attributes_controller/synced_boolean_attributes_controller';
3
+ class ToggleableController extends SyncedBooleanAttributesController {
4
+ constructor() {
5
+ super(...arguments);
6
+ this.outletUpdate = this.toggle;
7
+ }
8
+ connect() {
9
+ this.syncElementAttributes();
10
+ useClickOutside(this, { dispatchEvent: this.closeOnOutsideClickValue && this.stateValue });
11
+ }
12
+ toggle(event, updateTo = {}) {
13
+ var _a;
14
+ const v = (_a = updateTo.data) !== null && _a !== void 0 ? _a : !this.stateValue;
15
+ this.updateAttributesForElement(this.element, v);
16
+ this.stateValue = v;
17
+ this.sendToOutlets(event, Object.assign(Object.assign({}, updateTo), { data: v }));
18
+ }
19
+ on(event) {
20
+ this.toggle(event, { data: true });
21
+ }
22
+ off(event) {
23
+ this.toggle(event, { data: false });
24
+ }
25
+ clickOutside(event) {
26
+ if (this.closeOnOutsideClickValue && this.stateValue) {
27
+ this.toggle(event, { data: false });
28
+ }
29
+ }
30
+ getValueForElement(element) {
31
+ if (element !== this.element) {
32
+ return null;
33
+ }
34
+ return this.stateValue;
35
+ }
36
+ getElementsToSync() {
37
+ return [this.element];
38
+ }
39
+ getState() {
40
+ return this.stateValue;
41
+ }
42
+ get event_key_postfix() {
43
+ return this.stateValue ? 'on' : 'off';
44
+ }
45
+ }
46
+ ToggleableController.outlets = SyncedBooleanAttributesController.outlets;
47
+ ToggleableController.values = Object.assign(Object.assign({}, SyncedBooleanAttributesController.values), { state: {
48
+ type: Boolean,
49
+ default: false,
50
+ }, closeOnOutsideClick: {
51
+ type: Boolean,
52
+ default: false,
53
+ } });
54
+ export default ToggleableController;
@@ -0,0 +1,77 @@
1
+ import type {TOutletChangeData} from '../outlet_manager_controller/outlet_manager_controller'
2
+ import {useClickOutside} from 'stimulus-use'
3
+ import SyncedBooleanAttributesController from '../synced_boolean_attributes_controller/synced_boolean_attributes_controller'
4
+
5
+ export interface ToggleableOutlet extends SyncedBooleanAttributesController<boolean> {
6
+ toggle: (event: Event, updateTo?: TOutletChangeData<boolean>) => void
7
+ }
8
+
9
+ export default class ToggleableController
10
+ extends SyncedBooleanAttributesController<boolean>
11
+ implements ToggleableOutlet
12
+ {
13
+ static outlets = SyncedBooleanAttributesController.outlets
14
+ static values = {
15
+ ...SyncedBooleanAttributesController.values,
16
+ state: {
17
+ type: Boolean,
18
+ default: false,
19
+ },
20
+ closeOnOutsideClick: {
21
+ type: Boolean,
22
+ default: false,
23
+ },
24
+ }
25
+
26
+ declare stateValue: boolean
27
+ declare readonly closeOnOutsideClickValue: boolean
28
+
29
+ connect(): void {
30
+ this.syncElementAttributes()
31
+ useClickOutside(this, {dispatchEvent: this.closeOnOutsideClickValue && this.stateValue})
32
+ }
33
+
34
+ toggle(event: Event, updateTo: TOutletChangeData<boolean> = {}) {
35
+ const v = updateTo.data ?? !this.stateValue
36
+
37
+ this.updateAttributesForElement(this.element, v)
38
+ this.stateValue = v
39
+ this.sendToOutlets(event, {...updateTo, data: v})
40
+ }
41
+
42
+ on(event: Event) {
43
+ this.toggle(event, {data: true})
44
+ }
45
+
46
+ off(event: Event) {
47
+ this.toggle(event, {data: false})
48
+ }
49
+
50
+ clickOutside(event: Event) {
51
+ if (this.closeOnOutsideClickValue && this.stateValue) {
52
+ this.toggle(event, {data: false})
53
+ }
54
+ }
55
+
56
+ getValueForElement(element: Element): boolean | null {
57
+ if (element !== this.element) {
58
+ return null
59
+ }
60
+
61
+ return this.stateValue
62
+ }
63
+
64
+ getElementsToSync(): Element[] | null | undefined {
65
+ return [this.element]
66
+ }
67
+
68
+ getState() {
69
+ return this.stateValue
70
+ }
71
+
72
+ get event_key_postfix() {
73
+ return this.stateValue ? 'on' : 'off'
74
+ }
75
+
76
+ outletUpdate = this.toggle
77
+ }
@@ -3,6 +3,6 @@
3
3
  # :nocov:
4
4
  module Ariadne
5
5
  module ViewComponents
6
- VERSION = "0.0.47"
6
+ VERSION = "0.0.49"
7
7
  end
8
8
  end
data/static/arguments.yml CHANGED
@@ -574,6 +574,21 @@
574
574
  type: Hash
575
575
  default: "`{}`"
576
576
  description: "[Classes and attributes](/classes-attributes)"
577
+ - component: SubheaderComponent
578
+ source: https://github.com/yettoapp/ariadne/ruby/view_components/tree/main/app/components/ariadne/subheader_component.rb
579
+ parameters:
580
+ - name: tag
581
+ type: Symbol, String
582
+ default: "`:p`"
583
+ description: The rendered tag name.
584
+ - name: classes
585
+ type: String
586
+ default: '`""`'
587
+ description: "[Classes and attributes](/classes-attributes)"
588
+ - name: attributes
589
+ type: Hash
590
+ default: "`{}`"
591
+ description: "[Classes and attributes](/classes-attributes)"
577
592
  - component: TabComponent
578
593
  source: https://github.com/yettoapp/ariadne/ruby/view_components/tree/main/app/components/ariadne/tab_component.rb
579
594
  parameters:
@@ -702,6 +717,41 @@
702
717
  type: Hash
703
718
  default: "`{}`"
704
719
  description: "[Classes and attributes](/classes-attributes)"
720
+ - component: ToggleComponent
721
+ source: https://github.com/yettoapp/ariadne/ruby/view_components/tree/main/app/components/ariadne/toggle_component.rb
722
+ parameters:
723
+ - name: classes
724
+ type: String
725
+ default: "`nil`"
726
+ description: "[Classes and attributes](/classes-attributes)"
727
+ - name: color
728
+ type: String
729
+ default: "`:indigo`"
730
+ description: "[Classes and attributes](/classes-attributes)"
731
+ - name: checked
732
+ type: Boolean
733
+ default: "`false`"
734
+ description: "[Classes and attributes](/classes-attributes)"
735
+ - name: disabled
736
+ type: Boolean
737
+ default: "`false`"
738
+ description: "[Classes and attributes](/classes-attributes)"
739
+ - name: size
740
+ type: String
741
+ default: "`:md`"
742
+ description: "[Classes and attributes](/classes-attributes)"
743
+ - name: label
744
+ type: String
745
+ default: N/A
746
+ description: "[Classes and attributes](/classes-attributes)"
747
+ - name: status_label_position
748
+ type: String
749
+ default: "`:start`"
750
+ description: "[Classes and attributes](/classes-attributes)"
751
+ - name: attributes
752
+ type: Hash
753
+ default: "`{}`"
754
+ description: "[Classes and attributes](/classes-attributes)"
705
755
  - component: TooltipComponent
706
756
  source: https://github.com/yettoapp/ariadne/ruby/view_components/tree/main/app/components/ariadne/tooltip_component.rb
707
757
  parameters:
@@ -1,14 +1,22 @@
1
1
  {
2
+ "Ariadne::ActionCardComponent": "",
2
3
  "Ariadne::AvatarComponent": "",
3
4
  "Ariadne::AvatarStackComponent": "",
4
5
  "Ariadne::BaseButton": "",
5
6
  "Ariadne::BaseComponent": "",
6
7
  "Ariadne::BlankslateComponent": "",
7
8
  "Ariadne::BodyComponent": "",
9
+ "Ariadne::BottomTabComponent": "",
10
+ "Ariadne::BottomTabNavComponent": "",
11
+ "Ariadne::BreadcrumbsComponent": "",
8
12
  "Ariadne::ButtonComponent": "",
13
+ "Ariadne::CheckboxComponent": "",
9
14
  "Ariadne::ClipboardCopyComponent": "",
15
+ "Ariadne::CloseButtonComponent": "",
16
+ "Ariadne::ComboboxComponent": "",
10
17
  "Ariadne::CommentComponent": "",
11
18
  "Ariadne::ContainerComponent": "",
19
+ "Ariadne::Content": "",
12
20
  "Ariadne::CounterComponent": "",
13
21
  "Ariadne::DetailsComponent": "",
14
22
  "Ariadne::Dropdown::MenuComponent": "",
@@ -24,15 +32,23 @@
24
32
  "Ariadne::HeroiconComponent": "",
25
33
  "Ariadne::ImageComponent": "",
26
34
  "Ariadne::InlineFlexComponent": "",
35
+ "Ariadne::LayoutComponent": "",
27
36
  "Ariadne::LinkComponent": "",
28
37
  "Ariadne::ListComponent": "",
29
38
  "Ariadne::ListComponent::ListItem": "",
39
+ "Ariadne::ModalComponent": "",
30
40
  "Ariadne::NarrowContainerComponent": "",
31
41
  "Ariadne::PanelBarComponent": "",
32
42
  "Ariadne::PanelBarComponent::PanelItem": "",
33
43
  "Ariadne::PillComponent": "",
44
+ "Ariadne::PopoverComponent": "",
45
+ "Ariadne::ProgressBarComponent": "",
46
+ "Ariadne::RelativeTimeComponent": "",
34
47
  "Ariadne::RichTextAreaComponent": "",
48
+ "Ariadne::ShowMoreButtonComponent": "",
35
49
  "Ariadne::SlideoverComponent": "",
50
+ "Ariadne::SpinnerComponent": "",
51
+ "Ariadne::SubheaderComponent": "",
36
52
  "Ariadne::TabComponent": "",
37
53
  "Ariadne::TabContainerComponent": "",
38
54
  "Ariadne::TabNavComponent": "",
@@ -48,5 +64,6 @@
48
64
  "Ariadne::Text": "",
49
65
  "Ariadne::TimeAgoComponent": "",
50
66
  "Ariadne::TimelineComponent": "",
67
+ "Ariadne::ToggleComponent": "",
51
68
  "Ariadne::TooltipComponent": ""
52
69
  }