active_element 0.0.11 → 0.0.13

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/Gemfile +2 -1
  4. data/Gemfile.lock +10 -3
  5. data/app/assets/javascripts/active_element/highlight.js +311 -0
  6. data/app/assets/javascripts/active_element/json_field.js +51 -20
  7. data/app/assets/javascripts/active_element/popover.js +6 -4
  8. data/app/assets/javascripts/active_element/text_search_field.js +13 -1
  9. data/app/assets/stylesheets/active_element/_dark.scss +1 -1
  10. data/app/assets/stylesheets/active_element/application.scss +39 -1
  11. data/app/controllers/concerns/active_element/default_controller_actions.rb +7 -7
  12. data/app/views/active_element/components/fields/_json.html.erb +3 -2
  13. data/app/views/active_element/components/form/_field.html.erb +2 -1
  14. data/app/views/active_element/components/form/_json.html.erb +2 -0
  15. data/app/views/active_element/components/form/_label.html.erb +8 -1
  16. data/app/views/active_element/components/form/_templates.html.erb +8 -5
  17. data/app/views/active_element/components/form/_text_search.html.erb +1 -1
  18. data/app/views/active_element/components/form.html.erb +2 -2
  19. data/app/views/active_element/components/table/_field.html.erb +1 -1
  20. data/app/views/active_element/components/table/_ungrouped_collection.html.erb +1 -0
  21. data/app/views/active_element/components/table/item.html.erb +1 -0
  22. data/app/views/active_element/default_views/edit.html.erb +2 -2
  23. data/app/views/active_element/default_views/forbidden.html.erb +7 -0
  24. data/app/views/active_element/default_views/index.html.erb +7 -7
  25. data/app/views/active_element/default_views/new.html.erb +1 -1
  26. data/app/views/active_element/default_views/show.html.erb +3 -3
  27. data/app/views/layouts/active_element.html.erb +25 -4
  28. data/config/locales/en.yml +3 -0
  29. data/example_app/Gemfile.lock +1 -1
  30. data/example_app/app/controllers/pets_controller.rb +1 -0
  31. data/example_app/app/controllers/users_controller.rb +1 -0
  32. data/lib/active_element/components/form.rb +1 -8
  33. data/lib/active_element/components/text_search.rb +10 -1
  34. data/lib/active_element/components/util/display_value_mapping.rb +0 -2
  35. data/lib/active_element/components/util/form_field_mapping.rb +23 -10
  36. data/lib/active_element/components/util/numeric_field.rb +73 -0
  37. data/lib/active_element/components/util.rb +8 -0
  38. data/lib/active_element/controller_interface.rb +27 -30
  39. data/lib/active_element/controller_state.rb +44 -0
  40. data/lib/active_element/default_controller/actions.rb +3 -0
  41. data/lib/active_element/default_controller/controller.rb +145 -0
  42. data/lib/active_element/default_controller/json_params.rb +48 -0
  43. data/lib/active_element/default_controller/params.rb +97 -0
  44. data/lib/active_element/default_controller/search.rb +112 -0
  45. data/lib/active_element/default_controller.rb +10 -88
  46. data/lib/active_element/version.rb +1 -1
  47. data/lib/active_element.rb +1 -2
  48. data/rspec-documentation/_head.html.erb +2 -0
  49. data/rspec-documentation/pages/000-Introduction.md +8 -5
  50. data/rspec-documentation/pages/005-Setup.md +21 -28
  51. data/rspec-documentation/pages/010-Components/Form Fields.md +35 -0
  52. data/rspec-documentation/pages/015-Custom Controllers.md +32 -0
  53. data/rspec-documentation/pages/016-Default Controller.md +132 -0
  54. data/rspec-documentation/pages/Themes.md +3 -0
  55. metadata +15 -4
  56. data/lib/active_element/default_record_params.rb +0 -62
  57. data/lib/active_element/default_text_search.rb +0 -110
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 59c0c229f1a2c98d33fbcb36bfac256d0c41a03ae5149f2134736830eed704f5
4
- data.tar.gz: 25f487e038544884b13f224e7fbed2a831584b60b704900e5dae1f17082667c1
3
+ metadata.gz: a4fed8a2aa02e3d31a663293eaee2485fe9a483a74c0b089638e0a4d6d6a1521
4
+ data.tar.gz: edaae463c33a9e63827dbdf715b9f6cece1fdb593d17171f0f283f84f8c01689
5
5
  SHA512:
6
- metadata.gz: ca8865cdf14f3f7aad1c7935661a31b61a8de6e97928262d6a39a468e195934958f766e87e021c110e7c23369aa15c61e304bf375fb3ed7adef89f4532d36962
7
- data.tar.gz: aaa94959dfaddb83889c62bc5899a109394a1688428186c12550b29fc21d013852deaa37d8167165e48e831a636ed58e50a90a88f71c9e77ca04595619435910
6
+ metadata.gz: 8f54c3be4a35104dfa558d6842ddded264a21eb37ea210d2dd46e676d07655491d119037f4954e4225390a44f54fca827825a33d718ee5f9159133f6619fd73d
7
+ data.tar.gz: 1e9e43507054e3e2a659691072249880d65136371d15d9b5fdbbad451d3822ca6def3fdb69abed646ae7993e17c7ee47ac14d8e2832e7eaee03601d8bae6c0fc
data/.rubocop.yml CHANGED
@@ -25,6 +25,6 @@ Style/SymbolArray:
25
25
  Exclude:
26
26
  - 'rspec-documentation/pages/**/*.md'
27
27
 
28
- Style/Style/WordArray:
28
+ Style/WordArray:
29
29
  Exclude:
30
30
  - 'rspec-documentation/pages/**/*.md'
