proscenium 0.19.0.beta10-aarch64-linux → 0.19.0.beta11-aarch64-linux

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 (84) hide show
  1. checksums.yaml +4 -4
  2. data/lib/proscenium/bundled_gems.rb +1 -1
  3. data/lib/proscenium/css_module.rb +0 -5
  4. data/lib/proscenium/ext/proscenium +0 -0
  5. data/lib/proscenium/middleware.rb +0 -6
  6. data/lib/proscenium/phlex.rb +0 -6
  7. data/lib/proscenium/railtie.rb +0 -25
  8. data/lib/proscenium/resolver.rb +0 -9
  9. data/lib/proscenium/version.rb +1 -1
  10. data/lib/proscenium/view_component.rb +0 -6
  11. data/lib/proscenium.rb +5 -34
  12. metadata +24 -132
  13. data/lib/proscenium/registry/bundled_package.rb +0 -29
  14. data/lib/proscenium/registry/package.rb +0 -95
  15. data/lib/proscenium/registry/ruby_gem_package.rb +0 -30
  16. data/lib/proscenium/registry.rb +0 -29
  17. data/lib/proscenium/ruby_gems.rb +0 -67
  18. data/lib/proscenium/ui/breadcrumbs/component.module.css +0 -14
  19. data/lib/proscenium/ui/breadcrumbs/component.rb +0 -71
  20. data/lib/proscenium/ui/breadcrumbs/computed_element.rb +0 -69
  21. data/lib/proscenium/ui/breadcrumbs/control.rb +0 -95
  22. data/lib/proscenium/ui/breadcrumbs/mixins.css +0 -83
  23. data/lib/proscenium/ui/breadcrumbs.rb +0 -72
  24. data/lib/proscenium/ui/component.rb +0 -7
  25. data/lib/proscenium/ui/custom_element.js +0 -54
  26. data/lib/proscenium/ui/flash/bun.lock +0 -19
  27. data/lib/proscenium/ui/flash/index.css +0 -1
  28. data/lib/proscenium/ui/flash/index.js +0 -77
  29. data/lib/proscenium/ui/flash/node_modules/dom-mutations/index.d.ts +0 -33
  30. data/lib/proscenium/ui/flash/node_modules/dom-mutations/index.js +0 -44
  31. data/lib/proscenium/ui/flash/node_modules/dom-mutations/license +0 -9
  32. data/lib/proscenium/ui/flash/node_modules/dom-mutations/package.json +0 -59
  33. data/lib/proscenium/ui/flash/node_modules/dom-mutations/readme.md +0 -125
  34. data/lib/proscenium/ui/flash/node_modules/sourdough-toast/LICENSE +0 -20
  35. data/lib/proscenium/ui/flash/node_modules/sourdough-toast/README.md +0 -11
  36. data/lib/proscenium/ui/flash/node_modules/sourdough-toast/package.json +0 -44
  37. data/lib/proscenium/ui/flash/node_modules/sourdough-toast/src/sourdough-toast.css +0 -697
  38. data/lib/proscenium/ui/flash/node_modules/sourdough-toast/src/sourdough-toast.js +0 -537
  39. data/lib/proscenium/ui/flash/package.json +0 -11
  40. data/lib/proscenium/ui/flash.rb +0 -15
  41. data/lib/proscenium/ui/form/field_methods.rb +0 -88
  42. data/lib/proscenium/ui/form/fields/base.rb +0 -188
  43. data/lib/proscenium/ui/form/fields/checkbox/index.jsx +0 -48
  44. data/lib/proscenium/ui/form/fields/checkbox/index.module.css +0 -9
  45. data/lib/proscenium/ui/form/fields/checkbox/previews/basic.jsx +0 -8
  46. data/lib/proscenium/ui/form/fields/checkbox.rb +0 -32
  47. data/lib/proscenium/ui/form/fields/date.module.css +0 -27
  48. data/lib/proscenium/ui/form/fields/datetime.rb +0 -15
  49. data/lib/proscenium/ui/form/fields/hidden.rb +0 -9
  50. data/lib/proscenium/ui/form/fields/input/index.jsx +0 -71
  51. data/lib/proscenium/ui/form/fields/input/index.module.css +0 -13
  52. data/lib/proscenium/ui/form/fields/input/previews/basic.jsx +0 -8
  53. data/lib/proscenium/ui/form/fields/input.rb +0 -14
  54. data/lib/proscenium/ui/form/fields/radio_group.rb +0 -173
  55. data/lib/proscenium/ui/form/fields/radio_input/index.jsx +0 -44
  56. data/lib/proscenium/ui/form/fields/radio_input/index.module.css +0 -13
  57. data/lib/proscenium/ui/form/fields/radio_input/previews/basic.jsx +0 -8
  58. data/lib/proscenium/ui/form/fields/radio_input.rb +0 -17
  59. data/lib/proscenium/ui/form/fields/rich_textarea.css +0 -23
  60. data/lib/proscenium/ui/form/fields/rich_textarea.js +0 -6
  61. data/lib/proscenium/ui/form/fields/rich_textarea.rb +0 -18
  62. data/lib/proscenium/ui/form/fields/select.jsx +0 -47
  63. data/lib/proscenium/ui/form/fields/select.module.css +0 -46
  64. data/lib/proscenium/ui/form/fields/select.rb +0 -300
  65. data/lib/proscenium/ui/form/fields/tel.css +0 -297
  66. data/lib/proscenium/ui/form/fields/tel.js +0 -83
  67. data/lib/proscenium/ui/form/fields/tel.rb +0 -54
  68. data/lib/proscenium/ui/form/fields/textarea/index.jsx +0 -50
  69. data/lib/proscenium/ui/form/fields/textarea/index.module.css +0 -13
  70. data/lib/proscenium/ui/form/fields/textarea/previews/basic.jsx +0 -8
  71. data/lib/proscenium/ui/form/fields/textarea.rb +0 -18
  72. data/lib/proscenium/ui/form/translation.rb +0 -71
  73. data/lib/proscenium/ui/form.css +0 -52
  74. data/lib/proscenium/ui/form.rb +0 -211
  75. data/lib/proscenium/ui/props.css +0 -7
  76. data/lib/proscenium/ui/stimulus-loading.js +0 -65
  77. data/lib/proscenium/ui/test.js +0 -1
  78. data/lib/proscenium/ui/ujs/class.js +0 -15
  79. data/lib/proscenium/ui/ujs/data_confirm.js +0 -23
  80. data/lib/proscenium/ui/ujs/data_disable_with.js +0 -68
  81. data/lib/proscenium/ui/ujs/index.js +0 -9
  82. data/lib/proscenium/ui.rb +0 -11
  83. /data/lib/proscenium/{ui/react-manager → react-manager}/index.jsx +0 -0
  84. /data/lib/proscenium/{ui/react-manager → react-manager}/react.js +0 -0
