glib-web 4.39.1 → 4.39.2
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.
- checksums.yaml +4 -4
- data/app/controllers/glib/api_docs_controller.rb +145 -0
- data/app/helpers/glib/json_ui/abstract_builder.rb +16 -0
- data/app/helpers/glib/json_ui/action_builder/dialogs.rb +4 -0
- data/app/helpers/glib/json_ui/list_builders.rb +2 -0
- data/app/helpers/glib/json_ui/view_builder/fields.rb +15 -0
- data/app/helpers/glib/json_ui/view_builder/panels.rb +450 -11
- data/app/helpers/glib/json_ui/view_builder.rb +1 -1
- data/app/views/glib/api_docs/component.json.jbuilder +215 -0
- data/app/views/glib/api_docs/index.json.jbuilder +103 -0
- data/app/views/glib/api_docs/show.json.jbuilder +111 -0
- data/app/views/json_ui/garage/lists/templating.json.jbuilder +68 -44
- data/app/views/json_ui/garage/views/markdowns.json.jbuilder +2 -0
- data/config/routes.rb +4 -0
- data/lib/glib/doc_generator.rb +386 -0
- data/lib/glib/rubocop/cops/test_name_parentheses.rb +33 -0
- data/lib/glib/rubocop.rb +1 -0
- data/lib/tasks/db.rake +1 -1
- data/lib/tasks/docs.rake +59 -0
- metadata +8 -1
|
@@ -2,16 +2,57 @@ require 'js_regex'
|
|
|
2
2
|
|
|
3
3
|
class Glib::JsonUi::ViewBuilder
|
|
4
4
|
module Panels
|
|
5
|
+
# Form panel for collecting user input and submitting data.
|
|
6
|
+
#
|
|
7
|
+
# A form panel automatically handles CSRF tokens, form validation, and data submission.
|
|
8
|
+
# It supports nested associations and dynamic field groups.
|
|
9
|
+
#
|
|
10
|
+
# @example Basic form with text field
|
|
11
|
+
# panel.panels_form url: users_path, method: :post do |form|
|
|
12
|
+
# form.fields_text prop: :name, label: 'Full Name'
|
|
13
|
+
# form.fields_email prop: :email
|
|
14
|
+
# form.fields_submit text: 'Create User'
|
|
15
|
+
# end
|
|
16
|
+
#
|
|
17
|
+
# @example Form with model binding
|
|
18
|
+
# panel.panels_form model: @user, autoValidate: true do |form|
|
|
19
|
+
# form.fields_text prop: :name # Automatically gets label from I18n
|
|
20
|
+
# form.fields_email prop: :email
|
|
21
|
+
# form.fields_submit text: 'Save'
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# @example Form with onChange callback
|
|
25
|
+
# panel.panels_form url: products_path, onChange: ->(action) do
|
|
26
|
+
# action.http_get url: preview_product_path, silent: true
|
|
27
|
+
# end do |form|
|
|
28
|
+
# form.fields_select prop: :category_id, options: @categories
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# @see https://guides.rubyonrails.org/form_helpers.html Rails Form Helpers
|
|
5
32
|
class Form < View
|
|
6
33
|
attr_reader :model_name # See Panels::Form.field_name
|
|
7
34
|
attr_reader :_autoValidate
|
|
8
35
|
attr_reader :disable_dirty_check
|
|
9
36
|
attr_accessor :current_dynamic_group
|
|
10
37
|
|
|
38
|
+
# Action called when form is submitted successfully.
|
|
39
|
+
# Receives form data and can trigger navigation, dialogs, etc.
|
|
11
40
|
action :onSubmit
|
|
41
|
+
|
|
42
|
+
# Action called whenever any form field value changes.
|
|
43
|
+
# Useful for real-time previews or dependent field updates.
|
|
12
44
|
action :onChange
|
|
45
|
+
|
|
46
|
+
# Similar to onChange but triggers a page reload with new data.
|
|
47
|
+
# Use this when field changes require server-side processing.
|
|
13
48
|
action :onChangeAndLoad
|
|
49
|
+
|
|
50
|
+
# Custom parameter name for form data when submitting.
|
|
51
|
+
# By default, uses the model name as the parameter namespace.
|
|
14
52
|
string :paramNameForFormData
|
|
53
|
+
|
|
54
|
+
# If true, form submission will not use AJAX (full page reload).
|
|
55
|
+
# Set to true for file downloads or when you need full page refresh.
|
|
15
56
|
bool :local
|
|
16
57
|
|
|
17
58
|
def autoValidate(autoValidate)
|
|
@@ -265,28 +306,87 @@ class Glib::JsonUi::ViewBuilder
|
|
|
265
306
|
end
|
|
266
307
|
end
|
|
267
308
|
|
|
309
|
+
# List panel for displaying scrollable collections of items.
|
|
310
|
+
#
|
|
311
|
+
# Lists can display data in various formats (cards, rows, etc.) with support for
|
|
312
|
+
# pagination, infinite scrolling, and drag-and-drop reordering.
|
|
313
|
+
#
|
|
314
|
+
# @example Basic list with items
|
|
315
|
+
# panel.panels_list width: 'matchParent', firstSection: ->(section) do
|
|
316
|
+
# section.header childViews: ->(header) do
|
|
317
|
+
# header.h2 text: 'Products'
|
|
318
|
+
# end
|
|
319
|
+
# @products.each do |product|
|
|
320
|
+
# section.row childViews: ->(row) do
|
|
321
|
+
# row.label text: product.name
|
|
322
|
+
# row.label text: product.price
|
|
323
|
+
# end
|
|
324
|
+
# end
|
|
325
|
+
# end
|
|
326
|
+
#
|
|
327
|
+
# @example List with pagination
|
|
328
|
+
# panel.panels_list \
|
|
329
|
+
# nextPage: { url: products_path(page: @page + 1) },
|
|
330
|
+
# prevPage: { url: products_path(page: @page - 1) },
|
|
331
|
+
# firstSection: ->(section) do
|
|
332
|
+
# # ... items
|
|
333
|
+
# end
|
|
334
|
+
#
|
|
335
|
+
# @example Responsive grid list
|
|
336
|
+
# panel.panels_list responsiveCols: 3, firstSection: ->(section) do
|
|
337
|
+
# @images.each do |image|
|
|
338
|
+
# section.row childViews: ->(row) do
|
|
339
|
+
# row.image url: image.url
|
|
340
|
+
# end
|
|
341
|
+
# end
|
|
342
|
+
# end
|
|
268
343
|
class List < View
|
|
269
|
-
#
|
|
344
|
+
# Prefix for field names when list is used in edit mode.
|
|
345
|
+
# Setting this turns the list into an editable collection.
|
|
270
346
|
string :fieldPrefix
|
|
271
347
|
|
|
272
|
-
#
|
|
348
|
+
# Field name for editable title in list items.
|
|
349
|
+
# Enables inline editing of item titles.
|
|
273
350
|
string :fieldTitleName
|
|
351
|
+
|
|
352
|
+
# Field name for editable subtitle in list items.
|
|
274
353
|
string :fieldSubtitleName
|
|
354
|
+
|
|
355
|
+
# Field name for editable sub-subtitle in list items.
|
|
275
356
|
string :fieldSubsubtitleName
|
|
276
357
|
|
|
277
|
-
#
|
|
278
|
-
# deprecated
|
|
358
|
+
# Conditional check values for "check all" / "uncheck all" functionality.
|
|
359
|
+
# @deprecated Use custom checkbox handling instead
|
|
279
360
|
hash :fieldCheckValueIf
|
|
280
361
|
|
|
362
|
+
# Phoenix WebSocket configuration for real-time updates.
|
|
281
363
|
hash :phoenixSocket
|
|
282
364
|
# hash :actionCable
|
|
283
365
|
|
|
366
|
+
# Configuration for next page in pagination.
|
|
367
|
+
# Provide a hash with :url key pointing to the next page.
|
|
368
|
+
# @example { url: products_path(page: @page + 1) }
|
|
284
369
|
hash :nextPage
|
|
370
|
+
|
|
371
|
+
# Configuration for previous page in pagination.
|
|
372
|
+
# Provide a hash with :url key pointing to the previous page.
|
|
285
373
|
hash :prevPage
|
|
374
|
+
|
|
375
|
+
# Action triggered when user scrolls to the top of the list.
|
|
376
|
+
# Useful for pull-to-refresh functionality.
|
|
286
377
|
action :onScrollToTop
|
|
378
|
+
|
|
379
|
+
# Action triggered when user scrolls to the bottom of the list.
|
|
380
|
+
# Useful for infinite scrolling / load more functionality.
|
|
287
381
|
action :onScrollToBottom
|
|
288
382
|
|
|
383
|
+
# Number of columns for responsive grid layout.
|
|
384
|
+
# Items will be arranged in a grid with this many columns.
|
|
385
|
+
# @example responsiveCols: 3
|
|
289
386
|
int :responsiveCols
|
|
387
|
+
|
|
388
|
+
# Configuration for drag-and-drop reordering support.
|
|
389
|
+
# @example dragSupport: { onDrop: { action: 'http/post', url: reorder_path } }
|
|
290
390
|
hash :dragSupport
|
|
291
391
|
|
|
292
392
|
def firstSection(block)
|
|
@@ -445,82 +545,421 @@ class Glib::JsonUi::ViewBuilder
|
|
|
445
545
|
end
|
|
446
546
|
end
|
|
447
547
|
|
|
548
|
+
# Scrollable container panel for content that exceeds viewport height.
|
|
549
|
+
#
|
|
550
|
+
# Scroll panels automatically add scrollbars when content overflows.
|
|
551
|
+
# This is the most common container for page content.
|
|
552
|
+
#
|
|
553
|
+
# @example Basic scrollable content
|
|
554
|
+
# page.scroll padding: glib_json_padding_body, childViews: ->(scroll) do
|
|
555
|
+
# scroll.h1 text: 'Welcome'
|
|
556
|
+
# scroll.p text: 'Long content here...'
|
|
557
|
+
# end
|
|
448
558
|
class Scroll < View
|
|
559
|
+
# Child components to display inside the scroll container.
|
|
560
|
+
# Provide a block that receives the view builder for adding content.
|
|
449
561
|
views :childViews
|
|
450
562
|
end
|
|
451
563
|
|
|
564
|
+
# Split panel for creating multi-column layouts with fixed side panels.
|
|
565
|
+
#
|
|
566
|
+
# Split panels divide the horizontal space into left, center, and right sections.
|
|
567
|
+
# The center section expands to fill available space, while side sections
|
|
568
|
+
# maintain their content width.
|
|
569
|
+
#
|
|
570
|
+
# @example Two-column layout
|
|
571
|
+
# panel.panels_split width: 'matchParent', content: ->(content) do
|
|
572
|
+
# content.left childViews: ->(left) do
|
|
573
|
+
# left.button text: 'Menu'
|
|
574
|
+
# end
|
|
575
|
+
# content.center childViews: ->(center) do
|
|
576
|
+
# center.h1 text: 'Main Content', width: 'matchParent'
|
|
577
|
+
# end
|
|
578
|
+
# end
|
|
579
|
+
#
|
|
580
|
+
# @example Three-column layout with alignment
|
|
581
|
+
# panel.panels_split width: 'matchParent', align: 'middle', content: ->(content) do
|
|
582
|
+
# content.left childViews: ->(left) do
|
|
583
|
+
# left.button text: 'Back'
|
|
584
|
+
# end
|
|
585
|
+
# content.center childViews: ->(center) do
|
|
586
|
+
# center.label text: 'Page Title'
|
|
587
|
+
# end
|
|
588
|
+
# content.right childViews: ->(right) do
|
|
589
|
+
# right.button text: 'Save'
|
|
590
|
+
# end
|
|
591
|
+
# end
|
|
592
|
+
#
|
|
593
|
+
# @see app/views/json_ui/garage/panels/split.json.jbuilder Garage examples
|
|
452
594
|
class Split < View
|
|
453
595
|
# def content(block)
|
|
454
596
|
# block.call page.split_content_builder
|
|
455
597
|
# end
|
|
456
|
-
|
|
598
|
+
|
|
599
|
+
# Vertical alignment of content within the split panel.
|
|
600
|
+
# Aligns items to top, middle, or bottom of the panel height.
|
|
601
|
+
# @example align: 'middle'
|
|
602
|
+
enum :align, options: [:top, :middle, :bottom]
|
|
603
|
+
|
|
604
|
+
# Content builder for defining left, center, and right sections.
|
|
605
|
+
# Use content.left, content.center, or content.right to define each section.
|
|
457
606
|
panels_builder :content, :left, :center, :right
|
|
458
607
|
end
|
|
459
608
|
|
|
609
|
+
# Responsive grid panel using Vuetify's 12-column grid system.
|
|
610
|
+
#
|
|
611
|
+
# Responsive panels automatically adjust layout based on screen size.
|
|
612
|
+
# Use panels_column children to define grid columns with breakpoint-specific sizing.
|
|
613
|
+
#
|
|
614
|
+
# @example Responsive two-column layout
|
|
615
|
+
# panel.panels_responsive width: 'matchParent', childViews: ->(responsive) do
|
|
616
|
+
# responsive.panels_column lg: { cols: 8 }, xs: { cols: 12 }, childViews: ->(col) do
|
|
617
|
+
# col.h1 text: 'Main Content'
|
|
618
|
+
# end
|
|
619
|
+
# responsive.panels_column lg: { cols: 4 }, xs: { cols: 12 }, childViews: ->(col) do
|
|
620
|
+
# col.h2 text: 'Sidebar'
|
|
621
|
+
# end
|
|
622
|
+
# end
|
|
623
|
+
#
|
|
624
|
+
# @example With hover effect
|
|
625
|
+
# panel.panels_responsive \
|
|
626
|
+
# styleClasses: ['card'],
|
|
627
|
+
# hoverViews: ->(hover) { hover.label text: 'Click me!' },
|
|
628
|
+
# onClick: ->(action) { action.windows_open url: product_path(@product) },
|
|
629
|
+
# childViews: ->(panel) do
|
|
630
|
+
# panel.h3 text: @product.name
|
|
631
|
+
# end
|
|
632
|
+
#
|
|
633
|
+
# @see https://vuetifyjs.com/en/components/grids/ Vuetify Grid Documentation
|
|
634
|
+
# @see app/views/json_ui/garage/panels/responsive.json.jbuilder Garage examples
|
|
460
635
|
class Responsive < View
|
|
636
|
+
# Child components to display in the responsive grid.
|
|
637
|
+
# Typically contains panels_column components.
|
|
461
638
|
views :childViews
|
|
462
|
-
|
|
639
|
+
|
|
640
|
+
# Horizontal alignment of child columns.
|
|
641
|
+
# @example align: 'center'
|
|
642
|
+
enum :align, options: [:left, :center, :right]
|
|
643
|
+
|
|
644
|
+
# Action triggered when the panel is clicked.
|
|
645
|
+
# Makes the entire responsive panel clickable.
|
|
463
646
|
action :onClick
|
|
647
|
+
|
|
648
|
+
# Views to display when hovering over the panel.
|
|
649
|
+
# Useful for showing tooltips or preview content on mouse hover.
|
|
464
650
|
views :hoverViews
|
|
465
651
|
|
|
466
|
-
# Experimental
|
|
652
|
+
# Experimental: Additional panel sections for complex layouts.
|
|
653
|
+
# @note These are experimental features
|
|
467
654
|
panels_builder :accessory, :header, :footer
|
|
468
655
|
end
|
|
469
656
|
|
|
657
|
+
# Grid column for use within panels_responsive containers.
|
|
658
|
+
#
|
|
659
|
+
# Columns use Vuetify's 12-column grid system where you specify how many columns
|
|
660
|
+
# (out of 12) this component should occupy at different breakpoints.
|
|
661
|
+
#
|
|
662
|
+
# Breakpoints (from smallest to largest):
|
|
663
|
+
# - xs: < 600px (mobile phones)
|
|
664
|
+
# - sm: 600px - 960px (tablets)
|
|
665
|
+
# - md: 960px - 1264px (small laptops)
|
|
666
|
+
# - lg: 1264px - 1904px (desktops)
|
|
667
|
+
# - xl: 1904px - 2560px (large desktops)
|
|
668
|
+
# - xxl: > 2560px (ultra-wide displays)
|
|
669
|
+
#
|
|
670
|
+
# @example Responsive column that changes width at different screen sizes
|
|
671
|
+
# responsive.panels_column \
|
|
672
|
+
# lg: { cols: 4 }, # 4/12 = 1/3 width on large screens
|
|
673
|
+
# md: { cols: 6 }, # 6/12 = 1/2 width on medium screens
|
|
674
|
+
# xs: { cols: 12 }, # 12/12 = full width on mobile
|
|
675
|
+
# childViews: ->(col) do
|
|
676
|
+
# col.h3 text: 'Card Title'
|
|
677
|
+
# end
|
|
678
|
+
#
|
|
679
|
+
# @example Column with responsive padding and ordering
|
|
680
|
+
# responsive.panels_column \
|
|
681
|
+
# lg: { cols: 8, order: 0, padding: { bottom: 0 } },
|
|
682
|
+
# xs: { cols: 12, order: 1, padding: { bottom: 20 } },
|
|
683
|
+
# childViews: ->(col) do
|
|
684
|
+
# col.label text: 'Content'
|
|
685
|
+
# end
|
|
686
|
+
#
|
|
687
|
+
# @see https://vuetifyjs.com/en/components/grids/ Vuetify Grid System
|
|
470
688
|
class Column < View
|
|
689
|
+
# Configuration for xxl breakpoint (> 2560px).
|
|
690
|
+
# @example xxl: { cols: 3, order: 0, padding: { all: 16 } }
|
|
471
691
|
hash :xxl
|
|
692
|
+
|
|
693
|
+
# Configuration for xl breakpoint (1904px - 2560px).
|
|
694
|
+
# @example xl: { cols: 4, hide: false }
|
|
472
695
|
hash :xl
|
|
696
|
+
|
|
697
|
+
# Configuration for lg breakpoint (1264px - 1904px).
|
|
698
|
+
# @example lg: { cols: 6, order: 1 }
|
|
473
699
|
hash :lg
|
|
700
|
+
|
|
701
|
+
# Configuration for md breakpoint (960px - 1264px).
|
|
702
|
+
# @example md: { cols: 8 }
|
|
474
703
|
hash :md
|
|
704
|
+
|
|
705
|
+
# Configuration for sm breakpoint (600px - 960px).
|
|
706
|
+
# @example sm: { cols: 12 }
|
|
475
707
|
hash :sm
|
|
708
|
+
|
|
709
|
+
# Configuration for xs breakpoint (< 600px).
|
|
710
|
+
# @example xs: { cols: 12, hide: false }
|
|
476
711
|
hash :xs
|
|
477
712
|
|
|
713
|
+
# Configuration that applies only at xxl breakpoint.
|
|
478
714
|
hash :xxlOnly
|
|
715
|
+
|
|
716
|
+
# Configuration that applies only at xl breakpoint.
|
|
479
717
|
hash :xlOnly
|
|
718
|
+
|
|
719
|
+
# Configuration that applies only at lg breakpoint.
|
|
480
720
|
hash :lgOnly
|
|
721
|
+
|
|
722
|
+
# Configuration that applies only at md breakpoint.
|
|
481
723
|
hash :mdOnly
|
|
724
|
+
|
|
725
|
+
# Configuration that applies only at sm breakpoint.
|
|
482
726
|
hash :smOnly
|
|
727
|
+
|
|
728
|
+
# Configuration that applies only at xs breakpoint.
|
|
483
729
|
hash :xsOnly
|
|
484
730
|
|
|
731
|
+
# Configuration for xxl and smaller breakpoints.
|
|
485
732
|
hash :xxlAndDown
|
|
733
|
+
|
|
734
|
+
# Configuration for xl and smaller breakpoints.
|
|
486
735
|
hash :xlAndDown
|
|
736
|
+
|
|
737
|
+
# Configuration for lg and smaller breakpoints.
|
|
487
738
|
hash :lgAndDown
|
|
739
|
+
|
|
740
|
+
# Configuration for md and smaller breakpoints.
|
|
741
|
+
# @example mdAndDown: { hide: true } # Hide on medium screens and below
|
|
488
742
|
hash :mdAndDown
|
|
743
|
+
|
|
744
|
+
# Configuration for sm and smaller breakpoints.
|
|
489
745
|
hash :smAndDown
|
|
746
|
+
|
|
747
|
+
# Configuration for xs breakpoint and below.
|
|
490
748
|
hash :xsAndDown
|
|
491
749
|
|
|
750
|
+
# Child components to display inside the column.
|
|
492
751
|
views :childViews
|
|
752
|
+
|
|
753
|
+
# Action triggered when the column is clicked.
|
|
493
754
|
action :onClick
|
|
494
755
|
end
|
|
495
756
|
|
|
757
|
+
# Vertical layout panel that stacks children vertically (top to bottom).
|
|
758
|
+
#
|
|
759
|
+
# Vertical panels use CSS flexbox with flex-direction: column.
|
|
760
|
+
# Children are arranged vertically and can be aligned or distributed in various ways.
|
|
761
|
+
#
|
|
762
|
+
# @example Basic vertical stacking
|
|
763
|
+
# panel.panels_vertical backgroundColor: '#f0f0f0', childViews: ->(vert) do
|
|
764
|
+
# vert.button text: 'Button 1'
|
|
765
|
+
# vert.button text: 'Button 2'
|
|
766
|
+
# vert.button text: 'Button 3'
|
|
767
|
+
# end
|
|
768
|
+
#
|
|
769
|
+
# @example Centered content with equal spacing
|
|
770
|
+
# panel.panels_vertical \
|
|
771
|
+
# width: 'matchParent',
|
|
772
|
+
# height: 300,
|
|
773
|
+
# distribution: 'spaceEqually',
|
|
774
|
+
# align: 'center',
|
|
775
|
+
# childViews: ->(vert) do
|
|
776
|
+
# vert.button text: 'Top'
|
|
777
|
+
# vert.button text: 'Middle'
|
|
778
|
+
# vert.button text: 'Bottom'
|
|
779
|
+
# end
|
|
780
|
+
#
|
|
781
|
+
# @example Clickable vertical panel
|
|
782
|
+
# panel.panels_vertical \
|
|
783
|
+
# styleClasses: ['card'],
|
|
784
|
+
# onClick: ->(action) { action.windows_open url: item_path(@item) },
|
|
785
|
+
# childViews: ->(vert) do
|
|
786
|
+
# vert.h3 text: @item.title
|
|
787
|
+
# vert.p text: @item.description
|
|
788
|
+
# end
|
|
789
|
+
#
|
|
790
|
+
# @see app/views/json_ui/garage/panels/vertical.json.jbuilder Garage examples
|
|
496
791
|
class Vertical < View
|
|
792
|
+
# Child components to stack vertically.
|
|
497
793
|
views :childViews
|
|
498
|
-
|
|
499
|
-
|
|
794
|
+
|
|
795
|
+
# How children should be distributed vertically.
|
|
796
|
+
# - 'fillEqually': Each child gets equal height
|
|
797
|
+
# - 'spaceEqually': Equal spacing between children
|
|
798
|
+
# @example distribution: 'fillEqually'
|
|
799
|
+
enum :distribution, options: [:fillEqually, :spaceEqually]
|
|
800
|
+
|
|
801
|
+
# Horizontal alignment of children.
|
|
802
|
+
# - 'left': Align to left edge
|
|
803
|
+
# - 'center': Center horizontally
|
|
804
|
+
# - 'right': Align to right edge
|
|
805
|
+
# @example align: 'center'
|
|
806
|
+
enum :align, options: [:left, :center, :right]
|
|
807
|
+
|
|
808
|
+
# Action triggered when the panel is clicked.
|
|
500
809
|
action :onClick
|
|
501
810
|
end
|
|
502
811
|
|
|
812
|
+
# Horizontal layout panel that arranges children side-by-side (left to right).
|
|
813
|
+
#
|
|
814
|
+
# Horizontal panels use CSS flexbox with flex-direction: row.
|
|
815
|
+
# Supports drag-and-drop reordering and various distribution modes.
|
|
816
|
+
#
|
|
817
|
+
# @example Basic horizontal layout
|
|
818
|
+
# panel.panels_horizontal backgroundColor: '#f0f0f0', childViews: ->(horiz) do
|
|
819
|
+
# horiz.button text: '1'
|
|
820
|
+
# horiz.button text: '2'
|
|
821
|
+
# horiz.button text: '3'
|
|
822
|
+
# end
|
|
823
|
+
#
|
|
824
|
+
# @example With equal spacing and alignment
|
|
825
|
+
# panel.panels_horizontal \
|
|
826
|
+
# width: 300,
|
|
827
|
+
# distribution: 'spaceEqually',
|
|
828
|
+
# align: 'middle',
|
|
829
|
+
# childViews: ->(horiz) do
|
|
830
|
+
# horiz.button text: 'Left'
|
|
831
|
+
# horiz.button text: 'Center'
|
|
832
|
+
# horiz.button text: 'Right'
|
|
833
|
+
# end
|
|
834
|
+
#
|
|
835
|
+
# @example With drag-and-drop reordering
|
|
836
|
+
# panel.panels_horizontal \
|
|
837
|
+
# width: 300,
|
|
838
|
+
# dragSupport: {
|
|
839
|
+
# onDrop: { action: 'http/post', url: reorder_items_path },
|
|
840
|
+
# paramNameForFormData: 'order_data'
|
|
841
|
+
# },
|
|
842
|
+
# childViews: ->(horiz) do
|
|
843
|
+
# @items.each do |item|
|
|
844
|
+
# horiz.button id: "item_#{item.id}", text: item.name
|
|
845
|
+
# end
|
|
846
|
+
# end
|
|
847
|
+
#
|
|
848
|
+
# @example With overlapping items (negative margins)
|
|
849
|
+
# panel.panels_horizontal \
|
|
850
|
+
# distribution: 'overlap-3', # 12px negative margin
|
|
851
|
+
# childViews: ->(horiz) do
|
|
852
|
+
# horiz.avatar url: user1.avatar_url
|
|
853
|
+
# horiz.avatar url: user2.avatar_url
|
|
854
|
+
# horiz.avatar url: user3.avatar_url
|
|
855
|
+
# end
|
|
856
|
+
#
|
|
857
|
+
# @see app/views/json_ui/garage/panels/horizontal.json.jbuilder Garage examples
|
|
858
|
+
# @see https://vuetifyjs.com/en/styles/spacing/ Material Design Spacing
|
|
503
859
|
class Horizontal < View
|
|
860
|
+
# Child components to arrange horizontally.
|
|
504
861
|
views :childViews
|
|
862
|
+
|
|
863
|
+
# How children should be distributed horizontally.
|
|
864
|
+
# - 'fillEqually': Each child gets equal width
|
|
865
|
+
# - 'spaceEqually': Equal spacing between children
|
|
866
|
+
# - 'overlap-N': Negative spacing (N from 1-8, e.g., 'overlap-3' = -12px margin)
|
|
867
|
+
# - 'space-N': Positive spacing (N from 1-8, e.g., 'space-2' = 8px margin)
|
|
868
|
+
# @example distribution: 'spaceEqually'
|
|
869
|
+
# @note Uses Material Design spacing scale (4px increments)
|
|
505
870
|
string :distribution
|
|
506
|
-
|
|
871
|
+
|
|
872
|
+
# Vertical alignment of children.
|
|
873
|
+
# - 'top': Align to top edge
|
|
874
|
+
# - 'middle': Center vertically
|
|
875
|
+
# - 'bottom': Align to bottom edge
|
|
876
|
+
# @example align: 'middle'
|
|
877
|
+
enum :align, options: [:top, :middle, :bottom]
|
|
878
|
+
|
|
879
|
+
# Action triggered when the panel is clicked.
|
|
507
880
|
action :onClick
|
|
881
|
+
|
|
882
|
+
# Configuration for drag-and-drop reordering support.
|
|
883
|
+
# Enables users to reorder children by dragging them.
|
|
884
|
+
# @example dragSupport: { onDrop: { action: 'http/post', url: reorder_path }, paramNameForFormData: 'order' }
|
|
508
885
|
hash :dragSupport, optional: [:onDrop, :paramNameForFormData, :paramNameForNewIndex]
|
|
509
886
|
end
|
|
510
887
|
|
|
888
|
+
# Flow layout panel that wraps children like text (left to right, then top to bottom).
|
|
889
|
+
#
|
|
890
|
+
# Flow panels use CSS flexbox with flex-wrap, creating a responsive grid-like layout
|
|
891
|
+
# where children wrap to the next line when they exceed container width.
|
|
892
|
+
# Supports responsive gap and padding for different screen sizes.
|
|
893
|
+
#
|
|
894
|
+
# @example Basic flow layout
|
|
895
|
+
# panel.panels_flow width: 300, innerPadding: { all: 10 }, childViews: ->(flow) do
|
|
896
|
+
# (1..10).each do |n|
|
|
897
|
+
# flow.button text: "Item #{n}"
|
|
898
|
+
# end
|
|
899
|
+
# end
|
|
900
|
+
#
|
|
901
|
+
# @example Responsive gaps and padding
|
|
902
|
+
# panel.panels_flow \
|
|
903
|
+
# width: 'matchParent',
|
|
904
|
+
# xs: { gap: { x: 4, y: 4 }, padding: { all: 8 } },
|
|
905
|
+
# md: { gap: { x: 16, y: 16 }, padding: { all: 24 } },
|
|
906
|
+
# lg: { gap: { all: 32 } },
|
|
907
|
+
# childViews: ->(flow) do
|
|
908
|
+
# @products.each do |product|
|
|
909
|
+
# flow.panels_vertical styleClasses: ['card'], childViews: ->(card) do
|
|
910
|
+
# card.image url: product.image_url
|
|
911
|
+
# card.h4 text: product.name
|
|
912
|
+
# end
|
|
913
|
+
# end
|
|
914
|
+
# end
|
|
915
|
+
#
|
|
916
|
+
# @example Tag cloud with inner padding
|
|
917
|
+
# panel.panels_flow \
|
|
918
|
+
# innerPadding: { x: 5, y: 5 },
|
|
919
|
+
# childViews: ->(flow) do
|
|
920
|
+
# @tags.each do |tag|
|
|
921
|
+
# flow.chip text: tag.name
|
|
922
|
+
# end
|
|
923
|
+
# end
|
|
924
|
+
#
|
|
925
|
+
# @see app/views/json_ui/garage/panels/flow.json.jbuilder Garage examples
|
|
511
926
|
class Flow < View
|
|
927
|
+
# Padding applied to each child element wrapper.
|
|
928
|
+
# Different from the panel's own padding - this creates gaps between items.
|
|
929
|
+
# @example innerPadding: { x: 10, y: 10 }
|
|
930
|
+
# @example innerPadding: { top: 5, right: 10, bottom: 5, left: 10 }
|
|
512
931
|
hash :innerPadding, optional: [:top, :right, :bottom, :left, :x, :y]
|
|
513
932
|
|
|
933
|
+
# Configuration for xxl breakpoint (> 2560px).
|
|
934
|
+
# @example xxl: { gap: { all: 32 }, padding: { all: 48 } }
|
|
514
935
|
hash :xxl, optional: [:gap, :padding]
|
|
936
|
+
|
|
937
|
+
# Configuration for xl breakpoint (1904px - 2560px).
|
|
938
|
+
# @example xl: { gap: { x: 24, y: 24 } }
|
|
515
939
|
hash :xl, optional: [:gap, :padding]
|
|
940
|
+
|
|
941
|
+
# Configuration for lg breakpoint (1264px - 1904px).
|
|
942
|
+
# @example lg: { gap: { all: 16 }, padding: { x: 30, y: 30 } }
|
|
516
943
|
hash :lg, optional: [:gap, :padding]
|
|
944
|
+
|
|
945
|
+
# Configuration for md breakpoint (960px - 1264px).
|
|
946
|
+
# @example md: { gap: { y: 8, x: 8 } }
|
|
517
947
|
hash :md, optional: [:gap, :padding]
|
|
948
|
+
|
|
949
|
+
# Configuration for sm breakpoint (600px - 960px).
|
|
950
|
+
# @example sm: { gap: { y: 4, x: 6 }, padding: { all: 16 } }
|
|
518
951
|
hash :sm, optional: [:gap, :padding]
|
|
952
|
+
|
|
953
|
+
# Configuration for xs breakpoint (< 600px).
|
|
954
|
+
# @example xs: { gap: { y: 2, x: 2 }, padding: { left: 10, bottom: 8 } }
|
|
519
955
|
hash :xs, optional: [:gap, :padding]
|
|
520
956
|
|
|
957
|
+
# Child components to arrange in flow layout.
|
|
521
958
|
views :childViews
|
|
522
959
|
|
|
523
|
-
|
|
960
|
+
# Vertical alignment of children within each row.
|
|
961
|
+
# @example align: 'middle'
|
|
962
|
+
enum :align, options: [:top, :middle, :bottom]
|
|
524
963
|
|
|
525
964
|
# required :innerPadding
|
|
526
965
|
end
|
|
@@ -7,7 +7,7 @@ module Glib
|
|
|
7
7
|
included do
|
|
8
8
|
string :directUploadUrl
|
|
9
9
|
hash :accepts, optional: [:fileType, :maxFileSize, :maxFileLength, :maxFileSizeErrorText, :maxFileLengthErrorText]
|
|
10
|
-
|
|
10
|
+
enum :strategy, options: [:delegate, :dropUpload]
|
|
11
11
|
string :storagePrefix
|
|
12
12
|
hash :metadata
|
|
13
13
|
string :tagging
|