juxscript 1.1.4 → 1.1.6

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 (205) hide show
  1. package/index.d.ts +10 -10
  2. package/index.d.ts.map +1 -0
  3. package/lib/components/alert.d.ts +32 -0
  4. package/lib/components/alert.d.ts.map +1 -0
  5. package/lib/components/alert.js +153 -0
  6. package/lib/components/alert.ts +200 -0
  7. package/lib/components/app.d.ts +89 -0
  8. package/lib/components/app.d.ts.map +1 -0
  9. package/lib/components/app.js +175 -0
  10. package/lib/components/app.ts +247 -0
  11. package/lib/components/badge.d.ts +27 -0
  12. package/lib/components/badge.d.ts.map +1 -0
  13. package/lib/components/badge.js +70 -0
  14. package/lib/components/badge.ts +101 -0
  15. package/lib/components/base/BaseComponent.d.ts +142 -0
  16. package/lib/components/base/BaseComponent.d.ts.map +1 -0
  17. package/lib/components/base/BaseComponent.js +363 -0
  18. package/lib/components/base/BaseComponent.ts +421 -0
  19. package/lib/components/base/FormInput.d.ts +73 -0
  20. package/lib/components/base/FormInput.d.ts.map +1 -0
  21. package/lib/components/base/FormInput.js +163 -0
  22. package/lib/components/base/FormInput.ts +227 -0
  23. package/lib/components/button.d.ts +48 -0
  24. package/lib/components/button.d.ts.map +1 -0
  25. package/lib/components/button.js +121 -0
  26. package/lib/components/button.ts +178 -0
  27. package/lib/components/card.d.ts +34 -0
  28. package/lib/components/card.d.ts.map +1 -0
  29. package/lib/components/card.js +127 -0
  30. package/lib/components/card.ts +173 -0
  31. package/lib/components/chart.d.ts +45 -0
  32. package/lib/components/chart.d.ts.map +1 -0
  33. package/lib/components/chart.js +186 -0
  34. package/lib/components/chart.ts +231 -0
  35. package/lib/components/checkbox.d.ts +31 -0
  36. package/lib/components/checkbox.d.ts.map +1 -0
  37. package/lib/components/checkbox.js +185 -0
  38. package/lib/components/checkbox.ts +242 -0
  39. package/lib/components/code.d.ts +24 -0
  40. package/lib/components/code.d.ts.map +1 -0
  41. package/lib/components/code.js +88 -0
  42. package/lib/components/code.ts +123 -0
  43. package/lib/components/container.d.ts +42 -0
  44. package/lib/components/container.d.ts.map +1 -0
  45. package/lib/components/container.js +93 -0
  46. package/lib/components/container.ts +140 -0
  47. package/lib/components/data.d.ts +36 -0
  48. package/lib/components/data.d.ts.map +1 -0
  49. package/lib/components/data.js +110 -0
  50. package/lib/components/data.ts +135 -0
  51. package/lib/components/datepicker.d.ts +38 -0
  52. package/lib/components/datepicker.d.ts.map +1 -0
  53. package/lib/components/datepicker.js +177 -0
  54. package/lib/components/datepicker.ts +234 -0
  55. package/lib/components/dialog.d.ts +38 -0
  56. package/lib/components/dialog.d.ts.map +1 -0
  57. package/lib/components/dialog.js +126 -0
  58. package/lib/components/dialog.ts +172 -0
  59. package/lib/components/divider.d.ts +30 -0
  60. package/lib/components/divider.d.ts.map +1 -0
  61. package/lib/components/divider.js +69 -0
  62. package/lib/components/divider.ts +100 -0
  63. package/lib/components/dropdown.d.ts +39 -0
  64. package/lib/components/dropdown.d.ts.map +1 -0
  65. package/lib/components/dropdown.js +133 -0
  66. package/lib/components/dropdown.ts +186 -0
  67. package/lib/components/element.d.ts +50 -0
  68. package/lib/components/element.d.ts.map +1 -0
  69. package/lib/components/element.js +206 -0
  70. package/lib/components/element.ts +267 -0
  71. package/lib/components/fileupload.d.ts +40 -0
  72. package/lib/components/fileupload.d.ts.map +1 -0
  73. package/lib/components/fileupload.js +241 -0
  74. package/lib/components/fileupload.ts +309 -0
  75. package/lib/components/grid.d.ts +87 -0
  76. package/lib/components/grid.d.ts.map +1 -0
  77. package/lib/components/grid.js +205 -0
  78. package/lib/components/grid.ts +291 -0
  79. package/lib/components/guard.d.ts +41 -0
  80. package/lib/components/guard.d.ts.map +1 -0
  81. package/lib/components/guard.js +56 -0
  82. package/lib/components/guard.ts +92 -0
  83. package/lib/components/heading.d.ts +24 -0
  84. package/lib/components/heading.d.ts.map +1 -0
  85. package/lib/components/heading.js +67 -0
  86. package/lib/components/heading.ts +96 -0
  87. package/lib/components/helpers.d.ts +9 -0
  88. package/lib/components/helpers.d.ts.map +1 -0
  89. package/lib/components/helpers.js +30 -0
  90. package/lib/components/helpers.ts +41 -0
  91. package/lib/components/hero.d.ts +45 -0
  92. package/lib/components/hero.d.ts.map +1 -0
  93. package/lib/components/hero.js +165 -0
  94. package/lib/components/hero.ts +224 -0
  95. package/lib/components/icon.d.ts +35 -0
  96. package/lib/components/icon.d.ts.map +1 -0
  97. package/lib/components/icon.js +132 -0
  98. package/lib/components/icon.ts +178 -0
  99. package/lib/components/icons.d.ts +25 -0
  100. package/lib/components/icons.d.ts.map +1 -0
  101. package/lib/components/icons.js +440 -0
  102. package/lib/components/icons.ts +464 -0
  103. package/lib/components/include.d.ts +120 -0
  104. package/lib/components/include.d.ts.map +1 -0
  105. package/lib/components/include.js +350 -0
  106. package/lib/components/include.ts +410 -0
  107. package/lib/components/input.d.ts +83 -0
  108. package/lib/components/input.d.ts.map +1 -0
  109. package/lib/components/input.js +348 -0
  110. package/lib/components/input.ts +457 -0
  111. package/lib/components/list.d.ts +82 -0
  112. package/lib/components/list.d.ts.map +1 -0
  113. package/lib/components/list.js +311 -0
  114. package/lib/components/list.ts +419 -0
  115. package/lib/components/loading.d.ts +24 -0
  116. package/lib/components/loading.d.ts.map +1 -0
  117. package/lib/components/loading.js +73 -0
  118. package/lib/components/loading.ts +100 -0
  119. package/lib/components/menu.d.ts +37 -0
  120. package/lib/components/menu.d.ts.map +1 -0
  121. package/lib/components/menu.js +202 -0
  122. package/lib/components/menu.ts +275 -0
  123. package/lib/components/modal.d.ts +51 -0
  124. package/lib/components/modal.d.ts.map +1 -0
  125. package/lib/components/modal.js +227 -0
  126. package/lib/components/modal.ts +284 -0
  127. package/lib/components/nav.d.ts +45 -0
  128. package/lib/components/nav.d.ts.map +1 -0
  129. package/lib/components/nav.js +190 -0
  130. package/lib/components/nav.ts +257 -0
  131. package/lib/components/paragraph.d.ts +21 -0
  132. package/lib/components/paragraph.d.ts.map +1 -0
  133. package/lib/components/paragraph.js +70 -0
  134. package/lib/components/paragraph.ts +97 -0
  135. package/lib/components/progress.d.ts +39 -0
  136. package/lib/components/progress.d.ts.map +1 -0
  137. package/lib/components/progress.js +113 -0
  138. package/lib/components/progress.ts +159 -0
  139. package/lib/components/radio.d.ts +41 -0
  140. package/lib/components/radio.d.ts.map +1 -0
  141. package/lib/components/radio.js +203 -0
  142. package/lib/components/radio.ts +278 -0
  143. package/lib/components/req.d.ts +155 -0
  144. package/lib/components/req.d.ts.map +1 -0
  145. package/lib/components/req.js +253 -0
  146. package/lib/components/req.ts +303 -0
  147. package/lib/components/script.d.ts +14 -0
  148. package/lib/components/script.d.ts.map +1 -0
  149. package/lib/components/script.js +33 -0
  150. package/lib/components/script.ts +41 -0
  151. package/lib/components/select.d.ts +40 -0
  152. package/lib/components/select.d.ts.map +1 -0
  153. package/lib/components/select.js +183 -0
  154. package/lib/components/select.ts +252 -0
  155. package/lib/components/sidebar.d.ts +48 -0
  156. package/lib/components/sidebar.d.ts.map +1 -0
  157. package/lib/components/sidebar.js +207 -0
  158. package/lib/components/sidebar.ts +275 -0
  159. package/lib/components/style.d.ts +14 -0
  160. package/lib/components/style.d.ts.map +1 -0
  161. package/lib/components/style.js +33 -0
  162. package/lib/components/style.ts +41 -0
  163. package/lib/components/switch.d.ts +32 -0
  164. package/lib/components/switch.d.ts.map +1 -0
  165. package/lib/components/switch.js +186 -0
  166. package/lib/components/switch.ts +246 -0
  167. package/lib/components/table.d.ts +137 -0
  168. package/lib/components/table.d.ts.map +1 -0
  169. package/lib/components/table.js +1045 -0
  170. package/lib/components/table.ts +1249 -0
  171. package/lib/components/tabs.d.ts +36 -0
  172. package/lib/components/tabs.d.ts.map +1 -0
  173. package/lib/components/tabs.js +198 -0
  174. package/lib/components/tabs.ts +250 -0
  175. package/lib/components/theme-toggle.d.ts +44 -0
  176. package/lib/components/theme-toggle.d.ts.map +1 -0
  177. package/lib/components/theme-toggle.js +215 -0
  178. package/lib/components/theme-toggle.ts +293 -0
  179. package/lib/components/tooltip.d.ts +30 -0
  180. package/lib/components/tooltip.d.ts.map +1 -0
  181. package/lib/components/tooltip.js +109 -0
  182. package/lib/components/tooltip.ts +144 -0
  183. package/lib/components/view.d.ts +48 -0
  184. package/lib/components/view.d.ts.map +1 -0
  185. package/lib/components/view.js +149 -0
  186. package/lib/components/view.ts +190 -0
  187. package/lib/components/write.d.ts +107 -0
  188. package/lib/components/write.d.ts.map +1 -0
  189. package/lib/components/write.js +222 -0
  190. package/lib/components/write.ts +272 -0
  191. package/lib/layouts/default.css +260 -0
  192. package/lib/layouts/figma.css +334 -0
  193. package/lib/reactivity/state.d.ts +36 -0
  194. package/lib/reactivity/state.d.ts.map +1 -0
  195. package/lib/reactivity/state.js +67 -0
  196. package/lib/reactivity/state.ts +78 -0
  197. package/lib/utils/fetch.d.ts +176 -0
  198. package/lib/utils/fetch.d.ts.map +1 -0
  199. package/lib/utils/fetch.js +427 -0
  200. package/lib/utils/fetch.ts +553 -0
  201. package/machinery/compiler3.js +78 -0
  202. package/machinery/doc-generator.js +136 -0
  203. package/machinery/imports.js +155 -0
  204. package/machinery/ts-shim.js +46 -0
  205. package/package.json +9 -15
