ezfw-core 1.0.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/components/EzBaseComponent.ts +648 -0
- package/components/EzComponent.ts +89 -0
- package/components/EzInput.module.scss +183 -0
- package/components/EzInput.ts +104 -0
- package/components/EzLabel.ts +22 -0
- package/components/EzOutlet.ts +181 -0
- package/components/HtmlWrapper.ts +305 -0
- package/components/avatar/EzAvatar.module.scss +200 -0
- package/components/avatar/EzAvatar.ts +130 -0
- package/components/badge/EzBadge.module.scss +202 -0
- package/components/badge/EzBadge.ts +77 -0
- package/components/button/EzButton.module.scss +402 -0
- package/components/button/EzButton.ts +175 -0
- package/components/button/EzButtonGroup.ts +48 -0
- package/components/card/EzCard.module.scss +71 -0
- package/components/card/EzCard.ts +120 -0
- package/components/chart/EzBarChart.ts +47 -0
- package/components/chart/EzChart.module.scss +14 -0
- package/components/chart/EzChart.ts +279 -0
- package/components/chart/EzDoughnutChart.ts +47 -0
- package/components/chart/EzLineChart.ts +53 -0
- package/components/checkbox/EzCheckbox.module.scss +145 -0
- package/components/checkbox/EzCheckbox.ts +115 -0
- package/components/dataview/EzDataView.module.scss +115 -0
- package/components/dataview/EzDataView.ts +355 -0
- package/components/dataview/modes/EzDataViewCards.ts +322 -0
- package/components/dataview/modes/EzDataViewGrid.ts +76 -0
- package/components/datepicker/EzDatePicker.module.scss +348 -0
- package/components/datepicker/EzDatePicker.ts +519 -0
- package/components/dialog/EzDialog.module.scss +180 -0
- package/components/dropdown/EzDropdown.module.scss +107 -0
- package/components/dropdown/EzDropdown.ts +235 -0
- package/components/feed/EzActivityFeed.module.scss +90 -0
- package/components/feed/EzActivityFeed.ts +78 -0
- package/components/form/EzForm.ts +364 -0
- package/components/form/EzValidators.test.js +421 -0
- package/components/form/EzValidators.ts +202 -0
- package/components/grid/EzGrid.scss +88 -0
- package/components/grid/EzGrid.ts +1085 -0
- package/components/grid/EzGridContainer.ts +104 -0
- package/components/grid/body/EzGridBody.scss +283 -0
- package/components/grid/body/EzGridBody.ts +549 -0
- package/components/grid/body/EzGridCell.ts +211 -0
- package/components/grid/body/EzGridRow.ts +196 -0
- package/components/grid/filter/EzGridFilters.scss +78 -0
- package/components/grid/filter/EzGridFilters.ts +285 -0
- package/components/grid/footer/EzGridFooter.scss +136 -0
- package/components/grid/footer/EzGridFooter.ts +448 -0
- package/components/grid/header/EzGridHeader.scss +199 -0
- package/components/grid/header/EzGridHeader.ts +430 -0
- package/components/grid/query/EzGridQuery.ts +81 -0
- package/components/grid/state/EzGridColumns.ts +155 -0
- package/components/grid/state/EzGridController.ts +470 -0
- package/components/grid/state/EzGridLifecycle.ts +136 -0
- package/components/grid/state/EzGridNormalizers.test.js +273 -0
- package/components/grid/state/EzGridNormalizers.ts +162 -0
- package/components/grid/state/EzGridParts.ts +233 -0
- package/components/grid/state/EzGridPersistence.ts +140 -0
- package/components/grid/state/EzGridRemote.test.js +573 -0
- package/components/grid/state/EzGridRemote.ts +335 -0
- package/components/grid/state/EzGridSelection.ts +231 -0
- package/components/grid/state/EzGridSort.ts +286 -0
- package/components/grid/title/EzGridActionBar.ts +98 -0
- package/components/grid/title/EzGridTitle.ts +114 -0
- package/components/grid/title/EzGridTitleBar.scss +65 -0
- package/components/grid/title/EzGridTitleBar.ts +87 -0
- package/components/grid/types.ts +607 -0
- package/components/panel/EzPanel.module.scss +133 -0
- package/components/panel/EzPanel.ts +147 -0
- package/components/radio/EzRadio.module.scss +190 -0
- package/components/radio/EzRadio.ts +149 -0
- package/components/select/EzSelect.module.scss +153 -0
- package/components/select/EzSelect.ts +238 -0
- package/components/skeleton/EzSkeleton.module.scss +95 -0
- package/components/skeleton/EzSkeleton.ts +70 -0
- package/components/store/EzStore.ts +344 -0
- package/components/switch/EzSwitch.module.scss +164 -0
- package/components/switch/EzSwitch.ts +117 -0
- package/components/tabs/EzTabPanel.module.scss +181 -0
- package/components/tabs/EzTabPanel.ts +402 -0
- package/components/textarea/EzTextarea.module.scss +131 -0
- package/components/textarea/EzTextarea.ts +161 -0
- package/components/timepicker/EzTimePicker.module.scss +282 -0
- package/components/timepicker/EzTimePicker.ts +540 -0
- package/components/toast/EzToast.module.scss +291 -0
- package/components/tooltip/EzTooltip.module.scss +124 -0
- package/components/tooltip/EzTooltip.ts +153 -0
- package/core/EzComponentTypes.ts +693 -0
- package/core/EzError.ts +63 -0
- package/core/EzModel.ts +268 -0
- package/core/EzTypes.ts +328 -0
- package/core/eventBus.ts +284 -0
- package/core/ez.ts +617 -0
- package/core/loader.ts +725 -0
- package/core/renderer.ts +1010 -0
- package/core/router.ts +490 -0
- package/core/services.ts +124 -0
- package/core/state.ts +142 -0
- package/core/utils.ts +81 -0
- package/package.json +51 -0
- package/services/RouteUI.js +17 -0
- package/services/crypto.js +64 -0
- package/services/dialog.js +222 -0
- package/services/fetchApi.js +63 -0
- package/services/firebase.js +30 -0
- package/services/toast.js +214 -0
- package/template/doc/EzDocs.js +15 -0
- package/template/doc/EzDocs.module.scss +627 -0
- package/template/doc/EzDocsController.js +164 -0
- package/template/doc/data/activityfeed/EzActivityFeedDoc.js +42 -0
- package/template/doc/data/avatar/EzAvatarDoc.js +71 -0
- package/template/doc/data/badge/EzBadgeDoc.js +92 -0
- package/template/doc/data/button/EzButtonDoc.js +77 -0
- package/template/doc/data/buttongroup/EzButtonGroupDoc.js +102 -0
- package/template/doc/data/card/EzCardDoc.js +39 -0
- package/template/doc/data/chart/EzChartDoc.js +60 -0
- package/template/doc/data/checkbox/EzCheckboxDoc.js +67 -0
- package/template/doc/data/component/EzComponentDoc.js +34 -0
- package/template/doc/data/cssmodules/CSSModulesDoc.js +70 -0
- package/template/doc/data/datepicker/EzDatePickerDoc.js +126 -0
- package/template/doc/data/dialog/EzDialogDoc.js +217 -0
- package/template/doc/data/dropdown/EzDropdownDoc.js +178 -0
- package/template/doc/data/form/EzFormDoc.js +90 -0
- package/template/doc/data/grid/EzGridDoc.js +99 -0
- package/template/doc/data/input/EzInputDoc.js +92 -0
- package/template/doc/data/label/EzLabelDoc.js +40 -0
- package/template/doc/data/model/EzModelDoc.js +53 -0
- package/template/doc/data/outlet/EzOutletDoc.js +63 -0
- package/template/doc/data/panel/EzPanelDoc.js +214 -0
- package/template/doc/data/radio/EzRadioDoc.js +174 -0
- package/template/doc/data/router/EzRouterDoc.js +75 -0
- package/template/doc/data/select/EzSelectDoc.js +37 -0
- package/template/doc/data/skeleton/EzSkeletonDoc.js +149 -0
- package/template/doc/data/switch/EzSwitchDoc.js +82 -0
- package/template/doc/data/tabpanel/EzTabPanelDoc.js +44 -0
- package/template/doc/data/textarea/EzTextareaDoc.js +131 -0
- package/template/doc/data/timepicker/EzTimePickerDoc.js +107 -0
- package/template/doc/data/tooltip/EzTooltipDoc.js +193 -0
- package/template/doc/data/validators/EzValidatorsDoc.js +37 -0
- package/template/doc/sidebar/EzDocsSidebar.js +32 -0
- package/template/doc/sidebar/category/EzDocsCategory.js +33 -0
- package/template/doc/sidebar/item/EzDocsComponentItem.js +24 -0
- package/template/doc/viewer/EzDocsViewer.js +18 -0
- package/template/doc/viewer/codepanel/EzDocsCodePanel.js +51 -0
- package/template/doc/viewer/content/EzDocsContent.js +315 -0
- package/template/doc/viewer/header/EzDocsViewerHeader.js +46 -0
- package/template/doc/viewer/showcase/EzDocsShowcase.js +59 -0
- package/template/doc/viewer/showcase/EzDocsShowcaseSection.js +25 -0
- package/template/doc/viewer/showcase/EzDocsVariantItem.js +29 -0
- package/template/doc/welcome/EzDocsWelcome.js +48 -0
- package/themes/ez-theme.scss +179 -0
- package/themes/nature-fresh.scss +169 -0
- package/types/global.d.ts +21 -0
- package/utils/cssModules.js +81 -0
package/core/ez.ts
ADDED
|
@@ -0,0 +1,617 @@
|
|
|
1
|
+
import { EzError } from './EzError.js';
|
|
2
|
+
import { EzRouter, RouteDefinition, MiddlewareFunction, RouteInfo } from './router.js';
|
|
3
|
+
import { EzLoader } from './loader.js';
|
|
4
|
+
import { EzRenderer, ComponentConfig } from './renderer.js';
|
|
5
|
+
import { EzState, ControllerDefinition, GridControllerDefinition, GridBehaviorDefinition } from './state.js';
|
|
6
|
+
import { EzModel, ModelDefinition, Model } from './EzModel.js';
|
|
7
|
+
import { EzServices } from './services.js';
|
|
8
|
+
import { EzEventBus, EventHandler } from './eventBus.js';
|
|
9
|
+
import * as EzGridQuery from '../components/grid/query/EzGridQuery.js';
|
|
10
|
+
import moment from 'moment';
|
|
11
|
+
import { createEzStore } from '../components/store/EzStore.js';
|
|
12
|
+
import { EzUtils, format, capitalize, capitalizeWords, truncate, pluralize, FormatType, FormatOptions } from './utils.js';
|
|
13
|
+
import { ComponentDefinition, ControllerDef } from './EzTypes.js';
|
|
14
|
+
|
|
15
|
+
declare global {
|
|
16
|
+
interface Window {
|
|
17
|
+
ez: EzFramework;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface StoreEntry {
|
|
22
|
+
config: Record<string, unknown>;
|
|
23
|
+
instance: unknown | null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface RegistryMeta {
|
|
27
|
+
definedIn?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface EzContext {
|
|
31
|
+
route: string | null;
|
|
32
|
+
view: string | null;
|
|
33
|
+
controller: string | null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface EzFramework {
|
|
37
|
+
_registry: Record<string, unknown>;
|
|
38
|
+
_controllers: Record<string, ControllerDefinition>;
|
|
39
|
+
_models: Record<string, Model>;
|
|
40
|
+
_stores: Record<string, StoreEntry>;
|
|
41
|
+
_refs: Record<string, unknown>;
|
|
42
|
+
_registryMeta: Record<string, RegistryMeta>;
|
|
43
|
+
_context: EzContext;
|
|
44
|
+
_gridControllerDefinitions: Record<string, GridControllerDefinition>;
|
|
45
|
+
_gridStateRegistry: Record<string, unknown>;
|
|
46
|
+
_gridBehaviorDefinitions: Record<string, GridBehaviorDefinition>;
|
|
47
|
+
_gridBehaviors: Record<string, GridBehaviorDefinition>;
|
|
48
|
+
_styles: Record<string, () => Promise<unknown>>;
|
|
49
|
+
_stylesCache: Record<string, Record<string, string>>;
|
|
50
|
+
_theme: string;
|
|
51
|
+
_availableThemes: string[];
|
|
52
|
+
_router: EzRouter | null;
|
|
53
|
+
_loader: EzLoader | null;
|
|
54
|
+
_renderer: EzRenderer | null;
|
|
55
|
+
_state: EzState | null;
|
|
56
|
+
_model: EzModel | null;
|
|
57
|
+
_services: EzServices | null;
|
|
58
|
+
_eventBus: EzEventBus | null;
|
|
59
|
+
grid?: { query: typeof EzGridQuery };
|
|
60
|
+
moment: typeof moment;
|
|
61
|
+
|
|
62
|
+
_initModules(): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Define a component in the Ez framework
|
|
65
|
+
* @param name - Unique component name (used as eztype)
|
|
66
|
+
* @param definition - Component configuration:
|
|
67
|
+
* ```
|
|
68
|
+
* {
|
|
69
|
+
* eztype?: string // Base component to extend
|
|
70
|
+
* css?: string // CSS module name (auto-loads .module.scss)
|
|
71
|
+
* controller?: string // Controller name for state
|
|
72
|
+
* cls?: string | string[] // CSS classes
|
|
73
|
+
* layout?: 'hbox'|'vbox' // Flex direction
|
|
74
|
+
* style?: object // Inline styles
|
|
75
|
+
* items?: ItemConfig[] // Static children
|
|
76
|
+
* template?: (props) => ItemConfig // Dynamic render function
|
|
77
|
+
* bind?: BindConfig // Data bindings
|
|
78
|
+
* itemRender?: (item, index) => ItemConfig // List item renderer
|
|
79
|
+
* onLoad?: string // Async load method (controller)
|
|
80
|
+
* fallback?: ItemConfig // Loading placeholder
|
|
81
|
+
* ref?: string // Reference name for ez._refs
|
|
82
|
+
* }
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
define(name: string, definition: ComponentDefinition): void;
|
|
86
|
+
/**
|
|
87
|
+
* Define a controller for state management
|
|
88
|
+
* @param name - Controller name (referenced by component's controller property)
|
|
89
|
+
* @param definition - Controller configuration:
|
|
90
|
+
* ```
|
|
91
|
+
* {
|
|
92
|
+
* state?: object // Reactive state (auto-wrapped with deepSignal)
|
|
93
|
+
* onInit?: () => void // Called when controller initializes
|
|
94
|
+
* onRouteChange?: (params) => void // Called on route changes
|
|
95
|
+
* onDestroy?: () => void // Called when controller is destroyed
|
|
96
|
+
* [methodName]: Function // Custom methods (access state via this.state)
|
|
97
|
+
* }
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
defineController(name: string, definition: ControllerDefinition): void;
|
|
101
|
+
/**
|
|
102
|
+
* Define a grid-specific controller for EzGrid lifecycle hooks
|
|
103
|
+
* @param name - Grid controller name (referenced by grid's gridController property)
|
|
104
|
+
* @param definition - Grid controller configuration:
|
|
105
|
+
* ```
|
|
106
|
+
* {
|
|
107
|
+
* onInit?: () => void // Called when grid initializes
|
|
108
|
+
* beforeDataRender?: () => void // Called before rendering data
|
|
109
|
+
* afterDataRender?: () => void // Called after rendering data
|
|
110
|
+
* onSelectionChange?: (rows) => void // Called when selection changes
|
|
111
|
+
* onRowClick?: (row, e) => void // Called on row click
|
|
112
|
+
* onCellClick?: (cell, row, e) => void // Called on cell click
|
|
113
|
+
* }
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
defineGridController(name: string, definition: GridControllerDefinition): void;
|
|
117
|
+
/**
|
|
118
|
+
* Define a data model for type coercion and validation
|
|
119
|
+
* @param name - Model name (referenced by component's model property)
|
|
120
|
+
* @param definition - Model configuration:
|
|
121
|
+
* ```
|
|
122
|
+
* {
|
|
123
|
+
* fields: [
|
|
124
|
+
* { name: 'id', type: 'int', primaryKey: true },
|
|
125
|
+
* { name: 'email', type: 'string' },
|
|
126
|
+
* { name: 'age', type: 'int', default: 0 },
|
|
127
|
+
* { name: 'active', type: 'bool', nullable: true },
|
|
128
|
+
* { name: 'fullName', compute: (r) => r.first + ' ' + r.last }
|
|
129
|
+
* ]
|
|
130
|
+
* }
|
|
131
|
+
* ```
|
|
132
|
+
* Types: 'int' | 'float' | 'string' | 'bool' | 'date' | 'array' | 'object'
|
|
133
|
+
*/
|
|
134
|
+
defineModel(name: string, definition: ModelDefinition): void;
|
|
135
|
+
getModel(name: string): Model | null;
|
|
136
|
+
getModelSync(name: string): Model;
|
|
137
|
+
/**
|
|
138
|
+
* Define a global store for shared state across components
|
|
139
|
+
* @param name - Store name
|
|
140
|
+
* @param config - Store configuration:
|
|
141
|
+
* ```
|
|
142
|
+
* {
|
|
143
|
+
* state: { ... }, // Initial state
|
|
144
|
+
* getters: { ... }, // Computed values
|
|
145
|
+
* actions: { ... } // Methods to modify state
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
defineStore(name: string, config: Record<string, unknown>): void;
|
|
150
|
+
getStore(name: string): unknown;
|
|
151
|
+
registerComponent(eztype: string, cls: unknown): void;
|
|
152
|
+
installModules(mods: Record<string, () => Promise<unknown>>): void;
|
|
153
|
+
installStyles(styles: Record<string, () => Promise<unknown>>): void;
|
|
154
|
+
hasStyles(name: string): boolean;
|
|
155
|
+
resolveStyles(name: string): Promise<Record<string, string> | null>;
|
|
156
|
+
get(name: string): unknown;
|
|
157
|
+
getController(name: string): Promise<ControllerDefinition> | ControllerDefinition;
|
|
158
|
+
getControllerSync(name: string): ControllerDefinition;
|
|
159
|
+
_createElement(config: ComponentConfig, controllerName?: string | null, inheritedState?: unknown): Promise<Node>;
|
|
160
|
+
_createChildElements(items: ComponentConfig[], controllerName: string | null, inheritedState: unknown, parentCss?: string | null): Promise<Node[]>;
|
|
161
|
+
routes(routeDefs: RouteDefinition[]): void;
|
|
162
|
+
go(path: string): void;
|
|
163
|
+
navigate(viewName: string, route?: RouteInfo | null): Promise<void>;
|
|
164
|
+
installPopStateListener(): void;
|
|
165
|
+
prefetch(path: string): Promise<void>;
|
|
166
|
+
enableLinkPrefetch(): void;
|
|
167
|
+
beforeEach(fn: MiddlewareFunction): () => void;
|
|
168
|
+
afterEach(fn: MiddlewareFunction): () => void;
|
|
169
|
+
onNavigationError(fn: (error: Error, context: unknown) => void): () => void;
|
|
170
|
+
setNetworkAware(enabled?: boolean): void;
|
|
171
|
+
getNetworkInfo(): { strategy: string; online: boolean; effectiveType: string | null; saveData: boolean };
|
|
172
|
+
addPreloadHint(eztype: string): boolean;
|
|
173
|
+
addPreloadHintsForRoute(routePath: string): Promise<number>;
|
|
174
|
+
addPreloadHintsForAdjacentRoutes(): Promise<number>;
|
|
175
|
+
_onLocationChange(): Promise<void>;
|
|
176
|
+
on(event: string, fn: EventHandler['fn'], context?: object | null): () => boolean;
|
|
177
|
+
once(event: string, fn: EventHandler['fn'], context?: object | null): () => boolean;
|
|
178
|
+
off(event: string, fn?: EventHandler['fn']): boolean;
|
|
179
|
+
emit(event: string, data?: unknown): boolean;
|
|
180
|
+
emitAsync(event: string, data?: unknown): Promise<boolean>;
|
|
181
|
+
eventNamespace(namespace: string): unknown;
|
|
182
|
+
/**
|
|
183
|
+
* Define a reusable grid behavior (plugin pattern)
|
|
184
|
+
* @param name - Behavior name (referenced by grid's behaviors array)
|
|
185
|
+
* @param definition - Behavior configuration:
|
|
186
|
+
* ```
|
|
187
|
+
* {
|
|
188
|
+
* onInit?: (grid) => void // Called when behavior attaches
|
|
189
|
+
* onDestroy?: (grid) => void // Called when behavior detaches
|
|
190
|
+
* onDataChange?: (data, grid) => void // Called when data changes
|
|
191
|
+
* [hookName]: Function // Custom hooks
|
|
192
|
+
* }
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
defineGridBehavior(name: string, definition: GridBehaviorDefinition): void;
|
|
196
|
+
getGridBehavior(name: string): Promise<GridBehaviorDefinition | null>;
|
|
197
|
+
getDeepValue(obj: Record<string, unknown>, pathArray: string[]): unknown;
|
|
198
|
+
setDeepValue(obj: Record<string, unknown>, props: string[], value: unknown): void;
|
|
199
|
+
handleFrameworkError(error: Error | EzError): void;
|
|
200
|
+
_api: unknown;
|
|
201
|
+
_fb: unknown;
|
|
202
|
+
crypto: unknown;
|
|
203
|
+
routeUI: unknown;
|
|
204
|
+
dialog: unknown;
|
|
205
|
+
toast: unknown;
|
|
206
|
+
setTheme(themeName: string): void;
|
|
207
|
+
getTheme(): string;
|
|
208
|
+
getAvailableThemes(): string[];
|
|
209
|
+
toggleDarkMode(): string;
|
|
210
|
+
isDarkMode(): boolean;
|
|
211
|
+
_initTheme(): void;
|
|
212
|
+
format(value: unknown, type?: FormatType, options?: FormatOptions): string;
|
|
213
|
+
capitalize(str: string): string;
|
|
214
|
+
capitalizeWords(str: string): string;
|
|
215
|
+
truncate(str: string, length: number, suffix?: string): string;
|
|
216
|
+
pluralize(count: number, singular: string, plural?: string): string;
|
|
217
|
+
utils: typeof EzUtils;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const ez: EzFramework = {
|
|
221
|
+
_registry: {},
|
|
222
|
+
_controllers: {},
|
|
223
|
+
_models: {},
|
|
224
|
+
_stores: {},
|
|
225
|
+
_refs: {},
|
|
226
|
+
_registryMeta: {},
|
|
227
|
+
_context: {
|
|
228
|
+
route: null,
|
|
229
|
+
view: null,
|
|
230
|
+
controller: null
|
|
231
|
+
},
|
|
232
|
+
_gridControllerDefinitions: {},
|
|
233
|
+
_gridStateRegistry: {},
|
|
234
|
+
_gridBehaviorDefinitions: {},
|
|
235
|
+
_gridBehaviors: {},
|
|
236
|
+
_styles: {},
|
|
237
|
+
_stylesCache: {},
|
|
238
|
+
_theme: 'ocean-depths',
|
|
239
|
+
_availableThemes: [
|
|
240
|
+
'ocean-depths',
|
|
241
|
+
'ocean-depths-dark',
|
|
242
|
+
'nature-fresh',
|
|
243
|
+
'nature-fresh-dark'
|
|
244
|
+
],
|
|
245
|
+
_router: null,
|
|
246
|
+
_loader: null,
|
|
247
|
+
_renderer: null,
|
|
248
|
+
_state: null,
|
|
249
|
+
_model: null,
|
|
250
|
+
_services: null,
|
|
251
|
+
_eventBus: null,
|
|
252
|
+
moment: moment,
|
|
253
|
+
|
|
254
|
+
async _initModules(): Promise<void> {
|
|
255
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
256
|
+
const ezInstance = this as any;
|
|
257
|
+
this._loader = new EzLoader(ezInstance);
|
|
258
|
+
this._router = new EzRouter(ezInstance);
|
|
259
|
+
this._renderer = new EzRenderer(ezInstance);
|
|
260
|
+
this._state = new EzState(ezInstance);
|
|
261
|
+
this._model = new EzModel(ezInstance);
|
|
262
|
+
this._services = new EzServices(ezInstance);
|
|
263
|
+
this._eventBus = new EzEventBus();
|
|
264
|
+
await this._services.init();
|
|
265
|
+
},
|
|
266
|
+
|
|
267
|
+
define(name: string, definition: ComponentDefinition): void {
|
|
268
|
+
if (this._registry[name]) {
|
|
269
|
+
throw new EzError({
|
|
270
|
+
code: 'EZ_DEFINE_DUPLICATE',
|
|
271
|
+
message: `Component "${name}" is already defined`,
|
|
272
|
+
details: {
|
|
273
|
+
eztype: name,
|
|
274
|
+
definedIn: this._registryMeta[name]?.definedIn,
|
|
275
|
+
redefinedIn: this._loader?.getCurrentModulePath()
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
this._registry[name] = definition;
|
|
281
|
+
|
|
282
|
+
this._registryMeta[name] = {
|
|
283
|
+
definedIn: this._loader?.getCurrentModulePath() || undefined
|
|
284
|
+
};
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
defineController(name: string, definition: ControllerDefinition): void {
|
|
288
|
+
this._state!.defineController(name, definition);
|
|
289
|
+
},
|
|
290
|
+
|
|
291
|
+
defineGridController(name: string, definition: GridControllerDefinition): void {
|
|
292
|
+
this._state!.defineGridController(name, definition);
|
|
293
|
+
},
|
|
294
|
+
|
|
295
|
+
defineModel(name: string, definition: ModelDefinition): void {
|
|
296
|
+
this._model!.defineModel(name, definition);
|
|
297
|
+
},
|
|
298
|
+
|
|
299
|
+
getModel(name: string): Model | null {
|
|
300
|
+
return this._model!.getModel(name);
|
|
301
|
+
},
|
|
302
|
+
|
|
303
|
+
getModelSync(name: string): Model {
|
|
304
|
+
return this._model!.getModelSync(name);
|
|
305
|
+
},
|
|
306
|
+
|
|
307
|
+
defineStore(name: string, config: Record<string, unknown>): void {
|
|
308
|
+
if (this._stores[name]) {
|
|
309
|
+
console.warn(`[Ez] Store "${name}" already defined, overwriting.`);
|
|
310
|
+
}
|
|
311
|
+
this._stores[name] = { config, instance: null };
|
|
312
|
+
},
|
|
313
|
+
|
|
314
|
+
getStore(name: string): unknown {
|
|
315
|
+
const entry = this._stores[name];
|
|
316
|
+
if (!entry) {
|
|
317
|
+
console.warn(`[Ez] Store "${name}" not found.`);
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
if (!entry.instance) {
|
|
321
|
+
entry.instance = createEzStore(entry.config as Parameters<typeof createEzStore>[0]);
|
|
322
|
+
}
|
|
323
|
+
return entry.instance;
|
|
324
|
+
},
|
|
325
|
+
|
|
326
|
+
registerComponent(eztype: string, cls: unknown): void {
|
|
327
|
+
this._registry[eztype] = cls;
|
|
328
|
+
},
|
|
329
|
+
|
|
330
|
+
installModules(mods: Record<string, () => Promise<unknown>>): void {
|
|
331
|
+
this._loader!.installModules(mods);
|
|
332
|
+
},
|
|
333
|
+
|
|
334
|
+
installStyles(styles: Record<string, () => Promise<unknown>>): void {
|
|
335
|
+
this._styles = styles;
|
|
336
|
+
},
|
|
337
|
+
|
|
338
|
+
hasStyles(name: string): boolean {
|
|
339
|
+
if (!name || !this._styles) return false;
|
|
340
|
+
const lowerName = name.toLowerCase();
|
|
341
|
+
return Object.keys(this._styles).some(p => {
|
|
342
|
+
const fileName = p.split('/').pop()?.toLowerCase();
|
|
343
|
+
return fileName === `${lowerName}.module.scss`;
|
|
344
|
+
});
|
|
345
|
+
},
|
|
346
|
+
|
|
347
|
+
async resolveStyles(name: string): Promise<Record<string, string> | null> {
|
|
348
|
+
if (this._stylesCache[name]) {
|
|
349
|
+
return this._stylesCache[name];
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const lowerName = name.toLowerCase();
|
|
353
|
+
const path = Object.keys(this._styles).find(p => {
|
|
354
|
+
const fileName = p.split('/').pop()?.toLowerCase();
|
|
355
|
+
return fileName === `${lowerName}.module.scss`;
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
if (!path) {
|
|
359
|
+
const env = (import.meta as unknown as { env?: { DEV?: boolean } }).env;
|
|
360
|
+
if (env?.DEV) {
|
|
361
|
+
console.warn(`[Ez] CSS module "${name}" not found`);
|
|
362
|
+
}
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const module = await this._styles[path]();
|
|
367
|
+
const styles = (module as { default?: Record<string, string> }).default || module;
|
|
368
|
+
|
|
369
|
+
this._stylesCache[name] = styles as Record<string, string>;
|
|
370
|
+
|
|
371
|
+
return styles as Record<string, string>;
|
|
372
|
+
},
|
|
373
|
+
|
|
374
|
+
get(name: string): unknown {
|
|
375
|
+
return this._registry[name];
|
|
376
|
+
},
|
|
377
|
+
|
|
378
|
+
getController(name: string): Promise<ControllerDefinition> | ControllerDefinition {
|
|
379
|
+
return this._state!.getController(name);
|
|
380
|
+
},
|
|
381
|
+
|
|
382
|
+
getControllerSync(name: string): ControllerDefinition {
|
|
383
|
+
return this._state!.getControllerSync(name);
|
|
384
|
+
},
|
|
385
|
+
|
|
386
|
+
async _createElement(config: ComponentConfig, controllerName: string | null = null, inheritedState: unknown = null): Promise<Node> {
|
|
387
|
+
return this._renderer!.createElement(config, controllerName, inheritedState);
|
|
388
|
+
},
|
|
389
|
+
|
|
390
|
+
async _createChildElements(items: ComponentConfig[], controllerName: string | null, inheritedState: unknown, parentCss: string | null = null): Promise<Node[]> {
|
|
391
|
+
return this._renderer!.createChildElements(items, controllerName || '', inheritedState, parentCss);
|
|
392
|
+
},
|
|
393
|
+
|
|
394
|
+
routes(routeDefs: RouteDefinition[]): void {
|
|
395
|
+
this._router!.routes(routeDefs);
|
|
396
|
+
},
|
|
397
|
+
|
|
398
|
+
go(path: string): void {
|
|
399
|
+
this._router!.go(path);
|
|
400
|
+
},
|
|
401
|
+
|
|
402
|
+
async navigate(viewName: string, route: RouteInfo | null = null): Promise<void> {
|
|
403
|
+
return this._router!.navigate(viewName, route);
|
|
404
|
+
},
|
|
405
|
+
|
|
406
|
+
installPopStateListener(): void {
|
|
407
|
+
this._router!.installPopStateListener();
|
|
408
|
+
},
|
|
409
|
+
|
|
410
|
+
async prefetch(path: string): Promise<void> {
|
|
411
|
+
return this._router!.prefetch(path);
|
|
412
|
+
},
|
|
413
|
+
|
|
414
|
+
enableLinkPrefetch(): void {
|
|
415
|
+
this._router!.enableLinkPrefetch();
|
|
416
|
+
},
|
|
417
|
+
|
|
418
|
+
beforeEach(fn: MiddlewareFunction): () => void {
|
|
419
|
+
return this._router!.beforeEach(fn);
|
|
420
|
+
},
|
|
421
|
+
|
|
422
|
+
afterEach(fn: MiddlewareFunction): () => void {
|
|
423
|
+
return this._router!.afterEach(fn);
|
|
424
|
+
},
|
|
425
|
+
|
|
426
|
+
onNavigationError(fn: (error: Error, context: unknown) => void): () => void {
|
|
427
|
+
return this._router!.onError(fn as Parameters<EzRouter['onError']>[0]);
|
|
428
|
+
},
|
|
429
|
+
|
|
430
|
+
setNetworkAware(enabled: boolean = true): void {
|
|
431
|
+
this._loader!.setNetworkAware(enabled);
|
|
432
|
+
},
|
|
433
|
+
|
|
434
|
+
getNetworkInfo(): { strategy: string; online: boolean; effectiveType: string | null; saveData: boolean } {
|
|
435
|
+
return this._loader!.getNetworkInfo();
|
|
436
|
+
},
|
|
437
|
+
|
|
438
|
+
addPreloadHint(eztype: string): boolean {
|
|
439
|
+
return this._loader!.addPreloadHint(eztype);
|
|
440
|
+
},
|
|
441
|
+
|
|
442
|
+
async addPreloadHintsForRoute(routePath: string): Promise<number> {
|
|
443
|
+
return this._loader!.addPreloadHintsForRoute(routePath);
|
|
444
|
+
},
|
|
445
|
+
|
|
446
|
+
async addPreloadHintsForAdjacentRoutes(): Promise<number> {
|
|
447
|
+
return this._loader!.addPreloadHintsForAdjacentRoutes();
|
|
448
|
+
},
|
|
449
|
+
|
|
450
|
+
async _onLocationChange(): Promise<void> {
|
|
451
|
+
return (this._router as unknown as { _onLocationChange(): Promise<void> })._onLocationChange();
|
|
452
|
+
},
|
|
453
|
+
|
|
454
|
+
on(event: string, fn: EventHandler['fn'], context?: object | null): () => boolean {
|
|
455
|
+
return this._eventBus!.on(event, fn, context);
|
|
456
|
+
},
|
|
457
|
+
|
|
458
|
+
once(event: string, fn: EventHandler['fn'], context?: object | null): () => boolean {
|
|
459
|
+
return this._eventBus!.once(event, fn, context);
|
|
460
|
+
},
|
|
461
|
+
|
|
462
|
+
off(event: string, fn?: EventHandler['fn']): boolean {
|
|
463
|
+
return this._eventBus!.off(event, fn);
|
|
464
|
+
},
|
|
465
|
+
|
|
466
|
+
emit(event: string, data?: unknown): boolean {
|
|
467
|
+
return this._eventBus!.emit(event, data);
|
|
468
|
+
},
|
|
469
|
+
|
|
470
|
+
async emitAsync(event: string, data?: unknown): Promise<boolean> {
|
|
471
|
+
return this._eventBus!.emitAsync(event, data);
|
|
472
|
+
},
|
|
473
|
+
|
|
474
|
+
eventNamespace(namespace: string): unknown {
|
|
475
|
+
return this._eventBus!.namespace(namespace);
|
|
476
|
+
},
|
|
477
|
+
|
|
478
|
+
defineGridBehavior(name: string, definition: GridBehaviorDefinition): void {
|
|
479
|
+
this._state!.defineGridBehavior(name, definition);
|
|
480
|
+
},
|
|
481
|
+
|
|
482
|
+
async getGridBehavior(name: string): Promise<GridBehaviorDefinition | null> {
|
|
483
|
+
return this._state!.getGridBehavior(name);
|
|
484
|
+
},
|
|
485
|
+
|
|
486
|
+
getDeepValue(obj: Record<string, unknown>, pathArray: string[]): unknown {
|
|
487
|
+
return this._state!.getDeepValue(obj, pathArray);
|
|
488
|
+
},
|
|
489
|
+
|
|
490
|
+
setDeepValue(obj: Record<string, unknown>, props: string[], value: unknown): void {
|
|
491
|
+
this._state!.setDeepValue(obj, props, value);
|
|
492
|
+
},
|
|
493
|
+
|
|
494
|
+
handleFrameworkError(error: Error | EzError): void {
|
|
495
|
+
if (error instanceof EzError) {
|
|
496
|
+
console.group(`EZ Framework Error — ${error.code}`);
|
|
497
|
+
console.error(error.message);
|
|
498
|
+
console.info('Source:', error.source);
|
|
499
|
+
console.info('Route:', error.route);
|
|
500
|
+
console.info('View:', error.view);
|
|
501
|
+
if (error.details) {
|
|
502
|
+
console.info('Details:', error.details);
|
|
503
|
+
}
|
|
504
|
+
if (error.cause) {
|
|
505
|
+
console.error('Cause:', error.cause);
|
|
506
|
+
}
|
|
507
|
+
console.groupEnd();
|
|
508
|
+
} else {
|
|
509
|
+
console.error('[EZ] Unhandled error:', error);
|
|
510
|
+
}
|
|
511
|
+
},
|
|
512
|
+
|
|
513
|
+
get _api(): unknown {
|
|
514
|
+
return this._services?.api;
|
|
515
|
+
},
|
|
516
|
+
|
|
517
|
+
get _fb(): unknown {
|
|
518
|
+
return this._services?.firebase;
|
|
519
|
+
},
|
|
520
|
+
|
|
521
|
+
get crypto(): unknown {
|
|
522
|
+
return this._services?.crypto;
|
|
523
|
+
},
|
|
524
|
+
|
|
525
|
+
get routeUI(): unknown {
|
|
526
|
+
return this._services?.routeUI;
|
|
527
|
+
},
|
|
528
|
+
|
|
529
|
+
get dialog(): unknown {
|
|
530
|
+
return this._services?.dialog;
|
|
531
|
+
},
|
|
532
|
+
|
|
533
|
+
get toast(): unknown {
|
|
534
|
+
return this._services?.toast;
|
|
535
|
+
},
|
|
536
|
+
|
|
537
|
+
setTheme(themeName: string): void {
|
|
538
|
+
if (!this._availableThemes.includes(themeName)) {
|
|
539
|
+
console.warn(`[ez] Theme "${themeName}" not found. Available: ${this._availableThemes.join(', ')}`);
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
this._theme = themeName;
|
|
544
|
+
document.documentElement.setAttribute('data-ez-theme', themeName);
|
|
545
|
+
|
|
546
|
+
try {
|
|
547
|
+
localStorage.setItem('ez-theme', themeName);
|
|
548
|
+
} catch {
|
|
549
|
+
// localStorage not available
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
this._eventBus?.emit('theme:change', { theme: themeName });
|
|
553
|
+
},
|
|
554
|
+
|
|
555
|
+
getTheme(): string {
|
|
556
|
+
return this._theme;
|
|
557
|
+
},
|
|
558
|
+
|
|
559
|
+
getAvailableThemes(): string[] {
|
|
560
|
+
return [...this._availableThemes];
|
|
561
|
+
},
|
|
562
|
+
|
|
563
|
+
toggleDarkMode(): string {
|
|
564
|
+
const current = this._theme;
|
|
565
|
+
let newTheme: string;
|
|
566
|
+
|
|
567
|
+
if (current.endsWith('-dark')) {
|
|
568
|
+
newTheme = current.replace('-dark', '');
|
|
569
|
+
} else {
|
|
570
|
+
newTheme = current + '-dark';
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
if (this._availableThemes.includes(newTheme)) {
|
|
574
|
+
this.setTheme(newTheme);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
return this._theme;
|
|
578
|
+
},
|
|
579
|
+
|
|
580
|
+
isDarkMode(): boolean {
|
|
581
|
+
return this._theme.endsWith('-dark');
|
|
582
|
+
},
|
|
583
|
+
|
|
584
|
+
_initTheme(): void {
|
|
585
|
+
try {
|
|
586
|
+
const saved = localStorage.getItem('ez-theme');
|
|
587
|
+
if (saved && this._availableThemes.includes(saved)) {
|
|
588
|
+
this.setTheme(saved);
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
} catch {
|
|
592
|
+
// localStorage not available
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
document.documentElement.setAttribute('data-ez-theme', this._theme);
|
|
596
|
+
},
|
|
597
|
+
|
|
598
|
+
format,
|
|
599
|
+
capitalize,
|
|
600
|
+
capitalizeWords,
|
|
601
|
+
truncate,
|
|
602
|
+
pluralize,
|
|
603
|
+
utils: EzUtils
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
await ez._initModules();
|
|
607
|
+
ez._initTheme();
|
|
608
|
+
|
|
609
|
+
window.ez = ez;
|
|
610
|
+
|
|
611
|
+
ez.grid ??= { query: EzGridQuery };
|
|
612
|
+
ez.grid.query = EzGridQuery;
|
|
613
|
+
|
|
614
|
+
export { ez };
|
|
615
|
+
export default ez;
|
|
616
|
+
export type { ComponentDefinition, ControllerDef, ItemConfig, BindConfig } from './EzTypes.js';
|
|
617
|
+
export type { EzItemConfig } from './EzComponentTypes.js';
|