@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
@@ -0,0 +1,134 @@
1
+ onetype.AddonReady('elements', (elements) =>
2
+ {
3
+ elements.ItemAdd({
4
+ id: 'navigation-dock',
5
+ icon: 'dock_to_right',
6
+ name: 'Dock',
7
+ description: 'Slim icon rail with grouped navigation, logo, badges and tooltips.',
8
+ category: 'Navigation',
9
+ author: 'OneType',
10
+ config: {
11
+ logo: {
12
+ type: 'string'
13
+ },
14
+ groups: {
15
+ type: 'array',
16
+ value: [],
17
+ each: {
18
+ type: 'object',
19
+ config: {
20
+ placement: { type: 'string', value: 'top', options: ['top', 'bottom'] },
21
+ items: {
22
+ type: 'array',
23
+ value: [],
24
+ each: {
25
+ type: 'object',
26
+ config: {
27
+ icon: { type: 'string' },
28
+ label: { type: 'string' },
29
+ href: { type: 'string' },
30
+ match: { type: 'string' },
31
+ badge: { type: 'string|number' }
32
+ }
33
+ }
34
+ }
35
+ }
36
+ }
37
+ },
38
+ variant: {
39
+ type: 'array',
40
+ value: ['bg-2', 'border-right'],
41
+ options: ['bg-1', 'bg-2', 'bg-3', 'bg-4', 'border', 'border-top', 'border-right', 'border-bottom', 'border-left']
42
+ },
43
+ _click: {
44
+ type: 'function'
45
+ }
46
+ },
47
+ render: function()
48
+ {
49
+ const path = onetype.RouteCurrent();
50
+
51
+ this.isActive = (item) =>
52
+ {
53
+ const match = item.match || item.href;
54
+
55
+ if(!match)
56
+ {
57
+ return false;
58
+ }
59
+
60
+ if(match === '/')
61
+ {
62
+ return path === '/';
63
+ }
64
+
65
+ return path.startsWith(match);
66
+ };
67
+
68
+ this.compute = (groups) =>
69
+ {
70
+ return (groups || [])
71
+ .filter(group => group.items && group.items.length)
72
+ .map(group => ({
73
+ ...group,
74
+ items: group.items.map(item => ({ ...item, active: this.isActive(item) }))
75
+ }));
76
+ };
77
+
78
+ this.top = this.compute(this.groups.filter(group => (group.placement || 'top') === 'top'));
79
+ this.bottom = this.compute(this.groups.filter(group => group.placement === 'bottom'));
80
+
81
+ this.handle = (item, event) =>
82
+ {
83
+ if(this._click)
84
+ {
85
+ this._click({ event, value: item });
86
+ }
87
+ };
88
+
89
+ return /* html */ `
90
+ <aside :class="'holder ' + variant.join(' ')">
91
+ <a ot-if="logo" class="logo" href="/">
92
+ <img :src="logo" alt="" />
93
+ </a>
94
+
95
+ <div class="stack">
96
+ <div ot-for="group, groupIndex in top">
97
+ <div ot-if="groupIndex > 0 || logo" class="separator"></div>
98
+ <div class="group">
99
+ <a
100
+ ot-for="item in group.items"
101
+ :class="'item' + (item.active ? ' active' : '')"
102
+ :href="item.href || 'javascript:void(0)'"
103
+ :ot-tooltip="item.label ? { text: item.label, position: { x: 'right', y: 'center' } } : null"
104
+ ot-click="(event) => handle(item, event)"
105
+ >
106
+ <i>{{ item.icon }}</i>
107
+ <span ot-if="item.badge" class="badge">{{ item.badge }}</span>
108
+ </a>
109
+ </div>
110
+ </div>
111
+ </div>
112
+
113
+ <div ot-if="bottom.length" class="stack bottom">
114
+ <div ot-for="group, groupIndex in bottom">
115
+ <div ot-if="groupIndex > 0" class="separator"></div>
116
+ <div class="group">
117
+ <a
118
+ ot-for="item in group.items"
119
+ :class="'item' + (item.active ? ' active' : '')"
120
+ :href="item.href || 'javascript:void(0)'"
121
+ :ot-tooltip="item.label ? { text: item.label, position: { x: 'right', y: 'center' } } : null"
122
+ ot-click="(event) => handle(item, event)"
123
+ >
124
+ <i>{{ item.icon }}</i>
125
+ <span ot-if="item.badge" class="badge">{{ item.badge }}</span>
126
+ </a>
127
+ </div>
128
+ </div>
129
+ </div>
130
+ </aside>
131
+ `;
132
+ }
133
+ });
134
+ });
@@ -0,0 +1,356 @@
1
+ /* Root */
2
+
3
+ .e-71bcd7e2
4
+ {
5
+ display: block;
6
+ width: 100%;
7
+ }
8
+
9
+ /* Holder */
10
+
11
+ .e-71bcd7e2 > .holder
12
+ {
13
+ display: flex;
14
+ flex-direction: column;
15
+ width: 100%;
16
+ background: var(--ot-bg-1);
17
+ border-top: 1px solid transparent;
18
+ padding: var(--ot-spacing-l) var(--ot-spacing-l) var(--ot-spacing-m);
19
+ }
20
+
21
+ /* Background variants */
22
+
23
+ .e-71bcd7e2 > .holder.bg-1 { background: var(--ot-bg-1); }
24
+ .e-71bcd7e2 > .holder.bg-2 { background: var(--ot-bg-2); }
25
+ .e-71bcd7e2 > .holder.bg-3 { background: var(--ot-bg-3); }
26
+ .e-71bcd7e2 > .holder.bg-4 { background: var(--ot-bg-4); }
27
+
28
+ .e-71bcd7e2 > .holder.border-top
29
+ {
30
+ border-top-color: var(--ot-bg-2-border);
31
+ }
32
+
33
+ .e-71bcd7e2 > .holder.bg-1.border-top { border-top-color: var(--ot-bg-1-border); }
34
+ .e-71bcd7e2 > .holder.bg-2.border-top { border-top-color: var(--ot-bg-2-border); }
35
+ .e-71bcd7e2 > .holder.bg-3.border-top { border-top-color: var(--ot-bg-3-border); }
36
+ .e-71bcd7e2 > .holder.bg-4.border-top { border-top-color: var(--ot-bg-4-border); }
37
+
38
+ .e-71bcd7e2 > .holder.clean
39
+ {
40
+ background: transparent !important;
41
+ border-top-color: transparent !important;
42
+ }
43
+
44
+ /* ===== TOP SLOT ===== */
45
+
46
+ .e-71bcd7e2 > .holder > .top-slot
47
+ {
48
+ margin-bottom: var(--ot-spacing-l);
49
+ padding-bottom: var(--ot-spacing-l);
50
+ border-bottom: 1px solid var(--ot-bg-2-border);
51
+ }
52
+
53
+ /* ===== MAIN ===== */
54
+
55
+ .e-71bcd7e2 > .holder > .main
56
+ {
57
+ display: grid;
58
+ grid-template-columns: minmax(280px, 1.2fr) 3fr;
59
+ gap: var(--ot-spacing-l);
60
+ width: 100%;
61
+ }
62
+
63
+ /* ===== BRAND COLUMN ===== */
64
+
65
+ .e-71bcd7e2 > .holder > .main > .brand-col
66
+ {
67
+ display: flex;
68
+ flex-direction: column;
69
+ gap: var(--ot-spacing-m);
70
+ min-width: 0;
71
+ }
72
+
73
+ .e-71bcd7e2 > .holder > .main > .brand-col > .brand
74
+ {
75
+ display: inline-flex;
76
+ align-items: center;
77
+ text-decoration: none;
78
+ color: inherit;
79
+ }
80
+
81
+ .e-71bcd7e2 > .holder > .main > .brand-col > .brand > .brand-logo
82
+ {
83
+ display: block;
84
+ height: 28px;
85
+ width: auto;
86
+ }
87
+
88
+ .e-71bcd7e2 > .holder > .main > .brand-col > .tagline
89
+ {
90
+ margin: 0;
91
+ max-width: 340px;
92
+ font-family: var(--ot-font-primary);
93
+ font-size: var(--ot-size-s);
94
+ color: var(--ot-text-2);
95
+ line-height: 1.6;
96
+ }
97
+
98
+ /* Newsletter */
99
+
100
+ .e-71bcd7e2 > .holder > .main > .brand-col > .newsletter
101
+ {
102
+ display: flex;
103
+ flex-direction: column;
104
+ gap: var(--ot-spacing-s);
105
+ padding: var(--ot-spacing-m);
106
+ background: var(--ot-bg-2);
107
+ border: 1px solid var(--ot-bg-2-border);
108
+ border-radius: var(--ot-radius-m);
109
+ max-width: 420px;
110
+ }
111
+
112
+ .e-71bcd7e2 > .holder > .main > .brand-col > .newsletter > .newsletter-text
113
+ {
114
+ display: flex;
115
+ flex-direction: column;
116
+ gap: 2px;
117
+ }
118
+
119
+ .e-71bcd7e2 > .holder > .main > .brand-col > .newsletter > .newsletter-text > .newsletter-title
120
+ {
121
+ margin: 0;
122
+ font-family: var(--ot-font-secondary);
123
+ font-size: 16px;
124
+ font-weight: 600;
125
+ color: var(--ot-text-1);
126
+ letter-spacing: -0.01em;
127
+ }
128
+
129
+ .e-71bcd7e2 > .holder > .main > .brand-col > .newsletter > .newsletter-text > .newsletter-description
130
+ {
131
+ margin: 0;
132
+ font-family: var(--ot-font-primary);
133
+ font-size: var(--ot-size-s);
134
+ color: var(--ot-text-3);
135
+ line-height: 1.5;
136
+ }
137
+
138
+ .e-71bcd7e2 > .holder > .main > .brand-col > .newsletter > .newsletter-form
139
+ {
140
+ display: flex;
141
+ align-items: center;
142
+ gap: var(--ot-spacing-s);
143
+ flex-wrap: wrap;
144
+ }
145
+
146
+ .e-71bcd7e2 > .holder > .main > .brand-col > .newsletter > .newsletter-form > e-form-input
147
+ {
148
+ flex: 1 1 200px;
149
+ min-width: 0;
150
+ }
151
+
152
+ /* ===== GROUPS ===== */
153
+
154
+ .e-71bcd7e2 > .holder > .main > .groups
155
+ {
156
+ display: grid;
157
+ grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
158
+ gap: var(--ot-spacing-l);
159
+ align-content: start;
160
+ }
161
+
162
+ .e-71bcd7e2 > .holder > .main > .groups > .group
163
+ {
164
+ display: flex;
165
+ flex-direction: column;
166
+ gap: var(--ot-spacing-s);
167
+ min-width: 0;
168
+ }
169
+
170
+ .e-71bcd7e2 > .holder > .main > .groups > .group > .group-title
171
+ {
172
+ margin: 0 0 4px;
173
+ font-family: var(--ot-font-primary);
174
+ font-size: 11px;
175
+ font-weight: 700;
176
+ color: var(--ot-text-3);
177
+ text-transform: uppercase;
178
+ letter-spacing: 0.08em;
179
+ }
180
+
181
+ .e-71bcd7e2 > .holder > .main > .groups > .group > .group-list
182
+ {
183
+ list-style: none;
184
+ padding: 0;
185
+ margin: 0;
186
+ display: flex;
187
+ flex-direction: column;
188
+ gap: 2px;
189
+ }
190
+
191
+ .e-71bcd7e2 > .holder > .main > .groups > .group > .group-list .group-link
192
+ {
193
+ display: inline-flex;
194
+ align-items: center;
195
+ gap: 6px;
196
+ padding: 4px 0;
197
+ font-family: var(--ot-font-primary);
198
+ font-size: var(--ot-size-s);
199
+ font-weight: 500;
200
+ color: var(--ot-text-2);
201
+ text-decoration: none;
202
+ transition: color 0.15s cubic-bezier(0.22, 1, 0.36, 1);
203
+ }
204
+
205
+ .e-71bcd7e2 > .holder > .main > .groups > .group > .group-list .group-link:hover
206
+ {
207
+ color: var(--ot-text-1);
208
+ }
209
+
210
+ .e-71bcd7e2 > .holder > .main > .groups > .group > .group-list .group-link > i
211
+ {
212
+ font-size: 16px;
213
+ color: var(--ot-text-3);
214
+ }
215
+
216
+ .e-71bcd7e2 > .holder > .main > .groups > .group > .group-list .group-link > .group-badge
217
+ {
218
+ display: inline-flex;
219
+ align-items: center;
220
+ padding: 1px 6px;
221
+ background: var(--ot-brand-opacity);
222
+ color: var(--ot-brand);
223
+ border-radius: 100px;
224
+ font-size: 9px;
225
+ font-weight: 700;
226
+ text-transform: uppercase;
227
+ letter-spacing: 0.04em;
228
+ }
229
+
230
+ /* ===== BOTTOM BAR ===== */
231
+
232
+ .e-71bcd7e2 > .holder > .bottom
233
+ {
234
+ display: flex;
235
+ align-items: center;
236
+ gap: var(--ot-spacing-m);
237
+ flex-wrap: wrap;
238
+ margin-top: var(--ot-spacing-l);
239
+ padding-top: var(--ot-spacing-m);
240
+ border-top: 1px solid var(--ot-bg-2-border);
241
+ }
242
+
243
+ .e-71bcd7e2 > .holder > .bottom > .copyright
244
+ {
245
+ font-family: var(--ot-font-primary);
246
+ font-size: var(--ot-size-s);
247
+ color: var(--ot-text-3);
248
+ }
249
+
250
+ .e-71bcd7e2 > .holder > .bottom > .legal
251
+ {
252
+ display: flex;
253
+ align-items: center;
254
+ gap: var(--ot-spacing-s);
255
+ flex-wrap: wrap;
256
+ }
257
+
258
+ .e-71bcd7e2 > .holder > .bottom > .legal > .legal-link
259
+ {
260
+ font-family: var(--ot-font-primary);
261
+ font-size: var(--ot-size-s);
262
+ font-weight: 500;
263
+ color: var(--ot-text-3);
264
+ text-decoration: none;
265
+ transition: color 0.15s cubic-bezier(0.22, 1, 0.36, 1);
266
+ }
267
+
268
+ .e-71bcd7e2 > .holder > .bottom > .legal > .legal-link:hover
269
+ {
270
+ color: var(--ot-text-1);
271
+ }
272
+
273
+ .e-71bcd7e2 > .holder > .bottom > .legal > .legal-link:not(:last-child)::after
274
+ {
275
+ content: '·';
276
+ margin-left: var(--ot-spacing-s);
277
+ color: var(--ot-text-3);
278
+ opacity: 0.5;
279
+ }
280
+
281
+ .e-71bcd7e2 > .holder > .bottom > .social
282
+ {
283
+ display: flex;
284
+ align-items: center;
285
+ gap: 4px;
286
+ margin-left: auto;
287
+ }
288
+
289
+ .e-71bcd7e2 > .holder > .bottom > .social > .social-link
290
+ {
291
+ display: inline-flex;
292
+ align-items: center;
293
+ justify-content: center;
294
+ width: 34px;
295
+ height: 34px;
296
+ border-radius: var(--ot-radius-s);
297
+ background: transparent;
298
+ color: var(--ot-text-2);
299
+ text-decoration: none;
300
+ transition: background 0.2s cubic-bezier(0.22, 1, 0.36, 1), color 0.2s cubic-bezier(0.22, 1, 0.36, 1), transform 0.2s cubic-bezier(0.22, 1, 0.36, 1);
301
+ }
302
+
303
+ .e-71bcd7e2 > .holder > .bottom > .social > .social-link:hover
304
+ {
305
+ background: var(--ot-bg-2);
306
+ color: var(--ot-brand);
307
+ transform: translateY(-1px);
308
+ }
309
+
310
+ .e-71bcd7e2 > .holder > .bottom > .social > .social-link > i
311
+ {
312
+ font-size: 18px;
313
+ }
314
+
315
+ /* ===== BOTTOM SLOT ===== */
316
+
317
+ .e-71bcd7e2 > .holder > .bottom-slot
318
+ {
319
+ margin-top: var(--ot-spacing-m);
320
+ padding-top: var(--ot-spacing-m);
321
+ border-top: 1px solid var(--ot-bg-2-border);
322
+ }
323
+
324
+ /* ===== RESPONSIVE ===== */
325
+
326
+ @media (max-width: 900px)
327
+ {
328
+ .e-71bcd7e2 > .holder > .main
329
+ {
330
+ grid-template-columns: 1fr;
331
+ }
332
+
333
+ .e-71bcd7e2 > .holder > .main > .groups
334
+ {
335
+ grid-template-columns: repeat(2, 1fr);
336
+ }
337
+
338
+ .e-71bcd7e2 > .holder > .bottom
339
+ {
340
+ flex-direction: column;
341
+ align-items: flex-start;
342
+ }
343
+
344
+ .e-71bcd7e2 > .holder > .bottom > .social
345
+ {
346
+ margin-left: 0;
347
+ }
348
+ }
349
+
350
+ @media (max-width: 560px)
351
+ {
352
+ .e-71bcd7e2 > .holder > .main > .groups
353
+ {
354
+ grid-template-columns: 1fr;
355
+ }
356
+ }
@@ -0,0 +1,219 @@
1
+ onetype.AddonReady('elements', (elements) =>
2
+ {
3
+ elements.ItemAdd({
4
+ id: 'navigation-footer',
5
+ icon: 'call_to_action',
6
+ name: 'Footer',
7
+ description: 'Premium site footer with brand column, link groups, social icons, newsletter, legal bar and slots.',
8
+ category: 'Navigation',
9
+ author: 'OneType',
10
+ config: {
11
+ logo: {
12
+ type: 'string'
13
+ },
14
+ logoAlt: {
15
+ type: 'string',
16
+ value: 'Logo'
17
+ },
18
+ brandHref: {
19
+ type: 'string',
20
+ value: '/'
21
+ },
22
+ tagline: {
23
+ type: 'string'
24
+ },
25
+ groups: {
26
+ type: 'array',
27
+ value: [],
28
+ each: {
29
+ type: 'object',
30
+ config: {
31
+ title: { type: 'string' },
32
+ items: {
33
+ type: 'array',
34
+ each: {
35
+ type: 'object',
36
+ config: {
37
+ icon: { type: 'string' },
38
+ label: { type: 'string' },
39
+ href: { type: 'string' },
40
+ target: { type: 'string' },
41
+ badge: { type: 'string' }
42
+ }
43
+ }
44
+ }
45
+ }
46
+ }
47
+ },
48
+ social: {
49
+ type: 'array',
50
+ value: [],
51
+ each: {
52
+ type: 'object',
53
+ config: {
54
+ icon: { type: 'string' },
55
+ label: { type: 'string' },
56
+ href: { type: 'string' }
57
+ }
58
+ }
59
+ },
60
+ legal: {
61
+ type: 'array',
62
+ value: [],
63
+ each: {
64
+ type: 'object',
65
+ config: {
66
+ label: { type: 'string' },
67
+ href: { type: 'string' }
68
+ }
69
+ }
70
+ },
71
+ copyright: {
72
+ type: 'string'
73
+ },
74
+ newsletter: {
75
+ type: 'boolean'
76
+ },
77
+ newsletterTitle: {
78
+ type: 'string',
79
+ value: 'Stay in the loop'
80
+ },
81
+ newsletterDescription: {
82
+ type: 'string',
83
+ value: 'Get product updates and tips straight to your inbox.'
84
+ },
85
+ newsletterPlaceholder: {
86
+ type: 'string',
87
+ value: 'you@example.com'
88
+ },
89
+ newsletterButton: {
90
+ type: 'string',
91
+ value: 'Subscribe'
92
+ },
93
+ variant: {
94
+ type: 'array',
95
+ value: ['bg-1', 'border-top'],
96
+ options: ['bg-1', 'bg-2', 'bg-3', 'bg-4', 'border-top', 'clean']
97
+ },
98
+ _subscribe: {
99
+ type: 'function'
100
+ }
101
+ },
102
+ render: function()
103
+ {
104
+ this.hasTopSlot = !!this.Slots.top;
105
+ this.hasBottomSlot = !!this.Slots.bottom;
106
+ this.hasLogo = !!this.logo;
107
+ this.hasTagline = !!this.tagline;
108
+ this.hasGroups = this.groups && this.groups.length > 0;
109
+ this.hasSocial = this.social && this.social.length > 0;
110
+ this.hasLegal = this.legal && this.legal.length > 0;
111
+ this.hasCopyright = !!this.copyright;
112
+ this.hasBottomBar = this.hasLegal || this.hasCopyright || this.hasSocial;
113
+ this.hasNewsletter = !!this.newsletter;
114
+
115
+ this.newsletterEmail = '';
116
+
117
+ this.onNewsletterInput = ({ value }) =>
118
+ {
119
+ this.newsletterEmail = value;
120
+ };
121
+
122
+ this.subscribe = () =>
123
+ {
124
+ if(!this.newsletterEmail)
125
+ {
126
+ return;
127
+ }
128
+
129
+ if(this._subscribe)
130
+ {
131
+ this._subscribe({ value: this.newsletterEmail });
132
+ }
133
+
134
+ this.newsletterEmail = '';
135
+ };
136
+
137
+ return /* html */ `
138
+ <footer :class="'holder ' + variant.join(' ')">
139
+ <div ot-if="hasTopSlot" class="top-slot">
140
+ <slot name="top"></slot>
141
+ </div>
142
+
143
+ <div class="main">
144
+ <div class="brand-col">
145
+ <a ot-if="hasLogo" class="brand" :href="brandHref">
146
+ <img class="brand-logo" :src="logo" :alt="logoAlt" />
147
+ </a>
148
+
149
+ <p ot-if="hasTagline" class="tagline">{{ tagline }}</p>
150
+
151
+ <div ot-if="hasNewsletter" class="newsletter">
152
+ <div class="newsletter-text">
153
+ <h4 class="newsletter-title">{{ newsletterTitle }}</h4>
154
+ <p ot-if="newsletterDescription" class="newsletter-description">{{ newsletterDescription }}</p>
155
+ </div>
156
+ <form class="newsletter-form" ot-submit.prevent="subscribe">
157
+ <e-form-input
158
+ type="email"
159
+ icon="mail"
160
+ :placeholder="newsletterPlaceholder"
161
+ :value="newsletterEmail"
162
+ :_input="onNewsletterInput"
163
+ :variant="['bg-2', 'border', 'size-m']"
164
+ ></e-form-input>
165
+ <e-form-button
166
+ :text="newsletterButton"
167
+ icon-right="arrow_forward"
168
+ :_click="subscribe"
169
+ :variant="['brand', 'size-m']"
170
+ ></e-form-button>
171
+ </form>
172
+ </div>
173
+ </div>
174
+
175
+ <div ot-if="hasGroups" class="groups">
176
+ <div ot-for="group in groups" class="group">
177
+ <h4 ot-if="group.title" class="group-title">{{ group.title }}</h4>
178
+ <ul class="group-list">
179
+ <li ot-for="item in group.items">
180
+ <a class="group-link" :href="item.href || 'javascript:void(0)'" :target="item.target || null">
181
+ <i ot-if="item.icon">{{ item.icon }}</i>
182
+ <span>{{ item.label }}</span>
183
+ <span ot-if="item.badge" class="group-badge">{{ item.badge }}</span>
184
+ </a>
185
+ </li>
186
+ </ul>
187
+ </div>
188
+ </div>
189
+ </div>
190
+
191
+ <div ot-if="hasBottomBar" class="bottom">
192
+ <div ot-if="hasCopyright" class="copyright">{{ copyright }}</div>
193
+
194
+ <div ot-if="hasLegal" class="legal">
195
+ <a ot-for="entry in legal" class="legal-link" :href="entry.href || 'javascript:void(0)'">{{ entry.label }}</a>
196
+ </div>
197
+
198
+ <div ot-if="hasSocial" class="social">
199
+ <a
200
+ ot-for="entry in social"
201
+ class="social-link"
202
+ :href="entry.href || 'javascript:void(0)'"
203
+ target="_blank"
204
+ rel="noopener"
205
+ :ot-tooltip="{ text: entry.label || '', position: { x: 'center', y: 'top' } }"
206
+ >
207
+ <i>{{ entry.icon }}</i>
208
+ </a>
209
+ </div>
210
+ </div>
211
+
212
+ <div ot-if="hasBottomSlot" class="bottom-slot">
213
+ <slot name="bottom"></slot>
214
+ </div>
215
+ </footer>
216
+ `;
217
+ }
218
+ });
219
+ });