@onetype/framework 2.0.53 → 2.0.54

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 (150) hide show
  1. package/addons/float/popup/css/popup.css +2 -2
  2. package/addons/render/directives/front/functions/process.js +3 -1
  3. package/addons/render/directives/front/items/self/160-slot.js +9 -1
  4. package/addons/render/editor/addon.js +13 -0
  5. package/addons/render/editor/functions/block/add.js +57 -0
  6. package/addons/render/editor/functions/block/delete.js +32 -0
  7. package/addons/render/editor/functions/block/find.js +30 -0
  8. package/addons/render/editor/functions/render/block.js +114 -0
  9. package/addons/render/editor/functions/render/blocks.js +31 -0
  10. package/addons/render/editor/items/elements/editor.js +69 -0
  11. package/addons/render/editor/items/self/paragraph.js +21 -0
  12. package/addons/render/editor/styles/editor.css +252 -0
  13. package/addons/render/elements/front/functions/types/colors/badge.js +19 -0
  14. package/addons/render/elements/front/functions/types/colors/status.js +24 -0
  15. package/addons/render/elements/front/functions/types/escape.js +8 -0
  16. package/addons/render/elements/front/functions/types/format/currency.js +16 -0
  17. package/addons/render/elements/front/functions/types/format/date.js +16 -0
  18. package/addons/render/elements/front/functions/types/format/number.js +24 -0
  19. package/addons/render/elements/front/functions/types/format/timeago.js +43 -0
  20. package/addons/render/elements/front/functions/types/render/avatar.js +10 -0
  21. package/addons/render/elements/front/functions/types/render/badge.js +17 -0
  22. package/addons/render/elements/front/functions/types/render/boolean.js +8 -0
  23. package/addons/render/elements/front/functions/types/render/chip.js +6 -0
  24. package/addons/render/elements/front/functions/types/render/currency.js +7 -0
  25. package/addons/render/elements/front/functions/types/render/date.js +6 -0
  26. package/addons/render/elements/front/functions/types/render/description.js +12 -0
  27. package/addons/render/elements/front/functions/types/render/group.js +11 -0
  28. package/addons/render/elements/front/functions/types/render/icon.js +8 -0
  29. package/addons/render/elements/front/functions/types/render/image.js +9 -0
  30. package/addons/render/elements/front/functions/types/render/link.js +8 -0
  31. package/addons/render/elements/front/functions/types/render/media.js +16 -0
  32. package/addons/render/elements/front/functions/types/render/metric.js +13 -0
  33. package/addons/render/elements/front/functions/types/render/number.js +6 -0
  34. package/addons/render/elements/front/functions/types/render/progress.js +13 -0
  35. package/addons/render/elements/front/functions/types/render/status.js +12 -0
  36. package/addons/render/elements/front/functions/types/render/tag.js +6 -0
  37. package/addons/render/elements/front/functions/types/render/tags.js +11 -0
  38. package/addons/render/elements/front/functions/types/render/text.js +8 -0
  39. package/addons/render/elements/front/functions/types/render/timeago.js +6 -0
  40. package/addons/render/elements/front/functions/types/render.js +16 -0
  41. package/addons/render/elements/front/items/directives/element.js +8 -3
  42. package/addons/render/elements/front/items/self/cards/info/info.css +499 -0
  43. package/addons/render/elements/front/items/self/cards/info/info.js +224 -0
  44. package/addons/render/elements/front/items/self/cards/item/item.css +614 -0
  45. package/addons/render/elements/front/items/self/cards/item/item.js +200 -0
  46. package/addons/render/elements/front/items/self/cards/pricing/pricing.css +318 -46
  47. package/addons/render/elements/front/items/self/cards/pricing/pricing.js +81 -30
  48. package/addons/render/elements/front/items/self/cards/profile/profile.css +446 -0
  49. package/addons/render/elements/front/items/self/cards/profile/profile.js +186 -0
  50. package/addons/render/elements/front/items/self/cards/share/share.css +445 -0
  51. package/addons/render/elements/front/items/self/cards/share/share.js +316 -0
  52. package/addons/render/elements/front/items/self/cards/stat/stat.css +356 -0
  53. package/addons/render/elements/front/items/self/cards/stat/stat.js +146 -0
  54. package/addons/render/elements/front/items/self/charts/bar/bar.css +263 -0
  55. package/addons/render/elements/front/items/self/charts/bar/bar.js +156 -0
  56. package/addons/render/elements/front/items/self/charts/donut/donut.css +222 -0
  57. package/addons/render/elements/front/items/self/charts/donut/donut.js +164 -0
  58. package/addons/render/elements/front/items/self/charts/line/line.css +229 -0
  59. package/addons/render/elements/front/items/self/charts/line/line.js +249 -0
  60. package/addons/render/elements/front/items/self/charts/sparkline/sparkline.css +102 -0
  61. package/addons/render/elements/front/items/self/charts/sparkline/sparkline.js +164 -0
  62. package/addons/render/elements/front/items/self/core/builder/builder.css +71 -116
  63. package/addons/render/elements/front/items/self/core/builder/builder.js +212 -127
  64. package/addons/render/elements/front/items/self/core/repeater/repeater.css +338 -71
  65. package/addons/render/elements/front/items/self/core/repeater/repeater.js +191 -44
  66. package/addons/render/elements/front/items/self/data/filters/filters.css +541 -0
  67. package/addons/render/elements/front/items/self/data/filters/filters.js +504 -0
  68. package/addons/render/elements/front/items/self/data/table/table.css +588 -0
  69. package/addons/render/elements/front/items/self/data/table/table.js +589 -0
  70. package/addons/render/elements/front/items/self/form/button/button.css +430 -103
  71. package/addons/render/elements/front/items/self/form/button/button.js +109 -101
  72. package/addons/render/elements/front/items/self/form/checkbox/checkbox.css +356 -39
  73. package/addons/render/elements/front/items/self/form/checkbox/checkbox.js +109 -75
  74. package/addons/render/elements/front/items/self/form/color/color.css +255 -61
  75. package/addons/render/elements/front/items/self/form/color/color.js +135 -41
  76. package/addons/render/elements/front/items/self/form/date/date.css +289 -38
  77. package/addons/render/elements/front/items/self/form/date/date.js +108 -24
  78. package/addons/render/elements/front/items/self/form/editor/editor.css +447 -0
  79. package/addons/render/elements/front/items/self/form/editor/editor.js +794 -0
  80. package/addons/render/elements/front/items/self/form/field/field.css +160 -29
  81. package/addons/render/elements/front/items/self/form/field/field.js +36 -16
  82. package/addons/render/elements/front/items/self/form/input/input.css +272 -32
  83. package/addons/render/elements/front/items/self/form/input/input.js +324 -124
  84. package/addons/render/elements/front/items/self/form/radio/radio.css +310 -45
  85. package/addons/render/elements/front/items/self/form/radio/radio.js +99 -80
  86. package/addons/render/elements/front/items/self/form/rating/rating.css +234 -57
  87. package/addons/render/elements/front/items/self/form/rating/rating.js +216 -86
  88. package/addons/render/elements/front/items/self/form/section/section.css +247 -32
  89. package/addons/render/elements/front/items/self/form/section/section.js +53 -16
  90. package/addons/render/elements/front/items/self/form/select/select.css +362 -64
  91. package/addons/render/elements/front/items/self/form/select/select.js +156 -30
  92. package/addons/render/elements/front/items/self/form/slider/slider.css +331 -123
  93. package/addons/render/elements/front/items/self/form/slider/slider.js +124 -26
  94. package/addons/render/elements/front/items/self/form/tags/tags.css +328 -53
  95. package/addons/render/elements/front/items/self/form/tags/tags.js +155 -28
  96. package/addons/render/elements/front/items/self/form/textarea/textarea.css +128 -27
  97. package/addons/render/elements/front/items/self/form/textarea/textarea.js +172 -113
  98. package/addons/render/elements/front/items/self/form/toggle/toggle.css +239 -39
  99. package/addons/render/elements/front/items/self/form/toggle/toggle.js +32 -17
  100. package/addons/render/elements/front/items/self/form/transfer/transfer.css +377 -0
  101. package/addons/render/elements/front/items/self/form/transfer/transfer.js +453 -0
  102. package/addons/render/elements/front/items/self/form/upload/upload.css +408 -0
  103. package/addons/render/elements/front/items/self/form/upload/upload.js +469 -0
  104. package/addons/render/elements/front/items/self/global/accordion/accordion.css +377 -0
  105. package/addons/render/elements/front/items/self/global/accordion/accordion.js +135 -0
  106. package/addons/render/elements/front/items/self/global/code/code.css +207 -44
  107. package/addons/render/elements/front/items/self/global/code/code.js +327 -19
  108. package/addons/render/elements/front/items/self/global/gallery/gallery.css +521 -0
  109. package/addons/render/elements/front/items/self/global/gallery/gallery.js +291 -0
  110. package/addons/render/elements/front/items/self/global/heading/heading.css +151 -49
  111. package/addons/render/elements/front/items/self/global/heading/heading.js +30 -15
  112. package/addons/render/elements/front/items/self/global/markdown/markdown.css +284 -135
  113. package/addons/render/elements/front/items/self/global/markdown/markdown.js +35 -5
  114. package/addons/render/elements/front/items/self/global/menu/menu.css +311 -56
  115. package/addons/render/elements/front/items/self/global/menu/menu.js +95 -47
  116. package/addons/render/elements/front/items/self/global/notice/notice.css +263 -23
  117. package/addons/render/elements/front/items/self/global/notice/notice.js +51 -11
  118. package/addons/render/elements/front/items/self/global/parameters/parameters.css +276 -33
  119. package/addons/render/elements/front/items/self/global/parameters/parameters.js +86 -16
  120. package/addons/render/elements/front/items/self/global/tags/tags.css +215 -29
  121. package/addons/render/elements/front/items/self/global/tags/tags.js +91 -17
  122. package/addons/render/elements/front/items/self/navigation/dock/dock.css +221 -0
  123. package/addons/render/elements/front/items/self/navigation/dock/dock.js +134 -0
  124. package/addons/render/elements/front/items/self/navigation/footer/footer.css +356 -0
  125. package/addons/render/elements/front/items/self/navigation/footer/footer.js +219 -0
  126. package/addons/render/elements/front/items/self/navigation/navbar/navbar.css +736 -76
  127. package/addons/render/elements/front/items/self/navigation/navbar/navbar.js +437 -29
  128. package/addons/render/elements/front/items/self/navigation/sidebar/sidebar.css +327 -196
  129. package/addons/render/elements/front/items/self/navigation/sidebar/sidebar.js +115 -62
  130. package/addons/render/elements/front/items/self/navigation/steps/steps.css +345 -0
  131. package/addons/render/elements/front/items/self/navigation/steps/steps.js +113 -0
  132. package/addons/render/elements/front/items/self/navigation/tabs/tabs.css +507 -33
  133. package/addons/render/elements/front/items/self/navigation/tabs/tabs.js +62 -19
  134. package/addons/render/elements/front/items/self/status/code/code.css +83 -12
  135. package/addons/render/elements/front/items/self/status/code/code.js +15 -4
  136. package/addons/render/elements/front/items/self/status/empty/empty.css +95 -15
  137. package/addons/render/elements/front/items/self/status/empty/empty.js +17 -12
  138. package/addons/render/elements/front/items/self/status/error/error.css +99 -14
  139. package/addons/render/elements/front/items/self/status/error/error.js +21 -11
  140. package/addons/render/elements/front/items/self/status/loading/loading.css +85 -14
  141. package/addons/render/elements/front/items/self/status/loading/loading.js +5 -6
  142. package/addons/render/elements/front/styles/types.css +363 -0
  143. package/instructions.txt +28 -0
  144. package/lib/load.js +1 -0
  145. package/lib/styles/reset.css +89 -76
  146. package/package.json +1 -1
  147. package/addons/render/elements/front/items/self/form/editor-markdown/editor-markdown.css +0 -410
  148. package/addons/render/elements/front/items/self/form/editor-markdown/editor-markdown.js +0 -191
  149. package/addons/render/elements/front/items/self/global/faq/faq.css +0 -98
  150. package/addons/render/elements/front/items/self/global/faq/faq.js +0 -56
