Skip to content

Commit

Permalink
refactor(Root): Use index.ts exports in server.ts
Browse files Browse the repository at this point in the history
  • Loading branch information
eanorambuena committed Jul 24, 2024
1 parent de72d26 commit 8fc6530
Show file tree
Hide file tree
Showing 8 changed files with 4,560 additions and 567 deletions.
5 changes: 2 additions & 3 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,16 @@ export type MetaProps = {
children: () => string;
};
export type HTMLGenerator = ((props: EmmyComponent) => string) | ((component?: EmmyComponent) => string) | (() => string);
export type HTMLGeneratorGenerator = ((component: EmmyComponent) => HTMLGenerator) | ((component?: EmmyComponent) => HTMLGenerator) | (() => HTMLGenerator);
type Render = string | (() => string);
export type FunctionalComponentHtmlGenerator = ((props: MetaProps) => Render) | ((props?: MetaProps) => Render) | (() => Render);
export type FunctionalComponentGenerator = ((props: MetaProps) => Render) | ((props?: MetaProps) => Render) | (() => Render);
export type Callback = ((component: EmmyComponent) => void) | ((component?: EmmyComponent) => void) | (() => void);
declare global {
interface Window {
route: (event: Event) => void;
}
}
export type ClassComponent = Component | LightComponent;
export type ComponentType = ClassComponent | FunctionalComponent | FunctionalComponentHtmlGenerator | RouteString;
export type ComponentType = ClassComponent | FunctionalComponent | FunctionalComponentGenerator | RouteString;
export declare abstract class EmmyComponent extends HTMLElement {
contentGenerator: HTMLGenerator;
callback: Callback;
Expand Down
70 changes: 3 additions & 67 deletions dist/server.d.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,9 @@
import { UseEffect, UseState } from './hooks.js';
import { RouteString, StyleObject } from './utils.js';
export { useEffect, useState } from './hooks.js';
export { Emmy, loadGlobalEmmy, RouteString, StyleObject, capitalizeFirstLetter, uncapitalizeFirstLetter, createInlineStyle, parseCSS, html, javascript, processGenerator, routerClassNames, vanillaElement } from './utils.js';
export declare const jsx: any;
export type MetaProps = {
el: EmmyComponent;
props: () => object;
children: () => string;
};
export type HTMLGenerator = ((props: EmmyComponent) => string) | ((component?: EmmyComponent) => string) | (() => string);
export type HTMLGeneratorGenerator = ((component: EmmyComponent) => HTMLGenerator) | ((component?: EmmyComponent) => HTMLGenerator) | (() => HTMLGenerator);
type Render = string | (() => string);
export type FunctionalComponentHtmlGenerator = ((props: MetaProps) => Render) | ((props?: MetaProps) => Render) | (() => Render);
export type Callback = ((component: EmmyComponent) => void) | ((component?: EmmyComponent) => void) | (() => void);
declare global {
interface Window {
route: (event: Event) => void;
}
}
export type ClassComponent = Component | LightComponent;
export type ComponentType = ClassComponent | FunctionalComponent | FunctionalComponentHtmlGenerator | RouteString;
import { EmmyComponent, FunctionalComponent, HTMLGenerator, ClassComponent } from '../src/index.js';
export * from '../src/index.js';
type HTMLGeneratorGenerator = ((component: EmmyComponent) => HTMLGenerator) | ((component?: EmmyComponent) => HTMLGenerator) | (() => HTMLGenerator);
export type BuildOptions = {
dependencies: string;
template: string;
Expand All @@ -29,54 +13,6 @@ export type BuildOptions = {
};
path?: string;
};
declare abstract class EmmyComponent extends HTMLElement {
contentGenerator: HTMLGenerator;
callback: Callback;
Style: StyleObject;
constructor();
addStyle(style: StyleObject): void;
abstract connectedCallback(): void;
render(generator: string | HTMLGenerator, callback?: Callback): void;
abstract __querySelector(selector: string): HTMLElement | null;
querySelector(selector: string): HTMLElement | null;
}
export declare class Component extends EmmyComponent {
constructor();
connectedCallback(): void;
__querySelector(selector: string): HTMLElement | null;
}
export declare class LightComponent extends EmmyComponent {
connectedCallback(): void;
__querySelector(selector: string): HTMLElement | null;
}
export declare class FunctionalComponent extends LightComponent {
effectCallback: (component: FunctionalComponent) => void;
useState: UseState;
useEffect: UseEffect;
constructor(func: HTMLGenerator);
get props(): object;
set props(props: object);
connectedCallback(): void;
static get observedAttributes(): string[];
attributeChangedCallback(name: any, oldValue: any, newValue: any): void;
patchState(newState: object): void;
rerender(): void;
state(): any;
setState(newState: object): void;
__querySelector(selector: string): HTMLElement | null;
}
export declare class Route extends LightComponent {
static routes: {
[key: RouteString]: string;
};
constructor();
}
export declare class Router extends LightComponent {
handleLocation: () => void;
constructor();
}
export declare function launch(component: ClassComponent | FunctionalComponent, name: string): ClassComponent | FunctionalComponent;
export declare function load(func: ComponentType, name: string): ClassComponent | FunctionalComponent;
export declare function renderToString(component: ClassComponent | FunctionalComponent): Promise<string>;
export declare function renderFunctionToString(generator: HTMLGeneratorGenerator): string;
export declare function hydrateScript(generator: HTMLGeneratorGenerator, name: string): string;
Expand Down
211 changes: 2 additions & 209 deletions dist/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
};
import jsxToHtml from 'jsx-to-html';
const { render: renderJSX } = jsxToHtml;
import { useEffect, useState } from './hooks.js';
import { Emmy, capitalizeFirstLetter, createInlineStyle, html, javascript, processGenerator, routerClassNames, uncapitalizeFirstLetter, vanillaElement } from './utils.js';
import { Emmy, capitalizeFirstLetter, html, javascript, uncapitalizeFirstLetter, vanillaElement } from './utils.js';
export { useEffect, useState } from './hooks.js';
export { Emmy, loadGlobalEmmy, capitalizeFirstLetter, uncapitalizeFirstLetter, createInlineStyle, parseCSS, html, javascript, processGenerator, routerClassNames, vanillaElement } from './utils.js';
export const jsx = renderJSX;
Expand All @@ -19,213 +18,7 @@ import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const render = require('./ssr');
require('./ssr/register');
class EmmyComponent extends HTMLElement {
constructor() {
super();
this.contentGenerator = () => '';
this.callback = (component) => { };
this.Style = {};
}
addStyle(style) {
for (const [element, elementStyle] of Object.entries(style)) {
this.Style[element] = createInlineStyle(elementStyle);
if (element == 'this') {
this.setAttribute('style', this.Style[element]);
}
}
}
render(generator, callback) {
if (typeof generator !== 'function' && typeof generator !== 'string') {
try {
const htmlFromJSX = jsx(generator);
console.log(htmlFromJSX);
this.contentGenerator = () => htmlFromJSX;
}
catch (e) {
this.contentGenerator = () => generator;
}
}
else if (typeof generator !== 'function') {
this.contentGenerator = () => generator;
}
else {
this.contentGenerator = generator;
}
if (callback && typeof callback === 'function') {
this.callback = callback;
}
}
querySelector(selector) {
this.setAttribute('emmy-hydratation', 'true');
return this;
}
}
export class Component extends EmmyComponent {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
this.shadowRoot.innerHTML = processGenerator(this.contentGenerator(this));
this.callback.call(this, this);
}
__querySelector(selector) {
return this.shadowRoot.querySelector(vanillaElement(selector));
}
}
export class LightComponent extends EmmyComponent {
connectedCallback() {
this.innerHTML = processGenerator(this.contentGenerator(this));
this.callback.call(this, this);
}
__querySelector(selector) {
return HTMLElement.prototype.querySelector.call(this, vanillaElement(selector));
}
}
function bindHooks(component) {
component.useState = useState.bind(component);
component.useEffect = useEffect.bind(component);
}
export class FunctionalComponent extends LightComponent {
constructor(func) {
super();
this.effectCallback = (component) => { };
bindHooks.call(this, this);
this.setState({ rerenderCount: 0 });
const renderFunctionOrString = func.call(this, {
el: this,
props: () => this.props,
children: () => this.innerHTML
});
this.render(renderFunctionOrString);
}
get props() {
return Array.from(this.attributes).reduce((acc, attr) => {
const name = attr.name === 'class' ? 'className' : attr.name;
return Object.assign(Object.assign({}, acc), { [name]: () => this.getAttribute(attr.name) });
}, {});
}
set props(props) {
for (const [key, value] of Object.entries(props)) {
if (key === 'className') {
this.className = value;
continue;
}
this.setAttribute(key, value);
}
}
connectedCallback() {
super.connectedCallback();
this.effectCallback(this);
}
static get observedAttributes() {
return ['state'];
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'state') {
this.connectedCallback();
}
}
patchState(newState) {
const currentState = this.state();
const updatedState = Object.assign(currentState, newState);
this.setState(updatedState);
}
rerender() {
this.patchState({ rerenderCount: this.state().rerenderCount + 1 });
}
state() {
return JSON.parse(this.getAttribute('state').replace(/'/g, '"') || '');
}
setState(newState) {
this.setAttribute('state', JSON.stringify(newState).replace(/"/g, '\''));
}
__querySelector(selector) {
const element = HTMLElement.prototype.querySelector.call(this, vanillaElement(selector));
element.__proto__.addEventListener = (event, callback) => {
const newCallback = (event) => {
callback(event);
this.rerender();
};
HTMLElement.prototype.addEventListener.call(element, event, newCallback);
};
return element;
}
}
export class Route extends LightComponent {
constructor() {
super();
this.render('', () => {
const to = this.getAttribute('to') || '';
const componentName = 'emmy-' + to.toLowerCase();
const path = (this.getAttribute('href') === '/') ? '/root' : this.getAttribute('href') || '/404';
Route.routes[path] = `<${componentName}></${componentName}>`;
});
}
}
Route.routes = {};
export class Router extends LightComponent {
constructor() {
super();
this.className = routerClassNames;
this.handleLocation = () => {
const path = window.location.pathname;
const htmlText = (path === '/' ? Route.routes['/root'] : Route.routes[path])
|| Route.routes['/404'] || html `<h1>404</h1>`;
if (this.innerHTML !== htmlText)
this.innerHTML = htmlText;
};
window.route = (event) => {
event.preventDefault();
const target = event.target;
if (window.location.pathname === target.href)
return;
window.history.pushState({}, '', target.href);
this.handleLocation();
};
window.onpopstate = this.handleLocation;
this.render('', () => this.handleLocation());
}
}
export function launch(component, name) {
if (window.customElements.get(vanillaElement(name))) {
console.warn(`Custom element ${vanillaElement(name)} already defined`);
return component;
}
window.customElements.define(vanillaElement(name), component);
return component;
}
function createPageComponent(url, name) {
let component;
() => __awaiter(this, void 0, void 0, function* () {
const result = yield fetch(url);
const htmlText = yield result.text();
component = load(() => htmlText, name);
});
return component;
}
export function load(func, name) {
if (typeof func === 'string') {
return createPageComponent(func, name);
}
try {
const instance = new func();
if (instance instanceof Component || instance instanceof LightComponent || instance instanceof FunctionalComponent) {
return launch(func, name);
}
throw new Error('Not a valid component');
}
catch (e) {
class X extends FunctionalComponent {
constructor() {
super(func);
}
}
return launch(X, name);
}
}
load(Route, 'Route');
load(Router, 'Router');
export * from '../src/index.js';
export function renderToString(component) {
return __awaiter(this, void 0, void 0, function* () {
const instance = new component();
Expand Down
Loading

0 comments on commit 8fc6530

Please sign in to comment.