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,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 %>