@je-es/client 0.1.8 → 0.1.9

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/dist/main.d.cts CHANGED
@@ -1,7 +1,77 @@
1
+ import { ApiInterceptors } from '@je-es/capi';
2
+ export { ApiError, ApiInterceptors, ApiOptions, ApiResponse, ApiConfig as CapiConfig, HttpMethod, ParamValue, RequestData, api, configureApi, getApiConfig, http, resetApiConfig } from '@je-es/capi';
3
+ import * as _je_es_vdom from '@je-es/vdom';
1
4
  import { VNode } from '@je-es/vdom';
2
5
  export { VNode, VNodeChild, VNodeProps, createDOMElement, createElement, html, patch } from '@je-es/vdom';
3
- import { ApiInterceptors } from '@je-es/capi';
4
- export { ApiError, ApiInterceptors, ApiOptions, ApiResponse, HttpMethod, api, configureApi, getApiConfig, http, resetApiConfig } from '@je-es/capi';
6
+
7
+ declare abstract class Component<P = Record<string, unknown>, S = Record<string, unknown>> {
8
+ props: P;
9
+ state: S;
10
+ _isMounted: boolean;
11
+ private _isUnmounting;
12
+ private _element;
13
+ private _vnode;
14
+ private _styleId;
15
+ private _isScheduledForUpdate;
16
+ private _updateBatch;
17
+ private _refs;
18
+ private _subscriptions;
19
+ private _memoCache;
20
+ private _isInitializing;
21
+ private _skipNextUpdate;
22
+ private _preservedElements;
23
+ private _updateInProgress;
24
+ constructor(props?: P, initialState?: S);
25
+ onBeforeMount?(): void | Promise<void>;
26
+ onMount?(): void | Promise<void>;
27
+ onBeforeUpdate?(prevProps: P, prevState: S): void | Promise<void>;
28
+ onUpdate?(prevProps: P, prevState: S): void;
29
+ onBeforeUnmount?(): void;
30
+ onUnmount?(): void;
31
+ onError?(error: Error, errorInfo: {
32
+ componentStack?: string;
33
+ }): void;
34
+ onPropsChange?(prevProps: P, newProps: P): void;
35
+ onStateChange?(prevState: S, newState: S): void;
36
+ shouldUpdate?(prevProps: P, prevState: S): boolean;
37
+ abstract render(): VNode;
38
+ styles?(): string;
39
+ setState(partialState: Partial<S> | ((prevState: S) => Partial<S>), callback?: () => void): void;
40
+ setProps(newProps: Partial<P>): void;
41
+ batchUpdate(updater: () => void): void;
42
+ update(key?: string): void;
43
+ forceUpdate(): void;
44
+ skipNextUpdate(): void;
45
+ beginInitialization(): void;
46
+ endInitialization(): void;
47
+ mount(container: HTMLElement): Promise<void>;
48
+ unmount(): void;
49
+ getRef(name: string): HTMLElement | undefined;
50
+ createRef(name: string): (el: HTMLElement | null) => void;
51
+ memo<T>(key: string, compute: () => T, deps: unknown[]): T;
52
+ subscribe(subscription: () => void): void;
53
+ debounce<T extends (...args: unknown[]) => unknown>(fn: T, delay: number): (...args: Parameters<T>) => void;
54
+ throttle<T extends (...args: unknown[]) => unknown>(fn: T, delay: number): (...args: Parameters<T>) => void;
55
+ get element(): HTMLElement | null;
56
+ get isMounted(): boolean;
57
+ get isUnmounting(): boolean;
58
+ get isInitializing(): boolean;
59
+ private _performUpdate;
60
+ private _preserveComponentMounts;
61
+ private _restoreComponentMounts;
62
+ private _convertToVDomNode;
63
+ private _createElementFromVNode;
64
+ private _setElementProperty;
65
+ private _handleError;
66
+ private _areDepsEqual;
67
+ _invalidateAllComputed(): void;
68
+ _triggerWatchers(propertyName: string, newValue: unknown, oldValue: unknown): void;
69
+ setElement(element: HTMLElement): void;
70
+ }
71
+ interface ComponentConstructor {
72
+ __watchers__?: Record<string, string[]>;
73
+ __reactiveProps__?: string[];
74
+ }
5
75
 
