@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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dooboostore/simple-web-component",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.30",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -92,10 +92,10 @@
|
|
|
92
92
|
"webpack": "^5.93.0",
|
|
93
93
|
"webpack-cli": "^5.1.4",
|
|
94
94
|
"webpack-dev-server": "^5.2.0",
|
|
95
|
-
"@dooboostore/core-node": "1.0.12",
|
|
96
|
-
"@dooboostore/core-web": "1.0.10",
|
|
97
95
|
"@dooboostore/core": "1.0.30",
|
|
98
|
-
"@dooboostore/simple-boot": "1.0.54"
|
|
96
|
+
"@dooboostore/simple-boot": "1.0.54",
|
|
97
|
+
"@dooboostore/core-web": "1.0.10",
|
|
98
|
+
"@dooboostore/core-node": "1.0.12"
|
|
99
99
|
},
|
|
100
100
|
"scripts": {
|
|
101
101
|
"clean": "rm -rf dist",
|
|
@@ -92,6 +92,7 @@ export function attribute(selector: string, options: AttributeFieldOptions = {})
|
|
|
92
92
|
|
|
93
93
|
const applySetAttribute = (inst: any, targets: HTMLElement[], attrName: string, nv: any) => {
|
|
94
94
|
targets.forEach(it => {
|
|
95
|
+
// console.log('sssssssssssss', it, attrName, nv);
|
|
95
96
|
if (it && typeof (it as any).setAttribute === 'function') {
|
|
96
97
|
if (nv === null) {
|
|
97
98
|
(it as any).removeAttribute(attrName);
|
|
@@ -112,6 +113,7 @@ export function attribute(selector: string, options: AttributeFieldOptions = {})
|
|
|
112
113
|
|
|
113
114
|
Object.defineProperty(target, propertyKey, {
|
|
114
115
|
get(this: any) {
|
|
116
|
+
// console.log('------>??gettttt', this, propertyKey);
|
|
115
117
|
// try {
|
|
116
118
|
const attrName = options.name || String(propertyKey);
|
|
117
119
|
const conf = getElementConfig(this);
|
|
@@ -136,7 +138,9 @@ export function attribute(selector: string, options: AttributeFieldOptions = {})
|
|
|
136
138
|
return null;
|
|
137
139
|
}
|
|
138
140
|
|
|
139
|
-
|
|
141
|
+
const data = convertValue(this[privateKey], targetType);
|
|
142
|
+
// console.log('get rrr', data);
|
|
143
|
+
return data;
|
|
140
144
|
// } catch (err) {
|
|
141
145
|
// console.error('Error in getter:', err);
|
|
142
146
|
// throw err;
|
|
@@ -144,6 +148,7 @@ export function attribute(selector: string, options: AttributeFieldOptions = {})
|
|
|
144
148
|
},
|
|
145
149
|
set(this: any, nv: any) {
|
|
146
150
|
// this[propertyKey] = nv;
|
|
151
|
+
// console.log('------>??settttt', this, nv, propertyKey);
|
|
147
152
|
const attrName = options.name || String(propertyKey);
|
|
148
153
|
const conf = getElementConfig(this);
|
|
149
154
|
const currentWin = this._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);
|
|
@@ -91,6 +91,7 @@ export const ensureInit = (inst: any) => {
|
|
|
91
91
|
|
|
92
92
|
// Call constructor script if present
|
|
93
93
|
const hostSet = SwcUtils.getHostSet(inst);
|
|
94
|
+
const appHosts = SwcUtils.findAllParentAppHostsDirect(inst);
|
|
94
95
|
inst._executeSwcScript?.('swc-on-constructor', hostSet);
|
|
95
96
|
|
|
96
97
|
// Call @onInitialize lifecycle methods
|
|
@@ -172,14 +173,15 @@ const setupPrototype = (proto: any) => {
|
|
|
172
173
|
return (typeof window !== 'undefined' ? window : undefined) as Window;
|
|
173
174
|
};
|
|
174
175
|
|
|
175
|
-
proto._invokeLifecycleMethod = function (methodName: string | symbol, hostSet
|
|
176
|
+
proto._invokeLifecycleMethod = function (methodName: string | symbol, hostSet?: HostSet, extraArgs: any[] = []) {
|
|
176
177
|
ensureInit(this);
|
|
177
178
|
if (typeof (this as any)[methodName] !== 'function') return;
|
|
178
|
-
const
|
|
179
|
-
|
|
179
|
+
const useHostSet = hostSet ?? SwcUtils.getHostSet(this);
|
|
180
|
+
const app = useHostSet?.$appHost.simpleApplication;
|
|
181
|
+
// console.log('---->hh',app, this, methodName);
|
|
180
182
|
if (app) {
|
|
181
183
|
const otherStorage = new Map<any, any>();
|
|
182
|
-
const situations = new SituationTypeContainers([new SituationTypeContainer({ situationType: InjectSituationType.HOST_SET, data:
|
|
184
|
+
const situations = new SituationTypeContainers([new SituationTypeContainer({ situationType: InjectSituationType.HOST_SET, data: useHostSet }), new SituationTypeContainer({ situationType: InjectSituationType.APP_HOST, data: useHostSet.$appHost }), new SituationTypeContainer({ situationType: InjectSituationType.APP_HOSTS, data: useHostSet.$appHosts }), new SituationTypeContainer({ situationType: InjectSituationType.HOST, data: useHostSet.$host }), new SituationTypeContainer({ situationType: InjectSituationType.HOSTS, data: useHostSet.$hosts }), new SituationTypeContainer({ situationType: InjectSituationType.FIRST_HOST, data: useHostSet.$firstHost }), new SituationTypeContainer({ situationType: InjectSituationType.LAST_HOST, data: useHostSet.$lastHost }), new SituationTypeContainer({ situationType: InjectSituationType.FIRST_APP_HOST, data: useHostSet.$firstAppHost }), new SituationTypeContainer({ situationType: InjectSituationType.LAST_APP_HOST, data: useHostSet.$lastAppHost })]);
|
|
183
185
|
otherStorage.set(SituationTypeContainers, situations);
|
|
184
186
|
|
|
185
187
|
return app.simstanceManager.executeBindParameterSimPromise(
|
|
@@ -493,8 +495,14 @@ export const elementDefine =
|
|
|
493
495
|
(this as any).__swc_connected = true;
|
|
494
496
|
|
|
495
497
|
// Register to appHost LAST when all lifecycle completed
|
|
498
|
+
// console.log('!!!!!!!!!!!!!!', this, appHost)
|
|
499
|
+
const appHostss = SwcUtils.findAllParentAppHostsDirect(this)
|
|
500
|
+
// const nAppHostSet = SwcUtils.getHostSet(this as any);
|
|
496
501
|
if (appHost && typeof (appHost as any)._connected === 'function') {
|
|
497
502
|
(appHost as any)._connected(this);
|
|
503
|
+
} else if (appHost && typeof (appHost as any)) {
|
|
504
|
+
(appHost as any)._connected_safari ??= [];
|
|
505
|
+
(appHost as any)._connected_safari.push(this);
|
|
498
506
|
}
|
|
499
507
|
};
|
|
500
508
|
|
|
@@ -52,6 +52,7 @@ export function emitCustomEvent(selectorOrTarget: string, type: string, options:
|
|
|
52
52
|
const hostSet = SwcUtils.getHostSet(this as any);
|
|
53
53
|
const conf = getElementConfig(this);
|
|
54
54
|
const currentWin = (this as any)._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as Window);
|
|
55
|
+
// console.log('emitEEEEEEEEEEE', hostSet);
|
|
55
56
|
|
|
56
57
|
const eventTargets: EventTarget[] = [];
|
|
57
58
|
if (selectorOrTarget === ':window') eventTargets.push(currentWin);
|
package/src/decorators/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ export const ON_AFTER_DISCONNECTED_METADATA_KEY = Symbol.for('simple-web-compone
|
|
|
8
8
|
export const ON_BEFORE_ADOPTED_METADATA_KEY = Symbol.for('simple-web-component:on-before-adopted');
|
|
9
9
|
export const ON_AFTER_ADOPTED_METADATA_KEY = Symbol.for('simple-web-component:on-after-adopted');
|
|
10
10
|
export const ON_ADD_EVENT_LISTENER_METADATA_KEY = Symbol.for('simple-web-component:on-add-event-listener');
|
|
11
|
+
export const ON_CONNECTED_SWC_APP_METADATA_KEY = Symbol.for('simple-web-component:on-connected-swc-app');
|
|
11
12
|
export const INNER_HTML_METADATA_KEY = Symbol.for('simple-web-component:inner-html');
|
|
12
13
|
|
|
13
14
|
export const ATTRIBUTE_CHANGED_WILDCARD = '*';
|
|
@@ -48,6 +49,8 @@ export const onAdopted = onAfterAdopted;
|
|
|
48
49
|
|
|
49
50
|
export const onAddEventListener = createLifecycleDecorator(ON_ADD_EVENT_LISTENER_METADATA_KEY);
|
|
50
51
|
|
|
52
|
+
export const onConnectedSwcApp = createLifecycleDecorator(ON_CONNECTED_SWC_APP_METADATA_KEY);
|
|
53
|
+
|
|
51
54
|
/**
|
|
52
55
|
* @onConnectedInnerHtml decorator to define the initial HTML content when connected.
|
|
53
56
|
*/
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { ReflectUtils } from '@dooboostore/core';
|
|
2
|
+
import { ensureInit } from './elementDefine';
|
|
3
|
+
import { SwcUtils } from '../utils/Utils';
|
|
4
|
+
import { SwcQueryOptions } from '../types';
|
|
5
|
+
|
|
6
|
+
export interface PropertySetOptions extends SwcQueryOptions {
|
|
7
|
+
name?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface PropertySetMetadata {
|
|
11
|
+
propertyKey: string | symbol;
|
|
12
|
+
selector: string;
|
|
13
|
+
options: PropertySetOptions;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const PROPERTY_SET_METADATA_KEY = Symbol.for('simple-web-component:property-set');
|
|
17
|
+
|
|
18
|
+
export const setProperty = (selector: string, propertyNameOrOptions?: string | PropertySetOptions, options: PropertySetOptions = {}): MethodDecorator => {
|
|
19
|
+
return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
|
|
20
|
+
const constructor = target.constructor;
|
|
21
|
+
let metaList = ReflectUtils.getOwnMetadata(PROPERTY_SET_METADATA_KEY, constructor) as Map<string | symbol, PropertySetMetadata>;
|
|
22
|
+
if (!metaList) {
|
|
23
|
+
metaList = new Map<string | symbol, PropertySetMetadata>();
|
|
24
|
+
ReflectUtils.defineMetadata(PROPERTY_SET_METADATA_KEY, metaList, constructor);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let propertyName = typeof propertyNameOrOptions === 'string' ? propertyNameOrOptions : undefined;
|
|
28
|
+
let finalOptions = options;
|
|
29
|
+
|
|
30
|
+
if (typeof propertyNameOrOptions === 'object' && propertyNameOrOptions !== null) {
|
|
31
|
+
finalOptions = propertyNameOrOptions as PropertySetOptions;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
metaList.set(propertyKey, {
|
|
35
|
+
propertyKey,
|
|
36
|
+
selector,
|
|
37
|
+
options: { ...finalOptions, name: propertyName }
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const original = descriptor.value;
|
|
41
|
+
descriptor.value = async function (...args: any[]) {
|
|
42
|
+
ensureInit(this);
|
|
43
|
+
const res = await (original as any).apply(this, args);
|
|
44
|
+
if (res !== undefined) {
|
|
45
|
+
const win = (this as any).ownerDocument?.defaultView || window;
|
|
46
|
+
const host = this as unknown as HTMLElement;
|
|
47
|
+
const hostSet = { ...SwcUtils.getHelperAndHostSet(win, host), $this: this };
|
|
48
|
+
const r = finalOptions.root || 'auto';
|
|
49
|
+
const targetEls: HTMLElement[] = [];
|
|
50
|
+
|
|
51
|
+
const applyRoot = (t: any) => {
|
|
52
|
+
if (!t || !(t instanceof win.HTMLElement)) return;
|
|
53
|
+
targetEls.push(t);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
if (selector === ':parentHost') applyRoot(hostSet.$parentHost);
|
|
57
|
+
else if (selector === ':appHost') applyRoot(hostSet.$appHost);
|
|
58
|
+
else if (selector === ':firstHost') applyRoot(hostSet.$firstHost);
|
|
59
|
+
else if (selector === ':lastHost') applyRoot(hostSet.$lastHost);
|
|
60
|
+
else if (selector === ':firstAppHost') applyRoot(hostSet.$firstAppHost);
|
|
61
|
+
else if (selector === ':lastAppHost') applyRoot(hostSet.$lastAppHost);
|
|
62
|
+
else if (selector === ':hosts') hostSet.$hosts.forEach(applyRoot);
|
|
63
|
+
else if (selector === ':appHosts') hostSet.$appHosts.forEach(applyRoot);
|
|
64
|
+
else if (selector === ':host' || !selector) applyRoot(host);
|
|
65
|
+
else {
|
|
66
|
+
const targetRoot = r === 'auto' ? (host.shadowRoot || host) : (r === 'shadow' ? host.shadowRoot : host);
|
|
67
|
+
if (targetRoot) {
|
|
68
|
+
const found = targetRoot.querySelectorAll(selector);
|
|
69
|
+
if (found) targetEls.push(...(Array.from(found) as HTMLElement[]));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
targetEls.forEach(targetEl => {
|
|
74
|
+
const resolvedRes = typeof res === 'function' ? (res as any)(targetEl, hostSet) : res;
|
|
75
|
+
|
|
76
|
+
if (propertyName) {
|
|
77
|
+
// Case: @setProperty(selector, 'propertyName')
|
|
78
|
+
(targetEl as any)[propertyName] = resolvedRes;
|
|
79
|
+
} else if (typeof resolvedRes === 'object' && resolvedRes !== null && !Array.isArray(resolvedRes)) {
|
|
80
|
+
// Case: @setProperty(selector) with Object return - assign multiple properties
|
|
81
|
+
Object.entries(resolvedRes as any).forEach(([prop, val]) => {
|
|
82
|
+
const finalVal = typeof val === 'function' ? val(targetEl, hostSet) : val;
|
|
83
|
+
(targetEl as any)[prop] = finalVal;
|
|
84
|
+
});
|
|
85
|
+
} else {
|
|
86
|
+
// Simple value - assign to 'value' property by default
|
|
87
|
+
(targetEl as any).value = resolvedRes;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export const setPropertyHost = (propertyNameOrOptions?: string | PropertySetOptions, options: PropertySetOptions = {}): MethodDecorator => {
|
|
96
|
+
return setProperty(':host', propertyNameOrOptions, options);
|
|
97
|
+
};
|
|
@@ -42,11 +42,11 @@ export class SwcAppEngine {
|
|
|
42
42
|
|
|
43
43
|
// Router Selection
|
|
44
44
|
if (this._config.routeType === 'path') {
|
|
45
|
-
this.router = new PathRouter({ window: this._config.window
|
|
45
|
+
this.router = new PathRouter({ window: this._config.window });
|
|
46
46
|
} else if (this._config.routeType === 'hash') {
|
|
47
|
-
this.router = new HashRouter({ window: this._config.window
|
|
47
|
+
this.router = new HashRouter({ window: this._config.window });
|
|
48
48
|
} else if (this._config.routeType === 'element') {
|
|
49
|
-
this.router = new ElementRouter({ window: this._config.window
|
|
49
|
+
this.router = new ElementRouter({ window: this._config.window });
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
// console.log('vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv', this.router)
|
|
@@ -2,16 +2,25 @@ import { SwcAppEngine, SwcAttributeConfigType, SwcConfigType } from './SwcAppEng
|
|
|
2
2
|
import { SwcAppInterface } from '../types';
|
|
3
3
|
import { SwcUtils } from '../utils/Utils';
|
|
4
4
|
import { FunctionUtils, Subscription } from '@dooboostore/core';
|
|
5
|
-
import { RouterEventType } from '@dooboostore/core-web';
|
|
5
|
+
import { Router, RouterEventType } from '@dooboostore/core-web';
|
|
6
|
+
import { ON_CONNECTED_SWC_APP_METADATA_KEY, findAllLifecycleMetadata } from '../decorators/lifecycles';
|
|
6
7
|
import { getSubscribeSwcAppRouteChangeMetadata } from '../decorators/subscribeSwcAppRouteChange';
|
|
7
8
|
|
|
8
9
|
export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Base: T) {
|
|
10
|
+
//@ts-ignore
|
|
9
11
|
return class extends Base implements SwcAppInterface {
|
|
10
12
|
__swc_engine = new SwcAppEngine(this as any);
|
|
11
13
|
_swc_connected_instance = new Set<any>();
|
|
12
14
|
_routerSubscription?: Subscription;
|
|
13
15
|
_lastRouterEvent?: RouterEventType;
|
|
14
16
|
|
|
17
|
+
/*
|
|
18
|
+
사파리 is 일경우
|
|
19
|
+
<script src="https://unpkg.com/@ungap/custom-elements"></script>
|
|
20
|
+
이걸사용하는데 is 대응하는거다 그런데 이때 처리되는 순서가 크롬이나 표준에서는 부모부터 만들어지고 자식들이 만들어지는데
|
|
21
|
+
저 polyfill에서는 자식부터 만들어지고 부모가 만들어진다 is일때 아 .. 이문제때문에 자식이 _connected_safari 에 강제로 자기자식넣어준다
|
|
22
|
+
*/
|
|
23
|
+
_connected_safari = [];
|
|
15
24
|
get simpleApplication() {
|
|
16
25
|
return this.__swc_engine.simpleApplication;
|
|
17
26
|
}
|
|
@@ -19,6 +28,11 @@ export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Bas
|
|
|
19
28
|
return this.__swc_engine.router;
|
|
20
29
|
}
|
|
21
30
|
|
|
31
|
+
// constructor() {
|
|
32
|
+
// super();
|
|
33
|
+
// console.log('cccccccccccccccccccccc');
|
|
34
|
+
// }
|
|
35
|
+
|
|
22
36
|
_invokeRouteChangeSubscribers(instance: any, re: RouterEventType) {
|
|
23
37
|
const routeChangeSubscribers = getSubscribeSwcAppRouteChangeMetadata(instance);
|
|
24
38
|
if (routeChangeSubscribers && Array.isArray(routeChangeSubscribers)) {
|
|
@@ -56,20 +70,22 @@ export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Bas
|
|
|
56
70
|
|
|
57
71
|
// Invoke method if conditions pass
|
|
58
72
|
if (pathMatched && filterPassed) {
|
|
59
|
-
instance[methodName]?.(re, pathData
|
|
73
|
+
instance[methodName]?.({...re, pathData: pathData});
|
|
60
74
|
}
|
|
61
75
|
});
|
|
62
76
|
}
|
|
63
77
|
}
|
|
64
78
|
|
|
65
79
|
_connected(instance: any) {
|
|
66
|
-
// console.log('
|
|
80
|
+
// console.log('appmixin--> connected', this, instance);
|
|
67
81
|
if (instance) {
|
|
68
82
|
this._swc_connected_instance.add(instance);
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
this.
|
|
83
|
+
if (this.simpleApplication) {
|
|
84
|
+
this._invokeOnConnectedSwcAppStarted(instance);
|
|
85
|
+
// Notify current route subscribers immediately after connection
|
|
86
|
+
if (this.router && this._lastRouterEvent) {
|
|
87
|
+
this._invokeRouteChangeSubscribers(instance, this._lastRouterEvent);
|
|
88
|
+
}
|
|
73
89
|
}
|
|
74
90
|
}
|
|
75
91
|
}
|
|
@@ -127,19 +143,54 @@ export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Bas
|
|
|
127
143
|
}
|
|
128
144
|
}
|
|
129
145
|
|
|
130
|
-
//
|
|
146
|
+
// 사파리일떄 예외이다 is 일때 polyfill되는데 이떄 부모부터 만들어지는게 아니라 자식부터 만들어진다 그래서 부모가 만들어질때 자식들이 이미 만들어져있어서 부모가 자식들을 등록해주는 형태로 강제로 등록해준다
|
|
147
|
+
this._connected_safari.forEach((instance: any) => {
|
|
148
|
+
this._swc_connected_instance.add(instance);
|
|
149
|
+
});
|
|
150
|
+
// Invoke @onConnectedSwcApp lifecycle methods on all connected component instances
|
|
151
|
+
// const hostSet = SwcUtils.getHostSet(this as any);
|
|
152
|
+
this._swc_connected_instance.forEach((instance: any) => {
|
|
153
|
+
this._invokeOnConnectedSwcAppStarted(instance);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Safari fix: Manually scan DOM tree and register any SWC components that couldn't find parent
|
|
157
|
+
// This handles the case where is="" elements get upgraded in child-first order
|
|
158
|
+
// const allElements = (this as any).querySelectorAll('*');
|
|
159
|
+
// for (const el of allElements) {
|
|
160
|
+
// const isConnected = (el as any).__swc_connected;
|
|
161
|
+
// if (!isConnected && typeof (el as any)._resolveWindow === 'function') {
|
|
162
|
+
// // Element is an SWC component but hasn't registered with app yet
|
|
163
|
+
// try {
|
|
164
|
+
// this._connected(el);
|
|
165
|
+
// if ((el as any)._invokeOnConnectedSwcAppStarted) {
|
|
166
|
+
// this._invokeOnConnectedSwcAppStarted(el);
|
|
167
|
+
// }
|
|
168
|
+
// } catch (e) {
|
|
169
|
+
// console.warn('[SWC] Error registering discovered element:', el.tagName, e);
|
|
170
|
+
// }
|
|
171
|
+
// }
|
|
172
|
+
// }
|
|
173
|
+
|
|
131
174
|
// Subscribe to router changes after connect
|
|
132
175
|
if (!this._routerSubscription && this.router) {
|
|
133
176
|
this._routerSubscription = this.router.observable.subscribe((route: RouterEventType) => {
|
|
134
177
|
// console.log('Route changed:', route);
|
|
135
178
|
this._handleRouteChange(route);
|
|
136
179
|
});
|
|
137
|
-
|
|
138
180
|
// Navigate to initial path if specified
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
181
|
+
const config = this.__swc_engine.config;
|
|
182
|
+
if (config?.path) {
|
|
183
|
+
this.router.go(config.path);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
_invokeOnConnectedSwcAppStarted(instance: any) {
|
|
189
|
+
const startedMethods = findAllLifecycleMetadata(instance, ON_CONNECTED_SWC_APP_METADATA_KEY);
|
|
190
|
+
if (startedMethods) {
|
|
191
|
+
for (const m of startedMethods) {
|
|
192
|
+
instance._invokeLifecycleMethod(m);
|
|
193
|
+
}
|
|
143
194
|
}
|
|
144
195
|
}
|
|
145
196
|
|
|
@@ -177,7 +228,19 @@ export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Bas
|
|
|
177
228
|
}
|
|
178
229
|
|
|
179
230
|
async routing(path: string) {
|
|
180
|
-
await this.
|
|
231
|
+
await this.router?.go(path);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
back(): void {
|
|
235
|
+
this.router?.back();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
forward(): void {
|
|
239
|
+
this.router?.forward();
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
reload(): void {
|
|
243
|
+
this.router?.reload();
|
|
181
244
|
}
|
|
182
245
|
};
|
|
183
246
|
}
|
package/src/elements/SwcAsync.ts
CHANGED
|
@@ -31,7 +31,10 @@ export class SwcAsync extends HTMLTemplateElement {
|
|
|
31
31
|
@changedAttributeHost('on-get-value')
|
|
32
32
|
private refresh() {
|
|
33
33
|
const script = this.getAttribute('on-get-value');
|
|
34
|
-
if (!script)
|
|
34
|
+
if (!script) {
|
|
35
|
+
this.render('default');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
35
38
|
const win = this.ownerDocument?.defaultView || window;
|
|
36
39
|
const result = FunctionUtils.executeReturn({ script, context: this, args: SwcUtils.getHelperAndHostSet(win, this) });
|
|
37
40
|
|
|
@@ -85,6 +88,7 @@ export class SwcAsync extends HTMLTemplateElement {
|
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
connectedCallback() {
|
|
91
|
+
console.log('[SwcAsync] connectedCallback called');
|
|
88
92
|
this.refresh();
|
|
89
93
|
}
|
|
90
94
|
disconnectedCallback() {
|
|
@@ -5,6 +5,7 @@ import { FunctionUtils } from '@dooboostore/core';
|
|
|
5
5
|
export class SwcChoose extends HTMLTemplateElement {
|
|
6
6
|
private _nodes: Node[] = [];
|
|
7
7
|
private _value: any = null;
|
|
8
|
+
private _previousTemplate: HTMLTemplateElement | null = null;
|
|
8
9
|
|
|
9
10
|
get value(): any {
|
|
10
11
|
return this._value;
|
|
@@ -14,76 +15,114 @@ export class SwcChoose extends HTMLTemplateElement {
|
|
|
14
15
|
this.render();
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
private _resolvePortal(): Element | null {
|
|
18
|
-
const portalScript = this.getAttribute('on-get-portal');
|
|
19
|
-
if (!portalScript) return this.parentElement;
|
|
20
|
-
|
|
21
|
-
const win = this.ownerDocument?.defaultView || window;
|
|
22
|
-
const res = FunctionUtils.executeReturn({
|
|
23
|
-
script: portalScript,
|
|
24
|
-
context: this,
|
|
25
|
-
args: SwcUtils.getHelperAndHostSet(win, this)
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
if (res instanceof HTMLElement) return res;
|
|
29
|
-
if (typeof res === 'string') return win.document.querySelector(res);
|
|
30
|
-
return this.parentElement;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
18
|
private _executeCloneCallback(attr: string, args: any) {
|
|
34
19
|
const script = this.getAttribute(attr);
|
|
35
20
|
if (!script) return;
|
|
36
21
|
FunctionUtils.execute({ script, context: this, args });
|
|
37
22
|
}
|
|
38
23
|
|
|
39
|
-
@changedAttributeHost('
|
|
40
|
-
private refresh() {
|
|
41
|
-
|
|
42
|
-
if (
|
|
24
|
+
@changedAttributeHost('value')
|
|
25
|
+
private refresh(valueAttr?: string | null) {
|
|
26
|
+
valueAttr ??= this.getAttribute('value');
|
|
27
|
+
if (valueAttr === null) {
|
|
43
28
|
this.value = null;
|
|
44
29
|
return;
|
|
45
30
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
31
|
+
|
|
32
|
+
// {{ }} 브레이스로 감싸진 값은 스크립트 실행
|
|
33
|
+
if (valueAttr.startsWith('{{') && valueAttr.endsWith('}}')) {
|
|
34
|
+
const script = valueAttr.slice(2, -2).trim();
|
|
35
|
+
const win = this.ownerDocument?.defaultView || window;
|
|
36
|
+
const result = FunctionUtils.executeReturn({ script, context: this, args: SwcUtils.getHelperAndHostSet(win, this) });
|
|
37
|
+
this.value = result;
|
|
38
|
+
} else {
|
|
39
|
+
// 일반 문자열 값
|
|
40
|
+
this.value = valueAttr;
|
|
41
|
+
}
|
|
49
42
|
}
|
|
50
43
|
|
|
51
44
|
private render() {
|
|
52
|
-
this.cleanup();
|
|
53
|
-
const portal = this._resolvePortal();
|
|
54
|
-
if (!portal) return;
|
|
55
|
-
|
|
56
45
|
const win = this.ownerDocument?.defaultView || window;
|
|
57
46
|
const helperSet = SwcUtils.getHelperAndHostSet(win, this);
|
|
58
|
-
|
|
59
47
|
const templates = Array.from(this.content.querySelectorAll('template'));
|
|
60
48
|
let selected: HTMLTemplateElement | null = null;
|
|
49
|
+
|
|
61
50
|
for (const t of templates) {
|
|
62
|
-
if (t.getAttribute('is') === 'swc-when'
|
|
63
|
-
|
|
64
|
-
|
|
51
|
+
if (t.getAttribute('is') === 'swc-when') {
|
|
52
|
+
let matches = false;
|
|
53
|
+
const value = t.getAttribute('value') || '';
|
|
54
|
+
|
|
55
|
+
// {{ }} 브레이스로 감싸진 값은 스크립트 실행
|
|
56
|
+
if (value.startsWith('{{') && value.endsWith('}}')) {
|
|
57
|
+
const script = value.slice(2, -2).trim();
|
|
58
|
+
const result = FunctionUtils.executeReturn({
|
|
59
|
+
script,
|
|
60
|
+
context: t,
|
|
61
|
+
args: { ...helperSet, $value: this._value }
|
|
62
|
+
});
|
|
63
|
+
// console.log('rrrrrrrrrrrrrr', result);
|
|
64
|
+
matches = result === true;
|
|
65
|
+
} else {
|
|
66
|
+
// 일반 문자열 비교 (기존 방식)
|
|
67
|
+
matches = String(value) === String(this._value);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (matches) {
|
|
71
|
+
selected = t;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
65
74
|
}
|
|
66
75
|
}
|
|
76
|
+
|
|
67
77
|
const target = selected || (this.content.querySelector('template[is="swc-otherwise"]') as HTMLTemplateElement);
|
|
68
78
|
|
|
79
|
+
// skip-if-same attribute가 있고 이전과 같은 template이면 렌더링 스킵
|
|
80
|
+
// 최상위 skip-if-same 또는 각 when/otherwise의 skip-if-same 체크
|
|
81
|
+
const targetHasSkipIfSame = target?.hasAttribute('skip-if-same');
|
|
82
|
+
const shouldSkip = (this.hasAttribute('skip-if-same') || targetHasSkipIfSame) && this._previousTemplate === target;
|
|
83
|
+
if (shouldSkip) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
this.cleanup();
|
|
88
|
+
this._previousTemplate = target;
|
|
89
|
+
|
|
69
90
|
if (target) {
|
|
70
91
|
const clone = target.content.cloneNode(true) as DocumentFragment;
|
|
71
92
|
this._nodes = Array.from(clone.childNodes);
|
|
72
93
|
const elements = this._nodes.filter(n => n.nodeType === 1) as HTMLElement[];
|
|
73
94
|
const groupArgs = { ...helperSet, $value: this._value, $nodes: this._nodes, $elements: elements, $firstElement: elements[0] };
|
|
74
95
|
|
|
96
|
+
// 복제된 최상위 요소들은 SwcChoose의 직접 자식이 될 것이므로 __swc_host 설정 안 함
|
|
75
97
|
this._nodes.forEach((n, nodeIdx) => {
|
|
76
|
-
if (n instanceof HTMLElement) (n as any).__swc_host = this;
|
|
98
|
+
// if (n instanceof HTMLElement) (n as any).__swc_host = this; // 제거: 부모 체인 유지
|
|
77
99
|
this._executeCloneCallback('on-clone-node', { ...groupArgs, $node: n, $nodeIndex: nodeIdx, $isElement: n.nodeType === 1 });
|
|
100
|
+
|
|
101
|
+
// Attribute {{ }} 치환 - HTML string 차원에서 동적 치환
|
|
102
|
+
if (n instanceof HTMLElement) {
|
|
103
|
+
Array.from(n.attributes).forEach(attr => {
|
|
104
|
+
const value = attr.value || '';
|
|
105
|
+
if (value.startsWith('{{') && value.endsWith('}}')) {
|
|
106
|
+
const script = value.slice(2, -2).trim();
|
|
107
|
+
const result = FunctionUtils.executeReturn({
|
|
108
|
+
script,
|
|
109
|
+
context: n,
|
|
110
|
+
args: { ...groupArgs, $value: this._value }
|
|
111
|
+
});
|
|
112
|
+
n.setAttribute(attr.name, String(result));
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
78
116
|
});
|
|
79
117
|
|
|
80
118
|
this._executeCloneCallback('on-clone-nodes', groupArgs);
|
|
81
119
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
120
|
+
this.parentElement?.insertBefore(clone, this.nextSibling);
|
|
121
|
+
// if (portal === this.parentElement) {
|
|
122
|
+
// portal.insertBefore(clone, this.nextSibling);
|
|
123
|
+
// } else {
|
|
124
|
+
// portal.appendChild(clone);
|
|
125
|
+
// }
|
|
87
126
|
}
|
|
88
127
|
}
|
|
89
128
|
|