@jhits/botanics_and_you 0.0.9 → 0.0.11
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.
- package/dist/index.d.ts +2 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -4
- package/dist/plugin-blog/blocks/CategoryDropdown.d.ts.map +1 -1
- package/dist/plugin-blog/blocks/CategoryDropdown.js +18 -15
- package/dist/plugin-blog/blocks/Heading.d.ts.map +1 -1
- package/dist/plugin-blog/blocks/Heading.js +29 -26
- package/dist/plugin-blog/blocks/Hero.d.ts.map +1 -1
- package/dist/plugin-blog/blocks/Hero.js +12 -4
- package/dist/plugin-blog/blocks/List.d.ts.map +1 -1
- package/dist/plugin-blog/blocks/List.js +40 -171
- package/dist/plugin-blog/blocks/Paragraph.d.ts.map +1 -1
- package/dist/plugin-blog/blocks/Paragraph.js +19 -43
- package/dist/plugin-blog/blocks/Recipe.d.ts +0 -1
- package/dist/plugin-blog/blocks/Recipe.d.ts.map +1 -1
- package/dist/plugin-blog/blocks/Recipe.js +22 -23
- package/dist/plugin-blog/blocks/Table.d.ts +0 -3
- package/dist/plugin-blog/blocks/Table.d.ts.map +1 -1
- package/dist/plugin-blog/blocks/Table.js +19 -50
- package/dist/plugin-blog/colors.d.ts +12 -0
- package/dist/plugin-blog/colors.d.ts.map +1 -0
- package/dist/plugin-blog/colors.js +11 -0
- package/dist/plugin-blog/components/BotanyBlogWrapper.d.ts +15 -0
- package/dist/plugin-blog/components/BotanyBlogWrapper.d.ts.map +1 -0
- package/dist/plugin-blog/components/BotanyBlogWrapper.js +12 -0
- package/dist/plugin-blog/index.d.ts +1 -0
- package/dist/plugin-blog/index.d.ts.map +1 -1
- package/dist/plugin-blog/index.js +3 -0
- package/dist/plugin-blog/theme.d.ts.map +1 -1
- package/dist/plugin-blog/theme.js +7 -0
- package/dist/plugin-newsletter/index.d.ts +1 -0
- package/dist/plugin-newsletter/index.d.ts.map +1 -1
- package/dist/plugin-newsletter/index.js +8 -1
- package/package.json +4 -4
- package/src/index.ts +2 -4
- package/src/plugin-blog/blocks/CategoryDropdown.tsx +37 -22
- package/src/plugin-blog/blocks/Heading.tsx +33 -32
- package/src/plugin-blog/blocks/Hero.tsx +26 -11
- package/src/plugin-blog/blocks/List.tsx +72 -234
- package/src/plugin-blog/blocks/Paragraph.tsx +37 -53
- package/src/plugin-blog/blocks/Recipe.tsx +31 -28
- package/src/plugin-blog/blocks/Table.tsx +40 -87
- package/src/plugin-blog/colors.ts +11 -0
- package/src/plugin-blog/components/BotanyBlogWrapper.tsx +43 -0
- package/src/plugin-blog/index.ts +3 -0
- package/src/plugin-blog/theme.ts +7 -0
- package/src/plugin-newsletter/index.ts +10 -1
package/dist/index.d.ts
CHANGED
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
* BotanicsAndYou Client Configuration for JHITS
|
|
3
3
|
*
|
|
4
4
|
* This package contains all client-specific plugin configurations.
|
|
5
|
-
*
|
|
6
|
-
* Usage:
|
|
7
|
-
* import { blogPluginConfig, botanyBlocks } from '@jhits/BotanicsAndYou/plugin-blog';
|
|
8
5
|
*/
|
|
9
|
-
export
|
|
6
|
+
export { blogPluginConfig, botanyBlocks, customBlocks } from './plugin-blog';
|
|
7
|
+
export { newsletterPluginConfig, botanyNewsletterBlocks, customNewsletterBlocks } from './plugin-newsletter';
|
|
10
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
* BotanicsAndYou Client Configuration for JHITS
|
|
3
3
|
*
|
|
4
4
|
* This package contains all client-specific plugin configurations.
|
|
5
|
-
*
|
|
6
|
-
* Usage:
|
|
7
|
-
* import { blogPluginConfig, botanyBlocks } from '@jhits/BotanicsAndYou/plugin-blog';
|
|
8
5
|
*/
|
|
9
|
-
export
|
|
6
|
+
export { blogPluginConfig, botanyBlocks, customBlocks } from './plugin-blog';
|
|
7
|
+
export { newsletterPluginConfig, botanyNewsletterBlocks, customNewsletterBlocks } from './plugin-newsletter';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CategoryDropdown.d.ts","sourceRoot":"","sources":["../../../src/plugin-blog/blocks/CategoryDropdown.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CategoryDropdown.d.ts","sourceRoot":"","sources":["../../../src/plugin-blog/blocks/CategoryDropdown.tsx"],"names":[],"mappings":"AAMA,MAAM,WAAW,qBAAqB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,gBAAgB,CAAC,EAC7B,KAAK,EACL,QAAQ,EACR,kBAAuB,EACvB,SAAc,EACd,WAAyC,EACzC,SAAiB,GACpB,EAAE,qBAAqB,2CA+JvB"}
|
|
@@ -2,42 +2,41 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useEffect, useRef } from 'react';
|
|
4
4
|
import { ChevronDown, Plus } from 'lucide-react';
|
|
5
|
+
import { colors } from '../colors';
|
|
5
6
|
export function CategoryDropdown({ value, onChange, existingCategories = [], className = '', placeholder = 'Select or add category...', showLabel = false, }) {
|
|
6
7
|
const [isOpen, setIsOpen] = useState(false);
|
|
7
8
|
const [inputValue, setInputValue] = useState('');
|
|
8
9
|
const [isAddingNew, setIsAddingNew] = useState(false);
|
|
9
10
|
const dropdownRef = useRef(null);
|
|
10
11
|
const inputRef = useRef(null);
|
|
11
|
-
// This ref tracks if we have successfully set an initial value
|
|
12
|
-
// to avoid snapping back to the first item if the user manually clears the field
|
|
13
12
|
const hasAutoSelected = useRef(false);
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
const prevCategoriesRef = useRef(existingCategories);
|
|
14
|
+
// Reset auto-select when categories change (e.g., language switch)
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const prev = prevCategoriesRef.current;
|
|
17
|
+
const changed = prev.length !== existingCategories.length ||
|
|
18
|
+
prev.some((cat, i) => cat !== existingCategories[i]);
|
|
19
|
+
if (changed) {
|
|
20
|
+
hasAutoSelected.current = false;
|
|
21
|
+
prevCategoriesRef.current = existingCategories;
|
|
22
|
+
}
|
|
23
|
+
}, [existingCategories]);
|
|
18
24
|
useEffect(() => {
|
|
19
25
|
const isValueEmpty = !value || value.trim() === '';
|
|
20
26
|
if (isValueEmpty && existingCategories.length > 0 && !hasAutoSelected.current) {
|
|
21
27
|
const firstCategory = existingCategories.find(cat => cat && cat.trim() !== '');
|
|
22
28
|
if (firstCategory) {
|
|
23
|
-
// Set the flag FIRST to prevent race conditions
|
|
24
29
|
hasAutoSelected.current = true;
|
|
25
|
-
// Use requestAnimationFrame to ensure we are outside the
|
|
26
|
-
// render phase of the category fetch completion
|
|
27
30
|
requestAnimationFrame(() => {
|
|
28
31
|
onChange(firstCategory);
|
|
29
32
|
});
|
|
30
33
|
}
|
|
31
34
|
}
|
|
32
|
-
// If a value is manually set (by user or saved data),
|
|
33
|
-
// we mark auto-select as "done" so it doesn't fight the user
|
|
34
35
|
if (!isValueEmpty) {
|
|
35
36
|
hasAutoSelected.current = true;
|
|
36
37
|
}
|
|
37
38
|
}, [existingCategories, value, onChange]);
|
|
38
|
-
// UI filtering
|
|
39
39
|
const otherCategories = existingCategories.filter(cat => cat && cat.trim() !== '' && cat !== value);
|
|
40
|
-
// Outside Click Handler
|
|
41
40
|
useEffect(() => {
|
|
42
41
|
const handleClickOutside = (event) => {
|
|
43
42
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
@@ -51,7 +50,6 @@ export function CategoryDropdown({ value, onChange, existingCategories = [], cla
|
|
|
51
50
|
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
52
51
|
}
|
|
53
52
|
}, [isOpen]);
|
|
54
|
-
// Focus on new input
|
|
55
53
|
useEffect(() => {
|
|
56
54
|
if (isAddingNew && inputRef.current) {
|
|
57
55
|
inputRef.current.focus();
|
|
@@ -63,5 +61,10 @@ export function CategoryDropdown({ value, onChange, existingCategories = [], cla
|
|
|
63
61
|
setIsAddingNew(false);
|
|
64
62
|
setInputValue('');
|
|
65
63
|
};
|
|
66
|
-
return (_jsxs("div", { className: `relative ${className}`, ref: dropdownRef, children: [showLabel && (_jsx("label", { className: "text-[10px] text-neutral-500 uppercase font-bold block mb-2 tracking-widest", children: "Category" })), _jsxs("div", { className: "relative", children: [_jsxs("div", { onClick: () => setIsOpen(!isOpen), className: "w-full bg-transparent
|
|
64
|
+
return (_jsxs("div", { className: `relative ${className}`, ref: dropdownRef, children: [showLabel && (_jsx("label", { className: "text-[10px] text-neutral-500 uppercase font-bold block mb-2 tracking-widest", children: "Category" })), _jsxs("div", { className: "relative", children: [_jsxs("div", { onClick: () => setIsOpen(!isOpen), className: "w-full bg-transparent rounded-full px-4 py-1.5 text-xs font-bold uppercase tracking-[0.2em] flex items-center justify-between cursor-pointer transition-all", style: {
|
|
65
|
+
color: colors.sage,
|
|
66
|
+
borderWidth: 1,
|
|
67
|
+
borderStyle: 'solid',
|
|
68
|
+
borderColor: `${colors.sage}33`,
|
|
69
|
+
}, onMouseEnter: (e) => { e.currentTarget.style.backgroundColor = `${colors.sage}0D`; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = ''; }, children: [_jsx("span", { className: "truncate", children: value || placeholder }), _jsx(ChevronDown, { size: 14, style: { color: `${colors.sage}80` }, className: `transition-transform ${isOpen ? 'rotate-180' : ''}` })] }), isOpen && (_jsxs("div", { className: "absolute z-50 w-full mt-2 bg-white dark:bg-neutral-900 rounded-xl shadow-xl border border-neutral-100 dark:border-neutral-800 overflow-hidden animate-in fade-in zoom-in-95 duration-150", children: [otherCategories.length > 0 && (_jsx("div", { className: "py-1 max-h-48 overflow-y-auto", children: otherCategories.map((category) => (_jsx("button", { type: "button", onClick: () => handleSelect(category), className: "w-full text-left px-4 py-2.5 text-xs font-bold text-neutral-700 dark:text-neutral-300 transition-colors", onMouseEnter: (e) => { e.currentTarget.style.backgroundColor = `${colors.sage}0D`; e.currentTarget.style.color = colors.sage; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = ''; e.currentTarget.style.color = ''; }, children: category }, category))) })), !isAddingNew ? (_jsxs("button", { type: "button", onClick: () => setIsAddingNew(true), className: "w-full text-left px-4 py-3 text-xs font-bold transition-colors border-t border-neutral-50 dark:border-neutral-800 flex items-center gap-2", style: { color: colors.sage }, onMouseEnter: (e) => { e.currentTarget.style.backgroundColor = `${colors.sage}0D`; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = ''; }, children: [_jsx(Plus, { size: 14 }), " Add new category"] })) : (_jsxs("div", { className: "p-3 border-t border-neutral-50 dark:border-neutral-800 bg-neutral-50/50 dark:bg-neutral-800/50", children: [_jsx("input", { ref: inputRef, value: inputValue, onChange: (e) => setInputValue(e.target.value), onKeyDown: (e) => e.key === 'Enter' && inputValue.trim() && handleSelect(inputValue.trim()), placeholder: "Category name...", className: "w-full border border-neutral-200 dark:border-neutral-700 bg-white dark:bg-neutral-900 p-2 rounded-lg text-xs font-bold outline-none mb-2", style: { borderColor: undefined }, onFocus: (e) => { e.currentTarget.style.borderColor = colors.sage; }, onBlur: (e) => { e.currentTarget.style.borderColor = ''; } }), _jsxs("div", { className: "flex gap-2", children: [_jsx("button", { onClick: () => inputValue.trim() && handleSelect(inputValue.trim()), className: "flex-1 text-white px-3 py-1.5 rounded-lg text-[10px] font-bold uppercase tracking-wider", style: { backgroundColor: colors.sage }, children: "Add" }), _jsx("button", { onClick: () => { setIsAddingNew(false); setInputValue(''); }, className: "px-3 py-1.5 rounded-lg text-[10px] font-bold uppercase border border-neutral-200 dark:border-neutral-700 text-neutral-500", children: "Cancel" })] })] }))] }))] })] }));
|
|
67
70
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Heading.d.ts","sourceRoot":"","sources":["../../../src/plugin-blog/blocks/Heading.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAqC,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"Heading.d.ts","sourceRoot":"","sources":["../../../src/plugin-blog/blocks/Heading.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAqC,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAoH9F,eAAO,MAAM,YAAY,EAAE,qBAoB1B,CAAC"}
|
|
@@ -2,26 +2,34 @@
|
|
|
2
2
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { Heading, ChevronDown } from "lucide-react";
|
|
4
4
|
import { useState, useRef, useEffect } from "react";
|
|
5
|
+
const getStyle = (level) => {
|
|
6
|
+
const base = {
|
|
7
|
+
fontFamily: 'var(--content-heading-font, var(--font-serif, Georgia, serif))',
|
|
8
|
+
color: 'var(--color-forest, #6B7C5A)'
|
|
9
|
+
};
|
|
10
|
+
switch (level) {
|
|
11
|
+
case 4:
|
|
12
|
+
case 5:
|
|
13
|
+
case 6:
|
|
14
|
+
return Object.assign(Object.assign({}, base), { color: 'var(--color-sage, #9CAF88)', fontStyle: level === 4 ? 'italic' : undefined });
|
|
15
|
+
default:
|
|
16
|
+
return base;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
5
19
|
const getClassName = (level) => `
|
|
6
|
-
font-serif
|
|
20
|
+
font-[family:var(--content-heading-font,serif)]
|
|
7
21
|
${level === 1 ? "text-5xl lg:text-6xl mt-12 mb-8 font-bold" : ""}
|
|
8
22
|
${level === 2 ? "text-4xl lg:text-5xl mt-10 mb-2" : ""}
|
|
9
|
-
${level === 3 ? "text-3xl mt-8 mb-4
|
|
10
|
-
${level === 4 ? "text-xl mt-6 mb-3 font-medium
|
|
11
|
-
${level === 5 ? "text-lg mt-4 mb-2 font-medium
|
|
12
|
-
${level === 6 ? "text-base mt-3 mb-2 font-medium
|
|
23
|
+
${level === 3 ? "text-3xl mt-8 mb-4" : ""}
|
|
24
|
+
${level === 4 ? "text-xl mt-6 mb-3 font-medium" : ""}
|
|
25
|
+
${level === 5 ? "text-lg mt-4 mb-2 font-medium" : ""}
|
|
26
|
+
${level === 6 ? "text-base mt-3 mb-2 font-medium" : ""}
|
|
13
27
|
`;
|
|
14
|
-
|
|
15
|
-
* Heading Block
|
|
16
|
-
* Simple heading block for botanical articles with SEO-optimized heading levels
|
|
17
|
-
*/
|
|
18
|
-
const HeadingEdit = ({ block, onUpdate, isSelected }) => {
|
|
28
|
+
const HeadingEdit = ({ block, onUpdate }) => {
|
|
19
29
|
const level = block.data.level || 2;
|
|
20
30
|
const text = block.data.text || '';
|
|
21
31
|
const [showLevelDropdown, setShowLevelDropdown] = useState(false);
|
|
22
32
|
const dropdownRef = useRef(null);
|
|
23
|
-
const defaultClassName = getClassName(level);
|
|
24
|
-
// Close dropdown when clicking outside
|
|
25
33
|
useEffect(() => {
|
|
26
34
|
const handleClickOutside = (event) => {
|
|
27
35
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
@@ -39,25 +47,20 @@ const HeadingEdit = ({ block, onUpdate, isSelected }) => {
|
|
|
39
47
|
};
|
|
40
48
|
return (_jsx("div", { className: "relative group", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("div", { className: "relative", ref: dropdownRef, children: [_jsxs("button", { type: "button", onClick: () => setShowLevelDropdown(!showLevelDropdown), className: "flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-gray-200 bg-white hover:bg-gray-50 transition-colors text-xs font-bold text-gray-600", title: "Select heading level for SEO", children: [_jsxs("span", { children: ["H", level] }), _jsx(ChevronDown, { size: 12, className: `transition-transform ${showLevelDropdown ? 'rotate-180' : ''}` })] }), showLevelDropdown && (_jsx("div", { className: "absolute z-50 mt-1 bg-white border border-gray-200 rounded-lg shadow-lg overflow-hidden min-w-[120px]", children: [1, 2, 3, 4, 5, 6].map((lvl) => (_jsxs("button", { type: "button", onClick: () => handleLevelChange(lvl), className: `w-full text-left px-3 py-2 text-xs font-bold transition-colors ${level === lvl
|
|
41
49
|
? 'bg-primary/10 text-primary'
|
|
42
|
-
: 'text-gray-700 hover:bg-gray-50'}`, children: ["H", lvl, " ", lvl === 1 ? '(Page Title)' : lvl === 2 ? '(Section)' : lvl === 3 ? '(Subsection)' : ''] }, lvl))) }))] }), _jsx("input", { type: "text", value: text, onChange: (e) => onUpdate({ text: e.target.value }), placeholder: "Enter heading text...", className: `flex-1 ${
|
|
50
|
+
: 'text-gray-700 hover:bg-gray-50'}`, children: ["H", lvl, " ", lvl === 1 ? '(Page Title)' : lvl === 2 ? '(Section)' : lvl === 3 ? '(Subsection)' : ''] }, lvl))) }))] }), _jsx("input", { type: "text", value: text, onChange: (e) => onUpdate({ text: e.target.value }), placeholder: "Enter heading text...", style: getStyle(level), className: `flex-1 bg-transparent border-none outline-none focus:ring-0 ${getClassName(level)}` })] }) }));
|
|
43
51
|
};
|
|
44
52
|
const HeadingPreview = ({ block }) => {
|
|
45
53
|
const level = Math.min(Math.max(block.data.level || 2, 1), 6);
|
|
46
54
|
const text = block.data.text || '';
|
|
47
|
-
const
|
|
55
|
+
const style = getStyle(level);
|
|
56
|
+
const className = getClassName(level);
|
|
48
57
|
switch (level) {
|
|
49
|
-
case 1:
|
|
50
|
-
|
|
51
|
-
case
|
|
52
|
-
|
|
53
|
-
case
|
|
54
|
-
|
|
55
|
-
case 5:
|
|
56
|
-
return _jsx("h5", { className: defaultClassName, children: text });
|
|
57
|
-
case 6:
|
|
58
|
-
return _jsx("h6", { className: defaultClassName, children: text });
|
|
59
|
-
default:
|
|
60
|
-
return _jsx("h2", { className: defaultClassName, children: text });
|
|
58
|
+
case 1: return _jsx("h1", { style: style, className: className, children: text });
|
|
59
|
+
case 3: return _jsx("h3", { style: style, className: className, children: text });
|
|
60
|
+
case 4: return _jsx("h4", { style: style, className: className, children: text });
|
|
61
|
+
case 5: return _jsx("h5", { style: style, className: className, children: text });
|
|
62
|
+
case 6: return _jsx("h6", { style: style, className: className, children: text });
|
|
63
|
+
default: return _jsx("h2", { style: style, className: className, children: text });
|
|
61
64
|
}
|
|
62
65
|
};
|
|
63
66
|
export const HeadingBlock = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Hero.d.ts","sourceRoot":"","sources":["../../../src/plugin-blog/blocks/Hero.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"Hero.d.ts","sourceRoot":"","sources":["../../../src/plugin-blog/blocks/Hero.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAgB9F;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAyI7C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,GAAG;IAAE,aAAa,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAwDvG,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,qBAkBvB,CAAC"}
|
|
@@ -7,15 +7,17 @@ import { useCategories } from '@jhits/plugin-blog';
|
|
|
7
7
|
import { ImagePicker, Image as PluginImage } from '@jhits/plugin-images';
|
|
8
8
|
import { CategoryDropdown } from './CategoryDropdown';
|
|
9
9
|
import { createApiUrl } from '../api-config';
|
|
10
|
+
import { colors } from '../colors';
|
|
10
11
|
/**
|
|
11
12
|
* 2. Hero Edit Component
|
|
12
13
|
*/
|
|
13
|
-
export const HeroEdit = ({ block, onUpdate }) => {
|
|
14
|
+
export const HeroEdit = ({ block, onUpdate, context }) => {
|
|
14
15
|
const [showImagePicker, setShowImagePicker] = useState(false);
|
|
15
16
|
const [currentBrightness, setCurrentBrightness] = useState(100);
|
|
16
17
|
const [currentBlur, setCurrentBlur] = useState(0);
|
|
17
18
|
const [mounted, setMounted] = useState(false);
|
|
18
|
-
|
|
19
|
+
// Pass context locale to useCategories for localized suggestions
|
|
20
|
+
const { categories } = useCategories(context === null || context === void 0 ? void 0 : context.locale);
|
|
19
21
|
// Handle SSR - ensure we only render portal on client
|
|
20
22
|
useEffect(() => {
|
|
21
23
|
setMounted(true);
|
|
@@ -46,7 +48,7 @@ export const HeroEdit = ({ block, onUpdate }) => {
|
|
|
46
48
|
const updateField = (updates) => {
|
|
47
49
|
onUpdate(Object.assign(Object.assign({}, data), updates));
|
|
48
50
|
};
|
|
49
|
-
return (_jsxs("section", { className: "relative pt-32 pb-20 overflow-hidden group/hero", children: [_jsxs("div", { className: "max-w-7xl mx-auto px-6 lg:px-12 grid lg:grid-cols-2 gap-16 items-center", children: [_jsxs("div", { className: "order-2 lg:order-1 text-left flex flex-col items-start", children: [_jsx(CategoryDropdown, { value: category, onChange: (newCategory) => updateField({ category: newCategory }), existingCategories: categories, placeholder: "CATEGORIE" }), _jsx("textarea", { value: title, onChange: (e) => updateField({ title: e.target.value }), placeholder: "Artikel Titel...", rows: 2, className: "w-full text-5xl lg:text-7xl font-serif
|
|
51
|
+
return (_jsxs("section", { className: "relative pt-32 pb-20 overflow-hidden group/hero", children: [_jsxs("div", { className: "max-w-7xl mx-auto px-6 lg:px-12 grid lg:grid-cols-2 gap-16 items-center", children: [_jsxs("div", { className: "order-2 lg:order-1 text-left flex flex-col items-start", children: [_jsx(CategoryDropdown, { value: category, onChange: (newCategory) => updateField({ category: newCategory }), existingCategories: categories, placeholder: "CATEGORIE" }), _jsx("textarea", { value: title, onChange: (e) => updateField({ title: e.target.value }), placeholder: "Artikel Titel...", rows: 2, style: { color: colors.forest }, className: "w-full text-5xl lg:text-7xl font-serif mb-8 leading-[1.1] tracking-tight bg-transparent border-none outline-none focus:ring-0 p-0 resize-none placeholder:text-gray-200 overflow-hidden" }), _jsx("textarea", { value: summary, onChange: (e) => updateField({ summary: e.target.value }), placeholder: "Klik om een samenvatting te typen...", rows: 3, className: "w-full text-lg lg:text-xl text-gray-600 leading-relaxed font-light bg-transparent border-none outline-none focus:ring-0 p-0 resize-none placeholder:text-gray-300" })] }), _jsx("div", { className: "order-1 lg:order-2 w-full", children: _jsxs("div", { className: "relative rounded-3xl overflow-hidden shadow-2xl aspect-[4/5] lg:aspect-[3/4] bg-gray-50 border border-gray-100 cursor-pointer group/imgcontainer", onClick: () => setShowImagePicker(true), children: [imageId ? (_jsx(PluginImage, { id: imageId, alt: title || 'Hero', fill: true, sizes: "(max-width: 1024px) 100vw, 50vw", className: "object-cover w-full h-full transition-transform duration-700 group-hover/imgcontainer:scale-105", editable: false })) : (_jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center text-gray-400", children: [_jsx(ImageIcon, { size: 48, className: "mb-2" }), _jsx("p", { className: "text-sm font-bold", children: "Add Image" })] })), _jsx("div", { className: "absolute inset-0 bg-black/40 opacity-0 group-hover/imgcontainer:opacity-100 transition-opacity flex items-center justify-center z-10", children: _jsxs("div", { className: "bg-white px-4 py-2 rounded-full flex items-center gap-2", children: [_jsx(ImageIcon, { size: 16, className: "text-primary" }), _jsx("span", { className: "text-sm font-bold text-neutral-900", children: "Edit Image" })] }) })] }) })] }), showImagePicker && mounted && createPortal(_jsx("div", { className: "fixed inset-0 z-[100] flex items-center justify-center bg-black/60 backdrop-blur-sm p-4", children: _jsxs("div", { className: "bg-white dark:bg-neutral-900 rounded-2xl w-full max-w-2xl p-6 shadow-2xl max-h-[90vh] overflow-y-auto", children: [_jsxs("div", { className: "flex justify-between items-center mb-4", children: [_jsx("h3", { className: "font-bold text-neutral-900 dark:text-white", children: "Hero Image Settings" }), _jsx("button", { onClick: () => setShowImagePicker(false), className: "p-2 hover:bg-neutral-100 dark:hover:bg-neutral-800 rounded-lg transition-colors text-neutral-700 dark:text-neutral-300 hover:text-neutral-900 dark:hover:text-white", "aria-label": "Close", children: _jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "5", y1: "5", x2: "15", y2: "15" }), _jsx("line", { x1: "15", y1: "5", x2: "5", y2: "15" })] }) })] }), _jsx(ImagePicker, { value: imageId, onChange: (img) => {
|
|
50
52
|
updateField({ imageId: img === null || img === void 0 ? void 0 : img.id });
|
|
51
53
|
setTimeout(() => setShowImagePicker(false), 100);
|
|
52
54
|
}, showEffects: true, brightness: currentBrightness, blur: currentBlur, onBrightnessChange: (b) => { setCurrentBrightness(b); updateField({ brightness: b }); }, onBlurChange: (bl) => { setCurrentBlur(bl); updateField({ blur: bl }); } })] }) }), document.body)] }));
|
|
@@ -61,7 +63,13 @@ export const HeroPreview = ({ block, fallbackImage, context }) => {
|
|
|
61
63
|
// Logic: Use data.imageId, then fallback.id, then fallback.src
|
|
62
64
|
const activeImageId = data.imageId || (effectiveFallback === null || effectiveFallback === void 0 ? void 0 : effectiveFallback.id) || (effectiveFallback === null || effectiveFallback === void 0 ? void 0 : effectiveFallback.src);
|
|
63
65
|
const paragraphs = (data.summary || '').split('\n\n').filter(p => p.trim());
|
|
64
|
-
return (_jsx("section", { className: "relative pt-32 pb-20", children: _jsxs("div", { className: "max-w-7xl mx-auto px-6 lg:px-12 grid lg:grid-cols-2 gap-16 items-center", children: [_jsxs("div", { className: "order-2 lg:order-1", children: [_jsx("span", { className: "inline-flex px-4 py-1.5 rounded-full
|
|
66
|
+
return (_jsx("section", { className: "relative pt-32 pb-20", children: _jsxs("div", { className: "max-w-7xl mx-auto px-6 lg:px-12 grid lg:grid-cols-2 gap-16 items-center", children: [_jsxs("div", { className: "order-2 lg:order-1", children: [_jsx("span", { className: "inline-flex px-4 py-1.5 rounded-full text-xs font-bold uppercase tracking-widest mb-8", style: {
|
|
67
|
+
color: colors.sage,
|
|
68
|
+
borderWidth: 1,
|
|
69
|
+
borderStyle: 'solid',
|
|
70
|
+
borderColor: `${colors.sage}33`,
|
|
71
|
+
backgroundColor: `${colors.sage}0D`,
|
|
72
|
+
}, children: data.category || 'Plant Care' }), _jsx("h1", { className: "text-5xl lg:text-7xl font-serif mb-8 leading-[1.1]", style: { color: colors.forest }, children: data.title || 'Zonder Titel' }), paragraphs.map((p, i) => (_jsx("p", { className: "text-lg lg:text-xl text-gray-600 font-light mt-4", children: p }, i)))] }), _jsx("div", { className: "order-1 lg:order-2 w-full", children: _jsx("div", { className: "relative w-full aspect-[4/5] lg:aspect-[3/4] rounded-3xl overflow-hidden shadow-2xl bg-neutral-100", children: activeImageId && (_jsx(PluginImage, { id: activeImageId, alt: data.title || 'Hero', fill: true, sizes: "(max-width: 1024px) 100vw, 50vw", className: "object-cover w-full h-full", editable: false })) }) })] }) }));
|
|
65
73
|
};
|
|
66
74
|
export const heroBlock = {
|
|
67
75
|
type: 'hero',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"List.d.ts","sourceRoot":"","sources":["../../../src/plugin-blog/blocks/List.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"List.d.ts","sourceRoot":"","sources":["../../../src/plugin-blog/blocks/List.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAqC,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AA0H9F,eAAO,MAAM,SAAS,EAAE,qBAiBvB,CAAC"}
|
|
@@ -1,212 +1,81 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
+
import { useRef, useCallback } from 'react';
|
|
3
4
|
import { ListChecks } from "lucide-react";
|
|
4
|
-
import React from "react";
|
|
5
|
-
/**
|
|
6
|
-
* Rich Text Formatting Configuration for List Items
|
|
7
|
-
* Matches BotanicsAndYou's design system
|
|
8
|
-
*/
|
|
9
|
-
const listFormatting = {
|
|
10
|
-
bold: true,
|
|
11
|
-
italic: true,
|
|
12
|
-
underline: true,
|
|
13
|
-
links: true,
|
|
14
|
-
colors: ['text-forest', 'text-sage', 'text-primary'],
|
|
15
|
-
styles: {
|
|
16
|
-
bold: 'font-bold text-black',
|
|
17
|
-
italic: 'italic',
|
|
18
|
-
underline: 'underline decoration-primary/30',
|
|
19
|
-
link: 'text-primary underline decoration-primary/50 hover:text-primary/80 hover:decoration-primary/70 transition-colors',
|
|
20
|
-
colorClasses: {
|
|
21
|
-
'text-forest': 'text-forest',
|
|
22
|
-
'text-sage': 'text-sage',
|
|
23
|
-
'text-primary': 'text-primary',
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* 1. Shared UI Wrapper
|
|
29
|
-
*/
|
|
30
5
|
const ListContainer = ({ children, type }) => {
|
|
31
|
-
// Determine the tailwind class for bullet styling
|
|
32
6
|
const getListClass = () => {
|
|
33
7
|
if (type === "ol")
|
|
34
8
|
return "list-decimal pl-5";
|
|
35
9
|
if (type === "checklist")
|
|
36
10
|
return "list-none pl-0";
|
|
37
|
-
return "list-disc pl-5";
|
|
11
|
+
return "list-disc pl-5";
|
|
38
12
|
};
|
|
39
|
-
return (_jsx("div", { className: "
|
|
13
|
+
return (_jsx("div", { className: "rounded-2xl border border-gray-100 shadow-sm relative", children: _jsx("div", { className: "px-4 pb-4 mt-4", children: _jsx("ul", { className: `${getListClass()} space-y-3 pr-4 text-[color:var(--content-text-color,#374151)] font-[family:var(--content-font-family,inherit)]`, children: children }) }) }));
|
|
40
14
|
};
|
|
41
|
-
/**
|
|
42
|
-
* 2. Editor Component
|
|
43
|
-
*/
|
|
44
15
|
const ListEdit = ({ block, onUpdate }) => {
|
|
45
|
-
// Ensure items are treated consistently as ItemObj[]
|
|
46
|
-
// Handle both string[] (legacy) and ItemObj[] formats
|
|
47
|
-
const containerRef = React.useRef(null);
|
|
48
16
|
const rawItems = Array.isArray(block.data.items) ? block.data.items : [];
|
|
49
17
|
const items = rawItems.map((item) => {
|
|
50
|
-
if (typeof item === 'string')
|
|
51
|
-
return
|
|
52
|
-
}
|
|
18
|
+
if (typeof item === 'string')
|
|
19
|
+
return item;
|
|
53
20
|
if (typeof item === 'object' && item !== null && 'text' in item) {
|
|
54
|
-
|
|
55
|
-
return {
|
|
56
|
-
text: itemObj.text || '',
|
|
57
|
-
html: itemObj.html || itemObj.text || ''
|
|
58
|
-
};
|
|
21
|
+
return item.text || '';
|
|
59
22
|
}
|
|
60
|
-
return
|
|
23
|
+
return '';
|
|
61
24
|
});
|
|
62
25
|
const type = (block.data.type || "ul");
|
|
63
|
-
const
|
|
26
|
+
const inputRefs = useRef([]);
|
|
27
|
+
const handleKeyDown = useCallback((e, idx) => {
|
|
28
|
+
if (e.key === 'Enter') {
|
|
29
|
+
e.preventDefault();
|
|
30
|
+
const newItems = [...items];
|
|
31
|
+
newItems.splice(idx + 1, 0, '');
|
|
32
|
+
onUpdate({ items: newItems });
|
|
33
|
+
setTimeout(() => { var _a; return (_a = inputRefs.current[idx + 1]) === null || _a === void 0 ? void 0 : _a.focus(); }, 0);
|
|
34
|
+
}
|
|
35
|
+
if (e.key === 'Backspace' && items[idx] === '' && items.length > 1) {
|
|
36
|
+
e.preventDefault();
|
|
37
|
+
const newItems = items.filter((_, i) => i !== idx);
|
|
38
|
+
onUpdate({ items: newItems });
|
|
39
|
+
if (idx > 0) {
|
|
40
|
+
setTimeout(() => { var _a; return (_a = inputRefs.current[idx - 1]) === null || _a === void 0 ? void 0 : _a.focus(); }, 0);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}, [items, onUpdate]);
|
|
44
|
+
const handleChange = useCallback((idx, value) => {
|
|
64
45
|
const newItems = [...items];
|
|
65
|
-
newItems
|
|
46
|
+
newItems[idx] = value;
|
|
66
47
|
onUpdate({ items: newItems });
|
|
67
|
-
};
|
|
68
|
-
return (_jsx("
|
|
69
|
-
const html = item.html || item.text || '';
|
|
70
|
-
const isEmpty = !html || html.replace(/<[^>]*>/g, '').trim() === '';
|
|
71
|
-
return (_jsxs("li", { className: `${type === "checklist" ? "flex items-start gap-3" : ""}`, children: [type === "checklist" && (_jsx("input", { type: "checkbox", disabled: true, className: "mt-1.5 w-4 h-4 accent-gray-400 cursor-not-allowed shrink-0" })), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx(RichTextEditor, { value: html, onChange: (htmlContent) => {
|
|
72
|
-
const textContent = htmlContent.replace(/<[^>]*>/g, '').replace(/ /g, ' ');
|
|
73
|
-
const newItems = [...items];
|
|
74
|
-
newItems[idx] = {
|
|
75
|
-
text: textContent,
|
|
76
|
-
html: htmlContent
|
|
77
|
-
};
|
|
78
|
-
onUpdate({ items: newItems });
|
|
79
|
-
}, onKeyDown: (e) => {
|
|
80
|
-
const contentEditable = e.target;
|
|
81
|
-
if (!contentEditable || contentEditable.contentEditable !== 'true')
|
|
82
|
-
return;
|
|
83
|
-
const currentHtml = contentEditable.innerHTML || '';
|
|
84
|
-
const currentText = currentHtml.replace(/<[^>]*>/g, '').replace(/ /g, ' ').trim();
|
|
85
|
-
const isEmpty = !currentText || currentText === '';
|
|
86
|
-
// Intercept Enter key to create new list item instead of line break
|
|
87
|
-
if (e.key === 'Enter' && !e.shiftKey) {
|
|
88
|
-
e.preventDefault();
|
|
89
|
-
e.stopPropagation();
|
|
90
|
-
// Update current item with trimmed content
|
|
91
|
-
const newItems = [...items];
|
|
92
|
-
newItems[idx] = {
|
|
93
|
-
text: currentText,
|
|
94
|
-
html: currentText
|
|
95
|
-
};
|
|
96
|
-
// Add new item after current one
|
|
97
|
-
const newItem = { text: '', html: '' };
|
|
98
|
-
newItems.splice(idx + 1, 0, newItem);
|
|
99
|
-
onUpdate({ items: newItems });
|
|
100
|
-
// Focus the next editor after re-render
|
|
101
|
-
setTimeout(() => {
|
|
102
|
-
// Find all contentEditable elements and get the next one
|
|
103
|
-
const allEditors = document.querySelectorAll('[contenteditable="true"]');
|
|
104
|
-
const currentEditorIndex = Array.from(allEditors).indexOf(contentEditable);
|
|
105
|
-
const nextEditor = allEditors[currentEditorIndex + 1];
|
|
106
|
-
if (nextEditor) {
|
|
107
|
-
nextEditor.focus();
|
|
108
|
-
// Place cursor at the start
|
|
109
|
-
const range = document.createRange();
|
|
110
|
-
range.selectNodeContents(nextEditor);
|
|
111
|
-
range.collapse(true);
|
|
112
|
-
const selection = window.getSelection();
|
|
113
|
-
selection === null || selection === void 0 ? void 0 : selection.removeAllRanges();
|
|
114
|
-
selection === null || selection === void 0 ? void 0 : selection.addRange(range);
|
|
115
|
-
}
|
|
116
|
-
}, 0);
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
// Handle Backspace/Delete to remove empty list items
|
|
120
|
-
if ((e.key === 'Backspace' || e.key === 'Delete') && isEmpty && items.length > 1) {
|
|
121
|
-
const selection = window.getSelection();
|
|
122
|
-
if (!selection || selection.rangeCount === 0)
|
|
123
|
-
return;
|
|
124
|
-
const range = selection.getRangeAt(0);
|
|
125
|
-
const isAtStart = () => {
|
|
126
|
-
if (!range.collapsed)
|
|
127
|
-
return false;
|
|
128
|
-
const startRange = range.cloneRange();
|
|
129
|
-
startRange.selectNodeContents(contentEditable);
|
|
130
|
-
startRange.setEnd(range.startContainer, range.startOffset);
|
|
131
|
-
return startRange.toString().trim() === '';
|
|
132
|
-
};
|
|
133
|
-
if ((e.key === 'Backspace' && isAtStart())) {
|
|
134
|
-
e.preventDefault();
|
|
135
|
-
e.stopPropagation();
|
|
136
|
-
// Calculate focus index BEFORE updating state
|
|
137
|
-
const focusIndex = idx > 0 ? idx - 1 : 0;
|
|
138
|
-
const newItems = items.filter((_, i) => i !== idx);
|
|
139
|
-
onUpdate({ items: newItems });
|
|
140
|
-
setTimeout(() => {
|
|
141
|
-
// SCOPED SEARCH: Look only inside this specific list container
|
|
142
|
-
if (containerRef.current) {
|
|
143
|
-
const listEditors = containerRef.current.querySelectorAll('[contenteditable="true"]');
|
|
144
|
-
const targetEditor = listEditors[focusIndex];
|
|
145
|
-
if (targetEditor) {
|
|
146
|
-
targetEditor.focus();
|
|
147
|
-
const newRange = document.createRange();
|
|
148
|
-
newRange.selectNodeContents(targetEditor);
|
|
149
|
-
newRange.collapse(false); // Go to end of previous item
|
|
150
|
-
const newSel = window.getSelection();
|
|
151
|
-
newSel === null || newSel === void 0 ? void 0 : newSel.removeAllRanges();
|
|
152
|
-
newSel === null || newSel === void 0 ? void 0 : newSel.addRange(newRange);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}, 0);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}, placeholder: "Typ een item...", formatting: listFormatting, className: "leading-relaxed min-h-[1.5em] w-full text-gray-800", isFocused: false }), isEmpty && idx === items.length - 1 && (_jsx("button", { type: "button", onClick: () => handleAddItem(idx), className: "mt-2 text-xs text-gray-400 hover:text-gray-600", children: "+ Voeg item toe" }))] })] }, idx));
|
|
159
|
-
}) }) }));
|
|
48
|
+
}, [items, onUpdate]);
|
|
49
|
+
return (_jsx(ListContainer, { type: type, children: items.map((item, idx) => (_jsxs("li", { className: `${type === "checklist" ? "flex items-start gap-3" : ""}`, children: [type === "checklist" && (_jsx("input", { type: "checkbox", disabled: true, className: "mt-1.5 w-4 h-4 accent-gray-400 cursor-not-allowed shrink-0" })), _jsx("input", { ref: (el) => { inputRefs.current[idx] = el; }, type: "text", value: item, onChange: (e) => handleChange(idx, e.target.value), onKeyDown: (e) => handleKeyDown(e, idx), placeholder: "Typ een item...", className: "flex-1 leading-relaxed min-h-[1.5em] w-full text-[color:var(--content-text-color,#374151)] bg-transparent border-none outline-none focus:ring-0 p-0" })] }, idx))) }));
|
|
160
50
|
};
|
|
161
|
-
/**
|
|
162
|
-
* 3. Preview Component
|
|
163
|
-
*/
|
|
164
51
|
const ListPreview = ({ block }) => {
|
|
165
|
-
// Handle both string[] (legacy) and ItemObj[] formats
|
|
166
52
|
const rawItems = Array.isArray(block.data.items) ? block.data.items : [];
|
|
167
53
|
const items = rawItems.map((item) => {
|
|
168
|
-
if (typeof item === 'string')
|
|
169
|
-
return
|
|
170
|
-
}
|
|
54
|
+
if (typeof item === 'string')
|
|
55
|
+
return item;
|
|
171
56
|
if (typeof item === 'object' && item !== null && 'text' in item) {
|
|
172
|
-
|
|
173
|
-
return {
|
|
174
|
-
text: itemObj.text || '',
|
|
175
|
-
html: itemObj.html || itemObj.text || ''
|
|
176
|
-
};
|
|
57
|
+
return item.text || '';
|
|
177
58
|
}
|
|
178
|
-
return
|
|
59
|
+
return '';
|
|
179
60
|
});
|
|
180
61
|
const type = (block.data.type || "ul");
|
|
181
62
|
return (_jsx(ListContainer, { type: type, children: items.map((item, idx) => {
|
|
182
|
-
|
|
183
|
-
if (!html || html.replace(/<[^>]*>/g, '').trim() === '')
|
|
63
|
+
if (!item.trim())
|
|
184
64
|
return null;
|
|
185
|
-
return (_jsxs("li", { className: `${type === "checklist" ? "flex items-start gap-3" : ""}`, children: [type === "checklist" && (_jsx("input", { type: "checkbox", className: "mt-1.5 w-4 h-4 accent-gray-600 shrink-0" })), _jsx("
|
|
65
|
+
return (_jsxs("li", { className: `${type === "checklist" ? "flex items-start gap-3" : ""}`, children: [type === "checklist" && (_jsx("input", { type: "checkbox", className: "mt-1.5 w-4 h-4 accent-gray-600 shrink-0" })), _jsx("span", { className: "leading-relaxed text-[color:var(--content-text-color,#374151)]", children: item })] }, idx));
|
|
186
66
|
}) }));
|
|
187
67
|
};
|
|
188
68
|
export const listBlock = {
|
|
189
69
|
type: 'list',
|
|
190
70
|
name: 'Lijst',
|
|
191
|
-
description: '',
|
|
71
|
+
description: 'Opsomming met items',
|
|
192
72
|
icon: ListChecks,
|
|
193
73
|
defaultData: {
|
|
194
|
-
|
|
195
|
-
|
|
74
|
+
items: [''],
|
|
75
|
+
type: 'ul',
|
|
196
76
|
},
|
|
197
77
|
category: 'text',
|
|
198
|
-
validate: (data) =>
|
|
199
|
-
return typeof data.title === 'string' &&
|
|
200
|
-
Array.isArray(data.items) &&
|
|
201
|
-
data.items.every((item) => {
|
|
202
|
-
if (typeof item === 'string')
|
|
203
|
-
return true;
|
|
204
|
-
if (typeof item === 'object' && item !== null && 'text' in item) {
|
|
205
|
-
return typeof item.text === 'string';
|
|
206
|
-
}
|
|
207
|
-
return false;
|
|
208
|
-
});
|
|
209
|
-
},
|
|
78
|
+
validate: (data) => Array.isArray(data.items),
|
|
210
79
|
components: {
|
|
211
80
|
Edit: ListEdit,
|
|
212
81
|
Preview: ListPreview,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Paragraph.d.ts","sourceRoot":"","sources":["../../../src/plugin-blog/blocks/Paragraph.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Paragraph.d.ts","sourceRoot":"","sources":["../../../src/plugin-blog/blocks/Paragraph.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAqC,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAiD9F,eAAO,MAAM,cAAc,EAAE,qBAgB5B,CAAC"}
|