data/Gemfile CHANGED
@@ -10,9 +10,10 @@ gem 'devise', '~> 4.9'
10
10
  gem 'devpack', '~> 0.4.1'
11
11
  gem 'factory_bot_rails', '~> 5.2'
12
12
  gem 'faker', '~> 2.23'
13
+ gem 'listen', '~> 3.8'
13
14
  gem 'rake', '~> 13.0'
14
15
  gem 'rspec', '~> 3.12'
15
- gem 'rspec-documentation', '~> 0.0.9'
16
+ gem 'rspec-documentation', '~> 0.0.10'
16
17
  gem 'rspec-file_fixtures', '~> 0.1.6'
17
18
  gem 'rspec-html', '~> 0.3.2'
18
19
  gem 'rspec-its', '~> 1.3'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- active_element (0.0.11)
4
+ active_element (0.0.13)
5
5
  bootstrap (~> 5.3.0alpha3)
6
6
  kaminari (~> 1.2)
7
7
  paintbrush (~> 0.1.2)
@@ -135,6 +135,9 @@ GEM
135
135
  rexml
136
136
  kramdown-parser-gfm (1.1.0)
137
137
  kramdown (~> 2.0)
138
+ listen (3.8.0)
139
+ rb-fsevent (~> 0.10, >= 0.10.3)
140
+ rb-inotify (~> 0.9, >= 0.9.10)
138
141
  loofah (2.21.3)
139
142
  crass (~> 1.0.2)
140
143
  nokogiri (>= 1.12.0)
@@ -203,6 +206,9 @@ GEM
203
206
  zeitwerk (~> 2.5)
204
207
  rainbow (3.1.1)
205
208
  rake (13.0.6)
209
+ rb-fsevent (0.11.2)
210
+ rb-inotify (0.10.1)
211
+ ffi (~> 1.0)
206
212
  redcarpet (3.6.0)
207
213
  regexp_parser (2.8.1)
208
214
  responders (3.1.0)
@@ -216,7 +222,7 @@ GEM
216
222
  rspec-mocks (~> 3.12.0)
217
223
  rspec-core (3.12.2)
218
224
  rspec-support (~> 3.12.0)
219
- rspec-documentation (0.0.9)
225
+ rspec-documentation (0.0.10)
220
226
  htmlbeautifier (~> 1.4)
221
227
  kramdown (~> 2.4)
222
228
  kramdown-parser-gfm (~> 1.1)
@@ -325,9 +331,10 @@ DEPENDENCIES
325
331
  devpack (~> 0.4.1)
326
332
  factory_bot_rails (~> 5.2)
327
333
  faker (~> 2.23)
334
+ listen (~> 3.8)
328
335
  rake (~> 13.0)
329
336
  rspec (~> 3.12)
330
- rspec-documentation (~> 0.0.9)
337
+ rspec-documentation (~> 0.0.10)
331
338
  rspec-file_fixtures (~> 0.1.6)
332
339
  rspec-html (~> 0.3.2)
333
340
  rspec-its (~> 1.3)