@@ -13,168 +13,123 @@
13
13
  display: flex;
14
14
  flex-direction: column;
15
15
  width: 100%;
16
- border-radius: var(--ot-radius-m);
17
- border: 1px solid transparent;
16
+ gap: var(--ot-spacing-l);
18
17
  }
19
18
 
20
- /* Section */
21
-
22
- .e-7d599f7d > .holder > .section
19
+ .e-7d599f7d > .holder.has-steps
23
20
  {
24
- display: flex;
25
- flex-direction: column;
21
+ flex-direction: row;
22
+ align-items: flex-start;
26
23
  gap: var(--ot-spacing-m);
27
- padding: var(--ot-spacing-m) 0;
28
- }
29
-
30
- .e-7d599f7d > .holder > .section + .section
31
- {
32
- border-top: 1px solid var(--ot-bg-2-border);
33
- }
34
-
35
- .e-7d599f7d > .holder > .section:first-child
36
- {
37
- padding-top: 0 !important;
38
- }
39
-
40
- .e-7d599f7d > .holder > .section:last-child
41
- {
42
- padding-bottom: 0 !important;
43
- }
44
-
45
- /* Header */
46
-
47
- .e-7d599f7d > .holder > .section > .header
48
- {
49
- display: flex;
50
- align-items: center;
51
- justify-content: space-between;
52
- cursor: pointer;
53
- user-select: none;
54
- }
55
-
56
- .e-7d599f7d > .holder > .section > .header > .title
57
- {
58
- font-size: var(--ot-size-s);
59
- font-weight: 700;
60
- color: var(--ot-text-2);
61
- text-transform: uppercase;
62
- letter-spacing: 0.5px;
63
24
  }
