{"id":13806542,"url":"https://github.com/simonihmig/ember-stargate","last_synced_at":"2025-03-31T08:08:54.713Z","repository":{"id":36977892,"uuid":"273067390","full_name":"simonihmig/ember-stargate","owner":"simonihmig","description":"Modern lightweight portals for Ember","archived":false,"fork":false,"pushed_at":"2025-03-27T03:22:53.000Z","size":5660,"stargazers_count":68,"open_issues_count":14,"forks_count":12,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-29T02:08:23.465Z","etag":null,"topics":["ember","ember-addon"],"latest_commit_sha":null,"homepage":"","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/simonihmig.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","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}},"created_at":"2020-06-17T20:02:07.000Z","updated_at":"2025-03-26T23:15:44.000Z","dependencies_parsed_at":"2023-10-11T05:02:09.641Z","dependency_job_id":"5ded0d2b-3183-4bac-b349-1540203203dc","html_url":"https://github.com/simonihmig/ember-stargate","commit_stats":{"total_commits":930,"total_committers":13,"mean_commits":71.53846153846153,"dds":0.5967741935483871,"last_synced_commit":"65ac363786a7ea177ac7e750615b71f446746c19"},"previous_names":["kaliber5/ember-stargate"],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonihmig%2Fember-stargate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonihmig%2Fember-stargate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonihmig%2Fember-stargate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonihmig%2Fember-stargate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simonihmig","download_url":"https://codeload.github.com/simonihmig/ember-stargate/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246436390,"owners_count":20776995,"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","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":["ember","ember-addon"],"created_at":"2024-08-04T01:01:13.077Z","updated_at":"2025-03-31T08:08:54.692Z","avatar_url":"https://github.com/simonihmig.png","language":"TypeScript","funding_links":[],"categories":["Packages"],"sub_categories":["End-user customization"],"readme":"# ember-stargate\n\n[![CI](https://github.com/kaliber5/ember-stargate/actions/workflows/ci.yml/badge.svg)](https://github.com/kaliber5/ember-stargate/actions/workflows/ci.yml)\n[![Ember Observer Score](https://emberobserver.com/badges/ember-stargate.svg)](https://emberobserver.com/addons/ember-stargate)\n\nA modern take on using so-called \"portals\" to render things in a\ndifferent place of the DOM tree than they are logically defined in the app.\n\nImplemented using lightweight Glimmer components and Ember's new `{{in-element}}`,\nbut without its caveats.\n\n## Compatibility\n\n- Ember.js v4.12 or above\n- Embroider or ember-auto-import v2\n\n## Installation\n\n```\nember install ember-stargate\n```\n\n## Why this addon?\n\nThere are a number of existing solutions in the Ember ecosystem for the same\nproblem, so why this addon you may ask?\n\nLet's see how it compares to some of those...\n\n#### ember-wormhole\n\nThe first addon to make portals popular in Ember uses proprietary implementation\ntricks, that make it potentially less stable. Also defining portal targets in your\napp is less flexible.\n\n#### ember-elsewhere\n\nWhile using only public Ember APIs, due to its requirement to use Ember's\n`component` helper it comes with some caveats:\n\n- you cannot send arbitrary content though the portal, it must be a single component\n- you cannot use a [component in block form](https://github.com/ef4/ember-elsewhere/issues/2)\n- the component helper does not support passing HTML attributes (as in regular angle bracket invocation)\n\n#### in-element\n\nWhile Ember starting with 3.20 (or earlier using [ember-in-element-polyfill](https://github.com/ember-polyfills/ember-in-element-polyfill)\nhas a built-in primitive with `{{in-element}}`, due to its (intentional) low-level nature it is suitable\nmore for usage in addons (for things like modals, tooltips, dropdowns), but using it in apps is not very ergonomic:\n\n- it requires you to pass a reference to the target DOM element, which is less ergonomic than a CSS selector or some other\n  higher-level way to define the target (e.g. a target component)\n- that DOM element has to _exist_ already before using `{{in-element}}`, so it's sensitive to rendering timings\n\nOther than that, `{{in-element}}` is a very useful primitive, and in fact this addon uses it under the hood,\nwith just some simple higher-level abstractions on top of it!\n\n## Usage\n\nYou need two things to make a portal work: define the content that should be sent through the portal using\n`\u003cPortal @target=\"some-target\"\u003e`, and the target - identified by its name - where it should be rendered to\nusing `\u003cPortalTarget @name=\"some-target\"\u003e`.\n\nLet's take an example where we want to render a sticky footer inside `application.hbs`, as it will be used\nacross routes, but the actual content (left and right sections for action buttons etc. and a title) needs\nto be defined within the actual routes;\n\nstep1.hbs:\n\n```hbs\n\u003cPortal @target='footer-title'\u003eStep 1\u003c/Portal\u003e\n\n\u003cPortal @target='footer-left'\u003e\n  \u003cLinkTo @route='index'\u003eBack\u003c/LinkTo\u003e\n\u003c/Portal\u003e\n\n\u003cPortal @target='footer-right'\u003e\n  \u003cbutton type='button' {{on 'click' this.submit}}\u003eSubmit and proceed\u003c/button\u003e\n\u003c/Portal\u003e\n```\n\napplication.hbs:\n\n```hbs\n{{outlet}}\n\n\u003cfooter class='sticky-footer'\u003e\n  \u003cPortalTarget @name='footer-left' class='sticky-footer__left' /\u003e\n\n  \u003cPortalTarget @name='footer-title' class='sticky-footer__title' /\u003e\n\n  \u003cPortalTarget @name='footer-right' class='sticky-footer__right' /\u003e\n\u003c/footer\u003e\n```\n\nNote that although the footer will be rendered _after_ the portals, as it comes after the `{{outlet}}` at the\nbottom of the DOM, this poses no problem for this addon as it explicitly supports this case: a portal's content\nwill not be rendered until its target is available, but then the target will immediately show the portal's content.\n\n## API\n\n### Portal\n\n- `@target`: required argument to specify the name of the target\n- `@fallback`: by default the portal's content will not render until the target is available.\n  With `@fallback=\"inplace\"` the content will be rendered in place as long as the target is not available.\n- `@renderInPlace`: if `true` the portal is effectively disabled, and the content is rendered in place.\n\n### PortalTarget\n\n- `@name`: required argument that identifies the target\n- `@multiple`: by default if multiple portals refer to the same target, they will replace each other\n  (in the order of rendering). With `@multiple={{true}}` the portal's content will be appended (again in the order of rendering).\n- `@onChange`: whenever a portal is rendered to or removed from the target, this action will be called. It will receive\n  the current portal count of this target as an argument.\n\n## TypeScript usage\n\nAll components have proper [Glint](https://github.com/typed-ember/glint) types, which allow you when using TypeScript to get strict type checking in your templates.\n\nUnless you are using [strict mode](http://emberjs.github.io/rfcs/0496-handlebars-strict-mode.html) templates (via [first class component templates](http://emberjs.github.io/rfcs/0779-first-class-component-templates.html)),\nyou need to import the addon's Glint template registry entries as described in the [Using Addons](https://typed-ember.gitbook.io/glint/using-glint/ember/using-addons#using-glint-enabled-addons) documentation:\n\n```ts\n// e.g. types/glint.d.ts\nimport '@glint/environment-ember-loose';\nimport type StargateRegistry from 'ember-stargate/template-registry';\n\ndeclare module '@glint/environment-ember-loose/registry' {\n  export default interface Registry\n    extends StargateRegistry /* other addon registries */ {\n    // local entries\n  }\n}\n```\n\n\u003e Note that Glint itself is still under active development, and as such breaking changes might occur. Therefore, Glint support by this addon is also considered experimental, and not covered by our SemVer contract!\n\n## Contributing\n\nSee the [Contributing](CONTRIBUTING.md) guide for details.\n\n## License\n\nThis project is licensed under the [MIT License](LICENSE.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonihmig%2Fember-stargate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimonihmig%2Fember-stargate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonihmig%2Fember-stargate/lists"}