@wildwinter/app-shell 0.30.0 → 0.32.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/index.cjs +100 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +44 -2
- package/dist/index.d.ts +44 -2
- package/dist/index.js +98 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -180,8 +180,13 @@ function iconBtn(glyph, title, onClick, disabled = false, danger = false) {
|
|
|
180
180
|
return b;
|
|
181
181
|
}
|
|
182
182
|
function labelled(label2, control) {
|
|
183
|
-
const
|
|
183
|
+
const target = control.matches("input, select, textarea") ? control : control.querySelector("input:not([type=button]):not([type=submit]), select, textarea");
|
|
184
|
+
const w = el(target ? "label" : "div", "shell-labelled");
|
|
184
185
|
w.append(el("span", "shell-fieldcap", label2), control);
|
|
186
|
+
if (target) {
|
|
187
|
+
if (!target.id) target.id = `shell-f-${Math.random().toString(36).slice(2, 9)}`;
|
|
188
|
+
w.htmlFor = target.id;
|
|
189
|
+
}
|
|
185
190
|
return w;
|
|
186
191
|
}
|
|
187
192
|
function moveItem(arr, i, delta) {
|
|
@@ -892,6 +897,7 @@ function isCaseOnlyPropertyName(name) {
|
|
|
892
897
|
}
|
|
893
898
|
|
|
894
899
|
// src/property-name-field.ts
|
|
900
|
+
var refSyncs = /* @__PURE__ */ new WeakMap();
|
|
895
901
|
function propertyNameProblem(name) {
|
|
896
902
|
if (isValidPropertyName(name)) return void 0;
|
|
897
903
|
const suggestion = propertyNameify(name);
|
|
@@ -938,6 +944,96 @@ function bindPropertyName(input, onCommit, opts = {}) {
|
|
|
938
944
|
function firstIllegalPropertyName(host) {
|
|
939
945
|
return host.querySelector("input.illegal");
|
|
940
946
|
}
|
|
947
|
+
function nearest(name, known) {
|
|
948
|
+
const n = name.toLowerCase();
|
|
949
|
+
const byPrefix = known.filter((k) => k.toLowerCase().startsWith(n) || n.startsWith(k.toLowerCase()));
|
|
950
|
+
if (byPrefix.length === 1) return byPrefix[0];
|
|
951
|
+
let best;
|
|
952
|
+
let bestScore = 3;
|
|
953
|
+
for (const k of known) {
|
|
954
|
+
const a = k.toLowerCase();
|
|
955
|
+
if (Math.abs(a.length - n.length) > 2) continue;
|
|
956
|
+
let prev = Array.from({ length: n.length + 1 }, (_, i) => i);
|
|
957
|
+
for (let i = 1; i <= a.length; i++) {
|
|
958
|
+
const row = [i];
|
|
959
|
+
for (let j = 1; j <= n.length; j++) {
|
|
960
|
+
row[j] = Math.min(prev[j] + 1, row[j - 1] + 1, prev[j - 1] + (a[i - 1] === n[j - 1] ? 0 : 1));
|
|
961
|
+
}
|
|
962
|
+
prev = row;
|
|
963
|
+
}
|
|
964
|
+
const d = prev[n.length];
|
|
965
|
+
if (d < bestScore) {
|
|
966
|
+
bestScore = d;
|
|
967
|
+
best = k;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
return best;
|
|
971
|
+
}
|
|
972
|
+
function propertyRefProblem(name, opts) {
|
|
973
|
+
const scope = opts.scope ? `@${opts.scope}` : "that scope";
|
|
974
|
+
const folded = name.toLowerCase();
|
|
975
|
+
if (!isValidPropertyName(folded)) {
|
|
976
|
+
const suggestion = propertyNameify(name);
|
|
977
|
+
const tail = suggestion ? ` Try "${suggestion}", or press Tab.` : "";
|
|
978
|
+
if (RESERVED_PROPERTY_NAMES.includes(folded)) return `Cannot be used: "${folded}" is a keyword in expressions.${tail}`;
|
|
979
|
+
if (name.includes("-")) return `Cannot be used: a hyphen reads as subtraction in an expression.${tail}`;
|
|
980
|
+
if (/^[0-9]/.test(name)) return `Cannot be used: a name cannot start with a digit.${tail}`;
|
|
981
|
+
return `Cannot be used: only lower case letters, digits and underscores.${tail}`;
|
|
982
|
+
}
|
|
983
|
+
const known = opts.known();
|
|
984
|
+
if (known.some((k) => k.toLowerCase() === folded)) return void 0;
|
|
985
|
+
const near = nearest(folded, known);
|
|
986
|
+
if (near) return `No ${scope} property is called "${name}". Did you mean "${near}"?`;
|
|
987
|
+
if (known.length === 0) return `No ${scope} properties are declared yet. Declare one above first.`;
|
|
988
|
+
const shown = known.slice(0, 3).map((k) => `"${k}"`).join(", ");
|
|
989
|
+
const more = known.length > 3 ? `, and ${known.length - 3} more` : "";
|
|
990
|
+
return `No ${scope} property is called "${name}". Declared: ${shown}${more}.`;
|
|
991
|
+
}
|
|
992
|
+
function bindPropertyRef(input, onCommit, opts) {
|
|
993
|
+
const list = document.createElement("datalist");
|
|
994
|
+
list.id = `shell-propref-${Math.random().toString(36).slice(2, 9)}`;
|
|
995
|
+
input.setAttribute("list", list.id);
|
|
996
|
+
const attach = () => {
|
|
997
|
+
if (!list.isConnected && input.parentNode) input.after(list);
|
|
998
|
+
};
|
|
999
|
+
const sync = () => {
|
|
1000
|
+
attach();
|
|
1001
|
+
const known = opts.known();
|
|
1002
|
+
list.replaceChildren(...known.map((k) => {
|
|
1003
|
+
const o = document.createElement("option");
|
|
1004
|
+
o.value = k;
|
|
1005
|
+
return o;
|
|
1006
|
+
}));
|
|
1007
|
+
const v = input.value.trim();
|
|
1008
|
+
const problem = v === "" ? void 0 : propertyRefProblem(v, opts);
|
|
1009
|
+
input.classList.toggle("illegal", !!problem);
|
|
1010
|
+
if (problem) input.title = problem;
|
|
1011
|
+
else if (input.title.startsWith("Cannot be used") || input.title.startsWith("No ")) {
|
|
1012
|
+
if (opts.hint) input.title = opts.hint;
|
|
1013
|
+
else input.removeAttribute("title");
|
|
1014
|
+
}
|
|
1015
|
+
};
|
|
1016
|
+
refSyncs.set(input, sync);
|
|
1017
|
+
input.addEventListener("input", () => {
|
|
1018
|
+
onCommit(input.value);
|
|
1019
|
+
sync();
|
|
1020
|
+
});
|
|
1021
|
+
input.addEventListener("keydown", (e) => {
|
|
1022
|
+
if (e.key !== "Tab" || e.shiftKey) return;
|
|
1023
|
+
const typed = input.value.trim();
|
|
1024
|
+
if (typed === "" || isValidPropertyName(typed.toLowerCase())) return;
|
|
1025
|
+
const coerced = propertyNameify(typed);
|
|
1026
|
+
if (!coerced || coerced === input.value) return;
|
|
1027
|
+
e.preventDefault();
|
|
1028
|
+
input.value = coerced;
|
|
1029
|
+
onCommit(coerced);
|
|
1030
|
+
sync();
|
|
1031
|
+
});
|
|
1032
|
+
sync();
|
|
1033
|
+
}
|
|
1034
|
+
function revalidatePropertyRefs(host) {
|
|
1035
|
+
for (const input of host.querySelectorAll("input")) refSyncs.get(input)?.();
|
|
1036
|
+
}
|
|
941
1037
|
|
|
942
1038
|
// src/id-editor.ts
|
|
943
1039
|
function openGameIdEditor(opts) {
|
|
@@ -1611,6 +1707,7 @@ exports.PROPERTY_NAME_HINT = PROPERTY_NAME_HINT;
|
|
|
1611
1707
|
exports.RESERVED_PROPERTY_NAMES = RESERVED_PROPERTY_NAMES;
|
|
1612
1708
|
exports.askIdentity = askIdentity;
|
|
1613
1709
|
exports.bindPropertyName = bindPropertyName;
|
|
1710
|
+
exports.bindPropertyRef = bindPropertyRef;
|
|
1614
1711
|
exports.closeAnchoredPanel = closeAnchoredPanel;
|
|
1615
1712
|
exports.closeWithExit = closeWithExit;
|
|
1616
1713
|
exports.colourFor = colourFor;
|
|
@@ -1648,7 +1745,9 @@ exports.pinButton = pinButton;
|
|
|
1648
1745
|
exports.placeAnchored = placeAnchored;
|
|
1649
1746
|
exports.propertyNameProblem = propertyNameProblem;
|
|
1650
1747
|
exports.propertyNameify = propertyNameify;
|
|
1748
|
+
exports.propertyRefProblem = propertyRefProblem;
|
|
1651
1749
|
exports.renderStepperBar = renderStepperBar;
|
|
1750
|
+
exports.revalidatePropertyRefs = revalidatePropertyRefs;
|
|
1652
1751
|
exports.saveIndicator = saveIndicator;
|
|
1653
1752
|
exports.showAbout = showAbout;
|
|
1654
1753
|
exports.staleBar = staleBar;
|