aberdeen 1.5.0 → 1.7.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/dist/aberdeen.js CHANGED
@@ -154,9 +154,6 @@ var lastPrio = 0;
154
154
 
155
155
  class Scope {
156
156
  prio = --lastPrio;
157
- onChange(index) {
158
- queue(this);
159
- }
160
157
  remove() {
161
158
  const lastNode = this.getLastNode();
162
159
  if (lastNode)
@@ -176,6 +173,7 @@ class DelayedOneTimeRunner {
176
173
 
177
174
  class ContentScope extends Scope {
178
175
  cleaners;
176
+ changes;
179
177
  constructor(cleaners = []) {
180
178
  super();
181
179
  this.cleaners = cleaners;
@@ -196,7 +194,38 @@ class ContentScope extends Scope {
196
194
  sortedQueue?.remove(this);
197
195
  this.lastChild = undefined;
198
196
  }
197
+ onChange(target, index, newData, oldData) {
198
+ if (!this.changes) {
199
+ this.changes = new Map;
200
+ queue(this);
201
+ }
202
+ let targetDelta = this.changes.get(target);
203
+ if (!targetDelta) {
204
+ targetDelta = new Map;
205
+ this.changes.set(target, targetDelta);
206
+ }
207
+ if (targetDelta.has(index)) {
208
+ if (targetDelta.get(index) === newData)
209
+ targetDelta.delete(index);
210
+ } else {
211
+ targetDelta.set(index, oldData);
212
+ }
213
+ }
214
+ fetchHasChanges() {
215
+ if (!this.changes)
216
+ return false;
217
+ for (const targetDelta of this.changes.values()) {
218
+ if (targetDelta.size > 0) {
219
+ delete this.changes;
220
+ return true;
221
+ }
222
+ }
223
+ delete this.changes;
224
+ return false;
225
+ }
199
226
  queueRun() {
227
+ if (!this.fetchHasChanges())
228
+ return;
200
229
  this.remove();
201
230
  topRedrawScope = this;
202
231
  this.redraw();
@@ -205,9 +234,6 @@ class ContentScope extends Scope {
205
234
  getInsertAfterNode() {
206
235
  return this.getLastNode() || this.getPrecedingNode();
207
236
  }
208
- onChange() {
209
- queue(this);
210
- }
211
237
  getChildPrevSibling() {
212
238
  return this.lastChild;
213
239
  }
@@ -362,7 +388,7 @@ class OnEachScope extends Scope {
362
388
  target;
363
389
  byIndex = new Map;
364
390
  sortedSet = new ReverseSortedSet("sortKey");
365
- changedIndexes = new Set;
391
+ changedIndexes = new Map;
366
392
  constructor(proxy, renderer, makeSortKey) {
367
393
  super();
368
394
  this.renderer = renderer;
@@ -385,15 +411,22 @@ class OnEachScope extends Scope {
385
411
  getPrecedingNode() {
386
412
  return findLastNodeInPrevSiblings(this.prevSibling);
387
413
  }
388
- onChange(index) {
389
- if (!(this.target instanceof Array) || typeof index === "number")
390
- this.changedIndexes.add(index);
391
- queue(this);
414
+ onChange(target, index, newData, oldData) {
415
+ if (!(target instanceof Array) || typeof index === "number") {
416
+ if (this.changedIndexes.has(index)) {
417
+ if (this.changedIndexes.get(index) === newData) {
418
+ this.changedIndexes.delete(index);
419
+ }
420
+ } else {
421
+ this.changedIndexes.set(index, oldData);
422
+ queue(this);
423
+ }
424
+ }
392
425
  }
393
426
  queueRun() {
394
427
  const indexes = this.changedIndexes;
395
- this.changedIndexes = new Set;
396
- for (const index of indexes) {
428
+ this.changedIndexes = new Map;
429
+ for (const index of indexes.keys()) {
397
430
  const oldScope = this.byIndex.get(index);
398
431
  if (oldScope)
399
432
  oldScope.remove();
@@ -466,6 +499,8 @@ class OnEachItemScope extends ContentScope {
466
499
  queueRun() {
467
500
  if (currentScope !== ROOT_SCOPE)
468
501
  internalError(4);
502
+ if (!this.fetchHasChanges())
503
+ return;
469
504
  if (this.sortKey !== undefined) {
470
505
  const lastNode = this.getActualLastNode();
471
506
  if (lastNode)
@@ -593,23 +628,26 @@ function isEmpty(proxied) {
593
628
  if (target instanceof Array) {
594
629
  subscribe(target, "length", (index, newData, oldData) => {
595
630
  if (!newData !== !oldData)
596
- queue(scope);
631
+ scope.onChange(target, EMPTY, !newData, !oldData);
597
632
  });
598
633
  return !target.length;
599
634
  }
600
635
  if (target instanceof Map) {
601
636
  subscribe(target, MAP_SIZE_SYMBOL, (index, newData, oldData) => {
602
637
  if (!newData !== !oldData)
603
- queue(scope);
638
+ scope.onChange(target, EMPTY, !newData, !oldData);
604
639
  });
605
640
  return !target.size;
606
641
  }
607
- const result = isObjEmpty(target);
642
+ let oldEmpty = isObjEmpty(target);
608
643
  subscribe(target, ANY_SYMBOL, (index, newData, oldData) => {
609
- if (result ? oldData === EMPTY : newData === EMPTY)
610
- queue(scope);
644
+ if (newData === EMPTY !== (oldData === EMPTY)) {
645
+ const newEmpty = isObjEmpty(target);
646
+ scope.onChange(target, EMPTY, newEmpty, oldEmpty);
647
+ oldEmpty = newEmpty;
648
+ }
611
649
  });
612
- return result;
650
+ return oldEmpty;
613
651
  }
614
652
  function count(proxied) {
615
653
  if (proxied instanceof Array)
@@ -643,7 +681,7 @@ function defaultEmitHandler(target, index, newData, oldData) {
643
681
  if (typeof observer === "function")
644
682
  observer(index, newData, oldData);
645
683
  else
646
- observer.onChange(index);
684
+ observer.onChange(target, index, newData, oldData);
647
685
  }
648
686
  }
649
687
  }
@@ -1017,7 +1055,7 @@ function copyRecursive(dst, src, flags) {
1017
1055
  const old = dst.get(k);
1018
1056
  dst.delete(k);
1019
1057
  if (flags & COPY_EMIT) {
1020
- emit(dst, k, undefined, old);
1058
+ emit(dst, k, EMPTY, old);
1021
1059
  }
1022
1060
  changed = true;
1023
1061
  }
@@ -1047,7 +1085,7 @@ function copyRecursive(dst, src, flags) {
1047
1085
  const old = dst[k];
1048
1086
  delete dst[k];
1049
1087
  if (flags & COPY_EMIT && old !== undefined) {
1050
- emit(dst, k, undefined, old);
1088
+ emit(dst, k, EMPTY, old);
1051
1089
  }
1052
1090
  changed = true;
1053
1091
  }
@@ -1064,13 +1102,54 @@ var COPY_EMIT = 64;
1064
1102
  var NO_COPY = Symbol("NO_COPY");
1065
1103
  Promise.prototype[NO_COPY] = true;
1066
1104
  var cssVars = optProxy({});
1067
- for (let i = 1;i <= 12; i++) {
1068
- cssVars[i] = 2 ** (i - 3) + "rem";
1105
+ function setSpacingCssVars(base = 1, unit = "rem") {
1106
+ for (let i = 0;i <= 12; i++) {
1107
+ cssVars[i] = 2 ** (i - 3) * base + unit;
1108
+ }
1069
1109
  }
1110
+ var CSS_VAR_PATTERN = /(\([^)]*\))|("[^"]*")|(^| )\$(\w+)/g;
1070
1111
  var DIGIT_FIRST = /^\d/;
1071
- function cssVarRef(name) {
1072
- const varName = DIGIT_FIRST.test(name) ? `m${name}` : name;
1073
- return `var(--${varName})`;
1112
+ function cssVarRef(value) {
1113
+ if (value.indexOf("$") < 0)
1114
+ return value;
1115
+ return value.replace(CSS_VAR_PATTERN, (match, parens, quoted, prefix, name) => {
1116
+ if (parens || quoted)
1117
+ return match;
1118
+ const varName = DIGIT_FIRST.test(name) ? `m${name}` : name;
1119
+ return `${prefix}var(--${varName})`;
1120
+ });
1121
+ }
1122
+ if (typeof document !== "undefined") {
1123
+ leakScope(() => {
1124
+ $(() => {
1125
+ if (!isEmpty(cssVars)) {
1126
+ mount(document.head, () => {
1127
+ $("style", () => {
1128
+ let css = `:root {
1129
+ `;
1130
+ for (const [key, value] of Object.entries(cssVars)) {
1131
+ const varName = DIGIT_FIRST.test(String(key)) ? `m${key}` : key;
1132
+ css += ` --${varName}: ${value};
1133
+ `;
1134
+ }
1135
+ css += "}";
1136
+ $(`#${css}`);
1137
+ });
1138
+ });
1139
+ }
1140
+ });
1141
+ });
1142
+ }
1143
+ var darkModeState;
1144
+ function darkMode() {
1145
+ if (!darkModeState) {
1146
+ if (typeof window === "undefined" || !window.matchMedia)
1147
+ return false;
1148
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
1149
+ darkModeState = proxy({ value: mediaQuery.matches });
1150
+ mediaQuery.addEventListener("change", () => darkModeState.value = mediaQuery.matches);
1151
+ }
1152
+ return darkModeState.value;
1074
1153
  }
1075
1154
  function clone(src) {
1076
1155
  if (NO_COPY in src)
@@ -1182,16 +1261,32 @@ function $(...args) {
1182
1261
  for (let pos = 0;pos < argLen; pos = nextPos + 1) {
1183
1262
  nextPos = findFirst(arg, " .=:#", pos);
1184
1263
  const next = arg[nextPos];
1185
- if (next === ":" || next === "=") {
1186
- let key = arg.substring(pos, nextPos);
1187
- if (next === ":")
1188
- key = "$" + key;
1264
+ if (next === ":") {
1265
+ const key = "$" + arg.substring(pos, nextPos);
1189
1266
  if (nextPos + 1 >= argLen) {
1190
1267
  applyArg(el, key, args[++argIndex]);
1191
1268
  break;
1192
1269
  }
1193
- if (arg[nextPos + 1] === '"') {
1194
- const endIndex = findFirst(arg, '"', nextPos + 2);
1270
+ if (arg[nextPos + 1] === " ") {
1271
+ const endIndex = findFirst(arg, ";", nextPos + 2);
1272
+ const value = arg.substring(nextPos + 2, endIndex).trim();
1273
+ applyArg(el, key, value);
1274
+ nextPos = endIndex;
1275
+ } else {
1276
+ const endIndex = findFirst(arg, " ", nextPos + 1);
1277
+ const value = arg.substring(nextPos + 1, endIndex);
1278
+ applyArg(el, key, value);
1279
+ nextPos = endIndex;
1280
+ }
1281
+ } else if (next === "=") {
1282
+ const key = arg.substring(pos, nextPos);
1283
+ if (nextPos + 1 >= argLen) {
1284
+ applyArg(el, key, args[++argIndex]);
1285
+ break;
1286
+ }
1287
+ const afterEquals = arg[nextPos + 1];
1288
+ if (afterEquals === '"' || afterEquals === "'" || afterEquals === "`") {
1289
+ const endIndex = findFirst(arg, afterEquals, nextPos + 2);
1195
1290
  const value = arg.substring(nextPos + 2, endIndex);
1196
1291
  applyArg(el, key, value);
1197
1292
  nextPos = endIndex;
@@ -1264,65 +1359,98 @@ function findFirst(str, chars, startPos) {
1264
1359
  return strLen;
1265
1360
  }
1266
1361
  var cssCount = 0;
1267
- function insertCss(style, global = false) {
1268
- const prefix = global ? "" : `.AbdStl${++cssCount}`;
1269
- const css = styleToCss(style, prefix);
1362
+ function insertCss(style) {
1363
+ const prefix = `.AbdStl${++cssCount}`;
1364
+ const css = typeof style === "string" ? styleStringToCss(style, prefix) : objectToCss(style, prefix);
1270
1365
  if (css)
1271
1366
  $(`style#${css}`);
1272
1367
  return prefix;
1273
1368
  }
1369
+ function objectToCss(style, prefix) {
1370
+ let css = "";
1371
+ for (const [key, val] of Object.entries(style)) {
1372
+ if (val && typeof val === "object") {
1373
+ if (key.startsWith("@")) {
1374
+ css += `${key}{
1375
+ ${objectToCss(val, prefix)}}
1376
+ `;
1377
+ } else {
1378
+ const sel = key === "&" ? prefix : key.includes("&") ? key.replace(/&/g, prefix) : `${prefix} ${key}`.trim();
1379
+ css += objectToCss(val, sel);
1380
+ }
1381
+ } else if (typeof val === "string") {
1382
+ if (key.startsWith("@")) {
1383
+ css += `${key}{
1384
+ ${styleStringToCss(val, prefix)}}
1385
+ `;
1386
+ } else {
1387
+ const sel = key.includes("&") ? key.replace(/&/g, prefix) : `${prefix} ${key}`.trim();
1388
+ css += styleStringToCss(val, sel);
1389
+ }
1390
+ }
1391
+ }
1392
+ return css;
1393
+ }
1394
+ var KEBAB_SEGMENT = /-([a-z])/g;
1395
+ function toCamel(p) {
1396
+ return p.replace(KEBAB_SEGMENT, (_, l) => l.toUpperCase());
1397
+ }
1398
+ function styleStringToCss(styleStr, selector) {
1399
+ let props = "";
1400
+ for (let pos = 0, len = styleStr.length;pos < len; ) {
1401
+ while (styleStr[pos] === " ")
1402
+ pos++;
1403
+ if (pos >= len)
1404
+ break;
1405
+ const colon = styleStr.indexOf(":", pos);
1406
+ if (colon === -1)
1407
+ break;
1408
+ const key = styleStr.substring(pos, colon);
1409
+ pos = colon + 1;
1410
+ let val;
1411
+ if (styleStr[pos] === " ") {
1412
+ pos++;
1413
+ const semi = styleStr.indexOf(";", pos);
1414
+ val = styleStr.substring(pos, semi === -1 ? len : semi).trim();
1415
+ pos = semi === -1 ? len : semi + 1;
1416
+ } else {
1417
+ const space = styleStr.indexOf(" ", pos);
1418
+ val = styleStr.substring(pos, space === -1 ? len : space);
1419
+ pos = space === -1 ? len : space;
1420
+ }
1421
+ const v = cssVarRef(val);
1422
+ const exp = CSS_SHORT[key] || key;
1423
+ props += typeof exp === "string" ? `${exp}:${v};` : exp.map((p) => `${p}:${v};`).join("");
1424
+ }
1425
+ return props ? `${selector}{${props}}
1426
+ ` : "";
1427
+ }
1274
1428
  function insertGlobalCss(style) {
1275
- return insertCss(style, true);
1429
+ const css = objectToCss(style, "");
1430
+ if (css)
1431
+ $(`style#${css}`);
1276
1432
  }
1277
1433
  var CSS_SHORT = {
1278
1434
  m: "margin",
1279
- mt: "marginTop",
1280
- mb: "marginBottom",
1281
- ml: "marginLeft",
1282
- mr: "marginRight",
1283
- mh: ["marginLeft", "marginRight"],
1284
- mv: ["marginTop", "marginBottom"],
1435
+ mt: "margin-top",
1436
+ mb: "margin-bottom",
1437
+ ml: "margin-left",
1438
+ mr: "margin-right",
1439
+ mh: ["margin-left", "margin-right"],
1440
+ mv: ["margin-top", "margin-bottom"],
1285
1441
  p: "padding",
1286
- pt: "paddingTop",
1287
- pb: "paddingBottom",
1288
- pl: "paddingLeft",
1289
- pr: "paddingRight",
1290
- ph: ["paddingLeft", "paddingRight"],
1291
- pv: ["paddingTop", "paddingBottom"],
1442
+ pt: "padding-top",
1443
+ pb: "padding-bottom",
1444
+ pl: "padding-left",
1445
+ pr: "padding-right",
1446
+ ph: ["padding-left", "padding-right"],
1447
+ pv: ["padding-top", "padding-bottom"],
1292
1448
  w: "width",
1293
1449
  h: "height",
1294
1450
  bg: "background",
1295
1451
  fg: "color",
1296
- r: "borderRadius"
1452
+ r: "border-radius"
1297
1453
  };
1298
- function styleToCss(style, prefix) {
1299
- let props = "";
1300
- let rules = "";
1301
- for (const kOr of Object.keys(style)) {
1302
- const v = style[kOr];
1303
- for (const k of kOr.split(/, ?/g)) {
1304
- if (v && typeof v === "object") {
1305
- if (k.startsWith("@")) {
1306
- rules += `${k}{
1307
- ${styleToCss(v, prefix)}}
1308
- `;
1309
- } else {
1310
- rules += styleToCss(v, k.includes("&") ? k.replace(/&/g, prefix) : `${prefix} ${k}`);
1311
- }
1312
- } else {
1313
- const val = v == null || v === false ? "" : typeof v === "string" ? v[0] === "@" ? cssVarRef(v.substring(1)) : v : String(v);
1314
- const expanded = CSS_SHORT[k] || k;
1315
- for (const prop of Array.isArray(expanded) ? expanded : [expanded]) {
1316
- props += `${prop.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}:${val};`;
1317
- }
1318
- }
1319
- }
1320
- }
1321
- if (props)
1322
- rules = `${prefix.trimStart() || "*"}{${props}}
1323
- ${rules}`;
1324
- return rules;
1325
- }
1326
1454
  function applyArg(el, key, value) {
1327
1455
  if (typeof value === "object" && value !== null && value[TARGET_SYMBOL]) {
1328
1456
  if (key === "bind") {
@@ -1338,13 +1466,13 @@ function applyArg(el, key, value) {
1338
1466
  el.classList.remove(...classes);
1339
1467
  } else if (key[0] === "$") {
1340
1468
  key = key.substring(1);
1341
- const val = value == null || value === false ? "" : typeof value === "string" ? value[0] === "@" ? cssVarRef(value.substring(1)) : value : String(value);
1469
+ const val = value == null || value === false ? "" : typeof value === "string" ? cssVarRef(value) : String(value);
1342
1470
  const expanded = CSS_SHORT[key] || key;
1343
1471
  if (typeof expanded === "string") {
1344
- el.style[expanded] = val;
1472
+ el.style[toCamel(expanded)] = val;
1345
1473
  } else {
1346
1474
  for (const prop of expanded)
1347
- el.style[prop] = val;
1475
+ el.style[toCamel(prop)] = val;
1348
1476
  }
1349
1477
  } else if (value == null) {} else if (key in SPECIAL_PROPS) {
1350
1478
  SPECIAL_PROPS[key](el, value);
@@ -1366,9 +1494,6 @@ var onError = defaultOnError;
1366
1494
  function setErrorHandler(handler) {
1367
1495
  onError = handler || defaultOnError;
1368
1496
  }
1369
- function getParentElement() {
1370
- return currentScope.el;
1371
- }
1372
1497
  function clean(cleaner) {
1373
1498
  currentScope.cleaners.push(cleaner);
1374
1499
  }
@@ -1507,27 +1632,11 @@ function withEmitHandler(handler, func) {
1507
1632
  emit = oldEmitHandler;
1508
1633
  }
1509
1634
  }
1510
- if (typeof document !== "undefined") {
1511
- leakScope(() => {
1512
- mount(document.head, () => {
1513
- $("style", () => {
1514
- let css = `:root {
1515
- `;
1516
- for (const [key, value] of Object.entries(cssVars)) {
1517
- const varName = DIGIT_FIRST.test(String(key)) ? `m${key}` : key;
1518
- css += ` --${varName}: ${value};
1519
- `;
1520
- }
1521
- css += "}";
1522
- $(`#${css}`);
1523
- });
1524
- });
1525
- });
1526
- }
1527
1635
  export {
1528
1636
  withEmitHandler,
1529
1637
  unproxy,
1530
1638
  unmountAll,
1639
+ setSpacingCssVars,
1531
1640
  setErrorHandler,
1532
1641
  runQueue,
1533
1642
  ref,
@@ -1544,10 +1653,10 @@ export {
1544
1653
  invertString,
1545
1654
  insertGlobalCss,
1546
1655
  insertCss,
1547
- getParentElement,
1548
1656
  dump,
1549
1657
  derive,
1550
1658
  defaultEmitHandler,
1659
+ darkMode,
1551
1660
  cssVars,
1552
1661
  count,
1553
1662
  copy,
@@ -1557,5 +1666,5 @@ export {
1557
1666
  $
1558
1667
  };
1559
1668
 
1560
- //# debugId=69BD2D56BBDAB97164756E2164756E21
1669
+ //# debugId=77770EA398EEA24264756E2164756E21
1561
1670
  //# sourceMappingURL=aberdeen.js.map