juxscript 1.0.132 → 1.1.2
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/README.md +1 -32
- package/bin/cli.js +4 -2
- package/index.d.ts +200 -0
- package/index.js +96 -22
- package/juxconfig.example.js +58 -63
- package/lib/components/alert.ts +200 -0
- package/lib/components/app.ts +247 -0
- package/lib/components/badge.ts +101 -0
- package/lib/components/base/BaseComponent.ts +421 -0
- package/lib/components/base/FormInput.ts +227 -0
- package/lib/components/button.ts +178 -0
- package/lib/components/card.ts +173 -0
- package/lib/components/chart.ts +231 -0
- package/lib/components/checkbox.ts +242 -0
- package/lib/components/code.ts +123 -0
- package/lib/components/container.ts +140 -0
- package/lib/components/data.ts +135 -0
- package/lib/components/datepicker.ts +234 -0
- package/lib/components/dialog.ts +172 -0
- package/lib/components/divider.ts +100 -0
- package/lib/components/dropdown.ts +186 -0
- package/lib/components/element.ts +267 -0
- package/lib/components/fileupload.ts +309 -0
- package/lib/components/grid.ts +291 -0
- package/lib/components/guard.ts +92 -0
- package/lib/components/heading.ts +96 -0
- package/lib/components/helpers.ts +41 -0
- package/lib/components/hero.ts +224 -0
- package/lib/components/icon.ts +178 -0
- package/lib/components/icons.ts +464 -0
- package/lib/components/include.ts +410 -0
- package/lib/components/input.ts +457 -0
- package/lib/components/list.ts +419 -0
- package/lib/components/loading.ts +100 -0
- package/lib/components/menu.ts +275 -0
- package/lib/components/modal.ts +284 -0
- package/lib/components/nav.ts +257 -0
- package/lib/components/paragraph.ts +97 -0
- package/lib/components/progress.ts +159 -0
- package/lib/components/radio.ts +278 -0
- package/lib/components/req.ts +303 -0
- package/lib/components/script.ts +41 -0
- package/lib/components/select.ts +252 -0
- package/lib/components/sidebar.ts +275 -0
- package/lib/components/style.ts +41 -0
- package/lib/components/switch.ts +246 -0
- package/lib/components/table.ts +1249 -0
- package/lib/components/tabs.ts +250 -0
- package/lib/components/theme-toggle.ts +293 -0
- package/lib/components/tooltip.ts +144 -0
- package/lib/components/view.ts +190 -0
- package/lib/components/write.ts +272 -0
- package/lib/globals.d.ts +19 -5
- package/lib/layouts/default.css +260 -0
- package/lib/layouts/figma.css +334 -0
- package/lib/reactivity/state.ts +78 -0
- package/lib/utils/{fetch.js → fetch.ts} +206 -81
- package/machinery/ast.js +347 -0
- package/machinery/build.js +466 -0
- package/machinery/compiler3.js +6 -66
- package/machinery/config.js +6 -93
- package/machinery/doc-generator.js +136 -0
- package/machinery/imports.js +155 -0
- package/machinery/server.js +166 -0
- package/machinery/ts-shim.js +46 -0
- package/machinery/watcher.js +162 -50
- package/package.json +9 -30
- package/create/index.jux +0 -77
- package/create/layout.jux +0 -18
- package/create/style.css +0 -57
- package/create/themes/assets/jux.svg +0 -34
- package/create/themes/base.css +0 -197
- package/create/themes/base2.css +0 -54
- package/create/themes/layouts/base.jux +0 -16
- package/create/themes/layouts/base_marketing.jux +0 -0
- package/create/themes/layouts/base_saas.jux +0 -0
- package/lib/componentsv2/base/BaseEngine.d.ts +0 -112
- package/lib/componentsv2/base/BaseEngine.js +0 -279
- package/lib/componentsv2/base/BaseSkin.d.ts +0 -74
- package/lib/componentsv2/base/BaseSkin.js +0 -130
- package/lib/componentsv2/base/Neighborhood.d.ts +0 -22
- package/lib/componentsv2/base/Neighborhood.js +0 -56
- package/lib/componentsv2/base/OptionsContract.d.ts +0 -20
- package/lib/componentsv2/base/OptionsContract.js +0 -107
- package/lib/componentsv2/base/State.d.ts +0 -18
- package/lib/componentsv2/base/State.js +0 -68
- package/lib/componentsv2/element/Element.d.ts +0 -30
- package/lib/componentsv2/element/Element.js +0 -50
- package/lib/componentsv2/element/ElementEngine.d.ts +0 -59
- package/lib/componentsv2/element/ElementEngine.js +0 -118
- package/lib/componentsv2/element/ElementSkin.d.ts +0 -10
- package/lib/componentsv2/element/ElementSkin.js +0 -56
- package/lib/componentsv2/element/structure.css +0 -261
- package/lib/componentsv2/grid/Grid.d.ts +0 -13
- package/lib/componentsv2/grid/Grid.js +0 -27
- package/lib/componentsv2/grid/GridEngine.d.ts +0 -77
- package/lib/componentsv2/grid/GridEngine.js +0 -153
- package/lib/componentsv2/grid/GridSkin.d.ts +0 -11
- package/lib/componentsv2/grid/GridSkin.js +0 -84
- package/lib/componentsv2/grid/structure.css +0 -27
- package/lib/componentsv2/input/Input.d.ts +0 -6
- package/lib/componentsv2/input/Input.js +0 -21
- package/lib/componentsv2/input/InputEngine.d.ts +0 -70
- package/lib/componentsv2/input/InputEngine.js +0 -143
- package/lib/componentsv2/input/InputSkin.d.ts +0 -11
- package/lib/componentsv2/input/InputSkin.js +0 -89
- package/lib/componentsv2/input/structure.css +0 -47
- package/lib/componentsv2/list/List.d.ts +0 -49
- package/lib/componentsv2/list/List.js +0 -105
- package/lib/componentsv2/list/ListEngine.d.ts +0 -121
- package/lib/componentsv2/list/ListEngine.js +0 -322
- package/lib/componentsv2/list/ListSkin.d.ts +0 -20
- package/lib/componentsv2/list/ListSkin.js +0 -345
- package/lib/componentsv2/list/structure.css +0 -359
- package/lib/componentsv2/plugins/ClientSQLitePlugin.d.ts +0 -21
- package/lib/componentsv2/plugins/ClientSQLitePlugin.js +0 -130
- package/lib/componentsv2/plugins/IndexedDBPlugin.d.ts +0 -18
- package/lib/componentsv2/plugins/IndexedDBPlugin.js +0 -75
- package/lib/componentsv2/plugins/LocalStoragePlugin.d.ts +0 -20
- package/lib/componentsv2/plugins/LocalStoragePlugin.js +0 -65
- package/lib/componentsv2/plugins/ServerSQLitePlugin.d.ts +0 -25
- package/lib/componentsv2/plugins/ServerSQLitePlugin.js +0 -70
- package/lib/componentsv2/stubs/ComponentComposition.ts.stub +0 -32
- package/lib/componentsv2/stubs/ComponentEngine.ts.stub +0 -36
- package/lib/componentsv2/stubs/ComponentSkin.ts.stub +0 -35
- package/lib/componentsv2/stubs/ComponentStructure.css.d.ts.stub +0 -2
- package/lib/componentsv2/stubs/ComponentStructure.css.stub +0 -13
- package/lib/utils/fetch.d.ts +0 -176
- package/machinery/serve.js +0 -255
- package/types/css.d.ts +0 -10
- /package/{create/themes/layouts/base_blog.jux → machinery/bundleAssets.js} +0 -0
- /package/{create/themes/layouts/base_docs.jux → machinery/bundleJux.js} +0 -0
- /package/{create/themes/layouts/base_login.jux → machinery/bundleVendors.js} +0 -0
package/create/themes/base2.css
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/*gemini*/
|
|
3
|
-
:root {
|
|
4
|
-
/* Typography - Larger, more comfortable */
|
|
5
|
-
--font-family-base: 'Google Sans', system-ui, -apple-system, sans-serif;
|
|
6
|
-
--font-size-sm: 0.9375rem; /* 15px */
|
|
7
|
-
--font-size-base: 1.0625rem; /* 17px */
|
|
8
|
-
--font-size-lg: 1.25rem; /* 20px */
|
|
9
|
-
--line-height-normal: 1.6;
|
|
10
|
-
|
|
11
|
-
/* Spacing Scale - More generous */
|
|
12
|
-
--space-xs: 0.5rem; /* 8px */
|
|
13
|
-
--space-sm: 0.75rem; /* 12px */
|
|
14
|
-
--space-md: 1.25rem; /* 20px */
|
|
15
|
-
--space-lg: 2rem; /* 32px */
|
|
16
|
-
--space-xl: 3rem; /* 48px */
|
|
17
|
-
|
|
18
|
-
/* Layout - Softer, rounder */
|
|
19
|
-
--radius-sm: 8px;
|
|
20
|
-
--radius-md: 16px;
|
|
21
|
-
--radius-lg: 24px;
|
|
22
|
-
--border-width: 1px;
|
|
23
|
-
|
|
24
|
-
/* Animation - Smoother */
|
|
25
|
-
--transition-fast: 200ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
26
|
-
--transition-normal: 350ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
27
|
-
|
|
28
|
-
/* Color Palette (Semantic) - Gemini-inspired */
|
|
29
|
-
--color-brand: #1a73e8;
|
|
30
|
-
--color-brand-hover: #1557b0;
|
|
31
|
-
--color-brand-subtle: rgba(26, 115, 232, 0.08);
|
|
32
|
-
|
|
33
|
-
--color-text-primary: #202124;
|
|
34
|
-
--color-text-secondary: #5f6368;
|
|
35
|
-
--color-text-inverse: #ffffff;
|
|
36
|
-
|
|
37
|
-
--color-background: #ffffff;
|
|
38
|
-
--color-surface-base: #f8f9fa;
|
|
39
|
-
--color-surface-hover: #f1f3f4;
|
|
40
|
-
--color-surface-active: #e8eaed;
|
|
41
|
-
|
|
42
|
-
--color-border: #dadce0;
|
|
43
|
-
--color-border-hover: #bdc1c6;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/* Dark Mode Overrides */
|
|
47
|
-
[data-theme="dark"] {
|
|
48
|
-
--color-text-primary: #e8eaed;
|
|
49
|
-
--color-text-secondary: #9aa0a6;
|
|
50
|
-
--color-background: #202124;
|
|
51
|
-
--color-surface-base: #292a2d;
|
|
52
|
-
--color-surface-hover: #35363a;
|
|
53
|
-
--color-border: #5f6368;
|
|
54
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { juxV2 } from '../../lib/componentsv2';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
juxV2.Grid('base-layout')
|
|
5
|
-
.rows([
|
|
6
|
-
{ size: '60px', class: 'header-row' }, // Header
|
|
7
|
-
{ size: '1fr', class: 'content-row' }, // Content
|
|
8
|
-
{ size: '40px', class: 'footer-row' } // Footer
|
|
9
|
-
])
|
|
10
|
-
.columns([
|
|
11
|
-
{ size: '200px', class: 'sidebar-col' }, // Sidebar
|
|
12
|
-
{ size: '1fr', class: 'main-col' } // Main Content
|
|
13
|
-
])
|
|
14
|
-
.gap('12px')
|
|
15
|
-
.gridder(true) // Enable gridder to visualize the layout
|
|
16
|
-
.render('app');
|
|
File without changes
|
|
File without changes
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { OptionsContractSchema, ValidationResult } from './OptionsContract.js';
|
|
2
|
-
export interface JuxServiceContract<TEngine = any> {
|
|
3
|
-
name: string;
|
|
4
|
-
version?: string;
|
|
5
|
-
targetEnv?: 'client' | 'server' | 'universal';
|
|
6
|
-
install: (engine: TEngine) => void;
|
|
7
|
-
uninstall?: (engine: TEngine) => void;
|
|
8
|
-
}
|
|
9
|
-
export interface BaseState {
|
|
10
|
-
id: string;
|
|
11
|
-
classes: string[];
|
|
12
|
-
visible: boolean;
|
|
13
|
-
disabled: boolean;
|
|
14
|
-
loading: boolean;
|
|
15
|
-
attributes: Record<string, string>;
|
|
16
|
-
}
|
|
17
|
-
type EventListener<T = any> = (data: T) => void;
|
|
18
|
-
/**
|
|
19
|
-
* THE ENGINE AGREEMENT
|
|
20
|
-
*
|
|
21
|
-
* 1. Must define State and Options types.
|
|
22
|
-
* 2. Must implement `prepareState` to map Options -> Initial State.
|
|
23
|
-
* 3. Provides reactivity, eventing, and plugin systems out of the box.
|
|
24
|
-
*/
|
|
25
|
-
export declare abstract class BaseEngine<TState extends BaseState, TOptions = any> {
|
|
26
|
-
#private;
|
|
27
|
-
constructor(id: string, options: TOptions);
|
|
28
|
-
/**
|
|
29
|
-
* CONTRACT: Override to define the valid options schema for this engine.
|
|
30
|
-
* Enables option validation with helpful error messages.
|
|
31
|
-
*/
|
|
32
|
-
protected get optionsSchema(): OptionsContractSchema | null;
|
|
33
|
-
/**
|
|
34
|
-
* Access validation results (warnings, errors, normalized options)
|
|
35
|
-
*/
|
|
36
|
-
get validation(): ValidationResult | null;
|
|
37
|
-
/**
|
|
38
|
-
* CONTRACT: Must transform input options into the initial State.
|
|
39
|
-
* This separates "mapping logic" from "construction/startup logic".
|
|
40
|
-
*/
|
|
41
|
-
protected abstract prepareState(id: string, options: TOptions): TState;
|
|
42
|
-
get state(): TState;
|
|
43
|
-
subscribe(callback: (value: TState) => void): () => void;
|
|
44
|
-
/**
|
|
45
|
-
* Enable/Disable Active Console Logging
|
|
46
|
-
*/
|
|
47
|
-
debug(enabled?: boolean): this;
|
|
48
|
-
protected updateState(patch: Partial<TState>): void;
|
|
49
|
-
/**
|
|
50
|
-
* Revert the state to the previous snapshot
|
|
51
|
-
*/
|
|
52
|
-
rollback(): this;
|
|
53
|
-
/**
|
|
54
|
-
* Redo the previously rolled-back state
|
|
55
|
-
*/
|
|
56
|
-
rollforward(): this;
|
|
57
|
-
/**
|
|
58
|
-
* Local Subscription: Subscribe to a specific named event on THIS instance.
|
|
59
|
-
*/
|
|
60
|
-
on<T = any>(event: string, callback: EventListener<T>): this;
|
|
61
|
-
/**
|
|
62
|
-
* Unsubscribe from a local event.
|
|
63
|
-
*/
|
|
64
|
-
off<T = any>(event: string, callback: EventListener<T>): this;
|
|
65
|
-
/**
|
|
66
|
-
* THE LISTENER (Neighborhood Watch)
|
|
67
|
-
* Listen for events broadcasting on the global frequency.
|
|
68
|
-
* @param channel The global channel name (e.g. 'demo-list-v2:move')
|
|
69
|
-
* @param callback Reaction logic
|
|
70
|
-
*/
|
|
71
|
-
listenTo<T = any>(channel: string, callback: EventListener<T>): this;
|
|
72
|
-
/**
|
|
73
|
-
* Cleanup all global listeners attached by this engine.
|
|
74
|
-
*/
|
|
75
|
-
dispose(): void;
|
|
76
|
-
/**
|
|
77
|
-
* BROADCASTER
|
|
78
|
-
* Emits locally AND to the global neighborhood.
|
|
79
|
-
*/
|
|
80
|
-
protected emit(event: string, data: any): void;
|
|
81
|
-
/**
|
|
82
|
-
* DEBUG: Access the Global Event Bus registry to see active channels and listener identities.
|
|
83
|
-
* Useful for debugging communication topology from the console.
|
|
84
|
-
*/
|
|
85
|
-
get eventRegistry(): Record<string, string[]>;
|
|
86
|
-
/**
|
|
87
|
-
* DEBUG: Access the Internal State Ledger (History).
|
|
88
|
-
* Returns an array of JSON strings representing past states.
|
|
89
|
-
*/
|
|
90
|
-
get stateHistory(): string[];
|
|
91
|
-
/**
|
|
92
|
-
* DEBUG: Access the Event Emission Ledger.
|
|
93
|
-
*/
|
|
94
|
-
get emitHistory(): string[];
|
|
95
|
-
/**
|
|
96
|
-
* Inject a Service/Plugin into this Engine.
|
|
97
|
-
* @param plugin A contract object { name, install, uninstall? }
|
|
98
|
-
*/
|
|
99
|
-
addPlugin(plugin: JuxServiceContract<this>): this;
|
|
100
|
-
/**
|
|
101
|
-
* Remove a plugin and run its teardown logic.
|
|
102
|
-
*/
|
|
103
|
-
removePlugin(name: string): this;
|
|
104
|
-
addClass(className: string): this;
|
|
105
|
-
removeClass(className: string): this;
|
|
106
|
-
visible(isVisible: boolean): this;
|
|
107
|
-
disable(isDisabled?: boolean): this;
|
|
108
|
-
loading(isLoading?: boolean): this;
|
|
109
|
-
attr(key: string, value: string): this;
|
|
110
|
-
}
|
|
111
|
-
export {};
|
|
112
|
-
//# sourceMappingURL=BaseEngine.d.ts.map
|
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
-
};
|
|
6
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
7
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
9
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
10
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
11
|
-
};
|
|
12
|
-
var _BaseEngine_state, _BaseEngine_listeners, _BaseEngine_cleanupListeners, _BaseEngine_plugins, _BaseEngine_emitHistory, _BaseEngine_debugMode, _BaseEngine_validationResult;
|
|
13
|
-
import { State } from './State.js';
|
|
14
|
-
import { Neighborhood } from './Neighborhood.js';
|
|
15
|
-
import { validateOptions } from './OptionsContract.js';
|
|
16
|
-
/**
|
|
17
|
-
* THE ENGINE AGREEMENT
|
|
18
|
-
*
|
|
19
|
-
* 1. Must define State and Options types.
|
|
20
|
-
* 2. Must implement `prepareState` to map Options -> Initial State.
|
|
21
|
-
* 3. Provides reactivity, eventing, and plugin systems out of the box.
|
|
22
|
-
*/
|
|
23
|
-
export class BaseEngine {
|
|
24
|
-
constructor(id, options) {
|
|
25
|
-
_BaseEngine_state.set(this, void 0);
|
|
26
|
-
_BaseEngine_listeners.set(this, new Map());
|
|
27
|
-
_BaseEngine_cleanupListeners.set(this, []);
|
|
28
|
-
_BaseEngine_plugins.set(this, new Map());
|
|
29
|
-
_BaseEngine_emitHistory.set(this, []);
|
|
30
|
-
_BaseEngine_debugMode.set(this, false);
|
|
31
|
-
_BaseEngine_validationResult.set(this, null);
|
|
32
|
-
// Validate options if schema is defined
|
|
33
|
-
const schema = this.optionsSchema;
|
|
34
|
-
if (schema) {
|
|
35
|
-
__classPrivateFieldSet(this, _BaseEngine_validationResult, validateOptions(this.constructor.name, options, schema, __classPrivateFieldGet(this, _BaseEngine_debugMode, "f")), "f");
|
|
36
|
-
options = __classPrivateFieldGet(this, _BaseEngine_validationResult, "f").normalized;
|
|
37
|
-
}
|
|
38
|
-
// Enforce the Contract: Child must define how state is born from options
|
|
39
|
-
const initialState = this.prepareState(id, options);
|
|
40
|
-
__classPrivateFieldSet(this, _BaseEngine_state, new State(initialState), "f");
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* CONTRACT: Override to define the valid options schema for this engine.
|
|
44
|
-
* Enables option validation with helpful error messages.
|
|
45
|
-
*/
|
|
46
|
-
get optionsSchema() {
|
|
47
|
-
return null; // Override in child classes
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Access validation results (warnings, errors, normalized options)
|
|
51
|
-
*/
|
|
52
|
-
get validation() {
|
|
53
|
-
return __classPrivateFieldGet(this, _BaseEngine_validationResult, "f");
|
|
54
|
-
}
|
|
55
|
-
get state() {
|
|
56
|
-
return __classPrivateFieldGet(this, _BaseEngine_state, "f").value;
|
|
57
|
-
}
|
|
58
|
-
subscribe(callback) {
|
|
59
|
-
return __classPrivateFieldGet(this, _BaseEngine_state, "f").subscribe(callback);
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Enable/Disable Active Console Logging
|
|
63
|
-
*/
|
|
64
|
-
debug(enabled = true) {
|
|
65
|
-
__classPrivateFieldSet(this, _BaseEngine_debugMode, enabled, "f");
|
|
66
|
-
if (enabled) {
|
|
67
|
-
console.info(`%c[JUX DEBUG] Mode Enabled for %c${this.state.id}`, 'color: #ff00ff; font-weight: bold;', 'font-weight: bold;');
|
|
68
|
-
}
|
|
69
|
-
return this;
|
|
70
|
-
}
|
|
71
|
-
updateState(patch) {
|
|
72
|
-
if (__classPrivateFieldGet(this, _BaseEngine_debugMode, "f")) {
|
|
73
|
-
console.groupCollapsed(`%c 💾 STATE %c ${this.state.id}`, 'color: #ff9900; font-weight: bold;', 'color: #888');
|
|
74
|
-
console.log('Patch:', patch);
|
|
75
|
-
console.log('Result:', { ...__classPrivateFieldGet(this, _BaseEngine_state, "f").value, ...patch });
|
|
76
|
-
console.groupEnd();
|
|
77
|
-
}
|
|
78
|
-
__classPrivateFieldGet(this, _BaseEngine_state, "f").set({ ...__classPrivateFieldGet(this, _BaseEngine_state, "f").value, ...patch });
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Revert the state to the previous snapshot
|
|
82
|
-
*/
|
|
83
|
-
rollback() {
|
|
84
|
-
__classPrivateFieldGet(this, _BaseEngine_state, "f").rollback();
|
|
85
|
-
this.emit('rollback', { index: __classPrivateFieldGet(this, _BaseEngine_state, "f").history.length }); // ✅ Added Emission
|
|
86
|
-
return this; // ✅ Fluent Return
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Redo the previously rolled-back state
|
|
90
|
-
*/
|
|
91
|
-
rollforward() {
|
|
92
|
-
__classPrivateFieldGet(this, _BaseEngine_state, "f").rollforward();
|
|
93
|
-
this.emit('rollforward', { index: __classPrivateFieldGet(this, _BaseEngine_state, "f").history.length }); // ✅ Added Emission
|
|
94
|
-
return this; // ✅ Fluent Return
|
|
95
|
-
}
|
|
96
|
-
// --- Interaction System ---
|
|
97
|
-
/**
|
|
98
|
-
* Local Subscription: Subscribe to a specific named event on THIS instance.
|
|
99
|
-
*/
|
|
100
|
-
on(event, callback) {
|
|
101
|
-
if (!__classPrivateFieldGet(this, _BaseEngine_listeners, "f").has(event)) {
|
|
102
|
-
__classPrivateFieldGet(this, _BaseEngine_listeners, "f").set(event, new Set());
|
|
103
|
-
}
|
|
104
|
-
__classPrivateFieldGet(this, _BaseEngine_listeners, "f").get(event).add(callback);
|
|
105
|
-
return this;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Unsubscribe from a local event.
|
|
109
|
-
*/
|
|
110
|
-
off(event, callback) {
|
|
111
|
-
__classPrivateFieldGet(this, _BaseEngine_listeners, "f").get(event)?.delete(callback);
|
|
112
|
-
return this;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* THE LISTENER (Neighborhood Watch)
|
|
116
|
-
* Listen for events broadcasting on the global frequency.
|
|
117
|
-
* @param channel The global channel name (e.g. 'demo-list-v2:move')
|
|
118
|
-
* @param callback Reaction logic
|
|
119
|
-
*/
|
|
120
|
-
listenTo(channel, callback) {
|
|
121
|
-
Neighborhood.on(channel, callback);
|
|
122
|
-
// Track for cleanup
|
|
123
|
-
__classPrivateFieldGet(this, _BaseEngine_cleanupListeners, "f").push(() => Neighborhood.off(channel, callback));
|
|
124
|
-
return this;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Cleanup all global listeners attached by this engine.
|
|
128
|
-
*/
|
|
129
|
-
dispose() {
|
|
130
|
-
// 1. Uninstall Plugins
|
|
131
|
-
__classPrivateFieldGet(this, _BaseEngine_plugins, "f").forEach(p => {
|
|
132
|
-
try {
|
|
133
|
-
if (p.uninstall)
|
|
134
|
-
p.uninstall(this);
|
|
135
|
-
}
|
|
136
|
-
catch (e) {
|
|
137
|
-
console.error(`Jux: Error uninstalling plugin ${p.name}`, e);
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
__classPrivateFieldGet(this, _BaseEngine_plugins, "f").clear();
|
|
141
|
-
// 2. Clear Listeners
|
|
142
|
-
__classPrivateFieldGet(this, _BaseEngine_cleanupListeners, "f").forEach(cleanup => cleanup());
|
|
143
|
-
__classPrivateFieldSet(this, _BaseEngine_cleanupListeners, [], "f");
|
|
144
|
-
if (__classPrivateFieldGet(this, _BaseEngine_debugMode, "f"))
|
|
145
|
-
console.log(`%c[JUX] Disposed ${this.state.id}`, 'color: #888');
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* BROADCASTER
|
|
149
|
-
* Emits locally AND to the global neighborhood.
|
|
150
|
-
*/
|
|
151
|
-
emit(event, data) {
|
|
152
|
-
const timestamp = new Date().toISOString();
|
|
153
|
-
// 0. Record History
|
|
154
|
-
__classPrivateFieldGet(this, _BaseEngine_emitHistory, "f").push(JSON.stringify({ timestamp, event, data }));
|
|
155
|
-
if (__classPrivateFieldGet(this, _BaseEngine_debugMode, "f")) {
|
|
156
|
-
console.log(`%c 📡 EMIT %c ${this.state.id}:${event}`, 'color: #00ccff; font-weight: bold;', 'color: #333; font-weight: bold;', data);
|
|
157
|
-
}
|
|
158
|
-
// 1. Notify Local Listeners
|
|
159
|
-
__classPrivateFieldGet(this, _BaseEngine_listeners, "f").get(event)?.forEach(cb => cb(data));
|
|
160
|
-
// 2. Notify The Neighborhood (Global Bus)
|
|
161
|
-
// Format: "ComponentID:EventName"
|
|
162
|
-
const globalChannel = `${this.state.id}:${event}`;
|
|
163
|
-
Neighborhood.emit(globalChannel, {
|
|
164
|
-
...data,
|
|
165
|
-
_event: event,
|
|
166
|
-
_source: this.state.id
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* DEBUG: Access the Global Event Bus registry to see active channels and listener identities.
|
|
171
|
-
* Useful for debugging communication topology from the console.
|
|
172
|
-
*/
|
|
173
|
-
get eventRegistry() {
|
|
174
|
-
return Neighborhood.registry;
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* DEBUG: Access the Internal State Ledger (History).
|
|
178
|
-
* Returns an array of JSON strings representing past states.
|
|
179
|
-
*/
|
|
180
|
-
get stateHistory() {
|
|
181
|
-
return __classPrivateFieldGet(this, _BaseEngine_state, "f").history;
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* DEBUG: Access the Event Emission Ledger.
|
|
185
|
-
*/
|
|
186
|
-
get emitHistory() {
|
|
187
|
-
return [...__classPrivateFieldGet(this, _BaseEngine_emitHistory, "f")];
|
|
188
|
-
}
|
|
189
|
-
/* ═════════════════════════════════════════════════════════════════
|
|
190
|
-
* EXTENSION SYSTEM (DI / Plugins)
|
|
191
|
-
* ═════════════════════════════════════════════════════════════════ */
|
|
192
|
-
/**
|
|
193
|
-
* Inject a Service/Plugin into this Engine.
|
|
194
|
-
* @param plugin A contract object { name, install, uninstall? }
|
|
195
|
-
*/
|
|
196
|
-
addPlugin(plugin) {
|
|
197
|
-
if (__classPrivateFieldGet(this, _BaseEngine_plugins, "f").has(plugin.name)) {
|
|
198
|
-
console.warn(`Jux: Plugin "${plugin.name}" already registered on ${this.state.id}.`);
|
|
199
|
-
return this;
|
|
200
|
-
}
|
|
201
|
-
if (__classPrivateFieldGet(this, _BaseEngine_debugMode, "f")) {
|
|
202
|
-
console.log(`%c 🔌 PLUGIN %c Installed: ${plugin.name} (v${plugin.version || '?'})`, 'color: #cc00ff; font-weight: bold;', 'color: #333');
|
|
203
|
-
}
|
|
204
|
-
__classPrivateFieldGet(this, _BaseEngine_plugins, "f").set(plugin.name, plugin);
|
|
205
|
-
try {
|
|
206
|
-
plugin.install(this);
|
|
207
|
-
this.emit('plugin:added', { name: plugin.name });
|
|
208
|
-
}
|
|
209
|
-
catch (err) {
|
|
210
|
-
console.error(`Jux: Failed to install plugin "${plugin.name}"`, err);
|
|
211
|
-
// Rollback registration on failure
|
|
212
|
-
__classPrivateFieldGet(this, _BaseEngine_plugins, "f").delete(plugin.name);
|
|
213
|
-
}
|
|
214
|
-
return this;
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Remove a plugin and run its teardown logic.
|
|
218
|
-
*/
|
|
219
|
-
removePlugin(name) {
|
|
220
|
-
const plugin = __classPrivateFieldGet(this, _BaseEngine_plugins, "f").get(name);
|
|
221
|
-
if (plugin) {
|
|
222
|
-
if (plugin.uninstall) {
|
|
223
|
-
try {
|
|
224
|
-
plugin.uninstall(this);
|
|
225
|
-
}
|
|
226
|
-
catch (err) {
|
|
227
|
-
console.error(`Jux: Error uninstalling plugin "${name}"`, err);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
__classPrivateFieldGet(this, _BaseEngine_plugins, "f").delete(name);
|
|
231
|
-
this.emit('plugin:removed', { name });
|
|
232
|
-
}
|
|
233
|
-
return this;
|
|
234
|
-
}
|
|
235
|
-
/* ═════════════════════════════════════════════════════════════════
|
|
236
|
-
* COMMON FLUENT API (Universal Capabilities)
|
|
237
|
-
* ═════════════════════════════════════════════════════════════════ */
|
|
238
|
-
addClass(className) {
|
|
239
|
-
const current = this.state.classes;
|
|
240
|
-
if (!current.includes(className)) {
|
|
241
|
-
this.updateState({ classes: [...current, className] });
|
|
242
|
-
this.emit('classAdd', { className });
|
|
243
|
-
}
|
|
244
|
-
return this;
|
|
245
|
-
}
|
|
246
|
-
removeClass(className) {
|
|
247
|
-
const current = this.state.classes;
|
|
248
|
-
this.updateState({
|
|
249
|
-
classes: current.filter(c => c !== className)
|
|
250
|
-
});
|
|
251
|
-
this.emit('classRemove', { className });
|
|
252
|
-
return this;
|
|
253
|
-
}
|
|
254
|
-
visible(isVisible) {
|
|
255
|
-
this.updateState({ visible: isVisible });
|
|
256
|
-
this.emit('visible', { visible: isVisible });
|
|
257
|
-
return this;
|
|
258
|
-
}
|
|
259
|
-
disable(isDisabled = true) {
|
|
260
|
-
this.updateState({ disabled: isDisabled });
|
|
261
|
-
this.emit('disabled', { disabled: isDisabled });
|
|
262
|
-
return this;
|
|
263
|
-
}
|
|
264
|
-
loading(isLoading = true) {
|
|
265
|
-
this.updateState({ loading: isLoading });
|
|
266
|
-
this.emit('loading', { loading: isLoading });
|
|
267
|
-
return this;
|
|
268
|
-
}
|
|
269
|
-
attr(key, value) {
|
|
270
|
-
const current = this.state.attributes;
|
|
271
|
-
this.updateState({
|
|
272
|
-
attributes: { ...current, [key]: value }
|
|
273
|
-
});
|
|
274
|
-
this.emit('attribute', { key, value });
|
|
275
|
-
return this;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
_BaseEngine_state = new WeakMap(), _BaseEngine_listeners = new WeakMap(), _BaseEngine_cleanupListeners = new WeakMap(), _BaseEngine_plugins = new WeakMap(), _BaseEngine_emitHistory = new WeakMap(), _BaseEngine_debugMode = new WeakMap(), _BaseEngine_validationResult = new WeakMap();
|
|
279
|
-
//# sourceMappingURL=BaseEngine.js.map
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { BaseEngine, BaseState } from './BaseEngine.js';
|
|
2
|
-
/**
|
|
3
|
-
* THE SKIN AGREEMENT
|
|
4
|
-
*
|
|
5
|
-
* A Skin must:
|
|
6
|
-
* 1. Hold a reference to its Engine.
|
|
7
|
-
* 2. Implement `structureCss` to provide layout styles.
|
|
8
|
-
* 3. Implement hooks for creation (`createRoot`) and event binding (`bindEvents`).
|
|
9
|
-
* 4. Implement `updateSkin(state)` to react to State changes.
|
|
10
|
-
*/
|
|
11
|
-
export declare abstract class BaseSkin<TState extends BaseState, TEngine extends BaseEngine<TState>> {
|
|
12
|
-
protected engine: TEngine;
|
|
13
|
-
protected root: HTMLElement | null;
|
|
14
|
-
private _cleanupTasks;
|
|
15
|
-
constructor(engine: TEngine);
|
|
16
|
-
/**
|
|
17
|
-
* CONTRACT: Provide the URL/Path to the structural CSS file.
|
|
18
|
-
*
|
|
19
|
-
* 💡 WHY `import.meta.url`?
|
|
20
|
-
* Standard `import` statements load JS modules. To load ASSETS (like CSS) at runtime,
|
|
21
|
-
* we need their full URL. `import.meta.url` tells the browser "Start looking from THIS file".
|
|
22
|
-
*
|
|
23
|
-
* Usage: return new URL('./structure.css', import.meta.url).href;
|
|
24
|
-
*/
|
|
25
|
-
protected abstract get structureCss(): string;
|
|
26
|
-
/**
|
|
27
|
-
* Utility: Inject or Update a CSS Link tag in the document head.
|
|
28
|
-
* Allows for external CSS files ('references') and runtime Theme Swapping.
|
|
29
|
-
* @param id Unique ID for the link tag
|
|
30
|
-
* @param href The URL to the CSS file
|
|
31
|
-
*/
|
|
32
|
-
injectCSSLink(id: string, href: string): void;
|
|
33
|
-
/**
|
|
34
|
-
* Utility: Subscribe to MY Engine's events.
|
|
35
|
-
* "Me" refers to this component instance (Engine + Skin).
|
|
36
|
-
*
|
|
37
|
-
* Use this for internal signals like "loginSuccess", "error", or "animationStart".
|
|
38
|
-
*/
|
|
39
|
-
protected onSelf(event: string, callback: (data: any) => void): void;
|
|
40
|
-
/**
|
|
41
|
-
* Utility: Subscribe to the Global Bus (The Neighborhood).
|
|
42
|
-
* "Neighbors" refers to other components or global system events.
|
|
43
|
-
*
|
|
44
|
-
* Use this for purely visual coordination like "theme:switched" or "layout:collapse-all".
|
|
45
|
-
*/
|
|
46
|
-
protected onNeighbor(channel: string, callback: (data: any) => void): void;
|
|
47
|
-
/**
|
|
48
|
-
* Component Teardown.
|
|
49
|
-
* Removes the root element and cleans up all event listeners.
|
|
50
|
-
*/
|
|
51
|
-
dispose(): void;
|
|
52
|
-
/**
|
|
53
|
-
* Utility: Inject CSS into the document head if not already present.
|
|
54
|
-
* Useful for Skins to seamlessly load their required aesthetics.
|
|
55
|
-
*/
|
|
56
|
-
/**
|
|
57
|
-
* API: Hot-Swap the Aesthetic Skin.
|
|
58
|
-
* Replaces the component-specific CSS styles at runtime.
|
|
59
|
-
*/
|
|
60
|
-
setTheme(cssContent: string): void;
|
|
61
|
-
/**
|
|
62
|
-
* Template Method: Render
|
|
63
|
-
* Orchestrates the standard lifecycle: Create -> Bind -> Mount -> Subscribe.
|
|
64
|
-
*/
|
|
65
|
-
renderSkin(targetElement: HTMLElement, mode?: 'append' | 'prepend'): void;
|
|
66
|
-
protected createRoot(): HTMLElement;
|
|
67
|
-
protected abstract bindEvents(root: HTMLElement): void;
|
|
68
|
-
protected abstract updateSkin(state: TState): void;
|
|
69
|
-
/**
|
|
70
|
-
* HELPER: Applies universal Jux behavior (visibility, ID, disabled)
|
|
71
|
-
*/
|
|
72
|
-
protected applySkinAttributes(element: HTMLElement, state: TState): void;
|
|
73
|
-
}
|
|
74
|
-
//# sourceMappingURL=BaseSkin.d.ts.map
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { Neighborhood } from './Neighborhood.js';
|
|
2
|
-
/**
|
|
3
|
-
* THE SKIN AGREEMENT
|
|
4
|
-
*
|
|
5
|
-
* A Skin must:
|
|
6
|
-
* 1. Hold a reference to its Engine.
|
|
7
|
-
* 2. Implement `structureCss` to provide layout styles.
|
|
8
|
-
* 3. Implement hooks for creation (`createRoot`) and event binding (`bindEvents`).
|
|
9
|
-
* 4. Implement `updateSkin(state)` to react to State changes.
|
|
10
|
-
*/
|
|
11
|
-
export class BaseSkin {
|
|
12
|
-
constructor(engine) {
|
|
13
|
-
this.root = null;
|
|
14
|
-
this._cleanupTasks = [];
|
|
15
|
-
this.engine = engine;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Utility: Inject or Update a CSS Link tag in the document head.
|
|
19
|
-
* Allows for external CSS files ('references') and runtime Theme Swapping.
|
|
20
|
-
* @param id Unique ID for the link tag
|
|
21
|
-
* @param href The URL to the CSS file
|
|
22
|
-
*/
|
|
23
|
-
injectCSSLink(id, href) {
|
|
24
|
-
if (typeof document === 'undefined')
|
|
25
|
-
return;
|
|
26
|
-
let link = document.getElementById(id);
|
|
27
|
-
if (!link) {
|
|
28
|
-
link = document.createElement('link');
|
|
29
|
-
link.id = id;
|
|
30
|
-
link.rel = 'stylesheet';
|
|
31
|
-
document.head.appendChild(link);
|
|
32
|
-
}
|
|
33
|
-
if (link.href !== href) {
|
|
34
|
-
link.href = href;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Utility: Subscribe to MY Engine's events.
|
|
39
|
-
* "Me" refers to this component instance (Engine + Skin).
|
|
40
|
-
*
|
|
41
|
-
* Use this for internal signals like "loginSuccess", "error", or "animationStart".
|
|
42
|
-
*/
|
|
43
|
-
onSelf(event, callback) {
|
|
44
|
-
this.engine.on(event, callback);
|
|
45
|
-
this._cleanupTasks.push(() => this.engine.off(event, callback));
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Utility: Subscribe to the Global Bus (The Neighborhood).
|
|
49
|
-
* "Neighbors" refers to other components or global system events.
|
|
50
|
-
*
|
|
51
|
-
* Use this for purely visual coordination like "theme:switched" or "layout:collapse-all".
|
|
52
|
-
*/
|
|
53
|
-
onNeighbor(channel, callback) {
|
|
54
|
-
Neighborhood.on(channel, callback);
|
|
55
|
-
this._cleanupTasks.push(() => Neighborhood.off(channel, callback));
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Component Teardown.
|
|
59
|
-
* Removes the root element and cleans up all event listeners.
|
|
60
|
-
*/
|
|
61
|
-
dispose() {
|
|
62
|
-
this._cleanupTasks.forEach(task => task());
|
|
63
|
-
this._cleanupTasks = [];
|
|
64
|
-
if (this.root) {
|
|
65
|
-
this.root.remove();
|
|
66
|
-
this.root = null;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Utility: Inject CSS into the document head if not already present.
|
|
71
|
-
* Useful for Skins to seamlessly load their required aesthetics.
|
|
72
|
-
*/
|
|
73
|
-
/**
|
|
74
|
-
* API: Hot-Swap the Aesthetic Skin.
|
|
75
|
-
* Replaces the component-specific CSS styles at runtime.
|
|
76
|
-
*/
|
|
77
|
-
setTheme(cssContent) {
|
|
78
|
-
const id = `jux-skin-${this.engine.state.id}-theme`;
|
|
79
|
-
const oldStyle = document.getElementById(id);
|
|
80
|
-
if (oldStyle)
|
|
81
|
-
oldStyle.remove();
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Template Method: Render
|
|
85
|
-
* Orchestrates the standard lifecycle: Create -> Bind -> Mount -> Subscribe.
|
|
86
|
-
*/
|
|
87
|
-
renderSkin(targetElement, mode = 'append') {
|
|
88
|
-
// 0. Inject Immutable Structure (Layout logic)
|
|
89
|
-
// We use constructor.name to deduplicate style tags across multiple instances of the same component type.
|
|
90
|
-
// 1. Create Root (Abstract Hook)
|
|
91
|
-
this.root = this.createRoot();
|
|
92
|
-
// 2. Bind Events (Hook)
|
|
93
|
-
this.bindEvents(this.root);
|
|
94
|
-
// 3. Mount
|
|
95
|
-
if (mode === 'prepend') {
|
|
96
|
-
targetElement.prepend(this.root);
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
targetElement.appendChild(this.root);
|
|
100
|
-
}
|
|
101
|
-
// 4. Subscribe (Automatic)
|
|
102
|
-
this.engine.subscribe((state) => this.updateSkin(state));
|
|
103
|
-
}
|
|
104
|
-
createRoot() {
|
|
105
|
-
return document.createElement('div');
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* HELPER: Applies universal Jux behavior (visibility, ID, disabled)
|
|
109
|
-
*/
|
|
110
|
-
applySkinAttributes(element, state) {
|
|
111
|
-
element.style.display = state.visible ? '' : 'none';
|
|
112
|
-
element.dataset.id = state.id;
|
|
113
|
-
if (state.disabled) {
|
|
114
|
-
element.setAttribute('aria-disabled', 'true');
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
element.removeAttribute('aria-disabled');
|
|
118
|
-
}
|
|
119
|
-
if (state.loading) {
|
|
120
|
-
element.setAttribute('aria-busy', 'true');
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
element.removeAttribute('aria-busy');
|
|
124
|
-
}
|
|
125
|
-
Object.entries(state.attributes).forEach(([k, v]) => {
|
|
126
|
-
element.setAttribute(k, v);
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
//# sourceMappingURL=BaseSkin.js.map
|