@framesquared/component 0.1.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 John Carbone
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,350 @@
1
+ import { Base } from '@framesquared/core';
2
+
3
+ /**
4
+ * @framesquared/component – Template
5
+ *
6
+ * A simple template engine that supports `{token}` replacement.
7
+ * Used by Component to render content from data.
8
+ *
9
+ * ```ts
10
+ * const tpl = new Template('<div>{name} is {age} years old</div>');
11
+ * const html = tpl.apply({ name: 'Alice', age: 30 });
12
+ * // → '<div>Alice is 30 years old</div>'
13
+ * ```
14
+ */
15
+ declare class Template {
16
+ private source;
17
+ constructor(source: string);
18
+ /**
19
+ * Applies data to the template and returns the resulting HTML string.
20
+ * Replaces `{key}` tokens with values from the data object.
21
+ * Supports nested keys via dot notation: `{user.name}`.
22
+ */
23
+ apply(data: Record<string, unknown>): string;
24
+ /**
25
+ * Alias for apply().
26
+ */
27
+ render(data: Record<string, unknown>): string;
28
+ private resolve;
29
+ }
30
+
31
+ /**
32
+ * @framesquared/component – Component
33
+ *
34
+ * The base for all UI widgets. Provides a complete lifecycle,
35
+ * DOM element management, CSS operations, sizing with ResizeObserver,
36
+ * template rendering, focus management, and deterministic destruction.
37
+ */
38
+
39
+ interface ComponentConfig {
40
+ xtype?: string;
41
+ cls?: string | string[];
42
+ style?: Partial<CSSStyleDeclaration> | string;
43
+ width?: number | string;
44
+ height?: number | string;
45
+ minWidth?: number;
46
+ maxWidth?: number;
47
+ minHeight?: number;
48
+ maxHeight?: number;
49
+ margin?: number | string;
50
+ padding?: number | string;
51
+ hidden?: boolean;
52
+ disabled?: boolean;
53
+ html?: string;
54
+ tpl?: Template;
55
+ data?: Record<string, unknown>;
56
+ renderTo?: Element | string;
57
+ floating?: boolean;
58
+ listeners?: Record<string, Function>;
59
+ reference?: string;
60
+ [key: string]: unknown;
61
+ }
62
+ declare class Component extends Base {
63
+ static $className: string;
64
+ el: HTMLElement | null;
65
+ rendered: boolean;
66
+ /** The Container that owns this Component (set by Container.add). */
67
+ ownerCt: Component | null;
68
+ private _hidden;
69
+ private _disabled;
70
+ private _tpl;
71
+ private _data;
72
+ private _resizeObserver;
73
+ private _lastWidth;
74
+ private _lastHeight;
75
+ protected _config: ComponentConfig;
76
+ /** Unique component id */
77
+ readonly componentId: string;
78
+ $destroyHooks: (() => void)[];
79
+ constructor(config?: ComponentConfig);
80
+ /** Called before initialize(). Override in subclasses. */
81
+ protected beforeInitialize(): void;
82
+ /** Main initialization. Override in subclasses. */
83
+ protected initialize(): void;
84
+ /** Called after initialize(). Override in subclasses. */
85
+ protected afterInitialize(): void;
86
+ /** Called before render(). Override in subclasses. */
87
+ protected beforeRender(): void;
88
+ /** Called after render(). Override in subclasses. */
89
+ protected afterRender(): void;
90
+ /** Called before destroy(). Override in subclasses. */
91
+ protected beforeDestroy(): void;
92
+ /** Called during destroy(). Override in subclasses. */
93
+ protected onDestroy(): void;
94
+ /** Called after destroy(). Override in subclasses. */
95
+ protected afterDestroy(): void;
96
+ render(container?: Element | string, position?: number | Element): void;
97
+ private resolveElement;
98
+ private applyConfigs;
99
+ isVisible(): boolean;
100
+ setVisible(visible: boolean): void;
101
+ show(): void;
102
+ hide(): void;
103
+ isDisabled(): boolean;
104
+ enable(): void;
105
+ disable(): void;
106
+ getWidth(): number;
107
+ getHeight(): number;
108
+ getSize(): {
109
+ width: number;
110
+ height: number;
111
+ };
112
+ setWidth(width: number | string): void;
113
+ setHeight(height: number | string): void;
114
+ setSize(width: number | string, height: number | string): void;
115
+ getX(): number;
116
+ getY(): number;
117
+ setX(x: number): void;
118
+ setY(y: number): void;
119
+ setPosition(x: number, y: number): void;
120
+ getBox(): {
121
+ x: number;
122
+ y: number;
123
+ width: number;
124
+ height: number;
125
+ };
126
+ private setupResizeObserver;
127
+ addCls(...classes: string[]): void;
128
+ removeCls(...classes: string[]): void;
129
+ toggleCls(cls: string, state?: boolean): void;
130
+ hasCls(cls: string): boolean;
131
+ setStyle(propOrObj: string | Record<string, string>, value?: string): void;
132
+ getStyle(prop: string): string;
133
+ update(htmlOrData: string | Record<string, unknown>): void;
134
+ setHtml(html: string): void;
135
+ setData(data: Record<string, unknown>): void;
136
+ getEl(): HTMLElement | null;
137
+ getElement(): HTMLElement | null;
138
+ focus(): void;
139
+ blur(): void;
140
+ isFocusable(): boolean;
141
+ /** Returns the element that receives focus. Override for inner focus targets. */
142
+ protected getFocusEl(): HTMLElement | null;
143
+ /** Called when added to a Container. */
144
+ onAdded(_owner: Component, _index: number): void;
145
+ /** Called when removed from a Container. */
146
+ onRemoved(_destroying: boolean): void;
147
+ /**
148
+ * Walks up the ownerCt chain and returns the first Component whose
149
+ * xtype matches the given selector string.
150
+ */
151
+ up(selector: string): Component | undefined;
152
+ destroy(): void;
153
+ protected fire(eventName: string, ...args: unknown[]): boolean;
154
+ }
155
+
156
+ /**
157
+ * @framesquared/component – Layout (placeholder)
158
+ *
159
+ * Base layout class. Actual layout managers (HBox, VBox, Border, etc.)
160
+ * will be implemented in @framesquared/layout.
161
+ */
162
+ interface LayoutConfig {
163
+ type?: string;
164
+ [key: string]: unknown;
165
+ }
166
+ declare class Layout {
167
+ readonly type: string;
168
+ constructor(config?: LayoutConfig);
169
+ /**
170
+ * Performs layout calculation on the owner container.
171
+ * Override in subclasses.
172
+ */
173
+ doLayout(_owner: any): void;
174
+ }
175
+ /**
176
+ * Resolves a layout config to a Layout instance.
177
+ */
178
+ declare function resolveLayout(config: string | LayoutConfig | undefined): Layout;
179
+
180
+ /**
181
+ * @framesquared/component – Container
182
+ *
183
+ * A Component that manages an ordered collection of child Components.
184
+ * Provides add/insert/remove, Component Query (CQ) selectors,
185
+ * layout integration, defaults, reference handling, and destroy cascade.
186
+ */
187
+
188
+ interface ContainerConfig extends ComponentConfig {
189
+ items?: (Component | Record<string, unknown>)[];
190
+ layout?: string | LayoutConfig;
191
+ defaults?: Record<string, unknown>;
192
+ }
193
+ declare class Container extends Component {
194
+ static $className: string;
195
+ private _items;
196
+ private _layout;
197
+ private _bodyEl;
198
+ constructor(config?: ContainerConfig);
199
+ protected initialize(): void;
200
+ protected afterRender(): void;
201
+ protected onDestroy(): void;
202
+ /**
203
+ * Returns the inner element where children are rendered.
204
+ * Falls back to el if body hasn't been created yet.
205
+ */
206
+ getBodyEl(): HTMLElement;
207
+ add(...items: (Component | Record<string, unknown>)[]): Component[];
208
+ insert(index: number, item: Component | Record<string, unknown>): Component;
209
+ remove(item: Component, destroy?: boolean): Component;
210
+ removeAll(destroy?: boolean): Component[];
211
+ removeAt(index: number): Component;
212
+ getItems(): Component[];
213
+ getAt(index: number): Component | undefined;
214
+ getComponent(id: string): Component | undefined;
215
+ indexOf(item: Component): number;
216
+ contains(item: Component, deep?: boolean): boolean;
217
+ getCount(): number;
218
+ getLayout(): Layout;
219
+ doLayout(): void;
220
+ query(selector: string): Component[];
221
+ down(selector: string): Component | undefined;
222
+ child(selector: string): Component | undefined;
223
+ queryById(id: string): Component | undefined;
224
+ queryBy(fn: (item: Component) => boolean): Component[];
225
+ lookupReference(ref: string): Component | undefined;
226
+ private resolveItem;
227
+ private collectAllDescendants;
228
+ /**
229
+ * Fires an event and returns false if any listener returned false.
230
+ */
231
+ private fireReturning;
232
+ }
233
+
234
+ /**
235
+ * @framesquared/component – ComponentQuery
236
+ *
237
+ * Backward-compatible wrapper that delegates to the new AST-based CQ engine.
238
+ */
239
+
240
+ /**
241
+ * Tests if a component matches a simple selector. Used by Container.child()
242
+ * and Component.up().
243
+ */
244
+ declare function matchesCQ(cmp: Component, selector: string): boolean;
245
+ /**
246
+ * Legacy ComponentQuery class — delegates to CQMatcher.
247
+ */
248
+ declare class ComponentQuery {
249
+ static query(root: any, selector: string): Component[];
250
+ }
251
+
252
+ interface CompoundSelectorNode {
253
+ type: 'compound';
254
+ selectors: any[];
255
+ }
256
+ interface CombinatorNode {
257
+ type: 'combinator';
258
+ combinator: string;
259
+ left: SelectorNode;
260
+ right: SelectorNode;
261
+ }
262
+ interface SelectorListNode {
263
+ type: 'list';
264
+ items: SelectorNode[];
265
+ }
266
+ type SelectorNode = CompoundSelectorNode | CombinatorNode | SelectorListNode;
267
+ declare class CQParser {
268
+ private tokens;
269
+ private pos;
270
+ private constructor();
271
+ static parse(selector: string): SelectorNode;
272
+ private peek;
273
+ private advance;
274
+ private parseSelectorList;
275
+ private parseCombinatorExpr;
276
+ private parseCompound;
277
+ private parseAttribute;
278
+ private parsePseudo;
279
+ }
280
+
281
+ /**
282
+ * @framesquared/component – CQMatcher
283
+ *
284
+ * Evaluates parsed CQ AST nodes against Component instances.
285
+ * Handles simple selectors, compound selectors, all four combinators,
286
+ * pseudo-classes, method matchers, and comma-separated OR lists.
287
+ */
288
+
289
+ declare class CQMatcher {
290
+ /**
291
+ * Returns true if `component` matches the selector string.
292
+ */
293
+ static matches(component: Component, selector: string): boolean;
294
+ /**
295
+ * Returns all descendants of `root` matching the selector string.
296
+ */
297
+ static query(root: Component, selector: string): Component[];
298
+ }
299
+
300
+ /**
301
+ * @framesquared/component – CQ (Component Query static API)
302
+ *
303
+ * Static convenience API for querying component trees.
304
+ */
305
+
306
+ declare class CQ {
307
+ /**
308
+ * Finds all components matching the selector under the given root.
309
+ */
310
+ static query(selector: string, root?: Component): Component[];
311
+ /**
312
+ * Returns true if the component matches the selector.
313
+ */
314
+ static is(component: Component, selector: string): boolean;
315
+ }
316
+
317
+ /**
318
+ * @framesquared/component – XTemplate
319
+ *
320
+ * A powerful template engine inspired by ExtJS's XTemplate.
321
+ *
322
+ * Features:
323
+ * - `{field}` interpolation with dot paths
324
+ * - `{field:format}` built-in format functions
325
+ * - `<tpl if="expr">`, `<tpl elseif="expr">`, `<tpl else>`
326
+ * - `<tpl for="field">` loops with `{.}`, `{#}`, `{[xindex]}`, `{[xcount]}`, `{parent.x}`
327
+ * - `{[expression]}` inline JS expressions (`values` = current scope)
328
+ * - `{[this.method(...)]}` template member functions
329
+ * - Compiled to a JS function for fast repeat rendering
330
+ */
331
+ declare class XTemplate {
332
+ private source;
333
+ private memberFns;
334
+ private ast;
335
+ constructor(source: string, memberFns?: Record<string, Function>);
336
+ /**
337
+ * Pre-compiles the template. Called automatically on first apply().
338
+ */
339
+ compile(): void;
340
+ /**
341
+ * Applies data to the template and returns the resulting HTML string.
342
+ */
343
+ apply(data: any): string;
344
+ /**
345
+ * Applies data and appends the resulting HTML to an element.
346
+ */
347
+ append(el: Element, data: any): void;
348
+ }
349
+
350
+ export { CQ, CQMatcher, CQParser, type CombinatorNode, Component, type ComponentConfig, ComponentQuery, type CompoundSelectorNode, Container, type ContainerConfig, Layout, type LayoutConfig, type SelectorListNode, type SelectorNode, Template, XTemplate, matchesCQ, resolveLayout };