Buslowicz / twc

TypeScript based, boilerplate-less, Polymer toolbox friendly Polymer Modules
32 stars 1 forks source link

Working with behaviors #48

Closed tpluscode closed 7 years ago

tpluscode commented 7 years ago

I've been thinking about behaviors and decided to split them from #11 as a special case. Not sure how difficult it would be to implement, but maybe it could be possible to handle them in a special way, similarly to what you're doing with link!... and script!... imports.

Here's my idea:

  1. You have a behavior (or multiple) exported from a source file my-behavior.ts
export const MyBehavior = {
   name: string;
   connectedCallback: () => {};
};
  1. Processing my-behavior.ts produces a html file with exported behaviors added to global scope
<script>
window.MyBehavior = {
   properties: { name: string },
   connectedCallback: function() { }
}
</script>

Do you think it is safe to assume that any exported object could be treated as a behavior?

  1. You import that behavior and apply to an element in my-element.ts
import { MyBehavior } from `my-behavior.ts`

@behavior(MyBehavior)
export class MyElement { }
  1. Whenever my-element.ts is processed by twc and it encounters the import, it would replace it with an import link and correct the reference in behaviors array (tsc emits some generated namespace).
<link rel="import" href="my-behavior.html" />

<dom-module id="my-element">
   <script>
      Polymer({
         behaviors: [ window.MyBehavior ]
      });
   </script>
</dom-module>
tpluscode commented 7 years ago
  1. (bonus) As a second step it could be interesting to support namespaces

my-behavior.ts:

export namespace Example {
   export const MyBehavior = {};
}

my-behavior.html:

<script>
   window.Example = window.Example || {};
   window.Example.MyBehavior = { };
</script>

my-element.ts:

import { Example } from `my-behavior.ts`

@behavior(Example.MyBehavior)
export class MyElement { }

my-element.html:

<link rel="import" href="my-behavior.html" />

<dom-module id="my-element">
   <script>
      Polymer({
         behaviors: [ window.Example.MyBehavior ]
      });
   </script>
</dom-module>
Buslowicz commented 7 years ago

At first glace it seems rather easy. When transpiling imports to JS (currently it works on commonjs output), the above would create a variable like myBehavior_1. Simply finding the myBehavior_1.Example or myBehavior_1.MyBehavior and replacing the myBehavior_1 with window would probably work (at least in most cases). What do you think?

tpluscode commented 7 years ago

I would think so. I haven't looked at the code so you'll know better. But yes, for common scenarios it looks rather simple. Let's worry about edge cases (namespaces even) later