64
25
 
65
- .e-7d599f7d > .holder > .section > .header > .chevron
66
- {
67
- font-size: 18px;
68
- color: var(--ot-text-2);
69
- opacity: 0.5;
70
- transition: transform 0.2s ease;
71
- }
26
+ /* Steps sidebar */
72
27
 
73
- .e-7d599f7d > .holder > .section > .header > .chevron.collapsed
28
+ .e-7d599f7d > .holder > .steps
74
29
  {
75
- transform: rotate(-90deg);
30
+ flex-shrink: 0;
31
+ width: 260px;
32
+ position: sticky;
33
+ top: var(--ot-spacing-m);
76
34
  }
77
35
 
78
- /* Fields */
36
+ /* Main column */
79
37
 
80
- .e-7d599f7d > .holder > .section > .fields
38
+ .e-7d599f7d > .holder > .main
81
39
  {
82
40
  display: flex;
83
41
  flex-direction: column;
84
- gap: var(--ot-spacing-m);
42
+ flex: 1;
43
+ min-width: 0;
44
+ gap: var(--ot-spacing-l);
85
45
  }
86
46
 
87
- /* Field top */
47
+ /* Sections stack */
88
48
 
89
- .e-7d599f7d > .holder > .section > .fields > .field.top
49
+ .e-7d599f7d > .holder > .main > .sections
90
50
  {
91
51
  display: flex;
92
52
  flex-direction: column;
93
- gap: 6px;
53
+ gap: var(--ot-spacing-l);
94
54
  }
95
55
 
96
- .e-7d599f7d > .holder > .section > .fields > .field.top > .info
56
+ .e-7d599f7d > .holder > .main > .sections > .step-panel
97
57
  {
98
58
  display: flex;
99
59
  flex-direction: column;
100
- gap: 2px;
60
+ gap: var(--ot-spacing-l);
101
61
  }
102
62
 
103
- /* Field left */
63
+ /* Grid of fields inside a section */
104
64
 
105
- .e-7d599f7d > .holder > .section > .fields > .field.left
65
+ .e-7d599f7d .grid
106
66
  {
107
- display: flex;
108
- align-items: center;
67
+ display: grid;
109
68
  gap: var(--ot-spacing-m);
110
- }
111
-
112
- .e-7d599f7d > .holder > .section > .fields > .field.left > .info
113
- {
114
- display: flex;
115
- flex-direction: column;
116
- flex: 1;
117
- gap: 2px;
118
- min-width: 0;
119
- }
120
-
121
- .e-7d599f7d > .holder > .section > .fields > .field.left > .control
122
- {
123
- flex: 2;
124
- min-width: 0;
125
- }
126
-
127
- /* Label */
128
-
129
- .e-7d599f7d > .holder .field > .label,
130
- .e-7d599f7d > .holder .field > .info > .label
131
- {
132
- font-size: var(--ot-size-s);
133
- font-weight: 600;
134
- color: var(--ot-text-1);
135
- }
136
-
137
- /* Description */
138
-
139
- .e-7d599f7d > .holder .field > .description,
140
- .e-7d599f7d > .holder .field > .info > .description
141
- {
142
- font-size: var(--ot-size-s);
143
- color: var(--ot-text-2);
144
- line-height: 1.4;
69
+ width: 100%;
145
70
  }
146
71
 
147
72
  /* Footer */
148
73
 
149
- .e-7d599f7d > .holder > .footer
74
+ .e-7d599f7d > .holder > .main > .footer
150
75
  {
151
76
  display: flex;
152
77
  justify-content: flex-end;
153
- padding-top: var(--ot-spacing-m);
154
- border-top: 1px solid var(--ot-bg-2-border);
155
78
  }
156
79
 
157
80
  /* Background variants */
158
81
 
159
- .e-7d599f7d > .holder.bg-1 { background: var(--ot-bg-1); padding: var(--ot-spacing-m); }
160
- .e-7d599f7d > .holder.bg-2 { background: var(--ot-bg-2); padding: var(--ot-spacing-m); }
161
- .e-7d599f7d > .holder.bg-3 { background: var(--ot-bg-3); padding: var(--ot-spacing-m); }
162
- .e-7d599f7d > .holder.bg-4 { background: var(--ot-bg-4); padding: var(--ot-spacing-m); }
82
+ .e-7d599f7d > .holder.bg-1 { background: var(--ot-bg-1); padding: var(--ot-spacing-l); border-radius: var(--ot-radius-m); }
83
+ .e-7d599f7d > .holder.bg-2 { background: var(--ot-bg-2); padding: var(--ot-spacing-l); border-radius: var(--ot-radius-m); }
84
+ .e-7d599f7d > .holder.bg-3 { background: var(--ot-bg-3); padding: var(--ot-spacing-l); border-radius: var(--ot-radius-m); }
85
+ .e-7d599f7d > .holder.bg-4 { background: var(--ot-bg-4); padding: var(--ot-spacing-l); border-radius: var(--ot-radius-m); }
163
86
 
