juxscript 1.0.62 → 1.0.63

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.
Files changed (141) hide show
  1. package/bin/cli.js +161 -293
  2. package/docs/v2comps/HEADLESS.md +83 -0
  3. package/docs/v2comps/ISOMORPHISM.md +10 -0
  4. package/juxconfig.example.js +63 -58
  5. package/lib/componentsv2/base/BaseEngine.js +258 -0
  6. package/lib/componentsv2/base/BaseEngine.js.map +1 -0
  7. package/lib/componentsv2/base/BaseEngine.ts +303 -0
  8. package/lib/componentsv2/base/BaseSkin.js +108 -0
  9. package/lib/componentsv2/base/BaseSkin.js.map +1 -0
  10. package/lib/componentsv2/base/BaseSkin.ts +137 -0
  11. package/lib/componentsv2/base/GlobalBus.js +56 -0
  12. package/lib/componentsv2/base/GlobalBus.js.map +1 -0
  13. package/lib/componentsv2/base/GlobalBus.ts +60 -0
  14. package/lib/componentsv2/base/State.js +68 -0
  15. package/lib/componentsv2/base/State.js.map +1 -0
  16. package/lib/componentsv2/base/State.ts +62 -0
  17. package/lib/componentsv2/grid/component.js +41 -0
  18. package/lib/componentsv2/grid/component.js.map +1 -0
  19. package/lib/componentsv2/grid/component.ts +67 -0
  20. package/lib/componentsv2/grid/engine.js +73 -0
  21. package/lib/componentsv2/grid/engine.js.map +1 -0
  22. package/lib/componentsv2/grid/engine.ts +110 -0
  23. package/lib/componentsv2/grid/skin.js +95 -0
  24. package/lib/componentsv2/grid/skin.js.map +1 -0
  25. package/lib/componentsv2/grid/skin.ts +105 -0
  26. package/lib/componentsv2/grid/structure.css +58 -0
  27. package/lib/componentsv2/index.js +218 -0
  28. package/lib/componentsv2/index.js.map +1 -0
  29. package/lib/componentsv2/index.ts +253 -0
  30. package/lib/componentsv2/input/component.js +21 -0
  31. package/lib/componentsv2/input/component.js.map +1 -0
  32. package/lib/componentsv2/input/component.ts +28 -0
  33. package/lib/componentsv2/input/engine.js +50 -0
  34. package/lib/componentsv2/input/engine.js.map +1 -0
  35. package/lib/componentsv2/input/engine.ts +76 -0
  36. package/lib/componentsv2/input/skin.js +91 -0
  37. package/lib/componentsv2/input/skin.js.map +1 -0
  38. package/lib/componentsv2/input/skin.ts +91 -0
  39. package/lib/componentsv2/input/structure.css +47 -0
  40. package/lib/componentsv2/list/component.js +83 -0
  41. package/lib/componentsv2/list/component.js.map +1 -0
  42. package/lib/componentsv2/list/component.ts +97 -0
  43. package/lib/componentsv2/list/engine.js +261 -0
  44. package/lib/componentsv2/list/engine.js.map +1 -0
  45. package/lib/componentsv2/list/engine.ts +345 -0
  46. package/lib/componentsv2/list/skin.js +343 -0
  47. package/lib/componentsv2/list/skin.js.map +1 -0
  48. package/lib/componentsv2/list/skin.ts +367 -0
  49. package/lib/componentsv2/list/structure.css +359 -0
  50. package/lib/componentsv2/plugins/ClientSQLitePlugin.js +130 -0
  51. package/lib/componentsv2/plugins/ClientSQLitePlugin.js.map +1 -0
  52. package/lib/componentsv2/plugins/ClientSQLitePlugin.ts +154 -0
  53. package/lib/componentsv2/plugins/IndexedDBPlugin.js +75 -0
  54. package/lib/componentsv2/plugins/IndexedDBPlugin.js.map +1 -0
  55. package/lib/componentsv2/plugins/IndexedDBPlugin.ts +96 -0
  56. package/lib/componentsv2/plugins/LocalStoragePlugin.js +65 -0
  57. package/lib/componentsv2/plugins/LocalStoragePlugin.js.map +1 -0
  58. package/lib/componentsv2/plugins/LocalStoragePlugin.ts +86 -0
  59. package/lib/componentsv2/plugins/ServerSQLitePlugin.js +70 -0
  60. package/lib/componentsv2/plugins/ServerSQLitePlugin.js.map +1 -0
  61. package/lib/componentsv2/plugins/ServerSQLitePlugin.ts +99 -0
  62. package/lib/componentsv2/stubs/ComponentComposition.ts.stub +32 -0
  63. package/lib/componentsv2/stubs/ComponentEngine.ts.stub +36 -0
  64. package/lib/componentsv2/stubs/ComponentSkin.ts.stub +34 -0
  65. package/lib/componentsv2/stubs/ComponentStructure.css.stub +13 -0
  66. package/lib/componentsv2/tools/CreateSkin.js +62 -0
  67. package/lib/componentsv2/tools/DocSpam.js +134 -0
  68. package/lib/componentsv2/tools/FluencyAudit.js +141 -0
  69. package/lib/componentsv2/tools/OptionsAudit.js +177 -0
  70. package/lib/componentsv2/tools/Scaffold.js +140 -0
  71. package/lib/utils/fetch.js +428 -0
  72. package/lib/utils/fetch.js.map +1 -0
  73. package/machinery/build.js +2 -1
  74. package/machinery/compiler.js +200 -37
  75. package/machinery/config.js +93 -6
  76. package/machinery/diagnose.js +72 -0
  77. package/machinery/jux-module-pattern.md +118 -0
  78. package/machinery/server.js +23 -7
  79. package/machinery/verifier.js +143 -0
  80. package/machinery/watcher.js +53 -64
  81. package/package.json +11 -2
  82. package/lib/components/alert.ts +0 -200
  83. package/lib/components/app.ts +0 -258
  84. package/lib/components/badge.ts +0 -101
  85. package/lib/components/base/BaseComponent.ts +0 -417
  86. package/lib/components/base/FormInput.ts +0 -227
  87. package/lib/components/button.ts +0 -178
  88. package/lib/components/card.ts +0 -173
  89. package/lib/components/chart.ts +0 -231
  90. package/lib/components/checkbox.ts +0 -242
  91. package/lib/components/code.ts +0 -123
  92. package/lib/components/container.ts +0 -140
  93. package/lib/components/data.ts +0 -135
  94. package/lib/components/datepicker.ts +0 -234
  95. package/lib/components/dialog.ts +0 -172
  96. package/lib/components/divider.ts +0 -100
  97. package/lib/components/dropdown.ts +0 -186
  98. package/lib/components/element.ts +0 -267
  99. package/lib/components/error-handler.ts +0 -285
  100. package/lib/components/fileupload.ts +0 -309
  101. package/lib/components/grid.ts +0 -291
  102. package/lib/components/guard.ts +0 -92
  103. package/lib/components/heading.ts +0 -96
  104. package/lib/components/helpers.ts +0 -41
  105. package/lib/components/hero.ts +0 -224
  106. package/lib/components/icon.ts +0 -160
  107. package/lib/components/icons.ts +0 -175
  108. package/lib/components/include.ts +0 -440
  109. package/lib/components/input.ts +0 -457
  110. package/lib/components/list.ts +0 -419
  111. package/lib/components/loading.ts +0 -100
  112. package/lib/components/menu.ts +0 -260
  113. package/lib/components/modal.ts +0 -239
  114. package/lib/components/nav.ts +0 -257
  115. package/lib/components/paragraph.ts +0 -97
  116. package/lib/components/progress.ts +0 -139
  117. package/lib/components/radio.ts +0 -278
  118. package/lib/components/req.ts +0 -302
  119. package/lib/components/script.ts +0 -43
  120. package/lib/components/select.ts +0 -252
  121. package/lib/components/sidebar.ts +0 -167
  122. package/lib/components/style.ts +0 -43
  123. package/lib/components/switch.ts +0 -246
  124. package/lib/components/table.ts +0 -1249
  125. package/lib/components/tabs.ts +0 -250
  126. package/lib/components/theme-toggle.ts +0 -300
  127. package/lib/components/token-calculator.ts +0 -313
  128. package/lib/components/tooltip.ts +0 -144
  129. package/lib/components/view.ts +0 -190
  130. package/lib/components/write.ts +0 -272
  131. package/lib/jux.ts +0 -365
  132. package/lib/layouts/default.css +0 -260
  133. package/lib/layouts/figma.css +0 -334
  134. package/lib/reactivity/state.ts +0 -78
  135. package/machinery/bundleAssets.js +0 -0
  136. package/machinery/bundleJux.js +0 -0
  137. package/machinery/bundleVendors.js +0 -0
  138. package/presets/default/all.jux +0 -343
  139. package/presets/default/index.jux +0 -90
  140. package/presets/default/layout.jux +0 -57
  141. package/presets/default/style.css +0 -1612