@@ -0,0 +1,311 @@
1
+ /*!
2
+ Highlight.js v11.7.0 (git: 82688fad18)
3
+ (c) 2006-2022 undefined and other contributors
4
+ License: BSD-3-Clause
5
+ */
6
+ var hljs=function(){"use strict";var e={exports:{}};function t(e){
7
+ return e instanceof Map?e.clear=e.delete=e.set=()=>{
8
+ throw Error("map is read-only")}:e instanceof Set&&(e.add=e.clear=e.delete=()=>{
9
+ throw Error("set is read-only")
10
+ }),Object.freeze(e),Object.getOwnPropertyNames(e).forEach((n=>{var i=e[n]
11
+ ;"object"!=typeof i||Object.isFrozen(i)||t(i)})),e}
12
+ e.exports=t,e.exports.default=t;class n{constructor(e){
13
+ void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1}
14
+ ignoreMatch(){this.isMatchIgnored=!0}}function i(e){
15
+ return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;")
16
+ }function r(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t]
17
+ ;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}
18
+ const s=e=>!!e.scope||e.sublanguage&&e.language;class o{constructor(e,t){
19
+ this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){
20
+ this.buffer+=i(e)}openNode(e){if(!s(e))return;let t=""
21
+ ;t=e.sublanguage?"language-"+e.language:((e,{prefix:t})=>{if(e.includes(".")){
22
+ const n=e.split(".")
23
+ ;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${"_".repeat(t+1)}`))].join(" ")
24
+ }return`${t}${e}`})(e.scope,{prefix:this.classPrefix}),this.span(t)}
25
+ closeNode(e){s(e)&&(this.buffer+="</span>")}value(){return this.buffer}span(e){
26
+ this.buffer+=`<span class="${e}">`}}const a=(e={})=>{const t={children:[]}
27
+ ;return Object.assign(t,e),t};class c{constructor(){
28
+ this.rootNode=a(),this.stack=[this.rootNode]}get top(){
29
+ return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){
30
+ this.top.children.push(e)}openNode(e){const t=a({scope:e})
31
+ ;this.add(t),this.stack.push(t)}closeNode(){
32
+ if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){
33
+ for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}
34
+ walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){
35
+ return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t),
36
+ t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){
37
+ "string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{
38
+ c._collapse(e)})))}}class l extends c{constructor(e){super(),this.options=e}
39
+ addKeyword(e,t){""!==e&&(this.openNode(t),this.addText(e),this.closeNode())}
40
+ addText(e){""!==e&&this.add(e)}addSublanguage(e,t){const n=e.root
41
+ ;n.sublanguage=!0,n.language=t,this.add(n)}toHTML(){
42
+ return new o(this,this.options).value()}finalize(){return!0}}function g(e){
43
+ return e?"string"==typeof e?e:e.source:null}function d(e){return p("(?=",e,")")}
44
+ function u(e){return p("(?:",e,")*")}function h(e){return p("(?:",e,")?")}
45
+ function p(...e){return e.map((e=>g(e))).join("")}function f(...e){const t=(e=>{
46
+ const t=e[e.length-1]
47
+ ;return"object"==typeof t&&t.constructor===Object?(e.splice(e.length-1,1),t):{}
48
+ })(e);return"("+(t.capture?"":"?:")+e.map((e=>g(e))).join("|")+")"}
49
+ function b(e){return RegExp(e.toString()+"|").exec("").length-1}
50
+ const m=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./
51
+ ;function E(e,{joinWith:t}){let n=0;return e.map((e=>{n+=1;const t=n
52
+ ;let i=g(e),r="";for(;i.length>0;){const e=m.exec(i);if(!e){r+=i;break}
53
+ r+=i.substring(0,e.index),
54
+ i=i.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?r+="\\"+(Number(e[1])+t):(r+=e[0],
55
+ "("===e[0]&&n++)}return r})).map((e=>`(${e})`)).join(t)}
56
+ const x="[a-zA-Z]\\w*",w="[a-zA-Z_]\\w*",y="\\b\\d+(\\.\\d+)?",_="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",O="\\b(0b[01]+)",v={
57
+ begin:"\\\\[\\s\\S]",relevance:0},N={scope:"string",begin:"'",end:"'",
58
+ illegal:"\\n",contains:[v]},k={scope:"string",begin:'"',end:'"',illegal:"\\n",
59
+ contains:[v]},M=(e,t,n={})=>{const i=r({scope:"comment",begin:e,end:t,
60
+ contains:[]},n);i.contains.push({scope:"doctag",
61
+ begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)",
62
+ end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0})
63
+ ;const s=f("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/)
64
+ ;return i.contains.push({begin:p(/[ ]+/,"(",s,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),i
65
+ },S=M("//","$"),R=M("/\\*","\\*/"),j=M("#","$");var A=Object.freeze({
66
+ __proto__:null,MATCH_NOTHING_RE:/\b\B/,IDENT_RE:x,UNDERSCORE_IDENT_RE:w,
67
+ NUMBER_RE:y,C_NUMBER_RE:_,BINARY_NUMBER_RE:O,
68
+ RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",
69
+ SHEBANG:(e={})=>{const t=/^#![ ]*\//
70
+ ;return e.binary&&(e.begin=p(t,/.*\b/,e.binary,/\b.*/)),r({scope:"meta",begin:t,
71
+ end:/$/,relevance:0,"on:begin":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)},
72
+ BACKSLASH_ESCAPE:v,APOS_STRING_MODE:N,QUOTE_STRING_MODE:k,PHRASAL_WORDS_MODE:{
73
+ begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/
74
+ },COMMENT:M,C_LINE_COMMENT_MODE:S,C_BLOCK_COMMENT_MODE:R,HASH_COMMENT_MODE:j,
75
+ NUMBER_MODE:{scope:"number",begin:y,relevance:0},C_NUMBER_MODE:{scope:"number",
76
+ begin:_,relevance:0},BINARY_NUMBER_MODE:{scope:"number",begin:O,relevance:0},
77
+ REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{scope:"regexp",begin:/\//,
78
+ end:/\/[gimuy]*/,illegal:/\n/,contains:[v,{begin:/\[/,end:/\]/,relevance:0,
79
+ contains:[v]}]}]},TITLE_MODE:{scope:"title",begin:x,relevance:0},
80
+ UNDERSCORE_TITLE_MODE:{scope:"title",begin:w,relevance:0},METHOD_GUARD:{
81
+ begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:e=>Object.assign(e,{
82
+ "on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{
83
+ t.data._beginMatch!==e[1]&&t.ignoreMatch()}})});function I(e,t){
84
+ "."===e.input[e.index-1]&&t.ignoreMatch()}function T(e,t){
85
+ void 0!==e.className&&(e.scope=e.className,delete e.className)}function L(e,t){
86
+ t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)",
87
+ e.__beforeBegin=I,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords,
88
+ void 0===e.relevance&&(e.relevance=0))}function B(e,t){
89
+ Array.isArray(e.illegal)&&(e.illegal=f(...e.illegal))}function D(e,t){
90
+ if(e.match){
91
+ if(e.begin||e.end)throw Error("begin & end are not supported with match")
92
+ ;e.begin=e.match,delete e.match}}function H(e,t){
93
+ void 0===e.relevance&&(e.relevance=1)}const P=(e,t)=>{if(!e.beforeMatch)return
94
+ ;if(e.starts)throw Error("beforeMatch cannot be used with starts")
95
+ ;const n=Object.assign({},e);Object.keys(e).forEach((t=>{delete e[t]
96
+ })),e.keywords=n.keywords,e.begin=p(n.beforeMatch,d(n.begin)),e.starts={
97
+ relevance:0,contains:[Object.assign(n,{endsParent:!0})]
98
+ },e.relevance=0,delete n.beforeMatch
99
+ },C=["of","and","for","in","not","or","if","then","parent","list","value"]
100
+ ;function $(e,t,n="keyword"){const i=Object.create(null)
101
+ ;return"string"==typeof e?r(n,e.split(" ")):Array.isArray(e)?r(n,e):Object.keys(e).forEach((n=>{
102
+ Object.assign(i,$(e[n],t,n))})),i;function r(e,n){
103
+ t&&(n=n.map((e=>e.toLowerCase()))),n.forEach((t=>{const n=t.split("|")
104
+ ;i[n[0]]=[e,U(n[0],n[1])]}))}}function U(e,t){
105
+ return t?Number(t):(e=>C.includes(e.toLowerCase()))(e)?0:1}const z={},K=e=>{
106
+ console.error(e)},W=(e,...t)=>{console.log("WARN: "+e,...t)},X=(e,t)=>{
107
+ z[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),z[`${e}/${t}`]=!0)
108
+ },G=Error();function Z(e,t,{key:n}){let i=0;const r=e[n],s={},o={}
109
+ ;for(let e=1;e<=t.length;e++)o[e+i]=r[e],s[e+i]=!0,i+=b(t[e-1])
110
+ ;e[n]=o,e[n]._emit=s,e[n]._multi=!0}function F(e){(e=>{
111
+ e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope,
112
+ delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={
113
+ _wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope
114
+ }),(e=>{if(Array.isArray(e.begin)){
115
+ if(e.skip||e.excludeBegin||e.returnBegin)throw K("skip, excludeBegin, returnBegin not compatible with beginScope: {}"),
116
+ G
117
+ ;if("object"!=typeof e.beginScope||null===e.beginScope)throw K("beginScope must be object"),
118
+ G;Z(e,e.begin,{key:"beginScope"}),e.begin=E(e.begin,{joinWith:""})}})(e),(e=>{
119
+ if(Array.isArray(e.end)){
120
+ if(e.skip||e.excludeEnd||e.returnEnd)throw K("skip, excludeEnd, returnEnd not compatible with endScope: {}"),
121
+ G
122
+ ;if("object"!=typeof e.endScope||null===e.endScope)throw K("endScope must be object"),
123
+ G;Z(e,e.end,{key:"endScope"}),e.end=E(e.end,{joinWith:""})}})(e)}function V(e){
124
+ function t(t,n){
125
+ return RegExp(g(t),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(n?"g":""))
126
+ }class n{constructor(){
127
+ this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}
128
+ addRule(e,t){
129
+ t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]),
130
+ this.matchAt+=b(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null)
131
+ ;const e=this.regexes.map((e=>e[1]));this.matcherRe=t(E(e,{joinWith:"|"
132
+ }),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex
133
+ ;const t=this.matcherRe.exec(e);if(!t)return null
134
+ ;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),i=this.matchIndexes[n]
135
+ ;return t.splice(0,n),Object.assign(t,i)}}class i{constructor(){
136
+ this.rules=[],this.multiRegexes=[],
137
+ this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){
138
+ if(this.multiRegexes[e])return this.multiRegexes[e];const t=new n
139
+ ;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))),
140
+ t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){
141
+ return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){
142
+ this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){
143
+ const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex
144
+ ;let n=t.exec(e)
145
+ ;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{
146
+ const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)}
147
+ return n&&(this.regexIndex+=n.position+1,
148
+ this.regexIndex===this.count&&this.considerAll()),n}}
149
+ if(e.compilerExtensions||(e.compilerExtensions=[]),
150
+ e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.")
151
+ ;return e.classNameAliases=r(e.classNameAliases||{}),function n(s,o){const a=s
152
+ ;if(s.isCompiled)return a
153
+ ;[T,D,F,P].forEach((e=>e(s,o))),e.compilerExtensions.forEach((e=>e(s,o))),
154
+ s.__beforeBegin=null,[L,B,H].forEach((e=>e(s,o))),s.isCompiled=!0;let c=null
155
+ ;return"object"==typeof s.keywords&&s.keywords.$pattern&&(s.keywords=Object.assign({},s.keywords),
156
+ c=s.keywords.$pattern,
157
+ delete s.keywords.$pattern),c=c||/\w+/,s.keywords&&(s.keywords=$(s.keywords,e.case_insensitive)),
158
+ a.keywordPatternRe=t(c,!0),
159
+ o&&(s.begin||(s.begin=/\B|\b/),a.beginRe=t(a.begin),s.end||s.endsWithParent||(s.end=/\B|\b/),
160
+ s.end&&(a.endRe=t(a.end)),
161
+ a.terminatorEnd=g(a.end)||"",s.endsWithParent&&o.terminatorEnd&&(a.terminatorEnd+=(s.end?"|":"")+o.terminatorEnd)),
162
+ s.illegal&&(a.illegalRe=t(s.illegal)),
163
+ s.contains||(s.contains=[]),s.contains=[].concat(...s.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>r(e,{
164
+ variants:null},t)))),e.cachedVariants?e.cachedVariants:q(e)?r(e,{
165
+ starts:e.starts?r(e.starts):null
166
+ }):Object.isFrozen(e)?r(e):e))("self"===e?s:e)))),s.contains.forEach((e=>{n(e,a)
167
+ })),s.starts&&n(s.starts,o),a.matcher=(e=>{const t=new i
168
+ ;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin"
169
+ }))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end"
170
+ }),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(a),a}(e)}function q(e){
171
+ return!!e&&(e.endsWithParent||q(e.starts))}class J extends Error{
172
+ constructor(e,t){super(e),this.name="HTMLInjectionError",this.html=t}}
173
+ const Y=i,Q=r,ee=Symbol("nomatch");var te=(t=>{
174
+ const i=Object.create(null),r=Object.create(null),s=[];let o=!0
175
+ ;const a="Could not find the language '{}', did you forget to load/include a language module?",c={
176
+ disableAutodetect:!0,name:"Plain text",contains:[]};let g={
177
+ ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i,
178
+ languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",
179
+ cssSelector:"pre code",languages:null,__emitter:l};function b(e){
180
+ return g.noHighlightRe.test(e)}function m(e,t,n){let i="",r=""
181
+ ;"object"==typeof t?(i=e,
182
+ n=t.ignoreIllegals,r=t.language):(X("10.7.0","highlight(lang, code, ...args) has been deprecated."),
183
+ X("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"),
184
+ r=e,i=t),void 0===n&&(n=!0);const s={code:i,language:r};k("before:highlight",s)
185
+ ;const o=s.result?s.result:E(s.language,s.code,n)
186
+ ;return o.code=s.code,k("after:highlight",o),o}function E(e,t,r,s){
187
+ const c=Object.create(null);function l(){if(!N.keywords)return void M.addText(S)
188
+ ;let e=0;N.keywordPatternRe.lastIndex=0;let t=N.keywordPatternRe.exec(S),n=""
189
+ ;for(;t;){n+=S.substring(e,t.index)
190
+ ;const r=y.case_insensitive?t[0].toLowerCase():t[0],s=(i=r,N.keywords[i]);if(s){
191
+ const[e,i]=s
192
+ ;if(M.addText(n),n="",c[r]=(c[r]||0)+1,c[r]<=7&&(R+=i),e.startsWith("_"))n+=t[0];else{
193
+ const n=y.classNameAliases[e]||e;M.addKeyword(t[0],n)}}else n+=t[0]
194
+ ;e=N.keywordPatternRe.lastIndex,t=N.keywordPatternRe.exec(S)}var i
195
+ ;n+=S.substring(e),M.addText(n)}function d(){null!=N.subLanguage?(()=>{
196
+ if(""===S)return;let e=null;if("string"==typeof N.subLanguage){
197
+ if(!i[N.subLanguage])return void M.addText(S)
198
+ ;e=E(N.subLanguage,S,!0,k[N.subLanguage]),k[N.subLanguage]=e._top
199
+ }else e=x(S,N.subLanguage.length?N.subLanguage:null)
200
+ ;N.relevance>0&&(R+=e.relevance),M.addSublanguage(e._emitter,e.language)
201
+ })():l(),S=""}function u(e,t){let n=1;const i=t.length-1;for(;n<=i;){
202
+ if(!e._emit[n]){n++;continue}const i=y.classNameAliases[e[n]]||e[n],r=t[n]
203
+ ;i?M.addKeyword(r,i):(S=r,l(),S=""),n++}}function h(e,t){
204
+ return e.scope&&"string"==typeof e.scope&&M.openNode(y.classNameAliases[e.scope]||e.scope),
205
+ e.beginScope&&(e.beginScope._wrap?(M.addKeyword(S,y.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap),
206
+ S=""):e.beginScope._multi&&(u(e.beginScope,t),S="")),N=Object.create(e,{parent:{
207
+ value:N}}),N}function p(e,t,i){let r=((e,t)=>{const n=e&&e.exec(t)
208
+ ;return n&&0===n.index})(e.endRe,i);if(r){if(e["on:end"]){const i=new n(e)
209
+ ;e["on:end"](t,i),i.isMatchIgnored&&(r=!1)}if(r){
210
+ for(;e.endsParent&&e.parent;)e=e.parent;return e}}
211
+ if(e.endsWithParent)return p(e.parent,t,i)}function f(e){
212
+ return 0===N.matcher.regexIndex?(S+=e[0],1):(I=!0,0)}function b(e){
213
+ const n=e[0],i=t.substring(e.index),r=p(N,e,i);if(!r)return ee;const s=N
214
+ ;N.endScope&&N.endScope._wrap?(d(),
215
+ M.addKeyword(n,N.endScope._wrap)):N.endScope&&N.endScope._multi?(d(),
216
+ u(N.endScope,e)):s.skip?S+=n:(s.returnEnd||s.excludeEnd||(S+=n),
217
+ d(),s.excludeEnd&&(S=n));do{
218
+ N.scope&&M.closeNode(),N.skip||N.subLanguage||(R+=N.relevance),N=N.parent
219
+ }while(N!==r.parent);return r.starts&&h(r.starts,e),s.returnEnd?0:n.length}
220
+ let m={};function w(i,s){const a=s&&s[0];if(S+=i,null==a)return d(),0
221
+ ;if("begin"===m.type&&"end"===s.type&&m.index===s.index&&""===a){
222
+ if(S+=t.slice(s.index,s.index+1),!o){const t=Error(`0 width match regex (${e})`)
223
+ ;throw t.languageName=e,t.badRule=m.rule,t}return 1}
224
+ if(m=s,"begin"===s.type)return(e=>{
225
+ const t=e[0],i=e.rule,r=new n(i),s=[i.__beforeBegin,i["on:begin"]]
226
+ ;for(const n of s)if(n&&(n(e,r),r.isMatchIgnored))return f(t)
227
+ ;return i.skip?S+=t:(i.excludeBegin&&(S+=t),
228
+ d(),i.returnBegin||i.excludeBegin||(S=t)),h(i,e),i.returnBegin?0:t.length})(s)
229
+ ;if("illegal"===s.type&&!r){
230
+ const e=Error('Illegal lexeme "'+a+'" for mode "'+(N.scope||"<unnamed>")+'"')
231
+ ;throw e.mode=N,e}if("end"===s.type){const e=b(s);if(e!==ee)return e}
232
+ if("illegal"===s.type&&""===a)return 1
233
+ ;if(A>1e5&&A>3*s.index)throw Error("potential infinite loop, way more iterations than matches")
234
+ ;return S+=a,a.length}const y=O(e)
235
+ ;if(!y)throw K(a.replace("{}",e)),Error('Unknown language: "'+e+'"')
236
+ ;const _=V(y);let v="",N=s||_;const k={},M=new g.__emitter(g);(()=>{const e=[]
237
+ ;for(let t=N;t!==y;t=t.parent)t.scope&&e.unshift(t.scope)
238
+ ;e.forEach((e=>M.openNode(e)))})();let S="",R=0,j=0,A=0,I=!1;try{
239
+ for(N.matcher.considerAll();;){
240
+ A++,I?I=!1:N.matcher.considerAll(),N.matcher.lastIndex=j
241
+ ;const e=N.matcher.exec(t);if(!e)break;const n=w(t.substring(j,e.index),e)
242
+ ;j=e.index+n}
243
+ return w(t.substring(j)),M.closeAllNodes(),M.finalize(),v=M.toHTML(),{
244
+ language:e,value:v,relevance:R,illegal:!1,_emitter:M,_top:N}}catch(n){
245
+ if(n.message&&n.message.includes("Illegal"))return{language:e,value:Y(t),
246
+ illegal:!0,relevance:0,_illegalBy:{message:n.message,index:j,
247
+ context:t.slice(j-100,j+100),mode:n.mode,resultSoFar:v},_emitter:M};if(o)return{
248
+ language:e,value:Y(t),illegal:!1,relevance:0,errorRaised:n,_emitter:M,_top:N}
249
+ ;throw n}}function x(e,t){t=t||g.languages||Object.keys(i);const n=(e=>{
250
+ const t={value:Y(e),illegal:!1,relevance:0,_top:c,_emitter:new g.__emitter(g)}
251
+ ;return t._emitter.addText(e),t})(e),r=t.filter(O).filter(N).map((t=>E(t,e,!1)))
252
+ ;r.unshift(n);const s=r.sort(((e,t)=>{
253
+ if(e.relevance!==t.relevance)return t.relevance-e.relevance
254
+ ;if(e.language&&t.language){if(O(e.language).supersetOf===t.language)return 1
255
+ ;if(O(t.language).supersetOf===e.language)return-1}return 0})),[o,a]=s,l=o
256
+ ;return l.secondBest=a,l}function w(e){let t=null;const n=(e=>{
257
+ let t=e.className+" ";t+=e.parentNode?e.parentNode.className:""
258
+ ;const n=g.languageDetectRe.exec(t);if(n){const t=O(n[1])
259
+ ;return t||(W(a.replace("{}",n[1])),
260
+ W("Falling back to no-highlight mode for this block.",e)),t?n[1]:"no-highlight"}
261
+ return t.split(/\s+/).find((e=>b(e)||O(e)))})(e);if(b(n))return
262
+ ;if(k("before:highlightElement",{el:e,language:n
263
+ }),e.children.length>0&&(g.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."),
264
+ console.warn("https://github.com/highlightjs/highlight.js/wiki/security"),
265
+ console.warn("The element with unescaped HTML:"),
266
+ console.warn(e)),g.throwUnescapedHTML))throw new J("One of your code blocks includes unescaped HTML.",e.innerHTML)
267
+ ;t=e;const i=t.textContent,s=n?m(i,{language:n,ignoreIllegals:!0}):x(i)
268
+ ;e.innerHTML=s.value,((e,t,n)=>{const i=t&&r[t]||n
269
+ ;e.classList.add("hljs"),e.classList.add("language-"+i)
270
+ })(e,n,s.language),e.result={language:s.language,re:s.relevance,
271
+ relevance:s.relevance},s.secondBest&&(e.secondBest={
272
+ language:s.secondBest.language,relevance:s.secondBest.relevance
273
+ }),k("after:highlightElement",{el:e,result:s,text:i})}let y=!1;function _(){
274
+ "loading"!==document.readyState?document.querySelectorAll(g.cssSelector).forEach(w):y=!0
275
+ }function O(e){return e=(e||"").toLowerCase(),i[e]||i[r[e]]}
276
+ function v(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{
277
+ r[e.toLowerCase()]=t}))}function N(e){const t=O(e)
278
+ ;return t&&!t.disableAutodetect}function k(e,t){const n=e;s.forEach((e=>{
279
+ e[n]&&e[n](t)}))}
280
+ "undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(()=>{
281
+ y&&_()}),!1),Object.assign(t,{highlight:m,highlightAuto:x,highlightAll:_,
282
+ highlightElement:w,
283
+ highlightBlock:e=>(X("10.7.0","highlightBlock will be removed entirely in v12.0"),
284
+ X("10.7.0","Please use highlightElement now."),w(e)),configure:e=>{g=Q(g,e)},
285
+ initHighlighting:()=>{
286
+ _(),X("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")},
287
+ initHighlightingOnLoad:()=>{
288
+ _(),X("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.")
289
+ },registerLanguage:(e,n)=>{let r=null;try{r=n(t)}catch(t){
290
+ if(K("Language definition for '{}' could not be registered.".replace("{}",e)),
291
+ !o)throw t;K(t),r=c}
292
+ r.name||(r.name=e),i[e]=r,r.rawDefinition=n.bind(null,t),r.aliases&&v(r.aliases,{
293
+ languageName:e})},unregisterLanguage:e=>{delete i[e]
294
+ ;for(const t of Object.keys(r))r[t]===e&&delete r[t]},
295
+ listLanguages:()=>Object.keys(i),getLanguage:O,registerAliases:v,
296
+ autoDetection:N,inherit:Q,addPlugin:e=>{(e=>{
297
+ e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=t=>{
298
+ e["before:highlightBlock"](Object.assign({block:t.el},t))
299
+ }),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=t=>{
300
+ e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),s.push(e)}
301
+ }),t.debugMode=()=>{o=!1},t.safeMode=()=>{o=!0
302
+ },t.versionString="11.7.0",t.regex={concat:p,lookahead:d,either:f,optional:h,
303
+ anyNumberOfTimes:u};for(const t in A)"object"==typeof A[t]&&e.exports(A[t])
304
+ ;return Object.assign(t,A),t})({});return te}()
305
+ ;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);/*! `json` grammar compiled for Highlight.js 11.7.0 */
306
+ (()=>{var e=(()=>{"use strict";return e=>{const a=["true","false","null"],n={
307
+ scope:"literal",beginKeywords:a.join(" ")};return{name:"JSON",keywords:{
308
+ literal:a},contains:[{className:"attr",begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/,
309
+ relevance:1.01},{match:/[{}[\],:]/,className:"punctuation",relevance:0
310
+ },e.QUOTE_STRING_MODE,n,e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],
311
+ illegal:"\\S"}}})();hljs.registerLanguage("json",e)})();
@@ -4,11 +4,26 @@ ActiveElement.JsonField = (() => {
4
4
  const humanize = ({ string, singular = false }) => {
5
5
  if (!string) return '';
6
6
 
7
- const humanized = string.split('_').map(item => item.charAt(0).toUpperCase() + item.substring(1)).join(' ');
7
+ const humanized = string.split('_')
8
+ .map(item => item.charAt(0).toUpperCase() + item.substring(1)).join(' ')
9
+ .replace(/([a-z])([A-Z])/g, '$1 $2');
8
10
 
9
11
  if (!singular) return humanized;
10
12
 
11
- return humanized.replace(/s$/, ''); // FIXME: Expose translations from back-end to make this more useful.
13
+ // FIXME: Expose translations from back-end to make this more useful.
14
+ return humanized.replace(/[^u]s$/, '');
15
+ };
16
+
17
+ // Adapted from: https://stackoverflow.com/a/7557433
18
+ const isVisible = (element) => {
19
+ const boundingClientRect = element.getBoundingClientRect();
20
+
21
+ return (
22
+ boundingClientRect.top >= 0 &&
23
+ boundingClientRect.left >= 0 &&
24
+ boundingClientRect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
25
+ boundingClientRect.right <= (window.innerWidth || document.documentElement.clientWidth)
26
+ );
12
27
  };
13
28
 
14
29
  const isObject = (object) => object && typeof object === 'object';
@@ -44,7 +59,6 @@ ActiveElement.JsonField = (() => {
44
59
  };
45
60
 
46
61
  store.state = defaultState({ schema, path: [], defaultValue: data });
47
- console.log(store.state)
48
62
 
49
63
  const stateChangedCallbacks = [];
50
64
  const stateChanged = (callback, state) => stateChangedCallbacks.push([callback, state]);
@@ -211,10 +225,12 @@ ActiveElement.JsonField = (() => {
211
225
  };
212
226
 
213
227
  const Component = ({ store, stateChanged, connectState, schema, element, fieldName }) => {
214
- const ObjectField = ({ schema, state, path, omitLabel = false }) => {
228
+ const ObjectField = ({ schema, state, path, omitLabel = false, depth = 0 }) => {
215
229
  const getPath = () => schema.name ? path.concat(schema.name) : path;
216
230
  const currentPath = getPath();
217
231
 
232
+ depth = depth + 1;
233
+
218
234
  let element;
219
235
 
220
236
  switch (schema.type) {
@@ -235,7 +251,9 @@ ActiveElement.JsonField = (() => {
235
251
  case 'decimal':
236
252
  return DecimalField({ state, omitLabel, schema, path: currentPath });
237
253
  case 'object':
238
- element = cloneElement('form-group-floating');
254
+ element = cloneElement('form-group');
255
+ element.classList.add(`depth-${depth}`);
256
+ if (schema.name) element.append(Label({ schema }));
239
257
  (schema.shape.fields).forEach((field) => {
240
258
  element.append(
241
259
  ObjectField({
@@ -243,6 +261,7 @@ ActiveElement.JsonField = (() => {
243
261
  schema: field,
244
262
  state: state ? state[field.name] : null,
245
263
  path: currentPath,
264
+ depth,
246
265
  })
247
266
  );
248
267
  });
@@ -250,10 +269,10 @@ ActiveElement.JsonField = (() => {
250
269
  return element;
251
270
  case 'array':
252
271
  element = cloneElement('form-group');
253
- const list = ArrayField({ schema, state, path: currentPath });
272
+ const list = ArrayField({ schema, state, path: currentPath, depth });
254
273
  if (schema.shape?.type === 'object') list.classList.add('array-of-objects');
255
274
  element.append(AppendButton({ list, schema, state, path: currentPath }));
256
- element.append(Label({ title: schema.name }));
275
+ element.append(Label({ schema }));
257
276
  element.append(list);
258
277
  return element;
259
278
  }
@@ -270,12 +289,12 @@ ActiveElement.JsonField = (() => {
270
289
  const element = cloneElement('form-check');
271
290
 
272
291
  element.append(checkbox);
273
- element.append(Label({ title: schema.name, template: 'form-check-label' }));
292
+ element.append(Label({ schema, template: 'form-check-label', labelFor: checkbox }));
274
293
 
275
294
  return element;
276
295
  };
277
296
 
278
- const ArrayField = ({ schema, state, path: objectPath }) => {
297
+ const ArrayField = ({ schema, state, depth, path: objectPath }) => {
279
298
  const element = cloneElement('list-group');
280
299
 
281
300
  if (schema.focus) element.classList.add('focus');
@@ -284,21 +303,22 @@ ActiveElement.JsonField = (() => {
284
303
  if (state) {
285
304
  state.forEach((eachState, index) => {
286
305
  const path = objectPath.concat([index]);
287
- element.append(ArrayItem({ state: eachState, path, schema }));
306
+ element.append(ArrayItem({ state: eachState, path, schema, depth }));
288
307
  });
289
308
  }
290
309
 
291
310
  return element;
292
311
  };
293
312
 
294
- const ArrayItem = ({ state, path, schema, newItem = false }) => {
313
+ const ArrayItem = ({ state, path, schema, depth, newItem = false }) => {
295
314
  const element = cloneElement('list-item');
296
315
  const wrapper = document.createElement('div');
297
316
  const objectField = ObjectField({
298
317
  path,
299
318
  omitLabel: true,
300
319
  schema: { ...schema.shape },
301
- state: state
320
+ state: state,
321
+ depth,
302
322
  });
303
323
 
304
324
  // TODO: Use same template etc. for all delete buttons, use presentation layer to
@@ -366,6 +386,7 @@ ActiveElement.JsonField = (() => {
366
386
  valueElement.href = '#';
367
387
  modalBody.append(group);
368
388
  modalBody.classList.add('json-field');
389
+ group.classList.add('depth-1');
369
390
  titleElement.append(deleteObjectButton);
370
391
  modalHeader.append(deleteObjectButton);
371
392
  deleteObjectButton.addEventListener('click', () => bootstrapModal.hide());
@@ -382,10 +403,10 @@ ActiveElement.JsonField = (() => {
382
403
  return element;
383
404
  };
384
405
 
385
- const Label = ({ title, template, labelFor }) => {
406
+ const Label = ({ schema, template, labelFor }) => {
386
407
  const element = cloneElement(template || 'label');
387
408
 
388
- element.append(humanize({ string: title }));
409
+ element.append(schema.label || humanize({ string: schema.name }));
389
410
 
390
411
  if (labelFor) {
391
412
  element.htmlFor = labelFor.id;
@@ -443,7 +464,7 @@ ActiveElement.JsonField = (() => {
443
464
  const group = cloneElement('form-group-floating');
444
465
 
445
466
  group.append(element);
446
- group.append(Label({ title: schema.name, labelFor: element }));
467
+ group.append(Label({ schema, labelFor: element }));
447
468
 
448
469
  return group;
449
470
  };
@@ -464,9 +485,9 @@ ActiveElement.JsonField = (() => {
464
485
 
465
486
  if (floating) {
466
487
  group.append(element);
467
- group.append(Label({ title: schema.name, labelFor: element }));
488
+ group.append(Label({ schema, labelFor: element }));
468
489
  } else {
469
- group.append(Label({ title: schema.name, labelFor: element }));
490
+ group.append(Label({ schema, labelFor: element }));
470
491
  group.append(element);
471
492
  }
472
493
 
@@ -513,9 +534,8 @@ ActiveElement.JsonField = (() => {
513
534
 
514
535
  const AppendButton = ({ list, schema, state, path: objectPath }) => {
515
536
  const element = cloneElement('append-button');
516
- const humanName = humanize({ string: schema.name || fieldName, singular: true });
517
537
 
518
- element.append(`Add ${humanName}`);
538
+ element.append(`Add Item`);
519
539
  element.classList.add('append-button', 'float-end');
520
540
  element.onclick = (ev) => {
521
541
  ev.preventDefault();
@@ -524,7 +544,8 @@ ActiveElement.JsonField = (() => {
524
544
  const item = ArrayItem({ path, state: appendState, schema, newItem: true })
525
545
 
526
546
  list.append(item);
527
- item.scrollIntoView();
547
+
548
+ if (!isVisible(item)) item.scrollIntoView({ block: 'center' });
528
549
 
529
550
  return false;
530
551
  };
@@ -540,19 +561,29 @@ ActiveElement.JsonField = (() => {
540
561
  const formId = element.dataset.formId;
541
562
  const formFieldElement = document.querySelector(`#${element.dataset.fieldId}`);
542
563
  const schemaFieldElement = document.querySelector(`#${element.dataset.schemaFieldId}`);
564
+ const jsonViewModal = document.querySelector(`#${element.dataset.jsonViewModalId}`);
565
+ const jsonViewModalTrigger = document.querySelector(`#${element.dataset.jsonViewModalTriggerId}`);
543
566
  const fieldName = element.dataset.fieldName;
544
567
  const schema = getSchema(element);
545
568
  const { store, stateChanged, connectState } = createStore({ data, schema });
569
+ let currentState = null;
546
570
 
547
571
  schemaFieldElement.value = JSON.stringify(schema);
548
572
 
549
573
  stateChanged(({ getState }) => {
550
574
  const state = getState();
551
575
 
576
+ currentState = state;
552
577
  formFieldElement.value = JSON.stringify(state);
553
578
  ActiveElement.log.debug(state);
554
579
  });
555
580
 
581
+ jsonViewModalTrigger.addEventListener('click', () => {
582
+ const highlighted = hljs.highlight(JSON.stringify(currentState, null, 2), { language: 'json' }).value;
583
+ jsonViewModal.querySelector('[data-field-type="modal-body"]').innerHTML = `<pre>${highlighted}</pre>`;
584
+ return true;
585
+ });
586
+
556
587
  connectState({ element });
557
588
 
558
589
  const component = Component({ store, stateChanged, connectState, schema, element, fieldName });
@@ -1,6 +1,8 @@
1
1
  (() => {
2
- const popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
3
- const popoverList = popoverTriggerList.map(function (element) {
4
- return new bootstrap.Popover(element)
5
- })
2
+ window.addEventListener('DOMContentLoaded', () => {
3
+ const popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
4
+ const popoverList = popoverTriggerList.map(function (element) {
5
+ return new bootstrap.Popover(element)
6
+ })
7
+ });
6
8
  })();