tutuca 0.11.2 → 0.12.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/tutuca-cli.js +130 -104
- package/dist/tutuca-dev.ext.js +121 -90
- package/dist/tutuca-dev.js +121 -90
- package/dist/tutuca-dev.min.js +3 -3
- package/dist/tutuca-extra.ext.js +116 -59
- package/dist/tutuca-extra.js +116 -59
- package/dist/tutuca-extra.min.js +2 -2
- package/dist/tutuca-storybook.js +3 -3
- package/dist/tutuca.ext.js +116 -59
- package/dist/tutuca.js +116 -59
- package/dist/tutuca.min.js +2 -2
- package/package.json +1 -1
- package/skill/margaui/SKILL.md +105 -0
- package/skill/margaui/components/accordion.md +127 -0
- package/skill/margaui/components/alert.md +174 -0
- package/skill/margaui/components/aura.md +97 -0
- package/skill/margaui/components/avatar.md +220 -0
- package/skill/margaui/components/badge.md +193 -0
- package/skill/margaui/components/breadcrumbs.md +103 -0
- package/skill/margaui/components/button.md +322 -0
- package/skill/margaui/components/calendar.md +67 -0
- package/skill/margaui/components/card.md +373 -0
- package/skill/margaui/components/carousel.md +387 -0
- package/skill/margaui/components/chat.md +171 -0
- package/skill/margaui/components/checkbox.md +101 -0
- package/skill/margaui/components/collapse.md +172 -0
- package/skill/margaui/components/countdown.md +165 -0
- package/skill/margaui/components/diff.md +53 -0
- package/skill/margaui/components/divider.md +107 -0
- package/skill/margaui/components/dock.md +173 -0
- package/skill/margaui/components/drawer.md +184 -0
- package/skill/margaui/components/dropdown.md +388 -0
- package/skill/margaui/components/fab.md +346 -0
- package/skill/margaui/components/fieldset.md +88 -0
- package/skill/margaui/components/file-input.md +84 -0
- package/skill/margaui/components/filter.md +52 -0
- package/skill/margaui/components/footer.md +583 -0
- package/skill/margaui/components/hero.md +135 -0
- package/skill/margaui/components/hover-3d.md +129 -0
- package/skill/margaui/components/hover-gallery.md +49 -0
- package/skill/margaui/components/indicator.md +265 -0
- package/skill/margaui/components/input.md +389 -0
- package/skill/margaui/components/join.md +100 -0
- package/skill/margaui/components/kbd.md +127 -0
- package/skill/margaui/components/label.md +102 -0
- package/skill/margaui/components/link.md +96 -0
- package/skill/margaui/components/list.md +182 -0
- package/skill/margaui/components/loading.md +105 -0
- package/skill/margaui/components/mask.md +168 -0
- package/skill/margaui/components/megamenu.md +131 -0
- package/skill/margaui/components/menu.md +887 -0
- package/skill/margaui/components/mockup-browser.md +39 -0
- package/skill/margaui/components/mockup-code.md +81 -0
- package/skill/margaui/components/mockup-phone.md +39 -0
- package/skill/margaui/components/mockup-window.md +33 -0
- package/skill/margaui/components/modal.md +196 -0
- package/skill/margaui/components/navbar.md +282 -0
- package/skill/margaui/components/otp.md +171 -0
- package/skill/margaui/components/pagination.md +122 -0
- package/skill/margaui/components/progress.md +135 -0
- package/skill/margaui/components/radial-progress.md +67 -0
- package/skill/margaui/components/radio.md +133 -0
- package/skill/margaui/components/range.md +134 -0
- package/skill/margaui/components/rating.md +170 -0
- package/skill/margaui/components/select.md +225 -0
- package/skill/margaui/components/skeleton.md +64 -0
- package/skill/margaui/components/stack.md +142 -0
- package/skill/margaui/components/stat.md +254 -0
- package/skill/margaui/components/status.md +73 -0
- package/skill/margaui/components/steps.md +138 -0
- package/skill/margaui/components/swap.md +152 -0
- package/skill/margaui/components/tab.md +248 -0
- package/skill/margaui/components/table.md +1018 -0
- package/skill/margaui/components/text-rotate.md +91 -0
- package/skill/margaui/components/textarea.md +85 -0
- package/skill/margaui/components/theme-controller.md +266 -0
- package/skill/margaui/components/timeline.md +1356 -0
- package/skill/margaui/components/toast.md +165 -0
- package/skill/margaui/components/toggle.md +135 -0
- package/skill/margaui/components/tooltip.md +181 -0
- package/skill/margaui/components/validator.md +163 -0
- package/skill/tutuca/SKILL.md +56 -0
- package/skill/tutuca/advanced.md +212 -0
- package/skill/tutuca/cli.md +239 -0
- package/skill/tutuca/component-design.md +168 -0
- package/skill/tutuca/core.md +918 -0
- package/skill/tutuca/iteration.md +207 -0
- package/skill/tutuca/macros.md +86 -0
- package/skill/tutuca/margaui.md +175 -0
- package/skill/tutuca/messages-and-intents.md +399 -0
- package/skill/tutuca/patterns/README.md +48 -0
- package/skill/tutuca/patterns/add-a-story.md +26 -0
- package/skill/tutuca/patterns/bind-text-and-attributes.md +30 -0
- package/skill/tutuca/patterns/conditional-attribute-value.md +29 -0
- package/skill/tutuca/patterns/coordinate-components.md +54 -0
- package/skill/tutuca/patterns/edit-through-a-dynamic-target.md +27 -0
- package/skill/tutuca/patterns/enrich-each-item.md +25 -0
- package/skill/tutuca/patterns/file-input.md +39 -0
- package/skill/tutuca/patterns/filter-a-list.md +25 -0
- package/skill/tutuca/patterns/filter-and-paginate.md +60 -0
- package/skill/tutuca/patterns/handle-events.md +44 -0
- package/skill/tutuca/patterns/iterate-a-list.md +18 -0
- package/skill/tutuca/patterns/paginate-a-list.md +29 -0
- package/skill/tutuca/patterns/render-a-child-component.md +21 -0
- package/skill/tutuca/patterns/reuse-markup-with-macros.md +36 -0
- package/skill/tutuca/patterns/share-state-across-the-tree.md +38 -0
- package/skill/tutuca/patterns/show-or-hide-content.md +23 -0
- package/skill/tutuca/patterns/switch-between-views.md +30 -0
- package/skill/tutuca/patterns/tabbed-interface.md +43 -0
- package/skill/tutuca/semantics.md +195 -0
- package/skill/tutuca/storybook.md +270 -0
- package/skill/tutuca/styles.md +48 -0
- package/skill/tutuca/testing.md +345 -0
- package/skill/tutuca-source/SKILL.md +33 -0
- package/skill/tutuca-source/tutuca.ext.js +4301 -0
package/dist/tutuca.ext.js
CHANGED
|
@@ -566,6 +566,9 @@ var PathBuilder = class {
|
|
|
566
566
|
}
|
|
567
567
|
};
|
|
568
568
|
|
|
569
|
+
// src/util/env.js
|
|
570
|
+
var isMac = (globalThis.navigator?.userAgent ?? "").toLowerCase().includes("mac");
|
|
571
|
+
|
|
569
572
|
// src/value.js
|
|
570
573
|
var VALID_VAL_ID_RE = /^[a-zA-Z][a-zA-Z0-9_]*\??$/;
|
|
571
574
|
var isValidValId = (name) => VALID_VAL_ID_RE.test(name);
|
|
@@ -584,6 +587,7 @@ var K_NAME = 32;
|
|
|
584
587
|
var K_TYPE = 64;
|
|
585
588
|
var K_SEQ = 256;
|
|
586
589
|
var K_METHOD = 1024;
|
|
590
|
+
var K_EVENT = 2048;
|
|
587
591
|
var G_BOOL = K_FIELD | K_METHOD | K_BIND | K_DYN | K_CONST;
|
|
588
592
|
var G_TEXT = G_BOOL | K_STRTPL;
|
|
589
593
|
var G_COMPONENT = K_FIELD | K_SEQ | K_DYN;
|
|
@@ -591,6 +595,7 @@ var G_SEQUENCE = K_FIELD | K_DYN;
|
|
|
591
595
|
var G_PROVIDE = K_FIELD | K_SEQ;
|
|
592
596
|
var G_FIELD = K_FIELD | K_METHOD | K_CONST | K_SEQ;
|
|
593
597
|
var G_VALUE = K_FIELD | K_METHOD | K_BIND | K_DYN | K_NAME | K_TYPE | K_CONST;
|
|
598
|
+
var G_HANDLER_ARG = G_VALUE & ~K_NAME | K_EVENT;
|
|
594
599
|
var G_ALL = G_VALUE | K_STRTPL | K_SEQ;
|
|
595
600
|
function sizeOf(v) {
|
|
596
601
|
if (v == null) return null;
|
|
@@ -600,6 +605,10 @@ function sizeOf(v) {
|
|
|
600
605
|
if (typeof l === "number") return l;
|
|
601
606
|
return isPlainObject(v) ? Object.keys(v).length : null;
|
|
602
607
|
}
|
|
608
|
+
var toNullIfNaN = (v) => Number.isNaN(v) ? null : v;
|
|
609
|
+
function getValue(e) {
|
|
610
|
+
return e.target.type === "checkbox" ? e.target.checked : (e instanceof CustomEvent ? e.detail : e.target.value) ?? null;
|
|
611
|
+
}
|
|
603
612
|
var predTruthy = (v) => {
|
|
604
613
|
const n = sizeOf(v);
|
|
605
614
|
return n === null ? !!v : n > 0;
|
|
@@ -650,6 +659,10 @@ function parseToken(s, px) {
|
|
|
650
659
|
const num = VALID_FLOAT_RE.test(s) ? parseFloat(s) : null;
|
|
651
660
|
if (Number.isFinite(num)) return new ConstVal(num);
|
|
652
661
|
if (s === "true" || s === "false") return new ConstVal(s === "true");
|
|
662
|
+
if (c0 === 101) {
|
|
663
|
+
const m = /^e(\.[a-zA-Z][a-zA-Z0-9_]*)+$/.exec(s);
|
|
664
|
+
if (m !== null) return new EventMemberVal(s.split(".").slice(1));
|
|
665
|
+
}
|
|
653
666
|
if (c0 >= 97 && c0 <= 122) return mkVal(s, NameVal);
|
|
654
667
|
if (c0 >= 65 && c0 <= 90) return mkVal(s, TypeVal);
|
|
655
668
|
return null;
|
|
@@ -725,7 +738,7 @@ function _parseHandler(s, px, namespace, allowArgs, report, allowMethod) {
|
|
|
725
738
|
const args = new Array(tokens.length - 1);
|
|
726
739
|
for (let i = 1; i < tokens.length; i++) {
|
|
727
740
|
const val = parseToken(tokens[i], px);
|
|
728
|
-
if (val !== null && kindOf(val) &
|
|
741
|
+
if (val !== null && kindOf(val) & G_HANDLER_ARG) args[i - 1] = val;
|
|
729
742
|
else {
|
|
730
743
|
if (report) px.onParseIssue("bad-value", { role: "handler-arg", value: tokens[i] });
|
|
731
744
|
args[i - 1] = NULL_CONST_VAL;
|
|
@@ -768,6 +781,7 @@ function kindOf(val) {
|
|
|
768
781
|
if (val instanceof DynVal) return K_DYN;
|
|
769
782
|
if (val instanceof TypeVal) return K_TYPE;
|
|
770
783
|
if (val instanceof NameVal) return K_NAME;
|
|
784
|
+
if (val instanceof EventMemberVal) return K_EVENT;
|
|
771
785
|
return 0;
|
|
772
786
|
}
|
|
773
787
|
var BaseVal = class {
|
|
@@ -892,11 +906,14 @@ var HandlerNameVal = class extends NameVal {
|
|
|
892
906
|
this.namespace = namespace;
|
|
893
907
|
}
|
|
894
908
|
eval(stack) {
|
|
895
|
-
return stack.getHandlerFor(this.name, this.namespace) ?? mk404Handler(this.namespace, this.name);
|
|
909
|
+
return stack.getHandlerFor(this.name, this.namespace) ?? mk404Handler(stack, this.namespace, this.name);
|
|
896
910
|
}
|
|
897
911
|
};
|
|
898
|
-
var mk404Handler = (type, name) => function(...args) {
|
|
899
|
-
|
|
912
|
+
var mk404Handler = (stack, type, name) => function(...args) {
|
|
913
|
+
const transactor = stack?.ctx?.transactor;
|
|
914
|
+
if (transactor)
|
|
915
|
+
transactor.refuse("NO_HANDLER", { namespace: type, name, argCount: args.length });
|
|
916
|
+
else console.warn("handler not found", { type, name });
|
|
900
917
|
return this;
|
|
901
918
|
};
|
|
902
919
|
var TypeVal = class extends NameVal {
|
|
@@ -904,6 +921,53 @@ var TypeVal = class extends NameVal {
|
|
|
904
921
|
return stack.lookupType(this.name);
|
|
905
922
|
}
|
|
906
923
|
};
|
|
924
|
+
var keyIs = (k) => (e) => e.key === k;
|
|
925
|
+
var macCtrl = (e) => isMac && e.metaKey || e.ctrlKey;
|
|
926
|
+
var nullSafe = (fn) => (e, stack) => {
|
|
927
|
+
const info = stack.lookupDragInfo();
|
|
928
|
+
return info == null ? null : fn(info);
|
|
929
|
+
};
|
|
930
|
+
var EVENT_CONVENIENCES = {
|
|
931
|
+
value: (e) => getValue(e),
|
|
932
|
+
valueAsInt: (e) => toNullIfNaN(parseInt(getValue(e), 10)),
|
|
933
|
+
valueAsFloat: (e) => toNullIfNaN(parseFloat(getValue(e))),
|
|
934
|
+
isAlt: (e) => e.altKey,
|
|
935
|
+
isShift: (e) => e.shiftKey,
|
|
936
|
+
isCtrl: macCtrl,
|
|
937
|
+
isCmd: macCtrl,
|
|
938
|
+
isUpKey: keyIs("ArrowUp"),
|
|
939
|
+
isDownKey: keyIs("ArrowDown"),
|
|
940
|
+
isSend: keyIs("Enter"),
|
|
941
|
+
isCancel: keyIs("Escape"),
|
|
942
|
+
isTabKey: keyIs("Tab"),
|
|
943
|
+
dragInfo: (_e, stack) => stack.lookupDragInfo(),
|
|
944
|
+
dragType: nullSafe((info) => info.type),
|
|
945
|
+
dragValue: nullSafe((info) => info.val),
|
|
946
|
+
dragKey: nullSafe((info) => info.lookupBind("key"))
|
|
947
|
+
};
|
|
948
|
+
var EventMemberVal = class extends BaseVal {
|
|
949
|
+
constructor(members) {
|
|
950
|
+
super();
|
|
951
|
+
this.members = members;
|
|
952
|
+
}
|
|
953
|
+
eval(stack) {
|
|
954
|
+
const e = stack.lookupEvent();
|
|
955
|
+
if (e == null) return null;
|
|
956
|
+
if (this.members.length === 1) {
|
|
957
|
+
const convenience = EVENT_CONVENIENCES[this.members[0]];
|
|
958
|
+
if (convenience !== void 0) return convenience(e, stack);
|
|
959
|
+
}
|
|
960
|
+
let v = e;
|
|
961
|
+
for (const member of this.members) {
|
|
962
|
+
if (v == null) return null;
|
|
963
|
+
v = v[member];
|
|
964
|
+
}
|
|
965
|
+
return v ?? null;
|
|
966
|
+
}
|
|
967
|
+
toString() {
|
|
968
|
+
return `e.${this.members.join(".")}`;
|
|
969
|
+
}
|
|
970
|
+
};
|
|
907
971
|
var RenderVal = class extends BaseVal {
|
|
908
972
|
render(stack, _rx) {
|
|
909
973
|
return this.eval(stack);
|
|
@@ -1835,9 +1899,6 @@ var unkIter = () => {
|
|
|
1835
1899
|
};
|
|
1836
1900
|
var SEQ_INFO = /* @__PURE__ */ Symbol.for("tutuca.seqInfo");
|
|
1837
1901
|
|
|
1838
|
-
// src/util/env.js
|
|
1839
|
-
var isMac = (globalThis.navigator?.userAgent ?? "").toLowerCase().includes("mac");
|
|
1840
|
-
|
|
1841
1902
|
// src/anode.js
|
|
1842
1903
|
function resolveDynProducer(comp, name) {
|
|
1843
1904
|
let producerComp, producerProvide;
|
|
@@ -2884,8 +2945,19 @@ var Stack = class _Stack {
|
|
|
2884
2945
|
const fn = this.it[name];
|
|
2885
2946
|
return fn instanceof Function ? fn.call(this.it) : null;
|
|
2886
2947
|
}
|
|
2887
|
-
|
|
2888
|
-
|
|
2948
|
+
// Bare implicit event names are gone: a sigil-less word cannot reach a
|
|
2949
|
+
// handler-arg slot anymore, so this only ever serves stale NameVals parsed
|
|
2950
|
+
// before the removal (e.g. macro-attr pass-throughs). Always null.
|
|
2951
|
+
lookupName(_name) {
|
|
2952
|
+
return null;
|
|
2953
|
+
}
|
|
2954
|
+
// The dispatched DOM event / drag info, read only by EventMemberVal's
|
|
2955
|
+
// `e.<member>` handler args. Null outside a live event transaction.
|
|
2956
|
+
lookupEvent() {
|
|
2957
|
+
return this.ctx?.event ?? null;
|
|
2958
|
+
}
|
|
2959
|
+
lookupDragInfo() {
|
|
2960
|
+
return this.ctx?.dragInfo ?? null;
|
|
2889
2961
|
}
|
|
2890
2962
|
getHandlerFor(name, key) {
|
|
2891
2963
|
return this.comps.getHandlerFor(this.it, name, key);
|
|
@@ -3263,6 +3335,8 @@ var Transactor = class {
|
|
|
3263
3335
|
this.onTransactionPushed = () => {
|
|
3264
3336
|
};
|
|
3265
3337
|
this._observers = [];
|
|
3338
|
+
this.refusals = [];
|
|
3339
|
+
this._refusalObservers = [];
|
|
3266
3340
|
this._inflight = /* @__PURE__ */ new Set();
|
|
3267
3341
|
}
|
|
3268
3342
|
pushTransaction(t) {
|
|
@@ -3286,6 +3360,29 @@ var Transactor = class {
|
|
|
3286
3360
|
_emit(record) {
|
|
3287
3361
|
for (const cb of this._observers) cb(record);
|
|
3288
3362
|
}
|
|
3363
|
+
// Record a refusal: a dispatch the runtime could not carry out. Kinds are
|
|
3364
|
+
// open strings; today the runtime raises NO_HANDLER (a receive name with no
|
|
3365
|
+
// implementation, including the auto-generated fallback firing at dispatch
|
|
3366
|
+
// time) and FORWARD_NO_NAME (ctx.forward() from a handler whose view wrote
|
|
3367
|
+
// no name). Records carry { kind, info, timestamp } and are observational —
|
|
3368
|
+
// the dispatch itself has already failed gracefully.
|
|
3369
|
+
refuse(kind, info = {}) {
|
|
3370
|
+
const record = { kind, info, timestamp: Date.now() };
|
|
3371
|
+
this.refusals.push(record);
|
|
3372
|
+
if (this.refusals.length > REFUSAL_RING_CAP) this.refusals.shift();
|
|
3373
|
+
console.warn(`tutuca refusal [${kind}]`, info);
|
|
3374
|
+
for (const cb of this._refusalObservers) cb(record);
|
|
3375
|
+
return record;
|
|
3376
|
+
}
|
|
3377
|
+
// Subscribe to refusal records as they happen. Returns an unsubscribe fn,
|
|
3378
|
+
// like observe().
|
|
3379
|
+
observeRefusals(cb) {
|
|
3380
|
+
this._refusalObservers.push(cb);
|
|
3381
|
+
return () => {
|
|
3382
|
+
const i = this._refusalObservers.indexOf(cb);
|
|
3383
|
+
if (i !== -1) this._refusalObservers.splice(i, 1);
|
|
3384
|
+
};
|
|
3385
|
+
}
|
|
3289
3386
|
// Build and dispatch the observer record for a settled transaction. The
|
|
3290
3387
|
// resolved handler (`_resolvedHandler`/`_matched`) and per-leaf before/after
|
|
3291
3388
|
// (`_before`/`_after`) were captured while the handler ran (see callHandler /
|
|
@@ -3451,14 +3548,7 @@ var Transaction = class {
|
|
|
3451
3548
|
this._completion?.markSelfSettled({ value: newLeaf, old: curLeaf });
|
|
3452
3549
|
return curLeaf !== newLeaf ? txnPath.setValue(curRoot, newLeaf) : curRoot;
|
|
3453
3550
|
}
|
|
3454
|
-
lookupName(_name) {
|
|
3455
|
-
return null;
|
|
3456
|
-
}
|
|
3457
3551
|
};
|
|
3458
|
-
var toNullIfNaN = (v) => Number.isNaN(v) ? null : v;
|
|
3459
|
-
function getValue(e) {
|
|
3460
|
-
return e.target.type === "checkbox" ? e.target.checked : (e instanceof CustomEvent ? e.detail : e.target.value) ?? null;
|
|
3461
|
-
}
|
|
3462
3552
|
var InputEvent = class extends Transaction {
|
|
3463
3553
|
constructor(path, e, handler, transactor, dragInfo) {
|
|
3464
3554
|
super(path, transactor);
|
|
@@ -3496,8 +3586,10 @@ var InputEvent = class extends Transaction {
|
|
|
3496
3586
|
const { args = this._handlerArgs ?? [], ...rest } = f;
|
|
3497
3587
|
const hv = this.handler?.handlerCall?.handlerVal ?? this.handler?.handlerVal;
|
|
3498
3588
|
const name = hv?.name;
|
|
3499
|
-
if (name === void 0)
|
|
3500
|
-
|
|
3589
|
+
if (name === void 0) {
|
|
3590
|
+
this.transactor.refuse("FORWARD_NO_NAME", {});
|
|
3591
|
+
return;
|
|
3592
|
+
}
|
|
3501
3593
|
this.transactor.pushIntent(this.dispatchPath, name, args, rest, this);
|
|
3502
3594
|
}
|
|
3503
3595
|
buildRootStack(root, comps) {
|
|
@@ -3511,47 +3603,11 @@ var InputEvent = class extends Transaction {
|
|
|
3511
3603
|
args.push(new EventContext(path, this.transactor, this));
|
|
3512
3604
|
return [handler, args];
|
|
3513
3605
|
}
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
case "valueAsInt":
|
|
3520
|
-
return toNullIfNaN(parseInt(getValue(e), 10));
|
|
3521
|
-
case "valueAsFloat":
|
|
3522
|
-
return toNullIfNaN(parseFloat(getValue(e)));
|
|
3523
|
-
case "target":
|
|
3524
|
-
return e.target;
|
|
3525
|
-
case "event":
|
|
3526
|
-
return e;
|
|
3527
|
-
case "isAlt":
|
|
3528
|
-
return e.altKey;
|
|
3529
|
-
case "isShift":
|
|
3530
|
-
return e.shiftKey;
|
|
3531
|
-
case "isCtrl":
|
|
3532
|
-
/* falls through */
|
|
3533
|
-
case "isCmd":
|
|
3534
|
-
return isMac && e.metaKey || e.ctrlKey;
|
|
3535
|
-
case "key":
|
|
3536
|
-
return e.key;
|
|
3537
|
-
case "keyCode":
|
|
3538
|
-
return e.keyCode;
|
|
3539
|
-
case "isUpKey":
|
|
3540
|
-
return e.key === "ArrowUp";
|
|
3541
|
-
case "isDownKey":
|
|
3542
|
-
return e.key === "ArrowDown";
|
|
3543
|
-
case "isSend":
|
|
3544
|
-
return e.key === "Enter";
|
|
3545
|
-
case "isCancel":
|
|
3546
|
-
return e.key === "Escape";
|
|
3547
|
-
case "isTabKey":
|
|
3548
|
-
return e.key === "Tab";
|
|
3549
|
-
case "ctx":
|
|
3550
|
-
return new EventContext(this.dispatchPath, this.transactor, this);
|
|
3551
|
-
case "dragInfo":
|
|
3552
|
-
return this.dragInfo;
|
|
3553
|
-
}
|
|
3554
|
-
return null;
|
|
3606
|
+
// The dispatched DOM event, read only through `e.<member>` handler args
|
|
3607
|
+
// (src/value.js EventMemberVal via Stack.lookupEvent). There is no bare
|
|
3608
|
+
// implicit-name vocabulary anymore: every arg carries a sigil.
|
|
3609
|
+
get event() {
|
|
3610
|
+
return this.e;
|
|
3555
3611
|
}
|
|
3556
3612
|
};
|
|
3557
3613
|
var NameArgsTransaction = class extends Transaction {
|
|
@@ -3642,6 +3698,7 @@ var IntentEvent = class extends NameArgsTransaction {
|
|
|
3642
3698
|
}
|
|
3643
3699
|
};
|
|
3644
3700
|
var PASS = /* @__PURE__ */ Symbol.for("tutuca.intent.pass");
|
|
3701
|
+
var REFUSAL_RING_CAP = 200;
|
|
3645
3702
|
var DEFAULT_ROUTE = ["dyn", "lex"];
|
|
3646
3703
|
var INTENT_DEPTH = 64;
|
|
3647
3704
|
var IntentWalk = class {
|
package/dist/tutuca.js
CHANGED
|
@@ -1269,6 +1269,9 @@ var PathBuilder = class {
|
|
|
1269
1269
|
}
|
|
1270
1270
|
};
|
|
1271
1271
|
|
|
1272
|
+
// src/util/env.js
|
|
1273
|
+
var isMac = (globalThis.navigator?.userAgent ?? "").toLowerCase().includes("mac");
|
|
1274
|
+
|
|
1272
1275
|
// src/value.js
|
|
1273
1276
|
var VALID_VAL_ID_RE = /^[a-zA-Z][a-zA-Z0-9_]*\??$/;
|
|
1274
1277
|
var isValidValId = (name) => VALID_VAL_ID_RE.test(name);
|
|
@@ -1287,6 +1290,7 @@ var K_NAME = 32;
|
|
|
1287
1290
|
var K_TYPE = 64;
|
|
1288
1291
|
var K_SEQ = 256;
|
|
1289
1292
|
var K_METHOD = 1024;
|
|
1293
|
+
var K_EVENT = 2048;
|
|
1290
1294
|
var G_BOOL = K_FIELD | K_METHOD | K_BIND | K_DYN | K_CONST;
|
|
1291
1295
|
var G_TEXT = G_BOOL | K_STRTPL;
|
|
1292
1296
|
var G_COMPONENT = K_FIELD | K_SEQ | K_DYN;
|
|
@@ -1294,6 +1298,7 @@ var G_SEQUENCE = K_FIELD | K_DYN;
|
|
|
1294
1298
|
var G_PROVIDE = K_FIELD | K_SEQ;
|
|
1295
1299
|
var G_FIELD = K_FIELD | K_METHOD | K_CONST | K_SEQ;
|
|
1296
1300
|
var G_VALUE = K_FIELD | K_METHOD | K_BIND | K_DYN | K_NAME | K_TYPE | K_CONST;
|
|
1301
|
+
var G_HANDLER_ARG = G_VALUE & ~K_NAME | K_EVENT;
|
|
1297
1302
|
var G_ALL = G_VALUE | K_STRTPL | K_SEQ;
|
|
1298
1303
|
function sizeOf(v) {
|
|
1299
1304
|
if (v == null) return null;
|
|
@@ -1303,6 +1308,10 @@ function sizeOf(v) {
|
|
|
1303
1308
|
if (typeof l === "number") return l;
|
|
1304
1309
|
return isPlainObject(v) ? Object.keys(v).length : null;
|
|
1305
1310
|
}
|
|
1311
|
+
var toNullIfNaN = (v) => Number.isNaN(v) ? null : v;
|
|
1312
|
+
function getValue(e) {
|
|
1313
|
+
return e.target.type === "checkbox" ? e.target.checked : (e instanceof CustomEvent ? e.detail : e.target.value) ?? null;
|
|
1314
|
+
}
|
|
1306
1315
|
var predTruthy = (v) => {
|
|
1307
1316
|
const n = sizeOf(v);
|
|
1308
1317
|
return n === null ? !!v : n > 0;
|
|
@@ -1353,6 +1362,10 @@ function parseToken(s, px) {
|
|
|
1353
1362
|
const num = VALID_FLOAT_RE.test(s) ? parseFloat(s) : null;
|
|
1354
1363
|
if (Number.isFinite(num)) return new ConstVal(num);
|
|
1355
1364
|
if (s === "true" || s === "false") return new ConstVal(s === "true");
|
|
1365
|
+
if (c0 === 101) {
|
|
1366
|
+
const m = /^e(\.[a-zA-Z][a-zA-Z0-9_]*)+$/.exec(s);
|
|
1367
|
+
if (m !== null) return new EventMemberVal(s.split(".").slice(1));
|
|
1368
|
+
}
|
|
1356
1369
|
if (c0 >= 97 && c0 <= 122) return mkVal(s, NameVal);
|
|
1357
1370
|
if (c0 >= 65 && c0 <= 90) return mkVal(s, TypeVal);
|
|
1358
1371
|
return null;
|
|
@@ -1428,7 +1441,7 @@ function _parseHandler(s, px, namespace, allowArgs, report, allowMethod) {
|
|
|
1428
1441
|
const args = new Array(tokens.length - 1);
|
|
1429
1442
|
for (let i = 1; i < tokens.length; i++) {
|
|
1430
1443
|
const val = parseToken(tokens[i], px);
|
|
1431
|
-
if (val !== null && kindOf(val) &
|
|
1444
|
+
if (val !== null && kindOf(val) & G_HANDLER_ARG) args[i - 1] = val;
|
|
1432
1445
|
else {
|
|
1433
1446
|
if (report) px.onParseIssue("bad-value", { role: "handler-arg", value: tokens[i] });
|
|
1434
1447
|
args[i - 1] = NULL_CONST_VAL;
|
|
@@ -1471,6 +1484,7 @@ function kindOf(val) {
|
|
|
1471
1484
|
if (val instanceof DynVal) return K_DYN;
|
|
1472
1485
|
if (val instanceof TypeVal) return K_TYPE;
|
|
1473
1486
|
if (val instanceof NameVal) return K_NAME;
|
|
1487
|
+
if (val instanceof EventMemberVal) return K_EVENT;
|
|
1474
1488
|
return 0;
|
|
1475
1489
|
}
|
|
1476
1490
|
var BaseVal = class {
|
|
@@ -1595,11 +1609,14 @@ var HandlerNameVal = class extends NameVal {
|
|
|
1595
1609
|
this.namespace = namespace;
|
|
1596
1610
|
}
|
|
1597
1611
|
eval(stack) {
|
|
1598
|
-
return stack.getHandlerFor(this.name, this.namespace) ?? mk404Handler(this.namespace, this.name);
|
|
1612
|
+
return stack.getHandlerFor(this.name, this.namespace) ?? mk404Handler(stack, this.namespace, this.name);
|
|
1599
1613
|
}
|
|
1600
1614
|
};
|
|
1601
|
-
var mk404Handler = (type, name) => function(...args) {
|
|
1602
|
-
|
|
1615
|
+
var mk404Handler = (stack, type, name) => function(...args) {
|
|
1616
|
+
const transactor = stack?.ctx?.transactor;
|
|
1617
|
+
if (transactor)
|
|
1618
|
+
transactor.refuse("NO_HANDLER", { namespace: type, name, argCount: args.length });
|
|
1619
|
+
else console.warn("handler not found", { type, name });
|
|
1603
1620
|
return this;
|
|
1604
1621
|
};
|
|
1605
1622
|
var TypeVal = class extends NameVal {
|
|
@@ -1607,6 +1624,53 @@ var TypeVal = class extends NameVal {
|
|
|
1607
1624
|
return stack.lookupType(this.name);
|
|
1608
1625
|
}
|
|
1609
1626
|
};
|
|
1627
|
+
var keyIs = (k) => (e) => e.key === k;
|
|
1628
|
+
var macCtrl = (e) => isMac && e.metaKey || e.ctrlKey;
|
|
1629
|
+
var nullSafe = (fn) => (e, stack) => {
|
|
1630
|
+
const info = stack.lookupDragInfo();
|
|
1631
|
+
return info == null ? null : fn(info);
|
|
1632
|
+
};
|
|
1633
|
+
var EVENT_CONVENIENCES = {
|
|
1634
|
+
value: (e) => getValue(e),
|
|
1635
|
+
valueAsInt: (e) => toNullIfNaN(parseInt(getValue(e), 10)),
|
|
1636
|
+
valueAsFloat: (e) => toNullIfNaN(parseFloat(getValue(e))),
|
|
1637
|
+
isAlt: (e) => e.altKey,
|
|
1638
|
+
isShift: (e) => e.shiftKey,
|
|
1639
|
+
isCtrl: macCtrl,
|
|
1640
|
+
isCmd: macCtrl,
|
|
1641
|
+
isUpKey: keyIs("ArrowUp"),
|
|
1642
|
+
isDownKey: keyIs("ArrowDown"),
|
|
1643
|
+
isSend: keyIs("Enter"),
|
|
1644
|
+
isCancel: keyIs("Escape"),
|
|
1645
|
+
isTabKey: keyIs("Tab"),
|
|
1646
|
+
dragInfo: (_e, stack) => stack.lookupDragInfo(),
|
|
1647
|
+
dragType: nullSafe((info) => info.type),
|
|
1648
|
+
dragValue: nullSafe((info) => info.val),
|
|
1649
|
+
dragKey: nullSafe((info) => info.lookupBind("key"))
|
|
1650
|
+
};
|
|
1651
|
+
var EventMemberVal = class extends BaseVal {
|
|
1652
|
+
constructor(members) {
|
|
1653
|
+
super();
|
|
1654
|
+
this.members = members;
|
|
1655
|
+
}
|
|
1656
|
+
eval(stack) {
|
|
1657
|
+
const e = stack.lookupEvent();
|
|
1658
|
+
if (e == null) return null;
|
|
1659
|
+
if (this.members.length === 1) {
|
|
1660
|
+
const convenience = EVENT_CONVENIENCES[this.members[0]];
|
|
1661
|
+
if (convenience !== void 0) return convenience(e, stack);
|
|
1662
|
+
}
|
|
1663
|
+
let v = e;
|
|
1664
|
+
for (const member of this.members) {
|
|
1665
|
+
if (v == null) return null;
|
|
1666
|
+
v = v[member];
|
|
1667
|
+
}
|
|
1668
|
+
return v ?? null;
|
|
1669
|
+
}
|
|
1670
|
+
toString() {
|
|
1671
|
+
return `e.${this.members.join(".")}`;
|
|
1672
|
+
}
|
|
1673
|
+
};
|
|
1610
1674
|
var RenderVal = class extends BaseVal {
|
|
1611
1675
|
render(stack, _rx) {
|
|
1612
1676
|
return this.eval(stack);
|
|
@@ -2538,9 +2602,6 @@ var unkIter = () => {
|
|
|
2538
2602
|
};
|
|
2539
2603
|
var SEQ_INFO = /* @__PURE__ */ Symbol.for("tutuca.seqInfo");
|
|
2540
2604
|
|
|
2541
|
-
// src/util/env.js
|
|
2542
|
-
var isMac = (globalThis.navigator?.userAgent ?? "").toLowerCase().includes("mac");
|
|
2543
|
-
|
|
2544
2605
|
// src/anode.js
|
|
2545
2606
|
function resolveDynProducer(comp, name) {
|
|
2546
2607
|
let producerComp, producerProvide;
|
|
@@ -3587,8 +3648,19 @@ var Stack = class _Stack {
|
|
|
3587
3648
|
const fn = this.it[name];
|
|
3588
3649
|
return fn instanceof Function ? fn.call(this.it) : null;
|
|
3589
3650
|
}
|
|
3590
|
-
|
|
3591
|
-
|
|
3651
|
+
// Bare implicit event names are gone: a sigil-less word cannot reach a
|
|
3652
|
+
// handler-arg slot anymore, so this only ever serves stale NameVals parsed
|
|
3653
|
+
// before the removal (e.g. macro-attr pass-throughs). Always null.
|
|
3654
|
+
lookupName(_name) {
|
|
3655
|
+
return null;
|
|
3656
|
+
}
|
|
3657
|
+
// The dispatched DOM event / drag info, read only by EventMemberVal's
|
|
3658
|
+
// `e.<member>` handler args. Null outside a live event transaction.
|
|
3659
|
+
lookupEvent() {
|
|
3660
|
+
return this.ctx?.event ?? null;
|
|
3661
|
+
}
|
|
3662
|
+
lookupDragInfo() {
|
|
3663
|
+
return this.ctx?.dragInfo ?? null;
|
|
3592
3664
|
}
|
|
3593
3665
|
getHandlerFor(name, key) {
|
|
3594
3666
|
return this.comps.getHandlerFor(this.it, name, key);
|
|
@@ -3966,6 +4038,8 @@ var Transactor = class {
|
|
|
3966
4038
|
this.onTransactionPushed = () => {
|
|
3967
4039
|
};
|
|
3968
4040
|
this._observers = [];
|
|
4041
|
+
this.refusals = [];
|
|
4042
|
+
this._refusalObservers = [];
|
|
3969
4043
|
this._inflight = /* @__PURE__ */ new Set();
|
|
3970
4044
|
}
|
|
3971
4045
|
pushTransaction(t) {
|
|
@@ -3989,6 +4063,29 @@ var Transactor = class {
|
|
|
3989
4063
|
_emit(record) {
|
|
3990
4064
|
for (const cb of this._observers) cb(record);
|
|
3991
4065
|
}
|
|
4066
|
+
// Record a refusal: a dispatch the runtime could not carry out. Kinds are
|
|
4067
|
+
// open strings; today the runtime raises NO_HANDLER (a receive name with no
|
|
4068
|
+
// implementation, including the auto-generated fallback firing at dispatch
|
|
4069
|
+
// time) and FORWARD_NO_NAME (ctx.forward() from a handler whose view wrote
|
|
4070
|
+
// no name). Records carry { kind, info, timestamp } and are observational —
|
|
4071
|
+
// the dispatch itself has already failed gracefully.
|
|
4072
|
+
refuse(kind, info = {}) {
|
|
4073
|
+
const record = { kind, info, timestamp: Date.now() };
|
|
4074
|
+
this.refusals.push(record);
|
|
4075
|
+
if (this.refusals.length > REFUSAL_RING_CAP) this.refusals.shift();
|
|
4076
|
+
console.warn(`tutuca refusal [${kind}]`, info);
|
|
4077
|
+
for (const cb of this._refusalObservers) cb(record);
|
|
4078
|
+
return record;
|
|
4079
|
+
}
|
|
4080
|
+
// Subscribe to refusal records as they happen. Returns an unsubscribe fn,
|
|
4081
|
+
// like observe().
|
|
4082
|
+
observeRefusals(cb) {
|
|
4083
|
+
this._refusalObservers.push(cb);
|
|
4084
|
+
return () => {
|
|
4085
|
+
const i = this._refusalObservers.indexOf(cb);
|
|
4086
|
+
if (i !== -1) this._refusalObservers.splice(i, 1);
|
|
4087
|
+
};
|
|
4088
|
+
}
|
|
3992
4089
|
// Build and dispatch the observer record for a settled transaction. The
|
|
3993
4090
|
// resolved handler (`_resolvedHandler`/`_matched`) and per-leaf before/after
|
|
3994
4091
|
// (`_before`/`_after`) were captured while the handler ran (see callHandler /
|
|
@@ -4154,14 +4251,7 @@ var Transaction = class {
|
|
|
4154
4251
|
this._completion?.markSelfSettled({ value: newLeaf, old: curLeaf });
|
|
4155
4252
|
return curLeaf !== newLeaf ? txnPath.setValue(curRoot, newLeaf) : curRoot;
|
|
4156
4253
|
}
|
|
4157
|
-
lookupName(_name) {
|
|
4158
|
-
return null;
|
|
4159
|
-
}
|
|
4160
4254
|
};
|
|
4161
|
-
var toNullIfNaN = (v) => Number.isNaN(v) ? null : v;
|
|
4162
|
-
function getValue(e) {
|
|
4163
|
-
return e.target.type === "checkbox" ? e.target.checked : (e instanceof CustomEvent ? e.detail : e.target.value) ?? null;
|
|
4164
|
-
}
|
|
4165
4255
|
var InputEvent = class extends Transaction {
|
|
4166
4256
|
constructor(path, e, handler, transactor, dragInfo) {
|
|
4167
4257
|
super(path, transactor);
|
|
@@ -4199,8 +4289,10 @@ var InputEvent = class extends Transaction {
|
|
|
4199
4289
|
const { args = this._handlerArgs ?? [], ...rest } = f;
|
|
4200
4290
|
const hv = this.handler?.handlerCall?.handlerVal ?? this.handler?.handlerVal;
|
|
4201
4291
|
const name = hv?.name;
|
|
4202
|
-
if (name === void 0)
|
|
4203
|
-
|
|
4292
|
+
if (name === void 0) {
|
|
4293
|
+
this.transactor.refuse("FORWARD_NO_NAME", {});
|
|
4294
|
+
return;
|
|
4295
|
+
}
|
|
4204
4296
|
this.transactor.pushIntent(this.dispatchPath, name, args, rest, this);
|
|
4205
4297
|
}
|
|
4206
4298
|
buildRootStack(root, comps) {
|
|
@@ -4214,47 +4306,11 @@ var InputEvent = class extends Transaction {
|
|
|
4214
4306
|
args.push(new EventContext(path, this.transactor, this));
|
|
4215
4307
|
return [handler, args];
|
|
4216
4308
|
}
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
case "valueAsInt":
|
|
4223
|
-
return toNullIfNaN(parseInt(getValue(e), 10));
|
|
4224
|
-
case "valueAsFloat":
|
|
4225
|
-
return toNullIfNaN(parseFloat(getValue(e)));
|
|
4226
|
-
case "target":
|
|
4227
|
-
return e.target;
|
|
4228
|
-
case "event":
|
|
4229
|
-
return e;
|
|
4230
|
-
case "isAlt":
|
|
4231
|
-
return e.altKey;
|
|
4232
|
-
case "isShift":
|
|
4233
|
-
return e.shiftKey;
|
|
4234
|
-
case "isCtrl":
|
|
4235
|
-
/* falls through */
|
|
4236
|
-
case "isCmd":
|
|
4237
|
-
return isMac && e.metaKey || e.ctrlKey;
|
|
4238
|
-
case "key":
|
|
4239
|
-
return e.key;
|
|
4240
|
-
case "keyCode":
|
|
4241
|
-
return e.keyCode;
|
|
4242
|
-
case "isUpKey":
|
|
4243
|
-
return e.key === "ArrowUp";
|
|
4244
|
-
case "isDownKey":
|
|
4245
|
-
return e.key === "ArrowDown";
|
|
4246
|
-
case "isSend":
|
|
4247
|
-
return e.key === "Enter";
|
|
4248
|
-
case "isCancel":
|
|
4249
|
-
return e.key === "Escape";
|
|
4250
|
-
case "isTabKey":
|
|
4251
|
-
return e.key === "Tab";
|
|
4252
|
-
case "ctx":
|
|
4253
|
-
return new EventContext(this.dispatchPath, this.transactor, this);
|
|
4254
|
-
case "dragInfo":
|
|
4255
|
-
return this.dragInfo;
|
|
4256
|
-
}
|
|
4257
|
-
return null;
|
|
4309
|
+
// The dispatched DOM event, read only through `e.<member>` handler args
|
|
4310
|
+
// (src/value.js EventMemberVal via Stack.lookupEvent). There is no bare
|
|
4311
|
+
// implicit-name vocabulary anymore: every arg carries a sigil.
|
|
4312
|
+
get event() {
|
|
4313
|
+
return this.e;
|
|
4258
4314
|
}
|
|
4259
4315
|
};
|
|
4260
4316
|
var NameArgsTransaction = class extends Transaction {
|
|
@@ -4345,6 +4401,7 @@ var IntentEvent = class extends NameArgsTransaction {
|
|
|
4345
4401
|
}
|
|
4346
4402
|
};
|
|
4347
4403
|
var PASS = /* @__PURE__ */ Symbol.for("tutuca.intent.pass");
|
|
4404
|
+
var REFUSAL_RING_CAP = 200;
|
|
4348
4405
|
var DEFAULT_ROUTE = ["dyn", "lex"];
|
|
4349
4406
|
var INTENT_DEPTH = 64;
|
|
4350
4407
|
var IntentWalk = class {
|