@neeloong/form 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -4
- package/index.d.mts +78 -69
- package/index.js +365 -201
- package/index.min.js +6 -6
- package/index.min.mjs +6 -6
- package/index.mjs +365 -201
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @neeloong/form v0.
|
|
2
|
+
* @neeloong/form v0.4.0
|
|
3
3
|
* (c) 2024-2025 Fierflame
|
|
4
4
|
* @license Apache-2.0
|
|
5
5
|
*/
|
|
@@ -855,8 +855,8 @@ class ArrayStore extends Store {
|
|
|
855
855
|
}
|
|
856
856
|
|
|
857
857
|
const errors = {
|
|
858
|
-
CALC: 'no `
|
|
859
|
-
EVENT: 'no `
|
|
858
|
+
CALC: 'no `createCalc` option, no expression parsing support',
|
|
859
|
+
EVENT: 'no `createEvent`, options, no event parsing support',
|
|
860
860
|
/** @param {string} endTag @param {string} startTag */
|
|
861
861
|
CLOSE: (endTag, startTag) => `end tag name: ${endTag} is not match the current start tagName: ${startTag}`,
|
|
862
862
|
/** @param {string} name */
|
|
@@ -900,15 +900,15 @@ class ParseError extends Error {
|
|
|
900
900
|
|
|
901
901
|
/** @import * as Layout from './index.mjs' */
|
|
902
902
|
|
|
903
|
-
const attrPattern = /^(?<decorator>[
|
|
903
|
+
const attrPattern = /^(?<decorator>[:@!+*\.?]|style:|样式:)?(?<name>-?[\w\p{Unified_Ideograph}_][-\w\p{Unified_Ideograph}_:\d\.]*)$/u;
|
|
904
904
|
const nameRegex = /^(?<name>[a-zA-Z$\p{Unified_Ideograph}_][\da-zA-Z$\p{Unified_Ideograph}_]*)?$/u;
|
|
905
905
|
/**
|
|
906
906
|
* @param {Layout.Node} node
|
|
907
|
-
* @param {Exclude<Layout.Options['
|
|
908
|
-
* @param {Exclude<Layout.Options['
|
|
907
|
+
* @param {Exclude<Layout.Options['createCalc'], undefined>} createCalc
|
|
908
|
+
* @param {Exclude<Layout.Options['createEvent'], undefined>} createEvent
|
|
909
909
|
*/
|
|
910
|
-
function createAttributeAdder(node,
|
|
911
|
-
const { attrs, directives, events, classes, styles, vars, aliases } = node;
|
|
910
|
+
function createAttributeAdder(node, createCalc, createEvent) {
|
|
911
|
+
const { attrs, directives, events, classes, styles, vars, aliases, params } = node;
|
|
912
912
|
/**
|
|
913
913
|
* @param {string} qName
|
|
914
914
|
* @param {string} value
|
|
@@ -928,37 +928,36 @@ function createAttributeAdder(node, creteCalc, creteEvent) {
|
|
|
928
928
|
if (!decorator) {
|
|
929
929
|
attrs[name] = value;
|
|
930
930
|
} else if (decorator === ':') {
|
|
931
|
-
attrs[name] = nameRegex.test(value) ? {name: value} :
|
|
931
|
+
attrs[name] = nameRegex.test(value) ? {name: value} : createCalc(value);
|
|
932
932
|
} else if (decorator === '.') {
|
|
933
|
-
classes[name] = !value ? true : nameRegex.test(value) ? value :
|
|
933
|
+
classes[name] = !value ? true : nameRegex.test(value) ? value : createCalc(value);
|
|
934
934
|
} else if (decorator === 'style:') {
|
|
935
|
-
styles[name] = nameRegex.test(value) ? value :
|
|
935
|
+
styles[name] = nameRegex.test(value) ? value : createCalc(value);
|
|
936
936
|
} else if (decorator === '@') {
|
|
937
|
-
events[name] = nameRegex.test(value) ? value :
|
|
937
|
+
events[name] = nameRegex.test(value) ? value : createEvent(value);
|
|
938
938
|
} else if (decorator === '+') {
|
|
939
|
-
vars[name] = !value ? '' : nameRegex.test(value) ? value :
|
|
939
|
+
vars[name] = !value ? '' : nameRegex.test(value) ? value : createCalc(value);
|
|
940
940
|
} else if (decorator === '*') {
|
|
941
|
-
aliases[name] = nameRegex.test(value) ? value :
|
|
941
|
+
aliases[name] = nameRegex.test(value) ? value : createCalc(value);
|
|
942
|
+
} else if (decorator === '?') {
|
|
943
|
+
params[name] = nameRegex.test(value) ? value : createCalc(value);
|
|
942
944
|
} else if (decorator === '!') {
|
|
943
945
|
const key = name.toString();
|
|
944
946
|
switch (key) {
|
|
945
|
-
case 'fragment':
|
|
946
|
-
case 'else':
|
|
947
|
-
directives[key] = true;
|
|
948
|
-
break;
|
|
947
|
+
case 'fragment': directives.fragment = value || true; break;
|
|
948
|
+
case 'else': directives.else = true; break;
|
|
949
949
|
case 'enum':
|
|
950
|
-
directives.enum = value ? nameRegex.test(value) ? value :
|
|
950
|
+
directives.enum = value ? nameRegex.test(value) ? value : createCalc(value) : true;
|
|
951
951
|
break;
|
|
952
952
|
case 'if':
|
|
953
953
|
case 'text':
|
|
954
954
|
case 'html':
|
|
955
|
-
directives[key] = nameRegex.test(value) ? value :
|
|
956
|
-
break;
|
|
957
|
-
case 'bind':
|
|
958
|
-
case 'value':
|
|
959
|
-
case 'comment':
|
|
960
|
-
directives[key] = value;
|
|
955
|
+
directives[key] = nameRegex.test(value) ? value : createCalc(value);
|
|
961
956
|
break;
|
|
957
|
+
case 'template': directives.template = value; break;
|
|
958
|
+
case 'bind': directives.bind = value || true; break;
|
|
959
|
+
case 'value': directives.value = value; break;
|
|
960
|
+
case 'comment': directives.comment = value; break;
|
|
962
961
|
}
|
|
963
962
|
}
|
|
964
963
|
}
|
|
@@ -985,6 +984,7 @@ function createElement(name, is) {
|
|
|
985
984
|
styles: Object.create(null),
|
|
986
985
|
vars: Object.create(null),
|
|
987
986
|
aliases: Object.create(null),
|
|
987
|
+
params: Object.create(null),
|
|
988
988
|
};
|
|
989
989
|
}
|
|
990
990
|
|
|
@@ -1303,8 +1303,8 @@ function entityReplacer(a) {
|
|
|
1303
1303
|
* @returns {(Layout.Node | string)[]}
|
|
1304
1304
|
*/
|
|
1305
1305
|
function parse(source, {
|
|
1306
|
-
|
|
1307
|
-
|
|
1306
|
+
createCalc = () => { throw new ParseError('CALC'); },
|
|
1307
|
+
createEvent = () => { throw new ParseError('EVENT'); },
|
|
1308
1308
|
simpleTag = new Set,
|
|
1309
1309
|
} = {}) {
|
|
1310
1310
|
/** @type {(Layout.Node | string)[]} */
|
|
@@ -1424,7 +1424,7 @@ function parse(source, {
|
|
|
1424
1424
|
currentNode = createElement(tagRes.name, tagRes.is);
|
|
1425
1425
|
current.children.push(currentNode);
|
|
1426
1426
|
current = currentNode;
|
|
1427
|
-
const addAttribute = createAttributeAdder(currentNode,
|
|
1427
|
+
const addAttribute = createAttributeAdder(currentNode, createCalc, createEvent);
|
|
1428
1428
|
|
|
1429
1429
|
let run = true;
|
|
1430
1430
|
let closed = false;
|
|
@@ -1503,13 +1503,21 @@ function _xmlEncoder(c) {
|
|
|
1503
1503
|
* @returns {Iterable<string>}
|
|
1504
1504
|
*/
|
|
1505
1505
|
function* nodeToString(node, level = 0) {
|
|
1506
|
-
const { attrs, events, directives, children, is, name, classes, styles, aliases, vars } = node;
|
|
1506
|
+
const { attrs, events, directives, children, is, name, params, classes, styles, aliases, vars } = node;
|
|
1507
1507
|
const pad = level > 0 ? ''.padEnd(level, '\t') : '';
|
|
1508
1508
|
|
|
1509
1509
|
yield pad;
|
|
1510
1510
|
yield* ['<', name || '-'];
|
|
1511
1511
|
if (is) { yield* ['|', is]; }
|
|
1512
1512
|
|
|
1513
|
+
for (const [name, value] of Object.entries(params)) {
|
|
1514
|
+
if (value == null) { continue; }
|
|
1515
|
+
const val = typeof value === 'function' ? String(value) : value;
|
|
1516
|
+
yield* [' ?', name];
|
|
1517
|
+
if (val && typeof val === 'string') {
|
|
1518
|
+
yield* ['="', val.replace(/[<&"]/g, _xmlEncoder), '"'];
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1513
1521
|
for (const [name, value] of Object.entries(directives)) {
|
|
1514
1522
|
if (value === false || value == null) { continue; }
|
|
1515
1523
|
const val = typeof value === 'function' ? String(value) : value;
|
|
@@ -1631,27 +1639,29 @@ function toString(value, formable) {
|
|
|
1631
1639
|
/**
|
|
1632
1640
|
* @typedef {object} Directives
|
|
1633
1641
|
*
|
|
1634
|
-
* @property {
|
|
1642
|
+
* @property {string} [template]
|
|
1643
|
+
*
|
|
1644
|
+
* @property {boolean | string} [fragment]
|
|
1635
1645
|
*
|
|
1636
|
-
* @property {string |
|
|
1646
|
+
* @property {string | Calc} [if]
|
|
1637
1647
|
* @property {boolean} [else]
|
|
1638
1648
|
*
|
|
1639
1649
|
* @property {string} [value] 值关联(关联为列表)
|
|
1640
|
-
* @property {boolean | string |
|
|
1650
|
+
* @property {boolean | string | Calc} [enum] 列表属性枚举
|
|
1641
1651
|
*
|
|
1642
|
-
* @property {string} [bind]
|
|
1643
|
-
* @property {string |
|
|
1644
|
-
* @property {string |
|
|
1652
|
+
* @property {boolean | string} [bind]
|
|
1653
|
+
* @property {string | Calc} [text]
|
|
1654
|
+
* @property {string | Calc} [html]
|
|
1645
1655
|
*
|
|
1646
|
-
* @property {string
|
|
1656
|
+
* @property {string} [comment] 注释
|
|
1647
1657
|
*/
|
|
1648
1658
|
|
|
1649
1659
|
|
|
1650
1660
|
|
|
1651
1661
|
/**
|
|
1652
1662
|
* @typedef {object} Options
|
|
1653
|
-
* @property {(t: string) =>
|
|
1654
|
-
* @property {(t: string) =>
|
|
1663
|
+
* @property {(t: string) => Calc} [options.createCalc]
|
|
1664
|
+
* @property {(t: string) => EventListener} [options.createEvent]
|
|
1655
1665
|
* @property {Set<string>} [options.simpleTag]
|
|
1656
1666
|
*/
|
|
1657
1667
|
/**
|
|
@@ -1659,16 +1669,31 @@ function toString(value, formable) {
|
|
|
1659
1669
|
* @property {string} name
|
|
1660
1670
|
* @property {string?} [is]
|
|
1661
1671
|
* @property {string} [id]
|
|
1662
|
-
* @property {Record<string, string | {name: string} |
|
|
1663
|
-
* @property {Record<string, string |
|
|
1664
|
-
* @property {Record<string, string |
|
|
1665
|
-
* @property {Record<string, string |
|
|
1666
|
-
* @property {Record<string, string |
|
|
1667
|
-
* @property {Record<string, string |
|
|
1672
|
+
* @property {Record<string, string | {name: string} | Calc>} attrs
|
|
1673
|
+
* @property {Record<string, string | Calc>} params
|
|
1674
|
+
* @property {Record<string, string | boolean | Calc>} classes
|
|
1675
|
+
* @property {Record<string, string | Calc>} styles
|
|
1676
|
+
* @property {Record<string, string | EventListener>} events
|
|
1677
|
+
* @property {Record<string, string | Calc>} vars
|
|
1678
|
+
* @property {Record<string, string | Calc>} aliases
|
|
1668
1679
|
* @property {Directives} directives
|
|
1669
1680
|
* @property {(Node | string)[]} children
|
|
1670
1681
|
*/
|
|
1671
1682
|
|
|
1683
|
+
/**
|
|
1684
|
+
* @callback Calc
|
|
1685
|
+
* @param {Record<string, any>} env
|
|
1686
|
+
* @returns {any}
|
|
1687
|
+
*/
|
|
1688
|
+
|
|
1689
|
+
|
|
1690
|
+
/**
|
|
1691
|
+
* @callback EventListener
|
|
1692
|
+
* @param {*} $event
|
|
1693
|
+
* @param {Record<string, any>} env
|
|
1694
|
+
* @returns {void}
|
|
1695
|
+
*/
|
|
1696
|
+
|
|
1672
1697
|
var index$1 = /*#__PURE__*/Object.freeze({
|
|
1673
1698
|
__proto__: null,
|
|
1674
1699
|
parse: parse,
|
|
@@ -1740,9 +1765,8 @@ const bindable = {
|
|
|
1740
1765
|
/** @type {Set<keyof typeof bindable>} */
|
|
1741
1766
|
// @ts-ignore
|
|
1742
1767
|
const bindableSet = new Set(Object.keys(bindable));
|
|
1743
|
-
|
|
1744
|
-
/** @
|
|
1745
|
-
/** @typedef {{get?: null; calc(...p: any[]): any; exec?: null;}} CalcDefine */
|
|
1768
|
+
|
|
1769
|
+
/** @import { ValueDefine, ExecDefine, CalcDefine } from './index.mjs' */
|
|
1746
1770
|
/**
|
|
1747
1771
|
*
|
|
1748
1772
|
* @param {Store} val
|
|
@@ -1753,6 +1777,8 @@ function *toItem(val, key = '', sign = '$') {
|
|
|
1753
1777
|
yield [`${key}`, {get: () => val.value, set: v => val.value = v, store: val}];
|
|
1754
1778
|
yield [`${key}${sign}value`, {get: () => val.value, set: v => val.value = v}];
|
|
1755
1779
|
yield [`${key}${sign}state`, {get: () => val.state, set: v => val.state = v}];
|
|
1780
|
+
yield [`${key}${sign}store`, {get: () => val}];
|
|
1781
|
+
yield [`${key}${sign}schema`, {get: () => val.schema}];
|
|
1756
1782
|
yield [`${key}${sign}null`, {get: () => val.null}];
|
|
1757
1783
|
yield [`${key}${sign}index`, {get: () => val.index}];
|
|
1758
1784
|
yield [`${key}${sign}no`, {get: () => val.no}];
|
|
@@ -1760,7 +1786,6 @@ function *toItem(val, key = '', sign = '$') {
|
|
|
1760
1786
|
yield [`${key}${sign}creatable`, {get: () => val.creatable}];
|
|
1761
1787
|
yield [`${key}${sign}immutable`, {get: () => val.immutable}];
|
|
1762
1788
|
|
|
1763
|
-
yield [`${key}${sign}schema`, {get: () => val.schema}];
|
|
1764
1789
|
|
|
1765
1790
|
for (const k of bindableSet) {
|
|
1766
1791
|
yield [`${key}${sign}${k}`, {get: () => val[k]}];
|
|
@@ -1772,6 +1797,9 @@ function *toItem(val, key = '', sign = '$') {
|
|
|
1772
1797
|
yield [`${key}${sign}move`, {exec: (from, to) => val.move(from, to)}];
|
|
1773
1798
|
yield [`${key}${sign}exchange`, {exec: (a, b) => val.exchange(a, b)}];
|
|
1774
1799
|
}
|
|
1800
|
+
|
|
1801
|
+
/** @import { ValueDefine, ExecDefine, CalcDefine } from './index.mjs' */
|
|
1802
|
+
|
|
1775
1803
|
/**
|
|
1776
1804
|
*
|
|
1777
1805
|
* @param {Store?} parent
|
|
@@ -1811,9 +1839,95 @@ function *toParentItem(parent, val, key = '', sign = '$') {
|
|
|
1811
1839
|
parent.move(s, s + 1);
|
|
1812
1840
|
}}];
|
|
1813
1841
|
}
|
|
1842
|
+
|
|
1843
|
+
/** @import { ValueDefine, ExecDefine, CalcDefine } from './index.mjs' */
|
|
1844
|
+
/**
|
|
1845
|
+
*
|
|
1846
|
+
* @param {Record<string, ValueDefine | ExecDefine | CalcDefine>} items
|
|
1847
|
+
* @param {Store} store
|
|
1848
|
+
* @param {Store} [parent]
|
|
1849
|
+
*/
|
|
1850
|
+
function setStore(items, store, parent) {
|
|
1851
|
+
for (const [name, val] of store) {
|
|
1852
|
+
for (const [b, x] of toItem(val, name)) {
|
|
1853
|
+
items[b] = x;
|
|
1854
|
+
}
|
|
1855
|
+
for (const [b, x] of toItem(val, name, '$$')) {
|
|
1856
|
+
items[b] = x;
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
/** @import { ValueDefine, ExecDefine, CalcDefine } from './index.mjs' */
|
|
1863
|
+
|
|
1864
|
+
/**
|
|
1865
|
+
* @param {Record<string, Store | {get?(): any; set?(v: any): void; exec?(...p: any[]): any; calc?(...p: any[]): any }>?} [global]
|
|
1866
|
+
*/
|
|
1867
|
+
function toGlobal(global) {
|
|
1868
|
+
/** @type {Record<string, ValueDefine | ExecDefine | CalcDefine>} */
|
|
1869
|
+
const items = Object.create(null);
|
|
1870
|
+
if (!global || typeof global !== 'object') { return items; }
|
|
1871
|
+
for (const [key, value] of Object.entries(global)) {
|
|
1872
|
+
if (!key || key.includes('$')) { continue; }
|
|
1873
|
+
if (!value || typeof value !== 'object') { continue; }
|
|
1874
|
+
if (value instanceof Store) {
|
|
1875
|
+
for (const [k, v] of toItem(value, key)) {
|
|
1876
|
+
items[k] = v;
|
|
1877
|
+
}
|
|
1878
|
+
continue;
|
|
1879
|
+
}
|
|
1880
|
+
const {get,set,exec,calc} = value;
|
|
1881
|
+
if (typeof get === 'function') {
|
|
1882
|
+
items[key] = typeof set === 'function' ? {get,set} : {get};
|
|
1883
|
+
continue;
|
|
1884
|
+
}
|
|
1885
|
+
if (typeof calc === 'function') {
|
|
1886
|
+
items[key] = {calc};
|
|
1887
|
+
continue;
|
|
1888
|
+
}
|
|
1889
|
+
if (typeof exec === 'function') {
|
|
1890
|
+
items[key] = {exec};
|
|
1891
|
+
continue;
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
return items;
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
/** @import Store from '../../Store/index.mjs' */
|
|
1898
|
+
|
|
1899
|
+
/**
|
|
1900
|
+
* @param {Store} store
|
|
1901
|
+
* @param {*} env
|
|
1902
|
+
*/
|
|
1903
|
+
function addStore(store, env) {
|
|
1904
|
+
Object.defineProperty(env, '$store', {
|
|
1905
|
+
value: store,
|
|
1906
|
+
writable: false,
|
|
1907
|
+
configurable: true,
|
|
1908
|
+
enumerable: false,
|
|
1909
|
+
});
|
|
1910
|
+
Object.defineProperty(env, '$root', {
|
|
1911
|
+
value: store.root,
|
|
1912
|
+
writable: false,
|
|
1913
|
+
configurable: true,
|
|
1914
|
+
enumerable: false,
|
|
1915
|
+
});
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
/** @import * as Layout from '../../Layout/index.mjs' */
|
|
1919
|
+
|
|
1920
|
+
|
|
1921
|
+
/** @typedef {{get(): any; set?(v: any): void; exec?: null; store?: Store; calc?: null; }} ValueDefine */
|
|
1922
|
+
/** @typedef {{get?: null; exec(...p: any[]): any; calc?: null}} ExecDefine */
|
|
1923
|
+
/** @typedef {{get?: null; calc(...p: any[]): any; exec?: null;}} CalcDefine */
|
|
1924
|
+
|
|
1925
|
+
/**
|
|
1926
|
+
* @template {Store} [T=Store]
|
|
1927
|
+
*/
|
|
1814
1928
|
class Environment {
|
|
1815
1929
|
/**
|
|
1816
|
-
* @param {string |
|
|
1930
|
+
* @param {string | Layout.Calc} value
|
|
1817
1931
|
*/
|
|
1818
1932
|
exec(value) {
|
|
1819
1933
|
if (typeof value === 'string') {
|
|
@@ -1826,18 +1940,18 @@ class Environment {
|
|
|
1826
1940
|
}
|
|
1827
1941
|
}
|
|
1828
1942
|
/**
|
|
1829
|
-
* @param {string |
|
|
1943
|
+
* @param {string | Layout.Calc} value
|
|
1830
1944
|
* @param {(value: any) => void} cb
|
|
1831
1945
|
*/
|
|
1832
1946
|
watch(value, cb) { return watch(() => this.exec(value), cb); }
|
|
1833
1947
|
|
|
1834
1948
|
/**
|
|
1835
|
-
* @param {string |
|
|
1949
|
+
* @param {string | Layout.Calc | boolean | null} [name]
|
|
1836
1950
|
*/
|
|
1837
1951
|
enum(name) {
|
|
1838
|
-
if (
|
|
1839
|
-
|
|
1840
|
-
}
|
|
1952
|
+
if (!name) { return true; }
|
|
1953
|
+
if (name === true) { return this.store; }
|
|
1954
|
+
if (typeof name === 'function') { return () => name(this.getters); }
|
|
1841
1955
|
if (typeof name !== 'string') { return null; }
|
|
1842
1956
|
const item = this.#items[name];
|
|
1843
1957
|
if (typeof item?.get !== 'function') { return null }
|
|
@@ -1922,8 +2036,8 @@ class Environment {
|
|
|
1922
2036
|
}
|
|
1923
2037
|
|
|
1924
2038
|
/**
|
|
1925
|
-
* @param {string |
|
|
1926
|
-
* @returns {
|
|
2039
|
+
* @param {string | Layout.EventListener} event
|
|
2040
|
+
* @returns {Layout.EventListener?}
|
|
1927
2041
|
*/
|
|
1928
2042
|
getEvent(event) {
|
|
1929
2043
|
if (typeof event === 'function') { return event }
|
|
@@ -1936,10 +2050,11 @@ class Environment {
|
|
|
1936
2050
|
|
|
1937
2051
|
}
|
|
1938
2052
|
/**
|
|
1939
|
-
*
|
|
2053
|
+
* @param {T} store
|
|
1940
2054
|
* @param {Environment | Record<string, Store | {get?(): any; set?(v: any): void; exec?(...p: any[]): any; calc?(...p: any[]): any }>?} [global]
|
|
1941
2055
|
*/
|
|
1942
|
-
constructor(global) {
|
|
2056
|
+
constructor(store, global) {
|
|
2057
|
+
this.store = store;
|
|
1943
2058
|
if (global instanceof Environment) {
|
|
1944
2059
|
this.#global = global.#global;
|
|
1945
2060
|
const schemaItems = this.#schemaItems;
|
|
@@ -1952,33 +2067,8 @@ class Environment {
|
|
|
1952
2067
|
}
|
|
1953
2068
|
return;
|
|
1954
2069
|
}
|
|
1955
|
-
|
|
1956
|
-
this.#global =
|
|
1957
|
-
if (!global) { return }
|
|
1958
|
-
if (typeof global !== 'object') { return; }
|
|
1959
|
-
for (const [key, value] of Object.entries(global)) {
|
|
1960
|
-
if (!key || key.includes('$')) { continue; }
|
|
1961
|
-
if (!value || typeof value !== 'object') { return; }
|
|
1962
|
-
if (value instanceof Store) {
|
|
1963
|
-
for (const [k, v] of toItem(value, key)) {
|
|
1964
|
-
items[k] = v;
|
|
1965
|
-
}
|
|
1966
|
-
continue;
|
|
1967
|
-
}
|
|
1968
|
-
const {get,set,exec,calc} = value;
|
|
1969
|
-
if (typeof get === 'function') {
|
|
1970
|
-
items[key] = typeof set === 'function' ? {get,set} : {get};
|
|
1971
|
-
continue;
|
|
1972
|
-
}
|
|
1973
|
-
if (typeof calc === 'function') {
|
|
1974
|
-
items[key] = {calc};
|
|
1975
|
-
continue;
|
|
1976
|
-
}
|
|
1977
|
-
if (typeof exec === 'function') {
|
|
1978
|
-
items[key] = {exec};
|
|
1979
|
-
continue;
|
|
1980
|
-
}
|
|
1981
|
-
}
|
|
2070
|
+
setStore(this.#schemaItems, store);
|
|
2071
|
+
this.#global = toGlobal(global);
|
|
1982
2072
|
}
|
|
1983
2073
|
/** @type {Record<string, ValueDefine | ExecDefine | CalcDefine>} */
|
|
1984
2074
|
#global
|
|
@@ -1986,8 +2076,8 @@ class Environment {
|
|
|
1986
2076
|
#schemaItems = Object.create(null);
|
|
1987
2077
|
/** @type {Record<string, ValueDefine | ExecDefine | CalcDefine>} */
|
|
1988
2078
|
#explicit = Object.create(null);
|
|
1989
|
-
/** @type {
|
|
1990
|
-
|
|
2079
|
+
/** @readonly @type {T} */
|
|
2080
|
+
store
|
|
1991
2081
|
/** @type {Record<string, any>?} */
|
|
1992
2082
|
#object = null
|
|
1993
2083
|
/** @type {Store?} */
|
|
@@ -2003,10 +2093,14 @@ class Environment {
|
|
|
2003
2093
|
...this.#global,
|
|
2004
2094
|
...this.#explicit,
|
|
2005
2095
|
}));
|
|
2006
|
-
const store = this
|
|
2096
|
+
const store = this.store;
|
|
2007
2097
|
const parent = this.#parent;
|
|
2008
2098
|
const object = this.#object;
|
|
2009
|
-
if (
|
|
2099
|
+
if (object) {
|
|
2100
|
+
for (const k of Object.keys(object)) {
|
|
2101
|
+
ais[`$${k}`] = {get: () => object[k]};
|
|
2102
|
+
}
|
|
2103
|
+
} else {
|
|
2010
2104
|
for (const [key, item] of toItem(store)) {
|
|
2011
2105
|
ais[key] = item;
|
|
2012
2106
|
}
|
|
@@ -2014,50 +2108,114 @@ class Environment {
|
|
|
2014
2108
|
ais[key] = item;
|
|
2015
2109
|
}
|
|
2016
2110
|
}
|
|
2017
|
-
if (object) {
|
|
2018
|
-
for (const k of Object.keys(object)) {
|
|
2019
|
-
ais[`$${k}`] = {get: () => object[k]};
|
|
2020
|
-
}
|
|
2021
|
-
}
|
|
2022
2111
|
this.#allItems = ais;
|
|
2023
2112
|
return ais;
|
|
2024
2113
|
}
|
|
2025
2114
|
/**
|
|
2026
2115
|
*
|
|
2027
2116
|
* @param {Store} store
|
|
2028
|
-
* @param {Store}
|
|
2117
|
+
* @param {Store} parent
|
|
2029
2118
|
*/
|
|
2030
2119
|
setStore(store, parent) {
|
|
2031
|
-
const cloned = new Environment(this);
|
|
2032
|
-
cloned.#store = store;
|
|
2120
|
+
const cloned = new Environment(store, this);
|
|
2033
2121
|
if (parent) { cloned.#parent = parent; }
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2122
|
+
setStore(cloned.#schemaItems, store);
|
|
2123
|
+
return cloned;
|
|
2124
|
+
}
|
|
2125
|
+
/**
|
|
2126
|
+
*
|
|
2127
|
+
* @param {string?} [name]
|
|
2128
|
+
*/
|
|
2129
|
+
child(name) {
|
|
2130
|
+
if (!name) { return this; }
|
|
2131
|
+
const store = this.store.child(name);
|
|
2132
|
+
if (!store) { return null; }
|
|
2133
|
+
const cloned = new Environment(store, this);
|
|
2134
|
+
setStore(cloned.#schemaItems, store);
|
|
2135
|
+
return cloned;
|
|
2136
|
+
}
|
|
2137
|
+
/**
|
|
2138
|
+
*
|
|
2139
|
+
* @param {Layout.Node} template
|
|
2140
|
+
* @param {Layout.Node} source
|
|
2141
|
+
* @param {Environment} sourceEnv
|
|
2142
|
+
* @param {string | null | boolean} [bind]
|
|
2143
|
+
*/
|
|
2144
|
+
params({params}, {attrs}, sourceEnv, bind) {
|
|
2145
|
+
/** @type {Store} */
|
|
2146
|
+
let store = this.store;
|
|
2147
|
+
if (bind === true) {
|
|
2148
|
+
store = sourceEnv.store;
|
|
2149
|
+
} else if (bind) {
|
|
2150
|
+
const item = sourceEnv.#items[bind];
|
|
2151
|
+
const s = item?.get && item.store;
|
|
2152
|
+
if (s) { store = s; }
|
|
2153
|
+
}
|
|
2154
|
+
if (Object.keys(params).length === 0) { return this; }
|
|
2155
|
+
const cloned = new Environment(store, this);
|
|
2156
|
+
cloned.#parent = this.#parent;
|
|
2157
|
+
cloned.#object = this.#object;
|
|
2158
|
+
const explicit = cloned.#explicit;
|
|
2159
|
+
const items = cloned.#items;
|
|
2160
|
+
for (const [key, param] of Object.entries(params)) {
|
|
2161
|
+
const attr = key in attrs ? attrs[key] : null;
|
|
2162
|
+
if (typeof attr === 'string') {
|
|
2163
|
+
explicit[key] = items[key] = {get: () => attr};
|
|
2164
|
+
} else if (attr && typeof attr === 'object') {
|
|
2165
|
+
const item = sourceEnv.#items[attr.name];
|
|
2166
|
+
if (!item?.get) { continue; }
|
|
2167
|
+
if (!item.store) {
|
|
2168
|
+
explicit[key] = items[key] = item;
|
|
2169
|
+
continue;
|
|
2170
|
+
}
|
|
2171
|
+
for (const [k, it] of toItem(item.store, key)) {
|
|
2172
|
+
explicit[k] = items[k] = it;
|
|
2173
|
+
}
|
|
2174
|
+
continue;
|
|
2175
|
+
|
|
2176
|
+
} else if (typeof attr === 'function') {
|
|
2177
|
+
const val = new Signal.Computed(() => attr(sourceEnv.getters));
|
|
2178
|
+
explicit[key] = items[key] = {
|
|
2179
|
+
get: () => { return val.get(); },
|
|
2180
|
+
};
|
|
2181
|
+
continue;
|
|
2182
|
+
} else if (typeof param === 'function') {
|
|
2183
|
+
const getters = cloned.getters;
|
|
2184
|
+
cloned.#getters = null;
|
|
2185
|
+
const val = new Signal.Computed(() => param(getters));
|
|
2186
|
+
explicit[key] = items[key] = {
|
|
2187
|
+
get: () => { return val.get(); },
|
|
2188
|
+
};
|
|
2189
|
+
continue;
|
|
2190
|
+
} else {
|
|
2191
|
+
const item = items[param];
|
|
2192
|
+
if (!item?.get) { continue; }
|
|
2193
|
+
if (!item.store) {
|
|
2194
|
+
explicit[key] = items[key] = item;
|
|
2195
|
+
continue;
|
|
2196
|
+
}
|
|
2197
|
+
for (const [k, it] of toItem(item.store, key)) {
|
|
2198
|
+
explicit[k] = items[k] = it;
|
|
2199
|
+
}
|
|
2200
|
+
continue;
|
|
2042
2201
|
}
|
|
2043
2202
|
}
|
|
2044
2203
|
return cloned;
|
|
2045
2204
|
}
|
|
2046
2205
|
/** @param {Record<string, any>} object */
|
|
2047
2206
|
setObject(object) {
|
|
2048
|
-
const cloned = new Environment(this);
|
|
2207
|
+
const cloned = new Environment(this.store, this);
|
|
2049
2208
|
cloned.#object = object;
|
|
2050
2209
|
return cloned;
|
|
2051
2210
|
}
|
|
2052
2211
|
/**
|
|
2053
2212
|
*
|
|
2054
|
-
* @param {Record<string, string |
|
|
2055
|
-
* @param {Record<string,
|
|
2213
|
+
* @param {Record<string, string | Layout.Calc>} aliases
|
|
2214
|
+
* @param {Record<string, string | Layout.Calc>} vars
|
|
2056
2215
|
*/
|
|
2057
2216
|
set(aliases, vars) {
|
|
2058
2217
|
if (Object.keys(aliases).length + Object.keys(vars).length === 0) { return this; }
|
|
2059
|
-
const cloned = new Environment(this);
|
|
2060
|
-
cloned.#store = this.#store;
|
|
2218
|
+
const cloned = new Environment(this.store, this);
|
|
2061
2219
|
cloned.#parent = this.#parent;
|
|
2062
2220
|
cloned.#object = this.#object;
|
|
2063
2221
|
const explicit = cloned.#explicit;
|
|
@@ -2133,6 +2291,7 @@ class Environment {
|
|
|
2133
2291
|
});
|
|
2134
2292
|
}
|
|
2135
2293
|
}
|
|
2294
|
+
addStore(this.store, ngt);
|
|
2136
2295
|
this.#all = ngt;
|
|
2137
2296
|
return ngt;
|
|
2138
2297
|
}
|
|
@@ -2160,6 +2319,7 @@ class Environment {
|
|
|
2160
2319
|
});
|
|
2161
2320
|
}
|
|
2162
2321
|
}
|
|
2322
|
+
addStore(this.store, ngt);
|
|
2163
2323
|
this.#settable = ngt;
|
|
2164
2324
|
return ngt;
|
|
2165
2325
|
}
|
|
@@ -2186,19 +2346,22 @@ class Environment {
|
|
|
2186
2346
|
});
|
|
2187
2347
|
}
|
|
2188
2348
|
}
|
|
2349
|
+
addStore(this.store, ngt);
|
|
2189
2350
|
this.#getters = ngt;
|
|
2190
2351
|
return ngt;
|
|
2191
2352
|
}
|
|
2192
2353
|
}
|
|
2193
2354
|
|
|
2194
2355
|
/** @import { Component } from '../types.mjs' */
|
|
2356
|
+
/** @import * as Layout from '../Layout/index.mjs' */
|
|
2357
|
+
|
|
2195
2358
|
|
|
2196
2359
|
/**
|
|
2197
2360
|
* @param {Component.Handler} handler
|
|
2198
2361
|
* @param {Environment} envs
|
|
2199
|
-
* @param {Record<string, string | {name: string} |
|
|
2362
|
+
* @param {Record<string, string | {name: string} | Layout.Calc>} attrs
|
|
2200
2363
|
* @param {Record<string, Component.Attr>} componentAttrs
|
|
2201
|
-
* @param {string
|
|
2364
|
+
* @param {string | boolean | null} [bindValue]
|
|
2202
2365
|
*/
|
|
2203
2366
|
function bindAttrs(handler, envs, attrs, componentAttrs, bindValue) {
|
|
2204
2367
|
|
|
@@ -2210,7 +2373,7 @@ function bindAttrs(handler, envs, attrs, componentAttrs, bindValue) {
|
|
|
2210
2373
|
handler.set(name, attrValue);
|
|
2211
2374
|
continue;
|
|
2212
2375
|
}
|
|
2213
|
-
const attrSchema = typeof attrValue === 'function' ? attrValue : attrValue.name;
|
|
2376
|
+
const attrSchema = typeof attrValue === 'function' ? /** @type{Layout.Calc} */(attrValue) : attrValue.name;
|
|
2214
2377
|
if (attr.immutable) {
|
|
2215
2378
|
handler.set(name, envs.exec(attrSchema));
|
|
2216
2379
|
continue;
|
|
@@ -2219,7 +2382,7 @@ function bindAttrs(handler, envs, attrs, componentAttrs, bindValue) {
|
|
|
2219
2382
|
continue;
|
|
2220
2383
|
}
|
|
2221
2384
|
const bind = attr.bind;
|
|
2222
|
-
if (!bindValue || !bind) {
|
|
2385
|
+
if (!bindValue || !bind || typeof bindValue === 'boolean') {
|
|
2223
2386
|
handler.set(name, attr.default);
|
|
2224
2387
|
continue;
|
|
2225
2388
|
}
|
|
@@ -2263,12 +2426,14 @@ function bindAttrs(handler, envs, attrs, componentAttrs, bindValue) {
|
|
|
2263
2426
|
}
|
|
2264
2427
|
|
|
2265
2428
|
/** @import { Component } from '../types.mjs' */
|
|
2429
|
+
/** @import * as Layout from '../Layout/index.mjs' */
|
|
2430
|
+
|
|
2266
2431
|
|
|
2267
2432
|
/**
|
|
2268
2433
|
* @param {Component.Handler} handler
|
|
2269
2434
|
* @param {Environment} envs
|
|
2270
|
-
* @param {Record<string, string | {name: string} |
|
|
2271
|
-
* @param {string
|
|
2435
|
+
* @param {Record<string, string | {name: string} | Layout.Calc>} attrs
|
|
2436
|
+
* @param {string | boolean | null} [bindValue]
|
|
2272
2437
|
*/
|
|
2273
2438
|
function bindBaseAttrs(handler, envs, attrs, bindValue) {
|
|
2274
2439
|
const tag = handler.tag;
|
|
@@ -2278,7 +2443,7 @@ function bindBaseAttrs(handler, envs, attrs, bindValue) {
|
|
|
2278
2443
|
handler.set(name, attr);
|
|
2279
2444
|
continue;
|
|
2280
2445
|
}
|
|
2281
|
-
const attrSchema = typeof attr === 'function' ? attr : attr.name;
|
|
2446
|
+
const attrSchema = typeof attr === 'function' ? /** @type{Layout.Calc} */(attr) : attr.name;
|
|
2282
2447
|
if (typeof tag === 'string' && tag.toLocaleLowerCase() === 'input' && name.toLocaleLowerCase() === 'type') {
|
|
2283
2448
|
const value = envs.exec(attrSchema);
|
|
2284
2449
|
handler.set(name, value);
|
|
@@ -2286,7 +2451,7 @@ function bindBaseAttrs(handler, envs, attrs, bindValue) {
|
|
|
2286
2451
|
}
|
|
2287
2452
|
bk.add(envs.watch(attrSchema, val => handler.set(name, val)));
|
|
2288
2453
|
}
|
|
2289
|
-
if (bindValue) {
|
|
2454
|
+
if (bindValue && typeof bindValue !== 'boolean') {
|
|
2290
2455
|
for (const [key, effect] of Object.entries(envs.bindAll(bindValue) || {})) {
|
|
2291
2456
|
if (typeof effect !== 'function') { continue; }
|
|
2292
2457
|
bk.add(effect(val => handler.set(key, val)));
|
|
@@ -2306,10 +2471,13 @@ function bindBaseAttrs(handler, envs, attrs, bindValue) {
|
|
|
2306
2471
|
}
|
|
2307
2472
|
}
|
|
2308
2473
|
|
|
2474
|
+
/** @import * as Layout from '../Layout/index.mjs' */
|
|
2475
|
+
|
|
2476
|
+
|
|
2309
2477
|
/**
|
|
2310
2478
|
* @param {Node} node
|
|
2311
2479
|
* @param {Environment} envs
|
|
2312
|
-
* @param {Record<string, string | boolean |
|
|
2480
|
+
* @param {Record<string, string | boolean | Layout.Calc>} classes
|
|
2313
2481
|
*/
|
|
2314
2482
|
function bindClasses(node, classes, envs) {
|
|
2315
2483
|
if (!(node instanceof Element)) {
|
|
@@ -2343,6 +2511,9 @@ function bindClasses(node, classes, envs) {
|
|
|
2343
2511
|
}
|
|
2344
2512
|
}
|
|
2345
2513
|
|
|
2514
|
+
/** @import * as Layout from '../Layout/index.mjs' */
|
|
2515
|
+
|
|
2516
|
+
|
|
2346
2517
|
/** @type {Record<string, string>} */
|
|
2347
2518
|
const unit = {
|
|
2348
2519
|
'width': 'px',
|
|
@@ -2409,7 +2580,7 @@ function toStyle(name, value) {
|
|
|
2409
2580
|
/**
|
|
2410
2581
|
* @param {Element} node
|
|
2411
2582
|
* @param {Environment} envs
|
|
2412
|
-
* @param {Record<string, string |
|
|
2583
|
+
* @param {Record<string, string | Layout.Calc>} classes
|
|
2413
2584
|
*/
|
|
2414
2585
|
function bindStyles(node, classes, envs) {
|
|
2415
2586
|
if (!(node instanceof HTMLElement) && !(node instanceof SVGElement)) {
|
|
@@ -2481,10 +2652,11 @@ class EventEmitter {
|
|
|
2481
2652
|
}
|
|
2482
2653
|
|
|
2483
2654
|
/** @import { Component } from '../types.mjs' */
|
|
2484
|
-
/** @import Environment from './Environment.mjs' */
|
|
2655
|
+
/** @import Environment from './Environment/index.mjs' */
|
|
2656
|
+
/** @import Store from '../Store/index.mjs' */
|
|
2485
2657
|
|
|
2486
2658
|
|
|
2487
|
-
/** @type {Record<string,
|
|
2659
|
+
/** @type {Record<string, Component.Event.Filter>} */
|
|
2488
2660
|
const eventFilters = {
|
|
2489
2661
|
stop(evt) {
|
|
2490
2662
|
if (evt instanceof Event) { evt.stopPropagation(); }
|
|
@@ -2648,7 +2820,7 @@ function createContext(component, env) {
|
|
|
2648
2820
|
if (!filters) { return; }
|
|
2649
2821
|
/** @type {AddEventListenerOptions} */
|
|
2650
2822
|
const options = {};
|
|
2651
|
-
/** @type {[
|
|
2823
|
+
/** @type {[Component.Event.Filter, string[], boolean][]} */
|
|
2652
2824
|
const filterFns = [];
|
|
2653
2825
|
if (filters) for (let f = fs.shift();f;f = fs.shift()) {
|
|
2654
2826
|
const paramIndex = f.indexOf(':');
|
|
@@ -2964,19 +3136,17 @@ function createTagComponent (context, name, is) {
|
|
|
2964
3136
|
return node;
|
|
2965
3137
|
}
|
|
2966
3138
|
|
|
2967
|
-
/** @import * as Layout from '../Layout/index.mjs' */
|
|
2968
3139
|
/** @import Store, { ArrayStore } from '../Store/index.mjs' */
|
|
2969
3140
|
|
|
2970
3141
|
/**
|
|
2971
3142
|
*
|
|
2972
|
-
* @param {Layout.Node} layout
|
|
2973
3143
|
* @param {Element} parent
|
|
2974
3144
|
* @param {Node?} next
|
|
2975
3145
|
* @param {ArrayStore} store
|
|
2976
3146
|
* @param {Environment} env
|
|
2977
|
-
* @param {(
|
|
3147
|
+
* @param {(next: Node | null, env: any) => () => void} renderItem
|
|
2978
3148
|
*/
|
|
2979
|
-
function renderArray(
|
|
3149
|
+
function renderArray(parent, next, store, env, renderItem) {
|
|
2980
3150
|
const start = parent.insertBefore(document.createComment(''), next);
|
|
2981
3151
|
/** @type {Map<Store, [Comment, Comment, () => void]>} */
|
|
2982
3152
|
let seMap = new Map();
|
|
@@ -2999,7 +3169,7 @@ function renderArray(layout, parent, next, store, env, renderItem) {
|
|
|
2999
3169
|
if (!old) {
|
|
3000
3170
|
const ItemStart = parent.insertBefore(document.createComment(''), nextNode);
|
|
3001
3171
|
const itemEnd = parent.insertBefore(document.createComment(''), nextNode);
|
|
3002
|
-
const d = renderItem(
|
|
3172
|
+
const d = renderItem(itemEnd, env.setStore(child, store));
|
|
3003
3173
|
seMap.set(child, [ItemStart, itemEnd, d]);
|
|
3004
3174
|
continue;
|
|
3005
3175
|
}
|
|
@@ -3092,17 +3262,26 @@ function renderFillDirectives(parent, next, envs, { text, html }) {
|
|
|
3092
3262
|
* @param {Element} parent
|
|
3093
3263
|
* @param {Node?} next
|
|
3094
3264
|
* @param {Environment} envs
|
|
3095
|
-
* @param {
|
|
3265
|
+
* @param {Record<string, [Layout.Node, Environment]>} templates
|
|
3266
|
+
* @param {(layout: Layout.Node, templates: Record<string, any>) => () => void} renderItem
|
|
3096
3267
|
* @returns {() => void}
|
|
3097
3268
|
*/
|
|
3098
|
-
function renderList(layouts, parent, next, envs, renderItem) {
|
|
3269
|
+
function renderList(layouts, parent, next, envs, templates, renderItem) {
|
|
3099
3270
|
|
|
3100
3271
|
/** @type {Set<() => void>?} */
|
|
3101
3272
|
let bkList = new Set();
|
|
3102
|
-
/** @type {[string |
|
|
3273
|
+
/** @type {[string | Layout.Calc | null, Layout.Node][]} */
|
|
3103
3274
|
let ifList = [];
|
|
3275
|
+
/** @type {Record<string, [Layout.Node, Environment]>} */
|
|
3276
|
+
let currentTemplates = Object.create(templates);
|
|
3277
|
+
for (const layout of layouts) {
|
|
3278
|
+
if (typeof layout === 'string') { continue; }
|
|
3279
|
+
const name = layout.directives.template;
|
|
3280
|
+
if (!name) { continue; }
|
|
3281
|
+
currentTemplates[name] = [layout, envs];
|
|
3282
|
+
}
|
|
3104
3283
|
|
|
3105
|
-
/** @param {[string |
|
|
3284
|
+
/** @param {[string | Layout.Calc | null, Layout.Node][]} list */
|
|
3106
3285
|
function renderIf(list) {
|
|
3107
3286
|
if (!list.length || !bkList) { return; }
|
|
3108
3287
|
const end = parent.insertBefore(document.createComment(''), next);
|
|
@@ -3118,7 +3297,7 @@ function renderList(layouts, parent, next, envs, renderItem) {
|
|
|
3118
3297
|
function renderIndex(index) {
|
|
3119
3298
|
const layout = list[index]?.[1];
|
|
3120
3299
|
if (!layout) { return; }
|
|
3121
|
-
destroy = renderItem(layout);
|
|
3300
|
+
destroy = renderItem(layout, currentTemplates);
|
|
3122
3301
|
}
|
|
3123
3302
|
bkList.add(() => {
|
|
3124
3303
|
destroy();
|
|
@@ -3145,6 +3324,11 @@ function renderList(layouts, parent, next, envs, renderItem) {
|
|
|
3145
3324
|
bkList.add(() => node.remove());
|
|
3146
3325
|
continue;
|
|
3147
3326
|
}
|
|
3327
|
+
if (layout.directives.template) {
|
|
3328
|
+
renderIf(ifList);
|
|
3329
|
+
ifList = [];
|
|
3330
|
+
continue;
|
|
3331
|
+
}
|
|
3148
3332
|
if (ifList.length && layout.directives.else) {
|
|
3149
3333
|
const ifv = layout.directives.if || null;
|
|
3150
3334
|
ifList.push([ifv, layout]);
|
|
@@ -3162,7 +3346,7 @@ function renderList(layouts, parent, next, envs, renderItem) {
|
|
|
3162
3346
|
continue;
|
|
3163
3347
|
}
|
|
3164
3348
|
bkList.add(
|
|
3165
|
-
renderItem(layout)
|
|
3349
|
+
renderItem(layout, currentTemplates)
|
|
3166
3350
|
);
|
|
3167
3351
|
}
|
|
3168
3352
|
|
|
@@ -3176,23 +3360,21 @@ function renderList(layouts, parent, next, envs, renderItem) {
|
|
|
3176
3360
|
};
|
|
3177
3361
|
}
|
|
3178
3362
|
|
|
3179
|
-
/** @import
|
|
3180
|
-
/** @import Store, { ObjectStore } from '../Store/index.mjs' */
|
|
3363
|
+
/** @import { ObjectStore } from '../Store/index.mjs' */
|
|
3181
3364
|
|
|
3182
3365
|
/**
|
|
3183
3366
|
*
|
|
3184
|
-
* @param {Layout.Node} layout
|
|
3185
3367
|
* @param {Element} parent
|
|
3186
3368
|
* @param {Node?} next
|
|
3187
3369
|
* @param {ObjectStore} store
|
|
3188
3370
|
* @param {Environment} env
|
|
3189
|
-
* @param {(
|
|
3371
|
+
* @param {(next: Node | null, env: any) => () => void} renderItem
|
|
3190
3372
|
*/
|
|
3191
|
-
function renderObject(
|
|
3373
|
+
function renderObject(parent, next, store, env, renderItem) {
|
|
3192
3374
|
/** @type {(() => void)[]} */
|
|
3193
3375
|
const children = [];
|
|
3194
3376
|
for (const [k, child] of [...store]) {
|
|
3195
|
-
children.push(renderItem(
|
|
3377
|
+
children.push(renderItem(next, env.setStore(child, store)));
|
|
3196
3378
|
}
|
|
3197
3379
|
|
|
3198
3380
|
return () => {
|
|
@@ -3202,20 +3384,15 @@ function renderObject(layout, parent, next, store, env, renderItem) {
|
|
|
3202
3384
|
};
|
|
3203
3385
|
}
|
|
3204
3386
|
|
|
3205
|
-
/** @import * as Layout from '../Layout/index.mjs' */
|
|
3206
|
-
/** @import Store from '../Store/index.mjs' */
|
|
3207
|
-
|
|
3208
3387
|
/**
|
|
3209
3388
|
*
|
|
3210
|
-
* @param {Layout.Node} layout
|
|
3211
3389
|
* @param {Element} parent
|
|
3212
3390
|
* @param {Node?} next
|
|
3213
|
-
* @param {Store} store
|
|
3214
3391
|
* @param {() => any} getter
|
|
3215
3392
|
* @param {Environment} env
|
|
3216
|
-
* @param {(
|
|
3393
|
+
* @param {(next: Node | null, env: any) => () => void} renderItem
|
|
3217
3394
|
*/
|
|
3218
|
-
function renderEnum(
|
|
3395
|
+
function renderEnum(parent, next, getter, env, renderItem) {
|
|
3219
3396
|
|
|
3220
3397
|
/** @type {Signal.Computed<[value: any, index: number, kKey: any][]>} */
|
|
3221
3398
|
const list = new Signal.Computed(() => {
|
|
@@ -3256,7 +3433,7 @@ function renderEnum(layout, parent, next, store, getter, env, renderItem) {
|
|
|
3256
3433
|
const itemEnd = parent.insertBefore(document.createComment(''), nextNode);
|
|
3257
3434
|
const valueState = new Signal.State(value);
|
|
3258
3435
|
const indexState = new Signal.State(index);
|
|
3259
|
-
const d = renderItem(
|
|
3436
|
+
const d = renderItem(itemEnd, env.setObject({
|
|
3260
3437
|
get key() { return key; },
|
|
3261
3438
|
get value() { return valueState.get(); },
|
|
3262
3439
|
get index() { return indexState.get(); },
|
|
@@ -3297,29 +3474,25 @@ function renderEnum(layout, parent, next, store, getter, env, renderItem) {
|
|
|
3297
3474
|
* @param {Element} parent
|
|
3298
3475
|
* @param {Node?} next
|
|
3299
3476
|
* @param {Environment} env
|
|
3300
|
-
* @param {
|
|
3301
|
-
* @returns {() => void}
|
|
3302
|
-
*/
|
|
3303
|
-
function renderFragment(layout, parent, next, env, renderItem) {
|
|
3304
|
-
return renderFillDirectives(parent, next, env, layout.directives) ||
|
|
3305
|
-
renderList(layout.children || [], parent, next, env, renderItem);
|
|
3306
|
-
|
|
3307
|
-
}
|
|
3308
|
-
/**
|
|
3309
|
-
* @param {Layout.Node} layout
|
|
3310
|
-
* @param {Element} parent
|
|
3311
|
-
* @param {Node?} next
|
|
3312
|
-
* @param {Store} store
|
|
3313
|
-
* @param {Environment} env
|
|
3477
|
+
* @param {Record<string, [Layout.Node, Environment]>} templates
|
|
3314
3478
|
* @param {string[]} componentPath
|
|
3315
3479
|
* @param {((path: string[]) => Component?)?} [getComponent]
|
|
3316
3480
|
*/
|
|
3317
|
-
function renderItem(layout, parent, next,
|
|
3481
|
+
function renderItem(layout, parent, next, env, templates, componentPath, getComponent) {
|
|
3318
3482
|
env = env.set(layout.aliases, layout.vars);
|
|
3483
|
+
const fragment = layout.directives.fragment;
|
|
3484
|
+
if (fragment && typeof fragment === 'string') {
|
|
3485
|
+
const template = templates[fragment];
|
|
3486
|
+
if (!template) { return () => {}; }
|
|
3487
|
+
const [templateLayout, templateEnv] = template;
|
|
3488
|
+
const newEnv = templateEnv.params(templateLayout, layout, env, layout.directives.bind);
|
|
3489
|
+
return render(templateLayout, parent, next, newEnv, templates, componentPath, getComponent);
|
|
3490
|
+
}
|
|
3319
3491
|
if (!layout.name || layout.directives.fragment) {
|
|
3320
|
-
return
|
|
3321
|
-
|
|
3322
|
-
|
|
3492
|
+
return renderFillDirectives(parent, next, env, layout.directives) ||
|
|
3493
|
+
renderList(layout.children || [], parent, next, env, templates, (layout, templates) => {
|
|
3494
|
+
return render(layout, parent, next, env, templates, componentPath, getComponent);
|
|
3495
|
+
});
|
|
3323
3496
|
}
|
|
3324
3497
|
const path = [...componentPath, layout.name];
|
|
3325
3498
|
const component = getComponent?.(path);
|
|
@@ -3343,20 +3516,20 @@ function renderItem(layout, parent, next, store, env, componentPath, getComponen
|
|
|
3343
3516
|
: createTagComponent(context, component.tag, component.is)
|
|
3344
3517
|
: createTagComponent(context, layout.name, layout.is);
|
|
3345
3518
|
const root = Array.isArray(r) ? r[0] : r;
|
|
3346
|
-
const slot = Array.isArray(r)
|
|
3519
|
+
const slot = Array.isArray(r) ? r[1] : root;
|
|
3347
3520
|
parent.insertBefore(root, next);
|
|
3348
|
-
const children =
|
|
3521
|
+
const children = slot ?
|
|
3349
3522
|
renderFillDirectives(slot, null, env, layout.directives)
|
|
3350
|
-
|| renderList(layout.children || [], slot, null, env,
|
|
3351
|
-
return render(
|
|
3352
|
-
});
|
|
3523
|
+
|| renderList(layout.children || [], slot, null, env, templates, (layout, templates) => {
|
|
3524
|
+
return render(layout, slot, null, env, templates, componentPath, getComponent);
|
|
3525
|
+
}) : () => {};
|
|
3353
3526
|
|
|
3354
3527
|
|
|
3355
3528
|
bindClasses(root, layout.classes, env);
|
|
3356
3529
|
bindStyles(root, layout.styles, env);
|
|
3357
3530
|
|
|
3358
3531
|
handler.init();
|
|
3359
|
-
|
|
3532
|
+
|
|
3360
3533
|
return () => {
|
|
3361
3534
|
root.remove();
|
|
3362
3535
|
handler.destroy();
|
|
@@ -3369,40 +3542,30 @@ function renderItem(layout, parent, next, store, env, componentPath, getComponen
|
|
|
3369
3542
|
* @param {Layout.Node} layout
|
|
3370
3543
|
* @param {Element} parent
|
|
3371
3544
|
* @param {Node?} next
|
|
3372
|
-
* @param {Store} store
|
|
3373
3545
|
* @param {Environment} env
|
|
3546
|
+
* @param {Record<string, [Layout.Node, Environment]>} templates
|
|
3374
3547
|
* @param {string[]} componentPath
|
|
3375
3548
|
* @param {((path: string[]) => Component?)?} [getComponent]
|
|
3376
3549
|
* @returns {() => void}
|
|
3377
3550
|
*/
|
|
3378
|
-
function render(layout, parent, next,
|
|
3551
|
+
function render(layout, parent, next, env, templates, componentPath, getComponent) {
|
|
3379
3552
|
const { directives } = layout;
|
|
3380
|
-
const
|
|
3381
|
-
if (
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
const enumValue = directives.enum;
|
|
3388
|
-
if (!enumValue) {
|
|
3389
|
-
return renderItem(layout, parent, next, store, env, componentPath, getComponent);
|
|
3390
|
-
}
|
|
3391
|
-
const newStore = enumValue === true ? store : env.enum(enumValue);
|
|
3392
|
-
if (newStore instanceof ArrayStore) {
|
|
3393
|
-
return renderArray(layout, parent, next, newStore, env, (a, b, c, store, env) => {
|
|
3394
|
-
return renderItem(a, b, c, store, env, componentPath, getComponent);
|
|
3395
|
-
});
|
|
3553
|
+
const newEnv = env.child(directives.value);
|
|
3554
|
+
if (!newEnv) { return () => {}; }
|
|
3555
|
+
const list = newEnv.enum(directives.enum);
|
|
3556
|
+
/** @type {(next: Node | null, env: any) => () => void} */
|
|
3557
|
+
const r = (next, env) => renderItem(layout, parent, next, env, templates, componentPath, getComponent);
|
|
3558
|
+
if (list === true) {
|
|
3559
|
+
return r(next, newEnv);
|
|
3396
3560
|
}
|
|
3397
|
-
if (
|
|
3398
|
-
return
|
|
3399
|
-
return renderItem(a, b, c, store, env, componentPath, getComponent);
|
|
3400
|
-
});
|
|
3561
|
+
if (list instanceof ArrayStore) {
|
|
3562
|
+
return renderArray(parent, next, list, newEnv, r);
|
|
3401
3563
|
}
|
|
3402
|
-
if (
|
|
3403
|
-
return
|
|
3404
|
-
|
|
3405
|
-
|
|
3564
|
+
if (list instanceof ObjectStore) {
|
|
3565
|
+
return renderObject(parent, next, list, newEnv, r);
|
|
3566
|
+
}
|
|
3567
|
+
if (typeof list === 'function') {
|
|
3568
|
+
return renderEnum(parent, next, list, newEnv, r);
|
|
3406
3569
|
}
|
|
3407
3570
|
return () => { };
|
|
3408
3571
|
}
|
|
@@ -3435,9 +3598,10 @@ function index (store, layouts, parent, opt1, opt2) {
|
|
|
3435
3598
|
const options = [opt1, opt2];
|
|
3436
3599
|
const components = options.find(v => typeof v === 'function');
|
|
3437
3600
|
const global = options.find(v => typeof v === 'object');
|
|
3438
|
-
const env = new Environment(global)
|
|
3439
|
-
|
|
3440
|
-
|
|
3601
|
+
const env = new Environment(store, global);
|
|
3602
|
+
const templates = Object.create(null);
|
|
3603
|
+
return renderList(layouts, parent, null, env, templates, (layout, templates) => {
|
|
3604
|
+
return render(layout, parent, null, env, templates, [], components);
|
|
3441
3605
|
});
|
|
3442
3606
|
}
|
|
3443
3607
|
|