├── .all-contributorsrc ├── .commitlintrc.json ├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug-report.md │ ├── feature-request.md │ └── ui-package.md └── workflows │ └── release.yml ├── .gitignore ├── .husky ├── commit-msg └── post-checkout ├── .nvmrc ├── .prettierignore ├── .prettierrc ├── .vscode ├── extensions.json └── settings.json ├── CODE_OF_CONDUCT.md ├── DEVELOPMENT.md ├── LICENSE ├── README.md ├── apps └── website │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── jest.config.ts │ ├── project.json │ ├── server.ts │ ├── src │ ├── app │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── app.server.module.ts │ │ ├── bootstrap-breakpoints.ts │ │ ├── demos │ │ │ ├── components │ │ │ │ └── index │ │ │ │ │ ├── index.component.html │ │ │ │ │ ├── index.component.scss │ │ │ │ │ └── index.component.ts │ │ │ ├── demos.module.ts │ │ │ └── submodules │ │ │ │ └── dyn-forms │ │ │ │ ├── components │ │ │ │ ├── builder │ │ │ │ │ ├── builder.component.html │ │ │ │ │ ├── builder.component.scss │ │ │ │ │ ├── builder.component.spec.ts │ │ │ │ │ ├── builder.component.ts │ │ │ │ │ ├── builder.form.ts │ │ │ │ │ └── business.types.ts │ │ │ │ ├── combo │ │ │ │ │ ├── combo.component.html │ │ │ │ │ ├── combo.component.scss │ │ │ │ │ ├── combo.component.spec.ts │ │ │ │ │ ├── combo.component.ts │ │ │ │ │ ├── combo.form.ts │ │ │ │ │ └── combo.service.ts │ │ │ │ ├── simple │ │ │ │ │ ├── simple.component.html │ │ │ │ │ ├── simple.component.scss │ │ │ │ │ ├── simple.component.spec.ts │ │ │ │ │ ├── simple.component.ts │ │ │ │ │ └── simple.form.ts │ │ │ │ ├── single │ │ │ │ │ ├── single.component.html │ │ │ │ │ ├── single.component.scss │ │ │ │ │ ├── single.component.spec.ts │ │ │ │ │ ├── single.component.ts │ │ │ │ │ ├── single.form.ts │ │ │ │ │ └── success.control │ │ │ │ │ │ ├── success.component.html │ │ │ │ │ │ ├── success.component.scss │ │ │ │ │ │ └── success.component.ts │ │ │ │ └── stepper │ │ │ │ │ ├── step1 │ │ │ │ │ ├── step1.component.html │ │ │ │ │ ├── step1.component.scss │ │ │ │ │ ├── step1.component.spec.ts │ │ │ │ │ └── step1.component.ts │ │ │ │ │ ├── step2 │ │ │ │ │ ├── step2.component.html │ │ │ │ │ ├── step2.component.scss │ │ │ │ │ ├── step2.component.spec.ts │ │ │ │ │ └── step2.component.ts │ │ │ │ │ ├── stepper.component.html │ │ │ │ │ ├── stepper.component.scss │ │ │ │ │ ├── stepper.component.spec.ts │ │ │ │ │ ├── stepper.component.ts │ │ │ │ │ ├── stepper.form.ts │ │ │ │ │ └── summary │ │ │ │ │ ├── summary.component.html │ │ │ │ │ ├── summary.component.scss │ │ │ │ │ ├── summary.component.spec.ts │ │ │ │ │ └── summary.component.ts │ │ │ │ ├── constants │ │ │ │ └── dyn-forms.links.ts │ │ │ │ └── dyn-forms.module.ts │ │ ├── docs │ │ │ ├── components │ │ │ │ ├── content │ │ │ │ │ ├── content.component.html │ │ │ │ │ ├── content.component.scss │ │ │ │ │ └── content.component.ts │ │ │ │ ├── example │ │ │ │ │ ├── example.component.html │ │ │ │ │ ├── example.component.scss │ │ │ │ │ └── example.component.ts │ │ │ │ ├── layout │ │ │ │ │ ├── layout.component.html │ │ │ │ │ ├── layout.component.scss │ │ │ │ │ └── layout.component.ts │ │ │ │ ├── stackblitz │ │ │ │ │ ├── stackblitz.component.html │ │ │ │ │ ├── stackblitz.component.scss │ │ │ │ │ └── stackblitz.component.ts │ │ │ │ └── viewer │ │ │ │ │ ├── viewer.component.html │ │ │ │ │ ├── viewer.component.scss │ │ │ │ │ └── viewer.component.ts │ │ │ ├── docs.module.ts │ │ │ ├── interfaces │ │ │ │ ├── index.ts │ │ │ │ ├── metadata.interfaces.ts │ │ │ │ └── nav.interfaces.ts │ │ │ └── services │ │ │ │ ├── content.service.ts │ │ │ │ ├── i18n.service.ts │ │ │ │ └── index.ts │ │ ├── layout │ │ │ ├── components │ │ │ │ ├── footer │ │ │ │ │ ├── footer.component.html │ │ │ │ │ ├── footer.component.scss │ │ │ │ │ └── footer.component.ts │ │ │ │ ├── header │ │ │ │ │ ├── header.component.html │ │ │ │ │ ├── header.component.scss │ │ │ │ │ └── header.component.ts │ │ │ │ ├── index.ts │ │ │ │ ├── prompt │ │ │ │ │ ├── prompt-data.interface.ts │ │ │ │ │ ├── prompt.dialog.html │ │ │ │ │ ├── prompt.dialog.scss │ │ │ │ │ └── prompt.dialog.ts │ │ │ │ ├── section-actions │ │ │ │ │ ├── section-action.interface.ts │ │ │ │ │ ├── section-actions.component.html │ │ │ │ │ ├── section-actions.component.scss │ │ │ │ │ └── section-actions.component.ts │ │ │ │ └── section-badges │ │ │ │ │ ├── section-badge.interface.ts │ │ │ │ │ ├── section-badges.component.html │ │ │ │ │ ├── section-badges.component.scss │ │ │ │ │ └── section-badges.component.ts │ │ │ ├── containers │ │ │ │ ├── index.ts │ │ │ │ └── wrapper │ │ │ │ │ ├── wrapper.component.html │ │ │ │ │ ├── wrapper.component.scss │ │ │ │ │ └── wrapper.component.ts │ │ │ ├── index.ts │ │ │ └── layout.module.ts │ │ └── pages │ │ │ ├── components │ │ │ ├── docs │ │ │ │ ├── docs.component.html │ │ │ │ ├── docs.component.scss │ │ │ │ └── docs.component.ts │ │ │ ├── homepage │ │ │ │ ├── homepage.component.html │ │ │ │ ├── homepage.component.scss │ │ │ │ └── homepage.component.ts │ │ │ └── not-found │ │ │ │ ├── not-found.component.html │ │ │ │ ├── not-found.component.scss │ │ │ │ └── not-found.component.ts │ │ │ ├── index.ts │ │ │ └── pages.module.ts │ ├── assets │ │ ├── banners │ │ │ └── home-stats.svg │ │ ├── logo.png │ │ └── logos │ │ │ ├── bbb.svg │ │ │ ├── eho.svg │ │ │ ├── fb.svg │ │ │ ├── github.svg │ │ │ ├── linkedin.svg │ │ │ ├── netlify.svg │ │ │ └── tw.svg │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.jpg │ ├── index.html │ ├── main.server.ts │ ├── main.ts │ ├── material.scss │ ├── polyfills.ts │ ├── prism-mynd.css │ ├── styles.scss │ └── test-setup.ts │ ├── tsconfig.app.json │ ├── tsconfig.app.prod.json │ ├── tsconfig.editor.json │ ├── tsconfig.json │ ├── tsconfig.server.json │ └── tsconfig.spec.json ├── docs ├── docs.json ├── dyn-forms │ ├── examples │ │ └── basic │ │ │ ├── README.es.md │ │ │ └── README.md │ ├── intro │ │ ├── 1-getting-started.es.md │ │ ├── 1-getting-started.md │ │ ├── 2-controls.md │ │ ├── 3-modes.md │ │ ├── 3-params.md │ │ ├── 4-validators.md │ │ ├── 5-matchers.md │ │ ├── 6-conditions.md │ │ ├── 7-debugging.md │ │ ├── 7-events.md │ │ ├── 8-layout.md │ │ └── 9-schematics.md │ └── ui │ │ ├── packages │ │ └── README.md │ │ └── ui-material │ │ └── README.md ├── myndpm-dyn-forms-packages.svg └── myndpm-dyn-forms-sequence.svg ├── jest.config.ts ├── jest.preset.js ├── libs ├── demos │ ├── .eslintrc.json │ ├── README.md │ ├── dyn-forms │ │ ├── README.md │ │ ├── basic │ │ │ └── intro │ │ │ │ ├── app.component.html │ │ │ │ ├── app.component.scss │ │ │ │ ├── app.component.ts │ │ │ │ ├── app.module.ts │ │ │ │ ├── form.config.ts │ │ │ │ ├── index.json │ │ │ │ ├── index.ts │ │ │ │ └── ng-package.json │ │ ├── index.ts │ │ └── ng-package.json │ ├── example-data.ts │ ├── examples.json │ ├── index.ts │ ├── ng-package.json │ ├── package.json │ ├── project.json │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.lib.prod.json ├── forms │ ├── .eslintrc.json │ ├── CHANGELOG.md │ ├── README.md │ ├── TODO.md │ ├── core │ │ ├── index.ts │ │ ├── ng-package.json │ │ └── src │ │ │ ├── dyn-control-base.class.ts │ │ │ ├── dyn-control-wrapper.class.ts │ │ │ ├── dyn-control.class.ts │ │ │ ├── dyn-form-array.class.ts │ │ │ ├── dyn-form-container.class.ts │ │ │ ├── dyn-form-control.class.ts │ │ │ ├── dyn-form-group.class.ts │ │ │ ├── dyn-form-node.class.ts │ │ │ ├── dyn-providers.ts │ │ │ ├── form-control-node.service.ts │ │ │ ├── form-factory.service.ts │ │ │ ├── form-handlers.service.ts │ │ │ ├── form-registry.service.ts │ │ │ ├── form-resolver.service.ts │ │ │ ├── form.tokens.ts │ │ │ ├── hidden │ │ │ ├── control.component.ts │ │ │ └── group.component.ts │ │ │ ├── module.providers.ts │ │ │ ├── types │ │ │ ├── config.types.ts │ │ │ ├── control.types.ts │ │ │ ├── events.types.ts │ │ │ ├── forms.types.ts │ │ │ ├── matcher.types.ts │ │ │ ├── mode.types.ts │ │ │ ├── node.types.ts │ │ │ ├── params.types.ts │ │ │ ├── provider.types.ts │ │ │ ├── templates.types.ts │ │ │ ├── utils │ │ │ │ ├── option.types.ts │ │ │ │ └── tree.types.ts │ │ │ ├── validation.types.ts │ │ │ └── wrapper.types.ts │ │ │ └── utils │ │ │ ├── config.utils.ts │ │ │ ├── hidden.util.ts │ │ │ ├── merge.util.ts │ │ │ ├── rxjs.utils.ts │ │ │ └── tree.utils.ts │ ├── index.tests.ts │ ├── index.ts │ ├── jest.config.ts │ ├── lib │ │ ├── components │ │ │ ├── factory │ │ │ │ ├── factory.directive.spec.ts │ │ │ │ └── factory.directive.ts │ │ │ ├── form │ │ │ │ ├── form.component.html │ │ │ │ ├── form.component.scss │ │ │ │ ├── form.component.spec.ts │ │ │ │ ├── form.component.ts │ │ │ │ └── form.config.ts │ │ │ ├── group │ │ │ │ ├── group.component.html │ │ │ │ ├── group.component.spec.ts │ │ │ │ └── group.component.ts │ │ │ └── index.ts │ │ ├── dyn-forms.module.ts │ │ ├── migrations │ │ │ ├── 12_4_1 │ │ │ │ └── index.ts │ │ │ └── 12_6_1 │ │ │ │ └── index.ts │ │ └── schematics │ │ │ ├── control │ │ │ ├── files │ │ │ │ └── __name@dasherize@if-flat__ │ │ │ │ │ ├── __name@dasherize__.__type@dasherize__.__style__.template │ │ │ │ │ ├── __name@dasherize__.__type@dasherize__.html.template │ │ │ │ │ ├── __name@dasherize__.__type@dasherize__.params.ts.template │ │ │ │ │ ├── __name@dasherize__.__type@dasherize__.spec.ts.template │ │ │ │ │ └── __name@dasherize__.__type@dasherize__.ts.template │ │ │ ├── index.ts │ │ │ ├── schema.json │ │ │ └── schema.ts │ │ │ └── module │ │ │ ├── files │ │ │ └── __name@dasherize@if-flat__ │ │ │ │ ├── __name@dasherize__.factory.ts.template │ │ │ │ └── __name@dasherize__.module.ts.template │ │ │ ├── index.ts │ │ │ ├── schema.json │ │ │ └── schema.ts │ ├── logger │ │ ├── README.md │ │ ├── index.ts │ │ ├── ng-package.json │ │ └── src │ │ │ ├── interfaces │ │ │ └── node.interface.ts │ │ │ ├── log-driver.service.ts │ │ │ ├── log-level.token.ts │ │ │ ├── log-levels.constant.ts │ │ │ ├── log.interface.ts │ │ │ └── logger.service.ts │ ├── migrations.json │ ├── ng-package.json │ ├── package.json │ ├── project.json │ ├── schematics.json │ ├── testing │ │ ├── dyn-forms-testing.module.ts │ │ ├── form │ │ │ └── form-testing.component.ts │ │ ├── index.ts │ │ └── ng-package.json │ ├── tsconfig.json │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.schematics.json │ ├── tsconfig.spec.json │ ├── ui-bootstrap │ │ ├── index.ts │ │ ├── ng-package.json │ │ └── src │ │ │ ├── controls │ │ │ ├── checkbox │ │ │ │ ├── checkbox.component.html │ │ │ │ ├── checkbox.component.params.ts │ │ │ │ ├── checkbox.component.scss │ │ │ │ └── checkbox.component.ts │ │ │ ├── index.ts │ │ │ ├── input │ │ │ │ ├── input.component.html │ │ │ │ ├── input.component.params.ts │ │ │ │ ├── input.component.scss │ │ │ │ └── input.component.ts │ │ │ ├── radio │ │ │ │ ├── radio.component.html │ │ │ │ ├── radio.component.params.ts │ │ │ │ ├── radio.component.scss │ │ │ │ └── radio.component.ts │ │ │ └── select │ │ │ │ ├── select.component.html │ │ │ │ ├── select.component.params.ts │ │ │ │ ├── select.component.scss │ │ │ │ └── select.component.ts │ │ │ ├── dyn-forms-bootstrap.factory.ts │ │ │ └── dyn-forms-bootstrap.module.ts │ ├── ui-material │ │ ├── index.ts │ │ ├── ng-package.json │ │ └── src │ │ │ ├── controls │ │ │ ├── array │ │ │ │ ├── array.component.html │ │ │ │ ├── array.component.params.ts │ │ │ │ ├── array.component.scss │ │ │ │ ├── array.component.spec.ts │ │ │ │ └── array.component.ts │ │ │ ├── card │ │ │ │ ├── card.component.html │ │ │ │ ├── card.component.params.ts │ │ │ │ ├── card.component.scss │ │ │ │ ├── card.component.spec.ts │ │ │ │ └── card.component.ts │ │ │ ├── checkbox │ │ │ │ ├── checkbox.component.html │ │ │ │ ├── checkbox.component.params.ts │ │ │ │ ├── checkbox.component.scss │ │ │ │ ├── checkbox.component.spec.ts │ │ │ │ └── checkbox.component.ts │ │ │ ├── container │ │ │ │ ├── container.component.html │ │ │ │ ├── container.component.params.ts │ │ │ │ ├── container.component.scss │ │ │ │ ├── container.component.spec.ts │ │ │ │ └── container.component.ts │ │ │ ├── datepicker │ │ │ │ ├── datepicker.component.html │ │ │ │ ├── datepicker.component.params.ts │ │ │ │ ├── datepicker.component.scss │ │ │ │ ├── datepicker.component.spec.ts │ │ │ │ └── datepicker.component.ts │ │ │ ├── divider │ │ │ │ ├── divider.component.html │ │ │ │ ├── divider.component.params.ts │ │ │ │ ├── divider.component.scss │ │ │ │ └── divider.component.ts │ │ │ ├── index.ts │ │ │ ├── input │ │ │ │ ├── input.component.html │ │ │ │ ├── input.component.params.ts │ │ │ │ ├── input.component.scss │ │ │ │ ├── input.component.spec.ts │ │ │ │ └── input.component.ts │ │ │ ├── multicheckbox │ │ │ │ ├── multicheckbox.component.html │ │ │ │ ├── multicheckbox.component.params.ts │ │ │ │ ├── multicheckbox.component.scss │ │ │ │ ├── multicheckbox.component.spec.ts │ │ │ │ └── multicheckbox.component.ts │ │ │ ├── radio │ │ │ │ ├── radio.component.html │ │ │ │ ├── radio.component.params.ts │ │ │ │ ├── radio.component.scss │ │ │ │ ├── radio.component.spec.ts │ │ │ │ └── radio.component.ts │ │ │ ├── select │ │ │ │ ├── select.component.html │ │ │ │ ├── select.component.params.ts │ │ │ │ ├── select.component.scss │ │ │ │ ├── select.component.spec.ts │ │ │ │ └── select.component.ts │ │ │ ├── table-row │ │ │ │ ├── table-row.component.html │ │ │ │ └── table-row.component.ts │ │ │ └── table │ │ │ │ ├── table.component.html │ │ │ │ ├── table.component.params.ts │ │ │ │ ├── table.component.scss │ │ │ │ └── table.component.ts │ │ │ ├── dyn-forms-material.factory.ts │ │ │ ├── dyn-forms-material.module.ts │ │ │ └── wrappers │ │ │ ├── form-field │ │ │ ├── form-field.component.html │ │ │ ├── form-field.component.params.ts │ │ │ ├── form-field.component.scss │ │ │ └── form-field.component.ts │ │ │ └── index.ts │ └── ui-native │ │ ├── index.ts │ │ ├── ng-package.json │ │ └── src │ │ ├── controls │ │ ├── index.ts │ │ └── input │ │ │ ├── input.component.html │ │ │ ├── input.component.params.ts │ │ │ ├── input.component.scss │ │ │ ├── input.component.spec.ts │ │ │ └── input.component.ts │ │ ├── dyn-forms-native.factory.ts │ │ └── dyn-forms-native.module.ts ├── plugin │ ├── .babelrc │ ├── .eslintrc.json │ ├── CHANGELOG.md │ ├── README.md │ ├── executors.json │ ├── generators.json │ ├── jest.config.ts │ ├── package.json │ ├── project.json │ ├── src │ │ ├── executors │ │ │ ├── deploy-docker │ │ │ │ ├── executor.spec.ts │ │ │ │ ├── executor.ts │ │ │ │ ├── schema.d.ts │ │ │ │ └── schema.json │ │ │ └── deploy-npm │ │ │ │ ├── executor.ts │ │ │ │ ├── lib │ │ │ │ ├── deployer.spec.ts │ │ │ │ ├── deployer.ts │ │ │ │ └── engine.ts │ │ │ │ ├── schema.d.ts │ │ │ │ ├── schema.json │ │ │ │ └── utils │ │ │ │ ├── default-options.ts │ │ │ │ ├── index.ts │ │ │ │ ├── lib-paths.ts │ │ │ │ └── package-json.ts │ │ ├── generators │ │ │ └── nx │ │ │ │ ├── files │ │ │ │ └── src │ │ │ │ │ └── index.ts__template__ │ │ │ │ ├── generator.spec.ts │ │ │ │ ├── generator.ts │ │ │ │ ├── schema.d.ts │ │ │ │ └── schema.json │ │ └── index.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json └── utils │ ├── .babelrc │ ├── .eslintrc.json │ ├── CHANGELOG.md │ ├── README.md │ ├── jest.config.ts │ ├── package.json │ ├── project.json │ ├── src │ ├── index.ts │ ├── json.ts │ ├── rxjs-fs.ts │ ├── rxjs-shell.ts │ └── rxjs-tree.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json ├── netlify.toml ├── nx.json ├── package.json ├── tools └── tsconfig.tools.json ├── tsconfig.base.json ├── tsconfig.schematics.json └── yarn.lock /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | "login": "matheo", 10 | "name": "Mateo Tibaquirá", 11 | "avatar_url": "https://avatars.githubusercontent.com/u/260185?v=4", 12 | "profile": "http://matheo.co", 13 | "contributions": [ 14 | "projectManagement", 15 | "example", 16 | "ideas", 17 | "code", 18 | "doc" 19 | ] 20 | }, 21 | { 22 | "login": "nikita-emelianov", 23 | "name": "Nikita Emelianov", 24 | "avatar_url": "https://avatars.githubusercontent.com/u/42650220?v=4", 25 | "profile": "https://github.com/nikita-emelianov", 26 | "contributions": [ 27 | "code" 28 | ] 29 | } 30 | ], 31 | "contributorsPerLine": 7, 32 | "projectName": "open-source", 33 | "projectOwner": "myndpm", 34 | "repoType": "github", 35 | "repoHost": "https://github.com", 36 | "skipCi": true 37 | } 38 | -------------------------------------------------------------------------------- /.commitlintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@commitlint/config-angular"], 3 | "rules": {} 4 | } 5 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": ["**/*"], 4 | "plugins": ["@nx"], 5 | "overrides": [ 6 | { 7 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 8 | "rules": { 9 | "@nx/enforce-module-boundaries": [ 10 | "error", 11 | { 12 | "enforceBuildableLibDependency": true, 13 | "allow": [ 14 | "@myndpm/dyn-forms", 15 | "@myndpm/dyn-forms/core", 16 | "@myndpm/dyn-forms/logger" 17 | ], 18 | "depConstraints": [ 19 | { 20 | "sourceTag": "*", 21 | "onlyDependOnLibsWithTags": ["*"] 22 | } 23 | ] 24 | } 25 | ], 26 | "@typescript-eslint/ban-types": [ 27 | "error", 28 | { 29 | "types": { 30 | "Function": false 31 | }, 32 | "extendDefaults": true 33 | } 34 | ] 35 | } 36 | }, 37 | { 38 | "files": ["*.ts", "*.tsx"], 39 | "extends": ["plugin:@nx/typescript"], 40 | "rules": {} 41 | }, 42 | { 43 | "files": ["*.js", "*.jsx"], 44 | "extends": ["plugin:@nx/javascript"], 45 | "rules": {} 46 | } 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: matheo 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Report a problem with a library 4 | title: '' 5 | labels: 'bug / fix' 6 | assignees: '' 7 | --- 8 | 9 | ## Describe the bug 10 | 11 | A clear and concise description of what the bug is. 12 | 13 | ## To Reproduce 14 | 15 | Steps to reproduce the behavior: 16 | 17 | 1. Go to '...' 18 | 2. Click on '....' 19 | 3. Scroll down to '....' 20 | 4. See error 21 | 22 | ## Expected behavior 23 | 24 | A clear and concise description of what you expected to happen. 25 | 26 | ## Screenshots 27 | 28 | If applicable, add screenshots to help explain your problem. 29 | 30 | ## Desktop (please complete the following information) 31 | 32 | ```bash 33 | Copy the output of `ng version` here. 34 | ``` 35 | 36 | ## Additional context 37 | 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Suggest an idea for a library 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | ## Is your feature request related to a problem? Please describe 10 | 11 | A clear and concise description of what the problem is. 12 | 13 | ## Describe the solution you'd like 14 | 15 | A clear and concise description of what you want to happen. 16 | 17 | ## Describe alternatives you've considered 18 | 19 | A clear and concise description of any alternative solutions or features you've considered. 20 | 21 | ## Additional context 22 | 23 | Add any other context or screenshots about the feature request here. 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/ui-package.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: UI Package 3 | about: Add or Extend UI controls 4 | title: '' 5 | labels: 'enhancement' 6 | assignees: '' 7 | --- 8 | 9 | ## Which UI Framework do you want? 10 | 11 | Framework name, links to its documentation and demos of its controls. 12 | 13 | ## Describe the controls we could support 14 | 15 | Please describe the Controls and the Parameters we could need to support for them. 16 | -------------------------------------------------------------------------------- /.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 | /.angular/cache 29 | /.sass-cache 30 | /connect.lock 31 | /coverage 32 | /libpeerconnection.log 33 | npm-debug.log 34 | yarn-error.log 35 | testem.log 36 | /typings 37 | .npmrc 38 | 39 | # System Files 40 | .DS_Store 41 | Thumbs.db 42 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn commitlint --edit $1 5 | -------------------------------------------------------------------------------- /.husky/post-checkout: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | [ -n "$CI" ] && exit 0 4 | 5 | . "$(dirname -- "$0")/_/husky.sh" 6 | 7 | git fetch --tags --force 8 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 18 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | 3 | /dist 4 | /coverage 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "es5" 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "nrwl.angular-console", 4 | "angular.ng-template", 5 | "ms-vscode.vscode-typescript-tslint-plugin", 6 | "esbenp.prettier-vscode", 7 | "firsttris.vscode-jest-runner" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.pullTags": false, 3 | "git.autoStash": true 4 | } 5 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of the @myndpm/open-source project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities. 4 | 5 | Communication through any channel must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. 6 | 7 | We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the project to do the same. 8 | 9 | If any member of the community violates this code of conduct, the maintainers of the project may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate. 10 | 11 | If you are subject to or witness unacceptable behavior, or have any other concerns, please contact opensource at mynd.co. 12 | -------------------------------------------------------------------------------- /DEVELOPMENT.md: -------------------------------------------------------------------------------- 1 | # Development 2 | 3 | ## Considerations 4 | 5 | The `postinstall` script builds the `util` and `plugin` packages to setup the workspace from the `dist` folder. 6 | The compiled packages and their dependencies are available from /node_modules and consumed by the monorepo. 7 | 8 | To be able to run the website, build the demo package first with `yarn build`. 9 | 10 | ## Publishing to npm 11 | 12 | With GitHub Actions, there's a `release` workflow which needs to be manually triggered 13 | to publish the latest changes in the packages to NPM. 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Mynd Property Management Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /apps/website/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 2 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | not ios_saf 15.2-15.3 18 | not safari 15.2-15.3 19 | -------------------------------------------------------------------------------- /apps/website/.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/directive-selector": [ 13 | "error", 14 | { 15 | "type": "attribute", 16 | "prefix": "app", 17 | "style": "camelCase" 18 | } 19 | ], 20 | "@angular-eslint/component-selector": [ 21 | "error", 22 | { 23 | "type": "element", 24 | "prefix": "app", 25 | "style": "kebab-case" 26 | } 27 | ] 28 | } 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /apps/website/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'website', 4 | preset: '../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | globals: {}, 7 | coverageDirectory: '../../coverage/apps/website', 8 | snapshotSerializers: [ 9 | 'jest-preset-angular/build/serializers/no-ng-attributes', 10 | 'jest-preset-angular/build/serializers/ng-snapshot', 11 | 'jest-preset-angular/build/serializers/html-comment', 12 | ], 13 | transform: { 14 | '^.+.(ts|mjs|js|html)$': [ 15 | 'jest-preset-angular', 16 | { 17 | stringifyContentPathRegex: '\\.(html|svg)$', 18 | 19 | tsconfig: '/tsconfig.spec.json', 20 | }, 21 | ], 22 | }, 23 | transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], 24 | }; 25 | -------------------------------------------------------------------------------- /apps/website/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | template: '', 6 | }) 7 | export class AppComponent {} 8 | -------------------------------------------------------------------------------- /apps/website/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 4 | import { RouterModule, Routes } from '@angular/router'; 5 | import { AppComponent } from './app.component'; 6 | import { CustomBreakPointsProvider } from './bootstrap-breakpoints'; 7 | import { LayoutModule } from './layout'; 8 | import { PagesModule } from './pages/pages.module'; 9 | 10 | const routes: Routes = [ 11 | { 12 | path: 'demos', 13 | loadChildren: () => 14 | import('./demos/demos.module').then((m) => m.DemosModule), 15 | }, 16 | { 17 | path: '', 18 | loadChildren: () => import('./docs/docs.module').then((m) => m.DocsModule), 19 | }, 20 | ]; 21 | 22 | @NgModule({ 23 | declarations: [AppComponent], 24 | imports: [ 25 | BrowserModule.withServerTransition({ 26 | appId: 'myndOpenSource', 27 | }), 28 | BrowserAnimationsModule, 29 | RouterModule.forRoot(routes, { 30 | initialNavigation: 'enabledBlocking', 31 | }), 32 | LayoutModule, 33 | PagesModule, 34 | ], 35 | providers: [CustomBreakPointsProvider], 36 | bootstrap: [AppComponent], 37 | }) 38 | export class AppModule {} 39 | -------------------------------------------------------------------------------- /apps/website/src/app/app.server.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { FlexLayoutServerModule } from '@angular/flex-layout/server'; 3 | import { ServerModule } from '@angular/platform-server'; 4 | 5 | import { AppModule } from './app.module'; 6 | import { AppComponent } from './app.component'; 7 | 8 | @NgModule({ 9 | imports: [ 10 | AppModule, 11 | ServerModule, 12 | FlexLayoutServerModule, 13 | ], 14 | bootstrap: [AppComponent], 15 | }) 16 | export class AppServerModule {} 17 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/components/index/index.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 | 8 | 9 |
10 |

{{ item.title }}

11 |

{{ item.description }}

12 |
13 | 14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/components/index/index.component.scss: -------------------------------------------------------------------------------- 1 | .col { 2 | img { 3 | box-shadow: 2px 2px 4px 1px rgba(0, 0, 0, 0.2); 4 | } 5 | 6 | .col-body { 7 | position: relative; 8 | text-align: center; // FIXME restore if we add images per demo 9 | 10 | h2 a { 11 | text-decoration: none; 12 | } 13 | 14 | p { 15 | font-size: 14px; 16 | line-height: 24px; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/components/index/index.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-demos-index', 5 | templateUrl: './index.component.html', 6 | styleUrls: ['./index.component.scss'], 7 | changeDetection: ChangeDetectionStrategy.OnPush, 8 | }) 9 | export class IndexComponent { 10 | items = [ 11 | { 12 | title: 'Simple Subscription Form', 13 | link: './dyn-forms/single-form', 14 | description: 'Simple dyn-forms demo with custom modes.', 15 | }, 16 | { 17 | title: 'Simple Dynamic Form', 18 | link: './dyn-forms/simple-form', 19 | description: 'Simple dyn-forms demo with display mode.', 20 | }, 21 | { 22 | title: 'Combo Selectors Form', 23 | link: './dyn-forms/combo-form', 24 | description: 'Demo of selector updated with another selection.', 25 | }, 26 | { 27 | title: 'Dynamic Stepper Form', 28 | link: './dyn-forms/stepper-form', 29 | description: 'Demo of dyn-forms under different router-outlets.', 30 | }, 31 | { 32 | title: 'Config Builder Form', 33 | link: './dyn-forms/builder', 34 | description: 'Real use-case building a configuration with a custom condition and matcher.', 35 | }, 36 | ]; 37 | } 38 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/demos.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { NgModule } from '@angular/core'; 3 | import { FlexLayoutModule } from '@angular/flex-layout'; 4 | import { RouterModule, Routes } from '@angular/router'; 5 | import { LayoutModule, LayoutWrapperComponent } from '../layout'; 6 | import { IndexComponent } from './components/index/index.component'; 7 | 8 | const routes: Routes = [ 9 | { 10 | path: '', 11 | component: LayoutWrapperComponent, 12 | children: [ 13 | { 14 | path: '', 15 | pathMatch: 'full', 16 | component: IndexComponent, 17 | }, 18 | { 19 | path: 'dyn-forms', 20 | loadChildren: () => 21 | import('./submodules/dyn-forms/dyn-forms.module').then( 22 | (m) => m.DemoFormsModule 23 | ), 24 | }, 25 | ], 26 | }, 27 | ]; 28 | 29 | @NgModule({ 30 | imports: [ 31 | CommonModule, 32 | FlexLayoutModule, 33 | RouterModule.forChild(routes), 34 | LayoutModule, 35 | ], 36 | declarations: [IndexComponent], 37 | }) 38 | export class DemosModule {} 39 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/builder/builder.component.scss: -------------------------------------------------------------------------------- 1 | app-form-builder { 2 | dyn-form, 3 | dyn-group { 4 | display: flex; 5 | flex-wrap: wrap; 6 | 7 | .dyn-control { 8 | flex: 45%; 9 | margin-right: 5%; 10 | 11 | &.dyn-control-agentShowing, 12 | &.dyn-control-codeBox, 13 | &.dyn-control-smartLock { 14 | flex: 100%; 15 | margin-right: 0; 16 | } 17 | } 18 | } 19 | 20 | .mat-checkbox { 21 | display: block; 22 | // equalize to mat-form-field(outline) 23 | padding: 1.2em 0 2.65625em; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/builder/builder.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { BuilderComponent } from './builder.component'; 4 | 5 | describe('BuilderComponent', () => { 6 | let component: BuilderComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ BuilderComponent ] 12 | }).compileComponents(); 13 | }); 14 | 15 | beforeEach(() => { 16 | fixture = TestBed.createComponent(BuilderComponent); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | }); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/builder/business.types.ts: -------------------------------------------------------------------------------- 1 | import { DynOption } from '@myndpm/dyn-forms/core'; 2 | 3 | /** 4 | * Access Types 5 | */ 6 | export enum MyndAccessType { 7 | CodeBox = "CODE_BOX", 8 | SmartLock = "SMART_LOCK" 9 | } 10 | 11 | export const accessTypes: DynOption[] = [ 12 | { 13 | key: null, 14 | value: 'None', 15 | }, 16 | { 17 | key: MyndAccessType.CodeBox, 18 | value: 'Code Box', 19 | }, 20 | { 21 | key: MyndAccessType.SmartLock, 22 | value: 'Smart Lock', 23 | }, 24 | ]; 25 | 26 | /** 27 | * Unit Types 28 | */ 29 | export enum MyndUnitType { 30 | Normal = "NORMAL", 31 | Parking = "PARKING", 32 | Storage = "STORAGE" 33 | } 34 | 35 | export const unitTypes: DynOption[] = [ 36 | { 37 | key: MyndUnitType.Normal, 38 | value: 'Normal', 39 | }, 40 | { 41 | key: MyndUnitType.Parking, 42 | value: 'Parking', 43 | }, 44 | { 45 | key: MyndUnitType.Storage, 46 | value: 'Storage', 47 | }, 48 | ]; 49 | 50 | /** 51 | * Unit 52 | */ 53 | export interface IMyndUnit { 54 | unitType: MyndUnitType; 55 | } 56 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/combo/combo.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |
6 |

Combo Selectors Form

7 | 8 | 13 | 14 |
15 |
16 | 19 | 20 | 23 | 24 | 27 |
28 |
29 |
30 |
31 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/combo/combo.component.scss: -------------------------------------------------------------------------------- 1 | app-form-combo { 2 | .mat-card { 3 | margin-bottom: 0.5em; 4 | } 5 | 6 | .form-actions { 7 | margin-top: 1em; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/combo/combo.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ComboComponent } from './combo.component'; 4 | 5 | describe('ComboComponent', () => { 6 | let component: ComboComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ComboComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ComboComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/combo/combo.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import { DynOption } from "@myndpm/dyn-forms/core"; 3 | 4 | @Injectable() 5 | export class ComboService { 6 | 7 | getCountries(): DynOption[] { 8 | return [ 9 | { key: null, value: '- Choose one -' }, 10 | { key: 'CO', value: 'Colombia' }, 11 | { key: 'US', value: 'United States' }, 12 | { key: 'RU', value: 'Rusia' }, 13 | { key: 'UA', value: 'Ukraine' }, 14 | ]; 15 | } 16 | 17 | getCities(country?: string): DynOption[] { 18 | if (!country) { 19 | return []; 20 | } 21 | 22 | switch (country) { 23 | case 'CO': 24 | return [ 25 | { key: 'MDE', value: 'Medellin' }, 26 | { key: 'BOG', value: 'Bogotá' }, 27 | ]; 28 | case 'US': 29 | return [ 30 | { key: 'NYC', value: 'New York' }, 31 | { key: 'OAK', value: 'Oakland' }, 32 | ]; 33 | case 'RU': 34 | return [ 35 | { key: 'MSK', value: 'Moscow' }, 36 | { key: 'SPB', value: 'Saint Petersburg' }, 37 | ]; 38 | case 'UA': 39 | return [ 40 | { key: 'IEV', value: 'Kiev' }, 41 | { key: 'KIV', value: 'Kharkiv' }, 42 | ]; 43 | } 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/simple/simple.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |
6 |

Simple Dynamic Form

7 | 8 | 13 | 14 |
15 |
16 | 19 | 20 | 23 | 24 | 27 | 28 | 31 |
32 | 33 | 36 |
37 |
38 |
39 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/simple/simple.component.scss: -------------------------------------------------------------------------------- 1 | app-form-simple { 2 | .mat-card { 3 | margin-bottom: 0.5em; 4 | } 5 | 6 | .mat-radio-group { 7 | display: block; 8 | // equalize to mat-form-field(outline) 9 | padding: 1.4em 0 0.74625em; 10 | } 11 | 12 | .array-item { 13 | position: relative; 14 | 15 | // let the row to use 100% 16 | button { 17 | position: absolute; 18 | right: 0; 19 | top: 8px; 20 | } 21 | } 22 | 23 | .form-actions { 24 | margin-top: 1em; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/simple/simple.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { SimpleComponent } from './simple.component'; 4 | 5 | describe('SimpleComponent', () => { 6 | let component: SimpleComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ SimpleComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(SimpleComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/single/single.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |
6 |

Single Control

7 | 8 | 13 | 14 |
15 |
16 | 19 |
20 |
21 |
22 |
23 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/single/single.component.scss: -------------------------------------------------------------------------------- 1 | app-form-single { 2 | .mat-card { 3 | margin-bottom: 0.5em 4 | } 5 | 6 | .form-actions { 7 | margin-top: 1em 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/single/single.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { SingleComponent } from './single.component'; 4 | 5 | describe('SingleComponent', () => { 6 | let component: SingleComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ SingleComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(SingleComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/single/single.form.ts: -------------------------------------------------------------------------------- 1 | import { DynFormConfig } from '@myndpm/dyn-forms'; 2 | import { createMatConfig } from '@myndpm/dyn-forms/ui-material'; 3 | import { SingleSuccessComponent } from './success.control/success.component'; 4 | 5 | export function singleForm(): DynFormConfig<'form'|'success'> { 6 | return { 7 | controls: [ 8 | createMatConfig('INPUT', { 9 | name: 'email', 10 | validators: ['required', 'email'], 11 | cssClass: 'col-sm-6 col-md-4', 12 | params: { 13 | label: 'Email', 14 | type: 'email', 15 | }, 16 | modes: { 17 | success: SingleSuccessComponent.createConfig(), 18 | } 19 | }), 20 | ], 21 | errorMsgs: { 22 | email: 'Valid email is mandatory', 23 | }, 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/single/success.control/success.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Thank you! 4 | You are now subscribed 5 | 6 | 7 | 8 |

9 | You will receive our emails to {{ control.value }} 10 |

11 |
12 |
13 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/single/success.control/success.component.scss: -------------------------------------------------------------------------------- 1 | // fix left-margin of .mat-card-header-text when there's no card-avatar 2 | mat-card-header ::ng-deep > :first-child { 3 | margin-left: 0; 4 | } 5 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/single/success.control/success.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { 3 | DynBaseConfig, 4 | DynFormContainer, 5 | DynMode, 6 | DynParams, 7 | DynPartialControlConfig, 8 | } from '@myndpm/dyn-forms/core'; 9 | 10 | @Component({ 11 | selector: 'app-form-single-success', 12 | templateUrl: './success.component.html', 13 | styleUrls: ['./success.component.scss'], 14 | changeDetection: ChangeDetectionStrategy.OnPush, 15 | }) 16 | export class SingleSuccessComponent 17 | extends DynFormContainer { 18 | 19 | static dynControl: 'SUCCESS' = 'SUCCESS'; 20 | 21 | static createConfig( 22 | partial?: DynPartialControlConfig 23 | ): DynBaseConfig { 24 | return { 25 | ...partial, 26 | control: SingleSuccessComponent.dynControl, 27 | // reset unsupported options 28 | wrappers: [], 29 | controls: [], 30 | }; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/stepper/step1/step1.component.html: -------------------------------------------------------------------------------- 1 |

Personal Information

2 | 3 |
4 | 5 | 6 |
7 |   8 | 9 | 12 |
13 |
14 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/stepper/step1/step1.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myndpm/open-source/e760532f6ec16b36178f550a6368d7af2b3ec5ac/apps/website/src/app/demos/submodules/dyn-forms/components/stepper/step1/step1.component.scss -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/stepper/step1/step1.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { StepperStep1Component } from './step1.component'; 4 | 5 | describe('StepperStep1Component', () => { 6 | let component: StepperStep1Component; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [StepperStep1Component], 12 | }).compileComponents(); 13 | }); 14 | 15 | beforeEach(() => { 16 | fixture = TestBed.createComponent(StepperStep1Component); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | }); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/stepper/step1/step1.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { step1Form } from '../stepper.form'; 3 | 4 | @Component({ 5 | selector: 'app-form-stepper-step1', 6 | templateUrl: './step1.component.html', 7 | styleUrls: ['./step1.component.scss'], 8 | changeDetection: ChangeDetectionStrategy.OnPush, 9 | }) 10 | export class StepperStep1Component { 11 | config = step1Form(); 12 | } 13 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/stepper/step2/step2.component.html: -------------------------------------------------------------------------------- 1 |

Traveler Information

2 | 3 |
4 | 5 | 6 |
7 | 10 | 11 | 14 |
15 |
16 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/stepper/step2/step2.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myndpm/open-source/e760532f6ec16b36178f550a6368d7af2b3ec5ac/apps/website/src/app/demos/submodules/dyn-forms/components/stepper/step2/step2.component.scss -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/stepper/step2/step2.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { StepperStep2Component } from './step2.component'; 4 | 5 | describe('StepperStep2Component', () => { 6 | let component: StepperStep2Component; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [StepperStep2Component], 12 | }).compileComponents(); 13 | }); 14 | 15 | beforeEach(() => { 16 | fixture = TestBed.createComponent(StepperStep2Component); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | }); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/stepper/step2/step2.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { step2Form } from '../stepper.form'; 3 | 4 | @Component({ 5 | selector: 'app-form-stepper-step2', 6 | templateUrl: './step2.component.html', 7 | styleUrls: ['./step2.component.scss'], 8 | changeDetection: ChangeDetectionStrategy.OnPush, 9 | }) 10 | export class StepperStep2Component { 11 | config = step2Form(); 12 | } 13 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/stepper/stepper.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |
6 |

Dynamic Stepper Form

7 | 8 |
9 | Inspired from the talk 10 | "The ControlContainer and I" 11 | by Jennifer Wadella 12 |
13 | 14 |
15 | 16 | 17 | 18 |
19 |
20 |
21 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/stepper/stepper.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | .blockquote { 3 | background: #eee; 4 | border-left: 4px solid #ddd; 5 | border-radius: 4px; 6 | font-size: 90%; 7 | padding: 16px; 8 | } 9 | 10 | ::ng-deep { 11 | // a bit of grid spacing 12 | .dyn-control { 13 | margin-bottom: 0.25em; 14 | } 15 | 16 | // space-between buttons 17 | .form-actions { 18 | margin-top: 1em; 19 | 20 | display: flex; 21 | flex-direction: row; 22 | place-content: center space-between; 23 | align-items: center; 24 | } 25 | 26 | // final step summary 27 | pre { 28 | background: #f5f5f5; 29 | padding: 16px; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/stepper/stepper.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { StepperComponent } from './stepper.component'; 4 | 5 | describe('StepperComponent', () => { 6 | let component: StepperComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [StepperComponent], 12 | }).compileComponents(); 13 | }); 14 | 15 | beforeEach(() => { 16 | fixture = TestBed.createComponent(StepperComponent); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | }); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/stepper/summary/summary.component.html: -------------------------------------------------------------------------------- 1 |

Summary

2 | 3 |
4 | 5 | 6 |

Filled information:

7 | 8 |
{{ dyn.control.value | json }}
9 | 10 |
11 | 14 |
15 |
16 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/stepper/summary/summary.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myndpm/open-source/e760532f6ec16b36178f550a6368d7af2b3ec5ac/apps/website/src/app/demos/submodules/dyn-forms/components/stepper/summary/summary.component.scss -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/stepper/summary/summary.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { StepperSummaryComponent } from './summary.component'; 4 | 5 | describe('StepperSummaryComponent', () => { 6 | let component: StepperSummaryComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [StepperSummaryComponent], 12 | }).compileComponents(); 13 | }); 14 | 15 | beforeEach(() => { 16 | fixture = TestBed.createComponent(StepperSummaryComponent); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | }); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/components/stepper/summary/summary.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-form-stepper-summary', 5 | templateUrl: './summary.component.html', 6 | styleUrls: ['./summary.component.scss'], 7 | changeDetection: ChangeDetectionStrategy.OnPush, 8 | }) 9 | export class StepperSummaryComponent {} 10 | -------------------------------------------------------------------------------- /apps/website/src/app/demos/submodules/dyn-forms/constants/dyn-forms.links.ts: -------------------------------------------------------------------------------- 1 | import { SectionAction, SectionBadge } from '../../../../layout'; 2 | 3 | export const badges: SectionBadge[] = [ 4 | { 5 | link: "https://github.com/myndpm/open-source/tree/master/libs/forms", 6 | img: "https://img.shields.io/badge/%40myndpm-dyn--forms-brightgreen", 7 | alt: "Package", 8 | }, 9 | { 10 | link: "https://www.npmjs.com/package/@myndpm/dyn-forms", 11 | img: "https://badge.fury.io/js/%40myndpm%2Fdyn-forms.svg", 12 | alt: "NPM Badge", 13 | }, 14 | { 15 | link: "https://npmcharts.com/compare/@myndpm/dyn-forms?minimal=true", 16 | img: "https://img.shields.io/npm/dm/@myndpm/dyn-forms.svg?style=flat", 17 | alt: "NPM Downloads", 18 | }, 19 | ]; 20 | 21 | export const actions: SectionAction[] = [ 22 | { 23 | link: "https://prezi.com/view/4Ok1bgCWvf0g26FMVwfx/", 24 | ionicon: 'easel-outline', 25 | tooltip: 'Prezi', 26 | }, 27 | { 28 | link: "https://dev.to/myndpm/a-new-approach-to-have-dynamic-forms-in-angular-5d11", 29 | icon: 'article', 30 | tooltip: 'Article', 31 | }, 32 | { 33 | link: "https://stackblitz.com/edit/myndpm-dyn-forms?file=src/app/simple-form/simple.form.ts", 34 | ionicon: 'logo-angular', 35 | tooltip: 'Stackblitz', 36 | }, 37 | ]; 38 | -------------------------------------------------------------------------------- /apps/website/src/app/docs/components/content/content.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | -------------------------------------------------------------------------------- /apps/website/src/app/docs/components/content/content.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | 4 | .content-wrapper { 5 | padding: 1em; 6 | 7 | ::ng-deep { 8 | 9 | > .mat-tab-group { 10 | 11 | > .mat-tab-header { 12 | margin-bottom: 24px; 13 | 14 | .mat-tab-label-content { 15 | text-transform: uppercase; 16 | } 17 | } 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /apps/website/src/app/docs/components/example/example.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | margin: 0 0 24px 0; 4 | 5 | app-docs-viewer { 6 | background: #1e1e1e; 7 | overflow: hidden; 8 | } 9 | } 10 | 11 | 12 | 13 | .docs-example-viewer-wrapper { 14 | border: 1px solid rgba(0, 0, 0, 0.2); 15 | border-radius: 4px; 16 | margin: 24px 0; 17 | h3 { 18 | margin-top: 10px; 19 | } 20 | } 21 | 22 | 23 | 24 | .docs-example-viewer-title { 25 | align-content: center; 26 | align-items: center; 27 | border-bottom: 1px solid rgba(0, 0, 0, 0.1); 28 | display: flex; 29 | justify-content: center; 30 | padding: 8px 8px 8px 16px; 31 | } 32 | 33 | 34 | .docs-example-viewer-title-spacer { 35 | flex: 1 1 auto; 36 | } 37 | 38 | 39 | .docs-example-viewer-body { 40 | padding: 30px; 41 | } 42 | 43 | 44 | .button-bar { 45 | color: #fff; 46 | position: absolute; 47 | padding: 8px; 48 | right: 0; 49 | } 50 | 51 | 52 | code-snippet { 53 | padding: 20px; 54 | } 55 | 56 | 57 | .docs-example-source { 58 | // TODO(annieyw): remove when standalone snippets are removed 59 | padding: 0; 60 | margin: 0; 61 | border: none; 62 | background: none; 63 | } 64 | -------------------------------------------------------------------------------- /apps/website/src/app/docs/components/layout/layout.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | {{ parent.text }} 7 | 8 | 9 | 10 | 11 | {{ option.text }} 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | -------------------------------------------------------------------------------- /apps/website/src/app/docs/components/layout/layout.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | height: 100%; 4 | 5 | ::ng-deep { 6 | 7 | .mat-expansion-panel { 8 | border-radius: 0 !important; 9 | box-shadow: none; 10 | margin: 0; 11 | } 12 | 13 | .mat-expansion-panel-header { 14 | font-size: 16px; 15 | font-weight: 500; 16 | padding: 0 24px 0 16px; 17 | 18 | .mat-expansion-indicator { 19 | padding: 0 0 8px; 20 | } 21 | 22 | &.mat-expanded { 23 | height: 48px; 24 | } 25 | } 26 | 27 | .mat-expansion-panel-body { 28 | padding: 0; 29 | } 30 | 31 | .mat-list-base { 32 | padding: 0; 33 | } 34 | 35 | .mat-list-item { 36 | font-size: 14px; 37 | 38 | &.active { 39 | background: rgba(#38B87C, 0.5); 40 | } 41 | } 42 | } 43 | } 44 | 45 | .mat-accordion { 46 | border-right: 1px solid rgba(0, 0, 0, 0.12); 47 | } 48 | -------------------------------------------------------------------------------- /apps/website/src/app/docs/components/stackblitz/stackblitz.component.html: -------------------------------------------------------------------------------- 1 | Stackblitz button 2 | -------------------------------------------------------------------------------- /apps/website/src/app/docs/components/stackblitz/stackblitz.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myndpm/open-source/e760532f6ec16b36178f550a6368d7af2b3ec5ac/apps/website/src/app/docs/components/stackblitz/stackblitz.component.scss -------------------------------------------------------------------------------- /apps/website/src/app/docs/components/stackblitz/stackblitz.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-docs-stackblitz', 5 | templateUrl: './stackblitz.component.html', 6 | styleUrls: ['./stackblitz.component.scss'], 7 | changeDetection: ChangeDetectionStrategy.OnPush 8 | }) 9 | export class StackblitzComponent {} 10 | -------------------------------------------------------------------------------- /apps/website/src/app/docs/components/viewer/viewer.component.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /apps/website/src/app/docs/components/viewer/viewer.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | font-size: 16px; 4 | 5 | .content-wrapper { 6 | padding: 1em; 7 | } 8 | 9 | ::ng-deep { 10 | .mat-tab-label-content { 11 | text-transform: uppercase; 12 | } 13 | 14 | .mat-tab-header { 15 | margin-bottom: 24px; 16 | } 17 | 18 | h1 { 19 | font-size: 26px; 20 | } 21 | h2 { 22 | font-size: 24px; 23 | } 24 | h3 { 25 | font-size: 20px; 26 | text-align: left; 27 | &:after { 28 | display: none; 29 | } 30 | } 31 | 32 | p { 33 | font-size: 16px; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /apps/website/src/app/docs/interfaces/index.ts: -------------------------------------------------------------------------------- 1 | export * from './metadata.interfaces'; 2 | export * from './nav.interfaces'; 3 | -------------------------------------------------------------------------------- /apps/website/src/app/docs/interfaces/metadata.interfaces.ts: -------------------------------------------------------------------------------- 1 | export type DocsLocalized = { [lang: string]: string }; 2 | 3 | /** 4 | * Documentation JSON index 5 | */ 6 | 7 | export interface DocsIndex { 8 | [url: string]: DocsMetadata; 9 | } 10 | 11 | export interface DocsMetadata { 12 | title: DocsLocalized; 13 | content?: DocsLocalized; // README[.lang].md 14 | examples?: string[]; // example IDs 15 | redirectTo?: string; 16 | sourceLink?: string; 17 | } 18 | -------------------------------------------------------------------------------- /apps/website/src/app/docs/interfaces/nav.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { DynTree } from '@myndpm/dyn-forms/core'; 2 | 3 | /** 4 | * Layout Navigation 5 | */ 6 | export interface NavItem { 7 | text: string; 8 | link: string; 9 | } 10 | 11 | export type NavigationData = DynTree; 12 | -------------------------------------------------------------------------------- /apps/website/src/app/docs/services/i18n.service.ts: -------------------------------------------------------------------------------- 1 | import { Inject, Injectable, LOCALE_ID } from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root' 5 | }) 6 | export class I18nService { 7 | get lang(): string { 8 | return this.locale?.slice(0, 2) ?? 'en'; 9 | } 10 | 11 | constructor( 12 | @Inject(LOCALE_ID) private locale: string, 13 | ) {} 14 | } 15 | -------------------------------------------------------------------------------- /apps/website/src/app/docs/services/index.ts: -------------------------------------------------------------------------------- 1 | export * from './content.service'; 2 | export * from './i18n.service'; 3 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/footer/footer.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | background-color: #0a253a; 3 | display: block; 4 | 5 | .container { 6 | padding-top: 48px; 7 | padding-bottom: 72px; 8 | } 9 | 10 | .footer-logo { 11 | display: block; 12 | margin-bottom: 8px; 13 | } 14 | 15 | .footer-legal { 16 | color: #84929c; 17 | font-size: 12px; 18 | line-height: 16px; 19 | } 20 | 21 | .footer-logos { 22 | a { 23 | display: inline-block; 24 | max-width: 100%; 25 | 26 | img { 27 | margin-left: 8px; 28 | margin-right: 8px; 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/footer/footer.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-layout-footer', 5 | templateUrl: './footer.component.html', 6 | styleUrls: ['./footer.component.scss'], 7 | changeDetection: ChangeDetectionStrategy.OnPush 8 | }) 9 | export class FooterComponent {} 10 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/header/header.component.html: -------------------------------------------------------------------------------- 1 |

Mynd.co Open Source

2 | 3 | 25 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/header/header.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-layout-header', 5 | templateUrl: './header.component.html', 6 | styleUrls: ['./header.component.scss'], 7 | changeDetection: ChangeDetectionStrategy.OnPush 8 | }) 9 | export class HeaderComponent { 10 | menu = [ 11 | { 12 | title: 'Docs', 13 | link: '/docs/dyn-forms', 14 | }, 15 | { 16 | title: 'Demos', 17 | link: '/demos', 18 | }, 19 | ]; 20 | } 21 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './prompt/prompt.dialog'; 2 | export * from './prompt/prompt-data.interface'; 3 | export * from './section-actions/section-action.interface'; 4 | export * from './section-badges/section-badge.interface'; 5 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/prompt/prompt-data.interface.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Prompt data 3 | */ 4 | export interface PromptDialogData { 5 | title: string; 6 | content: string; 7 | no?: string; 8 | yes?: string; 9 | color?: string; 10 | } 11 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/prompt/prompt.dialog.html: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 |
5 | 6 |
7 | 8 | 9 |
10 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/prompt/prompt.dialog.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | padding-bottom: 10px; 4 | 5 | h4 { 6 | margin-top: 0; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/prompt/prompt.dialog.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; 2 | import { MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA, MatLegacyDialogRef as MatDialogRef } from '@angular/material/legacy-dialog'; 3 | import { PromptDialogData } from './prompt-data.interface'; 4 | 5 | @Component({ 6 | selector: 'app-prompt', 7 | templateUrl: 'prompt.dialog.html', 8 | styleUrls: ['./prompt.dialog.scss'], 9 | changeDetection: ChangeDetectionStrategy.OnPush, 10 | }) 11 | // tslint:disable-next-line: component-class-suffix 12 | export class PromptDialog { 13 | title = ''; 14 | content = ''; 15 | 16 | constructor( 17 | public dialogRef: MatDialogRef, 18 | @Inject(MAT_DIALOG_DATA) public data: PromptDialogData 19 | ) { 20 | this.data = { 21 | no: 'No', 22 | yes: 'Yes', 23 | color: 'accent', 24 | ...data 25 | }; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/section-actions/section-action.interface.ts: -------------------------------------------------------------------------------- 1 | export interface SectionAction { 2 | link: string; 3 | icon?: string; 4 | ionicon?: string; 5 | tooltip?: string; 6 | } 7 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/section-actions/section-actions.component.html: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/section-actions/section-actions.component.scss: -------------------------------------------------------------------------------- 1 | .section-actions { 2 | display: block; 3 | position: absolute; 4 | top: 16px; 5 | right: 8px; 6 | 7 | @media (min-width: 576px) { 8 | top: 32px; 9 | } 10 | 11 | a { 12 | color: #0a253a; 13 | } 14 | 15 | ion-icon { 16 | font-size: 24px; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/section-actions/section-actions.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; 2 | import { SectionAction } from './section-action.interface'; 3 | 4 | @Component({ 5 | selector: 'app-section-actions', 6 | templateUrl: './section-actions.component.html', 7 | styleUrls: ['./section-actions.component.scss'], 8 | changeDetection: ChangeDetectionStrategy.OnPush 9 | }) 10 | export class SectionActionsComponent { 11 | @Input() actions: SectionAction[] = []; 12 | } 13 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/section-badges/section-badge.interface.ts: -------------------------------------------------------------------------------- 1 | export interface SectionBadge { 2 | link: string; 3 | img: string; 4 | alt?: string; 5 | } 6 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/section-badges/section-badges.component.html: -------------------------------------------------------------------------------- 1 |
4 | 5 | 6 | 7 |
8 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/section-badges/section-badges.component.scss: -------------------------------------------------------------------------------- 1 | .badges { 2 | margin-bottom: 16px; 3 | } 4 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/components/section-badges/section-badges.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; 2 | import { SectionBadge } from './section-badge.interface'; 3 | 4 | @Component({ 5 | selector: 'app-section-badges', 6 | templateUrl: './section-badges.component.html', 7 | styleUrls: ['./section-badges.component.scss'], 8 | changeDetection: ChangeDetectionStrategy.OnPush 9 | }) 10 | export class SectionBadgesComponent { 11 | @Input() badges: SectionBadge[] = []; 12 | } 13 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/containers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './wrapper/wrapper.component'; 2 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/containers/wrapper/wrapper.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 | 7 | 8 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/containers/wrapper/wrapper.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: flex; 3 | flex-direction: column; 4 | height: 100%; 5 | 6 | div { 7 | flex: 1; 8 | 9 | ::ng-deep { 10 | section { 11 | padding: 24px 0; 12 | position: relative; 13 | 14 | @media (min-width: 576px) { 15 | padding: 42px 0; 16 | } 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/containers/wrapper/wrapper.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-layout-wrapper', 5 | templateUrl: './wrapper.component.html', 6 | styleUrls: ['./wrapper.component.scss'], 7 | changeDetection: ChangeDetectionStrategy.OnPush 8 | }) 9 | export class LayoutWrapperComponent {} 10 | -------------------------------------------------------------------------------- /apps/website/src/app/layout/index.ts: -------------------------------------------------------------------------------- 1 | export * from './layout.module'; 2 | export * from './containers'; 3 | export * from './components'; 4 | -------------------------------------------------------------------------------- /apps/website/src/app/pages/components/docs/docs.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 | 8 | 9 |
10 |

{{ item.title }}

11 |

{{ item.description }}

12 |
13 | 14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /apps/website/src/app/pages/components/docs/docs.component.scss: -------------------------------------------------------------------------------- 1 | .col { 2 | img { 3 | box-shadow: 2px 2px 4px 1px rgba(0, 0, 0, 0.2); 4 | } 5 | 6 | .col-body { 7 | position: relative; 8 | text-align: center; // FIXME restore if we add images per demo 9 | 10 | h2 a { 11 | text-decoration: none; 12 | } 13 | 14 | p { 15 | font-size: 14px; 16 | line-height: 24px; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/website/src/app/pages/components/docs/docs.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-docs', 5 | templateUrl: './docs.component.html', 6 | styleUrls: ['./docs.component.scss'], 7 | changeDetection: ChangeDetectionStrategy.OnPush, 8 | }) 9 | export class DocsIndexComponent { 10 | items = [ 11 | { 12 | title: '@myndpm/dyn-forms', 13 | link: './dyn-forms', 14 | description: 'Abstract layer to easily generate Dynamic Forms for Angular with a brand-new standard opened for community contributions and feedback!', 15 | }, 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /apps/website/src/app/pages/components/homepage/homepage.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Mynd.co + Angular

4 | Open Source libraries documentation 5 |
6 |
7 | 8 |
9 |
10 |
11 |

High Quality

12 |

13 | Clear and consistent code, inline documented 14 | to easily understand the purpose of each section. 15 |

16 |
17 | 18 |
19 |

Flexible

20 |

21 | Generic software for multiple purposes and use cases, 22 | to save time and avoid boilerplate. 23 |

24 |
25 | 26 |
27 |

Supported

28 |

29 | Backed by a big company with a large number 30 | of Senior Software Developers. 31 |

32 |
33 |
34 | 35 |
36 | 39 |
40 |
41 | -------------------------------------------------------------------------------- /apps/website/src/app/pages/components/homepage/homepage.component.scss: -------------------------------------------------------------------------------- 1 | @import 'bootstrap/scss/functions'; 2 | @import 'bootstrap/scss/variables'; 3 | @import 'bootstrap/scss/mixins/breakpoints'; 4 | 5 | header { 6 | background-color: #f2f2f7; 7 | height: 320px; 8 | margin-bottom: 20px; 9 | overflow: hidden; 10 | text-align: center; 11 | 12 | @include media-breakpoint-down(md) { 13 | height: 240px; 14 | } 15 | 16 | h2 { 17 | color: #38b87c; 18 | font-size: 56px; 19 | font-weight: 700; 20 | letter-spacing: -0.02em; 21 | line-height: 56px; 22 | margin: 15px 5px; 23 | 24 | @include media-breakpoint-down(lg) { 25 | font-size: 48px; 26 | } 27 | @include media-breakpoint-down(md) { 28 | font-size: 36px; 29 | } 30 | } 31 | 32 | span { 33 | font-size: 20px; 34 | font-weight: 300; 35 | line-height: 28px; 36 | } 37 | } 38 | 39 | main { 40 | p { 41 | text-align: center; 42 | } 43 | 44 | .call-to-action { 45 | margin: 20px 0 40px; 46 | 47 | button { 48 | font-size: 16px; 49 | line-height: 48px; 50 | } 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /apps/website/src/app/pages/components/homepage/homepage.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-homepage', 5 | templateUrl: './homepage.component.html', 6 | styleUrls: ['./homepage.component.scss'], 7 | changeDetection: ChangeDetectionStrategy.OnPush 8 | }) 9 | export class HomepageComponent {} 10 | -------------------------------------------------------------------------------- /apps/website/src/app/pages/components/not-found/not-found.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |

Not Found

4 | 5 |

The requested URL was not found.

6 | 7 | 10 |
11 | -------------------------------------------------------------------------------- /apps/website/src/app/pages/components/not-found/not-found.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: flex; 3 | padding: 120px 0; 4 | 5 | .container { 6 | text-align: center; 7 | } 8 | 9 | h2 { 10 | color: #0A253A; 11 | font-size: 40px; 12 | font-weight: 700; 13 | margin-top: 60px; 14 | } 15 | 16 | p { 17 | font-size: 18px; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/website/src/app/pages/components/not-found/not-found.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, Inject, Optional } from '@angular/core'; 2 | import { RESPONSE } from '@nguniversal/express-engine/tokens'; 3 | import { Response } from 'express'; 4 | 5 | @Component({ 6 | selector: 'app-not-found', 7 | templateUrl: './not-found.component.html', 8 | styleUrls: ['./not-found.component.scss'], 9 | changeDetection: ChangeDetectionStrategy.OnPush 10 | }) 11 | export class NotFoundComponent { 12 | constructor( 13 | @Optional() @Inject(RESPONSE) private response: Response, 14 | ) {} 15 | 16 | ngOnInit() { 17 | if (this.response) { 18 | this.response.statusCode = 404; 19 | this.response.statusMessage = 'Page Not Found'; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /apps/website/src/app/pages/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components/not-found/not-found.component'; 2 | -------------------------------------------------------------------------------- /apps/website/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myndpm/open-source/e760532f6ec16b36178f550a6368d7af2b3ec5ac/apps/website/src/assets/logo.png -------------------------------------------------------------------------------- /apps/website/src/assets/logos/fb.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/website/src/assets/logos/github.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/website/src/assets/logos/linkedin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/website/src/assets/logos/tw.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /apps/website/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/website/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /apps/website/src/favicon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myndpm/open-source/e760532f6ec16b36178f550a6368d7af2b3ec5ac/apps/website/src/favicon.jpg -------------------------------------------------------------------------------- /apps/website/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Mynd.co Open Source 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /apps/website/src/main.server.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { environment } from './environments/environment'; 3 | 4 | if (environment.production) { 5 | enableProdMode(); 6 | } 7 | 8 | export { AppServerModule } from './app/app.server.module'; 9 | export { renderModuleFactory } from '@angular/platform-server'; 10 | -------------------------------------------------------------------------------- /apps/website/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | document.addEventListener('DOMContentLoaded', () => { 12 | platformBrowserDynamic() 13 | .bootstrapModule(AppModule) 14 | .catch((err) => console.error(err)); 15 | }); 16 | -------------------------------------------------------------------------------- /apps/website/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest'; 2 | 3 | import { getTestBed } from '@angular/core/testing'; 4 | import { 5 | BrowserDynamicTestingModule, 6 | platformBrowserDynamicTesting, 7 | } from '@angular/platform-browser-dynamic/testing'; 8 | 9 | getTestBed().resetTestEnvironment(); 10 | getTestBed().initTestEnvironment( 11 | BrowserDynamicTestingModule, 12 | platformBrowserDynamicTesting(), 13 | { teardown: { destroyAfterEach: false } } 14 | ); 15 | -------------------------------------------------------------------------------- /apps/website/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "es2020", 6 | "target": "ES2022", 7 | "useDefineForClassFields": false, 8 | "types": [] 9 | }, 10 | "angularCompilerOptions": { 11 | "fullTemplateTypeCheck": true, 12 | "strictInjectionParameters": true, 13 | "strictInputAccessModifiers": true, 14 | "strictTemplates": true 15 | }, 16 | "files": ["src/main.ts", "src/polyfills.ts"], 17 | "exclude": ["**/*.spec.ts", "**/*.test.ts", "jest.config.ts"] 18 | } 19 | -------------------------------------------------------------------------------- /apps/website/tsconfig.app.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.app.json", 3 | "compilerOptions": { 4 | "noUnusedLocals": true, 5 | "target": "ES2022", 6 | "useDefineForClassFields": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /apps/website/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["**/*.ts"], 4 | "compilerOptions": { 5 | "types": ["jest", "node"] 6 | }, 7 | "exclude": ["jest.config.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /apps/website/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.app.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | }, 12 | { 13 | "path": "./tsconfig.editor.json" 14 | } 15 | ], 16 | "compilerOptions": { 17 | "target": "es2020" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/website/tsconfig.server.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.app.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/server", 5 | "target": "ES2022", 6 | "types": ["node"], 7 | "useDefineForClassFields": false 8 | }, 9 | "files": ["src/main.server.ts", "server.ts"], 10 | "angularCompilerOptions": { 11 | "entryModule": "./src/app/app.server.module#AppServerModule" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /apps/website/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "target": "es2016", 7 | "types": ["jest", "node"] 8 | }, 9 | "files": ["src/test-setup.ts"], 10 | "include": ["**/*.spec.ts", "**/*.test.ts", "**/*.d.ts", "jest.config.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /docs/dyn-forms/examples/basic/README.es.md: -------------------------------------------------------------------------------- 1 | # Configuración Básica 2 | 3 | Esta es la configuración más elemental de dyn-forms. 4 | 5 | Puedes ver como se consumen los controles provistos por un `ui-package` 6 | y sin clases CSS asignadas, los controles tomarán la fila completa. 7 | -------------------------------------------------------------------------------- /docs/dyn-forms/examples/basic/README.md: -------------------------------------------------------------------------------- 1 | # Basic Setup 2 | 3 | This is the most basic setup of dyn-forms. 4 | 5 | You can see how we consume the controls provided by a `ui-package` 6 | and with no CSS classes assigned the controls will take a whole row. 7 | -------------------------------------------------------------------------------- /docs/dyn-forms/intro/9-schematics.md: -------------------------------------------------------------------------------- 1 | # Schematics 2 | 3 | We have schematics since the [v11.2.9-beta.9](https://github.com/myndpm/open-source/releases/tag/%40myndpm%2Fdyn-forms%4011.2.9-beta.9) release. 4 | 5 | In VSCode we can use the NxConsole plugin to run the schematics with a friendly UI. 6 | 7 | ## DynModules 8 | 9 | We can easily create new modules to store our DynControls with: 10 | 11 | ```bash 12 | ng generate @myndpm/dyn-forms:module 13 | --project=forms 14 | --path=libs/forms/ui-taiga/src 15 | --prefix=dyn-tui 16 | --prefixClass 17 | --name=DynFormsTaiga 18 | --controlName=input 19 | --id=INPUT 20 | ``` 21 | 22 | ## DynControls 23 | 24 | And we can create the DynControl boilerplate with: 25 | 26 | ```bash 27 | ng generate @myndpm/dyn-forms:control 28 | --project=forms 29 | --path=libs/forms/ui-material/src/components 30 | --prefix=dyn-mat 31 | --prefixInterface=I 32 | --name=slider 33 | --id=SLIDER 34 | ``` 35 | 36 | We saved a lot of time with these ones :) 37 | 38 | ## Next 39 | 40 | - Learn about the [ui-packages](/docs/dyn-forms/ui). 41 | - Check the [live examples](/docs/dyn-forms/examples). 42 | -------------------------------------------------------------------------------- /docs/dyn-forms/ui/packages/README.md: -------------------------------------------------------------------------------- 1 | # UI Packages 2 | 3 | The `ui-packages` are subpackages of `@myndpm/dyn-forms` to provide some `DynControls` based on popular UI frameworks out there. The idea is that the community helps to support their preferred tools by working together and add support to most of their features. 4 | 5 | ## Example Pull Requests 6 | 7 | - [DynModule](https://github.com/myndpm/open-source/pull/22) example implementing `ui-native`. 8 | - [DynControl](https://github.com/myndpm/open-source/pull/19) DATEPICKER example in `ui-material`. 9 | - [DynControl](https://github.com/myndpm/open-source/pull/15) MULTICKECK example in `ui-material`. 10 | -------------------------------------------------------------------------------- /docs/dyn-forms/ui/ui-material/README.md: -------------------------------------------------------------------------------- 1 | # @myndpm/dyn-forms/ui-material 2 | 3 | This subpackage provides the `DynControls` to use the Angular Material components. 4 | 5 | ## Usage 6 | 7 | To provide it in your module you just need to import it: 8 | 9 | ```typescript 10 | import { ReactiveFormsModule } from '@angular/forms'; 11 | import { DynFormsMaterialModule } from '@myndpm/dyn-forms/ui-material`; 12 | 13 | @NgModule({ 14 | imports: [ 15 | ReactiveFormsModule, 16 | DynFormsMaterialModule.forFeature(), 17 | ] 18 | }) 19 | ``` 20 | 21 | and build your config with the provided Factory: 22 | 23 | ```typescript 24 | import { DynFormConfig } from '@myndpm/dyn-forms'; 25 | import { createMatConfig } from '@myndpm/dyn-forms/ui-material'; 26 | 27 | const config: DynFormConfig = { 28 | controls: [ 29 | createMatConfig('INPUT', { 30 | params: { label: 'My text input' } 31 | }), 32 | ], 33 | } 34 | ``` 35 | 36 | You can check the [demos](https://mynd.dev/demos) built with the Material `DynControls`. 37 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | const { getJestProjects } = require('@nx/jest'); 2 | 3 | export default { projects: getJestProjects() }; 4 | -------------------------------------------------------------------------------- /jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nx/jest/preset').default; 2 | 3 | module.exports = { ...nxPreset }; 4 | -------------------------------------------------------------------------------- /libs/demos/.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/directive-selector": [ 13 | "error", 14 | { 15 | "type": "attribute", 16 | "prefix": "myndpm", 17 | "style": "camelCase" 18 | } 19 | ], 20 | "@angular-eslint/component-selector": [ 21 | "error", 22 | { 23 | "type": "element", 24 | "prefix": "myndpm", 25 | "style": "kebab-case" 26 | } 27 | ] 28 | } 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /libs/demos/README.md: -------------------------------------------------------------------------------- 1 | # @myndpm/demos 2 | 3 | Library with demo module NgFactory and Dynamic Components. 4 | -------------------------------------------------------------------------------- /libs/demos/dyn-forms/README.md: -------------------------------------------------------------------------------- 1 | # @myndpm/demos/dyn-forms 2 | 3 | Package with NgModules and Components to be loaded dynamically by the docs. 4 | -------------------------------------------------------------------------------- /libs/demos/dyn-forms/basic/intro/app.component.html: -------------------------------------------------------------------------------- 1 |
2 | 6 | 7 | 8 |
9 | -------------------------------------------------------------------------------- /libs/demos/dyn-forms/basic/intro/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myndpm/open-source/e760532f6ec16b36178f550a6368d7af2b3ec5ac/libs/demos/dyn-forms/basic/intro/app.component.scss -------------------------------------------------------------------------------- /libs/demos/dyn-forms/basic/intro/app.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from "@angular/core"; 2 | import { FormGroup } from "@angular/forms"; 3 | import { formConfig } from "./form.config"; 4 | 5 | @Component({ 6 | selector: "dyn-forms-basic", 7 | templateUrl: "./app.component.html", 8 | styleUrls: ["./app.component.scss"], 9 | changeDetection: ChangeDetectionStrategy.OnPush, 10 | }) 11 | export class DynFormsBasicComponent { 12 | form = new FormGroup({}); 13 | config = formConfig(); 14 | 15 | doSubmit(): void { 16 | console.log(this.form.value); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /libs/demos/dyn-forms/basic/intro/form.config.ts: -------------------------------------------------------------------------------- 1 | import { DynFormConfig } from "@myndpm/dyn-forms"; 2 | import { createMatConfig } from "@myndpm/dyn-forms/ui-material"; 3 | 4 | export function formConfig(): DynFormConfig { 5 | return { 6 | controls: [ 7 | createMatConfig('INPUT', { 8 | name: 'fullName', 9 | params: { label: 'Full Name' }, 10 | }), 11 | createMatConfig('INPUT', { 12 | name: 'address', 13 | params: { label: 'Address' }, 14 | }), 15 | createMatConfig('SELECT', { 16 | name: 'country', 17 | params: { 18 | label: 'Country', 19 | options: [ 20 | { value: '- Choose one -', key: null }, 21 | { value: 'Colombia', key: 'CO' }, 22 | { value: 'United States', key: 'US' }, 23 | { value: 'China', key: 'CN' }, 24 | { value: 'Russia', key: 'RU' }, 25 | { value: 'Other', key: 'XX' }, 26 | ], 27 | }, 28 | }), 29 | createMatConfig('RADIO', { 30 | name: 'terms', 31 | params: { 32 | options: [ 33 | { value: 'Speaker', key: 'SPEAKER' }, 34 | { value: 'Attendant', key: 'ATTENDANT' }, 35 | ], 36 | }, 37 | }), 38 | ], 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /libs/demos/dyn-forms/basic/intro/index.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "dyn-forms.basic.intro", 4 | "title": { 5 | "en": "Basic Setup", 6 | "es": "Configuración Básica" 7 | }, 8 | "packagePath": "dyn-forms/basic/intro", 9 | "componentName": "AppComponent", 10 | "selector": "app-root", 11 | "primaryFile": "app.component.ts", 12 | "files": [ 13 | "form.config.ts", 14 | "app.component.ts", 15 | "app.component.html", 16 | "app.module.ts" 17 | ], 18 | "additionalComponents": [], 19 | "module": { 20 | "name": "DynFormsExampleIntro", 21 | "importSpecifier": "dyn-forms/basic/intro" 22 | } 23 | } 24 | ] 25 | -------------------------------------------------------------------------------- /libs/demos/dyn-forms/basic/intro/index.ts: -------------------------------------------------------------------------------- 1 | export * from './app.module'; 2 | export * from './app.component'; 3 | -------------------------------------------------------------------------------- /libs/demos/dyn-forms/basic/intro/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../../../../dist/libs/demos/dyn-forms", 4 | "lib": { 5 | "entryFile": "./index.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /libs/demos/dyn-forms/index.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /libs/demos/dyn-forms/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "lib": { 4 | "entryFile": "./index.ts" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /libs/demos/examples.json: -------------------------------------------------------------------------------- 1 | { 2 | "dyn-forms.basic.intro": { 3 | "id": "dyn-forms.basic.intro", 4 | "title": { 5 | "en": "Basic Setup", 6 | "es": "Configuración Básica" 7 | }, 8 | "componentName": "DynFormsBasicComponent", 9 | "selector": "dyn-forms-basic", 10 | "filesPath": "dyn-forms/basic/intro", 11 | "primaryFile": "app.component.ts", 12 | "files": [ 13 | "form.config.ts", 14 | "app.component.ts", 15 | "app.component.html", 16 | "app.module.ts" 17 | ], 18 | "additionalComponents": [], 19 | "module": { 20 | "name": "DemoFormsModule", 21 | "importSpecifier": "dyn-forms/basic/intro" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /libs/demos/index.ts: -------------------------------------------------------------------------------- 1 | import EXAMPLE_COMPONENTS from './examples.json'; 2 | 3 | export { EXAMPLE_COMPONENTS }; 4 | export * from './example-data'; 5 | -------------------------------------------------------------------------------- /libs/demos/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/demos", 4 | "assets": [ 5 | "examples.json" 6 | ], 7 | "lib": { 8 | "entryFile": "./index.ts" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /libs/demos/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@myndpm/demos", 3 | "version": "0.0.1", 4 | "description": "Mynd Components Examples", 5 | "keywords": [ 6 | "angular", 7 | "demos" 8 | ], 9 | "license": "MIT", 10 | "homepage": "https://mynd.netlify.app/", 11 | "repository": { 12 | "type": "git", 13 | "url": "git@github.com:myndpm/open-source.git", 14 | "directory": "libs/demos" 15 | }, 16 | "peerDependencies": { 17 | "@angular/common": ">=16.0.0", 18 | "@angular/core": ">=16.0.0" 19 | }, 20 | "dependencies": { 21 | "tslib": "^2.0.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /libs/demos/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demos", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/demos/src", 6 | "prefix": "demo", 7 | "targets": { 8 | "prebuild": { 9 | "executor": "@nx/angular:package", 10 | "options": { 11 | "updateBuildableProjectDepsInPackageJson": true, 12 | "tsConfig": "libs/demos/tsconfig.lib.json", 13 | "project": "libs/demos/ng-package.json" 14 | }, 15 | "configurations": { 16 | "production": { 17 | "tsConfig": "libs/demos/tsconfig.lib.prod.json" 18 | } 19 | } 20 | }, 21 | "build": { 22 | "executor": "nx:run-commands", 23 | "options": { 24 | "parallel": false, 25 | "commands": [ 26 | "yarn nx run demos:prebuild:production", 27 | "yarn install --ignore-scripts" 28 | ] 29 | } 30 | }, 31 | "lint": { 32 | "executor": "@nx/linter:eslint", 33 | "options": { 34 | "lintFilePatterns": [ 35 | "libs/demos/src/**/*.ts", 36 | "libs/demos/src/**/*.html" 37 | ] 38 | }, 39 | "outputs": ["{options.outputFile}"] 40 | } 41 | }, 42 | "tags": ["workspace"] 43 | } 44 | -------------------------------------------------------------------------------- /libs/demos/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.lib.json" 8 | }, 9 | { 10 | "path": "./tsconfig.lib.prod.json" 11 | } 12 | ], 13 | "compilerOptions": { 14 | "forceConsistentCasingInFileNames": true, 15 | "noImplicitReturns": true, 16 | "noFallthroughCasesInSwitch": true, 17 | "strict": true, 18 | "target": "es2020" 19 | }, 20 | "angularCompilerOptions": { 21 | "strictMetadataEmit": true, 22 | "strictInjectionParameters": true, 23 | "strictTemplates": false 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /libs/demos/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "target": "ES2022", 6 | "declaration": true, 7 | "declarationMap": true, 8 | "inlineSources": true, 9 | "lib": ["dom", "es2018"], 10 | "types": [], 11 | "useDefineForClassFields": false 12 | }, 13 | "angularCompilerOptions": { 14 | "skipTemplateCodegen": true, 15 | "strictMetadataEmit": true, 16 | "enableResourceInlining": true 17 | }, 18 | "exclude": [], 19 | "include": ["**/*.ts"] 20 | } 21 | -------------------------------------------------------------------------------- /libs/demos/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "compilerOptions": { 4 | "declarationMap": false, 5 | "noUnusedLocals": true, 6 | "target": "ES2022", 7 | "useDefineForClassFields": false 8 | }, 9 | "angularCompilerOptions": { 10 | "compilationMode": "partial" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /libs/forms/.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/directive-selector": [ 13 | "error", 14 | { 15 | "type": "attribute", 16 | "prefix": "dyn", 17 | "style": "camelCase" 18 | } 19 | ], 20 | "@angular-eslint/component-selector": [ 21 | "error", 22 | { 23 | "type": "element", 24 | "prefix": "dyn", 25 | "style": "kebab-case" 26 | } 27 | ], 28 | "@angular-eslint/directive-class-suffix": 0, 29 | "@typescript-eslint/member-ordering": 0, 30 | "@typescript-eslint/no-empty-function": 0, 31 | "@typescript-eslint/no-empty-interface": 0, 32 | "@typescript-eslint/no-explicit-any": 0, 33 | "@typescript-eslint/no-non-null-assertion": 0, 34 | "@typescript-eslint/no-unused-vars": 0 35 | } 36 | }, 37 | { 38 | "files": ["*.html"], 39 | "extends": ["plugin:@nx/angular-template"], 40 | "rules": {} 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /libs/forms/core/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/forms/core", 4 | "lib": { 5 | "entryFile": "./index.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /libs/forms/core/src/dyn-form-container.class.ts: -------------------------------------------------------------------------------- 1 | import { Directive, OnInit } from '@angular/core'; 2 | import { UntypedFormGroup } from '@angular/forms'; 3 | import { DynBaseConfig } from './types/config.types'; 4 | import { DynInstanceType } from './types/forms.types'; 5 | import { DynMode } from './types/mode.types'; 6 | import { DynParams } from './types/params.types'; 7 | import { DynControl } from './dyn-control.class'; 8 | 9 | @Directive() 10 | export abstract class DynFormContainer< 11 | TMode extends DynMode = DynMode, 12 | TParams extends DynParams = DynParams, 13 | TConfig extends DynBaseConfig = DynBaseConfig 14 | > 15 | extends DynControl 16 | implements OnInit { 17 | 18 | static dynInstance = DynInstanceType.Container; 19 | 20 | // auto-register in the form hierarchy 21 | ngOnInit(): void { 22 | // containers can initialize the node differently 23 | this.node.init({ 24 | ...this.config, 25 | instance: DynInstanceType.Container, 26 | component: this, 27 | }); 28 | 29 | // provide the parameters 30 | super.ngOnInit(); 31 | 32 | // log the successful initialization 33 | this._logger.nodeLoaded('dyn-form-container', this.node); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /libs/forms/core/src/dyn-form-group.class.ts: -------------------------------------------------------------------------------- 1 | import { Directive, OnInit } from '@angular/core'; 2 | import { UntypedFormGroup } from '@angular/forms'; 3 | import { DynConfig } from './types/config.types'; 4 | import { DynInstanceType } from './types/forms.types'; 5 | import { DynMode } from './types/mode.types'; 6 | import { DynParams } from './types/params.types'; 7 | import { DynControl } from './dyn-control.class'; 8 | 9 | @Directive() 10 | export abstract class DynFormGroup< 11 | TMode extends DynMode = DynMode, 12 | TParams extends DynParams = DynParams, 13 | TConfig extends DynConfig = DynConfig 14 | > 15 | extends DynControl 16 | implements OnInit { 17 | 18 | static dynInstance = DynInstanceType.Group; 19 | 20 | // auto-register in the form hierarchy 21 | ngOnInit(): void { 22 | // initialize the node 23 | this.node.init({ 24 | ...this.config, 25 | instance: DynInstanceType.Group, 26 | component: this, 27 | }); 28 | 29 | // provide the parameters 30 | super.ngOnInit(); 31 | 32 | // log the successful initialization 33 | this._logger.nodeLoaded('dyn-form-group', this.node); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /libs/forms/core/src/hidden/control.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { DynFormControl } from '../dyn-form-control.class'; 3 | 4 | @Component({ 5 | selector: 'dyn-hidden-control', 6 | template: '', 7 | changeDetection: ChangeDetectionStrategy.OnPush, 8 | }) 9 | export class DynHiddenControlComponent extends DynFormControl { 10 | static dynControl: 'HIDDEN' = 'HIDDEN'; 11 | } 12 | -------------------------------------------------------------------------------- /libs/forms/core/src/hidden/group.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { DynFormGroup } from '../dyn-form-group.class'; 3 | 4 | @Component({ 5 | selector: 'dyn-hidden-group', 6 | template: '', 7 | changeDetection: ChangeDetectionStrategy.OnPush, 8 | }) 9 | export class DynHiddenGroupComponent extends DynFormGroup { 10 | static dynControl: 'HIDDEN-GROUP' = 'HIDDEN-GROUP'; 11 | } 12 | -------------------------------------------------------------------------------- /libs/forms/core/src/types/config.types.ts: -------------------------------------------------------------------------------- 1 | import { DynControlConfig } from './control.types'; 2 | import { DynVisibility } from './forms.types'; 3 | import { DynMode, DynModes } from './mode.types'; 4 | import { DynParams } from './params.types'; 5 | 6 | // single form container/group/array config 7 | export interface DynBaseConfig< 8 | TMode extends DynMode = DynMode, 9 | TParams extends DynParams = DynParams, 10 | > extends DynControlConfig { 11 | // form/data hierarchy 12 | name?: string; // optional fieldName 13 | controls?: DynBaseConfig[]; 14 | modes?: DynModes; 15 | visibility?: DynVisibility; 16 | isolated?: boolean; // not part of the form hierarchy 17 | debug?: number; 18 | } 19 | 20 | // single form control config 21 | export interface DynConfig< 22 | TMode extends DynMode = DynMode, 23 | TParams extends DynParams = DynParams, 24 | > extends DynBaseConfig { 25 | // form/data hierarchy 26 | name: string; // mandatory fieldName 27 | } 28 | 29 | // useful types for Factory Method partial params 30 | export type DynPartialGroupConfig< 31 | TMode extends DynMode = DynMode, 32 | TParams extends DynParams = DynParams, 33 | > = Omit, 'control'>; 34 | 35 | export type DynPartialControlConfig< 36 | TMode extends DynMode = DynMode, 37 | TParams extends DynParams = DynParams, 38 | > = Omit, 'control'>; 39 | -------------------------------------------------------------------------------- /libs/forms/core/src/types/events.types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * callHook contract 3 | */ 4 | export interface DynHook { 5 | hook: string; 6 | payload?: any; 7 | plain?: boolean; // propagate the payload without modifications 8 | } 9 | 10 | /** 11 | * hook parameters 12 | */ 13 | export interface DynHookUpdateValidity { 14 | onlySelf?: boolean; 15 | emitEvent?: boolean; 16 | } 17 | -------------------------------------------------------------------------------- /libs/forms/core/src/types/forms.types.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from 'rxjs'; 2 | 3 | // form control type 4 | export enum DynInstanceType { 5 | Wrapper = 'WRAPPER', 6 | Group = 'GROUP', 7 | Array = 'ARRAY', 8 | Control = 'CONTROL', 9 | Container = 'CONTAINER', 10 | } 11 | 12 | // plain/serializable arguments (non-functions) 13 | export type DynConfigPrimitive = undefined | string | boolean | number | Set | RegExp | DynConfigPrimitive[] | { [k: string]: DynConfigPrimitive } | Observable; 14 | export type DynConfigArgs = DynConfigPrimitive | DynConfigPrimitive[] | null; 15 | 16 | /** 17 | * Visibility handled by DynControl 18 | */ 19 | export type DynVisibility = 'VISIBLE' | 'INVISIBLE' | 'HIDDEN'; 20 | 21 | /** 22 | * @deprecated use DynVisibility 23 | */ 24 | export type DynControlVisibility = DynVisibility; 25 | -------------------------------------------------------------------------------- /libs/forms/core/src/types/mode.types.ts: -------------------------------------------------------------------------------- 1 | import { DynControlConfig } from './control.types'; 2 | 3 | // display, edit, filter, etc 4 | export type DynMode = string; // Mode ID 5 | 6 | // config overrides per mode, handled by DynFormResolver 7 | export type DynModes = { 8 | [K in TMode]?: Partial; 9 | } 10 | 11 | /** 12 | * @deprecated use DynMode 13 | */ 14 | export type DynControlMode = DynMode; 15 | 16 | /** 17 | * @deprecated use DynModes 18 | */ 19 | export type DynControlModes = DynModes; 20 | -------------------------------------------------------------------------------- /libs/forms/core/src/types/params.types.ts: -------------------------------------------------------------------------------- 1 | import { DynBaseHandler } from './provider.types'; 2 | 3 | /** 4 | * control params 5 | */ 6 | export interface DynParams { 7 | // once merged with the paramFns they can have any type 8 | [key: string]: any; 9 | } 10 | 11 | /** 12 | * control functions 13 | * ie. { paramFns: { getValue: 'getOptionText' }} 14 | */ 15 | export type DynFunctionFn = (...args: any[]) => T; 16 | export type DynFunction = DynBaseHandler>; 17 | 18 | /** 19 | * @deprecated use DynParams 20 | */ 21 | export type DynControlParams = DynParams; 22 | 23 | /** 24 | * @deprecated use DynFunctionFn 25 | */ 26 | export type DynControlFunctionFn = DynFunctionFn; 27 | 28 | /** 29 | * @deprecated use DynFunction 30 | */ 31 | export type DynControlFunction = DynFunction; 32 | -------------------------------------------------------------------------------- /libs/forms/core/src/types/provider.types.ts: -------------------------------------------------------------------------------- 1 | import { DynConfigArgs } from './forms.types'; 2 | 3 | // a given id to a validator/async-validator/error-handler/function 4 | export type DynConfigId = string; 5 | 6 | /** 7 | * Base types 8 | */ 9 | export interface DynBaseProvider { 10 | priority?: number; 11 | } 12 | 13 | export type DynHandlerFactory = (...args: any[]) => F; 14 | 15 | export interface DynBaseHandler> extends DynBaseProvider { 16 | id: DynConfigId; 17 | fn: H; 18 | } 19 | 20 | // handlers provided can be referenced by id or [id with args] 21 | export type DynConfigProvider = F | DynConfigId | [DynConfigId, DynConfigArgs]; 22 | 23 | // object map of handlers 24 | export type DynConfigMap = Record; 25 | 26 | // collection of handlers to be used 27 | export type DynConfigCollection = Record | Array>; 28 | -------------------------------------------------------------------------------- /libs/forms/core/src/types/templates.types.ts: -------------------------------------------------------------------------------- 1 | import { TemplateRef } from '@angular/core'; 2 | 3 | /** 4 | * Used to communicate templates with its parameters to the Wrappers 5 | */ 6 | export interface DynTemplate { 7 | template: TemplateRef; 8 | params: Record; 9 | } 10 | 11 | /** 12 | * A custom Map of template+params grouped by different sections (id) like prefix, suffix. 13 | */ 14 | export class DynTemplates extends Map { 15 | add(id: string, template: TemplateRef, params: Record): void { 16 | if (!this.has(id)) { 17 | this.set(id, []); 18 | } 19 | this.get(id).push({ template, params }); 20 | } 21 | 22 | override get(id: string): DynTemplate[] { 23 | return super.get(id) ?? []; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /libs/forms/core/src/types/utils/option.types.ts: -------------------------------------------------------------------------------- 1 | import { DynTree } from './tree.types'; 2 | 3 | // map that could be converted with KeyValue pipe 4 | export type DynOptionsMap = Map; 5 | 6 | // generic type for selectors/radios/etc 7 | export interface DynOption { 8 | key: T; 9 | value: string; 10 | disabled?: boolean; 11 | [field: string]: any; 12 | } 13 | 14 | // tree of options 15 | export type DynOptionTree = DynTree>; 16 | -------------------------------------------------------------------------------- /libs/forms/core/src/types/utils/tree.types.ts: -------------------------------------------------------------------------------- 1 | // generic type for hierarchical trees 2 | export type DynTree = T & { 3 | name?: string; 4 | dynId?: string; 5 | detached?: boolean; 6 | children?: DynTree[]; 7 | } 8 | -------------------------------------------------------------------------------- /libs/forms/core/src/types/wrapper.types.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from 'rxjs'; 2 | import { DynFunctionFn, DynParams } from './params.types'; 3 | import { DynConfigMap, DynConfigProvider } from './provider.types'; 4 | 5 | export type DynWrapperId = string; // Wrapper ID 6 | 7 | export interface DynWrapperConfig { 8 | wrapper: DynWrapperId; 9 | params?: TParams | Observable; 10 | paramFns?: DynConfigMap>; 11 | } 12 | 13 | export type DynConfigWrapper = DynWrapperId | DynWrapperConfig; 14 | -------------------------------------------------------------------------------- /libs/forms/core/src/utils/config.utils.ts: -------------------------------------------------------------------------------- 1 | import { DynConfigWrapper, DynWrapperId } from '../types/wrapper.types'; 2 | 3 | /** 4 | * DynWrapperId extract util 5 | */ 6 | export function getWrapperId(config: DynConfigWrapper): DynWrapperId { 7 | return typeof config !== 'string' ? config.wrapper : config; 8 | } 9 | 10 | /** 11 | * Coerce boolean value 12 | */ 13 | export function coerceBoolean(value: any): boolean { 14 | const falsy = /^(?:f(?:alse)?|no?|0+)$/i; 15 | return !falsy.test(value) && !!value; 16 | } 17 | -------------------------------------------------------------------------------- /libs/forms/core/src/utils/hidden.util.ts: -------------------------------------------------------------------------------- 1 | import { DynControlConfig } from '../types/control.types'; 2 | 3 | export function isDynHidden(control: string | DynControlConfig): boolean { 4 | const id: string = typeof control !== 'string' 5 | ? control.control 6 | : control; 7 | return id === 'HIDDEN' || id === 'HIDDEN-GROUP'; 8 | } 9 | 10 | export function isNotDynHidden(control: string | DynControlConfig): boolean { 11 | return !isDynHidden(control); 12 | } 13 | -------------------------------------------------------------------------------- /libs/forms/core/src/utils/rxjs.utils.ts: -------------------------------------------------------------------------------- 1 | import { Observable, Subject } from 'rxjs'; 2 | 3 | export function onComplete( 4 | observable: Observable, 5 | next?: (value: T) => void, 6 | error?: (error: any) => void, 7 | complete?: () => void, 8 | ): Observable { 9 | const observe = new Subject(); 10 | 11 | observable.subscribe( 12 | next, 13 | error, 14 | () => { 15 | complete?.(); 16 | observe.next(); 17 | observe.complete(); 18 | }, 19 | ); 20 | 21 | return observe; 22 | } 23 | -------------------------------------------------------------------------------- /libs/forms/index.tests.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular'; 2 | 3 | import { getTestBed } from '@angular/core/testing'; 4 | import { 5 | BrowserDynamicTestingModule, 6 | platformBrowserDynamicTesting, 7 | } from '@angular/platform-browser-dynamic/testing'; 8 | 9 | getTestBed().resetTestEnvironment(); 10 | getTestBed().initTestEnvironment( 11 | BrowserDynamicTestingModule, 12 | platformBrowserDynamicTesting(), 13 | { teardown: { destroyAfterEach: false } } 14 | ); 15 | -------------------------------------------------------------------------------- /libs/forms/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/dyn-forms.module'; 2 | export * from './lib/components'; 3 | -------------------------------------------------------------------------------- /libs/forms/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'forms', 4 | preset: '../../jest.preset.js', 5 | setupFilesAfterEnv: ['/index.tests.ts'], 6 | globals: {}, 7 | coverageDirectory: '../../coverage/libs/forms', 8 | snapshotSerializers: [ 9 | 'jest-preset-angular/build/serializers/no-ng-attributes', 10 | 'jest-preset-angular/build/serializers/ng-snapshot', 11 | 'jest-preset-angular/build/serializers/html-comment', 12 | ], 13 | transform: { 14 | '^.+.(ts|mjs|js|html)$': [ 15 | 'jest-preset-angular', 16 | { 17 | stringifyContentPathRegex: '\\.(html|svg)$', 18 | 19 | tsconfig: '/tsconfig.spec.json', 20 | }, 21 | ], 22 | }, 23 | transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], 24 | }; 25 | -------------------------------------------------------------------------------- /libs/forms/lib/components/factory/factory.directive.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { DynFormRegistry } from '@myndpm/dyn-forms/core'; 3 | import { MockProvider } from 'ng-mocks'; 4 | import { DynFactoryDirective } from './factory.directive'; 5 | 6 | describe('DynFactoryDirective', () => { 7 | let component: DynFactoryDirective; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async () => { 11 | await TestBed.configureTestingModule({ 12 | declarations: [DynFactoryDirective], 13 | providers: [ 14 | MockProvider(DynFormRegistry), 15 | ], 16 | }).compileComponents(); 17 | }); 18 | 19 | beforeEach(() => { 20 | fixture = TestBed.createComponent(DynFactoryDirective); 21 | component = fixture.componentInstance; 22 | fixture.detectChanges(); 23 | }); 24 | 25 | it('should create', () => { 26 | expect(component).toBeTruthy(); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /libs/forms/lib/components/form/form.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | -------------------------------------------------------------------------------- /libs/forms/lib/components/form/form.component.scss: -------------------------------------------------------------------------------- 1 | dyn-form { 2 | .dyn-invisible { 3 | visibility: hidden !important; 4 | } 5 | .dyn-hidden { 6 | display: none !important; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /libs/forms/lib/components/form/form.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { DynControlNode } from '@myndpm/dyn-forms/core'; 3 | import { DynLogger } from '@myndpm/dyn-forms/logger'; 4 | import { MockProvider } from 'ng-mocks'; 5 | import { DynFormComponent } from './form.component'; 6 | 7 | describe('DynFormComponent', () => { 8 | let component: DynFormComponent; 9 | let fixture: ComponentFixture; 10 | 11 | beforeEach(async () => { 12 | await TestBed.configureTestingModule({ 13 | declarations: [DynFormComponent], 14 | providers: [ 15 | MockProvider(DynLogger), 16 | MockProvider(DynControlNode), 17 | ], 18 | }).compileComponents(); 19 | }); 20 | 21 | beforeEach(() => { 22 | fixture = TestBed.createComponent(DynFormComponent); 23 | component = fixture.componentInstance; 24 | fixture.detectChanges(); 25 | }); 26 | 27 | it('should create', () => { 28 | expect(component).toBeTruthy(); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /libs/forms/lib/components/form/form.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | DynBaseConfig, 3 | DynConfig, 4 | DynFormConfigErrors, 5 | DynMode, 6 | DynModes, 7 | } from '@myndpm/dyn-forms/core'; 8 | 9 | // typed config with any set of supported modes 10 | export interface DynFormConfig< 11 | M extends DynMode = DynMode, 12 | > extends DynFormConfigErrors { 13 | controls: Array | DynConfig>; 14 | modes?: DynModes; // default partial configs per mode 15 | debug?: number; 16 | } 17 | -------------------------------------------------------------------------------- /libs/forms/lib/components/group/group.component.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /libs/forms/lib/components/group/group.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { DynControlNode } from '@myndpm/dyn-forms/core'; 3 | import { DynLogger } from '@myndpm/dyn-forms/logger'; 4 | import { MockProvider } from 'ng-mocks'; 5 | import { DynGroupComponent } from './group.component'; 6 | 7 | describe('DynGroupComponent', () => { 8 | let component: DynGroupComponent; 9 | let fixture: ComponentFixture; 10 | 11 | beforeEach(async () => { 12 | await TestBed.configureTestingModule({ 13 | declarations: [DynGroupComponent], 14 | providers: [ 15 | MockProvider(DynLogger), 16 | MockProvider(DynControlNode), 17 | ], 18 | }).compileComponents(); 19 | }); 20 | 21 | beforeEach(() => { 22 | fixture = TestBed.createComponent(DynGroupComponent); 23 | component = fixture.componentInstance; 24 | fixture.detectChanges(); 25 | }); 26 | 27 | it('should create', () => { 28 | expect(component).toBeTruthy(); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /libs/forms/lib/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './factory/factory.directive'; 2 | export * from './form/form.component'; 3 | export * from './form/form.config'; 4 | export * from './group/group.component'; 5 | -------------------------------------------------------------------------------- /libs/forms/lib/migrations/12_6_1/index.ts: -------------------------------------------------------------------------------- 1 | import { Rule, Tree } from '@angular-devkit/schematics'; 2 | 3 | export default function (): Rule { 4 | return (tree: Tree) => { 5 | return tree.visit((path) => { 6 | if (path.includes('node_modules')) { 7 | return; 8 | } 9 | 10 | if (path.endsWith('.html') || path.endsWith('.scss') || path.endsWith('.sass')) { 11 | const buffer = tree.read(path); 12 | if (!buffer) { 13 | return; 14 | } 15 | 16 | const content = buffer.toString('utf-8'); 17 | 18 | let newContent = content 19 | // update the class renames 20 | .replace(//g, '') 22 | // css renames 23 | .replace(/dyn-factory/g, '.dyn-control'); 24 | 25 | // overwrite the tree only if there was a replacement 26 | if (content !== newContent) { 27 | tree.overwrite(path, newContent); 28 | } 29 | } 30 | }); 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /libs/forms/lib/schematics/control/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.__style__.template: -------------------------------------------------------------------------------- 1 | <% if(displayBlock){ if(style != 'sass') { %>:host { 2 | display: block; 3 | } 4 | <% } else { %>:host 5 | display: block 6 | <% }} %> -------------------------------------------------------------------------------- /libs/forms/lib/schematics/control/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.html.template: -------------------------------------------------------------------------------- 1 | <% if(instance == 'Container') { %> 2 |
3 | 8 |
9 | <% }else if(instance == 'Array') { %> 10 |
11 |
12 | 18 |
19 |
20 | <% }else if(instance == 'Group') { %> 21 |
22 | 27 |
28 | <% }else if(instance == 'Control') { %> 29 |
30 | 31 | 32 | 33 |
34 | <% } %> 35 | -------------------------------------------------------------------------------- /libs/forms/lib/schematics/control/files/__name@dasherize@if-flat__/__name@dasherize__.__type@dasherize__.params.ts.template: -------------------------------------------------------------------------------- 1 | import { DynParams } from '@myndpm/dyn-forms/core'; 2 | 3 | export interface <%= prefixInterface %><%= prefixClass ? classify(prefix) : '' %><%= classify(name) %>Params extends DynParams { 4 | } 5 | -------------------------------------------------------------------------------- /libs/forms/lib/schematics/module/files/__name@dasherize@if-flat__/__name@dasherize__.module.ts.template: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { ModuleWithProviders, NgModule } from '@angular/core'; 3 | import { ReactiveFormsModule } from '@angular/forms'; 4 | import { DynFormsModule } from '@myndpm/dyn-forms'; 5 | import { getModuleProviders } from '@myndpm/dyn-forms/core'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | CommonModule, 10 | ReactiveFormsModule, 11 | DynFormsModule, 12 | ], 13 | declarations: [], 14 | exports: [ 15 | DynFormsModule, // reduce the boilerplate 16 | ], 17 | }) 18 | export class <%= classify(name) %>Module { 19 | static forFeature(): ModuleWithProviders<<%= classify(name) %>Module> { 20 | return { 21 | ngModule: <%= classify(name) %>Module, 22 | providers: getModuleProviders({ 23 | controls: [ 24 | <%= prefixClass ? classify(prefix) : '' %><%= classify(controlName) %>Component, 25 | ], 26 | }), 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /libs/forms/lib/schematics/module/schema.ts: -------------------------------------------------------------------------------- 1 | 2 | export class Schema { 3 | /** 4 | * Angular options. 5 | */ 6 | path?: string; 7 | project?: string; 8 | prefix?: string; 9 | /** 10 | * The name of the DynModule. 11 | */ 12 | name!: string; 13 | /** 14 | * Default control options. 15 | */ 16 | controlPath?: string; 17 | controlName!: string; 18 | type?: string; 19 | id!: string; 20 | instance?: string; 21 | /** 22 | * The prefix to apply to the params interface. 23 | */ 24 | prefixInterface?: string; 25 | /** 26 | * Whether to prefix the control class name. 27 | */ 28 | prefixClass?: boolean; 29 | /** 30 | * Flag to indicate if a directory is created. 31 | */ 32 | flat?: boolean; 33 | /** 34 | * The declaring NgModule. 35 | */ 36 | module?: string; 37 | /** 38 | * Apply lint fixes after generating the module. 39 | */ 40 | lintFix?: boolean; 41 | } 42 | -------------------------------------------------------------------------------- /libs/forms/logger/README.md: -------------------------------------------------------------------------------- 1 | # @myndpm/dyn-forms/logger 2 | 3 | Mini fork of [@ngworker/lumberjack](https://github.com/ngworker/lumberjack) 4 | coupled to the needs of the library and simplified override of providers. 5 | -------------------------------------------------------------------------------- /libs/forms/logger/index.ts: -------------------------------------------------------------------------------- 1 | export * from './src/log-levels.constant'; 2 | export * from './src/log-level.token'; 3 | export * from './src/log.interface'; 4 | 5 | export * from './src/log-driver.service'; 6 | export * from './src/logger.service'; 7 | -------------------------------------------------------------------------------- /libs/forms/logger/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/forms/logger", 4 | "lib": { 5 | "entryFile": "./index.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /libs/forms/logger/src/interfaces/node.interface.ts: -------------------------------------------------------------------------------- 1 | export interface DynNode { 2 | parent?: DynNode; 3 | index?: number; 4 | deep: number; 5 | path: string[]; 6 | route: string[]; 7 | 8 | dynId?: string; 9 | instance: string; 10 | } 11 | -------------------------------------------------------------------------------- /libs/forms/logger/src/log-level.token.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from '@angular/core'; 2 | import { DynLogLevel } from './log-levels.constant'; 3 | 4 | export const DYN_LOG_LEVEL = new InjectionToken( 5 | '@myndpm/dyn-forms/logger' 6 | ); 7 | -------------------------------------------------------------------------------- /libs/forms/logger/src/log-levels.constant.ts: -------------------------------------------------------------------------------- 1 | 2 | export enum DynLogLevel { 3 | /** meant to be used with bitwise OR */ 4 | Testing = 2**10, 5 | All = 2**9 - 1, 6 | Runtime = 2**8, 7 | Ready = 2**7, 8 | Load = 2**6, 9 | Lifecycle = 2**5, 10 | Hierarchy = 2**4, 11 | Debug = 2**3, 12 | Warning = 2**2, 13 | Error = 2**1, 14 | Fatal = 2**0, 15 | None = 0, 16 | } 17 | 18 | export const dynLogLevels = new Map([ 19 | [DynLogLevel.Runtime, 'Runtime'], 20 | [DynLogLevel.Ready, 'READY'], 21 | [DynLogLevel.Load, 'LOAD'], 22 | [DynLogLevel.Lifecycle, 'CYCLE'], 23 | [DynLogLevel.Hierarchy, 'SETUP'], 24 | [DynLogLevel.Debug, 'DEBUG'], 25 | [DynLogLevel.Warning, 'WARN'], 26 | [DynLogLevel.Error, 'ERROR'], 27 | [DynLogLevel.Fatal, 'FATAL'], 28 | ]); 29 | -------------------------------------------------------------------------------- /libs/forms/logger/src/log.interface.ts: -------------------------------------------------------------------------------- 1 | import { DynLogLevel } from './log-levels.constant'; 2 | 3 | export interface DynLog { 4 | /** 5 | * Indent level. 6 | */ 7 | readonly deep?: number; 8 | /** 9 | * Level of severity. 10 | */ 11 | readonly level: DynLogLevel; 12 | /** 13 | * Log message describing an event. 14 | */ 15 | readonly message: string; 16 | /** 17 | * Optional payload related to the event. 18 | */ 19 | readonly payload?: any; 20 | } 21 | -------------------------------------------------------------------------------- /libs/forms/migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../@angular-devkit/schematics/collection-schema.json", 3 | "schematics": { 4 | "myndpm-forms-01": { 5 | "description": "Refactoring before the first official release", 6 | "version": "12.4.1", 7 | "factory": "./lib/migrations/12_4_1/index" 8 | }, 9 | "myndpm-forms-02": { 10 | "description": "DynFactory from component to directive", 11 | "version": "12.6.1", 12 | "factory": "./lib/migrations/12_6_1/index" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /libs/forms/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/forms", 4 | "lib": { 5 | "entryFile": "index.ts" 6 | }, 7 | "assets": [ 8 | "migrations.json", 9 | "schematics.json" 10 | ], 11 | "deleteDestPath": true, 12 | "allowedNonPeerDependencies": [ 13 | "fast-deep-equal", 14 | "is-callable", 15 | "merge", 16 | "ramda" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /libs/forms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@myndpm/dyn-forms", 3 | "version": "16.0.1", 4 | "description": "Abstract layer to easily generate Dynamic Forms for Angular", 5 | "keywords": [ 6 | "angular", 7 | "dynamic", 8 | "forms" 9 | ], 10 | "license": "MIT", 11 | "homepage": "https://mynd.dev/", 12 | "repository": { 13 | "type": "git", 14 | "url": "git@github.com:myndpm/open-source.git", 15 | "directory": "libs/forms" 16 | }, 17 | "schematics": "./schematics.json", 18 | "ng-update": { 19 | "packageGroup": [], 20 | "migrations": "./migrations.json" 21 | }, 22 | "peerDependencies": { 23 | "@angular/common": ">=16.0.0", 24 | "@angular/core": ">=16.0.0", 25 | "@angular/forms": ">=16.0.0", 26 | "rxjs": "*" 27 | }, 28 | "dependencies": { 29 | "ramda": "^0.29.0", 30 | "fast-deep-equal": "~3.1.3", 31 | "is-callable": "~1.2.7", 32 | "tslib": "^2.3.0" 33 | }, 34 | "devDependencies": { 35 | "@types/ramda": "^0.29.3" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /libs/forms/schematics.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../@angular-devkit/schematics/collection-schema.json", 3 | "schematics": { 4 | "module": { 5 | "description": "Create a DynControls Module", 6 | "factory": "./lib/schematics/module/index", 7 | "schema": "./lib/schematics/module/schema.json", 8 | "aliases": ["m"] 9 | }, 10 | "control": { 11 | "description": "Create a DynControl", 12 | "factory": "./lib/schematics/control/index", 13 | "schema": "./lib/schematics/control/schema.json", 14 | "aliases": ["c"] 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /libs/forms/testing/dyn-forms-testing.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { ModuleWithProviders, NgModule } from '@angular/core'; 3 | import { ReactiveFormsModule } from '@angular/forms'; 4 | import { DynFormsModule } from '@myndpm/dyn-forms'; 5 | import { DynModuleProviders, getModuleProviders } from '@myndpm/dyn-forms/core'; 6 | import { DynLogLevel } from '@myndpm/dyn-forms/logger'; 7 | import { DynFormTestingComponent } from './form/form-testing.component'; 8 | 9 | @NgModule({ 10 | imports: [ 11 | CommonModule, 12 | ReactiveFormsModule, 13 | DynFormsModule, 14 | ], 15 | declarations: [ 16 | DynFormTestingComponent, 17 | ], 18 | exports: [ 19 | ReactiveFormsModule, 20 | DynFormsModule, 21 | ], 22 | }) 23 | export class DynFormsTestingModule { 24 | static forTest(args?: DynModuleProviders): ModuleWithProviders { 25 | return { 26 | ngModule: DynFormsTestingModule, 27 | providers: getModuleProviders({ 28 | ...args, 29 | debug: args?.debug ? args.debug | DynLogLevel.Testing : undefined, 30 | }), 31 | }; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /libs/forms/testing/form/form-testing.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, Input, ViewChild } from '@angular/core'; 2 | import { FormGroup } from '@angular/forms'; 3 | import { DynFormComponent, DynFormConfig } from '@myndpm/dyn-forms'; 4 | import { DynMode } from '@myndpm/dyn-forms/core'; 5 | 6 | @Component({ 7 | selector: 'dyn-form-testing', 8 | template: ` 9 | 15 | `, 16 | changeDetection: ChangeDetectionStrategy.OnPush, 17 | }) 18 | export class DynFormTestingComponent { 19 | @Input() config!: DynFormConfig; 20 | @Input() mode!: DynMode; 21 | 22 | @ViewChild(DynFormComponent, { static: true }) 23 | dynForm!: DynFormComponent; 24 | 25 | form = new FormGroup({}); 26 | } 27 | -------------------------------------------------------------------------------- /libs/forms/testing/index.ts: -------------------------------------------------------------------------------- 1 | export * from './dyn-forms-testing.module'; 2 | 3 | export * from './form/form-testing.component'; 4 | -------------------------------------------------------------------------------- /libs/forms/testing/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/forms/testing", 4 | "lib": { 5 | "entryFile": "./index.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /libs/forms/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.lib.json" 8 | }, 9 | { 10 | "path": "./tsconfig.lib.prod.json" 11 | }, 12 | { 13 | "path": "./tsconfig.spec.json" 14 | } 15 | ], 16 | "compilerOptions": { 17 | "forceConsistentCasingInFileNames": true, 18 | "noImplicitReturns": true, 19 | "noFallthroughCasesInSwitch": true, 20 | "strict": true, 21 | "target": "es2020" 22 | }, 23 | "angularCompilerOptions": { 24 | "strictMetadataEmit": true, 25 | "strictInjectionParameters": true, 26 | "strictTemplates": true 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /libs/forms/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "target": "ES2022", 6 | "declaration": true, 7 | "declarationMap": true, 8 | "inlineSources": true, 9 | "lib": ["dom", "es2018"], 10 | "types": [], 11 | "useDefineForClassFields": false 12 | }, 13 | "angularCompilerOptions": { 14 | "skipTemplateCodegen": true, 15 | "strictMetadataEmit": true, 16 | "enableResourceInlining": true 17 | }, 18 | "exclude": [ 19 | "index.tests.ts", 20 | "**/*.spec.ts", 21 | "**/*.test.ts", 22 | "jest.config.ts" 23 | ], 24 | "include": ["**/*.ts"] 25 | } 26 | -------------------------------------------------------------------------------- /libs/forms/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "compilerOptions": { 4 | "declarationMap": false, 5 | "noUnusedLocals": true, 6 | "target": "ES2022", 7 | "useDefineForClassFields": false 8 | }, 9 | "angularCompilerOptions": { 10 | "compilationMode": "partial" 11 | }, 12 | "exclude": ["jest.config.ts"] 13 | } 14 | -------------------------------------------------------------------------------- /libs/forms/tsconfig.schematics.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.schematics.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/libs/forms", 5 | "rootDir": "." 6 | }, 7 | "exclude": [ 8 | "lib/schematics/*/files/**/*" 9 | ], 10 | "include": [ 11 | "lib/migrations/**/*", 12 | "lib/schematics/**/*" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /libs/forms/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "target": "es2016", 7 | "types": ["jest", "node"] 8 | }, 9 | "files": ["index.tests.ts"], 10 | "include": ["**/*.spec.ts", "**/*.test.ts", "**/*.d.ts", "jest.config.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/index.ts: -------------------------------------------------------------------------------- 1 | export * from './src/dyn-forms-bootstrap.module'; 2 | export * from './src/dyn-forms-bootstrap.factory'; 3 | export * from './src/controls/index'; 4 | -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/forms/ui-bootstrap", 4 | "lib": { 5 | "entryFile": "./index.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/checkbox/checkbox.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 |
{{ params.hint }}
6 | -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/checkbox/checkbox.component.params.ts: -------------------------------------------------------------------------------- 1 | import { DynParams } from '@myndpm/dyn-forms/core'; 2 | 3 | export interface DynBsCheckboxParams extends DynParams { 4 | label: string; 5 | hint?: string; 6 | } 7 | -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/checkbox/checkbox.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myndpm/open-source/e760532f6ec16b36178f550a6368d7af2b3ec5ac/libs/forms/ui-bootstrap/src/controls/checkbox/checkbox.component.scss -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/checkbox/checkbox.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ChangeDetectionStrategy } from '@angular/core'; 2 | import { 3 | DynBaseConfig, 4 | DynMode, 5 | DynFormControl, 6 | DynPartialControlConfig, 7 | } from '@myndpm/dyn-forms/core'; 8 | import { DynBsCheckboxParams } from './checkbox.component.params'; 9 | 10 | @Component({ 11 | selector: 'dyn-bs-checkbox', 12 | templateUrl: './checkbox.component.html', 13 | styleUrls: ['./checkbox.component.scss'], 14 | changeDetection: ChangeDetectionStrategy.OnPush, 15 | }) 16 | export class DynBsCheckboxComponent 17 | extends DynFormControl { 18 | 19 | static dynControl: 'CHECKBOX' = 'CHECKBOX'; 20 | 21 | static createConfig( 22 | partial: DynPartialControlConfig, 23 | ): DynBaseConfig { 24 | return { 25 | ...partial, 26 | control: DynBsCheckboxComponent.dynControl, 27 | }; 28 | } 29 | 30 | completeParams(params: Partial): DynBsCheckboxParams { 31 | return { 32 | ...params, 33 | label: params.label || '', 34 | }; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/index.ts: -------------------------------------------------------------------------------- 1 | export * from './checkbox/checkbox.component'; 2 | export * from './checkbox/checkbox.component.params'; 3 | export * from './input/input.component'; 4 | export * from './input/input.component.params'; 5 | export * from './radio/radio.component'; 6 | export * from './radio/radio.component.params'; 7 | export * from './select/select.component'; 8 | export * from './select/select.component.params'; 9 | -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/input/input.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 17 | 18 | 19 | 26 | 27 | 28 |
{{ params.hint }}
29 | -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/input/input.component.params.ts: -------------------------------------------------------------------------------- 1 | import { DynParams } from '@myndpm/dyn-forms/core'; 2 | 3 | export interface DynBsInputParams extends DynParams { 4 | type: 'color' | 'email' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'url' | 'textarea'; 5 | label?: string; 6 | placeholder?: string; 7 | rows?: number; 8 | hint?: string; 9 | size?: 'large' | 'small'; 10 | } 11 | -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/input/input.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myndpm/open-source/e760532f6ec16b36178f550a6368d7af2b3ec5ac/libs/forms/ui-bootstrap/src/controls/input/input.component.scss -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/input/input.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ChangeDetectionStrategy } from '@angular/core'; 2 | import { 3 | DynBaseConfig, 4 | DynFormControl, 5 | DynMode, 6 | DynPartialControlConfig, 7 | } from '@myndpm/dyn-forms/core'; 8 | import { DynBsInputParams } from './input.component.params'; 9 | 10 | @Component({ 11 | selector: 'dyn-bs-input', 12 | templateUrl: './input.component.html', 13 | styleUrls: ['./input.component.scss'], 14 | changeDetection: ChangeDetectionStrategy.OnPush, 15 | }) 16 | export class DynBsInputComponent 17 | extends DynFormControl { 18 | 19 | static dynControl: 'INPUT' = 'INPUT'; 20 | 21 | static createConfig( 22 | partial: DynPartialControlConfig, 23 | ): DynBaseConfig { 24 | return { 25 | ...partial, 26 | control: DynBsInputComponent.dynControl, 27 | }; 28 | } 29 | 30 | completeParams(params: Partial): DynBsInputParams { 31 | return { 32 | ...params, 33 | type: params.type || 'text', 34 | }; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/radio/radio.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 |
6 |
7 | -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/radio/radio.component.params.ts: -------------------------------------------------------------------------------- 1 | import { DynParams, DynOption } from '@myndpm/dyn-forms/core'; 2 | 3 | export interface DynBsRadioParams extends DynParams { 4 | options: DynOption[]; 5 | inline?: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/radio/radio.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myndpm/open-source/e760532f6ec16b36178f550a6368d7af2b3ec5ac/libs/forms/ui-bootstrap/src/controls/radio/radio.component.scss -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/radio/radio.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ChangeDetectionStrategy } from '@angular/core'; 2 | import { 3 | DynBaseConfig, 4 | DynFormControl, 5 | DynMode, 6 | DynPartialControlConfig, 7 | } from '@myndpm/dyn-forms/core'; 8 | import { DynBsRadioParams } from './radio.component.params'; 9 | 10 | @Component({ 11 | selector: 'dyn-bs-radio', 12 | templateUrl: './radio.component.html', 13 | styleUrls: ['./radio.component.scss'], 14 | changeDetection: ChangeDetectionStrategy.OnPush, 15 | }) 16 | export class DynBsRadioComponent 17 | extends DynFormControl { 18 | 19 | static dynControl: 'RADIO' = 'RADIO'; 20 | 21 | static createConfig( 22 | partial: DynPartialControlConfig, 23 | ): DynBaseConfig { 24 | return { 25 | ...partial, 26 | control: DynBsRadioComponent.dynControl, 27 | }; 28 | } 29 | 30 | completeParams(params: Partial): DynBsRadioParams { 31 | return { 32 | ...params, 33 | options: params.options || [], 34 | }; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/select/select.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | 14 |
{{ params.hint }}
15 | -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/select/select.component.params.ts: -------------------------------------------------------------------------------- 1 | import { DynParams, DynOption } from '@myndpm/dyn-forms/core'; 2 | 3 | export interface DynBsSelectParams extends DynParams { 4 | label?: string; 5 | options: DynOption[]; 6 | hint?: string; 7 | size?: 'large' | 'small'; 8 | } 9 | -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/select/select.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myndpm/open-source/e760532f6ec16b36178f550a6368d7af2b3ec5ac/libs/forms/ui-bootstrap/src/controls/select/select.component.scss -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/controls/select/select.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ChangeDetectionStrategy } from '@angular/core'; 2 | import { 3 | DynBaseConfig, 4 | DynFormControl, 5 | DynMode, 6 | DynPartialControlConfig, 7 | } from '@myndpm/dyn-forms/core'; 8 | import { DynBsSelectParams } from './select.component.params'; 9 | 10 | @Component({ 11 | selector: 'dyn-bs-select', 12 | templateUrl: './select.component.html', 13 | styleUrls: ['./select.component.scss'], 14 | changeDetection: ChangeDetectionStrategy.OnPush, 15 | }) 16 | export class DynBsSelectComponent 17 | extends DynFormControl { 18 | 19 | static dynControl: 'SELECT' = 'SELECT'; 20 | 21 | static createConfig( 22 | partial: DynPartialControlConfig, 23 | ): DynBaseConfig { 24 | return { 25 | ...partial, 26 | control: DynBsSelectComponent.dynControl, 27 | }; 28 | } 29 | 30 | completeParams(params: Partial): DynBsSelectParams { 31 | return { 32 | ...params, 33 | options: params.options || [], 34 | }; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /libs/forms/ui-bootstrap/src/dyn-forms-bootstrap.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { ModuleWithProviders, NgModule } from '@angular/core'; 3 | import { ReactiveFormsModule } from '@angular/forms'; 4 | import { DynFormsModule } from '@myndpm/dyn-forms'; 5 | import { getModuleProviders } from '@myndpm/dyn-forms/core'; 6 | import { 7 | DynBsCheckboxComponent, 8 | DynBsInputComponent, 9 | DynBsRadioComponent, 10 | DynBsSelectComponent, 11 | } from './controls'; 12 | 13 | @NgModule({ 14 | imports: [ 15 | CommonModule, 16 | ReactiveFormsModule, 17 | DynFormsModule, 18 | ], 19 | declarations: [ 20 | DynBsCheckboxComponent, 21 | DynBsInputComponent, 22 | DynBsRadioComponent, 23 | DynBsSelectComponent, 24 | ], 25 | exports: [ 26 | DynFormsModule, // reduce the boilerplate 27 | ], 28 | }) 29 | export class DynFormsBootstrapModule { 30 | static forFeature(): ModuleWithProviders { 31 | return { 32 | ngModule: DynFormsBootstrapModule, 33 | providers: getModuleProviders({ 34 | controls: [ 35 | DynBsCheckboxComponent, 36 | DynBsInputComponent, 37 | DynBsRadioComponent, 38 | DynBsSelectComponent, 39 | ], 40 | }), 41 | }; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /libs/forms/ui-material/index.ts: -------------------------------------------------------------------------------- 1 | export { DynFormsMaterialModule } from './src/dyn-forms-material.module'; 2 | export { createMatConfig } from './src/dyn-forms-material.factory'; 3 | export * from './src/controls/index'; 4 | -------------------------------------------------------------------------------- /libs/forms/ui-material/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/forms/ui-material", 4 | "lib": { 5 | "entryFile": "./index.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/array/array.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ params.title }} 5 | {{ params.subtitle }} 6 | 7 | 8 | 9 |
10 | 16 | 17 | 23 |
24 |
25 | 26 | 27 | 33 | 34 |
35 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/array/array.component.params.ts: -------------------------------------------------------------------------------- 1 | import { ThemePalette } from '@angular/material/core'; 2 | import { DynParams } from '@myndpm/dyn-forms/core'; 3 | 4 | export interface DynMatArrayParams extends DynParams { 5 | title?: string; 6 | subtitle?: string; 7 | avatar?: string; 8 | initItem?: boolean; 9 | addButton?: string; 10 | addColor?: ThemePalette; 11 | removeIcon?: string; 12 | removeColor?: ThemePalette; 13 | readonly?: boolean; 14 | } 15 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/array/array.component.scss: -------------------------------------------------------------------------------- 1 | // fix left-margin of .mat-card-header-text when there's no card-avatar 2 | mat-card-header ::ng-deep > :first-child { 3 | margin-left: 0; 4 | } 5 | 6 | .array-item { 7 | display: flex; 8 | flex-direction: row; 9 | place-content: center space-between; 10 | align-items: center; 11 | 12 | dyn-group { 13 | display: flex; 14 | flex: 1; 15 | } 16 | 17 | .mat-icon-button { 18 | margin-bottom: 20px; 19 | } 20 | } 21 | 22 | :host { 23 | &.readonly button { 24 | visibility: hidden; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/array/array.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { MatLegacyCardModule as MatCardModule } from '@angular/material/legacy-card'; 3 | import { DynLogger } from '@myndpm/dyn-forms/logger'; 4 | import { DynFormsModule } from '@myndpm/dyn-forms'; 5 | import { DynControlNode } from '@myndpm/dyn-forms/core'; 6 | import { MockProvider } from 'ng-mocks'; 7 | import { DynMatArrayComponent } from './array.component'; 8 | 9 | describe('DynMatArrayComponent', () => { 10 | let component: DynMatArrayComponent; 11 | let fixture: ComponentFixture; 12 | 13 | beforeEach(async () => { 14 | await TestBed.configureTestingModule({ 15 | imports: [ 16 | DynFormsModule.forFeature({ 17 | controls: [], 18 | }), 19 | MatCardModule, 20 | ], 21 | declarations: [DynMatArrayComponent], 22 | providers: [ 23 | MockProvider(DynLogger), 24 | MockProvider(DynControlNode), 25 | ], 26 | }).compileComponents(); 27 | }); 28 | 29 | beforeEach(() => { 30 | fixture = TestBed.createComponent(DynMatArrayComponent); 31 | component = fixture.componentInstance; 32 | fixture.detectChanges(); 33 | }); 34 | 35 | it('should create', () => { 36 | expect(component).toBeTruthy(); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/card/card.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ params.title }} 5 | {{ params.subtitle }} 6 | 7 | 8 | 9 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/card/card.component.params.ts: -------------------------------------------------------------------------------- 1 | import { DynParams } from '@myndpm/dyn-forms/core'; 2 | 3 | export interface DynMatCardParams extends DynParams { 4 | title?: string; 5 | subtitle?: string; 6 | avatar?: string; 7 | } 8 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/card/card.component.scss: -------------------------------------------------------------------------------- 1 | // fix left-margin of .mat-card-header-text when there's no card-avatar 2 | mat-card-header ::ng-deep > :first-child { 3 | margin-left: 0; 4 | } 5 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/card/card.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { MatLegacyCardModule as MatCardModule } from '@angular/material/legacy-card'; 3 | import { DynFormsModule } from '@myndpm/dyn-forms'; 4 | import { DynControlNode } from '@myndpm/dyn-forms/core'; 5 | import { DynLogger } from '@myndpm/dyn-forms/logger'; 6 | import { MockProvider } from 'ng-mocks'; 7 | import { DynMatCardComponent } from './card.component'; 8 | 9 | describe('DynMatCardComponent', () => { 10 | let component: DynMatCardComponent; 11 | let fixture: ComponentFixture; 12 | 13 | beforeEach(async () => { 14 | await TestBed.configureTestingModule({ 15 | imports: [ 16 | DynFormsModule.forFeature({ 17 | controls: [], 18 | }), 19 | MatCardModule, 20 | ], 21 | declarations: [DynMatCardComponent], 22 | providers: [ 23 | MockProvider(DynLogger), 24 | MockProvider(DynControlNode), 25 | ], 26 | }).compileComponents(); 27 | }); 28 | 29 | beforeEach(() => { 30 | fixture = TestBed.createComponent(DynMatCardComponent); 31 | component = fixture.componentInstance; 32 | fixture.detectChanges(); 33 | }); 34 | 35 | it('should create', () => { 36 | expect(component).toBeTruthy(); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/card/card.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { 3 | DynBaseConfig, 4 | DynFormContainer, 5 | DynMode, 6 | DynPartialControlConfig, 7 | } from '@myndpm/dyn-forms/core'; 8 | import { DynMatCardParams } from './card.component.params'; 9 | 10 | @Component({ 11 | selector: 'dyn-mat-card', 12 | templateUrl: './card.component.html', 13 | styleUrls: ['./card.component.scss'], 14 | changeDetection: ChangeDetectionStrategy.OnPush, 15 | }) 16 | export class DynMatCardComponent 17 | extends DynFormContainer { 18 | 19 | static dynControl: 'CARD' = 'CARD'; 20 | 21 | static createConfig( 22 | partial: DynPartialControlConfig 23 | ): DynBaseConfig { 24 | return { 25 | ...partial, 26 | control: DynMatCardComponent.dynControl, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/checkbox/checkbox.component.html: -------------------------------------------------------------------------------- 1 | 5 | {{ params.label }} 6 | 7 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/checkbox/checkbox.component.params.ts: -------------------------------------------------------------------------------- 1 | import { ThemePalette } from '@angular/material/core'; 2 | import { DynNode, DynParams } from '@myndpm/dyn-forms/core'; 3 | 4 | export interface DynMatCheckboxParams extends DynParams { 5 | label: string; 6 | labelPosition: 'before' | 'after'; 7 | color?: ThemePalette; 8 | indeterminate?: boolean; 9 | readonly?: boolean; 10 | // paramFns 11 | getValue?: (node: DynNode) => string; 12 | } 13 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/checkbox/checkbox.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/checkbox/checkbox.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { MatLegacyFormFieldModule as MatFormFieldModule } from '@angular/material/legacy-form-field'; 3 | import { DynFormsModule } from '@myndpm/dyn-forms'; 4 | import { DynControlNode } from '@myndpm/dyn-forms/core'; 5 | import { DynLogger } from '@myndpm/dyn-forms/logger'; 6 | import { MockProvider } from 'ng-mocks'; 7 | import { DynMatCheckboxComponent } from './checkbox.component'; 8 | 9 | describe('DynMatCheckboxComponent', () => { 10 | let component: DynMatCheckboxComponent; 11 | let fixture: ComponentFixture; 12 | 13 | beforeEach(async () => { 14 | await TestBed.configureTestingModule({ 15 | imports: [ 16 | DynFormsModule.forFeature({ 17 | controls: [], 18 | }), 19 | MatFormFieldModule, 20 | ], 21 | declarations: [DynMatCheckboxComponent], 22 | providers: [ 23 | MockProvider(DynLogger), 24 | MockProvider(DynControlNode), 25 | ], 26 | }).compileComponents(); 27 | }); 28 | 29 | beforeEach(() => { 30 | fixture = TestBed.createComponent(DynMatCheckboxComponent); 31 | component = fixture.componentInstance; 32 | fixture.detectChanges(); 33 | }); 34 | 35 | it('should create', () => { 36 | expect(component).toBeTruthy(); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/checkbox/checkbox.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, HostBinding } from '@angular/core'; 2 | import { 3 | DynConfig, 4 | DynFormControl, 5 | DynMode, 6 | DynPartialControlConfig, 7 | } from '@myndpm/dyn-forms/core'; 8 | import { DynMatCheckboxParams } from './checkbox.component.params'; 9 | 10 | @Component({ 11 | selector: 'dyn-mat-checkbox', 12 | templateUrl: './checkbox.component.html', 13 | styleUrls: ['./checkbox.component.scss'], 14 | changeDetection: ChangeDetectionStrategy.OnPush, 15 | }) 16 | export class DynMatCheckboxComponent 17 | extends DynFormControl { 18 | 19 | static dynControl: 'CHECKBOX' = 'CHECKBOX'; 20 | 21 | static createConfig( 22 | partial: DynPartialControlConfig 23 | ): DynConfig { 24 | return { 25 | ...partial, 26 | control: DynMatCheckboxComponent.dynControl, 27 | }; 28 | } 29 | 30 | @HostBinding('class.readonly') 31 | get isReadonly(): boolean { 32 | return Boolean(this.params.readonly); 33 | } 34 | 35 | completeParams(params: Partial): DynMatCheckboxParams { 36 | return { 37 | ...params, 38 | label: params.label || '-missing label-', 39 | labelPosition: params.labelPosition || 'after', 40 | }; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/container/container.component.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/container/container.component.params.ts: -------------------------------------------------------------------------------- 1 | import { DynParams } from '@myndpm/dyn-forms/core'; 2 | 3 | export interface DynMatContainerParams extends DynParams { 4 | } 5 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/container/container.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myndpm/open-source/e760532f6ec16b36178f550a6368d7af2b3ec5ac/libs/forms/ui-material/src/controls/container/container.component.scss -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/container/container.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ChangeDetectionStrategy } from '@angular/core'; 2 | import { 3 | DynConfig, 4 | DynFormContainer, 5 | DynMode, 6 | DynPartialControlConfig, 7 | } from '@myndpm/dyn-forms/core'; 8 | import { DynMatContainerParams } from './container.component.params'; 9 | 10 | @Component({ 11 | selector: 'dyn-mat-container', 12 | templateUrl: './container.component.html', 13 | styleUrls: ['./container.component.scss'], 14 | changeDetection: ChangeDetectionStrategy.OnPush 15 | }) 16 | export class DynMatContainerComponent 17 | extends DynFormContainer { 18 | 19 | static dynControl: 'CONTAINER' = 'CONTAINER'; 20 | 21 | static createConfig( 22 | partial: DynPartialControlConfig 23 | ): DynConfig { 24 | return { 25 | ...partial, 26 | control: DynMatContainerComponent.dynControl, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/datepicker/datepicker.component.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | {{ (params.getValue ? params.getValue(node) : control.value) || '-' }} 14 | 15 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/datepicker/datepicker.component.params.ts: -------------------------------------------------------------------------------- 1 | import { DynNode } from '@myndpm/dyn-forms/core'; 2 | import { DynMatFormFieldParams } from '../../wrappers'; 3 | 4 | export interface DynMatDatepickerParams extends Partial { 5 | placeholder: string; 6 | readonly?: boolean; 7 | // paramFns 8 | getValue?: (node: DynNode) => string; 9 | } 10 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/datepicker/datepicker.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | 4 | .mat-input-element { 5 | line-height: 1.2em; 6 | } 7 | 8 | &.readonly { 9 | mat-datepicker-toggle, 10 | mat-datepicker, 11 | input { 12 | display: none; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/divider/divider.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/divider/divider.component.params.ts: -------------------------------------------------------------------------------- 1 | import { DynParams } from '@myndpm/dyn-forms/core'; 2 | 3 | export interface DynMatDividerParams extends DynParams { 4 | invisible?: boolean; 5 | } 6 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/divider/divider.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | 4 | &.is-invisible { 5 | visibility: hidden; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/divider/divider.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ChangeDetectionStrategy, HostBinding } from '@angular/core'; 2 | import { DynConfig, DynFormContainer, DynMode, DynPartialControlConfig } from '@myndpm/dyn-forms/core'; 3 | import { DynMatDividerParams } from './divider.component.params'; 4 | 5 | @Component({ 6 | selector: 'dyn-mat-divider', 7 | templateUrl: './divider.component.html', 8 | styleUrls: ['./divider.component.scss'], 9 | changeDetection: ChangeDetectionStrategy.OnPush 10 | }) 11 | export class DynMatDividerComponent 12 | extends DynFormContainer { 13 | 14 | static dynControl: 'DIVIDER' = 'DIVIDER'; 15 | 16 | static createConfig( 17 | partial: DynPartialControlConfig 18 | ): DynConfig { 19 | return { 20 | ...partial, 21 | control: DynMatDividerComponent.dynControl, 22 | }; 23 | } 24 | 25 | @HostBinding('class.is-invisible') 26 | get isInvisible(): boolean { 27 | return Boolean(this.params.invisible); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/index.ts: -------------------------------------------------------------------------------- 1 | export * from './array/array.component'; 2 | export * from './array/array.component.params'; 3 | export * from './card/card.component'; 4 | export * from './card/card.component.params'; 5 | export * from './checkbox/checkbox.component'; 6 | export * from './checkbox/checkbox.component.params'; 7 | export * from './container/container.component'; 8 | export * from './container/container.component.params'; 9 | export * from './datepicker/datepicker.component'; 10 | export * from './datepicker/datepicker.component.params'; 11 | export * from './divider/divider.component'; 12 | export * from './divider/divider.component.params'; 13 | export * from './input/input.component'; 14 | export * from './input/input.component.params'; 15 | export * from './multicheckbox/multicheckbox.component'; 16 | export * from './multicheckbox/multicheckbox.component.params'; 17 | export * from './radio/radio.component'; 18 | export * from './radio/radio.component.params'; 19 | export * from './select/select.component'; 20 | export * from './select/select.component.params'; 21 | export * from './table/table.component'; 22 | export * from './table/table.component.params'; 23 | export * from './table-row/table-row.component'; 24 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/input/input.component.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | 13 | 14 | 21 | 22 | 23 | 24 | {{ (params.getValue ? params.getValue(node) : control.value) || '-' }} 25 | 26 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/input/input.component.params.ts: -------------------------------------------------------------------------------- 1 | import { ErrorStateMatcher } from '@angular/material/core'; 2 | import { DynNode } from '@myndpm/dyn-forms/core'; 3 | import { DynMatFormFieldParams } from '../../wrappers'; 4 | 5 | export interface DynMatInputParams extends Partial { 6 | type: 'color' | 'email' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'url' | 'textarea'; 7 | placeholder: string; 8 | readonly?: boolean; 9 | rows?: number; // for textarea type 10 | errorStateMatcher: ErrorStateMatcher; 11 | // paramFns 12 | getValue?: (node: DynNode) => string; 13 | } 14 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/input/input.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | 4 | .mat-input-element { 5 | line-height: 1.2em; 6 | } 7 | 8 | &.readonly { 9 | input, 10 | textarea { 11 | display: none; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/input/input.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { MatLegacyFormFieldModule as MatFormFieldModule } from '@angular/material/legacy-form-field'; 3 | import { DynFormsModule } from '@myndpm/dyn-forms'; 4 | import { DynControlNode } from '@myndpm/dyn-forms/core'; 5 | import { DynLogger } from '@myndpm/dyn-forms/logger'; 6 | import { MockProvider } from 'ng-mocks'; 7 | import { DynMatInputComponent } from './input.component'; 8 | 9 | describe('DynMatInputComponent', () => { 10 | let component: DynMatInputComponent; 11 | let fixture: ComponentFixture; 12 | 13 | beforeEach(async () => { 14 | await TestBed.configureTestingModule({ 15 | imports: [ 16 | DynFormsModule.forFeature({ 17 | controls: [], 18 | }), 19 | MatFormFieldModule, 20 | ], 21 | declarations: [DynMatInputComponent], 22 | providers: [ 23 | MockProvider(DynLogger), 24 | MockProvider(DynControlNode), 25 | ], 26 | }).compileComponents(); 27 | }); 28 | 29 | beforeEach(() => { 30 | fixture = TestBed.createComponent(DynMatInputComponent); 31 | component = fixture.componentInstance; 32 | fixture.detectChanges(); 33 | }); 34 | 35 | it('should create', () => { 36 | expect(component).toBeTruthy(); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/multicheckbox/multicheckbox.component.html: -------------------------------------------------------------------------------- 1 | {{ params.label }} 2 | 3 |
4 | 5 | {{ option.value }} 6 | 7 |
8 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/multicheckbox/multicheckbox.component.params.ts: -------------------------------------------------------------------------------- 1 | import { DynParams, DynOption } from '@myndpm/dyn-forms/core'; 2 | 3 | export interface DynMatMulticheckboxParams extends DynParams { 4 | label?: string; 5 | options: DynOption[]; 6 | } 7 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/multicheckbox/multicheckbox.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | margin: .25em 0; 4 | padding-bottom: 1.34375em; // spacing for mat-error 5 | 6 | mat-label { 7 | display: block; 8 | margin-bottom: .25em; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/radio/radio.component.html: -------------------------------------------------------------------------------- 1 | {{ params.label }} 2 | 3 | 4 | 9 | {{ option.value }} 10 | 11 | 12 | 13 | 14 | {{ (params.getValue ? params.getValue(node) : control.value) || '-' }} 15 | 16 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/radio/radio.component.params.ts: -------------------------------------------------------------------------------- 1 | import { DynParams, DynOption } from '@myndpm/dyn-forms/core'; 2 | 3 | export interface DynMatRadioParams extends DynParams { 4 | label?: string; 5 | options: DynOption[]; 6 | readonly?: boolean; 7 | } 8 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/radio/radio.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | margin: .25em 0; 4 | padding-bottom: 1.34375em; // spacing for mat-error 5 | 6 | mat-label { 7 | display: block; 8 | margin-bottom: .5em; 9 | } 10 | 11 | .mat-radio-button { 12 | margin-right: 1em; 13 | } 14 | 15 | &.readonly { 16 | .mat-radio-group { 17 | display: none; 18 | } 19 | 20 | span { 21 | display: block; 22 | padding: 1.4em 0 0.74625em; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/radio/radio.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { MatLegacyRadioModule as MatRadioModule } from '@angular/material/legacy-radio'; 3 | import { DynFormsModule } from '@myndpm/dyn-forms'; 4 | import { DynControlNode } from '@myndpm/dyn-forms/core'; 5 | import { DynLogger } from '@myndpm/dyn-forms/logger'; 6 | import { MockProvider } from 'ng-mocks'; 7 | import { DynMatRadioComponent } from './radio.component'; 8 | 9 | describe('DynMatRadioComponent', () => { 10 | let component: DynMatRadioComponent; 11 | let fixture: ComponentFixture; 12 | 13 | beforeEach(async () => { 14 | await TestBed.configureTestingModule({ 15 | imports: [ 16 | DynFormsModule.forFeature({ 17 | controls: [], 18 | }), 19 | MatRadioModule, 20 | ], 21 | declarations: [DynMatRadioComponent], 22 | providers: [ 23 | MockProvider(DynLogger), 24 | MockProvider(DynControlNode), 25 | ], 26 | }).compileComponents(); 27 | }); 28 | 29 | beforeEach(() => { 30 | fixture = TestBed.createComponent(DynMatRadioComponent); 31 | component = fixture.componentInstance; 32 | fixture.detectChanges(); 33 | }); 34 | 35 | it('should create', () => { 36 | expect(component).toBeTruthy(); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/radio/radio.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, HostBinding } from '@angular/core'; 2 | import { 3 | DynConfig, 4 | DynFormControl, 5 | DynMode, 6 | DynPartialControlConfig, 7 | } from '@myndpm/dyn-forms/core'; 8 | import { DynMatRadioParams } from './radio.component.params'; 9 | 10 | @Component({ 11 | selector: 'dyn-mat-radio', 12 | templateUrl: './radio.component.html', 13 | styleUrls: ['./radio.component.scss'], 14 | changeDetection: ChangeDetectionStrategy.OnPush, 15 | }) 16 | export class DynMatRadioComponent 17 | extends DynFormControl { 18 | 19 | static dynControl: 'RADIO' = 'RADIO'; 20 | 21 | static createConfig( 22 | partial: DynPartialControlConfig 23 | ): DynConfig { 24 | return { 25 | ...partial, 26 | control: DynMatRadioComponent.dynControl, 27 | }; 28 | } 29 | 30 | @HostBinding('class.readonly') 31 | get isReadonly(): boolean { 32 | return Boolean(this.params.readonly); 33 | } 34 | 35 | completeParams(params: Partial): DynMatRadioParams { 36 | return { 37 | ...params, 38 | options: params.options || [], 39 | }; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/select/select.component.html: -------------------------------------------------------------------------------- 1 | 9 | 10 | {{ option.value }} 11 | 12 | 13 | 14 | 15 | {{ (params.getValue ? params.getValue(node) : control.value) || '-' }} 16 | 17 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/select/select.component.params.ts: -------------------------------------------------------------------------------- 1 | import { MatLegacyOption as MatOption } from '@angular/material/legacy-core'; 2 | import { DynNode, DynOption } from '@myndpm/dyn-forms/core'; 3 | import { DynMatFormFieldParams } from '../../wrappers'; 4 | 5 | export interface DynMatSelectParams extends Partial { 6 | label?: string; 7 | placeholder: string; 8 | multiple?: boolean; 9 | options: DynOption[]; 10 | compareWith: (o1: any, o2: any) => boolean; 11 | sortComparator: (a: MatOption, b: MatOption, options: MatOption[]) => number; 12 | panelClass: string | string[] | Set | { [key: string]: any }; 13 | // paramFns 14 | getValue?: (node: DynNode) => string; 15 | } 16 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/select/select.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | 4 | &.readonly { 5 | .mat-select { 6 | display: none; 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/select/select.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select'; 3 | import { DynFormsModule } from '@myndpm/dyn-forms'; 4 | import { DynControlNode } from '@myndpm/dyn-forms/core'; 5 | import { DynLogger } from '@myndpm/dyn-forms/logger'; 6 | import { MockProvider } from 'ng-mocks'; 7 | import { DynMatSelectComponent } from './select.component'; 8 | 9 | describe('DynMatSelectComponent', () => { 10 | let component: DynMatSelectComponent; 11 | let fixture: ComponentFixture; 12 | 13 | beforeEach(async () => { 14 | await TestBed.configureTestingModule({ 15 | imports: [ 16 | DynFormsModule.forFeature({ 17 | controls: [], 18 | }), 19 | MatSelectModule, 20 | ], 21 | declarations: [DynMatSelectComponent], 22 | providers: [ 23 | MockProvider(DynLogger), 24 | MockProvider(DynControlNode), 25 | ], 26 | }).compileComponents(); 27 | }); 28 | 29 | beforeEach(() => { 30 | fixture = TestBed.createComponent(DynMatSelectComponent); 31 | component = fixture.componentInstance; 32 | fixture.detectChanges(); 33 | }); 34 | 35 | it('should create', () => { 36 | expect(component).toBeTruthy(); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/table-row/table-row.component.html: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 17 | 18 | 24 | 25 | 32 | 33 | 39 | 40 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/controls/table/table.component.params.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from 'rxjs'; 2 | 3 | export interface DynMatTableParams { 4 | headers: string[]; 5 | trackBy: string; 6 | title?: string; 7 | addNewButtonText?: string; 8 | emptyText?: string; 9 | disableRemove?: boolean; 10 | confirmDelete?: (payload: any) => Observable; 11 | } 12 | 13 | /** 14 | * Hooks 15 | */ 16 | 17 | export interface DynMatTableAddItemHook { 18 | userAction?: boolean; 19 | } 20 | 21 | export interface DynMatTableRemoveItemHook { 22 | index: number; 23 | doConfirm?: boolean; 24 | } 25 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/wrappers/form-field/form-field.component.params.ts: -------------------------------------------------------------------------------- 1 | import { LegacyFloatLabelType as FloatLabelType } from '@angular/material/legacy-form-field'; 2 | 3 | export interface DynMatFormFieldParams { 4 | floatLabel?: FloatLabelType; // readonly mode uses 'always' floating label 5 | hideRequiredMarker?: boolean; 6 | readonly?: boolean; 7 | label?: string; 8 | hint?: string; 9 | hintEnd?: string; 10 | iconPrefix?: string; 11 | iconSuffix?: string; 12 | textSuffix?: string; 13 | } 14 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/wrappers/form-field/form-field.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | 4 | // FIXME https://github.com/angular/components/pull/7083 5 | .mat-form-field { 6 | width: 100%; 7 | } 8 | 9 | &.readonly ::ng-deep { 10 | 11 | .mat-form-field-label-wrapper, 12 | .mat-form-field-outline, 13 | .mat-form-field-underline, 14 | .mat-error, 15 | .mat-hint { 16 | visibility: hidden; 17 | } 18 | 19 | .not-readonly { 20 | display: none; 21 | } 22 | 23 | .mat-form-field-appearance-fill .mat-form-field-flex { 24 | background: transparent; 25 | } 26 | 27 | // reset invalid colors in readonly 28 | .mat-form-field-invalid { 29 | &.mat-form-field { 30 | .mat-form-field-label { 31 | color: rgba(0, 0, 0, 0.6); // TODO mat-color 32 | } 33 | } 34 | &.mat-form-field-appearance-outline { 35 | .mat-form-field-outline-thick { 36 | color: rgba(0, 0, 0, 0.87); // TODO mat-color 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /libs/forms/ui-material/src/wrappers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './form-field/form-field.component'; 2 | export * from './form-field/form-field.component.params'; 3 | -------------------------------------------------------------------------------- /libs/forms/ui-native/index.ts: -------------------------------------------------------------------------------- 1 | export * from './src/dyn-forms-native.module'; 2 | export * from './src/dyn-forms-native.factory'; 3 | export * from './src/controls/index'; 4 | -------------------------------------------------------------------------------- /libs/forms/ui-native/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/forms/ui-native", 4 | "lib": { 5 | "entryFile": "./index.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /libs/forms/ui-native/src/controls/index.ts: -------------------------------------------------------------------------------- 1 | export * from './input/input.component'; 2 | export * from './input/input.component.params'; 3 | -------------------------------------------------------------------------------- /libs/forms/ui-native/src/controls/input/input.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /libs/forms/ui-native/src/controls/input/input.component.params.ts: -------------------------------------------------------------------------------- 1 | import { DynParams } from '@myndpm/dyn-forms/core'; 2 | 3 | export interface DynNatInputParams extends DynParams { 4 | type: 'email' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'url'; 5 | label?: string; 6 | } 7 | -------------------------------------------------------------------------------- /libs/forms/ui-native/src/controls/input/input.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /libs/forms/ui-native/src/controls/input/input.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { ReactiveFormsModule } from '@angular/forms'; 3 | import { DynFormsModule } from '@myndpm/dyn-forms'; 4 | import { DynControlNode } from '@myndpm/dyn-forms/core'; 5 | import { DynLogger } from '@myndpm/dyn-forms/logger'; 6 | import { MockProvider } from 'ng-mocks'; 7 | import { DynNatInputComponent } from './input.component'; 8 | 9 | describe('DynNatInputComponent', () => { 10 | let component: DynNatInputComponent; 11 | let fixture: ComponentFixture; 12 | 13 | beforeEach(async () => { 14 | await TestBed.configureTestingModule({ 15 | imports: [ 16 | ReactiveFormsModule, 17 | DynFormsModule.forFeature({ 18 | controls: [], 19 | }), 20 | ], 21 | declarations: [DynNatInputComponent], 22 | providers: [ 23 | MockProvider(DynLogger), 24 | MockProvider(DynControlNode), 25 | ], 26 | }).compileComponents(); 27 | }); 28 | 29 | beforeEach(() => { 30 | fixture = TestBed.createComponent(DynNatInputComponent); 31 | component = fixture.componentInstance; 32 | fixture.detectChanges(); 33 | }); 34 | 35 | it('should create', () => { 36 | expect(component).toBeTruthy(); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /libs/forms/ui-native/src/controls/input/input.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { 3 | DynConfig, 4 | DynFormControl, 5 | DynMode, 6 | DynPartialControlConfig, 7 | } from '@myndpm/dyn-forms/core'; 8 | import { DynNatInputParams } from './input.component.params'; 9 | 10 | @Component({ 11 | selector: 'dyn-nat-input', 12 | templateUrl: './input.component.html', 13 | styleUrls: ['./input.component.scss'], 14 | changeDetection: ChangeDetectionStrategy.OnPush, 15 | }) 16 | export class DynNatInputComponent 17 | extends DynFormControl { 18 | 19 | static dynControl: 'INPUT' = 'INPUT'; 20 | 21 | static createConfig( 22 | partial: DynPartialControlConfig 23 | ): DynConfig { 24 | return { 25 | ...partial, 26 | control: DynNatInputComponent.dynControl, 27 | }; 28 | } 29 | 30 | completeParams(params: Partial): DynNatInputParams { 31 | return { 32 | ...params, 33 | type: params.type || 'text', 34 | }; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /libs/forms/ui-native/src/dyn-forms-native.factory.ts: -------------------------------------------------------------------------------- 1 | import { 2 | DynConfig, 3 | DynControlId, 4 | DynMode, 5 | DynPartialControlConfig, 6 | } from '@myndpm/dyn-forms/core'; 7 | import { 8 | DynNatInputComponent, 9 | DynNatInputParams, 10 | } from './controls'; 11 | 12 | // control overloads 13 | export function createMatConfig( 14 | control: typeof DynNatInputComponent.dynControl, 15 | partial: DynPartialControlConfig> 16 | ): DynConfig; 17 | 18 | // factory 19 | export function createMatConfig( 20 | control: DynControlId, 21 | partial: any, 22 | ): DynConfig { 23 | switch (control) { 24 | // controls 25 | case DynNatInputComponent.dynControl: 26 | default: 27 | return DynNatInputComponent.createConfig(partial); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /libs/forms/ui-native/src/dyn-forms-native.module.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { ModuleWithProviders, NgModule } from '@angular/core'; 3 | import { ReactiveFormsModule } from '@angular/forms'; 4 | import { DynFormsModule } from '@myndpm/dyn-forms'; 5 | import { getModuleProviders } from '@myndpm/dyn-forms/core'; 6 | import { 7 | DynNatInputComponent, 8 | } from './controls'; 9 | 10 | @NgModule({ 11 | imports: [ 12 | CommonModule, 13 | ReactiveFormsModule, 14 | DynFormsModule, 15 | ], 16 | declarations: [ 17 | DynNatInputComponent, 18 | ], 19 | exports: [ 20 | // reduce the boilerplate 21 | DynFormsModule, 22 | ] 23 | }) 24 | export class DynFormsNativeModule { 25 | static forFeature(): ModuleWithProviders { 26 | return { 27 | ngModule: DynFormsNativeModule, 28 | providers: getModuleProviders({ 29 | controls: [ 30 | DynNatInputComponent, 31 | ], 32 | }), 33 | }; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /libs/plugin/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@nx/js/babel", 5 | { 6 | "useBuiltIns": "usage" 7 | } 8 | ] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /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 | } 19 | -------------------------------------------------------------------------------- /libs/plugin/README.md: -------------------------------------------------------------------------------- 1 | # @myndpm/nx 2 | 3 | Plugin for Nx by Mynd. 4 | 5 | ## Acknowledgements 6 | 7 | - [ngx-deploy-npm][1] 8 | 9 | [1]: https://github.com/bikecoders/ngx-deploy-npm 10 | -------------------------------------------------------------------------------- /libs/plugin/executors.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "builders": { 4 | "deploy-npm": { 5 | "implementation": "./src/executors/deploy-npm/executor", 6 | "schema": "./src/executors/deploy-npm/schema.json", 7 | "description": "Publish packages to NPM" 8 | } 9 | }, 10 | "executors": { 11 | "deploy-docker": { 12 | "implementation": "./src/executors/deploy-docker/executor", 13 | "schema": "./src/executors/deploy-docker/schema.json", 14 | "description": "Publish applications to Docker" 15 | }, 16 | "deploy-npm": { 17 | "implementation": "./src/executors/deploy-npm/executor", 18 | "schema": "./src/executors/deploy-npm/schema.json", 19 | "description": "Publish packages to NPM" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /libs/plugin/generators.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "name": "nx", 4 | "version": "0.0.1", 5 | "generators": { 6 | "nx": { 7 | "factory": "./src/generators/nx/generator", 8 | "schema": "./src/generators/nx/schema.json", 9 | "description": "nx generator" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /libs/plugin/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'nx', 4 | preset: '../../jest.preset.js', 5 | globals: {}, 6 | testEnvironment: 'node', 7 | transform: { 8 | '^.+\\.[tj]sx?$': [ 9 | 'ts-jest', 10 | { 11 | tsconfig: '/tsconfig.spec.json', 12 | }, 13 | ], 14 | }, 15 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], 16 | coverageDirectory: '../../coverage/libs/nx', 17 | coverageReporters: [['lcov', { projectRoot: 'libs/nx' }]], 18 | }; 19 | -------------------------------------------------------------------------------- /libs/plugin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@myndpm/nx", 3 | "version": "0.2.7", 4 | "description": "Plugin for Nx by Mynd", 5 | "repository": { 6 | "type": "git", 7 | "url": "git@github.com:myndpm/open-source.git", 8 | "directory": "libs/plugin" 9 | }, 10 | "main": "src/index.js", 11 | "generators": "./generators.json", 12 | "executors": "./executors.json", 13 | "dependencies": { 14 | "@myndpm/utils": "*" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /libs/plugin/src/executors/deploy-docker/executor.spec.ts: -------------------------------------------------------------------------------- 1 | import { DeployDockerExecutorSchema } from './schema'; 2 | import executor from './executor'; 3 | 4 | const options: DeployDockerExecutorSchema = {}; 5 | 6 | describe('DeployDocker Executor', () => { 7 | it('can run', async () => { 8 | const output = await executor(options); 9 | expect(output.success).toBe(true); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /libs/plugin/src/executors/deploy-docker/executor.ts: -------------------------------------------------------------------------------- 1 | import { DeployDockerExecutorSchema } from './schema'; 2 | 3 | export default async function runExecutor(options: DeployDockerExecutorSchema) { 4 | console.log('Executor ran for DeployDocker', options); 5 | return { 6 | success: true, 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /libs/plugin/src/executors/deploy-docker/schema.d.ts: -------------------------------------------------------------------------------- 1 | export interface DeployDockerExecutorSchema {} // eslint-disable-line 2 | -------------------------------------------------------------------------------- /libs/plugin/src/executors/deploy-docker/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "outputCapture": "direct-nodejs", 4 | "$schema": "http://json-schema.org/schema", 5 | "title": "DeployDocker executor", 6 | "description": "", 7 | "type": "object", 8 | "properties": {}, 9 | "required": [] 10 | } 11 | -------------------------------------------------------------------------------- /libs/plugin/src/executors/deploy-npm/executor.ts: -------------------------------------------------------------------------------- 1 | import { ExecutorContext, logger } from '@nx/devkit'; 2 | import deployer from './lib/deployer'; 3 | import * as engine from './lib/engine'; 4 | import { DeployNpmExecutorSchema } from './schema'; 5 | 6 | export default async function runExecutor( 7 | options: DeployNpmExecutorSchema, 8 | context: ExecutorContext 9 | ) { 10 | const buildTarget = `${context.projectName}${ 11 | options.target ? `:${options.target}` : ':build' 12 | }`; 13 | const outputTarget = `${context.projectName}${ 14 | options.outputTarget ? `:${options.outputTarget}` : ':build' 15 | }`; 16 | 17 | try { 18 | await deployer(engine, context, buildTarget, outputTarget, options); 19 | logger.info(`\n🚀 ${context.projectName} published successfully!`); 20 | } catch (e) { 21 | logger.error(`\n❌ error while trying to publish ${context.projectName}`); 22 | logger.error(e.stderr || e); 23 | return { success: false }; 24 | } 25 | 26 | return { success: true }; 27 | } 28 | -------------------------------------------------------------------------------- /libs/plugin/src/executors/deploy-npm/utils/default-options.ts: -------------------------------------------------------------------------------- 1 | import { DeployNpmExecutorSchema } from '../schema'; 2 | 3 | export enum npmAccess { 4 | public = 'public', 5 | restricted = 'restricted', 6 | } 7 | 8 | export type NpmPublishOptions = Pick< 9 | DeployNpmExecutorSchema, 10 | 'access' | 'tag' | 'otp' | 'dryRun' | 'exception' 11 | >; 12 | 13 | export const defaults: NpmPublishOptions = { 14 | tag: undefined, 15 | access: npmAccess.public, 16 | otp: undefined, 17 | dryRun: false, 18 | exception: false, 19 | }; 20 | 21 | export function prepareOptions( 22 | origOptions: DeployNpmExecutorSchema 23 | ): DeployNpmExecutorSchema { 24 | const options = { 25 | ...defaults, 26 | ...origOptions, 27 | }; 28 | 29 | return options; 30 | } 31 | -------------------------------------------------------------------------------- /libs/plugin/src/executors/deploy-npm/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './default-options'; 2 | export * from './lib-paths'; 3 | export * from './package-json'; 4 | -------------------------------------------------------------------------------- /libs/plugin/src/executors/deploy-npm/utils/package-json.ts: -------------------------------------------------------------------------------- 1 | import { jsonRead, jsonWrite } from '@myndpm/utils'; 2 | import * as path from 'path'; 3 | 4 | export function setPackageVersion( 5 | dir: string, 6 | version: string, 7 | dryRun = false 8 | ) { 9 | if (dryRun) { 10 | console.log(`setting ${version} into ${path.join(dir, 'package.json')}`); 11 | } 12 | 13 | const metadata = jsonRead(path.join(dir, 'package.json')); 14 | 15 | metadata.version = version; 16 | 17 | jsonWrite(path.join(dir, 'package.json'), metadata); 18 | } 19 | 20 | export function copyPackageVersion( 21 | origin: string, 22 | dest: string, 23 | dryRun = false 24 | ) { 25 | const metadata = jsonRead(path.join(origin, 'package.json')); 26 | 27 | if (dryRun) { 28 | console.log( 29 | `copying ${metadata.version} from ${path.join( 30 | origin, 31 | 'package.json' 32 | )} to ${path.join(dest, 'package.json')}` 33 | ); 34 | } 35 | 36 | setPackageVersion(dest, metadata.version); 37 | } 38 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/nx/files/src/index.ts__template__: -------------------------------------------------------------------------------- 1 | const variable = "<%= projectName %>"; -------------------------------------------------------------------------------- /libs/plugin/src/generators/nx/generator.spec.ts: -------------------------------------------------------------------------------- 1 | import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; 2 | import { Tree, readProjectConfiguration } from '@nx/devkit'; 3 | 4 | import generator from './generator'; 5 | import { NxGeneratorSchema } from './schema'; 6 | 7 | describe('nx generator', () => { 8 | let appTree: Tree; 9 | const options: NxGeneratorSchema = { name: 'test' }; 10 | 11 | beforeEach(() => { 12 | appTree = createTreeWithEmptyWorkspace(); 13 | }); 14 | 15 | it('should run successfully', async () => { 16 | await generator(appTree, options); 17 | const config = readProjectConfiguration(appTree, 'test'); 18 | expect(config).toBeDefined(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/nx/schema.d.ts: -------------------------------------------------------------------------------- 1 | export interface NxGeneratorSchema { 2 | name: string; 3 | tags?: string; 4 | directory?: string; 5 | } 6 | -------------------------------------------------------------------------------- /libs/plugin/src/generators/nx/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "$id": "Nx", 4 | "title": "", 5 | "type": "object", 6 | "properties": { 7 | "name": { 8 | "type": "string", 9 | "description": "", 10 | "$default": { 11 | "$source": "argv", 12 | "index": 0 13 | }, 14 | "x-prompt": "What name would you like to use?" 15 | }, 16 | "tags": { 17 | "type": "string", 18 | "description": "Add tags to the project (used for linting)", 19 | "alias": "t" 20 | }, 21 | "directory": { 22 | "type": "string", 23 | "description": "A directory where the project is placed", 24 | "alias": "d" 25 | } 26 | }, 27 | "required": [ 28 | "name" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /libs/plugin/src/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myndpm/open-source/e760532f6ec16b36178f550a6368d7af2b3ec5ac/libs/plugin/src/index.ts -------------------------------------------------------------------------------- /libs/plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.lib.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /libs/plugin/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "outDir": "../../dist/out-tsc", 6 | "declaration": true, 7 | "types": ["node"] 8 | }, 9 | "exclude": ["**/*.spec.ts", "**/*.test.ts", "jest.config.ts"], 10 | "include": ["**/*.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /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 | "**/*.test.ts", 10 | "**/*.spec.ts", 11 | "**/*.test.tsx", 12 | "**/*.spec.tsx", 13 | "**/*.test.js", 14 | "**/*.spec.js", 15 | "**/*.test.jsx", 16 | "**/*.spec.jsx", 17 | "**/*.d.ts", 18 | "jest.config.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /libs/utils/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@nx/js/babel", 5 | { 6 | "useBuiltIns": "usage" 7 | } 8 | ] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /libs/utils/.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 | } 19 | -------------------------------------------------------------------------------- /libs/utils/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). 4 | 5 | ## [0.1.4](https://github.com/myndpm/open-source/compare/@myndpm/utils@0.1.3...@myndpm/utils@0.1.4) (2022-10-28) 6 | 7 | 8 | 9 | ## [0.1.3](https://github.com/myndpm/open-source/compare/@myndpm/utils@0.1.2...@myndpm/utils@0.1.3) (2022-10-12) 10 | -------------------------------------------------------------------------------- /libs/utils/README.md: -------------------------------------------------------------------------------- 1 | # @myndpm/utils 2 | 3 | NPM package with misc utilities. 4 | 5 | ## Usage 6 | 7 | It's a base `dependency` of other packages like `@myndpm/nx` for JSON and RxJS filesystem manipulations. 8 | -------------------------------------------------------------------------------- /libs/utils/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'utils', 4 | preset: '../../jest.preset.js', 5 | globals: {}, 6 | testEnvironment: 'node', 7 | transform: { 8 | '^.+\\.[tj]sx?$': [ 9 | 'ts-jest', 10 | { 11 | tsconfig: '/tsconfig.spec.json', 12 | }, 13 | ], 14 | }, 15 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], 16 | coverageDirectory: '../../coverage/libs/tools/utils', 17 | }; 18 | -------------------------------------------------------------------------------- /libs/utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@myndpm/utils", 3 | "version": "0.1.4", 4 | "repository": { 5 | "type": "git", 6 | "url": "git@github.com:myndpm/open-source.git", 7 | "directory": "libs/utils" 8 | }, 9 | "dependencies": { 10 | "@ckapp/rxjs-node-fs": "^0.6.1", 11 | "chalk": "^4.0.0", 12 | "cross-spawn": "^7.0.3", 13 | "rxjs": "7.8.1", 14 | "rxjs-shell": "~3.1.3", 15 | "tslib": "^2.3.0" 16 | }, 17 | "devDependencies": { 18 | "@types/cross-spawn": "^6.0.2" 19 | }, 20 | "sideEffects": false 21 | } 22 | -------------------------------------------------------------------------------- /libs/utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './json'; 2 | export * from './rxjs-fs'; 3 | export * from './rxjs-shell'; 4 | export * from './rxjs-tree'; 5 | -------------------------------------------------------------------------------- /libs/utils/src/json.ts: -------------------------------------------------------------------------------- 1 | import { existsSync, readFileSync, writeFileSync } from 'fs'; 2 | 3 | /** 4 | * Sync operations to manipulate JSON files. 5 | */ 6 | 7 | const defaultPath = 'package.json'; 8 | 9 | export function jsonExists(path: string = defaultPath): boolean { 10 | return existsSync(path); 11 | } 12 | 13 | export function jsonRead(path: string = defaultPath, field?: string): any { 14 | if (jsonExists(path)) { 15 | const jsonFile = jsonParse(readFileSync(path, { encoding: 'utf8' })); 16 | if (field && jsonFile.hasOwnProperty(field)) { 17 | return jsonFile[field]; 18 | } 19 | return jsonFile; 20 | } 21 | return field ? null : {}; 22 | } 23 | 24 | export function jsonParse(content: string): any { 25 | try { 26 | // parse the data 27 | return JSON.parse(content); 28 | } catch (e) { 29 | // filter any existing comments 30 | return JSON.parse( 31 | content 32 | .split('\n') 33 | .filter((line) => !line.match(/^\s*?\//)) 34 | .join('\n') 35 | ); 36 | } 37 | } 38 | 39 | export function jsonWrite(path: string, packageJson: any): void { 40 | return writeFileSync(path, `${JSON.stringify(packageJson, null, 2)}\n`, { 41 | encoding: 'utf8', 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /libs/utils/src/rxjs-fs.ts: -------------------------------------------------------------------------------- 1 | import { readFile as rxReadFile } from '@ckapp/rxjs-node-fs'; 2 | import { rename } from 'fs'; 3 | import { bindNodeCallback, Observable } from 'rxjs'; 4 | import { map } from 'rxjs/operators'; 5 | 6 | /** 7 | * RxJs filesystem utilities. 8 | */ 9 | 10 | export { 11 | appendFile, 12 | readDir, 13 | stat, 14 | watch, 15 | writeFile, 16 | } from '@ckapp/rxjs-node-fs'; 17 | 18 | export function readFile( 19 | filepath: string, 20 | options?: { encoding?: BufferEncoding; flag?: string } | null 21 | ): Observable { 22 | return rxReadFile(filepath, options as any).pipe( 23 | map((buffer) => buffer?.toString()) 24 | ); 25 | } 26 | 27 | export const renameFile: ( 28 | oldPath: string, 29 | newPath: string 30 | ) => Observable = bindNodeCallback(rename); 31 | -------------------------------------------------------------------------------- /libs/utils/src/rxjs-tree.ts: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | import { from, Observable, of, throwError } from 'rxjs'; 3 | import { mergeMap } from 'rxjs/operators'; 4 | import { readDir, stat } from './rxjs-fs'; 5 | 6 | /** 7 | * Similar to @angular-devkit's Tree.visit. 8 | */ 9 | 10 | export function treeVisit(path: string): Observable { 11 | return stat(path).pipe( 12 | mergeMap((stats) => { 13 | if (stats.isDirectory()) { 14 | return readDir(path).pipe( 15 | mergeMap((files) => from(files)), 16 | mergeMap((file) => treeVisit(join(path, file))) 17 | ); 18 | } else if (stats.isFile()) { 19 | return of(path); 20 | } 21 | return throwError(`Not a directory nor file: ${path}`); 22 | }) 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /libs/utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.lib.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | } 12 | ], 13 | "compilerOptions": { 14 | "forceConsistentCasingInFileNames": true, 15 | "strict": true, 16 | "noImplicitReturns": true, 17 | "noFallthroughCasesInSwitch": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /libs/utils/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "outDir": "../../dist/out-tsc", 6 | "declaration": true, 7 | "types": ["node"] 8 | }, 9 | "exclude": ["**/*.spec.ts", "**/*.test.ts", "jest.config.ts"], 10 | "include": ["**/*.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /libs/utils/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 | "**/*.test.ts", 10 | "**/*.spec.ts", 11 | "**/*.test.tsx", 12 | "**/*.spec.tsx", 13 | "**/*.test.js", 14 | "**/*.spec.js", 15 | "**/*.test.jsx", 16 | "**/*.spec.jsx", 17 | "**/*.d.ts", 18 | "jest.config.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command = "yarn build:prod" 3 | publish = "dist/website/browser" 4 | [[redirects]] 5 | from = "/*" 6 | to = "/index.html" 7 | status = 200 8 | -------------------------------------------------------------------------------- /tools/tsconfig.tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc/tools", 5 | "rootDir": ".", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": ["node"], 9 | "importHelpers": false 10 | }, 11 | "include": ["**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "allowSyntheticDefaultImports": true, 7 | "declaration": false, 8 | "moduleResolution": "node", 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2015", 12 | "module": "esnext", 13 | "lib": ["es2018", "dom"], 14 | "esModuleInterop": true, 15 | "resolveJsonModule": true, 16 | "skipLibCheck": true, 17 | "skipDefaultLibCheck": true, 18 | "baseUrl": ".", 19 | "paths": { 20 | "@myndpm/demos": ["dist/libs/demos", "libs/demos/index.ts"], 21 | "@myndpm/demos/*": ["dist/libs/demos/*", "libs/demos/*"], 22 | "@myndpm/dyn-forms": ["libs/forms/index.ts"], 23 | "@myndpm/dyn-forms/core": ["libs/forms/core"], 24 | "@myndpm/dyn-forms/logger": ["libs/forms/logger"], 25 | "@myndpm/dyn-forms/ui-material": ["libs/forms/ui-material"], 26 | "@myndpm/dyn-forms/ui-native": ["libs/forms/ui-native"], 27 | "@myndpm/nx": ["libs/nx/src/index.ts"], 28 | "@myndpm/utils": ["libs/tools/utils/src/index.ts"] 29 | } 30 | }, 31 | "exclude": ["node_modules", "tmp"] 32 | } 33 | -------------------------------------------------------------------------------- /tsconfig.schematics.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "declaration": true, 5 | "emitDecoratorMetadata": true, 6 | "experimentalDecorators": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "noFallthroughCasesInSwitch": true, 9 | "noEmitOnError": true, 10 | "noImplicitAny": true, 11 | "noImplicitReturns": false, 12 | "noImplicitThis": true, 13 | "noUnusedLocals": false, 14 | "noUnusedParameters": true, 15 | "skipDefaultLibCheck": true, 16 | "skipLibCheck": true, 17 | "sourceMap": false, 18 | "strict": false, 19 | "strictBindCallApply": true, 20 | "strictFunctionTypes": true, 21 | "strictNullChecks": true, 22 | "moduleResolution": "node", 23 | "module": "commonjs", 24 | "target": "es6", 25 | "lib": [ 26 | "es2019", 27 | "dom" 28 | ], 29 | "types": [] 30 | }, 31 | "exclude": [ 32 | "**/*.spec.ts" 33 | ] 34 | } 35 | --------------------------------------------------------------------------------