├── dist ├── esm │ ├── core │ │ ├── types.js │ │ ├── directive.js │ │ ├── structure.js │ │ ├── directive.d.ts │ │ ├── structure.d.ts │ │ ├── pipe.js │ │ ├── component.d.ts │ │ ├── pipe.d.ts │ │ ├── component.js │ │ ├── context.d.ts │ │ ├── factory.d.ts │ │ └── context.js │ ├── platform │ │ ├── common │ │ │ ├── window │ │ │ │ ├── window.d.ts │ │ │ │ └── window.js │ │ │ ├── location │ │ │ │ ├── location.d.ts │ │ │ │ └── location.js │ │ │ ├── transfer │ │ │ │ ├── transfer.service.d.ts │ │ │ │ └── transfer.service.js │ │ │ └── serializer │ │ │ │ └── serializer.d.ts │ │ ├── browser.d.ts │ │ ├── platform.d.ts │ │ └── browser.js │ ├── json │ │ ├── json.pipe.d.ts │ │ ├── json.component.d.ts │ │ ├── json.pipe.js │ │ └── json.component.js │ ├── event │ │ ├── event.directive.d.ts │ │ └── event.directive.js │ ├── src │ │ ├── src.directive.d.ts │ │ └── src.directive.js │ ├── href │ │ ├── href.directive.d.ts │ │ ├── href-target.directive.d.ts │ │ ├── href.directive.js │ │ └── href-target.directive.js │ ├── inner-html │ │ ├── inner-html.directive.d.ts │ │ └── inner-html.directive.js │ ├── core.module.d.ts │ ├── class │ │ ├── class.directive.d.ts │ │ └── class.directive.js │ ├── if │ │ ├── if.structure.d.ts │ │ └── if.structure.js │ ├── style │ │ ├── style.directive.d.ts │ │ └── style.directive.js │ ├── for │ │ ├── for.item.d.ts │ │ ├── for.structure.d.ts │ │ └── for.item.js │ ├── error │ │ ├── error.d.ts │ │ └── error.js │ ├── core.module.js │ ├── rxcomp.js │ └── rxcomp.d.ts ├── cjs │ ├── platform │ │ ├── common │ │ │ ├── window │ │ │ │ ├── window.d.ts │ │ │ │ └── window.js │ │ │ ├── location │ │ │ │ ├── location.d.ts │ │ │ │ └── location.js │ │ │ ├── transfer │ │ │ │ └── transfer.service.d.ts │ │ │ └── serializer │ │ │ │ └── serializer.d.ts │ │ ├── browser.d.ts │ │ ├── platform.d.ts │ │ └── browser.js │ ├── core │ │ ├── types.js │ │ ├── directive.d.ts │ │ ├── structure.d.ts │ │ ├── component.d.ts │ │ ├── pipe.d.ts │ │ ├── pipe.js │ │ ├── directive.js │ │ ├── structure.js │ │ ├── context.d.ts │ │ ├── component.js │ │ └── factory.d.ts │ ├── json │ │ ├── json.pipe.d.ts │ │ ├── json.component.d.ts │ │ ├── json.pipe.js │ │ └── json.component.js │ ├── event │ │ ├── event.directive.d.ts │ │ └── event.directive.js │ ├── src │ │ ├── src.directive.d.ts │ │ └── src.directive.js │ ├── href │ │ ├── href.directive.d.ts │ │ ├── href-target.directive.d.ts │ │ ├── href.directive.js │ │ └── href-target.directive.js │ ├── inner-html │ │ ├── inner-html.directive.d.ts │ │ └── inner-html.directive.js │ ├── core.module.d.ts │ ├── class │ │ ├── class.directive.d.ts │ │ └── class.directive.js │ ├── if │ │ ├── if.structure.d.ts │ │ └── if.structure.js │ ├── style │ │ ├── style.directive.d.ts │ │ └── style.directive.js │ ├── for │ │ ├── for.item.d.ts │ │ ├── for.structure.d.ts │ │ └── for.item.js │ ├── error │ │ └── error.d.ts │ ├── core.module.js │ └── rxcomp.d.ts ├── rxcomp-dark.min.css ├── rxcomp-light.min.css ├── rxcomp-dark.css ├── rxcomp-light.css ├── rxcomp-dark.min.css.map └── rxcomp-light.min.css.map ├── .jshintrc ├── .npmignore ├── .eslintignore ├── web └── client │ ├── css │ ├── _fonts.scss │ ├── _components │ │ ├── _reset.scss │ │ ├── _responsive.scss │ │ ├── _base.scss │ │ ├── _forms.scss │ │ ├── _grid.css │ │ ├── _typography.scss │ │ ├── _locomotive.scss │ │ └── _buttons.scss │ ├── main.scss │ ├── main-cssvars.scss │ ├── _mixins.scss │ ├── _shared.scss │ ├── _variables │ │ ├── _grid.scss │ │ ├── _shared.scss │ │ ├── _main.scss │ │ ├── _main-cssvars.scss │ │ └── _cssvars.scss │ ├── _mixins │ │ ├── _scrollbar.scss │ │ └── _aspect.scss │ └── _fonts │ │ └── todomvc │ │ └── todomvc.scss │ ├── js │ ├── main.ts │ ├── todo-item │ │ ├── todo-item.ts │ │ └── todo-item.component.ts │ ├── app.module.ts │ ├── date │ │ └── date.pipe.ts │ ├── test.pipes.ts │ ├── test.for.ts │ ├── app.component.ts │ ├── colors │ │ └── colors.ts │ ├── local-storage │ │ └── local-storage.service.ts │ ├── test.parsing.ts │ └── store │ │ └── store.service.ts │ ├── templates │ ├── shared │ │ ├── header.html │ │ └── analytics.html │ └── layout.html │ ├── test.pipes.html │ ├── test.for.html │ ├── test.scope.html │ ├── index.html │ └── test.parsing.html ├── docs ├── img │ ├── favicon.ico │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── mstile-150x150.png │ ├── apple-touch-icon.png │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── browserconfig.xml │ └── site.webmanifest ├── fonts │ └── todomvc │ │ ├── todomvc.eot │ │ ├── todomvc.ttf │ │ ├── todomvc.woff │ │ └── todomvc.css ├── typedoc │ └── assets │ │ └── images │ │ ├── icons.png │ │ ├── widgets.png │ │ ├── icons@2x.png │ │ └── widgets@2x.png └── css │ ├── rxcomp-dark.min.css │ ├── rxcomp-light.min.css │ ├── rxcomp-dark.css │ ├── rxcomp-light.css │ ├── rxcomp-dark.min.css.map │ └── rxcomp-light.min.css.map ├── FUNDING.yml ├── src ├── core │ ├── directive.ts │ ├── structure.ts │ ├── pipe.ts │ ├── component.ts │ ├── context.ts │ └── types.ts ├── _scss │ ├── _mixins.scss │ ├── rxcomp-dark.scss │ ├── rxcomp-light.scss │ ├── _variables │ │ ├── _grid.scss │ │ ├── _shared.scss │ │ ├── _main.scss │ │ ├── _main-cssvars.scss │ │ └── _cssvars.scss │ ├── _mixins │ │ └── _aspect.scss │ └── _rxcomp │ │ └── _rxcomp.scss ├── platform │ ├── common │ │ ├── window │ │ │ └── window.ts │ │ ├── location │ │ │ └── location.ts │ │ └── transfer │ │ │ └── transfer.service.ts │ └── browser.ts ├── json │ ├── json.pipe.ts │ └── json.component.ts ├── src │ └── src.directive.ts ├── href │ ├── href.directive.ts │ └── href-target.directive.ts ├── inner-html │ └── inner-html.directive.ts ├── class │ └── class.directive.ts ├── for │ └── for.item.ts ├── style │ └── style.directive.ts ├── event │ └── event.directive.ts ├── core.module.ts ├── if │ └── if.structure.ts ├── error │ └── error.ts └── rxcomp.ts ├── .browserslistrc ├── .gitattributes ├── .babelrc ├── .eslintrc.json ├── tsconfig.json ├── gulpfile.js ├── .editorconfig ├── LICENSE ├── package.json ├── .gitignore ├── .jsbeautifyrc ├── typedoc.json └── CHANGELOG.md /dist/esm/core/types.js: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "validthis": true 3 | } 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | docs 2 | gulpfile 3 | src 4 | web 5 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/**/*.* 2 | docs/**/*.* 3 | build/**/*.* 4 | -------------------------------------------------------------------------------- /web/client/css/_fonts.scss: -------------------------------------------------------------------------------- 1 | @import '_fonts/todomvc/todomvc'; 2 | -------------------------------------------------------------------------------- /web/client/css/_components/_reset.scss: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | -------------------------------------------------------------------------------- /dist/cjs/platform/common/window/window.d.ts: -------------------------------------------------------------------------------- 1 | export declare const WINDOW: Window; 2 | -------------------------------------------------------------------------------- /dist/esm/platform/common/window/window.d.ts: -------------------------------------------------------------------------------- 1 | export declare const WINDOW: Window; 2 | -------------------------------------------------------------------------------- /docs/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/actarian/rxcomp/HEAD/docs/img/favicon.ico -------------------------------------------------------------------------------- /docs/img/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/actarian/rxcomp/HEAD/docs/img/favicon-16x16.png -------------------------------------------------------------------------------- /docs/img/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/actarian/rxcomp/HEAD/docs/img/favicon-32x32.png -------------------------------------------------------------------------------- /FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [rxcomp] 2 | patreon: lzampetti 3 | custom: ["https://www.paypal.me/circledev/5"] 4 | -------------------------------------------------------------------------------- /dist/cjs/core/types.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /docs/img/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/actarian/rxcomp/HEAD/docs/img/mstile-150x150.png -------------------------------------------------------------------------------- /docs/fonts/todomvc/todomvc.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/actarian/rxcomp/HEAD/docs/fonts/todomvc/todomvc.eot -------------------------------------------------------------------------------- /docs/fonts/todomvc/todomvc.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/actarian/rxcomp/HEAD/docs/fonts/todomvc/todomvc.ttf -------------------------------------------------------------------------------- /docs/fonts/todomvc/todomvc.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/actarian/rxcomp/HEAD/docs/fonts/todomvc/todomvc.woff -------------------------------------------------------------------------------- /docs/img/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/actarian/rxcomp/HEAD/docs/img/apple-touch-icon.png -------------------------------------------------------------------------------- /src/core/directive.ts: -------------------------------------------------------------------------------- 1 | import Factory from './factory'; 2 | 3 | export default class Directive extends Factory { } 4 | -------------------------------------------------------------------------------- /src/core/structure.ts: -------------------------------------------------------------------------------- 1 | import Factory from './factory'; 2 | 3 | export default class Structure extends Factory { } 4 | -------------------------------------------------------------------------------- /dist/esm/core/directive.js: -------------------------------------------------------------------------------- 1 | import Factory from './factory'; 2 | export default class Directive extends Factory { 3 | } 4 | -------------------------------------------------------------------------------- /dist/esm/core/structure.js: -------------------------------------------------------------------------------- 1 | import Factory from './factory'; 2 | export default class Structure extends Factory { 3 | } 4 | -------------------------------------------------------------------------------- /docs/img/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/actarian/rxcomp/HEAD/docs/img/android-chrome-192x192.png -------------------------------------------------------------------------------- /docs/img/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/actarian/rxcomp/HEAD/docs/img/android-chrome-512x512.png -------------------------------------------------------------------------------- /docs/typedoc/assets/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/actarian/rxcomp/HEAD/docs/typedoc/assets/images/icons.png -------------------------------------------------------------------------------- /dist/cjs/core/directive.d.ts: -------------------------------------------------------------------------------- 1 | import Factory from './factory'; 2 | export default class Directive extends Factory { 3 | } 4 | -------------------------------------------------------------------------------- /dist/cjs/core/structure.d.ts: -------------------------------------------------------------------------------- 1 | import Factory from './factory'; 2 | export default class Structure extends Factory { 3 | } 4 | -------------------------------------------------------------------------------- /dist/esm/core/directive.d.ts: -------------------------------------------------------------------------------- 1 | import Factory from './factory'; 2 | export default class Directive extends Factory { 3 | } 4 | -------------------------------------------------------------------------------- /dist/esm/core/structure.d.ts: -------------------------------------------------------------------------------- 1 | import Factory from './factory'; 2 | export default class Structure extends Factory { 3 | } 4 | -------------------------------------------------------------------------------- /docs/typedoc/assets/images/widgets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/actarian/rxcomp/HEAD/docs/typedoc/assets/images/widgets.png -------------------------------------------------------------------------------- /dist/esm/core/pipe.js: -------------------------------------------------------------------------------- 1 | export default class Pipe { 2 | static transform(value) { 3 | return value; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /docs/typedoc/assets/images/icons@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/actarian/rxcomp/HEAD/docs/typedoc/assets/images/icons@2x.png -------------------------------------------------------------------------------- /docs/typedoc/assets/images/widgets@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/actarian/rxcomp/HEAD/docs/typedoc/assets/images/widgets@2x.png -------------------------------------------------------------------------------- /web/client/css/main.scss: -------------------------------------------------------------------------------- 1 | @import '_variables/main'; 2 | @import '_variables/shared'; 3 | @import '_variables/grid'; 4 | @import 'shared'; 5 | -------------------------------------------------------------------------------- /src/_scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | @import "_mixins/aspect"; 2 | @import "_mixins/breakpoints"; 3 | @import "_mixins/functions"; 4 | @import "_mixins/grid"; 5 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | # supported browsers 2 | [production] 3 | > 1% 4 | ie 11 5 | 6 | [modern] 7 | last 2 version 8 | 9 | [ssr] 10 | node 12 11 | -------------------------------------------------------------------------------- /dist/cjs/core/component.d.ts: -------------------------------------------------------------------------------- 1 | import Factory from './factory'; 2 | export default class Component extends Factory { 3 | pushChanges(): void; 4 | } 5 | -------------------------------------------------------------------------------- /dist/esm/core/component.d.ts: -------------------------------------------------------------------------------- 1 | import Factory from './factory'; 2 | export default class Component extends Factory { 3 | pushChanges(): void; 4 | } 5 | -------------------------------------------------------------------------------- /web/client/js/main.ts: -------------------------------------------------------------------------------- 1 | import { Browser } from '../../../src/rxcomp'; 2 | import AppModule from './app.module'; 3 | 4 | Browser.bootstrap(AppModule); 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.html encoding=utf-8 3 | *.js encoding=utf-8 4 | *.ts encoding=utf-8 5 | *.json encoding=utf-8 6 | *.md encoding=utf-8 7 | -------------------------------------------------------------------------------- /web/client/css/main-cssvars.scss: -------------------------------------------------------------------------------- 1 | @import '_variables/main-cssvars'; 2 | @import '_variables/cssvars'; 3 | @import '_variables/grid'; 4 | @import 'shared'; 5 | -------------------------------------------------------------------------------- /dist/cjs/core/pipe.d.ts: -------------------------------------------------------------------------------- 1 | import { IPipeMeta } from "./types"; 2 | export default class Pipe { 3 | static transform(value: any): any; 4 | static meta: IPipeMeta; 5 | } 6 | -------------------------------------------------------------------------------- /dist/esm/core/pipe.d.ts: -------------------------------------------------------------------------------- 1 | import { IPipeMeta } from "./types"; 2 | export default class Pipe { 3 | static transform(value: any): any; 4 | static meta: IPipeMeta; 5 | } 6 | -------------------------------------------------------------------------------- /web/client/js/todo-item/todo-item.ts: -------------------------------------------------------------------------------- 1 | 2 | export default interface ITodoItem { 3 | id?: number; 4 | name?: string; 5 | date?: Date | string; 6 | done?: boolean; 7 | } 8 | -------------------------------------------------------------------------------- /web/client/css/_mixins.scss: -------------------------------------------------------------------------------- 1 | @import "_mixins/aspect"; 2 | @import "_mixins/breakpoints"; 3 | @import "_mixins/functions"; 4 | @import "_mixins/grid"; 5 | @import "_mixins/scrollbar"; 6 | -------------------------------------------------------------------------------- /src/core/pipe.ts: -------------------------------------------------------------------------------- 1 | import { IPipeMeta } from "./types"; 2 | 3 | export default class Pipe { 4 | static transform(value: any): any { 5 | return value; 6 | } 7 | static meta: IPipeMeta; 8 | } 9 | -------------------------------------------------------------------------------- /dist/esm/platform/common/window/window.js: -------------------------------------------------------------------------------- 1 | export const WINDOW = ((typeof self === 'object' && self.self === self && self) || (typeof global === 'object' && global.global === global && global) || this); 2 | -------------------------------------------------------------------------------- /src/platform/common/window/window.ts: -------------------------------------------------------------------------------- 1 | export const WINDOW: Window = ((typeof self === 'object' && self.self === self && self) || (typeof global === 'object' && global.global === global && global) || this) as unknown as Window; 2 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/env", 4 | "@babel/typescript" 5 | ], 6 | "plugins": [ 7 | "@babel/proposal-class-properties", 8 | "@babel/proposal-object-rest-spread" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /src/_scss/rxcomp-dark.scss: -------------------------------------------------------------------------------- 1 | @import '_variables/main'; 2 | @import '_variables/shared'; 3 | @import '_variables/grid'; 4 | @import 'mixins'; 5 | 6 | $background-dark: #111; 7 | $background-light: #333; 8 | 9 | @import '_rxcomp/rxcomp'; 10 | -------------------------------------------------------------------------------- /dist/cjs/json/json.pipe.d.ts: -------------------------------------------------------------------------------- 1 | import Pipe from '../core/pipe'; 2 | import { IPipeMeta } from '../core/types'; 3 | export default class JsonPipe extends Pipe { 4 | static transform(value: any): string | undefined; 5 | static meta: IPipeMeta; 6 | } 7 | -------------------------------------------------------------------------------- /dist/esm/json/json.pipe.d.ts: -------------------------------------------------------------------------------- 1 | import Pipe from '../core/pipe'; 2 | import { IPipeMeta } from '../core/types'; 3 | export default class JsonPipe extends Pipe { 4 | static transform(value: any): string | undefined; 5 | static meta: IPipeMeta; 6 | } 7 | -------------------------------------------------------------------------------- /src/_scss/rxcomp-light.scss: -------------------------------------------------------------------------------- 1 | @import '_variables/main'; 2 | @import '_variables/shared'; 3 | @import '_variables/grid'; 4 | @import 'mixins'; 5 | 6 | $background-dark: #111; 7 | $background-light: #f3f3f3; 8 | 9 | @import '_rxcomp/rxcomp'; 10 | -------------------------------------------------------------------------------- /dist/cjs/event/event.directive.d.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { IFactoryMeta } from '../core/types'; 3 | export default class EventDirective extends Directive { 4 | event: string; 5 | onInit(): void; 6 | static meta: IFactoryMeta; 7 | } 8 | -------------------------------------------------------------------------------- /dist/cjs/json/json.component.d.ts: -------------------------------------------------------------------------------- 1 | import Component from '../core/component'; 2 | import { IFactoryMeta } from '../core/types'; 3 | export default class JsonComponent extends Component { 4 | active: boolean; 5 | onToggle(): void; 6 | static meta: IFactoryMeta; 7 | } 8 | -------------------------------------------------------------------------------- /dist/esm/event/event.directive.d.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { IFactoryMeta } from '../core/types'; 3 | export default class EventDirective extends Directive { 4 | event: string; 5 | onInit(): void; 6 | static meta: IFactoryMeta; 7 | } 8 | -------------------------------------------------------------------------------- /dist/esm/json/json.component.d.ts: -------------------------------------------------------------------------------- 1 | import Component from '../core/component'; 2 | import { IFactoryMeta } from '../core/types'; 3 | export default class JsonComponent extends Component { 4 | active: boolean; 5 | onToggle(): void; 6 | static meta: IFactoryMeta; 7 | } 8 | -------------------------------------------------------------------------------- /dist/cjs/src/src.directive.d.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { IFactoryMeta } from '../core/types'; 3 | export default class SrcDirective extends Directive { 4 | set src(src: string); 5 | get src(): string; 6 | static meta: IFactoryMeta; 7 | } 8 | -------------------------------------------------------------------------------- /dist/esm/src/src.directive.d.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { IFactoryMeta } from '../core/types'; 3 | export default class SrcDirective extends Directive { 4 | set src(src: string); 5 | get src(): string; 6 | static meta: IFactoryMeta; 7 | } 8 | -------------------------------------------------------------------------------- /dist/cjs/href/href.directive.d.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { IFactoryMeta } from '../core/types'; 3 | export default class HrefDirective extends Directive { 4 | set href(href: string); 5 | get href(): string; 6 | static meta: IFactoryMeta; 7 | } 8 | -------------------------------------------------------------------------------- /dist/esm/href/href.directive.d.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { IFactoryMeta } from '../core/types'; 3 | export default class HrefDirective extends Directive { 4 | set href(href: string); 5 | get href(): string; 6 | static meta: IFactoryMeta; 7 | } 8 | -------------------------------------------------------------------------------- /dist/cjs/href/href-target.directive.d.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { IFactoryMeta } from '../core/types'; 3 | export default class HrefTargetDirective extends Directive { 4 | set target(target: string); 5 | get target(): string; 6 | static meta: IFactoryMeta; 7 | } 8 | -------------------------------------------------------------------------------- /dist/esm/href/href-target.directive.d.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { IFactoryMeta } from '../core/types'; 3 | export default class HrefTargetDirective extends Directive { 4 | set target(target: string); 5 | get target(): string; 6 | static meta: IFactoryMeta; 7 | } 8 | -------------------------------------------------------------------------------- /dist/cjs/platform/common/window/window.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.WINDOW = void 0; 4 | exports.WINDOW = ((typeof self === 'object' && self.self === self && self) || (typeof global === 'object' && global.global === global && global) || this); 5 | -------------------------------------------------------------------------------- /docs/img/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #212121 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /dist/cjs/inner-html/inner-html.directive.d.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { IFactoryMeta } from '../core/types'; 3 | export default class InnerHtmlDirective extends Directive { 4 | set innerHTML(innerHTML: string); 5 | get innerHTML(): string; 6 | static meta: IFactoryMeta; 7 | } 8 | -------------------------------------------------------------------------------- /dist/esm/inner-html/inner-html.directive.d.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { IFactoryMeta } from '../core/types'; 3 | export default class InnerHtmlDirective extends Directive { 4 | set innerHTML(innerHTML: string); 5 | get innerHTML(): string; 6 | static meta: IFactoryMeta; 7 | } 8 | -------------------------------------------------------------------------------- /dist/cjs/core/pipe.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var Pipe = /** @class */ (function () { 4 | function Pipe() { 5 | } 6 | Pipe.transform = function (value) { 7 | return value; 8 | }; 9 | return Pipe; 10 | }()); 11 | exports.default = Pipe; 12 | -------------------------------------------------------------------------------- /src/core/component.ts: -------------------------------------------------------------------------------- 1 | 2 | import Factory, { getContext } from './factory'; 3 | 4 | export default class Component extends Factory { 5 | pushChanges(): void { 6 | const { module, node } = getContext(this); 7 | if (module.instances) { 8 | this.changes$.next(this); 9 | module.parse(node, this); 10 | this.onView(); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /dist/cjs/platform/browser.d.ts: -------------------------------------------------------------------------------- 1 | import Module from '../module/module'; 2 | import Platform from './platform'; 3 | export default class Browser extends Platform { 4 | /** 5 | * @param moduleFactory 6 | * @description This method returns a Browser compiled module 7 | */ 8 | static bootstrap(moduleFactory?: typeof Module): Module; 9 | } 10 | -------------------------------------------------------------------------------- /dist/cjs/platform/common/location/location.d.ts: -------------------------------------------------------------------------------- 1 | export interface ILocationInit { 2 | href: string; 3 | protocol: string; 4 | host: string; 5 | hostname: string; 6 | port: string; 7 | pathname: string; 8 | search: string; 9 | hash: string; 10 | } 11 | export declare function getLocationComponents(href: string): ILocationInit; 12 | -------------------------------------------------------------------------------- /dist/esm/platform/browser.d.ts: -------------------------------------------------------------------------------- 1 | import Module from '../module/module'; 2 | import Platform from './platform'; 3 | export default class Browser extends Platform { 4 | /** 5 | * @param moduleFactory 6 | * @description This method returns a Browser compiled module 7 | */ 8 | static bootstrap(moduleFactory?: typeof Module): Module; 9 | } 10 | -------------------------------------------------------------------------------- /dist/esm/platform/common/location/location.d.ts: -------------------------------------------------------------------------------- 1 | export interface ILocationInit { 2 | href: string; 3 | protocol: string; 4 | host: string; 5 | hostname: string; 6 | port: string; 7 | pathname: string; 8 | search: string; 9 | hash: string; 10 | } 11 | export declare function getLocationComponents(href: string): ILocationInit; 12 | -------------------------------------------------------------------------------- /dist/cjs/core.module.d.ts: -------------------------------------------------------------------------------- 1 | import Factory from './core/factory'; 2 | import Pipe from './core/pipe'; 3 | import Module from './module/module'; 4 | export default class CoreModule extends Module { 5 | constructor(); 6 | static meta: { 7 | declarations: (typeof Factory | typeof Pipe)[]; 8 | exports: (typeof Factory | typeof Pipe)[]; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /dist/esm/core.module.d.ts: -------------------------------------------------------------------------------- 1 | import Factory from './core/factory'; 2 | import Pipe from './core/pipe'; 3 | import Module from './module/module'; 4 | export default class CoreModule extends Module { 5 | constructor(); 6 | static meta: { 7 | declarations: (typeof Factory | typeof Pipe)[]; 8 | exports: (typeof Factory | typeof Pipe)[]; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /web/client/css/_components/_responsive.scss: -------------------------------------------------------------------------------- 1 | @each $breakpoint in map-keys($grid-breakpoints) { 2 | @include media-breakpoint-down($breakpoint) { 3 | .hidden-#{$breakpoint}-down { 4 | display: none !important; 5 | } 6 | } 7 | 8 | @include media-breakpoint-up($breakpoint) { 9 | .hidden-#{$breakpoint}-up { 10 | display: none !important; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /dist/cjs/class/class.directive.d.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { IFactoryMeta } from '../core/types'; 3 | export default class ClassDirective extends Directive { 4 | class: { 5 | [key: string]: string; 6 | } | string | null; 7 | keys: string[]; 8 | onInit(): void; 9 | onChanges(): void; 10 | static meta: IFactoryMeta; 11 | } 12 | -------------------------------------------------------------------------------- /dist/esm/class/class.directive.d.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { IFactoryMeta } from '../core/types'; 3 | export default class ClassDirective extends Directive { 4 | class: { 5 | [key: string]: string; 6 | } | string | null; 7 | keys: string[]; 8 | onInit(): void; 9 | onChanges(): void; 10 | static meta: IFactoryMeta; 11 | } 12 | -------------------------------------------------------------------------------- /dist/esm/json/json.pipe.js: -------------------------------------------------------------------------------- 1 | import Pipe from '../core/pipe'; 2 | import Serializer, { encodeJsonWithOptions } from '../platform/common/serializer/serializer'; 3 | export default class JsonPipe extends Pipe { 4 | static transform(value) { 5 | return Serializer.encode(value, [encodeJsonWithOptions('#ref', 2)]); 6 | } 7 | } 8 | JsonPipe.meta = { 9 | name: 'json', 10 | }; 11 | -------------------------------------------------------------------------------- /web/client/css/_components/_base.scss: -------------------------------------------------------------------------------- 1 | html { 2 | width: 100%; 3 | height: 100%; 4 | margin: 0; 5 | overflow-x: hidden; 6 | overscroll-behavior: none; 7 | scroll-behavior: smooth; 8 | } 9 | 10 | body { 11 | width: 100%; 12 | min-height: 100%; 13 | margin: 0; 14 | padding: 0; 15 | } 16 | 17 | [unselectable] { 18 | -webkit-touch-callout: none; 19 | user-select: none; 20 | } 21 | -------------------------------------------------------------------------------- /web/client/css/_shared.scss: -------------------------------------------------------------------------------- 1 | @import 'fonts'; 2 | @import 'mixins'; 3 | 4 | @import '_components/reset'; 5 | @import '_components/base'; 6 | @import '_components/typography'; 7 | @import '_components/buttons'; 8 | @import '_components/forms'; 9 | // @import '_components/grid'; 10 | 11 | @import '_pages/todomvc'; 12 | @import '_pages/test'; 13 | 14 | @import '_components/responsive'; 15 | -------------------------------------------------------------------------------- /dist/esm/core/component.js: -------------------------------------------------------------------------------- 1 | import Factory, { getContext } from './factory'; 2 | export default class Component extends Factory { 3 | pushChanges() { 4 | const { module, node } = getContext(this); 5 | if (module.instances) { 6 | this.changes$.next(this); 7 | module.parse(node, this); 8 | this.onView(); 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /dist/cjs/if/if.structure.d.ts: -------------------------------------------------------------------------------- 1 | import Structure from '../core/structure'; 2 | import { IComment, IElement, IFactoryMeta } from '../core/types'; 3 | export default class IfStructure extends Structure { 4 | ifbegin?: IComment; 5 | ifend?: IComment; 6 | clonedNode?: IElement; 7 | element?: IElement; 8 | onInit(): void; 9 | onChanges(): void; 10 | static meta: IFactoryMeta; 11 | } 12 | -------------------------------------------------------------------------------- /dist/cjs/style/style.directive.d.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { IFactoryMeta } from '../core/types'; 3 | export default class StyleDirective extends Directive { 4 | style?: { 5 | [key: string]: string; 6 | } | null; 7 | previousStyle?: { 8 | [key: string]: string; 9 | } | null; 10 | onChanges(): void; 11 | static meta: IFactoryMeta; 12 | } 13 | -------------------------------------------------------------------------------- /dist/esm/if/if.structure.d.ts: -------------------------------------------------------------------------------- 1 | import Structure from '../core/structure'; 2 | import { IComment, IElement, IFactoryMeta } from '../core/types'; 3 | export default class IfStructure extends Structure { 4 | ifbegin?: IComment; 5 | ifend?: IComment; 6 | clonedNode?: IElement; 7 | element?: IElement; 8 | onInit(): void; 9 | onChanges(): void; 10 | static meta: IFactoryMeta; 11 | } 12 | -------------------------------------------------------------------------------- /dist/esm/style/style.directive.d.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { IFactoryMeta } from '../core/types'; 3 | export default class StyleDirective extends Directive { 4 | style?: { 5 | [key: string]: string; 6 | } | null; 7 | previousStyle?: { 8 | [key: string]: string; 9 | } | null; 10 | onChanges(): void; 11 | static meta: IFactoryMeta; 12 | } 13 | -------------------------------------------------------------------------------- /web/client/templates/shared/header.html: -------------------------------------------------------------------------------- 1 |
2 | RxComp 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | -------------------------------------------------------------------------------- /src/_scss/_variables/_grid.scss: -------------------------------------------------------------------------------- 1 | $grid-columns: 12 !default; 2 | $grid-gutter-widths: (xs: 20px, 3 | sm: 20px, 4 | md: 40px, 5 | lg: 40px, 6 | xl: 40px) !default; 7 | $grid-breakpoints: (xs: 0, 8 | sm: 768px, 9 | md: 1024px, 10 | lg: 1440px, 11 | xl: 1830px) !default; 12 | $container-max-widths: (sm: calc(100vw - 40px), 13 | md: calc(100vw - 160px), 14 | lg: calc(100vw - 160px), 15 | xl: 1920px) !default; // calc(100vw - 300px)) !default; 16 | -------------------------------------------------------------------------------- /web/client/css/_variables/_grid.scss: -------------------------------------------------------------------------------- 1 | $grid-columns: 12 !default; 2 | $grid-gutter-widths: (xs: 20px, 3 | sm: 20px, 4 | md: 40px, 5 | lg: 40px, 6 | xl: 40px) !default; 7 | $grid-breakpoints: (xs: 0, 8 | sm: 768px, 9 | md: 1024px, 10 | lg: 1440px, 11 | xl: 1830px) !default; 12 | $container-max-widths: (sm: calc(100vw - 40px), 13 | md: calc(100vw - 160px), 14 | lg: calc(100vw - 160px), 15 | xl: 1920px) !default; // calc(100vw - 300px)) !default; 16 | -------------------------------------------------------------------------------- /src/_scss/_variables/_shared.scss: -------------------------------------------------------------------------------- 1 | $font-primary: 'Open Sans', 2 | sans-serif; 3 | $font-secondary: 'Akkurat', 4 | serif; 5 | $font-size: 18px; 6 | $font-size-xs: 16px; 7 | $line-height: 1.77; 8 | $font-extralight: 200; 9 | $font-light: 300; 10 | $font-regular: 400; 11 | $font-medium: 500; 12 | $font-semibold: 600; 13 | $font-bold: 700; 14 | $font-extrabold: 800; 15 | $font-black: 900; 16 | $btn-radius: 20px; 17 | $card-radius: 30px; 18 | $bullet-size: 12px; 19 | -------------------------------------------------------------------------------- /src/json/json.pipe.ts: -------------------------------------------------------------------------------- 1 | import Pipe from '../core/pipe'; 2 | import { IPipeMeta } from '../core/types'; 3 | import Serializer, { encodeJsonWithOptions } from '../platform/common/serializer/serializer'; 4 | 5 | export default class JsonPipe extends Pipe { 6 | static transform(value: any): string | undefined { 7 | return Serializer.encode(value, [encodeJsonWithOptions('#ref', 2)]); 8 | } 9 | static meta: IPipeMeta = { 10 | name: 'json', 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /web/client/css/_variables/_shared.scss: -------------------------------------------------------------------------------- 1 | $font-primary: 'Open Sans', 2 | sans-serif; 3 | $font-secondary: 'Akkurat', 4 | serif; 5 | $font-size: 18px; 6 | $font-size-xs: 16px; 7 | $line-height: 1.77; 8 | $font-extralight: 200; 9 | $font-light: 300; 10 | $font-regular: 400; 11 | $font-medium: 500; 12 | $font-semibold: 600; 13 | $font-bold: 700; 14 | $font-extrabold: 800; 15 | $font-black: 900; 16 | $btn-radius: 20px; 17 | $card-radius: 30px; 18 | $bullet-size: 12px; 19 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "ecmaVersion": 8, 4 | "sourceType": "module", 5 | "ecmaFeatures": { 6 | "jsx": false 7 | } 8 | }, 9 | "rules": { 10 | "semi": "error", 11 | "comma-dangle": ["error", { 12 | "functions": "only-multiline", 13 | "arrays": "only-multiline", 14 | "objects": "only-multiline", 15 | "imports": "never", 16 | "exports": "never" 17 | }] 18 | }, 19 | "env": { 20 | "browser": true, 21 | "node": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /web/client/js/app.module.ts: -------------------------------------------------------------------------------- 1 | import { CoreModule, Module } from '../../../src/rxcomp'; 2 | import AppComponent from './app.component'; 3 | import DatePipe from './date/date.pipe'; 4 | import TodoItemComponent from './todo-item/todo-item.component'; 5 | 6 | export default class AppModule extends Module { } 7 | 8 | AppModule.meta = { 9 | imports: [ 10 | CoreModule 11 | ], 12 | declarations: [ 13 | TodoItemComponent, 14 | DatePipe, 15 | ], 16 | bootstrap: AppComponent, 17 | }; 18 | -------------------------------------------------------------------------------- /dist/cjs/for/for.item.d.ts: -------------------------------------------------------------------------------- 1 | import Context from '../core/context'; 2 | import Factory from '../core/factory'; 3 | export default class ForItem extends Context { 4 | index: number; 5 | count: number; 6 | [key: string]: any; 7 | constructor(key: string, $key: number | string, value: string, $value: any, index: number, count: number, parentInstance: Factory); 8 | get first(): boolean; 9 | get last(): boolean; 10 | get even(): boolean; 11 | get odd(): boolean; 12 | } 13 | -------------------------------------------------------------------------------- /dist/esm/for/for.item.d.ts: -------------------------------------------------------------------------------- 1 | import Context from '../core/context'; 2 | import Factory from '../core/factory'; 3 | export default class ForItem extends Context { 4 | index: number; 5 | count: number; 6 | [key: string]: any; 7 | constructor(key: string, $key: number | string, value: string, $value: any, index: number, count: number, parentInstance: Factory); 8 | get first(): boolean; 9 | get last(): boolean; 10 | get even(): boolean; 11 | get odd(): boolean; 12 | } 13 | -------------------------------------------------------------------------------- /docs/img/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "RxComp", 3 | "short_name": "RxComp", 4 | "icons": [ 5 | { 6 | "src": "/img/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/img/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "start_url": "https://actarian.github.io/rxcomp/", 17 | "theme_color": "#ffffff", 18 | "background_color": "#ffffff", 19 | "display": "standalone" 20 | } 21 | -------------------------------------------------------------------------------- /dist/cjs/core/directive.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var tslib_1 = require("tslib"); 4 | var factory_1 = tslib_1.__importDefault(require("./factory")); 5 | var Directive = /** @class */ (function (_super) { 6 | tslib_1.__extends(Directive, _super); 7 | function Directive() { 8 | return _super !== null && _super.apply(this, arguments) || this; 9 | } 10 | return Directive; 11 | }(factory_1.default)); 12 | exports.default = Directive; 13 | -------------------------------------------------------------------------------- /dist/cjs/core/structure.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var tslib_1 = require("tslib"); 4 | var factory_1 = tslib_1.__importDefault(require("./factory")); 5 | var Structure = /** @class */ (function (_super) { 6 | tslib_1.__extends(Structure, _super); 7 | function Structure() { 8 | return _super !== null && _super.apply(this, arguments) || this; 9 | } 10 | return Structure; 11 | }(factory_1.default)); 12 | exports.default = Structure; 13 | -------------------------------------------------------------------------------- /web/client/css/_components/_forms.scss: -------------------------------------------------------------------------------- 1 | .group--form { 2 | display: flex; 3 | padding: 10px 20px; 4 | } 5 | 6 | .control--text { 7 | width: 100%; 8 | margin: 0; 9 | padding: 0 20px 0 0; 10 | font-size: 28px; 11 | font-weight: 800; 12 | background: none; 13 | border: none; 14 | outline: none; 15 | color: $foreground; 16 | 17 | &::placeholder { 18 | font-size: 28px; 19 | font-weight: 800; 20 | color: rgba($foreground, 0.2); 21 | } 22 | } 23 | 24 | ::placeholder { 25 | font-family: $font-primary; 26 | } 27 | -------------------------------------------------------------------------------- /web/client/js/date/date.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe } from "../../../../src/rxcomp"; 2 | 3 | export default class DatePipe extends Pipe { 4 | 5 | static transform(value: Date | string, locale = 'it-IT-u-ca-gregory', options: Intl.DateTimeFormatOptions = { 6 | dateStyle: 'short', 7 | timeStyle: 'short', 8 | } as Intl.DateTimeFormatOptions): string { 9 | const localeDateString = new Date(value).toLocaleDateString(locale, options); 10 | return localeDateString; 11 | } 12 | 13 | static meta = { 14 | name: 'date', 15 | }; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "es2015", "es2016", "es2017", "es2020.string"], 4 | "target": "ESNext", 5 | "module": "ESNext", 6 | "moduleResolution": "node", 7 | "typeRoots": ["node_modules/@types"], 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "strict": true, 11 | "strictNullChecks": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noImplicitReturns": true, 14 | "noImplicitAny": true, 15 | "noUnusedLocals": true, 16 | "downlevelIteration": true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /dist/cjs/core/context.d.ts: -------------------------------------------------------------------------------- 1 | import Component from './component'; 2 | import Factory from './factory'; 3 | export default class Context extends Component { 4 | constructor(parentInstance: Factory, descriptors?: { 5 | [key: string]: PropertyDescriptor; 6 | }); 7 | pushChanges(): void; 8 | onParentDidChange(changes: Factory | Window): void; 9 | static mergeDescriptors(source: Object, instance: Factory, descriptors?: { 10 | [key: string]: PropertyDescriptor; 11 | }): { 12 | [key: string]: PropertyDescriptor; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /dist/esm/core/context.d.ts: -------------------------------------------------------------------------------- 1 | import Component from './component'; 2 | import Factory from './factory'; 3 | export default class Context extends Component { 4 | constructor(parentInstance: Factory, descriptors?: { 5 | [key: string]: PropertyDescriptor; 6 | }); 7 | pushChanges(): void; 8 | onParentDidChange(changes: Factory | Window): void; 9 | static mergeDescriptors(source: Object, instance: Factory, descriptors?: { 10 | [key: string]: PropertyDescriptor; 11 | }): { 12 | [key: string]: PropertyDescriptor; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /dist/cjs/platform/common/transfer/transfer.service.d.ts: -------------------------------------------------------------------------------- 1 | export default class TransferService { 2 | static makeKey(base: string, params?: { 3 | [key: string]: any; 4 | }): string; 5 | static has(key: string): boolean; 6 | static get(key: string): T | undefined; 7 | static get(key: string): { 8 | [key: string]: any; 9 | } | undefined; 10 | static set(key: string, value: { 11 | [key: string]: any; 12 | }): void; 13 | static remove(key: string): void; 14 | } 15 | export declare function optionsToKey(v: any, s?: string): string; 16 | -------------------------------------------------------------------------------- /dist/esm/platform/common/transfer/transfer.service.d.ts: -------------------------------------------------------------------------------- 1 | export default class TransferService { 2 | static makeKey(base: string, params?: { 3 | [key: string]: any; 4 | }): string; 5 | static has(key: string): boolean; 6 | static get(key: string): T | undefined; 7 | static get(key: string): { 8 | [key: string]: any; 9 | } | undefined; 10 | static set(key: string, value: { 11 | [key: string]: any; 12 | }): void; 13 | static remove(key: string): void; 14 | } 15 | export declare function optionsToKey(v: any, s?: string): string; 16 | -------------------------------------------------------------------------------- /dist/esm/src/src.directive.js: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { getContext } from '../core/factory'; 3 | export default class SrcDirective extends Directive { 4 | set src(src) { 5 | if (this.src_ !== src) { 6 | this.src_ = src; 7 | const { node } = getContext(this); 8 | src ? node.setAttribute('src', src) : node.removeAttribute('src'); 9 | } 10 | } 11 | get src() { 12 | return this.src_; 13 | } 14 | } 15 | SrcDirective.meta = { 16 | selector: '[[src]]', 17 | inputs: ['src'], 18 | }; 19 | -------------------------------------------------------------------------------- /dist/esm/href/href.directive.js: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { getContext } from '../core/factory'; 3 | export default class HrefDirective extends Directive { 4 | set href(href) { 5 | if (this.href_ !== href) { 6 | this.href_ = href; 7 | const { node } = getContext(this); 8 | href ? node.setAttribute('href', href) : node.removeAttribute('href'); 9 | } 10 | } 11 | get href() { 12 | return this.href_; 13 | } 14 | } 15 | HrefDirective.meta = { 16 | selector: '[[href]]', 17 | inputs: ['href'], 18 | }; 19 | -------------------------------------------------------------------------------- /src/src/src.directive.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { getContext } from '../core/factory'; 3 | import { IFactoryMeta } from '../core/types'; 4 | 5 | export default class SrcDirective extends Directive { 6 | set src(src: string) { 7 | if (this.src_ !== src) { 8 | this.src_ = src; 9 | const { node } = getContext(this); 10 | src ? node.setAttribute('src', src) : node.removeAttribute('src'); 11 | } 12 | } 13 | get src(): string { 14 | return this.src_; 15 | } 16 | static meta: IFactoryMeta = { 17 | selector: '[[src]]', 18 | inputs: ['src'], 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/_scss/_variables/_main.scss: -------------------------------------------------------------------------------- 1 | $background: #ffffff; 2 | $background-negative: #212121; 3 | $background-primary: #003adc; 4 | $background-secondary: #8f929b; 5 | // $background-tertiary: #f8f5f5; 6 | // $background-quaternary: #ffffff; 7 | // $background-quinary: #ffffff; 8 | // $background-senary: #ffffff; 9 | $foreground: #212121; 10 | $foreground-negative: #ffffff; 11 | $foreground-primary: #003adc; 12 | $foreground-secondary: #8f929b; 13 | // $foreground-tertiary: #1e2849; 14 | // $foreground-quaternary: #000000; 15 | // $foreground-quinary: #000000; 16 | // $foreground-senary: #000000; 17 | $border: #212121; 18 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const { 2 | build, 3 | buildAndWatch, 4 | buildWatchAndServe, 5 | buildCss, 6 | buildCssAndWatch, 7 | buildJs, 8 | buildJsAndWatch, 9 | bundle, 10 | compile, 11 | serve, 12 | watch 13 | } = require('gulpfile-config'); 14 | 15 | exports.compile = compile; 16 | exports.bundle = bundle; 17 | exports.serve = serve; 18 | exports.watch = watch; 19 | exports.build = build; 20 | exports.start = buildAndWatch; 21 | exports.buildCss = buildCss; 22 | exports.startCss = buildCssAndWatch; 23 | exports.buildJs = buildJs; 24 | exports.startJs = buildJsAndWatch; 25 | 26 | exports.default = buildWatchAndServe; 27 | -------------------------------------------------------------------------------- /src/href/href.directive.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { getContext } from '../core/factory'; 3 | import { IFactoryMeta } from '../core/types'; 4 | 5 | export default class HrefDirective extends Directive { 6 | set href(href: string) { 7 | if (this.href_ !== href) { 8 | this.href_ = href; 9 | const { node } = getContext(this); 10 | href ? node.setAttribute('href', href) : node.removeAttribute('href'); 11 | } 12 | } 13 | get href(): string { 14 | return this.href_; 15 | } 16 | static meta: IFactoryMeta = { 17 | selector: '[[href]]', 18 | inputs: ['href'], 19 | }; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /web/client/css/_variables/_main.scss: -------------------------------------------------------------------------------- 1 | $background: #ffffff; 2 | $background-negative: #212121; 3 | $background-primary: #003adc; 4 | // $background-secondary: #ffffff; 5 | // $background-tertiary: #f8f5f5; 6 | // $background-quaternary: #ffffff; 7 | // $background-quinary: #ffffff; 8 | // $background-senary: #ffffff; 9 | $foreground: #212121; 10 | $foreground-negative: #ffffff; 11 | $foreground-primary: #003adc; 12 | // $foreground-secondary: #1e2849; 13 | // $foreground-tertiary: #1e2849; 14 | // $foreground-quaternary: #000000; 15 | // $foreground-quinary: #000000; 16 | // $foreground-senary: #000000; 17 | $border: #212121; 18 | -------------------------------------------------------------------------------- /dist/esm/href/href-target.directive.js: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { getContext } from '../core/factory'; 3 | export default class HrefTargetDirective extends Directive { 4 | set target(target) { 5 | if (this.target_ !== target) { 6 | this.target_ = target; 7 | const { node } = getContext(this); 8 | target ? node.setAttribute('target', target) : node.removeAttribute('target'); 9 | } 10 | } 11 | get target() { 12 | return this.target_; 13 | } 14 | } 15 | HrefTargetDirective.meta = { 16 | selector: '[[target]]', 17 | inputs: ['target'], 18 | }; 19 | -------------------------------------------------------------------------------- /src/href/href-target.directive.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { getContext } from '../core/factory'; 3 | import { IFactoryMeta } from '../core/types'; 4 | 5 | export default class HrefTargetDirective extends Directive { 6 | set target(target: string) { 7 | if (this.target_ !== target) { 8 | this.target_ = target; 9 | const { node } = getContext(this); 10 | target ? node.setAttribute('target', target) : node.removeAttribute('target'); 11 | } 12 | } 13 | get target(): string { 14 | return this.target_; 15 | } 16 | static meta: IFactoryMeta = { 17 | selector: '[[target]]', 18 | inputs: ['target'], 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = tab 7 | indent_size = 4 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.json] 13 | indent_style = space 14 | indent_size = 2 15 | 16 | [*.md] 17 | max_line_length = off 18 | trim_trailing_whitespace = false 19 | indent_style = space 20 | indent_size = 2 21 | 22 | # The indent size used in the `package.json` file cannot be changed 23 | # https://github.com/npm/npm/pull/3180#issuecomment-16336516 24 | [{*.yml,*.yaml,package.json,package-lock.json}] 25 | indent_style = space 26 | indent_size = 2 27 | -------------------------------------------------------------------------------- /dist/esm/inner-html/inner-html.directive.js: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { getContext } from '../core/factory'; 3 | export default class InnerHtmlDirective extends Directive { 4 | set innerHTML(innerHTML) { 5 | if (this.innerHTML_ !== innerHTML) { 6 | this.innerHTML_ = innerHTML; 7 | const { node } = getContext(this); 8 | node.innerHTML = innerHTML == undefined ? '' : innerHTML; // !!! keep == loose equality 9 | } 10 | } 11 | get innerHTML() { 12 | return this.innerHTML_; 13 | } 14 | } 15 | InnerHtmlDirective.meta = { 16 | selector: `[innerHTML]`, 17 | inputs: ['innerHTML'], 18 | }; 19 | -------------------------------------------------------------------------------- /src/inner-html/inner-html.directive.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { getContext } from '../core/factory'; 3 | import { IFactoryMeta } from '../core/types'; 4 | 5 | export default class InnerHtmlDirective extends Directive { 6 | set innerHTML(innerHTML: string) { 7 | if (this.innerHTML_ !== innerHTML) { 8 | this.innerHTML_ = innerHTML; 9 | const { node } = getContext(this); 10 | node.innerHTML = innerHTML == undefined ? '' : innerHTML; // !!! keep == loose equality 11 | } 12 | } 13 | get innerHTML(): string { 14 | return this.innerHTML_; 15 | } 16 | static meta: IFactoryMeta = { 17 | selector: `[innerHTML]`, 18 | inputs: ['innerHTML'], 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /web/client/css/_mixins/_scrollbar.scss: -------------------------------------------------------------------------------- 1 | @mixin scrollbar() { 2 | 3 | &::-webkit-scrollbar { 4 | width: 6px; 5 | border-radius: 3px; 6 | } 7 | 8 | &::-webkit-scrollbar-button { 9 | display: none; 10 | } 11 | 12 | &::-webkit-scrollbar-button:hover { 13 | display: none; 14 | } 15 | 16 | &::-webkit-scrollbar-thumb { 17 | background-color: rgba(#000, 0.25); 18 | box-shadow: none; 19 | border-radius: 3px; 20 | 21 | &:hover { 22 | background-color: rgba(#000, 0.25); 23 | } 24 | } 25 | 26 | &::-webkit-scrollbar-track { 27 | background-color: transparent; 28 | border-radius: 3px; 29 | 30 | &:hover { 31 | background-color: transparent; 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /web/client/templates/shared/analytics.html: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /dist/cjs/for/for.structure.d.ts: -------------------------------------------------------------------------------- 1 | import Factory from '../core/factory'; 2 | import Structure from '../core/structure'; 3 | import { IComment, IElement, IFactoryMeta, IForExpressionTokens } from '../core/types'; 4 | import Module from '../module/module'; 5 | export default class ForStructure extends Structure { 6 | instances: Factory[]; 7 | forbegin: IComment; 8 | forend: IComment; 9 | tokens: IForExpressionTokens; 10 | onInit(): void; 11 | onChanges(): void; 12 | static getInputsTokens(instance: ForStructure, node: IElement, module: Module): { 13 | [key: string]: string; 14 | }; 15 | static getForExpressionTokens(expression: string): IForExpressionTokens; 16 | static meta: IFactoryMeta; 17 | } 18 | -------------------------------------------------------------------------------- /dist/esm/for/for.structure.d.ts: -------------------------------------------------------------------------------- 1 | import Factory from '../core/factory'; 2 | import Structure from '../core/structure'; 3 | import { IComment, IElement, IFactoryMeta, IForExpressionTokens } from '../core/types'; 4 | import Module from '../module/module'; 5 | export default class ForStructure extends Structure { 6 | instances: Factory[]; 7 | forbegin: IComment; 8 | forend: IComment; 9 | tokens: IForExpressionTokens; 10 | onInit(): void; 11 | onChanges(): void; 12 | static getInputsTokens(instance: ForStructure, node: IElement, module: Module): { 13 | [key: string]: string; 14 | }; 15 | static getForExpressionTokens(expression: string): IForExpressionTokens; 16 | static meta: IFactoryMeta; 17 | } 18 | -------------------------------------------------------------------------------- /web/client/css/_components/_grid.css: -------------------------------------------------------------------------------- 1 | @import './../mixins'; 2 | 3 | @include _assert-ascending($grid-breakpoints, "$grid-breakpoints"); 4 | @include _assert-starts-at-zero($grid-breakpoints, "$grid-breakpoints"); 5 | 6 | .container { 7 | @include make-container(); 8 | @include make-container-max-widths(); 9 | } 10 | 11 | .container-fluid { 12 | @include make-container(); 13 | } 14 | 15 | .row { 16 | @include make-row(); 17 | min-width: 100%; 18 | } 19 | 20 | .container { 21 | position: relative; 22 | 23 | @include media-breakpoint-down(xs) { 24 | padding-left: 30px; 25 | padding-right: 30px; 26 | } 27 | } 28 | 29 | @include make-grid-columns(); 30 | 31 | @include media-breakpoint-down(sm) { 32 | 33 | @for $i from 1 through 20 { 34 | 35 | .o-#{$i} { 36 | order: $i; 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /dist/cjs/core/component.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var tslib_1 = require("tslib"); 4 | var factory_1 = tslib_1.__importStar(require("./factory")); 5 | var Component = /** @class */ (function (_super) { 6 | tslib_1.__extends(Component, _super); 7 | function Component() { 8 | return _super !== null && _super.apply(this, arguments) || this; 9 | } 10 | Component.prototype.pushChanges = function () { 11 | var _a = (0, factory_1.getContext)(this), module = _a.module, node = _a.node; 12 | if (module.instances) { 13 | this.changes$.next(this); 14 | module.parse(node, this); 15 | this.onView(); 16 | } 17 | }; 18 | return Component; 19 | }(factory_1.default)); 20 | exports.default = Component; 21 | -------------------------------------------------------------------------------- /dist/cjs/json/json.pipe.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var tslib_1 = require("tslib"); 4 | var pipe_1 = tslib_1.__importDefault(require("../core/pipe")); 5 | var serializer_1 = tslib_1.__importStar(require("../platform/common/serializer/serializer")); 6 | var JsonPipe = /** @class */ (function (_super) { 7 | tslib_1.__extends(JsonPipe, _super); 8 | function JsonPipe() { 9 | return _super !== null && _super.apply(this, arguments) || this; 10 | } 11 | JsonPipe.transform = function (value) { 12 | return serializer_1.default.encode(value, [(0, serializer_1.encodeJsonWithOptions)('#ref', 2)]); 13 | }; 14 | JsonPipe.meta = { 15 | name: 'json', 16 | }; 17 | return JsonPipe; 18 | }(pipe_1.default)); 19 | exports.default = JsonPipe; 20 | -------------------------------------------------------------------------------- /web/client/test.pipes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
    6 |
  • 7 | 8 |
  • 9 |
  • 10 | {{time | time}} 11 |
  • 12 |
  • 13 | 14 |
  • 15 |
  • 16 | 17 |
  • 18 |
19 |
20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/json/json.component.ts: -------------------------------------------------------------------------------- 1 | import Component from '../core/component'; 2 | import { IFactoryMeta } from '../core/types'; 3 | 4 | export default class JsonComponent extends Component { 5 | active: boolean = false; 6 | onToggle() { 7 | this.active = !this.active; 8 | this.pushChanges(); 9 | } 10 | static meta: IFactoryMeta = { 11 | selector: 'json-component', 12 | inputs: ['item'], 13 | template: /* html */` 14 |
15 |
16 | 17 | + json 18 | - json 19 | 20 | 21 |
22 |
    23 |
  • 24 | 25 |
  • 26 |
27 |
`, 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /dist/esm/json/json.component.js: -------------------------------------------------------------------------------- 1 | import Component from '../core/component'; 2 | export default class JsonComponent extends Component { 3 | constructor() { 4 | super(...arguments); 5 | this.active = false; 6 | } 7 | onToggle() { 8 | this.active = !this.active; 9 | this.pushChanges(); 10 | } 11 | } 12 | JsonComponent.meta = { 13 | selector: 'json-component', 14 | inputs: ['item'], 15 | template: /* html */ ` 16 |
17 |
18 | 19 | + json 20 | - json 21 | 22 | 23 |
24 |
    25 |
  • 26 | 27 |
  • 28 |
29 |
`, 30 | }; 31 | -------------------------------------------------------------------------------- /dist/cjs/core/factory.d.ts: -------------------------------------------------------------------------------- 1 | import { ReplaySubject, Subject } from 'rxjs'; 2 | import Module from '../module/module'; 3 | import { IContext, IElement, IFactoryMeta } from './types'; 4 | export declare const CONTEXTS: { 5 | [key: number]: IContext; 6 | }; 7 | export declare const NODES: { 8 | [key: number]: IContext[]; 9 | }; 10 | export default class Factory { 11 | static meta: IFactoryMeta; 12 | rxcompId: number; 13 | unsubscribe$: Subject; 14 | changes$: ReplaySubject; 15 | onInit(): void; 16 | onChanges(changes: Factory | Window): void; 17 | onView(): void; 18 | onDestroy(): void; 19 | pushChanges(): void; 20 | onParentDidChange(changes: Factory | Window): void; 21 | [key: string]: any; 22 | constructor(...args: any[]); 23 | static getInputsTokens(instance: Factory, node: IElement, module: Module): { 24 | [key: string]: string; 25 | }; 26 | } 27 | export declare function getContext(instance: Factory): IContext; 28 | -------------------------------------------------------------------------------- /dist/esm/core/factory.d.ts: -------------------------------------------------------------------------------- 1 | import { ReplaySubject, Subject } from 'rxjs'; 2 | import Module from '../module/module'; 3 | import { IContext, IElement, IFactoryMeta } from './types'; 4 | export declare const CONTEXTS: { 5 | [key: number]: IContext; 6 | }; 7 | export declare const NODES: { 8 | [key: number]: IContext[]; 9 | }; 10 | export default class Factory { 11 | static meta: IFactoryMeta; 12 | rxcompId: number; 13 | unsubscribe$: Subject; 14 | changes$: ReplaySubject; 15 | onInit(): void; 16 | onChanges(changes: Factory | Window): void; 17 | onView(): void; 18 | onDestroy(): void; 19 | pushChanges(): void; 20 | onParentDidChange(changes: Factory | Window): void; 21 | [key: string]: any; 22 | constructor(...args: any[]); 23 | static getInputsTokens(instance: Factory, node: IElement, module: Module): { 24 | [key: string]: string; 25 | }; 26 | } 27 | export declare function getContext(instance: Factory): IContext; 28 | -------------------------------------------------------------------------------- /web/client/css/_components/_typography.scss: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: $font-primary; 3 | font-weight: $font-light; 4 | line-height: $line-height; 5 | background: $background; 6 | color: $foreground; 7 | 8 | @include media-breakpoint-up(sm) { 9 | font-size: $font-size; 10 | } 11 | 12 | @include media-breakpoint-down(xs) { 13 | font-size: $font-size-xs; 14 | } 15 | } 16 | 17 | b, 18 | strong { 19 | font-weight: $font-semibold; 20 | } 21 | 22 | .h1, 23 | .h2, 24 | .h3, 25 | .h4, 26 | .h5 { 27 | font-family: $font-primary; 28 | font-weight: $font-semibold; 29 | } 30 | 31 | .h1 { 32 | font-size: 4rem; 33 | line-height: 1; 34 | margin-bottom: 40px; 35 | } 36 | 37 | .h2 { 38 | font-size: 3.5rem; 39 | line-height: 1; 40 | margin-bottom: 30px; 41 | } 42 | 43 | .h3 { 44 | font-size: 3rem; 45 | margin-bottom: 20px; 46 | } 47 | 48 | .h4 { 49 | font-size: 2.5rem; 50 | margin-bottom: 10px; 51 | } 52 | 53 | .h5 { 54 | font-size: 2rem; 55 | } 56 | 57 | .h6 { 58 | font-size: 1.5rem; 59 | } 60 | -------------------------------------------------------------------------------- /dist/cjs/platform/common/serializer/serializer.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @example Serializer.encode(value, [encodeJson, encodeUriComponent, encodeBase64]); 3 | * @example Serializer.decode(value, [decodeBase64, decodeUriComponent, decodeJson]); 4 | */ 5 | export default class Serializer { 6 | static encode(value: any, encoders: ((from: any) => any)[]): T; 7 | static decode(value: any, decoders: ((from: any) => any)[]): T; 8 | static encodeJson(value: any): T; 9 | static decodeJson(value: any): T; 10 | static encodeBase64(value: any): T; 11 | static decodeBase64(value: any): T; 12 | } 13 | export declare function encodeJson(value: any, circularRef?: any, space?: string | number): string; 14 | export declare function encodeJsonWithOptions(circularRef?: any, space?: string | number): (value: any) => string; 15 | export declare function decodeJson(value: string): any; 16 | export declare function encodeBase64(value: string): string; 17 | export declare function decodeBase64(value: string): string; 18 | -------------------------------------------------------------------------------- /dist/esm/platform/common/serializer/serializer.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @example Serializer.encode(value, [encodeJson, encodeUriComponent, encodeBase64]); 3 | * @example Serializer.decode(value, [decodeBase64, decodeUriComponent, decodeJson]); 4 | */ 5 | export default class Serializer { 6 | static encode(value: any, encoders: ((from: any) => any)[]): T; 7 | static decode(value: any, decoders: ((from: any) => any)[]): T; 8 | static encodeJson(value: any): T; 9 | static decodeJson(value: any): T; 10 | static encodeBase64(value: any): T; 11 | static decodeBase64(value: any): T; 12 | } 13 | export declare function encodeJson(value: any, circularRef?: any, space?: string | number): string; 14 | export declare function encodeJsonWithOptions(circularRef?: any, space?: string | number): (value: any) => string; 15 | export declare function decodeJson(value: string): any; 16 | export declare function encodeBase64(value: string): string; 17 | export declare function decodeBase64(value: string): string; 18 | -------------------------------------------------------------------------------- /web/client/test.for.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 |
7 | 8 | 9 | 10 |
11 |
12 |
{{key}} {{value | json}}
13 |
14 |
15 |
16 |
{{item | example}}
17 |
18 |
19 |
20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /web/client/css/_components/_locomotive.scss: -------------------------------------------------------------------------------- 1 | html { 2 | &:not(.has-scroll-init) { 3 | cursor: wait; 4 | overflow: hidden; 5 | } 6 | 7 | &.has-scroll-smooth { 8 | overflow: hidden; 9 | } 10 | 11 | &.has-scroll-dragging { 12 | user-select: none; 13 | } 14 | } 15 | 16 | body { 17 | .has-scroll-smooth & { 18 | overflow: hidden; 19 | } 20 | } 21 | 22 | .o-scroll { 23 | box-sizing: border-box; 24 | overflow: hidden; 25 | width: 100vw; 26 | 27 | .has-scroll-smooth & { 28 | position: relative; 29 | } 30 | } 31 | 32 | .c-scrollbar { 33 | width: 8px; 34 | position: absolute; 35 | right: 2px; 36 | top: 0; 37 | height: 100vh; 38 | transform-origin: center right; 39 | transform: scaleX(1); 40 | transition: transform 0.2s linear; 41 | 42 | &:hover { 43 | transform: scaleX(1.3); 44 | cursor: grab; 45 | } 46 | } 47 | 48 | .c-scrollbar_thumb { 49 | background-color: rgba(0, 0, 0, 0.15); 50 | border-radius: 4px; 51 | position: absolute; 52 | top: 0; 53 | left: 0; 54 | right: 0; 55 | 56 | &:hover { 57 | cursor: pointer; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /web/client/js/test.pipes.ts: -------------------------------------------------------------------------------- 1 | import { Browser, Component, CoreModule, Module, Pipe } from '../../../src/rxcomp'; 2 | 3 | class RootComponent extends Component { 4 | time: Date = new Date(); 5 | value: number = 2; 6 | } 7 | RootComponent.meta = { 8 | selector: '[root-component]', 9 | }; 10 | 11 | class TimePipe extends Pipe { 12 | static transform(value: Date | string, options: number = 1): string { 13 | const date = new Date(value); 14 | return `${date.getHours()}:${date.getMinutes()}`; 15 | } 16 | } 17 | TimePipe.meta = { 18 | name: 'time', 19 | }; 20 | 21 | class MultPipe extends Pipe { 22 | static transform(value: string | number, mult1: number = 2, mult2: number = 1): number { 23 | return Number(value) * Number(mult1) * Number(mult2); 24 | } 25 | } 26 | MultPipe.meta = { 27 | name: 'mult', 28 | }; 29 | 30 | class AppModule extends Module { } 31 | AppModule.meta = { 32 | imports: [ 33 | CoreModule 34 | ], 35 | declarations: [ 36 | TimePipe, 37 | MultPipe 38 | ], 39 | bootstrap: RootComponent, 40 | }; 41 | 42 | Browser.bootstrap(AppModule); 43 | -------------------------------------------------------------------------------- /dist/esm/platform/common/location/location.js: -------------------------------------------------------------------------------- 1 | export function getLocationComponents(href) { 2 | let protocol = ''; 3 | let host = ''; 4 | let hostname = ''; 5 | let port = ''; 6 | let pathname = ''; 7 | let search = ''; 8 | let hash = ''; 9 | const regExp = /^((http\:|https\:)?\/\/)?((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])|(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])|locahost)?(\:([^\/]+))?(\.?\/[^\?]+)?(\?[^\#]+)?(\#.+)?$/g; 10 | const matches = []; 11 | let match; 12 | while ((match = regExp.exec(href)) !== null) { 13 | matches.push(match); 14 | } 15 | for (let match of matches) { 16 | protocol = match[2] || ''; 17 | host = hostname = match[3] || ''; 18 | port = match[11] || ''; 19 | pathname = match[12] || ''; 20 | search = match[13] || ''; 21 | hash = match[14] || ''; 22 | } 23 | return { href, protocol, host, hostname, port, pathname, search, hash }; 24 | } 25 | -------------------------------------------------------------------------------- /docs/fonts/todomvc/todomvc.css: -------------------------------------------------------------------------------- 1 | /* Generated by Glyphter (http://www.glyphter.com) on Fri Nov 08 2019*/ 2 | @font-face { 3 | font-family: 'todomvc'; 4 | src: url('../fonts/todomvc.eot'); 5 | src: url('../fonts/todomvc.eot?#iefix') format('embedded-opentype'), 6 | url('../fonts/todomvc.woff') format('woff'), 7 | url('../fonts/todomvc.ttf') format('truetype'), 8 | url('../fonts/todomvc.svg#todomvc') format('svg'); 9 | font-weight: normal; 10 | font-style: normal; 11 | } 12 | 13 | [class*='icon-']:before { 14 | display: inline-block; 15 | font-family: 'todomvc'; 16 | font-style: normal; 17 | font-weight: normal; 18 | line-height: 1; 19 | -webkit-font-smoothing: antialiased; 20 | -moz-osx-font-smoothing: grayscale 21 | } 22 | 23 | .icon-add:before { 24 | content: '\0041'; 25 | } 26 | 27 | .icon-remove:before { 28 | content: '\0042'; 29 | } 30 | 31 | .icon-check:before { 32 | content: '\0043'; 33 | } 34 | 35 | .icon-twitter:before { 36 | content: '\0044'; 37 | } 38 | 39 | .icon-github:before { 40 | content: '\0045'; 41 | } 42 | 43 | .icon-circle:before { 44 | content: '\0046'; 45 | } 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Luca Zampetti 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 | -------------------------------------------------------------------------------- /src/class/class.directive.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { getContext } from '../core/factory'; 3 | import { IFactoryMeta } from '../core/types'; 4 | 5 | export default class ClassDirective extends Directive { 6 | class: { [key: string]: string } | string | null = ''; 7 | keys: string[] = []; 8 | onInit() { 9 | const { node } = getContext(this); 10 | Array.prototype.slice.call(node.classList).forEach((value: string) => { 11 | this.keys.push(value); 12 | }); 13 | } 14 | onChanges() { 15 | const { node } = getContext(this); 16 | let keys: string[] = []; 17 | const object = this.class; 18 | if (typeof object === 'object') { 19 | for (let key in object) { 20 | if (object[key]) { 21 | keys.push(key); 22 | } 23 | } 24 | } else if (typeof object === 'string') { 25 | keys = object.split(/\s+/); 26 | } 27 | keys = keys.concat(this.keys); 28 | // console.log(keys); 29 | node.setAttribute('class', keys.join(' ')); 30 | // console.log('ClassDirective.onChanges', keys); 31 | } 32 | static meta: IFactoryMeta = { 33 | selector: `[[class]]`, 34 | inputs: ['class'] 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /web/client/css/_fonts/todomvc/todomvc.scss: -------------------------------------------------------------------------------- 1 | /* Generated by Glyphter (http://www.glyphter.com) on Fri Nov 08 2019*/ 2 | @font-face { 3 | font-family: 'todomvc'; 4 | src: url('../fonts/todomvc/todomvc.eot'); 5 | src: url('../fonts/todomvc/todomvc.eot?#iefix') format('embedded-opentype'), 6 | url('../fonts/todomvc/todomvc.woff') format('woff'), 7 | url('../fonts/todomvc/todomvc.ttf') format('truetype'), 8 | url('../fonts/todomvc/todomvc.svg#todomvc') format('svg'); 9 | font-weight: normal; 10 | font-style: normal; 11 | } 12 | 13 | [class*='icon--']:before { 14 | display: inline-block; 15 | font-family: 'todomvc'; 16 | font-style: normal; 17 | font-weight: normal; 18 | line-height: 1; 19 | -webkit-font-smoothing: antialiased; 20 | -moz-osx-font-smoothing: grayscale 21 | } 22 | 23 | .icon--add:before { 24 | content: '\0041'; 25 | } 26 | 27 | .icon--remove:before { 28 | content: '\0042'; 29 | } 30 | 31 | .icon--check:before { 32 | content: '\0043'; 33 | } 34 | 35 | .icon--twitter:before { 36 | content: '\0044'; 37 | } 38 | 39 | .icon--github:before { 40 | content: '\0045'; 41 | } 42 | 43 | .icon--circle:before { 44 | content: '\0046'; 45 | } 46 | -------------------------------------------------------------------------------- /src/_scss/_variables/_main-cssvars.scss: -------------------------------------------------------------------------------- 1 | @import 'shared'; 2 | 3 | body { 4 | --font-primary: #{$font-primary}; 5 | --font-secondary: #{$font-secondary}; 6 | --font-size: #{$font-size}; 7 | --line-height: #{$line-height}; 8 | --font-extralight: #{$font-extralight}; 9 | --font-light: #{$font-light}; 10 | --font-regular: #{$font-regular}; 11 | --font-semibold: #{$font-semibold}; 12 | --font-bold: #{$font-bold}; 13 | --font-extrabold: #{$font-extrabold}; 14 | --font-black: #{$font-black}; 15 | --btn-radius: #{$btn-radius}; 16 | --card-radius: #{$card-radius}; 17 | --bullet-size: #{$bullet-size}; 18 | } 19 | 20 | body { 21 | --background: #{$background}; 22 | --background-negative: #{$background-negative}; 23 | --background-primary: #{$background-primary}; 24 | // --background-secondary: #{$background-secondary}; 25 | // --background-tertiary: #{$background-tertiary}; 26 | --foreground: #{$foreground}; 27 | --foreground-negative: #{$foreground-negative}; 28 | --foreground-primary: #{$foreground-primary}; 29 | // --foreground-secondary: #{$foreground-secondary}; 30 | // --foreground-tertiary: #{$foreground-tertiary}; 31 | --border: #{$border}; 32 | } 33 | 34 | @import 'cssvars'; 35 | -------------------------------------------------------------------------------- /web/client/css/_variables/_main-cssvars.scss: -------------------------------------------------------------------------------- 1 | @import 'shared'; 2 | 3 | body { 4 | --font-primary: #{$font-primary}; 5 | --font-secondary: #{$font-secondary}; 6 | --font-size: #{$font-size}; 7 | --line-height: #{$line-height}; 8 | --font-extralight: #{$font-extralight}; 9 | --font-light: #{$font-light}; 10 | --font-regular: #{$font-regular}; 11 | --font-semibold: #{$font-semibold}; 12 | --font-bold: #{$font-bold}; 13 | --font-extrabold: #{$font-extrabold}; 14 | --font-black: #{$font-black}; 15 | --btn-radius: #{$btn-radius}; 16 | --card-radius: #{$card-radius}; 17 | --bullet-size: #{$bullet-size}; 18 | } 19 | 20 | body { 21 | --background: #{$background}; 22 | --background-negative: #{$background-negative}; 23 | --background-primary: #{$background-primary}; 24 | // --background-secondary: #{$background-secondary}; 25 | // --background-tertiary: #{$background-tertiary}; 26 | --foreground: #{$foreground}; 27 | --foreground-negative: #{$foreground-negative}; 28 | --foreground-primary: #{$foreground-primary}; 29 | // --foreground-secondary: #{$foreground-secondary}; 30 | // --foreground-tertiary: #{$foreground-tertiary}; 31 | --border: #{$border}; 32 | } 33 | 34 | @import 'cssvars'; 35 | -------------------------------------------------------------------------------- /dist/cjs/src/src.directive.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var tslib_1 = require("tslib"); 4 | var directive_1 = tslib_1.__importDefault(require("../core/directive")); 5 | var factory_1 = require("../core/factory"); 6 | var SrcDirective = /** @class */ (function (_super) { 7 | tslib_1.__extends(SrcDirective, _super); 8 | function SrcDirective() { 9 | return _super !== null && _super.apply(this, arguments) || this; 10 | } 11 | Object.defineProperty(SrcDirective.prototype, "src", { 12 | get: function () { 13 | return this.src_; 14 | }, 15 | set: function (src) { 16 | if (this.src_ !== src) { 17 | this.src_ = src; 18 | var node = (0, factory_1.getContext)(this).node; 19 | src ? node.setAttribute('src', src) : node.removeAttribute('src'); 20 | } 21 | }, 22 | enumerable: false, 23 | configurable: true 24 | }); 25 | SrcDirective.meta = { 26 | selector: '[[src]]', 27 | inputs: ['src'], 28 | }; 29 | return SrcDirective; 30 | }(directive_1.default)); 31 | exports.default = SrcDirective; 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Luca Zampetti ", 3 | "name": "rxcomp", 4 | "description": "Reactive component library for JavaScript", 5 | "version": "1.0.0-beta.21", 6 | "browser": "dist/umd/rxcomp.js", 7 | "main": "dist/cjs/rxcomp.js", 8 | "types": "dist/cjs/rxcomp.d.ts", 9 | "es2015": "dist/esm/rxcomp.js", 10 | "files": [ 11 | "dist/", 12 | "!.DS_Store" 13 | ], 14 | "license": "MIT", 15 | "keywords": [ 16 | "rxcomp", 17 | "framework", 18 | "rxjs", 19 | "es6", 20 | "es2015" 21 | ], 22 | "repository": { 23 | "type": "git", 24 | "url": "git://github.com/actarian/rxcomp.git" 25 | }, 26 | "bugs": { 27 | "url": "https://github.com/actarian/rxcomp/issues" 28 | }, 29 | "homepage": "https://github.com/actarian/rxcomp", 30 | "scripts": { 31 | "start": "gulp", 32 | "build": "gulp build --target dist", 33 | "docs": "typedoc --options typedoc.json" 34 | }, 35 | "dependencies": { 36 | "rxjs": "^6.6.7", 37 | "tslib": "^2.3.1" 38 | }, 39 | "devDependencies": { 40 | "@types/node": "17.0.21", 41 | "gulpfile-config": "1.0.0-alpha.18", 42 | "typedoc": "0.19.0", 43 | "typescript": "4.6.2" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /dist/cjs/href/href.directive.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var tslib_1 = require("tslib"); 4 | var directive_1 = tslib_1.__importDefault(require("../core/directive")); 5 | var factory_1 = require("../core/factory"); 6 | var HrefDirective = /** @class */ (function (_super) { 7 | tslib_1.__extends(HrefDirective, _super); 8 | function HrefDirective() { 9 | return _super !== null && _super.apply(this, arguments) || this; 10 | } 11 | Object.defineProperty(HrefDirective.prototype, "href", { 12 | get: function () { 13 | return this.href_; 14 | }, 15 | set: function (href) { 16 | if (this.href_ !== href) { 17 | this.href_ = href; 18 | var node = (0, factory_1.getContext)(this).node; 19 | href ? node.setAttribute('href', href) : node.removeAttribute('href'); 20 | } 21 | }, 22 | enumerable: false, 23 | configurable: true 24 | }); 25 | HrefDirective.meta = { 26 | selector: '[[href]]', 27 | inputs: ['href'], 28 | }; 29 | return HrefDirective; 30 | }(directive_1.default)); 31 | exports.default = HrefDirective; 32 | -------------------------------------------------------------------------------- /src/_scss/_variables/_cssvars.scss: -------------------------------------------------------------------------------- 1 | $background: var(--background); 2 | $background-negative: var(--background-negative); 3 | $background-primary: var(--background-primary); 4 | // $background-secondary: var(--background-secondary); 5 | // $background-tertiary: var(--background-tertiary); 6 | $foreground: var(--foreground); 7 | $foreground-negative: var(--foreground-negative); 8 | $foreground-primary: var(--foreground-primary); 9 | // $foreground-secondary: var(--foreground-secondary); 10 | // $foreground-tertiary: var(--foreground-tertiary); 11 | $border: var(--border); 12 | 13 | $font-primary: var(--font-primary); 14 | $font-secondary: var(--font-secondary); 15 | $font-size: var(--font-size); 16 | $font-size-xs: var(--font-size-xs); 17 | $line-height: var(--line-height); 18 | $font-weight: var(--font-weight); 19 | $font-extralight: var(--font-extralight); 20 | $font-light: var(--font-light); 21 | $font-regular: var(--font-regular); 22 | $font-medium: var(--font-medium); 23 | $font-semibold: var(--font-semibold); 24 | $font-bold: var(--font-bold); 25 | $font-extrabold: var(--font-extrabold); 26 | $font-black: var(--font-black); 27 | $btn-radius: var(--btn-radius); 28 | $card-radius: var(--card-radius); 29 | $bullet-size: var(--bullet-size); 30 | -------------------------------------------------------------------------------- /src/for/for.item.ts: -------------------------------------------------------------------------------- 1 | import Context from '../core/context'; 2 | import Factory from '../core/factory'; 3 | 4 | export default class ForItem extends Context { 5 | index: number; 6 | count: number; 7 | [key: string]: any; 8 | // !!! todo: payload options { key, $key, value, $value, index, count } 9 | constructor(key: string, $key: number | string, value: string, $value: any, index: number, count: number, parentInstance: Factory) { 10 | // console.log('ForItem', arguments); 11 | super(parentInstance); 12 | /* 13 | super(parentInstance, { 14 | [key]: { 15 | get: function() { 16 | return this.$key; 17 | }, 18 | set: function(key) { 19 | this.$key = key; 20 | } 21 | }, 22 | [value]: { 23 | get: function() { 24 | return this.$value; 25 | }, 26 | set: function(value) { 27 | this.$value = value; 28 | } 29 | } 30 | }); 31 | */ 32 | this[key] = $key; 33 | this[value] = $value; 34 | this.index = index; 35 | this.count = count; 36 | } 37 | get first(): boolean { return this.index === 0; } 38 | get last(): boolean { return this.index === this.count - 1; } 39 | get even(): boolean { return this.index % 2 === 0; } 40 | get odd(): boolean { return !this.even; } 41 | } 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dist 2 | # dist/ 3 | 4 | reports 5 | 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # Optional npm cache directory 48 | .npm 49 | 50 | # Optional eslint cache 51 | .eslintcache 52 | 53 | # Optional REPL history 54 | .node_repl_history 55 | 56 | # Output of 'npm pack' 57 | *.tgz 58 | 59 | # Yarn Integrity file 60 | .yarn-integrity 61 | 62 | # dotenv environment variables file 63 | .env 64 | 65 | # next.js build output 66 | .next 67 | -------------------------------------------------------------------------------- /web/client/css/_variables/_cssvars.scss: -------------------------------------------------------------------------------- 1 | $background: var(--background); 2 | $background-negative: var(--background-negative); 3 | $background-primary: var(--background-primary); 4 | // $background-secondary: var(--background-secondary); 5 | // $background-tertiary: var(--background-tertiary); 6 | $foreground: var(--foreground); 7 | $foreground-negative: var(--foreground-negative); 8 | $foreground-primary: var(--foreground-primary); 9 | // $foreground-secondary: var(--foreground-secondary); 10 | // $foreground-tertiary: var(--foreground-tertiary); 11 | $border: var(--border); 12 | 13 | $font-primary: var(--font-primary); 14 | $font-secondary: var(--font-secondary); 15 | $font-size: var(--font-size); 16 | $font-size-xs: var(--font-size-xs); 17 | $line-height: var(--line-height); 18 | $font-weight: var(--font-weight); 19 | $font-extralight: var(--font-extralight); 20 | $font-light: var(--font-light); 21 | $font-regular: var(--font-regular); 22 | $font-medium: var(--font-medium); 23 | $font-semibold: var(--font-semibold); 24 | $font-bold: var(--font-bold); 25 | $font-extrabold: var(--font-extrabold); 26 | $font-black: var(--font-black); 27 | $btn-radius: var(--btn-radius); 28 | $card-radius: var(--card-radius); 29 | $bullet-size: var(--bullet-size); 30 | -------------------------------------------------------------------------------- /src/platform/common/location/location.ts: -------------------------------------------------------------------------------- 1 | export interface ILocationInit { 2 | href: string; 3 | protocol: string; 4 | host: string; 5 | hostname: string; 6 | port: string; 7 | pathname: string; 8 | search: string; 9 | hash: string; 10 | } 11 | 12 | export function getLocationComponents(href: string): ILocationInit { 13 | let protocol = ''; 14 | let host = ''; 15 | let hostname = ''; 16 | let port = ''; 17 | let pathname = ''; 18 | let search = ''; 19 | let hash = ''; 20 | const regExp: RegExp = /^((http\:|https\:)?\/\/)?((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])|(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])|locahost)?(\:([^\/]+))?(\.?\/[^\?]+)?(\?[^\#]+)?(\#.+)?$/g; 21 | const matches = []; 22 | let match; 23 | while ((match = regExp.exec(href)) !== null) { 24 | matches.push(match); 25 | } 26 | for (let match of matches) { 27 | protocol = match[2] || ''; 28 | host = hostname = match[3] || ''; 29 | port = match[11] || ''; 30 | pathname = match[12] || ''; 31 | search = match[13] || ''; 32 | hash = match[14] || ''; 33 | } 34 | return { href, protocol, host, hostname, port, pathname, search, hash }; 35 | } 36 | -------------------------------------------------------------------------------- /dist/esm/class/class.directive.js: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { getContext } from '../core/factory'; 3 | export default class ClassDirective extends Directive { 4 | constructor() { 5 | super(...arguments); 6 | this.class = ''; 7 | this.keys = []; 8 | } 9 | onInit() { 10 | const { node } = getContext(this); 11 | Array.prototype.slice.call(node.classList).forEach((value) => { 12 | this.keys.push(value); 13 | }); 14 | } 15 | onChanges() { 16 | const { node } = getContext(this); 17 | let keys = []; 18 | const object = this.class; 19 | if (typeof object === 'object') { 20 | for (let key in object) { 21 | if (object[key]) { 22 | keys.push(key); 23 | } 24 | } 25 | } 26 | else if (typeof object === 'string') { 27 | keys = object.split(/\s+/); 28 | } 29 | keys = keys.concat(this.keys); 30 | // console.log(keys); 31 | node.setAttribute('class', keys.join(' ')); 32 | // console.log('ClassDirective.onChanges', keys); 33 | } 34 | } 35 | ClassDirective.meta = { 36 | selector: `[[class]]`, 37 | inputs: ['class'] 38 | }; 39 | -------------------------------------------------------------------------------- /dist/esm/for/for.item.js: -------------------------------------------------------------------------------- 1 | import Context from '../core/context'; 2 | export default class ForItem extends Context { 3 | // !!! todo: payload options { key, $key, value, $value, index, count } 4 | constructor(key, $key, value, $value, index, count, parentInstance) { 5 | // console.log('ForItem', arguments); 6 | super(parentInstance); 7 | /* 8 | super(parentInstance, { 9 | [key]: { 10 | get: function() { 11 | return this.$key; 12 | }, 13 | set: function(key) { 14 | this.$key = key; 15 | } 16 | }, 17 | [value]: { 18 | get: function() { 19 | return this.$value; 20 | }, 21 | set: function(value) { 22 | this.$value = value; 23 | } 24 | } 25 | }); 26 | */ 27 | this[key] = $key; 28 | this[value] = $value; 29 | this.index = index; 30 | this.count = count; 31 | } 32 | get first() { return this.index === 0; } 33 | get last() { return this.index === this.count - 1; } 34 | get even() { return this.index % 2 === 0; } 35 | get odd() { return !this.even; } 36 | } 37 | -------------------------------------------------------------------------------- /dist/cjs/href/href-target.directive.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var tslib_1 = require("tslib"); 4 | var directive_1 = tslib_1.__importDefault(require("../core/directive")); 5 | var factory_1 = require("../core/factory"); 6 | var HrefTargetDirective = /** @class */ (function (_super) { 7 | tslib_1.__extends(HrefTargetDirective, _super); 8 | function HrefTargetDirective() { 9 | return _super !== null && _super.apply(this, arguments) || this; 10 | } 11 | Object.defineProperty(HrefTargetDirective.prototype, "target", { 12 | get: function () { 13 | return this.target_; 14 | }, 15 | set: function (target) { 16 | if (this.target_ !== target) { 17 | this.target_ = target; 18 | var node = (0, factory_1.getContext)(this).node; 19 | target ? node.setAttribute('target', target) : node.removeAttribute('target'); 20 | } 21 | }, 22 | enumerable: false, 23 | configurable: true 24 | }); 25 | HrefTargetDirective.meta = { 26 | selector: '[[target]]', 27 | inputs: ['target'], 28 | }; 29 | return HrefTargetDirective; 30 | }(directive_1.default)); 31 | exports.default = HrefTargetDirective; 32 | -------------------------------------------------------------------------------- /dist/cjs/error/error.d.ts: -------------------------------------------------------------------------------- 1 | import { Observable, ReplaySubject } from "rxjs"; 2 | import Factory from "../core/factory"; 3 | import Module from "../module/module"; 4 | export declare class ModuleError extends Error { 5 | } 6 | export declare class ExpressionError extends Error { 7 | module: Module; 8 | instance: Factory; 9 | expression: string; 10 | params: any[]; 11 | template: string; 12 | constructor(error: Error, module: Module, instance: Factory, expression: string, params: any[]); 13 | } 14 | export interface IErrorHandler { 15 | handle(error: Error): Observable; 16 | } 17 | export interface IErrorInterceptor { 18 | intercept(error: Error | void, next: IErrorHandler): Observable; 19 | } 20 | export declare class ErrorInterceptorHandler implements IErrorHandler { 21 | private next; 22 | private interceptor; 23 | constructor(next: IErrorHandler, interceptor: IErrorInterceptor); 24 | handle(error: Error | void): Observable; 25 | } 26 | export declare class DefaultErrorHandler implements IErrorHandler { 27 | handle(error: Error | void): Observable; 28 | } 29 | export declare const ErrorInterceptors: IErrorInterceptor[]; 30 | export declare const nextError$: ReplaySubject; 31 | export declare const errors$: Observable; 32 | -------------------------------------------------------------------------------- /dist/cjs/inner-html/inner-html.directive.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var tslib_1 = require("tslib"); 4 | var directive_1 = tslib_1.__importDefault(require("../core/directive")); 5 | var factory_1 = require("../core/factory"); 6 | var InnerHtmlDirective = /** @class */ (function (_super) { 7 | tslib_1.__extends(InnerHtmlDirective, _super); 8 | function InnerHtmlDirective() { 9 | return _super !== null && _super.apply(this, arguments) || this; 10 | } 11 | Object.defineProperty(InnerHtmlDirective.prototype, "innerHTML", { 12 | get: function () { 13 | return this.innerHTML_; 14 | }, 15 | set: function (innerHTML) { 16 | if (this.innerHTML_ !== innerHTML) { 17 | this.innerHTML_ = innerHTML; 18 | var node = (0, factory_1.getContext)(this).node; 19 | node.innerHTML = innerHTML == undefined ? '' : innerHTML; // !!! keep == loose equality 20 | } 21 | }, 22 | enumerable: false, 23 | configurable: true 24 | }); 25 | InnerHtmlDirective.meta = { 26 | selector: "[innerHTML]", 27 | inputs: ['innerHTML'], 28 | }; 29 | return InnerHtmlDirective; 30 | }(directive_1.default)); 31 | exports.default = InnerHtmlDirective; 32 | -------------------------------------------------------------------------------- /dist/esm/error/error.d.ts: -------------------------------------------------------------------------------- 1 | import { Observable, ReplaySubject } from "rxjs"; 2 | import Factory from "../core/factory"; 3 | import Module from "../module/module"; 4 | export declare class ModuleError extends Error { 5 | } 6 | export declare class ExpressionError extends Error { 7 | module: Module; 8 | instance: Factory; 9 | expression: string; 10 | params: any[]; 11 | template: string; 12 | constructor(error: Error, module: Module, instance: Factory, expression: string, params: any[]); 13 | } 14 | export interface IErrorHandler { 15 | handle(error: Error): Observable; 16 | } 17 | export interface IErrorInterceptor { 18 | intercept(error: Error | void, next: IErrorHandler): Observable; 19 | } 20 | export declare class ErrorInterceptorHandler implements IErrorHandler { 21 | private next; 22 | private interceptor; 23 | constructor(next: IErrorHandler, interceptor: IErrorInterceptor); 24 | handle(error: Error | void): Observable; 25 | } 26 | export declare class DefaultErrorHandler implements IErrorHandler { 27 | handle(error: Error | void): Observable; 28 | } 29 | export declare const ErrorInterceptors: IErrorInterceptor[]; 30 | export declare const nextError$: ReplaySubject; 31 | export declare const errors$: Observable; 32 | -------------------------------------------------------------------------------- /web/client/test.scope.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | {{pippo | json}} 6 |
7 |
    8 |
  • 9 |
    10 |
  • 11 |
  • 12 |
    13 |
    {{currentLabel}}
    14 |
    15 |
  • 16 |
17 |
18 |
19 |
20 | 21 |
22 |
23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /dist/cjs/json/json.component.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var tslib_1 = require("tslib"); 4 | var component_1 = tslib_1.__importDefault(require("../core/component")); 5 | var JsonComponent = /** @class */ (function (_super) { 6 | tslib_1.__extends(JsonComponent, _super); 7 | function JsonComponent() { 8 | var _this = _super !== null && _super.apply(this, arguments) || this; 9 | _this.active = false; 10 | return _this; 11 | } 12 | JsonComponent.prototype.onToggle = function () { 13 | this.active = !this.active; 14 | this.pushChanges(); 15 | }; 16 | JsonComponent.meta = { 17 | selector: 'json-component', 18 | inputs: ['item'], 19 | template: /* html */ "\n\t\t
\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\t+ json \n\t\t\t\t\t- json \n\t\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\t\t\t
    \n\t\t\t\t
  • \n\t\t\t\t\t\n\t\t\t\t
  • \n\t\t\t
\n\t\t
", 20 | }; 21 | return JsonComponent; 22 | }(component_1.default)); 23 | exports.default = JsonComponent; 24 | -------------------------------------------------------------------------------- /src/style/style.directive.ts: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { getContext } from '../core/factory'; 3 | import { IFactoryMeta } from '../core/types'; 4 | 5 | export default class StyleDirective extends Directive { 6 | style?: { [key: string]: string } | null; 7 | previousStyle?: { [key: string]: string } | null; 8 | onChanges() { 9 | const { node } = getContext(this); 10 | const style = this.style; 11 | const previousStyle = this.previousStyle; 12 | if (previousStyle) { 13 | for (let key in previousStyle) { 14 | if (!style || !style[key]) { 15 | const splitted: string[] = key.split('.'); 16 | const propertyName = splitted.shift(); 17 | node.style.removeProperty(propertyName!); 18 | } 19 | } 20 | } 21 | if (style) { 22 | for (let key in style) { 23 | if (!previousStyle || previousStyle[key] !== style[key]) { 24 | const splitted: string[] = key.split('.'); 25 | const propertyName = splitted.shift(); 26 | const value = style[key] + (splitted.length ? splitted[0] : ''); 27 | // console.log(propertyName, value, style, key, style[key]); 28 | node.style.setProperty(propertyName!, value); 29 | } 30 | } 31 | } 32 | this.previousStyle = style; 33 | // console.log('StyleDirective.onChanges', style); 34 | } 35 | static meta: IFactoryMeta = { 36 | selector: `[[style]]`, 37 | inputs: ['style'] 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /dist/rxcomp-dark.min.css: -------------------------------------------------------------------------------- 1 | .rxc-block{word-wrap:break-word;background:#333;border-left:3px solid #003adc;color:#8f929b;display:flex;flex-direction:column;font-family:monospace;font-size:13px;justify-content:flex-start;line-height:1.2;margin:10px 0 0;overflow:auto;padding:0;page-break-inside:avoid;-webkit-user-select:none;-ms-user-select:none;user-select:none;white-space:pre}.rxc-head{align-items:center;display:flex;justify-content:space-between}.rxc-head__remove,.rxc-head__title{flex:1 1 auto;padding:5px}.rxc-head__title{align-items:center;cursor:pointer;display:flex;flex:1 1 calc(100% - 20px);justify-content:flex-start;overflow:hidden;text-overflow:ellipsis}.rxc-head__remove{cursor:pointer;flex:1 1 20px;margin-left:5px}.rxc-list{display:flex;flex-direction:column;list-style:none;margin:0;padding:0}.rxc-list__item{align-items:flex-start;border-bottom:1px solid #222;display:flex;justify-content:space-between;padding-bottom:2px}.rxc-list__item:last-child{border-bottom:none}.rxc-list__name,.rxc-list__remove,.rxc-list__title,.rxc-list__value{flex:1 1 auto;padding:5px}.rxc-list__name,.rxc-list__title,.rxc-list__value{overflow:hidden;text-overflow:ellipsis}.rxc-list__title{flex:1 1 calc(100% - 20px);font-family:sans-serif;font-size:16px;font-weight:500}.rxc-list__name{flex:1 1 30%}.rxc-list__value{flex:1 1 calc(70% - 20px);margin-left:5px}.rxc-list__remove{cursor:pointer;flex:1 1 20px;margin-left:5px} 2 | /*# sourceMappingURL=rxcomp-dark.min.css.map */ -------------------------------------------------------------------------------- /dist/rxcomp-light.min.css: -------------------------------------------------------------------------------- 1 | .rxc-block{word-wrap:break-word;background:#f3f3f3;border-left:3px solid #003adc;color:#8f929b;display:flex;flex-direction:column;font-family:monospace;font-size:13px;justify-content:flex-start;line-height:1.2;margin:10px 0 0;overflow:auto;padding:0;page-break-inside:avoid;-webkit-user-select:none;-ms-user-select:none;user-select:none;white-space:pre}.rxc-head{align-items:center;display:flex;justify-content:space-between}.rxc-head__remove,.rxc-head__title{flex:1 1 auto;padding:5px}.rxc-head__title{align-items:center;cursor:pointer;display:flex;flex:1 1 calc(100% - 20px);justify-content:flex-start;overflow:hidden;text-overflow:ellipsis}.rxc-head__remove{cursor:pointer;flex:1 1 20px;margin-left:5px}.rxc-list{display:flex;flex-direction:column;list-style:none;margin:0;padding:0}.rxc-list__item{align-items:flex-start;border-bottom:1px solid #222;display:flex;justify-content:space-between;padding-bottom:2px}.rxc-list__item:last-child{border-bottom:none}.rxc-list__name,.rxc-list__remove,.rxc-list__title,.rxc-list__value{flex:1 1 auto;padding:5px}.rxc-list__name,.rxc-list__title,.rxc-list__value{overflow:hidden;text-overflow:ellipsis}.rxc-list__title{flex:1 1 calc(100% - 20px);font-family:sans-serif;font-size:16px;font-weight:500}.rxc-list__name{flex:1 1 30%}.rxc-list__value{flex:1 1 calc(70% - 20px);margin-left:5px}.rxc-list__remove{cursor:pointer;flex:1 1 20px;margin-left:5px} 2 | /*# sourceMappingURL=rxcomp-light.min.css.map */ -------------------------------------------------------------------------------- /docs/css/rxcomp-dark.min.css: -------------------------------------------------------------------------------- 1 | .rxc-block{word-wrap:break-word;background:#333;border-left:3px solid #003adc;color:#8f929b;display:flex;flex-direction:column;font-family:monospace;font-size:13px;justify-content:flex-start;line-height:1.2;margin:10px 0 0;overflow:auto;padding:0;page-break-inside:avoid;-webkit-user-select:none;-ms-user-select:none;user-select:none;white-space:pre}.rxc-head{align-items:center;display:flex;justify-content:space-between}.rxc-head__remove,.rxc-head__title{flex:1 1 auto;padding:5px}.rxc-head__title{align-items:center;cursor:pointer;display:flex;flex:1 1 calc(100% - 20px);justify-content:flex-start;overflow:hidden;text-overflow:ellipsis}.rxc-head__remove{cursor:pointer;flex:1 1 20px;margin-left:5px}.rxc-list{display:flex;flex-direction:column;list-style:none;margin:0;padding:0}.rxc-list__item{align-items:flex-start;border-bottom:1px solid #222;display:flex;justify-content:space-between;padding-bottom:2px}.rxc-list__item:last-child{border-bottom:none}.rxc-list__name,.rxc-list__remove,.rxc-list__title,.rxc-list__value{flex:1 1 auto;padding:5px}.rxc-list__name,.rxc-list__title,.rxc-list__value{overflow:hidden;text-overflow:ellipsis}.rxc-list__title{flex:1 1 calc(100% - 20px);font-family:sans-serif;font-size:16px;font-weight:500}.rxc-list__name{flex:1 1 30%}.rxc-list__value{flex:1 1 calc(70% - 20px);margin-left:5px}.rxc-list__remove{cursor:pointer;flex:1 1 20px;margin-left:5px} 2 | /*# sourceMappingURL=rxcomp-dark.min.css.map */ -------------------------------------------------------------------------------- /docs/css/rxcomp-light.min.css: -------------------------------------------------------------------------------- 1 | .rxc-block{word-wrap:break-word;background:#f3f3f3;border-left:3px solid #003adc;color:#8f929b;display:flex;flex-direction:column;font-family:monospace;font-size:13px;justify-content:flex-start;line-height:1.2;margin:10px 0 0;overflow:auto;padding:0;page-break-inside:avoid;-webkit-user-select:none;-ms-user-select:none;user-select:none;white-space:pre}.rxc-head{align-items:center;display:flex;justify-content:space-between}.rxc-head__remove,.rxc-head__title{flex:1 1 auto;padding:5px}.rxc-head__title{align-items:center;cursor:pointer;display:flex;flex:1 1 calc(100% - 20px);justify-content:flex-start;overflow:hidden;text-overflow:ellipsis}.rxc-head__remove{cursor:pointer;flex:1 1 20px;margin-left:5px}.rxc-list{display:flex;flex-direction:column;list-style:none;margin:0;padding:0}.rxc-list__item{align-items:flex-start;border-bottom:1px solid #222;display:flex;justify-content:space-between;padding-bottom:2px}.rxc-list__item:last-child{border-bottom:none}.rxc-list__name,.rxc-list__remove,.rxc-list__title,.rxc-list__value{flex:1 1 auto;padding:5px}.rxc-list__name,.rxc-list__title,.rxc-list__value{overflow:hidden;text-overflow:ellipsis}.rxc-list__title{flex:1 1 calc(100% - 20px);font-family:sans-serif;font-size:16px;font-weight:500}.rxc-list__name{flex:1 1 30%}.rxc-list__value{flex:1 1 calc(70% - 20px);margin-left:5px}.rxc-list__remove{cursor:pointer;flex:1 1 20px;margin-left:5px} 2 | /*# sourceMappingURL=rxcomp-light.min.css.map */ -------------------------------------------------------------------------------- /src/event/event.directive.ts: -------------------------------------------------------------------------------- 1 | import { fromEvent, Observable } from 'rxjs'; 2 | import { shareReplay, takeUntil } from 'rxjs/operators'; 3 | import Directive from '../core/directive'; 4 | import { getContext } from '../core/factory'; 5 | import { IFactoryMeta } from '../core/types'; 6 | 7 | const EVENTS = ['mousedown', 'mouseup', 'mousemove', 'click', 'dblclick', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave', 'contextmenu', 'touchstart', 'touchmove', 'touchend', 'keydown', 'keyup', 'input', 'change', 'loaded']; 8 | 9 | export default class EventDirective extends Directive { 10 | event: string = ''; 11 | onInit() { 12 | const { module, node, parentInstance, selector } = getContext(this); 13 | const event = this.event = selector.replace(/\[|\]|\(|\)/g, ''); 14 | const event$: Observable = fromEvent(node, event).pipe(shareReplay(1)); 15 | const expression = node.getAttribute(`(${event})`); 16 | if (expression) { 17 | const outputFunction = module.makeFunction(expression, ['$event']); 18 | event$.pipe( 19 | takeUntil(this.unsubscribe$) 20 | ).subscribe(event => { 21 | module.resolve(outputFunction, parentInstance, event); 22 | }); 23 | } else { 24 | parentInstance[`${event}$`] = event$; 25 | } 26 | // console.log('EventDirective.onInit', 'selector', selector, 'event', event); 27 | } 28 | static meta: IFactoryMeta = { 29 | selector: `[(${EVENTS.join(')],[(')})]`, 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /web/client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 | 7 | 8 |
9 |
    10 |
  • 11 |
    12 | 16 | 19 |
    20 |
  • 21 |
22 |
23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /dist/esm/style/style.directive.js: -------------------------------------------------------------------------------- 1 | import Directive from '../core/directive'; 2 | import { getContext } from '../core/factory'; 3 | export default class StyleDirective extends Directive { 4 | onChanges() { 5 | const { node } = getContext(this); 6 | const style = this.style; 7 | const previousStyle = this.previousStyle; 8 | if (previousStyle) { 9 | for (let key in previousStyle) { 10 | if (!style || !style[key]) { 11 | const splitted = key.split('.'); 12 | const propertyName = splitted.shift(); 13 | node.style.removeProperty(propertyName); 14 | } 15 | } 16 | } 17 | if (style) { 18 | for (let key in style) { 19 | if (!previousStyle || previousStyle[key] !== style[key]) { 20 | const splitted = key.split('.'); 21 | const propertyName = splitted.shift(); 22 | const value = style[key] + (splitted.length ? splitted[0] : ''); 23 | // console.log(propertyName, value, style, key, style[key]); 24 | node.style.setProperty(propertyName, value); 25 | } 26 | } 27 | } 28 | this.previousStyle = style; 29 | // console.log('StyleDirective.onChanges', style); 30 | } 31 | } 32 | StyleDirective.meta = { 33 | selector: `[[style]]`, 34 | inputs: ['style'] 35 | }; 36 | -------------------------------------------------------------------------------- /dist/cjs/platform/platform.d.ts: -------------------------------------------------------------------------------- 1 | import { FactoryList, IElement, IModuleParsedImportedMeta, IModuleParsedMeta, MatchFunction, PipeMap, SelectorFunction } from '../core/types'; 2 | import Module from '../module/module'; 3 | export default class Platform { 4 | /** 5 | * @param moduleFactory 6 | * @description This method returns an uncompiled module 7 | */ 8 | static bootstrap(moduleFactory?: typeof Module): Module; 9 | protected static querySelector(selector: string): IElement | null; 10 | protected static resolveMeta(moduleFactory: typeof Module): IModuleParsedMeta; 11 | protected static resolveImportedMeta(moduleFactory: typeof Module): IModuleParsedImportedMeta; 12 | protected static resolvePipes(meta: IModuleParsedImportedMeta, exported?: boolean): PipeMap; 13 | protected static resolveFactories(meta: IModuleParsedImportedMeta, exported?: boolean): FactoryList; 14 | protected static sortFactories(factories: FactoryList): void; 15 | protected static getExpressions(selector: string): MatchFunction[]; 16 | protected static unwrapSelectors(factories: FactoryList): SelectorFunction[]; 17 | } 18 | export declare const PLATFORM_BROWSER: boolean; 19 | export declare const PLATFORM_JS_DOM: boolean; 20 | export declare const PLATFORM_NODE: boolean; 21 | export declare const PLATFORM_WEB_WORKER: boolean; 22 | export declare const isPlatformServer: boolean; 23 | export declare const isPlatformBrowser: boolean; 24 | export declare const isPlatformWorker: boolean; 25 | -------------------------------------------------------------------------------- /dist/esm/event/event.directive.js: -------------------------------------------------------------------------------- 1 | import { fromEvent } from 'rxjs'; 2 | import { shareReplay, takeUntil } from 'rxjs/operators'; 3 | import Directive from '../core/directive'; 4 | import { getContext } from '../core/factory'; 5 | const EVENTS = ['mousedown', 'mouseup', 'mousemove', 'click', 'dblclick', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave', 'contextmenu', 'touchstart', 'touchmove', 'touchend', 'keydown', 'keyup', 'input', 'change', 'loaded']; 6 | export default class EventDirective extends Directive { 7 | constructor() { 8 | super(...arguments); 9 | this.event = ''; 10 | } 11 | onInit() { 12 | const { module, node, parentInstance, selector } = getContext(this); 13 | const event = this.event = selector.replace(/\[|\]|\(|\)/g, ''); 14 | const event$ = fromEvent(node, event).pipe(shareReplay(1)); 15 | const expression = node.getAttribute(`(${event})`); 16 | if (expression) { 17 | const outputFunction = module.makeFunction(expression, ['$event']); 18 | event$.pipe(takeUntil(this.unsubscribe$)).subscribe(event => { 19 | module.resolve(outputFunction, parentInstance, event); 20 | }); 21 | } 22 | else { 23 | parentInstance[`${event}$`] = event$; 24 | } 25 | // console.log('EventDirective.onInit', 'selector', selector, 'event', event); 26 | } 27 | } 28 | EventDirective.meta = { 29 | selector: `[(${EVENTS.join(')],[(')})]`, 30 | }; 31 | -------------------------------------------------------------------------------- /dist/esm/platform/platform.d.ts: -------------------------------------------------------------------------------- 1 | import { FactoryList, IElement, IModuleParsedImportedMeta, IModuleParsedMeta, MatchFunction, PipeMap, SelectorFunction } from '../core/types'; 2 | import Module from '../module/module'; 3 | export default class Platform { 4 | /** 5 | * @param moduleFactory 6 | * @description This method returns an uncompiled module 7 | */ 8 | static bootstrap(moduleFactory?: typeof Module): Module; 9 | protected static querySelector(selector: string): IElement | null; 10 | protected static resolveMeta(moduleFactory: typeof Module): IModuleParsedMeta; 11 | protected static resolveImportedMeta(moduleFactory: typeof Module): IModuleParsedImportedMeta; 12 | protected static resolvePipes(meta: IModuleParsedImportedMeta, exported?: boolean): PipeMap; 13 | protected static resolveFactories(meta: IModuleParsedImportedMeta, exported?: boolean): FactoryList; 14 | protected static sortFactories(factories: FactoryList): void; 15 | protected static getExpressions(selector: string): MatchFunction[]; 16 | protected static unwrapSelectors(factories: FactoryList): SelectorFunction[]; 17 | } 18 | export declare const PLATFORM_BROWSER: boolean; 19 | export declare const PLATFORM_JS_DOM: boolean; 20 | export declare const PLATFORM_NODE: boolean; 21 | export declare const PLATFORM_WEB_WORKER: boolean; 22 | export declare const isPlatformServer: boolean; 23 | export declare const isPlatformBrowser: boolean; 24 | export declare const isPlatformWorker: boolean; 25 | -------------------------------------------------------------------------------- /dist/esm/core.module.js: -------------------------------------------------------------------------------- 1 | import { takeUntil } from 'rxjs/operators'; 2 | import ClassDirective from './class/class.directive'; 3 | import { errors$ } from './error/error'; 4 | import EventDirective from './event/event.directive'; 5 | import ForStructure from './for/for.structure'; 6 | import HrefTargetDirective from './href/href-target.directive'; 7 | import HrefDirective from './href/href.directive'; 8 | import IfStructure from './if/if.structure'; 9 | import InnerHtmlDirective from './inner-html/inner-html.directive'; 10 | import JsonComponent from './json/json.component'; 11 | import JsonPipe from './json/json.pipe'; 12 | import Module from './module/module'; 13 | import SrcDirective from './src/src.directive'; 14 | import StyleDirective from './style/style.directive'; 15 | const factories = [ 16 | ClassDirective, 17 | EventDirective, 18 | ForStructure, 19 | HrefDirective, 20 | HrefTargetDirective, 21 | IfStructure, 22 | InnerHtmlDirective, 23 | JsonComponent, 24 | SrcDirective, 25 | StyleDirective, 26 | ]; 27 | const pipes = [ 28 | JsonPipe, 29 | ]; 30 | export default class CoreModule extends Module { 31 | constructor() { 32 | super(); 33 | // console.log('CoreModule'); 34 | errors$.pipe(takeUntil(this.unsubscribe$)).subscribe(); 35 | } 36 | } 37 | CoreModule.meta = { 38 | declarations: [ 39 | ...factories, 40 | ...pipes, 41 | ], 42 | exports: [ 43 | ...factories, 44 | ...pipes, 45 | ] 46 | }; 47 | -------------------------------------------------------------------------------- /src/core.module.ts: -------------------------------------------------------------------------------- 1 | 2 | import { takeUntil } from 'rxjs/operators'; 3 | import ClassDirective from './class/class.directive'; 4 | import Factory from './core/factory'; 5 | import Pipe from './core/pipe'; 6 | import { errors$ } from './error/error'; 7 | import EventDirective from './event/event.directive'; 8 | import ForStructure from './for/for.structure'; 9 | import HrefTargetDirective from './href/href-target.directive'; 10 | import HrefDirective from './href/href.directive'; 11 | import IfStructure from './if/if.structure'; 12 | import InnerHtmlDirective from './inner-html/inner-html.directive'; 13 | import JsonComponent from './json/json.component'; 14 | import JsonPipe from './json/json.pipe'; 15 | import Module from './module/module'; 16 | import SrcDirective from './src/src.directive'; 17 | import StyleDirective from './style/style.directive'; 18 | 19 | const factories: typeof Factory[] = [ 20 | ClassDirective, 21 | EventDirective, 22 | ForStructure, 23 | HrefDirective, 24 | HrefTargetDirective, 25 | IfStructure, 26 | InnerHtmlDirective, 27 | JsonComponent, 28 | SrcDirective, 29 | StyleDirective, 30 | ]; 31 | const pipes: typeof Pipe[] = [ 32 | JsonPipe, 33 | ]; 34 | export default class CoreModule extends Module { 35 | constructor() { 36 | super(); 37 | // console.log('CoreModule'); 38 | errors$.pipe( 39 | takeUntil(this.unsubscribe$), 40 | ).subscribe(); 41 | } 42 | static meta = { 43 | declarations: [ 44 | ...factories, 45 | ...pipes, 46 | ], 47 | exports: [ 48 | ...factories, 49 | ...pipes, 50 | ] 51 | }; 52 | } 53 | -------------------------------------------------------------------------------- /src/_scss/_mixins/_aspect.scss: -------------------------------------------------------------------------------- 1 | @mixin aspect-grid($w: 4, $h: 3) { 2 | display: grid; 3 | 4 | &:before, 5 | &>img, 6 | &>svg, 7 | &>video, 8 | &>* { 9 | grid-area: 1 / 1 / 2 / 2; 10 | } 11 | 12 | &:before { 13 | content: ''; 14 | display: block; 15 | padding-top: calc(#{$h} / #{$w} * 100%); 16 | } 17 | 18 | /* 19 | &::before { 20 | content: url("data:image/svg+xml,%3Csvg viewBox='0 0 #{$w} #{$h}' xmlns='http://www.w3.org/2000/svg'%3E%3C/svg%3E"); 21 | } 22 | */ 23 | } 24 | 25 | @mixin as-aspect-clip() { 26 | position: relative; 27 | width: 100%; 28 | overflow: hidden; 29 | 30 | img, 31 | svg, 32 | video, 33 | canvas, 34 | ng-transclude { 35 | position: absolute; 36 | top: 0; 37 | left: 0; 38 | width: 100%; 39 | height: 100%; 40 | object-fit: cover; 41 | } 42 | } 43 | 44 | @mixin as-aspect-clip-size($w: 4, $h: 3) { 45 | padding-top: 100% / $w * $h; 46 | } 47 | 48 | @mixin aspect-clip($w: 4, $h: 3) { 49 | position: relative; 50 | width: 100%; 51 | padding-top: 100% / $w * $h; 52 | overflow: hidden; 53 | 54 | img, 55 | svg, 56 | video, 57 | canvas, 58 | ng-transclude { 59 | position: absolute; 60 | top: 0; 61 | left: 0; 62 | width: 100%; 63 | height: 100%; 64 | object-fit: cover; 65 | } 66 | } 67 | 68 | @mixin aspect-bottom($w: 4, $h: 3) { 69 | position: relative; 70 | width: 100%; 71 | padding-top: 100% / $w * $h; 72 | overflow: hidden; 73 | 74 | img, 75 | svg, 76 | video, 77 | canvas, 78 | ng-transclude { 79 | position: absolute; 80 | bottom: 10px; 81 | left: 0; 82 | width: 100%; 83 | height: auto; 84 | object-fit: cover; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /web/client/css/_mixins/_aspect.scss: -------------------------------------------------------------------------------- 1 | @mixin aspect-grid($w: 4, $h: 3) { 2 | display: grid; 3 | 4 | &:before, 5 | &>img, 6 | &>svg, 7 | &>video, 8 | &>* { 9 | grid-area: 1 / 1 / 2 / 2; 10 | } 11 | 12 | &:before { 13 | content: ''; 14 | display: block; 15 | padding-top: calc(#{$h} / #{$w} * 100%); 16 | } 17 | 18 | /* 19 | &::before { 20 | content: url("data:image/svg+xml,%3Csvg viewBox='0 0 #{$w} #{$h}' xmlns='http://www.w3.org/2000/svg'%3E%3C/svg%3E"); 21 | } 22 | */ 23 | } 24 | 25 | @mixin as-aspect-clip() { 26 | position: relative; 27 | width: 100%; 28 | overflow: hidden; 29 | 30 | img, 31 | svg, 32 | video, 33 | canvas, 34 | ng-transclude { 35 | position: absolute; 36 | top: 0; 37 | left: 0; 38 | width: 100%; 39 | height: 100%; 40 | object-fit: cover; 41 | } 42 | } 43 | 44 | @mixin as-aspect-clip-size($w: 4, $h: 3) { 45 | padding-top: 100% / $w * $h; 46 | } 47 | 48 | @mixin aspect-clip($w: 4, $h: 3) { 49 | position: relative; 50 | width: 100%; 51 | padding-top: 100% / $w * $h; 52 | overflow: hidden; 53 | 54 | img, 55 | svg, 56 | video, 57 | canvas, 58 | ng-transclude { 59 | position: absolute; 60 | top: 0; 61 | left: 0; 62 | width: 100%; 63 | height: 100%; 64 | object-fit: cover; 65 | } 66 | } 67 | 68 | @mixin aspect-bottom($w: 4, $h: 3) { 69 | position: relative; 70 | width: 100%; 71 | padding-top: 100% / $w * $h; 72 | overflow: hidden; 73 | 74 | img, 75 | svg, 76 | video, 77 | canvas, 78 | ng-transclude { 79 | position: absolute; 80 | bottom: 10px; 81 | left: 0; 82 | width: 100%; 83 | height: auto; 84 | object-fit: cover; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /dist/esm/error/error.js: -------------------------------------------------------------------------------- 1 | import { of, ReplaySubject } from "rxjs"; 2 | import { switchMap, tap } from "rxjs/operators"; 3 | import { getContext } from "../core/factory"; 4 | export class ModuleError extends Error { 5 | } 6 | export class ExpressionError extends Error { 7 | constructor(error, module, instance, expression, params) { 8 | const message = `ExpressionError in ${instance.constructor.name} "${expression}" 9 | ${error.message}`; 10 | super(message); 11 | this.name = error.name; 12 | // this.stack = error.stack; 13 | this.module = module; 14 | this.instance = instance; 15 | this.expression = expression; 16 | this.params = params; 17 | const { node } = getContext(instance); 18 | this.template = node.outerHTML; 19 | } 20 | } 21 | export class ErrorInterceptorHandler { 22 | constructor(next, interceptor) { 23 | this.next = next; 24 | this.interceptor = interceptor; 25 | } 26 | handle(error) { 27 | return this.interceptor.intercept(error, this.next); 28 | } 29 | } 30 | export class DefaultErrorHandler { 31 | handle(error) { 32 | return of(error); 33 | } 34 | } 35 | export const ErrorInterceptors = []; 36 | export const nextError$ = new ReplaySubject(1); 37 | export const errors$ = nextError$.pipe(switchMap((error) => { 38 | const chain = ErrorInterceptors.reduceRight((next, interceptor) => { 39 | return new ErrorInterceptorHandler(next, interceptor); 40 | }, new DefaultErrorHandler()); 41 | return chain.handle(error); 42 | }), tap((error) => { 43 | if (error) { 44 | console.error(error); 45 | } 46 | })); 47 | -------------------------------------------------------------------------------- /dist/esm/if/if.structure.js: -------------------------------------------------------------------------------- 1 | import { getContext } from '../core/factory'; 2 | import Structure from '../core/structure'; 3 | export default class IfStructure extends Structure { 4 | onInit() { 5 | const { node } = getContext(this); 6 | const ifbegin = this.ifbegin = document.createComment(`*if begin`); 7 | ifbegin.rxcompId = node.rxcompId; 8 | node.parentNode.replaceChild(ifbegin, node); 9 | const ifend = this.ifend = document.createComment(`*if end`); 10 | ifbegin.parentNode.insertBefore(ifend, ifbegin.nextSibling); 11 | const clonedNode = node.cloneNode(true); 12 | clonedNode.removeAttribute('*if'); 13 | this.clonedNode = clonedNode; 14 | this.element = clonedNode.cloneNode(true); 15 | } 16 | onChanges() { 17 | const { module } = getContext(this); 18 | const element = this.element; 19 | // console.log('IfStructure.onChanges.if', this.if); 20 | if (Boolean(this.if)) { // !!! keep == loose equality 21 | if (!element.parentNode) { 22 | const ifend = this.ifend; 23 | ifend.parentNode.insertBefore(element, ifend); 24 | module.compile(element); 25 | // console.log('IfStructure.onChanges.add', element); 26 | } 27 | } 28 | else { 29 | if (element.parentNode) { 30 | module.remove(element, this); 31 | element.parentNode.removeChild(element); 32 | this.element = this.clonedNode.cloneNode(true); 33 | // console.log('IfStructure.onChanges.remove', element); 34 | } 35 | } 36 | } 37 | } 38 | IfStructure.meta = { 39 | selector: '[*if]', 40 | inputs: ['if'], 41 | }; 42 | -------------------------------------------------------------------------------- /src/if/if.structure.ts: -------------------------------------------------------------------------------- 1 | import { getContext } from '../core/factory'; 2 | import Structure from '../core/structure'; 3 | import { IComment, IElement, IFactoryMeta } from '../core/types'; 4 | 5 | export default class IfStructure extends Structure { 6 | ifbegin?: IComment; 7 | ifend?: IComment; 8 | clonedNode?: IElement; 9 | element?: IElement; 10 | onInit() { 11 | const { node } = getContext(this); 12 | const ifbegin: IComment = this.ifbegin = document.createComment(`*if begin`); 13 | ifbegin.rxcompId = node.rxcompId; 14 | node.parentNode!.replaceChild(ifbegin, node); 15 | const ifend: IComment = this.ifend = document.createComment(`*if end`); 16 | ifbegin.parentNode!.insertBefore(ifend, ifbegin.nextSibling); 17 | const clonedNode = node.cloneNode(true) as IElement; 18 | clonedNode.removeAttribute('*if'); 19 | this.clonedNode = clonedNode; 20 | this.element = clonedNode.cloneNode(true) as IElement; 21 | } 22 | onChanges() { 23 | const { module } = getContext(this); 24 | const element: IElement = this.element!; 25 | // console.log('IfStructure.onChanges.if', this.if); 26 | if (Boolean(this.if)) { // !!! keep == loose equality 27 | if (!element.parentNode) { 28 | const ifend = this.ifend!; 29 | ifend.parentNode!.insertBefore(element, ifend); 30 | module.compile(element); 31 | // console.log('IfStructure.onChanges.add', element); 32 | } 33 | } else { 34 | if (element.parentNode) { 35 | module.remove(element, this); 36 | element.parentNode.removeChild(element); 37 | this.element = this.clonedNode!.cloneNode(true) as IElement; 38 | // console.log('IfStructure.onChanges.remove', element); 39 | } 40 | } 41 | } 42 | static meta: IFactoryMeta = { 43 | selector: '[*if]', 44 | inputs: ['if'], 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /.jsbeautifyrc: -------------------------------------------------------------------------------- 1 | { 2 | "brace_style": "collapse,preserve-inline", 3 | "break_chained_methods": false, 4 | "end_with_newline": true, 5 | "eol": "\n", 6 | "eval_code": false, 7 | "indent_char": "\t", 8 | "indent_size": 4, 9 | "indent_with_tabs": true, 10 | "keep_array_indentation": false, 11 | "keep_function_indentation": false, 12 | "max_preserve_newlines": 2, 13 | "preserve_newlines": true, 14 | "html": { 15 | "allowed_file_extensions": ["htm", "html", "xhtml", "shtml", "xml", "svg", "dust"], 16 | "indent_scripts": "keep", 17 | "max_preserve_newlines": 10, 18 | "unformatted": ["svg"], 19 | "wrap_line_length": 0 20 | }, 21 | "css": { 22 | "allowed_file_extensions": ["css", "scss", "sass", "less"], 23 | "newline_between_rules": true, 24 | "selector_separator": " ", 25 | "selector_separator_newline": true, 26 | "max_preserve_newlines": 10 27 | }, 28 | "js": { 29 | "allowed_file_extensions": ["ts", "js", "json", "jshintrc", "jsbeautifyrc"], 30 | "break_chained_methods": false, 31 | "comma_first": false, 32 | "e4x": false, 33 | "indent_empty_lines": true, 34 | "jslint_happy": false, 35 | "max_preserve_newlines": 0, 36 | "operator_position": "before-newline", 37 | "space_after_anon_function": false, 38 | "space_after_named_function": false, 39 | "space_before_conditional": true, 40 | "space_in_empty_paren": false, 41 | "space_in_paren": false, 42 | "templating": ["auto"], 43 | "unescape_strings": false, 44 | "unindent_chained_methods": false, 45 | "wrap_line_length": 0, 46 | "js": { 47 | "allowed_file_extensions": ["json", "jshintrc", "jsbeautifyrc"], 48 | "indent_char": " ", 49 | "indent_size": 2, 50 | "indent_with_tabs": false 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /dist/cjs/class/class.directive.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var tslib_1 = require("tslib"); 4 | var directive_1 = tslib_1.__importDefault(require("../core/directive")); 5 | var factory_1 = require("../core/factory"); 6 | var ClassDirective = /** @class */ (function (_super) { 7 | tslib_1.__extends(ClassDirective, _super); 8 | function ClassDirective() { 9 | var _this = _super !== null && _super.apply(this, arguments) || this; 10 | _this.class = ''; 11 | _this.keys = []; 12 | return _this; 13 | } 14 | ClassDirective.prototype.onInit = function () { 15 | var _this = this; 16 | var node = (0, factory_1.getContext)(this).node; 17 | Array.prototype.slice.call(node.classList).forEach(function (value) { 18 | _this.keys.push(value); 19 | }); 20 | }; 21 | ClassDirective.prototype.onChanges = function () { 22 | var node = (0, factory_1.getContext)(this).node; 23 | var keys = []; 24 | var object = this.class; 25 | if (typeof object === 'object') { 26 | for (var key in object) { 27 | if (object[key]) { 28 | keys.push(key); 29 | } 30 | } 31 | } 32 | else if (typeof object === 'string') { 33 | keys = object.split(/\s+/); 34 | } 35 | keys = keys.concat(this.keys); 36 | // console.log(keys); 37 | node.setAttribute('class', keys.join(' ')); 38 | // console.log('ClassDirective.onChanges', keys); 39 | }; 40 | ClassDirective.meta = { 41 | selector: "[[class]]", 42 | inputs: ['class'] 43 | }; 44 | return ClassDirective; 45 | }(directive_1.default)); 46 | exports.default = ClassDirective; 47 | -------------------------------------------------------------------------------- /web/client/js/todo-item/todo-item.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Factory } from '../../../../src/rxcomp'; 2 | import { accent, background, foreground } from '../colors/colors'; 3 | 4 | export default class TodoItemComponent extends Component { 5 | 6 | background: string | null = null; 7 | foreground: string | null = null; 8 | accent: string | null = null; 9 | 10 | // onInit() {} 11 | 12 | onChanges(changes: Factory | Window) { 13 | // console.log('onChanges', changes); 14 | this.background = background(this.item.id); 15 | this.foreground = foreground(this.item.id); 16 | this.accent = accent(this.item.id); 17 | } 18 | 19 | // onView() {} 20 | 21 | // onDestroy() {} 22 | 23 | onToggle($event: MouseEvent) { 24 | // console.log('onToggle', $event); 25 | this.toggle.next($event); 26 | } 27 | 28 | onRemove($event: MouseEvent) { 29 | // console.log('onRemove', $event); 30 | this.remove.next($event); 31 | } 32 | 33 | } 34 | 35 | TodoItemComponent.meta = { 36 | selector: '[todo-item-component]', 37 | inputs: ['item'], 38 | outputs: ['toggle', 'remove'], 39 | // template syntax example 40 | /* 41 | template: // html // ` 42 |
43 | 48 |
49 | 50 |
51 | `, 52 | */ 53 | }; 54 | -------------------------------------------------------------------------------- /web/client/js/test.for.ts: -------------------------------------------------------------------------------- 1 | import { interval } from 'rxjs'; 2 | import { take, takeUntil } from 'rxjs/operators'; 3 | import { Browser, Component, CoreModule, Module, Pipe } from '../../../src/rxcomp'; 4 | 5 | // component 6 | class RootComponent extends Component { 7 | flag = false; 8 | red = false; 9 | notred = true; 10 | nested = [ 11 | { items: [1, 2, 3, 4] }, 12 | { items: [1, 2, 3, 4] }, 13 | { items: [1, 2, 3, 4] } 14 | ]; 15 | items = [1, 2, 3, 4]; 16 | object = { a: 1, b: { c: 2 } }; 17 | 18 | onInit() { 19 | 20 | if (true) { 21 | interval(1000).pipe( 22 | take(1000), 23 | takeUntil(this.unsubscribe$) 24 | ).subscribe(() => { 25 | this.flag = !this.flag; 26 | this.pushChanges(); 27 | }); 28 | interval(500).pipe( 29 | take(500), 30 | takeUntil(this.unsubscribe$) 31 | ).subscribe(() => { 32 | this.red = !this.red; 33 | this.notred = !this.notred; 34 | this.pushChanges(); 35 | }); 36 | } 37 | 38 | /* 39 | interval(50).pipe( 40 | take(1000), 41 | takeUntil(this.unsubscribe$) 42 | ).subscribe(items => { 43 | this.items = new Array(1 + Math.floor(Math.random() * 9)).fill(0).map((x, i) => i + 1); 44 | this.pushChanges(); 45 | }); 46 | */ 47 | } 48 | 49 | getColor(index: number): string { 50 | return ['red', 'green', 'blue'][index % 3]; 51 | } 52 | } 53 | RootComponent.meta = { 54 | selector: '[root-component]', 55 | }; 56 | 57 | // pipe 58 | class ExamplePipe extends Pipe { 59 | static transform(value: number): number { 60 | return value * 2; 61 | } 62 | } 63 | ExamplePipe.meta = { 64 | name: 'example', 65 | }; 66 | 67 | class AppModule extends Module { } 68 | AppModule.meta = { 69 | imports: [ 70 | CoreModule 71 | ], 72 | declarations: [ 73 | ExamplePipe, 74 | ], 75 | bootstrap: RootComponent, 76 | }; 77 | 78 | Browser.bootstrap(AppModule); 79 | -------------------------------------------------------------------------------- /web/client/js/app.component.ts: -------------------------------------------------------------------------------- 1 | import { BehaviorSubject } from 'rxjs'; 2 | import { takeUntil } from 'rxjs/operators'; 3 | import { Component, getContext } from '../../../src/rxcomp'; 4 | import StoreService from './store/store.service'; 5 | import ITodoItem from './todo-item/todo-item'; 6 | 7 | export default class AppComponent extends Component { 8 | 9 | input?: HTMLInputElement; 10 | items?: any[]; 11 | store$?: BehaviorSubject 12 | 13 | onInit() { 14 | // context 15 | const context = getContext(this); 16 | // input 17 | this.input = context.node.querySelector('.control--text') as HTMLInputElement; 18 | // items 19 | this.items = []; 20 | // store service 21 | this.store$ = StoreService.get$(); 22 | this.store$.pipe( 23 | takeUntil(this.unsubscribe$) 24 | ).subscribe(items => { 25 | this.items = items; 26 | // onpush change detection strategy 27 | this.pushChanges(); 28 | }); 29 | } 30 | 31 | onInput($event: InputEvent) { 32 | // console.log('AppComponent.onInput', $event, this); 33 | this.pushChanges(); 34 | } 35 | 36 | onAddItem($event: MouseEvent) { 37 | if (this.input!.value) { 38 | StoreService.add$({ 39 | name: this.input!.value, 40 | }).subscribe((item: ITodoItem) => { 41 | // console.log('AppComponent.onAddItem', item); 42 | this.input!.value = ''; 43 | }); 44 | } 45 | } 46 | 47 | onToggleItem(item: ITodoItem) { 48 | StoreService.patch$({ 49 | id: item.id, 50 | done: !item.done, 51 | }).subscribe((item: ITodoItem) => { 52 | // console.log('AppComponent.onToggleItem', item); 53 | }); 54 | } 55 | 56 | onRemoveItem(item: ITodoItem) { 57 | StoreService.delete$(item).subscribe((item: ITodoItem) => { 58 | // console.log('AppComponent.onRemoveItem', item); 59 | }); 60 | } 61 | 62 | } 63 | 64 | AppComponent.meta = { 65 | selector: '[app-component]', 66 | }; 67 | -------------------------------------------------------------------------------- /dist/cjs/platform/common/location/location.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.getLocationComponents = void 0; 4 | var tslib_1 = require("tslib"); 5 | function getLocationComponents(href) { 6 | var e_1, _a; 7 | var protocol = ''; 8 | var host = ''; 9 | var hostname = ''; 10 | var port = ''; 11 | var pathname = ''; 12 | var search = ''; 13 | var hash = ''; 14 | var regExp = /^((http\:|https\:)?\/\/)?((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])|(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])|locahost)?(\:([^\/]+))?(\.?\/[^\?]+)?(\?[^\#]+)?(\#.+)?$/g; 15 | var matches = []; 16 | var match; 17 | while ((match = regExp.exec(href)) !== null) { 18 | matches.push(match); 19 | } 20 | try { 21 | for (var matches_1 = tslib_1.__values(matches), matches_1_1 = matches_1.next(); !matches_1_1.done; matches_1_1 = matches_1.next()) { 22 | var match_1 = matches_1_1.value; 23 | protocol = match_1[2] || ''; 24 | host = hostname = match_1[3] || ''; 25 | port = match_1[11] || ''; 26 | pathname = match_1[12] || ''; 27 | search = match_1[13] || ''; 28 | hash = match_1[14] || ''; 29 | } 30 | } 31 | catch (e_1_1) { e_1 = { error: e_1_1 }; } 32 | finally { 33 | try { 34 | if (matches_1_1 && !matches_1_1.done && (_a = matches_1.return)) _a.call(matches_1); 35 | } 36 | finally { if (e_1) throw e_1.error; } 37 | } 38 | return { href: href, protocol: protocol, host: host, hostname: hostname, port: port, pathname: pathname, search: search, hash: hash }; 39 | } 40 | exports.getLocationComponents = getLocationComponents; 41 | -------------------------------------------------------------------------------- /web/client/js/colors/colors.ts: -------------------------------------------------------------------------------- 1 | export const colors = [ 2 | { hex: '#ffffff', background: '#ffffff', foreground: '#003adc', accent: '#212121' }, 3 | { hex: '#212121', background: '#212121', foreground: '#ffffff', accent: '#003adc' }, 4 | { hex: '#ffffff', background: '#ffffff', foreground: '#212121', accent: '#003adc' }, 5 | { hex: '#003adc', background: '#003adc', foreground: '#ffffff', accent: '#212121' }, 6 | ]; 7 | 8 | export function hexToInt(hex: string): number { 9 | return parseInt(hex.replace(/^#/, ''), 16); 10 | } 11 | 12 | export function randomHex(): string { 13 | return colors[Math.floor(Math.random() * colors.length)].hex; 14 | } 15 | 16 | export function randomColor(): number { 17 | const hex = randomHex(); 18 | return hexToInt(hex); 19 | } 20 | 21 | export function color(index: number, alpha: number): string { 22 | return hexToRgb(colors[index % colors.length].hex, alpha); 23 | } 24 | 25 | export function background(index: number, alpha?: number): string { 26 | return hexToRgb(colors[index % colors.length].background, alpha); 27 | } 28 | 29 | export function foreground(index: number, alpha?: number): string { 30 | return hexToRgb(colors[index % colors.length].foreground, alpha); 31 | } 32 | 33 | export function accent(index: number, alpha?: number): string { 34 | return hexToRgb(colors[index % colors.length].accent, alpha); 35 | } 36 | 37 | let index: number = -1; 38 | 39 | export function nextHex() { 40 | index++; 41 | return colors[index % colors.length].hex; 42 | } 43 | 44 | export function nextColor(): number { 45 | const hex = nextHex(); 46 | return hexToInt(hex); 47 | } 48 | 49 | export function hexToRgb(hex: string, a?: number): string { 50 | const r = parseInt(hex.slice(1, 3), 16); 51 | const g = parseInt(hex.slice(3, 5), 16); 52 | const b = parseInt(hex.slice(5, 7), 16); 53 | if (a) { 54 | return `rgba(${r},${g},${b},${a})`; 55 | } else { 56 | return `rgb(${r},${g},${b})`; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /dist/cjs/style/style.directive.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var tslib_1 = require("tslib"); 4 | var directive_1 = tslib_1.__importDefault(require("../core/directive")); 5 | var factory_1 = require("../core/factory"); 6 | var StyleDirective = /** @class */ (function (_super) { 7 | tslib_1.__extends(StyleDirective, _super); 8 | function StyleDirective() { 9 | return _super !== null && _super.apply(this, arguments) || this; 10 | } 11 | StyleDirective.prototype.onChanges = function () { 12 | var node = (0, factory_1.getContext)(this).node; 13 | var style = this.style; 14 | var previousStyle = this.previousStyle; 15 | if (previousStyle) { 16 | for (var key in previousStyle) { 17 | if (!style || !style[key]) { 18 | var splitted = key.split('.'); 19 | var propertyName = splitted.shift(); 20 | node.style.removeProperty(propertyName); 21 | } 22 | } 23 | } 24 | if (style) { 25 | for (var key in style) { 26 | if (!previousStyle || previousStyle[key] !== style[key]) { 27 | var splitted = key.split('.'); 28 | var propertyName = splitted.shift(); 29 | var value = style[key] + (splitted.length ? splitted[0] : ''); 30 | // console.log(propertyName, value, style, key, style[key]); 31 | node.style.setProperty(propertyName, value); 32 | } 33 | } 34 | } 35 | this.previousStyle = style; 36 | // console.log('StyleDirective.onChanges', style); 37 | }; 38 | StyleDirective.meta = { 39 | selector: "[[style]]", 40 | inputs: ['style'] 41 | }; 42 | return StyleDirective; 43 | }(directive_1.default)); 44 | exports.default = StyleDirective; 45 | -------------------------------------------------------------------------------- /web/client/js/local-storage/local-storage.service.ts: -------------------------------------------------------------------------------- 1 | import { WINDOW } from "../../../../src/rxcomp"; 2 | 3 | export default class LocalStorageService { 4 | static supported = false; 5 | static delete(name: string) { 6 | if (this.isLocalStorageSupported()) { 7 | WINDOW.localStorage.removeItem(name); 8 | } 9 | } 10 | static exist(name: string): boolean { 11 | if (this.isLocalStorageSupported()) { 12 | return WINDOW.localStorage[name] !== undefined; 13 | } else { 14 | return false; 15 | } 16 | } 17 | static get(name: string): any { 18 | let value = null; 19 | if (this.isLocalStorageSupported() && WINDOW.localStorage[name] !== undefined) { 20 | try { 21 | value = JSON.parse(WINDOW.localStorage[name]); 22 | } catch (e) { 23 | console.log('LocalStorageService.get.error parsing', name, e); 24 | } 25 | } 26 | return value; 27 | } 28 | static set(name: string, value: any) { 29 | if (this.isLocalStorageSupported()) { 30 | try { 31 | const cache: any[] = []; 32 | const json = JSON.stringify(value, function (key, value) { 33 | if (typeof value === 'object' && value !== null) { 34 | if (cache.indexOf(value) !== -1) { 35 | // Circular reference found, discard key 36 | return; 37 | } 38 | cache.push(value); 39 | } 40 | return value; 41 | }); 42 | WINDOW.localStorage.setItem(name, json); 43 | } catch (e) { 44 | console.log('LocalStorageService.set.error serializing', name, value, e); 45 | } 46 | } 47 | } 48 | static isLocalStorageSupported(): boolean { 49 | if (this.supported) { 50 | return true; 51 | } 52 | let supported = false; 53 | try { 54 | supported = 'localStorage' in WINDOW && WINDOW.localStorage !== null; 55 | if (supported) { 56 | WINDOW.localStorage.setItem('test', '1'); 57 | WINDOW.localStorage.removeItem('test'); 58 | } else { 59 | supported = false; 60 | } 61 | } catch (e) { 62 | supported = false; 63 | } 64 | this.supported = supported; 65 | return supported; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /dist/cjs/event/event.directive.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var tslib_1 = require("tslib"); 4 | var rxjs_1 = require("rxjs"); 5 | var operators_1 = require("rxjs/operators"); 6 | var directive_1 = tslib_1.__importDefault(require("../core/directive")); 7 | var factory_1 = require("../core/factory"); 8 | var EVENTS = ['mousedown', 'mouseup', 'mousemove', 'click', 'dblclick', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave', 'contextmenu', 'touchstart', 'touchmove', 'touchend', 'keydown', 'keyup', 'input', 'change', 'loaded']; 9 | var EventDirective = /** @class */ (function (_super) { 10 | tslib_1.__extends(EventDirective, _super); 11 | function EventDirective() { 12 | var _this = _super !== null && _super.apply(this, arguments) || this; 13 | _this.event = ''; 14 | return _this; 15 | } 16 | EventDirective.prototype.onInit = function () { 17 | var _a = (0, factory_1.getContext)(this), module = _a.module, node = _a.node, parentInstance = _a.parentInstance, selector = _a.selector; 18 | var event = this.event = selector.replace(/\[|\]|\(|\)/g, ''); 19 | var event$ = (0, rxjs_1.fromEvent)(node, event).pipe((0, operators_1.shareReplay)(1)); 20 | var expression = node.getAttribute("(".concat(event, ")")); 21 | if (expression) { 22 | var outputFunction_1 = module.makeFunction(expression, ['$event']); 23 | event$.pipe((0, operators_1.takeUntil)(this.unsubscribe$)).subscribe(function (event) { 24 | module.resolve(outputFunction_1, parentInstance, event); 25 | }); 26 | } 27 | else { 28 | parentInstance["".concat(event, "$")] = event$; 29 | } 30 | // console.log('EventDirective.onInit', 'selector', selector, 'event', event); 31 | }; 32 | EventDirective.meta = { 33 | selector: "[(".concat(EVENTS.join(')],[('), ")]"), 34 | }; 35 | return EventDirective; 36 | }(directive_1.default)); 37 | exports.default = EventDirective; 38 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": [ 3 | "!src/**/*.ts" 4 | ], 5 | "out": "docs/typedoc", 6 | "mode": "file", 7 | "stripInternal": true, 8 | "excludePrivate": true, 9 | "excludeNotExported": true, 10 | "hideGenerator": true, 11 | "gaID": "GTM-WL42JM2", 12 | "name": "RxComp", 13 | "toc": [ 14 | "Browser", 15 | "ClassDirective", 16 | "Component", 17 | "Context", 18 | "CoreModule", 19 | "decodeBase64", 20 | "decodeJson", 21 | "default as Serializer", 22 | "DefaultErrorHandler", 23 | "Directive", 24 | "encodeBase64", 25 | "encodeJson", 26 | "encodeJsonWithOptions", 27 | "ErrorInterceptorHandler", 28 | "ErrorInterceptors", 29 | "errors$", 30 | "EventDirective", 31 | "ExpressionError", 32 | "ExpressionFunction", 33 | "Factory", 34 | "FactoryList", 35 | "ForItem", 36 | "ForStructure", 37 | "getContext", 38 | "getContextByNode", 39 | "getHost", 40 | "getLocationComponents", 41 | "getParsableContextByElement", 42 | "HrefDirective", 43 | "IComment", 44 | "IContext", 45 | "IElement", 46 | "IErrorHandler", 47 | "IErrorInterceptor", 48 | "IFactoryMeta", 49 | "IForExpressionTokens", 50 | "IfStructure", 51 | "ILocationInit", 52 | "IModuleMeta", 53 | "IModuleParsedImportedMeta", 54 | "IModuleParsedMeta", 55 | "InnerHtmlDirective", 56 | "IPipeMeta", 57 | "ISelectorResult", 58 | "isPlatformBrowser", 59 | "isPlatformServer", 60 | "isPlatformWorker", 61 | "IText", 62 | "JsonComponent", 63 | "JsonPipe", 64 | "MatchFunction", 65 | "Module", 66 | "ModuleError", 67 | "nextError$", 68 | "optionsToKey", 69 | "Pipe", 70 | "PipeList", 71 | "PipeMap", 72 | "PLATFORM_BROWSER", 73 | "PLATFORM_JS_DOM", 74 | "PLATFORM_NODE", 75 | "PLATFORM_WEB_WORKER", 76 | "Platform", 77 | "SelectorFunction", 78 | "SrcDirective", 79 | "Structure", 80 | "StyleDirective", 81 | "TransferService", 82 | "WINDOW" 83 | ] 84 | } 85 | -------------------------------------------------------------------------------- /web/client/js/test.parsing.ts: -------------------------------------------------------------------------------- 1 | import { interval } from 'rxjs'; 2 | import { takeUntil } from 'rxjs/operators'; 3 | import { Browser, Component, CoreModule, Module } from '../../../src/rxcomp'; 4 | import DatePipe from './date/date.pipe'; 5 | 6 | // !!! todo: check {{ item | json }} vs [innerHTML]="item | json" 7 | 8 | class RootComponent extends Component { 9 | html = /* html */ `bold`; 10 | valueUndefined = undefined; 11 | valueDefined = 1; 12 | ticks = -1; 13 | items = [1, 2]; 14 | object = { a: 1, b: 2 }; 15 | date = new Date(); 16 | 17 | onInit() { 18 | // console.log('RootComponent.onInit'); 19 | interval(1000).pipe( 20 | takeUntil(this.unsubscribe$) 21 | ).subscribe(ticks => { 22 | this.ticks = ticks; 23 | this.pushChanges(); 24 | }); 25 | } 26 | 27 | } 28 | RootComponent.meta = { 29 | selector: '[root-component]', 30 | }; 31 | 32 | class Root2Component extends Component { 33 | html = /* html */ `strong`; 34 | valueUndefined = undefined; 35 | valueDefined = 2; 36 | ticks = -1; 37 | items = [2, 3]; 38 | object = { a: 2, b: 3 }; 39 | date = new Date(); 40 | 41 | onInit() { 42 | // console.log('RootComponent.onInit'); 43 | interval(1000).pipe( 44 | takeUntil(this.unsubscribe$) 45 | ).subscribe(ticks => { 46 | this.ticks = ticks; 47 | this.pushChanges(); 48 | }); 49 | } 50 | 51 | } 52 | Root2Component.meta = { 53 | selector: '[root-component]', 54 | }; 55 | 56 | class AppModule extends Module { } 57 | AppModule.meta = { 58 | imports: [ 59 | CoreModule 60 | ], 61 | declarations: [ 62 | DatePipe, 63 | ], 64 | bootstrap: RootComponent, 65 | }; 66 | 67 | class App2Module extends Module { } 68 | App2Module.meta = { 69 | imports: [ 70 | CoreModule 71 | ], 72 | declarations: [ 73 | DatePipe, 74 | ], 75 | bootstrap: Root2Component, 76 | }; 77 | 78 | let module = Browser.bootstrap(AppModule); 79 | 80 | function init() { 81 | module.destroy(); 82 | module = Browser.bootstrap(App2Module); 83 | } 84 | 85 | setTimeout(() => { 86 | init(); 87 | }, 5000); 88 | -------------------------------------------------------------------------------- /src/platform/browser.ts: -------------------------------------------------------------------------------- 1 | import { IElement, IModuleParsedMeta } from '../core/types'; 2 | import { ModuleError } from '../error/error'; 3 | import Module from '../module/module'; 4 | import { WINDOW } from './common/window/window'; 5 | import Platform, { isPlatformBrowser } from './platform'; 6 | 7 | export default class Browser extends Platform { 8 | /** 9 | * @param moduleFactory 10 | * @description This method returns a Browser compiled module 11 | */ 12 | static bootstrap(moduleFactory?: typeof Module): Module { 13 | if (!isPlatformBrowser) { 14 | throw new ModuleError('missing platform browser, Window not found'); 15 | } 16 | if (!moduleFactory) { 17 | throw new ModuleError('missing moduleFactory'); 18 | } 19 | if (!moduleFactory.meta) { 20 | throw new ModuleError('missing moduleFactory meta'); 21 | } 22 | if (!moduleFactory.meta.bootstrap) { 23 | throw new ModuleError('missing bootstrap'); 24 | } 25 | if (!moduleFactory.meta.bootstrap.meta) { 26 | throw new ModuleError('missing bootstrap meta'); 27 | } 28 | if (!moduleFactory.meta.bootstrap.meta.selector) { 29 | throw new ModuleError('missing bootstrap meta selector'); 30 | } 31 | const meta: IModuleParsedMeta = this.resolveMeta(moduleFactory!); 32 | const module: Module = new moduleFactory(); 33 | module.meta = meta; 34 | meta.imports.forEach((moduleFactory: typeof Module) => { 35 | moduleFactory.prototype.onInit.call(module); 36 | }); 37 | if (WINDOW.rxcomp_hydrate_) { 38 | const clonedNode = meta.node.cloneNode() as IElement; 39 | clonedNode.innerHTML = meta.nodeInnerHTML = WINDOW.rxcomp_hydrate_.innerHTML; 40 | const instances = module.compile(clonedNode, WINDOW); 41 | module.instances = instances; 42 | const root = instances[0]; 43 | root.pushChanges(); 44 | meta.node.parentNode?.replaceChild(clonedNode, meta.node); 45 | } else { 46 | const instances = module.compile(meta.node, WINDOW); 47 | module.instances = instances; 48 | const root = instances[0]; 49 | root.pushChanges(); 50 | } 51 | return module; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /dist/rxcomp-dark.css: -------------------------------------------------------------------------------- 1 | .rxc-block { 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: flex-start; 5 | padding: 0; 6 | margin: 10px 0 0 0; 7 | overflow: auto; 8 | page-break-inside: avoid; 9 | word-wrap: break-word; 10 | white-space: pre; 11 | -webkit-user-select: none; 12 | -ms-user-select: none; 13 | user-select: none; 14 | font-family: monospace; 15 | font-size: 13px; 16 | line-height: 1.2; 17 | border-left: 3px solid #003adc; 18 | background: #333; 19 | color: #8f929b; 20 | } 21 | 22 | .rxc-head { 23 | display: flex; 24 | justify-content: space-between; 25 | align-items: center; 26 | } 27 | .rxc-head__title, .rxc-head__remove { 28 | flex: 1 1 auto; 29 | padding: 5px; 30 | } 31 | .rxc-head__title { 32 | flex: 1 1 calc(100% - 20px); 33 | display: flex; 34 | justify-content: flex-start; 35 | align-items: center; 36 | text-overflow: ellipsis; 37 | overflow: hidden; 38 | cursor: pointer; 39 | } 40 | .rxc-head__remove { 41 | flex: 1 1 20px; 42 | margin-left: 5px; 43 | cursor: pointer; 44 | } 45 | 46 | .rxc-list { 47 | display: flex; 48 | flex-direction: column; 49 | list-style: none; 50 | margin: 0; 51 | padding: 0; 52 | } 53 | .rxc-list__item { 54 | display: flex; 55 | justify-content: space-between; 56 | align-items: flex-start; 57 | padding-bottom: 2px; 58 | border-bottom: 1px solid #222222; 59 | } 60 | .rxc-list__item:last-child { 61 | border-bottom: none; 62 | } 63 | .rxc-list__title, .rxc-list__name, .rxc-list__value, .rxc-list__remove { 64 | flex: 1 1 auto; 65 | padding: 5px; 66 | } 67 | .rxc-list__title, .rxc-list__name, .rxc-list__value { 68 | text-overflow: ellipsis; 69 | overflow: hidden; 70 | } 71 | .rxc-list__title { 72 | flex: 1 1 calc(100% - 20px); 73 | font-family: sans-serif; 74 | font-size: 16px; 75 | font-weight: 500; 76 | } 77 | .rxc-list__name { 78 | flex: 1 1 30%; 79 | } 80 | .rxc-list__value { 81 | flex: 1 1 calc(70% - 20px); 82 | margin-left: 5px; 83 | } 84 | .rxc-list__remove { 85 | flex: 1 1 20px; 86 | margin-left: 5px; 87 | cursor: pointer; 88 | } -------------------------------------------------------------------------------- /dist/rxcomp-light.css: -------------------------------------------------------------------------------- 1 | .rxc-block { 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: flex-start; 5 | padding: 0; 6 | margin: 10px 0 0 0; 7 | overflow: auto; 8 | page-break-inside: avoid; 9 | word-wrap: break-word; 10 | white-space: pre; 11 | -webkit-user-select: none; 12 | -ms-user-select: none; 13 | user-select: none; 14 | font-family: monospace; 15 | font-size: 13px; 16 | line-height: 1.2; 17 | border-left: 3px solid #003adc; 18 | background: #f3f3f3; 19 | color: #8f929b; 20 | } 21 | 22 | .rxc-head { 23 | display: flex; 24 | justify-content: space-between; 25 | align-items: center; 26 | } 27 | .rxc-head__title, .rxc-head__remove { 28 | flex: 1 1 auto; 29 | padding: 5px; 30 | } 31 | .rxc-head__title { 32 | flex: 1 1 calc(100% - 20px); 33 | display: flex; 34 | justify-content: flex-start; 35 | align-items: center; 36 | text-overflow: ellipsis; 37 | overflow: hidden; 38 | cursor: pointer; 39 | } 40 | .rxc-head__remove { 41 | flex: 1 1 20px; 42 | margin-left: 5px; 43 | cursor: pointer; 44 | } 45 | 46 | .rxc-list { 47 | display: flex; 48 | flex-direction: column; 49 | list-style: none; 50 | margin: 0; 51 | padding: 0; 52 | } 53 | .rxc-list__item { 54 | display: flex; 55 | justify-content: space-between; 56 | align-items: flex-start; 57 | padding-bottom: 2px; 58 | border-bottom: 1px solid #222222; 59 | } 60 | .rxc-list__item:last-child { 61 | border-bottom: none; 62 | } 63 | .rxc-list__title, .rxc-list__name, .rxc-list__value, .rxc-list__remove { 64 | flex: 1 1 auto; 65 | padding: 5px; 66 | } 67 | .rxc-list__title, .rxc-list__name, .rxc-list__value { 68 | text-overflow: ellipsis; 69 | overflow: hidden; 70 | } 71 | .rxc-list__title { 72 | flex: 1 1 calc(100% - 20px); 73 | font-family: sans-serif; 74 | font-size: 16px; 75 | font-weight: 500; 76 | } 77 | .rxc-list__name { 78 | flex: 1 1 30%; 79 | } 80 | .rxc-list__value { 81 | flex: 1 1 calc(70% - 20px); 82 | margin-left: 5px; 83 | } 84 | .rxc-list__remove { 85 | flex: 1 1 20px; 86 | margin-left: 5px; 87 | cursor: pointer; 88 | } -------------------------------------------------------------------------------- /docs/css/rxcomp-dark.css: -------------------------------------------------------------------------------- 1 | .rxc-block { 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: flex-start; 5 | padding: 0; 6 | margin: 10px 0 0 0; 7 | overflow: auto; 8 | page-break-inside: avoid; 9 | word-wrap: break-word; 10 | white-space: pre; 11 | -webkit-user-select: none; 12 | -ms-user-select: none; 13 | user-select: none; 14 | font-family: monospace; 15 | font-size: 13px; 16 | line-height: 1.2; 17 | border-left: 3px solid #003adc; 18 | background: #333; 19 | color: #8f929b; 20 | } 21 | 22 | .rxc-head { 23 | display: flex; 24 | justify-content: space-between; 25 | align-items: center; 26 | } 27 | .rxc-head__title, .rxc-head__remove { 28 | flex: 1 1 auto; 29 | padding: 5px; 30 | } 31 | .rxc-head__title { 32 | flex: 1 1 calc(100% - 20px); 33 | display: flex; 34 | justify-content: flex-start; 35 | align-items: center; 36 | text-overflow: ellipsis; 37 | overflow: hidden; 38 | cursor: pointer; 39 | } 40 | .rxc-head__remove { 41 | flex: 1 1 20px; 42 | margin-left: 5px; 43 | cursor: pointer; 44 | } 45 | 46 | .rxc-list { 47 | display: flex; 48 | flex-direction: column; 49 | list-style: none; 50 | margin: 0; 51 | padding: 0; 52 | } 53 | .rxc-list__item { 54 | display: flex; 55 | justify-content: space-between; 56 | align-items: flex-start; 57 | padding-bottom: 2px; 58 | border-bottom: 1px solid #222222; 59 | } 60 | .rxc-list__item:last-child { 61 | border-bottom: none; 62 | } 63 | .rxc-list__title, .rxc-list__name, .rxc-list__value, .rxc-list__remove { 64 | flex: 1 1 auto; 65 | padding: 5px; 66 | } 67 | .rxc-list__title, .rxc-list__name, .rxc-list__value { 68 | text-overflow: ellipsis; 69 | overflow: hidden; 70 | } 71 | .rxc-list__title { 72 | flex: 1 1 calc(100% - 20px); 73 | font-family: sans-serif; 74 | font-size: 16px; 75 | font-weight: 500; 76 | } 77 | .rxc-list__name { 78 | flex: 1 1 30%; 79 | } 80 | .rxc-list__value { 81 | flex: 1 1 calc(70% - 20px); 82 | margin-left: 5px; 83 | } 84 | .rxc-list__remove { 85 | flex: 1 1 20px; 86 | margin-left: 5px; 87 | cursor: pointer; 88 | } -------------------------------------------------------------------------------- /docs/css/rxcomp-light.css: -------------------------------------------------------------------------------- 1 | .rxc-block { 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: flex-start; 5 | padding: 0; 6 | margin: 10px 0 0 0; 7 | overflow: auto; 8 | page-break-inside: avoid; 9 | word-wrap: break-word; 10 | white-space: pre; 11 | -webkit-user-select: none; 12 | -ms-user-select: none; 13 | user-select: none; 14 | font-family: monospace; 15 | font-size: 13px; 16 | line-height: 1.2; 17 | border-left: 3px solid #003adc; 18 | background: #f3f3f3; 19 | color: #8f929b; 20 | } 21 | 22 | .rxc-head { 23 | display: flex; 24 | justify-content: space-between; 25 | align-items: center; 26 | } 27 | .rxc-head__title, .rxc-head__remove { 28 | flex: 1 1 auto; 29 | padding: 5px; 30 | } 31 | .rxc-head__title { 32 | flex: 1 1 calc(100% - 20px); 33 | display: flex; 34 | justify-content: flex-start; 35 | align-items: center; 36 | text-overflow: ellipsis; 37 | overflow: hidden; 38 | cursor: pointer; 39 | } 40 | .rxc-head__remove { 41 | flex: 1 1 20px; 42 | margin-left: 5px; 43 | cursor: pointer; 44 | } 45 | 46 | .rxc-list { 47 | display: flex; 48 | flex-direction: column; 49 | list-style: none; 50 | margin: 0; 51 | padding: 0; 52 | } 53 | .rxc-list__item { 54 | display: flex; 55 | justify-content: space-between; 56 | align-items: flex-start; 57 | padding-bottom: 2px; 58 | border-bottom: 1px solid #222222; 59 | } 60 | .rxc-list__item:last-child { 61 | border-bottom: none; 62 | } 63 | .rxc-list__title, .rxc-list__name, .rxc-list__value, .rxc-list__remove { 64 | flex: 1 1 auto; 65 | padding: 5px; 66 | } 67 | .rxc-list__title, .rxc-list__name, .rxc-list__value { 68 | text-overflow: ellipsis; 69 | overflow: hidden; 70 | } 71 | .rxc-list__title { 72 | flex: 1 1 calc(100% - 20px); 73 | font-family: sans-serif; 74 | font-size: 16px; 75 | font-weight: 500; 76 | } 77 | .rxc-list__name { 78 | flex: 1 1 30%; 79 | } 80 | .rxc-list__value { 81 | flex: 1 1 calc(70% - 20px); 82 | margin-left: 5px; 83 | } 84 | .rxc-list__remove { 85 | flex: 1 1 20px; 86 | margin-left: 5px; 87 | cursor: pointer; 88 | } -------------------------------------------------------------------------------- /src/_scss/_rxcomp/_rxcomp.scss: -------------------------------------------------------------------------------- 1 | .rxc-block { 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: flex-start; 5 | padding: 0; 6 | margin: 10px 0 0 0; 7 | overflow: auto; 8 | page-break-inside: avoid; 9 | word-wrap: break-word; 10 | white-space: pre; 11 | user-select: none; 12 | font-family: monospace; 13 | font-size: 13px; 14 | line-height: 1.2; 15 | border-left: 3px solid $background-primary; 16 | background: $background-light; 17 | color: $foreground-secondary; 18 | } 19 | 20 | .rxc-head { 21 | display: flex; 22 | justify-content: space-between; 23 | align-items: center; 24 | 25 | &__title, 26 | &__remove { 27 | flex: 1 1 auto; 28 | padding: 5px; 29 | } 30 | 31 | &__title { 32 | flex: 1 1 calc(100% - 20px); 33 | display: flex; 34 | justify-content: flex-start; 35 | align-items: center; 36 | text-overflow: ellipsis; 37 | overflow: hidden; 38 | cursor: pointer; 39 | } 40 | 41 | &__remove { 42 | flex: 1 1 20px; 43 | margin-left: 5px; 44 | cursor: pointer; 45 | } 46 | } 47 | 48 | .rxc-list { 49 | display: flex; 50 | flex-direction: column; 51 | list-style: none; 52 | margin: 0; 53 | padding: 0; 54 | 55 | &__item { 56 | display: flex; 57 | justify-content: space-between; 58 | align-items: flex-start; 59 | padding-bottom: 2px; 60 | border-bottom: 1px solid #222222; 61 | 62 | &:last-child { 63 | border-bottom: none; 64 | } 65 | } 66 | 67 | &__title, 68 | &__name, 69 | &__value, 70 | &__remove { 71 | flex: 1 1 auto; 72 | padding: 5px; 73 | } 74 | 75 | &__title, 76 | &__name, 77 | &__value { 78 | text-overflow: ellipsis; 79 | overflow: hidden; 80 | } 81 | 82 | &__title { 83 | flex: 1 1 calc(100% - 20px); 84 | font-family: sans-serif; 85 | font-size: 16px; 86 | font-weight: 500; 87 | } 88 | 89 | &__name { 90 | flex: 1 1 30%; 91 | } 92 | 93 | &__value { 94 | flex: 1 1 calc(70% - 20px); 95 | margin-left: 5px; 96 | } 97 | 98 | &__remove { 99 | flex: 1 1 20px; 100 | margin-left: 5px; 101 | cursor: pointer; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/core/context.ts: -------------------------------------------------------------------------------- 1 | // import { BehaviorSubject, Subject } from 'rxjs'; 2 | import Component from './component'; 3 | import Factory, { getContext } from './factory'; 4 | 5 | const RESERVED_PROPERTIES = ['constructor', 'rxcompId', 'onInit', 'onChanges', 'onDestroy', 'pushChanges', 'changes$', 'unsubscribe$']; 6 | 7 | export default class Context extends Component { 8 | constructor(parentInstance: Factory, descriptors: { [key: string]: PropertyDescriptor } = {}) { 9 | super(); 10 | descriptors = Context.mergeDescriptors(parentInstance, parentInstance, descriptors); 11 | descriptors = Context.mergeDescriptors(Object.getPrototypeOf(parentInstance), parentInstance, descriptors); 12 | Object.defineProperties(this, descriptors); 13 | } 14 | pushChanges(): void { 15 | const context = getContext(this); 16 | if (!context.keys) { 17 | context.keys = Object.keys(context.parentInstance).filter(key => RESERVED_PROPERTIES.indexOf(key) === -1); 18 | // console.log(context.keys.join(',')); 19 | } 20 | if (context.module.instances) { 21 | context.keys.forEach(key => { 22 | // console.log('Context', key, context.parentInstance); 23 | this[key] = context.parentInstance[key]; 24 | }); 25 | } 26 | super.pushChanges(); 27 | } 28 | onParentDidChange(changes: Factory | Window): void { 29 | this.onChanges(changes); 30 | this.pushChanges(); 31 | } 32 | static mergeDescriptors(source: Object, instance: Factory, descriptors: { [key: string]: PropertyDescriptor } = {}): { [key: string]: PropertyDescriptor } { 33 | const properties: string[] = Object.getOwnPropertyNames(source); 34 | while (properties.length) { 35 | const key: string = properties.shift() as string; 36 | if (RESERVED_PROPERTIES.indexOf(key) === -1 && !descriptors.hasOwnProperty(key)) { 37 | const descriptor: PropertyDescriptor = Object.getOwnPropertyDescriptor(source, key) as PropertyDescriptor; 38 | if (typeof descriptor.value == 'function') { 39 | descriptor.value = (...args: any[]) => { 40 | return instance[key].apply(instance, args); 41 | }; 42 | } 43 | descriptors[key] = descriptor; 44 | } 45 | } 46 | return descriptors; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /dist/esm/rxcomp.js: -------------------------------------------------------------------------------- 1 | export { default as ClassDirective } from './class/class.directive'; 2 | export { default as CoreModule } from './core.module'; 3 | export { default as Component } from './core/component'; 4 | export { default as Context } from './core/context'; 5 | export { default as Directive } from './core/directive'; 6 | export { default as Factory, getContext } from './core/factory'; 7 | export { default as Pipe } from './core/pipe'; 8 | export { default as Structure } from './core/structure'; 9 | export { DefaultErrorHandler, ErrorInterceptorHandler, ErrorInterceptors, errors$, ExpressionError, ModuleError, nextError$ } from './error/error'; 10 | export { default as EventDirective } from './event/event.directive'; 11 | export { default as ForItem } from './for/for.item'; 12 | export { default as ForStructure } from './for/for.structure'; 13 | export { default as HrefTargetDirective } from './href/href-target.directive'; 14 | export { default as HrefDirective } from './href/href.directive'; 15 | export { default as IfStructure } from './if/if.structure'; 16 | export { default as InnerHtmlDirective } from './inner-html/inner-html.directive'; 17 | export { default as JsonComponent } from './json/json.component'; 18 | export { default as JsonPipe } from './json/json.pipe'; 19 | export { default as Module, getContextByNode, getHost, getParsableContextByElement } from './module/module'; 20 | export { default as Browser } from './platform/browser'; 21 | export { getLocationComponents } from './platform/common/location/location'; 22 | export { decodeBase64, decodeJson, default as Serializer, encodeBase64, encodeJson, encodeJsonWithOptions } from './platform/common/serializer/serializer'; 23 | export { default as TransferService, optionsToKey } from './platform/common/transfer/transfer.service'; 24 | export { WINDOW } from './platform/common/window/window'; 25 | export { default as Platform, isPlatformBrowser, isPlatformServer, isPlatformWorker, PLATFORM_BROWSER, PLATFORM_JS_DOM, PLATFORM_NODE, PLATFORM_WEB_WORKER } from './platform/platform'; 26 | export { default as SrcDirective } from './src/src.directive'; 27 | export { default as StyleDirective } from './style/style.directive'; 28 | -------------------------------------------------------------------------------- /web/client/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | <!--@@var=title--> 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /dist/esm/core/context.js: -------------------------------------------------------------------------------- 1 | // import { BehaviorSubject, Subject } from 'rxjs'; 2 | import Component from './component'; 3 | import { getContext } from './factory'; 4 | const RESERVED_PROPERTIES = ['constructor', 'rxcompId', 'onInit', 'onChanges', 'onDestroy', 'pushChanges', 'changes$', 'unsubscribe$']; 5 | export default class Context extends Component { 6 | constructor(parentInstance, descriptors = {}) { 7 | super(); 8 | descriptors = Context.mergeDescriptors(parentInstance, parentInstance, descriptors); 9 | descriptors = Context.mergeDescriptors(Object.getPrototypeOf(parentInstance), parentInstance, descriptors); 10 | Object.defineProperties(this, descriptors); 11 | } 12 | pushChanges() { 13 | const context = getContext(this); 14 | if (!context.keys) { 15 | context.keys = Object.keys(context.parentInstance).filter(key => RESERVED_PROPERTIES.indexOf(key) === -1); 16 | // console.log(context.keys.join(',')); 17 | } 18 | if (context.module.instances) { 19 | context.keys.forEach(key => { 20 | // console.log('Context', key, context.parentInstance); 21 | this[key] = context.parentInstance[key]; 22 | }); 23 | } 24 | super.pushChanges(); 25 | } 26 | onParentDidChange(changes) { 27 | this.onChanges(changes); 28 | this.pushChanges(); 29 | } 30 | static mergeDescriptors(source, instance, descriptors = {}) { 31 | const properties = Object.getOwnPropertyNames(source); 32 | while (properties.length) { 33 | const key = properties.shift(); 34 | if (RESERVED_PROPERTIES.indexOf(key) === -1 && !descriptors.hasOwnProperty(key)) { 35 | const descriptor = Object.getOwnPropertyDescriptor(source, key); 36 | if (typeof descriptor.value == 'function') { 37 | descriptor.value = (...args) => { 38 | return instance[key].apply(instance, args); 39 | }; 40 | } 41 | descriptors[key] = descriptor; 42 | } 43 | } 44 | return descriptors; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /dist/cjs/for/for.item.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var tslib_1 = require("tslib"); 4 | var context_1 = tslib_1.__importDefault(require("../core/context")); 5 | var ForItem = /** @class */ (function (_super) { 6 | tslib_1.__extends(ForItem, _super); 7 | // !!! todo: payload options { key, $key, value, $value, index, count } 8 | function ForItem(key, $key, value, $value, index, count, parentInstance) { 9 | var _this = 10 | // console.log('ForItem', arguments); 11 | _super.call(this, parentInstance) || this; 12 | /* 13 | super(parentInstance, { 14 | [key]: { 15 | get: function() { 16 | return this.$key; 17 | }, 18 | set: function(key) { 19 | this.$key = key; 20 | } 21 | }, 22 | [value]: { 23 | get: function() { 24 | return this.$value; 25 | }, 26 | set: function(value) { 27 | this.$value = value; 28 | } 29 | } 30 | }); 31 | */ 32 | _this[key] = $key; 33 | _this[value] = $value; 34 | _this.index = index; 35 | _this.count = count; 36 | return _this; 37 | } 38 | Object.defineProperty(ForItem.prototype, "first", { 39 | get: function () { return this.index === 0; }, 40 | enumerable: false, 41 | configurable: true 42 | }); 43 | Object.defineProperty(ForItem.prototype, "last", { 44 | get: function () { return this.index === this.count - 1; }, 45 | enumerable: false, 46 | configurable: true 47 | }); 48 | Object.defineProperty(ForItem.prototype, "even", { 49 | get: function () { return this.index % 2 === 0; }, 50 | enumerable: false, 51 | configurable: true 52 | }); 53 | Object.defineProperty(ForItem.prototype, "odd", { 54 | get: function () { return !this.even; }, 55 | enumerable: false, 56 | configurable: true 57 | }); 58 | return ForItem; 59 | }(context_1.default)); 60 | exports.default = ForItem; 61 | -------------------------------------------------------------------------------- /dist/esm/platform/browser.js: -------------------------------------------------------------------------------- 1 | import { ModuleError } from '../error/error'; 2 | import { WINDOW } from './common/window/window'; 3 | import Platform, { isPlatformBrowser } from './platform'; 4 | export default class Browser extends Platform { 5 | /** 6 | * @param moduleFactory 7 | * @description This method returns a Browser compiled module 8 | */ 9 | static bootstrap(moduleFactory) { 10 | var _a; 11 | if (!isPlatformBrowser) { 12 | throw new ModuleError('missing platform browser, Window not found'); 13 | } 14 | if (!moduleFactory) { 15 | throw new ModuleError('missing moduleFactory'); 16 | } 17 | if (!moduleFactory.meta) { 18 | throw new ModuleError('missing moduleFactory meta'); 19 | } 20 | if (!moduleFactory.meta.bootstrap) { 21 | throw new ModuleError('missing bootstrap'); 22 | } 23 | if (!moduleFactory.meta.bootstrap.meta) { 24 | throw new ModuleError('missing bootstrap meta'); 25 | } 26 | if (!moduleFactory.meta.bootstrap.meta.selector) { 27 | throw new ModuleError('missing bootstrap meta selector'); 28 | } 29 | const meta = this.resolveMeta(moduleFactory); 30 | const module = new moduleFactory(); 31 | module.meta = meta; 32 | meta.imports.forEach((moduleFactory) => { 33 | moduleFactory.prototype.onInit.call(module); 34 | }); 35 | if (WINDOW.rxcomp_hydrate_) { 36 | const clonedNode = meta.node.cloneNode(); 37 | clonedNode.innerHTML = meta.nodeInnerHTML = WINDOW.rxcomp_hydrate_.innerHTML; 38 | const instances = module.compile(clonedNode, WINDOW); 39 | module.instances = instances; 40 | const root = instances[0]; 41 | root.pushChanges(); 42 | (_a = meta.node.parentNode) === null || _a === void 0 ? void 0 : _a.replaceChild(clonedNode, meta.node); 43 | } 44 | else { 45 | const instances = module.compile(meta.node, WINDOW); 46 | module.instances = instances; 47 | const root = instances[0]; 48 | root.pushChanges(); 49 | } 50 | return module; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /web/client/js/store/store.service.ts: -------------------------------------------------------------------------------- 1 | import { BehaviorSubject, Observable, of } from 'rxjs'; 2 | import { delay } from 'rxjs/operators'; 3 | import LocalStorageService from '../local-storage/local-storage.service'; 4 | import ITodoItem from '../todo-item/todo-item'; 5 | 6 | export default class StoreService { 7 | static store$: BehaviorSubject; 8 | static set(items: ITodoItem[]) { 9 | LocalStorageService.set('items', items); 10 | return this.get$().next(items); 11 | } 12 | static get$(): BehaviorSubject { 13 | if (this.store$) { 14 | return this.store$; 15 | } 16 | let items: ITodoItem[] = LocalStorageService.get('items'); 17 | if (!items) { 18 | items = [ 19 | { id: 5, name: 'Cookies', date: new Date(Date.now()) }, 20 | { id: 4, name: 'Pizza', date: new Date(2019, 4, 4, 12) }, 21 | { id: 3, name: 'Pasta', date: new Date(2019, 3, 22, 12) }, 22 | { id: 2, name: 'Bread', date: new Date(2019, 0, 6, 12) }, 23 | { id: 1, name: 'Ham', date: new Date(2018, 11, 30, 12) }, 24 | ]; 25 | LocalStorageService.set('items', items); 26 | } 27 | this.store$ = new BehaviorSubject(items); 28 | return this.store$.pipe( 29 | delay(1) // simulate http 30 | ) as BehaviorSubject; 31 | } 32 | static add$(patch: ITodoItem): Observable { 33 | const item = Object.assign({ 34 | id: Date.now(), 35 | date: new Date(Date.now()) 36 | }, patch); 37 | const items = this.store$.getValue(); 38 | items.unshift(item); 39 | this.set(items); 40 | return of(item).pipe( 41 | delay(1) // simulate http 42 | ); 43 | } 44 | static patch$(patch: ITodoItem): Observable { 45 | const items = this.store$.getValue(); 46 | const item = items.find((x: ITodoItem) => x.id === patch.id); 47 | if (item) { 48 | Object.assign(item, patch); 49 | this.set(items); 50 | } 51 | return of(item).pipe( 52 | delay(1) // simulate http 53 | ); 54 | } 55 | static delete$(item: ITodoItem): Observable { 56 | const items = this.store$.getValue(); 57 | const index = items.indexOf(item); 58 | if (index !== -1) { 59 | items.splice(index, 1); 60 | this.set(items); 61 | } 62 | return of(item).pipe( 63 | delay(1) // simulate http 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /dist/cjs/if/if.structure.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var tslib_1 = require("tslib"); 4 | var factory_1 = require("../core/factory"); 5 | var structure_1 = tslib_1.__importDefault(require("../core/structure")); 6 | var IfStructure = /** @class */ (function (_super) { 7 | tslib_1.__extends(IfStructure, _super); 8 | function IfStructure() { 9 | return _super !== null && _super.apply(this, arguments) || this; 10 | } 11 | IfStructure.prototype.onInit = function () { 12 | var node = (0, factory_1.getContext)(this).node; 13 | var ifbegin = this.ifbegin = document.createComment("*if begin"); 14 | ifbegin.rxcompId = node.rxcompId; 15 | node.parentNode.replaceChild(ifbegin, node); 16 | var ifend = this.ifend = document.createComment("*if end"); 17 | ifbegin.parentNode.insertBefore(ifend, ifbegin.nextSibling); 18 | var clonedNode = node.cloneNode(true); 19 | clonedNode.removeAttribute('*if'); 20 | this.clonedNode = clonedNode; 21 | this.element = clonedNode.cloneNode(true); 22 | }; 23 | IfStructure.prototype.onChanges = function () { 24 | var module = (0, factory_1.getContext)(this).module; 25 | var element = this.element; 26 | // console.log('IfStructure.onChanges.if', this.if); 27 | if (Boolean(this.if)) { // !!! keep == loose equality 28 | if (!element.parentNode) { 29 | var ifend = this.ifend; 30 | ifend.parentNode.insertBefore(element, ifend); 31 | module.compile(element); 32 | // console.log('IfStructure.onChanges.add', element); 33 | } 34 | } 35 | else { 36 | if (element.parentNode) { 37 | module.remove(element, this); 38 | element.parentNode.removeChild(element); 39 | this.element = this.clonedNode.cloneNode(true); 40 | // console.log('IfStructure.onChanges.remove', element); 41 | } 42 | } 43 | }; 44 | IfStructure.meta = { 45 | selector: '[*if]', 46 | inputs: ['if'], 47 | }; 48 | return IfStructure; 49 | }(structure_1.default)); 50 | exports.default = IfStructure; 51 | -------------------------------------------------------------------------------- /src/error/error.ts: -------------------------------------------------------------------------------- 1 | import { Observable, of, ReplaySubject } from "rxjs"; 2 | import { switchMap, tap } from "rxjs/operators"; 3 | import Factory, { getContext } from "../core/factory"; 4 | import Module from "../module/module"; 5 | 6 | export class ModuleError extends Error { } 7 | 8 | export class ExpressionError extends Error { 9 | module: Module; 10 | instance: Factory; 11 | expression: string; 12 | params: any[]; 13 | template: string; 14 | constructor(error: Error, module: Module, instance: Factory, expression: string, params: any[]) { 15 | const message: string = `ExpressionError in ${instance.constructor.name} "${expression}" 16 | ${error.message}`; 17 | super(message); 18 | this.name = error.name; 19 | // this.stack = error.stack; 20 | this.module = module; 21 | this.instance = instance; 22 | this.expression = expression; 23 | this.params = params; 24 | const { node } = getContext(instance); 25 | this.template = node.outerHTML; 26 | } 27 | } 28 | export interface IErrorHandler { 29 | handle(error: Error): Observable 30 | } 31 | export interface IErrorInterceptor { 32 | intercept(error: Error | void, next: IErrorHandler): Observable 33 | } 34 | export class ErrorInterceptorHandler implements IErrorHandler { 35 | constructor( 36 | private next: IErrorHandler, 37 | private interceptor: IErrorInterceptor, 38 | ) { } 39 | handle(error: Error | void): Observable { 40 | return this.interceptor.intercept(error, this.next); 41 | } 42 | } 43 | export class DefaultErrorHandler implements IErrorHandler { 44 | handle(error: Error | void): Observable { 45 | return of(error); 46 | } 47 | } 48 | export const ErrorInterceptors: IErrorInterceptor[] = []; 49 | export const nextError$: ReplaySubject = new ReplaySubject(1); 50 | export const errors$: Observable = nextError$.pipe( 51 | switchMap((error: Error) => { 52 | const chain: IErrorHandler = ErrorInterceptors.reduceRight((next: IErrorHandler, interceptor: IErrorInterceptor) => { 53 | return new ErrorInterceptorHandler(next, interceptor); 54 | }, new DefaultErrorHandler()); 55 | return chain.handle(error); 56 | }), 57 | tap((error: Error | void) => { 58 | if (error) { 59 | console.error(error); 60 | } 61 | }), 62 | ); 63 | -------------------------------------------------------------------------------- /dist/cjs/core.module.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var tslib_1 = require("tslib"); 4 | var operators_1 = require("rxjs/operators"); 5 | var class_directive_1 = tslib_1.__importDefault(require("./class/class.directive")); 6 | var error_1 = require("./error/error"); 7 | var event_directive_1 = tslib_1.__importDefault(require("./event/event.directive")); 8 | var for_structure_1 = tslib_1.__importDefault(require("./for/for.structure")); 9 | var href_target_directive_1 = tslib_1.__importDefault(require("./href/href-target.directive")); 10 | var href_directive_1 = tslib_1.__importDefault(require("./href/href.directive")); 11 | var if_structure_1 = tslib_1.__importDefault(require("./if/if.structure")); 12 | var inner_html_directive_1 = tslib_1.__importDefault(require("./inner-html/inner-html.directive")); 13 | var json_component_1 = tslib_1.__importDefault(require("./json/json.component")); 14 | var json_pipe_1 = tslib_1.__importDefault(require("./json/json.pipe")); 15 | var module_1 = tslib_1.__importDefault(require("./module/module")); 16 | var src_directive_1 = tslib_1.__importDefault(require("./src/src.directive")); 17 | var style_directive_1 = tslib_1.__importDefault(require("./style/style.directive")); 18 | var factories = [ 19 | class_directive_1.default, 20 | event_directive_1.default, 21 | for_structure_1.default, 22 | href_directive_1.default, 23 | href_target_directive_1.default, 24 | if_structure_1.default, 25 | inner_html_directive_1.default, 26 | json_component_1.default, 27 | src_directive_1.default, 28 | style_directive_1.default, 29 | ]; 30 | var pipes = [ 31 | json_pipe_1.default, 32 | ]; 33 | var CoreModule = /** @class */ (function (_super) { 34 | tslib_1.__extends(CoreModule, _super); 35 | function CoreModule() { 36 | var _this = _super.call(this) || this; 37 | // console.log('CoreModule'); 38 | error_1.errors$.pipe((0, operators_1.takeUntil)(_this.unsubscribe$)).subscribe(); 39 | return _this; 40 | } 41 | CoreModule.meta = { 42 | declarations: tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(factories), false), tslib_1.__read(pipes), false), 43 | exports: tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(factories), false), tslib_1.__read(pipes), false) 44 | }; 45 | return CoreModule; 46 | }(module_1.default)); 47 | exports.default = CoreModule; 48 | -------------------------------------------------------------------------------- /dist/cjs/rxcomp.d.ts: -------------------------------------------------------------------------------- 1 | export { default as ClassDirective } from './class/class.directive'; 2 | export { default as CoreModule } from './core.module'; 3 | export { default as Component } from './core/component'; 4 | export { default as Context } from './core/context'; 5 | export { default as Directive } from './core/directive'; 6 | export { default as Factory, getContext } from './core/factory'; 7 | export { default as Pipe } from './core/pipe'; 8 | export { default as Structure } from './core/structure'; 9 | export { ExpressionFunction, FactoryList, IComment, IContext, IElement, IFactoryMeta, IForExpressionTokens, IModuleMeta, IModuleParsedImportedMeta, IModuleParsedMeta, IPipeMeta, ISelectorResult, IText, MatchFunction, PipeList, PipeMap, SelectorFunction } from './core/types'; 10 | export { DefaultErrorHandler, ErrorInterceptorHandler, ErrorInterceptors, errors$, ExpressionError, IErrorHandler, IErrorInterceptor, ModuleError, nextError$ } from './error/error'; 11 | export { default as EventDirective } from './event/event.directive'; 12 | export { default as ForItem } from './for/for.item'; 13 | export { default as ForStructure } from './for/for.structure'; 14 | export { default as HrefTargetDirective } from './href/href-target.directive'; 15 | export { default as HrefDirective } from './href/href.directive'; 16 | export { default as IfStructure } from './if/if.structure'; 17 | export { default as InnerHtmlDirective } from './inner-html/inner-html.directive'; 18 | export { default as JsonComponent } from './json/json.component'; 19 | export { default as JsonPipe } from './json/json.pipe'; 20 | export { default as Module, getContextByNode, getHost, getParsableContextByElement } from './module/module'; 21 | export { default as Browser } from './platform/browser'; 22 | export { getLocationComponents, ILocationInit } from './platform/common/location/location'; 23 | export { decodeBase64, decodeJson, default as Serializer, encodeBase64, encodeJson, encodeJsonWithOptions } from './platform/common/serializer/serializer'; 24 | export { default as TransferService, optionsToKey } from './platform/common/transfer/transfer.service'; 25 | export { WINDOW } from './platform/common/window/window'; 26 | export { default as Platform, isPlatformBrowser, isPlatformServer, isPlatformWorker, PLATFORM_BROWSER, PLATFORM_JS_DOM, PLATFORM_NODE, PLATFORM_WEB_WORKER } from './platform/platform'; 27 | export { default as SrcDirective } from './src/src.directive'; 28 | export { default as StyleDirective } from './style/style.directive'; 29 | -------------------------------------------------------------------------------- /dist/esm/rxcomp.d.ts: -------------------------------------------------------------------------------- 1 | export { default as ClassDirective } from './class/class.directive'; 2 | export { default as CoreModule } from './core.module'; 3 | export { default as Component } from './core/component'; 4 | export { default as Context } from './core/context'; 5 | export { default as Directive } from './core/directive'; 6 | export { default as Factory, getContext } from './core/factory'; 7 | export { default as Pipe } from './core/pipe'; 8 | export { default as Structure } from './core/structure'; 9 | export { ExpressionFunction, FactoryList, IComment, IContext, IElement, IFactoryMeta, IForExpressionTokens, IModuleMeta, IModuleParsedImportedMeta, IModuleParsedMeta, IPipeMeta, ISelectorResult, IText, MatchFunction, PipeList, PipeMap, SelectorFunction } from './core/types'; 10 | export { DefaultErrorHandler, ErrorInterceptorHandler, ErrorInterceptors, errors$, ExpressionError, IErrorHandler, IErrorInterceptor, ModuleError, nextError$ } from './error/error'; 11 | export { default as EventDirective } from './event/event.directive'; 12 | export { default as ForItem } from './for/for.item'; 13 | export { default as ForStructure } from './for/for.structure'; 14 | export { default as HrefTargetDirective } from './href/href-target.directive'; 15 | export { default as HrefDirective } from './href/href.directive'; 16 | export { default as IfStructure } from './if/if.structure'; 17 | export { default as InnerHtmlDirective } from './inner-html/inner-html.directive'; 18 | export { default as JsonComponent } from './json/json.component'; 19 | export { default as JsonPipe } from './json/json.pipe'; 20 | export { default as Module, getContextByNode, getHost, getParsableContextByElement } from './module/module'; 21 | export { default as Browser } from './platform/browser'; 22 | export { getLocationComponents, ILocationInit } from './platform/common/location/location'; 23 | export { decodeBase64, decodeJson, default as Serializer, encodeBase64, encodeJson, encodeJsonWithOptions } from './platform/common/serializer/serializer'; 24 | export { default as TransferService, optionsToKey } from './platform/common/transfer/transfer.service'; 25 | export { WINDOW } from './platform/common/window/window'; 26 | export { default as Platform, isPlatformBrowser, isPlatformServer, isPlatformWorker, PLATFORM_BROWSER, PLATFORM_JS_DOM, PLATFORM_NODE, PLATFORM_WEB_WORKER } from './platform/platform'; 27 | export { default as SrcDirective } from './src/src.directive'; 28 | export { default as StyleDirective } from './style/style.directive'; 29 | -------------------------------------------------------------------------------- /src/rxcomp.ts: -------------------------------------------------------------------------------- 1 | export { default as ClassDirective } from './class/class.directive'; 2 | export { default as CoreModule } from './core.module'; 3 | export { default as Component } from './core/component'; 4 | export { default as Context } from './core/context'; 5 | export { default as Directive } from './core/directive'; 6 | export { default as Factory, getContext } from './core/factory'; 7 | export { default as Pipe } from './core/pipe'; 8 | export { default as Structure } from './core/structure'; 9 | export { ExpressionFunction, FactoryList, IComment, IContext, IElement, IFactoryMeta, IForExpressionTokens, IModuleMeta, IModuleParsedImportedMeta, IModuleParsedMeta, IPipeMeta, ISelectorResult, IText, MatchFunction, PipeList, PipeMap, SelectorFunction } from './core/types'; 10 | export { DefaultErrorHandler, ErrorInterceptorHandler, ErrorInterceptors, errors$, ExpressionError, IErrorHandler, IErrorInterceptor, ModuleError, nextError$ } from './error/error'; 11 | export { default as EventDirective } from './event/event.directive'; 12 | export { default as ForItem } from './for/for.item'; 13 | export { default as ForStructure } from './for/for.structure'; 14 | export { default as HrefTargetDirective } from './href/href-target.directive'; 15 | export { default as HrefDirective } from './href/href.directive'; 16 | export { default as IfStructure } from './if/if.structure'; 17 | export { default as InnerHtmlDirective } from './inner-html/inner-html.directive'; 18 | export { default as JsonComponent } from './json/json.component'; 19 | export { default as JsonPipe } from './json/json.pipe'; 20 | export { default as Module, getContextByNode, getHost, getParsableContextByElement } from './module/module'; 21 | export { default as Browser } from './platform/browser'; 22 | export { getLocationComponents, ILocationInit } from './platform/common/location/location'; 23 | export { decodeBase64, decodeJson, default as Serializer, encodeBase64, encodeJson, encodeJsonWithOptions } from './platform/common/serializer/serializer'; 24 | export { default as TransferService, optionsToKey } from './platform/common/transfer/transfer.service'; 25 | export { WINDOW } from './platform/common/window/window'; 26 | export { default as Platform, isPlatformBrowser, isPlatformServer, isPlatformWorker, PLATFORM_BROWSER, PLATFORM_JS_DOM, PLATFORM_NODE, PLATFORM_WEB_WORKER } from './platform/platform'; 27 | export { default as SrcDirective } from './src/src.directive'; 28 | export { default as StyleDirective } from './style/style.directive'; 29 | 30 | -------------------------------------------------------------------------------- /src/platform/common/transfer/transfer.service.ts: -------------------------------------------------------------------------------- 1 | import Serializer, { decodeJson, encodeJson } from "../serializer/serializer"; 2 | 3 | export default class TransferService { 4 | static makeKey(base: string, params?: { [key: string]: any }): string { 5 | const paramsKey: string = params ? optionsToKey(params) : ''; 6 | let key: string = `rxcomp-hydrate-${base}-${paramsKey}`; 7 | key = key.replace(/(\s+)|(\W+)/g, function (...matches) { return matches[1] ? '' : '_' }); 8 | // console.log('TransferService.makeKey', key, base, paramsKey); 9 | return key; 10 | } 11 | static has(key: string): boolean { 12 | const script = document.querySelector(`#${key}`); 13 | return script !== null; 14 | } 15 | static get(key: string): T | undefined; 16 | static get(key: string): { [key: string]: any } | undefined; 17 | static get(key: string): any { 18 | const node = document.querySelector(`#${key}`); 19 | if (node && node.firstChild) { 20 | const json: string | null = node.firstChild.nodeValue; 21 | return json ? Serializer.decode(json, [decodeJson]) : undefined; 22 | } else { 23 | return undefined; 24 | } 25 | } 26 | static set(key: string, value: { [key: string]: any }): void { 27 | // console.log('TransferService.set', key, value); 28 | const json: string | undefined = Serializer.encode(value, [encodeJson]); 29 | if (!json) { 30 | return; 31 | } 32 | const text = document.createTextNode(json); 33 | let node = document.querySelector(`#${key}`); 34 | if (!node) { 35 | node = document.createElement('script'); 36 | node.setAttribute('id', key); 37 | node.setAttribute('type', 'text/template'); 38 | // console.log('node', node!!, 'document', document!!, 'head', document.head!!); 39 | node.append(text); 40 | document.head!.append(node); 41 | } else { 42 | node.replaceChild(text, node.firstChild!); 43 | } 44 | } 45 | static remove(key: string): void { 46 | let node = document.querySelector(`#${key}`); 47 | if (node && node.parentNode) { 48 | node.parentNode.removeChild(node); 49 | } 50 | } 51 | } 52 | export function optionsToKey(v: any, s: string = ''): string { 53 | if (typeof v === 'number') { 54 | s += '-' + v.toString(); 55 | } else if (typeof v === 'string') { 56 | s += '-' + v.substr(0, 20); 57 | } else if (v && Array.isArray(v)) { 58 | s += '-' + v.map(v => optionsToKey(v)).join(''); 59 | } else if (v && typeof v === 'object') { 60 | s += '-' + Object.keys(v).map(k => k + optionsToKey(v[k])).join('-'); 61 | } 62 | return s; 63 | } 64 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to the "rxcomp" library will be documented in this file. 3 | 4 | --- 5 | 6 | ## [1.0.0-beta.21] - 2022-03-21 7 | ### Fixing 8 | - ES6 calling module constructor without new 9 | 10 | --- 11 | 12 | ## [1.0.0-beta.20] - 2020-11-25 13 | ### Fixing 14 | - IE11 DomTokenList 15 | 16 | --- 17 | 18 | ## [1.0.0-beta.19] - 2020-10-19 19 | ### Fixing 20 | - Root Component Inputs 21 | 22 | --- 23 | 24 | ## [1.0.0-beta.18] - 2020-09-08 25 | ### Fixing 26 | - TextNode Parser 27 | 28 | --- 29 | 30 | ## [1.0.0-beta.14] - 2020-08-29 31 | ### Added 32 | - Platform Browser, getLocationComponents, Serializer, TransferService 33 | 34 | --- 35 | 36 | ## [1.0.0-beta.12] - 2020-08-06 37 | ### Updating 38 | - Dependancies 39 | 40 | --- 41 | 42 | ## [1.0.0-beta.11] - 2020-07-25 43 | ### Fixing 44 | - Context, TextNode Parser 45 | ### Modified 46 | - JsonPipe 47 | ### Added 48 | - JsonComponent 49 | 50 | --- 51 | 52 | ## [1.0.0-beta.10] - 2020-05-08 53 | ### Modified 54 | - SrcDirective, HrefDirective & InnerHtmlDirective 55 | 56 | --- 57 | 58 | ## [1.0.0-beta.9] - 2020-04-10 59 | ### Fixing 60 | - IE11 Support 61 | 62 | --- 63 | 64 | ## [1.0.0-beta.8] - 2020-03-05 65 | ### Fixing 66 | - Inputs, Outputs 67 | 68 | --- 69 | 70 | ## [1.0.0-beta.7] - 2020-03-04 71 | ### Refactoring 72 | - Typescript version 73 | 74 | --- 75 | 76 | ## [1.0.0-beta.5] - 2020-02-06 77 | ### Fixing 78 | - ForStructure, html attributes 79 | 80 | --- 81 | 82 | ## [1.0.0-beta.2] - 2020-01-22 83 | ### Added 84 | - SrcDirective, HrefDirective 85 | 86 | --- 87 | 88 | ## [1.0.0-beta.1] - 2019-12-25 89 | ### Modified 90 | - Optimized expression evaluation 91 | 92 | --- 93 | 94 | ## [1.0.0-alpha.14] - 2019-12-15 95 | ### Fixing 96 | - Destroy phase 97 | 98 | --- 99 | 100 | ## [1.0.0-alpha.11] - 2019-12-07 101 | ### Added 102 | - meta hosts { key: Factory } 103 | 104 | --- 105 | 106 | ## [1.0.0-alpha.8] - 2019-12-06 107 | ### Added 108 | - :not selector 109 | ### Fixing 110 | - TextNode parser 111 | 112 | --- 113 | 114 | ## [1.0.0-alpha.7] - 2019-12-03 115 | ### Fixing 116 | - Component scope 117 | 118 | --- 119 | 120 | ## [1.0.0-alpha.6] - 2019-12-01 121 | ### Added 122 | - Module import / export 123 | 124 | --- 125 | 126 | ## [1.0.0-alpha.5] - 2019-11-21 127 | ### Added 128 | - Initial release of RxComp library 129 | 130 | --- 131 | 132 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. 133 | -------------------------------------------------------------------------------- /dist/esm/platform/common/transfer/transfer.service.js: -------------------------------------------------------------------------------- 1 | import Serializer, { decodeJson, encodeJson } from "../serializer/serializer"; 2 | export default class TransferService { 3 | static makeKey(base, params) { 4 | const paramsKey = params ? optionsToKey(params) : ''; 5 | let key = `rxcomp-hydrate-${base}-${paramsKey}`; 6 | key = key.replace(/(\s+)|(\W+)/g, function (...matches) { return matches[1] ? '' : '_'; }); 7 | // console.log('TransferService.makeKey', key, base, paramsKey); 8 | return key; 9 | } 10 | static has(key) { 11 | const script = document.querySelector(`#${key}`); 12 | return script !== null; 13 | } 14 | static get(key) { 15 | const node = document.querySelector(`#${key}`); 16 | if (node && node.firstChild) { 17 | const json = node.firstChild.nodeValue; 18 | return json ? Serializer.decode(json, [decodeJson]) : undefined; 19 | } 20 | else { 21 | return undefined; 22 | } 23 | } 24 | static set(key, value) { 25 | // console.log('TransferService.set', key, value); 26 | const json = Serializer.encode(value, [encodeJson]); 27 | if (!json) { 28 | return; 29 | } 30 | const text = document.createTextNode(json); 31 | let node = document.querySelector(`#${key}`); 32 | if (!node) { 33 | node = document.createElement('script'); 34 | node.setAttribute('id', key); 35 | node.setAttribute('type', 'text/template'); 36 | // console.log('node', node!!, 'document', document!!, 'head', document.head!!); 37 | node.append(text); 38 | document.head.append(node); 39 | } 40 | else { 41 | node.replaceChild(text, node.firstChild); 42 | } 43 | } 44 | static remove(key) { 45 | let node = document.querySelector(`#${key}`); 46 | if (node && node.parentNode) { 47 | node.parentNode.removeChild(node); 48 | } 49 | } 50 | } 51 | export function optionsToKey(v, s = '') { 52 | if (typeof v === 'number') { 53 | s += '-' + v.toString(); 54 | } 55 | else if (typeof v === 'string') { 56 | s += '-' + v.substr(0, 20); 57 | } 58 | else if (v && Array.isArray(v)) { 59 | s += '-' + v.map(v => optionsToKey(v)).join(''); 60 | } 61 | else if (v && typeof v === 'object') { 62 | s += '-' + Object.keys(v).map(k => k + optionsToKey(v[k])).join('-'); 63 | } 64 | return s; 65 | } 66 | -------------------------------------------------------------------------------- /dist/rxcomp-dark.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["dist/rxcomp-dark.css"],"names":[],"mappings":"AAAA,WAQE,oBAAqB,CASrB,eAAgB,CADhB,6BAA8B,CAE9B,aAAc,CAjBd,YAAa,CACb,qBAAsB,CAWtB,qBAAsB,CACtB,cAAe,CAXf,0BAA2B,CAY3B,eAAgB,CAVhB,eAAkB,CAClB,aAAc,CAFd,SAAU,CAGV,uBAAwB,CAGxB,wBAAyB,CACrB,oBAAqB,CACjB,gBAAiB,CAHzB,eAUF,CAEA,UAGE,kBAAmB,CAFnB,YAAa,CACb,6BAEF,CACA,mCACE,aAAc,CACd,WACF,CACA,iBAIE,kBAAmB,CAGnB,cAAe,CALf,YAAa,CADb,0BAA2B,CAE3B,0BAA2B,CAG3B,eAAgB,CADhB,sBAGF,CACA,kBAGE,cAAe,CAFf,aAAc,CACd,eAEF,CAEA,UACE,YAAa,CACb,qBAAsB,CACtB,eAAgB,CAChB,QAAS,CACT,SACF,CACA,gBAGE,sBAAuB,CAEvB,4BAAgC,CAJhC,YAAa,CACb,6BAA8B,CAE9B,kBAEF,CACA,2BACE,kBACF,CACA,oEACE,aAAc,CACd,WACF,CACA,kDAEE,eAAgB,CADhB,sBAEF,CACA,iBACE,0BAA2B,CAC3B,sBAAuB,CACvB,cAAe,CACf,eACF,CACA,gBACE,YACF,CACA,iBACE,yBAA0B,CAC1B,eACF,CACA,kBAGE,cAAe,CAFf,aAAc,CACd,eAEF","file":"dist\\rxcomp-dark.min.css","sourcesContent":[".rxc-block {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n padding: 0;\n margin: 10px 0 0 0;\n overflow: auto;\n page-break-inside: avoid;\n word-wrap: break-word;\n white-space: pre;\n -webkit-user-select: none;\n -ms-user-select: none;\n user-select: none;\n font-family: monospace;\n font-size: 13px;\n line-height: 1.2;\n border-left: 3px solid #003adc;\n background: #333;\n color: #8f929b;\n}\n\n.rxc-head {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.rxc-head__title, .rxc-head__remove {\n flex: 1 1 auto;\n padding: 5px;\n}\n.rxc-head__title {\n flex: 1 1 calc(100% - 20px);\n display: flex;\n justify-content: flex-start;\n align-items: center;\n text-overflow: ellipsis;\n overflow: hidden;\n cursor: pointer;\n}\n.rxc-head__remove {\n flex: 1 1 20px;\n margin-left: 5px;\n cursor: pointer;\n}\n\n.rxc-list {\n display: flex;\n flex-direction: column;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n.rxc-list__item {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n padding-bottom: 2px;\n border-bottom: 1px solid #222222;\n}\n.rxc-list__item:last-child {\n border-bottom: none;\n}\n.rxc-list__title, .rxc-list__name, .rxc-list__value, .rxc-list__remove {\n flex: 1 1 auto;\n padding: 5px;\n}\n.rxc-list__title, .rxc-list__name, .rxc-list__value {\n text-overflow: ellipsis;\n overflow: hidden;\n}\n.rxc-list__title {\n flex: 1 1 calc(100% - 20px);\n font-family: sans-serif;\n font-size: 16px;\n font-weight: 500;\n}\n.rxc-list__name {\n flex: 1 1 30%;\n}\n.rxc-list__value {\n flex: 1 1 calc(70% - 20px);\n margin-left: 5px;\n}\n.rxc-list__remove {\n flex: 1 1 20px;\n margin-left: 5px;\n cursor: pointer;\n}"]} -------------------------------------------------------------------------------- /dist/rxcomp-light.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["dist/rxcomp-light.css"],"names":[],"mappings":"AAAA,WAQE,oBAAqB,CASrB,kBAAmB,CADnB,6BAA8B,CAE9B,aAAc,CAjBd,YAAa,CACb,qBAAsB,CAWtB,qBAAsB,CACtB,cAAe,CAXf,0BAA2B,CAY3B,eAAgB,CAVhB,eAAkB,CAClB,aAAc,CAFd,SAAU,CAGV,uBAAwB,CAGxB,wBAAyB,CACrB,oBAAqB,CACjB,gBAAiB,CAHzB,eAUF,CAEA,UAGE,kBAAmB,CAFnB,YAAa,CACb,6BAEF,CACA,mCACE,aAAc,CACd,WACF,CACA,iBAIE,kBAAmB,CAGnB,cAAe,CALf,YAAa,CADb,0BAA2B,CAE3B,0BAA2B,CAG3B,eAAgB,CADhB,sBAGF,CACA,kBAGE,cAAe,CAFf,aAAc,CACd,eAEF,CAEA,UACE,YAAa,CACb,qBAAsB,CACtB,eAAgB,CAChB,QAAS,CACT,SACF,CACA,gBAGE,sBAAuB,CAEvB,4BAAgC,CAJhC,YAAa,CACb,6BAA8B,CAE9B,kBAEF,CACA,2BACE,kBACF,CACA,oEACE,aAAc,CACd,WACF,CACA,kDAEE,eAAgB,CADhB,sBAEF,CACA,iBACE,0BAA2B,CAC3B,sBAAuB,CACvB,cAAe,CACf,eACF,CACA,gBACE,YACF,CACA,iBACE,yBAA0B,CAC1B,eACF,CACA,kBAGE,cAAe,CAFf,aAAc,CACd,eAEF","file":"dist\\rxcomp-light.min.css","sourcesContent":[".rxc-block {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n padding: 0;\n margin: 10px 0 0 0;\n overflow: auto;\n page-break-inside: avoid;\n word-wrap: break-word;\n white-space: pre;\n -webkit-user-select: none;\n -ms-user-select: none;\n user-select: none;\n font-family: monospace;\n font-size: 13px;\n line-height: 1.2;\n border-left: 3px solid #003adc;\n background: #f3f3f3;\n color: #8f929b;\n}\n\n.rxc-head {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.rxc-head__title, .rxc-head__remove {\n flex: 1 1 auto;\n padding: 5px;\n}\n.rxc-head__title {\n flex: 1 1 calc(100% - 20px);\n display: flex;\n justify-content: flex-start;\n align-items: center;\n text-overflow: ellipsis;\n overflow: hidden;\n cursor: pointer;\n}\n.rxc-head__remove {\n flex: 1 1 20px;\n margin-left: 5px;\n cursor: pointer;\n}\n\n.rxc-list {\n display: flex;\n flex-direction: column;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n.rxc-list__item {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n padding-bottom: 2px;\n border-bottom: 1px solid #222222;\n}\n.rxc-list__item:last-child {\n border-bottom: none;\n}\n.rxc-list__title, .rxc-list__name, .rxc-list__value, .rxc-list__remove {\n flex: 1 1 auto;\n padding: 5px;\n}\n.rxc-list__title, .rxc-list__name, .rxc-list__value {\n text-overflow: ellipsis;\n overflow: hidden;\n}\n.rxc-list__title {\n flex: 1 1 calc(100% - 20px);\n font-family: sans-serif;\n font-size: 16px;\n font-weight: 500;\n}\n.rxc-list__name {\n flex: 1 1 30%;\n}\n.rxc-list__value {\n flex: 1 1 calc(70% - 20px);\n margin-left: 5px;\n}\n.rxc-list__remove {\n flex: 1 1 20px;\n margin-left: 5px;\n cursor: pointer;\n}"]} -------------------------------------------------------------------------------- /docs/css/rxcomp-dark.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["docs/css/rxcomp-dark.css"],"names":[],"mappings":"AAAA,WAQE,oBAAqB,CASrB,eAAgB,CADhB,6BAA8B,CAE9B,aAAc,CAjBd,YAAa,CACb,qBAAsB,CAWtB,qBAAsB,CACtB,cAAe,CAXf,0BAA2B,CAY3B,eAAgB,CAVhB,eAAkB,CAClB,aAAc,CAFd,SAAU,CAGV,uBAAwB,CAGxB,wBAAyB,CACrB,oBAAqB,CACjB,gBAAiB,CAHzB,eAUF,CAEA,UAGE,kBAAmB,CAFnB,YAAa,CACb,6BAEF,CACA,mCACE,aAAc,CACd,WACF,CACA,iBAIE,kBAAmB,CAGnB,cAAe,CALf,YAAa,CADb,0BAA2B,CAE3B,0BAA2B,CAG3B,eAAgB,CADhB,sBAGF,CACA,kBAGE,cAAe,CAFf,aAAc,CACd,eAEF,CAEA,UACE,YAAa,CACb,qBAAsB,CACtB,eAAgB,CAChB,QAAS,CACT,SACF,CACA,gBAGE,sBAAuB,CAEvB,4BAAgC,CAJhC,YAAa,CACb,6BAA8B,CAE9B,kBAEF,CACA,2BACE,kBACF,CACA,oEACE,aAAc,CACd,WACF,CACA,kDAEE,eAAgB,CADhB,sBAEF,CACA,iBACE,0BAA2B,CAC3B,sBAAuB,CACvB,cAAe,CACf,eACF,CACA,gBACE,YACF,CACA,iBACE,yBAA0B,CAC1B,eACF,CACA,kBAGE,cAAe,CAFf,aAAc,CACd,eAEF","file":"docs\\css\\rxcomp-dark.min.css","sourcesContent":[".rxc-block {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n padding: 0;\n margin: 10px 0 0 0;\n overflow: auto;\n page-break-inside: avoid;\n word-wrap: break-word;\n white-space: pre;\n -webkit-user-select: none;\n -ms-user-select: none;\n user-select: none;\n font-family: monospace;\n font-size: 13px;\n line-height: 1.2;\n border-left: 3px solid #003adc;\n background: #333;\n color: #8f929b;\n}\n\n.rxc-head {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.rxc-head__title, .rxc-head__remove {\n flex: 1 1 auto;\n padding: 5px;\n}\n.rxc-head__title {\n flex: 1 1 calc(100% - 20px);\n display: flex;\n justify-content: flex-start;\n align-items: center;\n text-overflow: ellipsis;\n overflow: hidden;\n cursor: pointer;\n}\n.rxc-head__remove {\n flex: 1 1 20px;\n margin-left: 5px;\n cursor: pointer;\n}\n\n.rxc-list {\n display: flex;\n flex-direction: column;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n.rxc-list__item {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n padding-bottom: 2px;\n border-bottom: 1px solid #222222;\n}\n.rxc-list__item:last-child {\n border-bottom: none;\n}\n.rxc-list__title, .rxc-list__name, .rxc-list__value, .rxc-list__remove {\n flex: 1 1 auto;\n padding: 5px;\n}\n.rxc-list__title, .rxc-list__name, .rxc-list__value {\n text-overflow: ellipsis;\n overflow: hidden;\n}\n.rxc-list__title {\n flex: 1 1 calc(100% - 20px);\n font-family: sans-serif;\n font-size: 16px;\n font-weight: 500;\n}\n.rxc-list__name {\n flex: 1 1 30%;\n}\n.rxc-list__value {\n flex: 1 1 calc(70% - 20px);\n margin-left: 5px;\n}\n.rxc-list__remove {\n flex: 1 1 20px;\n margin-left: 5px;\n cursor: pointer;\n}"]} -------------------------------------------------------------------------------- /docs/css/rxcomp-light.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["docs/css/rxcomp-light.css"],"names":[],"mappings":"AAAA,WAQE,oBAAqB,CASrB,kBAAmB,CADnB,6BAA8B,CAE9B,aAAc,CAjBd,YAAa,CACb,qBAAsB,CAWtB,qBAAsB,CACtB,cAAe,CAXf,0BAA2B,CAY3B,eAAgB,CAVhB,eAAkB,CAClB,aAAc,CAFd,SAAU,CAGV,uBAAwB,CAGxB,wBAAyB,CACrB,oBAAqB,CACjB,gBAAiB,CAHzB,eAUF,CAEA,UAGE,kBAAmB,CAFnB,YAAa,CACb,6BAEF,CACA,mCACE,aAAc,CACd,WACF,CACA,iBAIE,kBAAmB,CAGnB,cAAe,CALf,YAAa,CADb,0BAA2B,CAE3B,0BAA2B,CAG3B,eAAgB,CADhB,sBAGF,CACA,kBAGE,cAAe,CAFf,aAAc,CACd,eAEF,CAEA,UACE,YAAa,CACb,qBAAsB,CACtB,eAAgB,CAChB,QAAS,CACT,SACF,CACA,gBAGE,sBAAuB,CAEvB,4BAAgC,CAJhC,YAAa,CACb,6BAA8B,CAE9B,kBAEF,CACA,2BACE,kBACF,CACA,oEACE,aAAc,CACd,WACF,CACA,kDAEE,eAAgB,CADhB,sBAEF,CACA,iBACE,0BAA2B,CAC3B,sBAAuB,CACvB,cAAe,CACf,eACF,CACA,gBACE,YACF,CACA,iBACE,yBAA0B,CAC1B,eACF,CACA,kBAGE,cAAe,CAFf,aAAc,CACd,eAEF","file":"docs\\css\\rxcomp-light.min.css","sourcesContent":[".rxc-block {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n padding: 0;\n margin: 10px 0 0 0;\n overflow: auto;\n page-break-inside: avoid;\n word-wrap: break-word;\n white-space: pre;\n -webkit-user-select: none;\n -ms-user-select: none;\n user-select: none;\n font-family: monospace;\n font-size: 13px;\n line-height: 1.2;\n border-left: 3px solid #003adc;\n background: #f3f3f3;\n color: #8f929b;\n}\n\n.rxc-head {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.rxc-head__title, .rxc-head__remove {\n flex: 1 1 auto;\n padding: 5px;\n}\n.rxc-head__title {\n flex: 1 1 calc(100% - 20px);\n display: flex;\n justify-content: flex-start;\n align-items: center;\n text-overflow: ellipsis;\n overflow: hidden;\n cursor: pointer;\n}\n.rxc-head__remove {\n flex: 1 1 20px;\n margin-left: 5px;\n cursor: pointer;\n}\n\n.rxc-list {\n display: flex;\n flex-direction: column;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n.rxc-list__item {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n padding-bottom: 2px;\n border-bottom: 1px solid #222222;\n}\n.rxc-list__item:last-child {\n border-bottom: none;\n}\n.rxc-list__title, .rxc-list__name, .rxc-list__value, .rxc-list__remove {\n flex: 1 1 auto;\n padding: 5px;\n}\n.rxc-list__title, .rxc-list__name, .rxc-list__value {\n text-overflow: ellipsis;\n overflow: hidden;\n}\n.rxc-list__title {\n flex: 1 1 calc(100% - 20px);\n font-family: sans-serif;\n font-size: 16px;\n font-weight: 500;\n}\n.rxc-list__name {\n flex: 1 1 30%;\n}\n.rxc-list__value {\n flex: 1 1 calc(70% - 20px);\n margin-left: 5px;\n}\n.rxc-list__remove {\n flex: 1 1 20px;\n margin-left: 5px;\n cursor: pointer;\n}"]} -------------------------------------------------------------------------------- /src/core/types.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from 'rxjs'; 2 | import Module from '../module/module'; 3 | import Factory from './factory'; 4 | import Pipe from './pipe'; 5 | 6 | declare global { 7 | interface Window { 8 | [key: string]: any; // extensible object 9 | } 10 | } 11 | export type PipeMap = { [key: string]: typeof Pipe }; 12 | export type PipeList = (typeof Pipe)[]; 13 | export type FactoryList = (typeof Factory)[]; 14 | export type MatchFunction = (node: HTMLElement) => boolean; 15 | export type SelectorFunction = (node: HTMLElement) => ISelectorResult | false; 16 | export type ExpressionFunction = (payload: any, module: Module) => any; 17 | export interface Type extends Function { new(...args: any[]): T; } 18 | export interface IContext { 19 | module: Module; 20 | instance: Factory; 21 | parentInstance: Factory | Window; 22 | node: IElement; 23 | factory: typeof Factory; 24 | selector: string; 25 | inputs?: { [key: string]: ExpressionFunction }; 26 | outputs?: { [key: string]: Observable }; 27 | keys?: string[]; 28 | } 29 | export interface IModuleMeta { 30 | declarations?: (typeof Factory | typeof Pipe)[]; 31 | exports?: (typeof Factory | typeof Pipe)[]; 32 | imports?: typeof Module[]; 33 | pipes?: { [key: string]: typeof Pipe }; 34 | factories?: typeof Factory[]; 35 | selectors?: SelectorFunction[]; 36 | bootstrap?: typeof Factory; 37 | node?: IElement; 38 | nodeInnerHTML?: string; 39 | } 40 | export interface IModuleParsedImportedMeta { 41 | imports: IModuleParsedImportedMeta[]; 42 | declarations: (typeof Factory | typeof Pipe)[]; 43 | pipes: { [key: string]: typeof Pipe }; 44 | exports: (typeof Factory | typeof Pipe)[]; 45 | } 46 | export interface IModuleParsedMeta { 47 | imports: typeof Module[]; 48 | factories: typeof Factory[]; 49 | pipes: { [key: string]: typeof Pipe }; 50 | selectors: SelectorFunction[]; 51 | bootstrap: typeof Factory; 52 | node: IElement; 53 | nodeInnerHTML: string; 54 | } 55 | export interface IFactoryMeta { 56 | selector?: string; 57 | hosts?: { [key: string]: typeof Factory }; 58 | inputs?: string[]; 59 | outputs?: string[]; 60 | template?: string; 61 | } 62 | export interface IPipeMeta { 63 | name: string; 64 | } 65 | export interface ISelectorResult { 66 | node: IElement; 67 | factory: typeof Factory; 68 | selector: string; 69 | } 70 | export interface IElement extends HTMLElement { 71 | rxcompId?: number; 72 | } 73 | export interface IComment extends Comment { 74 | rxcompId?: number; 75 | } 76 | export interface IText extends Text { 77 | nodeExpressions?: (ExpressionFunction | string)[]; 78 | } 79 | export interface IForExpressionTokens { 80 | key: string; 81 | value: string; 82 | iterable: string; 83 | } 84 | -------------------------------------------------------------------------------- /dist/cjs/platform/browser.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var tslib_1 = require("tslib"); 4 | var error_1 = require("../error/error"); 5 | var window_1 = require("./common/window/window"); 6 | var platform_1 = tslib_1.__importStar(require("./platform")); 7 | var Browser = /** @class */ (function (_super) { 8 | tslib_1.__extends(Browser, _super); 9 | function Browser() { 10 | return _super !== null && _super.apply(this, arguments) || this; 11 | } 12 | /** 13 | * @param moduleFactory 14 | * @description This method returns a Browser compiled module 15 | */ 16 | Browser.bootstrap = function (moduleFactory) { 17 | var _a; 18 | if (!platform_1.isPlatformBrowser) { 19 | throw new error_1.ModuleError('missing platform browser, Window not found'); 20 | } 21 | if (!moduleFactory) { 22 | throw new error_1.ModuleError('missing moduleFactory'); 23 | } 24 | if (!moduleFactory.meta) { 25 | throw new error_1.ModuleError('missing moduleFactory meta'); 26 | } 27 | if (!moduleFactory.meta.bootstrap) { 28 | throw new error_1.ModuleError('missing bootstrap'); 29 | } 30 | if (!moduleFactory.meta.bootstrap.meta) { 31 | throw new error_1.ModuleError('missing bootstrap meta'); 32 | } 33 | if (!moduleFactory.meta.bootstrap.meta.selector) { 34 | throw new error_1.ModuleError('missing bootstrap meta selector'); 35 | } 36 | var meta = this.resolveMeta(moduleFactory); 37 | var module = new moduleFactory(); 38 | module.meta = meta; 39 | meta.imports.forEach(function (moduleFactory) { 40 | moduleFactory.prototype.onInit.call(module); 41 | }); 42 | if (window_1.WINDOW.rxcomp_hydrate_) { 43 | var clonedNode = meta.node.cloneNode(); 44 | clonedNode.innerHTML = meta.nodeInnerHTML = window_1.WINDOW.rxcomp_hydrate_.innerHTML; 45 | var instances = module.compile(clonedNode, window_1.WINDOW); 46 | module.instances = instances; 47 | var root = instances[0]; 48 | root.pushChanges(); 49 | (_a = meta.node.parentNode) === null || _a === void 0 ? void 0 : _a.replaceChild(clonedNode, meta.node); 50 | } 51 | else { 52 | var instances = module.compile(meta.node, window_1.WINDOW); 53 | module.instances = instances; 54 | var root = instances[0]; 55 | root.pushChanges(); 56 | } 57 | return module; 58 | }; 59 | return Browser; 60 | }(platform_1.default)); 61 | exports.default = Browser; 62 | -------------------------------------------------------------------------------- /web/client/test.parsing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
    6 |
  • 7 |
    8 |
  • 9 |
  • 10 |
    11 |
  • 12 |
  • 13 |
    valueUndefined {{valueUndefined}}
    14 |
  • 15 |
  • 16 |
    valueUndefined  
    17 |
  • 18 |
  • 19 |
    {{valueUndefined || valueDefined}}
    20 |
  • 21 |
  • 22 |
     
    23 |
  • 24 |
  • 25 |
    {{ticks}}
    26 |
  • 27 |
  • 28 |
    {{{ a: { b: 1 } } | json}}
    29 |
  • 30 |
  • 31 |
    {{items | json}}
    32 |
  • 33 |
  • 34 |
    class
    35 |
  • 36 |
  • 37 |
    38 |
  • 39 |
  • 40 |
    41 |
  • 42 |
  • 43 |
    [{{item}}] {{{index}}, {{count}}, {{first}}, {{last}}, {{even}}, {{odd}}}
    44 |
  • 45 |
  • 46 |
    47 |
  • 48 |
  • 49 |
    50 |
  • 51 |
  • 52 |
    53 |
  • 54 |
  • 55 |
    56 |
  • 57 |
  • 58 |
    59 |
  • 60 |
  • 61 |
    62 |
  • 63 |
  • 64 |
    object.a {{object.a}}
    65 |
  • 66 |
  • 67 |
    {{object.a + ' ' + object.b}}
    68 |
  • 69 |
70 |
71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /web/client/css/_components/_buttons.scss: -------------------------------------------------------------------------------- 1 | a, 2 | button, 3 | [ng-reflect-router-link], 4 | .btn { 5 | display: inline-block; 6 | padding: 0; 7 | border: none; 8 | outline: none; 9 | background: none; 10 | appearance: none; 11 | cursor: pointer; 12 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 13 | // transition: ease-in-out 350ms; 14 | // transition-property: background-color, color, border, opacity; 15 | 16 | &, 17 | &:active, 18 | &:focus, 19 | &:hover, 20 | &:visited { 21 | color: inherit; 22 | text-decoration: none; 23 | outline: none; 24 | } 25 | 26 | /* 27 | &:hover { 28 | box-shadow: 0 10px 10px -5px rgba(0, 0, 0, 0.15); 29 | } 30 | */ 31 | 32 | &[disabled] { 33 | opacity: 0.5; 34 | pointer-events: none; 35 | } 36 | } 37 | 38 | .btn--primary { 39 | display: inline-block; 40 | 41 | &:hover, 42 | &:focus { 43 | 44 | span { 45 | color: #fff; 46 | border-color: $foreground-primary; 47 | background: $foreground-primary; 48 | transition: all ease-in-out .2s; 49 | } 50 | } 51 | 52 | span { 53 | display: inline-block; 54 | padding: 15px 50px; 55 | font-size: 13px; 56 | font-weight: $font-regular; 57 | color: $foreground-primary; 58 | border: 2px solid $foreground-primary; 59 | border-radius: 500px; 60 | transition: all ease-in-out .2s; 61 | font-family: $font-primary; 62 | } 63 | 64 | b { 65 | font-weight: $font-semibold; 66 | text-transform: uppercase; 67 | } 68 | 69 | .section--negative & { 70 | span { 71 | color: $foreground-negative; 72 | border-color: $foreground-negative; 73 | } 74 | 75 | &, 76 | &:active, 77 | &:focus, 78 | &:hover, 79 | &:visited { 80 | span { 81 | color: $foreground-negative; 82 | border-color: $foreground-negative; 83 | } 84 | } 85 | } 86 | 87 | @include media-breakpoint-down(xs) { 88 | display: block; 89 | } 90 | } 91 | 92 | .btn--secondary { 93 | display: inline-block; 94 | 95 | span { 96 | display: inline-block; 97 | padding: 15px 50px; 98 | text-transform: uppercase; 99 | font-size: 13px; 100 | font-weight: $font-semibold; 101 | color: #fff; 102 | background: $foreground-primary; 103 | border-radius: 50px; 104 | font-family: $font-primary; 105 | } 106 | 107 | &, 108 | &:active, 109 | &:focus, 110 | &:hover, 111 | &:visited { 112 | span { 113 | color: #fff; 114 | } 115 | } 116 | 117 | .section--negative & { 118 | span { 119 | color: $foreground-negative; 120 | border-color: $foreground-negative; 121 | } 122 | 123 | &, 124 | &:active, 125 | &:focus, 126 | &:hover, 127 | &:visited { 128 | span { 129 | color: $foreground-negative; 130 | border-color: $foreground-negative; 131 | } 132 | } 133 | } 134 | 135 | @include media-breakpoint-down(xs) { 136 | display: block; 137 | } 138 | } 139 | --------------------------------------------------------------------------------