Jake Vanderwerf
2026-09-13 1aa7c404dae63c9518468fe9b579fad819f8d871
=Single Event page setup done through the new Event block. Currently working on the Simple Calendar block setup
29 files modified
20 files added
1055 ■■■■■ changed files
build/_meta/fields.asset.php 2 ●●●●● patch | view | raw | blame | history
build/_meta/fields.js 2 ●●●●● patch | view | raw | blame | history
build/event/block.json 29 ●●●●● patch | view | raw | blame | history
build/event/index-rtl.css 1 ●●●●● patch | view | raw | blame | history
build/event/index.asset.php 1 ●●●●● patch | view | raw | blame | history
build/event/index.css 1 ●●●●● patch | view | raw | blame | history
build/event/index.js 1 ●●●●● patch | view | raw | blame | history
build/event/render.php 5 ●●●●● patch | view | raw | blame | history
build/event/style-index-rtl.css 1 ●●●●● patch | view | raw | blame | history
build/event/style-index.css 1 ●●●●● patch | view | raw | blame | history
build/event/view.asset.php 1 ●●●●● patch | view | raw | blame | history
build/event/view.js patch | view | raw | blame | history
build/meta/index.asset.php 2 ●●●●● patch | view | raw | blame | history
build/meta/index.js 2 ●●●●● patch | view | raw | blame | history
build/simple-calendar/index.asset.php 2 ●●●●● patch | view | raw | blame | history
build/simple-calendar/style-index-rtl.css 2 ●●●●● patch | view | raw | blame | history
build/simple-calendar/style-index.css 2 ●●●●● patch | view | raw | blame | history
inc/blocks/EventBlock.php 300 ●●●●● patch | view | raw | blame | history
inc/blocks/FAQBlock.php 5 ●●●●● patch | view | raw | blame | history
inc/blocks/MenuBlock.php 2 ●●●●● patch | view | raw | blame | history
inc/blocks/SimpleCalendarBlock.php 280 ●●●●● patch | view | raw | blame | history
inc/blocks/_setup.php 5 ●●●●● patch | view | raw | blame | history
inc/integrations/SyncHelpers.php 2 ●●●●● patch | view | raw | blame | history
inc/integrations/SyncToPost.php 4 ●●●●● patch | view | raw | blame | history
inc/integrations/SyncToTerm.php 5 ●●●●● patch | view | raw | blame | history
inc/integrations/SyncToUser.php 5 ●●●●● patch | view | raw | blame | history
inc/integrations/services/Cloudflare.php 22 ●●●●● patch | view | raw | blame | history
inc/managers/DirectoryManager.php 4 ●●●●● patch | view | raw | blame | history
inc/meta/Meta.php 3 ●●●●● patch | view | raw | blame | history
inc/meta/Sanitizer.php 40 ●●●●● patch | view | raw | blame | history
inc/registrar/Fields.php 62 ●●●●● patch | view | raw | blame | history
inc/registrar/Registrar.php 11 ●●●●● patch | view | raw | blame | history
inc/registrar/helpers/AddCustomFields.php 9 ●●●●● patch | view | raw | blame | history
inc/registrar/helpers/MakeCalendarType.php 28 ●●●●● patch | view | raw | blame | history
jvb.php 3 ●●●●● patch | view | raw | blame | history
src/_meta/fields/date-field.js 3 ●●●●● patch | view | raw | blame | history
src/_meta/fields/datetime-field.js 4 ●●●●● patch | view | raw | blame | history
src/_meta/fields/selector-field.js 4 ●●●●● patch | view | raw | blame | history
src/_meta/fields/upload-field.js 9 ●●●●● patch | view | raw | blame | history
src/event/block.json 24 ●●●●● patch | view | raw | blame | history
src/event/edit.js 29 ●●●●● patch | view | raw | blame | history
src/event/editor.scss 20 ●●●●● patch | view | raw | blame | history
src/event/index.js 39 ●●●●● patch | view | raw | blame | history
src/event/index.php patch | view | raw | blame | history
src/event/render.php 5 ●●●●● patch | view | raw | blame | history
src/event/save.js 3 ●●●●● patch | view | raw | blame | history
src/event/style.scss 60 ●●●●● patch | view | raw | blame | history
src/event/view.js 1 ●●●●● patch | view | raw | blame | history
src/simple-calendar/style.scss 9 ●●●●● patch | view | raw | blame | history
build/_meta/fields.asset.php
@@ -1 +1 @@
<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-editor', 'wp-element', 'wp-i18n', 'wp-media-utils', 'wp-plugins', 'wp-url'), 'version' => 'b289cda300edfd519494');
<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-editor', 'wp-element', 'wp-i18n', 'wp-media-utils', 'wp-plugins', 'wp-url'), 'version' => '7d164cd5586570c7c4fc');
build/_meta/fields.js
@@ -1 +1 @@
(()=>{"use strict";const e={n:l=>{const t=l&&l.__esModule?()=>l.default:()=>l;return e.d(t,{a:t}),t},d:(l,t)=>{for(var n in t)e.o(t,n)&&!e.o(l,n)&&Object.defineProperty(l,n,{enumerable:!0,get:t[n]})},o:(e,l)=>Object.hasOwn(e,l)},l=window.wp.plugins,t=(window.wp.i18n,window.wp.compose),n=window.wp.data,a=window.wp.editor,i=window.wp.coreData,s=window.wp.components,o=window.ReactJSXRuntime,r={text:"text",email:"email",tel:"tel",url:"url",number:"number"},d=({field:e,value:l,onChange:t})=>"textarea"===e.type?(0,o.jsx)(s.TextareaControl,{label:e.label,help:e.description,value:l??"",onChange:t,id:e.name}):(0,o.jsx)(s.TextControl,{label:e.label,help:e.description,type:r[e.type]||"text",value:l??"",onChange:t,required:e.required,id:e.name}),c=({field:e,value:l,onChange:t})=>{const n=Object.entries(e.options||{}).map(([e,l])=>({label:l,value:e}));return"radio"===e.type?(0,o.jsx)(s.RadioControl,{label:e.label,help:e.description,selected:l,options:n,onChange:t,id:e.name}):(0,o.jsx)(s.SelectControl,{label:e.label,help:e.description,value:l??"",options:[{label:"— Select â€”",value:""},...n],onChange:t,id:e.name})},p=({field:e,value:l,onChange:t})=>{const n=Array.isArray(l)?l:[];return(0,o.jsxs)("fieldset",{id:e.name,children:[(0,o.jsx)("legend",{className:"jvb-field-label",children:e.label}),Object.entries(e.options||{}).map(([e,l])=>(0,o.jsx)(s.CheckboxControl,{label:l,checked:n.includes(e),onChange:l=>((e,l)=>{t(l?[...n,e]:n.filter(l=>l!==e))})(e,l)},e))]})},u=window.React,m=e=>{if(!e)return null;const[l,t,n]=e.split("-").map(Number);return new Date(l,t-1,n)},h=e=>{if(e.description&&0!==e.description.length)return(0,o.jsx)("p",{className:"hint",children:e.description})},v=e=>{if(e.description&&0!==e.description.length)return(0,o.jsx)("p",{className:"hint",children:e.description})},b=window.wp.element,j=(e,l,t)=>e?.includes("{{")?e.replace(/{{(.*?)}}/g,(e,t)=>{const n=l[t];return void 0===n?"":Array.isArray(n)?n.join(", "):String(n)}):e,x=window.wp.mediaUtils,g=window.wp.blockEditor,f=window.wp.apiFetch;var w=e.n(f);const y={image:"image",video:"video",document:"application",all:""},C=({id:e,onRemove:l})=>{const[t,n]=(0,b.useState)(null);(0,b.useEffect)(()=>{let l=!1;if(e)return w()({path:`/wp/v2/media/${e}`}).then(e=>!l&&n(e)).catch(()=>{}),()=>{l=!0}},[e]);const a=t?.media_details?.sizes?.thumbnail?.source_url||t?.source_url,i="image"===t?.media_type;return(0,o.jsxs)("div",{className:"jvb-upload-thumb",children:[i&&a?(0,o.jsx)("img",{src:a,alt:t?.alt_text||""}):(0,o.jsx)("div",{className:"jvb-upload-thumb-placeholder",children:t?.title?.rendered||`#${e}`}),(0,o.jsx)(s.Button,{variant:"link",isDestructive:!0,onClick:()=>l(e),children:"Remove"})]})},_=window.wp.url,k=e=>e.subtype||e.type,S=(e,l,t)=>"post"===l?{title:t,status:"publish",postType:e.post_type}:{name:t},N=(e,l)=>"user"===l?e.name:e.title?.rendered??e.title??e.name,A={text:d,email:d,tel:d,url:d,number:d,textarea:d,select:c,radio:c,checkbox:p,set:p,true_false:({field:e,value:l,onChange:t})=>(0,o.jsx)(s.ToggleControl,{label:e.label,help:e.description,checked:!!l,onChange:t,id:e.name}),date:({field:e,value:l,onChange:t})=>(0,o.jsxs)("div",{className:"components-base-control",id:e.name,children:[(0,o.jsx)("label",{className:"components-base-control__label",children:e.label}),(0,o.jsx)(s.DatePicker,{currentDate:m(l),onChange:t,help:e.description}),h(e)]}),time:({field:e,value:l,onChange:t})=>(0,o.jsx)(s.BaseControl,{label:e.label,help:e.description,id:e.name,children:(0,o.jsx)("input",{type:"time",id:e.name,value:l??"",onChange:e=>t(e.target.value)})}),datetime:({field:e,value:l,onChange:t})=>{const[n,a]=(0,u.useState)(new Date);return(0,o.jsxs)("div",{className:"components-base-control",id:e.name,children:[(0,o.jsx)("label",{className:"components-base-control__label",children:e.label}),(0,o.jsx)(s.DateTimePicker,{currentDate:n,onChange:t,label:e.label,help:e.description,value:l??"",is12Hour:!0}),v(e)]})},repeater:({field:e,value:l,onChange:t,meta:n})=>{const a=Array.isArray(l)?l:[],i=e.fields||{},[r,d]=(0,b.useState)(null);return(0,o.jsxs)("div",{className:"jvb-repeater-field",id:e.name,children:[(0,o.jsx)("p",{className:"jvb-field-label",children:e.label}),(0,o.jsx)(s.Panel,{children:a.map((l,c)=>(0,o.jsxs)(s.PanelBody,{title:j(e.row_label,l)||`Row ${c+1}`,initialOpen:r===c,onToggle:()=>d(r===c?null:c),children:[Object.entries(i).map(([e,i])=>(0,o.jsx)(R,{field:{...i,name:e},value:l[e],onChange:l=>((e,l,n)=>{const i=a.map((t,a)=>a===e?{...t,[l]:n}:t);t(i)})(c,e,l),meta:n},e)),(0,o.jsx)(s.Button,{variant:"link",isDestructive:!0,onClick:()=>(e=>t(a.filter((l,t)=>t!==e)))(c),children:"Remove"})]},c))}),(0,o.jsx)(s.Button,{variant:"secondary",onClick:()=>{return t([...a,(e=i,Object.fromEntries(Object.entries(e||{}).map(([e,l])=>[e,l.default??""])))]);var e},children:e.add_label||"Add Row"})]})},upload:({field:e,value:l,onChange:t})=>{const n=e.multiple||"gallery"===e.type,a=n?Array.isArray(l)?l:[]:l,i=y[e.subtype]?[y[e.subtype]]:"",r=e=>{t(n?a.filter(l=>l!==e):0)};return(0,o.jsxs)("div",{className:"jvb-upload-field",id:e.name,children:[(0,o.jsx)("p",{className:"jvb-field-label",children:e.label}),(0,o.jsx)("div",{className:n?"jvb-upload-grid":"jvb-upload-single",children:n?a.map(e=>(0,o.jsx)(C,{id:e,onRemove:r},e)):!!a&&(0,o.jsx)(C,{id:a,onRemove:r})}),(0,o.jsx)(g.MediaUploadCheck,{children:(0,o.jsx)(x.MediaUpload,{onSelect:e=>t(n?e.map(e=>e.id):e.id),allowedTypes:i,multiple:n,value:n?a:a||void 0,render:({open:l})=>(0,o.jsxs)(s.Button,{variant:"secondary",onClick:l,children:[(n?a.length:a)?"Change":"Select"," ",e.label]})})})]})},selector:({field:e,value:l,onChange:t})=>{const n=k(e),a="taxonomy"===n,i=(e=>{const l=k(e);return"user"===l?e=>(0,_.addQueryArgs)("/wp/v2/users",{search:e,per_page:20}):"taxonomy"===l?l=>(0,_.addQueryArgs)(`/wp/v2/${e.taxonomy}`,{search:l,per_page:20,hide_empty:!1}):l=>(0,_.addQueryArgs)("/wp/v2/search",{search:l,type:"post",subtype:e.post_type,per_page:20})})(e),r=Array.isArray(l)?l:l?l.split(","):[],[d,c]=(0,b.useState)([]),[p,u]=(0,b.useState)({}),[m,h]=(0,b.useState)({}),[v,j]=(0,b.useState)(""),[x,g]=(0,b.useState)(!1),f=v?`Not found. Create "${v}"?`:null;(0,b.useEffect)(()=>{y("");let e=!1;if(r.length)return Promise.all(r.map(e=>w()({path:i("")+`&include=${e}`}))).then(l=>{if(e)return;const t={},a=[];l.flat().forEach(e=>{const l=N(e,n);t[l]=e.id,a.push(l)}),u(e=>({...e,...t})),c(a)}).catch(()=>{}),()=>{e=!0};c([])},[JSON.stringify(r)]);const y=(0,b.useCallback)(e=>{j(e),w()({path:i(e)}).then(e=>{const l={};e.forEach(e=>{l[N(e,n)]=e.id}),h(l)}).catch(()=>{})},[i,n]),C=l=>{const n=1===e.max;t(n?l[l.length-1]??0:(e.max?l.slice(0,e.max):l).join(","))},A=v&&!Object.keys(m).some(e=>e.toLowerCase()===v.toLowerCase()),O=1===e.max&&d.length?[]:[...Object.keys(m),...a&&A?[f]:[]];return(0,o.jsx)(s.FormTokenField,{label:e.label,help:e.description,value:d,suggestions:O,onChange:l=>{if(l.find(e=>e===f)&&a&&!x)return g(!0),void w()({path:`/wp/v2/${e.taxonomy}`,method:"POST",data:S(n,v)}).then(e=>{const l=N(e,n),t=d.filter(e=>e!==f).concat(l),a=t.map(t=>p[t]??m[t]??(t===l?e.id:void 0)).filter(e=>void 0!==e);u(t=>({...t,[l]:e.id})),c(t),C(a)}).catch(()=>{}).finally(()=>g(!1));const t=l.filter(e=>void 0!==p[e]||void 0!==m[e]),i=t.map(e=>p[e]??m[e]);c(t),u(e=>({...e,...m})),C(i)},onInputChange:y,maxLength:e.max||void 0,id:e.name,__experimentalExpandOnFocus:!0})},location:({field:e,value:l,onChange:n})=>{const a=l||{},[i,r]=(0,b.useState)(a.address||""),[d,c]=(0,b.useState)([]),[p,u]=(0,b.useState)(!1),m=(0,t.useDebounce)(e=>{if(!e)return c([]);u(!0),w()({path:`jvb/v1/geocode?q=${encodeURIComponent(e)}`}).then(c).finally(()=>u(!1))},400);return(0,o.jsxs)("div",{className:"jvb-location-field",id:e.name,children:[(0,o.jsx)(s.TextControl,{label:e.label,value:i,onChange:e=>{r(e),m(e)}}),p&&(0,o.jsx)(s.Spinner,{}),!!d.length&&(0,o.jsxs)("div",{className:"jvb-location-results",children:[d.map(e=>(0,o.jsx)(s.Button,{variant:"tertiary",onClick:()=>(e=>{const l=e.address||{},t={address:[l.house_number,l.road].filter(Boolean).join(" "),city:l.city||l.town||l.village||"",province:l.state||"",postal_code:l.postcode||"",country:l.country||"",lat:parseFloat(e.lat),lng:parseFloat(e.lng)};n(t),r(t.address),c([])})(e),style:{display:"block",textAlign:"left"},children:e.display_name},e.place_id)),!!a.lat&&(0,o.jsxs)("p",{className:"jvb-location-summary",children:[a.address,", ",a.city,", ",a.province," ",a.postal_code,", ",a.country,(0,o.jsx)("br",{}),(0,o.jsx)(s.Button,{variant:"link",isDestructive:!0,onClick:()=>{n({}),r(""),c([])},children:"Clear"})]})]})]})},group:({field:e,value:l,onChange:t})=>{const n=l||{};return(0,o.jsxs)("div",{className:"jvb-group-field",id:e.name,children:[e.label&&(0,o.jsx)("h4",{className:"components-base-control__label",children:e.label}),Object.entries(e.fields||{}).map(([e,l])=>(0,o.jsx)(R,{field:{...l,name:e},value:n[e],onChange:l=>((e,l)=>{t({...n,[e]:l})})(e,l),meta:n},e)),e.description&&(0,o.jsx)("p",{className:"hint",children:e.description})]})}},O={"=":(e,l)=>e==l,"==":(e,l)=>e==l,"!=":(e,l)=>e!=l,">":(e,l)=>e>l,"<":(e,l)=>e<l,in:(e,l)=>Array.isArray(l)?l.includes(e):String(l).split(",").includes(e)},R=({id:e,field:l,value:t,onChange:n,meta:a})=>{if(!((e,l)=>!e?.field||(O[e.operator]||O["="])(l?.[e.field],e.value))(l.condition,a))return null;const i=A[l.type];return i?(0,o.jsx)(s.PanelRow,{children:(0,o.jsx)(i,{field:l,value:t,onChange:n})}):null},P=({id:e,name:l,fields:t,meta:n,setMeta:a,isOpen:i=!1})=>(e="jvb-section-"+e,(0,o.jsx)(s.PanelBody,{name:e,title:l,initialOpen:i,children:t.map(e=>(0,o.jsx)(R,{field:e,value:n?.[e.name],onChange:l=>((e,l)=>a({...n,[e]:l}))(e.name,l),meta:n},e.name))})),F=()=>(0,o.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",fillRule:"evenodd",strokeLinecap:"square",strokeLinejoin:"round",strokeMiterlimit:"1.5",clipRule:"evenodd",viewBox:"0 0 32 32",children:(0,o.jsx)("path",{fill:"currentColor",fillRule:"nonzero",d:"M16.58 2.133c-7.715 0-15.14 6.014-14.547 13.707.561 7.287 6.938 13.185 13.938 13.947 8.25.898 14.47-5.953 14.004-13.988-.447-7.7-5.683-13.666-13.395-13.666m0 .607h.031v26.492q-.285-.017-.574-.048c-6.724-.732-12.86-6.391-13.398-13.391C2.072 8.442 9.209 2.74 16.58 2.74m-.488 1.145L16 3.889c-3.275.13-6.448 1.476-8.744 3.611-2.297 2.135-3.716 5.065-3.463 8.346.492 6.384 6.071 11.538 12.201 12.207l.09.01.021-.182-.091-.01c-6.041-.66-11.555-5.755-12.04-12.04-.247-3.221 1.142-6.092 3.405-8.196s5.4-3.437 8.629-3.565l.092-.004zm0 1.502L16 5.39c-2.868.113-5.647 1.293-7.658 3.164-2.012 1.87-3.255 4.436-3.033 7.31.43 5.593 5.316 10.106 10.685 10.692l.09.01.021-.18-.091-.01c-5.28-.576-10.1-5.031-10.524-10.525-.217-2.815.997-5.325 2.975-7.164 1.978-1.84 4.72-3.004 7.543-3.116l.092-.004zm0 1.504L16 6.893c-2.462.097-4.846 1.111-6.572 2.716-1.727 1.606-2.796 3.808-2.606 6.276.37 4.8 4.564 8.674 9.172 9.177l.09.01.021-.181-.091-.01c-4.52-.494-8.648-4.307-9.01-9.01-.186-2.408.854-4.554 2.547-6.129s4.04-2.57 6.457-2.666l.092-.004zm0 1.502L16 8.396c-2.055.082-4.045.926-5.486 2.266-1.442 1.34-2.335 3.182-2.176 5.244.309 4.009 3.808 7.24 7.656 7.66l.09.01.008-.068v-.002l.002-.01.004-.01v-.02l.007-.072-.091-.01c-3.76-.41-7.193-3.58-7.494-7.491-.155-2.002.709-3.787 2.117-5.096s3.361-2.14 5.37-2.219l.093-.004zm0 1.502L16 9.898a6.95 6.95 0 0 0-4.402 1.819c-1.157 1.075-1.872 2.553-1.744 4.209.247 3.216 3.053 5.81 6.14 6.146l.09.01.021-.182-.091-.01c-2.999-.327-5.739-2.86-5.979-5.978-.123-1.595.564-3.018 1.688-4.062a6.78 6.78 0 0 1 4.285-1.77l.092-.004zm0 1.503L16 11.4a5.24 5.24 0 0 0-3.316 1.372c-.872.81-1.413 1.924-1.317 3.173.187 2.425 2.3 4.377 4.627 4.631l.09.01.021-.182-.091-.01c-2.238-.244-4.286-2.136-4.465-4.462-.092-1.19.421-2.248 1.26-3.028a5.06 5.06 0 0 1 3.199-1.32l.092-.004zm0 1.502-.092.004a3.52 3.52 0 0 0-2.23.92c-.587.546-.952 1.3-.887 2.143.126 1.633 1.545 2.942 3.111 3.113h-.008l.01.002h.01l.078.01.022-.182-.092-.01c-1.477-.16-2.831-1.412-2.95-2.947-.06-.782.277-1.48.83-1.994a3.35 3.35 0 0 1 2.114-.873l.092-.004zm0 1.502-.092.004c-.43.017-.843.192-1.145.473-.301.28-.49.67-.457 1.107.065.841.791 1.512 1.596 1.6l.09.01.021-.182-.091-.01c-.717-.078-1.377-.688-1.434-1.431-.029-.377.132-.712.4-.961.269-.25.644-.409 1.028-.424l.092-.004z",clipRule:"nonzero",overflow:"visible"})}),T=(0,n.withSelect)(e=>({metaFields:e("core/editor").getEditedPostAttribute("meta"),postType:e("core/editor").getCurrentPostType()})),D=(0,n.withDispatch)(e=>({setMetaFields(l){e("core/editor").editPost({meta:l})}})),z=({section:e,fields:l})=>l.filter(l=>e.fields.includes(l.name)),B=e=>0===e,L=(0,t.compose)([T,D])(({postType:e,metaFields:l,setMetaFields:t})=>{const{fields:n,sections:s}=window.jvbFieldConfig||{},[r,d]=(0,i.useEntityProp)("postType",e,"meta");return n&&n.length?(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(a.PluginSidebarMoreMenuItem,{target:"jvb-meta-fields",icon:(0,o.jsx)(F,{}),children:"Additional Fields"}),(0,o.jsx)(a.PluginSidebar,{name:"jvb-meta-fields",icon:(0,o.jsx)(F,{}),title:"Additional Fields",children:Object.values(s).map((e,l)=>(0,o.jsx)(P,{name:e.title,fields:z({section:e,fields:n}),meta:r,setMeta:d,isOpen:B(l)},e.id))})]}):null});(0,l.registerPlugin)("jvb-meta-fields",{render:L})})();
(()=>{"use strict";const e={n:l=>{const t=l&&l.__esModule?()=>l.default:()=>l;return e.d(t,{a:t}),t},d:(l,t)=>{for(var n in t)e.o(t,n)&&!e.o(l,n)&&Object.defineProperty(l,n,{enumerable:!0,get:t[n]})},o:(e,l)=>Object.hasOwn(e,l)},l=window.wp.plugins,t=(window.wp.i18n,window.wp.compose),n=window.wp.data,a=window.wp.editor,i=window.wp.coreData,s=window.wp.components,o=window.ReactJSXRuntime,r={text:"text",email:"email",tel:"tel",url:"url",number:"number"},d=({field:e,value:l,onChange:t})=>"textarea"===e.type?(0,o.jsx)(s.TextareaControl,{label:e.label,help:e.description,value:l??"",onChange:t,id:e.name}):(0,o.jsx)(s.TextControl,{label:e.label,help:e.description,type:r[e.type]||"text",value:l??"",onChange:t,required:e.required,id:e.name}),c=({field:e,value:l,onChange:t})=>{const n=Object.entries(e.options||{}).map(([e,l])=>({label:l,value:e}));return"radio"===e.type?(0,o.jsx)(s.RadioControl,{label:e.label,help:e.description,selected:l,options:n,onChange:t,id:e.name}):(0,o.jsx)(s.SelectControl,{label:e.label,help:e.description,value:l??"",options:[{label:"— Select â€”",value:""},...n],onChange:t,id:e.name})},p=({field:e,value:l,onChange:t})=>{const n=Array.isArray(l)?l:[];return(0,o.jsxs)("fieldset",{id:e.name,children:[(0,o.jsx)("legend",{className:"jvb-field-label",children:e.label}),Object.entries(e.options||{}).map(([e,l])=>(0,o.jsx)(s.CheckboxControl,{label:l,checked:n.includes(e),onChange:l=>((e,l)=>{t(l?[...n,e]:n.filter(l=>l!==e))})(e,l)},e))]})},u=e=>{if(!e)return null;const[l,t,n]=e.split("-").map(Number);return l&&t&&n?new Date(l,t-1,n):null},m=e=>{if(e.description&&0!==e.description.length)return(0,o.jsx)("p",{className:"hint",children:e.description})},h=(window.React,e=>{if(e.description&&0!==e.description.length)return(0,o.jsx)("p",{className:"hint",children:e.description})}),v=window.wp.element,b=(e,l,t)=>e?.includes("{{")?e.replace(/{{(.*?)}}/g,(e,t)=>{const n=l[t];return void 0===n?"":Array.isArray(n)?n.join(", "):String(n)}):e,j=window.wp.mediaUtils,x=window.wp.blockEditor,g=window.wp.apiFetch;var f=e.n(g);const w={image:"image",video:"video",document:"application",all:""},y=({id:e,onRemove:l})=>{const[t,n]=(0,v.useState)(null);(0,v.useEffect)(()=>{let l=!1;if(e)return f()({path:`/wp/v2/media/${e}`}).then(e=>!l&&n(e)).catch(()=>{}),()=>{l=!0}},[e]);const a=t?.media_details?.sizes?.thumbnail?.source_url||t?.source_url,i="image"===t?.media_type;return(0,o.jsxs)("div",{className:"jvb-upload-thumb",children:[i&&a?(0,o.jsx)("img",{src:a,alt:t?.alt_text||""}):(0,o.jsx)("div",{className:"jvb-upload-thumb-placeholder",children:t?.title?.rendered||`#${e}`}),(0,o.jsx)(s.Button,{variant:"link",isDestructive:!0,onClick:()=>l(e),children:"Remove"})]})},C=window.wp.url,_=e=>e.subtype||e.type,k=(e,l,t)=>"post"===l?{title:t,status:"publish",postType:e.post_type}:{name:t},N=(e,l)=>"user"===l?e.name:e.title?.rendered??e.title??e.name,S={text:d,email:d,tel:d,url:d,number:d,textarea:d,select:c,radio:c,checkbox:p,set:p,true_false:({field:e,value:l,onChange:t})=>(0,o.jsx)(s.ToggleControl,{label:e.label,help:e.description,checked:!!l,onChange:t,id:e.name}),date:({field:e,value:l,onChange:t})=>(0,o.jsxs)("div",{className:"components-base-control",id:e.name,children:[(0,o.jsx)("label",{className:"components-base-control__label",children:e.label}),(0,o.jsx)(s.DatePicker,{currentDate:u(l),onChange:t,help:e.description}),m(e)]}),time:({field:e,value:l,onChange:t})=>(0,o.jsx)(s.BaseControl,{label:e.label,help:e.description,id:e.name,children:(0,o.jsx)("input",{type:"time",id:e.name,value:l??"",onChange:e=>t(e.target.value)})}),datetime:({field:e,value:l,onChange:t})=>(0,o.jsxs)("div",{className:"components-base-control",id:e.name,children:[(0,o.jsx)("label",{className:"components-base-control__label",children:e.label}),(0,o.jsx)(s.DateTimePicker,{currentDate:l||null,onChange:t,help:e.description,value:l??"",is12Hour:!0}),h(e)]}),repeater:({field:e,value:l,onChange:t,meta:n})=>{const a=Array.isArray(l)?l:[],i=e.fields||{},[r,d]=(0,v.useState)(null);return(0,o.jsxs)("div",{className:"jvb-repeater-field",id:e.name,children:[(0,o.jsx)("p",{className:"jvb-field-label",children:e.label}),(0,o.jsx)(s.Panel,{children:a.map((l,c)=>(0,o.jsxs)(s.PanelBody,{title:b(e.row_label,l)||`Row ${c+1}`,initialOpen:r===c,onToggle:()=>d(r===c?null:c),children:[Object.entries(i).map(([e,i])=>(0,o.jsx)(A,{field:{...i,name:e},value:l[e],onChange:l=>((e,l,n)=>{const i=a.map((t,a)=>a===e?{...t,[l]:n}:t);t(i)})(c,e,l),meta:n},e)),(0,o.jsx)(s.Button,{variant:"link",isDestructive:!0,onClick:()=>(e=>t(a.filter((l,t)=>t!==e)))(c),children:"Remove"})]},c))}),(0,o.jsx)(s.Button,{variant:"secondary",onClick:()=>{return t([...a,(e=i,Object.fromEntries(Object.entries(e||{}).map(([e,l])=>[e,l.default??""])))]);var e},children:e.add_label||"Add Row"})]})},upload:({field:e,value:l,onChange:t})=>{const n=e.multiple||"gallery"===e.type,a=n?"string"==typeof l&&l?l.split(",").map(Number):[]:l,i=w[e.subtype]?[w[e.subtype]]:"",r=e=>{t(n?a.filter(l=>l!==e).join(","):0)};return(0,o.jsxs)("div",{className:"jvb-upload-field",id:e.name,children:[(0,o.jsx)("p",{className:"jvb-field-label",children:e.label}),(0,o.jsx)("div",{className:n?"jvb-upload-grid":"jvb-upload-single",children:n?a.map(e=>(0,o.jsx)(y,{id:e,onRemove:r},e)):!!a&&(0,o.jsx)(y,{id:a,onRemove:r})}),(0,o.jsx)(x.MediaUploadCheck,{children:(0,o.jsx)(j.MediaUpload,{onSelect:e=>t(n?e.map(e=>e.id).join(","):e.id),allowedTypes:i,multiple:n,value:n?a:a||void 0,render:({open:l})=>(0,o.jsxs)(s.Button,{variant:"secondary",onClick:l,children:[(n?a.length:a)?"Change":"Select"," ",e.label]})})})]})},selector:({field:e,value:l,onChange:t})=>{const n=_(e),a="taxonomy"===n,i=(e=>{const l=_(e);return"user"===l?e=>(0,C.addQueryArgs)("/wp/v2/users",{search:e,per_page:20}):"taxonomy"===l?l=>(0,C.addQueryArgs)(`/wp/v2/${e.taxonomy}`,{search:l,per_page:20,hide_empty:!1}):l=>(0,C.addQueryArgs)("/wp/v2/search",{search:l,type:"post",subtype:e.post_type,per_page:20})})(e),r=Array.isArray(l)?l:l?l.split(","):[],[d,c]=(0,v.useState)([]),[p,u]=(0,v.useState)({}),[m,h]=(0,v.useState)({}),[b,j]=(0,v.useState)(""),[x,g]=(0,v.useState)(!1),w=b?`Not found. Create "${b}"?`:null;(0,v.useEffect)(()=>{y("");let e=!1;if(r.length)return Promise.all(r.map(e=>f()({path:i("")+`&include=${e}`}))).then(l=>{if(e)return;const t={},a=[];l.flat().forEach(e=>{const l=N(e,n);t[l]=e.id,a.push(l)}),u(e=>({...e,...t})),c(a)}).catch(()=>{}),()=>{e=!0};c([])},[JSON.stringify(r)]);const y=(0,v.useCallback)(e=>{j(e),f()({path:i(e)}).then(e=>{const l={};e.forEach(e=>{l[N(e,n)]=e.id}),h(l)}).catch(()=>{})},[i,n]),S=l=>{const n=1===e.max;t(n?l[l.length-1]??0:(e.max?l.slice(0,e.max):l).join(","))},O=b&&!Object.keys(m).some(e=>e.toLowerCase()===b.toLowerCase()),A=1===e.max&&d.length?[]:[...Object.keys(m),...a&&O?[w]:[]];return(0,o.jsx)(s.FormTokenField,{label:e.label,help:e.description,value:d,suggestions:A,onChange:l=>{if(l.find(e=>e===w)&&a&&!x)return g(!0),void f()({path:`/wp/v2/${e.taxonomy}`,method:"POST",data:k(e,n,b)}).then(e=>{const l=N(e,n),t=d.filter(e=>e!==w).concat(l),a=t.map(t=>p[t]??m[t]??(t===l?e.id:void 0)).filter(e=>void 0!==e);u(t=>({...t,[l]:e.id})),c(t),S(a)}).catch(()=>{}).finally(()=>g(!1));const t=l.filter(e=>void 0!==p[e]||void 0!==m[e]),i=t.map(e=>p[e]??m[e]);c(t),u(e=>({...e,...m})),S(i)},onInputChange:y,maxLength:e.max||void 0,id:e.name,__experimentalExpandOnFocus:!0})},location:({field:e,value:l,onChange:n})=>{const a=l||{},[i,r]=(0,v.useState)(a.address||""),[d,c]=(0,v.useState)([]),[p,u]=(0,v.useState)(!1),m=(0,t.useDebounce)(e=>{if(!e)return c([]);u(!0),f()({path:`jvb/v1/geocode?q=${encodeURIComponent(e)}`}).then(c).finally(()=>u(!1))},400);return(0,o.jsxs)("div",{className:"jvb-location-field",id:e.name,children:[(0,o.jsx)(s.TextControl,{label:e.label,value:i,onChange:e=>{r(e),m(e)}}),p&&(0,o.jsx)(s.Spinner,{}),!!d.length&&(0,o.jsxs)("div",{className:"jvb-location-results",children:[d.map(e=>(0,o.jsx)(s.Button,{variant:"tertiary",onClick:()=>(e=>{const l=e.address||{},t={address:[l.house_number,l.road].filter(Boolean).join(" "),city:l.city||l.town||l.village||"",province:l.state||"",postal_code:l.postcode||"",country:l.country||"",lat:parseFloat(e.lat),lng:parseFloat(e.lng)};n(t),r(t.address),c([])})(e),style:{display:"block",textAlign:"left"},children:e.display_name},e.place_id)),!!a.lat&&(0,o.jsxs)("p",{className:"jvb-location-summary",children:[a.address,", ",a.city,", ",a.province," ",a.postal_code,", ",a.country,(0,o.jsx)("br",{}),(0,o.jsx)(s.Button,{variant:"link",isDestructive:!0,onClick:()=>{n({}),r(""),c([])},children:"Clear"})]})]})]})},group:({field:e,value:l,onChange:t})=>{const n=l||{};return(0,o.jsxs)("div",{className:"jvb-group-field",id:e.name,children:[e.label&&(0,o.jsx)("h4",{className:"components-base-control__label",children:e.label}),Object.entries(e.fields||{}).map(([e,l])=>(0,o.jsx)(A,{field:{...l,name:e},value:n[e],onChange:l=>((e,l)=>{t({...n,[e]:l})})(e,l),meta:n},e)),e.description&&(0,o.jsx)("p",{className:"hint",children:e.description})]})}},O={"=":(e,l)=>e==l,"==":(e,l)=>e==l,"!=":(e,l)=>e!=l,">":(e,l)=>e>l,"<":(e,l)=>e<l,in:(e,l)=>Array.isArray(l)?l.includes(e):String(l).split(",").includes(e)},A=({id:e,field:l,value:t,onChange:n,meta:a})=>{if(!((e,l)=>!e?.field||(O[e.operator]||O["="])(l?.[e.field],e.value))(l.condition,a))return null;const i=S[l.type];return i?(0,o.jsx)(s.PanelRow,{children:(0,o.jsx)(i,{field:l,value:t,onChange:n})}):null},R=({id:e,name:l,fields:t,meta:n,setMeta:a,isOpen:i=!1})=>(e="jvb-section-"+e,(0,o.jsx)(s.PanelBody,{name:e,title:l,initialOpen:i,children:t.map(e=>(0,o.jsx)(A,{field:e,value:n?.[e.name],onChange:l=>((e,l)=>a({...n,[e]:l}))(e.name,l),meta:n},e.name))})),P=()=>(0,o.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",fillRule:"evenodd",strokeLinecap:"square",strokeLinejoin:"round",strokeMiterlimit:"1.5",clipRule:"evenodd",viewBox:"0 0 32 32",children:(0,o.jsx)("path",{fill:"currentColor",fillRule:"nonzero",d:"M16.58 2.133c-7.715 0-15.14 6.014-14.547 13.707.561 7.287 6.938 13.185 13.938 13.947 8.25.898 14.47-5.953 14.004-13.988-.447-7.7-5.683-13.666-13.395-13.666m0 .607h.031v26.492q-.285-.017-.574-.048c-6.724-.732-12.86-6.391-13.398-13.391C2.072 8.442 9.209 2.74 16.58 2.74m-.488 1.145L16 3.889c-3.275.13-6.448 1.476-8.744 3.611-2.297 2.135-3.716 5.065-3.463 8.346.492 6.384 6.071 11.538 12.201 12.207l.09.01.021-.182-.091-.01c-6.041-.66-11.555-5.755-12.04-12.04-.247-3.221 1.142-6.092 3.405-8.196s5.4-3.437 8.629-3.565l.092-.004zm0 1.502L16 5.39c-2.868.113-5.647 1.293-7.658 3.164-2.012 1.87-3.255 4.436-3.033 7.31.43 5.593 5.316 10.106 10.685 10.692l.09.01.021-.18-.091-.01c-5.28-.576-10.1-5.031-10.524-10.525-.217-2.815.997-5.325 2.975-7.164 1.978-1.84 4.72-3.004 7.543-3.116l.092-.004zm0 1.504L16 6.893c-2.462.097-4.846 1.111-6.572 2.716-1.727 1.606-2.796 3.808-2.606 6.276.37 4.8 4.564 8.674 9.172 9.177l.09.01.021-.181-.091-.01c-4.52-.494-8.648-4.307-9.01-9.01-.186-2.408.854-4.554 2.547-6.129s4.04-2.57 6.457-2.666l.092-.004zm0 1.502L16 8.396c-2.055.082-4.045.926-5.486 2.266-1.442 1.34-2.335 3.182-2.176 5.244.309 4.009 3.808 7.24 7.656 7.66l.09.01.008-.068v-.002l.002-.01.004-.01v-.02l.007-.072-.091-.01c-3.76-.41-7.193-3.58-7.494-7.491-.155-2.002.709-3.787 2.117-5.096s3.361-2.14 5.37-2.219l.093-.004zm0 1.502L16 9.898a6.95 6.95 0 0 0-4.402 1.819c-1.157 1.075-1.872 2.553-1.744 4.209.247 3.216 3.053 5.81 6.14 6.146l.09.01.021-.182-.091-.01c-2.999-.327-5.739-2.86-5.979-5.978-.123-1.595.564-3.018 1.688-4.062a6.78 6.78 0 0 1 4.285-1.77l.092-.004zm0 1.503L16 11.4a5.24 5.24 0 0 0-3.316 1.372c-.872.81-1.413 1.924-1.317 3.173.187 2.425 2.3 4.377 4.627 4.631l.09.01.021-.182-.091-.01c-2.238-.244-4.286-2.136-4.465-4.462-.092-1.19.421-2.248 1.26-3.028a5.06 5.06 0 0 1 3.199-1.32l.092-.004zm0 1.502-.092.004a3.52 3.52 0 0 0-2.23.92c-.587.546-.952 1.3-.887 2.143.126 1.633 1.545 2.942 3.111 3.113h-.008l.01.002h.01l.078.01.022-.182-.092-.01c-1.477-.16-2.831-1.412-2.95-2.947-.06-.782.277-1.48.83-1.994a3.35 3.35 0 0 1 2.114-.873l.092-.004zm0 1.502-.092.004c-.43.017-.843.192-1.145.473-.301.28-.49.67-.457 1.107.065.841.791 1.512 1.596 1.6l.09.01.021-.182-.091-.01c-.717-.078-1.377-.688-1.434-1.431-.029-.377.132-.712.4-.961.269-.25.644-.409 1.028-.424l.092-.004z",clipRule:"nonzero",overflow:"visible"})}),F=(0,n.withSelect)(e=>({metaFields:e("core/editor").getEditedPostAttribute("meta"),postType:e("core/editor").getCurrentPostType()})),T=(0,n.withDispatch)(e=>({setMetaFields(l){e("core/editor").editPost({meta:l})}})),z=({section:e,fields:l})=>l.filter(l=>e.fields.includes(l.name)),B=e=>0===e,D=(0,t.compose)([F,T])(({postType:e,metaFields:l,setMetaFields:t})=>{const{fields:n,sections:s}=window.jvbFieldConfig||{},[r,d]=(0,i.useEntityProp)("postType",e,"meta");return n&&n.length?(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(a.PluginSidebarMoreMenuItem,{target:"jvb-meta-fields",icon:(0,o.jsx)(P,{}),children:"Additional Fields"}),(0,o.jsx)(a.PluginSidebar,{name:"jvb-meta-fields",icon:(0,o.jsx)(P,{}),title:"Additional Fields",children:Object.values(s).map((e,l)=>(0,o.jsx)(R,{name:e.title,fields:z({section:e,fields:n}),meta:r,setMeta:d,isOpen:B(l)},e.id))})]}):null});(0,l.registerPlugin)("jvb-meta-fields",{render:D})})();
build/event/block.json
New file
@@ -0,0 +1,29 @@
{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "jvb/event",
  "title": "Event Summary",
  "category": "jvb",
  "icon": "align-center",
  "description": "Outputs the event information",
  "keywords": [
    "event"
  ],
  "version": "0.9.0",
  "textdomain": "jvb",
  "supports": {
    "html": false,
    "align": [
      "wide",
      "full"
    ]
  },
  "selectors": {
    "root": ".event-block"
  },
  "render": "file:./render.php",
  "editorScript": "file:./index.js",
  "editorStyle": "file:./index.css",
  "style": "file:./style-index.css",
  "viewScript": "file:./view.js"
}
build/event/index-rtl.css
New file
@@ -0,0 +1 @@
.jvb-summary-preview{background-color:#f8f9fa;border:1px solid #e2e4e7;border-radius:4px;padding:20px}.jvb-summary-preview h3{border-bottom:1px solid #ff0080;margin-top:0;padding-bottom:10px}.jvb-summary-preview-note{color:#555d66;font-style:italic;margin-bottom:0}
build/event/index.asset.php
New file
@@ -0,0 +1 @@
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n'), 'version' => 'cb644be845ba8e59afd4');
build/event/index.css
New file
@@ -0,0 +1 @@
.jvb-summary-preview{background-color:#f8f9fa;border:1px solid #e2e4e7;border-radius:4px;padding:20px}.jvb-summary-preview h3{border-bottom:1px solid #ff0080;margin-top:0;padding-bottom:10px}.jvb-summary-preview-note{color:#555d66;font-style:italic;margin-bottom:0}
build/event/index.js
New file
@@ -0,0 +1 @@
(()=>{"use strict";var e={391(){const e=window.wp.blocks,t=window.wp.i18n,n=window.wp.blockEditor,o=(window.wp.components,window.ReactJSXRuntime);(0,e.registerBlockType)("jvb/event",{edit:function({attributes:e,setAttributes:r}){const i=(0,n.useBlockProps)();return(0,o.jsx)("div",{...i,children:(0,o.jsxs)("div",{className:"jvb-summary-preview",children:[(0,o.jsx)("h3",{children:(0,t.__)("Summary","jvb")}),(0,o.jsx)("p",{className:"jvb-list-preview-note",children:(0,t.__)("This will inherit the current query to build the information from our custom meta on the front end.","jvb")})]})})},save:function(){return null}})}};const t={};function n(o){const r=t[o];if(void 0!==r)return r.exports;const i=t[o]={exports:{}};return e[o](i,i.exports,n),i.exports}n.m=e,(()=>{const e=[];n.O=(t,o,r,i)=>{if(o){i||=0;for(var s=e.length;s>0&&e[s-1][2]>i;s--)e[s]=e[s-1];return void(e[s]=[o,r,i])}let c=1/0;for(s=0;s<e.length;s++){let[o,r,i]=e[s],u=!0;for(var l=0;l<o.length;l++)1&i&&!(c>=i)||!Object.keys(n.O).every(e=>n.O[e](o[l]))?(u=!1,i<c&&(c=i)):o.splice(l--,1);if(u){e.splice(s--,1);const n=r();void 0!==n&&(t=n)}}return t}})(),n.o=(e,t)=>Object.hasOwn(e,t),(()=>{const e={188:0,44:0};n.O.j=t=>0===e[t];const t=(t,o)=>{let[r,i,s]=o;var c,l,u=0;if(r.some(t=>0!==e[t])){for(c in i)n.o(i,c)&&(n.m[c]=i[c]);if(s)var d=s(n)}for(t&&t(o);u<r.length;u++)l=r[u],n.o(e,l)&&e[l]&&e[l][0](),e[l]=0;return n.O(d)},o=globalThis.webpackChunkjvb||=[];o.forEach(t.bind(null,0)),o.push=t.bind(null,o.push.bind(o))})();let o=n.O(void 0,[44],()=>n(391));o=n.O(o)})();
build/event/render.php
New file
@@ -0,0 +1,5 @@
<?php
if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly
}
build/event/style-index-rtl.css
New file
@@ -0,0 +1 @@
.event-block .tags{--gap:1rem}.event-block .tags .tag{background-color:rgb(var(--action-0));border-radius:4px;color:rgb(var(--action-contrast));display:flex;font-size:var(--txt-x-small);gap:.5rem;padding:.25rem .5rem 0;text-transform:uppercase}.event-block header{--wrap:nowrap!important;gap:1rem}.event-block header h1{margin:0}.event-block .calendar.col{border:2px solid rgb(var(--action-0));border-radius:.5rem;width:var(--btn_);--align:stretch;--gap:0}.event-block .calendar.col span{line-height:.8;text-align:center;text-transform:uppercase}.event-block .calendar.col .weekday{background-color:rgb(var(--action-0));color:rgb(var(--action-contrast));font-family:var(--heading);font-weight:var(--fw-h-bold);line-height:1.4;margin-bottom:.5rem}.event-block .calendar.col .day{font-size:var(--txt-xx-large)}.event-block .gallery figure{aspect-ratio:1;max-width:min(15vw,8rem)!important;object-fit:cover}.event-block figcaption{display:none}
build/event/style-index.css
New file
@@ -0,0 +1 @@
.event-block .tags{--gap:1rem}.event-block .tags .tag{background-color:rgb(var(--action-0));border-radius:4px;color:rgb(var(--action-contrast));display:flex;font-size:var(--txt-x-small);gap:.5rem;padding:.25rem .5rem 0;text-transform:uppercase}.event-block header{--wrap:nowrap!important;gap:1rem}.event-block header h1{margin:0}.event-block .calendar.col{border:2px solid rgb(var(--action-0));border-radius:.5rem;width:var(--btn_);--align:stretch;--gap:0}.event-block .calendar.col span{line-height:.8;text-align:center;text-transform:uppercase}.event-block .calendar.col .weekday{background-color:rgb(var(--action-0));color:rgb(var(--action-contrast));font-family:var(--heading);font-weight:var(--fw-h-bold);line-height:1.4;margin-bottom:.5rem}.event-block .calendar.col .day{font-size:var(--txt-xx-large)}.event-block .gallery figure{aspect-ratio:1;max-width:min(15vw,8rem)!important;object-fit:cover}.event-block figcaption{display:none}
build/event/view.asset.php
New file
@@ -0,0 +1 @@
<?php return array('dependencies' => array(), 'version' => '31d6cfe0d16ae931b73c');
build/event/view.js
build/meta/index.asset.php
@@ -1 +1 @@
<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-media-utils', 'wp-url'), 'version' => '4fc77565e544173d57f5');
<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-element', 'wp-media-utils', 'wp-url'), 'version' => 'bd603a74c761d2467da8');
build/meta/index.js
@@ -1 +1 @@
(()=>{"use strict";const e={n:l=>{const t=l&&l.__esModule?()=>l.default:()=>l;return e.d(t,{a:t}),t},d:(l,t)=>{for(var a in t)e.o(t,a)&&!e.o(l,a)&&Object.defineProperty(l,a,{enumerable:!0,get:t[a]})},o:(e,l)=>Object.hasOwn(e,l)},l=window.wp.blocks,t=window.wp.blockEditor,a=window.wp.components,n=window.wp.coreData,i=window.wp.data,s=window.ReactJSXRuntime,o={text:"text",email:"email",tel:"tel",url:"url",number:"number"},r=({field:e,value:l,onChange:t})=>"textarea"===e.type?(0,s.jsx)(a.TextareaControl,{label:e.label,help:e.description,value:l??"",onChange:t,id:e.name}):(0,s.jsx)(a.TextControl,{label:e.label,help:e.description,type:o[e.type]||"text",value:l??"",onChange:t,required:e.required,id:e.name}),d=({field:e,value:l,onChange:t})=>{const n=Object.entries(e.options||{}).map(([e,l])=>({label:l,value:e}));return"radio"===e.type?(0,s.jsx)(a.RadioControl,{label:e.label,help:e.description,selected:l,options:n,onChange:t,id:e.name}):(0,s.jsx)(a.SelectControl,{label:e.label,help:e.description,value:l??"",options:[{label:"— Select â€”",value:""},...n],onChange:t,id:e.name})},c=({field:e,value:l,onChange:t})=>{const n=Array.isArray(l)?l:[];return(0,s.jsxs)("fieldset",{id:e.name,children:[(0,s.jsx)("legend",{className:"jvb-field-label",children:e.label}),Object.entries(e.options||{}).map(([e,l])=>(0,s.jsx)(a.CheckboxControl,{label:l,checked:n.includes(e),onChange:l=>((e,l)=>{t(l?[...n,e]:n.filter(l=>l!==e))})(e,l)},e))]})},p=window.React,u=e=>{if(!e)return null;const[l,t,a]=e.split("-").map(Number);return new Date(l,t-1,a)},m=e=>{if(e.description&&0!==e.description.length)return(0,s.jsx)("p",{className:"hint",children:e.description})},h=e=>{if(e.description&&0!==e.description.length)return(0,s.jsx)("p",{className:"hint",children:e.description})},b=window.wp.element,v=(e,l,t)=>e?.includes("{{")?e.replace(/{{(.*?)}}/g,(e,t)=>{const a=l[t];return void 0===a?"":Array.isArray(a)?a.join(", "):String(a)}):e,j=window.wp.mediaUtils,x=window.wp.apiFetch;var f=e.n(x);const g={image:"image",video:"video",document:"application",all:""},y=({id:e,onRemove:l})=>{const[t,n]=(0,b.useState)(null);(0,b.useEffect)(()=>{let l=!1;if(e)return f()({path:`/wp/v2/media/${e}`}).then(e=>!l&&n(e)).catch(()=>{}),()=>{l=!0}},[e]);const i=t?.media_details?.sizes?.thumbnail?.source_url||t?.source_url,o="image"===t?.media_type;return(0,s.jsxs)("div",{className:"jvb-upload-thumb",children:[o&&i?(0,s.jsx)("img",{src:i,alt:t?.alt_text||""}):(0,s.jsx)("div",{className:"jvb-upload-thumb-placeholder",children:t?.title?.rendered||`#${e}`}),(0,s.jsx)(a.Button,{variant:"link",isDestructive:!0,onClick:()=>l(e),children:"Remove"})]})},C=window.wp.url,w=e=>e.subtype||e.type,S=(e,l,t)=>"post"===l?{title:t,status:"publish",postType:e.post_type}:{name:t},_=(e,l)=>"user"===l?e.name:e.title?.rendered??e.title??e.name,k=window.wp.compose,N={text:r,email:r,tel:r,url:r,number:r,textarea:r,select:d,radio:d,checkbox:c,set:c,true_false:({field:e,value:l,onChange:t})=>(0,s.jsx)(a.ToggleControl,{label:e.label,help:e.description,checked:!!l,onChange:t,id:e.name}),date:({field:e,value:l,onChange:t})=>(0,s.jsxs)("div",{className:"components-base-control",id:e.name,children:[(0,s.jsx)("label",{className:"components-base-control__label",children:e.label}),(0,s.jsx)(a.DatePicker,{currentDate:u(l),onChange:t,help:e.description}),m(e)]}),time:({field:e,value:l,onChange:t})=>(0,s.jsx)(a.BaseControl,{label:e.label,help:e.description,id:e.name,children:(0,s.jsx)("input",{type:"time",id:e.name,value:l??"",onChange:e=>t(e.target.value)})}),datetime:({field:e,value:l,onChange:t})=>{const[n,i]=(0,p.useState)(new Date);return(0,s.jsxs)("div",{className:"components-base-control",id:e.name,children:[(0,s.jsx)("label",{className:"components-base-control__label",children:e.label}),(0,s.jsx)(a.DateTimePicker,{currentDate:n,onChange:t,label:e.label,help:e.description,value:l??"",is12Hour:!0}),h(e)]})},repeater:({field:e,value:l,onChange:t,meta:n})=>{const i=Array.isArray(l)?l:[],o=e.fields||{},[r,d]=(0,b.useState)(null);return(0,s.jsxs)("div",{className:"jvb-repeater-field",id:e.name,children:[(0,s.jsx)("p",{className:"jvb-field-label",children:e.label}),(0,s.jsx)(a.Panel,{children:i.map((l,c)=>(0,s.jsxs)(a.PanelBody,{title:v(e.row_label,l)||`Row ${c+1}`,initialOpen:r===c,onToggle:()=>d(r===c?null:c),children:[Object.entries(o).map(([e,a])=>(0,s.jsx)(O,{field:{...a,name:e},value:l[e],onChange:l=>((e,l,a)=>{const n=i.map((t,n)=>n===e?{...t,[l]:a}:t);t(n)})(c,e,l),meta:n},e)),(0,s.jsx)(a.Button,{variant:"link",isDestructive:!0,onClick:()=>(e=>t(i.filter((l,t)=>t!==e)))(c),children:"Remove"})]},c))}),(0,s.jsx)(a.Button,{variant:"secondary",onClick:()=>{return t([...i,(e=o,Object.fromEntries(Object.entries(e||{}).map(([e,l])=>[e,l.default??""])))]);var e},children:e.add_label||"Add Row"})]})},upload:({field:e,value:l,onChange:n})=>{const i=e.multiple||"gallery"===e.type,o=i?Array.isArray(l)?l:[]:l,r=g[e.subtype]?[g[e.subtype]]:"",d=e=>{n(i?o.filter(l=>l!==e):0)};return(0,s.jsxs)("div",{className:"jvb-upload-field",id:e.name,children:[(0,s.jsx)("p",{className:"jvb-field-label",children:e.label}),(0,s.jsx)("div",{className:i?"jvb-upload-grid":"jvb-upload-single",children:i?o.map(e=>(0,s.jsx)(y,{id:e,onRemove:d},e)):!!o&&(0,s.jsx)(y,{id:o,onRemove:d})}),(0,s.jsx)(t.MediaUploadCheck,{children:(0,s.jsx)(j.MediaUpload,{onSelect:e=>n(i?e.map(e=>e.id):e.id),allowedTypes:r,multiple:i,value:i?o:o||void 0,render:({open:l})=>(0,s.jsxs)(a.Button,{variant:"secondary",onClick:l,children:[(i?o.length:o)?"Change":"Select"," ",e.label]})})})]})},selector:({field:e,value:l,onChange:t})=>{const n=w(e),i="taxonomy"===n,o=(e=>{const l=w(e);return"user"===l?e=>(0,C.addQueryArgs)("/wp/v2/users",{search:e,per_page:20}):"taxonomy"===l?l=>(0,C.addQueryArgs)(`/wp/v2/${e.taxonomy}`,{search:l,per_page:20,hide_empty:!1}):l=>(0,C.addQueryArgs)("/wp/v2/search",{search:l,type:"post",subtype:e.post_type,per_page:20})})(e),r=Array.isArray(l)?l:l?l.split(","):[],[d,c]=(0,b.useState)([]),[p,u]=(0,b.useState)({}),[m,h]=(0,b.useState)({}),[v,j]=(0,b.useState)(""),[x,g]=(0,b.useState)(!1),y=v?`Not found. Create "${v}"?`:null;(0,b.useEffect)(()=>{k("");let e=!1;if(r.length)return Promise.all(r.map(e=>f()({path:o("")+`&include=${e}`}))).then(l=>{if(e)return;const t={},a=[];l.flat().forEach(e=>{const l=_(e,n);t[l]=e.id,a.push(l)}),u(e=>({...e,...t})),c(a)}).catch(()=>{}),()=>{e=!0};c([])},[JSON.stringify(r)]);const k=(0,b.useCallback)(e=>{j(e),f()({path:o(e)}).then(e=>{const l={};e.forEach(e=>{l[_(e,n)]=e.id}),h(l)}).catch(()=>{})},[o,n]),N=l=>{const a=1===e.max;t(a?l[l.length-1]??0:(e.max?l.slice(0,e.max):l).join(","))},A=v&&!Object.keys(m).some(e=>e.toLowerCase()===v.toLowerCase()),O=1===e.max&&d.length?[]:[...Object.keys(m),...i&&A?[y]:[]];return(0,s.jsx)(a.FormTokenField,{label:e.label,help:e.description,value:d,suggestions:O,onChange:l=>{if(l.find(e=>e===y)&&i&&!x)return g(!0),void f()({path:`/wp/v2/${e.taxonomy}`,method:"POST",data:S(n,v)}).then(e=>{const l=_(e,n),t=d.filter(e=>e!==y).concat(l),a=t.map(t=>p[t]??m[t]??(t===l?e.id:void 0)).filter(e=>void 0!==e);u(t=>({...t,[l]:e.id})),c(t),N(a)}).catch(()=>{}).finally(()=>g(!1));const t=l.filter(e=>void 0!==p[e]||void 0!==m[e]),a=t.map(e=>p[e]??m[e]);c(t),u(e=>({...e,...m})),N(a)},onInputChange:k,maxLength:e.max||void 0,id:e.name,__experimentalExpandOnFocus:!0})},location:({field:e,value:l,onChange:t})=>{const n=l||{},[i,o]=(0,b.useState)(n.address||""),[r,d]=(0,b.useState)([]),[c,p]=(0,b.useState)(!1),u=(0,k.useDebounce)(e=>{if(!e)return d([]);p(!0),f()({path:`jvb/v1/geocode?q=${encodeURIComponent(e)}`}).then(d).finally(()=>p(!1))},400);return(0,s.jsxs)("div",{className:"jvb-location-field",id:e.name,children:[(0,s.jsx)(a.TextControl,{label:e.label,value:i,onChange:e=>{o(e),u(e)}}),c&&(0,s.jsx)(a.Spinner,{}),!!r.length&&(0,s.jsxs)("div",{className:"jvb-location-results",children:[r.map(e=>(0,s.jsx)(a.Button,{variant:"tertiary",onClick:()=>(e=>{const l=e.address||{},a={address:[l.house_number,l.road].filter(Boolean).join(" "),city:l.city||l.town||l.village||"",province:l.state||"",postal_code:l.postcode||"",country:l.country||"",lat:parseFloat(e.lat),lng:parseFloat(e.lng)};t(a),o(a.address),d([])})(e),style:{display:"block",textAlign:"left"},children:e.display_name},e.place_id)),!!n.lat&&(0,s.jsxs)("p",{className:"jvb-location-summary",children:[n.address,", ",n.city,", ",n.province," ",n.postal_code,", ",n.country,(0,s.jsx)("br",{}),(0,s.jsx)(a.Button,{variant:"link",isDestructive:!0,onClick:()=>{t({}),o(""),d([])},children:"Clear"})]})]})]})},group:({field:e,value:l,onChange:t})=>{const a=l||{};return(0,s.jsxs)("div",{className:"jvb-group-field",id:e.name,children:[e.label&&(0,s.jsx)("h4",{className:"components-base-control__label",children:e.label}),Object.entries(e.fields||{}).map(([e,l])=>(0,s.jsx)(O,{field:{...l,name:e},value:a[e],onChange:l=>((e,l)=>{t({...a,[e]:l})})(e,l),meta:a},e)),e.description&&(0,s.jsx)("p",{className:"hint",children:e.description})]})}},A={"=":(e,l)=>e==l,"==":(e,l)=>e==l,"!=":(e,l)=>e!=l,">":(e,l)=>e>l,"<":(e,l)=>e<l,in:(e,l)=>Array.isArray(l)?l.includes(e):String(l).split(",").includes(e)},O=({id:e,field:l,value:t,onChange:n,meta:i})=>{if(!((e,l)=>!e?.field||(A[e.operator]||A["="])(l?.[e.field],e.value))(l.condition,i))return null;const o=N[l.type];return o?(0,s.jsx)(a.PanelRow,{children:(0,s.jsx)(o,{field:l,value:t,onChange:n})}):null},P=JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":3,"name":"jvb/meta","version":"0.1.0","title":"Custom Field","category":"jvb","icon":"edit-large","description":"Add a specific field from this content","example":{},"attributes":{"fieldName":{"type":"string","default":""}},"supports":{"align":["wide","full"]},"textdomain":"jvb","selectors":{"root":".jvb-meta"},"editorScript":"file:./index.js","editorStyle":"file:./index.css","style":"file:./style-index.css","render":"file:./render.php","viewScript":"file:./view.js"}');(0,l.registerBlockType)(P,{edit:({attributes:e,setAttributes:l})=>{const{fieldName:o}=e,{fields:r}=window.jvbFieldConfig||{},d=(0,i.useSelect)(e=>e("core/editor").getCurrentPostType(),[]),[c,p]=(0,n.useEntityProp)("postType",d,"meta"),u=(r||[]).find(e=>e.name===o),m=(0,t.useBlockProps)();return(0,s.jsxs)("div",{...m,children:[(0,s.jsx)(t.InspectorControls,{children:(0,s.jsx)(a.PanelBody,{title:"Field",children:(0,s.jsx)(a.SelectControl,{label:"Meta field",value:o,options:[{label:"Select a field…",value:""},...(r||[]).map(e=>({label:e.label||e.name,value:e.name}))],onChange:e=>l({fieldName:e})})})}),!u&&(0,s.jsx)(a.Placeholder,{label:"Meta Field",instructions:"Select a field in the block settings."}),u&&(0,s.jsx)(O,{field:u,value:c?.[o],onChange:e=>p({...c,[o]:e}),meta:c})]})},save:()=>null})})();
(()=>{"use strict";const e={n:l=>{const t=l&&l.__esModule?()=>l.default:()=>l;return e.d(t,{a:t}),t},d:(l,t)=>{for(var a in t)e.o(t,a)&&!e.o(l,a)&&Object.defineProperty(l,a,{enumerable:!0,get:t[a]})},o:(e,l)=>Object.hasOwn(e,l)},l=window.wp.blocks,t=window.wp.blockEditor,a=window.wp.components,n=window.wp.coreData,i=window.wp.data,s=window.ReactJSXRuntime,o={text:"text",email:"email",tel:"tel",url:"url",number:"number"},r=({field:e,value:l,onChange:t})=>"textarea"===e.type?(0,s.jsx)(a.TextareaControl,{label:e.label,help:e.description,value:l??"",onChange:t,id:e.name}):(0,s.jsx)(a.TextControl,{label:e.label,help:e.description,type:o[e.type]||"text",value:l??"",onChange:t,required:e.required,id:e.name}),d=({field:e,value:l,onChange:t})=>{const n=Object.entries(e.options||{}).map(([e,l])=>({label:l,value:e}));return"radio"===e.type?(0,s.jsx)(a.RadioControl,{label:e.label,help:e.description,selected:l,options:n,onChange:t,id:e.name}):(0,s.jsx)(a.SelectControl,{label:e.label,help:e.description,value:l??"",options:[{label:"— Select â€”",value:""},...n],onChange:t,id:e.name})},c=({field:e,value:l,onChange:t})=>{const n=Array.isArray(l)?l:[];return(0,s.jsxs)("fieldset",{id:e.name,children:[(0,s.jsx)("legend",{className:"jvb-field-label",children:e.label}),Object.entries(e.options||{}).map(([e,l])=>(0,s.jsx)(a.CheckboxControl,{label:l,checked:n.includes(e),onChange:l=>((e,l)=>{t(l?[...n,e]:n.filter(l=>l!==e))})(e,l)},e))]})},p=e=>{if(!e)return null;const[l,t,a]=e.split("-").map(Number);return l&&t&&a?new Date(l,t-1,a):null},u=e=>{if(e.description&&0!==e.description.length)return(0,s.jsx)("p",{className:"hint",children:e.description})},m=(window.React,e=>{if(e.description&&0!==e.description.length)return(0,s.jsx)("p",{className:"hint",children:e.description})}),h=window.wp.element,b=(e,l,t)=>e?.includes("{{")?e.replace(/{{(.*?)}}/g,(e,t)=>{const a=l[t];return void 0===a?"":Array.isArray(a)?a.join(", "):String(a)}):e,v=window.wp.mediaUtils,j=window.wp.apiFetch;var x=e.n(j);const f={image:"image",video:"video",document:"application",all:""},g=({id:e,onRemove:l})=>{const[t,n]=(0,h.useState)(null);(0,h.useEffect)(()=>{let l=!1;if(e)return x()({path:`/wp/v2/media/${e}`}).then(e=>!l&&n(e)).catch(()=>{}),()=>{l=!0}},[e]);const i=t?.media_details?.sizes?.thumbnail?.source_url||t?.source_url,o="image"===t?.media_type;return(0,s.jsxs)("div",{className:"jvb-upload-thumb",children:[o&&i?(0,s.jsx)("img",{src:i,alt:t?.alt_text||""}):(0,s.jsx)("div",{className:"jvb-upload-thumb-placeholder",children:t?.title?.rendered||`#${e}`}),(0,s.jsx)(a.Button,{variant:"link",isDestructive:!0,onClick:()=>l(e),children:"Remove"})]})},y=window.wp.url,C=e=>e.subtype||e.type,w=(e,l,t)=>"post"===l?{title:t,status:"publish",postType:e.post_type}:{name:t},_=(e,l)=>"user"===l?e.name:e.title?.rendered??e.title??e.name,k=window.wp.compose,N={text:r,email:r,tel:r,url:r,number:r,textarea:r,select:d,radio:d,checkbox:c,set:c,true_false:({field:e,value:l,onChange:t})=>(0,s.jsx)(a.ToggleControl,{label:e.label,help:e.description,checked:!!l,onChange:t,id:e.name}),date:({field:e,value:l,onChange:t})=>(0,s.jsxs)("div",{className:"components-base-control",id:e.name,children:[(0,s.jsx)("label",{className:"components-base-control__label",children:e.label}),(0,s.jsx)(a.DatePicker,{currentDate:p(l),onChange:t,help:e.description}),u(e)]}),time:({field:e,value:l,onChange:t})=>(0,s.jsx)(a.BaseControl,{label:e.label,help:e.description,id:e.name,children:(0,s.jsx)("input",{type:"time",id:e.name,value:l??"",onChange:e=>t(e.target.value)})}),datetime:({field:e,value:l,onChange:t})=>(0,s.jsxs)("div",{className:"components-base-control",id:e.name,children:[(0,s.jsx)("label",{className:"components-base-control__label",children:e.label}),(0,s.jsx)(a.DateTimePicker,{currentDate:l||null,onChange:t,help:e.description,value:l??"",is12Hour:!0}),m(e)]}),repeater:({field:e,value:l,onChange:t,meta:n})=>{const i=Array.isArray(l)?l:[],o=e.fields||{},[r,d]=(0,h.useState)(null);return(0,s.jsxs)("div",{className:"jvb-repeater-field",id:e.name,children:[(0,s.jsx)("p",{className:"jvb-field-label",children:e.label}),(0,s.jsx)(a.Panel,{children:i.map((l,c)=>(0,s.jsxs)(a.PanelBody,{title:b(e.row_label,l)||`Row ${c+1}`,initialOpen:r===c,onToggle:()=>d(r===c?null:c),children:[Object.entries(o).map(([e,a])=>(0,s.jsx)(A,{field:{...a,name:e},value:l[e],onChange:l=>((e,l,a)=>{const n=i.map((t,n)=>n===e?{...t,[l]:a}:t);t(n)})(c,e,l),meta:n},e)),(0,s.jsx)(a.Button,{variant:"link",isDestructive:!0,onClick:()=>(e=>t(i.filter((l,t)=>t!==e)))(c),children:"Remove"})]},c))}),(0,s.jsx)(a.Button,{variant:"secondary",onClick:()=>{return t([...i,(e=o,Object.fromEntries(Object.entries(e||{}).map(([e,l])=>[e,l.default??""])))]);var e},children:e.add_label||"Add Row"})]})},upload:({field:e,value:l,onChange:n})=>{const i=e.multiple||"gallery"===e.type,o=i?"string"==typeof l&&l?l.split(",").map(Number):[]:l,r=f[e.subtype]?[f[e.subtype]]:"",d=e=>{n(i?o.filter(l=>l!==e).join(","):0)};return(0,s.jsxs)("div",{className:"jvb-upload-field",id:e.name,children:[(0,s.jsx)("p",{className:"jvb-field-label",children:e.label}),(0,s.jsx)("div",{className:i?"jvb-upload-grid":"jvb-upload-single",children:i?o.map(e=>(0,s.jsx)(g,{id:e,onRemove:d},e)):!!o&&(0,s.jsx)(g,{id:o,onRemove:d})}),(0,s.jsx)(t.MediaUploadCheck,{children:(0,s.jsx)(v.MediaUpload,{onSelect:e=>n(i?e.map(e=>e.id).join(","):e.id),allowedTypes:r,multiple:i,value:i?o:o||void 0,render:({open:l})=>(0,s.jsxs)(a.Button,{variant:"secondary",onClick:l,children:[(i?o.length:o)?"Change":"Select"," ",e.label]})})})]})},selector:({field:e,value:l,onChange:t})=>{const n=C(e),i="taxonomy"===n,o=(e=>{const l=C(e);return"user"===l?e=>(0,y.addQueryArgs)("/wp/v2/users",{search:e,per_page:20}):"taxonomy"===l?l=>(0,y.addQueryArgs)(`/wp/v2/${e.taxonomy}`,{search:l,per_page:20,hide_empty:!1}):l=>(0,y.addQueryArgs)("/wp/v2/search",{search:l,type:"post",subtype:e.post_type,per_page:20})})(e),r=Array.isArray(l)?l:l?l.split(","):[],[d,c]=(0,h.useState)([]),[p,u]=(0,h.useState)({}),[m,b]=(0,h.useState)({}),[v,j]=(0,h.useState)(""),[f,g]=(0,h.useState)(!1),k=v?`Not found. Create "${v}"?`:null;(0,h.useEffect)(()=>{N("");let e=!1;if(r.length)return Promise.all(r.map(e=>x()({path:o("")+`&include=${e}`}))).then(l=>{if(e)return;const t={},a=[];l.flat().forEach(e=>{const l=_(e,n);t[l]=e.id,a.push(l)}),u(e=>({...e,...t})),c(a)}).catch(()=>{}),()=>{e=!0};c([])},[JSON.stringify(r)]);const N=(0,h.useCallback)(e=>{j(e),x()({path:o(e)}).then(e=>{const l={};e.forEach(e=>{l[_(e,n)]=e.id}),b(l)}).catch(()=>{})},[o,n]),S=l=>{const a=1===e.max;t(a?l[l.length-1]??0:(e.max?l.slice(0,e.max):l).join(","))},A=v&&!Object.keys(m).some(e=>e.toLowerCase()===v.toLowerCase()),O=1===e.max&&d.length?[]:[...Object.keys(m),...i&&A?[k]:[]];return(0,s.jsx)(a.FormTokenField,{label:e.label,help:e.description,value:d,suggestions:O,onChange:l=>{if(l.find(e=>e===k)&&i&&!f)return g(!0),void x()({path:`/wp/v2/${e.taxonomy}`,method:"POST",data:w(e,n,v)}).then(e=>{const l=_(e,n),t=d.filter(e=>e!==k).concat(l),a=t.map(t=>p[t]??m[t]??(t===l?e.id:void 0)).filter(e=>void 0!==e);u(t=>({...t,[l]:e.id})),c(t),S(a)}).catch(()=>{}).finally(()=>g(!1));const t=l.filter(e=>void 0!==p[e]||void 0!==m[e]),a=t.map(e=>p[e]??m[e]);c(t),u(e=>({...e,...m})),S(a)},onInputChange:N,maxLength:e.max||void 0,id:e.name,__experimentalExpandOnFocus:!0})},location:({field:e,value:l,onChange:t})=>{const n=l||{},[i,o]=(0,h.useState)(n.address||""),[r,d]=(0,h.useState)([]),[c,p]=(0,h.useState)(!1),u=(0,k.useDebounce)(e=>{if(!e)return d([]);p(!0),x()({path:`jvb/v1/geocode?q=${encodeURIComponent(e)}`}).then(d).finally(()=>p(!1))},400);return(0,s.jsxs)("div",{className:"jvb-location-field",id:e.name,children:[(0,s.jsx)(a.TextControl,{label:e.label,value:i,onChange:e=>{o(e),u(e)}}),c&&(0,s.jsx)(a.Spinner,{}),!!r.length&&(0,s.jsxs)("div",{className:"jvb-location-results",children:[r.map(e=>(0,s.jsx)(a.Button,{variant:"tertiary",onClick:()=>(e=>{const l=e.address||{},a={address:[l.house_number,l.road].filter(Boolean).join(" "),city:l.city||l.town||l.village||"",province:l.state||"",postal_code:l.postcode||"",country:l.country||"",lat:parseFloat(e.lat),lng:parseFloat(e.lng)};t(a),o(a.address),d([])})(e),style:{display:"block",textAlign:"left"},children:e.display_name},e.place_id)),!!n.lat&&(0,s.jsxs)("p",{className:"jvb-location-summary",children:[n.address,", ",n.city,", ",n.province," ",n.postal_code,", ",n.country,(0,s.jsx)("br",{}),(0,s.jsx)(a.Button,{variant:"link",isDestructive:!0,onClick:()=>{t({}),o(""),d([])},children:"Clear"})]})]})]})},group:({field:e,value:l,onChange:t})=>{const a=l||{};return(0,s.jsxs)("div",{className:"jvb-group-field",id:e.name,children:[e.label&&(0,s.jsx)("h4",{className:"components-base-control__label",children:e.label}),Object.entries(e.fields||{}).map(([e,l])=>(0,s.jsx)(A,{field:{...l,name:e},value:a[e],onChange:l=>((e,l)=>{t({...a,[e]:l})})(e,l),meta:a},e)),e.description&&(0,s.jsx)("p",{className:"hint",children:e.description})]})}},S={"=":(e,l)=>e==l,"==":(e,l)=>e==l,"!=":(e,l)=>e!=l,">":(e,l)=>e>l,"<":(e,l)=>e<l,in:(e,l)=>Array.isArray(l)?l.includes(e):String(l).split(",").includes(e)},A=({id:e,field:l,value:t,onChange:n,meta:i})=>{if(!((e,l)=>!e?.field||(S[e.operator]||S["="])(l?.[e.field],e.value))(l.condition,i))return null;const o=N[l.type];return o?(0,s.jsx)(a.PanelRow,{children:(0,s.jsx)(o,{field:l,value:t,onChange:n})}):null},O=JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":3,"name":"jvb/meta","version":"0.1.0","title":"Custom Field","category":"jvb","icon":"edit-large","description":"Add a specific field from this content","example":{},"attributes":{"fieldName":{"type":"string","default":""}},"supports":{"align":["wide","full"]},"textdomain":"jvb","selectors":{"root":".jvb-meta"},"editorScript":"file:./index.js","editorStyle":"file:./index.css","style":"file:./style-index.css","render":"file:./render.php","viewScript":"file:./view.js"}');(0,l.registerBlockType)(O,{edit:({attributes:e,setAttributes:l})=>{const{fieldName:o}=e,{fields:r}=window.jvbFieldConfig||{},d=(0,i.useSelect)(e=>e("core/editor").getCurrentPostType(),[]),[c,p]=(0,n.useEntityProp)("postType",d,"meta"),u=(r||[]).find(e=>e.name===o),m=(0,t.useBlockProps)();return(0,s.jsxs)("div",{...m,children:[(0,s.jsx)(t.InspectorControls,{children:(0,s.jsx)(a.PanelBody,{title:"Field",children:(0,s.jsx)(a.SelectControl,{label:"Meta field",value:o,options:[{label:"Select a field…",value:""},...(r||[]).map(e=>({label:e.label||e.name,value:e.name}))],onChange:e=>l({fieldName:e})})})}),!u&&(0,s.jsx)(a.Placeholder,{label:"Meta Field",instructions:"Select a field in the block settings."}),u&&(0,s.jsx)(A,{field:u,value:c?.[o],onChange:e=>p({...c,[o]:e}),meta:c})]})},save:()=>null})})();
build/simple-calendar/index.asset.php
@@ -1 +1 @@
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-i18n'), 'version' => 'e8eefb198c6c47107fc4');
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-i18n'), 'version' => 'c9d53040b1ae8b423795');
build/simple-calendar/style-index-rtl.css
@@ -1 +1 @@
p.empty{background-color:rgb(var(--base));border:2px dashed rgba(var(--base-200));border-radius:var(--radius);font-style:italic;text-align:center}details{margin:2rem 0}details h2{margin:0}
p.empty{background-color:rgb(var(--base));border:2px dashed rgba(var(--base-200));border-radius:var(--radius);font-style:italic;text-align:center}details{margin:2rem 0}details h2{margin:0}nav.calendar.types.types{height:max-content}
build/simple-calendar/style-index.css
@@ -1 +1 @@
p.empty{background-color:rgb(var(--base));border:2px dashed rgba(var(--base-200));border-radius:var(--radius);font-style:italic;text-align:center}details{margin:2rem 0}details h2{margin:0}
p.empty{background-color:rgb(var(--base));border:2px dashed rgba(var(--base-200));border-radius:var(--radius);font-style:italic;text-align:center}details{margin:2rem 0}details h2{margin:0}nav.calendar.types.types{height:max-content}
inc/blocks/EventBlock.php
New file
@@ -0,0 +1,300 @@
<?php
namespace JVBase\blocks;
use DateTime;
use JVBase\meta\Meta;
use JVBase\utility\Image;
use WP_Block;
if (!defined('ABSPATH')) {
    exit;
}
class EventBlock {
    public function __construct()
    {
        add_action('init', [$this, 'registerBlock']);
    }
    public function registerBlock():void
    {
        register_block_type(
            JVB_DIR . '/build/event',
            [
                'render_callback' => [$this, 'render']
            ]
        );
    }
    public function render(array $attributes, string $content, WP_Block $block):string
    {
        if (!is_singular(BASE.'event')) {
            return '';
        }
        $meta = Meta::forPost(get_the_ID());
        $values = $meta->getAll();
        $out = '<section class="event-block">';
        $out .= '<div class="event tags row right">';
            $get = ['is_free' => 'Free', 'rsvp_required' => 'Must RSVP', 'public' => 'Private Event'];
            foreach ($get as $k => $g) {
                $check = !empty($values[$k]) && $values[$k] === '1';
                if ($k === 'public') {
                    $check = !$check;
                }
                $icon = match ($k) {
                    'is_free'   => jvbIcon('check-circle'),
                    'rsvp_required'   => jvbIcon('envelope'),
                    'public'   => jvbIcon('lock-key'),
                };
                if ($check) {
                    $out .= sprintf(
                        '<div class="tag">%s%s</div>',
                        $icon,
                        $g
                    );
                }
            }
        $out .= '</div>';
        if (!empty($values['post_thumbnail'])) {
            $out .= jvbFormatImage($values['post_thumbnail']);
        }
        $out .= '<header class="row x-btw">';
            if (!empty($values['post_title'])) {
                $out .= sprintf(
                    '<h1 id="%s">%s</h1>',
                    sanitize_title($values['post_title']),
                    $values['post_title']
                );
            }
            $out .= $this->calendarDay($values['date_start']??'');
        $out .= '</header>';
        $out .= '<div class="meta">';
            $out .= sprintf(
                '<ul class="time term-list row left"><li class="title">%s</li>',
                jvbIcon('clock')
            );
                $out .= $this->formatDay($values['date_start']??'', $values['time_start']??'', $values['time_end']??'');
                foreach ($values['schedule']??[] as $date) {
                    $out .= $this->formatDay($date['date'], $date['time_start'], $date['time_end'], $date['notes']);
                }
            $out .= '</ul>';
                $out .= $this->location($values['location']??[], $values['location_notes']??'');
            $out .= $this->price($values['cost']??'', $values['ticket_url']??'');
            $out .= $this->participants($values['max_participants']??'');
            $get = ['city', 'event_category'];
            foreach ($get as $g) {
                if (!empty($values[$g])) {
                    $out .= jvbMetaTermList($values[$g], $g);
                }
            }
            $out .= $this->rsvp($values['rsvp_required']??'', $values['rsvp_limit']??'', $values['rsvp_deadline']);
        $out .= '</div>';
        $out .= $this->gallery($values['gallery']??'');
        $out .= $this->moreInfo($values['external_url']??'');
        $out .= '</section>';
        return $out;
    }
    public function renderGallery():void
    {
        jvbRenderGallery();
    }
    protected function calendarDay(string $day):string
    {
        $out = '';
        if (!empty($day)) {
            $date = new DateTime($day, wp_timezone());
            $weekday = $date->format('D');
            $num = $date->format('d');
            $month = $date->format('M');
            $out .= sprintf(
                '<div class="col calendar">
                        <span class="weekday">%s</span>
                        <span class="month">%s</span>
                        <span class="day">%d</span>
                    </div>',
                $weekday,
                $month,
                $num
            );
        }
        return $out;
    }
    protected function renderLocationString(array $location):string
    {
        if (!array_key_exists('address', $location) ||
            !array_key_exists('street', $location) ||
            !array_key_exists('city', $location) ||
            !array_key_exists('province', $location) ||
            !array_key_exists('country', $location)) {
            return '';
        }
        return sprintf(
            '<p class="location">%s%s<br>%s, %s %s</p>',
            $location['address'],
            $location['street'],
            $location['city'],
            $location['province'],
            $location['country'] === 'CA' ? '' : $location['country']
        );
    }
    protected function formatDay(string $date, string $start, string $end, string $notes = ''):string
    {
        $out = '<li>';
        if (!empty($date)) {
            $out .= sprintf(
                '<time datetime="%s">%s</time><br>',
                date('c', strtotime($date)),
                date('F j, Y', strtotime($date))
            );
        }
        $doit = false;
        if (!empty($start)) {
            $doit = true;
            $d = strtotime($date.' '.$start);
            $out .= sprintf(
                '<time datetime="%s">%s</time>',
                date('c', $d),
                date('g:ia', $d)
            );
        }
        if (!empty($end)) {
            if ($doit) {
                $out .= ' - ';
            }
            $d = strtotime($date.' '.$end);
            $out .= sprintf(
                '<time datetime="%s">%s</time>',
                date('c', $d),
                date('g:ia', $d)
            );
        }
        if (!empty($notes)) {
            $out .= wpautop($notes);
        }
        $out .= '</li>';
        return $out;
    }
    protected function location(array $location, string $notes = ''):string
    {
        $out = '';
        if (!empty($location['address']??'')) {
            $out .= sprintf(
                '<ul class="location term-list row left">
                    <li class="title">%sLocation</li>
                    <li>%s</li>
                    <li>%s</li>
                    %s
                    </ul>',
                jvbIcon('map-pin'),
                $this->renderLocationString($location),
                jvbLocationLinks($location),
                empty($notes) ? '' : '<li>'.$notes.'</li>',
            );
        }
        return $out;
    }
    protected function price(string $price, string $url):string
    {
        $out = '';
        if (!empty($price) || $price !== '0') {
            $out = jvbCurrency($price);
        }
        if (!empty($url)) {
            $out .= sprintf(
                '<br><a href="%s">%sPurchase Tickets</a>',
                esc_url($url),
                jvbIcon('ticket')
            );
        }
        return empty($out) ? $out : '<p>'.$out.'</p>';
    }
    protected function participants(string $num):string
    {
        $out = '';
        if (!empty($num) || $num !== '0') {
            $out .= sprintf(
                '<p>Maximum %d participants</p>',
                $num
            );
        }
        return $out;
    }
    protected function moreInfo(string $url):string
    {
        $out = '';
        if (!empty($url)) {
            $out .= sprintf(
                '<p>%s<a href="%s" target="_blank">Learn More</a></p>',
                jvbIcon('link'),
                esc_url($url)
            );
        }
        return $out;
    }
    protected function rsvp(string $mustRSVP, string $limit, string $deadline):string
    {
        $out = '';
        if (!empty($mustRSVP) && $mustRSVP === '1') {
            $out = '<p class="rsvp">RSVP Required';
            if (!empty($limit) && $limit !== '0') {
                $out .= sprintf(
                    '<br>Maximum %d Seats',
                    $limit
                );
            }
            if (!empty($deadline)) {
                $out .= sprintf(
                    '<br>RSVP Deadline: <time datetime="%s">%s</time>',
                    date('c', $deadline),
                    date('F j, Y', $deadline)
                );
            }
            $out .= '</p>';
        }
        return $out;
    }
    protected function gallery(string $gallery):string
    {
        $out = '';
        if (!empty($gallery)) {
            add_action('wp_footer', [$this, 'renderGallery']);
            $out = '<div class="gallery row left">';
            $gallery = array_map('absint', explode(',', $gallery));
            foreach ($gallery as $id) {
                $caption = wp_get_attachment_caption($id);
                $out .= sprintf(
                    '<figure>%s<figcaption>%s</figcaption></figure>',
                    jvbFormatImage($id,'tiny','medium',true,'event'),
                    empty($caption) ? '' : $caption
                );
            }
            $out .= '</div>';
        }
        return $out;
    }
}
inc/blocks/FAQBlock.php
@@ -24,7 +24,8 @@
    /**
     * Register the FAQ block
     */
    public function registerBlock() {
    public function registerBlock():void
    {
        // Register the block
        register_block_type(
            JVB_DIR . '/build/faq',
@@ -125,7 +126,7 @@
     * @param WP_Block $block Block instance
     * @return string Rendered block HTML
     */
    public function render($attributes, $content, $block)
    public function render(array $attributes, string $content, WP_Block $block):string
    {
        ob_start();
        ?>
inc/blocks/MenuBlock.php
@@ -47,7 +47,7 @@
        if (wp_is_post_revision($postID) || wp_is_post_autosave($postID)) return;
        $postType = $post->post_type;
        if ($postType !== 'product' && !in_array($postType, Registrar::getFoodMenuTypes())) {
        if ($postType !== 'product' || !in_array($postType, Registrar::getFoodMenuTypes())) {
            return;
        }
        error_log('Flushing food menu block cache');
inc/blocks/SimpleCalendarBlock.php
@@ -1,6 +1,7 @@
<?php
namespace JVBase\blocks;
use DateTime;
use JVBase\managers\Cache;
use JVBase\meta\Meta;
use JVBase\registrar\Registrar;
@@ -31,6 +32,7 @@
    public function __construct()
    {
        $this->cache = Cache::for('calendar', 'post',  DAY_IN_SECONDS);
        $this->cache->flush();
        add_action('init', [ $this, 'registerBlock' ]);
    }
@@ -73,6 +75,14 @@
        } else {
            $this->params = [];
        }
        foreach (['eyear', 'emonth', 'eday'] as $key) {
            $val = get_query_var($key);
            if (!empty($val)) {
                $this->params[$key] = $val;
            }
        }
    }
    public function render(array $attributes, string $content, WP_Block $block)
@@ -95,19 +105,20 @@
    protected function renderBlock():void
    {
        echo '<section class="simple-calendar">';
        $this->renderHeader();
        $this->renderCalendar();
        $this->renderOnThisPage();
        echo '</section>';
    }
    protected function renderHeader():void
    {
        $title = 'Events';
        if(!in_array('all', $this->params)) {
            $title = '<small>'.$title.'</small>';
        }
        $title = $this->determineTitle();
        ?>
        <header id="top">
            <h1><?=$title?></h1>
            <?php $this->buildNav(); ?>
@@ -118,6 +129,50 @@
        </section>
        <?php
    }
        protected function determineTitle():string
        {
            if (is_tax(BASE.'event_category')) {
                $title = sprintf(
                    '%s Events',
                    get_queried_object()->name,
                );
            } else {
                $title = 'Events';
            }
            if(!in_array('all', $this->params)) {
                $title = '<small>'.$title.'</small>';
            }
            if (is_tax(BASE.'city')) {
                $title .= sprintf(
                    ' in %s',
                    get_queried_object()->name,
                );
            }
            if ($this->has('emonth')) {
                $title .= sprintf(
                    ' %s %s',
                    is_tax() ? 'happening on' : 'in',
                    $this->getMonthName((int)$this->has('emonth')),
                );
            }
            if ($this->has('eday')) {
                $title .= sprintf(
                    ' %s,',
                    (int)$this->has('eday')
                );
            }
            if ($this->has('eyear')) {
                $title.= sprintf(
                    ' %s%s',
                    !$this->has('emonth') ? 'in ' : '',
                    $this->has('eyear')
                );
            }
            return $title;
        }
        protected function buildNav():void
        {
            $content = $taxonomies = '';
@@ -159,7 +214,7 @@
                    }
                    if (!empty($out)) {
                        $taxonomies .= sprintf(
                            '<ul class="term-list %s"><li class="label">%s</li>%s</ul>',
                            '<ul class="term-list row start %s"><li class="label">%s</li>%s</ul>',
                            $slug,
                            $title,
                            implode('', $out)
@@ -168,14 +223,109 @@
                }
            }
            if (!empty($content) || !empty($taxonomies)) {
            $dates = $this->getDateNavigation();
            if (!is_post_type_archive($this->content[0]) || $this->isDatedArchive()) {
                echo sprintf(
                    '<nav class="types">%s%s</nav>',
                    '<a href="%s" class="btn chip">All Events</a>',
                    get_post_type_archive_link($this->content[0])
                );
            }
            if (!empty($content) || !empty($taxonomies) || !empty($dates)) {
                echo sprintf(
                    '<nav class="calendar types">%s%s%s</nav>',
                    $content,
                    $taxonomies
                    $taxonomies,
                    $dates
                );
            }
        }
            protected function isDatedArchive():bool
            {
                foreach (['eyear', 'emonth', 'eday'] as $key) {
                    if (array_key_exists($key, $this->params)) {
                        return true;
                    }
                }
                return false;
            }
            protected function getDateNavigation():string
            {
                $type = get_post_type();
                if (empty($type)) {
                    return '';
                }
                return $this->cache->remember(
                    $type.'dateNav',
                    function() use ($type) {
                        $tmp = new WP_Query([
                            'post_type' => $type,
                            'post_status' => 'publish',
                            'posts_per_page' => -1,
                            'fields' => 'ids',
                        ]);
                        $dates = [];
                        foreach ($tmp->posts as $id) {
                            $meta = Meta::forPost($id);
                            $start = $meta->get('date_start');
                            if (!empty($start)) {
                                $date = new DateTime($start);
                                $year = $date->format('Y');
                                $month = $date->format('m');
                                $day = $date->format('d');
                                if (!array_key_exists($year, $dates)) {
                                    $dates[$year] = [];
                                }
                                if (!array_key_exists($month, $dates[$year])) {
                                    $dates[$year][$month] = [];
                                }
                                if (!in_array($day, $dates[$year][$month])) {
                                    $dates[$year][$month][] = $day;
                                }
                            }
                        }
                        if (empty($dates)) {
                            return '';
                        }
                        $base = get_post_type_archive_link($type);
                        $out = sprintf(
                        '<details class="dates row start"><summary>%sBy Date</summary>',
                            jvbIcon('calendar')
                        );
                        foreach ($dates as $year => $months) {
                            $out .= sprintf(
                                '<details><summary><a href="%s/%d" title="See all in %d">%d</a></summary><ul>',
                                $base,
                                $year,
                                $year,
                                $year
                            );
                            foreach ($months as $month => $days) {
                                $m = intval($month);
                                $monthName = $this->getMonthName($m);
                                $out .= sprintf(
                                    '<li><a href="%s/%d/%s" title="View all posts in %s, %d">%s</a></li>',
                                    $base,
                                    $year,
                                    $month,
                                    $monthName,
                                    $year,
                                    $monthName
                                );
                            }
                            $out .= '</ul></details>';
                        }
                        $out .= '</details>';
                        return $out;
                    }
                );
            }
    protected function renderCalendar():void
    {
@@ -201,7 +351,7 @@
        }
        if (is_tax()) {
            $tax = get_queried_object();
            jvbDump($tax);
            jvbDump($tax, 'taxonomy');
        }
        return [];
    }
@@ -213,27 +363,7 @@
            return $this->formatSingular();
        }
        $page = $past
            ? $_GET['jpast']??1
            : $_GET['jpage']??1;
        $items = new WP_Query([
            'post_type' =>$this->getCurrentPostTypes(),
            'post_status'   => 'publish',
            'orderby'       => 'meta_value',
            'meta_key'      => BASE.'date_start',
            'posts_per_page'=> 30,
            'fields'        => 'ids',
            'paged'         => $page,
            'meta_type'     => 'DATETIME',
            'meta_query'    => [
                [
                    'key'   => BASE.'past',
                    'value' => '1',
                    'compare' => $past ? '=' : '!='
                ]
            ]
        ]);
        $items = new WP_Query($this->buildArgs($past));
        $events = implode('', array_map([$this, 'formatItem'], $items->posts));
@@ -248,19 +378,78 @@
            $events .= paginate_links([
                'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
                'format' => '?'.$format.'=%#%',
                'current' => $page,
                'current' => $items->query_vars['paged'],
                'total' => $total
            ]);
        }
        wp_reset_postdata();
        return $events;
    }
    protected function buildArgs(bool $past):array
    {
        $page = $past
            ? min($_GET['jpast']??1, 1)
            : min($_GET['jpage']??1, 1);
        $postTypes = $this->getCurrentPostTypes();
        $args = [
            'post_type' => $postTypes,
            'post_status'   => 'publish',
            'orderby'       => 'meta_value',
            'meta_key'      => BASE.'date_start',
            'meta_type'     => 'DATETIME',
            'posts_per_page'=> 30,
            'fields'        => 'ids',
            'paged'         => $page,
            'meta_query'    => [
                [
                    'key'   => BASE.'past',
                    'value' => '1',
                    'compare' => $past ? 'EXISTS' : 'NOT EXISTS'
                ]
            ]
        ];
        if ($this->has('eyear')) {
            $args['meta_query'][] = [
                'key'   => BASE.'year',
                'value' => intval($this->has('eyear')),
            ];
        }
        if ($this->has('emonth')) {
            $args['meta_query'][] = [
                'key'   => BASE.'month',
                'value' => str_pad($this->has('emonth'), 2, "0", STR_PAD_LEFT),
            ];
        }
        if ($this->has('eday')) {
            $args['meta_query'][] = [
                'key'   => BASE.'day',
                'value' => str_pad($this->has('eday'), 2, "0", STR_PAD_LEFT),
            ];
        }
        if (is_tax()) {
            $obj = get_queried_object();
            $args['tax_query']= [
                [
                    'taxonomy'  => $obj->taxonomy,
                    'terms'     => $obj->term_id,
                ]
            ];
        }
        return $args;
    }
    protected function formatItem(int $ID):string
    {
        $meta = Meta::forPost($ID);
        $type = jvbNoBase(get_post_type($ID));
        $date = strtotime($meta->get('date_start'));
        return sprintf(
    '<li class="item %s">
                %s
@@ -274,8 +463,8 @@
            empty($meta->get('post_thumbnail')) ? '' : jvbFormatImage($meta->get('post_thumbnail'), 'tiny', 'medium'),
            get_the_permalink($ID),
            $meta->get('post_title'),
            date('c', $meta->get('date_start')),
            date('F j, Y', $meta->get('date_start')),
            date('c', $date),
            date('F j, Y', $date),
            empty($meta->get('post_excerpt')) ? '' : wpautop($meta->get('post_excerpt'))
        );
    }
@@ -293,4 +482,29 @@
        }
        echo jvbOnThisPage(array_keys($this->details));
    }
    protected function has(string $key):false|string
    {
        return array_key_exists($key, $this->params) && absint($this->params[$key]) > 0 ?
            $this->params[$key] :
            false;
    }
    protected function getMonthName(int $num):string
    {
        return match($num) {
            1 => 'January',
            2 => 'February',
            3 => 'March',
            4 => 'April',
            5 => 'May',
            6 => 'June',
            7 => 'July',
            8 => 'August',
            9 => 'September',
            10 => 'October',
            11 => 'November',
            12 => 'December',
        };
    }
}
inc/blocks/_setup.php
@@ -64,6 +64,11 @@
        ]
    );
    if (!empty(Registrar::withFeature('is_calendar'))) {
        require('EventBlock.php');
        new JVBase\blocks\EventBlock();
    }
}
inc/integrations/SyncHelpers.php
@@ -24,6 +24,8 @@
    protected static string $syncCustomer;
    protected static string $import;
    protected static array $syncing = ['posts' => [], 'users' => [], 'terms' => []];
    protected function setQueueTypes():void
    {
inc/integrations/SyncToPost.php
@@ -13,7 +13,6 @@
trait SyncToPost
{
    use SyncTo, SyncHelpers, UserConnection;
    public function addSavePost():void
    {
        if (!has_action('save_post', [$this, 'handleSavePost'])) {
@@ -28,6 +27,8 @@
    {
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
        if (wp_is_post_revision($postID) || wp_is_post_autosave($postID)) return;
        if (isset(self::$syncing['posts'][$postID])) return;
        self::$syncing['posts'][$postID] = true;
        error_log('=== ['.$this->service_name.']::handleSavePost called');
@@ -70,6 +71,7 @@
        $this->removeSavePost();
        $this->handleTheSavePost($postID, $post, $update, $settings);
        $this->addSavePost();
        unset(self::$syncing['posts'][$postID]);
    }
    /**
     * Handle post save for syncing
inc/integrations/SyncToTerm.php
@@ -30,6 +30,9 @@
    }
    protected function handleSaveTerm(int $termID, int $tt_id, string $taxonomy, bool $update, array $args):void
    {
        if (isset(self::$syncing['terms'][$termID])) {
            return;
        }
        $tax = jvbNoBase($taxonomy);
        if (!in_array($tax, $this->syncTaxonomies)) {
            return;
@@ -54,9 +57,11 @@
        if ($isShared && $update && !$fields['_keep_synced_'.$this->service_name]) {
            return;
        }
        self::$syncing['terms'][$termID] = true;
        $this->removeSaveTerm();
        $this->handleTheSaveTerm($termID, $update, $taxonomy, $settings);
        $this->addSaveTerm();
        unset(self::$syncing['terms'][$termID]);
    }
    /**
inc/integrations/SyncToUser.php
@@ -36,6 +36,9 @@
    }
    protected function handleUpdateUser(int $userID):void
    {
        if (isset(self::$syncing['users'][$userID])) {
            return;
        }
        $user = $this->getOrCreateUser($userID);
        if (!$user) {
            return;
@@ -45,10 +48,12 @@
        if (!empty($fields["_{$this->service_name}_item_id"])) {
            return;
        }
        self::$syncing['users'][$userID] = true;
        $this->removeSaveUser();
        $this->handleTheSaveUser($userID);
        $this->addSaveUser();
        unset(self::$syncing['users'][$userID]);
    }
    protected function getOrCreateUser(int $userID):string|false
inc/integrations/services/Cloudflare.php
@@ -49,6 +49,9 @@
    protected function initialize(): void
    {
        // TODO: Implement initialize() method.
        add_action('woocommerce_review_order_before_submit', [$this, 'addToCheckout']);
        add_action('wp_enqueue_scripts', [$this, 'enqueueOnCheckout']);
        add_action('woocommerce_checkout_process', [$this, 'checkoutTurnstile']);
    }
    public function getServiceDescription():string
@@ -188,4 +191,23 @@
        }
        return $result['success'] ?? false;
    }
    public function enqueueOnCheckout():void
    {
        if (function_exists('is_checkout') && is_checkout()) {
            self::enqueueTurnstileScripts();
        }
    }
    public function addToCheckout():void
    {
        self::renderTurnstile();
    }
    public function checkoutTurnstile():void
    {
        $verified = $this->verifyTurnstile();
        if (!$verified && function_exists('wc_add_notice')) {
            wc_add_notice('Security check failed. Please try again', 'error');
            return;
        }
    }
}
inc/managers/DirectoryManager.php
@@ -37,8 +37,8 @@
        jvb_register_do_once('buildDirectories', [$this, 'activate']);
        add_action('init', [$this, 'registerDirectories']);
        add_filter('pre_render_block', [$this, 'renderBlock'], 20, 3);
        add_action('save_post', [$this, 'flushCache']);
        add_action('edit_terms', [$this, 'flushCache']);
        add_action('save_post', [$this, 'flushPostCache']);
        add_action('edit_terms', [$this, 'flushPostCache']);
    }
    public function flushPostCache(int $postID):void
inc/meta/Meta.php
@@ -86,6 +86,9 @@
                'user'  => get_user_meta($this->ID),
                default => []
            };
            $this->fields = array_map(fn($values) => is_array($values) ? $values[0] : $values, $this->fields);
            $this->fields = array_combine(
                array_map('jvbNoBase', array_keys($this->fields)),
                $this->fields
inc/meta/Sanitizer.php
@@ -14,13 +14,18 @@
    public static function sanitize(mixed $value, array $field_config): mixed
    {
        $callback = static::getCallback($field_config);
//      $caller = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
//      error_log('Called from: '.print_r($caller, true));
//      $name = $field_config['name']??'';
//
//      error_log('Sanitizing '.$name. ' with value: '.print_r($value, true));
        if (is_array($callback)) {
            return call_user_func([static::class, $callback[1]], $value, $field_config);
        }
        if (method_exists(static::class, $callback)) {
        } elseif (method_exists(static::class, $callback)) {
            return static::$callback($value, $field_config);
        }
        return call_user_func($callback, $value);
    }
@@ -236,25 +241,30 @@
        return implode(',', array_intersect($value, array_keys($field_config['options'])));
    }
    protected static function sanitizeDate(string $value, array $field_config):string
    {
        $timestamp = strtotime($value);
        return $timestamp ? date('Y-m-d', $timestamp) : '';
    }
    protected static function sanitizeDateTime(string $value, array $field_config): string
    protected static function sanitizeDate(?string $value, array $field_config): string
    {
        if (empty($value)) {
            return '';
        }
        $timestamp = strtotime($value);
        if (!$timestamp) {
        try {
            $date = new \DateTime($value, wp_timezone());
        } catch (\Exception $e) {
            return '';
        }
        return $date->format('Y-m-d');
    }
        // Return in MySQL datetime format
        return date('Y-m-d H:i:s', $timestamp);
    protected static function sanitizeDateTime(?string $value, array $field_config): string
    {
        if (empty($value)) {
            return '';
        }
        try {
            $date = new \DateTime($value, wp_timezone());
        } catch (\Exception $e) {
            return '';
        }
        return $date->format('Y-m-d H:i:s');
    }
    protected static function sanitizeTime(string $value, array $field_config):string
inc/registrar/Fields.php
@@ -437,37 +437,37 @@
        $business->setHasOfferCatalogField($this);
    }
    public function registerPostFields():void
    {
        $postType = $this->registrar->getBased();
        add_meta_box(
            $postType.'_fields',
            'Extra Fields',
            [$this, 'renderMyMetaBox'],
            $postType,
            'side',
            'high'
        );
    }
    public function renderMyMetaBox():void
    {
        $ID = get_the_ID();
        $meta = match ($this->type) {
            'post'  => Meta::forPost($ID),
            'term'  => Meta::forTerm($ID),
            'user'  => Meta::forUser($ID),
        };
        $defaults = array_keys(match($this->type) {
            'post'  => $this->defaultPostFields(),
            'term'  => $this->defaultTermFields(),
            'user'  => $this->defaultUserFields()
        });
        foreach ($this->fields as $fName => $field){
            if (!in_array($fName, $defaults)){
                echo Form::render($fName, $meta->get($fName),$field->getConfig());
            }
        }
    }
//  public function registerPostFields():void
//  {
//      $postType = $this->registrar->getBased();
//      add_meta_box(
//          $postType.'_fields',
//          'Extra Fields',
//          [$this, 'renderMyMetaBox'],
//          $postType,
//          'side',
//          'high'
//      );
//  }
//  public function renderMyMetaBox():void
//  {
//      $ID = get_the_ID();
//      $meta = match ($this->type) {
//          'post'  => Meta::forPost($ID),
//          'term'  => Meta::forTerm($ID),
//          'user'  => Meta::forUser($ID),
//      };
//      $defaults = array_keys(match($this->type) {
//          'post'  => $this->defaultPostFields(),
//          'term'  => $this->defaultTermFields(),
//          'user'  => $this->defaultUserFields()
//      });
//      foreach ($this->fields as $fName => $field){
//          if (!in_array($fName, $defaults)){
//              echo Form::render($fName, $meta->get($fName),$field->getConfig());
//          }
//      }
//  }
    public static function getUserFields():array
    {
inc/registrar/Registrar.php
@@ -238,6 +238,9 @@
    private static array $instances = [];
    protected string $based;
    protected static array $processing = ['terms'=>[],'posts'=>[],'users' =>[]];
    private function __construct(string $slug, string $singular, string $plural, string $type) {
        $this->slug = $slug;
        $this->based = jvbCheckBase($slug);
@@ -1060,14 +1063,12 @@
        }
        public function addTermUpdatedMeta(int $termId):void
        {
            static $processing = [];
            if (isset($processing[$termId])) return;
            $processing[$termId] = true;
            if (self::$processing['terms'][$termId]) return;
            self::$processing['terms'][$termId] = true;
            update_term_meta($termId, BASE . 'date_modified', date('Y-m-d H:i:s'));
            unset($processing[$termId]);
            unset(self::$processing['terms'][$termId]);
        }
    public function renderContent(string $content, array $block):string
inc/registrar/helpers/AddCustomFields.php
@@ -23,7 +23,7 @@
    {
        switch ($this->registrar->getType()) {
            case 'post':
                add_action('save_post', [$this, 'checkPostFields']);
                add_action('save_post', [$this, 'checkPostFields'], 10, 2);
                add_action('enqueue_block_editor_assets', [$this, 'enqueue']);
                break;
            case 'term':
@@ -92,11 +92,13 @@
                ? $this->determineSchema($config)
                : true;
            $schema = is_array($rawSchema) ? $this->schema($rawSchema) : $rawSchema;
            //Allow for null
            if ($metaType === 'object') {
                $metaType = ['object', 'null'];
                $rawSchema['type'] = ['object', 'null'];
            }
            $schema = is_array($rawSchema) ? $this->schema($rawSchema) : $rawSchema;
            register_post_meta($this->registrar->getBased(), jvbCheckBase($name), [
                'single'            => true,
                'type'              => $metaType,
@@ -104,7 +106,6 @@
                'sanitize_callback' => fn($value) => (Sanitizer::sanitize($value, $config)),
                'auth_callback'     => fn($allowed, $key, $postID) => current_user_can('edit_post', $postID),
                'show_in_rest'      => $schema,
                'revisions_enabled' => true,
            ]);
        }
    }
inc/registrar/helpers/MakeCalendarType.php
@@ -1,6 +1,7 @@
<?php
namespace JVBase\registrar\helpers;
use DateTime;
use JVBase\meta\Meta;
use JVBase\registrar\Registrar;
use WP_Post;
@@ -82,17 +83,20 @@
                'hidden'    => true,
            ],
            'year' => [
                'type'      => 'number',
                'type'      => 'text',
                'subtype'   => 'number',
                'label'     => 'Year',
                'hidden'    => true,
            ],
            'month' => [
                'type'      => 'number',
                'type'      => 'text',
                'subtype'   => 'number',
                'label'     => 'Month',
                'hidden'    => true,
            ],
            'day' => [
                'type'      => 'number',
                'type'      => 'text',
                'subtype'   => 'number',
                'label'     => 'Day',
                'hidden'    => true,
            ],
@@ -129,6 +133,7 @@
            'max_participants' => [
                'type'      => 'number',
                'label'     => 'Maximum Participants',
                'hint'      => 'Leave 0 for no maximum'
            ],
            'is_free' => [
                'type' => 'true_false',
@@ -311,6 +316,23 @@
        if ($post->post_type === $this->postType) {
            $get = ['year', 'month','day'];
            $values = Meta::forPost($post->ID)->getAll($get);
            if (empty($values['year']) || empty($values['month']) || empty($values['day'])) {
                $value = Meta::forPost($post->ID)->get('date_start');
                if (!empty($value)) {
                    $date = new DateTime($value, wp_timezone());
                    $year = $date->format('Y');
                    $month = $date->format('m');
                    $day = $date->format('d');
                    $values = [
                        'year'  => $year,
                        'month' => $month,
                        'day'   => $day
                    ];
                    Meta::forPost($post->ID)->setAll($values);
                }
            }
            foreach ($values as $key => $value) {
                if (!empty($value) && $value !== 0) {
                    $url = str_replace("%e$key%", $value, $url);
jvb.php
@@ -442,7 +442,7 @@
    {
        NewsRoutes::getInstance();
    }
    OpenStreetMaps::getInstance();
}
@@ -563,3 +563,4 @@
{
    return Registrar::maybeExcludeSingles($IDs);
}
src/_meta/fields/date-field.js
@@ -1,8 +1,8 @@
import { useState } from 'react';
import { DatePicker } from '@wordpress/components';
const DateField = ({field, value, onChange}) => {
    // const [ date, setDate ] = useState( new Date() );
    return (
        <div className="components-base-control" id={field.name}>
            <label className="components-base-control__label">
@@ -21,6 +21,7 @@
const toLocalDate = (value) => {
    if (!value) return null;
    const [year, month, day] = value.split('-').map(Number);
    if (!year || !month || !day) return null;
    return new Date(year, month - 1, day);
};
src/_meta/fields/datetime-field.js
@@ -2,7 +2,6 @@
import { DateTimePicker } from '@wordpress/components';
const DateTimeField = ({field, value, onChange}) => {
    const [ date, setDate ] = useState( new Date() );
    return (
@@ -11,9 +10,8 @@
                { field.label }
            </label>
            <DateTimePicker
                currentDate={ date }
                currentDate={ value||null }
                onChange={ onChange }
                label={ field.label }
                help={ field.description }
                value={value??''}
                is12Hour={ true }
src/_meta/fields/selector-field.js
@@ -18,7 +18,7 @@
};
const createPayload = (field, subtype, name) =>
    subtype === 'post' ? { title: name, status: 'publish', postType: field.post_type } : { name };
    subtype === 'post' ? { title: name, status: 'publish', postType: field.post_type } : { name: name };
const labelOf = (item, subtype) => (subtype === 'user' ? item.name : item.title?.rendered ?? item.title ?? item.name);
@@ -90,7 +90,7 @@
        if (pendingCreate && canCreate && !creating) {
            setCreating(true);
            apiFetch({ path: `/wp/v2/${field.taxonomy}`, method: 'POST', data: createPayload(subtype, search) })
            apiFetch({ path: `/wp/v2/${field.taxonomy}`, method: 'POST', data: createPayload(field, subtype, search) })
                .then((item) => {
                    const label = labelOf(item, subtype);
                    const finalTokens = tokens.filter((t) => t !== createLabel).concat(label);
src/_meta/fields/upload-field.js
@@ -39,13 +39,16 @@
const UploadField = ({ field, value, onChange }) => {
    const multiple = field.multiple || field.type === 'gallery';
    const ids = multiple ? (Array.isArray(value) ? value : []) : value;
    const ids = multiple
        ? (typeof value === 'string' && value ? value.split(',').map(Number) : [])
        : value;
    const allowedTypes = SUBTYPE_MAP[field.subtype] ? [SUBTYPE_MAP[field.subtype]] : '';
    const onSelect = (media) => onChange(multiple ? media.map((m) => m.id) : media.id);
    const onSelect = (media) =>
        onChange(multiple ? media.map((m) => m.id).join(',') : media.id);
    const onRemove = (id) => {
        onChange(multiple ? ids.filter((existing) => existing !== id) : 0);
        onChange(multiple ? ids.filter((existing) => existing !== id).join(',') : 0);
    };
    return (
src/event/block.json
New file
@@ -0,0 +1,24 @@
{
    "$schema": "https://schemas.wp.org/trunk/block.json",
    "apiVersion": 3,
    "name": "jvb/event",
    "title": "Event Summary",
    "category": "jvb",
    "icon": "align-center",
    "description": "Outputs the event information",
    "keywords": [ "event" ],
    "version": "0.9.0",
    "textdomain": "jvb",
    "supports": {
        "html": false,
        "align": ["wide", "full"]
    },
    "selectors": {
        "root": ".event-block"
    },
    "render": "file:./render.php",
    "editorScript": "file:./index.js",
    "editorStyle": "file:./index.css",
    "style": "file:./style-index.css",
    "viewScript": "file:./view.js"
}
src/event/edit.js
New file
@@ -0,0 +1,29 @@
/**
 * WordPress dependencies
 */
import { __ } from '@wordpress/i18n';
import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
import { SelectControl, ToggleControl, PanelBody } from '@wordpress/components';
/**
 * Styles
 */
import './editor.scss';
/**
 * Edit function for Summary Block
 */
export default function Edit({ attributes, setAttributes }) {
    const blockProps = useBlockProps();
    return (
        <div {...blockProps}>
            <div className="jvb-summary-preview">
                <h3>{__('Summary', 'jvb')}</h3>
                <p className="jvb-list-preview-note">
                    {__('This will inherit the current query to build the information from our custom meta on the front end.', 'jvb')}
                </p>
            </div>
        </div>
    );
}
src/event/editor.scss
New file
@@ -0,0 +1,20 @@
/**
 * Directory List Block Editor Styles
 */
.jvb-summary-preview {
    padding: 20px;
    background-color: #f8f9fa;
    border: 1px solid #e2e4e7;
    border-radius: 4px;
    h3 {
        margin-top: 0;
        padding-bottom: 10px;
        border-bottom: 1px solid #ff0080;
    }
    &-note {
        font-style: italic;
        color: #555d66;
        margin-bottom: 0;
    }
}
src/event/index.js
New file
@@ -0,0 +1,39 @@
/**
 * Registers a new block provided a unique name and an object defining its behavior.
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
 */
import { registerBlockType } from '@wordpress/blocks';
/**
 * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
 * All files containing `style` keyword are bundled together. The code used
 * gets applied both to the front of your site and to the editor.
 *
 * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
 */
import './style.scss';
/**
 * Internal dependencies
 */
import Edit from './edit';
import save from './save';
import metadata from './block.json';
/**
 * Every block starts by registering a new block type definition.
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
 */
registerBlockType( metadata.name, {
    /**
     * @see ./edit.js
     */
    edit: Edit,
    /**
     * @see ./save.js
     */
    save,
} );
src/event/index.php
src/event/render.php
New file
@@ -0,0 +1,5 @@
<?php
if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly
}
src/event/save.js
New file
@@ -0,0 +1,3 @@
export default function save() {
    return null; // Dynamic block rendered by PHP
}
src/event/style.scss
New file
@@ -0,0 +1,60 @@
.event-block {
    .tags {
        --gap: 1rem;
        .tag {
            display: flex;
            gap: .5rem;
            background-color: rgb(var(--action-0));
            color: rgb(var(--action-contrast));
            font-size: var(--txt-x-small);
            text-transform: uppercase;
            border-radius: 4px;
            padding: .25rem .5rem 0;
        }
    }
    header {
        --wrap: nowrap!important;
        gap: 1rem;
        h1 {
            margin: 0;
        }
    }
    .calendar.col {
        border-radius: .5rem;
        border: 2px solid rgb(var(--action-0));
        width: var(--btn_);
        --align: stretch;
        --gap: 0;
        span {
            text-align: center;
            text-transform: uppercase;
            line-height: .8;
        }
        .weekday {
            background-color: rgb(var(--action-0));
            color: rgb(var(--action-contrast));
            font-weight: var(--fw-h-bold);
            font-family: var(--heading);
            line-height: 1.4;
            margin-bottom: .5rem;
        }
        .day {
            font-size: var(--txt-xx-large);
        }
    }
    .gallery figure {
        max-width: min(15vw, 8rem) !important;
        aspect-ratio: 1;
        object-fit: cover;
    }
    figcaption {
        display: none;
    }
}
src/event/view.js
New file
@@ -0,0 +1 @@
src/simple-calendar/style.scss
@@ -12,3 +12,12 @@
        margin: 0;
    }
}
.simple-calendar {
    nav.calendar.types {
        height: max-content;
    }
}