@@ -1,537 +0,0 @@
1
- // vim: foldmethod=marker
2
-
3
- const DEFAULT_OPTIONS = {
4
- maxToasts: 3,
5
- duration: 4000,
6
- width: 356,
7
- gap: 14,
8
- theme: "light",
9
- viewportOffset: 32,
10
- expandedByDefault: false,
11
- yPosition: "bottom",
12
- xPosition: "right",
13
- };
14
-
15
- let toastsCounter = 0;
16
-
17
- // {{{ Helpers
18
- const SVG_NS = "http://www.w3.org/2000/svg";
19
-
20
- const svgTags = ["svg", "path", "line", "circle"];
21
-
22
- const h = (tag, props = {}, children = [], isSvg = false) => {
23
- const element =
24
- svgTags.includes(tag) || isSvg
25
- ? document.createElementNS(SVG_NS, tag)
26
- : document.createElement(tag);
27
-
28
- for (const [key, value] of Object.entries(props)) {
29
- if (key === "style") {
30
- if (typeof value === "string") {
31
- element.style = value;
32
- } else {
33
- for (const [k, v] of Object.entries(value)) {
34
- element.style.setProperty(k, v);
35
- }
36
- }
37
- } else if (key === "dataset") {
38
- for (const [k, v] of Object.entries(value)) {
39
- element.dataset[k] = v;
40
- }
41
- } else {
42
- element.setAttribute(key, value);
43
- }
44
- }
45
-
46
- for (const child of children) {
47
- if (typeof child === "string") {
48
- element.appendChild(document.createTextNode(child));
49
- continue;
50
- } else if (Array.isArray(child)) {
51
- for (const c of child) {
52
- element.appendChild(c);
53
- }
54
- continue;
55
- } else if (child instanceof HTMLElement || child instanceof SVGElement) {
56
- element.appendChild(child);
57
- }
58
- }
59
-
60
- return element;
61
- };
62
-
63
- const svgAttrs = {
64
- xmlns: "http://www.w3.org/2000/svg",
65
- viewBox: "0 0 24 24",
66
- height: "20",
67
- width: "20",
68
- fill: "none",
69
- stroke: "currentColor",
70
- "stroke-width": "1.5",
71
- "stroke-linecap": "round",
72
- "stroke-linejoin": "round",
73
- dataset: { slot: "icon" },
74
- };
75
-
76
- const icons = {
77
- success: h("svg", svgAttrs, [h("path", { d: "M20 6 9 17l-5-5" })]),
78
- info: h("svg", svgAttrs, [
79
- h("circle", { cx: "12", cy: "12", r: "10" }),
80
- h("path", { d: "M12 16v-4" }),
81
- h("path", { d: "M12 8h.01" }),
82
- ]),
83
- warning: h("svg", svgAttrs, [
84
- h("path", {
85
- d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",
86
- }),
87
- h("path", { d: "M12 9v4" }),
88
- h("path", { d: "M12 17h.01" }),
89
- ]),
90
- error: h("svg", svgAttrs, [
91
- h("circle", { cx: "12", cy: "12", r: "10" }),
92
- h("path", { d: "m4.9 4.9 14.2 14.2" }),
93
- ]),
94
- spinner: h(
95
- "svg",
96
- {
97
- ...svgAttrs,
98
- viewBox: "0 0 2400 2400",
99
- stroke: "black",
100
- "data-sourdough-spinner": "",
101
- "stroke-width": "200",
102
- "stroke-linecap": "round",
103
- },
104
- [
105
- h("line", { x1: "1200", y1: "600", x2: "1200", y2: "100" }),
106
- h("line", {
107
- opacity: "0.5",
108
- x1: "1200",
109
- y1: "2300",
110
- x2: "1200",
111
- y2: "1800",
112
- }),
113
- h("line", {
114
- opacity: "0.917",
115
- x1: "900",
116
- y1: "680.4",
117
- x2: "650",
118
- y2: "247.4",
119
- }),
120
- h("line", {
121
- opacity: "0.417",
122
- x1: "1750",
123
- y1: "2152.6",
124
- x2: "1500",
125
- y2: "1719.6",
126
- }),
127
- h("line", {
128
- opacity: "0.833",
129
- x1: "680.4",
130
- y1: "900",
131
- x2: "247.4",
132
- y2: "650",
133
- }),
134
- h("line", {
135
- opacity: "0.333",
136
- x1: "2152.6",
137
- y1: "1750",
138
- x2: "1719.6",
139
- y2: "1500",
140
- }),
141
- h("line", {
142
- opacity: "0.75",
143
- x1: "600",
144
- y1: "1200",
145
- x2: "100",
146
- y2: "1200",
147
- }),
148
- h("line", {
149
- opacity: "0.25",
150
- x1: "2300",
151
- y1: "1200",
152
- x2: "1800",
153
- y2: "1200",
154
- }),
155
- h("line", {
156
- opacity: "0.667",
157
- x1: "680.4",
158
- y1: "1500",
159
- x2: "247.4",
160
- y2: "1750",
161
- }),
162
- h("line", {
163
- opacity: "0.167",
164
- x1: "2152.6",
165
- y1: "650",
166
- x2: "1719.6",
167
- y2: "900",
168
- }),
169
- h("line", {
170
- opacity: "0.583",
171
- x1: "900",
172
- y1: "1719.6",
173
- x2: "650",
174
- y2: "2152.6",
175
- }),
176
- h("line", {
177
- opacity: "0.083",
178
- x1: "1750",
179
- y1: "247.4",
180
- x2: "1500",
181
- y2: "680.4",
182
- }),
183
- ],
184
- ),
185
- };
186
-
187
- function getDocumentDirection() {
188
- if (typeof window === "undefined") return "ltr";
189
-
190
- const dirAttribute = document.documentElement.getAttribute("dir");
191
-
192
- if (dirAttribute === "auto" || !dirAttribute) {
193
- return window.getComputedStyle(document.documentElement).direction;
194
- }
195
-
196
- return dirAttribute;
197
- }
198
- // }}}
199
-
200
- // {{{ class Store
201
- class Store extends EventTarget {
202
- #subscribers = [];
203
-
204
- constructor() {
205
- super();
206
-
207
- this.data = {
208
- toasts: [],
209
- expanded: false,
210
- interacting: false,
211
- };
212
- }
213
-
214
- subscribe = (fn) => {
215
- this.#subscribers.push(fn);
216
-
217
- return () => {
218
- this.#subscribers = this.#subscribers.filter((f) => f !== fn);
219
- };
220
- };
221
-
222
- #publish = () => {
223
- this.#subscribers.forEach((fn) => fn(this.data));
224
- };
225
-
226
- #set = (fn) => {
227
- const change = fn({ ...this.data });
228
- this.data = { ...this.data, ...change };
229
- this.#publish(this.data);
230
- };
231
-
232
- touch = () => {
233
- this.#publish();
234
- };
235
-
236
- create = (opts) => {
237
- const id = (toastsCounter++).toString();
238
- const toast = { id, ...opts };
239
-
240
- this.#set((data) => ({
241
- toasts: [...data.toasts, toast],
242
- }));
243
- };
244
-
245
- remove = (id) => {
246
- this.#set((data) => ({
247
- toasts: data.toasts.filter((t) => t.id !== id),
248
- }));
249
- };
250
-
251
- expand = () => {
252
- this.#set(() => ({ expanded: true }));
253
- };
254
-
255
- collapse = () => {
256
- this.#set(() => ({ expanded: false }));
257
- };
258
-
259
- focus = () => {
260
- this.#set(() => ({ interacting: true }));
261
- };
262
-
263
- blur = () => {
264
- this.#set(() => ({ interacting: false }));
265
- };
266
- } // }}}
267
-
268
- // {{{ class Toast
269
- class Toast {
270
- constructor(sourdough, opts = {}) {
271
- this.sourdough = sourdough;
272
- this.opts = opts;
273
-
274
- this.paused = false;
275
-
276
- const children = [];
277
-
278
- let icon = null;
279
- if (opts.type) {
280
- switch (opts.type) {
281
- case "success":
282
- icon = icons.success;
283
- break;
284
- case "info":
285
- icon = icons.info;
286
- break;
287
- case "warning":
288
- icon = icons.warning;
289
- break;
290
- case "error":
291
- icon = icons.error;
292
- break;
293
- }
294
- }
295
-
296
- if (icon) {
297
- children.push(
298
- h("div", { dataset: { icon: "" } }, [icon.cloneNode(true)]),
299
- );
300
- }
301
-
302
- const contentChildren = [];
303
-
304
- const title = h("div", { dataset: { title: "" } }, opts.title);
305
-
306
- contentChildren.push(title);
307
-
308
- if (opts.description) {
309
- const description = h(
310
- "div",
311
- { dataset: { description: "" } },
312
- opts.description,
313
- );
314
- contentChildren.push(description);
315
- }
316
-
317
- const content = h("div", { dataset: { content: "" } }, contentChildren);
318
-
319
- children.push(content);
320
-
321
- const li = h(
322
- "li",
323
- {
324
- dataset: {
325
- sourdoughToast: "",
326
- expanded: sourdough.opts.expanded,
327
- styled: true,
328
- swiping: false,
329
- swipeOut: false,
330
- type: opts.type,
331
- yPosition: sourdough.opts.yPosition,
332
- xPosition: sourdough.opts.xPosition,
333
- },
334
- style: {},
335
- },
336
- [children],
337
- );
338
-
339
- this.element = li;
340
- }
341
-
342
- mount = () => {
343
- this.element.dataset.mounted = "true";
344
-
345
- this.initialHeight = this.element.offsetHeight;
346
-
347
- state.touch();
348
-
349
- this.timeLeft = this.sourdough.opts.duration;
350
- this.resume();
351
- };
352
-
353
- remove = () => {
354
- this.element.dataset.removed = "true";
355
-
356
- setTimeout(() => {
357
- this.element.remove();
358
- state.remove(this.opts.id);
359
- }, 400);
360
- };
361
-
362
- pause = () => {
363
- this.paused = true;
364
- this.timeLeft = this.timeLeft - (Date.now() - this.startedAt);
365
- clearTimeout(this.timer);
366
- };
367
-
368
- resume = () => {
369
- this.paused = false;
370
- this.startedAt = Date.now();
371
- this.timer = setTimeout(this.remove, this.timeLeft);
372
- };
373
- }
374
- // }}}
375
-
376
- class Sourdough {
377
- constructor(opts = {}) {
378
- this.opts = Object.assign({}, DEFAULT_OPTIONS, opts);
379
-
380
- this.expanded = this.opts.expandedByDefault;
381
- if (this.opts.expandedByDefault) setTimeout(state.expand);
382
-
383
- // Cache rendered toasts by id
384
- this.renderedToastsById = {};
385
-
386
- this.list = h("ol", {
387
- dir: getDocumentDirection(),
388
- dataset: {
389
- sourdoughToaster: "",
390
- expanded: this.expanded,
391
- theme: this.opts.theme,
392
- richColors: this.opts.richColors,
393
- yPosition: this.opts.yPosition,
394
- xPosition: this.opts.xPosition,
395
- },
396
- style: {
397
- "--width": `${this.opts.width}px`,
398
- "--gap": `${this.opts.gap}px`,
399
- "--offset": `${this.opts.viewportOffset}px`,
400
- },
401
- });
402
-
403
- this.list.addEventListener("mouseenter", state.focus);
404
- this.list.addEventListener("mouseleave", state.blur);
405
-
406
- this.element = h(
407
- "div",
408
- {
409
- dataset: {
410
- sourdough: "",
411
- ...opts.dataset,
412
- },
413
- },
414
- [this.list],
415
- );
416
-
417
- this.subscription = state.subscribe(this.update.bind(this));
418
- }
419
-
420
- boot = () => {
421
- if (document.querySelector("[data-sourdough]")) {
422
- return;
423
- }
424
- document.body.appendChild(this.element);
425
- };
426
-
427
- update = (state) => {
428
- this.expanded = state.expanded || state.interacting;
429
- this.list.dataset.expanded = this.expanded;
430
-
431
- // Get first X toasts
432
- const toasts = state.toasts.slice(-this.opts.maxToasts);
433
-
434
- // Render and cache toasts that haven't been rendered yet
435
- const renderedIds = [];
436
- const toastsToRender = toasts.reduce((coll, t) => {
437
- renderedIds.push(t.id);
438
- coll.push(this.renderedToastsById[t.id] || this.createToast(t));
439
- return coll;
440
- }, []);
441
-
442
- // Uncache and remove toast elements that are not to be rendered
443
- Object.keys(this.renderedToastsById).forEach((id) => {
444
- if (!renderedIds.includes(id)) {
445
- this.renderedToastsById[id].element.remove();
446
- delete this.renderedToastsById[id];
447
- }
448
- });
449
-
450
- const front = toastsToRender[toastsToRender.length - 1];
451
-
452
- if (front) {
453
- this.list.style.setProperty(
454
- "--front-toast-height",
455
- `${front.element.offsetHeight}px`,
456
- );
457
- }
458
-
459
- for (const [index, t] of toastsToRender.entries()) {
460
- if (t.paused && !state.interacting) {
461
- t.resume();
462
- } else if (!t.paused && state.interacting) {
463
- t.pause();
464
- }
465
-
466
- t.element.dataset.index = index;
467
- t.element.dataset.front = t === front;
468
- t.element.dataset.expanded = this.expanded;
469
-
470
- t.element.style.setProperty("--index", index);
471
- t.element.style.setProperty(
472
- "--toasts-before",
473
- toastsToRender.length - index - 1,
474
- );
475
- t.element.style.setProperty("--z-index", index);
476
-
477
- t.element.style.setProperty(
478
- "--initial-height",
479
- this.expanded ? "auto" : `${t.initialHeight}px`,
480
- );
481
-
482
- // Calculate offset by adding all the heights of the toasts before
483
- // the current one + the gap between them.
484
- // Note: We're calculating the total height once per loop which is
485
- // not ideal.
486
- const [heightBefore, totalHeight] = toastsToRender.reduce(
487
- ([before, total], t, i) => {
488
- const boxHeight = t.initialHeight + this.opts.gap;
489
- if (i < index) before += boxHeight;
490
- total += boxHeight;
491
- return [before, total];
492
- },
493
- [0, 0],
494
- );
495
-
496
- const offset =
497
- totalHeight - heightBefore - t.initialHeight - this.opts.gap;
498
- t.element.style.setProperty(
499
- "--offset",
500
- `${t.element.dataset.removed ? "0" : offset || 0}px`,
501
- );
502
- }
503
- };
504
-
505
- createToast = (opts) => {
506
- const toast = new Toast(this, opts);
507
- this.renderedToastsById[opts.id] = toast;
508
- this.list.appendChild(toast.element);
509
-
510
- setTimeout(toast.mount, 0);
511
-
512
- return toast;
513
- };
514
- }
515
-
516
- const state = new Store();
517
-
518
- const toast = (title) => {
519
- state.create({ title });
520
- };
521
- toast.message = ({ title, description, ...opts }) => {
522
- state.create({ title, description, ...opts });
523
- };
524
- toast.success = (title, opts = {}) => {
525
- state.create({ title, type: "success", ...opts });
526
- };
527
- toast.info = (title, opts = {}) => {
528
- state.create({ title, type: "info", ...opts });
529
- };
530
- toast.warning = (title, opts = {}) => {
531
- state.create({ title, type: "warning", ...opts });
532
- };
533
- toast.error = (title, opts = {}) => {
534
- state.create({ title, type: "error", ...opts });
535
- };
536
-
537
- export { toast, Sourdough };
@@ -1,11 +0,0 @@
1
- {
2
- "name": "@proscenium/flash",
3
- "module": "index.js",
4
- "type": "module",
5
- "devDependencies": {
6
- "sourdough-toast": "latest"
7
- },
8
- "dependencies": {
9
- "dom-mutations": "^1.0.0"
10
- }
11
- }
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Proscenium::UI
4
- class Flash < Component
5
- register_element :pui_flash
6
-
7
- def self.source_path
8
- super / '../flash/index.rb'
9
- end
10
-
11
- def view_template
12
- pui_flash data: { flash: helpers.flash.to_hash }
13
- end
14
- end
15
- end
@@ -1,88 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Proscenium::UI::Form
4
- module FieldMethods
5
- # Renders a hidden input field.
6
- #
7
- # @param args [Array<Symbol>] name or nested names of model attribute
8
- # @param attributes [Hash] passed through to each input
9
- def hidden_field(*args, **)
10
- render Fields::Hidden.new(args, @model, self, **)
11
- end
12
-
13
- # @param args [Array<Symbol>] name or nested names of model attribute
14
- # @param attributes [Hash] passed through to each input
15
- def rich_textarea_field(*args, **attributes)
16
- merge_bang_attributes! args, attributes
17
- render Fields::RichTextarea.new(args, @model, self, **attributes)
18
- end
19
-
20
- # @param args [Array<Symbol>] name or nested names of model attribute
21
- # @param attributes [Hash] passed through to each input
22
- def datetime_local_field(*args, **attributes)
23
- merge_bang_attributes! args, attributes
24
- render Fields::Datetime.new(args, @model, self, **attributes)
25
- end
26
-
27
- # @param args [Array<Symbol>] name or nested names of model attribute
28
- # @param attributes [Hash] passed through to each input
29
- def checkbox_field(*args, **attributes)
30
- merge_bang_attributes! args, attributes
31
- render Fields::Checkbox.new(args, @model, self, **attributes)
32
- end
33
-
34
- # @param args [Array<Symbol>] name or nested names of model attribute
35
- # @param attributes [Hash] passed through to each input
36
- def tel_field(*args, **attributes)
37
- merge_bang_attributes! args, attributes
38
- render Fields::Tel.new(args, @model, self, **attributes)
39
- end
40
-
41
- # @param args [Array<Symbol>] name or nested names of model attribute
42
- # @param attributes [Hash] passed through to each input
43
- def select_field(*args, **attributes, &)
44
- merge_bang_attributes! args, attributes, additional_bang_attrs: [:typeahead]
45
- render Fields::Select.new(args, @model, self, **attributes, &)
46
- end
47
-
48
- # @see #select_field
49
- def select_country_field(*args, **attributes)
50
- merge_bang_attributes! args, attributes
51
- attributes[:typeahead] = true
52
- attributes[:options] = '/countries'
53
- attributes[:component_props] = {
54
- items_on_search: true,
55
- input_props: { required: attributes.delete(:required) }
56
- }
57
-
58
- select_field(*args, **attributes)
59
- end
60
-
61
- # Renders a <textarea> field for the given `attribute`.
62
- #
63
- # @param args [Array<Symbol>] name or nested names of model attribute
64
- # @param attributes [Hash] passed through to each input
65
- def textarea_field(*args, **attributes)
66
- merge_bang_attributes! args, attributes
67
- render Fields::Textarea.new(args, @model, self, **attributes)
68
- end
69
-
70
- # Renders a group of radio inputs for each option of the given `field`.
71
- #
72
- # @param args [Array<Symbol>] name or nested names of model attribute
73
- # @param attributes [Hash] passed through to each input
74
- def radio_group(*args, **attributes)
75
- attributes[:options] = args.pop if args.last.is_a?(Array)
76
-
77
- render Fields::RadioGroup.new(args, @model, self, **attributes)
78
- end
79
-
80
- def radio_field(...)
81
- div { radio_input(...) }
82
- end
83
-
84
- def radio_input(*args, **)
85
- render Fields::RadioInput.new(args, @model, self, **)
86
- end
87
- end
88
- end