6
76
  interface BuildConfig {
7
77
  entry: string;
@@ -48,6 +118,13 @@ interface DevToolsConfig {
48
118
  showRouterInfo?: boolean;
49
119
  showStateChanges?: boolean;
50
120
  }
121
+ type LanguageCode = string;
122
+ type TranslationSet = Record<string, Record<string, string>>;
123
+ interface I18nConfig {
124
+ defaultLanguage?: LanguageCode;
125
+ supportedLanguages?: LanguageCode[];
126
+ staticPath?: string;
127
+ }
51
128
  interface ClientConfig {
52
129
  build?: BuildConfig;
53
130
  app?: AppConfig;
@@ -116,70 +193,224 @@ interface FormFieldConfig {
116
193
  }
117
194
  type FormSubmitHandler = (data: Record<string, unknown>, event: Event) => void | Promise<void>;
118
195
  type ClassValue = string | Record<string, boolean> | undefined | null | false;
196
+ type DeepPartial<T> = {
197
+ [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
198
+ };
199
+ type EventHandler<T extends Event = Event> = (event: T) => void;
119
200
 
120
- declare abstract class Component<P = Record<string, unknown>, S = Record<string, unknown>> {
121
- props: P;
122
- state: S;
123
- _isMounted: boolean;
124
- private _isUnmounting;
125
- private _element;
126
- private _vnode;
127
- private _styleId;
128
- private _isScheduledForUpdate;
129
- private _updateBatch;
130
- private _refs;
131
- private _subscriptions;
132
- private _memoCache;
133
- constructor(props?: P, initialState?: S);
134
- onBeforeMount?(): void | Promise<void>;
135
- onMount?(): void | Promise<void>;
136
- onBeforeUpdate?(prevProps: P, prevState: S): void | Promise<void>;
137
- onUpdate?(prevProps: P, prevState: S): void;
138
- onBeforeUnmount?(): void;
139
- onUnmount?(): void;
140
- onError?(error: Error, errorInfo: {
141
- componentStack?: string;
142
- }): void;
143
- onPropsChange?(prevProps: P, newProps: P): void;
144
- onStateChange?(prevState: S, newState: S): void;
145
- shouldUpdate?(prevProps: P, prevState: S): boolean;
146
- abstract render(): VNode;
147
- styles?(): string;
148
- setState(partialState: Partial<S> | ((prevState: S) => Partial<S>), callback?: () => void): void;
149
- setProps(newProps: Partial<P>): void;
150
- batchUpdate(updater: () => void): void;
151
- update(key?: string): void;
152
- forceUpdate(): void;
153
- mount(container: HTMLElement): Promise<void>;
154
- unmount(): void;
155
- getRef(name: string): HTMLElement | undefined;
156
- createRef(name: string): (el: HTMLElement | null) => void;
157
- memo<T>(key: string, compute: () => T, deps: unknown[]): T;
158
- subscribe(subscription: () => void): void;
159
- debounce<T extends (...args: unknown[]) => unknown>(fn: T, delay: number): (...args: Parameters<T>) => void;
160
- throttle<T extends (...args: unknown[]) => unknown>(fn: T, delay: number): (...args: Parameters<T>) => void;
161
- get element(): HTMLElement | null;
162
- get isMounted(): boolean;
163
- get isUnmounting(): boolean;
164
- private _performUpdate;
165
- private _convertToVDomNode;
166
- private _createElementFromVNode;
167
- private _setElementProperty;
168
- private _handleError;
169
- private _areDepsEqual;
201
+ interface ClassFieldDecoratorContext<This = unknown, Value = unknown> {
202
+ kind: 'field';
203
+ name: string | symbol;
204
+ access: {
205
+ get(object: This): Value;
206
+ set(object: This, value: Value): void;
207
+ };
208
+ addInitializer(initializer: (this: This) => void): void;
209
+ }
210
+ interface ClassGetterDecoratorContext<This = unknown, Value = unknown> {
211
+ kind: 'getter';
212
+ name: string | symbol;
213
+ access: {
214
+ get(object: This): Value;
215
+ };
216
+ addInitializer(initializer: (this: This) => void): void;
217
+ }
218
+ interface ClassMethodDecoratorContext<This = unknown, Value = unknown> {
219
+ kind: 'method';
220
+ name: string | symbol;
221
+ access: {
222
+ get(object: This): Value;
223
+ };
224
+ addInitializer(initializer: (this: This) => void): void;
225
+ }
226
+ /**
227
+ * State decorator - makes property reactive
228
+ * Usage: @state fields = [];
229
+ *
230
+ * Supports both TypeScript 5 decorators and legacy decorators
231
+ */
232
+ declare function state<This, Value>(target: undefined, context: ClassFieldDecoratorContext<This, Value>): (this: This, initialValue: Value) => Value;
233
+ declare function state(target: Record<string, unknown>, context: string): void;
234
+ /**
235
+ * Computed decorator - creates computed property
236
+ * Usage: @computed get fullName() { return this.firstName + ' ' + this.lastName; }
237
+ */
238
+ declare function computed<This, Value>(originalGetter: (this: This) => Value, context: ClassGetterDecoratorContext<This, Value>): (this: This) => Value;
239
+ declare function computed(target: Record<string, unknown>, context: string, descriptor: PropertyDescriptor): PropertyDescriptor;
240
+ declare function computed(targetOrGetter: unknown, context: unknown): never;
241
+ /**
242
+ * Watch decorator - watches for property changes
243
+ * Usage: @watch('propertyName') onPropertyChange(newValue, oldValue) {}
244
+ */
245
+ declare function watch(propertyName: string): {
246
+ <This, Args extends unknown[], Return>(originalMethod: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>): void;
247
+ (target: Record<string, unknown>, context: string, descriptor: PropertyDescriptor): PropertyDescriptor;
248
+ };
249
+
250
+ type UpdateCallback = () => void;
251
+ /**
252
+ * Update Scheduler
253
+ * Batches multiple state changes into a single render
254
+ */
255
+ declare class UpdateScheduler {
256
+ private queue;
257
+ private isFlushScheduled;
258
+ private isFlushing;
170
259
  /**
171
- * Invalidate all computed property caches (called by decorators)
260
+ * Schedule a component update
172
261
  */
173
- _invalidateAllComputed(): void;
262
+ schedule(callback: UpdateCallback): void;
263
+ /**
264
+ * Force immediate flush (for urgent updates)
265
+ */
266
+ flushSync(callback: UpdateCallback): void;
174
267
  /**
175
- * Trigger watchers for a property (called by decorators)
268
+ * Flush all pending updates
176
269
  */
177
- _triggerWatchers(propertyName: string, newValue: unknown, oldValue: unknown): void;
270
+ private flush;
271
+ /**
272
+ * Clear all pending updates
273
+ */
274
+ clear(): void;
275
+ /**
276
+ * Get queue size (for debugging)
277
+ */
278
+ get size(): number;
178
279
  }
179
- interface ComponentConstructor {
180
- __watchers__?: Record<string, string[]>;
181
- __reactiveProps__?: string[];
280
+ declare const scheduler: UpdateScheduler;
281
+
282
+ type ContextSubscriber<T> = (value: T) => void;
283
+ interface ProviderProps<T> {
284
+ context: Context<T>;
285
+ value: T;
286
+ children: VNode | VNode[];
287
+ }
288
+ /**
289
+ * Context class for sharing data across component tree
290
+ */
291
+ declare class Context<T = unknown> {
292
+ private _value;
293
+ private _subscribers;
294
+ private _defaultValue;
295
+ constructor(defaultValue: T);
296
+ get value(): T;
297
+ set value(newValue: T);
298
+ subscribe(subscriber: ContextSubscriber<T>): () => void;
299
+ reset(): void;
300
+ update(updater: (prev: T) => T): void;
301
+ private _notify;
302
+ get subscriberCount(): number;
303
+ }
304
+ /**
305
+ * Create a new context
306
+ */
307
+ declare function createContext<T>(defaultValue: T): Context<T>;
308
+ declare class Provider<T> extends Component<ProviderProps<T>> {
309
+ onMount(): void;
310
+ onUpdate(): void;
311
+ onUnmount(): void;
312
+ render(): VNode;
182
313
  }
314
+ /**
315
+ * Hook-like function to use context in components
316
+ * Call this in your component to get context value
317
+ */
318
+ declare function useContext<T>(context: Context<T>, component: Component): T;
319
+ /**
320
+ * Combined context for complex state management
321
+ */
322
+ declare class CombinedContext<T extends Record<string, unknown>> {
323
+ private contexts;
324
+ constructor(initialValues: T);
325
+ get<K extends keyof T>(key: K): Context<T[K]>;
326
+ set<K extends keyof T>(key: K, value: T[K]): void;
327
+ subscribe<K extends keyof T>(key: K, subscriber: ContextSubscriber<T[K]>): () => void;
328
+ reset(): void;
329
+ }
330
+ /**
331
+ * Create combined context
332
+ */
333
+ declare function createCombinedContext<T extends Record<string, unknown>>(initialValues: T): CombinedContext<T>;
334
+
335
+ /**
336
+ * Set current component context for hooks
337
+ */
338
+ declare function setHookContext(component: Component): void;
339
+ /**
340
+ * Clear hook context
341
+ */
342
+ declare function clearHookContext(): void;
343
+ /**
344
+ * useState hook - manages component state
345
+ */
346
+ declare function useState<T>(initialValue: T | (() => T)): [T, (newValue: T | ((prev: T) => T)) => void];
347
+ /**
348
+ * useEffect hook - side effects
349
+ */
350
+ declare function useEffect(effect: () => void | (() => void), deps?: unknown[]): void;
351
+ /**
352
+ * useMemo hook - memoize expensive computations
353
+ */
354
+ declare function useMemo<T>(factory: () => T, deps: unknown[]): T;
355
+ /**
356
+ * useCallback hook - memoize callbacks
357
+ */
358
+ declare function useCallback<T extends (...args: unknown[]) => unknown>(callback: T, deps: unknown[]): T;
359
+ /**
360
+ * useRef hook - persistent value across renders
361
+ */
362
+ declare function useRef<T>(initialValue: T): {
363
+ current: T;
364
+ };
365
+ /**
366
+ * useReducer hook - complex state management
367
+ */
368
+ declare function useReducer<S, A>(reducer: (state: S, action: A) => S, initialState: S): [S, (action: A) => void];
369
+ /**
370
+ * useLocalStorage hook - sync state with localStorage
371
+ */
372
+ declare function useLocalStorage<T>(key: string, initialValue: T): [T, (value: T | ((prev: T) => T)) => void];
373
+ /**
374
+ * useDebounce hook - debounce value changes
375
+ */
376
+ declare function useDebounce<T>(value: T, delay: number): T;
377
+ /**
378
+ * usePrevious hook - get previous value
379
+ */
380
+ declare function usePrevious<T>(value: T): T | undefined;
381
+ /**
382
+ * useToggle hook - boolean toggle
383
+ */
384
+ declare function useToggle(initialValue?: boolean): [boolean, () => void];
385
+ /**
386
+ * useInterval hook - setInterval with cleanup
387
+ */
388
+ declare function useInterval(callback: () => void, delay: number | null): void;
389
+ /**
390
+ * useFetch hook - data fetching
391
+ */
392
+ declare function useFetch<T>(url: string, options?: RequestInit): {
393
+ data: T | null;
394
+ loading: boolean;
395
+ error: Error | null;
396
+ refetch: () => void;
397
+ };
398
+ /**
399
+ * useWindowSize hook - track window dimensions
400
+ */
401
+ declare function useWindowSize(): {
402
+ width: number;
403
+ height: number;
404
+ };
405
+ /**
406
+ * useEventListener hook - add event listener
407
+ */
408
+ declare function useEventListener<K extends keyof WindowEventMap>(eventName: K, handler: (event: WindowEventMap[K]) => void, element?: HTMLElement | Window): void;
409
+ /**
410
+ * Create a functional component with hooks
411
+ * Returns a component class that can be instantiated
412
+ */
413
+ declare function createFunctionalComponent<P extends Record<string, unknown> = Record<string, unknown>>(fn: (props: P) => VNode, displayName?: string): new (props?: P) => Component<P>;
183
414
 
184
415
  declare class Router {
185
416
  private routes;
@@ -279,56 +510,46 @@ declare class Router {
279
510
  private _parseQuery;
280
511
  }
281
512
  declare const router: Router;
282
-
283
- declare global {
284
- interface Window {
285
- __JEES_DEV__?: {
286
- router: typeof router;
287
- config: ClientConfig;
288
- version: string;
289
- };
290
- }
291
- }
292
513
  /**
293
- * Client builder
294
- * Handles build process and runtime configuration
514
+ * Navigate to a new route
295
515
  */
296
- declare function client(config: ClientConfig): {
297
- /**
298
- * Build the client application
299
- * This compiles TypeScript components to vanilla JavaScript
300
- */
301
- build(): Promise<void>;
302
- /**
303
- * Build JavaScript bundle
304
- */
305
- _buildJS(): Promise<void>;
306
- /**
307
- * Build SCSS/CSS styles
308
- */
309
- _buildStyles(): Promise<void>;
310
- /**
311
- * Recursively collect all SCSS files (excluding .sass)
312
- */
313
- _collectScssFiles(dir: string): Promise<string[]>;
314
- /**
315
- * Watch mode for development
316
- */
317
- watch(): Promise<void>;
318
- /**
319
- * Initialize the client runtime
320
- * This runs in the browser
321
- */
322
- init(): void;
323
- /**
324
- * Enable development tools
325
- */
326
- _enableDevTools(): void;
327
- /**
328
- * Get configuration
329
- */
330
- getConfig(): ClientConfig;
331
- };
516
+ declare function navigate(path: string, replace?: boolean): void;
517
+ /**
518
+ * Navigate back in history
519
+ */
520
+ declare function goBack(): void;
521
+ /**
522
+ * Navigate forward in history
523
+ */
524
+ declare function goForward(): void;
525
+ /**
526
+ * Get current path
527
+ */
528
+ declare function getCurrentPath(): string;
529
+ /**
530
+ * Check if current path matches
531
+ */
532
+ declare function isCurrentPath(path: string): boolean;
533
+ /**
534
+ * Check if current path starts with
535
+ */
536
+ declare function isCurrentPathPrefix(prefix: string): boolean;
537
+ /**
538
+ * Reload current route
539
+ */
540
+ declare function reloadRoute(): void;
541
+ /**
542
+ * Navigate with query params
543
+ */
544
+ declare function navigateWithQuery(path: string, params: Record<string, string>): void;
545
+ /**
546
+ * Get query parameters
547
+ */
548
+ declare function getQueryParams(): URLSearchParams;
549
+ /**
550
+ * Get single query parameter
551
+ */
552
+ declare function getQueryParam(key: string): string | null;
332
553
 
333
554
  /**
334
555
  * Store - Global state management with improved features
@@ -433,6 +654,56 @@ declare function connect<T extends Record<string, unknown>, C extends {
433
654
  update?: () => void;
434
655
  }>(store: Store<T>, component: C, mapStateToProps: (state: T) => Partial<C>): () => void;
435
656
 
657
+ declare global {
658
+ interface Window {
659
+ __JEES_DEV__?: {
660
+ router: typeof router;
661
+ config: ClientConfig;
662
+ version: string;
663
+ };
664
+ }
665
+ }
666
+ /**
667
+ * Client builder
668
+ * Handles build process and runtime configuration
669
+ */
670
+ declare function client(config: ClientConfig): {
671
+ /**
672
+ * Build the client application
673
+ * This compiles TypeScript components to vanilla JavaScript
674
+ */
675
+ build(): Promise<void>;
676
+ /**
677
+ * Build JavaScript bundle
678
+ */
679
+ _buildJS(): Promise<void>;
680
+ /**
681
+ * Build SCSS/CSS styles
682
+ */
683
+ _buildStyles(): Promise<void>;
684
+ /**
685
+ * Recursively collect all SCSS files (excluding .sass)
686
+ */
687
+ _collectScssFiles(dir: string): Promise<string[]>;
688
+ /**
689
+ * Watch mode for development
690
+ */
691
+ watch(): Promise<void>;
692
+ /**
693
+ * Initialize the client runtime
694
+ * This runs in the browser
695
+ */
696
+ init(): Promise<void>;
697
+ /**
698
+ * Enable development tools
699
+ */
700
+ _enableDevTools(): void;
701
+ /**
702
+ * Get configuration
703
+ */
704
+ getConfig(): ClientConfig;
705
+ };
706
+
436
707
  /**
437
708
  * Style Manager - handles CSS injection and scoping
438
709
  */
@@ -462,55 +733,360 @@ declare class StyleManager {
462
733
  */
463
734
  declare function css(strings: TemplateStringsArray, ...values: unknown[]): string;
464
735
 
465
- interface ClassFieldDecoratorContext<This = unknown, Value = unknown> {
466
- kind: 'field';
467
- name: string | symbol;
468
- access: {
469
- get(object: This): Value;
470
- set(object: This, value: Value): void;
471
- };
472
- addInitializer(initializer: (this: This) => void): void;
473
- }
474
- interface ClassGetterDecoratorContext<This = unknown, Value = unknown> {
475
- kind: 'getter';
476
- name: string | symbol;
477
- access: {
478
- get(object: This): Value;
479
- };
480
- addInitializer(initializer: (this: This) => void): void;
481
- }
482
- interface ClassMethodDecoratorContext<This = unknown, Value = unknown> {
483
- kind: 'method';
484
- name: string | symbol;
485
- access: {
486
- get(object: This): Value;
487
- };
488
- addInitializer(initializer: (this: This) => void): void;
736
+ declare class I18nManager {
737
+ private translations;
738
+ private currentLanguage;
739
+ private defaultLanguage;
740
+ private supportedLanguages;
741
+ private cachePath;
742
+ private readyListeners;
743
+ constructor(config?: I18nConfig);
744
+ /**
745
+ * Load translations for a specific language
746
+ * @param lang Language code (e.g., 'en', 'ar', 'fr')
747
+ * @param translations Translation object
748
+ */
749
+ loadLanguage(lang: LanguageCode, translations: Record<string, string>): void;
750
+ /**
751
+ * Load all translations from static files
752
+ * @param translations Object with language codes as keys and translation objects as values
753
+ */
754
+ loadTranslations(translations: TranslationSet): void;
755
+ /**
756
+ * Set the current language
757
+ * @param lang Language code
758
+ */
759
+ setLanguage(lang: LanguageCode): void;
760
+ /**
761
+ * Get the current language
762
+ */
763
+ getLanguage(): LanguageCode;
764
+ /**
765
+ * Get all supported languages
766
+ */
767
+ getSupportedLanguages(): LanguageCode[];
768
+ /**
769
+ * Translate a key with smart parameter replacement
770
+ * Supports nested translation keys as parameter values
771
+ *
772
+ * @example
773
+ * // Simple translation
774
+ * t('hello') // => "Hello" or "مرحبا" depending on current language
775
+ *
776
+ * @example
777
+ * // With parameters
778
+ * t('welcome', { app_name: 'MyApp' })
779
+ * // => "Welcome to MyApp"
780
+ *
781
+ * @example
782
+ * // With nested translation keys as parameters
783
+ * t('greeting', { salutation: 'hello' })
784
+ * // => "Say Hello to everyone"
785
+ *
786
+ * @param key Translation key
787
+ * @param params Optional parameters for replacement
788
+ * @param defaultValue Optional default translation key
789
+ * @returns Translated string with replaced parameters
790
+ */
791
+ t(key: string, params?: Record<string, string>, defaultValue?: string): string;
792
+ private getTranslation;
793
+ /**
794
+ * Translate with a specific language (overrides current language temporarily)
795
+ *
796
+ * @param key Translation key
797
+ * @param lang Language code
798
+ * @param params Optional parameters
799
+ * @returns Translated string
800
+ */
801
+ tLang(key: string, lang: LanguageCode, params?: Record<string, string>): string;
802
+ /**
803
+ * Translate a key and convert HTML tags in the translation to VNode elements
804
+ * Supports tags like <br>, <strong>, <em>, <b>, <i>, etc.
805
+ * Useful for multiline translations with formatting
806
+ *
807
+ * @example
808
+ * // Translation: "Hello <br> World"
809
+ * tHtml('greeting') // => [text node, br element, text node]
810
+ *
811
+ * @param key Translation key
812
+ * @param params Optional parameters for replacement
813
+ * @returns Array of VNode and string elements that can be used as children
814
+ */
815
+ tHtml(key: string, params?: Record<string, string>): (VNode | string)[];
816
+ /**
817
+ * Parse HTML string into VNode and text elements
818
+ * Converts \n and /n sequences to <br> tags
819
+ * @private
820
+ */
821
+ private parseHtmlString;
822
+ /**
823
+ * Get all translations for current language
824
+ */
825
+ getTranslations(): Record<string, string>;
826
+ /**
827
+ * Check if a translation key exists
828
+ * @param key Translation key
829
+ * @returns true if key exists in current or default language
830
+ */
831
+ hasKey(key: string): boolean;
832
+ /**
833
+ * Create a reactive translation function that listens to language changes
834
+ * @param updateCallback Callback function to execute when language changes
835
+ * @returns Function to unsubscribe from language changes
836
+ */
837
+ createTranslator(updateCallback: () => void): () => void;
838
+ /**
839
+ * Load translations from URL(s)
840
+ * Supports patterns like '/static/i18n/*.json' or specific URLs
841
+ *
842
+ * @example
843
+ * // Load from a pattern
844
+ * await loadFromUrl('/static/i18n/*.json');
845
+ *
846
+ * @example
847
+ * // Load specific language files
848
+ * await loadFromUrl(['/static/i18n/en.json', '/static/i18n/ar.json']);
849
+ *
850
+ * @param urlPattern String pattern or array of URLs
851
+ * @returns Promise that resolves when all translations are loaded
852
+ */
853
+ loadFromUrl(urlPattern: string | string[]): Promise<void>;
854
+ /**
855
+ * Register a callback for when i18n is ready
856
+ */
857
+ onReady(callback: () => void): void;
858
+ /**
859
+ * Notify all listeners that i18n is ready
860
+ */
861
+ private notifyReady;
862
+ /**
863
+ * Get language from localStorage
864
+ */
865
+ private getStoredLanguage;
866
+ /**
867
+ * Store language in localStorage
868
+ */
869
+ private storeLanguage;
870
+ /**
871
+ * Dispatch language change event
872
+ */
873
+ private dispatchLanguageChangeEvent;
489
874
  }
490
875
  /**
491
- * State decorator - makes property reactive
492
- * Usage: @state fields = [];
876
+ * Get the global i18n instance
877
+ */
878
+ declare function getI18n(): I18nManager;
879
+
880
+ /**
881
+ * Global translation function
882
+ * @param key Translation key
883
+ * @param params Optional parameters
884
+ * @param defaultValue Optional default translation key
885
+ * @returns Translated string
886
+ */
887
+ declare function t(key: string, params?: Record<string, string>, defaultValue?: string): string;
888
+ /**
889
+ * Translate with a specific language (overrides current language temporarily)
890
+ * @param key Translation key
891
+ * @param lang Language code
892
+ * @param params Optional parameters
893
+ * @returns Translated string
894
+ */
895
+ declare function tLang(key: string, lang: string, params?: Record<string, string>): string;
896
+ /**
897
+ * Translate a key and convert HTML tags to VNode elements
898
+ * Useful for multiline translations with formatting like <br>
899
+ * @param key Translation key
900
+ * @param params Optional parameters
901
+ * @returns Array of VNode and string elements that can be used as children
902
+ */
903
+ declare function tHtml(key: string, params?: Record<string, string>): (VNode | string)[];
904
+ /**
905
+ * Set the current language globally (synchronous)
906
+ * @param lang Language code
907
+ */
908
+ declare function setLanguage(lang: string): void;
909
+ /**
910
+ * Set the current language globally with lazy-loading support (asynchronous)
911
+ * Use this when you want to lazy-load language files on demand
912
+ * @param lang Language code
913
+ * @param staticPath Path to language files for lazy-loading
914
+ * @returns Promise that resolves when language is loaded and set
915
+ */
916
+ declare function setLanguageAsync(lang: string, staticPath?: string): Promise<void>;
917
+ /**
918
+ * Get the current language
919
+ */
920
+ declare function getCurrentLanguage(): string;
921
+ /**
922
+ * Load translations for a specific language
923
+ * @param lang Language code
924
+ * @param translations Translation object
925
+ */
926
+ declare function loadLanguage(lang: string, translations: Record<string, string>): void;
927
+ /**
928
+ * Load all translations
929
+ * @param translations The translations object
930
+ */
931
+ declare function loadTranslations(translations: Record<string, Record<string, string>>): void;
932
+ /**
933
+ * Get all supported languages
934
+ */
935
+ declare function getSupportedLanguages(): string[];
936
+ /**
937
+ * Check if a translation key exists
938
+ * @param key The translation key to check
939
+ * @returns Whether the key exists
940
+ */
941
+ declare function hasKey(key: string): boolean;
942
+ /**
943
+ * Get all translations for current language
944
+ */
945
+ declare function getTranslations(): Record<string, string>;
946
+ /**
947
+ * Create a reactive translator that listens to language changes
948
+ * @param updateCallback Callback function to execute when language changes
949
+ * @returns Function to unsubscribe from language changes
950
+ */
951
+ declare function createTranslator(updateCallback: () => void): () => void;
952
+ /**
953
+ * Load translations from URL(s)
954
+ * Supports patterns like '/static/i18n/*.json' or specific URLs
493
955
  *
494
- * Supports both TypeScript 5 decorators and legacy decorators
956
+ * @example
957
+ * // Load from a pattern
958
+ * await loadFromUrl('/static/i18n/*.json');
959
+ *
960
+ * @example
961
+ * // Load specific language files
962
+ * await loadFromUrl(['/static/i18n/en.json', '/static/i18n/ar.json']);
963
+ *
964
+ * @param urlPattern String pattern or array of URLs
965
+ * @returns Promise that resolves when all translations are loaded
495
966
  */
496
- declare function state<This, Value>(target: undefined, context: ClassFieldDecoratorContext<This, Value>): (this: This, initialValue: Value) => Value;
497
- declare function state(target: Record<string, unknown>, context: string): void;
967
+ declare function loadFromUrl(urlPattern: string | string[]): Promise<void>;
498
968
  /**
499
- * Computed decorator - creates computed property
500
- * Usage: @computed get fullName() { return this.firstName + ' ' + this.lastName; }
969
+ * Initialize i18n synchronously (useful for testing)
970
+ * Creates a new I18nManager instance with the provided config
971
+ *
972
+ * @param config I18n configuration
973
+ *
974
+ * @example
975
+ * initializeI18n({
976
+ * defaultLanguage: 'en',
977
+ * supportedLanguages: ['en', 'ar']
978
+ * });
501
979
  */
502
- declare function computed<This, Value>(originalGetter: (this: This) => Value, context: ClassGetterDecoratorContext<This, Value>): (this: This) => Value;
503
- declare function computed(target: Record<string, unknown>, context: string, descriptor: PropertyDescriptor): PropertyDescriptor;
504
- declare function computed(targetOrGetter: unknown, context: unknown): never;
980
+ declare function initializeI18n(config?: I18nConfig): void;
505
981
  /**
506
- * Watch decorator - watches for property changes
507
- * Usage: @watch('propertyName') onPropertyChange(newValue, oldValue) {}
982
+ * Setup i18n: Initialize and load the currently selected language
983
+ * Uses stored language from localStorage if available, otherwise uses default
984
+ * Other languages are lazy-loaded when setLanguage is called
985
+ *
986
+ * @param config I18n configuration
987
+ * @returns Promise that resolves when the selected language is loaded
988
+ *
989
+ * @example
990
+ * await setupI18n({
991
+ * defaultLanguage: 'en',
992
+ * supportedLanguages: ['en', 'ar'],
993
+ * staticPath: 'static/i18n'
994
+ * });
995
+ * console.log(t('hello')); // Ready to use in current language!
508
996
  */
509
- declare function watch(propertyName: string): {
510
- <This, Args extends unknown[], Return>(originalMethod: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>): void;
511
- (target: Record<string, unknown>, context: string, descriptor: PropertyDescriptor): PropertyDescriptor;
997
+ declare function setupI18n(config: I18nConfig): Promise<void>;
998
+ /**
999
+ * Load a specific language file on-demand
1000
+ * Use this when user switches to a language that hasn't been loaded yet
1001
+ *
1002
+ * @param lang Language code (e.g., 'ar', 'fr')
1003
+ * @param staticPath Optional path to language files (defaults to 'static/i18n')
1004
+ * @returns Promise that resolves when language is loaded
1005
+ *
1006
+ * @example
1007
+ * // User switches to Arabic - load it first if not already loaded
1008
+ * await loadLanguageFile('ar');
1009
+ * setLanguage('ar');
1010
+ */
1011
+ declare function loadLanguageFile(lang: string, staticPath?: string): Promise<void>;
1012
+
1013
+ type ToastType = 'success' | 'error' | 'info' | 'warning';
1014
+ interface ToastMessage {
1015
+ id: number;
1016
+ message: string;
1017
+ type: ToastType;
1018
+ translateKey?: string;
1019
+ }
1020
+ declare class Toast extends Component {
1021
+ messages: ToastMessage[];
1022
+ private nextId;
1023
+ /**
1024
+ * Show a toast notification
1025
+ */
1026
+ show(message: string, type?: ToastType, duration?: number, translateKey?: string): void;
1027
+ /**
1028
+ * Convenience methods
1029
+ */
1030
+ success(message: string, duration?: number, translateKey?: string): void;
1031
+ error(message: string, duration?: number, translateKey?: string): void;
1032
+ info(message: string, duration?: number, translateKey?: string): void;
1033
+ warning(message: string, duration?: number, translateKey?: string): void;
1034
+ render(): _je_es_vdom.VNode;
1035
+ renderToast(msg: ToastMessage): _je_es_vdom.VNode;
1036
+ }
1037
+ declare function initToast(container?: HTMLElement): Toast;
1038
+ declare function getToast(): Toast;
1039
+ declare const toast: {
1040
+ show: (message: string, type?: ToastType, duration?: number, translateKey?: string) => void;
1041
+ success: (message: string, duration?: number, translateKey?: string) => void;
1042
+ error: (message: string, duration?: number, translateKey?: string) => void;
1043
+ info: (message: string, duration?: number, translateKey?: string) => void;
1044
+ warning: (message: string, duration?: number, translateKey?: string) => void;
512
1045
  };
513
1046
 
1047
+ type LoaderSize = 'small' | 'medium' | 'large';
1048
+ type LoaderVariant = 'spinner' | 'dots' | 'pulse';
1049
+ interface LoaderOptions {
1050
+ message?: string;
1051
+ variant?: LoaderVariant;
1052
+ size?: LoaderSize;
1053
+ overlay?: boolean;
1054
+ }
1055
+ declare class Loader extends Component {
1056
+ visible: boolean;
1057
+ message: string;
1058
+ variant: LoaderVariant;
1059
+ size: LoaderSize;
1060
+ overlay: boolean;
1061
+ progress: number;
1062
+ showProgress: boolean;
1063
+ private animationFrame;
1064
+ private hideTimeout;
1065
+ onMount(): Promise<void>;
1066
+ onUnmount(): void;
1067
+ render(): _je_es_vdom.VNode;
1068
+ renderSpinner(): _je_es_vdom.VNode;
1069
+ renderMessage(): _je_es_vdom.VNode;
1070
+ renderProgressBar(): _je_es_vdom.VNode;
1071
+ show(options?: LoaderOptions | string): void;
1072
+ hide(delay?: number): void;
1073
+ setMessage(message: string): void;
1074
+ setProgress(progress: number): void;
1075
+ updateProgress(increment: number): void;
1076
+ private performHide;
1077
+ private applyBodyLock;
1078
+ private removeBodyLock;
1079
+ private setupKeyboardListener;
1080
+ private handleKeyPress;
1081
+ private initializeAccessibility;
1082
+ isVisible(): boolean;
1083
+ getStatus(): {
1084
+ visible: boolean;
1085
+ message: string;
1086
+ progress: number;
1087
+ };
1088
+ }
1089
+
514
1090
  interface FormConfig {
515
1091
  fields: FormFieldConfig[];
516
1092
  endpoint?: string;
@@ -579,6 +1155,396 @@ declare class SmartFormComponent extends Component<FormConfig> {
579
1155
  */
580
1156
  declare function SmartForm(config: FormConfig): VNode;
581
1157
 
1158
+ type PopupType = 'confirm' | 'alert' | 'form' | 'custom' | 'prompt';
1159
+ type PopupVariant = 'default' | 'danger' | 'warning' | 'success' | 'info';
1160
+ type PopupSize = 'small' | 'medium' | 'large' | 'xlarge' | 'fullscreen';
1161
+ interface PopupButton {
1162
+ label: string;
1163
+ translateKey?: string;
1164
+ variant?: 'primary' | 'secondary' | 'danger' | 'success';
1165
+ icon?: string;
1166
+ onClick: () => void | Promise<void>;
1167
+ loading?: boolean;
1168
+ }
1169
+ interface PopupFormOptions {
1170
+ title: string;
1171
+ titleTranslateKey?: string;
1172
+ description?: string;
1173
+ descriptionTranslateKey?: string;
1174
+ formConfig: FormConfig;
1175
+ variant?: PopupVariant;
1176
+ icon?: string;
1177
+ size?: PopupSize;
1178
+ closeOnOverlay?: boolean;
1179
+ closeOnEscape?: boolean;
1180
+ showCloseButton?: boolean;
1181
+ }
1182
+ interface PopupOptions {
1183
+ title: string;
1184
+ titleTranslateKey?: string;
1185
+ message?: string;
1186
+ messageTranslateKey?: string;
1187
+ description?: string;
1188
+ descriptionTranslateKey?: string;
1189
+ type?: PopupType;
1190
+ variant?: PopupVariant;
1191
+ size?: PopupSize;
1192
+ buttons?: PopupButton[];
1193
+ customContent?: VNode;
1194
+ formConfig?: FormConfig;
1195
+ closeOnOverlay?: boolean;
1196
+ closeOnEscape?: boolean;
1197
+ showCloseButton?: boolean;
1198
+ icon?: string;
1199
+ onConfirm?: () => void | Promise<void>;
1200
+ onCancel?: () => void | Promise<void>;
1201
+ }
1202
+ interface ActivePopup extends PopupOptions {
1203
+ id: number;
1204
+ resolve?: (value: boolean | string | null | unknown) => void;
1205
+ inputValue?: string;
1206
+ isSubmitting?: boolean;
1207
+ }
1208
+ declare class Popup extends Component {
1209
+ popups: ActivePopup[];
1210
+ private nextId;
1211
+ private handleEscapeKey?;
1212
+ onMount(): Promise<void>;
1213
+ onUnmount(): void;
1214
+ render(): VNode;
1215
+ renderPopup(popup: ActivePopup): VNode;
1216
+ /**
1217
+ * Show a custom popup
1218
+ */
1219
+ show(options: PopupOptions): Promise<boolean | string | null | unknown>;
1220
+ /**
1221
+ * Show a form popup
1222
+ */
1223
+ showForm(options: PopupFormOptions): Promise<unknown>;
1224
+ /**
1225
+ * Show a confirmation dialog
1226
+ */
1227
+ confirm(options: {
1228
+ title: string;
1229
+ titleTranslateKey?: string;
1230
+ message: string;
1231
+ messageTranslateKey?: string;
1232
+ confirmLabel?: string;
1233
+ confirmTranslateKey?: string;
1234
+ cancelLabel?: string;
1235
+ cancelTranslateKey?: string;
1236
+ variant?: PopupVariant;
1237
+ icon?: string;
1238
+ size?: PopupSize;
1239
+ onConfirm?: () => void | Promise<void>;
1240
+ onCancel?: () => void | Promise<void>;
1241
+ }): Promise<boolean>;
1242
+ /**
1243
+ * Show an alert dialog
1244
+ */
1245
+ alert(options: {
1246
+ title: string;
1247
+ titleTranslateKey?: string;
1248
+ message: string;
1249
+ messageTranslateKey?: string;
1250
+ okLabel?: string;
1251
+ okTranslateKey?: string;
1252
+ variant?: PopupVariant;
1253
+ icon?: string;
1254
+ size?: PopupSize;
1255
+ onConfirm?: () => void | Promise<void>;
1256
+ }): Promise<boolean>;
1257
+ /**
1258
+ * Show a prompt dialog
1259
+ */
1260
+ prompt(options: {
1261
+ title: string;
1262
+ titleTranslateKey?: string;
1263
+ message: string;
1264
+ messageTranslateKey?: string;
1265
+ defaultValue?: string;
1266
+ confirmLabel?: string;
1267
+ confirmTranslateKey?: string;
1268
+ cancelLabel?: string;
1269
+ cancelTranslateKey?: string;
1270
+ icon?: string;
1271
+ onConfirm?: (value: string) => void | Promise<void>;
1272
+ onCancel?: () => void | Promise<void>;
1273
+ }): Promise<string | null>;
1274
+ /**
1275
+ * Close a specific popup
1276
+ */
1277
+ closePopup(id: number, result: boolean | string | null | unknown): void;
1278
+ /**
1279
+ * Close all popups
1280
+ */
1281
+ closeAll(): void;
1282
+ private applyBodyLock;
1283
+ private removeBodyLock;
1284
+ private setupKeyboardListener;
1285
+ }
1286
+ declare function initPopup(container?: HTMLElement): Popup;
1287
+ declare function getPopup(): Popup;
1288
+ declare const popup: {
1289
+ show: (options: PopupOptions) => Promise<unknown>;
1290
+ confirm: (options: Parameters<Popup["confirm"]>[0]) => Promise<boolean>;
1291
+ alert: (options: Parameters<Popup["alert"]>[0]) => Promise<boolean>;
1292
+ prompt: (options: {
1293
+ title: string;
1294
+ titleTranslateKey?: string;
1295
+ message: string;
1296
+ icon?: string;
1297
+ messageTranslateKey?: string;
1298
+ onConfirm?: () => void | Promise<void>;
1299
+ }) => Promise<string | null>;
1300
+ showForm: (options: PopupFormOptions) => Promise<unknown>;
1301
+ closePopup: (id: number, result: boolean | string | null | unknown) => void;
1302
+ closeLastPopup: () => void;
1303
+ closeFirstPopup: () => void;
1304
+ closeAll: () => void;
1305
+ };
1306
+
1307
+ type TabPosition = 'top' | 'side';
1308
+ type TabStyle = 'default' | 'pills' | 'minimal';
1309
+ interface Tab {
1310
+ id: string;
1311
+ label: string;
1312
+ translateKey?: string;
1313
+ icon?: string;
1314
+ badge?: number | string;
1315
+ disabled?: boolean;
1316
+ component?: Component | (() => VNode);
1317
+ content?: VNode;
1318
+ onActivate?: () => void | Promise<void>;
1319
+ }
1320
+ interface TabbedViewOptions {
1321
+ tabs: Tab[];
1322
+ defaultTab?: string;
1323
+ position?: TabPosition;
1324
+ style?: TabStyle;
1325
+ className?: string;
1326
+ headerClassName?: string;
1327
+ contentClassName?: string;
1328
+ showTabCount?: boolean;
1329
+ persistState?: boolean;
1330
+ storageKey?: string;
1331
+ onChange?: (tabId: string) => void | Promise<void>;
1332
+ }
1333
+ declare class TabbedView extends Component {
1334
+ activeTabId: string;
1335
+ tabs: Tab[];
1336
+ position: TabPosition;
1337
+ style: TabStyle;
1338
+ className: string;
1339
+ headerClassName: string;
1340
+ contentClassName: string;
1341
+ showTabCount: boolean;
1342
+ persistState: boolean;
1343
+ storageKey: string;
1344
+ private currentTabComponent;
1345
+ private onChange?;
1346
+ onMount(): Promise<void>;
1347
+ onUnmount(): void;
1348
+ /**
1349
+ * Initialize the tabbed view with options
1350
+ */
1351
+ init(options: TabbedViewOptions): this;
1352
+ /**
1353
+ * Set active tab
1354
+ */
1355
+ setActiveTab(tabId: string): Promise<void>;
1356
+ /**
1357
+ * Add a new tab dynamically
1358
+ */
1359
+ addTab(tab: Tab): void;
1360
+ /**
1361
+ * Remove a tab
1362
+ */
1363
+ removeTab(tabId: string): void;
1364
+ /**
1365
+ * Update tab properties
1366
+ */
1367
+ updateTab(tabId: string, updates: Partial<Tab>): void;
1368
+ /**
1369
+ * Get active tab
1370
+ */
1371
+ getActiveTab(): Tab | undefined;
1372
+ render(): VNode;
1373
+ renderTabList(): VNode;
1374
+ renderTab(tab: Tab): VNode;
1375
+ renderTabContent(): VNode;
1376
+ renderActiveTabContent(tab: Tab): any;
1377
+ }
1378
+ /**
1379
+ * Create a new TabbedView instance with options
1380
+ */
1381
+ declare function createTabbedView(options: TabbedViewOptions): TabbedView;
1382
+ /**
1383
+ * Helper to create a simple tabbed view and mount it
1384
+ */
1385
+ declare function mountTabbedView(container: HTMLElement, options: TabbedViewOptions): Promise<TabbedView>;
1386
+
1387
+ interface ItemsLoaderConfig<T> {
1388
+ fetchUrl: string | ((page: number, filters: Record<string, unknown>) => string);
1389
+ renderItem: (item: T, index: number) => HTMLElement;
1390
+ pageSize?: number;
1391
+ emptyStateConfig?: {
1392
+ icon: string;
1393
+ title: string;
1394
+ description: string;
1395
+ };
1396
+ loadMoreText?: string;
1397
+ loadingText?: string;
1398
+ errorText?: string;
1399
+ containerClassName?: string;
1400
+ itemClassName?: string;
1401
+ filters?: Record<string, unknown>;
1402
+ onFiltersChange?: (filters: Record<string, unknown>) => void;
1403
+ enableSearch?: boolean;
1404
+ searchPlaceholder?: string;
1405
+ searchFilterKey?: string;
1406
+ searchDebounceMs?: number;
1407
+ onItemClick?: (item: T, index: number) => void;
1408
+ onLoadMore?: (page: number, items: T[]) => void;
1409
+ onError?: (error: Error) => void;
1410
+ initialItems?: T[];
1411
+ extractItems?: (response: any) => T[];
1412
+ extractTotal?: (response: any) => number;
1413
+ getAuthToken?: () => string | null;
1414
+ enableInfiniteScroll?: boolean;
1415
+ scrollThreshold?: number;
1416
+ enableVisibilityTracking?: boolean;
1417
+ visibilityThreshold?: number;
1418
+ visibilityRootMargin?: string;
1419
+ onItemsViewed?: (viewedItems: T[]) => Promise<void>;
1420
+ getItemId?: (item: T) => number | string;
1421
+ shouldTrackItem?: (item: T) => boolean;
1422
+ onDropdownOpen?: () => void;
1423
+ onDropdownClose?: () => void;
1424
+ onBatchAction?: (action: string, itemIds: (number | string)[]) => Promise<void>;
1425
+ }
1426
+ interface LoadState {
1427
+ loading: boolean;
1428
+ error: string | null;
1429
+ hasMore: boolean;
1430
+ page: number;
1431
+ total: number;
1432
+ }
1433
+ declare class ItemsLoader<T = unknown> extends Component {
1434
+ items: T[];
1435
+ loadState: LoadState;
1436
+ filters: Record<string, unknown>;
1437
+ config: ItemsLoaderConfig<T>;
1438
+ private scrollContainer;
1439
+ private loadMoreObserver;
1440
+ private currentLoadMoreTrigger;
1441
+ private loadMoreMutationObserver;
1442
+ private visibilityObserver;
1443
+ private viewedItems;
1444
+ private dropdownIsOpen;
1445
+ private itemsListContainer;
1446
+ private searchInput;
1447
+ private isUpdating;
1448
+ private searchDebounceTimer;
1449
+ initialize(config: ItemsLoaderConfig<T>): void;
1450
+ onMount(): Promise<void>;
1451
+ onUnmount(): void;
1452
+ loadMore(): Promise<void>;
1453
+ reload(): Promise<void>;
1454
+ applyFilters(newFilters: Record<string, unknown>): Promise<void>;
1455
+ handleSearch(searchQuery: string): Promise<void>;
1456
+ updateItems(updatedItems: T[]): void;
1457
+ private setupVisibilityTracking;
1458
+ private observeTrackableItems;
1459
+ private trackAlreadyVisibleItems;
1460
+ private disconnectVisibilityObserver;
1461
+ handleDropdownOpen(): void;
1462
+ handleDropdownClose(): Promise<void>;
1463
+ performBatchAction(action: string, itemIds: (number | string)[]): Promise<void>;
1464
+ private appendNewItems;
1465
+ private updateLoadingState;
1466
+ updateFooter(): void;
1467
+ private setupInfiniteScroll;
1468
+ private reconnectInfiniteScrollObserver;
1469
+ private disconnectInfiniteScrollObserver;
1470
+ private setupScrollListener;
1471
+ private handleScroll;
1472
+ private findScrollContainer;
1473
+ private buildUrl;
1474
+ private buildHeaders;
1475
+ private handleItemClick;
1476
+ private createElementFromVNode;
1477
+ render(): VNode;
1478
+ private renderSearchBar;
1479
+ renderEmptyState(): VNode;
1480
+ private renderLoading;
1481
+ private renderError;
1482
+ private renderLoadMoreTrigger;
1483
+ private renderEndMessage;
1484
+ }
1485
+ declare function createItemsLoader<T>(config: ItemsLoaderConfig<T>): ItemsLoader<T>;
1486
+
1487
+ interface DropdownItemConfig {
1488
+ id?: string;
1489
+ icon?: string;
1490
+ label: string;
1491
+ onclick?: (e: Event) => void;
1492
+ className?: string;
1493
+ disabled?: boolean;
1494
+ selected?: boolean;
1495
+ }
1496
+ interface DropdownConfig {
1497
+ id: string;
1498
+ trigger: {
1499
+ text?: string;
1500
+ icon?: string;
1501
+ element?: () => unknown;
1502
+ className?: string;
1503
+ };
1504
+ items: (DropdownItemConfig | 'divider')[];
1505
+ position?: 'left' | 'right';
1506
+ parentId?: string;
1507
+ closeOnItemClick?: boolean;
1508
+ preventAutoClose?: boolean;
1509
+ onOpen?: () => void;
1510
+ onClose?: () => void;
1511
+ }
1512
+ declare class Dropdown extends Component {
1513
+ config: DropdownConfig;
1514
+ isOpen: boolean;
1515
+ private mounted;
1516
+ constructor(config: DropdownConfig);
1517
+ onMount(): void;
1518
+ onUnmount(): void;
1519
+ /**
1520
+ * Public method to set open state (called by manager)
1521
+ */
1522
+ setOpen(open: boolean): void;
1523
+ /**
1524
+ * Toggle dropdown
1525
+ */
1526
+ toggle(e: Event): void;
1527
+ /**
1528
+ * Handle item click
1529
+ */
1530
+ handleItemClick(item: DropdownItemConfig, e: Event): void;
1531
+ render(): VNode;
1532
+ /**
1533
+ * Manually update the dropdown's DOM without triggering parent re-renders
1534
+ */
1535
+ private updateDOM;
1536
+ /**
1537
+ * Create DOM element from VNode (simplified version)
1538
+ */
1539
+ private createElementFromVNode;
1540
+ private renderTrigger;
1541
+ private renderMenu;
1542
+ }
1543
+ /**
1544
+ * Create a dropdown instance
1545
+ */
1546
+ declare function createDropdown(config: DropdownConfig): Dropdown;
1547
+
582
1548
  /**
583
1549
  * Debounce function
584
1550
  * Delays function execution until after wait time
@@ -683,169 +1649,80 @@ declare const utils: {
683
1649
  safeJsonParse: typeof safeJsonParse;
684
1650
  };
685
1651
 
686
- type ContextSubscriber<T> = (value: T) => void;
687
- interface ProviderProps<T> {
688
- context: Context<T>;
689
- value: T;
690
- children: VNode | VNode[];
691
- }
692
- /**
693
- * Context class for sharing data across component tree
694
- */
695
- declare class Context<T = unknown> {
696
- private _value;
697
- private _subscribers;
698
- private _defaultValue;
699
- constructor(defaultValue: T);
700
- get value(): T;
701
- set value(newValue: T);
702
- subscribe(subscriber: ContextSubscriber<T>): () => void;
703
- reset(): void;
704
- update(updater: (prev: T) => T): void;
705
- private _notify;
706
- get subscriberCount(): number;
707
- }
708
1652
  /**
709
- * Create a new context
1653
+ * Configuration for intersection observer
710
1654
  */
711
- declare function createContext<T>(defaultValue: T): Context<T>;
712
- declare class Provider<T> extends Component<ProviderProps<T>> {
713
- onMount(): void;
714
- onUpdate(): void;
715
- onUnmount(): void;
716
- render(): VNode;
1655
+ interface IntersectionConfig {
1656
+ root?: Element | null;
1657
+ rootMargin?: string;
1658
+ threshold?: number | number[];
1659
+ onEnter?: (entry: IntersectionObserverEntry) => void;
1660
+ onExit?: (entry: IntersectionObserverEntry) => void;
1661
+ once?: boolean;
717
1662
  }
718
1663
  /**
719
- * Hook-like function to use context in components
720
- * Call this in your component to get context value
721
- */
722
- declare function useContext<T>(context: Context<T>, component: Component): T;
723
- /**
724
- * Combined context for complex state management
1664
+ * Simple wrapper around Intersection Observer API
1665
+ * Makes it easy to detect when elements become visible
725
1666
  */
726
- declare class CombinedContext<T extends Record<string, unknown>> {
727
- private contexts;
728
- constructor(initialValues: T);
729
- get<K extends keyof T>(key: K): Context<T[K]>;
730
- set<K extends keyof T>(key: K, value: T[K]): void;
731
- subscribe<K extends keyof T>(key: K, subscriber: ContextSubscriber<T[K]>): () => void;
732
- reset(): void;
1667
+ declare class VisibilityObserver {
1668
+ private observer;
1669
+ private observedElements;
1670
+ constructor(config: IntersectionConfig);
1671
+ /**
1672
+ * Start observing an element
1673
+ */
1674
+ observe(element: Element): void;
1675
+ /**
1676
+ * Stop observing an element
1677
+ */
1678
+ unobserve(element: Element): void;
1679
+ /**
1680
+ * Disconnect the observer
1681
+ */
1682
+ disconnect(): void;
733
1683
  }
734
1684
  /**
735
- * Create combined context
1685
+ * Helper function to observe when element becomes visible (once)
1686
+ * @param element - Element to observe
1687
+ * @param callback - Callback when element becomes visible
1688
+ * @returns Function to stop observing
736
1689
  */
737
- declare function createCombinedContext<T extends Record<string, unknown>>(initialValues: T): CombinedContext<T>;
1690
+ declare function observeVisibility(element: Element, callback: (entry: IntersectionObserverEntry) => void): () => void;
738
1691
 
739
1692
  /**
740
- * Set current component context for hooks
741
- */
742
- declare function setHookContext(component: Component): void;
743
- /**
744
- * Clear hook context
745
- */
746
- declare function clearHookContext(): void;
747
- /**
748
- * useState hook - manages component state
749
- */
750
- declare function useState<T>(initialValue: T | (() => T)): [T, (newValue: T | ((prev: T) => T)) => void];
751
- /**
752
- * useEffect hook - side effects
753
- */
754
- declare function useEffect(effect: () => void | (() => void), deps?: unknown[]): void;
755
- /**
756
- * useMemo hook - memoize expensive computations
757
- */
758
- declare function useMemo<T>(factory: () => T, deps: unknown[]): T;
759
- /**
760
- * useCallback hook - memoize callbacks
761
- */
762
- declare function useCallback<T extends (...args: unknown[]) => unknown>(callback: T, deps: unknown[]): T;
763
- /**
764
- * useRef hook - persistent value across renders
765
- */
766
- declare function useRef<T>(initialValue: T): {
767
- current: T;
768
- };
769
- /**
770
- * useReducer hook - complex state management
771
- */
772
- declare function useReducer<S, A>(reducer: (state: S, action: A) => S, initialState: S): [S, (action: A) => void];
773
- /**
774
- * useLocalStorage hook - sync state with localStorage
775
- */
776
- declare function useLocalStorage<T>(key: string, initialValue: T): [T, (value: T | ((prev: T) => T)) => void];
777
- /**
778
- * useDebounce hook - debounce value changes
779
- */
780
- declare function useDebounce<T>(value: T, delay: number): T;
781
- /**
782
- * usePrevious hook - get previous value
783
- */
784
- declare function usePrevious<T>(value: T): T | undefined;
785
- /**
786
- * useToggle hook - boolean toggle
787
- */
788
- declare function useToggle(initialValue?: boolean): [boolean, () => void];
789
- /**
790
- * useInterval hook - setInterval with cleanup
791
- */
792
- declare function useInterval(callback: () => void, delay: number | null): void;
793
- /**
794
- * useFetch hook - data fetching
1693
+ * Formats a timestamp into a relative time string with translation
1694
+ * Returns the formatted time and original ISO string as title attribute
1695
+ *
1696
+ * @param timestamp - ISO 8601 timestamp string or Date object
1697
+ * @returns Object with formatted time and original timestamp for title
795
1698
  */
796
- declare function useFetch<T>(url: string, options?: RequestInit): {
797
- data: T | null;
798
- loading: boolean;
799
- error: Error | null;
800
- refetch: () => void;
1699
+ declare function formatRelativeTime(timestamp: string | Date): {
1700
+ formatted: string;
1701
+ originalDate: string;
1702
+ title: string;
801
1703
  };
802
1704
  /**
803
- * useWindowSize hook - track window dimensions
1705
+ * Creates an HTML time element with relative time and title attribute
1706
+ * Usage: place this directly in your component render
1707
+ *
1708
+ * @param timestamp - ISO 8601 timestamp string or Date object
1709
+ * @returns Object with text content and title for use in createElement
804
1710
  */
805
- declare function useWindowSize(): {
806
- width: number;
807
- height: number;
1711
+ declare function getTimeDisplay(timestamp: string | Date): {
1712
+ text: string;
1713
+ title: string;
808
1714
  };
809
1715
  /**
810
- * useEventListener hook - add event listener
811
- */
812
- declare function useEventListener<K extends keyof WindowEventMap>(eventName: K, handler: (event: WindowEventMap[K]) => void, element?: HTMLElement | Window): void;
813
- /**
814
- * Create a functional component with hooks
815
- * Returns a component class that can be instantiated
1716
+ * Format time for display with full date fallback
1717
+ * @param timestamp - ISO 8601 timestamp string or Date object
1718
+ * @returns Formatted string like "2 hours ago"
816
1719
  */
817
- declare function createFunctionalComponent<P extends Record<string, unknown> = Record<string, unknown>>(fn: (props: P) => VNode, displayName?: string): new (props?: P) => Component<P>;
818
-
819
- type UpdateCallback = () => void;
1720
+ declare function formatTimeAgo(timestamp: string | Date): string;
820
1721
  /**
821
- * Update Scheduler
822
- * Batches multiple state changes into a single render
1722
+ * Get the ISO string for title attribute
1723
+ * @param timestamp - ISO 8601 timestamp string or Date object
1724
+ * @returns Localized full date string
823
1725
  */
824
- declare class UpdateScheduler {
825
- private queue;
826
- private isFlushScheduled;
827
- private isFlushing;
828
- /**
829
- * Schedule a component update
830
- */
831
- schedule(callback: UpdateCallback): void;
832
- /**
833
- * Force immediate flush (for urgent updates)
834
- */
835
- flushSync(callback: UpdateCallback): void;
836
- /**
837
- * Flush all pending updates
838
- */
839
- private flush;
840
- /**
841
- * Clear all pending updates
842
- */
843
- clear(): void;
844
- /**
845
- * Get queue size (for debugging)
846
- */
847
- get size(): number;
848
- }
849
- declare const scheduler: UpdateScheduler;
1726
+ declare function getTimeTitle(timestamp: string | Date): string;
850
1727
 
851
- export { type ApiConfig, type AppConfig, type BuildConfig, type ClientConfig, CombinedContext, Component, type ComponentConstructor, Context, type DevToolsConfig, type FormConfig, type FormFieldConfig, type FormFieldOption, type FormSubmitHandler, type FormsConfig, type NavigationGuard, Provider, type Route, type RouteConfig, Router, type RouterConfig, SmartForm, SmartFormComponent, type StateConfig, Store, type StoreMiddleware, type StoreOptions, type StoreSubscriber, StyleManager, type ValidationRule, camelCase, capitalize, clamp, classNames, clearHookContext, client, computed, connect, createCombinedContext, createComputedStore, createContext, createFunctionalComponent, createStore, css, debounce, deepClone, deepMerge, formatDate, isBrowser, isEmpty, kebabCase, parseQuery, pascalCase, router, safeJsonParse, scheduler, setHookContext, sleep, state, stringifyQuery, throttle, truncate, uniqueId, useCallback, useContext, useDebounce, useEffect, useEventListener, useFetch, useInterval, useLocalStorage, useMemo, usePrevious, useReducer, useRef, useState, useToggle, useWindowSize, utils, watch };
1728
+ export { type ApiConfig, type AppConfig, type BuildConfig, type ClassValue, type ClientConfig, CombinedContext, Component, type ComponentConstructor, Context, type ContextSubscriber, type DeepPartial, type DevToolsConfig, Dropdown, type DropdownConfig, type DropdownItemConfig, type EventHandler, type FormConfig, type FormField, type FormFieldConfig, type FormFieldOption, type FormSubmitHandler, type FormsConfig, type I18nConfig, I18nManager, type IntersectionConfig, ItemsLoader, type ItemsLoaderConfig, type LanguageCode, Loader, type LoaderOptions, type LoaderSize, type LoaderVariant, type NavigationGuard, Popup, type PopupButton, type PopupFormOptions, type PopupOptions, type PopupSize, type PopupType, type PopupVariant, Provider, type ProviderProps, type Route, type RouteConfig, Router, type RouterConfig, SmartForm, SmartFormComponent, type StateConfig, Store, type StoreMiddleware, type StoreOptions, type StoreSubscriber, StyleManager, type Tab, type TabPosition, type TabStyle, TabbedView, type TabbedViewOptions, Toast, type ToastMessage, type ToastType, type TranslationSet, type ValidationRule, VisibilityObserver, camelCase, capitalize, clamp, classNames, clearHookContext, client, computed, connect, createCombinedContext, createComputedStore, createContext, createDropdown, createFunctionalComponent, createItemsLoader, createStore, createTabbedView, createTranslator, css, debounce, deepClone, deepMerge, formatDate, formatRelativeTime, formatTimeAgo, getCurrentLanguage, getCurrentPath, getI18n, getPopup, getQueryParam, getQueryParams, getSupportedLanguages, getTimeDisplay, getTimeTitle, getToast, getTranslations, goBack, goForward, hasKey, initPopup, initToast, initializeI18n, isBrowser, isCurrentPath, isCurrentPathPrefix, isEmpty, kebabCase, loadFromUrl, loadLanguage, loadLanguageFile, loadTranslations, mountTabbedView, navigate, navigateWithQuery, observeVisibility, parseQuery, pascalCase, popup, reloadRoute, router, safeJsonParse, scheduler, setHookContext, setLanguage, setLanguageAsync, setupI18n, sleep, state, stringifyQuery, t, tHtml, tLang, throttle, toast, truncate, uniqueId, useCallback, useContext, useDebounce, useEffect, useEventListener, useFetch, useInterval, useLocalStorage, useMemo, usePrevious, useReducer, useRef, useState, useToggle, useWindowSize, utils, watch };