@dooboostore/simple-web-component 1.0.33 → 1.0.35
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 +23 -30
- package/dist/cjs/decorators/addEventListener.js.map +1 -1
- package/dist/cjs/decorators/applyAttribute.js +67 -57
- package/dist/cjs/decorators/applyAttribute.js.map +2 -2
- package/dist/cjs/decorators/applyClass.js +80 -70
- package/dist/cjs/decorators/applyClass.js.map +2 -2
- package/dist/cjs/decorators/applyNode.js +5 -8
- package/dist/cjs/decorators/applyNode.js.map +2 -2
- package/dist/cjs/decorators/applyStyle.js +66 -56
- package/dist/cjs/decorators/applyStyle.js.map +2 -2
- package/dist/cjs/decorators/attribute.js +35 -29
- package/dist/cjs/decorators/attribute.js.map +2 -2
- package/dist/cjs/decorators/changedAttributeHost.js +32 -12
- package/dist/cjs/decorators/changedAttributeHost.js.map +2 -2
- package/dist/cjs/decorators/elementDefine.js +238 -180
- package/dist/cjs/decorators/elementDefine.js.map +2 -2
- package/dist/cjs/decorators/emitCustomEvent.js +67 -48
- package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
- package/dist/cjs/decorators/lifecycles.js +15 -17
- package/dist/cjs/decorators/lifecycles.js.map +2 -2
- package/dist/cjs/decorators/setProperty.js +50 -39
- package/dist/cjs/decorators/setProperty.js.map +2 -2
- package/dist/cjs/decorators/subscribeSwcAppMessageWhileConnected.js.map +1 -1
- package/dist/cjs/decorators/subscribeSwcAppRouteChangeWhileConnected.js +2 -2
- package/dist/cjs/decorators/subscribeSwcAppRouteChangeWhileConnected.js.map +2 -2
- package/dist/cjs/elements/SwcAppEngine.js +14 -8
- package/dist/cjs/elements/SwcAppEngine.js.map +3 -3
- package/dist/cjs/elements/SwcAppMixin.js +154 -81
- package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
- package/dist/cjs/elements/SwcAsync.js +28 -18
- package/dist/cjs/elements/SwcAsync.js.map +2 -2
- package/dist/cjs/elements/SwcChoose.js +68 -45
- package/dist/cjs/elements/SwcChoose.js.map +2 -2
- package/dist/cjs/elements/SwcIf.js +52 -30
- package/dist/cjs/elements/SwcIf.js.map +2 -2
- package/dist/cjs/elements/SwcLoop.js +109 -35
- package/dist/cjs/elements/SwcLoop.js.map +2 -2
- package/dist/cjs/elements/register.js +263 -131
- package/dist/cjs/elements/register.js.map +2 -2
- package/dist/cjs/router/ElementRouter.js +4 -2
- package/dist/cjs/router/ElementRouter.js.map +1 -1
- package/dist/cjs/types.js.map +1 -1
- package/dist/cjs/utils/Utils.js +25 -7
- package/dist/cjs/utils/Utils.js.map +2 -2
- package/dist/esm/decorators/addEventListener.js.map +1 -1
- package/dist/esm/decorators/applyAttribute.js +67 -57
- package/dist/esm/decorators/applyAttribute.js.map +2 -2
- package/dist/esm/decorators/applyClass.js +80 -70
- package/dist/esm/decorators/applyClass.js.map +2 -2
- package/dist/esm/decorators/applyNode.js +5 -8
- package/dist/esm/decorators/applyNode.js.map +2 -2
- package/dist/esm/decorators/applyStyle.js +66 -56
- package/dist/esm/decorators/applyStyle.js.map +2 -2
- package/dist/esm/decorators/attribute.js +35 -29
- package/dist/esm/decorators/attribute.js.map +2 -2
- package/dist/esm/decorators/changedAttributeHost.js +32 -12
- package/dist/esm/decorators/changedAttributeHost.js.map +2 -2
- package/dist/esm/decorators/elementDefine.js +240 -182
- package/dist/esm/decorators/elementDefine.js.map +2 -2
- package/dist/esm/decorators/emitCustomEvent.js +67 -48
- package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
- package/dist/esm/decorators/lifecycles.js +15 -17
- package/dist/esm/decorators/lifecycles.js.map +2 -2
- package/dist/esm/decorators/setProperty.js +50 -39
- package/dist/esm/decorators/setProperty.js.map +2 -2
- package/dist/esm/decorators/subscribeSwcAppMessageWhileConnected.js.map +1 -1
- package/dist/esm/decorators/subscribeSwcAppRouteChangeWhileConnected.js +2 -2
- package/dist/esm/decorators/subscribeSwcAppRouteChangeWhileConnected.js.map +2 -2
- package/dist/esm/elements/SwcAppEngine.js +14 -7
- package/dist/esm/elements/SwcAppEngine.js.map +2 -2
- package/dist/esm/elements/SwcAppMixin.js +156 -82
- package/dist/esm/elements/SwcAppMixin.js.map +2 -2
- package/dist/esm/elements/SwcAsync.js +28 -18
- package/dist/esm/elements/SwcAsync.js.map +2 -2
- package/dist/esm/elements/SwcChoose.js +69 -46
- package/dist/esm/elements/SwcChoose.js.map +2 -2
- package/dist/esm/elements/SwcIf.js +53 -31
- package/dist/esm/elements/SwcIf.js.map +2 -2
- package/dist/esm/elements/SwcLoop.js +110 -36
- package/dist/esm/elements/SwcLoop.js.map +2 -2
- package/dist/esm/elements/register.js +264 -132
- package/dist/esm/elements/register.js.map +2 -2
- package/dist/esm/router/ElementRouter.js +5 -2
- package/dist/esm/router/ElementRouter.js.map +1 -1
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/utils/Utils.js +25 -7
- package/dist/esm/utils/Utils.js.map +2 -2
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +728 -595
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
- package/dist/types/decorators/addEventListener.d.ts +4 -1
- package/dist/types/decorators/addEventListener.d.ts.map +1 -1
- package/dist/types/decorators/applyAttribute.d.ts +5 -1
- package/dist/types/decorators/applyAttribute.d.ts.map +1 -1
- package/dist/types/decorators/applyClass.d.ts +4 -0
- package/dist/types/decorators/applyClass.d.ts.map +1 -1
- package/dist/types/decorators/applyNode.d.ts +5 -1
- package/dist/types/decorators/applyNode.d.ts.map +1 -1
- package/dist/types/decorators/applyStyle.d.ts +5 -1
- package/dist/types/decorators/applyStyle.d.ts.map +1 -1
- package/dist/types/decorators/attribute.d.ts +5 -0
- package/dist/types/decorators/attribute.d.ts.map +1 -1
- package/dist/types/decorators/changedAttributeHost.d.ts +14 -3
- package/dist/types/decorators/changedAttributeHost.d.ts.map +1 -1
- package/dist/types/decorators/elementDefine.d.ts +1 -1
- package/dist/types/decorators/elementDefine.d.ts.map +1 -1
- package/dist/types/decorators/emitCustomEvent.d.ts +15 -7
- package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
- package/dist/types/decorators/lifecycles.d.ts +10 -7
- package/dist/types/decorators/lifecycles.d.ts.map +1 -1
- package/dist/types/decorators/setProperty.d.ts +5 -1
- package/dist/types/decorators/setProperty.d.ts.map +1 -1
- package/dist/types/decorators/subscribeSwcAppMessageWhileConnected.d.ts +2 -2
- package/dist/types/decorators/subscribeSwcAppMessageWhileConnected.d.ts.map +1 -1
- package/dist/types/decorators/subscribeSwcAppRouteChangeWhileConnected.d.ts +5 -6
- package/dist/types/decorators/subscribeSwcAppRouteChangeWhileConnected.d.ts.map +1 -1
- package/dist/types/elements/SwcAppEngine.d.ts +9 -3
- package/dist/types/elements/SwcAppEngine.d.ts.map +1 -1
- package/dist/types/elements/SwcAppMixin.d.ts +12 -7
- package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
- package/dist/types/elements/register.d.ts.map +1 -1
- package/dist/types/types.d.ts +1 -0
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils/Utils.d.ts +4 -1
- package/dist/types/utils/Utils.d.ts.map +1 -1
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +728 -595
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
- package/package.json +5 -5
- package/src/decorators/addEventListener.ts +1 -1
- package/src/decorators/applyAttribute.ts +74 -61
- package/src/decorators/applyClass.ts +91 -77
- package/src/decorators/applyNode.ts +16 -13
- package/src/decorators/applyStyle.ts +75 -61
- package/src/decorators/attribute.ts +55 -43
- package/src/decorators/changedAttributeHost.ts +49 -15
- package/src/decorators/elementDefine.ts +401 -340
- package/src/decorators/emitCustomEvent.ts +92 -62
- package/src/decorators/lifecycles.ts +11 -10
- package/src/decorators/setProperty.ts +58 -44
- package/src/decorators/subscribeSwcAppMessageWhileConnected.ts +2 -2
- package/src/decorators/subscribeSwcAppRouteChangeWhileConnected.ts +11 -11
- package/src/elements/SwcAppEngine.ts +19 -13
- package/src/elements/SwcAppMixin.ts +214 -102
- package/src/elements/SwcAsync.ts +28 -17
- package/src/elements/SwcChoose.ts +94 -36
- package/src/elements/SwcIf.ts +59 -22
- package/src/elements/SwcLoop.ts +140 -27
- package/src/elements/register.ts +319 -100
- package/src/types.ts +1 -0
- package/src/utils/Utils.ts +38 -10
- package/tsconfig.json +2 -2
package/src/elements/register.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { elementDefine, attributeHost, changedAttributeHost } from '../decorators';
|
|
1
|
+
import { getElementConfig, elementDefine, attributeHost, changedAttributeHost, getAttributeValue } from '../decorators';
|
|
2
2
|
import { SwcAppMixin } from './SwcAppMixin';
|
|
3
3
|
import { SwcUtils } from '../utils/Utils';
|
|
4
4
|
import { FunctionUtils,ActionExpression } from '@dooboostore/core';
|
|
@@ -148,11 +148,17 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
148
148
|
|
|
149
149
|
@elementDefine('swc-if', { extends: 'template', window: w })
|
|
150
150
|
class SwcIf extends HTMLTemplateElement {
|
|
151
|
-
|
|
151
|
+
// id =
|
|
152
|
+
// @attributeHost('value')
|
|
152
153
|
_value: any;
|
|
153
154
|
|
|
154
|
-
@attributeHost('replace-wrap')
|
|
155
|
-
|
|
155
|
+
@attributeHost('replace-wrap-start')
|
|
156
|
+
_replaceWrapStart: string | null;
|
|
157
|
+
@attributeHost('replace-wrap-end')
|
|
158
|
+
_replaceWrapEnd: string | null;
|
|
159
|
+
|
|
160
|
+
@attributeHost('skip-if-same')
|
|
161
|
+
_skipIfSame: string | null;
|
|
156
162
|
|
|
157
163
|
private _nodes: Node[] = [];
|
|
158
164
|
|
|
@@ -165,14 +171,37 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
165
171
|
this.refresh(nv);
|
|
166
172
|
}
|
|
167
173
|
|
|
168
|
-
|
|
169
|
-
|
|
174
|
+
constructor() {
|
|
175
|
+
super();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@changedAttributeHost('value')
|
|
179
|
+
private setValue(value: any, o: string, n: string) {
|
|
180
|
+
this._value = value;
|
|
181
|
+
this.refresh(this._value);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// @changedAttributeHost('replace-wrap')
|
|
185
|
+
// private setReplaceWrap(replaceWrapAttr?: string | null) {
|
|
186
|
+
// this.refresh();
|
|
187
|
+
// }
|
|
188
|
+
|
|
189
|
+
private replaceExpressions(html: string, groupArgs: any, context: any, wrap: {start: string, end: string}): string {
|
|
190
|
+
let config: any = undefined;
|
|
191
|
+
if (wrap) {
|
|
192
|
+
config = {
|
|
193
|
+
expression: {
|
|
194
|
+
replace: { start: `${wrap.start}`, end: `${wrap.end}` },
|
|
195
|
+
callReturn: { start: `${wrap.start}=`, end: `${wrap.end}` },
|
|
196
|
+
call: { start: `${wrap.start}@`, end: `${wrap.end}` }
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
}
|
|
170
200
|
const ae = new ActionExpression(html, config);
|
|
171
|
-
const filterOptions = wrap ? { type: 'replace' as const, wrap } : 'replace';
|
|
172
201
|
const win = this.ownerDocument?.defaultView || window;
|
|
173
|
-
|
|
202
|
+
|
|
174
203
|
// @ts-ignore
|
|
175
|
-
for (const expr of ae.getExpressions(
|
|
204
|
+
for (const expr of ae.getExpressions('replace')) {
|
|
176
205
|
try {
|
|
177
206
|
const value = FunctionUtils.executeReturn({
|
|
178
207
|
script: ConvertUtils.decodeHtmlEntity(expr.script, win.document),
|
|
@@ -187,39 +216,47 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
187
216
|
return ae.getUnprocessedTemplate();
|
|
188
217
|
}
|
|
189
218
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
this.refresh();
|
|
193
|
-
}
|
|
219
|
+
refresh(value?: any) {
|
|
220
|
+
const targetValue = value !== undefined ? value : (getAttributeValue(this, 'value') ?? this._value);
|
|
194
221
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
222
|
+
// skip-if-same 속성이 존재하고(true/빈 문자열), 이전 값과 새로운 값이 완전히 동일하면 렌더링 스킵!
|
|
223
|
+
if (this.hasAttribute('skip-if-same') && this._value === targetValue && this._nodes.length > 0) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
199
226
|
|
|
200
|
-
refresh(value = this._value) {
|
|
201
227
|
this.cleanup();
|
|
228
|
+
this._value = targetValue;
|
|
229
|
+
|
|
202
230
|
const portal = this.parentElement;
|
|
203
|
-
if (!portal || !
|
|
231
|
+
if (!portal || !this._value) return;
|
|
204
232
|
|
|
205
233
|
const win = this.ownerDocument?.defaultView || window;
|
|
206
234
|
const helperSet = SwcUtils.getHelperAndHostSet(win, this);
|
|
207
235
|
|
|
208
236
|
let htmlString = this.innerHTML;
|
|
209
|
-
const groupArgs = { ...helperSet, $value:
|
|
237
|
+
const groupArgs = { ...helperSet, $value: this._value, $templateHost: this };
|
|
210
238
|
|
|
211
|
-
htmlString = this.replaceExpressions(htmlString, groupArgs, this, this.
|
|
239
|
+
htmlString = this.replaceExpressions(htmlString, groupArgs, this, {start:this._replaceWrapStart ?? '{#{', end: this._replaceWrapEnd ?? '}#}'});
|
|
212
240
|
|
|
213
241
|
const result = this.ownerDocument?.createElement('template') || document.createElement('template');
|
|
214
242
|
result.innerHTML = htmlString;
|
|
215
243
|
const processedFragment = result.content;
|
|
216
244
|
|
|
217
245
|
this._nodes = Array.from(processedFragment.childNodes);
|
|
246
|
+
this._nodes.forEach((node: any) => {
|
|
247
|
+
if (node instanceof HTMLElement) (node as any).__swc_template_host = this;
|
|
248
|
+
});
|
|
249
|
+
|
|
218
250
|
portal.insertBefore(processedFragment, this.nextSibling);
|
|
219
251
|
}
|
|
220
252
|
|
|
221
253
|
private cleanup() {
|
|
222
|
-
this._nodes.forEach(n =>
|
|
254
|
+
this._nodes.forEach(n => {
|
|
255
|
+
const realNode = (n as any).__upgraded_instance || n;
|
|
256
|
+
if (realNode.parentElement) {
|
|
257
|
+
realNode.parentElement.removeChild(realNode);
|
|
258
|
+
}
|
|
259
|
+
});
|
|
223
260
|
this._nodes = [];
|
|
224
261
|
}
|
|
225
262
|
|
|
@@ -230,43 +267,64 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
230
267
|
|
|
231
268
|
@elementDefine('swc-loop', { extends: 'template', window: w })
|
|
232
269
|
class SwcLoop extends HTMLTemplateElement {
|
|
233
|
-
|
|
234
|
-
_value: any[];
|
|
270
|
+
_value: any[] = [];
|
|
235
271
|
|
|
236
|
-
@attributeHost('replace-wrap')
|
|
237
|
-
|
|
272
|
+
@attributeHost('replace-wrap-start')
|
|
273
|
+
_replaceWrapStart: string | null;
|
|
274
|
+
@attributeHost('replace-wrap-end')
|
|
275
|
+
_replaceWrapEnd: string | null;
|
|
238
276
|
|
|
239
277
|
private _nodeGroups: Node[][] = [];
|
|
240
278
|
|
|
241
279
|
get value(): any[] {
|
|
242
280
|
return this._value;
|
|
243
281
|
}
|
|
282
|
+
|
|
244
283
|
set value(nv: any[]) {
|
|
245
|
-
|
|
284
|
+
this._value = nv;
|
|
246
285
|
this.refresh(nv);
|
|
247
286
|
}
|
|
248
287
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
this.refresh();
|
|
288
|
+
getValue(index: number) {
|
|
289
|
+
return this._value?.[index];
|
|
252
290
|
}
|
|
253
291
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
292
|
+
constructor() {
|
|
293
|
+
super();
|
|
294
|
+
// console.log('swc SwcLoop constructor called!');
|
|
295
|
+
// console.log('swc SwcLoop', this.getAttribute('value'));
|
|
257
296
|
}
|
|
258
297
|
|
|
259
|
-
|
|
260
|
-
|
|
298
|
+
@changedAttributeHost('value')
|
|
299
|
+
private setValue(value: any, o: string, n: string) {
|
|
300
|
+
this._value = value;
|
|
301
|
+
this.refresh(this._value);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// @changedAttributeHost('replace-wrap')
|
|
305
|
+
// private setReplaceWrap(replaceWrapAttr?: string | null) {
|
|
306
|
+
// this.refresh();
|
|
307
|
+
// }
|
|
308
|
+
|
|
309
|
+
private replaceExpressions(html: string, groupArgs: any, context: any, wrap: {start: string, end: string}): string {
|
|
310
|
+
let config: any = undefined;
|
|
311
|
+
config = {
|
|
312
|
+
expression: {
|
|
313
|
+
replace: { start: `${wrap.start}`, end: `${wrap.end}` },
|
|
314
|
+
callReturn: { start: `${wrap.start}=`, end: `${wrap.end}` },
|
|
315
|
+
call: { start: `${wrap.start}@`, end: `${wrap.end}` }
|
|
316
|
+
}
|
|
317
|
+
};
|
|
261
318
|
const ae = new ActionExpression(html, config);
|
|
262
|
-
const filterOptions = wrap ? { type: 'replace' as const, wrap } : 'replace';
|
|
263
319
|
const win = this.ownerDocument?.defaultView || window;
|
|
264
320
|
|
|
265
321
|
// @ts-ignore
|
|
266
|
-
|
|
322
|
+
const expressions = ae.getExpressions('replace');
|
|
323
|
+
for (const expr of expressions) {
|
|
324
|
+
const script = ConvertUtils.decodeHtmlEntity(expr.script, win.document);
|
|
267
325
|
try {
|
|
268
326
|
const value = FunctionUtils.executeReturn({
|
|
269
|
-
script:
|
|
327
|
+
script: script,
|
|
270
328
|
context,
|
|
271
329
|
args: groupArgs
|
|
272
330
|
});
|
|
@@ -278,35 +336,127 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
278
336
|
return ae.getUnprocessedTemplate();
|
|
279
337
|
}
|
|
280
338
|
|
|
281
|
-
|
|
282
|
-
this.cleanup();
|
|
283
|
-
if (value?.length<=0) return;
|
|
284
|
-
const portal = this.parentElement;
|
|
285
|
-
if (!portal) return;
|
|
286
|
-
|
|
339
|
+
private createFragmentAndNodes(items: any[], helperSet: any, startIndex: number = 0): { fragment: DocumentFragment; newNodesGroup: Node[][] } {
|
|
287
340
|
const win = this.ownerDocument?.defaultView || window;
|
|
288
|
-
const helperSet = SwcUtils.getHelperAndHostSet(win, this);
|
|
289
341
|
const fragment = win.document.createDocumentFragment();
|
|
342
|
+
const newNodesGroup: Node[][] = [];
|
|
290
343
|
|
|
291
|
-
|
|
344
|
+
items.forEach((item, i) => {
|
|
345
|
+
const index = startIndex + i;
|
|
292
346
|
let htmlString = this.innerHTML;
|
|
293
347
|
const groupArgs = { ...helperSet, $item: item, $index: index, $value: this._value };
|
|
294
348
|
|
|
295
|
-
htmlString = this.replaceExpressions(htmlString, groupArgs, this, this.
|
|
349
|
+
htmlString = this.replaceExpressions(htmlString, groupArgs, this, {start:this._replaceWrapStart ?? '{#{', end: this._replaceWrapEnd ?? '}#}'});
|
|
296
350
|
|
|
297
351
|
const temp = this.ownerDocument?.createElement('template') || document.createElement('template');
|
|
298
352
|
temp.innerHTML = htmlString;
|
|
299
353
|
|
|
300
354
|
const content = temp.content;
|
|
301
355
|
const nodes = Array.from(content.childNodes);
|
|
302
|
-
|
|
356
|
+
|
|
357
|
+
const setTemplateHost = (element: HTMLElement) => {
|
|
358
|
+
(element as any).__swc_template_host = this;
|
|
359
|
+
Array.from(element.children).forEach((child: any) => {
|
|
360
|
+
if (child instanceof HTMLElement) {
|
|
361
|
+
setTemplateHost(child);
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
nodes.forEach((node: any) => {
|
|
367
|
+
if (node instanceof HTMLElement) {
|
|
368
|
+
setTemplateHost(node as HTMLElement);
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
newNodesGroup.push(nodes);
|
|
303
372
|
fragment.appendChild(content);
|
|
304
373
|
});
|
|
305
374
|
|
|
375
|
+
return { fragment, newNodesGroup };
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
appendItem(...items: any[]) {
|
|
379
|
+
if (!items || items.length <= 0) return;
|
|
380
|
+
const portal = SwcUtils.getParentContainer(this);
|
|
381
|
+
if (!portal) return;
|
|
382
|
+
|
|
383
|
+
const win = this.ownerDocument?.defaultView || window;
|
|
384
|
+
const helperSet = SwcUtils.getHelperAndHostSet(win, this);
|
|
385
|
+
|
|
386
|
+
const startIndex = this._value ? this._value.length : 0;
|
|
387
|
+
|
|
388
|
+
// 내부 상태(value) 업데이트 (기존 배열에 새 아이템 추가)
|
|
389
|
+
if (this._value !== items) {
|
|
390
|
+
this._value = [...(this._value || []), ...items];
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const { fragment, newNodesGroup } = this.createFragmentAndNodes(items, helperSet, startIndex);
|
|
394
|
+
this._nodeGroups.push(...newNodesGroup);
|
|
395
|
+
|
|
396
|
+
console.log('뭐야 씨발');
|
|
397
|
+
// append 위치 계산: 기존에 그려진 마지막 노드 뒤에 삽입, 없으면 템플릿 바로 뒤에 삽입
|
|
398
|
+
let insertReference: Node | null = this.nextSibling;
|
|
399
|
+
if (this._nodeGroups.length > items.length) {
|
|
400
|
+
const lastExistingGroup = this._nodeGroups[this._nodeGroups.length - items.length - 1];
|
|
401
|
+
if (lastExistingGroup && lastExistingGroup.length > 0) {
|
|
402
|
+
const lastNode = lastExistingGroup[lastExistingGroup.length - 1];
|
|
403
|
+
insertReference = lastNode.nextSibling;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
portal.insertBefore(fragment, insertReference);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
async prependItem(...items: any[]) {
|
|
411
|
+
if (!items || items.length <= 0) return;
|
|
412
|
+
const portal = SwcUtils.getParentContainer(this);
|
|
413
|
+
if (!portal) return;
|
|
414
|
+
|
|
415
|
+
const win = this.ownerDocument?.defaultView || window;
|
|
416
|
+
const helperSet = SwcUtils.getHelperAndHostSet(win, this);
|
|
417
|
+
|
|
418
|
+
// 내부 상태(value) 업데이트 (기존 배열의 앞쪽에 새 아이템 추가)
|
|
419
|
+
if (this._value !== items) {
|
|
420
|
+
this._value = [...items, ...(this._value || [])];
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const { fragment, newNodesGroup } = this.createFragmentAndNodes(items, helperSet, 0);
|
|
424
|
+
|
|
425
|
+
// 기존의 nodeGroups 배열 맨 앞에 새로운 그룹들을 추가
|
|
426
|
+
this._nodeGroups = [...newNodesGroup, ...this._nodeGroups];
|
|
427
|
+
|
|
428
|
+
// prepend 위치: 이 템플릿(SwcLoop) 노드의 바로 다음 위치 (가장 위)
|
|
306
429
|
portal.insertBefore(fragment, this.nextSibling);
|
|
307
430
|
}
|
|
308
431
|
|
|
432
|
+
refresh(value?: any) {
|
|
433
|
+
// 1. 그릴 대상 확정
|
|
434
|
+
const targetValue = value !== undefined ? value : (getAttributeValue(this, 'value') ?? this._value ?? []);
|
|
435
|
+
|
|
436
|
+
// 2. 화면 정리
|
|
437
|
+
this.cleanup();
|
|
438
|
+
|
|
439
|
+
// 3. 상태 완전 교체 (이어붙이지 않음!)
|
|
440
|
+
this._value = targetValue;
|
|
441
|
+
|
|
442
|
+
if (!this._value || this._value.length <= 0) return;
|
|
443
|
+
|
|
444
|
+
// 4. 화면 다시 그리기 (appendItem을 쓰지 않고 바로 그리기)
|
|
445
|
+
const win = this.ownerDocument?.defaultView || window;
|
|
446
|
+
const helperSet = SwcUtils.getHelperAndHostSet(win, this);
|
|
447
|
+
helperSet.$templateHost = this;
|
|
448
|
+
const { fragment, newNodesGroup } = this.createFragmentAndNodes(this._value, helperSet, 0);
|
|
449
|
+
|
|
450
|
+
this._nodeGroups = newNodesGroup;
|
|
451
|
+
const portal = SwcUtils.getParentContainer(this);
|
|
452
|
+
if (portal) {
|
|
453
|
+
// console.log('append????!~~~~~!?',fragment)
|
|
454
|
+
portal.insertBefore(fragment, this.nextSibling);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
309
458
|
private cleanup() {
|
|
459
|
+
console.log('누가 cleanup');
|
|
310
460
|
this._nodeGroups.forEach(nodes => nodes.forEach(n => n.parentElement?.removeChild(n)));
|
|
311
461
|
this._nodeGroups = [];
|
|
312
462
|
}
|
|
@@ -318,11 +468,12 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
318
468
|
|
|
319
469
|
@elementDefine('swc-choose', { extends: 'template', window: w })
|
|
320
470
|
class SwcChoose extends HTMLTemplateElement {
|
|
321
|
-
@attributeHost('value')
|
|
322
471
|
_value: any;
|
|
323
472
|
|
|
324
|
-
@attributeHost('replace-wrap')
|
|
325
|
-
|
|
473
|
+
@attributeHost('replace-wrap-start')
|
|
474
|
+
_replaceWrapStart: string | null;
|
|
475
|
+
@attributeHost('replace-wrap-end')
|
|
476
|
+
_replaceWrapEnd: string | null;
|
|
326
477
|
|
|
327
478
|
private _nodes: Node[] = [];
|
|
328
479
|
private _previousTemplate: HTMLTemplateElement | null = null;
|
|
@@ -332,27 +483,52 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
332
483
|
}
|
|
333
484
|
|
|
334
485
|
set value(nv: any) {
|
|
335
|
-
this.
|
|
486
|
+
this._value = nv;
|
|
487
|
+
this.refresh(this._value);
|
|
336
488
|
}
|
|
337
489
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
490
|
+
constructor() {
|
|
491
|
+
super();
|
|
492
|
+
// console.log('swc chooooooooooooooooooooooooose constructor called!');
|
|
493
|
+
// console.log('swc cccccccss', this.getAttribute('value'));
|
|
341
494
|
}
|
|
342
495
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
496
|
+
// static get observedAttributes() {
|
|
497
|
+
// return ['value'];
|
|
498
|
+
// }
|
|
499
|
+
|
|
500
|
+
attributeChangedCallback(na, o, n) {
|
|
501
|
+
// console.log('-----------------choooooooose attr origin', na, o, n);
|
|
346
502
|
}
|
|
347
503
|
|
|
348
|
-
|
|
349
|
-
|
|
504
|
+
@changedAttributeHost('value')
|
|
505
|
+
private setValue(value: any, o: string, n: string) {
|
|
506
|
+
console.log('chooooooose value', value)
|
|
507
|
+
this._value = value;
|
|
508
|
+
this.refresh(this._value);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// @changedAttributeHost('replace-wrap')
|
|
512
|
+
// private setReplaceWrap(replaceWrapAttr?: string | null) {
|
|
513
|
+
// this.refresh();
|
|
514
|
+
// }
|
|
515
|
+
|
|
516
|
+
private replaceExpressions(html: string, groupArgs: any, context: any, wrap: {start: string, end: string}): string {
|
|
517
|
+
let config: any = undefined;
|
|
518
|
+
if (wrap) {
|
|
519
|
+
config = {
|
|
520
|
+
expression: {
|
|
521
|
+
replace: { start: `${wrap.start}`, end: `${wrap.end}` },
|
|
522
|
+
callReturn: { start: `${wrap.start}=`, end: `${wrap.end}` },
|
|
523
|
+
call: { start: `${wrap.start}@`, end: `${wrap.end}` }
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
}
|
|
350
527
|
const ae = new ActionExpression(html, config);
|
|
351
|
-
const filterOptions = wrap ? { type: 'replace' as const, wrap } : 'replace';
|
|
352
528
|
const win = this.ownerDocument?.defaultView || window;
|
|
353
529
|
|
|
354
530
|
// @ts-ignore
|
|
355
|
-
for (const expr of ae.getExpressions(
|
|
531
|
+
for (const expr of ae.getExpressions('replace')) {
|
|
356
532
|
try {
|
|
357
533
|
const value = FunctionUtils.executeReturn({
|
|
358
534
|
script: ConvertUtils.decodeHtmlEntity(expr.script, win.document),
|
|
@@ -367,37 +543,50 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
367
543
|
return ae.getUnprocessedTemplate();
|
|
368
544
|
}
|
|
369
545
|
|
|
370
|
-
refresh(value
|
|
371
|
-
|
|
372
|
-
|
|
546
|
+
refresh(value?: any) {
|
|
547
|
+
value = getAttributeValue(this, 'value') ?? this._value;
|
|
548
|
+
console.log('[DEBUG] SwcChoose.refresh called, value:', value);
|
|
549
|
+
const portal = SwcUtils.getParentContainer(this);
|
|
550
|
+
if (!portal) {
|
|
551
|
+
console.log('[DEBUG] SwcChoose portal is null!');
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
373
554
|
|
|
374
|
-
const win = this.ownerDocument?.defaultView || window;
|
|
555
|
+
const win = (getElementConfig(this).window ?? this.ownerDocument?.defaultView) || window;
|
|
375
556
|
const helperSet = SwcUtils.getHelperAndHostSet(win, this);
|
|
376
|
-
const groupArgs = { ...helperSet, $value: value };
|
|
557
|
+
const groupArgs = { ...helperSet, $value: value, $templateHost: this };
|
|
377
558
|
|
|
378
559
|
const templates = Array.from(this.content.querySelectorAll('template'));
|
|
379
560
|
let selected: HTMLTemplateElement | null = null;
|
|
380
561
|
|
|
381
562
|
for (const t of templates) {
|
|
382
563
|
if (t.getAttribute('is') === 'swc-when') {
|
|
383
|
-
const attrVal = t.getAttribute('
|
|
564
|
+
const attrVal = t.getAttribute('test') || '';
|
|
384
565
|
let matches = false;
|
|
385
566
|
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
const result = FunctionUtils.executeReturn({
|
|
570
|
+
script: attrVal,
|
|
571
|
+
context: t,
|
|
572
|
+
args: groupArgs
|
|
573
|
+
});
|
|
574
|
+
matches = !!result;
|
|
386
575
|
// Use ActionExpression to parse and extract script from value attribute
|
|
387
|
-
const ae = new ActionExpression(attrVal);
|
|
388
|
-
const expr = ae.getFirstExpression('replace');
|
|
389
|
-
|
|
390
|
-
if (expr) {
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
} else {
|
|
399
|
-
|
|
400
|
-
}
|
|
576
|
+
// const ae = new ActionExpression(attrVal);
|
|
577
|
+
// const expr = ae.getFirstExpression('replace');
|
|
578
|
+
|
|
579
|
+
// if (expr) {
|
|
580
|
+
// const decodedScript = ConvertUtils.decodeHtmlEntity(expr.script, win.document);
|
|
581
|
+
// const result = FunctionUtils.executeReturn({
|
|
582
|
+
// script: decodedScript,
|
|
583
|
+
// context: t,
|
|
584
|
+
// args: groupArgs
|
|
585
|
+
// });
|
|
586
|
+
// matches = !!result;
|
|
587
|
+
// } else {
|
|
588
|
+
// matches = String(attrVal) === String(value);
|
|
589
|
+
// }
|
|
401
590
|
|
|
402
591
|
if (matches) {
|
|
403
592
|
selected = t;
|
|
@@ -422,14 +611,33 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
422
611
|
|
|
423
612
|
if (target) {
|
|
424
613
|
let htmlString = target.innerHTML;
|
|
425
|
-
htmlString = this.replaceExpressions(htmlString, groupArgs, this, this.
|
|
614
|
+
htmlString = this.replaceExpressions(htmlString, groupArgs, this, {start:this._replaceWrapStart ?? '{#{', end: this._replaceWrapEnd ?? '}#}'});
|
|
426
615
|
|
|
427
616
|
const result = this.ownerDocument?.createElement('template') || document.createElement('template');
|
|
428
617
|
result.innerHTML = htmlString;
|
|
429
618
|
const processedFragment = result.content;
|
|
430
619
|
|
|
620
|
+
// console.log('[DEBUG] SwcChoose processedFragment children:', processedFragment._childNodesInternal?.length);
|
|
431
621
|
this._nodes = Array.from(processedFragment.childNodes);
|
|
622
|
+
|
|
623
|
+
const setTemplateHost = (element: HTMLElement) => {
|
|
624
|
+
(element as any).__swc_template_host = this;
|
|
625
|
+
Array.from(element.children).forEach((child: any) => {
|
|
626
|
+
if (child instanceof HTMLElement) {
|
|
627
|
+
setTemplateHost(child);
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
};
|
|
631
|
+
|
|
632
|
+
this._nodes.forEach((node: any) => {
|
|
633
|
+
if (node instanceof HTMLElement) {
|
|
634
|
+
setTemplateHost(node as HTMLElement);
|
|
635
|
+
}
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
console.log(`[DEBUG] SwcChoose before insertBefore, portal: ${portal?.tagName}, isConnected: ${(portal as any)?.isConnected}`);
|
|
432
639
|
portal.insertBefore(processedFragment, this.nextSibling);
|
|
640
|
+
console.log('[DEBUG] SwcChoose after insertBefore');
|
|
433
641
|
}
|
|
434
642
|
}
|
|
435
643
|
|
|
@@ -447,11 +655,10 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
447
655
|
class SwcAsync extends HTMLTemplateElement {
|
|
448
656
|
@attributeHost('value')
|
|
449
657
|
_value: any;
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
resultValue?: any;
|
|
658
|
+
@attributeHost('replace-wrap-start')
|
|
659
|
+
_replaceWrapStart: string | null;
|
|
660
|
+
@attributeHost('replace-wrap-end')
|
|
661
|
+
_replaceWrapEnd: string | null; resultValue?: any;
|
|
455
662
|
|
|
456
663
|
get value(): boolean {
|
|
457
664
|
return this._value;
|
|
@@ -468,10 +675,10 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
468
675
|
this.executeAsync(this._value);
|
|
469
676
|
}
|
|
470
677
|
|
|
471
|
-
@changedAttributeHost('replace-wrap')
|
|
472
|
-
private setReplaceWrap() {
|
|
473
|
-
|
|
474
|
-
}
|
|
678
|
+
// @changedAttributeHost('replace-wrap')
|
|
679
|
+
// private setReplaceWrap() {
|
|
680
|
+
// this.executeAsync(this._value);
|
|
681
|
+
// }
|
|
475
682
|
|
|
476
683
|
private executeAsync(result: any = this._value) {
|
|
477
684
|
if (result === undefined || result === null) {
|
|
@@ -497,14 +704,22 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
497
704
|
}
|
|
498
705
|
}
|
|
499
706
|
|
|
500
|
-
private replaceExpressions(html: string, groupArgs: any, context: any, wrap
|
|
501
|
-
|
|
707
|
+
private replaceExpressions(html: string, groupArgs: any, context: any, wrap: {start: string, end: string}): string {
|
|
708
|
+
let config: any = undefined;
|
|
709
|
+
if (wrap) {
|
|
710
|
+
config = {
|
|
711
|
+
expression: {
|
|
712
|
+
replace: { start: `${wrap.start}`, end: `${wrap.end}` },
|
|
713
|
+
callReturn: { start: `${wrap.start}=`, end: `${wrap.end}` },
|
|
714
|
+
call: { start: `${wrap.start}@`, end: `${wrap.end}` }
|
|
715
|
+
}
|
|
716
|
+
};
|
|
717
|
+
}
|
|
502
718
|
const ae = new ActionExpression(html, config);
|
|
503
|
-
const filterOptions = wrap ? { type: 'replace' as const, wrap } : 'replace';
|
|
504
719
|
const win = this.ownerDocument?.defaultView || window;
|
|
505
720
|
|
|
506
721
|
// @ts-ignore
|
|
507
|
-
for (const expr of ae.getExpressions(
|
|
722
|
+
for (const expr of ae.getExpressions('replace')) {
|
|
508
723
|
try {
|
|
509
724
|
const value = FunctionUtils.executeReturn({
|
|
510
725
|
script: ConvertUtils.decodeHtmlEntity(expr.script, win.document),
|
|
@@ -520,9 +735,9 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
520
735
|
}
|
|
521
736
|
|
|
522
737
|
refresh(state: string = 'default') {
|
|
523
|
-
console.log('rrrrrrrrrrrrrrrrr', state);
|
|
738
|
+
// console.log('rrrrrrrrrrrrrrrrr', state);
|
|
524
739
|
this.cleanup();
|
|
525
|
-
const portal = this
|
|
740
|
+
const portal = SwcUtils.getParentContainer(this);
|
|
526
741
|
if (!portal) return;
|
|
527
742
|
|
|
528
743
|
const win = this.ownerDocument?.defaultView || window;
|
|
@@ -531,15 +746,19 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
531
746
|
const t = this.content.querySelector(`template[is="swc-${state}"]`) as HTMLTemplateElement;
|
|
532
747
|
if (t) {
|
|
533
748
|
let htmlString = t.innerHTML;
|
|
534
|
-
const groupArgs = { ...helperSet, $value: this._value, $state: state };
|
|
749
|
+
const groupArgs = { ...helperSet, $value: this._value, $state: state, $templateHost: this };
|
|
535
750
|
|
|
536
|
-
htmlString = this.replaceExpressions(htmlString, groupArgs, this, this.
|
|
751
|
+
htmlString = this.replaceExpressions(htmlString, groupArgs, this, {start:this._replaceWrapStart ?? '{#{', end: this._replaceWrapEnd ?? '}#}'});
|
|
537
752
|
|
|
538
753
|
const temp = this.ownerDocument?.createElement('template') || document.createElement('template');
|
|
539
754
|
temp.innerHTML = htmlString;
|
|
540
755
|
const content = temp.content;
|
|
541
756
|
|
|
542
757
|
this._nodes = Array.from(content.childNodes);
|
|
758
|
+
this._nodes.forEach((node: any) => {
|
|
759
|
+
if (node instanceof HTMLElement) (node as any).__template_swc_host = this;
|
|
760
|
+
});
|
|
761
|
+
|
|
543
762
|
portal.insertBefore(content, this.nextSibling);
|
|
544
763
|
}
|
|
545
764
|
}
|
package/src/types.ts
CHANGED
|
@@ -35,6 +35,7 @@ export type HostSet = {
|
|
|
35
35
|
$hosts: HTMLElement[]; // [root, ..., parent, self]
|
|
36
36
|
$firstHost: HTMLElement | null; // Top-most SWC ancestor
|
|
37
37
|
$lastHost: HTMLElement | null; // Same as $parentHost (for backward compatibility or clarity)
|
|
38
|
+
$templateHost: HTMLTemplateElement | null | undefined;
|
|
38
39
|
$appHost: SwcAppInterface | null;
|
|
39
40
|
$appHosts: SwcAppInterface[];
|
|
40
41
|
$firstAppHost: SwcAppInterface | null;
|