diff --git a/compat/ember-decorators/component.ts b/compat/ember-decorators/component.ts new file mode 100644 index 0000000..d6eed93 --- /dev/null +++ b/compat/ember-decorators/component.ts @@ -0,0 +1,13 @@ +export { + className, + attribute, + classNames, + classNameBindings, + attributeBindings, + tagName, +} from '@ember-decorators/component'; + +// noop +export const layout = () => (target) => { + return target; +}; diff --git a/package.json b/package.json index 60fc166..ba14c7e 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,7 @@ "ember-cookies": "^1.0.0", "ember-data": "5.1.1", "ember-intl": "^5.7.2", + "ember-modal-dialog": "^4.1.2", "ember-modifier": "^4.0.0", "ember-notify": "^6.0.4", "ember-page-title": "^7.0.0", diff --git a/plugins/drop-import-sync.ts b/plugins/drop-import-sync.ts new file mode 100644 index 0000000..403e188 --- /dev/null +++ b/plugins/drop-import-sync.ts @@ -0,0 +1,71 @@ +export function dropImportSync(addons: string[]) { + return function dropImportSyncPlugin(babel) { + const { types: t } = babel; + let cnt = 0; + function keyValue() { + return `_$key${cnt++}`; + } + const shouldContinue = (state) => { + const fName = state.file.opts.filename; + return ( + fName.includes('node_modules') && + addons.some((el) => fName.includes(`/${el}/`)) + ); + }; + + return { + name: 'drop-import-sync', // not required + visitor: { + Program: { + exit(path, state) { + if (!shouldContinue(state)) { + return; + } + if (state.importsToAppend) { + state.importsToAppend.forEach((el) => { + path.node.body.unshift(el); + }); + path.node.body.push( + t.functionDeclaration( + t.identifier('_$importSync'), + [t.identifier('_$a')], + t.blockStatement([t.returnStatement(t.identifier('_$a'))]) + ) + ); + } + }, + }, + ImportDeclaration(path, state) { + if (!shouldContinue(state)) { + return; + } + if (path.node.source.value === '@embroider/macros') { + path.node.specifiers = path.node.specifiers.filter((el) => { + return el.imported.name !== 'importSync'; + }); + if (path.node.specifiers.length === 0) { + path.remove(); + } + } + }, + CallExpression(path, state) { + if (!shouldContinue(state)) { + return; + } + if (path.node.callee && path.node.callee.name === 'importSync') { + path.node.callee.name = '_$importSync'; + state.importsToAppend = state.importsToAppend || []; + const literalName = keyValue(); + state.importsToAppend.push( + t.importDeclaration( + [t.importNamespaceSpecifier(t.identifier(literalName))], + t.stringLiteral(path.node.arguments[0].value) + ) + ); + path.node.arguments[0] = t.identifier(literalName); + } + }, + }, + }; + }; +} diff --git a/plugins/remove-legacy-layout.js b/plugins/remove-legacy-layout.js deleted file mode 100644 index c9484c4..0000000 --- a/plugins/remove-legacy-layout.js +++ /dev/null @@ -1,56 +0,0 @@ -export function removeLegacyLayout() { - const shouldContinue = (state) => { - const fName = state.file.opts.filename; - return fName.includes('node_modules') && fName.includes('addon'); - }; - // const { types: t } = babel; - return { - name: 'ast-transform', // not required - visitor: { - ImportDeclaration(path, state) { - if (!shouldContinue(state)) { - return; - } - if (path.node.source.value === '@ember-decorators/component') { - path.remove(); - } else if (path.node.source.value.includes('/templates/')) { - path.remove(); - } - }, - ObjectProperty(path, state) { - if (!shouldContinue(state)) { - return; - } - if ( - path.node.value.name === 'layout' && - path.node.key.name === 'layout' - ) { - path.remove(); - } - }, - ClassProperty(path, state) { - if (!shouldContinue(state)) { - return; - } - if ( - path.node.value && - path.node.value.name === 'layout' && - path.node.key && - path.node.key.name === 'layout' - ) { - path.remove(); - } - }, - Decorator(path, state) { - if (!shouldContinue(state)) { - return; - } - if (path.node.expression && path.node.expression.callee) { - if (path.node.expression.callee.name === 'templateLayout') { - path.remove(); - } - } - }, - }, - }; -} diff --git a/plugins/remove-legacy-layout.ts b/plugins/remove-legacy-layout.ts new file mode 100644 index 0000000..c3303d6 --- /dev/null +++ b/plugins/remove-legacy-layout.ts @@ -0,0 +1,92 @@ +export function removeLegacyLayout(addons: string[]) { + return function removeLegacyLayoutPlugin (babel) { + const shouldContinue = (state) => { + const fName = state.file.opts.filename; + return ( + fName.includes('node_modules') && + addons.some((el) => fName.includes(`/${el}/`)) + ); + }; + const { types: t } = babel; + return { + name: 'remove-layout', + visitor: { + Program: { + exit(path, state) { + if (state.shouldAppendLayout) { + path.node.body.push( + t.variableDeclaration('var', [ + t.variableDeclarator( + t.identifier('layout'), + t.stringLiteral('') + ), + ]) + ); + } + }, + }, + ImportDeclaration(path, state) { + if (!shouldContinue(state)) { + return; + } + if (path.node.source.value.endsWith('/config/environment')) { + path.node.source.value = '@/config/env'; + } + if (path.node.source.value === '@ember-decorators/component') { + // path.node.specifiers = path.node.specifiers.filter((el) => { + // return el.imported.name !== 'layout'; + // }); + // if (!path.node.specifiers.length) { + // path.remove(); + // } + path.node.source.value = 'compat-ember-decorators/component'; + } else if (path.node.source.value.includes('/templates/')) { + path.remove(); + // add `layout` variable to programm + state.shouldAppendLayout = true; + } + }, + ObjectProperty(path, state) { + if (!shouldContinue(state)) { + return; + } + if ( + path.node.value.name === 'layout' && + path.node.key.name === 'layout' + ) { + path.remove(); + } + }, + ClassProperty(path, state) { + if (!shouldContinue(state)) { + return; + } + if ( + path.node.value && + path.node.value.name === 'layout' && + path.node.key && + path.node.key.name === 'layout' + ) { + path.remove(); + } + }, + // Decorator(path, state) { + // if (!shouldContinue(state)) { + // return; + // } + // if (path.node.expression && path.node.expression.callee) { + // if ( + // path.node.expression.callee.name === 'templateLayout' || + // path.node.expression.callee.name === 'layout' + // ) { + // path.remove(); + // } else { + // console.log(path.node.expression.callee.name); + // } + // } + // }, + }, + }; + } + +} \ No newline at end of file diff --git a/readme.md b/readme.md index 818901d..e9c1d2b 100644 --- a/readme.md +++ b/readme.md @@ -90,6 +90,7 @@ yarn dev 1. `ember-page-title` 1. `ember-notify` 1. `ember-ref-bucket` +1. `ember-modal-dialog` [(see code for samples)](https://github.com/lifeart/demo-ember-vite/tree/master/src/addons) diff --git a/src/addons/ember-modal-dialog.ts b/src/addons/ember-modal-dialog.ts new file mode 100644 index 0000000..43d3cce --- /dev/null +++ b/src/addons/ember-modal-dialog.ts @@ -0,0 +1,39 @@ +import { setComponentTemplate } from '@glimmer/manager'; +import ModalDialogComponent from 'ember-modal-dialog/components/modal-dialog.js'; +import ModalDialogTemplate from 'ember-modal-dialog/templates/components/modal-dialog.hbs'; +import ModalDialogService from 'ember-modal-dialog/app/services/modal-dialog.js'; + +import ModalDialogBasicDialogComponent from 'ember-modal-dialog/components/basic-dialog.js'; +import ModalDialogBasicDialogTemplate from 'ember-modal-dialog/templates/components/basic-dialog.hbs'; + +import EmberWormholeComponent from 'ember-wormhole/addon/components/ember-wormhole.js'; +import EmberWormholeTemplate from 'ember-wormhole/addon/templates/components/ember-wormhole.hbs'; + +import IgnoreChildren from 'ember-modal-dialog/helpers/ignore-children.js'; + +import PositionedContainerComponent from 'ember-modal-dialog/components/positioned-container.js'; + +import 'ember-modal-dialog/app/styles/ember-modal-dialog/ember-modal-appearance.css'; +import 'ember-modal-dialog/app/styles/ember-modal-dialog/ember-modal-structure.css'; + +setComponentTemplate( + ModalDialogBasicDialogTemplate, + ModalDialogBasicDialogComponent +); + +const registry = { + 'component:modal-dialog': setComponentTemplate( + ModalDialogTemplate, + ModalDialogComponent + ), + 'component:ember-wormhole': setComponentTemplate( + EmberWormholeTemplate, + EmberWormholeComponent + ), + 'component:ember-modal-dialog-positioned-container': + PositionedContainerComponent, + 'service:modal-dialog': ModalDialogService, + 'helper:ignore-children': IgnoreChildren, +}; + +export default registry; diff --git a/src/addons/index.ts b/src/addons/index.ts index c691539..03bce77 100644 --- a/src/addons/index.ts +++ b/src/addons/index.ts @@ -10,6 +10,7 @@ import EmberIntl from './ember-intl'; import EmberPageTitle from './ember-page-title'; import EmberData from './ember-data'; import EmberNotify from './ember-notify'; +import EmberModalDialog from './ember-modal-dialog'; const registry = { ...EmberSimpleAuthRegistry, @@ -24,6 +25,7 @@ const registry = { ...EmberPageTitle, ...EmberData, ...EmberNotify, + ...EmberModalDialog, }; export default registry; diff --git a/src/config/initializer.ts b/src/config/initializer.ts index ab42ae7..1f34618 100644 --- a/src/config/initializer.ts +++ b/src/config/initializer.ts @@ -3,7 +3,8 @@ import registry from './registry'; import type ApplicationClass from '@ember/application'; import type RouteClass from './router'; import { default as initializer } from '../initializers/logger'; -import { default as instanceInitializer } from '../instance-initializers/logger'; +import { default as logger } from '../instance-initializers/logger'; +import { default as modalDialog } from '../instance-initializers/ember-modal-dialog'; import { default as emberDataInitializer } from '../initializers/ember-data'; export function init( @@ -15,7 +16,8 @@ export function init( Application.initializer(emberDataInitializer); // Init instance initializers - Application.instanceInitializer(instanceInitializer); + Application.instanceInitializer(logger); + Application.instanceInitializer(modalDialog); const app = Application.create({ name: ENV.modulePrefix, diff --git a/src/controllers/application.ts b/src/controllers/application.ts index 44697a4..04ab0bb 100644 --- a/src/controllers/application.ts +++ b/src/controllers/application.ts @@ -1,10 +1,16 @@ import Controller from '@ember/controller'; import { service } from '@ember/service'; import type SessionService from 'ember-simple-auth/addon/services/session'; -import type EmberNotify from 'ember-notify' +import type EmberNotify from 'ember-notify'; +import { tracked } from '@glimmer/tracking'; export class ApplicationController extends Controller { @service session: SessionService; @service notify: EmberNotify; + @tracked showModal = true; + + closeModal = () => { + this.showModal = false; + }; constructor(...args: ConstructorParameters) { super(...args); diff --git a/src/instance-initializers/ember-modal-dialog.ts b/src/instance-initializers/ember-modal-dialog.ts new file mode 100644 index 0000000..64a6f43 --- /dev/null +++ b/src/instance-initializers/ember-modal-dialog.ts @@ -0,0 +1,10 @@ +import initialize from 'ember-modal-dialog/instance-initializers/add-modals-container.js'; +import type ApplicationInstance from '@ember/application/instance'; + +export default { + name: 'add-modals-container', + initialize: function (application: ApplicationInstance) { + console.log('instance initializer init'); + initialize(application); + }, +}; diff --git a/src/templates/application.hbs b/src/templates/application.hbs index 60e831a..9d95231 100644 --- a/src/templates/application.hbs +++ b/src/templates/application.hbs @@ -1,5 +1,10 @@
+{{#if this.showModal}} + + Ember Modal Dialog test + +{{/if}}
diff --git a/vite.config.ts b/vite.config.ts index 6a48fd8..1336106 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -10,6 +10,7 @@ import { generateDefineConfig } from './compat/ember-data-private-build-infra/in import refBucketTransform from 'ember-ref-bucket/lib/ref-transform.js'; import { babelHotReloadPlugin } from './plugins/hot-reload'; import { removeLegacyLayout } from './plugins/remove-legacy-layout'; +import { dropImportSync } from './plugins/drop-import-sync'; export default defineConfig(({ mode }) => { const isProd = mode === 'production'; const isDev = mode === 'development'; @@ -33,32 +34,32 @@ export default defineConfig(({ mode }) => { } : { output: { - manualChunks(id) { - if ( - id.includes('/compat/') || - id.includes('@ember/') || - id.includes('/rsvp/') || - id.includes('/router_js/') || - id.includes('dag-map') || - id.includes('route-recognizer') || - id.includes('tracked-built-ins') || - id.includes('tracked-toolbox') || - id.includes('@ember-data/') || - id.includes('embroider-macros') || - id.includes('/backburner.js/') || - id.includes('@glimmer') || - id.includes('ember-inflector') || - id.includes('ember-source') - ) { - // chunk for ember runtime - return 'core'; - } - if (id.endsWith('/src/addons/index.ts')) { - // initial addons and application chunk - return 'app'; - } - return undefined; - }, + // manualChunks(id) { + // if ( + // id.includes('/compat/') || + // id.includes('@ember/') || + // id.includes('/rsvp/') || + // id.includes('/router_js/') || + // id.includes('dag-map') || + // id.includes('route-recognizer') || + // id.includes('tracked-built-ins') || + // id.includes('tracked-toolbox') || + // id.includes('@ember-data/') || + // id.includes('embroider-macros') || + // id.includes('/backburner.js/') || + // id.includes('@glimmer') || + // id.includes('ember-inflector') || + // id.includes('ember-source') + // ) { + // // chunk for ember runtime + // return 'core'; + // } + // if (id.endsWith('/src/addons/index.ts')) { + // // initial addons and application chunk + // return 'app'; + // } + // return undefined; + // }, }, }, }, @@ -87,6 +88,7 @@ export default defineConfig(({ mode }) => { addonExport('ember-inflector'), addonExport('@ember/string'), addonExport('ember-notify'), + addonExport('ember-modal-dialog'), { find: 'ember-simple-auth/use-session-setup-method', replacement: './compat/ember-simple-auth/use-session-setup-method.ts', @@ -124,6 +126,10 @@ export default defineConfig(({ mode }) => { find: 'ember-cli-version-checker', replacement: compatPath('ember-cli-version-checker/index.ts'), }, + { + find: 'compat-ember-decorators/component', + replacement: compatPath('ember-decorators/component.ts'), + }, { find: 'require', replacement: compatPath('require/index.ts'), @@ -293,8 +299,18 @@ export default defineConfig(({ mode }) => { babel({ // regexp to match files in src folder filter: - /^.*(@ember-data|ember-notify|ember-bootstrap|ember-ref-bucket|tracked-toolbox|ember-power-select|ember-basic-dropdown|page-title)\/.*\.(ts|js|hbs)$/, - babelConfig: addonBabelConfig([], isProd), + /^.*(@ember-data|ember-notify|ember-wormhole|ember-modal-dialog|ember-bootstrap|ember-ref-bucket|tracked-toolbox|ember-power-select|ember-basic-dropdown|page-title)\/.*\.(ts|js|hbs)$/, + babelConfig: addonBabelConfig( + [ + dropImportSync(['ember-modal-dialog']), + removeLegacyLayout([ + 'ember-wormhole', + 'ember-modal-dialog', + 'ember-notify', + ]), + ], + isProd + ), }), // ... ].filter((el) => el !== null), @@ -340,6 +356,10 @@ function localScopes() { function addonExport(name: string) { return [ + { + find: `${name}/app`, + replacement: nodePath(`${name}/app`), + }, { find: `${name}/vendor`, replacement: nodePath(`${name}/vendor`), @@ -415,7 +435,6 @@ function defaultBabelPlugins(isProd: boolean) { loose: true, }, ], - removeLegacyLayout, templateCompilationPlugin(isProd), ]; } diff --git a/yarn.lock b/yarn.lock index 84a6220..f8f59e8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5301,7 +5301,7 @@ ember-cli-babel-plugin-helpers@^1.0.0, ember-cli-babel-plugin-helpers@^1.1.0, em resolved "https://registry.yarnpkg.com/ember-cli-babel-plugin-helpers/-/ember-cli-babel-plugin-helpers-1.1.1.tgz#5016b80cdef37036c4282eef2d863e1d73576879" integrity sha512-sKvOiPNHr5F/60NLd7SFzMpYPte/nnGkq/tMIfXejfKHIhaiIkYFqX8Z9UFTKWLLn+V7NOaby6niNPZUdvKCRw== -ember-cli-babel@^7.0.0, ember-cli-babel@^7.1.3, ember-cli-babel@^7.10.0, ember-cli-babel@^7.13.2, ember-cli-babel@^7.19.0, ember-cli-babel@^7.20.5, ember-cli-babel@^7.21.0, ember-cli-babel@^7.22.1, ember-cli-babel@^7.23.0, ember-cli-babel@^7.23.1, ember-cli-babel@^7.26.0, ember-cli-babel@^7.26.11, ember-cli-babel@^7.26.5, ember-cli-babel@^7.26.6, ember-cli-babel@^7.7.3: +ember-cli-babel@^7.0.0, ember-cli-babel@^7.1.3, ember-cli-babel@^7.10.0, ember-cli-babel@^7.13.2, ember-cli-babel@^7.19.0, ember-cli-babel@^7.20.5, ember-cli-babel@^7.21.0, ember-cli-babel@^7.22.1, ember-cli-babel@^7.23.0, ember-cli-babel@^7.23.1, ember-cli-babel@^7.26.0, ember-cli-babel@^7.26.11, ember-cli-babel@^7.26.5, ember-cli-babel@^7.26.6, ember-cli-babel@^7.26.8, ember-cli-babel@^7.7.3: version "7.26.11" resolved "https://registry.yarnpkg.com/ember-cli-babel/-/ember-cli-babel-7.26.11.tgz#50da0fe4dcd99aada499843940fec75076249a9f" integrity sha512-JJYeYjiz/JTn34q7F5DSOjkkZqy8qwFOOxXfE6pe9yEJqWGu4qErKxlz8I22JoVEQ/aBUO+OcKTpmctvykM9YA== @@ -5524,7 +5524,7 @@ ember-cli-typescript@^5.0.0: stagehand "^1.0.0" walk-sync "^2.2.0" -ember-cli-version-checker@^2.1.2: +ember-cli-version-checker@^2.1.0, ember-cli-version-checker@^2.1.2: version "2.2.0" resolved "https://registry.yarnpkg.com/ember-cli-version-checker/-/ember-cli-version-checker-2.2.0.tgz#47771b731fe0962705e27c8199a9e3825709f3b3" integrity sha512-G+KtYIVlSOWGcNaTFHk76xR4GdzDLzAS4uxZUKdASuFX0KJE43C6DaqL+y3VTpUFLI2FIkAS6HZ4I1YBi+S3hg== @@ -5625,7 +5625,7 @@ ember-data@5.1.1: ember-inflector "^4.0.2" webpack "^5.82.1" -ember-decorators@^6.1.0: +ember-decorators@^6.1.0, ember-decorators@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/ember-decorators/-/ember-decorators-6.1.1.tgz#6d770f8999cf5a413a1ee459afd520838c0fc470" integrity sha512-63vZPntPn1aqMyeNRLoYjJD+8A8obd+c2iZkJflswpDRNVIsp2m7aQdSCtPt4G0U/TEq2251g+N10maHX3rnJQ== @@ -5725,6 +5725,19 @@ ember-maybe-in-element@^2.0.3: ember-cli-version-checker "^5.1.1" ember-in-element-polyfill "^1.0.1" +ember-modal-dialog@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/ember-modal-dialog/-/ember-modal-dialog-4.1.2.tgz#436c6d780afe1bc20ee743c522e242358b8df8a2" + integrity sha512-Wl5jPE74ciSmwbmmhqRNAri7YHbiY1gVjteHPmsgKpUqlW2Yoghp7qoCvVN6v3Nnx1sqv+FXWFPwEcJknWkvaA== + dependencies: + "@embroider/macros" "^1.0.0" + "@embroider/util" "^1.0.0" + ember-cli-babel "^7.26.8" + ember-cli-htmlbars "^6.0.1" + ember-cli-version-checker "^2.1.0" + ember-decorators "^6.1.1" + ember-wormhole "^0.6.0" + ember-modifier-manager-polyfill@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/ember-modifier-manager-polyfill/-/ember-modifier-manager-polyfill-1.2.0.tgz#cf4444e11a42ac84f5c8badd85e635df57565dda" @@ -6025,6 +6038,14 @@ ember-text-measurer@^0.6.0: dependencies: ember-cli-babel "^7.22.1" +ember-wormhole@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/ember-wormhole/-/ember-wormhole-0.6.0.tgz#1f9143aa05c0f0abdf14a97ff22520ebaf85eca0" + integrity sha512-b7RrRxkwCBEJxM2zR34dEzIET81BOZWTcYNJtkidLycLQvdbxPys5QJEjJ/IfDikT/z5HuQBdZRKBhXI0vZNXQ== + dependencies: + ember-cli-babel "^7.22.1" + ember-cli-htmlbars "^5.3.1" + emittery@^0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad"