├── .all-contributorsrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .github ├── scripts │ └── merge-all-contributors.js └── workflows │ ├── astro.yml │ ├── auto-approve.yml │ ├── ci.yml │ └── merge-all-contributors.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .vscode ├── extensions.json └── settings.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── apps ├── test-app-e2e │ ├── .eslintrc.json │ ├── cypress.config.ts │ ├── project.json │ ├── src │ │ ├── e2e │ │ │ ├── active-element.cy.ts │ │ │ ├── drag.cy.ts │ │ │ ├── if-validator.cy.ts │ │ │ ├── resize.cy.ts │ │ │ └── track-by.cy.ts │ │ └── support │ │ │ ├── app.po.ts │ │ │ ├── commands.ts │ │ │ └── e2e.ts │ └── tsconfig.json └── test-app │ ├── .eslintrc.json │ ├── project.json │ ├── src │ ├── app │ │ ├── active-element │ │ │ └── active-element.component.ts │ │ ├── app.component.ts │ │ ├── app.config.ts │ │ ├── control-error │ │ │ └── control-error.component.ts │ │ ├── control-value-accessor │ │ │ └── control-value-accessor.ts │ │ ├── document-visibility-state │ │ │ └── document-visibility-state.component.ts │ │ ├── drag │ │ │ └── drag.component.ts │ │ ├── form-events │ │ │ └── form-events.component.ts │ │ ├── if-validator │ │ │ └── if-validator.component.ts │ │ ├── intl │ │ │ └── intl.component.ts │ │ ├── linked-query-param │ │ │ ├── linked-query-param-array.component.ts │ │ │ ├── linked-query-param-basic.component.ts │ │ │ ├── linked-query-param-booleans.component.ts │ │ │ ├── linked-query-param-insideObject.component.ts │ │ │ ├── linked-query-param-number.component.ts │ │ │ ├── linked-query-param-object.component.ts │ │ │ ├── linked-query-param.component.ts │ │ │ └── routes.ts │ │ ├── resize │ │ │ └── resize.component.ts │ │ ├── signal-history │ │ │ └── signal-history.component.ts │ │ ├── svg-sprite │ │ │ ├── svg-sprite.component.css │ │ │ └── svg-sprite.component.ts │ │ ├── text-selection │ │ │ └── text-selection.component.ts │ │ └── track-by │ │ │ └── track-by.component.ts │ ├── assets │ │ ├── .gitkeep │ │ └── fontawesome │ │ │ ├── LICENSE.txt │ │ │ └── sprites │ │ │ ├── brands.svg │ │ │ ├── regular.svg │ │ │ └── solid.svg │ ├── favicon.ico │ ├── index.html │ ├── main.ts │ └── styles.css │ ├── tsconfig.app.json │ ├── tsconfig.editor.json │ └── tsconfig.json ├── docs ├── .gitignore ├── .vscode │ ├── extensions.json │ └── launch.json ├── README.md ├── astro.config.mjs ├── package.json ├── pnpm-lock.yaml ├── project.json ├── public │ ├── favicon.svg │ ├── logo.svg │ ├── ngxt-angular.svg │ ├── ngxt-black.svg │ ├── ngxt-blue.svg │ ├── ngxt-white.svg │ ├── ngxtension-angular.svg │ ├── ngxtension-black.svg │ ├── ngxtension-blue.svg │ └── ngxtension-white.svg ├── src │ ├── components │ │ ├── Content.astro │ │ ├── Contributors.astro │ │ ├── PageTitle.astro │ │ └── Sidebar.astro │ ├── content │ │ ├── config.ts │ │ ├── contributors │ │ │ ├── chau-tran.json │ │ │ ├── dafnik.json │ │ │ ├── dale-nguyen.json │ │ │ ├── daniele-morosinotto.json │ │ │ ├── enea-jahollari.json │ │ │ ├── evgeniy-oz.json │ │ │ ├── fabiendehopre.json │ │ │ ├── fiorelozere.json │ │ │ ├── ion-prodan.json │ │ │ ├── jeanmeche.json │ │ │ ├── josh-morony.json │ │ │ ├── kevinkreuzer.json │ │ │ ├── krzysztof-kachniarz.json │ │ │ ├── lilbeqiri.json │ │ │ ├── lorenzo-dianni.json │ │ │ ├── lucas-garcia.json │ │ │ ├── mateusz-stefanczyk.json │ │ │ ├── michael-berger.json │ │ │ ├── nevzat-topçu.json │ │ │ ├── pawel-ostromecki.json │ │ │ ├── robby-rabbitman.json │ │ │ ├── sergi-dote.json │ │ │ ├── thomas-laforge.json │ │ │ └── tomer.json │ │ └── docs │ │ │ ├── 404.md │ │ │ ├── es │ │ │ ├── getting-started │ │ │ │ ├── installation.mdx │ │ │ │ └── introduction.md │ │ │ ├── index.mdx │ │ │ └── utilities │ │ │ │ ├── Assets │ │ │ │ └── svg-sprites.md │ │ │ │ ├── Components │ │ │ │ └── host-binding.md │ │ │ │ ├── Directives │ │ │ │ ├── click-outside.md │ │ │ │ ├── repeat.md │ │ │ │ ├── resize.mdx │ │ │ │ └── trackby-id-prop.md │ │ │ │ ├── Forms │ │ │ │ ├── control-error.md │ │ │ │ ├── control-value-accessor.md │ │ │ │ └── if-validator.md │ │ │ │ ├── Gesture │ │ │ │ ├── gesture.mdx │ │ │ │ └── intro.md │ │ │ │ ├── Injectors │ │ │ │ ├── active-element.md │ │ │ │ ├── assert-injector.md │ │ │ │ ├── auto-effect.md │ │ │ │ ├── create-injectable.md │ │ │ │ ├── create-injection-token.md │ │ │ │ ├── inject-destroy.md │ │ │ │ ├── inject-document-visibility.md │ │ │ │ ├── inject-is-intersecting.md │ │ │ │ ├── inject-lazy.md │ │ │ │ ├── inject-network.md │ │ │ │ ├── inject-params.md │ │ │ │ ├── inject-query-params.md │ │ │ │ ├── inject-route-data.md │ │ │ │ ├── inject-route-fragment.md │ │ │ │ └── navigation-end.md │ │ │ │ ├── Intl │ │ │ │ └── intl.md │ │ │ │ ├── Migrations │ │ │ │ └── inject-migration.md │ │ │ │ ├── Miscellaneous │ │ │ │ └── singleton-proxy.md │ │ │ │ ├── Operators │ │ │ │ ├── debug.md │ │ │ │ ├── filter-array.md │ │ │ │ ├── filter-nil.md │ │ │ │ ├── map-array.md │ │ │ │ ├── map-skip-undefined.md │ │ │ │ ├── reduce-array.md │ │ │ │ └── rx-effect.md │ │ │ │ └── Signals │ │ │ │ ├── computed-async.md │ │ │ │ ├── computed-from.md │ │ │ │ └── computed-previous.md │ │ │ ├── getting-started │ │ │ ├── installation.mdx │ │ │ └── introduction.md │ │ │ ├── index.mdx │ │ │ ├── logos │ │ │ └── logos.md │ │ │ └── utilities │ │ │ ├── Assets │ │ │ └── svg-sprites.md │ │ │ ├── Components │ │ │ └── host-binding.md │ │ │ ├── Directives │ │ │ ├── click-outside.md │ │ │ ├── merge-inputs.md │ │ │ ├── repeat.mdx │ │ │ ├── resize.mdx │ │ │ └── trackby-id-prop.md │ │ │ ├── Forms │ │ │ ├── control-error.md │ │ │ ├── control-value-accessor.md │ │ │ ├── form-events.md │ │ │ ├── if-validator.md │ │ │ └── not-pattern.md │ │ │ ├── Gesture │ │ │ ├── gesture.mdx │ │ │ └── intro.md │ │ │ ├── Http │ │ │ └── merge-http-context.md │ │ │ ├── Injectors │ │ │ ├── active-element.md │ │ │ ├── assert-injector.md │ │ │ ├── auto-effect.md │ │ │ ├── create-injectable.md │ │ │ ├── create-injection-token.md │ │ │ ├── inject-destroy.md │ │ │ ├── inject-document-visibility.md │ │ │ ├── inject-inputs.md │ │ │ ├── inject-is-intersecting.md │ │ │ ├── inject-lazy.md │ │ │ ├── inject-local-storage.md │ │ │ ├── inject-network.md │ │ │ ├── inject-params.md │ │ │ ├── inject-query-params.md │ │ │ ├── inject-route-data.md │ │ │ ├── inject-route-fragment.md │ │ │ ├── inject-text-selection.md │ │ │ ├── linked-query-param.md │ │ │ ├── navigation-end.md │ │ │ └── signal-history.md │ │ │ ├── Intl │ │ │ └── intl.md │ │ │ ├── Migrations │ │ │ ├── host-binding-migration.md │ │ │ ├── inject-migration.md │ │ │ ├── new-outputs-migration.md │ │ │ ├── queries-migration.md │ │ │ ├── self-closing-tags.md │ │ │ ├── sfc-migration.md │ │ │ └── signal-inputs-migration.md │ │ │ ├── Miscellaneous │ │ │ └── singleton-proxy.md │ │ │ ├── Operators │ │ │ ├── create-repeat.md │ │ │ ├── debug.md │ │ │ ├── derive-loading.md │ │ │ ├── filter-array.md │ │ │ ├── filter-nil.md │ │ │ ├── map-array.md │ │ │ ├── map-skip-undefined.md │ │ │ ├── poll.md │ │ │ ├── reduce-array.md │ │ │ ├── rx-effect.md │ │ │ ├── take-latest-from.md │ │ │ └── when-document-visible.md │ │ │ ├── Pipes │ │ │ ├── call-apply.md │ │ │ └── repeat.mdx │ │ │ ├── Signals │ │ │ ├── computed-async.md │ │ │ ├── computed-from.md │ │ │ ├── computed-previous.md │ │ │ ├── computed.md │ │ │ ├── connect.md │ │ │ ├── create-notifier.md │ │ │ ├── create-signal.md │ │ │ ├── derived-async.md │ │ │ ├── derived-from.md │ │ │ ├── effect-once-if.md │ │ │ ├── explicit-effect.md │ │ │ ├── merge-from.md │ │ │ ├── signal-slice.md │ │ │ ├── to-lazy-signal.md │ │ │ └── to-observable-signal.md │ │ │ └── Stores │ │ │ └── create-effect.md │ ├── env.d.ts │ └── styles │ │ └── custom.css └── tsconfig.json ├── jest.config.ts ├── jest.preset.js ├── libs ├── local-plugin │ ├── .eslintrc.json │ ├── README.md │ ├── generators.json │ ├── jest.config.ts │ ├── package.json │ ├── project.json │ ├── src │ │ ├── generators │ │ │ ├── convert-entry-point-to-project │ │ │ │ ├── generator.spec.ts │ │ │ │ ├── generator.ts │ │ │ │ ├── schema.d.ts │ │ │ │ └── schema.json │ │ │ └── entry-point │ │ │ │ ├── generator.spec.ts │ │ │ │ ├── generator.ts │ │ │ │ └── schema.json │ │ └── index.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json ├── ngxtension │ ├── .eslintrc.json │ ├── README.md │ ├── active-element │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── active-element.spec.ts │ │ │ ├── active-element.ts │ │ │ └── index.ts │ ├── assert-injector │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── assert-injector.spec.ts │ │ │ ├── assert-injector.ts │ │ │ └── index.ts │ ├── auto-effect │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── auto-effect.spec.ts │ │ │ ├── auto-effect.ts │ │ │ └── index.ts │ ├── call-apply │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── call-apply.spec.ts │ │ │ ├── call-apply.ts │ │ │ └── index.ts │ ├── click-outside │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── click-outside.spec.ts │ │ │ ├── click-outside.ts │ │ │ └── index.ts │ ├── computed-async │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ └── index.ts │ ├── computed-from │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ └── index.ts │ ├── computed-previous │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── computed-previous.spec.ts │ │ │ ├── computed-previous.ts │ │ │ └── index.ts │ ├── computed │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── computed.spec.ts │ │ │ ├── computed.ts │ │ │ └── index.ts │ ├── connect │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── connect.spec.ts │ │ │ ├── connect.ts │ │ │ └── index.ts │ ├── control-error │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── control-error.spec.ts │ │ │ ├── control-error.ts │ │ │ └── index.ts │ ├── control-value-accessor │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── control-value-accessor.spec.ts │ │ │ ├── control-value-accessor.ts │ │ │ └── index.ts │ ├── create-effect │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── create-effect.spec.ts │ │ │ ├── create-effect.ts │ │ │ └── index.ts │ ├── create-injectable │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── create-injectable.spec.ts │ │ │ ├── create-injectable.ts │ │ │ └── index.ts │ ├── create-injection-token │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── create-injection-token.spec.ts │ │ │ ├── create-injection-token.ts │ │ │ └── index.ts │ ├── create-notifier │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── create-notifier.spec.ts │ │ │ ├── create-notifier.ts │ │ │ └── index.ts │ ├── create-repeat │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── create-repeat.spec.ts │ │ │ ├── create-repeat.ts │ │ │ └── index.ts │ ├── create-signal │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── create-signal.spec.ts │ │ │ ├── create-signal.ts │ │ │ └── index.ts │ ├── debug │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── debug.spec.ts │ │ │ ├── debug.ts │ │ │ └── index.ts │ ├── derive-loading │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── derive-loading.spec.ts │ │ │ ├── derive-loading.ts │ │ │ └── index.ts │ ├── derived-async │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── derived-async.spec.ts │ │ │ ├── derived-async.ts │ │ │ └── index.ts │ ├── derived-from │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── derived-from.spec.ts │ │ │ ├── derived-from.ts │ │ │ └── index.ts │ ├── effect-once-if │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── effect-once-if.spec.ts │ │ │ ├── effect-once-if.ts │ │ │ └── index.ts │ ├── explicit-effect │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── explicit-effect.spec.ts │ │ │ ├── explicit-effect.ts │ │ │ └── index.ts │ ├── filter-array │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── filter-array.spec.ts │ │ │ ├── filter-array.ts │ │ │ └── index.ts │ ├── filter-nil │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── filter-nil.spec.ts │ │ │ ├── filter-nil.ts │ │ │ └── index.ts │ ├── form-events │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── form-events.spec.ts │ │ │ ├── form-events.ts │ │ │ └── index.ts │ ├── gestures │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── drag.ts │ │ │ ├── gesture.ts │ │ │ ├── hover.ts │ │ │ ├── index.ts │ │ │ ├── move.ts │ │ │ ├── pinch.ts │ │ │ ├── scroll.ts │ │ │ ├── wheel.ts │ │ │ └── zoneless-gesture.ts │ ├── host-binding │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── host-binding.spec.ts │ │ │ ├── host-binding.ts │ │ │ └── index.ts │ ├── if-validator │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── if-validator.spec.ts │ │ │ ├── if-validator.ts │ │ │ └── index.ts │ ├── inject-destroy │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── inject-destroy.spec.ts │ │ │ └── inject-destroy.ts │ ├── inject-document-visibility │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── inject-document-visibility.spec.ts │ │ │ └── inject-document-visibility.ts │ ├── inject-inputs │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ └── lib │ │ │ ├── inject-inputs.spec.ts │ │ │ ├── inject-inputs.ts │ │ │ ├── merge-inputs.spec.ts │ │ │ └── merge-inputs.ts │ ├── inject-is-intersecting │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── inject-is-intersecting.spec.ts │ │ │ ├── inject-is-intersecting.ts │ │ │ └── is-in-viewport.service.ts │ ├── inject-lazy │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── inject-lazy-impl.ts │ │ │ ├── inject-lazy.spec.ts │ │ │ └── inject-lazy.ts │ ├── inject-local-storage │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── inject-local-storage.spec.ts │ │ │ └── inject-local-storage.ts │ ├── inject-network │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── inject-network.spec.ts │ │ │ └── inject-network.ts │ ├── inject-params │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── inject-params.spec.ts │ │ │ └── inject-params.ts │ ├── inject-query-params │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── inject-query-params.spec.ts │ │ │ └── inject-query-params.ts │ ├── inject-route-data │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── inject-route-data.spec.ts │ │ │ └── inject-route-data.ts │ ├── inject-route-fragment │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── inject-route-fragment.spec.ts │ │ │ └── inject-route-fragment.ts │ ├── inject-text-selection │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── inject-text-selection.spec.ts │ │ │ └── inject-text-selection.ts │ ├── intl │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── display-names.pipe.ts │ │ │ ├── display-names.spec.ts │ │ │ ├── index.ts │ │ │ ├── list-format.pipe.ts │ │ │ ├── list-format.spec.ts │ │ │ ├── plural-rules.pipe.ts │ │ │ ├── plural-rules.spec.ts │ │ │ ├── relative-time-format.pipe.ts │ │ │ ├── relative-time-format.spec.ts │ │ │ ├── supportedValuesOf.pipe.ts │ │ │ └── supportedValuesOf.spec.ts │ ├── jest.config.ts │ ├── linked-query-param │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── linked-query-param.spec.ts │ │ │ └── linked-query-param.ts │ ├── map-array │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── map-array.spec.ts │ │ │ └── map-array.ts │ ├── map-skip-undefined │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── map-skip-undefined.spec.ts │ │ │ └── map-skip-undefined.ts │ ├── merge-from │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ └── lib │ │ │ ├── merge-from.spec.ts │ │ │ └── merge-from.ts │ ├── merge-http-context │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── merge-http-context.spec.ts │ │ │ └── merge-http-context.ts │ ├── navigation-end │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── navigation-end.spec.ts │ │ │ └── navigation-end.ts │ ├── ng-package.json │ ├── not-pattern │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── not-pattern.spec.ts │ │ │ └── not-pattern.ts │ ├── package.json │ ├── poll │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── poll.spec.ts │ │ │ └── poll.ts │ ├── project.json │ ├── reduce-array │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── reduce-array.spec.ts │ │ │ └── reduce-array.ts │ ├── repeat-pipe │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── repeat-pipe.spec.ts │ │ │ └── repeat-pipe.ts │ ├── repeat │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── repeat.spec.ts │ │ │ └── repeat.ts │ ├── resize │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ └── resize.ts │ ├── rx-effect │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── rx-effect.spec.ts │ │ │ └── rx-effect.ts │ ├── shared │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ └── options │ │ │ ├── default-value.ts │ │ │ ├── index.ts │ │ │ ├── injector.ts │ │ │ └── parse.ts │ ├── signal-history │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── signal-history.spec.ts │ │ │ └── signal-history.ts │ ├── signal-slice │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── signal-slice.spec.ts │ │ │ └── signal-slice.ts │ ├── singleton-proxy │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── singleton-proxy.spec.ts │ │ │ └── singleton-proxy.ts │ ├── src │ │ ├── index.ts │ │ └── test-setup.ts │ ├── svg-sprite │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── svg-sprite.spec.ts │ │ │ └── svg-sprite.ts │ ├── take-latest-from │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── take-latest-from.spec.ts │ │ │ └── take-latest-from.ts │ ├── to-lazy-signal │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── to-lazy-signal.spec.ts │ │ │ └── to-lazy-signal.ts │ ├── to-observable-signal │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── to-observable-signal.spec.ts │ │ │ └── to-observable-signal.ts │ ├── trackby-id-prop │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ │ ├── index.ts │ │ │ ├── trackby-id-prop.spec.ts │ │ │ └── trackby-id-prop.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ └── when-document-visible │ │ ├── README.md │ │ ├── ng-package.json │ │ ├── project.json │ │ └── src │ │ ├── index.ts │ │ ├── when-document-visible.spec.ts │ │ └── when-document-visible.ts └── plugin │ ├── .eslintrc.json │ ├── README.md │ ├── generators.json │ ├── jest.config.ts │ ├── migrations.json │ ├── package.json │ ├── project.json │ ├── src │ ├── generators │ │ ├── convert-di-to-inject │ │ │ ├── __snapshots__ │ │ │ │ └── generator.spec.ts.snap │ │ │ ├── compat.ts │ │ │ ├── generator.spec.ts │ │ │ ├── generator.ts │ │ │ ├── schema.d.ts │ │ │ └── schema.json │ │ ├── convert-host-binding │ │ │ ├── __snapshots__ │ │ │ │ └── generator.spec.ts.snap │ │ │ ├── compat.ts │ │ │ ├── generator.spec.ts │ │ │ ├── generator.ts │ │ │ ├── schema.d.ts │ │ │ └── schema.json │ │ ├── convert-outputs │ │ │ ├── __snapshots__ │ │ │ │ └── generator.spec.ts.snap │ │ │ ├── compat.ts │ │ │ ├── generator.spec.ts │ │ │ ├── generator.ts │ │ │ ├── schema.d.ts │ │ │ └── schema.json │ │ ├── convert-queries │ │ │ ├── __snapshots__ │ │ │ │ └── generator.spec.ts.snap │ │ │ ├── compat.ts │ │ │ ├── generator.spec.ts │ │ │ ├── generator.ts │ │ │ ├── schema.d.ts │ │ │ └── schema.json │ │ ├── convert-signal-inputs │ │ │ ├── __snapshots__ │ │ │ │ └── generator.spec.ts.snap │ │ │ ├── compat.ts │ │ │ ├── generator.spec.ts │ │ │ ├── generator.ts │ │ │ ├── schema.d.ts │ │ │ └── schema.json │ │ ├── convert-to-self-closing-tag │ │ │ ├── __snapshots__ │ │ │ │ └── generator.spec.ts.snap │ │ │ ├── compat.ts │ │ │ ├── generator.spec.ts │ │ │ ├── generator.ts │ │ │ ├── schema.d.ts │ │ │ └── schema.json │ │ ├── convert-to-sfc │ │ │ ├── __snapshots__ │ │ │ │ └── generator.spec.ts.snap │ │ │ ├── compat.ts │ │ │ ├── generator.spec.ts │ │ │ ├── generator.ts │ │ │ ├── schema.d.ts │ │ │ └── schema.json │ │ ├── init │ │ │ ├── compat.ts │ │ │ ├── generator.spec.ts │ │ │ ├── generator.ts │ │ │ └── schema.json │ │ └── shared-utils │ │ │ ├── contents-store.ts │ │ │ ├── import-utils.ts │ │ │ ├── migrate-signals-in-template.ts │ │ │ └── migrate-signals-in-ts.ts │ ├── index.ts │ └── migrations │ │ ├── rename-computeds │ │ ├── compat.ts │ │ ├── rename-computeds.spec.ts │ │ └── rename-computeds.ts │ │ └── rename-document-visibility │ │ ├── compat.ts │ │ ├── rename-document-visibility.spec.ts │ │ └── rename-document-visibility.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json ├── migrations.json ├── nx.json ├── package.json ├── pnpm-lock.yaml └── tsconfig.base.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.github/workflows/auto-approve.yml: -------------------------------------------------------------------------------- 1 | name: Auto approve All Contributors 2 | 3 | on: pull_request_target 4 | 5 | jobs: 6 | auto-approve: 7 | runs-on: ubuntu-latest 8 | permissions: 9 | pull-requests: write 10 | if: github.actor == 'allcontributors[bot]' 11 | steps: 12 | - uses: hmarr/auto-approve-action@v3 13 | with: 14 | github-token: ${{ secrets.GITHUB_TOKEN }} 15 | -------------------------------------------------------------------------------- /.github/workflows/merge-all-contributors.yml: -------------------------------------------------------------------------------- 1 | name: Merge All Contributors PR 2 | 3 | on: 4 | pull_request: 5 | types: 6 | - 'closed' 7 | 8 | jobs: 9 | if_merged: 10 | if: github.event.pull_request.merged == true 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: actions/github-script@v6 15 | with: 16 | script: | 17 | const script = require('./.github/scripts/merge-all-contributors.js') 18 | await script({ github, context }); 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | dist 5 | tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | 37 | # System Files 38 | .DS_Store 39 | Thumbs.db 40 | 41 | .angular 42 | .env 43 | 44 | .nx/cache 45 | .nx/workspace-data -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | /dist 3 | /coverage 4 | .angular 5 | pnpm-lock.yaml 6 | CHANGELOG.md 7 | README.md 8 | .gitignore 9 | .prettierignore 10 | 11 | /.nx/cache 12 | **/*.snap 13 | 14 | /apps/test-app/src/assets/fontawesome 15 | 16 | /.nx/workspace-data 17 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "useTabs": true, 4 | "htmlWhitespaceSensitivity": "ignore", 5 | "plugins": ["prettier-plugin-astro", "prettier-plugin-organize-imports"], 6 | "overrides": [ 7 | { 8 | "files": "*.md", 9 | "options": { 10 | "printWidth": 80 11 | } 12 | }, 13 | { 14 | "files": "*.astro", 15 | "options": { 16 | "parser": "astro" 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "nrwl.angular-console", 4 | "esbenp.prettier-vscode", 5 | "firsttris.vscode-jest-runner", 6 | "dbaeumer.vscode-eslint" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.validate": ["json"] 3 | } 4 | -------------------------------------------------------------------------------- /apps/test-app-e2e/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["plugin:cypress/recommended", "../test-app/.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": { 8 | "@typescript-eslint/no-unused-vars": 0 9 | } 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /apps/test-app-e2e/cypress.config.ts: -------------------------------------------------------------------------------- 1 | import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset'; 2 | import { defineConfig } from 'cypress'; 3 | 4 | export default defineConfig({ 5 | e2e: nxE2EPreset(__dirname), 6 | }); 7 | -------------------------------------------------------------------------------- /apps/test-app-e2e/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test-app-e2e", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "apps/test-app-e2e/src", 5 | "projectType": "application", 6 | "targets": { 7 | "e2e": { 8 | "executor": "@nx/cypress:cypress", 9 | "options": { 10 | "cypressConfig": "apps/test-app-e2e/cypress.config.ts", 11 | "devServerTarget": "test-app:serve:development", 12 | "testingType": "e2e" 13 | }, 14 | "configurations": { 15 | "production": { 16 | "devServerTarget": "test-app:serve:production" 17 | }, 18 | "ci": { 19 | "devServerTarget": "test-app:serve-static" 20 | } 21 | } 22 | }, 23 | "lint": { 24 | "executor": "@nx/eslint:lint", 25 | "outputs": ["{options.outputFile}"] 26 | } 27 | }, 28 | "tags": [], 29 | "implicitDependencies": ["test-app"] 30 | } 31 | -------------------------------------------------------------------------------- /apps/test-app-e2e/src/e2e/active-element.cy.ts: -------------------------------------------------------------------------------- 1 | describe('activeElement', () => { 2 | beforeEach(() => cy.visit('/active-element')); 3 | 4 | it('should emit the focussed button', () => { 5 | cy.get('button').eq(1).as('buttonToFocus'); 6 | cy.get('span').as('focussedElementHTML'); 7 | 8 | cy.get('@buttonToFocus').focus(); 9 | cy.get('@focussedElementHTML').should('contain.text', 'btn2'); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /apps/test-app-e2e/src/e2e/drag.cy.ts: -------------------------------------------------------------------------------- 1 | describe('drag', () => { 2 | beforeEach(() => cy.visit('/drag')); 3 | 4 | it('should update coord after drag', () => { 5 | cy.get('.pink-draggable-box > span').as('coordSpan'); 6 | cy.get('.pink-draggable-box').as('box'); 7 | cy.get('@coordSpan').should('contain.text', '0,0'); 8 | 9 | cy.get('@box').trigger('pointerdown', { 10 | pointerId: 1, 11 | clientX: 0, 12 | clientY: 0, 13 | }); 14 | cy.get('@box').trigger('pointermove', { 15 | pointerId: 1, 16 | clientX: 300, 17 | clientY: 300, 18 | }); 19 | cy.get('@box').trigger('pointerup', { pointerId: 1 }); 20 | 21 | cy.get('@coordSpan').should('contain.text', '300,300'); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /apps/test-app-e2e/src/e2e/if-validator.cy.ts: -------------------------------------------------------------------------------- 1 | describe('if-validator', () => { 2 | beforeEach(() => cy.visit('/if-validator')); 3 | 4 | it('should dynamically change form validation', () => { 5 | cy.get('pre').should('contain.text', 'Is Form Valid: true'); // Default shouldValidate is false, form valid 6 | cy.get('button').click(); // Click the btn change shouldValidate to true 7 | cy.get('pre').should('contain.text', 'Is Form Valid: false'); // Form invalid 8 | cy.get('input').type('ngxextension@ng.com'); // Type valid email text 9 | cy.get('pre').should('contain.text', 'Is Form Valid: true'); // Form valid 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /apps/test-app-e2e/src/e2e/resize.cy.ts: -------------------------------------------------------------------------------- 1 | describe('resize', () => { 2 | beforeEach(() => cy.visit('/resize')); 3 | 4 | it('should react to viewport resize', () => { 5 | cy.viewport(500, 500); 6 | cy.get('pre').should('contain.text', '"width": 500'); 7 | 8 | cy.viewport(800, 800); 9 | cy.get('pre').should('contain.text', '"width": 800'); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /apps/test-app-e2e/src/e2e/track-by.cy.ts: -------------------------------------------------------------------------------- 1 | describe('track-by', () => { 2 | it('should track by properly', () => { 3 | cy.visit('/track-by'); 4 | 5 | cy.get('[id=without-track-by]').as('withoutTrackBy'); 6 | cy.get('[id=with-track-by]').as('withTrackBy'); 7 | cy.get('[id=with-track-by-prop]').as('withTrackByProp'); 8 | 9 | // initial 10 | assertCount(3 /* initial 3 */, 3 /* initial 3 */); 11 | 12 | // first click 13 | cy.get('button').click(); 14 | assertCount( 15 | 10 /* initial 3 + 7 (3 removed, 4 new) */, 16 | 4 /* initial 3 + 1 new */, 17 | ); 18 | 19 | // second click 20 | cy.get('button').click(); 21 | assertCount( 22 | 19 /* initial 3 + 7 (3 removed, 4 new) + 9 (4 removed, 5 new) */, 23 | 5 /* initial 3 + 1 + 1 new */, 24 | ); 25 | }); 26 | }); 27 | 28 | function assertCount(withoutTrackByCount: number, withTrackByCount: number) { 29 | cy.get('@withoutTrackBy').contains(withoutTrackByCount); 30 | cy.get('@withTrackBy').contains(withTrackByCount); 31 | cy.get('@withTrackByProp').contains(withTrackByCount); 32 | } 33 | -------------------------------------------------------------------------------- /apps/test-app-e2e/src/support/app.po.ts: -------------------------------------------------------------------------------- 1 | export const getGreeting = () => cy.get('h1'); 2 | -------------------------------------------------------------------------------- /apps/test-app-e2e/src/support/e2e.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands'; 18 | -------------------------------------------------------------------------------- /apps/test-app-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "sourceMap": false, 5 | "outDir": "../../dist/out-tsc", 6 | "allowJs": true, 7 | "types": ["cypress", "node"], 8 | "forceConsistentCasingInFileNames": true, 9 | "strict": true, 10 | "noImplicitOverride": true, 11 | "noPropertyAccessFromIndexSignature": true, 12 | "noImplicitReturns": true, 13 | "noFallthroughCasesInSwitch": true 14 | }, 15 | "include": ["src/**/*.ts", "src/**/*.js", "cypress.config.ts"] 16 | } 17 | -------------------------------------------------------------------------------- /apps/test-app/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "rules": { 12 | "@angular-eslint/component-class-suffix": 0, 13 | "@angular-eslint/no-host-metadata-property": 0 14 | } 15 | }, 16 | { 17 | "files": ["*.html"], 18 | "extends": ["plugin:@nx/angular-template"], 19 | "rules": {} 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /apps/test-app/src/app/active-element/active-element.component.ts: -------------------------------------------------------------------------------- 1 | import { AsyncPipe } from '@angular/common'; 2 | import { Component } from '@angular/core'; 3 | import { injectActiveElement } from 'ngxtension/active-element'; 4 | 5 | @Component({ 6 | standalone: true, 7 | host: { 8 | style: 'display: block; margin: 12px', 9 | }, 10 | imports: [AsyncPipe], 11 | template: ` 12 | 13 | 14 | 15 | 16 | {{ (activeElement$ | async)?.innerHTML }} 17 | 18 | `, 19 | }) 20 | export default class ActiveElement { 21 | readonly activeElement$ = injectActiveElement(); 22 | } 23 | -------------------------------------------------------------------------------- /apps/test-app/src/app/document-visibility-state/document-visibility-state.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, effect } from '@angular/core'; 2 | import { injectDocumentVisibility } from 'ngxtension/inject-document-visibility'; 3 | 4 | @Component({ 5 | template: ` 6 | {{ visibilityState() }} 7 | `, 8 | standalone: true, 9 | }) 10 | export default class DocumentVisibilityStateComponent { 11 | visibilityState = injectDocumentVisibility(); 12 | 13 | constructor() { 14 | effect(() => { 15 | console.log(this.visibilityState()); 16 | }); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /apps/test-app/src/app/if-validator/if-validator.component.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { Component } from '@angular/core'; 3 | import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms'; 4 | import { ifValidator } from 'ngxtension/if-validator'; 5 | 6 | @Component({ 7 | standalone: true, 8 | imports: [CommonModule, ReactiveFormsModule], 9 | host: { 10 | style: 'display: block; margin: 12px', 11 | }, 12 | template: ` 13 | 14 | 15 |
Is Form Valid: {{ form.valid }}
16 | 17 | 18 | `, 19 | }) 20 | export default class IfValidator { 21 | public shouldValidate = false; 22 | public form = new FormControl( 23 | null, 24 | ifValidator( 25 | () => this.shouldValidate, 26 | [Validators.required, Validators.email], 27 | ), 28 | ); 29 | 30 | public changeCondition() { 31 | this.shouldValidate = !this.shouldValidate; 32 | this.form.updateValueAndValidity(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /apps/test-app/src/app/resize/resize.component.ts: -------------------------------------------------------------------------------- 1 | import { JsonPipe } from '@angular/common'; 2 | import { Component } from '@angular/core'; 3 | import { toSignal } from '@angular/core/rxjs-interop'; 4 | import { injectResize } from 'ngxtension/resize'; 5 | 6 | @Component({ 7 | standalone: true, 8 | template: ` 9 |
{{ resize() | json }}
10 | `, 11 | host: { 12 | style: 'display: block', 13 | }, 14 | imports: [JsonPipe], 15 | }) 16 | export default class TestResize { 17 | resize = toSignal(injectResize()); 18 | } 19 | -------------------------------------------------------------------------------- /apps/test-app/src/app/svg-sprite/svg-sprite.component.css: -------------------------------------------------------------------------------- 1 | :host { 2 | svg { 3 | width: 4rem; 4 | border: 2px red solid; 5 | margin: 0 1rem; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/test-app/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxtension/ngxtension-platform/ca1520ec1428ab899438174976d6ccea9cb6e917/apps/test-app/src/assets/.gitkeep -------------------------------------------------------------------------------- /apps/test-app/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxtension/ngxtension-platform/ca1520ec1428ab899438174976d6ccea9cb6e917/apps/test-app/src/favicon.ico -------------------------------------------------------------------------------- /apps/test-app/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | test-app 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /apps/test-app/src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrapApplication } from '@angular/platform-browser'; 2 | import { AppComponent } from './app/app.component'; 3 | import { appConfig } from './app/app.config'; 4 | 5 | bootstrapApplication(AppComponent, appConfig).catch((err) => 6 | console.error(err), 7 | ); 8 | -------------------------------------------------------------------------------- /apps/test-app/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | html, 3 | body { 4 | height: 100%; 5 | margin: 0; 6 | box-sizing: border-box; 7 | } 8 | 9 | .draggable-box { 10 | display: block; 11 | position: relative; 12 | width: 100px; 13 | height: 100px; 14 | border-radius: 0.25rem; 15 | touch-action: none; 16 | } 17 | 18 | .pink-draggable-box { 19 | background: hotpink; 20 | } 21 | 22 | .blue-draggable-box { 23 | background: dodgerblue; 24 | } 25 | 26 | .green-draggable-box { 27 | background: greenyellow; 28 | } 29 | -------------------------------------------------------------------------------- /apps/test-app/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "files": ["src/main.ts"], 8 | "include": ["src/**/*.d.ts"], 9 | "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/test-app/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["src/**/*.ts"], 4 | "compilerOptions": { 5 | "types": [] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/test-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true 11 | }, 12 | "files": [], 13 | "include": [], 14 | "references": [ 15 | { 16 | "path": "./tsconfig.app.json" 17 | }, 18 | { 19 | "path": "./tsconfig.editor.json" 20 | } 21 | ], 22 | "extends": "../../tsconfig.base.json", 23 | "angularCompilerOptions": { 24 | "enableI18nLegacyMessageIdFormat": false, 25 | "strictInjectionParameters": true, 26 | "strictInputAccessModifiers": true, 27 | "strictTemplates": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | # generated types 4 | .astro/ 5 | 6 | # dependencies 7 | node_modules/ 8 | 9 | # logs 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | -------------------------------------------------------------------------------- /docs/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /docs/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "command": "./node_modules/.bin/astro dev", 6 | "name": "Development server", 7 | "request": "launch", 8 | "type": "node-terminal" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "astro dev", 7 | "start": "astro dev", 8 | "build": "astro build", 9 | "preview": "astro preview", 10 | "astro": "astro" 11 | }, 12 | "dependencies": { 13 | "@astrojs/starlight": "^0.22.0", 14 | "astro": "^4.7.0", 15 | "sharp": "^0.33.3" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /docs/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "$schema": "../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "application", 5 | "targets": { 6 | "package": { 7 | "executor": "nx:run-commands", 8 | "options": { 9 | "commands": [ 10 | "pnpm nx run docs:build-docs", 11 | "pnpm nx run docs:copy-static" 12 | ], 13 | "parallel": false 14 | } 15 | }, 16 | "build-docs": { 17 | "executor": "nx:run-commands", 18 | "options": { 19 | "commands": [ 20 | "pnpm exec nx build docs", 21 | "pnpm exec nx graph --file=docs/dist/dep-graph/index.html" 22 | ], 23 | "parallel": false 24 | } 25 | }, 26 | "copy-static": { 27 | "command": "cp -r dep-graph/static static", 28 | "options": { 29 | "cwd": "docs/dist" 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /docs/public/favicon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/src/components/Content.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Default from '@astrojs/starlight/components/MarkdownContent.astro'; 3 | import type { Props } from '@astrojs/starlight/props'; 4 | import { getEntry } from 'astro:content'; 5 | import Contributors from './Contributors.astro'; 6 | 7 | const contributors = Astro.props.entry.data.contributors 8 | ? await Promise.all( 9 | Astro.props.entry.data.contributors.map((contributor) => 10 | getEntry(contributor), 11 | ), 12 | ) 13 | : null; 14 | --- 15 | 16 | {contributors && } 17 | 18 | 19 | 20 | 27 | -------------------------------------------------------------------------------- /docs/src/content/config.ts: -------------------------------------------------------------------------------- 1 | import { docsSchema } from '@astrojs/starlight/schema'; 2 | import { defineCollection, reference, z } from 'astro:content'; 3 | 4 | const contributors = defineCollection({ 5 | type: 'data', 6 | schema: z.object({ 7 | name: z.string(), 8 | twitter: z.string().url().optional(), 9 | linkedin: z.string().url().optional(), 10 | github: z.string().url().optional(), 11 | website: z.string().url().optional(), 12 | }), 13 | }); 14 | 15 | const docs = defineCollection({ 16 | schema: (ctx) => 17 | docsSchema()(ctx).extend({ 18 | badge: z 19 | .enum(['stable', 'unstable', 'experimental', 'deprecated']) 20 | .optional(), 21 | entryPoint: z.string().optional(), 22 | contributors: z.array(reference('contributors')).optional(), 23 | }), 24 | }); 25 | 26 | export const collections = { docs, contributors }; 27 | -------------------------------------------------------------------------------- /docs/src/content/contributors/chau-tran.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Chau Tran", 3 | "twitter": "https://twitter.com/Nartc1410", 4 | "github": "https://github.com/nartc", 5 | "website": "https://nartc.me" 6 | } 7 | -------------------------------------------------------------------------------- /docs/src/content/contributors/dafnik.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Dafnik", 3 | "github": "https://github.com/dafnik", 4 | "website": "https://dafnik.me" 5 | } 6 | -------------------------------------------------------------------------------- /docs/src/content/contributors/dale-nguyen.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Dale Nguyen" 3 | } 4 | -------------------------------------------------------------------------------- /docs/src/content/contributors/daniele-morosinotto.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Daniele Morosinotto" 3 | } 4 | -------------------------------------------------------------------------------- /docs/src/content/contributors/enea-jahollari.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Enea Jahollari", 3 | "twitter": "https://twitter.com/Enea_Jahollari", 4 | "linkedin": "https://www.linkedin.com/in/eneajahollari/", 5 | "github": "https://github.com/eneajaho", 6 | "website": "https://eneajaho.me" 7 | } 8 | -------------------------------------------------------------------------------- /docs/src/content/contributors/evgeniy-oz.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Evgeniy OZ", 3 | "twitter": "https://twitter.com/eugeniyoz", 4 | "github": "https://github.com/e-oz", 5 | "website": "https://medium.com/@eugeniyoz" 6 | } 7 | -------------------------------------------------------------------------------- /docs/src/content/contributors/fabiendehopre.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Fabien Dehopré", 3 | "twitter": "https://twitter.com/FabienDehopre", 4 | "github": "https://github.com/FabienDehopre", 5 | "linkedin": "https://www.linkedin.com/in/fabien1979/" 6 | } 7 | -------------------------------------------------------------------------------- /docs/src/content/contributors/fiorelozere.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Fiorelo Zere", 3 | "twitter": "https://twitter.com/Fiorelo_z", 4 | "github": "https://github.com/fiorelozere", 5 | "linkedin": "https://www.linkedin.com/in/fiorelo-zere-937785183" 6 | } 7 | -------------------------------------------------------------------------------- /docs/src/content/contributors/ion-prodan.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ion Prodan" 3 | } 4 | -------------------------------------------------------------------------------- /docs/src/content/contributors/jeanmeche.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Matthieu Riegler", 3 | "twitter": "https://twitter.com/jean__meche", 4 | "linkedin": "https://www.linkedin.com/in/matthieuriegler/", 5 | "github": "https://github.com/jeanmeche", 6 | "website": "https://riegler.fr" 7 | } 8 | -------------------------------------------------------------------------------- /docs/src/content/contributors/josh-morony.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Josh Morony", 3 | "twitter": "https://twitter.com/joshuamorony", 4 | "github": "https://github.com/joshuamorony", 5 | "website": "https://www.joshmorony.com" 6 | } 7 | -------------------------------------------------------------------------------- /docs/src/content/contributors/kevinkreuzer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Kevin Kreuzer", 3 | "twitter": "https://twitter.com/kreuzercode", 4 | "linkedin": "https://www.linkedin.com/in/kevin-kreuzer-a63b39121/", 5 | "github": "https://github.com/kreuzerk", 6 | "website": "https://nivek.me/" 7 | } 8 | -------------------------------------------------------------------------------- /docs/src/content/contributors/krzysztof-kachniarz.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Krzysztof Kachniarz", 3 | "twitter": "https://twitter.com/kachniarzk", 4 | "linkedin": "https://www.linkedin.com/in/krzysztof-kachniarz-094350186/", 5 | "github": "https://github.com/kkachniarz220" 6 | } 7 | -------------------------------------------------------------------------------- /docs/src/content/contributors/lilbeqiri.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ilir Beqiri", 3 | "twitter": "https://twitter.com/lilbeqiri", 4 | "linkedin": "https://www.linkedin.com/in/ilirbeqiri/", 5 | "github": "https://github.com/ilirbeqirii" 6 | } 7 | -------------------------------------------------------------------------------- /docs/src/content/contributors/lorenzo-dianni.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Lorenzo D'Ianni", 3 | "twitter": "https://x.com/lorenzodianni", 4 | "linkedin": "https://www.linkedin.com/in/lorenzo-d-ianni-3990bba6/", 5 | "github": "https://github.com/lorenzodianni" 6 | } 7 | -------------------------------------------------------------------------------- /docs/src/content/contributors/lucas-garcia.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Lucas Garcia", 3 | "twitter": "https://x.com/LcsGa_", 4 | "github": "https://github.com/LcsGa" 5 | } 6 | -------------------------------------------------------------------------------- /docs/src/content/contributors/mateusz-stefanczyk.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Mateusz Stefańczyk" 3 | } 4 | -------------------------------------------------------------------------------- /docs/src/content/contributors/michael-berger.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Michael Berger", 3 | "twitter": "https://x.com/mikelgo812", 4 | "github": "https://github.com/mikelgo", 5 | "website": "https://www.berger-engineering.io/" 6 | } 7 | -------------------------------------------------------------------------------- /docs/src/content/contributors/nevzat-topçu.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Nevzat Topçu" 3 | } 4 | -------------------------------------------------------------------------------- /docs/src/content/contributors/pawel-ostromecki.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Paweł Ostromecki", 3 | "twitter": "https://twitter.com/ostromeckyp", 4 | "linkedin": "https://www.linkedin.com/in/ostromeckyp/", 5 | "github": "https://github.com/ostromeckyp", 6 | "website": "https://ostromecki.dev" 7 | } 8 | -------------------------------------------------------------------------------- /docs/src/content/contributors/robby-rabbitman.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Robby Rabbitman", 3 | "github": "https://github.com/RobbyRabbitman" 4 | } 5 | -------------------------------------------------------------------------------- /docs/src/content/contributors/sergi-dote.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Sergi Dote Teixidor", 3 | "linkedin": "https://www.linkedin.com/in/sergidote/", 4 | "github": "https://github.com/sergidt" 5 | } 6 | -------------------------------------------------------------------------------- /docs/src/content/contributors/thomas-laforge.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Thomas Laforge", 3 | "twitter": "https://twitter.com/laforge_toma", 4 | "linkedin": "https://www.linkedin.com/in/thomas-laforge-2b05a945/", 5 | "github": "https://github.com/tomalaforge" 6 | } 7 | -------------------------------------------------------------------------------- /docs/src/content/contributors/tomer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Tomer" 3 | } 4 | -------------------------------------------------------------------------------- /docs/src/content/docs/404.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: '404' 3 | template: splash 4 | editUrl: false 5 | hero: 6 | title: '404' 7 | tagline: Page not found. Check the URL or try using the search bar. 8 | actions: 9 | - text: Go to Homepage 10 | link: / 11 | icon: right-arrow 12 | variant: primary 13 | --- 14 | -------------------------------------------------------------------------------- /docs/src/content/docs/es/getting-started/installation.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Instalación 3 | description: Cómo agregar ngxtension a tu proyecto 4 | sidebar: 5 | order: 2 6 | --- 7 | 8 | import { Tabs, TabItem } from '@astrojs/starlight/components'; 9 | 10 | ### Automático 11 | 12 | ```shell 13 | npm install -D ngxtension-plugin 14 | ``` 15 | 16 | 17 | 18 | 19 | ```shell title="Invocar el init generator" 20 | ng g ngxtension-plugin:init 21 | ``` 22 | 23 | 24 | 25 | 26 | ```shell title="Invocar el init generator" 27 | nx g ngxtension-plugin:init 28 | ``` 29 | 30 | 31 | 32 | 33 | ### Manual 34 | 35 | Instala `ngxtension` utilizando el comando anterior y luego activa `skipLibCheck: true` en el archivo tsconfig.json `root` del proyecto. 36 | 37 | > Para Nx, podría ser `tsconfig.base.json` 38 | 39 | ## Matriz de Compatibilidad 40 | 41 | WIP 42 | -------------------------------------------------------------------------------- /docs/src/content/docs/es/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Bienvenido a ngxtension 3 | template: splash 4 | hero: 5 | tagline: Una colección de utilidades para Angular. 6 | image: 7 | alt: ngxtension logo 8 | file: ../../../../public/ngxt-blue.svg 9 | dark: ../../../../public/ngxt-white.png 10 | light: ../../../../public/ngxt-blue.png 11 | 12 | actions: 13 | - text: Inicio 14 | link: /es/getting-started/introduction 15 | icon: right-arrow 16 | variant: primary 17 | - text: Ver en GitHub 18 | link: https://github.com/nartc/ngxtension-platform 19 | icon: external 20 | --- 21 | 22 | Documentation powered by [Starlight Astro](https://starlight.astro.build/). 23 | -------------------------------------------------------------------------------- /docs/src/content/docs/es/utilities/Directives/click-outside.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: clickOutside 3 | description: An Angular directive that is used to detect clicks outside the element. 4 | entryPoint: click-outside 5 | badge: stable 6 | contributors: ['dale-nguyen'] 7 | --- 8 | 9 | ## Importa la directiva 10 | 11 | ```ts 12 | import { ClickOutside } from 'ngxtension/click-outside'; 13 | ``` 14 | 15 | ## Uso 16 | 17 | ### Básico 18 | 19 | Agrega la directiva `clickOutside` al elemento Angular. 20 | 21 | ```ts 22 | @Component({ 23 | standalone: true, 24 | template: ` 25 |
26 | `, 27 | imports: [ClickOutside], 28 | }) 29 | class TestComponent { 30 | close() { 31 | // close logic 32 | } 33 | } 34 | ``` 35 | 36 | Esto activará el método `close()` cuando el usuario haga clic fuera del elemento objetivo. 37 | -------------------------------------------------------------------------------- /docs/src/content/docs/es/utilities/Injectors/inject-route-fragment.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: injectRouteFragment 3 | description: ngxtension/inject-route-fragment 4 | entryPoint: inject-route-fragment 5 | contributors: ['sergi-dote'] 6 | --- 7 | 8 | `injectRouteFragment` es una función auxiliar que nos permite inyectar el fragmento url de la ruta actual, como signal. 9 | 10 | ```ts 11 | import { injectRouteFragment } from 'ngxtension/inject-route-fragment'; 12 | ``` 13 | 14 | ## Uso 15 | 16 | `injectRouteFragment` cuando se invoca, devuelve una signal con el fragmento url actual. 17 | 18 | ```ts 19 | @Component(...) 20 | class TestComponent { 21 | fragment = injectRouteFragment(); 22 | } 23 | ``` 24 | 25 | Podemos pasar una función de transformación o un inyector personalizado. 26 | 27 | ```ts 28 | @Component() 29 | class TestComponent implements OnInit { 30 | injector = inject(Injector); 31 | 32 | ngOnInit() { 33 | const isFragmentAvailable: Signal = injectRouteFragment({ 34 | parse: (fragment) => !!fragment, 35 | injector: this.injector, 36 | }); 37 | } 38 | } 39 | ``` 40 | -------------------------------------------------------------------------------- /docs/src/content/docs/es/utilities/Miscellaneous/singleton-proxy.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: createSingletonProxy 3 | description: ngxtension/singleton-proxy 4 | badge: stable 5 | entryPoint: singleton-proxy 6 | contributors: ['chau-tran'] 7 | --- 8 | 9 | `createSingletonProxy` crea una instancia singleton de una clase dada cuando se accede a una propiedad dentro de ella, no antes. 10 | 11 | :::tip[Créditos] 12 | Crédito a [Poimandres](https://pmnd.rs/) por el código original en [R3F Rapier](https://github.com/pmndrs/react-three-rapier) 13 | ::: 14 | 15 | ## Uso 16 | 17 | ```ts 18 | import { createSingletonProxy } from 'ngxtension/singleton-proxy'; 19 | 20 | const { proxy: worldProxy, reset: resetWorld } = createSingletonProxy( 21 | () => new rapier.World([0, -9.81, 0]), 22 | ); 23 | 24 | worldProxy.gravity; // rapier.World() será creado hasta que llegue a este punto 25 | 26 | resetWorld(); // resetea la instancia 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/src/content/docs/es/utilities/Operators/filter-nil.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: filterNil 3 | description: An RxJS operator designed to filter out `undefined` and `null` values from an Observable stream, returning a strongly-typed value. 4 | entryPoint: filter-nil 5 | badge: stable 6 | contributors: ['thomas-laforge', 'sergi-dote'] 7 | --- 8 | 9 | ## Import 10 | 11 | ```ts 12 | import { filterNil } from 'ngxtension/filter-nil'; 13 | ``` 14 | 15 | ## Uso 16 | 17 | ### Básico 18 | 19 | Filtra los valores `undefined` y `null` de un stream Observable. 20 | 21 | ```ts 22 | import { of } from 'rxjs'; 23 | import { filterNil } from 'ngxtension/filter-nil'; 24 | 25 | const source$ = of(undefined, null, 1, undefined); 26 | const filtered$ = source$.pipe(filterNil()); 27 | ``` 28 | 29 | ## Ejemplos 30 | 31 | ### Ejemplo 1: Eliminar valores Undefined y Null 32 | 33 | ```ts 34 | const source$ = of(undefined, null, 1, 2, null); 35 | const filtered$ = source$.pipe(filterNil()); 36 | // Salida: 1, 2 37 | ``` 38 | 39 | ## API 40 | 41 | ### Inputs 42 | 43 | No se requiere ningún input para este operador. 44 | -------------------------------------------------------------------------------- /docs/src/content/docs/es/utilities/Signals/computed-async.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: computedAsync 3 | description: ngxtension/computed-async 4 | entryPoint: computed-async 5 | badge: stable 6 | contributors: ['enea-jahollari'] 7 | --- 8 | 9 | `computedAsync` ha sido renombrado a [`derivedAsync`](/utilities/signals/derived-async). 10 | 11 | Si quieres migrar tu código, ejecuta el siguiente comando: 12 | 13 | ```bash 14 | ng update ngxtension@latest 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/src/content/docs/es/utilities/Signals/computed-from.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: computedFrom 3 | description: ngxtension/computed-from 4 | entryPoint: computed-from 5 | badge: stable 6 | contributors: ['enea-jahollari'] 7 | --- 8 | 9 | `computedFrom` ha sido renombrado a [`derivedFrom`](/utilities/signals/derived-from). 10 | 11 | Si quieres migrar tu código, ejecuta el siguiente comando: 12 | 13 | ```bash 14 | ng update ngxtension@latest 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/src/content/docs/es/utilities/Signals/computed-previous.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: computedPrevious 3 | description: ngxtension/computed-previous 4 | entryPoint: computed-previous 5 | badge: stable 6 | contributors: ['enea-jahollari'] 7 | --- 8 | 9 | `computedPrevious` es una función de utilidad que nos retorna un `signal` thatque emite el valor previo del `signal` proporcionado. Esta utilidad es útil cuando queremos tener un registro del valor previo de un signal. 10 | Emite `null` como valor previo cuando el signal ha sido creado. 11 | 12 | ```ts 13 | import { computedPrevious } from 'ngxtension/computed-previous'; 14 | ``` 15 | 16 | ## Usage 17 | 18 | `computedPrevious` accepta un `Signal` y devuelve un `Signal` que emite el valor previo del `Signal` pasado por parámetro. 19 | 20 | ```ts 21 | const a = signal(1); 22 | const b = computedPrevious(a); 23 | 24 | console.log(b()); // null 25 | 26 | a.set(2); 27 | console.log(b()); // 1 28 | 29 | a.set(3); 30 | console.log(b()); // 2 31 | ``` 32 | 33 | ## API 34 | 35 | ```ts 36 | computedPrevious(signal: Signal): Signal 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/src/content/docs/getting-started/installation.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Installation 3 | description: How to add ngxtension to your project 4 | sidebar: 5 | order: 2 6 | --- 7 | 8 | import { Tabs, TabItem } from '@astrojs/starlight/components'; 9 | 10 | ### Automatic 11 | 12 | ```shell 13 | npm install -D ngxtension-plugin 14 | ``` 15 | 16 | 17 | 18 | 19 | ```shell title="Invoking init generator" 20 | ng g ngxtension-plugin:init 21 | ``` 22 | 23 | 24 | 25 | 26 | ```shell title="Invoking init generator" 27 | nx g ngxtension-plugin:init 28 | ``` 29 | 30 | 31 | 32 | 33 | ### Manual 34 | 35 | Install `ngxtension` using the above command then turn `skipLibCheck: true` on the project's root `tsconfig.json` 36 | 37 | > For Nx, it might be `tsconfig.base.json` 38 | 39 | ## Compatibility Matrix 40 | 41 | WIP 42 | -------------------------------------------------------------------------------- /docs/src/content/docs/logos/logos.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Press Kit 3 | --- 4 | 5 |
6 | 7 | 8 | 9 |
10 | 11 |
12 |
13 |
14 | 15 | 16 | 17 |
18 | 19 |
20 |
21 | -------------------------------------------------------------------------------- /docs/src/content/docs/utilities/Directives/click-outside.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: clickOutside 3 | description: An Angular directive that is used to detect clicks outside the element. 4 | entryPoint: ngxtension/click-outside 5 | badge: stable 6 | contributors: ['dale-nguyen'] 7 | --- 8 | 9 | ## Import 10 | 11 | ```ts 12 | import { ClickOutside } from 'ngxtension/click-outside'; 13 | ``` 14 | 15 | ## Usage 16 | 17 | ### Basic 18 | 19 | Add `clickOutside` directive directly to the Angular element. 20 | 21 | ```ts 22 | @Component({ 23 | standalone: true, 24 | template: ` 25 |
26 | `, 27 | imports: [ClickOutside], 28 | }) 29 | class TestComponent { 30 | close() { 31 | // close logic 32 | } 33 | } 34 | ``` 35 | 36 | This will trigger the `close()` method when user clicks outside of the target element. 37 | -------------------------------------------------------------------------------- /docs/src/content/docs/utilities/Injectors/inject-inputs.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: injectInputs 3 | description: ngxtension/inject-inputs 4 | entryPoint: ngxtension/inject-inputs 5 | badge: stable 6 | contributors: ['chau-tran'] 7 | --- 8 | 9 | `injectInputs` is a utility function that provides a reactive signal for all Signal Inputs in a Directive or Component as an object. This is useful for tracking the state of all Inputs in a component or directive without having to create the `computed` manually. 10 | 11 | ```ts 12 | import { injectInputs } from 'ngxtension/inject-inputs'; 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```ts 18 | @Component({ standalone: true, template: '' }) 19 | class Foo { 20 | foo = input(1); 21 | bar = input(''); 22 | 23 | inputs = injectInputs(this, Foo); 24 | 25 | constructor() { 26 | console.log(this.inputs()); // { foo: 1, bar: '' } 27 | } 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/src/content/docs/utilities/Miscellaneous/singleton-proxy.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: createSingletonProxy 3 | description: ngxtension/singleton-proxy 4 | entryPoint: ngxtension/singleton-proxy 5 | badge: stable 6 | contributors: ['chau-tran'] 7 | --- 8 | 9 | `createSingletonProxy` creates a singleton instance of a given class when a property within it is accessed, not before. 10 | 11 | :::tip[Credits] 12 | Credits to [Poimandres](https://pmnd.rs/) for the original code in [R3F Rapier](https://github.com/pmndrs/react-three-rapier) 13 | ::: 14 | 15 | ## Usage 16 | 17 | ```ts 18 | import { createSingletonProxy } from 'ngxtension/singleton-proxy'; 19 | 20 | const { proxy: worldProxy, reset: resetWorld } = createSingletonProxy( 21 | () => new rapier.World([0, -9.81, 0]), 22 | ); 23 | 24 | worldProxy.gravity; // rapier.World() won't be created until this point 25 | 26 | resetWorld(); // reset the instance 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/src/content/docs/utilities/Operators/filter-array.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: filterArray 3 | description: An RxJS operator to simplify the process of filtering arrays within an Observable stream. 4 | entryPoint: ngxtension/filter-array 5 | badge: stable 6 | contributors: ['thomas-laforge'] 7 | --- 8 | 9 | ## Import 10 | 11 | ```ts 12 | import { filterArray } from 'ngxtension/filter-array'; 13 | ``` 14 | 15 | ## Usage 16 | 17 | ### Basic 18 | 19 | Apply a filtering function to an array emitted by an Observable. 20 | 21 | ```ts 22 | import { of } from 'rxjs'; 23 | import { filterArray } from 'ngxtension/filter-array'; 24 | 25 | const source$ = of([1, 2, 3]); 26 | const filtered$ = source$.pipe(filterArray((element) => element <= 2)); 27 | ``` 28 | 29 | ## Examples 30 | 31 | ### Example 1: Filter Even Numbers 32 | 33 | ```ts 34 | const source$ = of([1, 2, 3, 4, 5]); 35 | const filtered$ = source$.pipe(filterArray((element) => element % 2 === 0)); 36 | ``` 37 | 38 | ## API 39 | 40 | ### Inputs 41 | 42 | - `filterFn: (item: T, index: number) => boolean` - A function to filter the array, similar to JavaScript's `.filter()` method. 43 | -------------------------------------------------------------------------------- /docs/src/content/docs/utilities/Operators/filter-nil.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: filterNil 3 | description: An RxJS operator designed to filter out `undefined` and `null` values from an Observable stream, returning a strongly-typed value. 4 | entryPoint: ngxtension/filter-nil 5 | badge: stable 6 | contributors: ['thomas-laforge'] 7 | --- 8 | 9 | ## Import 10 | 11 | ```ts 12 | import { filterNil } from 'ngxtension/filter-nil'; 13 | ``` 14 | 15 | ## Usage 16 | 17 | ### Basic 18 | 19 | Filter out `undefined` and `null` values from an Observable stream. 20 | 21 | ```ts 22 | import { of } from 'rxjs'; 23 | import { filterNil } from 'ngxtension/filter-nil'; 24 | 25 | const source$ = of(undefined, null, 1, undefined); 26 | const filtered$ = source$.pipe(filterNil()); 27 | ``` 28 | 29 | ## Examples 30 | 31 | ### Example 1: Removing Undefined and Null Values 32 | 33 | ```ts 34 | const source$ = of(undefined, null, 1, 2, null); 35 | const filtered$ = source$.pipe(filterNil()); 36 | // Output: 1, 2 37 | ``` 38 | 39 | ## API 40 | 41 | ### Inputs 42 | 43 | No inputs needed for this operator. 44 | -------------------------------------------------------------------------------- /docs/src/content/docs/utilities/Operators/map-array.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: mapArray 3 | description: An RxJS operator designed to apply a map function to an array within an Observable stream, simplifying array transformations. 4 | entryPoint: ngxtension/map-array 5 | badge: stable 6 | contributors: ['thomas-laforge'] 7 | --- 8 | 9 | ## Import 10 | 11 | ```ts 12 | import { mapArray } from 'ngxtension/map-array'; 13 | ``` 14 | 15 | ## Usage 16 | 17 | ### Basic 18 | 19 | Apply a map function to an array emitted by an Observable. 20 | 21 | ```ts 22 | import { of } from 'rxjs'; 23 | import { mapArray } from 'ngxtension/map-array'; 24 | 25 | const source$ = of([1, 2, 3]); 26 | const transformed$ = source$.pipe(mapArray((e) => e + 1)); 27 | ``` 28 | 29 | ## Examples 30 | 31 | ### Example 1: Double Array Elements 32 | 33 | ```ts 34 | const source$ = of([1, 2, 3]); 35 | const transformed$ = source$.pipe(mapArray((e) => e * 2)); 36 | // Output: [2, 4, 6] 37 | ``` 38 | 39 | ## API 40 | 41 | ### Inputs 42 | 43 | - `mapFn: (item: T, index: number) => R` - A function to transform each element of the array, similar to JavaScript's `.map()` method. 44 | -------------------------------------------------------------------------------- /docs/src/content/docs/utilities/Operators/poll.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: poll 3 | description: RxJS operator to apply to a stream that you want to poll every "period" milliseconds after an optional "initialDelay" milliseconds. 4 | entryPoint: ngxtension/poll 5 | badge: stable 6 | contributors: ['fabiendehopre'] 7 | --- 8 | 9 | ## Import 10 | 11 | ```typescript 12 | import { poll } from 'ngxtension/poll'; 13 | ``` 14 | 15 | ## Usage 16 | 17 | You can use this operator to poll and API at a fixed interval with an optional initial delay. 18 | 19 | ```typescript 20 | import { HttpClient } from '@angular/common/http'; 21 | import { inject } from '@angular/core'; 22 | import { poll } from 'ngxtension/poll'; 23 | 24 | const httpClient = inject(HttpClient); 25 | httpClient 26 | .get('https://api.example.com/data') 27 | .pipe( 28 | poll(10000, 5000), // poll every 10s after 5s 29 | ) 30 | .subscribe(console.log); 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/src/content/docs/utilities/Signals/computed-async.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: computedAsync 3 | description: ngxtension/computed-async 4 | entryPoint: ngxtension/computed-async 5 | badge: stable 6 | contributors: ['enea-jahollari'] 7 | --- 8 | 9 | `computedAsync` has been renamed to [`derivedAsync`](/utilities/signals/derived-async). 10 | 11 | In order to migrate your code please run the following command: 12 | 13 | ```bash 14 | ng update ngxtension@latest 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/src/content/docs/utilities/Signals/computed-from.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: computedFrom 3 | description: ngxtension/computed-from 4 | entryPoint: ngxtension/computed-from 5 | badge: stable 6 | contributors: ['enea-jahollari'] 7 | --- 8 | 9 | `computedFrom` has been renamed to [`derivedFrom`](/utilities/signals/derived-from). 10 | 11 | In order to migrate your code please run the following command: 12 | 13 | ```bash 14 | ng update ngxtension@latest 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/src/content/docs/utilities/Signals/computed-previous.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: computedPrevious 3 | description: ngxtension/computed-previous 4 | entryPoint: ngxtension/computed-previous 5 | badge: stable 6 | contributors: ['enea-jahollari'] 7 | --- 8 | 9 | `computedPrevious` is a helper function that returns a `signal` that emits the previous value of the passed `signal`. It's useful when you want to keep track of the previous value of a signal. 10 | As the initial value it will emit the current value of the signal, and then it will emit the previous value every time the signal changes. 11 | 12 | ```ts 13 | import { computedPrevious } from 'ngxtension/computed-previous'; 14 | ``` 15 | 16 | ## Usage 17 | 18 | `computedPrevious` accepts a `Signal` and returns a `Signal` that emits the previous value of the passed `Signal`. 19 | 20 | ```ts 21 | const a = signal(1); 22 | const b = computedPrevious(a); 23 | 24 | console.log(b()); // 1 25 | 26 | a.set(2); 27 | console.log(b()); // 1 28 | 29 | a.set(3); 30 | console.log(b()); // 2 31 | ``` 32 | 33 | ## API 34 | 35 | ```ts 36 | computedPrevious(signal: Signal): Signal 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/src/content/docs/utilities/Signals/effect-once-if.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: effectOnceIf 3 | description: ngxtension/effect-once-if 4 | entryPoint: effect-once-if 5 | badge: stable 6 | contributors: ['lorenzo-dianni'] 7 | --- 8 | 9 | `effectOnceIf` is a helper function that allows you to create an effect that will be executed only once if a certain condition occurs. 10 | 11 | ## Usage 12 | 13 | ```ts 14 | @Component({}) 15 | class Example { 16 | count = signal(0); 17 | 18 | effectOnceIfRef = effectOnceIf( 19 | // condition function: if it returns a truly value, the execution function will run 20 | () => this.count() > 3, 21 | // execution function: will run only once 22 | (valueReturnedFromCondition, onCleanup) => { 23 | console.log( 24 | `triggered with value returned: ${valueReturnedFromCondition}`, 25 | ); 26 | onCleanup(() => console.log('cleanup')); 27 | }, 28 | ); 29 | } 30 | 31 | // example.count.set(1); 32 | // -> nothing happens 33 | // example.count.set(4); 34 | // -> log: triggered with value returned: true 35 | // -> log: cleanup 36 | // example.count.set(6); 37 | // -> nothing happens 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /docs/src/styles/custom.css: -------------------------------------------------------------------------------- 1 | .home-links ul { 2 | list-style-type: disc; 3 | padding-left: 25px; 4 | } 5 | 6 | .home-links a { 7 | text-decoration: none; 8 | } 9 | 10 | .home-links a::after { 11 | content: ' → '; 12 | } 13 | -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strict" 3 | } 4 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | import { getJestProjectsAsync } from '@nx/jest'; 2 | 3 | export default async () => ({ 4 | projects: await getJestProjectsAsync(), 5 | }); 6 | -------------------------------------------------------------------------------- /jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nx/jest/preset').default; 2 | 3 | module.exports = { ...nxPreset }; 4 | -------------------------------------------------------------------------------- /libs/local-plugin/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "rules": {} 12 | }, 13 | { 14 | "files": ["*.js", "*.jsx"], 15 | "rules": {} 16 | }, 17 | { 18 | "files": ["*.json"], 19 | "parser": "jsonc-eslint-parser", 20 | "rules": { 21 | "@nx/nx-plugin-checks": ["error"] 22 | } 23 | }, 24 | { 25 | "files": ["./package.json", "./generators.json"], 26 | "parser": "jsonc-eslint-parser", 27 | "rules": { 28 | "@nx/nx-plugin-checks": ["error"] 29 | } 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /libs/local-plugin/README.md: -------------------------------------------------------------------------------- 1 | # local-plugin 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Building 6 | 7 | Run `nx build local-plugin` to build the library. 8 | 9 | ## Running unit tests 10 | 11 | Run `nx test local-plugin` to execute the unit tests via [Jest](https://jestjs.io). 12 | -------------------------------------------------------------------------------- /libs/local-plugin/generators.json: -------------------------------------------------------------------------------- 1 | { 2 | "generators": { 3 | "convert-entry-point-to-project": { 4 | "factory": "./src/generators/convert-entry-point-to-project/generator", 5 | "schema": "./src/generators/convert-entry-point-to-project/schema.json", 6 | "description": "convert-entry-point-to-project generator" 7 | }, 8 | "entry-point": { 9 | "factory": "./src/generators/entry-point/generator", 10 | "schema": "./src/generators/entry-point/schema.json", 11 | "description": "entry-point generator" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /libs/local-plugin/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'local-plugin', 4 | preset: '../../jest.preset.js', 5 | transform: { 6 | '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], 7 | }, 8 | moduleFileExtensions: ['ts', 'js', 'html'], 9 | coverageDirectory: '../../coverage/libs/local-plugin', 10 | }; 11 | -------------------------------------------------------------------------------- /libs/local-plugin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "local-plugin", 3 | "version": "0.0.1", 4 | "dependencies": { 5 | "@nx/devkit": "16.8.1", 6 | "tslib": "^2.3.0" 7 | }, 8 | "type": "commonjs", 9 | "main": "./src/index.js", 10 | "typings": "./src/index.d.ts", 11 | "generators": "./generators.json" 12 | } 13 | -------------------------------------------------------------------------------- /libs/local-plugin/src/generators/convert-entry-point-to-project/schema.d.ts: -------------------------------------------------------------------------------- 1 | export interface ConvertEntryPointToProjectGeneratorSchema { 2 | name: string; 3 | project: string; 4 | } 5 | -------------------------------------------------------------------------------- /libs/local-plugin/src/generators/convert-entry-point-to-project/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "ConvertEntryPointToProject", 4 | "title": "", 5 | "type": "object", 6 | "properties": { 7 | "name": { 8 | "type": "string", 9 | "description": "The name of the entry point to convert", 10 | "$default": { 11 | "$source": "argv", 12 | "index": 0 13 | }, 14 | "x-prompt": "What entry point would you like to convert to a Project?" 15 | }, 16 | "project": { 17 | "type": "string", 18 | "description": "The project that contains the entry point", 19 | "$default": { 20 | "$source": "projectName" 21 | }, 22 | "x-priority": "important", 23 | "x-prompt": "What is the project that contains the entry point?" 24 | } 25 | }, 26 | "required": ["name", "project"] 27 | } 28 | -------------------------------------------------------------------------------- /libs/local-plugin/src/generators/entry-point/generator.spec.ts: -------------------------------------------------------------------------------- 1 | import { UnitTestRunner, libraryGenerator } from '@nx/angular/generators'; 2 | import { type Tree } from '@nx/devkit'; 3 | import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; 4 | import entryPointGenerator from './generator'; 5 | 6 | describe('entry-point generator', () => { 7 | let tree: Tree; 8 | 9 | async function setup() { 10 | tree = createTreeWithEmptyWorkspace(); 11 | 12 | await libraryGenerator(tree, { 13 | name: 'main-entry', 14 | publishable: true, 15 | importPath: 'main-entry', 16 | routing: false, 17 | spec: false, 18 | skipTests: true, 19 | skipModule: true, 20 | unitTestRunner: UnitTestRunner.None, 21 | }); 22 | } 23 | 24 | it('should run successfully', async () => { 25 | await setup(); 26 | await entryPointGenerator(tree, { 27 | name: 'entry-point', 28 | library: 'main-entry', 29 | skipModule: true, 30 | }); 31 | 32 | expect(tree.exists('main-entry/entry-point/project.json')).toEqual(true); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /libs/local-plugin/src/generators/entry-point/generator.ts: -------------------------------------------------------------------------------- 1 | import { librarySecondaryEntryPointGenerator } from '@nx/angular/generators'; 2 | import type { GeneratorOptions as SecondaryEntryPointGeneratorOptions } from '@nx/angular/src/generators/library-secondary-entry-point/schema'; 3 | import { formatFiles, Tree } from '@nx/devkit'; 4 | import convertEntryPointToProjectGenerator from '../convert-entry-point-to-project/generator'; 5 | 6 | export async function entryPointGenerator( 7 | tree: Tree, 8 | options: SecondaryEntryPointGeneratorOptions, 9 | ) { 10 | await librarySecondaryEntryPointGenerator(tree, options); 11 | await convertEntryPointToProjectGenerator(tree, { 12 | name: options.name, 13 | project: options.library, 14 | }); 15 | await formatFiles(tree); 16 | } 17 | 18 | export default entryPointGenerator; 19 | -------------------------------------------------------------------------------- /libs/local-plugin/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as convertEntryPointToProjectGenerator } from './generators/convert-entry-point-to-project/generator'; 2 | export { default as entryPointGenerator } from './generators/entry-point/generator'; 3 | -------------------------------------------------------------------------------- /libs/local-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "verbatimModuleSyntax": false, 5 | "module": "commonjs" 6 | }, 7 | "files": [], 8 | "include": [], 9 | "references": [ 10 | { 11 | "path": "./tsconfig.lib.json" 12 | }, 13 | { 14 | "path": "./tsconfig.spec.json" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /libs/local-plugin/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "types": ["node"] 7 | }, 8 | "include": ["src/**/*.ts"], 9 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/local-plugin/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "jest.config.ts", 10 | "src/**/*.test.ts", 11 | "src/**/*.spec.ts", 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /libs/ngxtension/README.md: -------------------------------------------------------------------------------- 1 | # NG Extension Platform 2 | 3 | A collection of utilities for [Angular](https://angular.dev). 4 | 5 | ## Installation 6 | 7 | ```shell 8 | npm install -D ngxtension-plugin 9 | ``` 10 | 11 | ``` 12 | 13 | ```shell 14 | ng generate ngxtension-plugin:init 15 | # nx generate ngxtension-plugin:init 16 | ``` 17 | 18 | ## Utilities 19 | 20 | 21 | 22 | Check [the documentation](https://ngxtension.netlify.app/). 23 | 24 | 25 | -------------------------------------------------------------------------------- /libs/ngxtension/active-element/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/active-element 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/active-element`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/active-element/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/active-element/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/active-element", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/active-element/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["active-element"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/active-element/src/active-element.ts: -------------------------------------------------------------------------------- 1 | import { DOCUMENT } from '@angular/common'; 2 | import { inject, Injector } from '@angular/core'; 3 | import { assertInjector } from 'ngxtension/assert-injector'; 4 | import { fromEvent, map, merge, shareReplay } from 'rxjs'; 5 | 6 | export function injectActiveElement(injector?: Injector) { 7 | return assertInjector(injectActiveElement, injector, () => { 8 | const doc = inject(DOCUMENT); 9 | return merge( 10 | fromEvent(doc, 'focus', { capture: true, passive: true }).pipe( 11 | map(() => true), 12 | ), 13 | fromEvent(doc, 'blur', { capture: true, passive: true }).pipe( 14 | map(() => false), 15 | ), 16 | ).pipe( 17 | map((hasFocus) => (hasFocus ? doc.activeElement : null)), 18 | shareReplay({ refCount: true, bufferSize: 1 }), 19 | ); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /libs/ngxtension/active-element/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './active-element'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/assert-injector/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/assert-injector 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/assert-injector`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/assert-injector/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/assert-injector/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/assert-injector", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/assert-injector/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["assert-injector"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/assert-injector/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './assert-injector'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/auto-effect/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/auto-effect 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/auto-effect`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/auto-effect/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/auto-effect/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/auto-effect", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/auto-effect/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["auto-effect"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/auto-effect/src/auto-effect.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Injector, 3 | effect, 4 | inject, 5 | type CreateEffectOptions, 6 | } from '@angular/core'; 7 | import { assertInjector } from 'ngxtension/assert-injector'; 8 | 9 | export function injectAutoEffect(injector?: Injector) { 10 | return assertInjector(injectAutoEffect, injector, () => { 11 | const assertedInjector = inject(Injector); 12 | const injectorOptions = { injector: assertedInjector }; 13 | return ( 14 | autoEffectCallback: (autoEffectInjector: Injector) => void | (() => void), 15 | options: Omit = {}, 16 | ) => { 17 | return effect( 18 | (onCleanup) => { 19 | const maybeCleanup = autoEffectCallback(assertedInjector); 20 | if (typeof maybeCleanup === 'function') { 21 | onCleanup(() => maybeCleanup()); 22 | } 23 | }, 24 | Object.assign(options, injectorOptions), 25 | ); 26 | }; 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /libs/ngxtension/auto-effect/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './auto-effect'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/call-apply/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/call-apply 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/call-apply`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/call-apply/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/call-apply/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/call-apply", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/call-apply/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["call-apply"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/call-apply/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './call-apply'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/click-outside/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/click-outside 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/click-outside`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/click-outside/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/click-outside/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/click-outside", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/click-outside/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["click-outside"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/click-outside/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './click-outside'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/computed-async/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/computed-async 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/computed-async`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/computed-async/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/computed-async/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/computed-async", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/computed-async/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["computed-async"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/computed-async/src/index.ts: -------------------------------------------------------------------------------- 1 | import { derivedAsync } from 'ngxtension/derived-async'; 2 | 3 | /** 4 | * This function is deprecated. Use `derivedAsync` instead. 5 | * Run: `npx ng update ngxtension@latest` to migrate automatically. 6 | * 7 | * @deprecated Use `derivedAsync` instead. Will be removed in v3. 8 | */ 9 | const computedAsync = derivedAsync; 10 | 11 | export { computedAsync }; 12 | -------------------------------------------------------------------------------- /libs/ngxtension/computed-from/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/computed-from 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/computed-from`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/computed-from/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/computed-from/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/computed-from", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/computed-from/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["computed-from"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/computed-from/src/index.ts: -------------------------------------------------------------------------------- 1 | import { derivedFrom } from 'ngxtension/derived-from'; 2 | 3 | /** 4 | * This function is deprecated. Use `derivedFrom` instead. 5 | * Run: `npx ng update ngxtension@latest` to migrate automatically. 6 | * 7 | * @deprecated Use `derivedFrom` instead. Will be removed in v3. 8 | */ 9 | const computedFrom = derivedFrom; 10 | 11 | export { computedFrom }; 12 | -------------------------------------------------------------------------------- /libs/ngxtension/computed-previous/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/computed-previous 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/computed-previous`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/computed-previous/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/computed-previous/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/computed-previous", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/computed-previous/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["computed-previous"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/computed-previous/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './computed-previous'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/computed/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/computed 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/computed`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/computed/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/computed/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/computed", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/computed/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["computed"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/computed/src/computed.ts: -------------------------------------------------------------------------------- 1 | import type { CreateComputedOptions } from '@angular/core'; 2 | import { computed as ngComputed } from '@angular/core'; 3 | 4 | /** 5 | * @deprecated Use `linkedSignal`. Will be removed in v5 6 | * @since v4 7 | */ 8 | export function computed( 9 | computedCallback: (currentValue: TValue) => TValue, 10 | options?: CreateComputedOptions, 11 | ) { 12 | if (!options) { 13 | options = { equal: Object.is }; 14 | } 15 | 16 | let currentValue: TValue = undefined!; 17 | return ngComputed(() => { 18 | return (currentValue = computedCallback(currentValue)); 19 | }, options); 20 | } 21 | 22 | /** 23 | * @deprecated Use `linkedSignal`. Will be removed in v5 24 | * @since v4 25 | */ 26 | export const extendedComputed = computed; 27 | -------------------------------------------------------------------------------- /libs/ngxtension/computed/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './computed'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/connect/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/connect 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/connect`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/connect/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/connect/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/connect", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/connect/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["connect"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/connect/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './connect'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/control-error/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/control-error 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/control-error`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/control-error/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/control-error/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/control-error", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/control-error/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["control-error"], 13 | "passWithNoTests": false 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/control-error/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './control-error'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/control-value-accessor/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/control-value-accessor 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/control-value-accessor`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/control-value-accessor/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/control-value-accessor/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/control-value-accessor", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/control-value-accessor/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["control-value-accessor"], 13 | "passWithNoTests": false 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/control-value-accessor/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './control-value-accessor'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/create-effect/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/create-effect 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/create-effect`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/create-effect/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/create-effect/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/create-effect", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/create-effect/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["create-effect"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/create-effect/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './create-effect'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/create-injectable/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/create-injectable 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/create-injectable`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/create-injectable/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/create-injectable/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/create-injectable", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/create-injectable/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["create-injectable"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/create-injectable/src/create-injectable.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, type Type } from '@angular/core'; 2 | 3 | export function createInjectable object>( 4 | factory: TFactory, 5 | { providedIn = 'root' }: { providedIn?: 'root' | 'platform' | 'scoped' } = {}, 6 | ): Type> { 7 | @Injectable({ providedIn: providedIn === 'scoped' ? null : providedIn }) 8 | class _Injectable { 9 | constructor() { 10 | const result: any = factory(); 11 | 12 | for (const key of Reflect.ownKeys(result)) { 13 | Object.defineProperty(this, key, { 14 | get: () => result[key], 15 | set: (value: any) => { 16 | result[key] = value; 17 | }, 18 | enumerable: true, 19 | configurable: true, 20 | }); 21 | } 22 | } 23 | } 24 | 25 | if (factory.name) { 26 | Object.defineProperty(_Injectable, 'name', { 27 | value: `_Injectable_${factory.name}`, 28 | }); 29 | } 30 | 31 | return _Injectable as Type>; 32 | } 33 | -------------------------------------------------------------------------------- /libs/ngxtension/create-injectable/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './create-injectable'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/create-injection-token/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/create-injection-token 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/create-injection-token`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/create-injection-token/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/create-injection-token/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/create-injection-token", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/create-injection-token/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["create-injection-token"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/create-injection-token/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './create-injection-token'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/create-notifier/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/create-notifier 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/create-notifier`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/create-notifier/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/create-notifier/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/create-notifier", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/create-notifier/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["create-notifier"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/create-notifier/src/create-notifier.ts: -------------------------------------------------------------------------------- 1 | import { signal } from '@angular/core'; 2 | 3 | /** 4 | * Creates a signal notifier that can be used to notify effects or other consumers. 5 | * 6 | * @returns A notifier object. 7 | */ 8 | export function createNotifier() { 9 | const sourceSignal = signal(0); 10 | 11 | return { 12 | notify: () => { 13 | sourceSignal.update((v) => (v >>> 0) + 1); 14 | }, 15 | listen: sourceSignal.asReadonly(), 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /libs/ngxtension/create-notifier/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './create-notifier'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/create-repeat/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/create-repeat 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/create-repeat`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/create-repeat/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/create-repeat/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/create-repeat", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/create-repeat/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["create-repeat"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/create-repeat/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './create-repeat'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/create-signal/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/create-signal 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/create-signal`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/create-signal/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/create-signal/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/create-signal", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/create-signal/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["create-signal"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/create-signal/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './create-signal'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/debug/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/debug 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/debug`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/debug/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/debug/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/debug", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/debug/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["debug"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/debug/src/debug.ts: -------------------------------------------------------------------------------- 1 | import { tap } from 'rxjs/operators'; 2 | 3 | export type ExtraNotifications = { 4 | subscribe?: boolean; 5 | unsubscribe?: boolean; 6 | finalize?: boolean; 7 | }; 8 | 9 | //INSPIRED BY @netbasal ARTICLE https://netbasal.com/creating-custom-operators-in-rxjs-32f052d69457 10 | export function debug(tag: string, extraNotifications?: ExtraNotifications) { 11 | const formatNotif = (notif: string, data?: unknown) => [ 12 | new Date().toISOString(), 13 | `[${tag}: ${notif}]`, 14 | data, 15 | ]; 16 | return tap({ 17 | next: (value) => console.log(...formatNotif('Next', value)), 18 | error: (err) => console.error(...formatNotif('Error', err)), 19 | complete: () => console.warn(...formatNotif('Completed')), 20 | subscribe: () => 21 | extraNotifications?.subscribe && 22 | console.info(...formatNotif('Subscribed')), 23 | unsubscribe: () => 24 | extraNotifications?.unsubscribe && 25 | console.info(...formatNotif(`Unsubscribed`)), 26 | finalize: () => 27 | extraNotifications?.finalize && console.info(...formatNotif(`Finalized`)), 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /libs/ngxtension/debug/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './debug'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/derive-loading/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/derive-loading 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/derive-loading`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/derive-loading/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/derive-loading/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/derive-loading", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/derive-loading/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["derive-loading"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/derive-loading/src/index.ts: -------------------------------------------------------------------------------- 1 | export { DeriveLoadingOptions, deriveLoading } from './derive-loading'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/derived-async/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/derived-async 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/derived-async`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/derived-async/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/derived-async/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/derived-async", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/derived-async/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["derived-async"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/derived-async/src/index.ts: -------------------------------------------------------------------------------- 1 | export { derivedAsync } from './derived-async'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/derived-from/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/derived-from 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/derived-from`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/derived-from/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/derived-from/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/derived-from", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/derived-from/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["derived-from"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/derived-from/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './derived-from'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/effect-once-if/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/effect-once-if 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/effect-once-if`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/effect-once-if/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/effect-once-if/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/effect-once-if", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/effect-once-if/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["effect-once-if"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/effect-once-if/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './effect-once-if'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/explicit-effect/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/explicit-effect 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/explicit-effect`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/explicit-effect/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/explicit-effect/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/explicit-effect", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/explicit-effect/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["explicit-effect"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/explicit-effect/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './explicit-effect'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/filter-array/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/filter-array 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/filter-array`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/filter-array/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/filter-array/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/filter-array", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/filter-array/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["filter-array"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/filter-array/src/filter-array.spec.ts: -------------------------------------------------------------------------------- 1 | import { of } from 'rxjs'; 2 | import { filterArray } from './filter-array'; 3 | 4 | describe(filterArray.name, () => { 5 | const dummyObs = of([1, 2, 3]); 6 | 7 | it('given an observable of [1,2,3] and a function filtering each element above 2, then result is an observable of [1,2]', (done) => { 8 | const result = dummyObs.pipe(filterArray((n) => n <= 2)); 9 | 10 | result.subscribe((r) => { 11 | expect(r).toEqual([1, 2]); 12 | done(); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /libs/ngxtension/filter-array/src/filter-array.ts: -------------------------------------------------------------------------------- 1 | import { map } from 'rxjs'; 2 | 3 | export const filterArray = (filterFn: (item: T, index: number) => boolean) => 4 | map((array: T[]) => array.filter((item, index) => filterFn(item, index))); 5 | -------------------------------------------------------------------------------- /libs/ngxtension/filter-array/src/index.ts: -------------------------------------------------------------------------------- 1 | export { filterArray } from './filter-array'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/filter-nil/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/filter-nil 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/filter-nil`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/filter-nil/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/filter-nil/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/filter-nil", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/filter-nil/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["filter-nil"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/filter-nil/src/filter-nil.spec.ts: -------------------------------------------------------------------------------- 1 | import { of } from 'rxjs'; 2 | import { filterNil } from './filter-nil'; 3 | 4 | describe(filterNil.name, () => { 5 | it('given an observable of undefined, null, 1, then only value 1 is expected', (done) => { 6 | const dummyObs = of(undefined, null, 1); 7 | const result = dummyObs.pipe(filterNil()); 8 | 9 | result.subscribe((r) => { 10 | expect(r).toEqual(1); 11 | done(); 12 | }); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /libs/ngxtension/filter-nil/src/filter-nil.ts: -------------------------------------------------------------------------------- 1 | import { filter } from 'rxjs'; 2 | 3 | export const filterNil = () => 4 | filter( 5 | (value: T): value is NonNullable => 6 | value !== undefined && value !== null, 7 | ); 8 | -------------------------------------------------------------------------------- /libs/ngxtension/filter-nil/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './filter-nil'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/form-events/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/form-events 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/form-events`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/form-events/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/form-events/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/form-events", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/form-events/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["form-events"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/form-events/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './form-events'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/gestures/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/gestures 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/gestures`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/gestures/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/gestures/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/gestures", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/gestures/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["gestures"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/gestures/src/drag.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Directive, 3 | EventEmitter, 4 | Injector, 5 | Input, 6 | Output, 7 | inject, 8 | signal, 9 | type OnInit, 10 | } from '@angular/core'; 11 | import { DragGesture } from '@use-gesture/vanilla'; 12 | import { createGesture, type GestureInfer } from './gesture'; 13 | 14 | export const injectDrag = createGesture('drag', DragGesture); 15 | export type NgxInjectDrag = GestureInfer; 16 | 17 | @Directive({ 18 | selector: '[ngxDrag]', 19 | standalone: true, 20 | }) 21 | export class NgxDrag implements OnInit { 22 | private config = signal({}); 23 | @Input('ngxDragConfig') set _config(config: NgxInjectDrag['config']) { 24 | this.config.set(config); 25 | } 26 | @Input('ngxDragZoneless') zoneless?: boolean; 27 | @Output() ngxDrag = new EventEmitter(); 28 | 29 | private injector = inject(Injector); 30 | 31 | ngOnInit(): void { 32 | injectDrag(this.ngxDrag.emit.bind(this.ngxDrag), { 33 | injector: this.injector, 34 | zoneless: this.zoneless, 35 | config: this.config, 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /libs/ngxtension/gestures/src/hover.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Directive, 3 | EventEmitter, 4 | Injector, 5 | Input, 6 | Output, 7 | inject, 8 | signal, 9 | type OnInit, 10 | } from '@angular/core'; 11 | import { HoverGesture } from '@use-gesture/vanilla'; 12 | import { createGesture, type GestureInfer } from './gesture'; 13 | 14 | export const injectHover = createGesture('hover', HoverGesture); 15 | export type NgxInjectHover = GestureInfer; 16 | 17 | @Directive({ 18 | selector: '[ngxHover]', 19 | standalone: true, 20 | }) 21 | export class NgxHover implements OnInit { 22 | private config = signal({}); 23 | @Input('ngxHoverConfig') set _config(config: NgxInjectHover['config']) { 24 | this.config.set(config); 25 | } 26 | @Input('ngxHoverZoneless') zoneless?: boolean; 27 | @Output() ngxHover = new EventEmitter(); 28 | 29 | private injector = inject(Injector); 30 | 31 | ngOnInit(): void { 32 | injectHover(this.ngxHover.emit.bind(this.ngxHover), { 33 | injector: this.injector, 34 | zoneless: this.zoneless, 35 | config: this.config, 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /libs/ngxtension/gestures/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './drag'; 2 | export * from './hover'; 3 | export * from './move'; 4 | export * from './pinch'; 5 | export * from './scroll'; 6 | export * from './wheel'; 7 | export * from './zoneless-gesture'; 8 | -------------------------------------------------------------------------------- /libs/ngxtension/gestures/src/move.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Directive, 3 | EventEmitter, 4 | Injector, 5 | Input, 6 | Output, 7 | inject, 8 | signal, 9 | type OnInit, 10 | } from '@angular/core'; 11 | import { MoveGesture } from '@use-gesture/vanilla'; 12 | import { createGesture, type GestureInfer } from './gesture'; 13 | 14 | export const injectMove = createGesture('move', MoveGesture); 15 | export type NgxInjectMove = GestureInfer; 16 | 17 | @Directive({ 18 | selector: '[ngxMove]', 19 | standalone: true, 20 | }) 21 | export class NgxMove implements OnInit { 22 | private config = signal({}); 23 | @Input('ngxMoveConfig') set _config(config: NgxInjectMove['config']) { 24 | this.config.set(config); 25 | } 26 | @Input('ngxMoveZoneless') zoneless?: boolean; 27 | @Output() ngxMove = new EventEmitter(); 28 | 29 | private injector = inject(Injector); 30 | 31 | ngOnInit(): void { 32 | injectMove(this.ngxMove.emit.bind(this.ngxMove), { 33 | injector: this.injector, 34 | zoneless: this.zoneless, 35 | config: this.config, 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /libs/ngxtension/gestures/src/pinch.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Directive, 3 | EventEmitter, 4 | Injector, 5 | Input, 6 | Output, 7 | inject, 8 | signal, 9 | type OnInit, 10 | } from '@angular/core'; 11 | import { PinchGesture } from '@use-gesture/vanilla'; 12 | import { createGesture, type GestureInfer } from './gesture'; 13 | 14 | export const injectPinch = createGesture('pinch', PinchGesture); 15 | export type NgxInjectPinch = GestureInfer; 16 | 17 | @Directive({ 18 | selector: '[ngxPinch]', 19 | standalone: true, 20 | }) 21 | export class NgxPinch implements OnInit { 22 | private config = signal({}); 23 | @Input('ngxPinchConfig') set _config(config: NgxInjectPinch['config']) { 24 | this.config.set(config); 25 | } 26 | @Input('ngxPinchZoneless') zoneless?: boolean; 27 | @Output() ngxPinch = new EventEmitter(); 28 | 29 | private injector = inject(Injector); 30 | 31 | ngOnInit(): void { 32 | injectPinch(this.ngxPinch.emit.bind(this.ngxPinch), { 33 | injector: this.injector, 34 | zoneless: this.zoneless, 35 | config: this.config, 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /libs/ngxtension/gestures/src/zoneless-gesture.ts: -------------------------------------------------------------------------------- 1 | import { createInjectionToken } from 'ngxtension/create-injection-token'; 2 | 3 | const [injectZonelessGesture, provideFn] = createInjectionToken(() => false); 4 | 5 | function provideZonelessGesture() { 6 | return provideFn(true); 7 | } 8 | 9 | export { injectZonelessGesture, provideZonelessGesture }; 10 | -------------------------------------------------------------------------------- /libs/ngxtension/host-binding/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/host-binding 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/host-binding`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/host-binding/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/host-binding/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/host-binding", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/host-binding/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["host-binding"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/host-binding/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './host-binding'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/if-validator/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/if-validator 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/if-validator`. -------------------------------------------------------------------------------- /libs/ngxtension/if-validator/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/if-validator/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/if-validator", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/if-validator/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["if-validator"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/if-validator/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './if-validator'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-destroy/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/inject-destroy 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/inject-destroy`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-destroy/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-destroy/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/inject-destroy", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/inject-destroy/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["inject-destroy"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-destroy/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './inject-destroy'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-document-visibility/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/inject-document-visibility 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/inject-document-visibility`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-document-visibility/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-document-visibility/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/inject-document-visibility", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/inject-document-visibility/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["inject-document-visibility"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-document-visibility/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './inject-document-visibility'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-inputs/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/inject-inputs 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/inject-inputs`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-inputs/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-inputs/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/inject-inputs", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/inject-inputs/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["inject-inputs"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-inputs/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/inject-inputs'; 2 | export * from './lib/merge-inputs'; 3 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-inputs/src/lib/merge-inputs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * `mergeInputs` is meant to be used as a `transform` function for Object-input (input with object value) 3 | */ 4 | export function mergeInputs( 5 | defaultValue: TInputs = {} as TInputs, 6 | ): (value: '' | Partial) => TInputs { 7 | return (value: '' | Partial) => { 8 | // NOTE: if the directive is used as `
` without binding syntax 9 | // then the bound value is `''` in which case we'll return the `defaultValue` for the input 10 | if (value === '') return defaultValue; 11 | return { ...defaultValue, ...value }; 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-is-intersecting/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/inject-is-intersecting 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/inject-is-intersecting`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-is-intersecting/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-is-intersecting/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/inject-is-intersecting", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/inject-is-intersecting/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["inject-is-intersecting"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-is-intersecting/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './inject-is-intersecting'; 2 | export * from './is-in-viewport.service'; 3 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-lazy/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/inject-lazy 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/inject-lazy`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-lazy/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-lazy/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/inject-lazy", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/inject-lazy/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["inject-lazy"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-lazy/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './inject-lazy'; 2 | export * from './inject-lazy-impl'; 3 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-local-storage/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/inject-local-storage 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/inject-local-storage`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-local-storage/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-local-storage/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/inject-local-storage", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/inject-local-storage/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["inject-local-storage"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-local-storage/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './inject-local-storage'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-network/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/inject-network 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/inject-network`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-network/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-network/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/inject-network", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/inject-network/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["inject-network"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-network/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './inject-network'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-params/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/inject-params 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/inject-params`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-params/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-params/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/inject-params", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/inject-params/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["inject-params"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-params/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './inject-params'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-query-params/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/inject-query-params 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/inject-query-params`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-query-params/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-query-params/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/inject-query-params", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/inject-query-params/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["inject-query-params"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-query-params/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './inject-query-params'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-route-data/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/inject-route-data 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/inject-route-data`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-route-data/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-route-data/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/inject-route-data", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/inject-route-data/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["inject-route-data"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-route-data/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './inject-route-data'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-route-fragment/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/inject-route-fragment 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/inject-route-fragment`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-route-fragment/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-route-fragment/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/inject-route-fragment", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/inject-route-fragment/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["inject-route-fragment"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-route-fragment/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './inject-route-fragment'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-text-selection/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/inject-text-selection 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/inject-text-selection`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-text-selection/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-text-selection/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/inject-text-selection", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/inject-text-selection/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["inject-text-selection"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/inject-text-selection/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './inject-text-selection'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/intl/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/intl 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/intl`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/intl/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/intl/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/intl", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/intl/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["intl"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/intl/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './display-names.pipe'; 2 | export * from './list-format.pipe'; 3 | export * from './plural-rules.pipe'; 4 | export * from './relative-time-format.pipe'; 5 | export * from './supportedValuesOf.pipe'; 6 | -------------------------------------------------------------------------------- /libs/ngxtension/intl/src/supportedValuesOf.spec.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { TestBed } from '@angular/core/testing'; 3 | import { By } from '@angular/platform-browser'; 4 | import { SupportedValuesOf } from './supportedValuesOf.pipe'; 5 | 6 | @Component({ 7 | standalone: true, 8 | template: ` 9 |

{{ 'currency' | supportedValuesOf }}

10 |

{{ 'unit' | supportedValuesOf }}

11 | `, 12 | imports: [SupportedValuesOf], 13 | }) 14 | class TestComponent {} 15 | 16 | describe(SupportedValuesOf.name, () => { 17 | it('should display the supported values of the type', () => { 18 | const fixture = TestBed.createComponent(TestComponent); 19 | fixture.detectChanges(); 20 | 21 | const elP = fixture.debugElement.queryAll(By.css('p')); 22 | expect(elP[0].nativeElement.textContent).toContain('USD'); 23 | expect(elP[1].nativeElement.textContent).toContain('meter'); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /libs/ngxtension/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'ngxtension', 4 | preset: '../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | coverageDirectory: '../../coverage/libs/ngxtension', 7 | transform: { 8 | '^.+\\.(ts|mjs|js|html)$': [ 9 | 'jest-preset-angular', 10 | { 11 | tsconfig: '/tsconfig.spec.json', 12 | stringifyContentPathRegex: '\\.(html|svg)$', 13 | }, 14 | ], 15 | }, 16 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 17 | snapshotSerializers: [ 18 | 'jest-preset-angular/build/serializers/no-ng-attributes', 19 | 'jest-preset-angular/build/serializers/ng-snapshot', 20 | 'jest-preset-angular/build/serializers/html-comment', 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /libs/ngxtension/linked-query-param/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/linked-query-param 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/linked-query-param`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/linked-query-param/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/linked-query-param/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/linked-query-param", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/linked-query-param/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["linked-query-param"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/linked-query-param/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './linked-query-param'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/map-array/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/map-array 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/map-array`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/map-array/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/map-array/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/map-array", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/map-array/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["map-array"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/map-array/src/index.ts: -------------------------------------------------------------------------------- 1 | export { mapArray } from './map-array'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/map-array/src/map-array.spec.ts: -------------------------------------------------------------------------------- 1 | import { combineLatest, of } from 'rxjs'; 2 | import { mapArray } from './map-array'; 3 | 4 | describe(mapArray.name, () => { 5 | const dummyObs = of([1, 2, 3]); 6 | 7 | it('given an observable of [1,2,3] and a mapping function of adding 1 to each element, then result is an observable of [2,3,4], [2, 4, 6] with index', (done) => { 8 | const result = dummyObs.pipe(mapArray((n) => n + 1)); 9 | const resultWithIndex = dummyObs.pipe(mapArray((n, i) => n + 1 + i)); 10 | 11 | combineLatest([result, resultWithIndex]).subscribe(([r, rI]) => { 12 | expect(r).toEqual([2, 3, 4]); 13 | expect(rI).toEqual([2, 4, 6]); 14 | done(); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /libs/ngxtension/map-array/src/map-array.ts: -------------------------------------------------------------------------------- 1 | import { map } from 'rxjs'; 2 | 3 | export const mapArray = (mapFn: (item: T, index: number) => R) => 4 | map((array: T[]) => array.map((item, index) => mapFn(item, index))); 5 | -------------------------------------------------------------------------------- /libs/ngxtension/map-skip-undefined/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/map-skip-undefined 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/map-skip-undefined`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/map-skip-undefined/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/map-skip-undefined/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/map-skip-undefined", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/map-skip-undefined/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["map-skip-undefined"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/map-skip-undefined/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './map-skip-undefined'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/map-skip-undefined/src/map-skip-undefined.ts: -------------------------------------------------------------------------------- 1 | import { type Observable } from 'rxjs'; 2 | import { filter, map } from 'rxjs/operators'; 3 | 4 | export const filterUndefined = () => 5 | filter((value: T): value is Exclude => value !== undefined); 6 | 7 | export function mapSkipUndefined( 8 | fnTrasformSkipUndefined: (value: T) => R, 9 | ) { 10 | return function (source: Observable) { 11 | return source.pipe(map(fnTrasformSkipUndefined), filterUndefined()); 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /libs/ngxtension/merge-from/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/merge-from 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/merge-from`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/merge-from/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/merge-from/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/merge-from", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/merge-from/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["merge-from"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/merge-from/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/merge-from'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/merge-http-context/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/merge-http-context 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/merge-http-context`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/merge-http-context/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/merge-http-context/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/merge-http-context", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/merge-http-context/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["merge-http-context"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/merge-http-context/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './merge-http-context'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/merge-http-context/src/merge-http-context.ts: -------------------------------------------------------------------------------- 1 | import { HttpContext } from '@angular/common/http'; 2 | 3 | /** 4 | * Merge multiple HttpContext. 5 | * 6 | * @param contexts Two or more http contexts to be merged. 7 | * @returns A merged HttpContext. 8 | * 9 | */ 10 | 11 | export function mergeHttpContext(...contexts: HttpContext[]): HttpContext { 12 | return contexts.reduce((prev, curr) => { 13 | Array.from(curr.keys()).forEach((contextToken) => 14 | prev.set(contextToken, curr.get(contextToken)), 15 | ); 16 | return prev; 17 | }, new HttpContext()); 18 | } 19 | -------------------------------------------------------------------------------- /libs/ngxtension/navigation-end/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/navigation-end 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/navigation-end`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/navigation-end/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/navigation-end/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/navigation-end", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/navigation-end/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["navigation-end"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/navigation-end/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './navigation-end'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/navigation-end/src/navigation-end.ts: -------------------------------------------------------------------------------- 1 | import { Injector, inject, runInInjectionContext } from '@angular/core'; 2 | import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; 3 | import { NavigationEnd, Router, type Event } from '@angular/router'; 4 | import { assertInjector } from 'ngxtension/assert-injector'; 5 | import { filter, type Observable } from 'rxjs'; 6 | 7 | /** 8 | * Creates an Observable that emits when a navigation ends. 9 | * @returns An Observable of NavigationEnd events. 10 | */ 11 | export function injectNavigationEnd( 12 | injector?: Injector, 13 | ): Observable { 14 | injector = assertInjector(injectNavigationEnd, injector); 15 | return runInInjectionContext(injector, () => { 16 | return inject(Router).events.pipe( 17 | filter( 18 | (event: Event): event is NavigationEnd => 19 | event instanceof NavigationEnd, 20 | ), 21 | takeUntilDestroyed(), 22 | ); 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /libs/ngxtension/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/ngxtension", 4 | "lib": { 5 | "entryFile": "src/index.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /libs/ngxtension/not-pattern/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/not-pattern 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/not-pattern`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/not-pattern/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/not-pattern/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/not-pattern", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/not-pattern/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["not-pattern"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/not-pattern/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './not-pattern'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension", 3 | "description": "Utilities library for Angular", 4 | "version": "0.0.0-replace", 5 | "engines": { 6 | "node": ">=18" 7 | }, 8 | "repository": "ngxtension/ngxtension-platform", 9 | "homepage": "https://ngxtension.netlify.app", 10 | "license": "MIT", 11 | "keywords": [ 12 | "ng2", 13 | "ngx", 14 | "ngxtension", 15 | "angular", 16 | "typescript", 17 | "rxjs", 18 | "signals" 19 | ], 20 | "peerDependencies": { 21 | "@angular/common": ">=16.0.0", 22 | "@angular/core": ">=16.0.0", 23 | "@use-gesture/vanilla": "^10.0.0", 24 | "rxjs": "^6.0.0 || ^7.0.0" 25 | }, 26 | "peerDependenciesMeta": { 27 | "@use-gesture/vanilla": { 28 | "optional": true 29 | } 30 | }, 31 | "dependencies": { 32 | "tslib": "^2.3.0" 33 | }, 34 | "sideEffects": false 35 | } 36 | -------------------------------------------------------------------------------- /libs/ngxtension/poll/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/poll 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/poll`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/poll/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/poll/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/poll", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/poll/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["poll"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/poll/src/index.ts: -------------------------------------------------------------------------------- 1 | export { poll } from './poll'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/poll/src/poll.ts: -------------------------------------------------------------------------------- 1 | import { concatMap, MonoTypeOperatorFunction, Observable, timer } from 'rxjs'; 2 | // source: https://netbasal.com/use-rxjs-to-modify-app-behavior-based-on-page-visibility-ce499c522be4 3 | 4 | /** 5 | * RxJS operator to apply to a stream that you want to poll every "period" milliseconds after an optional "initialDelay" milliseconds. 6 | * 7 | * @param period - Indicates the delay between 2 polls. 8 | * @param initialDelay - Indicates the delay before the first poll occurs. 9 | * @example This example shows how to do an HTTP GET every 5 seconds: 10 | * ```ts 11 | * http.get('http://api').pipe(poll(5000)).subscribe(result => {}); 12 | * ``` 13 | * @public 14 | */ 15 | export function poll( 16 | period: number, 17 | initialDelay = 0, 18 | ): MonoTypeOperatorFunction { 19 | // eslint-disable-next-line @typescript-eslint/no-unsafe-argument 20 | return (source: Observable) => { 21 | return timer(initialDelay, period).pipe(concatMap(() => source)); 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /libs/ngxtension/reduce-array/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/reduce-array 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/reduce-array`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/reduce-array/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/reduce-array/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/reduce-array", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/reduce-array/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["reduce-array"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/reduce-array/src/index.ts: -------------------------------------------------------------------------------- 1 | export { reduceArray } from './reduce-array'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/reduce-array/src/reduce-array.ts: -------------------------------------------------------------------------------- 1 | import { map, type Observable } from 'rxjs'; 2 | 3 | type Reduce = Array['reduce']; 4 | 5 | export function reduceArray( 6 | reduceFn: (acc: T, item: T, index: number) => T, 7 | ): (source: Observable) => Observable; 8 | 9 | export function reduceArray( 10 | reduceFn: (acc: R, item: T, index: number) => R, 11 | initialValue: R, 12 | ): (source: Observable) => Observable; 13 | 14 | export function reduceArray( 15 | reduceFn: Parameters[0], 16 | initialValue?: Parameters[1], 17 | ) { 18 | return map((array: Array) => { 19 | // call reduce function with initialValue 20 | if (initialValue !== undefined) { 21 | return array.reduce(reduceFn, initialValue); 22 | } 23 | // no initialValue 24 | 25 | // Javascript throws error if array is empty: [].reduce((acc,n) => acc +n) 26 | // avoid errors and return undefined 27 | if (!array.length) { 28 | return undefined; 29 | } 30 | // if array is not empty, call the reduceFn without initialValue 31 | return array.reduce(reduceFn); 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /libs/ngxtension/repeat-pipe/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/repeat-pipe 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/repeat-pipe`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/repeat-pipe/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/repeat-pipe/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/repeat-pipe", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/repeat-pipe/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["repeat-pipe"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/repeat-pipe/src/index.ts: -------------------------------------------------------------------------------- 1 | export { RepeatPipe } from './repeat-pipe'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/repeat/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/repeat 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/repeat`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/repeat/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/repeat/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/repeat", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/repeat/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["repeat"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/repeat/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './repeat'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/repeat/src/repeat.spec.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { TestBed } from '@angular/core/testing'; 3 | import { By } from '@angular/platform-browser'; 4 | import { Repeat } from './repeat'; 5 | 6 | describe(Repeat.name, () => { 7 | @Component({ 8 | standalone: true, 9 | template: ` 10 |

{{ i }}

11 | `, 12 | imports: [Repeat], 13 | }) 14 | class Dummy {} 15 | 16 | it('given 3, when render, then render 3 items', () => { 17 | const fixture = TestBed.createComponent(Dummy); 18 | fixture.detectChanges(); 19 | 20 | const items = fixture.debugElement.queryAll(By.css('p')); 21 | expect(items).toHaveLength(3); 22 | items.forEach((item, i) => { 23 | expect(item.nativeElement.textContent).toContain(i.toString()); 24 | }); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /libs/ngxtension/repeat/src/repeat.ts: -------------------------------------------------------------------------------- 1 | import { NgFor } from '@angular/common'; 2 | import { Directive, Input } from '@angular/core'; 3 | 4 | /** 5 | * An extension of `NgFor` directive that allows consumers to iterate "x times" instead of through a list of items 6 | * 7 | * @param {number} count - a positive integer starting from 0 8 | * 9 | * @example 10 | * 11 | * ```html 12 | * 13 | *

{{i}}

14 | * 15 | *

{{i}}

16 | * ``` 17 | */ 18 | @Directive({ 19 | standalone: true, 20 | selector: '[ngFor][ngForRepeat]', 21 | }) 22 | export class Repeat extends NgFor { 23 | @Input() set ngForRepeat(count: number) { 24 | if (Number.isNaN(count) || !Number.isInteger(count)) { 25 | throw new Error( 26 | `[Repeat] repeat requires an integer but ${count} is passed in`, 27 | ); 28 | } 29 | this.ngForOf = Array.from({ length: count }, (_, i) => i); 30 | this.ngForTrackBy = (i) => i; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /libs/ngxtension/resize/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/resize 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/resize`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/resize/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/resize/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/resize", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/resize/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["resize"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/resize/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './resize'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/rx-effect/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/rx-effect 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/rx-effect`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/rx-effect/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/rx-effect/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/rx-effect", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/rx-effect/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["rx-effect"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/rx-effect/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './rx-effect'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/shared/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/shared 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/shared`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/shared/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/shared/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/shared", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/shared/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["shared"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/shared/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './options'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/shared/src/options/default-value.ts: -------------------------------------------------------------------------------- 1 | export type DefaultValueOptions = { 2 | /** 3 | * The default value to use 4 | */ 5 | defaultValue?: DefaultValueT; 6 | }; 7 | -------------------------------------------------------------------------------- /libs/ngxtension/shared/src/options/index.ts: -------------------------------------------------------------------------------- 1 | export * from './default-value'; 2 | export * from './injector'; 3 | export * from './parse'; 4 | -------------------------------------------------------------------------------- /libs/ngxtension/shared/src/options/injector.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The optional "custom" Injector. If this is not provided, will be retrieved from the current injection context 3 | */ 4 | import type { Injector } from '@angular/core'; 5 | 6 | export type InjectorOptions = { 7 | injector?: Injector; 8 | }; 9 | -------------------------------------------------------------------------------- /libs/ngxtension/shared/src/options/parse.ts: -------------------------------------------------------------------------------- 1 | export type ParseOptions = { 2 | /** 3 | * A function to convert the written value to the expected read value. 4 | * 5 | * @param v - The value to parse. 6 | * @returns The parsed value. 7 | */ 8 | parse?: (v: WriteT) => ReadT; 9 | }; 10 | -------------------------------------------------------------------------------- /libs/ngxtension/signal-history/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/signal-history 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/signal-history`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/signal-history/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/signal-history/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/signal-history", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/signal-history/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["signal-history"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/signal-history/src/index.ts: -------------------------------------------------------------------------------- 1 | export { signalHistory } from './signal-history'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/signal-slice/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/signal-slice 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/signal-slice`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/signal-slice/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/signal-slice/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/signal-slice", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/signal-slice/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["signal-slice"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/signal-slice/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './signal-slice'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/singleton-proxy/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/singleton-proxy 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/singleton-proxy`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/singleton-proxy/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/singleton-proxy/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/singleton-proxy", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/singleton-proxy/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["singleton-proxy"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/singleton-proxy/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './singleton-proxy'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/src/index.ts: -------------------------------------------------------------------------------- 1 | export default void 0; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/svg-sprite/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/svg-sprite 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/svg-sprite`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/svg-sprite/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/svg-sprite/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/svg-sprite", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/svg-sprite/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["svg-sprite"], 13 | "passWithNoTests": false 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/svg-sprite/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './svg-sprite'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/take-latest-from/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/take-latest-from 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/take-latest-from`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/take-latest-from/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/take-latest-from/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/take-latest-from", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/take-latest-from/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["take-latest-from"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/take-latest-from/src/index.ts: -------------------------------------------------------------------------------- 1 | export { takeLatestFrom } from './take-latest-from'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/to-lazy-signal/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/to-lazy-signal 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/to-lazy-signal`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/to-lazy-signal/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/to-lazy-signal/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/to-lazy-signal", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/to-lazy-signal/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["to-lazy-signal"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/to-lazy-signal/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './to-lazy-signal'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/to-observable-signal/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/to-observable-signal 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/to-observable-signal`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/to-observable-signal/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/to-observable-signal/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/to-observable-signal", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/to-observable-signal/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["to-observable-signal"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/to-observable-signal/src/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | toObservableSignal, 3 | type ObservableSignal, 4 | } from './to-observable-signal'; 5 | -------------------------------------------------------------------------------- /libs/ngxtension/trackby-id-prop/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/trackby-id-prop 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/trackby-id-prop`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/trackby-id-prop/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/trackby-id-prop/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/trackby-id-prop", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/trackby-id-prop/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["trackby-id-prop"] 13 | } 14 | }, 15 | "lint": { 16 | "executor": "@nx/eslint:lint", 17 | "outputs": ["{options.outputFile}"] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngxtension/trackby-id-prop/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './trackby-id-prop'; 2 | -------------------------------------------------------------------------------- /libs/ngxtension/trackby-id-prop/src/trackby-id-prop.ts: -------------------------------------------------------------------------------- 1 | //INSPIRED BY https://medium.com/ngconf/make-trackby-easy-to-use-a3dd5f1f733b 2 | import { NgForOf } from '@angular/common'; 3 | import { Directive, Input, inject, type NgIterable } from '@angular/core'; 4 | 5 | @Directive({ 6 | selector: '[ngForTrackById]', 7 | standalone: true, 8 | }) 9 | export class TrackById { 10 | @Input() ngForOf!: NgIterable; 11 | private ngFor = inject(NgForOf, { self: true }); 12 | 13 | constructor() { 14 | this.ngFor.ngForTrackBy = (index: number, item: T) => item.id; 15 | } 16 | } 17 | 18 | @Directive({ 19 | selector: '[ngForTrackByProp]', 20 | standalone: true, 21 | }) 22 | export class TrackByProp { 23 | @Input() ngForOf!: NgIterable; 24 | private ngFor = inject(NgForOf, { self: true }); 25 | 26 | @Input({ required: true }) 27 | set ngForTrackByProp(trackByProp: keyof T) { 28 | if (!trackByProp) return; 29 | this.ngFor.ngForTrackBy = (index: number, item: T) => item[trackByProp]; 30 | } 31 | } 32 | 33 | export const TRACK_BY_DIRECTIVES = [TrackById, TrackByProp] as const; 34 | -------------------------------------------------------------------------------- /libs/ngxtension/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true 11 | }, 12 | "files": [], 13 | "include": [], 14 | "references": [ 15 | { 16 | "path": "./tsconfig.lib.json" 17 | }, 18 | { 19 | "path": "./tsconfig.spec.json" 20 | } 21 | ], 22 | "extends": "../../tsconfig.base.json", 23 | "angularCompilerOptions": { 24 | "enableI18nLegacyMessageIdFormat": false, 25 | "strictInjectionParameters": true, 26 | "strictInputAccessModifiers": true, 27 | "strictTemplates": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /libs/ngxtension/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "inlineSources": true, 8 | "types": [] 9 | }, 10 | "exclude": [ 11 | "**/*.spec.ts", 12 | "test-setup.ts", 13 | "jest.config.ts", 14 | "**/*.test.ts" 15 | ], 16 | "include": ["**/*.ts"] 17 | } 18 | -------------------------------------------------------------------------------- /libs/ngxtension/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "compilerOptions": { 4 | "declarationMap": false 5 | }, 6 | "angularCompilerOptions": { 7 | "compilationMode": "partial" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /libs/ngxtension/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "verbatimModuleSyntax": false, 6 | "module": "commonjs", 7 | "target": "es2016", 8 | "noImplicitReturns": false, 9 | "types": ["jest", "node"] 10 | }, 11 | "files": ["src/test-setup.ts"], 12 | "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] 13 | } 14 | -------------------------------------------------------------------------------- /libs/ngxtension/when-document-visible/README.md: -------------------------------------------------------------------------------- 1 | # ngxtension/when-document-visible 2 | 3 | Secondary entry point of `ngxtension`. It can be used by importing from `ngxtension/when-document-visible`. 4 | -------------------------------------------------------------------------------- /libs/ngxtension/when-document-visible/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "lib": { 3 | "entryFile": "src/index.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /libs/ngxtension/when-document-visible/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension/when-document-visible", 3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngxtension/when-document-visible/src", 6 | "targets": { 7 | "test": { 8 | "executor": "@nx/jest:jest", 9 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 10 | "options": { 11 | "jestConfig": "libs/ngxtension/jest.config.ts", 12 | "testPathPattern": ["when-document-visible"], 13 | "passWithNoTests": true 14 | }, 15 | "configurations": { 16 | "ci": { 17 | "ci": true, 18 | "codeCoverage": true 19 | } 20 | } 21 | }, 22 | "lint": { 23 | "executor": "@nx/eslint:lint", 24 | "outputs": ["{options.outputFile}"] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libs/ngxtension/when-document-visible/src/index.ts: -------------------------------------------------------------------------------- 1 | export { whenDocumentVisible } from './when-document-visible'; 2 | -------------------------------------------------------------------------------- /libs/plugin/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "rules": {} 12 | }, 13 | { 14 | "files": ["*.js", "*.jsx"], 15 | "rules": {} 16 | }, 17 | { 18 | "files": ["*.json"], 19 | "parser": "jsonc-eslint-parser", 20 | "rules": { 21 | "@nx/dependency-checks": [ 22 | "warn", 23 | { 24 | "ignoredDependencies": [ 25 | "tslib", 26 | "ts-morph", 27 | "@angular-eslint/bundled-angular-compiler", 28 | "@nx/devkit", 29 | "@nx/dependency-checks" 30 | ] 31 | } 32 | ] 33 | } 34 | }, 35 | { 36 | "files": ["./package.json", "./generators.json"], 37 | "parser": "jsonc-eslint-parser", 38 | "rules": { 39 | "@nx/nx-plugin-checks": "warn" 40 | } 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /libs/plugin/README.md: -------------------------------------------------------------------------------- 1 | # plugin 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Building 6 | 7 | Run `nx build plugin` to build the library. 8 | 9 | ## Running unit tests 10 | 11 | Run `nx test plugin` to execute the unit tests via [Jest](https://jestjs.io). 12 | -------------------------------------------------------------------------------- /libs/plugin/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'plugin', 4 | preset: '../../jest.preset.js', 5 | transform: { 6 | '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], 7 | }, 8 | moduleFileExtensions: ['ts', 'js', 'html'], 9 | coverageDirectory: '../../coverage/libs/plugin', 10 | }; 11 | -------------------------------------------------------------------------------- /libs/plugin/migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "generators": { 3 | "rename-document-visibility": { 4 | "version": "1.7.0", 5 | "description": "Rename 'injectDocumentVisibility' import", 6 | "implementation": "./src/migrations/rename-document-visibility/rename-document-visibility" 7 | }, 8 | "rename-computed": { 9 | "version": "3.0.1", 10 | "description": "Rename 'computedFrom' and 'computedAsync' to 'derivedFrom' and 'derivedAsync'", 11 | "implementation": "./src/migrations/rename-computeds/rename-computeds" 12 | } 13 | }, 14 | "schematics": { 15 | "rename-document-visibility": { 16 | "version": "1.7.0", 17 | "description": "Rename 'injectDocumentVisibility' import", 18 | "factory": "./src/migrations/rename-document-visibility/compat" 19 | }, 20 | "rename-computed": { 21 | "version": "3.0.1", 22 | "description": "Rename 'computedFrom' and 'computedAsync' to 'derivedFrom' and 'derivedAsync'", 23 | "factory": "./src/migrations/rename-computeds/compat" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /libs/plugin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngxtension-plugin", 3 | "version": "0.0.0-replace", 4 | "type": "commonjs", 5 | "dependencies": { 6 | "@angular-eslint/bundled-angular-compiler": "^18.0.1", 7 | "@nx/devkit": "^20.0.0", 8 | "nx": "^20.0.0", 9 | "ts-morph": "^22.0.0" 10 | }, 11 | "main": "./src/index.js", 12 | "types": "./src/index.d.ts", 13 | "exports": { 14 | "./package.json": "./package.json", 15 | ".": { 16 | "types": "./src/index.d.ts", 17 | "default": "./src/index.js" 18 | }, 19 | "./generators": { 20 | "types": "./src/generators/index.d.ts", 21 | "default": "./src/generators/index.js" 22 | } 23 | }, 24 | "generators": "./generators.json", 25 | "schematics": "./generators.json", 26 | "nx-migrations": { 27 | "migrations": "./migrations.json" 28 | }, 29 | "ng-update": { 30 | "migrations": "./migrations.json" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-di-to-inject/compat.ts: -------------------------------------------------------------------------------- 1 | import { convertNxGenerator } from '@nx/devkit'; 2 | import convertDiToInjectGenerator from './generator'; 3 | 4 | export default convertNxGenerator(convertDiToInjectGenerator); 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-di-to-inject/schema.d.ts: -------------------------------------------------------------------------------- 1 | export interface ConvertDiToInjectGeneratorSchema { 2 | project?: string; 3 | path?: string; 4 | includeReadonlyByDefault?: boolean; 5 | useEsprivateFieldNotation?: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-di-to-inject/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "", 4 | "title": "", 5 | "type": "object", 6 | "properties": { 7 | "project": { 8 | "type": "string", 9 | "aliases": ["name", "projectName"], 10 | "description": "Project for which to convert from constructor DI to inject function." 11 | }, 12 | "path": { 13 | "type": "string", 14 | "description": "Path to the component/directive/pipe you want to convert to use the inject function" 15 | }, 16 | "includeReadonlyByDefault": { 17 | "type": "boolean", 18 | "aliases": ["includeReadonly", "includeReadonlyByDefault"], 19 | "description": "Whether to include readonly for injections by default. Default is false." 20 | }, 21 | "useEsprivateFieldNotation": { 22 | "type": "boolean", 23 | "aliases": [ 24 | "useESPrivateFieldNotation", 25 | "useEsprivateFieldNotation", 26 | "useEsPrivateFieldNotation" 27 | ], 28 | "description": "Whether to replace TS private modifier with ES private field notation. Default is false." 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-host-binding/compat.ts: -------------------------------------------------------------------------------- 1 | import { convertNxGenerator } from '@nx/devkit'; 2 | import { convertHostBindingGenerator } from './generator'; 3 | 4 | export default convertNxGenerator(convertHostBindingGenerator); 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-host-binding/schema.d.ts: -------------------------------------------------------------------------------- 1 | export interface ConvertHostBindingGeneratorSchema { 2 | project?: string; 3 | path?: string; 4 | } 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-host-binding/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "ConvertHostBinding", 4 | "title": "", 5 | "type": "object", 6 | "properties": { 7 | "project": { 8 | "type": "string", 9 | "aliases": ["name", "projectName"], 10 | "description": "Project for which to convert from host binding to host property." 11 | }, 12 | "path": { 13 | "type": "string", 14 | "description": "Path to the component/directive you want to convert to use the host property." 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-outputs/compat.ts: -------------------------------------------------------------------------------- 1 | import { convertNxGenerator } from '@nx/devkit'; 2 | import convertOutputsGenerator from './generator'; 3 | 4 | export default convertNxGenerator(convertOutputsGenerator); 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-outputs/schema.d.ts: -------------------------------------------------------------------------------- 1 | export interface ConvertOutputsGeneratorSchema { 2 | project?: string; 3 | path?: string; 4 | } 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-outputs/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "", 4 | "title": "", 5 | "type": "object", 6 | "properties": { 7 | "project": { 8 | "type": "string", 9 | "aliases": ["name", "projectName"], 10 | "description": "Project for which to convert to new outputs." 11 | }, 12 | "path": { 13 | "type": "string", 14 | "description": "Path to the component/directive you want to convert to use new outputs" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-queries/compat.ts: -------------------------------------------------------------------------------- 1 | import { convertNxGenerator } from '@nx/devkit'; 2 | import convertQueriesGenerator from './generator'; 3 | 4 | export default convertNxGenerator(convertQueriesGenerator); 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-queries/schema.d.ts: -------------------------------------------------------------------------------- 1 | export interface ConvertContentQueriesGeneratorSchema { 2 | project?: string; 3 | path?: string; 4 | } 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-queries/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "", 4 | "title": "", 5 | "type": "object", 6 | "properties": { 7 | "project": { 8 | "type": "string", 9 | "aliases": ["name", "projectName"], 10 | "description": "Project for which to convert to new content queries." 11 | }, 12 | "path": { 13 | "type": "string", 14 | "description": "Path to the component/directive you want to convert to use new content queries." 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-signal-inputs/compat.ts: -------------------------------------------------------------------------------- 1 | import { convertNxGenerator } from '@nx/devkit'; 2 | import convertSignalInputsGenerator from './generator'; 3 | 4 | export default convertNxGenerator(convertSignalInputsGenerator); 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-signal-inputs/schema.d.ts: -------------------------------------------------------------------------------- 1 | export interface ConvertSignalInputsGeneratorSchema { 2 | project?: string; 3 | path?: string; 4 | } 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-signal-inputs/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "", 4 | "title": "", 5 | "type": "object", 6 | "properties": { 7 | "project": { 8 | "type": "string", 9 | "aliases": ["name", "projectName"], 10 | "description": "Project for which to convert signal inputs." 11 | }, 12 | "path": { 13 | "type": "string", 14 | "description": "Path to the component/directive you want to conver to signal inputs" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-to-self-closing-tag/compat.ts: -------------------------------------------------------------------------------- 1 | import { convertNxGenerator } from '@nx/devkit'; 2 | import convertGenerator from './generator'; 3 | 4 | export default convertNxGenerator(convertGenerator); 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-to-self-closing-tag/schema.d.ts: -------------------------------------------------------------------------------- 1 | export interface ConvertToSelfClosingTagGeneratorSchema { 2 | project?: string; 3 | path?: string; 4 | } 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-to-self-closing-tag/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "", 4 | "title": "", 5 | "type": "object", 6 | "properties": { 7 | "project": { 8 | "type": "string", 9 | "aliases": ["name", "projectName"], 10 | "description": "Project for which to convert to self closing tags." 11 | }, 12 | "path": { 13 | "type": "string", 14 | "description": "Path to the component/directive you want to convert to self closing tags" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-to-sfc/compat.ts: -------------------------------------------------------------------------------- 1 | import { convertNxGenerator } from '@nx/devkit'; 2 | import convertGenerator from './generator'; 3 | 4 | export default convertNxGenerator(convertGenerator); 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-to-sfc/schema.d.ts: -------------------------------------------------------------------------------- 1 | export interface ConvertToSFCGeneratorSchema { 2 | project?: string; 3 | path?: string; 4 | moveStyles?: boolean; 5 | maxInlineTemplateLines?: number; 6 | maxInlineStyleLines?: number; 7 | } 8 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/convert-to-sfc/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "", 4 | "title": "", 5 | "type": "object", 6 | "properties": { 7 | "project": { 8 | "type": "string", 9 | "aliases": ["name", "projectName"], 10 | "description": "Project for which to convert to single file components." 11 | }, 12 | "path": { 13 | "type": "string", 14 | "description": "Path to the component to convert to a single file component." 15 | }, 16 | "maxInlineTemplateLines": { 17 | "type": "number", 18 | "description": "If the template has more lines than this, it will be skipped.", 19 | "default": 200 20 | }, 21 | "maxInlineStyleLines": { 22 | "type": "number", 23 | "description": "If the styles have more lines than this, they will be skipped.", 24 | "default": 200 25 | }, 26 | "moveStyles": { 27 | "type": "boolean", 28 | "description": "Move styles to the single file component.", 29 | "default": false 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/init/compat.ts: -------------------------------------------------------------------------------- 1 | import { convertNxGenerator } from '@nx/devkit'; 2 | import init from './generator'; 3 | 4 | export default convertNxGenerator(init); 5 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/init/generator.spec.ts: -------------------------------------------------------------------------------- 1 | import { Tree, readJson } from '@nx/devkit'; 2 | import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; 3 | 4 | import { initGenerator } from './generator'; 5 | 6 | describe('init generator', () => { 7 | let tree: Tree; 8 | 9 | beforeEach(() => { 10 | tree = createTreeWithEmptyWorkspace(); 11 | }); 12 | 13 | it('should run successfully', async () => { 14 | await initGenerator(tree); 15 | const packageJson = readJson(tree, 'package.json'); 16 | expect(packageJson.dependencies['ngxtension']).toEqual('latest'); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/init/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "Init", 4 | "title": "Init" 5 | } 6 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/shared-utils/contents-store.ts: -------------------------------------------------------------------------------- 1 | import { Project } from 'ts-morph'; 2 | 3 | export class ContentsStore { 4 | private _project: Project = null!; 5 | 6 | collection: Array<{ path: string; content: string }> = []; 7 | withTransforms = new Set(); 8 | 9 | get project() { 10 | if (!this._project) { 11 | this._project = new Project({ useInMemoryFileSystem: true }); 12 | } 13 | 14 | return this._project; 15 | } 16 | 17 | track(path: string, content: string) { 18 | this.collection.push({ path, content }); 19 | this.project.createSourceFile(path, content, { overwrite: true }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /libs/plugin/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as initGenerator } from './generators/init/generator'; 2 | -------------------------------------------------------------------------------- /libs/plugin/src/migrations/rename-computeds/compat.ts: -------------------------------------------------------------------------------- 1 | import { convertNxGenerator } from '@nx/devkit'; 2 | import update from './rename-computeds'; 3 | 4 | export default convertNxGenerator(update); 5 | -------------------------------------------------------------------------------- /libs/plugin/src/migrations/rename-document-visibility/compat.ts: -------------------------------------------------------------------------------- 1 | import { convertNxGenerator } from '@nx/devkit'; 2 | import update from './rename-document-visibility'; 3 | 4 | export default convertNxGenerator(update); 5 | -------------------------------------------------------------------------------- /libs/plugin/src/migrations/rename-document-visibility/rename-document-visibility.ts: -------------------------------------------------------------------------------- 1 | import { 2 | formatFiles, 3 | getProjects, 4 | visitNotIgnoredFiles, 5 | type Tree, 6 | } from '@nx/devkit'; 7 | 8 | export default async function update(host: Tree) { 9 | const projects = getProjects(host); 10 | 11 | for (const [, projectConfiguration] of projects.entries()) { 12 | visitNotIgnoredFiles(host, projectConfiguration.root, (path) => { 13 | if (path.endsWith('.ts')) { 14 | const content = host.read(path, 'utf8'); 15 | const updatedContent = content.replace( 16 | /ngxtension\/document-visibility-state/g, 17 | 'ngxtension/inject-document-visibility', 18 | ); 19 | 20 | if (updatedContent !== content) { 21 | host.write(path, updatedContent); 22 | } 23 | } 24 | }); 25 | } 26 | 27 | await formatFiles(host); 28 | } 29 | -------------------------------------------------------------------------------- /libs/plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "verbatimModuleSyntax": false, 5 | "module": "commonjs" 6 | }, 7 | "files": [], 8 | "include": [], 9 | "references": [ 10 | { 11 | "path": "./tsconfig.lib.json" 12 | }, 13 | { 14 | "path": "./tsconfig.spec.json" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /libs/plugin/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "types": ["node"] 7 | }, 8 | "include": ["src/**/*.ts"], 9 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/plugin/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "jest.config.ts", 10 | "src/**/*.test.ts", 11 | "src/**/*.spec.ts", 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "migrations": [ 3 | { 4 | "version": "20.0.1", 5 | "description": "Set `useLegacyCache` to true for migrating workspaces", 6 | "implementation": "./src/migrations/update-20-0-1/use-legacy-cache", 7 | "x-repair-skip": true, 8 | "package": "nx", 9 | "name": "use-legacy-cache" 10 | } 11 | ] 12 | } 13 | --------------------------------------------------------------------------------