{"id":30718173,"url":"https://github.com/smartlabsat/directus-expandable-blocks","last_synced_at":"2025-09-03T09:10:40.492Z","repository":{"id":304234987,"uuid":"1018198819","full_name":"smartlabsAT/directus-expandable-blocks","owner":"smartlabsAT","description":"Advanced M2A interface for Directus with inline expandable editing, drag \u0026 drop sorting, and native save integration - no custom API calls needed","archived":false,"fork":false,"pushed_at":"2025-08-31T12:55:27.000Z","size":1813,"stargazers_count":17,"open_issues_count":12,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-31T12:58:47.874Z","etag":null,"topics":["block-editor","cms","content-blocks","content-management","directus","directus-extension","directus-interface","drag-and-drop","inline-editing","m2a","typescript","vue3","vuedraggable"],"latest_commit_sha":null,"homepage":"https://github.com/smartlabsAT/directus-expandable-blocks","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/smartlabsAT.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-11T19:29:02.000Z","updated_at":"2025-08-31T12:49:27.000Z","dependencies_parsed_at":"2025-08-02T23:39:54.007Z","dependency_job_id":null,"html_url":"https://github.com/smartlabsAT/directus-expandable-blocks","commit_stats":null,"previous_names":["smartlabsat/directus-expandable-blocks"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/smartlabsAT/directus-expandable-blocks","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartlabsAT%2Fdirectus-expandable-blocks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartlabsAT%2Fdirectus-expandable-blocks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartlabsAT%2Fdirectus-expandable-blocks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartlabsAT%2Fdirectus-expandable-blocks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smartlabsAT","download_url":"https://codeload.github.com/smartlabsAT/directus-expandable-blocks/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartlabsAT%2Fdirectus-expandable-blocks/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273418386,"owners_count":25102060,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-03T02:00:09.631Z","response_time":76,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["block-editor","cms","content-blocks","content-management","directus","directus-extension","directus-interface","drag-and-drop","inline-editing","m2a","typescript","vue3","vuedraggable"],"created_at":"2025-09-03T09:10:36.164Z","updated_at":"2025-09-03T09:10:40.477Z","avatar_url":"https://github.com/smartlabsAT.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Directus Expandable Blocks Interface\n\n[![npm version](https://img.shields.io/npm/v/directus-extension-expandable-blocks?style=flat-square\u0026color=blue)](https://www.npmjs.com/package/directus-extension-expandable-blocks)\n[![npm downloads](https://img.shields.io/npm/dm/directus-extension-expandable-blocks?style=flat-square)](https://www.npmjs.com/package/directus-extension-expandable-blocks)\n[![GitHub release](https://img.shields.io/github/release/smartlabsAT/directus-expandable-blocks?style=flat-square)](https://github.com/smartlabsAT/directus-expandable-blocks/releases)\n[![license](https://img.shields.io/npm/l/directus-extension-expandable-blocks?style=flat-square)](https://github.com/smartlabsAT/directus-expandable-blocks/blob/master/LICENSE)\n[![Directus 11+](https://img.shields.io/badge/Directus-11%2B-64f?style=flat-square\u0026logo=directus)](https://directus.io)\n[![Tests](https://img.shields.io/badge/tests-470%20passing-success?style=flat-square)](https://github.com/smartlabsAT/directus-expandable-blocks)\n[![TypeScript](https://img.shields.io/badge/TypeScript-strict-blue?style=flat-square\u0026logo=typescript)](https://www.typescriptlang.org/)\n\nA powerful, production-ready M2A (Many-to-Any) interface extension for Directus with inline expandable editing, advanced item selection, comprehensive permissions, and seamless integration with Directus' native save system. **Also provides reusable ItemSelector components for other extensions.**\n\n![Directus Expandable Blocks Extension - Feature Presentation](https://raw.githubusercontent.com/wiki/smartlabsAT/directus-expandable-blocks/assets/demo.gif)\n\n[📚 Documentation](https://github.com/smartlabsAT/directus-expandable-blocks/wiki) • \n[🐛 Report Bug](https://github.com/smartlabsAT/directus-expandable-blocks/issues/new?template=bug_report.md) • \n[✨ Request Feature](https://github.com/smartlabsAT/directus-expandable-blocks/issues/new?template=feature_request.md) • \n[📦 NPM Package](https://www.npmjs.com/package/directus-extension-expandable-blocks)\n\n## 📖 Table of Contents\n\n- [Why Expandable Blocks?](#-why-expandable-blocks)\n- [Features](#-features)\n- [Installation](#-installation)\n- [Usage](#-usage)\n- [Configuration](#️-configuration)\n- [Shared Components](#-shared-components-for-other-extensions)\n- [Testing](#-testing)\n- [Development](#-development)\n- [Documentation](#-documentation)\n- [Contributing](#-contributing)\n- [License](#-license)\n\n## 🎯 Why Expandable Blocks?\n\nUnlike other block editors, this extension **works directly with Directus' native form system** and provides **unique killer features**:\n\n### 🚀 Killer Features\n- 🔍 **Reference Tracking** - See EVERYWHERE an item is used across your entire system\n- 🔗 **Link or Copy** - Choose to reference existing items or create independent copies\n- ⚠️ **Usage Protection** - Never accidentally delete content that's used elsewhere\n\n### ✅ Native Integration\n- **Native Save \u0026 Stay** - Works perfectly with Directus' save options\n- **Global Discard** - Integrates with Directus' \"Discard Changes\" button\n- **Proper Dirty State** - Save button only appears when changes exist\n- **No Data Loss** - All changes tracked through Directus' form state\n- **Enterprise Ready** - Production-tested with comprehensive permissions\n- **100% Test Coverage** - 470 unit tests ensuring reliability\n\n## ✨ Features\n\n### 🎨 Core Interface Features\n\n#### **Block Management**\n- 📝 **Inline Expandable Editing** - Edit content without opening separate forms\n- 🎯 **Drag \u0026 Drop Sorting** - Intuitive block reordering with visual feedback\n- 🆕 **Visual NEW Indicator** - See unsaved blocks at a glance\n- 📊 **Status Management** - Quick status changes with color-coded indicators\n- 📋 **Duplicate Blocks** - Clone existing blocks with one click\n- 🗑️ **Smart Delete** - Unlink or permanently delete with confirmation\n- 🔄 **Discard Changes** - Revert individual blocks to original state\n\n#### **Item Selection \u0026 Search**\n- 🔍 **Advanced Item Selector** - Select and link existing items from any collection\n- 🔗 **Link or Copy Mode** - Choose to reference existing items or create copies\n- 📊 **Table View** - Browse items in a sortable, filterable table\n- 🏷️ **Tag-Based Search** - Search with AND/OR operators and field-specific queries\n- 🎯 **Smart Search** - Simple search mode with optional advanced tag search\n- 🔎 **Search Highlighting** - See matching terms highlighted in results\n- 📌 **Search History** - Remember and reuse previous searches\n- 📈 **Result Count** - See number of matching items instantly\n\n#### **Table Features**\n- 📊 **Intelligent Columns** - Auto-sizing based on field types\n- 📌 **Sticky Columns** - Keep important columns visible while scrolling\n- ↕️ **Sortable Headers** - Sort by any field with 3-click cycle\n- 🎨 **Field Display** - Smart rendering for all Directus field types\n- 🖼️ **Image Preview** - Hover to see full images\n- 📝 **WYSIWYG Support** - Automatic HTML stripping for clean display\n- ⚡ **Virtual Scrolling** - Handle thousands of items efficiently\n\n### 🌍 Advanced Features\n\n#### **Translation Support**\n- 🌐 **Multi-Language** - Full support for Directus translations\n- 🔄 **Language Switching** - Change languages on the fly\n- 🔍 **Translation Search** - Search across all language versions\n- 🏷️ **Language Indicators** - See which fields are translatable\n\n#### **Permissions \u0026 Security**\n- 🔐 **Directus Permissions** - Respects all native permissions\n- 👥 **Role-Based Control** - Configure per-role access\n- 🔒 **Read-Only Mode** - Automatic for restricted items\n- ⚠️ **Permission Indicators** - Visual feedback for restricted actions\n- 🛡️ **Security** - Built-in validation and permission checks\n\n#### **Usage Tracking \u0026 References** 🚀 *(Requires API Extension)*\n- 🔍 **Reference Detection** - Instantly see ALL places where an item is used across your entire Directus instance\n- 📍 **Cross-Collection References** - Track usage across different collections and relationships\n- 🔗 **Deep Links** - Navigate directly to parent items with one click\n- ⚠️ **Usage Warnings** - Get alerts before deleting items that are referenced elsewhere\n- 📊 **Usage Paths** - Visual breadcrumbs showing complete relationship chains\n- 🎯 **Smart Prevention** - Prevents accidental deletion of referenced content\n\n\u003e **Note:** These features require the optional [API extension](https://www.npmjs.com/package/directus-extension-expandable-blocks-api) to be installed.\n\n#### **Inline Editing**\n- ✏️ **Edit Drawer** - Edit items without leaving the interface\n- 💾 **Independent Saves** - Save edits without affecting main form\n- 🔄 **Live Updates** - See changes reflected immediately\n- 📐 **Adjustable Width** - Resize drawer to your preference\n\n### ⚡ Performance \u0026 Quality\n\n#### **Performance**\n- 🚀 **Multi-Layer Caching** - Configurable TTLs for optimal speed\n- 📊 **Smart Loading** - Load only what's needed\n- 🔄 **Debounced Operations** - Prevent excessive API calls\n- ⚡ **Optimized Re-renders** - Using Vue 3's advanced features\n- 💾 **Persistent Preferences** - Remember user settings\n\n#### **Code Quality**\n- ✅ **100% Test Coverage** - 470 passing unit tests\n- 🎯 **TypeScript Strict Mode** - Zero type errors\n- 📏 **ESLint Compliant** - Zero linting errors\n- 🏗️ **Modular Architecture** - 15+ reusable components\n- 📚 **Comprehensive Docs** - Wiki, API docs, and inline comments\n\n### 🛠️ Developer Features\n\n#### **Extension Architecture**\n- 📦 **Interface Extension** - Clean, focused interface implementation\n- 🔌 **Composable Architecture** - Reusable Vue composables\n- 🎨 **Component Library** - Modular, tested components\n- 🔧 **Utility Functions** - Shared helpers and validators\n- 📝 **TypeScript Types** - Full type definitions\n\n\n## 📦 Installation\n\n### Via NPM (Recommended)\n\n```bash\n# Install the interface extension\nnpm install directus-extension-expandable-blocks\n\n# Optional: Install the API extension for advanced usage tracking\nnpm install directus-extension-expandable-blocks-api\n```\n\n### Via pnpm\n\n```bash\n# Install the interface extension\npnpm add directus-extension-expandable-blocks\n\n# Optional: Install the API extension for advanced usage tracking\npnpm add directus-extension-expandable-blocks-api\n```\n\n### Manual Installation\n\n1. Download the latest release from [GitHub Releases](https://github.com/smartlabsAT/directus-expandable-blocks/releases)\n2. Extract to your Directus `extensions/` directory\n3. Restart Directus\n4. **Optional**: Install the [API extension](https://github.com/smartlabsAT/directus-expandable-blocks-api) for usage tracking\n\n### Docker Installation\n\n```dockerfile\n# Install the interface extension\nRUN npm install directus-extension-expandable-blocks\n\n# Optional: Install the API extension for advanced usage tracking\nRUN npm install directus-extension-expandable-blocks-api\n```\n\n### 📝 Important Note About the API Extension\n\n**The API extension is now a separate, optional package.** The core Expandable Blocks interface works perfectly without it, using Directus' native API for all standard operations.\n\n#### When to install the API extension:\n- ✅ You want to see where items are used before deleting them\n- ✅ You need to track references across M2A relationships\n- ✅ You want protection against accidentally deleting referenced content\n\n#### The interface works without the API extension:\n- ✅ All core features (editing, sorting, adding blocks) work normally\n- ✅ Uses native Directus API for all operations\n- ⚠️ Cannot verify item usage before deletion (shows warning instead)\n\n## 🚀 Usage\n\n### Basic Setup\n\n#### 1️⃣ Create an M2A Field\n\n1. Navigate to **Settings → Data Model → [Your Collection]**\n2. Click **\"Create Field\"**\n3. Choose **\"Many to Any Relationship (M2A)\"**\n4. Configure the relationship\n\n#### 2️⃣ Select the Expandable Blocks Interface\n\n1. In the field configuration, go to **\"Interface\"** tab\n2. Select **\"Expandable Blocks\"** from the dropdown\n3. Configure your options\n\n#### 3️⃣ Configure Options\n\nThe interface provides extensive configuration grouped into logical sections:\n\n- **Display Options** - Visual preferences\n- **Permissions \u0026 Actions** - What users can do\n- **Collections \u0026 Relations** - Available collections\n- **Advanced Settings** - Caching, translations, etc.\n\n## ⚙️ Configuration\n\n### Display Settings\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `enableSorting` | boolean | `true` | Enable drag \u0026 drop reordering |\n| `showItemId` | boolean | `true` | Display item IDs |\n| `showCollectionName` | boolean | `true` | Show collection type |\n| `startExpanded` | boolean | `false` | Start with blocks expanded |\n| `accordionMode` | boolean | `false` | One block open at a time |\n| `compactMode` | boolean | `false` | Condensed view |\n\n### Permissions\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `isAllowedDelete` | boolean | `true` | Allow deletion |\n| `isAllowedDuplicate` | boolean | `true` | Allow duplication |\n| `allowLinkExisting` | boolean | `true` | Allow linking existing |\n| `allowDuplicateExisting` | boolean | `true` | Allow duplicating linked |\n| `maxBlocks` | number | `null` | Maximum blocks allowed |\n\n### Collections\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `collection` | array | `[]` | Collections for new blocks |\n| `allowedCollectionsExisting` | array | `[]` | Collections for existing items |\n\n### Advanced\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `enableCache` | boolean | `true` | Enable API caching |\n| `enableTranslations` | boolean | `true` | Support translations |\n| `showUsageWarnings` | boolean | `true` | Show usage indicators |\n\n### Environment Variables\n\nConfigure caching behavior:\n\n```bash\n# Cache TTL Settings (in minutes)\nEXPANDABLE_BLOCKS_CACHE_TTL_METADATA=30\nEXPANDABLE_BLOCKS_CACHE_TTL_SEARCH=5\nEXPANDABLE_BLOCKS_CACHE_TTL_DETAIL=10\nEXPANDABLE_BLOCKS_CACHE_TTL_PATHS=10\n\n# Maximum cache size\nEXPANDABLE_BLOCKS_CACHE_MAX_SIZE=50000\n```\n\n## 🔗 Shared Components for Other Extensions\n\nThis extension provides **reusable ItemSelector components** that can be used in other Directus extensions, allowing you to avoid code duplication and maintain consistent UX across extensions.\n\n### Quick Start for Extension Developers\n\n```bash\n# Add as dependency to your extension\nnpm install directus-extension-expandable-blocks\n```\n\n```typescript\n// Import shared components in your extension\nimport { \n  useItemSelector, \n  ItemSelectorDrawer,\n  type ItemSelectorConfig \n} from 'directus-extension-expandable-blocks/shared';\n\n// Configure for your extension\nconst itemSelector = useItemSelector(api, ['pages', 'articles'], {\n  loggerPrefix: '[MyExtension]',\n  allowLink: true,\n  allowDuplicate: false,\n  collectionIcons: {\n    'pages': 'description',\n    'articles': 'article'\n  }\n});\n```\n\n### Available Shared Components\n\n- **`useItemSelector`** - Core composable with all functionality\n- **`ItemSelectorDrawer`** - Main selector interface  \n- **`ItemSearchPanel`** - Advanced search with operators\n- **`FieldDisplay`** - Field value display component\n- **`UsagePopover`** - Shows item usage across collections\n\n### Configuration Options\n\n```typescript\ninterface ItemSelectorConfig {\n  loggerPrefix?: string;           // Custom logging prefix\n  allowLink?: boolean;             // Allow linking items\n  allowDuplicate?: boolean;        // Allow duplicating items  \n  defaultItemsPerPage?: number;    // Pagination size\n  defaultLanguage?: string;        // Translation language\n  collectionIcons?: Record\u003cstring, string\u003e; // Custom icons\n  fieldMappings?: Record\u003cstring, string\u003e;   // Field name mappings\n  debug?: boolean;                 // Enable debug logging\n}\n```\n\n### Full Documentation\n\n📖 **[Complete Shared Components Documentation](SHARED_COMPONENTS.md)** - Detailed usage guide, examples, and API reference for extension developers.\n\n### Example Usage in LayoutBlocks Extension\n\n```vue\n\u003ctemplate\u003e\n  \u003cItemSelectorDrawer\n    :open=\"itemSelector.isOpen.value\"\n    :collection=\"itemSelector.selectedCollection.value\"\n    :items=\"itemSelector.availableItems.value\"\n    :loading=\"itemSelector.loading.value\"\n    :logger-prefix=\"'[LayoutBlocks]'\"\n    @close=\"itemSelector.close\"\n    @confirm=\"handleItemsSelected\"\n  /\u003e\n\u003c/template\u003e\n\n\u003cscript setup\u003e\nimport { useItemSelector, ItemSelectorDrawer } from 'directus-extension-expandable-blocks/shared';\n\nconst itemSelector = useItemSelector(api, ['layouts'], {\n  loggerPrefix: '[LayoutBlocks]',\n  allowDuplicate: false\n});\n\u003c/script\u003e\n```\n\n## 🧪 Testing\n\n```bash\n# Run all tests (100% coverage)\nnpm run test -- --run\n\n# Test with UI\nnpm run test:ui\n\n# Coverage report\nnpm run test:coverage\n\n# Type checking\nnpm run type-check\n\n# Linting\nnpm run lint\n```\n\n### Test Statistics\n- ✅ **470 unit tests** - All passing\n- ✅ **100% coverage** - Full test coverage\n- ✅ **0 TypeScript errors** - Strict mode compliant\n- ✅ **0 ESLint errors** - Clean code\n\n## 📝 Development\n\n```bash\n# Install dependencies (we use pnpm)\npnpm install\n\n# Development mode\nnpm run dev\n\n# Production build\nnpm run build\n\n# Type checking\nnpm run type-check\n\n# Create demo videos\nnpm run demo:product\nnpm run demo:highlights\n```\n\n### Project Structure\n\n```\nexpandable-blocks/\n├── config/           # Configuration files\n│   ├── scripts/      # Build scripts\n│   └── *.config.*    # Various configs\n├── src/\n│   ├── components/   # Vue components\n│   ├── composables/  # Vue composables\n│   ├── types/        # TypeScript types\n│   └── utils/        # Utilities\n├── test/             # Test files\n└── wiki/             # Documentation\n```\n\n## 📚 Documentation\n\n### Wiki Documentation\n\nVisit our **[GitHub Wiki](https://github.com/smartlabsAT/directus-expandable-blocks/wiki)** for:\n\n- 🏠 [Getting Started](https://github.com/smartlabsAT/directus-expandable-blocks/wiki)\n- 📦 [Installation Guide](https://github.com/smartlabsAT/directus-expandable-blocks/wiki/Installation)\n- ⚙️ [Configuration](https://github.com/smartlabsAT/directus-expandable-blocks/wiki/Configuration)\n- 🏗️ [Architecture](https://github.com/smartlabsAT/directus-expandable-blocks/wiki/Architecture-Overview)\n- 🔐 [Security](https://github.com/smartlabsAT/directus-expandable-blocks/wiki/Security)\n- 🚀 [Advanced Features](https://github.com/smartlabsAT/directus-expandable-blocks/wiki/Advanced-Features)\n- 🎬 [Demo Videos](https://github.com/smartlabsAT/directus-expandable-blocks/wiki/Demo-Video-Recording)\n- ⚡ [Cache Configuration](https://github.com/smartlabsAT/directus-expandable-blocks/wiki/Cache-Configuration)\n\n## 🤝 Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](https://github.com/smartlabsAT/directus-expandable-blocks/wiki/Contributing) for details.\n\n## 📄 License\n\nMIT License - see [LICENSE](LICENSE) file for details\n\n## 🙏 Acknowledgments\n\nMade with ❤️ for the Directus community\n\n## 🏆 Stats\n\n- **200+ commits** of continuous improvement\n- **15+ components** for modular architecture\n- **470 tests** ensuring reliability\n- **0 errors** in TypeScript and ESLint\n- **100% coverage** for peace of mind\n\n---\n\n**Ready for production use!** 🚀","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmartlabsat%2Fdirectus-expandable-blocks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmartlabsat%2Fdirectus-expandable-blocks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmartlabsat%2Fdirectus-expandable-blocks/lists"}