@thomas-siegfried/tapout 0.0.1 → 0.0.3
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/LICENSE +21 -21
- package/README.md +1207 -1205
- package/decorator-config.md +220 -0
- package/dist/wireParams.d.ts.map +1 -1
- package/dist/wireParams.js +27 -4
- package/dist/wireParams.js.map +1 -1
- package/llms.txt +360 -0
- package/package.json +57 -55
- package/src/applyBindings.ts +372 -372
- package/src/arrayToDomMapping.ts +300 -300
- package/src/attributeInterpolationMarkup.ts +91 -91
- package/src/bindingContext.ts +207 -207
- package/src/bindingEvent.ts +198 -198
- package/src/bindingProvider.ts +260 -260
- package/src/bindings.ts +963 -963
- package/src/compareArrays.ts +122 -122
- package/src/componentBinding.ts +318 -318
- package/src/componentDecorator.ts +62 -62
- package/src/components.ts +367 -367
- package/src/computed.ts +439 -439
- package/src/configure.ts +52 -52
- package/src/controlFlowBindings.ts +206 -206
- package/src/core.ts +60 -60
- package/src/decorators.ts +407 -407
- package/src/dependencyDetection.ts +76 -76
- package/src/disposable.ts +36 -36
- package/src/domData.ts +42 -42
- package/src/domNodeDisposal.ts +94 -94
- package/src/effects.ts +29 -29
- package/src/event.ts +173 -173
- package/src/expressionRewriting.ts +219 -219
- package/src/extenders.ts +102 -102
- package/src/filters.ts +91 -91
- package/src/index.ts +150 -150
- package/src/interpolationMarkup.ts +130 -130
- package/src/memoization.ts +71 -71
- package/src/namespacedBindings.ts +132 -132
- package/src/observable.ts +48 -48
- package/src/observableArray.ts +397 -397
- package/src/options.ts +25 -25
- package/src/selectExtensions.ts +68 -68
- package/src/slotBinding.ts +84 -84
- package/src/subscribable.ts +266 -266
- package/src/tasks.ts +79 -79
- package/src/templateEngine.ts +108 -108
- package/src/templateRendering.ts +399 -399
- package/src/templateRewriting.ts +94 -94
- package/src/templateSources.ts +134 -134
- package/src/utils.ts +123 -123
- package/src/utilsDom.ts +87 -87
- package/src/virtualElements.ts +153 -153
- package/src/wireParams.ts +69 -49
package/src/options.ts
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2
|
-
type Constructor = new (...args: any[]) => any;
|
|
3
|
-
export type ViewModelFactory = (ctor: Constructor) => unknown;
|
|
4
|
-
|
|
5
|
-
const defaultViewModelFactory: ViewModelFactory = (ctor) => new ctor();
|
|
6
|
-
|
|
7
|
-
export const options: {
|
|
8
|
-
deferUpdates: boolean;
|
|
9
|
-
onError: ((error: unknown) => void) | null;
|
|
10
|
-
viewModelFactory: ViewModelFactory;
|
|
11
|
-
customElementDisplayContents: boolean;
|
|
12
|
-
interpolation: boolean;
|
|
13
|
-
attributeInterpolation: boolean;
|
|
14
|
-
namespacedBindings: boolean;
|
|
15
|
-
filters: boolean;
|
|
16
|
-
} = {
|
|
17
|
-
deferUpdates: false,
|
|
18
|
-
onError: null,
|
|
19
|
-
viewModelFactory: defaultViewModelFactory,
|
|
20
|
-
customElementDisplayContents: true,
|
|
21
|
-
interpolation: false,
|
|
22
|
-
attributeInterpolation: false,
|
|
23
|
-
namespacedBindings: false,
|
|
24
|
-
filters: false,
|
|
25
|
-
};
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2
|
+
type Constructor = new (...args: any[]) => any;
|
|
3
|
+
export type ViewModelFactory = (ctor: Constructor) => unknown;
|
|
4
|
+
|
|
5
|
+
const defaultViewModelFactory: ViewModelFactory = (ctor) => new ctor();
|
|
6
|
+
|
|
7
|
+
export const options: {
|
|
8
|
+
deferUpdates: boolean;
|
|
9
|
+
onError: ((error: unknown) => void) | null;
|
|
10
|
+
viewModelFactory: ViewModelFactory;
|
|
11
|
+
customElementDisplayContents: boolean;
|
|
12
|
+
interpolation: boolean;
|
|
13
|
+
attributeInterpolation: boolean;
|
|
14
|
+
namespacedBindings: boolean;
|
|
15
|
+
filters: boolean;
|
|
16
|
+
} = {
|
|
17
|
+
deferUpdates: false,
|
|
18
|
+
onError: null,
|
|
19
|
+
viewModelFactory: defaultViewModelFactory,
|
|
20
|
+
customElementDisplayContents: true,
|
|
21
|
+
interpolation: false,
|
|
22
|
+
attributeInterpolation: false,
|
|
23
|
+
namespacedBindings: false,
|
|
24
|
+
filters: false,
|
|
25
|
+
};
|
package/src/selectExtensions.ts
CHANGED
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
import { domDataGet, domDataSet, domDataNextKey } from './domData.js';
|
|
2
|
-
|
|
3
|
-
const optionValueDomDataKey = domDataNextKey();
|
|
4
|
-
const HAS_DOM_DATA = '__tapout_hasDomData';
|
|
5
|
-
|
|
6
|
-
function tagNameLower(element: Node): string {
|
|
7
|
-
return (element as Element).tagName ? (element as Element).tagName.toLowerCase() : '';
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function readValue(element: Node): unknown {
|
|
11
|
-
const el = element as HTMLOptionElement & HTMLSelectElement & HTMLInputElement & Record<string, unknown>;
|
|
12
|
-
switch (tagNameLower(element)) {
|
|
13
|
-
case 'option':
|
|
14
|
-
if (el[HAS_DOM_DATA] === true) {
|
|
15
|
-
return domDataGet(element, optionValueDomDataKey);
|
|
16
|
-
}
|
|
17
|
-
return el.value;
|
|
18
|
-
case 'select':
|
|
19
|
-
return el.selectedIndex >= 0
|
|
20
|
-
? readValue((el.options as HTMLOptionsCollection)[el.selectedIndex])
|
|
21
|
-
: undefined;
|
|
22
|
-
default:
|
|
23
|
-
return el.value;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function writeValue(element: Node, value: unknown, allowUnset?: boolean): void {
|
|
28
|
-
const el = element as HTMLOptionElement & HTMLSelectElement & HTMLInputElement & Record<string, unknown>;
|
|
29
|
-
switch (tagNameLower(element)) {
|
|
30
|
-
case 'option':
|
|
31
|
-
if (typeof value === 'string') {
|
|
32
|
-
domDataSet(element, optionValueDomDataKey, undefined);
|
|
33
|
-
if (HAS_DOM_DATA in el) {
|
|
34
|
-
delete el[HAS_DOM_DATA];
|
|
35
|
-
}
|
|
36
|
-
el.value = value;
|
|
37
|
-
} else {
|
|
38
|
-
domDataSet(element, optionValueDomDataKey, value);
|
|
39
|
-
el[HAS_DOM_DATA] = true;
|
|
40
|
-
el.value = typeof value === 'number' ? String(value) : '';
|
|
41
|
-
}
|
|
42
|
-
break;
|
|
43
|
-
case 'select': {
|
|
44
|
-
if (value === '' || value === null) value = undefined;
|
|
45
|
-
let selection = -1;
|
|
46
|
-
const options = el.options as HTMLOptionsCollection;
|
|
47
|
-
for (let i = 0, n = options.length; i < n; ++i) {
|
|
48
|
-
const optionValue = readValue(options[i]);
|
|
49
|
-
if (optionValue == value || (optionValue === '' && value === undefined)) {
|
|
50
|
-
selection = i;
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (allowUnset || selection >= 0 || (value === undefined && el.size > 1)) {
|
|
55
|
-
el.selectedIndex = selection;
|
|
56
|
-
}
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
default:
|
|
60
|
-
if (value === null || value === undefined) value = '';
|
|
61
|
-
el.value = value as string;
|
|
62
|
-
break;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function getOptionValueDomDataKey(): string {
|
|
67
|
-
return optionValueDomDataKey;
|
|
68
|
-
}
|
|
1
|
+
import { domDataGet, domDataSet, domDataNextKey } from './domData.js';
|
|
2
|
+
|
|
3
|
+
const optionValueDomDataKey = domDataNextKey();
|
|
4
|
+
const HAS_DOM_DATA = '__tapout_hasDomData';
|
|
5
|
+
|
|
6
|
+
function tagNameLower(element: Node): string {
|
|
7
|
+
return (element as Element).tagName ? (element as Element).tagName.toLowerCase() : '';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function readValue(element: Node): unknown {
|
|
11
|
+
const el = element as HTMLOptionElement & HTMLSelectElement & HTMLInputElement & Record<string, unknown>;
|
|
12
|
+
switch (tagNameLower(element)) {
|
|
13
|
+
case 'option':
|
|
14
|
+
if (el[HAS_DOM_DATA] === true) {
|
|
15
|
+
return domDataGet(element, optionValueDomDataKey);
|
|
16
|
+
}
|
|
17
|
+
return el.value;
|
|
18
|
+
case 'select':
|
|
19
|
+
return el.selectedIndex >= 0
|
|
20
|
+
? readValue((el.options as HTMLOptionsCollection)[el.selectedIndex])
|
|
21
|
+
: undefined;
|
|
22
|
+
default:
|
|
23
|
+
return el.value;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function writeValue(element: Node, value: unknown, allowUnset?: boolean): void {
|
|
28
|
+
const el = element as HTMLOptionElement & HTMLSelectElement & HTMLInputElement & Record<string, unknown>;
|
|
29
|
+
switch (tagNameLower(element)) {
|
|
30
|
+
case 'option':
|
|
31
|
+
if (typeof value === 'string') {
|
|
32
|
+
domDataSet(element, optionValueDomDataKey, undefined);
|
|
33
|
+
if (HAS_DOM_DATA in el) {
|
|
34
|
+
delete el[HAS_DOM_DATA];
|
|
35
|
+
}
|
|
36
|
+
el.value = value;
|
|
37
|
+
} else {
|
|
38
|
+
domDataSet(element, optionValueDomDataKey, value);
|
|
39
|
+
el[HAS_DOM_DATA] = true;
|
|
40
|
+
el.value = typeof value === 'number' ? String(value) : '';
|
|
41
|
+
}
|
|
42
|
+
break;
|
|
43
|
+
case 'select': {
|
|
44
|
+
if (value === '' || value === null) value = undefined;
|
|
45
|
+
let selection = -1;
|
|
46
|
+
const options = el.options as HTMLOptionsCollection;
|
|
47
|
+
for (let i = 0, n = options.length; i < n; ++i) {
|
|
48
|
+
const optionValue = readValue(options[i]);
|
|
49
|
+
if (optionValue == value || (optionValue === '' && value === undefined)) {
|
|
50
|
+
selection = i;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (allowUnset || selection >= 0 || (value === undefined && el.size > 1)) {
|
|
55
|
+
el.selectedIndex = selection;
|
|
56
|
+
}
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
default:
|
|
60
|
+
if (value === null || value === undefined) value = '';
|
|
61
|
+
el.value = value as string;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function getOptionValueDomDataKey(): string {
|
|
67
|
+
return optionValueDomDataKey;
|
|
68
|
+
}
|
package/src/slotBinding.ts
CHANGED
|
@@ -1,84 +1,84 @@
|
|
|
1
|
-
import type { BindingHandler } from './bindingProvider.js';
|
|
2
|
-
import { bindingHandlers } from './bindingProvider.js';
|
|
3
|
-
import type { BindingContext } from './bindingContext.js';
|
|
4
|
-
import { applyBindingsToDescendants } from './applyBindings.js';
|
|
5
|
-
import {
|
|
6
|
-
allowedVirtualElementBindings,
|
|
7
|
-
virtualChildNodes,
|
|
8
|
-
virtualSetChildren,
|
|
9
|
-
} from './virtualElements.js';
|
|
10
|
-
import { cloneNodes } from './utilsDom.js';
|
|
11
|
-
|
|
12
|
-
const DEFAULT_SLOT = '';
|
|
13
|
-
|
|
14
|
-
function partitionTemplateNodes(
|
|
15
|
-
templateNodes: Node[],
|
|
16
|
-
): { defaultNodes: Node[]; namedSlots: Map<string, Node[]> } {
|
|
17
|
-
const namedSlots = new Map<string, Node[]>();
|
|
18
|
-
const defaultNodes: Node[] = [];
|
|
19
|
-
|
|
20
|
-
for (const node of templateNodes) {
|
|
21
|
-
const slotAttr = node.nodeType === 1
|
|
22
|
-
? (node as Element).getAttribute('slot')
|
|
23
|
-
: null;
|
|
24
|
-
|
|
25
|
-
if (slotAttr) {
|
|
26
|
-
let bucket = namedSlots.get(slotAttr);
|
|
27
|
-
if (!bucket) {
|
|
28
|
-
bucket = [];
|
|
29
|
-
namedSlots.set(slotAttr, bucket);
|
|
30
|
-
}
|
|
31
|
-
bucket.push(node);
|
|
32
|
-
} else {
|
|
33
|
-
defaultNodes.push(node);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return { defaultNodes, namedSlots };
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const slotHandler: BindingHandler = {
|
|
41
|
-
init(element, valueAccessor, _allBindings, _viewModel, bindingContext) {
|
|
42
|
-
const slotName = valueAccessor() as string | undefined;
|
|
43
|
-
const name = (typeof slotName === 'string' ? slotName : DEFAULT_SLOT);
|
|
44
|
-
|
|
45
|
-
const templateNodes = (bindingContext as BindingContext & { $componentTemplateNodes?: Node[] })
|
|
46
|
-
.$componentTemplateNodes;
|
|
47
|
-
|
|
48
|
-
if (!templateNodes || templateNodes.length === 0) {
|
|
49
|
-
applyBindingsToDescendants(bindingContext, element);
|
|
50
|
-
return { controlsDescendantBindings: true };
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const { defaultNodes, namedSlots } = partitionTemplateNodes(templateNodes);
|
|
54
|
-
const matchingNodes = name === DEFAULT_SLOT ? defaultNodes : (namedSlots.get(name) || []);
|
|
55
|
-
|
|
56
|
-
if (matchingNodes.length === 0) {
|
|
57
|
-
applyBindingsToDescendants(bindingContext, element);
|
|
58
|
-
return { controlsDescendantBindings: true };
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const cloned = cloneNodes(matchingNodes);
|
|
62
|
-
virtualSetChildren(element, cloned);
|
|
63
|
-
|
|
64
|
-
const parentContext = findParentOuterContext(bindingContext);
|
|
65
|
-
applyBindingsToDescendants(parentContext, element);
|
|
66
|
-
|
|
67
|
-
return { controlsDescendantBindings: true };
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Walk up the context chain to find the outer (pre-component) context.
|
|
73
|
-
* The component binding creates a child context with $component set,
|
|
74
|
-
* so we look for the context just above that boundary.
|
|
75
|
-
*/
|
|
76
|
-
function findParentOuterContext(bindingContext: BindingContext): BindingContext {
|
|
77
|
-
if (bindingContext.$parentContext && '$component' in bindingContext) {
|
|
78
|
-
return bindingContext.$parentContext;
|
|
79
|
-
}
|
|
80
|
-
return bindingContext;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
bindingHandlers['slot'] = slotHandler;
|
|
84
|
-
allowedVirtualElementBindings['slot'] = true;
|
|
1
|
+
import type { BindingHandler } from './bindingProvider.js';
|
|
2
|
+
import { bindingHandlers } from './bindingProvider.js';
|
|
3
|
+
import type { BindingContext } from './bindingContext.js';
|
|
4
|
+
import { applyBindingsToDescendants } from './applyBindings.js';
|
|
5
|
+
import {
|
|
6
|
+
allowedVirtualElementBindings,
|
|
7
|
+
virtualChildNodes,
|
|
8
|
+
virtualSetChildren,
|
|
9
|
+
} from './virtualElements.js';
|
|
10
|
+
import { cloneNodes } from './utilsDom.js';
|
|
11
|
+
|
|
12
|
+
const DEFAULT_SLOT = '';
|
|
13
|
+
|
|
14
|
+
function partitionTemplateNodes(
|
|
15
|
+
templateNodes: Node[],
|
|
16
|
+
): { defaultNodes: Node[]; namedSlots: Map<string, Node[]> } {
|
|
17
|
+
const namedSlots = new Map<string, Node[]>();
|
|
18
|
+
const defaultNodes: Node[] = [];
|
|
19
|
+
|
|
20
|
+
for (const node of templateNodes) {
|
|
21
|
+
const slotAttr = node.nodeType === 1
|
|
22
|
+
? (node as Element).getAttribute('slot')
|
|
23
|
+
: null;
|
|
24
|
+
|
|
25
|
+
if (slotAttr) {
|
|
26
|
+
let bucket = namedSlots.get(slotAttr);
|
|
27
|
+
if (!bucket) {
|
|
28
|
+
bucket = [];
|
|
29
|
+
namedSlots.set(slotAttr, bucket);
|
|
30
|
+
}
|
|
31
|
+
bucket.push(node);
|
|
32
|
+
} else {
|
|
33
|
+
defaultNodes.push(node);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return { defaultNodes, namedSlots };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const slotHandler: BindingHandler = {
|
|
41
|
+
init(element, valueAccessor, _allBindings, _viewModel, bindingContext) {
|
|
42
|
+
const slotName = valueAccessor() as string | undefined;
|
|
43
|
+
const name = (typeof slotName === 'string' ? slotName : DEFAULT_SLOT);
|
|
44
|
+
|
|
45
|
+
const templateNodes = (bindingContext as BindingContext & { $componentTemplateNodes?: Node[] })
|
|
46
|
+
.$componentTemplateNodes;
|
|
47
|
+
|
|
48
|
+
if (!templateNodes || templateNodes.length === 0) {
|
|
49
|
+
applyBindingsToDescendants(bindingContext, element);
|
|
50
|
+
return { controlsDescendantBindings: true };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const { defaultNodes, namedSlots } = partitionTemplateNodes(templateNodes);
|
|
54
|
+
const matchingNodes = name === DEFAULT_SLOT ? defaultNodes : (namedSlots.get(name) || []);
|
|
55
|
+
|
|
56
|
+
if (matchingNodes.length === 0) {
|
|
57
|
+
applyBindingsToDescendants(bindingContext, element);
|
|
58
|
+
return { controlsDescendantBindings: true };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const cloned = cloneNodes(matchingNodes);
|
|
62
|
+
virtualSetChildren(element, cloned);
|
|
63
|
+
|
|
64
|
+
const parentContext = findParentOuterContext(bindingContext);
|
|
65
|
+
applyBindingsToDescendants(parentContext, element);
|
|
66
|
+
|
|
67
|
+
return { controlsDescendantBindings: true };
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Walk up the context chain to find the outer (pre-component) context.
|
|
73
|
+
* The component binding creates a child context with $component set,
|
|
74
|
+
* so we look for the context just above that boundary.
|
|
75
|
+
*/
|
|
76
|
+
function findParentOuterContext(bindingContext: BindingContext): BindingContext {
|
|
77
|
+
if (bindingContext.$parentContext && '$component' in bindingContext) {
|
|
78
|
+
return bindingContext.$parentContext;
|
|
79
|
+
}
|
|
80
|
+
return bindingContext;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
bindingHandlers['slot'] = slotHandler;
|
|
84
|
+
allowedVirtualElementBindings['slot'] = true;
|