164
87
  /* Border variant */
165
88
 
166
- .e-7d599f7d > .holder.border { border: 1px solid var(--ot-bg-2-border); padding: var(--ot-spacing-m); }
89
+ .e-7d599f7d > .holder.border
90
+ {
91
+ border: 1px solid var(--ot-bg-2-border);
92
+ padding: var(--ot-spacing-l);
93
+ border-radius: var(--ot-radius-m);
94
+ }
167
95
 
168
96
  /* Size variants */
169
97
 
170
- .e-7d599f7d > .holder.size-s > .section { gap: var(--ot-spacing-s); padding: var(--ot-spacing-s) 0; }
171
- .e-7d599f7d > .holder.size-s > .section > .fields { gap: var(--ot-spacing-s); }
172
- .e-7d599f7d > .holder.size-s > .footer { padding-top: var(--ot-spacing-s); }
98
+ .e-7d599f7d > .holder.size-s { gap: var(--ot-spacing-m); }
99
+ .e-7d599f7d > .holder.size-s > .main { gap: var(--ot-spacing-m); }
100
+ .e-7d599f7d > .holder.size-s > .main > .sections { gap: var(--ot-spacing-m); }
101
+ .e-7d599f7d > .holder.size-s > .main > .sections > .step-panel { gap: var(--ot-spacing-m); }
102
+ .e-7d599f7d > .holder.size-s .grid { gap: var(--ot-spacing-s); }
103
+
104
+ .e-7d599f7d > .holder.size-m { gap: var(--ot-spacing-l); }
105
+ .e-7d599f7d > .holder.size-m > .main { gap: var(--ot-spacing-l); }
106
+ .e-7d599f7d > .holder.size-m > .main > .sections { gap: var(--ot-spacing-l); }
107
+ .e-7d599f7d > .holder.size-m > .main > .sections > .step-panel { gap: var(--ot-spacing-l); }
108
+ .e-7d599f7d > .holder.size-m .grid { gap: var(--ot-spacing-m); }
173
109
 
174
- .e-7d599f7d > .holder.size-m > .section { gap: var(--ot-spacing-m); padding: var(--ot-spacing-m) 0; }
175
- .e-7d599f7d > .holder.size-m > .section > .fields { gap: var(--ot-spacing-m); }
176
- .e-7d599f7d > .holder.size-m > .footer { padding-top: var(--ot-spacing-m); }
110
+ .e-7d599f7d > .holder.size-l { gap: var(--ot-spacing-l); }
111
+ .e-7d599f7d > .holder.size-l > .main { gap: var(--ot-spacing-l); }
112
+ .e-7d599f7d > .holder.size-l > .main > .sections { gap: var(--ot-spacing-l); }
113
+ .e-7d599f7d > .holder.size-l > .main > .sections > .step-panel { gap: var(--ot-spacing-l); }
114
+ .e-7d599f7d > .holder.size-l .grid { gap: var(--ot-spacing-l); }
177
115
 
