@onetype/framework 2.0.49 → 2.0.52

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 (104) hide show
  1. package/addons/core/commands/front/directives/run.js +1 -1
  2. package/addons/core/commands/front/directives/submit.js +1 -1
  3. package/addons/core/commands/front/functions/api.js +1 -1
  4. package/addons/core/database/back/addon.js +14 -0
  5. package/addons/core/database/back/events/addon.init.js +42 -0
  6. package/addons/core/database/back/events/addon.item.init.js +24 -0
  7. package/addons/core/database/back/functions/item/create.js +92 -0
  8. package/addons/core/database/back/functions/item/delete.js +34 -0
  9. package/addons/core/database/back/functions/item/save.js +13 -0
  10. package/addons/core/database/back/functions/item/update.js +90 -0
  11. package/addons/core/database/back/functions/items/builder.js +160 -0
  12. package/addons/core/database/back/functions/items/filter.js +32 -0
  13. package/addons/core/database/back/functions/items/filters.js +7 -0
  14. package/addons/core/database/back/functions/items/find.js +28 -0
  15. package/addons/core/database/back/functions/items/methods/aggregate.js +15 -0
  16. package/addons/core/database/back/functions/items/methods/count.js +12 -0
  17. package/addons/core/database/back/functions/items/methods/exists.js +8 -0
  18. package/addons/core/database/back/functions/items/methods/many.js +13 -0
  19. package/addons/core/database/back/functions/items/methods/one.js +8 -0
  20. package/addons/core/database/back/functions/items/methods/plain.js +29 -0
  21. package/addons/core/database/back/functions/items/methods/query.js +33 -0
  22. package/addons/core/database/back/functions/items/methods.js +142 -0
  23. package/addons/core/database/back/functions/items/transform/join.js +63 -0
  24. package/addons/core/database/back/functions/items/transform/translate.js +57 -0
  25. package/addons/core/database/back/functions/items/validation.js +125 -0
  26. package/addons/core/database/back/item/catch/add.js +1 -1
  27. package/addons/core/database/back/items/commands/create.js +54 -0
  28. package/addons/core/database/back/items/commands/delete.js +62 -0
  29. package/addons/core/database/back/items/commands/find.js +118 -0
  30. package/addons/core/database/back/items/commands/update.js +70 -0
  31. package/addons/core/database/back/load.js +27 -26
  32. package/addons/core/database/front/events/addon.init.js +42 -0
  33. package/addons/core/database/front/functions/create.js +11 -0
  34. package/addons/core/database/front/functions/delete.js +10 -0
  35. package/addons/core/database/front/functions/find.js +96 -142
  36. package/addons/core/database/front/functions/update.js +12 -0
  37. package/addons/float/popup/css/popup.css +141 -18
  38. package/addons/float/popup/js/addon.js +5 -0
  39. package/addons/float/popup/js/functions/confirm.js +100 -0
  40. package/addons/float/popup/js/functions/toast.js +1 -1
  41. package/addons/float/popup/js/items/directives/tooltip.js +5 -1
  42. package/addons/render/directives/front/addon.js +5 -0
  43. package/addons/render/directives/front/functions/process/data.js +19 -1
  44. package/addons/render/directives/front/functions/process/locale.js +46 -0
  45. package/addons/render/directives/front/functions/process.js +4 -1
  46. package/addons/render/directives/front/items/self/660-form.js +74 -163
  47. package/addons/render/directives/front/items/self/750-html.js +1 -1
  48. package/addons/render/elements/front/items/self/form/button/button.css +9 -0
  49. package/addons/render/elements/front/items/self/form/button/button.js +1 -1
  50. package/addons/render/elements/front/items/self/form/color/color.css +1 -1
  51. package/addons/render/elements/front/items/self/form/color/color.js +25 -10
  52. package/addons/render/elements/front/items/self/form/editor-markdown/editor-markdown.css +410 -0
  53. package/addons/render/elements/front/items/self/form/editor-markdown/editor-markdown.js +191 -0
  54. package/addons/render/elements/front/items/self/form/field/field.css +18 -4
  55. package/addons/render/elements/front/items/self/form/field/field.js +6 -1
  56. package/addons/render/elements/front/items/self/form/section/section.js +3 -1
  57. package/addons/render/elements/front/items/self/navigation/tabs/tabs.css +8 -3
  58. package/addons/render/pages/core/addon.js +1 -1
  59. package/addons/render/pages/front/items/directives/change.js +1 -1
  60. package/addons/render/pages/front/styles/page.css +0 -7
  61. package/addons/render/transforms/js/functions/data.js +21 -2
  62. package/lib/src/classes/addon/class.js +0 -16
  63. package/lib/src/classes/addon/classes/item/class.js +0 -2
  64. package/lib/src/classes/addon/classes/item/mixins/get.js +0 -1
  65. package/lib/src/classes/addon/classes/render/mixins/compile.js +3 -2
  66. package/lib/src/classes/addon/mixins/items.js +2 -0
  67. package/lib/src/mixins/addons.js +2 -0
  68. package/lib/src/mixins/data.js +10 -9
  69. package/lib/src/mixins/emitter.js +5 -1
  70. package/lib/src/mixins/form.js +4 -0
  71. package/lib/src/mixins/function.js +6 -1
  72. package/lib/src/mixins/language.js +55 -0
  73. package/lib/src/mixins/locale.js +49 -0
  74. package/lib/src/onetype.js +6 -11
  75. package/package.json +1 -1
  76. package/addons/core/database/back/events/addon.add.js +0 -18
  77. package/addons/core/database/back/events/middleware/addon.items.find.js +0 -24
  78. package/addons/core/database/back/events/middleware/item.crud.create.js +0 -24
  79. package/addons/core/database/back/events/middleware/item.crud.delete.js +0 -24
  80. package/addons/core/database/back/events/middleware/item.crud.update.js +0 -24
  81. package/addons/core/database/back/functions/create.js +0 -6
  82. package/addons/core/database/back/functions/delete.js +0 -6
  83. package/addons/core/database/back/functions/find/builder.js +0 -160
  84. package/addons/core/database/back/functions/find/count.js +0 -12
  85. package/addons/core/database/back/functions/find/filter.js +0 -37
  86. package/addons/core/database/back/functions/find/filters.js +0 -7
  87. package/addons/core/database/back/functions/find/many.js +0 -93
  88. package/addons/core/database/back/functions/find/methods.js +0 -235
  89. package/addons/core/database/back/functions/find/plain.js +0 -25
  90. package/addons/core/database/back/functions/find/validation.js +0 -214
  91. package/addons/core/database/back/functions/find.js +0 -25
  92. package/addons/core/database/back/functions/update.js +0 -6
  93. package/addons/core/database/back/item/functions/create.js +0 -94
  94. package/addons/core/database/back/item/functions/delete.js +0 -25
  95. package/addons/core/database/back/item/functions/find.js +0 -19
  96. package/addons/core/database/back/item/functions/save.js +0 -15
  97. package/addons/core/database/back/item/functions/transaction.js +0 -17
  98. package/addons/core/database/back/item/functions/update.js +0 -76
  99. package/addons/core/database/back/items/commands/expose.js +0 -321
  100. package/addons/core/database/front/events/addon.add.js +0 -13
  101. package/lib/src/classes/addon/classes/item/mixins/crud.js +0 -28
  102. package/lib/src/classes/addon/mixins/find.js +0 -12
  103. package/lib/src/classes/addon/mixins/table.js +0 -35
  104. package/lib/src/mixins/dependencies.js +0 -104
