@dooboostore/simple-web-component 1.0.28 → 1.0.30
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/README.md +437 -25
- package/dist/cjs/decorators/attribute.js +2 -1
- package/dist/cjs/decorators/attribute.js.map +2 -2
- package/dist/cjs/decorators/elementDefine.js +8 -2
- package/dist/cjs/decorators/elementDefine.js.map +2 -2
- package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
- package/dist/cjs/decorators/index.js +1 -0
- package/dist/cjs/decorators/index.js.map +2 -2
- package/dist/cjs/decorators/lifecycles.js +4 -0
- package/dist/cjs/decorators/lifecycles.js.map +2 -2
- package/dist/cjs/decorators/setProperty.js +97 -0
- package/dist/cjs/decorators/setProperty.js.map +7 -0
- package/dist/cjs/elements/SwcAppEngine.js +3 -3
- package/dist/cjs/elements/SwcAppEngine.js.map +2 -2
- package/dist/cjs/elements/SwcAppMixin.js +44 -6
- package/dist/cjs/elements/SwcAppMixin.js.map +3 -3
- package/dist/cjs/elements/SwcAsync.js +4 -1
- package/dist/cjs/elements/SwcAsync.js.map +2 -2
- package/dist/cjs/elements/SwcChoose.js +54 -38
- package/dist/cjs/elements/SwcChoose.js.map +2 -2
- package/dist/cjs/elements/register.js +131 -39
- package/dist/cjs/elements/register.js.map +2 -2
- package/dist/cjs/index.js +2 -1
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/types.js.map +1 -1
- package/dist/cjs/utils/Utils.js +30 -1
- package/dist/cjs/utils/Utils.js.map +2 -2
- package/dist/esm/decorators/attribute.js +2 -1
- package/dist/esm/decorators/attribute.js.map +2 -2
- package/dist/esm/decorators/elementDefine.js +8 -2
- package/dist/esm/decorators/elementDefine.js.map +2 -2
- package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
- package/dist/esm/decorators/index.js +1 -0
- package/dist/esm/decorators/index.js.map +2 -2
- package/dist/esm/decorators/lifecycles.js +4 -0
- package/dist/esm/decorators/lifecycles.js.map +2 -2
- package/dist/esm/decorators/setProperty.js +78 -0
- package/dist/esm/decorators/setProperty.js.map +7 -0
- package/dist/esm/elements/SwcAppEngine.js +3 -3
- package/dist/esm/elements/SwcAppEngine.js.map +2 -2
- package/dist/esm/elements/SwcAppMixin.js +44 -6
- package/dist/esm/elements/SwcAppMixin.js.map +3 -3
- package/dist/esm/elements/SwcAsync.js +4 -1
- package/dist/esm/elements/SwcAsync.js.map +2 -2
- package/dist/esm/elements/SwcChoose.js +54 -38
- package/dist/esm/elements/SwcChoose.js.map +2 -2
- package/dist/esm/elements/register.js +131 -39
- package/dist/esm/elements/register.js.map +2 -2
- package/dist/esm/index.js +2 -1
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/utils/Utils.js +30 -1
- package/dist/esm/utils/Utils.js.map +2 -2
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +118 -4
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
- package/dist/types/decorators/attribute.d.ts.map +1 -1
- package/dist/types/decorators/elementDefine.d.ts.map +1 -1
- package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
- package/dist/types/decorators/index.d.ts +1 -0
- package/dist/types/decorators/index.d.ts.map +1 -1
- package/dist/types/decorators/lifecycles.d.ts +2 -0
- package/dist/types/decorators/lifecycles.d.ts.map +1 -1
- package/dist/types/decorators/setProperty.d.ts +13 -0
- package/dist/types/decorators/setProperty.d.ts.map +1 -0
- package/dist/types/elements/SwcAppMixin.d.ts +7 -2
- package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
- package/dist/types/elements/SwcAsync.d.ts.map +1 -1
- package/dist/types/elements/SwcChoose.d.ts +1 -1
- package/dist/types/elements/SwcChoose.d.ts.map +1 -1
- package/dist/types/elements/register.d.ts +3 -1
- package/dist/types/elements/register.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/types.d.ts +3 -0
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils/Utils.d.ts +13 -0
- package/dist/types/utils/Utils.d.ts.map +1 -1
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +118 -4
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
- package/package.json +4 -4
- package/src/decorators/attribute.ts +6 -1
- package/src/decorators/elementDefine.ts +12 -4
- package/src/decorators/emitCustomEvent.ts +1 -0
- package/src/decorators/index.ts +1 -0
- package/src/decorators/lifecycles.ts +3 -0
- package/src/decorators/setProperty.ts +97 -0
- package/src/elements/SwcAppEngine.ts +3 -3
- package/src/elements/SwcAppMixin.ts +77 -14
- package/src/elements/SwcAsync.ts +5 -1
- package/src/elements/SwcChoose.ts +76 -37
- package/src/elements/register.ts +158 -39
- package/src/index.ts +3 -1
- package/src/types.ts +3 -0
- package/src/utils/Utils.ts +55 -1
package/README.md
CHANGED
|
@@ -17,8 +17,7 @@ Register Web Components with automatic lifecycle management and DI support.
|
|
|
17
17
|
@elementDefine('my-component')
|
|
18
18
|
class MyComponent extends HTMLElement {
|
|
19
19
|
@onInitialize
|
|
20
|
-
|
|
21
|
-
super();
|
|
20
|
+
onconstructor(service: MyService) {
|
|
22
21
|
}
|
|
23
22
|
}
|
|
24
23
|
```
|
|
@@ -30,10 +29,9 @@ Inject services into Web Components using the `@onInitialize` decorator.
|
|
|
30
29
|
@elementDefine('dashboard')
|
|
31
30
|
class Dashboard extends HTMLElement {
|
|
32
31
|
@onInitialize
|
|
33
|
-
|
|
32
|
+
onconstructor(
|
|
34
33
|
@Inject({ symbol: UserService.SYMBOL }) userService: UserService
|
|
35
34
|
) {
|
|
36
|
-
super();
|
|
37
35
|
this.userService = userService;
|
|
38
36
|
}
|
|
39
37
|
}
|
|
@@ -220,8 +218,7 @@ Bind attributes on host element itself.
|
|
|
220
218
|
productId: string = '';
|
|
221
219
|
|
|
222
220
|
@onInitialize
|
|
223
|
-
|
|
224
|
-
super();
|
|
221
|
+
onconstructor() {
|
|
225
222
|
if (this.productId) {
|
|
226
223
|
this.loadProduct(this.productId);
|
|
227
224
|
}
|
|
@@ -241,32 +238,65 @@ onDisconnected() {
|
|
|
241
238
|
// Called when element leaves DOM
|
|
242
239
|
}
|
|
243
240
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
241
|
+
|
|
242
|
+
@onConnectedSwcApp
|
|
243
|
+
onAppReady(router: Router) {
|
|
244
|
+
// Called after SwcApp.connect() completes on all already-connected components
|
|
245
|
+
// Full DI support available through hostSet
|
|
246
|
+
console.log('Application initialization complete!');
|
|
247
247
|
}
|
|
248
248
|
```
|
|
249
249
|
|
|
250
|
-
### 8. **Routing with
|
|
251
|
-
|
|
250
|
+
### 8. **Declarative Routing with swc-choose**
|
|
251
|
+
Combine `@subscribeSwcAppRouteChange` with `swc-choose` for clean, declarative routing without boilerplate.
|
|
252
252
|
|
|
253
253
|
```typescript
|
|
254
254
|
@elementDefine('root-router')
|
|
255
255
|
class RootRouter extends HTMLElement {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
256
|
+
private router: Router;
|
|
257
|
+
|
|
258
|
+
@onInitialize
|
|
259
|
+
onconstructor(router: Router) {
|
|
260
|
+
this.router = router;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
@setProperty('#router', 'value')
|
|
264
|
+
@subscribeSwcAppRouteChange(['/', '/product/{id}'])
|
|
265
|
+
routeChanged(router: RouterEventType) {
|
|
266
|
+
return router;
|
|
260
267
|
}
|
|
261
268
|
|
|
262
|
-
@
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
269
|
+
@onConnectedInnerHtml
|
|
270
|
+
render() {
|
|
271
|
+
return `
|
|
272
|
+
<template id="router" is="swc-choose">
|
|
273
|
+
<!-- Home -->
|
|
274
|
+
<template is="swc-when" value="{{ ['', '/'].includes($value?.path) }}">
|
|
275
|
+
<home-page/>
|
|
276
|
+
</template>
|
|
277
|
+
|
|
278
|
+
<!-- Product Detail -->
|
|
279
|
+
<template is="swc-when" value="{{ $value?.path.startsWith('/product/') }}">
|
|
280
|
+
<product-page product-id="{{$value?.pathData?.id}}"/>
|
|
281
|
+
</template>
|
|
282
|
+
|
|
283
|
+
<!-- Not Found -->
|
|
284
|
+
<template is="swc-otherwise">
|
|
285
|
+
<not-found-page/>
|
|
286
|
+
</template>
|
|
287
|
+
</template>
|
|
288
|
+
`;
|
|
266
289
|
}
|
|
267
290
|
}
|
|
268
291
|
```
|
|
269
292
|
|
|
293
|
+
**Benefits:**
|
|
294
|
+
- ✅ **No imperative route methods** - routes are declarative templates
|
|
295
|
+
- ✅ **Automatic re-rendering** - attributes like `product-id` update automatically
|
|
296
|
+
- ✅ **Performance optimization** - use `skip-if-same` on templates to prevent re-renders
|
|
297
|
+
- ✅ **Dynamic path parameters** - use `{{$value?.pathData?.id}}` syntax to inject route params
|
|
298
|
+
- ✅ **Cleaner DX** - single unified routing pattern
|
|
299
|
+
|
|
270
300
|
### 9. **Accommodation Pattern**
|
|
271
301
|
Factory-based component registration with explicit DI.
|
|
272
302
|
|
|
@@ -280,8 +310,7 @@ export default (w: Window) => {
|
|
|
280
310
|
@elementDefine(tagName, { window: w })
|
|
281
311
|
class MyComponent extends w.HTMLElement {
|
|
282
312
|
@onInitialize
|
|
283
|
-
|
|
284
|
-
super();
|
|
313
|
+
onconstructor(service: MyService) {
|
|
285
314
|
this.service = service;
|
|
286
315
|
}
|
|
287
316
|
}
|
|
@@ -307,6 +336,390 @@ appElement.connect({
|
|
|
307
336
|
});
|
|
308
337
|
```
|
|
309
338
|
|
|
339
|
+
### 10. **Quickstart - Basic SPA Setup**
|
|
340
|
+
|
|
341
|
+
Complete example of setting up a production SPA with routing, services, and components.
|
|
342
|
+
|
|
343
|
+
#### Step 1. HTML Entry Point
|
|
344
|
+
```html
|
|
345
|
+
<!DOCTYPE html>
|
|
346
|
+
<html>
|
|
347
|
+
<head>
|
|
348
|
+
<meta charset="UTF-8">
|
|
349
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
350
|
+
<title>My SPA</title>
|
|
351
|
+
<!-- Web Components polyfill for older browsers -->
|
|
352
|
+
<script src="https://unpkg.com/@ungap/custom-elements"></script>
|
|
353
|
+
</head>
|
|
354
|
+
<body id="app" is="swc-app-body">
|
|
355
|
+
<!-- Root router will render pages here -->
|
|
356
|
+
<root-router></root-router>
|
|
357
|
+
</body>
|
|
358
|
+
<script src="bundle.js"></script>
|
|
359
|
+
</html>
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
#### Step 2. Services (Dependency Injection)
|
|
363
|
+
```typescript
|
|
364
|
+
// services/UserService.ts
|
|
365
|
+
import { Sim } from '@dooboostore/simple-boot';
|
|
366
|
+
import { ConstructorType } from '@dooboostore/core';
|
|
367
|
+
|
|
368
|
+
export namespace UserService {
|
|
369
|
+
export const SYMBOL = Symbol('UserService');
|
|
370
|
+
|
|
371
|
+
export interface User {
|
|
372
|
+
id: number;
|
|
373
|
+
name: string;
|
|
374
|
+
email: string;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const users: User[] = [
|
|
378
|
+
{ id: 1, name: 'Alice', email: 'alice@example.com' },
|
|
379
|
+
{ id: 2, name: 'Bob', email: 'bob@example.com' }
|
|
380
|
+
];
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export interface UserService {
|
|
384
|
+
getUser(id: number): UserService.User | undefined;
|
|
385
|
+
getAllUsers(): UserService.User[];
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Factory function: accepts container and returns service class
|
|
389
|
+
export default (container: symbol): ConstructorType<any> => {
|
|
390
|
+
@Sim({ symbol: UserService.SYMBOL, container: container })
|
|
391
|
+
class UserServiceImpl implements UserService {
|
|
392
|
+
getUser(id: number) {
|
|
393
|
+
return UserService.users.find(u => u.id === id);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
getAllUsers() {
|
|
397
|
+
return [...UserService.users];
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
return UserServiceImpl;
|
|
402
|
+
};
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
// services/index.ts
|
|
407
|
+
import userServiceFactory from './UserService';
|
|
408
|
+
|
|
409
|
+
export const serviceFactories = [userServiceFactory];
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
#### Step 3. Router Configuration (Declarative with swc-choose)
|
|
413
|
+
```typescript
|
|
414
|
+
// pages/RootRouter.ts
|
|
415
|
+
import { elementDefine, subscribeSwcAppRouteChange, setProperty, onConnectedInnerHtml, onInitialize } from '@dooboostore/simple-web-component';
|
|
416
|
+
import { Router, RouterEventType } from '@dooboostore/core-web';
|
|
417
|
+
|
|
418
|
+
const rootRouterFactory = (w: Window) => {
|
|
419
|
+
const tagName = 'root-router';
|
|
420
|
+
const existing = w.customElements.get(tagName);
|
|
421
|
+
if (existing) return tagName;
|
|
422
|
+
|
|
423
|
+
@elementDefine(tagName, { window: w })
|
|
424
|
+
class RootRouter extends w.HTMLElement {
|
|
425
|
+
private router: Router;
|
|
426
|
+
|
|
427
|
+
@onInitialize
|
|
428
|
+
onconstructor(router: Router) {
|
|
429
|
+
this.router = router;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
@setProperty('#router', 'value')
|
|
433
|
+
@subscribeSwcAppRouteChange(['/', '/users', '/users/{id}'])
|
|
434
|
+
routeChanged(route: RouterEventType) {
|
|
435
|
+
return route;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
navigate(path: string): void {
|
|
439
|
+
this.router?.go(path);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
@onConnectedInnerHtml
|
|
443
|
+
render() {
|
|
444
|
+
return `
|
|
445
|
+
<template id="router" is="swc-choose">
|
|
446
|
+
<!-- Home Page -->
|
|
447
|
+
<template is="swc-when" value="{{ ['', '/'].includes($value?.path) }}">
|
|
448
|
+
<home-page/>
|
|
449
|
+
</template>
|
|
450
|
+
|
|
451
|
+
<!-- Users List -->
|
|
452
|
+
<template is="swc-when" value="{{ $value?.path === '/users' }}">
|
|
453
|
+
<users-list-page/>
|
|
454
|
+
</template>
|
|
455
|
+
|
|
456
|
+
<!-- User Detail -->
|
|
457
|
+
<template is="swc-when" value="{{ $value?.path.startsWith('/users/') }}">
|
|
458
|
+
<user-detail-page user-id="{{$value?.pathData?.id}}"/>
|
|
459
|
+
</template>
|
|
460
|
+
|
|
461
|
+
<!-- Not Found -->
|
|
462
|
+
<template is="swc-otherwise">
|
|
463
|
+
<not-found-page/>
|
|
464
|
+
</template>
|
|
465
|
+
</template>
|
|
466
|
+
`;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
return tagName;
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
export default rootRouterFactory;
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
#### Step 4. Page Components
|
|
477
|
+
```typescript
|
|
478
|
+
// pages/HomePage.ts
|
|
479
|
+
import { elementDefine, onConnectedInnerHtml } from '@dooboostore/simple-web-component';
|
|
480
|
+
|
|
481
|
+
const HomePage = (w: Window) => {
|
|
482
|
+
const tagName = 'home-page';
|
|
483
|
+
const existing = w.customElements.get(tagName);
|
|
484
|
+
if (existing) return tagName;
|
|
485
|
+
|
|
486
|
+
@elementDefine(tagName, { window: w })
|
|
487
|
+
class HomePage extends w.HTMLElement {
|
|
488
|
+
@onConnectedInnerHtml({ useShadow: true })
|
|
489
|
+
render() {
|
|
490
|
+
return `
|
|
491
|
+
<style>
|
|
492
|
+
:host { display: block; padding: 20px; }
|
|
493
|
+
h1 { color: #333; }
|
|
494
|
+
a { color: #0066cc; text-decoration: none; margin-right: 20px; }
|
|
495
|
+
</style>
|
|
496
|
+
<h1>Welcome to My SPA</h1>
|
|
497
|
+
<nav>
|
|
498
|
+
<a href="/users">View All Users</a>
|
|
499
|
+
</nav>
|
|
500
|
+
`;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
return tagName;
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
export default HomePage;
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
```typescript
|
|
511
|
+
// pages/UsersListPage.ts
|
|
512
|
+
import { elementDefine, onConnectedInnerHtml, onConnectedSwcApp } from '@dooboostore/simple-web-component';
|
|
513
|
+
import { Inject } from '@dooboostore/simple-boot';
|
|
514
|
+
import { UserService } from '../services/UserService';
|
|
515
|
+
|
|
516
|
+
const UsersListPage = (w: Window) => {
|
|
517
|
+
const tagName = 'users-list-page';
|
|
518
|
+
const existing = w.customElements.get(tagName);
|
|
519
|
+
if (existing) return tagName;
|
|
520
|
+
|
|
521
|
+
@elementDefine(tagName, { window: w })
|
|
522
|
+
class UsersListPage extends w.HTMLElement {
|
|
523
|
+
private users: any[] = [];
|
|
524
|
+
|
|
525
|
+
@onConnectedSwcApp
|
|
526
|
+
onconstructor(@Inject({ symbol: UserService.SYMBOL }) userService: UserService) {
|
|
527
|
+
this.users = userService.getAllUsers();
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
@onConnectedInnerHtml({ useShadow: true })
|
|
531
|
+
render() {
|
|
532
|
+
const usersList = this.users
|
|
533
|
+
.map(u => `<li><a href="/users/${u.id}">${u.name}</a></li>`)
|
|
534
|
+
.join('');
|
|
535
|
+
|
|
536
|
+
return `
|
|
537
|
+
<style>
|
|
538
|
+
:host { display: block; padding: 20px; }
|
|
539
|
+
h1 { color: #333; }
|
|
540
|
+
ul { list-style: none; padding: 0; }
|
|
541
|
+
li { margin: 10px 0; }
|
|
542
|
+
a { color: #0066cc; text-decoration: none; }
|
|
543
|
+
</style>
|
|
544
|
+
<h1>Users</h1>
|
|
545
|
+
<ul>${usersList}</ul>
|
|
546
|
+
<a href="/">Back to Home</a>
|
|
547
|
+
`;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
return tagName;
|
|
552
|
+
};
|
|
553
|
+
|
|
554
|
+
export default UsersListPage;
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
#### Step 4-1. Reusable Components
|
|
558
|
+
```typescript
|
|
559
|
+
// components/UserCard.ts
|
|
560
|
+
import { elementDefine, onConnectedInnerHtml, attributeHost } from '@dooboostore/simple-web-component';
|
|
561
|
+
|
|
562
|
+
const UserCard = (w: Window) => {
|
|
563
|
+
const tagName = 'user-card';
|
|
564
|
+
const existing = w.customElements.get(tagName);
|
|
565
|
+
if (existing) return tagName;
|
|
566
|
+
|
|
567
|
+
@elementDefine(tagName, { window: w })
|
|
568
|
+
class UserCard extends w.HTMLElement {
|
|
569
|
+
@attributeHost('data-username')
|
|
570
|
+
username: string;
|
|
571
|
+
|
|
572
|
+
@attributeHost('data-email')
|
|
573
|
+
email: string;
|
|
574
|
+
|
|
575
|
+
@onConnectedInnerHtml({ useShadow: true })
|
|
576
|
+
render() {
|
|
577
|
+
return `
|
|
578
|
+
<style>
|
|
579
|
+
:host { display: block; }
|
|
580
|
+
.card { border: 1px solid #ddd; border-radius: 4px; padding: 12px; }
|
|
581
|
+
.name { font-weight: bold; font-size: 14px; }
|
|
582
|
+
.email { color: #666; font-size: 12px; }
|
|
583
|
+
</style>
|
|
584
|
+
<div class="card">
|
|
585
|
+
<div class="name">${this.username}</div>
|
|
586
|
+
<div class="email">${this.email}</div>
|
|
587
|
+
</div>
|
|
588
|
+
`;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
return tagName;
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
export default UserCard;
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
#### Step 5. Export Factories
|
|
599
|
+
|
|
600
|
+
**services/index.ts** - Export all service factories
|
|
601
|
+
```typescript
|
|
602
|
+
// services/index.ts
|
|
603
|
+
import userServiceFactory from './UserService';
|
|
604
|
+
|
|
605
|
+
export const serviceFactories = [userServiceFactory];
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
**components/index.ts** - Export all component factories
|
|
609
|
+
```typescript
|
|
610
|
+
// components/index.ts
|
|
611
|
+
import UserCard from './UserCard';
|
|
612
|
+
|
|
613
|
+
export const componentFactories = [
|
|
614
|
+
UserCard,
|
|
615
|
+
];
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
**pages/index.ts** - Export all page factories with router
|
|
619
|
+
```typescript
|
|
620
|
+
// pages/index.ts
|
|
621
|
+
import rootRouterFactory from './RootRouter';
|
|
622
|
+
import HomePage from './HomePage';
|
|
623
|
+
import UsersListPage from './UsersListPage';
|
|
624
|
+
import UserDetailPage from './UserDetailPage';
|
|
625
|
+
|
|
626
|
+
export const pageFactories = [
|
|
627
|
+
rootRouterFactory, // Router first
|
|
628
|
+
HomePage,
|
|
629
|
+
UsersListPage,
|
|
630
|
+
UserDetailPage
|
|
631
|
+
];
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
#### Step 6. Application Bootstrap
|
|
635
|
+
```typescript
|
|
636
|
+
// bootFactory.ts
|
|
637
|
+
import { register } from '@dooboostore/simple-web-component';
|
|
638
|
+
import { serviceFactories } from './services';
|
|
639
|
+
import { componentFactories } from './components';
|
|
640
|
+
import { pageFactories } from './pages';
|
|
641
|
+
|
|
642
|
+
export default (w: Window, container: symbol) => {
|
|
643
|
+
// Initialize services with container (dependency injection)
|
|
644
|
+
// Each factory receives the container symbol and registers its service in the DI container
|
|
645
|
+
serviceFactories.forEach(serviceFactory => serviceFactory(container));
|
|
646
|
+
|
|
647
|
+
// Register pages and components
|
|
648
|
+
register(w, [...pageFactories, ...componentFactories]);
|
|
649
|
+
};
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
#### Step 7. Application Entry Point
|
|
653
|
+
```typescript
|
|
654
|
+
// index.ts
|
|
655
|
+
import 'reflect-metadata';
|
|
656
|
+
import { SwcAppInterface } from '@dooboostore/simple-web-component';
|
|
657
|
+
import bootFactory from './bootFactory';
|
|
658
|
+
|
|
659
|
+
const w = window;
|
|
660
|
+
|
|
661
|
+
w.document.addEventListener('DOMContentLoaded', async () => {
|
|
662
|
+
const container = Symbol('app');
|
|
663
|
+
|
|
664
|
+
// Initialize services and components
|
|
665
|
+
bootFactory(w, container);
|
|
666
|
+
|
|
667
|
+
// Wait for customized built-in element to be defined
|
|
668
|
+
await w.customElements.whenDefined('swc-app-body');
|
|
669
|
+
|
|
670
|
+
// Get app root element
|
|
671
|
+
const appElement = w.document.querySelector('#app') as SwcAppInterface;
|
|
672
|
+
|
|
673
|
+
if (appElement && typeof appElement.connect === 'function') {
|
|
674
|
+
// Connect SPA with routing and DI
|
|
675
|
+
appElement.connect({
|
|
676
|
+
path: '/',
|
|
677
|
+
routeType: 'path',
|
|
678
|
+
container: container,
|
|
679
|
+
window: w,
|
|
680
|
+
onEngineStarted: () => {
|
|
681
|
+
console.log('🚀 Application started successfully');
|
|
682
|
+
// Root router automatically initialized via @elementDefine
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
} else {
|
|
686
|
+
console.error('Failed to initialize SPA');
|
|
687
|
+
}
|
|
688
|
+
});
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
#### Resulting Application Structure
|
|
692
|
+
```
|
|
693
|
+
src/
|
|
694
|
+
├── index.ts # Entry point
|
|
695
|
+
├── index.html # HTML root with <root-router>
|
|
696
|
+
├── bootFactory.ts # Bootstrap services & components via register()
|
|
697
|
+
├── services/
|
|
698
|
+
│ ├── UserService.ts # Service factory (export default)
|
|
699
|
+
│ └── index.ts # Export serviceFactories
|
|
700
|
+
├── pages/
|
|
701
|
+
│ ├── RootRouter.ts # Router factory (export default)
|
|
702
|
+
│ ├── HomePage.ts # Page factory (export default)
|
|
703
|
+
│ ├── UsersListPage.ts # Page factory (export default)
|
|
704
|
+
│ ├── UserDetailPage.ts # Page factory (export default)
|
|
705
|
+
│ └── index.ts # Export pageFactories
|
|
706
|
+
└── components/
|
|
707
|
+
├── UserCard.ts # Component factory (export default)
|
|
708
|
+
└── index.ts # Export componentFactories
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
**Key Flow:**
|
|
712
|
+
1. HTML loads → `<root-router>` element already in DOM
|
|
713
|
+
2. `index.ts` executes → calls `bootFactory`
|
|
714
|
+
3. `bootFactory` registers services and components (including `rootRouterFactory`)
|
|
715
|
+
4. App waits for `swc-app-body` to be defined
|
|
716
|
+
5. `appElement.connect()` initializes routing & DI
|
|
717
|
+
6. `<root-router>` becomes active with `@subscribeSwcAppRouteChange` + `swc-choose` template
|
|
718
|
+
7. Route changes automatically trigger `swc-choose` re-evaluation and template re-rendering
|
|
719
|
+
8. Template attributes like `user-id="{{$value?.pathData?.id}}"` are dynamically populated with route params
|
|
720
|
+
9. All components have access to injected services via `@onInitialize` or `@onConnectedSwcApp`
|
|
721
|
+
|
|
722
|
+
|
|
310
723
|
---
|
|
311
724
|
|
|
312
725
|
## ⚠️ Critical Rules
|
|
@@ -316,14 +729,14 @@ appElement.connect({
|
|
|
316
729
|
|
|
317
730
|
```typescript
|
|
318
731
|
// ✅ CORRECT
|
|
319
|
-
@Sim
|
|
732
|
+
@Sim
|
|
320
733
|
export class UserService { }
|
|
321
734
|
|
|
322
735
|
@elementDefine(tagName, { window: w })
|
|
323
736
|
class UserWidget extends w.HTMLElement { }
|
|
324
737
|
|
|
325
738
|
// ❌ WRONG
|
|
326
|
-
@Sim
|
|
739
|
+
@Sim
|
|
327
740
|
@elementDefine(tagName, { window: w })
|
|
328
741
|
class UserWidget extends w.HTMLElement { }
|
|
329
742
|
```
|
|
@@ -346,8 +759,7 @@ export default (w: Window) => {
|
|
|
346
759
|
```typescript
|
|
347
760
|
// ✅ CORRECT
|
|
348
761
|
@onInitialize
|
|
349
|
-
|
|
350
|
-
super();
|
|
762
|
+
onconstructor(@Inject({ symbol: Service.SYMBOL }) service: Service) {
|
|
351
763
|
this.service = service;
|
|
352
764
|
}
|
|
353
765
|
|
|
@@ -120,7 +120,8 @@ function attribute(selector, options = {}) {
|
|
|
120
120
|
}
|
|
121
121
|
return null;
|
|
122
122
|
}
|
|
123
|
-
|
|
123
|
+
const data = convertValue(this[privateKey], targetType);
|
|
124
|
+
return data;
|
|
124
125
|
},
|
|
125
126
|
set(nv) {
|
|
126
127
|
const attrName = options.name || String(propertyKey);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/decorators/attribute.ts"],
|
|
4
|
-
"sourcesContent": ["import {ReflectUtils} from '@dooboostore/core';\nimport {ensureInit, getElementConfig} from './elementDefine';\nimport {SwcUtils} from '../utils/Utils';\nimport {SpecialSelector, SwcQueryOptions} from '../types';\nexport interface AttributeFieldOptions extends SwcQueryOptions {\n name?: string;\n // connectedInitialize?: boolean;\n type?: typeof Number | typeof Boolean | typeof String;\n}\n\nexport interface AttributeFieldMetadata {\n propertyKey: string | symbol;\n selector: string;\n options: AttributeFieldOptions;\n privateKey: symbol;\n}\n\nexport const ATTRIBUTE_FIELD_METADATA_KEY = Symbol.for('simple-web-component:attribute-field');\n\nconst convertValue = (val: string | null, type: any): any => {\n if (val === null || val === undefined) return val;\n if (type === Number) return Number(val);\n if (type === Boolean) return val === 'false' || val === '0' ? false : true;\n return val;\n};\n\nexport const resolveTargetEls = (inst: any, selector: string, options: AttributeFieldOptions, currentWin: any): HTMLElement[] => {\n const r = options.root || 'auto';\n const results: HTMLElement[] = [];\n\n const applyRoot = (target: any) => {\n if (!target) return;\n if (r === 'auto') {\n results.push(target);\n } else {\n if (r === 'light' || r === 'all') results.push(target);\n if ((r === 'shadow' || r === 'all') && target.shadowRoot) results.push(target.shadowRoot);\n }\n };\n\n if (selector === ':host' || !selector) {\n applyRoot(inst);\n } else if (selector === ':window') {\n results.push(currentWin);\n } else if (selector === ':document') {\n results.push(currentWin.document);\n } else {\n const hostSet = SwcUtils.getHostSet(inst);\n if (selector === ':parentHost') applyRoot(hostSet.$parentHost);\n else if (selector === ':appHost') applyRoot(hostSet.$appHost as any);\n else if (selector === ':firstHost') applyRoot(hostSet.$firstHost);\n else if (selector === ':lastHost') applyRoot(hostSet.$lastHost);\n else if (selector === ':firstAppHost') applyRoot(hostSet.$firstAppHost as any);\n else if (selector === ':lastAppHost') applyRoot(hostSet.$lastAppHost as any);\n else {\n if (r === 'shadow') {\n const found = inst.shadowRoot?.querySelectorAll(selector);\n if (found) results.push(...found);\n } else if (r === 'light') {\n const found = inst.querySelectorAll(selector);\n if (found) results.push(...found);\n } else if (r === 'all') {\n const sMatch = inst.shadowRoot?.querySelectorAll(selector);\n const lMatch = inst.querySelectorAll(selector);\n if (sMatch) results.push(...sMatch);\n if (lMatch) results.push(...lMatch);\n } else {\n const found = (inst.shadowRoot || inst).querySelectorAll(selector);\n if (found) results.push(...found);\n }\n }\n }\n return results;\n};\n\n/**\n * @attribute decorator to sync a field value with an element's attribute.\n */\nexport function attribute(selector: string, options: AttributeFieldOptions = {}): PropertyDecorator {\n return (target: Object, propertyKey: string | symbol) => {\n const constructor = target.constructor;\n const privateKey = Symbol(String(propertyKey));\n //\n const designType = (Reflect as any).getMetadata('design:type', target, propertyKey);\n //\n let metaList = ReflectUtils.getOwnMetadata(ATTRIBUTE_FIELD_METADATA_KEY, constructor) as AttributeFieldMetadata[];\n if (!metaList) {\n metaList = [];\n ReflectUtils.defineMetadata(ATTRIBUTE_FIELD_METADATA_KEY, metaList, constructor);\n }\n metaList.push({propertyKey, selector, options, privateKey});\n\n const applySetAttribute = (inst: any, targets: HTMLElement[], attrName: string, nv: any) => {\n targets.forEach(it => {\n if (it && typeof (it as any).setAttribute === 'function') {\n if (nv === null) {\n (it as any).removeAttribute(attrName);\n } else {\n (it as any).setAttribute(attrName, String(nv));\n }\n } else {\n inst[privateKey] = nv;\n }\n });\n };\n\n try {\n // Own property\uB97C \uC0AD\uC81C\uD558\uC5EC getter\uAC00 \uC791\uB3D9\uD558\uB3C4\uB85D \uD568\n // delete target[propertyKey];\n\n // const defineTarget = target instanceof Function ? target : (target as any).constructor;\n \n Object.defineProperty(target, propertyKey, {\n get(this: any) {\n // try {\n const attrName = options.name || String(propertyKey);\n const conf = getElementConfig(this);\n const currentWin = this._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);\n const targetType = options.type || designType;\n //\n // connectedInitialize: true\uC774\uBA74 privateKey \uAC12\uB9CC \uBC18\uD658 (DOM \uBB34\uC2DC)\n // if (options.connectedInitialize === true && (this as any).__swc_syncing_init) {\n // console.log('cccccccc2');\n // return this[privateKey];\n // // return convertValue(this[privateKey], targetType);\n // }\n\n const targets = resolveTargetEls(this, selector, options, currentWin);\n const primaryTarget = targets[0];\n\n if (primaryTarget && typeof (primaryTarget as any).hasAttribute === 'function') {\n if ((primaryTarget as any).hasAttribute(attrName)) {\n const domVal = (primaryTarget as any).getAttribute(attrName);\n return convertValue(domVal, targetType);\n }\n return null;\n }\n\n
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAA2B;AAC3B,2BAA2C;AAC3C,mBAAuB;AAehB,MAAM,+BAA+B,OAAO,IAAI,sCAAsC;AAE7F,MAAM,eAAe,CAAC,KAAoB,SAAmB;AAC3D,MAAI,QAAQ,QAAQ,QAAQ,OAAW,QAAO;AAC9C,MAAI,SAAS,OAAQ,QAAO,OAAO,GAAG;AACtC,MAAI,SAAS,QAAS,QAAO,QAAQ,WAAW,QAAQ,MAAM,QAAQ;AACtE,SAAO;AACT;AAEO,MAAM,mBAAmB,CAAC,MAAW,UAAkB,SAAgC,eAAmC;AAC/H,QAAM,IAAI,QAAQ,QAAQ;AAC1B,QAAM,UAAyB,CAAC;AAEhC,QAAM,YAAY,CAAC,WAAgB;AACjC,QAAI,CAAC,OAAQ;AACb,QAAI,MAAM,QAAQ;AAChB,cAAQ,KAAK,MAAM;AAAA,IACrB,OAAO;AACL,UAAI,MAAM,WAAW,MAAM,MAAO,SAAQ,KAAK,MAAM;AACrD,WAAK,MAAM,YAAY,MAAM,UAAU,OAAO,WAAY,SAAQ,KAAK,OAAO,UAAU;AAAA,IAC1F;AAAA,EACF;AAEA,MAAI,aAAa,WAAW,CAAC,UAAU;AACrC,cAAU,IAAI;AAAA,EAChB,WAAW,aAAa,WAAW;AACjC,YAAQ,KAAK,UAAU;AAAA,EACzB,WAAW,aAAa,aAAa;AACnC,YAAQ,KAAK,WAAW,QAAQ;AAAA,EAClC,OAAO;AACL,UAAM,UAAU,sBAAS,WAAW,IAAI;AACxC,QAAI,aAAa,cAAe,WAAU,QAAQ,WAAW;AAAA,aACpD,aAAa,WAAY,WAAU,QAAQ,QAAe;AAAA,aAC1D,aAAa,aAAc,WAAU,QAAQ,UAAU;AAAA,aACvD,aAAa,YAAa,WAAU,QAAQ,SAAS;AAAA,aACrD,aAAa,gBAAiB,WAAU,QAAQ,aAAoB;AAAA,aACpE,aAAa,eAAgB,WAAU,QAAQ,YAAmB;AAAA,SACtE;AACH,UAAI,MAAM,UAAU;AAClB,cAAM,QAAQ,KAAK,YAAY,iBAAiB,QAAQ;AACxD,YAAI,MAAO,SAAQ,KAAK,GAAG,KAAK;AAAA,MAClC,WAAW,MAAM,SAAS;AACxB,cAAM,QAAQ,KAAK,iBAAiB,QAAQ;AAC5C,YAAI,MAAO,SAAQ,KAAK,GAAG,KAAK;AAAA,MAClC,WAAW,MAAM,OAAO;AACtB,cAAM,SAAS,KAAK,YAAY,iBAAiB,QAAQ;AACzD,cAAM,SAAS,KAAK,iBAAiB,QAAQ;AAC7C,YAAI,OAAQ,SAAQ,KAAK,GAAG,MAAM;AAClC,YAAI,OAAQ,SAAQ,KAAK,GAAG,MAAM;AAAA,MACpC,OAAO;AACL,cAAM,SAAS,KAAK,cAAc,MAAM,iBAAiB,QAAQ;AACjE,YAAI,MAAO,SAAQ,KAAK,GAAG,KAAK;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,UAAU,UAAkB,UAAiC,CAAC,GAAsB;AAClG,SAAO,CAAC,QAAgB,gBAAiC;AACvD,UAAM,cAAc,OAAO;AAC3B,UAAM,aAAa,OAAO,OAAO,WAAW,CAAC;AAE7C,UAAM,aAAc,QAAgB,YAAY,eAAe,QAAQ,WAAW;AAElF,QAAI,WAAW,yBAAa,eAAe,8BAA8B,WAAW;AACpF,QAAI,CAAC,UAAU;AACb,iBAAW,CAAC;AACZ,+BAAa,eAAe,8BAA8B,UAAU,WAAW;AAAA,IACjF;AACA,aAAS,KAAK,EAAC,aAAa,UAAU,SAAS,WAAU,CAAC;AAE1D,UAAM,oBAAoB,CAAC,MAAW,SAAwB,UAAkB,OAAY;AAC1F,cAAQ,QAAQ,QAAM;
|
|
4
|
+
"sourcesContent": ["import {ReflectUtils} from '@dooboostore/core';\nimport {ensureInit, getElementConfig} from './elementDefine';\nimport {SwcUtils} from '../utils/Utils';\nimport {SpecialSelector, SwcQueryOptions} from '../types';\nexport interface AttributeFieldOptions extends SwcQueryOptions {\n name?: string;\n // connectedInitialize?: boolean;\n type?: typeof Number | typeof Boolean | typeof String;\n}\n\nexport interface AttributeFieldMetadata {\n propertyKey: string | symbol;\n selector: string;\n options: AttributeFieldOptions;\n privateKey: symbol;\n}\n\nexport const ATTRIBUTE_FIELD_METADATA_KEY = Symbol.for('simple-web-component:attribute-field');\n\nconst convertValue = (val: string | null, type: any): any => {\n if (val === null || val === undefined) return val;\n if (type === Number) return Number(val);\n if (type === Boolean) return val === 'false' || val === '0' ? false : true;\n return val;\n};\n\nexport const resolveTargetEls = (inst: any, selector: string, options: AttributeFieldOptions, currentWin: any): HTMLElement[] => {\n const r = options.root || 'auto';\n const results: HTMLElement[] = [];\n\n const applyRoot = (target: any) => {\n if (!target) return;\n if (r === 'auto') {\n results.push(target);\n } else {\n if (r === 'light' || r === 'all') results.push(target);\n if ((r === 'shadow' || r === 'all') && target.shadowRoot) results.push(target.shadowRoot);\n }\n };\n\n if (selector === ':host' || !selector) {\n applyRoot(inst);\n } else if (selector === ':window') {\n results.push(currentWin);\n } else if (selector === ':document') {\n results.push(currentWin.document);\n } else {\n const hostSet = SwcUtils.getHostSet(inst);\n if (selector === ':parentHost') applyRoot(hostSet.$parentHost);\n else if (selector === ':appHost') applyRoot(hostSet.$appHost as any);\n else if (selector === ':firstHost') applyRoot(hostSet.$firstHost);\n else if (selector === ':lastHost') applyRoot(hostSet.$lastHost);\n else if (selector === ':firstAppHost') applyRoot(hostSet.$firstAppHost as any);\n else if (selector === ':lastAppHost') applyRoot(hostSet.$lastAppHost as any);\n else {\n if (r === 'shadow') {\n const found = inst.shadowRoot?.querySelectorAll(selector);\n if (found) results.push(...found);\n } else if (r === 'light') {\n const found = inst.querySelectorAll(selector);\n if (found) results.push(...found);\n } else if (r === 'all') {\n const sMatch = inst.shadowRoot?.querySelectorAll(selector);\n const lMatch = inst.querySelectorAll(selector);\n if (sMatch) results.push(...sMatch);\n if (lMatch) results.push(...lMatch);\n } else {\n const found = (inst.shadowRoot || inst).querySelectorAll(selector);\n if (found) results.push(...found);\n }\n }\n }\n return results;\n};\n\n/**\n * @attribute decorator to sync a field value with an element's attribute.\n */\nexport function attribute(selector: string, options: AttributeFieldOptions = {}): PropertyDecorator {\n return (target: Object, propertyKey: string | symbol) => {\n const constructor = target.constructor;\n const privateKey = Symbol(String(propertyKey));\n //\n const designType = (Reflect as any).getMetadata('design:type', target, propertyKey);\n //\n let metaList = ReflectUtils.getOwnMetadata(ATTRIBUTE_FIELD_METADATA_KEY, constructor) as AttributeFieldMetadata[];\n if (!metaList) {\n metaList = [];\n ReflectUtils.defineMetadata(ATTRIBUTE_FIELD_METADATA_KEY, metaList, constructor);\n }\n metaList.push({propertyKey, selector, options, privateKey});\n\n const applySetAttribute = (inst: any, targets: HTMLElement[], attrName: string, nv: any) => {\n targets.forEach(it => {\n // console.log('sssssssssssss', it, attrName, nv);\n if (it && typeof (it as any).setAttribute === 'function') {\n if (nv === null) {\n (it as any).removeAttribute(attrName);\n } else {\n (it as any).setAttribute(attrName, String(nv));\n }\n } else {\n inst[privateKey] = nv;\n }\n });\n };\n\n try {\n // Own property\uB97C \uC0AD\uC81C\uD558\uC5EC getter\uAC00 \uC791\uB3D9\uD558\uB3C4\uB85D \uD568\n // delete target[propertyKey];\n\n // const defineTarget = target instanceof Function ? target : (target as any).constructor;\n \n Object.defineProperty(target, propertyKey, {\n get(this: any) {\n // console.log('------>??gettttt', this, propertyKey);\n // try {\n const attrName = options.name || String(propertyKey);\n const conf = getElementConfig(this);\n const currentWin = this._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);\n const targetType = options.type || designType;\n //\n // connectedInitialize: true\uC774\uBA74 privateKey \uAC12\uB9CC \uBC18\uD658 (DOM \uBB34\uC2DC)\n // if (options.connectedInitialize === true && (this as any).__swc_syncing_init) {\n // console.log('cccccccc2');\n // return this[privateKey];\n // // return convertValue(this[privateKey], targetType);\n // }\n\n const targets = resolveTargetEls(this, selector, options, currentWin);\n const primaryTarget = targets[0];\n\n if (primaryTarget && typeof (primaryTarget as any).hasAttribute === 'function') {\n if ((primaryTarget as any).hasAttribute(attrName)) {\n const domVal = (primaryTarget as any).getAttribute(attrName);\n return convertValue(domVal, targetType);\n }\n return null;\n }\n\n const data = convertValue(this[privateKey], targetType);\n // console.log('get rrr', data);\n return data;\n // } catch (err) {\n // console.error('Error in getter:', err);\n // throw err;\n // }\n },\n set(this: any, nv: any) {\n // this[propertyKey] = nv;\n // console.log('------>??settttt', this, nv, propertyKey);\n const attrName = options.name || String(propertyKey);\n const conf = getElementConfig(this);\n const currentWin = this._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);\n\n\n // if (!this.__swc_connected) {\n // this[privateKey] = nv;\n // return;\n // }\n\n const targets = resolveTargetEls(this, selector, options, currentWin);\n applySetAttribute(this, targets, attrName, nv);\n },\n enumerable: true,\n configurable: true\n });\n } catch (err) {\n console.error('[SWC] defineProperty error:', err);\n }\n };\n}\n\n/**\n * @attributeHost decorator to sync a field value with the :host element's attribute.\n */\nexport function attributeHost(target: Object, propertyKey: string | symbol): void;\nexport function attributeHost(options: AttributeFieldOptions): PropertyDecorator;\nexport function attributeHost(attrName: string): PropertyDecorator;\nexport function attributeHost(attrName: string, options: AttributeFieldOptions): PropertyDecorator;\nexport function attributeHost(targetOrAttrOrOptions?: any, propertyKeyOrOptions?: any): any {\n if (propertyKeyOrOptions !== undefined && (typeof propertyKeyOrOptions === 'string' || typeof propertyKeyOrOptions === 'symbol')) {\n return attribute(':host', { name: String(propertyKeyOrOptions) })(targetOrAttrOrOptions, propertyKeyOrOptions);\n }\n\n if (typeof targetOrAttrOrOptions === 'string') {\n const attrName = targetOrAttrOrOptions;\n const options = (typeof propertyKeyOrOptions === 'object' ? propertyKeyOrOptions : {}) as AttributeFieldOptions;\n return attribute(':host', { ...options, name: attrName });\n } else if (typeof targetOrAttrOrOptions === 'object') {\n const options = targetOrAttrOrOptions as AttributeFieldOptions;\n return (target: Object, propertyKey: string | symbol) => {\n return attribute(':host', { ...options, name: String(propertyKey) })(target, propertyKey);\n };\n } else {\n return (target: Object, propertyKey: string | symbol) => {\n return attribute(':host', { name: String(propertyKey) })(target, propertyKey);\n };\n }\n}\n\nexport const findAllAttributeMetadata = (target: any): AttributeFieldMetadata[] => {\n const actualTarget = target instanceof Function ? target : target.constructor;\n return ReflectUtils.findAllMetadata<AttributeFieldMetadata[]>(ATTRIBUTE_FIELD_METADATA_KEY, actualTarget).flat();\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -66,6 +66,7 @@ const ensureInit = (inst) => {
|
|
|
66
66
|
});
|
|
67
67
|
}
|
|
68
68
|
const hostSet = import_Utils.SwcUtils.getHostSet(inst);
|
|
69
|
+
const appHosts = import_Utils.SwcUtils.findAllParentAppHostsDirect(inst);
|
|
69
70
|
inst._executeSwcScript?.("swc-on-constructor", hostSet);
|
|
70
71
|
const cMethods = (0, import_lifecycles.findAllLifecycleMetadata)(inst, import_lifecycles.ON_INITIALIZE_METADATA_KEY);
|
|
71
72
|
if (cMethods) {
|
|
@@ -137,10 +138,11 @@ const setupPrototype = (proto) => {
|
|
|
137
138
|
proto._invokeLifecycleMethod = function(methodName, hostSet, extraArgs = []) {
|
|
138
139
|
ensureInit(this);
|
|
139
140
|
if (typeof this[methodName] !== "function") return;
|
|
140
|
-
const
|
|
141
|
+
const useHostSet = hostSet ?? import_Utils.SwcUtils.getHostSet(this);
|
|
142
|
+
const app = useHostSet?.$appHost.simpleApplication;
|
|
141
143
|
if (app) {
|
|
142
144
|
const otherStorage = /* @__PURE__ */ new Map();
|
|
143
|
-
const situations = new import_Inject.SituationTypeContainers([new import_Inject.SituationTypeContainer({ situationType: import_types.InjectSituationType.HOST_SET, data:
|
|
145
|
+
const situations = new import_Inject.SituationTypeContainers([new import_Inject.SituationTypeContainer({ situationType: import_types.InjectSituationType.HOST_SET, data: useHostSet }), new import_Inject.SituationTypeContainer({ situationType: import_types.InjectSituationType.APP_HOST, data: useHostSet.$appHost }), new import_Inject.SituationTypeContainer({ situationType: import_types.InjectSituationType.APP_HOSTS, data: useHostSet.$appHosts }), new import_Inject.SituationTypeContainer({ situationType: import_types.InjectSituationType.HOST, data: useHostSet.$host }), new import_Inject.SituationTypeContainer({ situationType: import_types.InjectSituationType.HOSTS, data: useHostSet.$hosts }), new import_Inject.SituationTypeContainer({ situationType: import_types.InjectSituationType.FIRST_HOST, data: useHostSet.$firstHost }), new import_Inject.SituationTypeContainer({ situationType: import_types.InjectSituationType.LAST_HOST, data: useHostSet.$lastHost }), new import_Inject.SituationTypeContainer({ situationType: import_types.InjectSituationType.FIRST_APP_HOST, data: useHostSet.$firstAppHost }), new import_Inject.SituationTypeContainer({ situationType: import_types.InjectSituationType.LAST_APP_HOST, data: useHostSet.$lastAppHost })]);
|
|
144
146
|
otherStorage.set(import_Inject.SituationTypeContainers, situations);
|
|
145
147
|
return app.simstanceManager.executeBindParameterSimPromise(
|
|
146
148
|
{
|
|
@@ -409,8 +411,12 @@ const elementDefine = (name, config = {}) => (constructor) => {
|
|
|
409
411
|
this._executeSwcScript("swc-on-connected", hostSet);
|
|
410
412
|
this._executeSwcScript("swc-on-after-connected", hostSet);
|
|
411
413
|
this.__swc_connected = true;
|
|
414
|
+
const appHostss = import_Utils.SwcUtils.findAllParentAppHostsDirect(this);
|
|
412
415
|
if (appHost && typeof appHost._connected === "function") {
|
|
413
416
|
appHost._connected(this);
|
|
417
|
+
} else if (appHost && typeof appHost) {
|
|
418
|
+
appHost._connected_safari ?? (appHost._connected_safari = []);
|
|
419
|
+
appHost._connected_safari.push(this);
|
|
414
420
|
}
|
|
415
421
|
};
|
|
416
422
|
const originalDisconnected = proto.disconnectedCallback;
|