PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.7
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.7
2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 trunk 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8
blockenberg / blocks / nutrition-label / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/nutrition-label/index.js

274 lines 17.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 ( function () {
2 var el = wp.element.createElement;
3 var useState = wp.element.useState;
4 var Fragment = wp.element.Fragment;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var __ = wp.i18n.__;
7 var InspectorControls = wp.blockEditor.InspectorControls;
8 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
9 var useBlockProps = wp.blockEditor.useBlockProps;
10 var PanelBody = wp.components.PanelBody;
11 var RangeControl = wp.components.RangeControl;
12 var SelectControl = wp.components.SelectControl;
13 var TextControl = wp.components.TextControl;
14 var ToggleControl = wp.components.ToggleControl;
15 var Button = wp.components.Button;
16
17 var _tc, _tv;
18 function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
19 function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
20
21 /* ── Daily Value reference amounts ─────────────────── */
22 var DV = {
23 totalFat: 78, saturatedFat: 20, cholesterol: 300,
24 sodium: 2300, totalCarbs: 275, dietaryFiber: 28,
25 addedSugars: 50, protein: 50,
26 vitaminD: 20, calcium: 1300, iron: 18, potassium: 4700
27 };
28
29 function pct(val, key) {
30 if (!DV[key] || !val) return null;
31 return Math.round((val / DV[key]) * 100);
32 }
33
34 /* ── Nutrition label renderer ───────────────────────── */
35 function NutritionLabelPreview(props) {
36 var a = props.attributes;
37 var set = props.setAttributes;
38
39 function field(label, val, key, unit, bold, indent) {
40 var dv = pct(val, key);
41 return el('div', {
42 className: 'bkbg-nl-row' + (bold ? ' bkbg-nl-bold' : '') + (indent ? ' bkbg-nl-indent' : ''),
43 style: { borderTop: '1px solid ' + a.borderColor }
44 },
45 el('span', { className: 'bkbg-nl-nutrient' },
46 el('span', { style: { fontWeight: bold ? '700' : '400' } }, label),
47 el('span', { style: { fontWeight: '400', marginLeft: 2 } }, ' ' + val + unit)
48 ),
49 dv !== null ? el('span', {
50 className: 'bkbg-nl-dv',
51 style: { color: a.dvColor }
52 }, el('strong', null, dv + '%')) : null
53 );
54 }
55
56 var containerStyle = {
57 paddingTop: a.paddingTop + 'px',
58 paddingBottom: a.paddingBottom + 'px',
59 background: a.containerBg || undefined,
60 display: 'flex',
61 justifyContent: 'center'
62 };
63
64 var labelStyle = {
65 fontFamily: 'Arial, Helvetica, sans-serif',
66 fontSize: a.fontSize + 'px',
67 background: a.bgColor,
68 color: a.accentColor,
69 border: a.borderWidth + 'px solid ' + a.borderColor,
70 borderRadius: a.borderRadius + 'px',
71 width: a.labelWidth + 'px',
72 maxWidth: '100%',
73 padding: '8px 8px 4px',
74 boxSizing: 'border-box'
75 };
76
77 return el(Fragment, null,
78 el('div', { className: 'bkbg-nl-wrap', style: containerStyle },
79 el('div', { className: 'bkbg-nl-label', style: labelStyle },
80
81 /* header */
82 el('div', { className: 'bkbg-nl-header' },
83 el('div', { className: 'bkbg-nl-title' }, 'Nutrition Facts'),
84 a.foodName ? el('div', { className: 'bkbg-nl-foodname', style: { fontSize: a.fontSize * 0.9 + 'px', marginTop: 2 } }, a.foodName) : null,
85 el('div', { className: 'bkbg-nl-servings', style: { borderTop: '4px solid ' + a.borderColor, borderBottom: '4px solid ' + a.borderColor, padding: '2px 0', margin: '4px 0', fontSize: a.fontSize * 0.85 + 'px' } },
86 el('div', null, a.servingsPerContainer + ' servings per container'),
87 el('div', { style: { display: 'flex', justifyContent: 'space-between', fontWeight: '700' } },
88 el('span', null, 'Serving size'),
89 el('span', null, a.servingSize)
90 )
91 )
92 ),
93
94 /* calories */
95 el('div', { className: 'bkbg-nl-calories-block', style: { borderBottom: '8px solid ' + a.borderColor, paddingBottom: 4 } },
96 el('div', { style: { fontSize: a.fontSize * 0.75 + 'px', fontWeight: '700' } }, 'Amount per serving'),
97 el('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' } },
98 el('div', { style: { fontSize: a.fontSize * 1.1 + 'px', fontWeight: '700' } }, 'Calories'),
99 el('div', { style: { fontSize: a.fontSize * 2.8 + 'px', fontWeight: '900', lineHeight: 1, color: a.calorieColor } }, a.calories)
100 )
101 ),
102
103 /* % DV header */
104 el('div', { style: { textAlign: 'right', fontSize: a.fontSize * 0.75 + 'px', borderBottom: '1px solid ' + a.borderColor, paddingBottom: 2 } },
105 el('strong', null, '% Daily Value*')
106 ),
107
108 /* fats */
109 field('Total Fat', a.totalFat, 'totalFat', 'g', true, false),
110 field('Saturated Fat', a.saturatedFat, 'saturatedFat', 'g', false, true),
111 el('div', { className: 'bkbg-nl-row bkbg-nl-indent', style: { borderTop: '1px solid ' + a.borderColor } },
112 el('span', { className: 'bkbg-nl-nutrient' },
113 el('em', null, 'Trans'), ' Fat ', a.transFat + 'g'
114 )
115 ),
116 a.showPolyMono ? field('Polyunsaturated Fat', a.polyFat, null, 'g', false, true) : null,
117 a.showPolyMono ? field('Monounsaturated Fat', a.monoFat, null, 'g', false, true) : null,
118
119 /* cholesterol / sodium */
120 field('Cholesterol', a.cholesterol, 'cholesterol', 'mg', true, false),
121 field('Sodium', a.sodium, 'sodium', 'mg', true, false),
122
123 /* carbs */
124 field('Total Carbohydrate', a.totalCarbs, 'totalCarbs', 'g', true, false),
125 field('Dietary Fiber', a.dietaryFiber, 'dietaryFiber', 'g', false, true),
126 el('div', { className: 'bkbg-nl-row bkbg-nl-indent', style: { borderTop: '1px solid ' + a.borderColor } },
127 el('span', { className: 'bkbg-nl-nutrient' }, 'Total Sugars ', a.totalSugars + 'g')
128 ),
129 a.showAddedSugars ? el('div', { className: 'bkbg-nl-row bkbg-nl-indent2', style: { borderTop: '1px solid ' + a.borderColor } },
130 el('span', { className: 'bkbg-nl-nutrient' }, 'Includes ' + a.addedSugars + 'g Added Sugars'),
131 el('span', { className: 'bkbg-nl-dv', style: { color: a.dvColor } }, el('strong', null, pct(a.addedSugars, 'addedSugars') + '%'))
132 ) : null,
133
134 /* protein */
135 el('div', { className: 'bkbg-nl-row', style: { borderTop: '4px solid ' + a.borderColor } },
136 el('span', { className: 'bkbg-nl-nutrient' }, el('strong', null, 'Protein '), a.protein + 'g')
137 ),
138
139 /* vitamins */
140 a.showVitamins ? el(Fragment, null,
141 el('div', { style: { borderTop: '8px solid ' + a.borderColor } }),
142 el('div', { className: 'bkbg-nl-vitamins', style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '2px 8px', padding: '4px 0', fontSize: a.fontSize * 0.85 + 'px' } },
143 el('span', null, 'Vitamin D ' + a.vitaminD + 'mcg'),
144 el('span', null, pct(a.vitaminD, 'vitaminD') + '%'),
145 el('span', null, 'Calcium ' + a.calcium + 'mg'),
146 el('span', null, pct(a.calcium, 'calcium') + '%'),
147 el('span', null, 'Iron ' + a.iron + 'mg'),
148 el('span', null, pct(a.iron, 'iron') + '%'),
149 el('span', null, 'Potassium ' + a.potassium + 'mg'),
150 el('span', null, pct(a.potassium, 'potassium') + '%')
151 )
152 ) : null,
153
154 /* footnote */
155 a.showFootnote ? el('div', { className: 'bkbg-nl-footnote', style: { borderTop: '4px solid ' + a.borderColor, fontSize: a.fontSize * 0.72 + 'px', paddingTop: 4 } },
156 '* The % Daily Value (DV) tells you how much a nutrient in a serving of food contributes to a daily diet. ' + a.dvRef + ' calories a day is used for general nutrition advice.'
157 ) : null
158 )
159 )
160 );
161 }
162
163 /* ── Inspector ──────────────────────────────────────── */
164 function NutritionLabelEdit(props) {
165 var a = props.attributes;
166 var set = props.setAttributes;
167 var blockProps = useBlockProps((function () {
168 var _tvf = getTypoCssVars();
169 var s = {};
170 if (_tvf) { Object.assign(s, _tvf(a.titleTypo, '--bkbg-nutl-tt-')); }
171 return { className: 'bkbg-nl-editor-wrap', style: s };
172 })());
173
174 function n(key) { return function(v) { var o = {}; o[key] = typeof v === 'number' ? v : Number(v) || 0; set(o); }; }
175 function s(key) { return function(v) { var o = {}; o[key] = v; set(o); }; }
176 function t(key) { return function(v) { var o = {}; o[key] = v; set(o); }; }
177
178 return el(Fragment, null,
179 el(InspectorControls, null,
180
181 /* Serving */
182 el(PanelBody, { title: __('Serving Info', 'blockenberg'), initialOpen: true },
183 el(TextControl, { label: __('Food Name (optional)', 'blockenberg'), value: a.foodName, onChange: s('foodName') }),
184 el(TextControl, { label: __('Serving Size', 'blockenberg'), value: a.servingSize, onChange: s('servingSize'), help: __('e.g. 1 cup (240g)', 'blockenberg') }),
185 el(TextControl, { label: __('Servings Per Container', 'blockenberg'), value: a.servingsPerContainer, onChange: s('servingsPerContainer') }),
186 el(TextControl, { label: __('Calories', 'blockenberg'), value: String(a.calories), onChange: n('calories'), type: 'number' })
187 ),
188
189 /* Fats */
190 el(PanelBody, { title: __('Fats', 'blockenberg'), initialOpen: false },
191 el(TextControl, { label: __('Total Fat (g)', 'blockenberg'), value: String(a.totalFat), onChange: n('totalFat'), type: 'number' }),
192 el(TextControl, { label: __('Saturated Fat (g)', 'blockenberg'), value: String(a.saturatedFat), onChange: n('saturatedFat'), type: 'number' }),
193 el(TextControl, { label: __('Trans Fat (g)', 'blockenberg'), value: String(a.transFat), onChange: n('transFat'), type: 'number' }),
194 el(ToggleControl, { label: __('Show Poly/Mono Fat', 'blockenberg'), checked: a.showPolyMono, onChange: t('showPolyMono'), __nextHasNoMarginBottom: true }),
195 a.showPolyMono ? el(TextControl, { label: __('Polyunsaturated Fat (g)', 'blockenberg'), value: String(a.polyFat), onChange: n('polyFat'), type: 'number' }) : null,
196 a.showPolyMono ? el(TextControl, { label: __('Monounsaturated Fat (g)', 'blockenberg'), value: String(a.monoFat), onChange: n('monoFat'), type: 'number' }) : null
197 ),
198
199 /* Carbs & Other */
200 el(PanelBody, { title: __('Carbs & Other', 'blockenberg'), initialOpen: false },
201 el(TextControl, { label: __('Cholesterol (mg)', 'blockenberg'), value: String(a.cholesterol), onChange: n('cholesterol'), type: 'number' }),
202 el(TextControl, { label: __('Sodium (mg)', 'blockenberg'), value: String(a.sodium), onChange: n('sodium'), type: 'number' }),
203 el(TextControl, { label: __('Total Carbohydrate (g)', 'blockenberg'), value: String(a.totalCarbs), onChange: n('totalCarbs'), type: 'number' }),
204 el(TextControl, { label: __('Dietary Fiber (g)', 'blockenberg'), value: String(a.dietaryFiber), onChange: n('dietaryFiber'), type: 'number' }),
205 el(TextControl, { label: __('Total Sugars (g)', 'blockenberg'), value: String(a.totalSugars), onChange: n('totalSugars'), type: 'number' }),
206 el(ToggleControl, { label: __('Show Added Sugars', 'blockenberg'), checked: a.showAddedSugars, onChange: t('showAddedSugars'), __nextHasNoMarginBottom: true }),
207 a.showAddedSugars ? el(TextControl, { label: __('Added Sugars (g)', 'blockenberg'), value: String(a.addedSugars), onChange: n('addedSugars'), type: 'number' }) : null,
208 el(TextControl, { label: __('Protein (g)', 'blockenberg'), value: String(a.protein), onChange: n('protein'), type: 'number' })
209 ),
210
211 /* Vitamins */
212 el(PanelBody, { title: __('Vitamins & Minerals', 'blockenberg'), initialOpen: false },
213 el(ToggleControl, { label: __('Show Vitamins Section', 'blockenberg'), checked: a.showVitamins, onChange: t('showVitamins'), __nextHasNoMarginBottom: true }),
214 a.showVitamins ? el(Fragment, null,
215 el(TextControl, { label: __('Vitamin D (mcg)', 'blockenberg'), value: String(a.vitaminD), onChange: n('vitaminD'), type: 'number' }),
216 el(TextControl, { label: __('Calcium (mg)', 'blockenberg'), value: String(a.calcium), onChange: n('calcium'), type: 'number' }),
217 el(TextControl, { label: __('Iron (mg)', 'blockenberg'), value: String(a.iron), onChange: n('iron'), type: 'number' }),
218 el(TextControl, { label: __('Potassium (mg)', 'blockenberg'), value: String(a.potassium), onChange: n('potassium'), type: 'number' })
219 ) : null
220 ),
221
222 /* Display */
223 el(PanelBody, { title: __('Display', 'blockenberg'), initialOpen: false },
224 el(ToggleControl, { label: __('Show Footnote', 'blockenberg'), checked: a.showFootnote, onChange: t('showFootnote'), __nextHasNoMarginBottom: true }),
225 el(TextControl, { label: __('Daily Value Reference (cal)', 'blockenberg'), value: a.dvRef, onChange: s('dvRef'), type: 'number' })
226 ),
227
228 /* Colors */
229
230 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
231 el(getTypoControl(), { label: __('Title Typography', 'blockenberg'), value: a.titleTypo, onChange: function(v){ set({titleTypo:v}); } }),
232 el(RangeControl, { label: __('Base Font Size (px)', 'blockenberg'), value: a.fontSize, onChange: n('fontSize'), min: 10, max: 20 })
233 ),
234 el(PanelColorSettings, {
235 title: __('Colors', 'blockenberg'),
236 initialOpen: false,
237 colorSettings: [
238 { value: a.bgColor, onChange: s('bgColor'), label: __('Label Background', 'blockenberg') },
239 { value: a.accentColor, onChange: s('accentColor'), label: __('Text Color', 'blockenberg') },
240 { value: a.borderColor, onChange: s('borderColor'), label: __('Border Color', 'blockenberg') },
241 { value: a.calorieColor, onChange: s('calorieColor'), label: __('Calorie Number', 'blockenberg') },
242 { value: a.dvColor, onChange: s('dvColor'), label: __('% DV Color', 'blockenberg') },
243 { value: a.containerBg, onChange: s('containerBg'), label: __('Section Background', 'blockenberg') }
244 ]
245 }),
246
247 /* Sizing */
248 el(PanelBody, { title: __('Sizing', 'blockenberg'), initialOpen: false },
249 el(RangeControl, { label: __('Label Width (px)', 'blockenberg'), value: a.labelWidth, onChange: n('labelWidth'), min: 200, max: 600, step: 10 }),
250 el(RangeControl, { label: __('Border Width (px)', 'blockenberg'), value: a.borderWidth, onChange: n('borderWidth'), min: 1, max: 8 }),
251 el(RangeControl, { label: __('Border Radius (px)', 'blockenberg'), value: a.borderRadius, onChange: n('borderRadius'), min: 0, max: 24 }),
252 el(RangeControl, { label: __('Padding Top (px)', 'blockenberg'), value: a.paddingTop, onChange: n('paddingTop'), min: 0, max: 120 }),
253 el(RangeControl, { label: __('Padding Bottom (px)', 'blockenberg'), value: a.paddingBottom, onChange: n('paddingBottom'), min: 0, max: 120 })
254 )
255 ),
256
257 el('div', blockProps,
258 el(NutritionLabelPreview, { attributes: a, setAttributes: set })
259 )
260 );
261 }
262
263 registerBlockType('blockenberg/nutrition-label', {
264 edit: NutritionLabelEdit,
265 save: function (props) {
266 var a = props.attributes;
267 return el('div', wp.blockEditor.useBlockProps.save({
268 className: 'bkbg-nl-app',
269 'data-opts': JSON.stringify(a)
270 }));
271 }
272 });
273 }() );
274