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.
@@ -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
- # Setting this will turn the list into edit mode.
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
- # Setting this will enable title editing.
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
- # This can be used to implement "check all" and "uncheck all".
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
- string :align
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
- string :align
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
- string :distribution
499
- string :align
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
- string :align
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
- string :align
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
- string :strategy # can be "delegate" or "dropUpload"
10
+ enum :strategy, options: [:delegate, :dropUpload]
11
11
  string :storagePrefix
12
12
  hash :metadata
13
13
  string :tagging