ariadne_view_components 0.0.47-x86_64-linux → 0.0.49-x86_64-linux

Sign up to get free protection for your applications and to get access to all the features.
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,237 @@
1
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
3
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
+ };
6
+ var _OutletManagerController_instances, _OutletManagerController_outlets_get;
7
+ import { Controller } from '@hotwired/stimulus';
8
+ class OutletManagerController extends Controller {
9
+ constructor() {
10
+ super(...arguments);
11
+ _OutletManagerController_instances.add(this);
12
+ this.outletEventsLookup = null;
13
+ this.eventRecords = new Map();
14
+ }
15
+ getOutlets() {
16
+ return null;
17
+ }
18
+ outletUpdate(event, data) { }
19
+ getState() {
20
+ return null;
21
+ }
22
+ connect() {
23
+ this.syncOutlets();
24
+ }
25
+ syncOutlets() {
26
+ const event = new Event('init');
27
+ this.sendToOutlets(event, {
28
+ data: this.getState(),
29
+ eventKey: this.getEventKey(event),
30
+ });
31
+ }
32
+ sendToOutlets(event, updateTo = {}) {
33
+ var _a;
34
+ const eventKey = (_a = updateTo.eventKey) !== null && _a !== void 0 ? _a : this.getEventKey(event);
35
+ const outlets = __classPrivateFieldGet(this, _OutletManagerController_instances, "a", _OutletManagerController_outlets_get);
36
+ if (outlets === null || outlets === void 0 ? void 0 : outlets.length) {
37
+ for (const index in outlets) {
38
+ const outlet = outlets[index];
39
+ if (outlet.isListeningForOutletEvent(eventKey) && !this.hasHeardEvent(event)) {
40
+ const isSameControllerType = this.identifier === outlet.identifier;
41
+ outlet.outletUpdate(event, { eventKey, data: isSameControllerType ? updateTo.data : undefined });
42
+ }
43
+ }
44
+ }
45
+ }
46
+ isListeningForOutletEvent(eventTypes) {
47
+ const eventTypeNames = eventTypes.split('-');
48
+ if (!eventTypeNames.length) {
49
+ return false;
50
+ }
51
+ let lookup = this.outletEvents;
52
+ for (let i = 0; i < eventTypeNames.length; i++) {
53
+ const name = eventTypeNames[i];
54
+ if (typeof lookup === 'boolean') {
55
+ return lookup;
56
+ }
57
+ const hasWildCard = lookup['*'] !== undefined;
58
+ let nextKey = name;
59
+ if (hasWildCard) {
60
+ nextKey = '*';
61
+ }
62
+ else {
63
+ const isListeningForDOMEvent = lookup.domEvent !== undefined;
64
+ if (isListeningForDOMEvent && !this.isDOMEventName(name)) {
65
+ return false;
66
+ }
67
+ else if (isListeningForDOMEvent) {
68
+ nextKey = 'domEvent';
69
+ }
70
+ }
71
+ if (!lookup[nextKey]) {
72
+ return false;
73
+ }
74
+ lookup = lookup[nextKey];
75
+ }
76
+ return true;
77
+ }
78
+ isDOMEventName(eventName) {
79
+ return OutletManagerController.domEvents[eventName];
80
+ }
81
+ getEventKey(event) {
82
+ const pre = this.event_key_prefix;
83
+ const post = this.event_key_postfix;
84
+ const maybePreHyphen = pre ? '-' : '';
85
+ const maybePrefix = pre !== null && pre !== void 0 ? pre : '';
86
+ const maybePostHyphen = post ? '-' : '';
87
+ const maybePostfix = post !== null && post !== void 0 ? post : '';
88
+ return `${this.identifier}-${maybePrefix}${maybePreHyphen}${event.type}${maybePostHyphen}${maybePostfix}`;
89
+ }
90
+ hasHeardEvent(event) {
91
+ if (this.eventRecords.has(event)) {
92
+ return true;
93
+ }
94
+ this.eventRecords.set(event, true);
95
+ setTimeout(() => this.eventRecords.delete(event));
96
+ return false;
97
+ }
98
+ get event_key_prefix() {
99
+ return '';
100
+ }
101
+ get event_key_postfix() {
102
+ return '';
103
+ }
104
+ get outletEvents() {
105
+ if (!this.outletEventsLookup && this.hasOutletEventsValue) {
106
+ this.outletEventsLookup = this.outletEventsValue.reduce((acc, eventType) => {
107
+ let step = acc;
108
+ eventType.split('-').forEach((eventTypeName, i, splitArr) => {
109
+ if (typeof step === 'boolean') {
110
+ return;
111
+ }
112
+ if (i === splitArr.length - 1) {
113
+ step[eventTypeName] = true;
114
+ }
115
+ else if (step[eventTypeName] === undefined) {
116
+ step[eventTypeName] = {};
117
+ }
118
+ step = step[eventTypeName];
119
+ });
120
+ return acc;
121
+ }, {});
122
+ }
123
+ else if (!this.outletEventsLookup) {
124
+ this.outletEventsLookup = { '*': true };
125
+ }
126
+ return this.outletEventsLookup;
127
+ }
128
+ }
129
+ _OutletManagerController_instances = new WeakSet(), _OutletManagerController_outlets_get = function _OutletManagerController_outlets_get() {
130
+ const outlets = this.getOutlets();
131
+ if (outlets) {
132
+ return outlets;
133
+ }
134
+ const defaultOutlets = [];
135
+ if (this.hasToggleableOutlet) {
136
+ defaultOutlets.push(...this.toggleableOutlets);
137
+ }
138
+ if (this.hasOptionsOutlet) {
139
+ defaultOutlets.push(...this.optionsOutlets);
140
+ }
141
+ if (this.hasStringMatchOutlet) {
142
+ defaultOutlets.push(...this.stringMatchOutlets);
143
+ }
144
+ return defaultOutlets;
145
+ };
146
+ OutletManagerController.values = {
147
+ outletEvents: Array,
148
+ };
149
+ OutletManagerController.outlets = ['toggleable', 'options', 'string-match'];
150
+ OutletManagerController.domEvents = {
151
+ abort: true,
152
+ afterprint: true,
153
+ animationend: true,
154
+ animationiteration: true,
155
+ animationstart: true,
156
+ beforeprint: true,
157
+ beforeunload: true,
158
+ blur: true,
159
+ canplay: true,
160
+ canplaythrough: true,
161
+ change: true,
162
+ click: true,
163
+ contextmenu: true,
164
+ copy: true,
165
+ cut: true,
166
+ dblclick: true,
167
+ drag: true,
168
+ dragend: true,
169
+ dragenter: true,
170
+ dragleave: true,
171
+ dragover: true,
172
+ dragstart: true,
173
+ drop: true,
174
+ durationchange: true,
175
+ ended: true,
176
+ error: true,
177
+ focus: true,
178
+ focusin: true,
179
+ focusout: true,
180
+ fullscreenchange: true,
181
+ fullscreenerror: true,
182
+ hashchange: true,
183
+ input: true,
184
+ invalid: true,
185
+ keydown: true,
186
+ keypress: true,
187
+ keyup: true,
188
+ load: true,
189
+ loadeddata: true,
190
+ loadedmetadata: true,
191
+ loadstart: true,
192
+ message: true,
193
+ mousedown: true,
194
+ mouseenter: true,
195
+ mouseleave: true,
196
+ mousemove: true,
197
+ mouseover: true,
198
+ mouseout: true,
199
+ mouseup: true,
200
+ mousewheel: true,
201
+ offline: true,
202
+ online: true,
203
+ open: true,
204
+ pagehide: true,
205
+ pageshow: true,
206
+ paste: true,
207
+ pause: true,
208
+ play: true,
209
+ playing: true,
210
+ popstate: true,
211
+ progress: true,
212
+ ratechange: true,
213
+ resize: true,
214
+ reset: true,
215
+ scroll: true,
216
+ search: true,
217
+ seeked: true,
218
+ seeking: true,
219
+ select: true,
220
+ show: true,
221
+ stalled: true,
222
+ storage: true,
223
+ submit: true,
224
+ suspend: true,
225
+ timeupdate: true,
226
+ toggle: true,
227
+ touchcancel: true,
228
+ touchend: true,
229
+ touchmove: true,
230
+ touchstart: true,
231
+ transitionend: true,
232
+ unload: true,
233
+ volumechange: true,
234
+ waiting: true,
235
+ wheel: true,
236
+ };
237
+ export default OutletManagerController;
@@ -0,0 +1,278 @@
1
+ import {Controller} from '@hotwired/stimulus'
2
+
3
+ type TOutletEventLookup = boolean | {[k: string]: TOutletEventLookup}
4
+
5
+ export type TOutletChangeData<T> =
6
+ | {
7
+ eventKey?: string
8
+ data?: T
9
+ }
10
+ | undefined
11
+
12
+ export default class OutletManagerController<T> extends Controller {
13
+ static values = {
14
+ outletEvents: Array,
15
+ }
16
+
17
+ declare readonly outletEventsValue: Array<string>
18
+ declare readonly hasOutletEventsValue: boolean
19
+
20
+ static outlets = ['toggleable', 'options', 'string-match']
21
+ declare readonly toggleableOutlets: Array<OutletManagerController<T>>
22
+ declare readonly hasToggleableOutlet: boolean
23
+ declare readonly optionsOutlets: Array<OutletManagerController<T>>
24
+ declare readonly hasOptionsOutlet: boolean
25
+ declare readonly stringMatchOutlets: Array<OutletManagerController<T>>
26
+ declare readonly hasStringMatchOutlet: boolean
27
+
28
+ outletEventsLookup: TOutletEventLookup | null = null
29
+
30
+ static domEvents: {[k: string]: boolean} = {
31
+ abort: true,
32
+ afterprint: true,
33
+ animationend: true,
34
+ animationiteration: true,
35
+ animationstart: true,
36
+ beforeprint: true,
37
+ beforeunload: true,
38
+ blur: true,
39
+ canplay: true,
40
+ canplaythrough: true,
41
+ change: true,
42
+ click: true,
43
+ contextmenu: true,
44
+ copy: true,
45
+ cut: true,
46
+ dblclick: true,
47
+ drag: true,
48
+ dragend: true,
49
+ dragenter: true,
50
+ dragleave: true,
51
+ dragover: true,
52
+ dragstart: true,
53
+ drop: true,
54
+ durationchange: true,
55
+ ended: true,
56
+ error: true,
57
+ focus: true,
58
+ focusin: true,
59
+ focusout: true,
60
+ fullscreenchange: true,
61
+ fullscreenerror: true,
62
+ hashchange: true,
63
+ input: true,
64
+ invalid: true,
65
+ keydown: true,
66
+ keypress: true,
67
+ keyup: true,
68
+ load: true,
69
+ loadeddata: true,
70
+ loadedmetadata: true,
71
+ loadstart: true,
72
+ message: true,
73
+ mousedown: true,
74
+ mouseenter: true,
75
+ mouseleave: true,
76
+ mousemove: true,
77
+ mouseover: true,
78
+ mouseout: true,
79
+ mouseup: true,
80
+ mousewheel: true,
81
+ offline: true,
82
+ online: true,
83
+ open: true,
84
+ pagehide: true,
85
+ pageshow: true,
86
+ paste: true,
87
+ pause: true,
88
+ play: true,
89
+ playing: true,
90
+ popstate: true,
91
+ progress: true,
92
+ ratechange: true,
93
+ resize: true,
94
+ reset: true,
95
+ scroll: true,
96
+ search: true,
97
+ seeked: true,
98
+ seeking: true,
99
+ select: true,
100
+ show: true,
101
+ stalled: true,
102
+ storage: true,
103
+ submit: true,
104
+ suspend: true,
105
+ timeupdate: true,
106
+ toggle: true,
107
+ touchcancel: true,
108
+ touchend: true,
109
+ touchmove: true,
110
+ touchstart: true,
111
+ transitionend: true,
112
+ unload: true,
113
+ volumechange: true,
114
+ waiting: true,
115
+ wheel: true,
116
+ }
117
+
118
+ eventRecords: Map<Event, boolean> = new Map()
119
+
120
+ getOutlets(): Array<OutletManagerController<T>> | null | void {
121
+ return null
122
+ }
123
+
124
+ outletUpdate(event: Event, data: TOutletChangeData<T>): void {}
125
+
126
+ getState(): T {
127
+ return null as T
128
+ }
129
+
130
+ connect() {
131
+ this.syncOutlets()
132
+ }
133
+
134
+ syncOutlets() {
135
+ const event = new Event('init')
136
+ this.sendToOutlets(event, {
137
+ data: this.getState(),
138
+ eventKey: this.getEventKey(event),
139
+ })
140
+ }
141
+
142
+ sendToOutlets(event: Event, updateTo: TOutletChangeData<T> = {}): void {
143
+ const eventKey = updateTo.eventKey ?? this.getEventKey(event)
144
+ const outlets = this.#outlets
145
+ if (outlets?.length) {
146
+ for (const index in outlets) {
147
+ const outlet = outlets[index]
148
+ if (outlet.isListeningForOutletEvent(eventKey) && !this.hasHeardEvent(event)) {
149
+ const isSameControllerType = this.identifier === outlet.identifier
150
+ outlet.outletUpdate(event, {eventKey, data: isSameControllerType ? updateTo.data : undefined})
151
+ }
152
+ }
153
+ }
154
+ }
155
+
156
+ isListeningForOutletEvent(eventTypes: string) {
157
+ const eventTypeNames = eventTypes.split('-')
158
+
159
+ if (!eventTypeNames.length) {
160
+ return false
161
+ }
162
+
163
+ let lookup = this.outletEvents
164
+ for (let i = 0; i < eventTypeNames.length; i++) {
165
+ const name = eventTypeNames[i]
166
+ if (typeof lookup === 'boolean') {
167
+ return lookup
168
+ }
169
+
170
+ const hasWildCard = lookup['*'] !== undefined
171
+ let nextKey = name
172
+ if (hasWildCard) {
173
+ nextKey = '*'
174
+ } else {
175
+ const isListeningForDOMEvent = lookup.domEvent !== undefined
176
+ if (isListeningForDOMEvent && !this.isDOMEventName(name)) {
177
+ return false
178
+ } else if (isListeningForDOMEvent) {
179
+ nextKey = 'domEvent'
180
+ }
181
+ }
182
+
183
+ if (!lookup[nextKey]) {
184
+ return false
185
+ }
186
+
187
+ lookup = lookup[nextKey]
188
+ }
189
+
190
+ return true
191
+ }
192
+
193
+ isDOMEventName(eventName: string) {
194
+ return OutletManagerController.domEvents[eventName]
195
+ }
196
+
197
+ getEventKey(event: Event) {
198
+ const pre = this.event_key_prefix
199
+ const post = this.event_key_postfix
200
+
201
+ const maybePreHyphen = pre ? '-' : ''
202
+ const maybePrefix = pre ?? ''
203
+ const maybePostHyphen = post ? '-' : ''
204
+ const maybePostfix = post ?? ''
205
+
206
+ return `${this.identifier}-${maybePrefix}${maybePreHyphen}${event.type}${maybePostHyphen}${maybePostfix}`
207
+ }
208
+
209
+ hasHeardEvent(event: Event) {
210
+ if (this.eventRecords.has(event)) {
211
+ return true
212
+ }
213
+
214
+ this.eventRecords.set(event, true)
215
+ setTimeout(() => this.eventRecords.delete(event))
216
+
217
+ return false
218
+ }
219
+
220
+ get event_key_prefix() {
221
+ return ''
222
+ }
223
+
224
+ get event_key_postfix() {
225
+ return ''
226
+ }
227
+
228
+ get outletEvents() {
229
+ if (!this.outletEventsLookup && this.hasOutletEventsValue) {
230
+ this.outletEventsLookup = this.outletEventsValue.reduce((acc, eventType) => {
231
+ let step = acc
232
+ eventType.split('-').forEach((eventTypeName, i, splitArr) => {
233
+ if (typeof step === 'boolean') {
234
+ return
235
+ }
236
+
237
+ if (i === splitArr.length - 1) {
238
+ step[eventTypeName] = true
239
+ } else if (step[eventTypeName] === undefined) {
240
+ step[eventTypeName] = {}
241
+ }
242
+
243
+ step = step[eventTypeName]
244
+ })
245
+
246
+ return acc
247
+ }, {} as TOutletEventLookup)
248
+ } else if (!this.outletEventsLookup) {
249
+ this.outletEventsLookup = {'*': true}
250
+ }
251
+
252
+ return this.outletEventsLookup
253
+ }
254
+
255
+ get #outlets(): Array<OutletManagerController<T>> | null | void {
256
+ const outlets = this.getOutlets()
257
+
258
+ if (outlets) {
259
+ return outlets
260
+ }
261
+
262
+ const defaultOutlets: Array<OutletManagerController<T>> = []
263
+
264
+ if (this.hasToggleableOutlet) {
265
+ defaultOutlets.push(...this.toggleableOutlets)
266
+ }
267
+
268
+ if (this.hasOptionsOutlet) {
269
+ defaultOutlets.push(...this.optionsOutlets)
270
+ }
271
+
272
+ if (this.hasStringMatchOutlet) {
273
+ defaultOutlets.push(...this.stringMatchOutlets)
274
+ }
275
+
276
+ return defaultOutlets
277
+ }
278
+ }
@@ -0,0 +1,10 @@
1
+ <%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do |component| %>
2
+ <div class="<%= @base_classes %>">
3
+ <%= base %>
4
+ </div>
5
+ <div class="<%= @items_wrapper_classes %>" data-action="click->toggleable#toggle">
6
+ <% items.each do |item| %>
7
+ <%= item %>
8
+ <% end %>
9
+ </div>
10
+ <% end %>
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ariadne
4
+ # Displays content in a box that hovers over other content
5
+ class PopoverComponent < Ariadne::Component
6
+ DEFAULT_TAG = :div
7
+ TAG_OPTIONS = [DEFAULT_TAG].freeze
8
+
9
+ DIRECTIONS = [:top, :right, :bottom, :left]
10
+
11
+ # Menu: List of selectable items (ie: navigation)
12
+ # Dialog: Essentiall a modal
13
+ # Listbox: Something like a dropdown for a <select> element
14
+ # Tooltip: plain text
15
+ ROLES = [:menu, :dialog, :listbox, :tooltip]
16
+ HORIZONTAL_ALIGNMENTS = [:left, :right, :center]
17
+
18
+ DEFAULT_CLASSES = {
19
+ wrapper: "ariadne-group ariadne-relative ariadne-w-fit",
20
+ items: "ariadne-w-fit ariadne-absolute ariadne-shadow-lg ariadne-z-10 ariadne-p-2 ariadne-bg-white ariadne-rounded-md",
21
+ base: "ariadne-inline-block",
22
+ }
23
+
24
+ ITEMS_DIRECITON_CLASSES = "group-data-[popover-direction=top]:ariadne-bottom-full group-data-[popover-direction=top]:-ariadne-translate-y-2 group-data-[popover-direction=bottom]:ariadne-top-full group-data-[popover-direction=bottom]:ariadne-translate-y-2"
25
+ ITEMS_HORIZONTAL_ALIGNMENT_CLASSES = "group-data-[popover-horizontal-alignment=left]:ariadne-left-0 group-data-[popover-horizontal-alignment=right]:ariadne-right-0 group-data-[popover-horizontal-alignment=center]:ariadne-left-1/2 group-data-[popover-horizontal-alignment=center]:-ariadne-translate-x-1/2"
26
+ ITEMS_VISIBILITY_CLASSES = "group-data-[popover-visible=false]:ariadne-hidden"
27
+
28
+ DEFAULT_ATTRIBUTES = {
29
+ "data-controller": "toggleable",
30
+ "data-action": "click->toggleable#toggle",
31
+ "data-toggleable-synced-attrs-value": '["data-popover-visible"]',
32
+ }
33
+
34
+ renders_one :base
35
+
36
+ renders_many :items
37
+
38
+ # @example Default
39
+ #
40
+ # <%= render(Ariadne::PopoverComponent.new) { "Example" } %>
41
+ #
42
+ # @param tag [Symbol, String] The rendered tag name.
43
+ # @param classes [String] <%= link_to_classes_docs %>
44
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
45
+ def initialize(
46
+ tag: DEFAULT_TAG,
47
+ direction: :bottom,
48
+ classes: "",
49
+ role:,
50
+ attributes: {},
51
+ horizontal_alignment: :center,
52
+ initial_visible: false,
53
+ base_wrapper_classes: "",
54
+ items_wrapper_classes: ""
55
+ )
56
+ @tag = check_incoming_tag(DEFAULT_TAG, tag)
57
+ @direction = fetch_or_raise(DIRECTIONS, direction)
58
+ @horizontal_alignment = fetch_or_raise(HORIZONTAL_ALIGNMENTS, horizontal_alignment)
59
+ @role = fetch_or_raise(ROLES, role)
60
+ @classes = merge_class_names(DEFAULT_CLASSES[:wrapper], classes)
61
+
62
+ @attributes = DEFAULT_ATTRIBUTES
63
+ .merge({
64
+ "data-popover-direction": @direction,
65
+ "data-popover-horizontal-alignment": @horizontal_alignment,
66
+ "data-popover-visible": initial_visible,
67
+ "data-toggleable-close-on-outside-click-value": true,
68
+ })
69
+ .merge(attributes)
70
+
71
+ @base_classes = merge_class_names(DEFAULT_CLASSES[:base], base_wrapper_classes)
72
+ @items_wrapper_classes = merge_class_names(
73
+ DEFAULT_CLASSES[:items],
74
+ ITEMS_DIRECITON_CLASSES,
75
+ ITEMS_HORIZONTAL_ALIGNMENT_CLASSES,
76
+ ITEMS_VISIBILITY_CLASSES,
77
+ items_wrapper_classes,
78
+ )
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,5 @@
1
+ <%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do |c| %>
2
+ <% items.each do |item| %>
3
+ <%= item %>
4
+ <% end %>
5
+ <% end %>
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ariadne
4
+ # Bar used to show a progress in an activity, supports single bars or multiple bars within one component
5
+ # use aria-labelledby and aria-describedby to describe the progress bar's purpose
6
+ class ProgressBarComponent < Ariadne::Component
7
+ DEFAULT_TAGS = {
8
+ wrapper: :div,
9
+ item: :div,
10
+ }
11
+
12
+ DEFAULT_CLASSES = {
13
+ wrapper: "ariadne-flex ariadne-gap-1 ariadne-bg-slate-200 ariadne-rounded-md ariadne-overflow-hidden",
14
+ item: "",
15
+ }
16
+
17
+ DEFAULT_ATTRIBUTES = {
18
+ wrapper: {
19
+ role: "progressbar",
20
+ "data-controller": "accumulator",
21
+ "aria-valuenow": 0,
22
+ },
23
+ item: { "data-accumulator-target": "sum" },
24
+ }
25
+
26
+ BAR_SIZES = {
27
+ sm: "ariadne-h-2",
28
+ md: "ariadne-h-3",
29
+ lg: "ariadne-h-4",
30
+ }
31
+
32
+ renders_many :items, lambda { |tag: DEFAULT_TAGS[:item], classes: "", value: 0, attributes: {}|
33
+ Ariadne::BaseComponent.new(
34
+ tag: check_incoming_tag(DEFAULT_TAGS[:item], tag),
35
+ classes: merge_class_names(DEFAULT_CLASSES[:item], BAR_SIZES[@size], classes),
36
+ attributes: DEFAULT_ATTRIBUTES[:item].merge({
37
+ style: "width: #{(value - @min).to_f / (@max - @min) * 100}%",
38
+ "data-value": value,
39
+ }).merge(attributes),
40
+ )
41
+ }
42
+
43
+ # @example Default
44
+ #
45
+ # <%= render(Ariadne::ProgressBarComponent.new) { "Example" } %>
46
+ #
47
+ # @param tag [Symbol, String] The rendered tag name.
48
+ # @param classes [String] <%= link_to_classes_docs %>
49
+ # @param attributes [Hash] <%= link_to_attributes_docs %>
50
+ def initialize(tag: DEFAULT_TAGS[:wrapper], min: 0, max: 100, classes: "", size: :md, attributes: {})
51
+ @tag = check_incoming_tag(DEFAULT_TAGS[:wrapper], tag)
52
+ @classes = merge_class_names(DEFAULT_CLASSES[:wrapper], classes)
53
+
54
+ @min = min
55
+ @max = max
56
+ @size = size
57
+ @attributes = DEFAULT_ATTRIBUTES[:wrapper].merge({
58
+ "aria-valuemin": @min,
59
+ "aria-valuemax": @max,
60
+ }).merge(attributes)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,3 @@
1
+ <%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do |component| %>
2
+ <%= @formatted_date %>
3
+ <% end %>