@@ -0,0 +1,142 @@
1
+ import { State } from '../../reactivity/state.js';
2
+ /**
3
+ * Abstract base class for all JUX components
4
+ * Provides common storage, event routing, and lifecycle methods
5
+ *
6
+ * Children must provide:
7
+ * - TRIGGER_EVENTS constant (readonly string[])
8
+ * - CALLBACK_EVENTS constant (readonly string[])
9
+ * - render() implementation
10
+ */
11
+ export declare abstract class BaseComponent<TState extends Record<string, any>> {
12
+ state: TState;
13
+ container: HTMLElement | null;
14
+ _id: string;
15
+ id: string;
16
+ protected _bindings: Array<{
17
+ event: string;
18
+ handler: Function;
19
+ }>;
20
+ protected _syncBindings: Array<{
21
+ property: string;
22
+ stateObj: State<any>;
23
+ toState?: Function;
24
+ toComponent?: Function;
25
+ }>;
26
+ protected _triggerHandlers: Map<string, Function>;
27
+ protected _callbackHandlers: Map<string, Function>;
28
+ constructor(id: string, initialState: TState);
29
+ protected abstract getTriggerEvents(): readonly string[];
30
+ protected abstract getCallbackEvents(): readonly string[];
31
+ abstract render(targetId?: string): this;
32
+ /**
33
+ * Set component style
34
+ */
35
+ style(value: string): this;
36
+ /**
37
+ * Set component class
38
+ */
39
+ class(value: string): this;
40
+ /**
41
+ * Add a CSS class to the component
42
+ */
43
+ addClass(value: string): this;
44
+ /**
45
+ * Remove a CSS class from the component
46
+ */
47
+ removeClass(value: string): this;
48
+ /**
49
+ * Toggle a CSS class on the component
50
+ */
51
+ toggleClass(value: string): this;
52
+ /**
53
+ * Set component visibility
54
+ */
55
+ visible(value: boolean): this;
56
+ /**
57
+ * Show the component
58
+ */
59
+ show(): this;
60
+ /**
61
+ * Hide the component
62
+ */
63
+ hide(): this;
64
+ /**
65
+ * Toggle component visibility
66
+ */
67
+ toggleVisibility(): this;
68
+ /**
69
+ * Set a single HTML attribute
70
+ */
71
+ attr(name: string, value: string): this;
72
+ /**
73
+ * Set multiple HTML attributes
74
+ */
75
+ attrs(attributes: Record<string, string>): this;
76
+ /**
77
+ * Remove an HTML attribute
78
+ */
79
+ removeAttr(name: string): this;
80
+ /**
81
+ * Set disabled state for interactive elements
82
+ */
83
+ disabled(value: boolean): this;
84
+ /**
85
+ * Enable the component
86
+ */
87
+ enable(): this;
88
+ /**
89
+ * Disable the component
90
+ */
91
+ disable(): this;
92
+ /**
93
+ * Set loading state
94
+ */
95
+ loading(value: boolean): this;
96
+ /**
97
+ * Focus the first focusable element in the component
98
+ */
99
+ focus(): this;
100
+ /**
101
+ * Blur the currently focused element in the component
102
+ */
103
+ blur(): this;
104
+ /**
105
+ * Remove the component from the DOM
106
+ */
107
+ remove(): this;
108
+ bind(event: string, handler: Function): this;
109
+ /**
110
+ * Sync a component property with a State object
111
+ * @param property - The property to sync
112
+ * @param stateObj - The State object to sync with
113
+ * @param toStateOrTransform - Either toState function OR a simple transform function
114
+ * @param toComponent - Optional toComponent function (if toState was provided)
115
+ */
116
+ sync(property: string, stateObj: State<any>, toStateOrTransform?: Function, toComponent?: Function): this;
117
+ protected _isTriggerEvent(event: string): boolean;
118
+ protected _isCallbackEvent(event: string): boolean;
119
+ protected _triggerCallback(eventName: string, ...args: any[]): void;
120
+ protected _setupContainer(targetId?: string): HTMLElement;
121
+ protected _wireStandardEvents(element: HTMLElement): void;
122
+ /**
123
+ * Automatically wire ALL sync bindings by calling the corresponding method
124
+ * if it exists on the component
125
+ */
126
+ protected _wireAllSyncs(): void;
127
+ renderTo(juxComponent: any): this;
128
+ /**
129
+ * ✅ Read-only accessor for component state
130
+ * Provides clear separation between setters (fluent methods) and getters
131
+ *
132
+ * @example
133
+ * const myCard = card('example')
134
+ * .title('Hello') // ✅ SETTER (fluent)
135
+ * .content('World'); // ✅ SETTER (fluent)
136
+ *
137
+ * console.log(myCard.props.title); // ✅ GETTER: 'Hello'
138
+ * console.log(myCard.props.content); // ✅ GETTER: 'World'
139
+ */
140
+ get props(): Readonly<TState>;
141
+ }
142
+ //# sourceMappingURL=BaseComponent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseComponent.d.ts","sourceRoot":"","sources":["BaseComponent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,363 @@
1
+ import { getOrCreateContainer } from '../helpers.js';
2
+ /**
3
+ * Abstract base class for all JUX components
4
+ * Provides common storage, event routing, and lifecycle methods
5
+ *
6
+ * Children must provide:
7
+ * - TRIGGER_EVENTS constant (readonly string[])
8
+ * - CALLBACK_EVENTS constant (readonly string[])
9
+ * - render() implementation
10
+ */
11
+ export class BaseComponent {
12
+ constructor(id, initialState) {
13
+ this.container = null;
14
+ // Event & sync storage (populated by bind() and sync())
15
+ this._bindings = [];
16
+ this._syncBindings = [];
17
+ this._triggerHandlers = new Map();
18
+ this._callbackHandlers = new Map();
19
+ this._id = id;
20
+ this.id = id;
21
+ this.state = initialState;
22
+ }
23
+ /* ═════════════════════════════════════════════════════════════════
24
+ * COMMON FLUENT API (Inherited by all components)
25
+ * ═════════════════════════════════════════════════════════════════ */
26
+ /**
27
+ * Set component style
28
+ */
29
+ style(value) {
30
+ this.state.style = value;
31
+ return this;
32
+ }
33
+ /**
34
+ * Set component class
35
+ */
36
+ class(value) {
37
+ this.state.class = value;
38
+ return this;
39
+ }
40
+ /* ═════════════════════════════════════════════════════════════════
41
+ * CSS CLASS MANAGEMENT
42
+ * ═════════════════════════════════════════════════════════════════ */
43
+ /**
44
+ * Add a CSS class to the component
45
+ */
46
+ addClass(value) {
47
+ const current = this.state.class || '';
48
+ const classes = current.split(' ').filter((c) => c);
49
+ if (!classes.includes(value)) {
50
+ classes.push(value);
51
+ this.state.class = classes.join(' ');
52
+ if (this.container)
53
+ this.container.classList.add(value);
54
+ }
55
+ return this;
56
+ }
57
+ /**
58
+ * Remove a CSS class from the component
59
+ */
60
+ removeClass(value) {
61
+ const current = this.state.class || '';
62
+ const classes = current.split(' ').filter((c) => c && c !== value);
63
+ this.state.class = classes.join(' ');
64
+ if (this.container)
65
+ this.container.classList.remove(value);
66
+ return this;
67
+ }
68
+ /**
69
+ * Toggle a CSS class on the component
70
+ */
71
+ toggleClass(value) {
72
+ const current = this.state.class || '';
73
+ const hasClass = current.split(' ').includes(value);
74
+ return hasClass ? this.removeClass(value) : this.addClass(value);
75
+ }
76
+ /* ═════════════════════════════════════════════════════════════════
77
+ * VISIBILITY CONTROL
78
+ * ═════════════════════════════════════════════════════════════════ */
79
+ /**
80
+ * Set component visibility
81
+ */
82
+ visible(value) {
83
+ this.state.visible = value;
84
+ if (this.container) {
85
+ // Find the actual component wrapper, not the parent container
86
+ const wrapper = this.container.querySelector(`#${this._id}`);
87
+ if (wrapper) {
88
+ wrapper.style.display = value ? '' : 'none';
89
+ }
90
+ }
91
+ return this;
92
+ }
93
+ /**
94
+ * Show the component
95
+ */
96
+ show() {
97
+ return this.visible(true);
98
+ }
99
+ /**
100
+ * Hide the component
101
+ */
102
+ hide() {
103
+ return this.visible(false);
104
+ }
105
+ /**
106
+ * Toggle component visibility
107
+ */
108
+ toggleVisibility() {
109
+ const isVisible = this.state.visible ?? true;
110
+ return this.visible(!isVisible);
111
+ }
112
+ /* ═════════════════════════════════════════════════════════════════
113
+ * ATTRIBUTE MANAGEMENT
114
+ * ═════════════════════════════════════════════════════════════════ */
115
+ /**
116
+ * Set a single HTML attribute
117
+ */
118
+ attr(name, value) {
119
+ const attrs = this.state.attributes || {};
120
+ this.state.attributes = { ...attrs, [name]: value };
121
+ if (this.container)
122
+ this.container.setAttribute(name, value);
123
+ return this;
124
+ }
125
+ /**
126
+ * Set multiple HTML attributes
127
+ */
128
+ attrs(attributes) {
129
+ Object.entries(attributes).forEach(([name, value]) => {
130
+ this.attr(name, value);
131
+ });
132
+ return this;
133
+ }
134
+ /**
135
+ * Remove an HTML attribute
136
+ */
137
+ removeAttr(name) {
138
+ const attrs = this.state.attributes || {};
139
+ delete attrs[name];
140
+ if (this.container)
141
+ this.container.removeAttribute(name);
142
+ return this;
143
+ }
144
+ /* ═════════════════════════════════════════════════════════════════
145
+ * DISABLED STATE
146
+ * ═════════════════════════════════════════════════════════════════ */
147
+ /**
148
+ * Set disabled state for interactive elements
149
+ */
150
+ disabled(value) {
151
+ this.state.disabled = value;
152
+ if (this.container) {
153
+ const inputs = this.container.querySelectorAll('input, button, select, textarea');
154
+ inputs.forEach(el => {
155
+ el.disabled = value;
156
+ });
157
+ this.container.setAttribute('aria-disabled', String(value));
158
+ }
159
+ return this;
160
+ }
161
+ /**
162
+ * Enable the component
163
+ */
164
+ enable() {
165
+ return this.disabled(false);
166
+ }
167
+ /**
168
+ * Disable the component
169
+ */
170
+ disable() {
171
+ return this.disabled(true);
172
+ }
173
+ /* ═════════════════════════════════════════════════════════════════
174
+ * LOADING STATE
175
+ * ═════════════════════════════════════════════════════════════════ */
176
+ /**
177
+ * Set loading state
178
+ */
179
+ loading(value) {
180
+ this.state.loading = value;
181
+ if (this.container) {
182
+ if (value) {
183
+ this.container.classList.add('jux-loading');
184
+ this.container.setAttribute('aria-busy', 'true');
185
+ }
186
+ else {
187
+ this.container.classList.remove('jux-loading');
188
+ this.container.removeAttribute('aria-busy');
189
+ }
190
+ }
191
+ return this;
192
+ }
193
+ /* ═════════════════════════════════════════════════════════════════
194
+ * FOCUS MANAGEMENT
195
+ * ═════════════════════════════════════════════════════════════════ */
196
+ /**
197
+ * Focus the first focusable element in the component
198
+ */
199
+ focus() {
200
+ if (this.container) {
201
+ const focusable = this.container.querySelector('input, button, select, textarea, [tabindex]');
202
+ if (focusable)
203
+ focusable.focus();
204
+ }
205
+ return this;
206
+ }
207
+ /**
208
+ * Blur the currently focused element in the component
209
+ */
210
+ blur() {
211
+ if (this.container) {
212
+ const focused = this.container.querySelector(':focus');
213
+ if (focused)
214
+ focused.blur();
215
+ }
216
+ return this;
217
+ }
218
+ /* ═════════════════════════════════════════════════════════════════
219
+ * DOM MANIPULATION
220
+ * ═════════════════════════════════════════════════════════════════ */
221
+ /**
222
+ * Remove the component from the DOM
223
+ */
224
+ remove() {
225
+ if (this.container) {
226
+ this.container.remove();
227
+ this.container = null;
228
+ }
229
+ return this;
230
+ }
231
+ /* ═════════════════════════════════════════════════════════════════
232
+ * EVENT BINDING (Shared logic)
233
+ * ═════════════════════════════════════════════════════════════════ */
234
+ bind(event, handler) {
235
+ if (this._isTriggerEvent(event)) {
236
+ this._triggerHandlers.set(event, handler);
237
+ }
238
+ else if (this._isCallbackEvent(event)) {
239
+ this._callbackHandlers.set(event, handler);
240
+ }
241
+ else {
242
+ this._bindings.push({ event, handler });
243
+ }
244
+ return this;
245
+ }
246
+ /**
247
+ * Sync a component property with a State object
248
+ * @param property - The property to sync
249
+ * @param stateObj - The State object to sync with
250
+ * @param toStateOrTransform - Either toState function OR a simple transform function
251
+ * @param toComponent - Optional toComponent function (if toState was provided)
252
+ */
253
+ sync(property, stateObj, toStateOrTransform, toComponent) {
254
+ if (!stateObj || typeof stateObj.subscribe !== 'function') {
255
+ throw new Error(`${this.constructor.name}.sync: Expected a State object for property "${property}"`);
256
+ }
257
+ // If only 3 args provided, treat the function as toComponent (the common case)
258
+ const actualToState = (toComponent !== undefined) ? toStateOrTransform : undefined;
259
+ const actualToComponent = (toComponent !== undefined) ? toComponent : toStateOrTransform;
260
+ this._syncBindings.push({
261
+ property,
262
+ stateObj,
263
+ toState: actualToState,
264
+ toComponent: actualToComponent
265
+ });
266
+ return this;
267
+ }
268
+ _isTriggerEvent(event) {
269
+ return this.getTriggerEvents().includes(event);
270
+ }
271
+ _isCallbackEvent(event) {
272
+ return this.getCallbackEvents().includes(event);
273
+ }
274
+ _triggerCallback(eventName, ...args) {
275
+ if (this._callbackHandlers.has(eventName)) {
276
+ const handler = this._callbackHandlers.get(eventName);
277
+ handler(...args);
278
+ }
279
+ else {
280
+ console.warn(`🔍 No handler found for "${eventName}"`);
281
+ }
282
+ }
283
+ /* ═════════════════════════════════════════════════════════════════
284
+ * COMMON RENDER HELPERS
285
+ * ═════════════════════════════════════════════════════════════════ */
286
+ _setupContainer(targetId) {
287
+ let container;
288
+ if (targetId) {
289
+ // Strip leading # if present
290
+ const id = targetId.startsWith('#') ? targetId.slice(1) : targetId;
291
+ const target = document.getElementById(id);
292
+ if (target) {
293
+ container = target;
294
+ }
295
+ else {
296
+ // Gracefully create the container instead of throwing
297
+ console.warn(`[Jux] Target "${targetId}" not found, creating it with graceful fallback`);
298
+ container = getOrCreateContainer(id);
299
+ }
300
+ }
301
+ else {
302
+ container = getOrCreateContainer(this._id);
303
+ }
304
+ // Add universal component class for DOM inspection
305
+ // container.classList.add('jux-component');
306
+ this.container = container;
307
+ return container;
308
+ }
309
+ _wireStandardEvents(element) {
310
+ this._bindings.forEach(({ event, handler }) => {
311
+ element.addEventListener(event, handler);
312
+ });
313
+ }
314
+ /**
315
+ * Automatically wire ALL sync bindings by calling the corresponding method
316
+ * if it exists on the component
317
+ */
318
+ _wireAllSyncs() {
319
+ this._syncBindings.forEach(({ property, stateObj, toComponent }) => {
320
+ const transform = toComponent || ((v) => v);
321
+ // Check if component has a method matching the property name
322
+ const method = this[property];
323
+ if (typeof method === 'function') {
324
+ // Set initial value
325
+ const initialValue = transform(stateObj.value);
326
+ method.call(this, initialValue);
327
+ // Subscribe to changes
328
+ stateObj.subscribe((val) => {
329
+ const transformed = transform(val);
330
+ method.call(this, transformed);
331
+ });
332
+ }
333
+ else {
334
+ console.warn(`[Jux] ${this.constructor.name}.sync('${property}'): ` +
335
+ `No method .${property}() found. Property will not be synced.`);
336
+ }
337
+ });
338
+ }
339
+ renderTo(juxComponent) {
340
+ if (!juxComponent?._id) {
341
+ throw new Error(`${this.constructor.name}.renderTo: Invalid component`);
342
+ }
343
+ return this.render(`#${juxComponent._id}`);
344
+ }
345
+ /* ═════════════════════════════════════════════════════════════════
346
+ * PROPS ACCESSOR - Read-only access to component state
347
+ * ═════════════════════════════════════════════════════════════════ */
348
+ /**
349
+ * ✅ Read-only accessor for component state
350
+ * Provides clear separation between setters (fluent methods) and getters
351
+ *
352
+ * @example
353
+ * const myCard = card('example')
354
+ * .title('Hello') // ✅ SETTER (fluent)
355
+ * .content('World'); // ✅ SETTER (fluent)
356
+ *
357
+ * console.log(myCard.props.title); // ✅ GETTER: 'Hello'
358
+ * console.log(myCard.props.content); // ✅ GETTER: 'World'
359
+ */
360
+ get props() {
361
+ return this.state;
362
+ }
363
+ }