@ibyar/aurora
v3.1.1
Published
Create and define a usable 'custom elements', that compatible with other frameworks, using Typescript
Downloads
128
Maintainers
Readme
Aurora
Ibyar Aurora, is a web framework, that can create and define a Web Component standards ('custom elements', 'Shadow DOM' and 'HTML Templates'), that compatible with other frameworks, using Typescript.
This framework build with-in a embedded JavaScript Engine @ibyar/expressions to execute Template syntax and attributes binding.
- Demo: https://muhammad-salem.github.io/aurora-demo
- API Doc: https://muhammad-salem.github.io/aurora-docs
- Ibyar Expression & Elements parser: https://muhammad-salem.github.io/astexplorer
- select: JavaScript: @ibyar/expressions
- select: HTML: @ibyar/elements
- Custom Elements Everywhere for Aurora Test & Results: https://muhammad-salem.github.io/custom-elements-everywhere/libraries/aurora/results/results.html
CLI Install
npm i -g @ibyar/cli
yarn global add @ibyar/cli
Install
npm i --save @ibyar/aurora
yarn add @ibyar/aurora
Dependencies
| README | Description | NPM, PKG, SRC |
| ------ | ----------- | ------------- |
| @ibyar/cli | ibyar cli package |
|
| @ibyar/aurora | a central package to manage dependance only |
|
| @ibyar/core | create components, render elements bind attributes and handling events |
|
| @ibyar/expressions | a JavaScript engine, parser and evaluator build by the guid of V8 JavaScript engine.Introduce a reactive scope concept to detect changes for scope variables,subscriptions based on a
wave effect
like concept, (simple what is subscribed will only be reevaluated again). Follow ESTree structural to generate an ast object. |
|
| @ibyar/elements | parse
HTML Template
, has tag
names, properties for each tag
|
|
| @ibyar/pipes | implement all supported pipes |
|
| @ibyar/directives | implement all supported directives |
|
| @ibyar/platform | utility package for and plural stuff, json patch |
|
| @ibyar/decorators | ibyar decorators package |
|
| typescript | Runtime library for TypeScript helpers. |
|
| tslib | Runtime library for TypeScript helpers. |
|
'HTML Template' Features
| Support | HTML Template| | -------------------- | - | | Parsing Attributes | ✓ | | One Way Data Binding | ✓ | | Two Way Data Binding | ✓ | | Event Binding | ✓ | | Template Parser | ✓ | | Template Syntax | ✓ | | Control Flow Syntax | ✓ | | Variables in templates | ✓ | | Template Reference Variables | ✓ | | Template HTML File | fetch or embedded | | Fragment | ✓ | | camelCase Property Naming | ✓ | | lowercase for root element Property Naming | ✓ |
Library Features
- [x] ES Module
- [x] Dependency Injection
- [x] Component
- [x] Directives (Attribute and Structural Directives)
- [x] Pipes
- [x] Modules
- [x] Lifecycle
- [x] Signals
- [x] input signal
- [x] output signal
- [x] view signal
- [x] viewChild signal
- [x] @HostListener [Supported by Component and Attribute directive].
- [x] @HostBinding [Supported by Component and Attribute directive].
- [ ] XSS (cross-site-scripting)
Built-in Directive
Structure Directives
- [x] *if
- [x] *for is same as ( *forOf )
- [x] *forIn
- [x] *forAwait
- [x] *switch and (*case, *default)
-- support control flow syntax
-- see directive syntax
structural-directive-syntax-reference
Attributes Directives
- [x] class [support
Single class binding
,Multi-class binding
]. - [x] style [support
Single style binding
,Multi-style binding
]. theSingle style binding with units
not yet supported.
Built-in Pipes ( Pipeline operator '|>' )
- [x] async
- [x] json
- [x] lowercase
- [x] uppercase
- [x] titlecase
- [x] keyvalue
- [x] slice
- [ ] date
- [ ] currency
- [ ] number
- [ ] percent
- [ ] i18nPlural
- [ ] i18nSelect
Web Component standards
- [x] Custom Elements
- [x] Shadow DOM
- [x] HTML Templates Element
- [x] HTML Templates Element with Shadow DOM
Custom Elements standards
- [x] Reflecting Properties to Attributes
- [x] Observing Changes to Attributes
- [x] Element Upgrades
- [x] Styling a Custom Element
- [x] Extending native HTML elements
- [ ] Extending a Custom Element
- [x] Two Component On Same Model Class
- [ ] Two Component Share Same Model Instance
Shadow DOM standards
- [x] Open Mode
- [x] Closed Mode
- [x] delegatesFocus
- [x] Shadow DOM event model
HTML Templates Element standards
- [x] Load template by ID from document
- [x] As Normal Custom Element
- [x] As Shadow DOM Element
how to bundle your package before publish
# always run ibyar cli to pre-build (AOT) your template and view types.
ibyar --build
#or
ibyar --build --watch
How to use:
HTML -- template parser example
in a polyfills.ts file
- use
aurora
zone for detect changes
import 'zone.js';
import { bootstrapZone } from '@ibyar/aurora';
bootstrapZone('aurora');
- or use
manual
Zone, if you don't like to useZone.js
all the events likerxjs
observables, setTimeout and fetch, etc.. can't be detected, use signals to connect to variables changes, provide better debugging experience.
import { bootstrapZone } from '@ibyar/aurora';
bootstrapZone('manual');
- or use
proxy
Zone, if you don't like to useZone.js
but still like to have full change detection for your application. it my be hard in debugging your application.
import { bootstrapZone } from '@ibyar/aurora';
bootstrapZone('proxy');
you still can control the zone peer component while define your component by add
zone
t one of the zone types 'aurora', 'manual' and 'proxy'. ifaurora
is selected, you need to import theZone.js
package.the
zone
property in the@Component({zone: 'manual'})
is optional and will get the default value frombootstrapZone()
import { Component, HostListener, isModel, OnDestroy, OnInit } from '@ibyar/aurora';
import { interval, Subscription } from 'rxjs';
@Component({
selector: 'pipe-app',
zone: 'AURORA',
template: `
<style>.bs-color{color: var({{currentColor}});}</style>
@for(let color of colors; let i = index, isOdd = odd) {
isOdd :{{ isOdd? 'odd': 'even'}}
color: {{color}}
}
<!-- Local template variables -->
@let name = user.name;
@let name = user.name, age = user.age; <!-- comma separated variable declaration -->
@let greeting = 'Hello, ' + name;
@let data = data$ | async;
@let pi = 3.1459;
@let coordinates = {x: 50, y: 100};
@let longExpression = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit ' +
'sed do eiusmod tempor incididunt ut labore et dolore magna ' +
'Ut enim ad minim veniam...';
<div *for="const color of colors">
color: {{color}} <span *if="color === currentColor" class="bs-color"> Current Color ='{{currentColor}}'</span>
</div>
<table class="table">
<thead>
<tr>
<th class="bs-color" scope="col">pipe</th>
<th class="bs-color" scope="col">expression</th>
<th class="bs-color" scope="col">view</th>
</tr>
</thead>
<tbody>
<tr>
<td>async</td>
<td>observable |> async</td>
<td>{{observable |> async}}</td>
</tr>
<tr>
<td>*</td>
<td>text</td>
<td>{{text}}</td>
</tr>
<tr>
<td>lowercase</td>
<td>text |> lowercase</td>
<td>{{text |> lowercase}}</td>
</tr>
<tr>
<td>titlecase</td>
<td>text |> titlecase</td>
<td>{{text |> titlecase}}</td>
</tr>
<tr>
<td>uppercase</td>
<td>text |> uppercase</td>
<td>{{text |> uppercase}}</td>
</tr>
<tr>
<td>json</td>
<td>obj |> json</td>
<td>{{obj |> json}}</td>
</tr>
<tr>
<td>json <small>pre element</small></td>
<td>obj |> json:undefined:2</td>
<td>
<pre>{{obj |> json:undefined:2}}</pre>
</td>
</tr>
<tr>
<td>keyvalue</td>
<td>keyValueObject |> keyvalue</td>
<td>{{keyValueObject |> keyvalue |> json}}</td>
</tr>
<tr>
<td>keyvalue</td>
<td>keyValueObject |> keyvalue</td>
<td>{{keyValueObject |> keyvalue |> json}}</td>
</tr>
<tr>
<td>keyvalue</td>
<td>keyValueMap |> keyvalue</td>
<td>{{keyValueMap |> keyvalue |> json}}</td>
</tr>
<tr>
<td>slice</td>
<td>array |> slice:1:3</td>
<td>{{array |> slice:1:3}}</td>
</tr>
<tr>
<td>slice</td>
<td>slice(array, 1, 3)</td>
<td>{{slice(array, 1, 3)}}</td>
</tr>
<tr>
<td>call windows method directly</td>
<td>3345.54645 |> Math.trunc</td>
<td>{{3345.54645 |> Math.trunc}}</td>
</tr>
</tbody>
</table>
`
})
export class PipeAppComponent implements OnInit, OnDestroy {
text = 'Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts and visual mockups';
obj = {
a: [1, 2, 3],
b: 'property b',
c: {
d: [],
e: 4,
f: [{ 5: 'g' }]
}
};
keyValueObject = {
1: 100,
a: 'A00'
};
keyValueArray = [200, 300];
keyValueMap = new Map<number, number | string>([[1, 400], [2, 500], [3, 'B200']]);
observable = interval(1000);
array = ['a', 'b', 'c', 'd'];
readonly name = input('name');
readonly age = input.required();
readonly inputWithAlias = input('init-value', { alias: 'alias-name-1' });
readonly requiredInputWithAlias = input.required({ alias: 'alias-name-2' });
readonly event = output<string>();
colors = [
'--bs-blue',
'--bs-indigo',
'--bs-purple',
'--bs-pink',
'--bs-red',
'--bs-orange',
'--bs-yellow',
'--bs-green',
'--bs-teal',
'--bs-cyan',
'--bs-white',
'--bs-gray',
'--bs-gray-dark'
];
currentColor = this.colors[0];
subscription: Subscription;
onInit() {
let index = 0;
this.subscription = this.observable.subscribe(() => {
if (index === this.colors.length) {
index = 0;
}
this.currentColor = this.colors[index++];
if (isModel(this)) {
this.emitChangeModel('currentColor');
}
console.log(this.currentColor);
});
}
@HostListener('currentColor')
onCurrentColorChange() {
console.log(this.currentColor);
}
onDestroy() {
this.subscription.unsubscribe();
}
}
in index.html add:
<body>
<pipe-app></pipe-app>
<script type="module" src="path-to-main-file/index.js"></script>
</body>
how to build
git clone https://github.com/ibyar/aurora.git
cd aurora
yarn install
yarn build
For NPM 7(workshop support):
git clone https://github.com/ibyar/aurora.git
cd aurora
npm install
npm run build
see test app for full example
Integration with Webpack
add @ibyar/cli as loader
module.exports = {
entry: './src/index.ts',
module: {
exprContextCritical: false,
rules: [
{
test: /\.tsx?$/,
use: ['@ibyar/cli',],
exclude: /node_modules/,
}
]
}
};
use ts-loader
// 1. import default from the plugin module
import {
beforeCompileDirectiveOptions, beforeCompileComponentOptions,
afterDeclarationsCompileComponentOptions,
afterDeclarationsCompileDirectiveOptions,
scanDirectivesOnceAsTransformer,
} from '@ibyar/cli';
// 3. add getCustomTransformer method to the loader config
var config = {
...
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
options: {
... // other loader's options
getCustomTransformers: () => ({
before: [
scanDirectivesOnceAsTransformer(),
beforeCompileDirectiveOptions,
beforeCompileComponentOptions,
],
after: [],
afterDeclarations: [
afterDeclarationsCompileComponentOptions,
afterDeclarationsCompileDirectiveOptions,
],
})
}
}
]
}
...
};
Integration with Rollup
import typescript from '@rollup/plugin-typescript';
import {
beforeCompileDirectiveOptions, beforeCompileComponentOptions,
afterDeclarationsCompileComponentOptions,
afterDeclarationsCompileDirectiveOptions,
scanDirectivesOnceAsTransformer,
} from '@ibyar/cli';
export default = {
...,
plugins: [
typescript({
transformers: {
before: [
{ type: 'program', factory: scanDirectivesOnceAsTransformer() },
{ type: 'program', factory: beforeCompileDirectiveOptions },
{ type: 'program', factory: beforeCompileComponentOptions },
],
after: [],
afterDeclarations: [
{ type: 'program', factory: afterDeclarationsCompileComponentOptions },
{ type: 'program', factory: afterDeclarationsCompileDirectiveOptions },
],
}
}),
],
...
};
see test app for full webpack
see test app for full rollup