{"id":36632514,"url":"https://github.com/eldomagan/alpine-define-component","last_synced_at":"2026-01-12T09:39:59.744Z","repository":{"id":321672973,"uuid":"1086794114","full_name":"eldomagan/alpine-define-component","owner":"eldomagan","description":null,"archived":false,"fork":false,"pushed_at":"2025-10-30T23:20:19.000Z","size":0,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-30T23:29:20.673Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eldomagan.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-30T23:11:56.000Z","updated_at":"2025-10-30T23:20:15.000Z","dependencies_parsed_at":"2025-10-30T23:29:28.988Z","dependency_job_id":"32139111-12f3-42cf-aa49-9d68a084134f","html_url":"https://github.com/eldomagan/alpine-define-component","commit_stats":null,"previous_names":["eldomagan/alpine-define-component"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/eldomagan/alpine-define-component","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eldomagan%2Falpine-define-component","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eldomagan%2Falpine-define-component/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eldomagan%2Falpine-define-component/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eldomagan%2Falpine-define-component/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eldomagan","download_url":"https://codeload.github.com/eldomagan/alpine-define-component/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eldomagan%2Falpine-define-component/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28337740,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T06:09:07.588Z","status":"ssl_error","status_checked_at":"2026-01-12T06:05:18.301Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2026-01-12T09:39:59.676Z","updated_at":"2026-01-12T09:39:59.736Z","avatar_url":"https://github.com/eldomagan.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# alpine-define-component\n\nStructured component system for Alpine.js with parts/slots support and full TypeScript support.\n\n## Installation\n\n```bash\nnpm install alpine-define-component\n```\n\n## Quick Start\n\n```typescript\nimport Alpine from 'alpinejs';\nimport { defineComponent } from 'alpine-define-component';\n\nconst accordion = defineComponent({\n  name: 'accordion',\n  setup: (props) =\u003e ({\n    value: props.value || [],\n\n    toggle(id) {\n      const isOpen = this.value.includes(id);\n      this.value = isOpen ? this.value.filter((i) =\u003e i !== id) : [id];\n    },\n\n    isOpen(id) {\n      return this.value.includes(id);\n    },\n  }),\n\n  parts: {\n    item(api, el, { value }) {\n      return {\n        'x-on:click': () =\u003e api.toggle(value),\n        'x-bind:data-open': () =\u003e api.isOpen(value),\n      };\n    },\n  },\n});\n\nAlpine.plugin(accordion);\nAlpine.start();\n```\n\n```html\n\u003cdiv x-accordion=\"{ value: [] }\"\u003e\n  \u003cdiv x-accordion:item=\"'item-1'\"\u003eItem 1\u003c/div\u003e\n  \u003cdiv x-accordion:item=\"'item-2'\"\u003eItem 2\u003c/div\u003e\n\u003c/div\u003e\n```\n\n## TypeScript\n\n### `setup` Helper (Optional)\n\nFor TypeScript users who want Alpine magics (`this.$dispatch`, `this.$watch`, etc.) typed in methods:\n\n```typescript\nimport { defineComponent, setup } from 'alpine-define-component';\n\nconst counter = defineComponent({\n  name: 'counter',\n  setup: setup((props: { count?: number }) =\u003e ({\n    count: props.count ?? 0,\n\n    increment() {\n      this.count++;\n      this.$dispatch('incremented');\n    },\n  })),\n});\n```\n\n## Scoped Parts\n\nUse `defineScope` to create isolated reactive contexts for repeating parts (like tabs, accordion items, list items):\n\n```typescript\nimport { defineComponent, defineScope } from 'alpine-define-component';\n\nconst tabs = defineComponent({\n  name: 'tabs',\n  setup: (props) =\u003e ({\n    activeTab: props.defaultTab || 'tab1',\n    setTab(tab: string) {\n      this.activeTab = tab;\n    }\n  }),\n\n  parts: {\n    item: defineScope({\n      name: 'tabItem',\n      setup: (api, el, { value }) =\u003e ({\n        id: value,\n        isActive: () =\u003e api.activeTab === value\n      }),\n      bindings: (api, scope) =\u003e ({\n        'x-on:click': () =\u003e api.setTab(scope.id),\n        'x-bind:class': () =\u003e ({ active: scope.isActive() })\n      })\n    })\n  }\n});\n```\n\n```html\n\u003cdiv x-tabs=\"{ defaultTab: 'tab1' }\"\u003e\n  \u003c!-- Each item has its own scope via $tabItem --\u003e\n  \u003cbutton x-tabs:item=\"'tab1'\" x-text=\"$tabItem.isActive() ? 'Active' : 'Tab 1'\"\u003e\n    Tab 1\n  \u003c/button\u003e\n  \u003cbutton x-tabs:item=\"'tab2'\" x-text=\"$tabItem.isActive() ? 'Active' : 'Tab 2'\"\u003e\n    Tab 2\n  \u003c/button\u003e\n\u003c/div\u003e\n```\n\n**Benefits:**\n- Isolated reactive state per part instance\n- Access parent API and scope data together\n- Scope available as `$scopeName` magic in HTML\n- Perfect for lists, tabs, accordions, menu items, etc.\n\n### Scope Typing (TypeScript)\n\nFor full type safety with scopes, use the parts-as-function pattern with `withScopes`:\n\n```typescript\nimport { defineComponent, defineScope, setup } from 'alpine-define-component';\n\nconst accordion = defineComponent({\n  name: 'accordion',\n  setup: setup(() =\u003e ({\n    openItems: [] as string[],\n    toggle(itemId: string) { /* ... */ },\n    isOpen(itemId: string) { /* ... */ },\n  })),\n\n  parts: ({ withScopes }) =\u003e withScopes\u003c{\n    $item: { id: string; isOpen: boolean; toggle: () =\u003e void };\n  }\u003e({\n    item: defineScope({\n      name: 'item',\n      setup: (api, _, { value: itemId }) =\u003e ({\n        id: itemId,\n        isOpen: api.isOpen(itemId),\n        toggle() { api.toggle(itemId); },\n      }),\n    }),\n\n    header(api) {\n      // api.$item is correctly typed (from withScopes)\n      return {\n        'x-on:click': () =\u003e api.$item.toggle(),\n        'x-bind:class': () =\u003e ({ open: api.$item.isOpen }),\n      };\n    },\n  }),\n});\n```\n\n## API\n\n### `defineComponent(config)`\n\n```typescript\ndefineComponent({\n  name: string,                  // Component/directive name\n  setup: (props, ctx) =\u003e {...},  // Returns component API\n  parts?: {...}                  // Optional part handlers\n})\n```\n\n### `defineScope(options)`\n\nCreates an isolated reactive scope for component parts.\n\n```typescript\ndefineScope({\n  name: string,                        // Scope name (accessible as $name in template)\n  setup: (api, el, ctx) =\u003e {...},      // Returns scope data\n  bindings?: (api, scope) =\u003e {...}     // Optional Alpine bindings\n})\n```\n\n**Returns:** Part handler function\n\n### `setup(fn)` (TypeScript)\n\nType helper for Alpine magics in methods.\n\n## Inspiration\n\n- [@alpine/ui](https://alpinejs.dev/components#headless)\n- [alpine-zag](https://github.com/TunkShif/alpine-zag)\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feldomagan%2Falpine-define-component","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feldomagan%2Falpine-define-component","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feldomagan%2Falpine-define-component/lists"}