@veribir/m2a-interface 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2025 Veribir Technology Services Ltd
1
+ Copyright (c) 2026 Veribir Technology Services Ltd
2
2
 
3
3
 
4
4
  All rights reserved.
package/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # Builder (M2A) Button Matrix for Directus
2
+
3
+ This interface extension replaces Directus' default Many-to-Any (M2A) builder dropdown with a fast, visual grid that makes large collections easy to scan. Users can open a modal, search, filter by category or tag, and trigger the original builder actions with keyboard shortcuts or mouse clicks.
4
+
5
+ ## Highlights
6
+ - Transforms the M2A builder into a responsive grid with collection banners, icons, and labels.
7
+ - Supports optional search, category, and tag chips so editors can zero in on the right content type.
8
+ - Mirrors the built-in builder actions, so you keep existing permissions, relations, and behaviors.
9
+ - Keyboard-friendly: arrow keys, Home/End, and Enter continue to work for power users.
10
+ - Written with the Directus Extensions SDK, Vue 3, and VueUse utilities for a lightweight footprint.
11
+
12
+ ## Requirements
13
+ - Directus `^11.8.0` (the interface hooks into the builder introduced in 11.8).
14
+ - Node.js `>=18` (matches the Directus SDK toolchain) and npm.
15
+ - Access to your Directus project files so you can place the compiled interface under `extensions/interfaces`.
16
+
17
+ ## Installation
18
+ 1. **Install dependencies**
19
+ ```bash
20
+ npm install
21
+ ```
22
+ 2. **Build the extension**
23
+ ```bash
24
+ npm run build
25
+ ```
26
+ This emits `dist/index.js`, the entry point declared in `package.json`.
27
+ 3. **Copy or link the interface into Directus**
28
+ - Copy the `dist` folder (or the entire repository) into `<directus-root>/extensions/interfaces/m2a-button-matrix`, **or**
29
+ - Run `npm run link` to symlink the extension into a locally running Directus instance via the Extensions SDK helper.
30
+ 4. **Restart Directus** so it discovers the new interface.
31
+
32
+ > **Tip:** `npm run dev` rebuilds the extension in watch mode and is ideal when paired with `npm run link` during active development.
33
+
34
+ ## Usage inside Directus
35
+ 1. Open *Settings → Data Model* and edit the collection that contains your existing M2A field.
36
+ 2. Add a new field (alias or presentation) where you want the matrix to render.
37
+ 3. Choose **Builder (M2A) Button Matrix** as the interface.
38
+ 4. Configure the options below, then place the field directly above or below the real M2A builder as indicated by the notice rendered by the interface.
39
+
40
+ ### Configuration Options
41
+ | Option | Type | Description |
42
+ | --- | --- | --- |
43
+ | **Target Builder (M2A) field placement** | Select (`above` or `below`) | Where the original builder sits relative to this presentation field. Determines which sibling DOM node the extension hijacks.
44
+ | **Enable Search** | Boolean | Turns on the search input inside the modal.
45
+ | **Search Placeholder** | String | Placeholder text for the search bar (only visible when search is enabled).
46
+ | **Category Collection** | Collection picker | Optional collection containing category terms.
47
+ | **Category Relation Field** | String | Field name (in the allowed collections) that stores the category relation. Used to auto-tag the grid cards.
48
+ | **Tag Collection** | Collection picker | Optional collection containing tag terms.
49
+ | **Tag Relation Field** | String | Field name in the allowed collections that stores tag relations.
50
+
51
+ ### Filters & Keyboard Controls
52
+ - **Search:** Type to instantly filter the cards by their label.
53
+ - **Category/Tag chips:** Click chips to toggle filters; the modal shows active filters above the grid.
54
+ - **Clear filters:** Use the *Clear all* button to reset search, categories, and tags.
55
+ - **Arrow keys:** Navigate between cards.
56
+ - **Home / End:** Jump to the first or last card.
57
+ - **Enter / Space:** Activate the focused card, triggering the original builder action.
58
+
59
+ ## Development Workflow
60
+ - `npm run dev` – watch mode build with readable output; pair with `npm run link` for hot iterations.
61
+ - `npm run build` – production build with minified output.
62
+ - `npm run link` – symlink the extension into a Directus project (requires the `DIRECTUS_ENV` variables expected by the Extensions SDK).
63
+ - `npm run validate` – run the Directus validator to ensure the manifest, bundle, and metadata are correct before shipping.
64
+
65
+ ### Project Structure
66
+ ```
67
+ src/
68
+ index.ts # Registers the interface, exposes builder options, and metadata.
69
+ interface.vue # Vue 3 component implementing the matrix UI, modal, filters, and keyboard UX.
70
+ tsconfig.json # TypeScript settings used by the Extensions SDK build.
71
+ ```
72
+
73
+ ## Releasing
74
+ 1. Update `version` in `package.json` according to semver.
75
+ 2. Run `npm run build`.
76
+ 3. Publish the package or distribute the `dist` folder to customers or internal projects.
77
+
78
+ ## Publishing to npm
79
+ 1. **Tag & commit** – ensure the version bump and build artifacts are committed and pushed (`git tag vX.Y.Z && git push --tags`).
80
+ 2. **Authenticate** – run `npm login` (or `npm login --scope @veribir` for scoped publishing) with an account that has publish rights; complete the 2FA prompt if required.
81
+ 3. **Verify access level** – this package is scoped and should stay public, so use `npm publish --access public` unless your org mandates otherwise.
82
+ 4. **Publish** – execute `npm publish --workspace .` (or run from this folder) after confirming `dist/` contains the latest build.
83
+ 5. **Post-publish checks** – confirm the new version appears on npmjs.com, then update downstream Directus projects or internal registries.
84
+
85
+ ## License
86
+ Proprietary © Veribir. All rights reserved.
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{useApi as e,useStores as t,defineInterface as n}from"@directus/extensions-sdk";import{getCurrentScope as a,onScopeDispose as r,toRef as l,readonly as o,customRef as i,ref as c,watch as d,computed as u,toValue as s,shallowRef as v,unref as f,onBeforeUpdate as m,defineComponent as p,onMounted as h,nextTick as g,resolveComponent as b,openBlock as y,createElementBlock as x,Fragment as w,createElementVNode as k,createBlock as C,withCtx as _,createTextVNode as A,toDisplayString as S,createCommentVNode as B,Teleport as M,createVNode as V,normalizeClass as $,renderList as E,withKeys as F,withModifiers as T}from"vue";const q="undefined"!=typeof window&&"undefined"!=typeof document;"undefined"!=typeof WorkerGlobalScope&&(globalThis,WorkerGlobalScope);const H=Object.prototype.toString,O=()=>{};function z(e){return Array.isArray(e)?e:[e]}const I=q?window:void 0;function P(...e){const t=[],n=()=>{t.forEach(e=>e()),t.length=0},l=u(()=>{const t=z(s(e[0])).filter(e=>null!=e);return t.every(e=>"string"!=typeof e)?t:void 0}),o=(i=()=>{var t,n;return[null!=(n=null==(t=l.value)?void 0:t.map(e=>function(e){var t;const n=s(e);return null!=(t=null==n?void 0:n.$el)?t:n}(e)))?n:[I].filter(e=>null!=e),z(s(l.value?e[1]:e[0])),z(f(l.value?e[2]:e[1])),s(l.value?e[3]:e[2])]},c=([e,a,r,l])=>{if(n(),!(null==e?void 0:e.length)||!(null==a?void 0:a.length)||!(null==r?void 0:r.length))return;const o=(i=l,"[object Object]"===H.call(i)?{...l}:l);var i;t.push(...e.flatMap(e=>a.flatMap(t=>r.map(n=>((e,t,n,a)=>(e.addEventListener(t,n,a),()=>e.removeEventListener(t,n,a)))(e,t,n,o)))))},v={flush:"post"},d(i,c,{...v,immediate:!0}));var i,c,v;var m;return m=n,a()&&r(m),()=>{o(),n()}}function R(...e){let t,n,a={};3===e.length?(t=e[0],n=e[1],a=e[2]):2===e.length?"object"==typeof e[1]?(t=!0,n=e[0],a=e[1]):(t=e[0],n=e[1]):(t=!0,n=e[0]);const{target:r=I,eventName:l="keydown",passive:o=!1,dedupe:i=!1}=a,c="function"==typeof(d=t)?d:"string"==typeof d?e=>e.key===d:Array.isArray(d)?e=>d.includes(e.key):()=>!0;var d;return P(r,l,e=>{e.repeat&&s(i)||c(e)&&n(e)},o)}function j(e,t){const n=v(null!=(r=s(null!=(a=null==t?void 0:t.initialValue)?a:s(e)[0]))?r:void 0);var a,r;const f=function(...e){if(1!==e.length)return l(...e);const t=e[0];return"function"==typeof t?o(i(()=>({get:t,set:O}))):c(t)}(e),m=u({get(){var e;const a=f.value;let r=(null==t?void 0:t.getIndexOf)?t.getIndexOf(n.value,a):a.indexOf(n.value);return r<0&&(r=null!=(e=null==t?void 0:t.fallbackIndex)?e:0),r},set(e){p(e)}});function p(e){const t=f.value,a=t.length,r=t[(e%a+a)%a];return n.value=r,r}function h(e=1){return p(m.value+e)}return d(f,()=>p(m.value)),{state:n,index:m,next:function(e=1){return h(e)},prev:function(e=1){return h(-e)},go:p}}const L={key:0,class:"btn-matrix"},N={className:"collection-modal"},Z={class:"modal-title"},D={class:"filters"},K={key:0,class:"filter-section"},U={class:"filter-chips-container"},G={class:"filter-chips"},W=["onClick"],Y={key:1,class:"filter-section"},J={class:"filter-chips-container"},Q={class:"filter-chips"},X=["onClick"],ee={key:2,class:"filter-section"},te={class:"collection-visual"},ne=["src","alt"];var ae=p({__name:"interface",props:{value:{},target:{default:"below"},enableSearch:{type:Boolean,default:!1},searchPlaceholder:{default:"Search..."},collection:{},categoryCollection:{},categoryRelationField:{},tagCollection:{},tagRelationField:{}},setup(n){const a=n,r=e(),{useCollectionsStore:l}=t(),o=l(),i=c(),s=c(),v=c([]),p=c([]),q=c([]),H=c([]),O=c([]),{targetBuilder:z}=function(e,{onFound:t}){const n=c();return h(()=>{var r,l,o,i,c,d;const u="above"===a.target?"previousElementSibling":"nextElementSibling";n.value=null==(o=null==(l=null==(r=e.value)?void 0:r.closest(".field"))?void 0:l[u])?void 0:o.querySelector(".m2a-builder"),n.value&&(t(),s.value=null!=(d=null==(c=null==(i=n.value)?void 0:i.closest(".field"))?void 0:c.getAttribute("data-field"))?d:void 0)}),{targetBuilder:n}}(i,{onFound:()=>{var e,t;null==(t=null==(e=i.value)?void 0:e.closest(".field"))||t.remove()}}),{label:I,buttonMatrix:ae,triggerClick:re}=function(e){const t=c(""),n=c([]);let l;return d(()=>e.value,async function(){var n,c,d,h;const b=null==(n=e.value)?void 0:n.querySelector(".actions>.v-menu");if(l=null==b?void 0:b.querySelector(".v-button button"),!l)return;t.value=null!=(c=l.textContent)?c:"";const y=20;let x,w=0;do{await m(w?50:0),w++,l.click(),await g(),x=i()}while(!x&&w<y);if(!x)return;if(function(e){e.style.visibility="hidden",e.style.display="block",e.style.position="absolute"}(b),u(x),f(x),!s.value)return;try{const e=await r.get(`/relations/${a.collection}_${s.value}`),t=((null==(h=null==(d=e.data)?void 0:d.data)?void 0:h.filter(e=>"item"===e.field))||[]).map(e=>{var t;return(null==(t=e.meta)?void 0:t.one_allowed_collections)||[]}).flat();v.value=null==t?void 0:t.map(e=>o.getCollection(e)).filter(Boolean),console.log("collectionList",v.value),await ue(),await se(),console.log("Categories:",p.value),console.log("Tags:",q.value)}catch(e){console.warn("Error fetching collection data:",e)}},{once:!0}),{label:t,buttonMatrix:n,triggerClick:async function(e){null==l||l.click(),await g();const t=document.querySelector(".v-menu-popper.active");if(!t)return;const n=null==t?void 0:t.querySelectorAll(".v-list-item.link.clickable"),a=null==n?void 0:n[e];a&&a.click();await g(),t.style.visibility="hidden",document.body.click()}};function i(){const e=document.querySelector("#menu-outlet .v-menu-popper.active:not([data-hacked])");if(e)return e.dataset.hacked="hacked",e}function u(e){var t;null==(t=e.querySelectorAll(".v-list-item.link.clickable"))||t.forEach(e=>{var t,a,r;const l=e.textContent,o=null!=(r=null==(a=null==(t=e.querySelector(".v-icon [data-icon]"))?void 0:t.dataset)?void 0:a.icon)?r:"database";n.value.push({label:l,icon:o})})}async function f(e){e.style.visibility="hidden",await m(150),document.body.click()}function m(e){return new Promise(t=>setTimeout(t,e))}}(z),le=c(""),oe=c(!1),ie=u(()=>{let e=ae.value;return v.value.length>0&&(e=ae.value.map((e,t)=>{var n,a,r;const l=v.value[t];return{...e,collectionKey:null==l?void 0:l.collection,collectionBanner:null==(n=null==l?void 0:l.meta)?void 0:n.collection_banner,categories:(null==(a=null==l?void 0:l.meta)?void 0:a.category)?[l.meta.category]:[],tags:(null==(r=null==l?void 0:l.meta)?void 0:r.tags)||[]}})),e=e.filter(e=>{if(le.value){const t=le.value.toLowerCase();if(!e.label.toLowerCase().includes(t))return!1}return!(H.value.length>0&&(!e.categories||!H.value.some(t=>e.categories.includes(t))))&&!(O.value.length>0&&(!e.tags||!O.value.some(t=>e.tags.includes(t))))}),e});function ce(){oe.value=!0}function de(){oe.value=!1}async function ue(){var e;if(a.categoryCollection)try{const t=await r.get(`/items/${a.categoryCollection}`);p.value=(null==(e=t.data)?void 0:e.data)||[]}catch(e){console.warn("Error fetching categories:",e)}}async function se(){var e;if(a.tagCollection)try{const t=await r.get(`/items/${a.tagCollection}`);q.value=(null==(e=t.data)?void 0:e.data)||[]}catch(e){console.warn("Error fetching tags:",e)}}function ve(){H.value=[],O.value=[],le.value=""}function fe(e){return e?`/assets/${e}?quality=80`:null}const me=c(null),pe=function(){const e=c([]);return e.value.set=t=>{t&&e.value.push(t)},m(()=>{e.value.length=0}),e}(),he=u(()=>ie.value.map((e,t)=>t)),{state:ge,next:be,prev:ye,go:xe}=j(he,{initialValue:0});function we(e){g(()=>{const t=pe.value[e];if(null==t?void 0:t.$el){const e=t.$el,n=null==e?void 0:e.querySelector("button");null==n||n.focus()}})}const ke={target:me,passive:!1};return R(["ArrowDown","ArrowRight"],e=>{e.preventDefault(),be(),we(ge.value)},ke),R(["ArrowUp","ArrowLeft"],e=>{e.preventDefault(),ye(),we(ge.value)},ke),R("Home",e=>{e.preventDefault(),xe(0),we(ge.value)},ke),R("End",e=>{e.preventDefault();const t=he.value.length-1;t>=0&&(xe(t),we(ge.value))},ke),d(he,e=>{(!e.includes(ge.value)&&e.length>0||0===e.length)&&xe(0)},{flush:"post"}),P(me,"focus",e=>{var t;!(null==(t=me.value)?void 0:t.contains(e.relatedTarget))&&he.value.length>0&&we(ge.value)}),h(async()=>{(a.categoryCollection||a.tagCollection)&&(await ue(),await se())}),(e,t)=>{const n=b("v-notice"),r=b("v-divider"),l=b("v-icon"),o=b("v-button"),c=b("v-card-title"),d=b("v-input"),u=b("v-text-overflow"),s=b("v-card"),v=b("v-card-text"),m=b("v-dialog");return y(),x(w,null,[k("div",{ref_key:"el",ref:i},[f(z)?B("v-if",!0):(y(),C(n,{key:0,type:"warning",icon:"vertical_align_"+("above"===e.target?"top":"bottom")},{default:_(()=>[A(" No Builder (M2A) field found "+S(e.target)+" this field! ",1)]),_:1},8,["icon"]))],512),f(z)?(y(),C(M,{key:0,to:f(z)},[f(ae).length>0?(y(),x("div",L,[f(I)?(y(),C(r,{key:0,"inline-title":"",class:"label"},{default:_(()=>[A(S(f(I)),1)]),_:1})):B("v-if",!0),B(" Button to open modal "),V(o,{secondary:"","full-width":"",class:"open-modal-btn",onClick:ce},{default:_(()=>[V(l,{name:"add"}),t[3]||(t[3]=A(" Create New "))]),_:1})])):B("v-if",!0)],8,["to"])):B("v-if",!0),B(" Modal Implementation "),V(m,{modelValue:oe.value,"onUpdate:modelValue":t[2]||(t[2]=e=>oe.value=e)},{default:_(()=>[k("div",N,[V(s,{class:"modal-card"},{default:_(()=>[V(c,{class:"modal-header"},{default:_(()=>[k("h1",Z,S(f(I)),1),V(o,{secondary:!0,icon:!0,rounded:!0,type:"div"},{default:_(()=>[V(l,{name:"close",onClick:de})]),_:1})]),_:1}),V(v,{class:"modal-content"},{default:_(()=>{var e;return[a.enableSearch?(y(),C(d,{key:0,modelValue:le.value,"onUpdate:modelValue":t[0]||(t[0]=e=>le.value=e),placeholder:a.searchPlaceholder,class:"modal-search"},{prepend:_(()=>[V(l,{name:"search"})]),_:1},8,["modelValue","placeholder"])):B("v-if",!0),k("div",D,[B(" Category Filter Chips "),(null==(e=p.value)?void 0:e.length)>0?(y(),x("div",K,[t[4]||(t[4]=k("div",{class:"filter-label"},"Categories:",-1)),k("div",U,[k("div",G,[B(" All button (active when selectedCategories array is empty) "),k("button",{class:$([{active:0===H.value.length},"custom-chip"]),onClick:ve}," All ",2),(y(!0),x(w,null,E(p.value,(e,t)=>(y(),x("button",{key:e.id||t,class:$([{active:H.value.includes(e.id)},"custom-chip"]),onClick:t=>function(e){const t=H.value.indexOf(e);t>-1?H.value.splice(t,1):H.value.push(e)}(e.id)},S(e.title),11,W))),128))])])])):B("v-if",!0),B(" Tag Filter Chips "),q.value.length>0?(y(),x("div",Y,[t[5]||(t[5]=k("div",{class:"filter-label"},"Tags:",-1)),k("div",J,[k("div",Q,[B(" All button (active when selectedTags array is empty) "),k("button",{class:$([{active:0===O.value.length},"custom-chip"]),onClick:ve}," All ",2),(y(!0),x(w,null,E(q.value,(e,t)=>(y(),x("button",{key:e.id||t,class:$([{active:O.value.includes(e.id)},"custom-chip"]),onClick:t=>function(e){const t=O.value.indexOf(e);t>-1?O.value.splice(t,1):O.value.push(e)}(e.id)},S(e.title),11,X))),128))])])])):B("v-if",!0),B(" Clear Filters Button "),H.value.length>0||O.value.length>0||le.value?(y(),x("div",ee,[V(o,{secondary:"",small:"",onClick:ve},{default:_(()=>[V(l,{name:"clear"}),t[6]||(t[6]=A(" Clear All Filters "))]),_:1})])):B("v-if",!0)]),k("div",{ref_key:"gridRef",ref:me,class:"modal-grid",tabindex:"0"},[(y(!0),x(w,null,E(ie.value,(e,n)=>(y(),C(s,{key:e.label,ref_for:!0,ref:f(pe).set,tabindex:n===f(ge)?0:-1,class:"collection-button",onClick:e=>{f(re)(n),de()},onKeydown:[F(T(e=>{f(re)(n),de()},["prevent"]),["enter"]),F(T(e=>{f(re)(n),de()},["prevent"]),["space"])]},{default:_(()=>[B(" Collection Image or Icon "),k("div",te,[e.collectionBanner&&fe(e.collectionBanner)?(y(),x("img",{key:0,src:fe(e.collectionBanner),alt:e.label,class:"collection-image",onError:t[1]||(t[1]=e=>e.target.style.display="none")},null,40,ne)):(y(),C(l,{key:1,name:e.icon,class:"collection-icon"},null,8,["name"]))]),V(c,{class:"collection-title"},{default:_(()=>[V(u,{text:e.label,size:"small"},null,8,["text"])]),_:2},1024)]),_:2},1032,["tabindex","onClick","onKeydown"]))),128))],512)]}),_:1})]),_:1})])]),_:1},8,["modelValue"])],64)}}}),re=[],le=[];!function(e,t){if(e&&"undefined"!=typeof document){var n,a=!0===t.prepend?"prepend":"append",r=!0===t.singleTag,l="string"==typeof t.container?document.querySelector(t.container):document.getElementsByTagName("head")[0];if(r){var o=re.indexOf(l);-1===o&&(o=re.push(l)-1,le[o]={}),n=le[o]&&le[o][a]?le[o][a]:le[o][a]=i()}else n=i();65279===e.charCodeAt(0)&&(e=e.substring(1)),n.styleSheet?n.styleSheet.cssText+=e:n.appendChild(document.createTextNode(e))}function i(){var e=document.createElement("style");if(e.setAttribute("type","text/css"),t.attributes)for(var n=Object.keys(t.attributes),r=0;r<n.length;r++)e.setAttribute(n[r],t.attributes[n[r]]);var o="prepend"===a?"afterbegin":"beforeend";return l.insertAdjacentElement(o,e),e}}("\n.m2a-builder:has(.btn-matrix) .actions {\r\n\tmargin-top: 0px;\n}\n.m2a-builder:has(.btn-matrix) .actions:has(.v-menu + .v-menu) {\r\n\tmargin-top: 8px;\n}\n.btn-matrix[data-v-3fa1247f] {\r\n\tmargin-top: 8px;\r\n\tcontainer-type: inline-size;\n}\n.label[data-v-3fa1247f] {\r\n\tmargin-bottom: 8px;\n}\n.open-modal-btn[data-v-3fa1247f] {\r\n\tmargin-bottom: 12px;\r\n\t--v-button-height: 48px;\n}\n.open-modal-btn[data-v-3fa1247f] .content {\r\n\tgap: 8px;\r\n\tflex-direction: row;\r\n\t--v-icon-color: var(--theme--foreground-subdued);\n}\n.open-modal-btn[data-v-3fa1247f]:hover .content {\r\n\t--v-icon-color: var(--theme--primary);\n}\n.v-text-overflow[data-v-3fa1247f] {\r\n\twidth: 100%;\n}\n.v-divider[data-v-3fa1247f] .type-text {\r\n\tcolor: var(--theme--foreground-subdued);\n}\r\n\r\n/* Modal Styles */\n.collection-modal[data-v-3fa1247f] .modal-card {\r\n\twidth: 90vw;\r\n\tmargin: 0 auto;\r\n\tmax-width: 100rem;\n}\n.modal-card[data-v-3fa1247f] {\r\n\tbackground: var(--theme--background);\r\n\tborder-radius: var(--theme--border-radius);\r\n\tbox-shadow: 0px 4px 12px rgba(38, 50, 56, 0.1), 0px 0px 0px 1px var(--theme--border-color-subdued);\r\n\toverflow: hidden;\n}\n.modal-header[data-v-3fa1247f] {\r\n\tdisplay: flex;\r\n\talign-items: center;\r\n\tjustify-content: space-between;\r\n\tpadding: 12px 16px;\r\n\tbackground: var(--theme--background);\r\n\tborder-bottom: var(--theme--border-width) solid var(--theme--border-color-subdued);\r\n\tmin-height: 48px;\n}\n.modal-title[data-v-3fa1247f] {\r\n\tcolor: var(--theme--foreground);\r\n\tfont-weight: 600;\r\n\tfont-size: 16px;\r\n\tfont-family: var(--theme--fonts--display--font-family);\r\n\tmargin: 0;\r\n\tline-height: 24px;\n}\n.modal-close[data-v-3fa1247f] {\r\n\t--v-icon-color: var(--theme--foreground-subdued);\r\n\tcursor: pointer;\r\n\ttransition: color var(--fast) var(--transition);\r\n\tpadding: 4px;\r\n\tmargin: -4px;\n}\n.modal-close[data-v-3fa1247f]:hover {\r\n\t--v-icon-color: var(--theme--foreground);\n}\n.modal-content[data-v-3fa1247f] {\r\n\tpadding: 24px;\r\n\tbackground: var(--theme--background);\r\n\tmax-height: 60vh;\r\n\toverflow-y: auto;\n}\n.modal-search[data-v-3fa1247f] {\r\n\tmargin-bottom: 20px;\n}\n.modal-search[data-v-3fa1247f] .v-input {\r\n\t--input-background-color: var(--theme--background-subdued);\r\n\t--input-border-color: var(--theme--border-color);\n}\r\n\r\n/* Filter Sections */\n.filter-section[data-v-3fa1247f] {\r\n\tmargin-bottom: 20px;\n}\n.filter-label[data-v-3fa1247f] {\r\n\tfont-size: 14px;\r\n\tfont-weight: 500;\r\n\tcolor: var(--theme--foreground);\r\n\tmargin-bottom: 8px;\n}\n.filter-chips-container[data-v-3fa1247f] {\r\n\toverflow: auto;\n}\n.filter-chips[data-v-3fa1247f] {\r\n\tdisplay: flex;\r\n\tgap: 8px;\r\n\twidth: max-content;\n}\n.filter-chip[data-v-3fa1247f] {\r\n\t--v-chip-color: var(--theme--foreground-subdued);\r\n\t--v-chip-background-color: var(--theme--background-subdued);\r\n\t--v-chip-color-active: var(--theme--primary-foreground);\r\n\t--v-chip-background-color-active: var(--theme--primary);\r\n\tborder: 1px solid var(--theme--border-color);\r\n\ttransition: all var(--fast) var(--transition);\n}\n.filter-chip[data-v-3fa1247f]:hover {\r\n\t--v-chip-color: var(--theme--primary);\r\n\tborder-color: var(--theme--primary);\n}\n.filter-chip[active][data-v-3fa1247f] {\r\n\tborder-color: var(--theme--primary);\n}\r\n\r\n/* Custom Chip Styles */\n.custom-chip[data-v-3fa1247f] {\r\n\tdisplay: inline-flex;\r\n\talign-items: center;\r\n\theight: 32px;\r\n\tpadding: 0 12px;\r\n\tcolor: var(--theme--foreground-subdued);\r\n\tfont-weight: var(--weight-normal);\r\n\tfont-size: 14px;\r\n\tline-height: 22px;\r\n\tbackground-color: var(--theme--background-subdued);\r\n\tborder: var(--theme--border-width) solid var(--theme--border-color);\r\n\tborder-radius: 16px;\r\n\tcursor: pointer;\r\n\ttransition: all var(--fast) var(--transition);\n}\n.custom-chip[data-v-3fa1247f]:hover {\r\n\tcolor: var(--theme--primary);\r\n\tborder-color: var(--theme--primary);\r\n\tbackground-color: var(--theme--background-accent);\n}\n.custom-chip.active[data-v-3fa1247f] {\r\n\tcolor: var(--foreground-inverted);\r\n\tbackground-color: var(--theme--primary);\r\n\tborder-color: var(--theme--primary);\n}\n.custom-chip.active[data-v-3fa1247f]:hover {\r\n\tbackground-color: var(--theme--primary-accent);\r\n\tborder-color: var(--theme--primary-accent);\n}\n.modal-grid[data-v-3fa1247f] {\r\n\tdisplay: grid;\r\n\tgrid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));\r\n\tgap: 16px;\n}\n.modal-grid .collection-button[data-v-3fa1247f] {\r\n\tmax-width: 50rem;\n}\n.collection-button[data-v-3fa1247f] {\r\n\t--v-button-background-color: var(--theme--background-subdued);\r\n\t--v-button-background-color-hover: var(--theme--background-accent);\r\n\t--v-button-color: var(--theme--foreground);\r\n\t--v-button-color-hover: var(--theme--foreground);\r\n\tborder: var(--theme--border-width) solid var(--theme--border-color);\r\n\tborder-radius: var(--theme--border-radius);\r\n\ttransition: all var(--fast) var(--transition);\r\n\tcursor: pointer;\r\n\tmin-width: unset;\n}\n.collection-button[data-v-3fa1247f]:hover {\r\n\tborder-color: var(--theme--primary);\r\n\ttransform: translateY(-1px);\r\n\tbox-shadow: 0px 2px 8px rgba(38, 50, 56, 0.1);\n}\n.collection-button[data-v-3fa1247f] .content {\r\n\tpadding: 16px 12px;\r\n\tgap: 12px;\r\n\tflex-direction: column;\r\n\talign-items: center;\n}\n.collection-visual[data-v-3fa1247f] {\r\n\twidth: 100%;\r\n\theight: 10rem;\r\n\tdisplay: flex;\r\n\talign-items: center;\r\n\tjustify-content: center;\r\n\tborder-radius: var(--theme--border-radius);\r\n\toverflow: hidden;\r\n\tbackground: var(--theme--background-accent);\n}\n.collection-image[data-v-3fa1247f] {\r\n\tborder-radius: var(--theme--border-radius);\r\n\tmax-height: 100%;\r\n\tmin-height: 100%;\r\n\ttransition: all var(--fast) var(--transition);\n}\n.collection-button:hover .collection-image[data-v-3fa1247f] {\r\n\tmin-height: 0;\r\n\tmax-width: 100%;\n}\n.collection-icon[data-v-3fa1247f] {\r\n\t--v-icon-color: var(--theme--foreground-subdued);\r\n\tfont-size: 24px;\n}\n.collection-button:hover .collection-icon[data-v-3fa1247f] {\r\n\t--v-icon-color: var(--theme--primary);\n}\n.collection-title[data-v-3fa1247f] {\r\n\ttext-align: center;\r\n\tpadding: 0;\r\n\tfont-size: 13px;\r\n\tline-height: 2;\r\n\tcolor: var(--theme--foreground);\r\n\tfont-weight: 500;\r\n\tmargin: 1rem 0;\n}\n.collection-title[data-v-3fa1247f] .v-text-overflow {\r\n\tdisplay: -webkit-box;\r\n\t-webkit-box-orient: vertical;\r\n\t-webkit-line-clamp: 1;\r\n\tline-clamp: 1;\r\n\twhite-space: unset;\n}\n@media (min-width: 600px) {\n.modal-grid[data-v-3fa1247f] {\r\n\t\tgrid-template-columns: repeat(auto-fill, minmax(25rem, 1fr));\r\n\t\tgap: 20px;\n}\n.collection-visual[data-v-3fa1247f] {\r\n\t\theight: 12rem;\n}\n}\n@media (min-width: 768px) {\n.modal-grid[data-v-3fa1247f] {\r\n\t\tgrid-template-columns: repeat(auto-fill, minmax(30rem, 1fr));\n}\n.modal-content[data-v-3fa1247f] {\r\n\t\tpadding: 32px;\n}\n.collection-visual[data-v-3fa1247f] {\r\n\t\theight: 15rem;\n}\n}\n@media screen and (min-width: 1024px) {\n.filters[data-v-3fa1247f] {\r\n\t\tdisplay: flex;\r\n\t\tgap: 24px;\r\n\t\tflex-wrap: wrap;\r\n\t\talign-items: end;\r\n\t\tmargin-bottom: 32px;\n}\n.filter-section[data-v-3fa1247f] {\r\n\t\tmargin-bottom: 0;\n}\n}\r\n",{});var oe=n({id:"srt-labs-experimental-m2a-interface",name:"Builder (M2A) Button Matrix",icon:"grid_view",description:"Add a matrix button selector to the built-in M2A interface",component:((e,t)=>{const n=e.__vccOpts||e;for(const[e,a]of t)n[e]=a;return n})(ae,[["__scopeId","data-v-3fa1247f"],["__file","interface.vue"]]),types:["alias"],localTypes:["presentation"],group:"presentation",options:[{field:"target",name:"Target Builder (M2A) field placement",type:"string",meta:{width:"full",interface:"select-dropdown",options:{choices:[{text:"Above this field",value:"above",icon:"vertical_align_top"},{text:"Below this field",value:"below",icon:"vertical_align_bottom"}]}},schema:{default_value:"below"}},{field:"info",type:"alias",meta:{width:"full",interface:"presentation-notice",conditions:[{rule:{_and:[{target:{_eq:"below"}}]},options:{text:ie({targetPlacedBelow:!0})}}],options:{icon:!1,text:ie({targetPlacedBelow:!1})}}},{field:"enableSearch",name:"Enable Search",type:"boolean",meta:{width:"half",interface:"boolean"},schema:{default_value:!1}},{field:"searchPlaceholder",name:"Search Placeholder",type:"string",meta:{width:"half",interface:"input",hidden:!0,conditions:[{rule:{enableSearch:{_eq:!0}},hidden:!1}]},schema:{default_value:"Search..."}},{field:"categoryCollection",name:"Category Collection",type:"string",meta:{width:"half",interface:"system-collection",note:"Collection that contains category items"}},{field:"categoryRelationField",name:"Category Relation Field",type:"string",meta:{width:"half",interface:"input",note:"Field name in target collections that relates to categories",hidden:!0,conditions:[{rule:{categoryCollection:{_nnull:!0}},hidden:!1}]}},{field:"tagCollection",name:"Tag Collection",type:"string",meta:{width:"half",interface:"system-collection",note:"Collection that contains tag items"}},{field:"tagRelationField",name:"Tag Relation Field",type:"string",meta:{width:"half",interface:"input",note:"Field name in target collections that relates to tags",hidden:!0,conditions:[{rule:{tagCollection:{_nnull:!0}},hidden:!1}]}}]});function ie({targetPlacedBelow:e}){return`${`<svg style="vertical-align:middle" width="120" height="50" viewBox="0 0 120 50" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M114 1H6C3.23858 1 1 3.23858 1 6V16C1 18.7614 3.23858 21 6 21H114C116.761 21 119 18.7614 119 16V6C119 3.23858 116.761 1 114 1Z" stroke="var(--theme--primary)" stroke-opacity="${e?"1":"0.25"}" stroke-width="2"/><path d="M114 29H6C3.23858 29 1 31.2386 1 34V44C1 46.7614 3.23858 49 6 49H114C116.761 49 119 46.7614 119 44V34C119 31.2386 116.761 29 114 29Z" stroke="var(--theme--primary)" stroke-opacity="${e?"0.25":"1"}" stroke-width="2"/><path opacity="${e?"0.5":"1"}" d="M20 37H10V38.2691H20V37ZM10 40.7778H20V39.5087H10V40.7778Z" fill="var(--theme--primary)"/><path opacity="${e?"1":"0.5"}" d="M20 9H10V10.2691H20V9ZM10 12.7778H20V11.5087H10V12.7778Z" fill="var(--theme--primary)"/><text opacity="${e?"1":"0.5"}" fill="var(--theme--primary)" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="10" font-weight="500" letter-spacing="0em"><tspan x="28" y="14.6364">${e?"Button Matrix":"Builder (M2A)"}</tspan></text><text opacity="${e?"0.5":"1"}" fill="var(--theme--primary)" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="10" font-weight="500" letter-spacing="0em"><tspan x="28" y="42.6364">${e?"Builder (M2A)":"Button Matrix"}</tspan></text></svg>`}${`<span style="padding-left: 12px">Place this field directly ${e?"above":"below"} the Builder (M2A) field!</span>`}`}export{oe as default};
1
+ import{useApi as e,useStores as t,defineInterface as n}from"@directus/extensions-sdk";import{getCurrentScope as a,onScopeDispose as r,toRef as o,readonly as l,customRef as i,ref as c,watch as d,computed as u,toValue as s,shallowRef as v,unref as f,onBeforeUpdate as m,defineComponent as p,onMounted as h,nextTick as g,resolveComponent as b,openBlock as y,createElementBlock as x,Fragment as w,createElementVNode as k,createBlock as C,withCtx as _,createTextVNode as A,toDisplayString as S,createCommentVNode as B,Teleport as M,createVNode as V,normalizeClass as $,renderList as E,withKeys as F,withModifiers as T}from"vue";const I="undefined"!=typeof window&&"undefined"!=typeof document;"undefined"!=typeof WorkerGlobalScope&&(globalThis,WorkerGlobalScope);const q=Object.prototype.toString,H=()=>{};function O(e){return Array.isArray(e)?e:[e]}const U=I?window:void 0;function z(...e){const t=[],n=()=>{t.forEach(e=>e()),t.length=0},o=u(()=>{const t=O(s(e[0])).filter(e=>null!=e);return t.every(e=>"string"!=typeof e)?t:void 0}),l=(i=()=>{var t,n;return[null!=(n=null==(t=o.value)?void 0:t.map(e=>function(e){var t;const n=s(e);return null!=(t=null==n?void 0:n.$el)?t:n}(e)))?n:[U].filter(e=>null!=e),O(s(o.value?e[1]:e[0])),O(f(o.value?e[2]:e[1])),s(o.value?e[3]:e[2])]},c=([e,a,r,o])=>{if(n(),!(null==e?void 0:e.length)||!(null==a?void 0:a.length)||!(null==r?void 0:r.length))return;const l=(i=o,"[object Object]"===q.call(i)?{...o}:o);var i;t.push(...e.flatMap(e=>a.flatMap(t=>r.map(n=>((e,t,n,a)=>(e.addEventListener(t,n,a),()=>e.removeEventListener(t,n,a)))(e,t,n,l)))))},v={flush:"post"},d(i,c,{...v,immediate:!0}));var i,c,v;var m;return m=n,a()&&r(m),()=>{l(),n()}}function D(...e){let t,n,a={};3===e.length?(t=e[0],n=e[1],a=e[2]):2===e.length?"object"==typeof e[1]?(t=!0,n=e[0],a=e[1]):(t=e[0],n=e[1]):(t=!0,n=e[0]);const{target:r=U,eventName:o="keydown",passive:l=!1,dedupe:i=!1}=a,c="function"==typeof(d=t)?d:"string"==typeof d?e=>e.key===d:Array.isArray(d)?e=>d.includes(e.key):()=>!0;var d;return z(r,o,e=>{e.repeat&&s(i)||c(e)&&n(e)},l)}function P(e,t){const n=v(null!=(r=s(null!=(a=null==t?void 0:t.initialValue)?a:s(e)[0]))?r:void 0);var a,r;const f=function(...e){if(1!==e.length)return o(...e);const t=e[0];return"function"==typeof t?l(i(()=>({get:t,set:H}))):c(t)}(e),m=u({get(){var e;const a=f.value;let r=(null==t?void 0:t.getIndexOf)?t.getIndexOf(n.value,a):a.indexOf(n.value);return r<0&&(r=null!=(e=null==t?void 0:t.fallbackIndex)?e:0),r},set(e){p(e)}});function p(e){const t=f.value,a=t.length,r=t[(e%a+a)%a];return n.value=r,r}function h(e=1){return p(m.value+e)}return d(f,()=>p(m.value)),{state:n,index:m,next:function(e=1){return h(e)},prev:function(e=1){return h(-e)},go:p}}const R={key:0,class:"btn-matrix"},j={className:"collection-modal"},L={class:"modal-title"},N={class:"filters"},Z={key:0,class:"filter-section"},G={class:"filter-chips-container"},K={class:"filter-chips"},W=["onClick"],Y={key:1,class:"filter-section"},J={class:"filter-chips-container"},Q={class:"filter-chips"},X=["onClick"],ee={key:2,class:"filter-section"},te={class:"collection-visual"},ne=["src","alt"];var ae=p({__name:"interface",props:{value:{},target:{default:"below"},enableSearch:{type:Boolean,default:!1},searchPlaceholder:{default:"Search..."},collection:{},categoryCollection:{},categoryRelationField:{},tagCollection:{},tagRelationField:{}},setup(n){const a=n,r=e(),{useCollectionsStore:o}=t(),l=o(),i=c(),s=c(),v=c([]),p=c([]),I=c([]),q=c([]),H=c([]),{targetBuilder:O}=function(e,{onFound:t}){const n=c();return h(()=>{var r,o,l,i,c,d;const u="above"===a.target?"previousElementSibling":"nextElementSibling";n.value=null==(l=null==(o=null==(r=e.value)?void 0:r.closest(".field"))?void 0:o[u])?void 0:l.querySelector(".m2a-builder"),n.value&&(t(),s.value=null!=(d=null==(c=null==(i=n.value)?void 0:i.closest(".field"))?void 0:c.getAttribute("data-field"))?d:void 0)}),{targetBuilder:n}}(i,{onFound:()=>{var e,t;null==(t=null==(e=i.value)?void 0:e.closest(".field"))||t.remove()}}),{label:U,buttonMatrix:ae,triggerClick:re}=function(e){const t=c(""),n=c([]);let o;return d(()=>e.value,async function(){var n,c,d,h;const b=null==(n=e.value)?void 0:n.querySelector(".actions>.v-menu");if(o=null==b?void 0:b.querySelector(".v-button button"),!o)return;t.value=null!=(c=o.textContent)?c:"";const y=20;let x,w=0;do{await m(w?50:0),w++,o.click(),await g(),x=i()}while(!x&&w<y);if(!x)return;if(function(e){e.style.visibility="hidden",e.style.display="block",e.style.position="absolute"}(b),u(x),f(x),!s.value)return;try{const e=await r.get(`/relations/${a.collection}_${s.value}`),t=((null==(h=null==(d=e.data)?void 0:d.data)?void 0:h.filter(e=>"item"===e.field))||[]).map(e=>{var t;return(null==(t=e.meta)?void 0:t.one_allowed_collections)||[]}).flat();v.value=null==t?void 0:t.map(e=>l.getCollection(e)).filter(Boolean),console.log("collectionList",v.value),await ue(),await se(),console.log("Categories:",p.value),console.log("Tags:",I.value)}catch(e){console.warn("Error fetching collection data:",e)}},{once:!0}),{label:t,buttonMatrix:n,triggerClick:async function(e){const t=n.value.findIndex(t=>t.guid===e);if(-1===t)return void console.warn("Button with GUID not found:",e);null==o||o.click(),await g();const a=document.querySelector(".v-menu-popper.active");if(!a)return;const r=null==a?void 0:a.querySelectorAll(".v-list-item.link.clickable"),l=null==r?void 0:r[t];l&&l.click();await g(),a.style.visibility="hidden",document.body.click()}};function i(){const e=document.querySelector("#menu-outlet .v-menu-popper.active:not([data-hacked])");if(e)return e.dataset.hacked="hacked",e}function u(e){var t;null==(t=e.querySelectorAll(".v-list-item.link.clickable"))||t.forEach(e=>{var t,a,r;const o=e.textContent,l=null!=(r=null==(a=null==(t=e.querySelector(".v-icon [data-icon]"))?void 0:t.dataset)?void 0:a.icon)?r:"database";n.value.push({label:o,icon:l,guid:crypto.randomUUID()})})}async function f(e){e.style.visibility="hidden",await m(150),document.body.click()}function m(e){return new Promise(t=>setTimeout(t,e))}}(O),oe=c(""),le=c(!1),ie=u(()=>{let e=ae.value;return e=v.value.length>0?ae.value.map((e,t)=>{var n,a,r;const o=v.value[t];return{...e,guid:e.guid||crypto.randomUUID(),collectionKey:null==o?void 0:o.collection,collectionBanner:null==(n=null==o?void 0:o.meta)?void 0:n.collection_banner,categories:(null==(a=null==o?void 0:o.meta)?void 0:a.category)?[o.meta.category]:[],tags:(null==(r=null==o?void 0:o.meta)?void 0:r.tags)||[]}}):ae.value.map(e=>({...e,guid:e.guid||crypto.randomUUID()})),e=e.filter(e=>{if(oe.value){const t=oe.value.toLowerCase();if(!e.label.toLowerCase().includes(t))return!1}return!(q.value.length>0&&(!e.categories||!q.value.some(t=>e.categories.includes(t))))&&!(H.value.length>0&&(!e.tags||!H.value.some(t=>e.tags.includes(t))))}),e});function ce(){le.value=!0}function de(){le.value=!1}async function ue(){var e;if(a.categoryCollection)try{const t=await r.get(`/items/${a.categoryCollection}`);p.value=(null==(e=t.data)?void 0:e.data)||[]}catch(e){console.warn("Error fetching categories:",e)}}async function se(){var e;if(a.tagCollection)try{const t=await r.get(`/items/${a.tagCollection}`);I.value=(null==(e=t.data)?void 0:e.data)||[]}catch(e){console.warn("Error fetching tags:",e)}}function ve(){q.value=[],H.value=[],oe.value=""}function fe(e){return e?`/assets/${e}?quality=80`:null}const me=c(null),pe=function(){const e=c([]);return e.value.set=t=>{t&&e.value.push(t)},m(()=>{e.value.length=0}),e}(),he=u(()=>ie.value.map((e,t)=>t)),{state:ge,next:be,prev:ye,go:xe}=P(he,{initialValue:0});function we(e){g(()=>{const t=pe.value[e];if(null==t?void 0:t.$el){const e=t.$el,n=null==e?void 0:e.querySelector("button");null==n||n.focus()}})}const ke={target:me,passive:!1};return D(["ArrowDown","ArrowRight"],e=>{e.preventDefault(),be(),we(ge.value)},ke),D(["ArrowUp","ArrowLeft"],e=>{e.preventDefault(),ye(),we(ge.value)},ke),D("Home",e=>{e.preventDefault(),xe(0),we(ge.value)},ke),D("End",e=>{e.preventDefault();const t=he.value.length-1;t>=0&&(xe(t),we(ge.value))},ke),d(he,e=>{(!e.includes(ge.value)&&e.length>0||0===e.length)&&xe(0)},{flush:"post"}),z(me,"focus",e=>{var t;!(null==(t=me.value)?void 0:t.contains(e.relatedTarget))&&he.value.length>0&&we(ge.value)}),h(async()=>{(a.categoryCollection||a.tagCollection)&&(await ue(),await se())}),(e,t)=>{const n=b("v-notice"),r=b("v-divider"),o=b("v-icon"),l=b("v-button"),c=b("v-card-title"),d=b("v-input"),u=b("v-text-overflow"),s=b("v-card"),v=b("v-card-text"),m=b("v-dialog");return y(),x(w,null,[k("div",{ref_key:"el",ref:i},[f(O)?B("v-if",!0):(y(),C(n,{key:0,type:"warning",icon:"vertical_align_"+("above"===e.target?"top":"bottom")},{default:_(()=>[A(" No Builder (M2A) field found "+S(e.target)+" this field! ",1)]),_:1},8,["icon"]))],512),f(O)?(y(),C(M,{key:0,to:f(O)},[f(ae).length>0?(y(),x("div",R,[f(U)?(y(),C(r,{key:0,"inline-title":"",class:"label"},{default:_(()=>[A(S(f(U)),1)]),_:1})):B("v-if",!0),B(" Button to open modal "),V(l,{secondary:"","full-width":"",class:"open-modal-btn",onClick:ce},{default:_(()=>[V(o,{name:"add"}),t[3]||(t[3]=A(" Create New "))]),_:1})])):B("v-if",!0)],8,["to"])):B("v-if",!0),B(" Modal Implementation "),V(m,{modelValue:le.value,"onUpdate:modelValue":t[2]||(t[2]=e=>le.value=e)},{default:_(()=>[k("div",j,[V(s,{class:"modal-card"},{default:_(()=>[V(c,{class:"modal-header"},{default:_(()=>[k("h1",L,S(f(U)),1),V(l,{secondary:!0,icon:!0,rounded:!0,type:"div"},{default:_(()=>[V(o,{name:"close",onClick:de})]),_:1})]),_:1}),V(v,{class:"modal-content"},{default:_(()=>{var e;return[a.enableSearch?(y(),C(d,{key:0,modelValue:oe.value,"onUpdate:modelValue":t[0]||(t[0]=e=>oe.value=e),placeholder:a.searchPlaceholder,class:"modal-search"},{prepend:_(()=>[V(o,{name:"search"})]),_:1},8,["modelValue","placeholder"])):B("v-if",!0),k("div",N,[B(" Category Filter Chips "),(null==(e=p.value)?void 0:e.length)>0?(y(),x("div",Z,[t[4]||(t[4]=k("div",{class:"filter-label"},"Categories:",-1)),k("div",G,[k("div",K,[B(" All button (active when selectedCategories array is empty) "),k("button",{class:$([{active:0===q.value.length},"custom-chip"]),onClick:ve}," All ",2),(y(!0),x(w,null,E(p.value,(e,t)=>(y(),x("button",{key:e.id||t,class:$([{active:q.value.includes(e.id)},"custom-chip"]),onClick:t=>function(e){const t=q.value.indexOf(e);t>-1?q.value.splice(t,1):q.value.push(e)}(e.id)},S(e.title),11,W))),128))])])])):B("v-if",!0),B(" Tag Filter Chips "),I.value.length>0?(y(),x("div",Y,[t[5]||(t[5]=k("div",{class:"filter-label"},"Tags:",-1)),k("div",J,[k("div",Q,[B(" All button (active when selectedTags array is empty) "),k("button",{class:$([{active:0===H.value.length},"custom-chip"]),onClick:ve}," All ",2),(y(!0),x(w,null,E(I.value,(e,t)=>(y(),x("button",{key:e.id||t,class:$([{active:H.value.includes(e.id)},"custom-chip"]),onClick:t=>function(e){const t=H.value.indexOf(e);t>-1?H.value.splice(t,1):H.value.push(e)}(e.id)},S(e.title),11,X))),128))])])])):B("v-if",!0),B(" Clear Filters Button "),q.value.length>0||H.value.length>0||oe.value?(y(),x("div",ee,[V(l,{secondary:"",small:"",onClick:ve},{default:_(()=>[V(o,{name:"clear"}),t[6]||(t[6]=A(" Clear All Filters "))]),_:1})])):B("v-if",!0)]),k("div",{ref_key:"gridRef",ref:me,class:"modal-grid",tabindex:"0"},[(y(!0),x(w,null,E(ie.value,(e,n)=>(y(),C(s,{key:e.guid||e.label,ref_for:!0,ref:f(pe).set,tabindex:n===f(ge)?0:-1,class:"collection-button",onClick:t=>{f(re)(e.guid),de()},onKeydown:[F(T(t=>{f(re)(e.guid),de()},["prevent"]),["enter"]),F(T(t=>{f(re)(e.guid),de()},["prevent"]),["space"])]},{default:_(()=>[B(" Collection Image or Icon "),k("div",te,[e.collectionBanner&&fe(e.collectionBanner)?(y(),x("img",{key:0,src:fe(e.collectionBanner),alt:e.label,class:"collection-image",onError:t[1]||(t[1]=e=>e.target.style.display="none")},null,40,ne)):(y(),C(o,{key:1,name:e.icon,class:"collection-icon"},null,8,["name"]))]),V(c,{class:"collection-title"},{default:_(()=>[V(u,{text:e.label,size:"small"},null,8,["text"])]),_:2},1024)]),_:2},1032,["tabindex","onClick","onKeydown"]))),128))],512)]}),_:1})]),_:1})])]),_:1},8,["modelValue"])],64)}}}),re=[],oe=[];!function(e,t){if(e&&"undefined"!=typeof document){var n,a=!0===t.prepend?"prepend":"append",r=!0===t.singleTag,o="string"==typeof t.container?document.querySelector(t.container):document.getElementsByTagName("head")[0];if(r){var l=re.indexOf(o);-1===l&&(l=re.push(o)-1,oe[l]={}),n=oe[l]&&oe[l][a]?oe[l][a]:oe[l][a]=i()}else n=i();65279===e.charCodeAt(0)&&(e=e.substring(1)),n.styleSheet?n.styleSheet.cssText+=e:n.appendChild(document.createTextNode(e))}function i(){var e=document.createElement("style");if(e.setAttribute("type","text/css"),t.attributes)for(var n=Object.keys(t.attributes),r=0;r<n.length;r++)e.setAttribute(n[r],t.attributes[n[r]]);var l="prepend"===a?"afterbegin":"beforeend";return o.insertAdjacentElement(l,e),e}}("\n.m2a-builder:has(.btn-matrix) .actions {\r\n\tmargin-top: 0px;\n}\n.m2a-builder:has(.btn-matrix) .actions:has(.v-menu + .v-menu) {\r\n\tmargin-top: 8px;\n}\n.btn-matrix[data-v-8379f505] {\r\n\tmargin-top: 8px;\r\n\tcontainer-type: inline-size;\n}\n.label[data-v-8379f505] {\r\n\tmargin-bottom: 8px;\n}\n.open-modal-btn[data-v-8379f505] {\r\n\tmargin-bottom: 12px;\r\n\t--v-button-height: 48px;\n}\n.open-modal-btn[data-v-8379f505] .content {\r\n\tgap: 8px;\r\n\tflex-direction: row;\r\n\t--v-icon-color: var(--theme--foreground-subdued);\n}\n.open-modal-btn[data-v-8379f505]:hover .content {\r\n\t--v-icon-color: var(--theme--primary);\n}\n.v-text-overflow[data-v-8379f505] {\r\n\twidth: 100%;\n}\n.v-divider[data-v-8379f505] .type-text {\r\n\tcolor: var(--theme--foreground-subdued);\n}\r\n\r\n/* Modal Styles */\n.collection-modal[data-v-8379f505] .modal-card {\r\n\twidth: 90vw;\r\n\tmargin: 0 auto;\r\n\tmax-width: 100rem;\n}\n.modal-card[data-v-8379f505] {\r\n\tbackground: var(--theme--background);\r\n\tborder-radius: var(--theme--border-radius);\r\n\tbox-shadow: 0px 4px 12px rgba(38, 50, 56, 0.1), 0px 0px 0px 1px var(--theme--border-color-subdued);\r\n\toverflow: hidden;\n}\n.modal-header[data-v-8379f505] {\r\n\tdisplay: flex;\r\n\talign-items: center;\r\n\tjustify-content: space-between;\r\n\tpadding: 12px 16px;\r\n\tbackground: var(--theme--background);\r\n\tborder-bottom: var(--theme--border-width) solid var(--theme--border-color-subdued);\r\n\tmin-height: 48px;\n}\n.modal-title[data-v-8379f505] {\r\n\tcolor: var(--theme--foreground);\r\n\tfont-weight: 600;\r\n\tfont-size: 16px;\r\n\tfont-family: var(--theme--fonts--display--font-family);\r\n\tmargin: 0;\r\n\tline-height: 24px;\n}\n.modal-close[data-v-8379f505] {\r\n\t--v-icon-color: var(--theme--foreground-subdued);\r\n\tcursor: pointer;\r\n\ttransition: color var(--fast) var(--transition);\r\n\tpadding: 4px;\r\n\tmargin: -4px;\n}\n.modal-close[data-v-8379f505]:hover {\r\n\t--v-icon-color: var(--theme--foreground);\n}\n.modal-content[data-v-8379f505] {\r\n\tpadding: 24px;\r\n\tbackground: var(--theme--background);\r\n\tmax-height: 60vh;\r\n\toverflow-y: auto;\n}\n.modal-search[data-v-8379f505] {\r\n\tmargin-bottom: 20px;\n}\n.modal-search[data-v-8379f505] .v-input {\r\n\t--input-background-color: var(--theme--background-subdued);\r\n\t--input-border-color: var(--theme--border-color);\n}\r\n\r\n/* Filter Sections */\n.filter-section[data-v-8379f505] {\r\n\tmargin-bottom: 20px;\n}\n.filter-label[data-v-8379f505] {\r\n\tfont-size: 14px;\r\n\tfont-weight: 500;\r\n\tcolor: var(--theme--foreground);\r\n\tmargin-bottom: 8px;\n}\n.filter-chips-container[data-v-8379f505] {\r\n\toverflow: auto;\n}\n.filter-chips[data-v-8379f505] {\r\n\tdisplay: flex;\r\n\tgap: 8px;\r\n\twidth: max-content;\n}\n.filter-chip[data-v-8379f505] {\r\n\t--v-chip-color: var(--theme--foreground-subdued);\r\n\t--v-chip-background-color: var(--theme--background-subdued);\r\n\t--v-chip-color-active: var(--theme--primary-foreground);\r\n\t--v-chip-background-color-active: var(--theme--primary);\r\n\tborder: 1px solid var(--theme--border-color);\r\n\ttransition: all var(--fast) var(--transition);\n}\n.filter-chip[data-v-8379f505]:hover {\r\n\t--v-chip-color: var(--theme--primary);\r\n\tborder-color: var(--theme--primary);\n}\n.filter-chip[active][data-v-8379f505] {\r\n\tborder-color: var(--theme--primary);\n}\r\n\r\n/* Custom Chip Styles */\n.custom-chip[data-v-8379f505] {\r\n\tdisplay: inline-flex;\r\n\talign-items: center;\r\n\theight: 32px;\r\n\tpadding: 0 12px;\r\n\tcolor: var(--theme--foreground-subdued);\r\n\tfont-weight: var(--weight-normal);\r\n\tfont-size: 14px;\r\n\tline-height: 22px;\r\n\tbackground-color: var(--theme--background-subdued);\r\n\tborder: var(--theme--border-width) solid var(--theme--border-color);\r\n\tborder-radius: 16px;\r\n\tcursor: pointer;\r\n\ttransition: all var(--fast) var(--transition);\n}\n.custom-chip[data-v-8379f505]:hover {\r\n\tcolor: var(--theme--primary);\r\n\tborder-color: var(--theme--primary);\r\n\tbackground-color: var(--theme--background-accent);\n}\n.custom-chip.active[data-v-8379f505] {\r\n\tcolor: var(--foreground-inverted);\r\n\tbackground-color: var(--theme--primary);\r\n\tborder-color: var(--theme--primary);\n}\n.custom-chip.active[data-v-8379f505]:hover {\r\n\tbackground-color: var(--theme--primary-accent);\r\n\tborder-color: var(--theme--primary-accent);\n}\n.modal-grid[data-v-8379f505] {\r\n\tdisplay: grid;\r\n\tgrid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));\r\n\tgap: 16px;\n}\n.modal-grid .collection-button[data-v-8379f505] {\r\n\tmax-width: 50rem;\n}\n.collection-button[data-v-8379f505] {\r\n\t--v-button-background-color: var(--theme--background-subdued);\r\n\t--v-button-background-color-hover: var(--theme--background-accent);\r\n\t--v-button-color: var(--theme--foreground);\r\n\t--v-button-color-hover: var(--theme--foreground);\r\n\tborder: var(--theme--border-width) solid var(--theme--border-color);\r\n\tborder-radius: var(--theme--border-radius);\r\n\ttransition: all var(--fast) var(--transition);\r\n\tcursor: pointer;\r\n\tmin-width: unset;\n}\n.collection-button[data-v-8379f505]:hover {\r\n\tborder-color: var(--theme--primary);\r\n\ttransform: translateY(-1px);\r\n\tbox-shadow: 0px 2px 8px rgba(38, 50, 56, 0.1);\n}\n.collection-button[data-v-8379f505] .content {\r\n\tpadding: 16px 12px;\r\n\tgap: 12px;\r\n\tflex-direction: column;\r\n\talign-items: center;\n}\n.collection-visual[data-v-8379f505] {\r\n\twidth: 100%;\r\n\theight: 10rem;\r\n\tdisplay: flex;\r\n\talign-items: center;\r\n\tjustify-content: center;\r\n\tborder-radius: var(--theme--border-radius);\r\n\toverflow: hidden;\r\n\tbackground: var(--theme--background-accent);\n}\n.collection-image[data-v-8379f505] {\r\n\tborder-radius: var(--theme--border-radius);\r\n\tmax-height: 100%;\r\n\tmin-height: 100%;\r\n\ttransition: all var(--fast) var(--transition);\n}\n.collection-button:hover .collection-image[data-v-8379f505] {\r\n\tmin-height: 0;\r\n\tmax-width: 100%;\n}\n.collection-icon[data-v-8379f505] {\r\n\t--v-icon-color: var(--theme--foreground-subdued);\r\n\tfont-size: 24px;\n}\n.collection-button:hover .collection-icon[data-v-8379f505] {\r\n\t--v-icon-color: var(--theme--primary);\n}\n.collection-title[data-v-8379f505] {\r\n\ttext-align: center;\r\n\tpadding: 0;\r\n\tfont-size: 13px;\r\n\tline-height: 2;\r\n\tcolor: var(--theme--foreground);\r\n\tfont-weight: 500;\r\n\tmargin: 1rem 0;\n}\n.collection-title[data-v-8379f505] .v-text-overflow {\r\n\tdisplay: -webkit-box;\r\n\t-webkit-box-orient: vertical;\r\n\t-webkit-line-clamp: 1;\r\n\tline-clamp: 1;\r\n\twhite-space: unset;\n}\n@media (min-width: 600px) {\n.modal-grid[data-v-8379f505] {\r\n\t\tgrid-template-columns: repeat(auto-fill, minmax(25rem, 1fr));\r\n\t\tgap: 20px;\n}\n.collection-visual[data-v-8379f505] {\r\n\t\theight: 12rem;\n}\n}\n@media (min-width: 768px) {\n.modal-grid[data-v-8379f505] {\r\n\t\tgrid-template-columns: repeat(auto-fill, minmax(30rem, 1fr));\n}\n.modal-content[data-v-8379f505] {\r\n\t\tpadding: 32px;\n}\n.collection-visual[data-v-8379f505] {\r\n\t\theight: 15rem;\n}\n}\n@media screen and (min-width: 1024px) {\n.filters[data-v-8379f505] {\r\n\t\tdisplay: flex;\r\n\t\tgap: 24px;\r\n\t\tflex-wrap: wrap;\r\n\t\talign-items: end;\r\n\t\tmargin-bottom: 32px;\n}\n.filter-section[data-v-8379f505] {\r\n\t\tmargin-bottom: 0;\n}\n}\r\n",{});var le=n({id:"srt-labs-experimental-m2a-interface",name:"Builder (M2A) Button Matrix",icon:"grid_view",description:"Add a matrix button selector to the built-in M2A interface",component:((e,t)=>{const n=e.__vccOpts||e;for(const[e,a]of t)n[e]=a;return n})(ae,[["__scopeId","data-v-8379f505"],["__file","interface.vue"]]),types:["alias"],localTypes:["presentation"],group:"presentation",options:[{field:"target",name:"Target Builder (M2A) field placement",type:"string",meta:{width:"full",interface:"select-dropdown",options:{choices:[{text:"Above this field",value:"above",icon:"vertical_align_top"},{text:"Below this field",value:"below",icon:"vertical_align_bottom"}]}},schema:{default_value:"below"}},{field:"info",type:"alias",meta:{width:"full",interface:"presentation-notice",conditions:[{rule:{_and:[{target:{_eq:"below"}}]},options:{text:ie({targetPlacedBelow:!0})}}],options:{icon:!1,text:ie({targetPlacedBelow:!1})}}},{field:"enableSearch",name:"Enable Search",type:"boolean",meta:{width:"half",interface:"boolean"},schema:{default_value:!1}},{field:"searchPlaceholder",name:"Search Placeholder",type:"string",meta:{width:"half",interface:"input",hidden:!0,conditions:[{rule:{enableSearch:{_eq:!0}},hidden:!1}]},schema:{default_value:"Search..."}},{field:"categoryCollection",name:"Category Collection",type:"string",meta:{width:"half",interface:"system-collection",note:"Collection that contains category items"}},{field:"categoryRelationField",name:"Category Relation Field",type:"string",meta:{width:"half",interface:"input",note:"Field name in target collections that relates to categories",hidden:!0,conditions:[{rule:{categoryCollection:{_nnull:!0}},hidden:!1}]}},{field:"tagCollection",name:"Tag Collection",type:"string",meta:{width:"half",interface:"system-collection",note:"Collection that contains tag items"}},{field:"tagRelationField",name:"Tag Relation Field",type:"string",meta:{width:"half",interface:"input",note:"Field name in target collections that relates to tags",hidden:!0,conditions:[{rule:{tagCollection:{_nnull:!0}},hidden:!1}]}}]});function ie({targetPlacedBelow:e}){return`${`<svg style="vertical-align:middle" width="120" height="50" viewBox="0 0 120 50" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M114 1H6C3.23858 1 1 3.23858 1 6V16C1 18.7614 3.23858 21 6 21H114C116.761 21 119 18.7614 119 16V6C119 3.23858 116.761 1 114 1Z" stroke="var(--theme--primary)" stroke-opacity="${e?"1":"0.25"}" stroke-width="2"/><path d="M114 29H6C3.23858 29 1 31.2386 1 34V44C1 46.7614 3.23858 49 6 49H114C116.761 49 119 46.7614 119 44V34C119 31.2386 116.761 29 114 29Z" stroke="var(--theme--primary)" stroke-opacity="${e?"0.25":"1"}" stroke-width="2"/><path opacity="${e?"0.5":"1"}" d="M20 37H10V38.2691H20V37ZM10 40.7778H20V39.5087H10V40.7778Z" fill="var(--theme--primary)"/><path opacity="${e?"1":"0.5"}" d="M20 9H10V10.2691H20V9ZM10 12.7778H20V11.5087H10V12.7778Z" fill="var(--theme--primary)"/><text opacity="${e?"1":"0.5"}" fill="var(--theme--primary)" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="10" font-weight="500" letter-spacing="0em"><tspan x="28" y="14.6364">${e?"Button Matrix":"Builder (M2A)"}</tspan></text><text opacity="${e?"0.5":"1"}" fill="var(--theme--primary)" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="10" font-weight="500" letter-spacing="0em"><tspan x="28" y="42.6364">${e?"Builder (M2A)":"Button Matrix"}</tspan></text></svg>`}${`<span style="padding-left: 12px">Place this field directly ${e?"above":"below"} the Builder (M2A) field!</span>`}`}export{le as default};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@veribir/m2a-interface",
3
3
  "type": "module",
4
- "version": "0.0.3",
4
+ "version": "0.0.5",
5
5
  "description": "This Directus extension transforms the standard Many-to-Any (M2A) Builder dropdown into an intuitive visual modal with card-based collection selection. Users can quickly filter collections using category and tag chips, search by name, and navigate with keyboard shortcuts. The responsive grid layout displays collection icons and banners, making it easy to find the right content type in large Directus projects with many available collections.",
6
6
  "author": "Veribir",
7
7
  "license": "Proprietary",
@@ -35,12 +35,12 @@
35
35
  "link": "directus-extension link",
36
36
  "validate": "directus-extension validate"
37
37
  },
38
- "dependencies": {
39
- "@vueuse/core": "^13.1.0"
40
- },
41
38
  "devDependencies": {
42
- "@directus/extensions-sdk": "13.0.4",
43
- "typescript": "^5.8.3",
44
- "vue": "3.5.13"
39
+ "@directus/extensions-sdk": "^17.0.4",
40
+ "typescript": "^5.9.3",
41
+ "vue": "^3.5.26"
42
+ },
43
+ "dependencies": {
44
+ "@vueuse/core": "^14.1.0"
45
45
  }
46
46
  }