@@ -1,278 +0,0 @@
1
- import { FormInput, FormInputState } from './base/FormInput.js';
2
-
3
- // Event definitions
4
- const TRIGGER_EVENTS = [] as const;
5
- const CALLBACK_EVENTS = ['change'] as const;
6
-
7
- export interface RadioOption {
8
- label: string;
9
- value: string;
10
- disabled?: boolean;
11
- }
12
-
13
- export interface RadioOptions {
14
- options?: RadioOption[];
15
- value?: string;
16
- label?: string;
17
- required?: boolean;
18
- disabled?: boolean;
19
- name?: string;
20
- orientation?: 'vertical' | 'horizontal'; // ✅ Add orientation
21
- style?: string;
22
- class?: string;
23
- onValidate?: (value: string) => boolean | string;
24
- }
25
-
26
- interface RadioState extends FormInputState {
27
- options: RadioOption[];
28
- value: string;
29
- orientation: 'vertical' | 'horizontal'; // ✅ Add to state
30
- }
31
-
32
- export class Radio extends FormInput<RadioState> {
33
- private _radioInputs: HTMLInputElement[] = [];
34
-
35
- constructor(id: string, options: RadioOptions = {}) {
36
- super(id, {
37
- options: options.options ?? [],
38
- value: options.value ?? '',
39
- label: options.label ?? '',
40
- required: options.required ?? false,
41
- disabled: options.disabled ?? false,
42
- name: options.name ?? id,
43
- orientation: options.orientation ?? 'vertical', // ✅ Default to vertical
44
- style: options.style ?? '',
45
- class: options.class ?? '',
46
- errorMessage: undefined
47
- });
48
-
49
- if (options.onValidate) {
50
- this._onValidate = options.onValidate;
51
- }
52
- }
53
-
54
- protected getTriggerEvents(): readonly string[] {
55
- return TRIGGER_EVENTS;
56
- }
57
-
58
- protected getCallbackEvents(): readonly string[] {
59
- return CALLBACK_EVENTS;
60
- }
61
-
62
- /* ═════════════════════════════════════════════════════════════════
63
- * FLUENT API
64
- * ═════════════════════════════════════════════════════════════════ */
65
-
66
- // ✅ Inherited from FormInput/BaseComponent:
67
- // - label(), required(), name(), onValidate()
68
- // - validate(), isValid()
69
- // - style(), class()
70
- // - bind(), sync(), renderTo()
71
- // - disabled(), enable(), disable()
72
-
73
- options(value: RadioOption[]): this {
74
- this.state.options = value;
75
- return this;
76
- }
77
-
78
- value(value: string): this {
79
- return this.setValue(value);
80
- }
81
-
82
- addOption(option: RadioOption): this {
83
- this.state.options = [...this.state.options, option];
84
- return this;
85
- }
86
-
87
- orientation(value: 'vertical' | 'horizontal'): this {
88
- this.state.orientation = value;
89
- return this;
90
- }
91
-
92
- /* ═════════════════════════════════════════════════════════════════
93
- * FORM INPUT IMPLEMENTATION
94
- * ═════════════════════════════════════════════════════════════════ */
95
-
96
- getValue(): string {
97
- return this.state.value;
98
- }
99
-
100
- setValue(value: string): this {
101
- this.state.value = value;
102
-
103
- // Update all radio inputs
104
- this._radioInputs.forEach(input => {
105
- input.checked = input.value === value;
106
- });
107
-
108
- return this;
109
- }
110
-
111
- protected _validateValue(value: string): boolean | string {
112
- const { required, options } = this.state;
113
-
114
- if (required && !value) {
115
- return 'Please select an option';
116
- }
117
-
118
- // Validate that value is one of the options
119
- if (value && !options.some(opt => opt.value === value)) {
120
- return 'Invalid option selected';
121
- }
122
-
123
- if (this._onValidate) {
124
- const result = this._onValidate(value);
125
- if (result !== true) {
126
- return result || 'Invalid value';
127
- }
128
- }
129
-
130
- return true;
131
- }
132
-
133
- protected _buildInputElement(): HTMLElement {
134
- // Radio uses a container, not a single input
135
- const container = document.createElement('div');
136
- container.className = 'jux-radio-options';
137
- return container;
138
- }
139
-
140
- /* ═════════════════════════════════════════════════════════════════
141
- * RENDER
142
- * ═════════════════════════════════════════════════════════════════ */
143
-
144
- render(targetId?: string): this {
145
- const container = this._setupContainer(targetId);
146
-
147
- const { options, value, name, disabled, orientation, style, class: className } = this.state; // ✅ Destructure orientation
148
-
149
- // Build wrapper
150
- const wrapper = document.createElement('div');
151
- wrapper.className = 'jux-radio';
152
- wrapper.id = this._id;
153
- if (className) wrapper.className += ` ${className}`;
154
- if (style) wrapper.setAttribute('style', style);
155
-
156
- // Label
157
- if (this.state.label) {
158
- wrapper.appendChild(this._renderLabel());
159
- }
160
-
161
- // Radio options container
162
- const optionsContainer = document.createElement('div');
163
- optionsContainer.className = `jux-radio-options jux-radio-${orientation}`; // ✅ Add orientation class
164
- this._inputElement = optionsContainer;
165
-
166
- this._radioInputs = [];
167
-
168
- options.forEach((option, index) => {
169
- const radioWrapper = document.createElement('label');
170
- radioWrapper.className = 'jux-radio-option';
171
-
172
- const input = document.createElement('input');
173
- input.type = 'radio';
174
- input.className = 'jux-radio-input';
175
- input.id = `${this._id}-option-${index}`;
176
- input.name = name;
177
- input.value = option.value;
178
- input.checked = option.value === value;
179
- input.disabled = disabled || option.disabled || false;
180
-
181
- this._radioInputs.push(input);
182
-
183
- const radioMark = document.createElement('span');
184
- radioMark.className = 'jux-radio-mark';
185
-
186
- const labelText = document.createElement('span');
187
- labelText.className = 'jux-radio-label-text';
188
- labelText.textContent = option.label;
189
-
190
- radioWrapper.appendChild(input);
191
- radioWrapper.appendChild(radioMark);
192
- radioWrapper.appendChild(labelText);
193
-
194
- optionsContainer.appendChild(radioWrapper);
195
- });
196
-
197
- wrapper.appendChild(optionsContainer);
198
-
199
- // Error element
200
- wrapper.appendChild(this._renderError());
201
-
202
- // Wire events
203
- this._wireStandardEvents(wrapper);
204
-
205
- // Wire radio-specific sync
206
- const valueSync = this._syncBindings.find(b => b.property === 'value');
207
-
208
- if (valueSync) {
209
- const { stateObj, toState, toComponent } = valueSync;
210
-
211
- const transformToState = toState || ((v: string) => v);
212
- const transformToComponent = toComponent || ((v: any) => String(v));
213
-
214
- let isUpdating = false;
215
-
216
- // State → Component
217
- stateObj.subscribe((val: any) => {
218
- if (isUpdating) return;
219
- const transformed = transformToComponent(val);
220
- this.setValue(transformed);
221
- });
222
-
223
- // Component → State
224
- this._radioInputs.forEach(input => {
225
- input.addEventListener('change', () => {
226
- if (isUpdating) return;
227
- isUpdating = true;
228
-
229
- const selectedValue = input.value;
230
- this.state.value = selectedValue;
231
- this._clearError();
232
-
233
- const transformed = transformToState(selectedValue);
234
- stateObj.set(transformed);
235
-
236
- // 🎯 Fire the change callback event
237
- this._triggerCallback('change', selectedValue);
238
-
239
- setTimeout(() => { isUpdating = false; }, 0);
240
- });
241
- });
242
- } else {
243
- // Default behavior without sync
244
- this._radioInputs.forEach(input => {
245
- input.addEventListener('change', () => {
246
- this.state.value = input.value;
247
- this._clearError();
248
-
249
- // 🎯 Fire the change callback event
250
- this._triggerCallback('change', input.value);
251
- });
252
- });
253
- }
254
-
255
- // Always add blur validation
256
- this._radioInputs.forEach(input => {
257
- input.addEventListener('blur', () => {
258
- this.validate();
259
- });
260
- });
261
-
262
- // Sync label changes
263
- const labelSync = this._syncBindings.find(b => b.property === 'label');
264
- if (labelSync) {
265
- const transform = labelSync.toComponent || ((v: any) => String(v));
266
- labelSync.stateObj.subscribe((val: any) => {
267
- this.label(transform(val));
268
- });
269
- }
270
-
271
- container.appendChild(wrapper);
272
- return this;
273
- }
274
- }
275
-
276
- export function radio(id: string, options: RadioOptions = {}): Radio {
277
- return new Radio(id, options);
278
- }
@@ -1,302 +0,0 @@
1
- /**
2
- * Request information and utilities
3
- * Provides access to URL, query params, path, referrer, etc.
4
- */
5
-
6
- export interface RequestInfo {
7
- url: string;
8
- path: string;
9
- query: Record<string, string>;
10
- params: Record<string, string>;
11
- hash: string;
12
- referrer: string;
13
- method: string;
14
- headers: Record<string, string>;
15
- }
16
-
17
- export class Req {
18
- private static _instance: Req | null = null;
19
- private _info: RequestInfo;
20
-
21
- private constructor() {
22
- this._info = this._parseRequest();
23
- }
24
-
25
- /**
26
- * Singleton instance
27
- */
28
- static get instance(): Req {
29
- if (!Req._instance) {
30
- Req._instance = new Req();
31
- }
32
- return Req._instance;
33
- }
34
-
35
- /**
36
- * Parse current request information
37
- */
38
- private _parseRequest(): RequestInfo {
39
- const url = new URL(window.location.href);
40
-
41
- // Parse query string
42
- const query: Record<string, string> = {};
43
- url.searchParams.forEach((value, key) => {
44
- query[key] = value;
45
- });
46
-
47
- // Parse path segments as params (basic routing)
48
- const pathSegments = url.pathname.split('/').filter(s => s);
49
- const params: Record<string, string> = {};
50
- pathSegments.forEach((segment, index) => {
51
- params[`${index}`] = segment;
52
- });
53
-
54
- return {
55
- url: url.href,
56
- path: url.pathname,
57
- query,
58
- params,
59
- hash: url.hash.slice(1), // Remove leading #
60
- referrer: document.referrer,
61
- method: 'GET', // Browser requests are always GET initially
62
- headers: {
63
- 'user-agent': navigator.userAgent,
64
- 'accept-language': navigator.language
65
- }
66
- };
67
- }
68
-
69
- /**
70
- * Get full URL
71
- */
72
- get url(): string {
73
- return this._info.url;
74
- }
75
-
76
- /**
77
- * Get current path (e.g., "/examples/sample/dashboards")
78
- */
79
- get path(): string {
80
- return this._info.path;
81
- }
82
-
83
- /**
84
- * Get query string parameters
85
- */
86
- get query(): Record<string, string> {
87
- return { ...this._info.query };
88
- }
89
-
90
- /**
91
- * Get path parameters
92
- */
93
- get params(): Record<string, string> {
94
- return { ...this._info.params };
95
- }
96
-
97
- /**
98
- * Get URL hash (without #)
99
- */
100
- get hash(): string {
101
- return this._info.hash;
102
- }
103
-
104
- /**
105
- * Get referrer URL
106
- */
107
- get referrer(): string {
108
- return this._info.referrer;
109
- }
110
-
111
- /**
112
- * Get request method (always GET for browser)
113
- */
114
- get method(): string {
115
- return this._info.method;
116
- }
117
-
118
- /**
119
- * Get request headers
120
- */
121
- get headers(): Record<string, string> {
122
- return { ...this._info.headers };
123
- }
124
-
125
- /**
126
- * Check if current path matches a pattern
127
- * @param pattern - Path pattern (supports wildcards)
128
- *
129
- * Examples:
130
- * req.matches('/examples/sample/*')
131
- * req.matches('/examples/sample/dashboards')
132
- * req.matches('/examples/*\/dashboards')
133
- */
134
- matches(pattern: string): boolean {
135
- const regexPattern = pattern
136
- .replace(/\*/g, '.*')
137
- .replace(/\//g, '\\/');
138
- const regex = new RegExp(`^${regexPattern}$`);
139
- return regex.test(this.path);
140
- }
141
-
142
- /**
143
- * Check if current path starts with prefix
144
- */
145
- startsWith(prefix: string): boolean {
146
- return this.path.startsWith(prefix);
147
- }
148
-
149
- /**
150
- * Check if current path ends with suffix
151
- */
152
- endsWith(suffix: string): boolean {
153
- return this.path.endsWith(suffix);
154
- }
155
-
156
- /**
157
- * Get query parameter value
158
- */
159
- getQuery(key: string, defaultValue?: string): string | undefined {
160
- return this.query[key] ?? defaultValue;
161
- }
162
-
163
- /**
164
- * Get path parameter value
165
- */
166
- getParam(key: string, defaultValue?: string): string | undefined {
167
- return this.params[key] ?? defaultValue;
168
- }
169
-
170
- /**
171
- * Check if query parameter exists
172
- */
173
- hasQuery(key: string): boolean {
174
- return key in this.query;
175
- }
176
-
177
- /**
178
- * Get all query parameters as URLSearchParams
179
- */
180
- getSearchParams(): URLSearchParams {
181
- return new URLSearchParams(this.query);
182
- }
183
-
184
- /**
185
- * Refresh request info (call after navigation)
186
- */
187
- refresh(): void {
188
- this._info = this._parseRequest();
189
- }
190
-
191
- /**
192
- * Set active state on nav items based on current path
193
- * @param items - Nav items to update
194
- * @returns Updated nav items with active state set
195
- */
196
- setActiveNavItems(items: Array<{ href: string; active?: boolean }>): Array<{ href: string; active: boolean }> {
197
- return items.map(item => ({
198
- ...item,
199
- active: this.isActiveNavItem(item.href)
200
- }));
201
- }
202
-
203
- /**
204
- * Check if a nav item should be active based on current path
205
- * @param href - The nav item's href
206
- */
207
- isActiveNavItem(href: string): boolean {
208
- // Exact match
209
- if (href === this.path) {
210
- return true;
211
- }
212
-
213
- // Starts with match (for parent routes)
214
- // Must be followed by a path separator or end of string
215
- // e.g., "/examples/sample" matches "/examples/sample/dashboards"
216
- // but "/examples/sam" does NOT match "/examples/sample/dashboards"
217
- if (href !== '/' && (this.path === href || this.path.startsWith(href + '/'))) {
218
- return true;
219
- }
220
-
221
- return false;
222
- }
223
-
224
- /**
225
- * Get breadcrumbs from current path
226
- * @returns Array of breadcrumb objects with label and href
227
- */
228
- getBreadcrumbs(): Array<{ label: string; href: string }> {
229
- const segments = this.path.split('/').filter(s => s);
230
- const breadcrumbs: Array<{ label: string; href: string }> = [
231
- { label: 'Home', href: '/' }
232
- ];
233
-
234
- let currentPath = '';
235
- segments.forEach(segment => {
236
- currentPath += `/${segment}`;
237
- breadcrumbs.push({
238
- label: this._formatBreadcrumbLabel(segment),
239
- href: currentPath
240
- });
241
- });
242
-
243
- return breadcrumbs;
244
- }
245
-
246
- /**
247
- * Format segment into readable breadcrumb label
248
- */
249
- private _formatBreadcrumbLabel(segment: string): string {
250
- return segment
251
- .split('-')
252
- .map(word => word.charAt(0).toUpperCase() + word.slice(1))
253
- .join(' ');
254
- }
255
-
256
- /**
257
- * Check if this is the home/root path
258
- */
259
- get isHome(): boolean {
260
- return this.path === '/' || this.path === '';
261
- }
262
-
263
- /**
264
- * Get current domain
265
- */
266
- get domain(): string {
267
- return window.location.hostname;
268
- }
269
-
270
- /**
271
- * Get current port
272
- */
273
- get port(): string {
274
- return window.location.port;
275
- }
276
-
277
- /**
278
- * Get current protocol
279
- */
280
- get protocol(): string {
281
- return window.location.protocol.replace(':', '');
282
- }
283
-
284
- /**
285
- * Check if HTTPS
286
- */
287
- get isSecure(): boolean {
288
- return this.protocol === 'https';
289
- }
290
- }
291
-
292
- /**
293
- * Global request instance
294
- */
295
- export const req = Req.instance;
296
-
297
- /**
298
- * Factory function (returns singleton)
299
- */
300
- export function request(): Req {
301
- return Req.instance;
302
- }
@@ -1,43 +0,0 @@
1
- import { ErrorHandler } from './error-handler.js';
2
-
3
- /**
4
- * Script - Inject inline JavaScript into the document
5
- * For external scripts, use Import component instead
6
- * Auto-renders when created or modified
7
- */
8
- export class Script {
9
- private _id: string;
10
- private code: string;
11
-
12
- constructor(code: string, id?: string) {
13
- // ID only for deduplication, auto-generate if not provided
14
- this._id = id || `jux-script-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
15
- this.code = code;
16
- }
17
-
18
- render(): this {
19
- // Check if script with this ID already exists
20
- if (document.getElementById(this._id)) {
21
- return this;
22
- }
23
-
24
- const script = document.createElement('script');
25
- script.id = this._id;
26
- script.textContent = this.code;
27
- document.head.appendChild(script);
28
-
29
- return this;
30
- }
31
-
32
- remove(): void {
33
- const existing = document.getElementById(this._id);
34
- if (existing) {
35
- existing.remove();
36
- }
37
- }
38
- }
39
-
40
- // ✅ ID is optional
41
- export function script(code: string, id?: string): Script {
42
- return new Script(code, id);
43
- }