@nutin/cli 1.3.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +122 -8
- package/README.md +21 -37
- package/bin/add-feature.mjs +9 -0
- package/bin/cli.mjs +8 -0
- package/bin/create-app.mjs +5 -4
- package/bin/update-app.mjs +9 -0
- package/lib/index.mjs +81 -30
- package/lib/src/add-feature/feature-adder.mjs +83 -0
- package/lib/src/add-feature/feature-context-builder.mjs +25 -0
- package/lib/src/add-feature/nutin-config-updater.mjs +29 -0
- package/lib/src/add-feature/package-json-updater.mjs +49 -0
- package/lib/src/common/feature-registry.mjs +11 -0
- package/lib/src/common/file-generator.mjs +159 -0
- package/lib/src/common/meta-bootstrap-prompt.mjs +33 -0
- package/lib/src/common/package-data.mjs +10 -0
- package/lib/src/common/package-json-helper.mjs +103 -0
- package/lib/src/common/project-meta.mjs +54 -0
- package/lib/src/create-app/context-builder.mjs +21 -0
- package/lib/src/{git-manager.mjs → create-app/git-manager.mjs} +2 -2
- package/lib/src/create-app/json-manager.mjs +73 -0
- package/lib/src/create-app/new-app-prompt.mjs +51 -0
- package/lib/src/{project-generator.mjs → create-app/project-generator.mjs} +15 -13
- package/lib/src/create-app/success-message.mjs +14 -0
- package/lib/src/update-app/conflict-report-writer.mjs +31 -0
- package/lib/src/update-app/fetch-old-templates.mjs +61 -0
- package/lib/src/update-app/project-updater.mjs +136 -0
- package/lib/src/update-app/template-differ.mjs +124 -0
- package/lib/src/update-app/update-context-builder.mjs +25 -0
- package/lib/src/update-app/update-summary-printer.mjs +22 -0
- package/lib/src/update-app/version-compare.mjs +12 -0
- package/lib/src/utils/print.mjs +36 -0
- package/lib/src/utils/promise-exec-alias.mjs +4 -0
- package/package.json +17 -12
- package/templates/base/.gitignore.hbs +6 -1
- package/templates/base/AGENTS.md.hbs +169 -0
- package/templates/base/GETTING_STARTED.md.hbs +227 -0
- package/templates/base/README.md.hbs +8 -17
- package/templates/base/config/languages.json.hbs +6 -0
- package/templates/base/config/seo.json.hbs +12 -0
- package/templates/base/nutin.config.js.hbs +51 -0
- package/templates/base/src/app/components/index.ts.hbs +1 -2
- package/templates/base/src/app/globals.d.ts.hbs +3 -15
- package/templates/base/src/{libs/guards → app}/guards.ts.hbs +1 -5
- package/templates/base/src/app/main.ts.hbs +7 -26
- package/templates/base/src/app/services/index.ts.hbs +1 -1
- package/templates/base/src/app/views/home/home.view.html.hbs +7 -0
- package/templates/base/src/app/views/home/home.view.ts.hbs +1 -56
- package/templates/base/src/app/views/index.ts.hbs +1 -0
- package/templates/base/src/app/views/not-found/not-found.view.html.hbs +8 -0
- package/templates/base/src/app/views/not-found/not-found.view.ts.hbs +4 -37
- package/templates/base/src/core/base-classes/base-component/base-component.test.js.hbs +158 -0
- package/templates/base/src/core/base-classes/base-component/base-component.ts.hbs +81 -31
- package/templates/base/src/core/base-classes/base-component/helpers/catalog.helper.test.js.hbs +124 -0
- package/templates/base/src/core/base-classes/base-component/helpers/catalog.helper.ts.hbs +38 -23
- package/templates/base/src/core/base-classes/base-component/helpers/children.helper.test.js.hbs +74 -0
- package/templates/base/src/core/base-classes/base-component/helpers/children.helper.ts.hbs +1 -1
- package/templates/base/src/core/base-classes/base-component/helpers/dom.helper.test.js.hbs +145 -0
- package/templates/base/src/core/base-classes/base-component/helpers/dom.helper.ts.hbs +41 -1
- package/templates/base/src/core/base-classes/base-component/helpers/event.helper.test.js.hbs +88 -0
- package/templates/base/src/core/base-classes/base-component/helpers/event.helper.ts.hbs +13 -14
- package/templates/base/src/core/base-classes/base-component/helpers/i18n.helper.test.js.hbs +62 -0
- package/templates/base/src/core/base-classes/base-component/helpers/pipe.helper.test.js.hbs +82 -0
- package/templates/base/src/core/base-classes/base-component/helpers/security.helper.test.js.hbs +142 -0
- package/templates/base/src/core/base-classes/base-component/helpers/security.helper.ts.hbs +67 -22
- package/templates/base/src/core/base-classes/base-component/helpers/token.helper.test.js.hbs +183 -0
- package/templates/base/src/core/base-classes/component/component.test.js.hbs +85 -0
- package/templates/base/src/core/base-classes/component/component.ts.hbs +27 -40
- package/templates/base/src/core/base-classes/component/helpers/config.helper.test.js.hbs +58 -0
- package/templates/base/src/core/base-classes/component/helpers/config.helper.ts.hbs +17 -0
- package/templates/base/src/core/base-classes/component/helpers/data-binding.helper.test.js.hbs +75 -0
- package/templates/base/src/core/base-classes/service/service.test.js.hbs +150 -0
- package/templates/base/src/core/base-classes/service/service.ts.hbs +26 -20
- package/templates/base/src/core/base-classes/view/view.test.js.hbs +74 -0
- package/templates/base/src/core/base-classes/view/view.ts.hbs +17 -41
- package/templates/base/src/core/config.ts.hbs +7 -0
- package/templates/base/src/core/index.ts.hbs +0 -3
- package/templates/base/src/core/internals.d.ts.hbs +27 -0
- package/templates/base/src/core/nutin-config.d.ts.hbs +4 -0
- package/templates/base/src/core/services/event-bus/event-bus.test.js.hbs +67 -3
- package/templates/base/src/core/services/event-bus/event-bus.ts.hbs +9 -4
- package/templates/base/src/core/services/event-bus/index.ts.hbs +3 -0
- package/templates/base/src/core/services/event-bus/lifecycle.facade.test.js.hbs +123 -0
- package/templates/base/src/core/services/event-bus/lifecycle.facade.ts.hbs +61 -0
- package/templates/base/src/core/services/event-bus/navigation.facade.test.js.hbs +46 -0
- package/templates/base/src/core/services/event-bus/navigation.facade.ts.hbs +25 -0
- package/templates/base/src/core/services/globals/globals.test.js.hbs +149 -0
- package/templates/base/src/core/services/globals/globals.ts.hbs +95 -0
- package/templates/base/src/core/services/http-client/helpers/http-builder.helper.test.js.hbs +25 -0
- package/templates/base/src/core/services/http-client/helpers/http-manager.helper.test.js.hbs +20 -0
- package/templates/base/src/core/services/http-client/http-client.test.js.hbs +43 -0
- package/templates/base/src/core/services/i18n/i18n.test.js.hbs +270 -0
- package/templates/{features/i18n → base}/src/core/services/i18n/i18n.ts.hbs +60 -9
- package/templates/base/src/core/services/index.ts.hbs +5 -6
- package/templates/base/src/core/services/pipe-registry/pipe-registry.test.js.hbs +60 -1
- package/templates/base/src/core/services/pipe-registry/pipe-registry.ts.hbs +1 -1
- package/templates/base/src/core/services/pipe-registry/pipes.test.js.hbs +128 -0
- package/templates/base/src/{libs/pipes → core/services/pipe-registry}/pipes.ts.hbs +8 -5
- package/templates/base/src/core/services/router/helpers/navigation-manager.helper.test.js.hbs +149 -6
- package/templates/base/src/core/services/router/helpers/navigation-manager.helper.ts.hbs +42 -30
- package/templates/base/src/core/services/router/helpers/route-guard-manager.helper.test.js.hbs +27 -0
- package/templates/base/src/core/services/router/helpers/view-render-manager.helper.test.js.hbs +83 -17
- package/templates/base/src/core/services/router/helpers/view-render-manager.helper.ts.hbs +13 -70
- package/templates/base/src/core/services/router/router.test.js.hbs +226 -2
- package/templates/base/src/core/services/router/router.ts.hbs +40 -9
- package/templates/base/src/index.html.hbs +2 -6
- package/templates/base/src/styles/_styles.scss.hbs +102 -43
- package/templates/base/src/styles/base/_variables.scss.hbs +1 -85
- package/templates/base/src/styles/main.scss.hbs +1 -18
- package/templates/base/src/styles/tailwind.css.hbs +2 -0
- package/templates/base/tools/builder/builder.config.js.hbs +40 -0
- package/templates/base/tools/builder/builder.js.hbs +24 -26
- package/templates/base/tools/builder/core/app/binary-extensions.test.js.hbs +16 -0
- package/templates/base/tools/builder/core/app/compile-ts.js.hbs +16 -0
- package/templates/base/tools/builder/core/{copy-static.js.hbs → app/copy-static.js.hbs} +27 -34
- package/templates/base/tools/builder/core/app/validate-routes.js.hbs +77 -0
- package/templates/base/tools/builder/core/finalize-build.js.hbs +16 -7
- package/templates/base/tools/builder/core/{add-tags.js.hbs → html-index/add-tags.js.hbs} +2 -2
- package/templates/base/tools/builder/core/html-index/add-tags.test.js.hbs +56 -0
- package/templates/base/tools/builder/core/{validate-html.js.hbs → html-index/validate-html.js.hbs} +5 -11
- package/templates/base/tools/builder/core/html-templates/merge-templates.js.hbs +152 -0
- package/templates/base/tools/builder/core/html-templates/minify-html.js.hbs +15 -0
- package/templates/base/tools/builder/core/html-templates/process-html-templates.js.hbs +8 -0
- package/templates/{features/i18n/tools/builder/core → base/tools/builder/core/i18n}/build-i18n.js.hbs +6 -17
- package/templates/base/tools/builder/core/prod-bundle/compress-files.js.hbs +37 -0
- package/templates/base/tools/builder/core/prod-bundle/esbuild.js.hbs +30 -0
- package/templates/base/tools/builder/core/{hash-files.js.hbs → prod-bundle/hash-files.js.hbs} +14 -11
- package/templates/base/tools/builder/core/seo/generate-robots-txt.js.hbs +51 -0
- package/templates/base/tools/builder/core/seo/generate-seo-files.js.hbs +16 -0
- package/templates/base/tools/builder/core/seo/generate-seo-html.js.hbs +128 -0
- package/templates/base/tools/builder/core/seo/generate-sitemap-xml.js.hbs +43 -0
- package/templates/base/tools/builder/core/seo/html-substitutions.js.hbs +99 -0
- package/templates/base/tools/builder/core/seo/i18n-resolution.js.hbs +66 -0
- package/templates/base/tools/builder/core/seo/route-output.js.hbs +64 -0
- package/templates/base/tools/builder/core/seo/ssr/ssr-bundle.js.hbs +54 -0
- package/templates/base/tools/builder/core/seo/ssr/ssr-polyfills.js.hbs +132 -0
- package/templates/base/tools/builder/core/seo/ssr/ssr-render.js.hbs +95 -0
- package/templates/base/tools/builder/core/styles/sass.js.hbs +40 -0
- package/templates/base/tools/builder/core/styles/tailwind.js.hbs +84 -0
- package/templates/base/tools/dev/dev-serve.js.hbs +26 -18
- package/templates/base/tools/dev/serve.js.hbs +11 -1
- package/templates/base/tools/dev/watcher.js.hbs +14 -6
- package/templates/base/tools/generator/generator.js.hbs +64 -47
- package/templates/base/tools/generator/handle-file.js.hbs +17 -44
- package/templates/base/tools/generator/handle-file.test.js.hbs +72 -0
- package/templates/base/tools/generator/templates/{component.template.js.hbs → component/component.template.js.hbs} +3 -2
- package/templates/base/tools/generator/templates/component/component.template.test.js.hbs +23 -0
- package/templates/base/tools/generator/templates/html/html.template.js.hbs +2 -0
- package/templates/base/tools/generator/templates/html/html.template.test.js.hbs +7 -0
- package/templates/base/tools/generator/templates/index.js.hbs +7 -12
- package/templates/base/tools/generator/templates/locale/locale.template.js.hbs +4 -0
- package/templates/base/tools/generator/templates/locale/locale.template.test.js.hbs +7 -0
- package/templates/base/tools/generator/templates/scss/scss.template.js.hbs +1 -0
- package/templates/base/tools/generator/templates/scss/scss.template.test.js.hbs +7 -0
- package/templates/base/tools/generator/templates/service/service.template.js.hbs +17 -0
- package/templates/base/tools/generator/templates/service/service.template.test.js.hbs +22 -0
- package/templates/base/tools/generator/templates/test/test.template.js.hbs +10 -0
- package/templates/base/tools/generator/templates/test/test.template.test.js.hbs +27 -0
- package/templates/base/tools/generator/templates/{view.template.js.hbs → view/view.template.js.hbs} +3 -2
- package/templates/base/tools/generator/templates/view/view.template.test.js.hbs +24 -0
- package/templates/base/tools/testin-nutin/core/coverage/collect-coverage.js.hbs +39 -0
- package/templates/base/tools/testin-nutin/core/coverage/compute-coverage.js.hbs +115 -0
- package/templates/base/tools/testin-nutin/core/coverage/compute-coverage.test.js.hbs +74 -0
- package/templates/base/tools/testin-nutin/core/coverage/write-summary-report.js.hbs +54 -0
- package/templates/base/tools/testin-nutin/core/coverage/write-uncovered-report.js.hbs +44 -0
- package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/assertion-lib.js.hbs +62 -24
- package/templates/base/tools/testin-nutin/core/globals/clock.js.hbs +206 -0
- package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/jsdom-setup.js.hbs +19 -6
- package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/register-test-globals.js.hbs +13 -4
- package/templates/base/tools/testin-nutin/core/globals/silence-console.js.hbs +23 -0
- package/templates/{features/testinNutin/testin-nutin/core/src → base/tools/testin-nutin/core}/globals/spyon.js.hbs +2 -0
- package/templates/base/tools/testin-nutin/core/index.js.hbs +9 -0
- package/templates/base/tools/testin-nutin/core/printer.js.hbs +85 -0
- package/templates/base/tools/testin-nutin/core/queue/queue.test.js.hbs +46 -0
- package/templates/base/tools/testin-nutin/core/queue/test-discovery.test.js.hbs +46 -0
- package/templates/base/tools/testin-nutin/core/queue/test-queue.js.hbs +154 -0
- package/templates/{features/testinNutin → base/tools}/testin-nutin/core/tests/assertions.test.js.hbs +27 -0
- package/templates/base/tools/testin-nutin/core/tests/clock.test.js.hbs +118 -0
- package/templates/base/tools/testin-nutin/core/tests/globals-each-all.test.js.hbs +28 -0
- package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/create-mock-method.js.hbs +2 -1
- package/templates/base/tools/testin-nutin/mocks/create-mock-method.test.js.hbs +64 -0
- package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-event-bus.js.hbs +3 -2
- package/templates/base/tools/testin-nutin/mocks/mock-event-bus.test.js.hbs +66 -0
- package/templates/base/tools/testin-nutin/mocks/mock-http-client.test.js.hbs +26 -0
- package/templates/base/tools/testin-nutin/mocks/mock-i18n.test.js.hbs +61 -0
- package/templates/base/tools/testin-nutin/mocks/mock-router.test.js.hbs +29 -0
- package/templates/base/tools/testin-nutin/runner.js.hbs +100 -0
- package/templates/base/tools/testin-nutin/watch-tests.js.hbs +37 -0
- package/templates/base/tools/utils/error-exit.js.hbs +8 -0
- package/templates/base/tools/utils/format.js.hbs +10 -10
- package/templates/base/tools/utils/format.test.js.hbs +45 -0
- package/templates/base/tools/utils/get-files-recursive.js.hbs +6 -1
- package/templates/base/tools/utils/get-files-recursive.test.js.hbs +49 -0
- package/templates/base/tools/utils/get-rel-to-core.test.js.hbs +18 -0
- package/templates/base/tools/utils/index.js.hbs +1 -3
- package/templates/base/tools/utils/languages.js.hbs +15 -0
- package/templates/base/tools/utils/languages.test.js.hbs +16 -0
- package/templates/base/tools/utils/print.js.hbs +19 -13
- package/templates/base/tools/utils/print.test.js.hbs +60 -0
- package/templates/base/tools/utils/prompt-boolean.js.hbs +7 -0
- package/templates/base/tools/utils/prompt-boolean.test.js.hbs +54 -0
- package/templates/base/tools/utils/run-command.js.hbs +4 -2
- package/templates/base/tools/utils/run-command.test.js.hbs +19 -0
- package/templates/base/tools/utils/run-script.js.hbs +14 -3
- package/templates/base/tools/utils/run-script.test.js.hbs +40 -0
- package/templates/features/{deployHelper → docker}/.dockerignore.hbs +4 -4
- package/templates/features/docker/tools/docker/Dockerfile.template.hbs +51 -0
- package/templates/features/{deployHelper/tools/deployment/nginx.conf.hbs → docker/tools/docker/nginx.conf.template} +4 -2
- package/templates/features/docker/tools/docker/scripts/docker-build.js.hbs +20 -0
- package/templates/features/docker/tools/docker/scripts/docker-ports.js.hbs +48 -0
- package/templates/features/docker/tools/docker/scripts/docker-ports.test.js.hbs +52 -0
- package/templates/features/docker/tools/docker/scripts/docker-run.js.hbs +28 -0
- package/templates/features/docker/tools/docker/scripts/render-docker-template.js.hbs +23 -0
- package/templates/features/docker/tools/docker/scripts/render-docker-template.test.js.hbs +60 -0
- package/templates/features/docker/tools/docker/scripts/validate-docker.js.hbs +30 -0
- package/lib/src/context-builder.mjs +0 -35
- package/lib/src/file-generator.mjs +0 -109
- package/lib/src/json-generator.mjs +0 -31
- package/lib/src/package-manager.mjs +0 -139
- package/lib/src/print.mjs +0 -31
- package/lib/src/prompts.mjs +0 -123
- package/lib/src/utils.mjs +0 -18
- package/lib/src/version.mjs +0 -1
- package/templates/base/builder.config.js.hbs +0 -35
- package/templates/base/src/app/components/common/anchor/anchor.component.ts.hbs +0 -32
- package/templates/base/src/app/components/common/button/button.component.ts.hbs +0 -40
- package/templates/base/src/app/dom.test.js.hbs +0 -13
- package/templates/base/src/app/services/example/example.service.ts.hbs +0 -18
- package/templates/base/src/app/views/home/home.view.test.js.hbs +0 -26
- package/templates/base/src/core/services/store/store.test.js.hbs +0 -8
- package/templates/base/src/core/services/store/store.ts.hbs +0 -39
- package/templates/base/src/core/utils/anchor-manager/anchor-manager.utils.test.js.hbs +0 -0
- package/templates/base/src/core/utils/anchor-manager/anchor-manager.utils.ts.hbs +0 -85
- package/templates/base/src/core/utils/button-manager/button-manager.utils.test.js.hbs +0 -249
- package/templates/base/src/core/utils/button-manager/button-manager.utils.ts.hbs +0 -108
- package/templates/base/src/core/utils/helpers/attributes.helper.ts.hbs +0 -50
- package/templates/base/src/core/utils/index.ts.hbs +0 -2
- package/templates/base/src/libs/index.ts.hbs +0 -4
- package/templates/base/src/libs/popover/popover.ts.hbs +0 -145
- package/templates/base/src/libs/snackbar/snackbar.ts.hbs +0 -72
- package/templates/base/src/styles/base/_functions.scss.hbs +0 -9
- package/templates/base/src/styles/core/_libs.scss.hbs +0 -132
- package/templates/base/tools/builder/core/esbuild.js.hbs +0 -25
- package/templates/base/tools/builder/core/minify-html.js.hbs +0 -60
- package/templates/base/tools/builder/core/sass.js.hbs +0 -22
- package/templates/base/tools/builder/core/tsc.js.hbs +0 -12
- package/templates/base/tools/generator/templates/service.template.js.hbs +0 -17
- package/templates/base/tools/utils/export-flags.js.hbs +0 -6
- package/templates/features/deployHelper/tools/builder/core/compress-files.js.hbs +0 -56
- package/templates/features/deployHelper/tools/deployment/Dockerfile.hbs +0 -30
- package/templates/features/i18n/src/app/views/home/locales/en.json.hbs +0 -9
- package/templates/features/i18n/src/app/views/not-found/locales/en.json +0 -8
- package/templates/features/i18n/src/app/views/not-found/locales/fr.json +0 -8
- package/templates/features/i18n/src/core/config.ts.hbs +0 -3
- package/templates/features/i18n/src/core/services/i18n/i18n.test.js.hbs +0 -125
- package/templates/features/i18n/tools/generator/templates/json.template.js.hbs +0 -8
- package/templates/features/i18n/tools/utils/languages.js.hbs +0 -7
- package/templates/features/stylinNutin/src/styles/_custom-classes.scss.hbs +0 -9
- package/templates/features/stylinNutin/src/styles/base/_mixins.scss.hbs +0 -372
- package/templates/features/stylinNutin/src/styles/components/_index.scss.hbs +0 -3
- package/templates/features/stylinNutin/src/styles/core/_utilities.scss.hbs +0 -240
- package/templates/features/stylinNutin/src/styles/views/_index.scss.hbs +0 -0
- package/templates/features/stylinNutin/tools/generator/templates/scss.template.js.hbs +0 -4
- package/templates/features/template/src/app/views/home/home.view.html.hbs +0 -56
- package/templates/features/template/src/app/views/not-found/not-found.view.html.hbs +0 -19
- package/templates/features/template/tools/builder/core/merge-templates.js.hbs +0 -49
- package/templates/features/template/tools/generator/templates/html.template.js.hbs +0 -2
- package/templates/features/testinNutin/testin-nutin/core/index.js.hbs +0 -5
- package/templates/features/testinNutin/testin-nutin/core/src/utils/print.js.hbs +0 -64
- package/templates/features/testinNutin/testin-nutin/core/src/utils/test-queue.js.hbs +0 -64
- package/templates/features/testinNutin/testin-nutin/core/tests/globals-each-all.test.js.hbs +0 -28
- package/templates/features/testinNutin/testin-nutin/mocks/mock-store.js.hbs +0 -38
- package/templates/features/testinNutin/testin-nutin/runner.js.hbs +0 -36
- package/templates/features/testinNutin/testin-nutin/watch-tests.js.hbs +0 -21
- package/templates/features/testinNutin/testin-nutin.config.js.hbs +0 -14
- /package/lib/src/{template-compiler.mjs → common/template-compiler.mjs} +0 -0
- /package/templates/{features/i18n → base}/src/core/base-classes/base-component/helpers/i18n.helper.ts.hbs +0 -0
- /package/templates/{features/i18n → base}/src/core/services/i18n/languages.ts.hbs +0 -0
- /package/templates/base/tools/builder/{variables → core/app}/binary-extensions.js.hbs +0 -0
- /package/templates/base/tools/builder/core/{paths.js.hbs → app/paths.js.hbs} +0 -0
- /package/templates/{features/testinNutin/testin-nutin/core/src/utils → base/tools/testin-nutin/core/queue}/queue.js.hbs +0 -0
- /package/templates/{features/testinNutin/testin-nutin/core/src/utils → base/tools/testin-nutin/core/queue}/test-discovery.js.hbs +0 -0
- /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-http-client.js.hbs +0 -0
- /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-i18n.js.hbs +0 -0
- /package/templates/{features/testinNutin → base/tools}/testin-nutin/mocks/mock-router.js.hbs +0 -0
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { Service, AppEventBus } from "../../index.js";
|
|
2
|
-
|
|
3
|
-
export type StoreState = Record<string, any>;
|
|
4
|
-
|
|
5
|
-
export class Store extends Service<Store> {
|
|
6
|
-
private _state: StoreState = {};
|
|
7
|
-
|
|
8
|
-
constructor() {
|
|
9
|
-
super();
|
|
10
|
-
this.registerCleanup(this.clear);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
public set<T = any>(key: string, value: T): void {
|
|
14
|
-
this._state[key] = value;
|
|
15
|
-
AppEventBus.emit(`store:${key}`, value);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
public get<T = any>(key: string): T | undefined {
|
|
19
|
-
return this._state[key];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
public subscribe<T = any>(key: string, callback: (value: T) => void): void {
|
|
23
|
-
AppEventBus.subscribe(`store:${key}`, callback);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
public unsubscribe<T = any>(key: string, callback: (value: T) => void): void {
|
|
27
|
-
AppEventBus.off(`store:${key}`, callback);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
public clear(): void {
|
|
31
|
-
this._state = {};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
protected onDestroy(): void {
|
|
35
|
-
this.clear();
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export const AppStore = Store.getInstance();
|
|
File without changes
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { AttributesHelper, IAttributesConfig } from "../helpers/attributes.helper.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* ```typescript
|
|
5
|
-
interface IAttributesConfig {
|
|
6
|
-
{{#if i18n}}
|
|
7
|
-
i18nKey?: string;
|
|
8
|
-
{{/if}}
|
|
9
|
-
textContent?: string;
|
|
10
|
-
className?: string;
|
|
11
|
-
style?: string;
|
|
12
|
-
// use regular pipe syntax for arguments / chaining
|
|
13
|
-
pipes?: string;
|
|
14
|
-
}
|
|
15
|
-
interface IAnchorConfig extends IAttributesConfig {
|
|
16
|
-
// prefix href with '#' for internal anchor
|
|
17
|
-
href: string;
|
|
18
|
-
target?: string;
|
|
19
|
-
tagName?: keyof HTMLElementTagNameMap;
|
|
20
|
-
}
|
|
21
|
-
```
|
|
22
|
-
*/
|
|
23
|
-
export interface IAnchorConfig extends IAttributesConfig {
|
|
24
|
-
href: string;
|
|
25
|
-
target?: string;
|
|
26
|
-
tagName?: keyof HTMLElementTagNameMap;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export class AnchorManager {
|
|
30
|
-
private config: IAnchorConfig;
|
|
31
|
-
|
|
32
|
-
constructor(
|
|
33
|
-
config: IAnchorConfig,
|
|
34
|
-
target: HTMLElement
|
|
35
|
-
) {
|
|
36
|
-
this.config = config;
|
|
37
|
-
this.appendAnchorElement(target);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
private appendAnchorElement(target: HTMLElement): void {
|
|
41
|
-
const container = this.createAnchorContainer();
|
|
42
|
-
target.appendChild(container);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
private createAnchorContainer(): HTMLSpanElement {
|
|
46
|
-
const container = document.createElement('span');
|
|
47
|
-
const anchor = this.createAnchor();
|
|
48
|
-
|
|
49
|
-
container.appendChild(anchor);
|
|
50
|
-
|
|
51
|
-
return container;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
private createAnchor(): HTMLElement {
|
|
55
|
-
const anchor = document.createElement('a');
|
|
56
|
-
|
|
57
|
-
this.setAnchorRef(anchor);
|
|
58
|
-
|
|
59
|
-
AttributesHelper.setAttributes(anchor, this.config);
|
|
60
|
-
|
|
61
|
-
this.handleClick(anchor);
|
|
62
|
-
|
|
63
|
-
return anchor;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
private setAnchorRef(anchor: HTMLAnchorElement): void {
|
|
67
|
-
anchor.setAttribute('href', this.config.href);
|
|
68
|
-
if (this.config.target) {
|
|
69
|
-
anchor.setAttribute('target', this.config.target);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
private handleClick(anchor: HTMLAnchorElement): void {
|
|
74
|
-
const isInternal = this.config.href.startsWith('#');
|
|
75
|
-
if (!isInternal) return;
|
|
76
|
-
|
|
77
|
-
const id = this.config.href.slice(1);
|
|
78
|
-
|
|
79
|
-
anchor?.addEventListener('click', (e) => {
|
|
80
|
-
e.preventDefault();
|
|
81
|
-
const target = document.getElementById(id);
|
|
82
|
-
target?.scrollIntoView({ behavior: 'smooth' });
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
}
|
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
import { ButtonManager } from '#root/dist/src/core/index.js';
|
|
2
|
-
|
|
3
|
-
describe('ButtonManager', () => {
|
|
4
|
-
it('should initialize with default options', () => {
|
|
5
|
-
const mockComponent = {};
|
|
6
|
-
const manager = new ButtonManager(mockComponent);
|
|
7
|
-
|
|
8
|
-
expect(manager.component).toBe(mockComponent);
|
|
9
|
-
expect(manager.buttons.length).toBe(0);
|
|
10
|
-
expect(manager.containerOptions.containerClassName).toBe('dynamic-buttons');
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('should initialize with custom options', () => {
|
|
14
|
-
const mockComponent = {};
|
|
15
|
-
const buttons = [{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'test' }];
|
|
16
|
-
const options = {
|
|
17
|
-
containerClassName: 'custom-container',
|
|
18
|
-
buttonClassName: 'custom-button'
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const manager = new ButtonManager(mockComponent, buttons, options);
|
|
22
|
-
|
|
23
|
-
expect(manager.buttons.length).toBe(1);
|
|
24
|
-
expect(manager.containerOptions.containerClassName).toBe('custom-container');
|
|
25
|
-
expect(manager.containerOptions.buttonClassName).toBe('custom-button');
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('should return null for empty buttons array', () => {
|
|
29
|
-
const mockComponent = {};
|
|
30
|
-
const manager = new ButtonManager(mockComponent, []);
|
|
31
|
-
|
|
32
|
-
const container = manager.createButtonContainer();
|
|
33
|
-
expect(container).toBeUndefined();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('should return null for undefined buttons', () => {
|
|
37
|
-
const mockComponent = {};
|
|
38
|
-
const manager = new ButtonManager(mockComponent);
|
|
39
|
-
|
|
40
|
-
const container = manager.createButtonContainer();
|
|
41
|
-
expect(container).toBeUndefined();
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('should create container with correct class name', () => {
|
|
45
|
-
const mockComponent = {};
|
|
46
|
-
const buttons = [{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'test' }];
|
|
47
|
-
const manager = new ButtonManager(mockComponent, buttons);
|
|
48
|
-
|
|
49
|
-
const container = manager.createButtonContainer();
|
|
50
|
-
|
|
51
|
-
expect(container).toBeDefined();
|
|
52
|
-
expect(container.className).toBe('dynamic-buttons');
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('should create container with custom class name', () => {
|
|
56
|
-
const mockComponent = {};
|
|
57
|
-
const buttons = [{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'test' }];
|
|
58
|
-
const options = { containerClassName: 'my-buttons' };
|
|
59
|
-
const manager = new ButtonManager(mockComponent, buttons, options);
|
|
60
|
-
|
|
61
|
-
const container = manager.createButtonContainer();
|
|
62
|
-
|
|
63
|
-
expect(container.className).toBe('my-buttons');
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('should create correct number of buttons', () => {
|
|
67
|
-
const mockComponent = {};
|
|
68
|
-
const buttons = [
|
|
69
|
-
{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'button1' },
|
|
70
|
-
{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'button2' },
|
|
71
|
-
{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'button3' }
|
|
72
|
-
];
|
|
73
|
-
const manager = new ButtonManager(mockComponent, buttons);
|
|
74
|
-
|
|
75
|
-
const container = manager.createButtonContainer();
|
|
76
|
-
|
|
77
|
-
expect(container.children.length).toBe(3);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('should create button with {{#if i18n}}i18nKey{{else}}textContent{{/if}} as text', () => {
|
|
81
|
-
const mockComponent = {};
|
|
82
|
-
const manager = new ButtonManager(mockComponent);
|
|
83
|
-
const btn = { {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'save' };
|
|
84
|
-
|
|
85
|
-
const button = manager.createButton(btn, 0);
|
|
86
|
-
|
|
87
|
-
{{#if i18n}}
|
|
88
|
-
expect(button.getAttribute('data-i18n')).toBe('save');
|
|
89
|
-
{{else}}
|
|
90
|
-
expect(button.textContent).toBe('save');
|
|
91
|
-
{{/if}}
|
|
92
|
-
});
|
|
93
|
-
{{#if i18n}}
|
|
94
|
-
|
|
95
|
-
it('should prioritize textContent over i18nKey', () => {
|
|
96
|
-
const mockComponent = {};
|
|
97
|
-
const manager = new ButtonManager(mockComponent);
|
|
98
|
-
const btn = {
|
|
99
|
-
i18nKey: 'save',
|
|
100
|
-
textContent: 'Save Document'
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const button = manager.createButton(btn, 0);
|
|
104
|
-
|
|
105
|
-
expect(button.textContent).toBe('Save Document');
|
|
106
|
-
expect(button.getAttribute('data-i18n')).toBe('save');
|
|
107
|
-
});
|
|
108
|
-
{{/if}}
|
|
109
|
-
|
|
110
|
-
it('should set button className correctly', () => {
|
|
111
|
-
const mockComponent = {};
|
|
112
|
-
const manager = new ButtonManager(mockComponent, []);
|
|
113
|
-
const btn = {
|
|
114
|
-
i18nKey: 'save',
|
|
115
|
-
className: 'btn-primary'
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
const button = manager.createButton(btn, 0);
|
|
119
|
-
|
|
120
|
-
expect(button.className).toBe('btn-primary');
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it('should set data-event attribute correctly', () => {
|
|
124
|
-
const mockComponent = {};
|
|
125
|
-
const manager = new ButtonManager(mockComponent);
|
|
126
|
-
const btn = { {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'save' };
|
|
127
|
-
|
|
128
|
-
const button = manager.createButton(btn, 2);
|
|
129
|
-
|
|
130
|
-
expect(button.getAttribute('data-event')).toBe('click:onButtonClick_2');
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('should bind callback method to component', () => {
|
|
134
|
-
const mockComponent = {};
|
|
135
|
-
const manager = new ButtonManager(mockComponent);
|
|
136
|
-
const btn = {
|
|
137
|
-
{{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'test',
|
|
138
|
-
callback: () => 'called'
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
manager.bindButtonCallback(btn, 1);
|
|
142
|
-
|
|
143
|
-
expect(typeof mockComponent.onButtonClick_1).toBe('function')
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it('should execute callback when bound method is called', () => {
|
|
147
|
-
const mockComponent = {};
|
|
148
|
-
const manager = new ButtonManager(mockComponent);
|
|
149
|
-
let callbackExecuted = false;
|
|
150
|
-
const btn = {
|
|
151
|
-
{{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'test',
|
|
152
|
-
callback: () => { callbackExecuted = true; }
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
manager.bindButtonCallback(btn, 0);
|
|
156
|
-
mockComponent.onButtonClick_0();
|
|
157
|
-
|
|
158
|
-
expect(callbackExecuted).toBe(true);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it('should append button container to target element', () => {
|
|
162
|
-
const mockComponent = {};
|
|
163
|
-
const buttons = [{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'test' }];
|
|
164
|
-
const manager = new ButtonManager(mockComponent, buttons);
|
|
165
|
-
const target = document.createElement('div');
|
|
166
|
-
|
|
167
|
-
manager.appendTo(target);
|
|
168
|
-
|
|
169
|
-
expect(target.children.length).toBe(1);
|
|
170
|
-
expect(target.children[0].className).toBe('dynamic-buttons')
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it('should not append anything for empty buttons', () => {
|
|
174
|
-
const mockComponent = {};
|
|
175
|
-
const manager = new ButtonManager(mockComponent, []);
|
|
176
|
-
const target = document.createElement('div');
|
|
177
|
-
|
|
178
|
-
manager.appendTo(target);
|
|
179
|
-
|
|
180
|
-
expect(target.children.length).toBe(0);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it('should create complete button setup end-to-end', () => {
|
|
184
|
-
const mockComponent = {};
|
|
185
|
-
let button1Clicked = false;
|
|
186
|
-
let button2Clicked = false;
|
|
187
|
-
|
|
188
|
-
const buttons = [
|
|
189
|
-
{
|
|
190
|
-
{{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'save',
|
|
191
|
-
className: 'btn-primary',
|
|
192
|
-
callback: () => { button1Clicked = true; }
|
|
193
|
-
},
|
|
194
|
-
{
|
|
195
|
-
{{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'cancel',
|
|
196
|
-
textContent: 'Cancel Action',
|
|
197
|
-
className: 'btn-secondary',
|
|
198
|
-
callback: () => { button2Clicked = true; }
|
|
199
|
-
}
|
|
200
|
-
];
|
|
201
|
-
|
|
202
|
-
const manager = new ButtonManager(mockComponent, buttons, {
|
|
203
|
-
containerClassName: 'form-buttons'
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
const container = manager.createButtonContainer();
|
|
207
|
-
|
|
208
|
-
expect(container.className).toBe('form-buttons');
|
|
209
|
-
expect(container.children.length).toBe(2);
|
|
210
|
-
|
|
211
|
-
const firstButton = container.children[0];
|
|
212
|
-
expect(firstButton.className).toBe('btn-primary');
|
|
213
|
-
expect(firstButton.getAttribute('data-event')).toBe('click:onButtonClick_0');
|
|
214
|
-
|
|
215
|
-
const secondButton = container.children[1];
|
|
216
|
-
expect(secondButton.className).toBe('btn-secondary');
|
|
217
|
-
expect(secondButton.getAttribute('data-event')).toBe('click:onButtonClick_1');
|
|
218
|
-
|
|
219
|
-
mockComponent.onButtonClick_0();
|
|
220
|
-
mockComponent.onButtonClick_1();
|
|
221
|
-
|
|
222
|
-
expect(button1Clicked).toBe(true);
|
|
223
|
-
expect(button2Clicked).toBe(true);
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
it('should handle button with empty {{#if i18n}}i18nKey{{else}}textContent{{/if}}', () => {
|
|
227
|
-
const mockComponent = {};
|
|
228
|
-
const manager = new ButtonManager(mockComponent);
|
|
229
|
-
const btn = { {{#if i18n}}i18nKey{{else}}textContent{{/if}}: '' };
|
|
230
|
-
|
|
231
|
-
const button = manager.createButton(btn, 0);
|
|
232
|
-
|
|
233
|
-
expect(button.textContent).toBe('');
|
|
234
|
-
expect(button.getAttribute('data-i18n')).toBe(null);
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
it('should handle updateButtons method', () => {
|
|
238
|
-
const mockComponent = {};
|
|
239
|
-
const initialButtons = [{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'initial' }];
|
|
240
|
-
const manager = new ButtonManager(mockComponent, initialButtons);
|
|
241
|
-
|
|
242
|
-
const newButtons = [{ {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'new1' }, { {{#if i18n}}i18nKey{{else}}textContent{{/if}}: 'new2' }];
|
|
243
|
-
manager.updateButtons(newButtons);
|
|
244
|
-
|
|
245
|
-
expect(manager.buttons.length).toBe(2);
|
|
246
|
-
expect(manager.buttons[0].{{#if i18n}}i18nKey{{else}}textContent{{/if}}).toBe('new1');
|
|
247
|
-
expect(manager.buttons[1].{{#if i18n}}i18nKey{{else}}textContent{{/if}}).toBe('new2');
|
|
248
|
-
});
|
|
249
|
-
})
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { AttributesHelper, IAttributesConfig } from "../helpers/attributes.helper.js";
|
|
2
|
-
|
|
3
|
-
export interface BaseButton extends IAttributesConfig {
|
|
4
|
-
callback: () => void;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export interface ButtonContainerOptions {
|
|
8
|
-
containerClassName?: string;
|
|
9
|
-
containerStyles?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* ```typescript
|
|
14
|
-
interface IAttributesConfig {
|
|
15
|
-
{{#if i18n}}
|
|
16
|
-
i18nKey?: string;
|
|
17
|
-
{{/if}}
|
|
18
|
-
textContent?: string;
|
|
19
|
-
className?: string;
|
|
20
|
-
style?: string;
|
|
21
|
-
// use regular pipe syntax for arguments / chaining
|
|
22
|
-
pipes?: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface BaseButton extends IAttributesConfig {
|
|
26
|
-
callback: () => void;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface ButtonContainerOptions {
|
|
30
|
-
containerClassName?: string;
|
|
31
|
-
containerStyles?: string;
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
*/
|
|
35
|
-
export class ButtonManager {
|
|
36
|
-
private component: any;
|
|
37
|
-
private buttons: BaseButton[];
|
|
38
|
-
private containerOptions: ButtonContainerOptions;
|
|
39
|
-
|
|
40
|
-
constructor(
|
|
41
|
-
component: any,
|
|
42
|
-
buttons: BaseButton[] = [],
|
|
43
|
-
containerOptions: ButtonContainerOptions = {}
|
|
44
|
-
) {
|
|
45
|
-
this.component = component;
|
|
46
|
-
this.buttons = buttons;
|
|
47
|
-
this.containerOptions = {
|
|
48
|
-
containerClassName: 'dynamic-buttons',
|
|
49
|
-
containerStyles: '',
|
|
50
|
-
...containerOptions
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
public createButtonContainer(): HTMLElement | null {
|
|
55
|
-
if (!Array.isArray(this.buttons) || this.buttons.length === 0) {
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const container = document.createElement('div');
|
|
60
|
-
container.className = this.containerOptions.containerClassName || 'dynamic-buttons';
|
|
61
|
-
container.style = this.containerOptions.containerStyles || '';
|
|
62
|
-
|
|
63
|
-
this.buttons.forEach((config, index) => {
|
|
64
|
-
const button = this.createButton(config, index);
|
|
65
|
-
container.appendChild(button);
|
|
66
|
-
this.bindButtonCallback(config, index);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
return container;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
public appendTo(target: HTMLElement): void {
|
|
73
|
-
const container = this.createButtonContainer();
|
|
74
|
-
if (container) {
|
|
75
|
-
target.appendChild(container);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
private createButton(config: BaseButton, index: number): HTMLElement {
|
|
80
|
-
const button = document.createElement('button');
|
|
81
|
-
|
|
82
|
-
AttributesHelper.setAttributes(button, config);
|
|
83
|
-
|
|
84
|
-
this.setDataEvent(button, index);
|
|
85
|
-
|
|
86
|
-
return button;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
private setDataEvent(button: HTMLButtonElement, index: number): void {
|
|
90
|
-
button.setAttribute('data-event', `click:onButtonClick_${index}`);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
private bindButtonCallback(config: BaseButton, index: number): void {
|
|
94
|
-
const methodName = `onButtonClick_${index}`;
|
|
95
|
-
|
|
96
|
-
this.component[methodName] = () => {
|
|
97
|
-
if (typeof config.callback === 'function') {
|
|
98
|
-
config.callback();
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/** Note : doesn't track container
|
|
104
|
-
*/
|
|
105
|
-
public updateButtons(newButtons: BaseButton[]): void {
|
|
106
|
-
this.buttons = newButtons;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
export interface IAttributesConfig {
|
|
2
|
-
{{#if i18n}}
|
|
3
|
-
i18nKey?: string;
|
|
4
|
-
{{/if}}
|
|
5
|
-
textContent?: string;
|
|
6
|
-
className?: string;
|
|
7
|
-
style?: string;
|
|
8
|
-
// use regular pipe syntax for arguments / chaining
|
|
9
|
-
pipes?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export class AttributesHelper {
|
|
13
|
-
public static setAttributes(element: HTMLElement, config: IAttributesConfig): void {
|
|
14
|
-
this.setContent(element, config);
|
|
15
|
-
this.setPipes(element, config);
|
|
16
|
-
this.setStyle(element, config);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
private static setContent(element: HTMLElement, config: IAttributesConfig): void {
|
|
20
|
-
element.textContent = config.textContent || '';
|
|
21
|
-
{{#if i18n}}
|
|
22
|
-
if (config.i18nKey) {
|
|
23
|
-
element.setAttribute('data-i18n', config.i18nKey);
|
|
24
|
-
}
|
|
25
|
-
{{/if}}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
private static setPipes(element: HTMLElement, config: IAttributesConfig): void {
|
|
29
|
-
if (!config.pipes) return;
|
|
30
|
-
element.setAttribute('data-pipe', config.pipes);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
private static setStyle(element: HTMLElement, config: IAttributesConfig): void {
|
|
34
|
-
const classes = [
|
|
35
|
-
config.className
|
|
36
|
-
].filter(Boolean).join(' ');
|
|
37
|
-
|
|
38
|
-
const style = [
|
|
39
|
-
config.style
|
|
40
|
-
].filter(Boolean).join(' ');
|
|
41
|
-
|
|
42
|
-
if (classes) {
|
|
43
|
-
element.className = classes;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if(style) {
|
|
47
|
-
element.style = style;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { View, ButtonManager, BaseButton, ViewRenderManager } from '../../core/index.js';
|
|
2
|
-
|
|
3
|
-
export interface PopoverButton extends BaseButton {
|
|
4
|
-
// if needed for Popover-specific properties
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export interface PopoverOptions {
|
|
8
|
-
template: string;
|
|
9
|
-
viewName?: string;
|
|
10
|
-
onClose?: () => void;
|
|
11
|
-
buttons?: PopoverButton[];
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export class PopoverView extends View {
|
|
15
|
-
private onClose?: () => void;
|
|
16
|
-
private overlay: HTMLElement | null = null;
|
|
17
|
-
private buttonManager: ButtonManager;
|
|
18
|
-
|
|
19
|
-
constructor({
|
|
20
|
-
template,
|
|
21
|
-
buttons = [],
|
|
22
|
-
onClose,
|
|
23
|
-
viewName = 'popover',
|
|
24
|
-
}: PopoverOptions) {
|
|
25
|
-
super({template, tagName: 'div', mountTarget: 'body', viewName});
|
|
26
|
-
this.onClose = onClose;
|
|
27
|
-
this.buttonManager = new ButtonManager(
|
|
28
|
-
this,
|
|
29
|
-
this.wrapButtonCallbacks(buttons),
|
|
30
|
-
{ containerClassName: 'popover-buttons' }
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
public override shouldUpdateMetaContent(): boolean {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
public override render(): HTMLElement {
|
|
39
|
-
document.body.classList.add('no-scroll');
|
|
40
|
-
this.overlay = this.createOverlay();
|
|
41
|
-
|
|
42
|
-
const wrapper = this.createWrapper();
|
|
43
|
-
const content = this.createContent();
|
|
44
|
-
|
|
45
|
-
this.appendCloseButton(content);
|
|
46
|
-
this.appendFooterButtons(content);
|
|
47
|
-
|
|
48
|
-
wrapper.appendChild(content);
|
|
49
|
-
this.overlay.appendChild(wrapper);
|
|
50
|
-
document.body.appendChild(this.overlay);
|
|
51
|
-
|
|
52
|
-
this.autoBindEvents();
|
|
53
|
-
this.parseDataAttributes();
|
|
54
|
-
this.animateIn(wrapper);
|
|
55
|
-
|
|
56
|
-
this.bindOverlayClose();
|
|
57
|
-
|
|
58
|
-
return this.overlay;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
public override destroy(): void {
|
|
62
|
-
if (this.overlay) {
|
|
63
|
-
const wrapper = this.overlay.querySelector('.popover-wrapper');
|
|
64
|
-
this.overlay.classList.remove('show');
|
|
65
|
-
wrapper?.classList.remove('show');
|
|
66
|
-
|
|
67
|
-
setTimeout(() => {
|
|
68
|
-
wrapper?.remove()
|
|
69
|
-
this.overlay?.remove();
|
|
70
|
-
this.overlay = null;
|
|
71
|
-
}, 250); // match transition duration
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
document.body.classList.remove('no-scroll');
|
|
75
|
-
super.destroy();
|
|
76
|
-
|
|
77
|
-
if (typeof this.onClose === 'function') {
|
|
78
|
-
this.onClose();
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Wraps button callbacks to include destroy() call
|
|
83
|
-
private wrapButtonCallbacks(buttons: PopoverButton[]): PopoverButton[] {
|
|
84
|
-
return buttons.map(btn => ({
|
|
85
|
-
...btn,
|
|
86
|
-
callback: () => {
|
|
87
|
-
if (btn.callback) {
|
|
88
|
-
btn.callback();
|
|
89
|
-
}
|
|
90
|
-
this.destroy();
|
|
91
|
-
}
|
|
92
|
-
}));
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
private createOverlay(): HTMLElement {
|
|
96
|
-
const overlay = document.createElement('div');
|
|
97
|
-
overlay.className = 'popover-overlay';
|
|
98
|
-
return overlay;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
private createWrapper(): HTMLElement {
|
|
102
|
-
const wrapper = document.createElement('div');
|
|
103
|
-
wrapper.className = 'popover-wrapper';
|
|
104
|
-
return wrapper;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
private createContent(): HTMLElement {
|
|
108
|
-
const content = super.render();
|
|
109
|
-
content.classList.add('popover-content');
|
|
110
|
-
ViewRenderManager.cleanupOptionalContent();
|
|
111
|
-
return content;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
private appendCloseButton(content: HTMLElement): void {
|
|
115
|
-
const closeButton = document.createElement('button');
|
|
116
|
-
closeButton.className = 'popover-close-button';
|
|
117
|
-
closeButton.innerHTML = '×';
|
|
118
|
-
closeButton.setAttribute('aria-label', 'Close');
|
|
119
|
-
// bind method onCloseClick
|
|
120
|
-
closeButton.setAttribute('data-event', 'click:onCloseClick');
|
|
121
|
-
content.prepend(closeButton);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Handles the close button (via data-event bound in appendCloseButton)
|
|
125
|
-
private onCloseClick(): void {
|
|
126
|
-
this.destroy();
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
private appendFooterButtons(content: HTMLElement): void {
|
|
130
|
-
this.buttonManager.appendTo(content);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
private bindOverlayClose(): void {
|
|
134
|
-
this.overlay?.addEventListener('click', (e: MouseEvent) => {
|
|
135
|
-
if (e.target === this.overlay) this.destroy();
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
private animateIn(wrapper: HTMLElement): void {
|
|
140
|
-
requestAnimationFrame(() => {
|
|
141
|
-
this.overlay?.classList.add('show');
|
|
142
|
-
wrapper.classList.add('show');
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
}
|