@relax.js/core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +188 -0
- package/dist/DataLoader.d.ts +51 -0
- package/dist/DependencyInjection.d.ts +271 -0
- package/dist/DependencyInjectionOld.d.ts +35 -0
- package/dist/Metadata.d.ts +8 -0
- package/dist/SequentialId.d.ts +47 -0
- package/dist/_alt/src/MustardEngine.d.ts +30 -0
- package/dist/_alt/src/MustardParser.d.ts +63 -0
- package/dist/_alt/src/MustardParser2.d.ts +35 -0
- package/dist/_alt/src/pipes.d.ts +93 -0
- package/dist/_alt/src/template.d.ts +166 -0
- package/dist/_alt/src/tools.d.ts +4 -0
- package/dist/_alt/tests/pipes.tests.d.ts +1 -0
- package/dist/_alt/tests/template.tests.d.ts +1 -0
- package/dist/_alt/vitest.config.d.ts +2 -0
- package/dist/collections/Index.d.ts +1 -0
- package/dist/collections/LinkedList.d.ts +75 -0
- package/dist/collections/Pager.d.ts +15 -0
- package/dist/collections/index.js +2 -0
- package/dist/collections/index.js.map +7 -0
- package/dist/collections/index.mjs +2 -0
- package/dist/collections/index.mjs.map +7 -0
- package/dist/components/Table.d.ts +13 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +128 -0
- package/dist/components/index.js.map +7 -0
- package/dist/components/index.mjs +128 -0
- package/dist/components/index.mjs.map +7 -0
- package/dist/components/lists/Table.d.ts +59 -0
- package/dist/components/lists/TreeView.d.ts +67 -0
- package/dist/components/lists/index.d.ts +2 -0
- package/dist/components/loader.d.ts +60 -0
- package/dist/components/menus/MenuItem.d.ts +30 -0
- package/dist/components/menus/TopMenu.d.ts +16 -0
- package/dist/components/menus/index.d.ts +2 -0
- package/dist/components/panels/tabs.d.ts +15 -0
- package/dist/di/index.d.ts +1 -0
- package/dist/di/index.js +2 -0
- package/dist/di/index.js.map +7 -0
- package/dist/di/index.mjs +2 -0
- package/dist/di/index.mjs.map +7 -0
- package/dist/elements/CopyAttributes.d.ts +2 -0
- package/dist/elements/dom.d.ts +18 -0
- package/dist/elements/index.d.ts +2 -0
- package/dist/elements/index.js +2 -0
- package/dist/elements/index.js.map +7 -0
- package/dist/elements/index.mjs +2 -0
- package/dist/elements/index.mjs.map +7 -0
- package/dist/errors.d.ts +71 -0
- package/dist/forms/FormReader.d.ts +182 -0
- package/dist/forms/FormValidator.d.ts +114 -0
- package/dist/forms/ValidationRules.d.ts +103 -0
- package/dist/forms/index.d.ts +4 -0
- package/dist/forms/index.js +2 -0
- package/dist/forms/index.js.map +7 -0
- package/dist/forms/index.mjs +2 -0
- package/dist/forms/index.mjs.map +7 -0
- package/dist/forms/setFormData.d.ts +49 -0
- package/dist/getParentComponent.d.ts +43 -0
- package/dist/html/TableRenderer.d.ts +44 -0
- package/dist/html/TreeBinder.d.ts +9 -0
- package/dist/html/html.d.ts +55 -0
- package/dist/html/index.d.ts +5 -0
- package/dist/html/index.js +2 -0
- package/dist/html/index.js.map +7 -0
- package/dist/html/index.mjs +2 -0
- package/dist/html/index.mjs.map +7 -0
- package/dist/html/template.d.ts +167 -0
- package/dist/http/ServerSentEvents.d.ts +116 -0
- package/dist/http/SimpleWebSocket.d.ts +153 -0
- package/dist/http/http.d.ts +177 -0
- package/dist/http/index.d.ts +3 -0
- package/dist/http/index.js +2 -0
- package/dist/http/index.js.map +7 -0
- package/dist/http/index.mjs +2 -0
- package/dist/http/index.mjs.map +7 -0
- package/dist/i18n/i18n.d.ts +105 -0
- package/dist/i18n/icu.d.ts +64 -0
- package/dist/i18n/index.d.ts +2 -0
- package/dist/i18n/index.js +2 -0
- package/dist/i18n/index.js.map +7 -0
- package/dist/i18n/index.mjs +2 -0
- package/dist/i18n/index.mjs.map +7 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +7 -0
- package/dist/index.mjs +5 -0
- package/dist/index.mjs.map +7 -0
- package/dist/lib/DataLoader.d.ts +51 -0
- package/dist/lib/DependencyInjection.d.ts +271 -0
- package/dist/lib/InvokeParent.d.ts +10 -0
- package/dist/lib/Pipes.d.ts +236 -0
- package/dist/lib/SequentialId.d.ts +47 -0
- package/dist/lib/collections/Index.d.ts +1 -0
- package/dist/lib/collections/LinkedList.d.ts +75 -0
- package/dist/lib/collections/Pager.d.ts +15 -0
- package/dist/lib/collections/TableRenderer.d.ts +44 -0
- package/dist/lib/di/index.d.ts +1 -0
- package/dist/lib/elements/CopyAttributes.d.ts +2 -0
- package/dist/lib/elements/dom.d.ts +18 -0
- package/dist/lib/elements/index.d.ts +2 -0
- package/dist/lib/errors.d.ts +71 -0
- package/dist/lib/forms/FormReader.d.ts +182 -0
- package/dist/lib/forms/FormValidator.d.ts +114 -0
- package/dist/lib/forms/ValidationRules.d.ts +103 -0
- package/dist/lib/forms/index.d.ts +4 -0
- package/dist/lib/forms/setFormData.d.ts +49 -0
- package/dist/lib/getParentComponent.d.ts +43 -0
- package/dist/lib/html/TableRenderer.d.ts +44 -0
- package/dist/lib/html/TreeBinder.d.ts +9 -0
- package/dist/lib/html/html.d.ts +55 -0
- package/dist/lib/html/html2.d.ts +55 -0
- package/dist/lib/html/index.d.ts +5 -0
- package/dist/lib/html/m.d.ts +167 -0
- package/dist/lib/html/m2.d.ts +8 -0
- package/dist/lib/html/m3.d.ts +0 -0
- package/dist/lib/html/template.d.ts +167 -0
- package/dist/lib/http/HttpClient.d.ts +153 -0
- package/dist/lib/http/ServerSentEvents.d.ts +116 -0
- package/dist/lib/http/SimpleWebSocket.d.ts +153 -0
- package/dist/lib/http/http.d.ts +177 -0
- package/dist/lib/http/index.d.ts +3 -0
- package/dist/lib/i18n/i18n.d.ts +105 -0
- package/dist/lib/i18n/icu.d.ts +64 -0
- package/dist/lib/i18n/index.d.ts +2 -0
- package/dist/lib/index.d.ts +16 -0
- package/dist/lib/routing/NavigateRouteEvent.d.ts +52 -0
- package/dist/lib/routing/RouteLink.d.ts +7 -0
- package/dist/lib/routing/Routing.d.ts +270 -0
- package/dist/lib/routing/RoutingTarget.d.ts +22 -0
- package/dist/lib/routing/index.d.ts +7 -0
- package/dist/lib/routing/navigation.d.ts +70 -0
- package/dist/lib/routing/routeMatching.d.ts +21 -0
- package/dist/lib/routing/routeTargetRegistry.d.ts +23 -0
- package/dist/lib/routing/types.d.ts +130 -0
- package/dist/lib/templates/NodeTemplate.d.ts +38 -0
- package/dist/lib/templates/accessorParser.d.ts +87 -0
- package/dist/lib/templates/parseTemplate.d.ts +6 -0
- package/dist/lib/templates/tokenizer.d.ts +76 -0
- package/dist/lib/tools.d.ts +30 -0
- package/dist/lib/utils/index.d.ts +4 -0
- package/dist/pipes.d.ts +236 -0
- package/dist/routing/NavigateRouteEvent.d.ts +52 -0
- package/dist/routing/RouteLink.d.ts +7 -0
- package/dist/routing/RoutingTarget.d.ts +22 -0
- package/dist/routing/index.d.ts +7 -0
- package/dist/routing/index.js +5 -0
- package/dist/routing/index.js.map +7 -0
- package/dist/routing/index.mjs +5 -0
- package/dist/routing/index.mjs.map +7 -0
- package/dist/routing/navigation.d.ts +70 -0
- package/dist/routing/routeMatching.d.ts +21 -0
- package/dist/routing/routeTargetRegistry.d.ts +23 -0
- package/dist/routing/types.d.ts +130 -0
- package/dist/templates/NodeTemplate.d.ts +38 -0
- package/dist/templates/accessorParser.d.ts +87 -0
- package/dist/templates/parseTemplate.d.ts +6 -0
- package/dist/templates/tokenizer.d.ts +76 -0
- package/dist/tools.d.ts +30 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +7 -0
- package/dist/utils/index.mjs +2 -0
- package/dist/utils/index.mjs.map +7 -0
- package/docs/Architecture.md +333 -0
- package/docs/DependencyInjection.md +237 -0
- package/docs/Errors.md +87 -0
- package/docs/GettingStarted.md +231 -0
- package/docs/Pipes.md +211 -0
- package/docs/Translations.md +312 -0
- package/docs/WhyRelaxjs.md +336 -0
- package/docs/elements/dom.md +102 -0
- package/docs/forms/creating-form-components.md +924 -0
- package/docs/forms/form-api.md +94 -0
- package/docs/forms/forms.md +99 -0
- package/docs/forms/patterns.md +311 -0
- package/docs/forms/reading-writing.md +365 -0
- package/docs/forms/validation.md +351 -0
- package/docs/html/TableRenderer.md +292 -0
- package/docs/html/html.md +175 -0
- package/docs/html/index.md +54 -0
- package/docs/html/template.md +422 -0
- package/docs/http/HttpClient.md +459 -0
- package/docs/http/ServerSentEvents.md +184 -0
- package/docs/http/index.md +109 -0
- package/docs/i18n/i18n.md +309 -0
- package/docs/i18n/intl-standard.md +178 -0
- package/docs/routing/RouteLink.md +98 -0
- package/docs/routing/Routing.md +332 -0
- package/docs/routing/RoutingTarget.md +136 -0
- package/docs/routing/layouts.md +207 -0
- package/docs/utilities.md +143 -0
- package/package.json +93 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export declare class TableRenderer {
|
|
2
|
+
private table;
|
|
3
|
+
private template;
|
|
4
|
+
private component;
|
|
5
|
+
private dataMap;
|
|
6
|
+
private rowMap;
|
|
7
|
+
IdColumn: string;
|
|
8
|
+
constructor(table: HTMLTableElement, template: HTMLTemplateElement, idColumn: string, component: HTMLElement);
|
|
9
|
+
render(data: Record<string, any>[]): void;
|
|
10
|
+
private clearRows;
|
|
11
|
+
private renderRow;
|
|
12
|
+
private populateRow;
|
|
13
|
+
private attachEventHandlers;
|
|
14
|
+
update(data: Record<string, any>): void;
|
|
15
|
+
}
|
|
16
|
+
export declare class SortChangeEvent extends CustomEvent<SortColumn[]> {
|
|
17
|
+
constructor(sortColumns: SortColumn[]);
|
|
18
|
+
}
|
|
19
|
+
type SortDirection = 'asc' | 'desc';
|
|
20
|
+
export type SortColumn = {
|
|
21
|
+
column: string;
|
|
22
|
+
direction: SortDirection;
|
|
23
|
+
};
|
|
24
|
+
export declare class TableSorter {
|
|
25
|
+
private table;
|
|
26
|
+
private sortColumns;
|
|
27
|
+
private component;
|
|
28
|
+
constructor(table: HTMLTableElement, component: HTMLElement);
|
|
29
|
+
private setupListeners;
|
|
30
|
+
private toggle;
|
|
31
|
+
private emit;
|
|
32
|
+
private updateSortIndicators;
|
|
33
|
+
getSortColumns(): SortColumn[];
|
|
34
|
+
clear(): void;
|
|
35
|
+
}
|
|
36
|
+
declare global {
|
|
37
|
+
interface HTMLTableElementEventMap extends HTMLElementEventMap {
|
|
38
|
+
'sortchange': SortChangeEvent;
|
|
39
|
+
}
|
|
40
|
+
interface HTMLTableElement {
|
|
41
|
+
addEventListener<K extends keyof HTMLTableElementEventMap>(type: K, listener: (this: HTMLTableElement, ev: HTMLTableElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module html
|
|
3
|
+
* HTML template engine with update capabilities.
|
|
4
|
+
* Creates templates that can be re-rendered with new data without recreating DOM nodes.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Result of rendering a template.
|
|
8
|
+
* Provides the DOM fragment and an update function for re-rendering.
|
|
9
|
+
*/
|
|
10
|
+
export interface RenderTemplate {
|
|
11
|
+
/** The rendered DOM fragment */
|
|
12
|
+
fragment: DocumentFragment;
|
|
13
|
+
/** Updates the DOM with new data without recreating elements */
|
|
14
|
+
update(context: any): void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Creates an updateable HTML template using tagged template literals.
|
|
18
|
+
* Returns an object with the fragment and an update method for efficient re-rendering.
|
|
19
|
+
*
|
|
20
|
+
* Supports:
|
|
21
|
+
* - Template literal substitutions (`${}`)
|
|
22
|
+
* - Mustache-style bindings (`{{property}}`)
|
|
23
|
+
* - Pipe transformations (`{{value|uppercase}}`)
|
|
24
|
+
* - Event handler binding
|
|
25
|
+
*
|
|
26
|
+
* @param templateStrings - The static parts of the template literal
|
|
27
|
+
* @param substitutions - The dynamic values interpolated into the template
|
|
28
|
+
* @returns A function that takes context and returns a RenderTemplate
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* // Create and render a template
|
|
32
|
+
* const template = html`
|
|
33
|
+
* <div class="user">
|
|
34
|
+
* <h2>{{name}}</h2>
|
|
35
|
+
* <p>{{email}}</p>
|
|
36
|
+
* <span>{{createdAt|daysAgo}}</span>
|
|
37
|
+
* </div>
|
|
38
|
+
* `;
|
|
39
|
+
*
|
|
40
|
+
* const result = template({ name: 'John', email: 'john@example.com', createdAt: new Date() });
|
|
41
|
+
* container.appendChild(result.fragment);
|
|
42
|
+
*
|
|
43
|
+
* // Later, update with new data
|
|
44
|
+
* result.update({ name: 'Jane', email: 'jane@example.com', createdAt: new Date() });
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* // With event handlers
|
|
48
|
+
* const row = html`
|
|
49
|
+
* <tr>
|
|
50
|
+
* <td>{{name}}</td>
|
|
51
|
+
* <td><button onclick=${function() { this.edit(this.id) }}>Edit</button></td>
|
|
52
|
+
* </tr>
|
|
53
|
+
* `;
|
|
54
|
+
*/
|
|
55
|
+
export declare function html(templateStrings: TemplateStringsArray, ...substitutions: any[]): (context: any) => RenderTemplate;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module html2
|
|
3
|
+
* Enhanced HTML template engine with update capabilities.
|
|
4
|
+
* Creates templates that can be re-rendered with new data without recreating DOM nodes.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Result of rendering a template.
|
|
8
|
+
* Provides the DOM fragment and an update function for re-rendering.
|
|
9
|
+
*/
|
|
10
|
+
export interface RenderTemplate {
|
|
11
|
+
/** The rendered DOM fragment */
|
|
12
|
+
fragment: DocumentFragment;
|
|
13
|
+
/** Updates the DOM with new data without recreating elements */
|
|
14
|
+
update(context: any): void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Creates an updateable HTML template using tagged template literals.
|
|
18
|
+
* Unlike `html`, this returns an object with an update method for efficient re-rendering.
|
|
19
|
+
*
|
|
20
|
+
* Supports:
|
|
21
|
+
* - Template literal substitutions (`${}`)
|
|
22
|
+
* - Mustache-style bindings (`{{property}}`)
|
|
23
|
+
* - Pipe transformations (`{{value|uppercase}}`)
|
|
24
|
+
* - Event handler binding
|
|
25
|
+
*
|
|
26
|
+
* @param templateStrings - The static parts of the template literal
|
|
27
|
+
* @param substitutions - The dynamic values interpolated into the template
|
|
28
|
+
* @returns A function that takes context and returns a RenderTemplate
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* // Create and render a template
|
|
32
|
+
* const template = html2`
|
|
33
|
+
* <div class="user">
|
|
34
|
+
* <h2>{{name}}</h2>
|
|
35
|
+
* <p>{{email}}</p>
|
|
36
|
+
* <span>{{createdAt|daysAgo}}</span>
|
|
37
|
+
* </div>
|
|
38
|
+
* `;
|
|
39
|
+
*
|
|
40
|
+
* const result = template({ name: 'John', email: 'john@example.com', createdAt: new Date() });
|
|
41
|
+
* container.appendChild(result.fragment);
|
|
42
|
+
*
|
|
43
|
+
* // Later, update with new data
|
|
44
|
+
* result.update({ name: 'Jane', email: 'jane@example.com', createdAt: new Date() });
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* // With event handlers
|
|
48
|
+
* const row = html2`
|
|
49
|
+
* <tr>
|
|
50
|
+
* <td>{{name}}</td>
|
|
51
|
+
* <td><button onclick=${function() { this.edit(this.id) }}>Edit</button></td>
|
|
52
|
+
* </tr>
|
|
53
|
+
* `;
|
|
54
|
+
*/
|
|
55
|
+
export declare function html2(templateStrings: TemplateStringsArray, ...substitutions: any[]): (context: any) => RenderTemplate;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { html, RenderTemplate } from './html';
|
|
2
|
+
export { compileTemplate, EngineConfig, CompiledTemplate } from './template';
|
|
3
|
+
export * from '../templates/NodeTemplate';
|
|
4
|
+
export { TableRenderer, TableSorter, SortChangeEvent } from './TableRenderer';
|
|
5
|
+
export type { SortColumn } from './TableRenderer';
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module m
|
|
3
|
+
* DOM-based template engine with reactive rendering capabilities.
|
|
4
|
+
*
|
|
5
|
+
* Compiles HTML templates with mustache-style expressions into efficient
|
|
6
|
+
* render functions that update the DOM when data changes.
|
|
7
|
+
*
|
|
8
|
+
* **Features:**
|
|
9
|
+
* - Text interpolation: `{{name}}`, `{{user.profile.email}}`
|
|
10
|
+
* - Attribute binding: `<div class="{{className}}">`
|
|
11
|
+
* - Pipes: `{{price | currency}}`, `{{name | uppercase | truncate:20}}`
|
|
12
|
+
* - Function calls: `{{formatDate(createdAt)}}`, `{{add(5, 3)}}`
|
|
13
|
+
* - Array indexing: `{{items[0]}}`, `{{users[1].name}}`
|
|
14
|
+
* - Conditionals: `<div if="isVisible">`, `<div unless="isHidden">`
|
|
15
|
+
* - Loops: `<li loop="item in items">{{item.name}}</li>`
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // Basic usage
|
|
19
|
+
* import { compileTemplate } from './m';
|
|
20
|
+
*
|
|
21
|
+
* const { content, render } = compileTemplate(`
|
|
22
|
+
* <div class="card">
|
|
23
|
+
* <h2>{{title}}</h2>
|
|
24
|
+
* <p>{{description}}</p>
|
|
25
|
+
* </div>
|
|
26
|
+
* `);
|
|
27
|
+
*
|
|
28
|
+
* render({ title: 'Hello', description: 'World' });
|
|
29
|
+
* document.body.appendChild(content);
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* // With pipes and functions
|
|
33
|
+
* import { createPipeRegistry } from '../pipes';
|
|
34
|
+
*
|
|
35
|
+
* const pipeRegistry = createPipeRegistry();
|
|
36
|
+
* const { content, render } = compileTemplate(`
|
|
37
|
+
* <span>{{user.name | uppercase}}</span>
|
|
38
|
+
* <span>{{formatDate(user.createdAt)}}</span>
|
|
39
|
+
* `, { strict: false, pipeRegistry });
|
|
40
|
+
*
|
|
41
|
+
* render(
|
|
42
|
+
* { user: { name: 'john', createdAt: new Date() } },
|
|
43
|
+
* { formatDate: (d) => d.toLocaleDateString() }
|
|
44
|
+
* );
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* // With loops and conditionals
|
|
48
|
+
* const { content, render } = compileTemplate(`
|
|
49
|
+
* <ul>
|
|
50
|
+
* <li loop="item in items" if="item.visible">
|
|
51
|
+
* {{item.name}}: {{item.price | currency}}
|
|
52
|
+
* </li>
|
|
53
|
+
* </ul>
|
|
54
|
+
* `);
|
|
55
|
+
*
|
|
56
|
+
* render({ items: [
|
|
57
|
+
* { name: 'Apple', price: 1.5, visible: true },
|
|
58
|
+
* { name: 'Hidden', price: 0, visible: false }
|
|
59
|
+
* ]});
|
|
60
|
+
*/
|
|
61
|
+
import { PipeRegistry } from '../pipes';
|
|
62
|
+
/**
|
|
63
|
+
* Configuration options for the template engine.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* const config: EngineConfig = {
|
|
67
|
+
* strict: true,
|
|
68
|
+
* onError: (msg) => console.error(msg),
|
|
69
|
+
* pipeRegistry: createPipeRegistry()
|
|
70
|
+
* };
|
|
71
|
+
*/
|
|
72
|
+
export interface EngineConfig {
|
|
73
|
+
/** When true, throws errors for missing paths/functions. When false, returns empty string. */
|
|
74
|
+
strict: boolean;
|
|
75
|
+
/** Optional callback invoked when errors occur, receives formatted error message. */
|
|
76
|
+
onError?: (msg: string) => void;
|
|
77
|
+
/** Custom pipe registry for transformations. Defaults to built-in pipes. */
|
|
78
|
+
pipeRegistry?: PipeRegistry;
|
|
79
|
+
}
|
|
80
|
+
export type Path = string;
|
|
81
|
+
export type TemplateValue = string | number | boolean | null | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* Data context object passed to render function.
|
|
84
|
+
* Contains the data values that expressions resolve against.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* const ctx: Context = {
|
|
88
|
+
* user: { name: 'John', age: 30 },
|
|
89
|
+
* items: ['a', 'b', 'c'],
|
|
90
|
+
* isActive: true
|
|
91
|
+
* };
|
|
92
|
+
*/
|
|
93
|
+
export interface Context {
|
|
94
|
+
[key: string]: ContextValue;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Functions context object passed as second argument to render.
|
|
98
|
+
* Contains callable functions that can be invoked from templates.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* const fns: FunctionsContext = {
|
|
102
|
+
* formatDate: (d) => d.toLocaleDateString(),
|
|
103
|
+
* add: (a, b) => a + b,
|
|
104
|
+
* greet: (name) => `Hello, ${name}!`
|
|
105
|
+
* };
|
|
106
|
+
*/
|
|
107
|
+
export interface FunctionsContext {
|
|
108
|
+
[key: string]: (...args: any[]) => any;
|
|
109
|
+
}
|
|
110
|
+
export type ContextValue = TemplateValue | any[] | Context | ((...args: any[]) => any);
|
|
111
|
+
export type Getter = (ctx: Context, path: Path, debugInfo?: string) => TemplateValue;
|
|
112
|
+
export type Setter = (ctx: Context, fns?: FunctionsContext) => void;
|
|
113
|
+
export type Patcher = (node: Node, get: Getter, config: EngineConfig) => Setter | void;
|
|
114
|
+
export type ExpressionFn = (ctx: Context, fns?: FunctionsContext) => TemplateValue;
|
|
115
|
+
/**
|
|
116
|
+
* Result of compiling a template.
|
|
117
|
+
* Contains the DOM content and a render function for updating it with data.
|
|
118
|
+
*/
|
|
119
|
+
export interface CompiledTemplate {
|
|
120
|
+
/** The compiled DOM element containing the template structure. */
|
|
121
|
+
content: DocumentFragment | HTMLElement;
|
|
122
|
+
/**
|
|
123
|
+
* Updates the DOM with the provided data context.
|
|
124
|
+
* Memoized: only re-renders when context object reference changes.
|
|
125
|
+
* @param ctx - Data context with values for template expressions
|
|
126
|
+
* @param fns - Optional functions context for callable expressions
|
|
127
|
+
*/
|
|
128
|
+
render: (ctx: Context, fns?: FunctionsContext) => void;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Compiles an HTML template string into a reusable render function.
|
|
132
|
+
*
|
|
133
|
+
* The template supports mustache-style expressions `{{expression}}` for:
|
|
134
|
+
* - Path resolution: `{{user.name}}`, `{{items[0].title}}`
|
|
135
|
+
* - Pipes: `{{value | uppercase}}`, `{{price | currency}}`
|
|
136
|
+
* - Function calls: `{{formatDate(createdAt)}}`, `{{add(a, b)}}`
|
|
137
|
+
*
|
|
138
|
+
* Directive attributes for control flow:
|
|
139
|
+
* - `if="condition"` - Renders element only when condition is truthy
|
|
140
|
+
* - `unless="condition"` - Renders element only when condition is falsy
|
|
141
|
+
* - `loop="item in items"` - Repeats element for each array item
|
|
142
|
+
*
|
|
143
|
+
* @param templateStr - HTML template string with mustache expressions
|
|
144
|
+
* @param config - Optional engine configuration
|
|
145
|
+
* @returns Compiled template with content and render function
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* // Simple data binding
|
|
149
|
+
* const { content, render } = compileTemplate('<h1>{{title}}</h1>');
|
|
150
|
+
* render({ title: 'Hello World' });
|
|
151
|
+
* document.body.appendChild(content);
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* // Re-rendering with new data
|
|
155
|
+
* const { content, render } = compileTemplate('<span>Count: {{count}}</span>');
|
|
156
|
+
* render({ count: 0 });
|
|
157
|
+
* render({ count: 1 }); // DOM updates automatically
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* // With strict mode and error handling
|
|
161
|
+
* const { render } = compileTemplate('{{missing}}', {
|
|
162
|
+
* strict: true,
|
|
163
|
+
* onError: (msg) => console.error(msg)
|
|
164
|
+
* });
|
|
165
|
+
* render({}); // Throws error for missing path
|
|
166
|
+
*/
|
|
167
|
+
export declare function compileTemplate(templateStr: string, config?: EngineConfig): CompiledTemplate;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type PipeFunction = (value: any) => any;
|
|
2
|
+
export type StrictMode = boolean;
|
|
3
|
+
interface MustacheOptions {
|
|
4
|
+
strict?: StrictMode;
|
|
5
|
+
}
|
|
6
|
+
export declare function parseTemplate(template: string, options?: MustacheOptions): (data: any, component?: any) => string;
|
|
7
|
+
export declare function parse(template: string, data: any, component?: any, options?: MustacheOptions): string;
|
|
8
|
+
export {};
|
|
File without changes
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module template
|
|
3
|
+
* DOM-based template engine with reactive rendering capabilities.
|
|
4
|
+
*
|
|
5
|
+
* Compiles HTML templates with mustache-style expressions into efficient
|
|
6
|
+
* render functions that update the DOM when data changes.
|
|
7
|
+
*
|
|
8
|
+
* **Features:**
|
|
9
|
+
* - Text interpolation: `{{name}}`, `{{user.profile.email}}`
|
|
10
|
+
* - Attribute binding: `<div class="{{className}}">`
|
|
11
|
+
* - Pipes: `{{price | currency}}`, `{{name | uppercase | shorten:20}}`
|
|
12
|
+
* - Function calls: `{{formatDate(createdAt)}}`, `{{add(5, 3)}}`
|
|
13
|
+
* - Array indexing: `{{items[0]}}`, `{{users[1].name}}`
|
|
14
|
+
* - Conditionals: `<div if="isVisible">`, `<div unless="isHidden">`
|
|
15
|
+
* - Loops: `<li loop="item in items">{{item.name}}</li>`
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // Basic usage
|
|
19
|
+
* import { compileTemplate } from './m';
|
|
20
|
+
*
|
|
21
|
+
* const { content, render } = compileTemplate(`
|
|
22
|
+
* <div class="card">
|
|
23
|
+
* <h2>{{title}}</h2>
|
|
24
|
+
* <p>{{description}}</p>
|
|
25
|
+
* </div>
|
|
26
|
+
* `);
|
|
27
|
+
*
|
|
28
|
+
* render({ title: 'Hello', description: 'World' });
|
|
29
|
+
* document.body.appendChild(content);
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* // With pipes and functions
|
|
33
|
+
* import { createPipeRegistry } from '../pipes';
|
|
34
|
+
*
|
|
35
|
+
* const pipeRegistry = createPipeRegistry();
|
|
36
|
+
* const { content, render } = compileTemplate(`
|
|
37
|
+
* <span>{{user.name | uppercase}}</span>
|
|
38
|
+
* <span>{{formatDate(user.createdAt)}}</span>
|
|
39
|
+
* `, { strict: false, pipeRegistry });
|
|
40
|
+
*
|
|
41
|
+
* render(
|
|
42
|
+
* { user: { name: 'john', createdAt: new Date() } },
|
|
43
|
+
* { formatDate: (d) => d.toLocaleDateString() }
|
|
44
|
+
* );
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* // With loops and conditionals
|
|
48
|
+
* const { content, render } = compileTemplate(`
|
|
49
|
+
* <ul>
|
|
50
|
+
* <li loop="item in items" if="item.visible">
|
|
51
|
+
* {{item.name}}: {{item.price | currency}}
|
|
52
|
+
* </li>
|
|
53
|
+
* </ul>
|
|
54
|
+
* `);
|
|
55
|
+
*
|
|
56
|
+
* render({ items: [
|
|
57
|
+
* { name: 'Apple', price: 1.5, visible: true },
|
|
58
|
+
* { name: 'Hidden', price: 0, visible: false }
|
|
59
|
+
* ]});
|
|
60
|
+
*/
|
|
61
|
+
import { PipeRegistry } from '../pipes';
|
|
62
|
+
/**
|
|
63
|
+
* Configuration options for the template engine.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* const config: EngineConfig = {
|
|
67
|
+
* strict: true,
|
|
68
|
+
* onError: (msg) => console.error(msg),
|
|
69
|
+
* pipeRegistry: createPipeRegistry()
|
|
70
|
+
* };
|
|
71
|
+
*/
|
|
72
|
+
export interface EngineConfig {
|
|
73
|
+
/** When true, throws errors for missing paths/functions. When false, returns empty string. */
|
|
74
|
+
strict: boolean;
|
|
75
|
+
/** Optional callback invoked when errors occur, receives formatted error message. */
|
|
76
|
+
onError?: (msg: string) => void;
|
|
77
|
+
/** Custom pipe registry for transformations. Defaults to built-in pipes. */
|
|
78
|
+
pipeRegistry?: PipeRegistry;
|
|
79
|
+
}
|
|
80
|
+
export type Path = string;
|
|
81
|
+
export type TemplateValue = string | number | boolean | null | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* Data context object passed to render function.
|
|
84
|
+
* Contains the data values that expressions resolve against.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* const ctx: Context = {
|
|
88
|
+
* user: { name: 'John', age: 30 },
|
|
89
|
+
* items: ['a', 'b', 'c'],
|
|
90
|
+
* isActive: true
|
|
91
|
+
* };
|
|
92
|
+
*/
|
|
93
|
+
export interface Context {
|
|
94
|
+
[key: string]: ContextValue;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Functions context object passed as second argument to render.
|
|
98
|
+
* Contains callable functions that can be invoked from templates.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* const fns: FunctionsContext = {
|
|
102
|
+
* formatDate: (d) => d.toLocaleDateString(),
|
|
103
|
+
* add: (a, b) => a + b,
|
|
104
|
+
* greet: (name) => `Hello, ${name}!`
|
|
105
|
+
* };
|
|
106
|
+
*/
|
|
107
|
+
export interface FunctionsContext {
|
|
108
|
+
[key: string]: (...args: any[]) => any;
|
|
109
|
+
}
|
|
110
|
+
export type ContextValue = TemplateValue | any[] | Context | ((...args: any[]) => any);
|
|
111
|
+
export type Getter = (ctx: Context, path: Path, debugInfo?: string) => TemplateValue;
|
|
112
|
+
export type Setter = (ctx: Context, fns?: FunctionsContext) => void;
|
|
113
|
+
export type Patcher = (node: Node, get: Getter, config: EngineConfig) => Setter | void;
|
|
114
|
+
export type ExpressionFn = (ctx: Context, fns?: FunctionsContext) => TemplateValue;
|
|
115
|
+
/**
|
|
116
|
+
* Result of compiling a template.
|
|
117
|
+
* Contains the DOM content and a render function for updating it with data.
|
|
118
|
+
*/
|
|
119
|
+
export interface CompiledTemplate {
|
|
120
|
+
/** The compiled DOM element containing the template structure. */
|
|
121
|
+
content: DocumentFragment | HTMLElement;
|
|
122
|
+
/**
|
|
123
|
+
* Updates the DOM with the provided data context.
|
|
124
|
+
* Memoized: only re-renders when context object reference changes.
|
|
125
|
+
* @param ctx - Data context with values for template expressions
|
|
126
|
+
* @param fns - Optional functions context for callable expressions
|
|
127
|
+
*/
|
|
128
|
+
render: (ctx: Context, fns?: FunctionsContext) => void;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Compiles an HTML template string into a reusable render function.
|
|
132
|
+
*
|
|
133
|
+
* The template supports mustache-style expressions `{{expression}}` for:
|
|
134
|
+
* - Path resolution: `{{user.name}}`, `{{items[0].title}}`
|
|
135
|
+
* - Pipes: `{{value | uppercase}}`, `{{price | currency}}`
|
|
136
|
+
* - Function calls: `{{formatDate(createdAt)}}`, `{{add(a, b)}}`
|
|
137
|
+
*
|
|
138
|
+
* Directive attributes for control flow:
|
|
139
|
+
* - `if="condition"` - Renders element only when condition is truthy
|
|
140
|
+
* - `unless="condition"` - Renders element only when condition is falsy
|
|
141
|
+
* - `loop="item in items"` - Repeats element for each array item
|
|
142
|
+
*
|
|
143
|
+
* @param templateStr - HTML template string with mustache expressions
|
|
144
|
+
* @param config - Optional engine configuration
|
|
145
|
+
* @returns Compiled template with content and render function
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* // Simple data binding
|
|
149
|
+
* const { content, render } = compileTemplate('<h1>{{title}}</h1>');
|
|
150
|
+
* render({ title: 'Hello World' });
|
|
151
|
+
* document.body.appendChild(content);
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* // Re-rendering with new data
|
|
155
|
+
* const { content, render } = compileTemplate('<span>Count: {{count}}</span>');
|
|
156
|
+
* render({ count: 0 });
|
|
157
|
+
* render({ count: 1 }); // DOM updates automatically
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* // With strict mode and error handling
|
|
161
|
+
* const { render } = compileTemplate('{{missing}}', {
|
|
162
|
+
* strict: true,
|
|
163
|
+
* onError: (msg) => console.error(msg)
|
|
164
|
+
* });
|
|
165
|
+
* render({}); // Throws error for missing path
|
|
166
|
+
*/
|
|
167
|
+
export declare function compileTemplate(templateStr: string, config?: EngineConfig): CompiledTemplate;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module HttpClient
|
|
3
|
+
* Type-safe HTTP client built on fetch() with automatic JWT handling.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const api = new HttpClient({ baseUrl: '/api' });
|
|
7
|
+
* const response = await api.get('/users');
|
|
8
|
+
* const users = response.as<User[]>();
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Configuration options for HttpClient.
|
|
12
|
+
*/
|
|
13
|
+
export interface HttpClientOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Root URL to remote endpoint. Used so that each method only have to specify path in requests.
|
|
16
|
+
*/
|
|
17
|
+
baseUrl?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Default content type to use if none is specified in the request method.
|
|
20
|
+
*/
|
|
21
|
+
contentType?: string;
|
|
22
|
+
/***
|
|
23
|
+
* Checks for a JWT token in localStorage to automatically include it in requests.
|
|
24
|
+
*
|
|
25
|
+
* Undefined = use "jwt", null = disable.
|
|
26
|
+
*/
|
|
27
|
+
bearerTokenName?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* HTTP client wrapper around fetch() with convenience features.
|
|
31
|
+
*
|
|
32
|
+
* Features:
|
|
33
|
+
* - Automatic base URL prefixing
|
|
34
|
+
* - JWT token handling from localStorage
|
|
35
|
+
* - Type-safe response casting
|
|
36
|
+
* - Consistent error handling
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* // Create client with base URL
|
|
40
|
+
* const api = new HttpClient({ baseUrl: '/api/v1' });
|
|
41
|
+
*
|
|
42
|
+
* // GET request
|
|
43
|
+
* const users = await api.get('/users');
|
|
44
|
+
* const data = users.as<User[]>();
|
|
45
|
+
*
|
|
46
|
+
* // POST request
|
|
47
|
+
* const result = await api.post('/users', JSON.stringify({ name: 'John' }));
|
|
48
|
+
*/
|
|
49
|
+
export declare class HttpClient {
|
|
50
|
+
private options?;
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
* @param urlPrefix Can be used to specify the URL early (to allow only path to be used in all methods).
|
|
54
|
+
* @param defaultContentType Content type to use if not specified in the constructor
|
|
55
|
+
*/
|
|
56
|
+
constructor(options?: HttpClientOptions);
|
|
57
|
+
/**
|
|
58
|
+
*
|
|
59
|
+
* @param url URL to make the request against.
|
|
60
|
+
* @param options Request options.
|
|
61
|
+
* @returns Response from server.
|
|
62
|
+
*/
|
|
63
|
+
request(url: string, options?: RequestInit): Promise<HttpResponse>;
|
|
64
|
+
/**
|
|
65
|
+
* GET a resource.
|
|
66
|
+
* @param url URL to get resource from.
|
|
67
|
+
* @param queryString Optional query string.
|
|
68
|
+
* @param options Request options.
|
|
69
|
+
* @returns HTTP response.
|
|
70
|
+
*/
|
|
71
|
+
get(url: string, queryString?: Record<string, string>, options?: RequestInit): Promise<HttpResponse>;
|
|
72
|
+
/**
|
|
73
|
+
* POST a resource.
|
|
74
|
+
* @param url URL to post to.
|
|
75
|
+
* @param data Data to post.
|
|
76
|
+
* @param options Request options.
|
|
77
|
+
* @returns HTTP response.
|
|
78
|
+
*/
|
|
79
|
+
post(url: string, data: BodyInit, options?: RequestInit): Promise<HttpResponse>;
|
|
80
|
+
/**
|
|
81
|
+
* DELETE a resource.
|
|
82
|
+
* @param url url to resource.
|
|
83
|
+
* @param options request options.
|
|
84
|
+
* @returns response.
|
|
85
|
+
*/
|
|
86
|
+
put(url: string, data: BodyInit, options?: RequestInit): Promise<HttpResponse>;
|
|
87
|
+
/**
|
|
88
|
+
* DELETE a resource.
|
|
89
|
+
* @param url url to resource.
|
|
90
|
+
* @param options request options.
|
|
91
|
+
* @returns response.
|
|
92
|
+
*/
|
|
93
|
+
delete(url: string, options?: RequestInit): Promise<HttpResponse>;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Response for request methods in @see HttpClient
|
|
97
|
+
*/
|
|
98
|
+
export interface HttpResponse {
|
|
99
|
+
/**
|
|
100
|
+
* Http status code.
|
|
101
|
+
*/
|
|
102
|
+
statusCode: number;
|
|
103
|
+
/**
|
|
104
|
+
* Reason to why the status code was used.
|
|
105
|
+
*/
|
|
106
|
+
statusReason: string;
|
|
107
|
+
/**
|
|
108
|
+
* this is a 2x response.
|
|
109
|
+
*/
|
|
110
|
+
success: boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Content type of response body.
|
|
113
|
+
*/
|
|
114
|
+
contentType: string | null;
|
|
115
|
+
/**
|
|
116
|
+
* Body returned.
|
|
117
|
+
*
|
|
118
|
+
* Body has been read and deserialized from json (if the request content type was 'application/json' which is per default is).
|
|
119
|
+
*/
|
|
120
|
+
body: unknown;
|
|
121
|
+
/**
|
|
122
|
+
* Charset used in body.
|
|
123
|
+
*/
|
|
124
|
+
charset: string | null;
|
|
125
|
+
/**
|
|
126
|
+
* Cast body to a type.
|
|
127
|
+
*/
|
|
128
|
+
as<T>(): T;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Error thrown when a request fails.
|
|
132
|
+
*/
|
|
133
|
+
export declare class HttpError extends Error {
|
|
134
|
+
message: string;
|
|
135
|
+
response: HttpResponse;
|
|
136
|
+
constructor(response: HttpResponse);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* HTTP request options.
|
|
140
|
+
*/
|
|
141
|
+
export interface RequestOptions {
|
|
142
|
+
method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
143
|
+
mode?: 'cors' | 'no-cors' | '*cors' | 'same-origin';
|
|
144
|
+
cache: 'default' | 'no-store' | 'reload' | 'no-cache' | 'force-cache' | 'only-if-cached';
|
|
145
|
+
credentials: 'omit' | 'same-origin' | 'include';
|
|
146
|
+
headers: Map<string, string>;
|
|
147
|
+
redirect: 'follow' | 'manual' | '*follow' | 'error';
|
|
148
|
+
referrerPolicy: 'no-referrer' | '*no-referrer-when-downgrade' | 'origin' | 'origin-when-cross-origin' | 'same-origin' | 'strict-origin' | 'strict-origin-when-cross-origin' | 'unsafe-url';
|
|
149
|
+
/**
|
|
150
|
+
* Will be serialized if the content type is json (and the body is an object).
|
|
151
|
+
*/
|
|
152
|
+
body: unknown;
|
|
153
|
+
}
|