178
- .e-7d599f7d > .holder.size-l > .section { gap: var(--ot-spacing-l); padding: var(--ot-spacing-l) 0; }
179
- .e-7d599f7d > .holder.size-l > .section > .fields { gap: var(--ot-spacing-l); }
180
- .e-7d599f7d > .holder.size-l > .footer { padding-top: var(--ot-spacing-l); }
116
+ /* Responsive collapse steps sidebar and grid on small screens */
117
+
118
+ @media (max-width: 900px)
119
+ {
120
+ .e-7d599f7d > .holder.has-steps
121
+ {
122
+ flex-direction: column;
123
+ }
124
+
125
+ .e-7d599f7d > .holder > .steps
126
+ {
127
+ width: 100%;
128
+ position: static;
129
+ }
130
+
131
+ .e-7d599f7d .grid
132
+ {
133
+ grid-template-columns: 1fr !important;
134
+ }
135
+ }
@@ -4,7 +4,7 @@ onetype.AddonReady('elements', (elements) =>
4
4
  id: 'core-builder',
5
5
  icon: 'dashboard_customize',
6
6
  name: 'Builder',
7
- description: 'Config-driven form builder with sections, conditions, and any element.',
7
+ description: 'Config-driven form builder with steps, sections, grid columns, conditions and reusable form-section / form-field elements.',
8
8
  category: 'Core',
9
9
  author: 'OneType',
10
10
  config: {
@@ -12,46 +12,41 @@ onetype.AddonReady('elements', (elements) =>
12
12
  type: 'object',
13
13
  value: {}
14
14
  },
15
- sections: {
15
+ steps: {
16
16
  type: 'array',
17
17
  value: [],
18
18
  each: {
19
19
  type: 'object',
20
20
  config: {
21
- title: { type: 'string', value: '' },
22
- collapsed: { type: 'boolean', value: false },
23
- condition: { type: 'function' },
24
- fields: {
25
- type: 'array',
26
- value: [],
27
- each: {
28
- type: 'object',
29
- config: {
30
- key: { type: 'string', value: '' },
31
- label: { type: 'string', value: '' },
32
- description: { type: 'string', value: '' },
33
- position: { type: 'string', value: 'top' },
34
- element: { type: 'string', value: '' },
35
- properties: { type: 'object', value: {} },
36
- condition: { type: 'function' }
37
- }
38
- }
39
- }
21
+ id: { type: 'string' },
22
+ label: { type: 'string' },
23
+ description: { type: 'string' },
24
+ icon: { type: 'string' },
25
+ sections: { type: 'array', value: [] }
40
26
  }
41
27
  }
42
28
  },
29
+ sections: {
30
+ type: 'array',
31
+ value: [],
32
+ each: {
33
+ type: 'object'
34
+ }
35
+ },
43
36
  save: {
44
- type: 'string',
45
- value: ''
37
+ type: 'string'
38
+ },
39
+ saveVariant: {
40
+ type: 'array',
41
+ value: ['brand', 'size-m']
46
42
  },
47
43
  disabled: {
48
- type: 'boolean',
49
- value: false
44
+ type: 'boolean'
50
45
  },
51
46
  variant: {
52
47
  type: 'array',
53
48
  value: ['size-m'],
54
- options: ['bg-1', 'bg-2', 'bg-3', 'bg-4', 'border', 'size-s', 'size-m', 'size-l']
49
+ options: ['bg-1', 'bg-2', 'bg-3', 'bg-4', 'border', 'clean', 'size-s', 'size-m', 'size-l']
55
50
  },
56
51
  _input: {
57
52
  type: 'function'
@@ -65,23 +60,73 @@ onetype.AddonReady('elements', (elements) =>
65
60
  },
66
61
  render: function()
67
62
  {
68
- // State
63
+ // Step state
64
+
65
+ this.hasSteps = this.steps.length > 0;
66
+ this.activeStep = this.hasSteps ? this.steps[0].id : '';
69
67
 
70
- this.collapsed = {};
68
+ // Current sections depend on step or flat sections
71
69
 
72
- this.sections.forEach((section, index) =>
70
+ this.currentSections = () =>
73
71
  {
74
- if (section.collapsed)
72
+ if(this.hasSteps)
73
+ {
74
+ const step = this.steps.find(s => s.id === this.activeStep) || this.steps[0];
75
+ return step.sections || [];
76
+ }
77
+
78
+ return this.sections;
79
+ };
80
+
81
+ // Detect conditions — if any exist we re-render on change
82
+
83
+ this.hasConditions = (() =>
84
+ {
85
+ const scan = (sections) =>
86
+ {
87
+ for(const section of sections)
88
+ {
89
+ if(section.condition)
90
+ {
91
+ return true;
92
+ }
93
+
94
+ if(section.fields)
95
+ {
96
+ for(const field of section.fields)
97
+ {
98
+ if(field.condition)
99
+ {
100
+ return true;
101
+ }
102
+ }
103
+ }
104
+ }
105
+
106
+ return false;
107
+ };
108
+
109
+ if(this.hasSteps)
75
110
  {
76
- this.collapsed[index] = true;
111
+ for(const step of this.steps)
112
+ {
113
+ if(scan(step.sections || []))
114
+ {
115
+ return true;
116
+ }
117
+ }
118
+
119
+ return false;
77
120
  }
78
- });
121
+
122
+ return scan(this.sections);
123
+ })();
79
124
 
80
125
  // Helpers
81
126
 
82
127
  this.visible = (condition) =>
83
128
  {
84
- if (!condition)
129
+ if(!condition)
85
130
  {
86
131
  return true;
87
132
  }
@@ -91,7 +136,7 @@ onetype.AddonReady('elements', (elements) =>
91
136
 
92
137
  this.val = (key) =>
93
138
  {
94
- if (!this.values)
139
+ if(!this.values)
95
140
  {
96
141
  return null;
97
142
  }
@@ -101,18 +146,21 @@ onetype.AddonReady('elements', (elements) =>
101
146
 
102
147
  // Actions
103
148
 
104
- this.toggle = (index) =>
149
+ this.selectStep = ({ value }) =>
105
150
  {
106
- this.collapsed[index] = !this.collapsed[index];
107
- this.Update();
151
+ this.activeStep = value;
108
152
  };
109
153
 
110
154
  this.input = (key, data) =>
111
155
  {
112
156
  this.values[key] = data.value;
113
- this.Update();
114
157
 
115
- if (this._input)
158
+ if(this.hasConditions)
159
+ {
160
+ this.Update();
161
+ }
162
+
163
+ if(this._input)
116
164
  {
117
165
  this._input({ key, value: data.value });
118
166
  }
@@ -121,9 +169,13 @@ onetype.AddonReady('elements', (elements) =>
121
169
  this.change = (key, data) =>
122
170
  {
123
171
  this.values[key] = data.value;
124
- this.Update();
125
172
 
126
- if (this._change)
173
+ if(this.hasConditions)
174
+ {
175
+ this.Update();
176
+ }
177
+
178
+ if(this._change)
127
179
  {
128
180
  this._change({ key, value: data.value });
129
181
  }
@@ -131,124 +183,157 @@ onetype.AddonReady('elements', (elements) =>
131
183
 
132
184
  this.submit = () =>
133
185
  {
134
- if (this._save)
186
+ if(this._save)
135
187
  {
136
188
  this._save({ value: this.values });
137
189
  }
138
190
  };
139
191
 
140
- // Build sections
192
+ // Escape attr value safely
141
193
 
142
- const html = this.sections.map((section, sectionIndex) =>
194
+ const escape = (value) =>
143
195
  {
144
- // Section condition
145
-
146
- const sectionCondition = section.condition
147
- ? `ot-if="visible(sections[${sectionIndex}].condition)"`
148
- : '';
196
+ return String(value).replace(/&/g, '&amp;').replace(/'/g, '&#39;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
197
+ };
149
198
 
150
- // Section header
199
+ // Build field element tag with properties
151
200
 
152
- const header = section.title
153
- ? `
154
- <div class="header" ot-click="() => toggle(${sectionIndex})">
155
- <span class="title">{{ sections[${sectionIndex}].title }}</span>
156
- <i :class="'chevron' + (collapsed[${sectionIndex}] ? ' collapsed' : '')">expand_more</i>
157
- </div>
158
- `
159
- : '';
201
+ const buildField = (field, sectionIndex, fieldIndex, scope) =>
202
+ {
203
+ const tag = 'e-' + field.element;
204
+ const props = field.properties || {};
205
+ const span = field.span || 1;
160
206
 
161
- // Fields
207
+ let attrs = '';
162
208
 
163
- const fields = section.fields.map((field, fieldIndex) =>
209
+ Object.keys(props).forEach((key) =>
164
210
  {
165
- const tag = 'e-' + field.element;
166
- const props = field.properties || {};
167
- const position = field.position || 'top';
168
-
169
- // Build properties attributes
170
-
171
- let attrs = '';
211
+ const value = props[key];
172
212
 
173
- Object.keys(props).forEach((key) =>
213
+ if(typeof value === 'string')
214
+ {
215
+ attrs += ` ${key}="${escape(value)}"`;
216
+ }
217
+ else
174
218
  {
175
- const val = props[key];
219
+ attrs += ` :${key}='${escape(JSON.stringify(value))}'`;
220
+ }
221
+ });
222
+
223
+ const input = `
224
+ <${tag}
225
+ :value="val('${field.key}')"
226
+ :_input="(data) => input('${field.key}', data)"
227
+ :_change="(data) => change('${field.key}', data)"
228
+ ${attrs}
229
+ ></${tag}>
230
+ `;
176
231
 
177
- if (typeof val === 'string')
178
- {
179
- attrs += ` ${key}="${val}"`;
180
- }
181
- else
182
- {
183
- attrs += ` :${key}='${JSON.stringify(val)}'`;
184
- }
185
- });
232
+ const fieldCondition = field.condition
233
+ ? `ot-if="visible(${scope}[${sectionIndex}].fields[${fieldIndex}].condition)"`
234
+ : '';
186
235
 
187
- // Element tag
236
+ const fieldVariant = field.variant ? JSON.stringify(field.variant) : JSON.stringify(['size-m']);
188
237
 
189
- const element = `<${tag} :value="val('${field.key}')" :_input="(data) => input('${field.key}', data)" :_change="(data) => change('${field.key}', data)"${attrs}></${tag}>`;
238
+ return `
239
+ <e-form-field
240
+ ${fieldCondition}
241
+ #class="field"
242
+ #style="grid-column: span ${span};"
243
+ label="${escape(field.label || '')}"
244
+ description="${escape(field.description || '')}"
245
+ hint="${escape(field.hint || '')}"
246
+ :required="${field.required ? 'true' : 'false'}"
247
+ orientation="${field.orientation || 'horizontal'}"
248
+ :variant='${escape(fieldVariant)}'
249
+ >
250
+ <div slot="input">
251
+ ${input}
252
+ </div>
253
+ </e-form-field>
254
+ `;
255
+ };
190
256
 
191
- // Label
257
+ // Build a single section
192
258
 
193
- const label = field.label
194
- ? `<span class="label">{{ sections[${sectionIndex}].fields[${fieldIndex}].label }}</span>`
195
- : '';
259
+ const buildSection = (section, sectionIndex, scope) =>
260
+ {
261
+ const columns = section.columns || 1;
262
+ const sectionFields = section.fields || [];
263
+ const fields = sectionFields.map((field, fieldIndex) => buildField(field, sectionIndex, fieldIndex, scope)).join('');
196
264
 
197
- // Description
265
+ const sectionCondition = section.condition
266
+ ? `ot-if="visible(${scope}[${sectionIndex}].condition)"`
267
+ : '';
198
268
 
199
- const description = field.description
200
- ? `<span class="description">{{ sections[${sectionIndex}].fields[${fieldIndex}].description }}</span>`
201
- : '';
269
+ const sectionVariant = section.variant ? JSON.stringify(section.variant) : JSON.stringify(['clean']);
202
270
 
203
- // Field condition
271
+ return `
272
+ <e-form-section
273
+ ${sectionCondition}
274
+ eyebrow="${escape(section.eyebrow || '')}"
275
+ icon="${escape(section.icon || '')}"
276
+ title="${escape(section.title || '')}"
277
+ description="${escape(section.description || '')}"
278
+ :collapsible="${section.collapsible ? 'true' : 'false'}"
279
+ :collapsed="${section.collapsed ? 'true' : 'false'}"
280
+ :variant='${escape(sectionVariant)}'
281
+ >
282
+ <div slot="content">
283
+ <div class="grid" style="grid-template-columns: repeat(${columns}, minmax(0, 1fr));">
284
+ ${fields}
285
+ </div>
286
+ </div>
287
+ </e-form-section>
288
+ `;
289
+ };
204
290
 
205
- const fieldCondition = field.condition
206
- ? `ot-if="visible(sections[${sectionIndex}].fields[${fieldIndex}].condition)"`
207
- : '';
291
+ // Build all sections for current step (or flat)
208
292
 
209
- // Position layout
293
+ let sectionsHtml = '';
210
294
 
211
- if (position === 'left')
212
- {
213
- return `
214
- <div class="field left" ${fieldCondition}>
215
- <div class="info">
216
- ${label}
217
- ${description}
218
- </div>
219
- <div class="control">
220
- ${element}
221
- </div>
222
- </div>
223
- `;
224
- }
295
+ if(this.hasSteps)
296
+ {
297
+ sectionsHtml = this.steps.map((step, stepIndex) =>
298
+ {
299
+ const sections = (step.sections || []).map((section, sectionIndex) => buildSection(section, sectionIndex, `steps[${stepIndex}].sections`)).join('');
225
300
 
226
301
  return `
227
- <div class="field top" ${fieldCondition}>
228
- <div class="info">
229
- ${label}
230
- ${description}
231
- </div>
232
- ${element}
302
+ <div ot-if="activeStep === '${step.id}'" class="step-panel">
303
+ ${sections}
233
304
  </div>
234
305
  `;
235
306
  }).join('');
307
+ }
308
+ else
309
+ {
310
+ sectionsHtml = this.sections.map((section, sectionIndex) => buildSection(section, sectionIndex, 'sections')).join('');
311
+ }
236
312
 
237
- return `
238
- <div class="section" ${sectionCondition}>
239
- ${header}
240
- <div ot-if="!collapsed[${sectionIndex}]" class="fields">
241
- ${fields}
313
+ return /* html */ `
314
+ <div :class="'holder ' + variant.join(' ') + (hasSteps ? ' has-steps' : '')">
315
+ <e-navigation-steps
316
+ ot-if="hasSteps"
317
+ #class="steps"
318
+ :items="steps"
319
+ :active="activeStep"
320
+ orientation="vertical"
321
+ :variant="['bg-1', 'border', 'connected', 'size-m']"
322
+ :_change="selectStep"
323
+ ></e-navigation-steps>
324
+
325
+ <div class="main">
326
+ <div class="sections">
327
+ ${sectionsHtml}
328
+ </div>
329
+ <div ot-if="save" class="footer">
330
+ <e-form-button
331
+ :text="save"
332
+ :_click="submit"
333
+ :disabled="disabled"
334
+ :variant="saveVariant"
335
+ ></e-form-button>
242
336
  </div>
243
- </div>
244
- `;
245
- }).join('');
246
-
247
- return `
248
- <div :class="'holder ' + variant.join(' ')">
249
- ${html}
250
- <div ot-if="save" class="footer">
251
- <e-form-button :text="save" :_click="submit" :disabled="disabled" :variant="['brand', 'size-s']"></e-form-button>
252
337
  </div>
253
338
  </div>
254
339
  `;