@@ -10,7 +10,7 @@ onetype.AddonReady('elements', (elements) =>
10
10
  config: {
11
11
  value: {
12
12
  type: 'string',
13
- value: '#E27055'
13
+ value: ''
14
14
  },
15
15
  name: {
16
16
  type: 'string',
@@ -38,21 +38,34 @@ onetype.AddonReady('elements', (elements) =>
38
38
  },
39
39
  render: function()
40
40
  {
41
+ this.sync = () =>
42
+ {
43
+ const input = this.Element?.querySelector('input.input');
44
+ if(input) input.value = this.value || '';
45
+ };
46
+
41
47
  this.pick = ({ event, value }) =>
42
48
  {
43
49
  this.value = value;
50
+ this.sync();
44
51
 
45
- if (this._input)
52
+ if(this._input)
46
53
  {
47
54
  this._input({ event, value });
48
55
  }
56
+
57
+ if(this._change)
58
+ {
59
+ this._change({ event, value });
60
+ }
49
61
  };
50
62
 
51
63
  this.commit = ({ event, value }) =>
52
64
  {
53
65
  this.value = value;
66
+ this.sync();
54
67
 
55
- if (this._change)
68
+ if(this._change)
56
69
  {
57
70
  this._change({ event, value });
58
71
  }
@@ -62,14 +75,15 @@ onetype.AddonReady('elements', (elements) =>
62
75
  {
63
76
  let hex = value.trim();
64
77
 
65
- if (hex && hex.charAt(0) !== '#')
78
+ if(hex && hex.charAt(0) !== '#')
66
79
  {
67
80
  hex = '#' + hex;
68
81
  }
69
82
 
70
83
  this.value = hex;
84
+ this.sync();
71
85
 
72
- if (this._change)
86
+ if(this._change)
73
87
  {
74
88
  this._change({ event, value: hex });
75
89
  }
@@ -88,6 +102,7 @@ onetype.AddonReady('elements', (elements) =>
88
102
  this.clear = () =>
89
103
  {
90
104
  this.value = '';
105
+ this.sync();
91
106
 
92
107
  if (this._change)
93
108
  {
@@ -97,12 +112,12 @@ onetype.AddonReady('elements', (elements) =>
97
112
 
98
113
  return `
99
114
  <div :class="'holder ' + variant.join(' ')">
100
- <input type="hidden" :name="name" :value="value" />
101
- <button class="swatch" :style="'background: ' + (value || 'transparent')" ot-click="open" :disabled="disabled">
115
+ <div class="swatch" :style="'background: ' + (value || 'transparent')" ot-click="open" :disabled="disabled">
102
116
  <input class="native" type="color" :value="value" ot-input="pick" ot-change="commit" tabindex="-1" />
103
- </button>
117
+ </div>
104
118
  <input
105
119
  class="input"
120
+ :name="name"
106
121
  type="text"
107
122
  :value="value"
108
123
  :placeholder="placeholder"
@@ -112,9 +127,9 @@ onetype.AddonReady('elements', (elements) =>
112
127
  spellcheck="false"
113
128
  ot-change="input"
114
129
  />
115
- <button ot-if="value && !disabled" class="clear" ot-click.stop="clear">
130
+ <div ot-if="value && !disabled" class="clear" ot-click.stop="clear">
116
131
  <i>close</i>
117
- </button>
132
+ </div>
118
133
  </div>
119
134
  `;
120
135
  }
@@ -0,0 +1,410 @@
1
+ /* Root */
2
+
3
+ .e-72b9255c
4
+ {
5
+ display: block;
6
+ width: 100%;
7
+ }
8
+
9
+ /* Holder */
10
+
11
+ .e-72b9255c > .holder
12
+ {
13
+ display: flex;
14
+ flex-direction: column;
15
+ background: var(--ot-bg-1);
16
+ border: 1px solid var(--ot-bg-1-border);
17
+ border-radius: var(--ot-radius-l);
18
+ overflow: hidden;
19
+ }
20
+
21
+ /* Toolbar */
22
+
23
+ .e-72b9255c > .holder > .toolbar
24
+ {
25
+ display: flex;
26
+ align-items: center;
27
+ gap: 2px;
28
+ padding: 10px 16px;
29
+ border-bottom: 1px solid var(--ot-bg-1-border);
30
+ background: var(--ot-bg-1);
31
+ flex-wrap: wrap;
32
+ }
33
+
34
+ .e-72b9255c > .holder > .toolbar .btn
35
+ {
36
+ width: 34px;
37
+ height: 34px;
38
+ border-radius: 8px;
39
+ display: flex;
40
+ align-items: center;
41
+ justify-content: center;
42
+ color: var(--ot-text-2);
43
+ background: none;
44
+ border: none;
45
+ cursor: pointer;
46
+ transition: background 0.15s ease, color 0.15s ease;
47
+ }
48
+
49
+ .e-72b9255c > .holder > .toolbar .btn:hover
50
+ {
51
+ background: var(--ot-bg-3);
52
+ color: var(--ot-text-1);
53
+ }
54
+
55
+ .e-72b9255c > .holder > .toolbar .btn > i
56
+ {
57
+ font-size: 18px;
58
+ }
59
+
60
+ .e-72b9255c > .holder > .toolbar .sep
61
+ {
62
+ width: 1px;
63
+ height: 22px;
64
+ background: var(--ot-bg-1-border);
65
+ margin: 0 6px;
66
+ }
67
+
68
+ /* Cover */
69
+
70
+ .e-72b9255c > .holder > .cover
71
+ {
72
+ width: 100%;
73
+ height: 320px;
74
+ background-size: cover;
75
+ background-position: center;
76
+ position: relative;
77
+ }
78
+
79
+ .e-72b9255c > .holder > .cover > .change
80
+ {
81
+ position: absolute;
82
+ bottom: 16px;
83
+ right: 16px;
84
+ display: inline-flex;
85
+ align-items: center;
86
+ gap: 6px;
87
+ padding: 8px 16px;
88
+ background: rgba(255, 255, 255, 0.95);
89
+ backdrop-filter: blur(10px);
90
+ border: none;
91
+ border-radius: 100px;
92
+ font-size: 12px;
93
+ font-weight: 600;
94
+ color: var(--ot-text-1);
95
+ cursor: pointer;
96
+ transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1);
97
+ }
98
+
99
+ .e-72b9255c > .holder > .cover > .change:hover
100
+ {
101
+ transform: translateY(-1px);
102
+ }
103
+
104
+ .e-72b9255c > .holder > .cover > .change > i
105
+ {
106
+ font-size: 15px;
107
+ }
108
+
109
+ .e-72b9255c > .holder > .cover-empty
110
+ {
111
+ width: 100%;
112
+ height: 160px;
113
+ display: flex;
114
+ align-items: center;
115
+ justify-content: center;
116
+ gap: 8px;
117
+ background: var(--ot-bg-2);
118
+ border-bottom: 1px solid var(--ot-bg-1-border);
119
+ color: var(--ot-text-3);
120
+ font-size: 13px;
121
+ cursor: pointer;
122
+ transition: background 0.15s ease, color 0.15s ease;
123
+ }
124
+
125
+ .e-72b9255c > .holder > .cover-empty:hover
126
+ {
127
+ background: var(--ot-bg-3);
128
+ color: var(--ot-text-2);
129
+ }
130
+
131
+ .e-72b9255c > .holder > .cover-empty > i
132
+ {
133
+ font-size: 22px;
134
+ }
135
+
136
+ /* Content */
137
+
138
+ .e-72b9255c > .holder > .content
139
+ {
140
+ padding: 40px 64px 60px;
141
+ max-width: 800px;
142
+ margin: 0 auto;
143
+ width: 100%;
144
+ }
145
+
146
+ /* Title */
147
+
148
+ .e-72b9255c > .holder > .content > .title-area
149
+ {
150
+ margin-bottom: 32px;
151
+ }
152
+
153
+ .e-72b9255c > .holder > .content > .title-area > .title-input
154
+ {
155
+ width: 100%;
156
+ font-family: var(--ot-font-secondary);
157
+ font-size: 42px;
158
+ font-weight: 500;
159
+ line-height: 1.1;
160
+ letter-spacing: -0.025em;
161
+ color: var(--ot-text-1);
162
+ border: none;
163
+ outline: none;
164
+ background: transparent;
165
+ margin-bottom: 12px;
166
+ font-variation-settings: 'opsz' 144;
167
+ }
168
+
169
+ .e-72b9255c > .holder > .content > .title-area > .title-input::placeholder
170
+ {
171
+ color: var(--ot-text-3);
172
+ }
173
+
174
+ .e-72b9255c > .holder > .content > .title-area > .subtitle-input
175
+ {
176
+ width: 100%;
177
+ font-family: var(--ot-font-secondary);
178
+ font-size: 19px;
179
+ font-style: italic;
180
+ font-weight: 400;
181
+ color: var(--ot-text-2);
182
+ border: none;
183
+ outline: none;
184
+ background: transparent;
185
+ }
186
+
187
+ .e-72b9255c > .holder > .content > .title-area > .subtitle-input::placeholder
188
+ {
189
+ color: var(--ot-text-3);
190
+ }
191
+
192
+ /* Body */
193
+
194
+ .e-72b9255c > .holder > .content > .body
195
+ {
196
+ font-family: var(--ot-font-primary);
197
+ font-size: 14px;
198
+ line-height: 1.75;
199
+ color: var(--ot-text-1);
200
+ outline: none;
201
+ min-height: 200px;
202
+ }
203
+
204
+ .e-72b9255c > .holder > .content > .body:empty::before
205
+ {
206
+ content: attr(data-placeholder);
207
+ color: var(--ot-text-3);
208
+ pointer-events: none;
209
+ }
210
+
211
+ .e-72b9255c > .holder > .content > .body > *:first-child
212
+ {
213
+ margin-top: 0;
214
+ }
215
+
216
+ .e-72b9255c > .holder > .content > .body > *:last-child
217
+ {
218
+ margin-bottom: 0;
219
+ }
220
+
221
+ /* Headings */
222
+
223
+ .e-72b9255c > .holder > .content > .body :is(h1, h2, h3, h4, h5, h6)
224
+ {
225
+ font-family: var(--ot-font-secondary);
226
+ font-weight: 500;
227
+ letter-spacing: -0.02em;
228
+ color: var(--ot-text-1);
229
+ font-variation-settings: 'opsz' 144;
230
+ line-height: 1.15;
231
+ }
232
+
233
+ .e-72b9255c > .holder > .content > .body h1 { font-size: 2.25em; margin: 0 0 0.9em; }
234
+ .e-72b9255c > .holder > .content > .body h2 { font-size: 1.5em; margin: 1em 0 0.75em; }
235
+ .e-72b9255c > .holder > .content > .body h3 { font-size: 1.25em; margin: 1.6em 0 0.6em; }
236
+ .e-72b9255c > .holder > .content > .body h4 { font-size: 1.1em; margin: 1.5em 0 0.5em; }
237
+
238
+ .e-72b9255c > .holder > .content > .body :is(h1, h2, h3, h4) + :is(h1, h2, h3, h4)
239
+ {
240
+ margin-top: 0;
241
+ }
242
+
243
+ .e-72b9255c > .holder > .content > .body em
244
+ {
245
+ font-style: italic;
246
+ color: var(--ot-brand);
247
+ }
248
+
249
+ /* Paragraphs */
250
+
251
+ .e-72b9255c > .holder > .content > .body p
252
+ {
253
+ margin: 0 0 1.25em;
254
+ color: var(--ot-text-2);
255
+ line-height: 1.75;
256
+ }
257
+
258
+ .e-72b9255c > .holder > .content > .body > p:first-child
259
+ {
260
+ color: var(--ot-text-1);
261
+ }
262
+
263
+ /* Links */
264
+
265
+ .e-72b9255c > .holder > .content > .body a
266
+ {
267
+ color: var(--ot-brand);
268
+ text-decoration: underline;
269
+ text-decoration-color: var(--ot-brand-opacity);
270
+ text-underline-offset: 3px;
271
+ transition: text-decoration-color 0.2s;
272
+ }
273
+
274
+ .e-72b9255c > .holder > .content > .body a:hover
275
+ {
276
+ text-decoration-color: var(--ot-brand);
277
+ }
278
+
279
+ /* Strong */
280
+
281
+ .e-72b9255c > .holder > .content > .body strong
282
+ {
283
+ font-weight: 700;
284
+ color: var(--ot-text-1);
285
+ }
286
+
287
+ /* Lists */
288
+
289
+ .e-72b9255c > .holder > .content > .body :is(ul, ol)
290
+ {
291
+ margin: 0 0 1.25em;
292
+ padding-left: 1.6em;
293
+ }
294
+
295
+ .e-72b9255c > .holder > .content > .body ul { list-style: disc; }
296
+ .e-72b9255c > .holder > .content > .body ol { list-style: decimal; }
297
+
298
+ .e-72b9255c > .holder > .content > .body li
299
+ {
300
+ margin: 0 0 0.5em;
301
+ color: var(--ot-text-2);
302
+ }
303
+
304
+ .e-72b9255c > .holder > .content > .body li:last-child
305
+ {
306
+ margin-bottom: 0;
307
+ }
308
+
309
+ /* Blockquote */
310
+
311
+ .e-72b9255c > .holder > .content > .body blockquote
312
+ {
313
+ margin: 1.6em 0;
314
+ padding: 0.25em 0 0.25em 1.2em;
315
+ border-left: 3px solid var(--ot-brand);
316
+ font-family: var(--ot-font-secondary);
317
+ font-size: 1.3em;
318
+ font-style: italic;
319
+ line-height: 1.45;
320
+ color: var(--ot-text-1);
321
+ font-variation-settings: 'opsz' 144;
322
+ }
323
+
324
+ .e-72b9255c > .holder > .content > .body blockquote p
325
+ {
326
+ margin: 0;
327
+ color: inherit;
328
+ }
329
+
330
+ /* Code */
331
+
332
+ .e-72b9255c > .holder > .content > .body code
333
+ {
334
+ font-family: ui-monospace, 'SF Mono', Menlo, monospace;
335
+ font-size: 0.9em;
336
+ padding: 0.15em 0.4em;
337
+ border-radius: 4px;
338
+ background: var(--ot-bg-2);
339
+ border: 1px solid var(--ot-bg-2-border);
340
+ color: var(--ot-text-1);
341
+ }
342
+
343
+ .e-72b9255c > .holder > .content > .body pre
344
+ {
345
+ margin: 1.7em 0;
346
+ padding: 1.1em 1.3em;
347
+ border-radius: var(--ot-radius-m);
348
+ background: var(--ot-bg-2);
349
+ border: 1px solid var(--ot-bg-2-border);
350
+ overflow-x: auto;
351
+ font-family: ui-monospace, 'SF Mono', Menlo, monospace;
352
+ font-size: 0.9em;
353
+ line-height: 1.6;
354
+ }
355
+
356
+ .e-72b9255c > .holder > .content > .body pre > code
357
+ {
358
+ background: transparent;
359
+ border: none;
360
+ padding: 0;
361
+ }
362
+
363
+ /* Images */
364
+
365
+ .e-72b9255c > .holder > .content > .body img
366
+ {
367
+ display: block;
368
+ width: 100%;
369
+ height: auto;
370
+ border-radius: var(--ot-radius-l);
371
+ margin: 2em 0 0.5em;
372
+ }
373
+
374
+ .e-72b9255c > .holder > .content > .body img + em
375
+ {
376
+ display: block;
377
+ font-size: 0.85em;
378
+ font-style: italic;
379
+ color: var(--ot-text-3);
380
+ text-align: center;
381
+ margin-bottom: 2em;
382
+ }
383
+
384
+ /* HR */
385
+
386
+ .e-72b9255c > .holder > .content > .body hr
387
+ {
388
+ border: none;
389
+ height: 1px;
390
+ background: var(--ot-bg-2-border);
391
+ margin: 3em 0;
392
+ }
393
+
394
+ /* Compact */
395
+
396
+ .e-72b9255c > .holder.compact > .content
397
+ {
398
+ padding: 24px;
399
+ }
400
+
401
+ .e-72b9255c > .holder.compact > .content > .title-area > .title-input
402
+ {
403
+ font-size: 28px;
404
+ }
405
+
406
+ .e-72b9255c > .holder.compact > .content > .body
407
+ {
408
+ font-size: 14px;
409
+ min-height: 120px;
410
+ }
@@ -0,0 +1,191 @@
1
+ onetype.AddonReady('elements', (elements) =>
2
+ {
3
+ elements.ItemAdd({
4
+ id: 'form-editor-markdown',
5
+ icon: 'edit_note',
6
+ name: 'Markdown Editor',
7
+ description: 'WYSIWYG markdown editor with toolbar, cover image, title, and body.',
8
+ category: 'Form',
9
+ author: 'OneType',
10
+ config: {
11
+ value: {
12
+ type: 'string',
13
+ value: ''
14
+ },
15
+ title: {
16
+ type: 'string',
17
+ value: ''
18
+ },
19
+ subtitle: {
20
+ type: 'string',
21
+ value: ''
22
+ },
23
+ cover: {
24
+ type: 'string',
25
+ value: ''
26
+ },
27
+ placeholder: {
28
+ type: 'string',
29
+ value: 'Start writing…'
30
+ },
31
+ name: {
32
+ type: 'string',
33
+ value: ''
34
+ },
35
+ variant: {
36
+ type: 'array',
37
+ value: [],
38
+ options: ['compact', 'no-toolbar', 'no-cover', 'no-title']
39
+ },
40
+ _change: {
41
+ type: 'function'
42
+ }
43
+ },
44
+ render: function()
45
+ {
46
+ this.tools = [
47
+ { cmd: 'bold', icon: 'format_bold', label: 'Bold' },
48
+ { cmd: 'italic', icon: 'format_italic', label: 'Italic' },
49
+ { cmd: 'underline', icon: 'format_underlined', label: 'Underline' },
50
+ { sep: true },
51
+ { cmd: 'heading1', icon: 'title', label: 'Heading 1' },
52
+ { cmd: 'heading2', icon: 'text_fields', label: 'Heading 2' },
53
+ { cmd: 'blockquote', icon: 'format_quote', label: 'Quote' },
54
+ { sep: true },
55
+ { cmd: 'insertUnorderedList', icon: 'format_list_bulleted', label: 'Bullet list' },
56
+ { cmd: 'insertOrderedList', icon: 'format_list_numbered', label: 'Numbered list' },
57
+ { sep: true },
58
+ { cmd: 'link', icon: 'link', label: 'Link' },
59
+ { cmd: 'image', icon: 'image', label: 'Image' },
60
+ { sep: true },
61
+ { cmd: 'undo', icon: 'undo', label: 'Undo' },
62
+ { cmd: 'redo', icon: 'redo', label: 'Redo' }
63
+ ];
64
+
65
+ this.exec = (cmd) =>
66
+ {
67
+ if(cmd === 'heading1')
68
+ {
69
+ document.execCommand('formatBlock', false, 'h2');
70
+ }
71
+ else if(cmd === 'heading2')
72
+ {
73
+ document.execCommand('formatBlock', false, 'h3');
74
+ }
75
+ else if(cmd === 'blockquote')
76
+ {
77
+ document.execCommand('formatBlock', false, 'blockquote');
78
+ }
79
+ else if(cmd === 'link')
80
+ {
81
+ const url = prompt('Enter URL:');
82
+ if(url) document.execCommand('createLink', false, url);
83
+ }
84
+ else if(cmd === 'image')
85
+ {
86
+ const url = prompt('Enter image URL:');
87
+ if(url) document.execCommand('insertImage', false, url);
88
+ }
89
+ else
90
+ {
91
+ document.execCommand(cmd, false, null);
92
+ }
93
+ };
94
+
95
+ this.changeCover = () =>
96
+ {
97
+ const url = prompt('Enter cover image URL:', this.cover);
98
+ if(url !== null) this.cover = url;
99
+ };
100
+
101
+ this.hasCover = !this.variant.includes('no-cover');
102
+ this.hasTitle = !this.variant.includes('no-title');
103
+ this.hasToolbar = !this.variant.includes('no-toolbar');
104
+
105
+ this.OnReady(() =>
106
+ {
107
+ const body = this.Element.querySelector('.body');
108
+
109
+ if(body && this.value)
110
+ {
111
+ body.innerHTML = onetype.Markdown ? onetype.Markdown(this.value) : this.value;
112
+ }
113
+
114
+ const hidden = this.Element.querySelector('input.hidden');
115
+
116
+ if(body)
117
+ {
118
+ body.addEventListener('input', () =>
119
+ {
120
+ if(hidden) hidden.value = body.innerHTML;
121
+
122
+ if(this._change)
123
+ {
124
+ this._change({
125
+ value: body.innerHTML,
126
+ title: this.title,
127
+ subtitle: this.subtitle,
128
+ cover: this.cover
129
+ });
130
+ }
131
+ });
132
+ }
133
+
134
+ this.Element.querySelectorAll('.toolbar .btn').forEach(btn =>
135
+ {
136
+ btn.addEventListener('mousedown', (e) =>
137
+ {
138
+ e.preventDefault();
139
+ const cmd = btn.getAttribute('data-cmd');
140
+ if(cmd) this.exec(cmd);
141
+ });
142
+ });
143
+ });
144
+
145
+ this.changeTitle = ({ value }) =>
146
+ {
147
+ this.title = value;
148
+ };
149
+
150
+ this.changeSubtitle = ({ value }) =>
151
+ {
152
+ this.subtitle = value;
153
+ };
154
+
155
+ return /* html */ `
156
+ <div :class="'holder ' + variant.join(' ')">
157
+ <input ot-if="name" class="hidden" type="hidden" :name="name" :value="value" />
158
+ <div ot-if="hasToolbar" class="toolbar">
159
+ <div ot-for="tool in tools">
160
+ <div ot-if="tool.sep" class="sep"></div>
161
+ <button ot-if="!tool.sep" class="btn" :data-cmd="tool.cmd">
162
+ <i>{{ tool.icon }}</i>
163
+ </button>
164
+ </div>
165
+ </div>
166
+
167
+ <div ot-if="hasCover && cover" class="cover" :style="'background-image: url(' + cover + ')'">
168
+ <button class="change" ot-click="changeCover">
169
+ <i>photo_camera</i>
170
+ <span>Change cover</span>
171
+ </button>
172
+ </div>
173
+
174
+ <div ot-if="hasCover && !cover" class="cover-empty" ot-click="changeCover">
175
+ <i>add_photo_alternate</i>
176
+ <span>Add cover image</span>
177
+ </div>
178
+
179
+ <div class="content">
180
+ <div ot-if="hasTitle" class="title-area">
181
+ <input class="title-input" type="text" :value="title" :placeholder="'Title'" ot-input="changeTitle" />
182
+ <input class="subtitle-input" type="text" :value="subtitle" :placeholder="'Subtitle (optional)'" ot-input="changeSubtitle" />
183
+ </div>
184
+
185
+ <div class="body" contenteditable="true" :data-placeholder="placeholder"></div>
186
+ </div>
187
+ </div>
188
+ `;
189
+ }
190
+ });
191
+ });