@selimssevgi/cube-design-angular 0.2.1 → 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.
@@ -1,6 +1,6 @@
1
1
  import * as i0 from "@angular/core";
2
- import { ChangeDetectionStrategy, Component, DestroyRef, Directive, ElementRef, InjectionToken, TemplateRef, afterNextRender, computed, contentChild, effect, inject, input, output, signal, untracked, viewChild } from "@angular/core";
3
- import { NgTemplateOutlet } from "@angular/common";
2
+ import { ChangeDetectionStrategy, Component, DestroyRef, Directive, ElementRef, InjectionToken, PLATFORM_ID, Renderer2, TemplateRef, afterNextRender, computed, contentChild, effect, inject, input, output, signal, untracked, viewChild } from "@angular/core";
3
+ import { NgTemplateOutlet, isPlatformBrowser } from "@angular/common";
4
4
  function sizeFor(count) {
5
5
  let s = 1;
6
6
  while (s * s * s < count && s < 7) s++;
@@ -453,6 +453,633 @@ i0.ɵɵngDeclareClassMetadata({
453
453
  }]
454
454
  }
455
455
  });
456
+ const CUBE_PINCH_APART = 1.25;
457
+ const CUBE_PINCH_TOGETHER = .8;
458
+ const CUBE_WHEEL_QUIET_MS = 250;
459
+ function startsWheelGesture(lastAt, now, quietMs = 250) {
460
+ return now - lastAt >= quietMs;
461
+ }
462
+ const stream = {
463
+ wheelAt: -Infinity,
464
+ gestureAt: -Infinity,
465
+ heard: null,
466
+ heardAfter: -Infinity,
467
+ ownedUntil: -Infinity
468
+ };
469
+ let listening = false;
470
+ function listenToThePage(quietMs) {
471
+ const w = globalThis.window;
472
+ if (listening || !w?.addEventListener) return;
473
+ listening = true;
474
+ w.addEventListener("wheel", (e) => {
475
+ if (!e.ctrlKey) return;
476
+ const now = performance.now();
477
+ stream.heard = e;
478
+ stream.heardAfter = stream.wheelAt;
479
+ stream.wheelAt = now;
480
+ if (now - stream.heardAfter < quietMs && now < stream.ownedUntil + quietMs) {
481
+ stream.ownedUntil = now;
482
+ e.preventDefault();
483
+ }
484
+ }, {
485
+ capture: true,
486
+ passive: false
487
+ });
488
+ }
489
+ var CubePinch = class CubePinch {
490
+ cubePinchDisabled = input(false, ...ngDevMode ? [{ debugName: "cubePinchDisabled" }] : /* istanbul ignore next */ []);
491
+ cubePinchQuietMs = input(250, ...ngDevMode ? [{ debugName: "cubePinchQuietMs" }] : /* istanbul ignore next */ []);
492
+ cubePinched = output();
493
+ constructor() {
494
+ listenToThePage(250);
495
+ }
496
+ pointers = /* @__PURE__ */ new Map();
497
+ pinch = null;
498
+ down(e) {
499
+ if (this.cubePinchDisabled()) return;
500
+ this.pointers.set(e.pointerId, {
501
+ x: e.clientX,
502
+ y: e.clientY
503
+ });
504
+ if (this.pointers.size !== 2) {
505
+ this.pinch = null;
506
+ return;
507
+ }
508
+ const [a, b] = [...this.pointers.values()];
509
+ this.pinch = {
510
+ distance: Math.max(1, Math.hypot(a.x - b.x, a.y - b.y)),
511
+ at: pointAt((a.x + b.x) / 2, (a.y + b.y) / 2)
512
+ };
513
+ }
514
+ move(e) {
515
+ if (this.pointers.has(e.pointerId)) this.pointers.set(e.pointerId, {
516
+ x: e.clientX,
517
+ y: e.clientY
518
+ });
519
+ }
520
+ up(e) {
521
+ if (this.pinch && this.pointers.size === 2 && this.pointers.has(e.pointerId)) {
522
+ this.pointers.set(e.pointerId, {
523
+ x: e.clientX,
524
+ y: e.clientY
525
+ });
526
+ const [a, b] = [...this.pointers.values()];
527
+ const ratio = Math.hypot(a.x - b.x, a.y - b.y) / this.pinch.distance;
528
+ const at = this.pinch.at;
529
+ this.pinch = null;
530
+ if (ratio > 1.25) this.emit("in", at, "touch", e);
531
+ else if (ratio < .8) this.emit("out", at, "touch", e);
532
+ }
533
+ this.pointers.delete(e.pointerId);
534
+ }
535
+ cancel(e) {
536
+ this.pinch = null;
537
+ this.pointers.delete(e.pointerId);
538
+ }
539
+ wheel(e) {
540
+ if (this.cubePinchDisabled() || !e.ctrlKey) return;
541
+ e.preventDefault();
542
+ const now = performance.now();
543
+ const starts = startsWheelGesture(stream.heard === e ? stream.heardAfter : stream.wheelAt, now, this.cubePinchQuietMs());
544
+ stream.wheelAt = now;
545
+ stream.ownedUntil = now;
546
+ if (!starts || e.deltaY === 0) return;
547
+ if (e.deltaY < 0) this.emit("in", pointAt(e.clientX, e.clientY), "wheel", e);
548
+ else this.emit("out", pointAt(e.clientX, e.clientY), "wheel", e);
549
+ }
550
+ gestureStart(e) {
551
+ if (this.cubePinchDisabled()) return;
552
+ e.preventDefault();
553
+ }
554
+ gestureChange(e) {
555
+ if (this.cubePinchDisabled()) return;
556
+ e.preventDefault();
557
+ }
558
+ gestureEnd(e) {
559
+ if (this.cubePinchDisabled()) return;
560
+ e.preventDefault();
561
+ const now = performance.now();
562
+ if (!startsWheelGesture(stream.wheelAt, now, this.cubePinchQuietMs())) return;
563
+ if (!startsWheelGesture(stream.gestureAt, now, this.cubePinchQuietMs())) return;
564
+ const g = e;
565
+ const scale = g.scale ?? 1;
566
+ const at = g.clientX === void 0 || g.clientY === void 0 ? null : pointAt(g.clientX, g.clientY);
567
+ if (scale > 1.25) this.emit("in", at, "gesture", e);
568
+ else if (scale < .8) this.emit("out", at, "gesture", e);
569
+ else return;
570
+ stream.gestureAt = now;
571
+ }
572
+ emit(way, at, via, event) {
573
+ this.cubePinched.emit({
574
+ way,
575
+ at,
576
+ via,
577
+ event
578
+ });
579
+ }
580
+ static ɵfac = i0.ɵɵngDeclareFactory({
581
+ minVersion: "12.0.0",
582
+ version: "22.2.4",
583
+ ngImport: i0,
584
+ type: CubePinch,
585
+ deps: [],
586
+ target: i0.ɵɵFactoryTarget.Directive
587
+ });
588
+ static ɵdir = i0.ɵɵngDeclareDirective({
589
+ minVersion: "17.1.0",
590
+ version: "22.2.4",
591
+ type: CubePinch,
592
+ isStandalone: true,
593
+ selector: "[cubePinch]",
594
+ inputs: {
595
+ cubePinchDisabled: {
596
+ classPropertyName: "cubePinchDisabled",
597
+ publicName: "cubePinchDisabled",
598
+ isSignal: true,
599
+ isRequired: false,
600
+ transformFunction: null
601
+ },
602
+ cubePinchQuietMs: {
603
+ classPropertyName: "cubePinchQuietMs",
604
+ publicName: "cubePinchQuietMs",
605
+ isSignal: true,
606
+ isRequired: false,
607
+ transformFunction: null
608
+ }
609
+ },
610
+ outputs: { cubePinched: "cubePinched" },
611
+ host: { listeners: {
612
+ "pointerdown": "down($event)",
613
+ "pointermove": "move($event)",
614
+ "pointerup": "up($event)",
615
+ "pointercancel": "cancel($event)",
616
+ "wheel": "wheel($event)",
617
+ "gesturestart": "gestureStart($event)",
618
+ "gesturechange": "gestureChange($event)",
619
+ "gestureend": "gestureEnd($event)"
620
+ } },
621
+ ngImport: i0
622
+ });
623
+ };
624
+ i0.ɵɵngDeclareClassMetadata({
625
+ minVersion: "12.0.0",
626
+ version: "22.2.4",
627
+ ngImport: i0,
628
+ type: CubePinch,
629
+ decorators: [{
630
+ type: Directive,
631
+ args: [{
632
+ selector: "[cubePinch]",
633
+ host: {
634
+ "(pointerdown)": "down($event)",
635
+ "(pointermove)": "move($event)",
636
+ "(pointerup)": "up($event)",
637
+ "(pointercancel)": "cancel($event)",
638
+ "(wheel)": "wheel($event)",
639
+ "(gesturestart)": "gestureStart($event)",
640
+ "(gesturechange)": "gestureChange($event)",
641
+ "(gestureend)": "gestureEnd($event)"
642
+ }
643
+ }]
644
+ }],
645
+ ctorParameters: () => [],
646
+ propDecorators: {
647
+ cubePinchDisabled: [{
648
+ type: i0.Input,
649
+ args: [{
650
+ isSignal: true,
651
+ alias: "cubePinchDisabled",
652
+ required: false
653
+ }]
654
+ }],
655
+ cubePinchQuietMs: [{
656
+ type: i0.Input,
657
+ args: [{
658
+ isSignal: true,
659
+ alias: "cubePinchQuietMs",
660
+ required: false
661
+ }]
662
+ }],
663
+ cubePinched: [{
664
+ type: i0.Output,
665
+ args: ["cubePinched"]
666
+ }]
667
+ }
668
+ });
669
+ const pointAt = (x, y) => globalThis.document?.elementFromPoint?.(x, y) ?? null;
670
+ const CUBE_DROP_OUT = "out";
671
+ const CUBE_CARRY_MOVE = 12;
672
+ const CUBE_CARRY_CLASSES = {
673
+ carrying: "cube-carrying",
674
+ lifted: "cube-carry-lifted",
675
+ ghost: "cube-carry-ghost",
676
+ over: "cube-carry-over"
677
+ };
678
+ const TOUCH_ECHO_MS = 800;
679
+ var CubeCarry = class CubeCarry {
680
+ cubeCarry = input(null, ...ngDevMode ? [{ debugName: "cubeCarry" }] : /* istanbul ignore next */ []);
681
+ cubeCarryDisabled = input(false, ...ngDevMode ? [{ debugName: "cubeCarryDisabled" }] : /* istanbul ignore next */ []);
682
+ cubeHoldMs = input(520, ...ngDevMode ? [{ debugName: "cubeHoldMs" }] : /* istanbul ignore next */ []);
683
+ cubeHoldSlop = input(10, ...ngDevMode ? [{ debugName: "cubeHoldSlop" }] : /* istanbul ignore next */ []);
684
+ cubeHoldBuzz = input(true, ...ngDevMode ? [{ debugName: "cubeHoldBuzz" }] : /* istanbul ignore next */ []);
685
+ cubeHeld = output();
686
+ cubeLifted = output();
687
+ cubeCarriedOver = output();
688
+ cubeDropped = output();
689
+ cubeCarryEnd = output();
690
+ element = inject(ElementRef).nativeElement;
691
+ press = null;
692
+ lastTouch = 0;
693
+ swallow = false;
694
+ doc = this.element.ownerDocument;
695
+ listening = [];
696
+ constructor() {
697
+ const swallow = (e) => {
698
+ if (!this.swallow) return;
699
+ this.swallow = false;
700
+ e.preventDefault();
701
+ e.stopImmediatePropagation();
702
+ };
703
+ this.element.addEventListener("click", swallow, true);
704
+ inject(DestroyRef).onDestroy(() => {
705
+ this.cancel();
706
+ this.element.removeEventListener("click", swallow, true);
707
+ });
708
+ }
709
+ get carrying() {
710
+ return !!this.press?.lifted;
711
+ }
712
+ touchStart(e) {
713
+ this.lastTouch = Date.now();
714
+ if (this.cubeCarryDisabled()) return;
715
+ if (e.touches.length !== 1) {
716
+ this.cancel();
717
+ return;
718
+ }
719
+ const t = e.touches[0];
720
+ this.begin(t.clientX, t.clientY, true, e);
721
+ }
722
+ mouseDown(e) {
723
+ if (this.cubeCarryDisabled() || e.button !== 0) return;
724
+ if (Date.now() - this.lastTouch < TOUCH_ECHO_MS) return;
725
+ this.begin(e.clientX, e.clientY, false, e);
726
+ }
727
+ menu(e) {
728
+ if (this.cubeCarryDisabled()) return;
729
+ e.preventDefault();
730
+ if (Date.now() - this.lastTouch < TOUCH_ECHO_MS || this.press) return;
731
+ this.fireHeld("menu", e);
732
+ }
733
+ noDrag(e) {
734
+ if (!this.cubeCarryDisabled()) e.preventDefault();
735
+ }
736
+ begin(x, y, touch, event) {
737
+ this.cancel();
738
+ this.swallow = false;
739
+ const p = {
740
+ x,
741
+ y,
742
+ touch,
743
+ event,
744
+ lifted: false,
745
+ moved: false,
746
+ scrolled: false,
747
+ dx: 0,
748
+ dy: 0,
749
+ target: null
750
+ };
751
+ this.press = p;
752
+ p.timer = setTimeout(() => this.lift(), this.cubeHoldMs());
753
+ if (touch) {
754
+ this.listen("touchmove", (ev) => this.touchMove(ev), { passive: false });
755
+ this.listen("touchend", (ev) => this.touchEnd(ev), { passive: false });
756
+ this.listen("touchcancel", () => this.cancel(), {});
757
+ this.listen("touchstart", (ev) => ev.touches.length > 1 && this.cancel(), { passive: true });
758
+ } else {
759
+ this.listen("mousemove", (ev) => this.moveTo(ev.clientX, ev.clientY), {});
760
+ this.listen("mouseup", () => this.end(), {});
761
+ }
762
+ this.listen("keydown", (ev) => {
763
+ if (ev.key !== "Escape" || !this.press) return;
764
+ if (this.press.lifted) ev.stopPropagation();
765
+ this.cancel();
766
+ }, { capture: true });
767
+ }
768
+ touchMove(e) {
769
+ if (!this.press) return;
770
+ if (e.touches.length > 1) {
771
+ this.cancel();
772
+ return;
773
+ }
774
+ if (this.press.lifted && e.cancelable) e.preventDefault();
775
+ const t = e.touches[0];
776
+ if (t) this.moveTo(t.clientX, t.clientY);
777
+ }
778
+ touchEnd(e) {
779
+ if (!this.press || e.touches.length > 0) return;
780
+ if (this.press.lifted && e.cancelable) e.preventDefault();
781
+ this.end();
782
+ }
783
+ lift() {
784
+ const p = this.press;
785
+ if (!p) return;
786
+ p.timer = void 0;
787
+ const piece = this.cubeCarry();
788
+ if (!piece) {
789
+ this.forget();
790
+ this.fireHeld("press", p.event);
791
+ return;
792
+ }
793
+ p.lifted = true;
794
+ this.swallow = true;
795
+ if (this.cubeHoldBuzz()) globalThis.navigator?.vibrate?.(12);
796
+ const r = this.element.getBoundingClientRect();
797
+ const ghost = this.element.cloneNode(true);
798
+ ghost.removeAttribute("data-drop");
799
+ ghost.removeAttribute("id");
800
+ ghost.querySelectorAll("[id],[data-drop]").forEach((el) => {
801
+ el.removeAttribute("id");
802
+ el.removeAttribute("data-drop");
803
+ });
804
+ ghost.classList.add(CUBE_CARRY_CLASSES.ghost);
805
+ ghost.setAttribute("aria-hidden", "true");
806
+ Object.assign(ghost.style, {
807
+ position: "fixed",
808
+ zIndex: "var(--cube-carry-ghost-z, 1000)",
809
+ pointerEvents: "none",
810
+ margin: "0",
811
+ boxSizing: "border-box",
812
+ width: r.width + "px",
813
+ height: r.height + "px",
814
+ left: r.left + "px",
815
+ top: r.top + "px",
816
+ transform: "var(--cube-carry-ghost-transform, scale(1.08) rotate(-2deg))",
817
+ boxShadow: "var(--cube-carry-ghost-shadow, 0 14px 32px rgb(0 0 0 / 0.28))",
818
+ opacity: "var(--cube-carry-ghost-opacity, 0.95)"
819
+ });
820
+ p.dx = p.x - r.left;
821
+ p.dy = p.y - r.top;
822
+ p.ghost = ghost;
823
+ this.doc.body.appendChild(ghost);
824
+ this.element.classList.add(CUBE_CARRY_CLASSES.lifted);
825
+ p.opacity = this.element.style.opacity;
826
+ this.element.style.opacity = "var(--cube-carry-lifted-opacity, 0.3)";
827
+ this.doc.body.classList.add(CUBE_CARRY_CLASSES.carrying);
828
+ this.cubeLifted.emit({
829
+ piece,
830
+ element: this.element,
831
+ ghost
832
+ });
833
+ }
834
+ moveTo(x, y) {
835
+ const p = this.press;
836
+ if (!p) return;
837
+ if (!p.lifted) {
838
+ if (Math.hypot(x - p.x, y - p.y) > this.cubeHoldSlop()) {
839
+ clearTimeout(p.timer);
840
+ p.timer = void 0;
841
+ p.scrolled = true;
842
+ }
843
+ return;
844
+ }
845
+ if (!p.ghost) return;
846
+ if (Math.hypot(x - p.x, y - p.y) > 12) p.moved = true;
847
+ p.ghost.style.left = x - p.dx + "px";
848
+ p.ghost.style.top = y - p.dy + "px";
849
+ let target = (this.doc.elementFromPoint?.(x, y) ?? null)?.closest("[data-drop]") ?? null;
850
+ if (target && (target === this.element || this.element.contains(target))) target = null;
851
+ if (target !== p.target) {
852
+ p.target?.classList.remove(CUBE_CARRY_CLASSES.over);
853
+ p.target = target;
854
+ target?.classList.add(CUBE_CARRY_CLASSES.over);
855
+ this.cubeCarriedOver.emit({
856
+ piece: this.cubeCarry() ?? "",
857
+ onto: target?.dataset["drop"] ?? null,
858
+ target
859
+ });
860
+ }
861
+ }
862
+ end() {
863
+ const p = this.press;
864
+ if (!p) return;
865
+ this.forget();
866
+ if (!p.lifted) return;
867
+ const piece = this.cubeCarry() ?? "";
868
+ this.clean(p);
869
+ if (!p.moved) {
870
+ this.fireHeld("press", p.event, false);
871
+ this.cubeCarryEnd.emit("held");
872
+ return;
873
+ }
874
+ if (!p.target) {
875
+ this.cubeCarryEnd.emit("nowhere");
876
+ return;
877
+ }
878
+ this.cubeDropped.emit({
879
+ piece,
880
+ onto: p.target.dataset["drop"] ?? "",
881
+ target: p.target
882
+ });
883
+ this.cubeCarryEnd.emit("dropped");
884
+ }
885
+ cancel() {
886
+ const p = this.press;
887
+ if (!p) return;
888
+ this.forget();
889
+ if (p.lifted) {
890
+ this.clean(p);
891
+ this.cubeCarryEnd.emit("cancelled");
892
+ }
893
+ }
894
+ clean(p) {
895
+ p.ghost?.remove();
896
+ p.target?.classList.remove(CUBE_CARRY_CLASSES.over);
897
+ this.element.classList.remove(CUBE_CARRY_CLASSES.lifted);
898
+ if (p.opacity !== void 0) this.element.style.opacity = p.opacity;
899
+ this.doc.body.classList.remove(CUBE_CARRY_CLASSES.carrying);
900
+ }
901
+ forget() {
902
+ if (this.press) clearTimeout(this.press.timer);
903
+ this.press = null;
904
+ for (const [type, fn, opts] of this.listening.splice(0)) this.doc.removeEventListener(type, fn, opts);
905
+ }
906
+ listen(type, fn, opts) {
907
+ this.doc.addEventListener(type, fn, opts);
908
+ this.listening.push([
909
+ type,
910
+ fn,
911
+ opts
912
+ ]);
913
+ }
914
+ fireHeld(via, event, buzz = true) {
915
+ this.swallow = true;
916
+ if (buzz && this.cubeHoldBuzz()) globalThis.navigator?.vibrate?.(12);
917
+ this.cubeHeld.emit({
918
+ via,
919
+ element: this.element,
920
+ event
921
+ });
922
+ }
923
+ static ɵfac = i0.ɵɵngDeclareFactory({
924
+ minVersion: "12.0.0",
925
+ version: "22.2.4",
926
+ ngImport: i0,
927
+ type: CubeCarry,
928
+ deps: [],
929
+ target: i0.ɵɵFactoryTarget.Directive
930
+ });
931
+ static ɵdir = i0.ɵɵngDeclareDirective({
932
+ minVersion: "17.1.0",
933
+ version: "22.2.4",
934
+ type: CubeCarry,
935
+ isStandalone: true,
936
+ selector: "[cubeCarry]",
937
+ inputs: {
938
+ cubeCarry: {
939
+ classPropertyName: "cubeCarry",
940
+ publicName: "cubeCarry",
941
+ isSignal: true,
942
+ isRequired: false,
943
+ transformFunction: null
944
+ },
945
+ cubeCarryDisabled: {
946
+ classPropertyName: "cubeCarryDisabled",
947
+ publicName: "cubeCarryDisabled",
948
+ isSignal: true,
949
+ isRequired: false,
950
+ transformFunction: null
951
+ },
952
+ cubeHoldMs: {
953
+ classPropertyName: "cubeHoldMs",
954
+ publicName: "cubeHoldMs",
955
+ isSignal: true,
956
+ isRequired: false,
957
+ transformFunction: null
958
+ },
959
+ cubeHoldSlop: {
960
+ classPropertyName: "cubeHoldSlop",
961
+ publicName: "cubeHoldSlop",
962
+ isSignal: true,
963
+ isRequired: false,
964
+ transformFunction: null
965
+ },
966
+ cubeHoldBuzz: {
967
+ classPropertyName: "cubeHoldBuzz",
968
+ publicName: "cubeHoldBuzz",
969
+ isSignal: true,
970
+ isRequired: false,
971
+ transformFunction: null
972
+ }
973
+ },
974
+ outputs: {
975
+ cubeHeld: "cubeHeld",
976
+ cubeLifted: "cubeLifted",
977
+ cubeCarriedOver: "cubeCarriedOver",
978
+ cubeDropped: "cubeDropped",
979
+ cubeCarryEnd: "cubeCarryEnd"
980
+ },
981
+ host: {
982
+ listeners: {
983
+ "touchstart": "touchStart($event)",
984
+ "mousedown": "mouseDown($event)",
985
+ "contextmenu": "menu($event)",
986
+ "dragstart": "noDrag($event)",
987
+ "keydown": "swallow = false"
988
+ },
989
+ properties: {
990
+ "style.user-select": "cubeCarryDisabled() ? null : \"none\"",
991
+ "style.-webkit-user-select": "cubeCarryDisabled() ? null : \"none\"",
992
+ "style.-webkit-touch-callout": "cubeCarryDisabled() ? null : \"none\""
993
+ }
994
+ },
995
+ ngImport: i0
996
+ });
997
+ };
998
+ i0.ɵɵngDeclareClassMetadata({
999
+ minVersion: "12.0.0",
1000
+ version: "22.2.4",
1001
+ ngImport: i0,
1002
+ type: CubeCarry,
1003
+ decorators: [{
1004
+ type: Directive,
1005
+ args: [{
1006
+ selector: "[cubeCarry]",
1007
+ host: {
1008
+ "[style.user-select]": "cubeCarryDisabled() ? null : \"none\"",
1009
+ "[style.-webkit-user-select]": "cubeCarryDisabled() ? null : \"none\"",
1010
+ "[style.-webkit-touch-callout]": "cubeCarryDisabled() ? null : \"none\"",
1011
+ "(touchstart)": "touchStart($event)",
1012
+ "(mousedown)": "mouseDown($event)",
1013
+ "(contextmenu)": "menu($event)",
1014
+ "(dragstart)": "noDrag($event)",
1015
+ "(keydown)": "swallow = false"
1016
+ }
1017
+ }]
1018
+ }],
1019
+ ctorParameters: () => [],
1020
+ propDecorators: {
1021
+ cubeCarry: [{
1022
+ type: i0.Input,
1023
+ args: [{
1024
+ isSignal: true,
1025
+ alias: "cubeCarry",
1026
+ required: false
1027
+ }]
1028
+ }],
1029
+ cubeCarryDisabled: [{
1030
+ type: i0.Input,
1031
+ args: [{
1032
+ isSignal: true,
1033
+ alias: "cubeCarryDisabled",
1034
+ required: false
1035
+ }]
1036
+ }],
1037
+ cubeHoldMs: [{
1038
+ type: i0.Input,
1039
+ args: [{
1040
+ isSignal: true,
1041
+ alias: "cubeHoldMs",
1042
+ required: false
1043
+ }]
1044
+ }],
1045
+ cubeHoldSlop: [{
1046
+ type: i0.Input,
1047
+ args: [{
1048
+ isSignal: true,
1049
+ alias: "cubeHoldSlop",
1050
+ required: false
1051
+ }]
1052
+ }],
1053
+ cubeHoldBuzz: [{
1054
+ type: i0.Input,
1055
+ args: [{
1056
+ isSignal: true,
1057
+ alias: "cubeHoldBuzz",
1058
+ required: false
1059
+ }]
1060
+ }],
1061
+ cubeHeld: [{
1062
+ type: i0.Output,
1063
+ args: ["cubeHeld"]
1064
+ }],
1065
+ cubeLifted: [{
1066
+ type: i0.Output,
1067
+ args: ["cubeLifted"]
1068
+ }],
1069
+ cubeCarriedOver: [{
1070
+ type: i0.Output,
1071
+ args: ["cubeCarriedOver"]
1072
+ }],
1073
+ cubeDropped: [{
1074
+ type: i0.Output,
1075
+ args: ["cubeDropped"]
1076
+ }],
1077
+ cubeCarryEnd: [{
1078
+ type: i0.Output,
1079
+ args: ["cubeCarryEnd"]
1080
+ }]
1081
+ }
1082
+ });
456
1083
  const CUBE_ICON_NAMES = [
457
1084
  "names",
458
1085
  "name",
@@ -793,6 +1420,7 @@ const CONTEXT_PART_ORDER = [
793
1420
  "view",
794
1421
  "sort",
795
1422
  "move",
1423
+ "where",
796
1424
  "whose",
797
1425
  "hide"
798
1426
  ];
@@ -802,7 +1430,10 @@ function orderParts(parts) {
802
1430
  }
803
1431
  const CONTEXT_CUBE_SOURCE = new InjectionToken("CONTEXT_CUBE_SOURCE");
804
1432
  const CONTEXT_CUBE_WORDS = new InjectionToken("CONTEXT_CUBE_WORDS");
805
- const PART_ICONS = { hide: "shown" };
1433
+ const PART_ICONS = {
1434
+ hide: "shown",
1435
+ where: "place"
1436
+ };
806
1437
  function partsLevel(parts, words, now = {}) {
807
1438
  return orderParts(parts).map((p) => ({
808
1439
  key: p,
@@ -857,9 +1488,12 @@ function gridFor(view, count) {
857
1488
  }
858
1489
  }
859
1490
  }
860
- function sortItems(items, by, dir) {
1491
+ const TEXT_ORDERS = ["natural", "plain"];
1492
+ function sortItems(items, by, dir, text = "natural") {
861
1493
  const sign = dir === "down" ? -1 : 1;
862
- const known = (v) => v !== null && v !== void 0 && v !== "";
1494
+ const known = (v) => v !== null && v !== void 0 && v !== "" && !(typeof v === "number" && Number.isNaN(v));
1495
+ const collator = new Intl.Collator(void 0, { numeric: text === "natural" });
1496
+ const compare = (a, b) => typeof a === "number" && typeof b === "number" ? a - b : collator.compare(String(a), String(b));
863
1497
  return items.map((item, at) => ({
864
1498
  item,
865
1499
  at,
@@ -871,10 +1505,6 @@ function sortItems(items, by, dir) {
871
1505
  return sign * compare(a.value, b.value) || a.at - b.at;
872
1506
  }).map((x) => x.item);
873
1507
  }
874
- function compare(a, b) {
875
- if (typeof a === "number" && typeof b === "number") return a - b;
876
- return String(a).localeCompare(String(b));
877
- }
878
1508
  function namesLevel(names, words, opts = {}) {
879
1509
  const tiles = [...names.filter((n) => n.current), ...names.filter((n) => !n.current).reverse()].map((n, i) => ({
880
1510
  key: `name:${i}:${n.name}`,
@@ -952,6 +1582,122 @@ function sortDirectionsLevel(option, now, words) {
952
1582
  data: dir
953
1583
  }));
954
1584
  }
1585
+ function insideOf(source, piece) {
1586
+ const seen = /* @__PURE__ */ new Set();
1587
+ const walk = [...source.partsOf(piece)];
1588
+ while (walk.length) {
1589
+ const p = walk.pop();
1590
+ if (p === piece || seen.has(p)) continue;
1591
+ seen.add(p);
1592
+ walk.push(...source.partsOf(p));
1593
+ }
1594
+ return seen;
1595
+ }
1596
+ function wouldLoop(source, piece, place) {
1597
+ return piece === place || insideOf(source, piece).has(place);
1598
+ }
1599
+ function refusalOf(source, piece, place) {
1600
+ if (source.placesOf(piece).includes(place)) return null;
1601
+ if (wouldLoop(source, piece, place)) return "inside-itself";
1602
+ return source.refuses?.(piece, place) ?? null;
1603
+ }
1604
+ function placesOf(source, held, opts = {}) {
1605
+ const at = opts.at ?? source.top;
1606
+ const inside = insideOf(source, held);
1607
+ const where = new Set(source.placesOf(held));
1608
+ const given = source.givenPlaceOf?.(held) ?? null;
1609
+ const hidden = (id) => !!source.hidden?.(id);
1610
+ const shown = (place) => source.partsOf(place).filter((p) => !hidden(p));
1611
+ const refused = (place) => refusalOf(source, held, place);
1612
+ const usable = (q) => q !== held && !inside.has(q) && (where.has(q) || !refused(q));
1613
+ const reached = /* @__PURE__ */ new Map();
1614
+ const reaches = (q, trail = /* @__PURE__ */ new Set()) => {
1615
+ if (reached.has(q)) return reached.get(q);
1616
+ if (trail.has(q)) return false;
1617
+ trail.add(q);
1618
+ const r = shown(q).some((p) => p !== held && !inside.has(p) && (usable(p) || reaches(p, trail)));
1619
+ reached.set(q, r);
1620
+ return r;
1621
+ };
1622
+ const place = (key, isAt, deeper) => {
1623
+ const stands = where.has(key);
1624
+ const holds = shown(key).filter((p) => p !== held);
1625
+ const tap = stands ? "take-out" : "stand";
1626
+ return {
1627
+ key,
1628
+ title: source.nameOf(key),
1629
+ at: isAt,
1630
+ top: key === source.top,
1631
+ in: stands,
1632
+ last: stands && where.size === 1,
1633
+ given: given === key,
1634
+ self: false,
1635
+ inside: false,
1636
+ tap,
1637
+ refused: stands ? given === key ? "given-place" : where.size === 1 ? "last-place" : null : refused(key),
1638
+ holds,
1639
+ empty: holds.length === 0,
1640
+ deeper
1641
+ };
1642
+ };
1643
+ const pale = (key, self) => {
1644
+ const holds = shown(key).filter((p) => p !== held);
1645
+ return {
1646
+ key,
1647
+ title: source.nameOf(key),
1648
+ at: false,
1649
+ top: key === source.top,
1650
+ in: false,
1651
+ last: false,
1652
+ given: false,
1653
+ self,
1654
+ inside: !self,
1655
+ tap: null,
1656
+ refused: "inside-itself",
1657
+ holds,
1658
+ empty: holds.length === 0,
1659
+ deeper: false
1660
+ };
1661
+ };
1662
+ if (opts.flat) {
1663
+ const out = [];
1664
+ const seen = /* @__PURE__ */ new Set();
1665
+ const queue = [at];
1666
+ while (queue.length) {
1667
+ const q = queue.shift();
1668
+ if (seen.has(q) || q === held || inside.has(q)) continue;
1669
+ seen.add(q);
1670
+ if (usable(q) || q === at && q === source.top) out.push(place(q, q === at, false));
1671
+ queue.push(...shown(q));
1672
+ }
1673
+ return out;
1674
+ }
1675
+ const out = [];
1676
+ if (at !== held && !inside.has(at) && (usable(at) || at === source.top)) out.push(place(at, true, false));
1677
+ for (const p of shown(at)) {
1678
+ if (p === at) continue;
1679
+ if (p === held || inside.has(p)) {
1680
+ out.push(pale(p, p === held));
1681
+ continue;
1682
+ }
1683
+ const deeper = reaches(p);
1684
+ if (usable(p) || deeper) out.push(place(p, false, deeper));
1685
+ }
1686
+ return out;
1687
+ }
1688
+ function whereLevel(places, words = {}, opts = {}) {
1689
+ const pathOf = opts.pathOf ?? ((p) => ["where", p.key]);
1690
+ return places.map((p) => ({
1691
+ key: "where:" + p.key,
1692
+ title: words.title?.(p) ?? p.title,
1693
+ line: words.line?.(p) ?? null,
1694
+ icon: "place",
1695
+ inUse: p.in,
1696
+ pale: p.tap === null || !p.in && p.refused !== null,
1697
+ zoom: p.deeper ? pathOf(p) : null,
1698
+ data: p
1699
+ }));
1700
+ }
955
1701
  const TURNING_SIDES = 4;
956
1702
  function turningRows(pieces, own, cols = 3, rows = cols) {
957
1703
  const across = Math.max(1, Math.floor(cols));
@@ -1087,7 +1833,7 @@ const noteTurned = (key) => {
1087
1833
  localStorage.setItem(key, String(readTurned(key) + 1));
1088
1834
  } catch {}
1089
1835
  };
1090
- const reducedMotion = () => typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
1836
+ const reducedMotion$1 = () => typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
1091
1837
  var CubeSquare = class CubeSquare {
1092
1838
  tiles = input.required(...ngDevMode ? [{ debugName: "tiles" }] : /* istanbul ignore next */ []);
1093
1839
  view = input("square", ...ngDevMode ? [{ debugName: "view" }] : /* istanbul ignore next */ []);
@@ -1149,7 +1895,7 @@ var CubeSquare = class CubeSquare {
1149
1895
  openPlaces = computed(() => Array.from({ length: this.layout().open }, (_, i) => i), ...ngDevMode ? [{ debugName: "openPlaces" }] : /* istanbul ignore next */ []);
1150
1896
  angles = signal({}, ...ngDevMode ? [{ debugName: "angles" }] : /* istanbul ignore next */ []);
1151
1897
  dragging = signal(null, ...ngDevMode ? [{ debugName: "dragging" }] : /* istanbul ignore next */ []);
1152
- still = signal(reducedMotion(), ...ngDevMode ? [{ debugName: "still" }] : /* istanbul ignore next */ []);
1898
+ still = signal(reducedMotion$1(), ...ngDevMode ? [{ debugName: "still" }] : /* istanbul ignore next */ []);
1153
1899
  nudging = signal(false, ...ngDevMode ? [{ debugName: "nudging" }] : /* istanbul ignore next */ []);
1154
1900
  drag = null;
1155
1901
  fingers = /* @__PURE__ */ new Set();
@@ -1264,7 +2010,7 @@ var CubeSquare = class CubeSquare {
1264
2010
  }
1265
2011
  nudge() {
1266
2012
  const rings = this.rings();
1267
- if (this.nudged || !rings || reducedMotion()) return;
2013
+ if (this.nudged || !rings || reducedMotion$1()) return;
1268
2014
  if (readTurned(this.nudgeKey()) >= 3) return;
1269
2015
  const rows = rings.sides.flatMap((s, i) => s > 1 ? [i] : []);
1270
2016
  if (!rows.length) return;
@@ -1318,7 +2064,7 @@ var CubeSquare = class CubeSquare {
1318
2064
  const { cols, list } = this.layout();
1319
2065
  const view = this.view();
1320
2066
  const el = this.grid()?.nativeElement;
1321
- if (el && before && cols !== before && view === beforeView && !list && !reducedMotion() && typeof el.animate === "function") el.animate([{ transform: `scale(${cols / before})` }, { transform: "none" }], {
2067
+ if (el && before && cols !== before && view === beforeView && !list && !reducedMotion$1() && typeof el.animate === "function") el.animate([{ transform: `scale(${cols / before})` }, { transform: "none" }], {
1322
2068
  duration: 420,
1323
2069
  easing: "cubic-bezier(.2,.7,.2,1)"
1324
2070
  });
@@ -1799,12 +2545,71 @@ function contextIcon(tile) {
1799
2545
  if (tile.icon === "hide") return "shown";
1800
2546
  return "face";
1801
2547
  }
2548
+ var ContextAttrs = class ContextAttrs {
2549
+ ccAttrs = input(...ngDevMode ? [void 0, { debugName: "ccAttrs" }] : /* istanbul ignore next */ []);
2550
+ el = inject(ElementRef);
2551
+ renderer = inject(Renderer2);
2552
+ set = [];
2553
+ constructor() {
2554
+ effect(() => {
2555
+ const attrs = this.ccAttrs() ?? {};
2556
+ const node = this.el.nativeElement;
2557
+ const next = Object.keys(attrs).filter((k) => k.startsWith("data-") && attrs[k] != null);
2558
+ for (const k of this.set) if (!next.includes(k)) this.renderer.removeAttribute(node, k);
2559
+ for (const k of next) this.renderer.setAttribute(node, k, attrs[k]);
2560
+ this.set = next;
2561
+ });
2562
+ }
2563
+ static ɵfac = i0.ɵɵngDeclareFactory({
2564
+ minVersion: "12.0.0",
2565
+ version: "22.2.4",
2566
+ ngImport: i0,
2567
+ type: ContextAttrs,
2568
+ deps: [],
2569
+ target: i0.ɵɵFactoryTarget.Directive
2570
+ });
2571
+ static ɵdir = i0.ɵɵngDeclareDirective({
2572
+ minVersion: "17.1.0",
2573
+ version: "22.2.4",
2574
+ type: ContextAttrs,
2575
+ isStandalone: true,
2576
+ selector: "[ccAttrs]",
2577
+ inputs: { ccAttrs: {
2578
+ classPropertyName: "ccAttrs",
2579
+ publicName: "ccAttrs",
2580
+ isSignal: true,
2581
+ isRequired: false,
2582
+ transformFunction: null
2583
+ } },
2584
+ ngImport: i0
2585
+ });
2586
+ };
2587
+ i0.ɵɵngDeclareClassMetadata({
2588
+ minVersion: "12.0.0",
2589
+ version: "22.2.4",
2590
+ ngImport: i0,
2591
+ type: ContextAttrs,
2592
+ decorators: [{
2593
+ type: Directive,
2594
+ args: [{ selector: "[ccAttrs]" }]
2595
+ }],
2596
+ ctorParameters: () => [],
2597
+ propDecorators: { ccAttrs: [{
2598
+ type: i0.Input,
2599
+ args: [{
2600
+ isSignal: true,
2601
+ alias: "ccAttrs",
2602
+ required: false
2603
+ }]
2604
+ }] }
2605
+ });
1802
2606
  var CubeContext = class CubeContext {
1803
2607
  held = input.required(...ngDevMode ? [{ debugName: "held" }] : /* istanbul ignore next */ []);
1804
2608
  path = input([], ...ngDevMode ? [{ debugName: "path" }] : /* istanbul ignore next */ []);
1805
2609
  source = input(null, ...ngDevMode ? [{ debugName: "source" }] : /* istanbul ignore next */ []);
1806
2610
  words = input(null, ...ngDevMode ? [{ debugName: "words" }] : /* istanbul ignore next */ []);
1807
2611
  maxSide = input(880, ...ngDevMode ? [{ debugName: "maxSide" }] : /* istanbul ignore next */ []);
2612
+ heldKey = input((held) => held, ...ngDevMode ? [{ debugName: "heldKey" }] : /* istanbul ignore next */ []);
1808
2613
  enter = output();
1809
2614
  out = output();
1810
2615
  done = output();
@@ -1838,6 +2643,14 @@ var CubeContext = class CubeContext {
1838
2643
  untracked(() => this.busy.set(null));
1839
2644
  });
1840
2645
  }
2646
+ zoomInto(tile, element) {
2647
+ if (this.busy() !== null || !tile.zoom?.length) return;
2648
+ if (element) this.tapped.emit({
2649
+ tile,
2650
+ element
2651
+ });
2652
+ this.enter.emit([...tile.zoom]);
2653
+ }
1841
2654
  async tap(tile, element) {
1842
2655
  if (this.busy() !== null) return;
1843
2656
  if (element) this.tapped.emit({
@@ -1847,7 +2660,8 @@ var CubeContext = class CubeContext {
1847
2660
  const held = this.held();
1848
2661
  const path = this.path();
1849
2662
  const where = this.where();
1850
- const here = () => this.held() === held && this.where() === where;
2663
+ const key = this.heldKey();
2664
+ const here = () => key(this.held()) === key(held) && this.where() === where;
1851
2665
  this.busy.set(tile.key);
1852
2666
  try {
1853
2667
  const picked = await this.from().pick(held, path, tile);
@@ -1915,6 +2729,13 @@ var CubeContext = class CubeContext {
1915
2729
  isSignal: true,
1916
2730
  isRequired: false,
1917
2731
  transformFunction: null
2732
+ },
2733
+ heldKey: {
2734
+ classPropertyName: "heldKey",
2735
+ publicName: "heldKey",
2736
+ isSignal: true,
2737
+ isRequired: false,
2738
+ transformFunction: null
1918
2739
  }
1919
2740
  },
1920
2741
  outputs: {
@@ -1933,35 +2754,57 @@ var CubeContext = class CubeContext {
1933
2754
  [class.cc-adds]="adds()"
1934
2755
  >
1935
2756
  <ng-template [cubeSquareTile]="tiles()" let-t let-level="level">
1936
- <button
1937
- type="button"
1938
- [class]="'cc-tile cc-l' + level"
1939
- [class.cc-in-use]="!!t.inUse"
1940
- [class.cc-pale]="!!t.pale"
1941
- [class.cc-adds]="!!t.adds"
1942
- [class.cc-busy]="busy() === t.key"
1943
- [disabled]="busy() !== null"
1944
- [attr.aria-label]="level >= 4 ? t.title : null"
1945
- [attr.aria-current]="t.inUse ? 'true' : null"
1946
- [attr.title]="level >= 3 ? t.title : null"
1947
- (click)="tap(t, $any($event.currentTarget))"
1948
- >
1949
- <span class="cc-icon"><cube-icon [icon]="iconOf(t)" [inUse]="!!t.inUse" /></span>
1950
- @if (level < 4) {
1951
- <span class="cc-t">{{ t.title }}</span>
1952
- }
1953
- @if (t.line && level < 3) {
1954
- <span class="cc-m">{{ t.line }}</span>
1955
- }
1956
- @if (t.inUse && inUseWord() && level < 3) {
1957
- <span class="cc-tick">{{ inUseWord() }}</span>
2757
+ <div class="cc-cell" [ccAttrs]="t.attrs">
2758
+ <button
2759
+ type="button"
2760
+ [class]="'cc-tile cc-l' + level"
2761
+ [class.cc-in-use]="!!t.inUse"
2762
+ [class.cc-pale]="!!t.pale"
2763
+ [class.cc-adds]="!!t.adds"
2764
+ [class.cc-busy]="busy() === t.key"
2765
+ [disabled]="busy() !== null"
2766
+ [attr.aria-label]="level >= 4 ? t.title : null"
2767
+ [attr.aria-current]="t.inUse ? 'true' : null"
2768
+ [attr.title]="level >= 3 ? t.title : null"
2769
+ (click)="tap(t, $any($event.currentTarget))"
2770
+ >
2771
+ <span class="cc-icon"><cube-icon [icon]="iconOf(t)" [inUse]="!!t.inUse" /></span>
2772
+ @if (level < 4) {
2773
+ <span class="cc-t">{{ t.title }}</span>
2774
+ }
2775
+ @if (t.line && level < 3) {
2776
+ <span class="cc-m">{{ t.line }}</span>
2777
+ }
2778
+ @if (t.inUse && inUseWord() && level < 3) {
2779
+ <span class="cc-tick">{{ inUseWord() }}</span>
2780
+ }
2781
+ </button>
2782
+ @if (t.zoom?.length) {
2783
+ <button
2784
+ type="button"
2785
+ class="cc-go"
2786
+ [disabled]="busy() !== null"
2787
+ [attr.aria-label]="t.zoomLabel || t.title"
2788
+ (click)="zoomInto(t, $any($event.currentTarget))"
2789
+ >
2790
+ <svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
2791
+ <path
2792
+ d="M6 3l5 5-5 5"
2793
+ fill="none"
2794
+ stroke="currentColor"
2795
+ stroke-width="2"
2796
+ stroke-linecap="round"
2797
+ stroke-linejoin="round"
2798
+ />
2799
+ </svg>
2800
+ </button>
1958
2801
  }
1959
- </button>
2802
+ </div>
1960
2803
  </ng-template>
1961
2804
  </cube-square>
1962
2805
  `,
1963
2806
  isInline: true,
1964
- styles: [":host{display:block;font:inherit;color:var(--cube-context-ink, #1f2a26);--cube-square-place: color-mix(in srgb, var(--cube-context-line, #dae0d9) 55%, transparent);--cube-square-place-dashed: var(--cube-context-line, #dae0d9);--cube-square-radius: var(--cube-context-radius, 20px)}.cc-tile{all:unset;cursor:pointer;box-sizing:border-box;min-width:0;min-height:0;height:100%;overflow:hidden;display:grid;justify-items:center;align-content:center;gap:6px;padding:14px 10px 12px;text-align:center;background:var(--cube-context-tile, #ffffff);border:1px solid var(--cube-context-line, #dae0d9);border-radius:var(--cube-context-radius, 20px);user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;transition:transform .16s}.cc-tile:active:not(:disabled){transform:scale(.97)}.cc-tile:focus-visible{outline:3px solid var(--cube-context-focus, #5f9a80);outline-offset:2px}.cc-tile.cc-in-use{border:2px solid var(--cube-context-in-use, #3b5a4c)}.cc-tile.cc-pale{background:transparent;border:2px dashed var(--cube-context-line, #dae0d9);color:var(--cube-context-quiet, #5d6a64)}.cc-tile.cc-adds{border:2px solid var(--cube-context-adds, #c8693f)}.cc-tile.cc-busy{opacity:.6;cursor:progress}.cc-tile:disabled:not(.cc-busy){cursor:default}.cc-icon{display:grid;place-items:center;line-height:0}.cc-tile.cc-adds .cc-icon{width:52px;height:52px;border-radius:50%;background:var(--cube-context-adds-bg, #f3e3d6);--cube-icon-stroke: var(--cube-context-adds-ink, #7a4a2b);--cube-icon-size: 26px}.cc-t,.cc-m{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}.cc-t{-webkit-line-clamp:var(--cube-context-title-lines, 2);line-clamp:var(--cube-context-title-lines, 2)}.cc-m{-webkit-line-clamp:var(--cube-context-line-lines, 2);line-clamp:var(--cube-context-line-lines, 2)}.cc-t{font-size:var(--cube-context-title-size, 17px);font-weight:700;line-height:1.2}.cc-m{font-size:var(--cube-context-line-size, 13px);line-height:1.3;color:var(--cube-context-quiet, #5d6a64)}.cc-tick{font-size:var(--cube-context-line-size, 13px);font-weight:800;color:var(--cube-context-in-use, #3b5a4c)}.cc-tile.cc-l0{border-radius:28px;padding:24px;gap:10px}.cc-l0 .cc-t{font-size:calc(var(--cube-context-title-size, 17px) * 26 / 17)}.cc-l0 .cc-m{font-size:calc(var(--cube-context-line-size, 13px) * 16 / 13)}.cc-l0 .cc-icon{--cube-icon-size: 64px}.cc-tile.cc-l0.cc-adds .cc-icon{width:96px;height:96px;--cube-icon-size: 40px}.cc-tile.cc-l2{border-radius:16px;padding:10px 6px;gap:5px}.cc-l2 .cc-t{font-size:calc(var(--cube-context-title-size, 17px) * 14 / 17)}.cc-l2 .cc-m{font-size:calc(var(--cube-context-line-size, 13px) * 12 / 13)}.cc-tile.cc-l3{border-radius:12px;padding:6px 4px;gap:3px}.cc-l3 .cc-t{font-size:calc(var(--cube-context-title-size, 17px) * 12 / 17)}.cc-tile.cc-l4{border-radius:9px;padding:2px;gap:0}.cc-l3 .cc-icon,.cc-l4 .cc-icon{--cube-icon-size: 24px}.cc-tile.cc-l3.cc-adds .cc-icon,.cc-tile.cc-l4.cc-adds .cc-icon{width:30px;height:30px;--cube-icon-size: 18px}\n"],
2807
+ styles: [":host{display:block;font:inherit;color:var(--cube-context-ink, #1f2a26);--cube-square-place: color-mix(in srgb, var(--cube-context-line, #dae0d9) 55%, transparent);--cube-square-place-dashed: var(--cube-context-line, #dae0d9);--cube-square-radius: var(--cube-context-radius, 20px)}.cc-cell{position:relative;height:100%;min-width:0;min-height:0;display:grid}.cc-go{all:unset;cursor:pointer;position:absolute;top:6px;right:6px;width:32px;height:32px;display:grid;place-items:center;border-radius:50%;color:var(--cube-context-ink, #1f2a26);background:var( --cube-context-go, color-mix(in srgb, var(--cube-context-line, #dae0d9) 60%, transparent) )}.cc-go:focus-visible{outline:3px solid var(--cube-context-focus, #5f9a80);outline-offset:2px}.cc-go:disabled{cursor:default}.cc-tile{all:unset;cursor:pointer;box-sizing:border-box;min-width:0;min-height:0;height:100%;overflow:hidden;display:grid;justify-items:center;align-content:center;gap:6px;padding:14px 10px 12px;text-align:center;background:var(--cube-context-tile, #ffffff);border:1px solid var(--cube-context-line, #dae0d9);border-radius:var(--cube-context-radius, 20px);user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;transition:transform .16s}.cc-tile:active:not(:disabled){transform:scale(.97)}.cc-tile:focus-visible{outline:3px solid var(--cube-context-focus, #5f9a80);outline-offset:2px}.cc-tile.cc-in-use{border:2px solid var(--cube-context-in-use, #3b5a4c)}.cc-tile.cc-pale{background:transparent;border:2px dashed var(--cube-context-line, #dae0d9);color:var(--cube-context-quiet, #5d6a64)}.cc-tile.cc-adds{border:2px solid var(--cube-context-adds, #c8693f)}.cc-tile.cc-busy{opacity:.6;cursor:progress}.cc-tile:disabled:not(.cc-busy){cursor:default}.cc-icon{display:grid;place-items:center;line-height:0}.cc-tile.cc-adds .cc-icon{width:52px;height:52px;border-radius:50%;background:var(--cube-context-adds-bg, #f3e3d6);--cube-icon-stroke: var(--cube-context-adds-ink, #7a4a2b);--cube-icon-size: 26px}.cc-t,.cc-m{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}.cc-t{-webkit-line-clamp:var(--cube-context-title-lines, 2);line-clamp:var(--cube-context-title-lines, 2)}.cc-m{-webkit-line-clamp:var(--cube-context-line-lines, 2);line-clamp:var(--cube-context-line-lines, 2)}.cc-t{font-size:var(--cube-context-title-size, 17px);font-weight:700;line-height:1.2}.cc-m{font-size:var(--cube-context-line-size, 13px);line-height:1.3;color:var(--cube-context-quiet, #5d6a64)}.cc-tick{font-size:var(--cube-context-line-size, 13px);font-weight:800;color:var(--cube-context-in-use, #3b5a4c)}.cc-tile.cc-l0{border-radius:28px;padding:24px;gap:10px}.cc-l0 .cc-t{font-size:calc(var(--cube-context-title-size, 17px) * 26 / 17)}.cc-l0 .cc-m{font-size:calc(var(--cube-context-line-size, 13px) * 16 / 13)}.cc-l0 .cc-icon{--cube-icon-size: 64px}.cc-tile.cc-l0.cc-adds .cc-icon{width:96px;height:96px;--cube-icon-size: 40px}.cc-tile.cc-l2{border-radius:16px;padding:10px 6px;gap:5px}.cc-l2 .cc-t{font-size:calc(var(--cube-context-title-size, 17px) * 14 / 17)}.cc-l2 .cc-m{font-size:calc(var(--cube-context-line-size, 13px) * 12 / 13)}.cc-tile.cc-l3{border-radius:12px;padding:6px 4px;gap:3px}.cc-l3 .cc-t{font-size:calc(var(--cube-context-title-size, 17px) * 12 / 17)}.cc-tile.cc-l4{border-radius:9px;padding:2px;gap:0}.cc-l3 .cc-icon,.cc-l4 .cc-icon{--cube-icon-size: 24px}.cc-tile.cc-l3.cc-adds .cc-icon,.cc-tile.cc-l4.cc-adds .cc-icon{width:30px;height:30px;--cube-icon-size: 18px}\n"],
1965
2808
  dependencies: [
1966
2809
  {
1967
2810
  kind: "component",
@@ -1992,6 +2835,12 @@ var CubeContext = class CubeContext {
1992
2835
  type: CubeSquareTile,
1993
2836
  selector: "ng-template[cubeSquareTile]",
1994
2837
  inputs: ["cubeSquareTile"]
2838
+ },
2839
+ {
2840
+ kind: "directive",
2841
+ type: ContextAttrs,
2842
+ selector: "[ccAttrs]",
2843
+ inputs: ["ccAttrs"]
1995
2844
  }
1996
2845
  ],
1997
2846
  changeDetection: i0.ChangeDetectionStrategy.OnPush
@@ -2009,7 +2858,8 @@ i0.ɵɵngDeclareClassMetadata({
2009
2858
  imports: [
2010
2859
  CubeIcon,
2011
2860
  CubeSquare,
2012
- CubeSquareTile
2861
+ CubeSquareTile,
2862
+ ContextAttrs
2013
2863
  ],
2014
2864
  template: `
2015
2865
  <cube-square
@@ -2020,35 +2870,57 @@ i0.ɵɵngDeclareClassMetadata({
2020
2870
  [class.cc-adds]="adds()"
2021
2871
  >
2022
2872
  <ng-template [cubeSquareTile]="tiles()" let-t let-level="level">
2023
- <button
2024
- type="button"
2025
- [class]="'cc-tile cc-l' + level"
2026
- [class.cc-in-use]="!!t.inUse"
2027
- [class.cc-pale]="!!t.pale"
2028
- [class.cc-adds]="!!t.adds"
2029
- [class.cc-busy]="busy() === t.key"
2030
- [disabled]="busy() !== null"
2031
- [attr.aria-label]="level >= 4 ? t.title : null"
2032
- [attr.aria-current]="t.inUse ? 'true' : null"
2033
- [attr.title]="level >= 3 ? t.title : null"
2034
- (click)="tap(t, $any($event.currentTarget))"
2035
- >
2036
- <span class="cc-icon"><cube-icon [icon]="iconOf(t)" [inUse]="!!t.inUse" /></span>
2037
- @if (level < 4) {
2038
- <span class="cc-t">{{ t.title }}</span>
2039
- }
2040
- @if (t.line && level < 3) {
2041
- <span class="cc-m">{{ t.line }}</span>
2042
- }
2043
- @if (t.inUse && inUseWord() && level < 3) {
2044
- <span class="cc-tick">{{ inUseWord() }}</span>
2873
+ <div class="cc-cell" [ccAttrs]="t.attrs">
2874
+ <button
2875
+ type="button"
2876
+ [class]="'cc-tile cc-l' + level"
2877
+ [class.cc-in-use]="!!t.inUse"
2878
+ [class.cc-pale]="!!t.pale"
2879
+ [class.cc-adds]="!!t.adds"
2880
+ [class.cc-busy]="busy() === t.key"
2881
+ [disabled]="busy() !== null"
2882
+ [attr.aria-label]="level >= 4 ? t.title : null"
2883
+ [attr.aria-current]="t.inUse ? 'true' : null"
2884
+ [attr.title]="level >= 3 ? t.title : null"
2885
+ (click)="tap(t, $any($event.currentTarget))"
2886
+ >
2887
+ <span class="cc-icon"><cube-icon [icon]="iconOf(t)" [inUse]="!!t.inUse" /></span>
2888
+ @if (level < 4) {
2889
+ <span class="cc-t">{{ t.title }}</span>
2890
+ }
2891
+ @if (t.line && level < 3) {
2892
+ <span class="cc-m">{{ t.line }}</span>
2893
+ }
2894
+ @if (t.inUse && inUseWord() && level < 3) {
2895
+ <span class="cc-tick">{{ inUseWord() }}</span>
2896
+ }
2897
+ </button>
2898
+ @if (t.zoom?.length) {
2899
+ <button
2900
+ type="button"
2901
+ class="cc-go"
2902
+ [disabled]="busy() !== null"
2903
+ [attr.aria-label]="t.zoomLabel || t.title"
2904
+ (click)="zoomInto(t, $any($event.currentTarget))"
2905
+ >
2906
+ <svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
2907
+ <path
2908
+ d="M6 3l5 5-5 5"
2909
+ fill="none"
2910
+ stroke="currentColor"
2911
+ stroke-width="2"
2912
+ stroke-linecap="round"
2913
+ stroke-linejoin="round"
2914
+ />
2915
+ </svg>
2916
+ </button>
2045
2917
  }
2046
- </button>
2918
+ </div>
2047
2919
  </ng-template>
2048
2920
  </cube-square>
2049
2921
  `,
2050
2922
  changeDetection: ChangeDetectionStrategy.OnPush,
2051
- styles: [":host{display:block;font:inherit;color:var(--cube-context-ink, #1f2a26);--cube-square-place: color-mix(in srgb, var(--cube-context-line, #dae0d9) 55%, transparent);--cube-square-place-dashed: var(--cube-context-line, #dae0d9);--cube-square-radius: var(--cube-context-radius, 20px)}.cc-tile{all:unset;cursor:pointer;box-sizing:border-box;min-width:0;min-height:0;height:100%;overflow:hidden;display:grid;justify-items:center;align-content:center;gap:6px;padding:14px 10px 12px;text-align:center;background:var(--cube-context-tile, #ffffff);border:1px solid var(--cube-context-line, #dae0d9);border-radius:var(--cube-context-radius, 20px);user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;transition:transform .16s}.cc-tile:active:not(:disabled){transform:scale(.97)}.cc-tile:focus-visible{outline:3px solid var(--cube-context-focus, #5f9a80);outline-offset:2px}.cc-tile.cc-in-use{border:2px solid var(--cube-context-in-use, #3b5a4c)}.cc-tile.cc-pale{background:transparent;border:2px dashed var(--cube-context-line, #dae0d9);color:var(--cube-context-quiet, #5d6a64)}.cc-tile.cc-adds{border:2px solid var(--cube-context-adds, #c8693f)}.cc-tile.cc-busy{opacity:.6;cursor:progress}.cc-tile:disabled:not(.cc-busy){cursor:default}.cc-icon{display:grid;place-items:center;line-height:0}.cc-tile.cc-adds .cc-icon{width:52px;height:52px;border-radius:50%;background:var(--cube-context-adds-bg, #f3e3d6);--cube-icon-stroke: var(--cube-context-adds-ink, #7a4a2b);--cube-icon-size: 26px}.cc-t,.cc-m{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}.cc-t{-webkit-line-clamp:var(--cube-context-title-lines, 2);line-clamp:var(--cube-context-title-lines, 2)}.cc-m{-webkit-line-clamp:var(--cube-context-line-lines, 2);line-clamp:var(--cube-context-line-lines, 2)}.cc-t{font-size:var(--cube-context-title-size, 17px);font-weight:700;line-height:1.2}.cc-m{font-size:var(--cube-context-line-size, 13px);line-height:1.3;color:var(--cube-context-quiet, #5d6a64)}.cc-tick{font-size:var(--cube-context-line-size, 13px);font-weight:800;color:var(--cube-context-in-use, #3b5a4c)}.cc-tile.cc-l0{border-radius:28px;padding:24px;gap:10px}.cc-l0 .cc-t{font-size:calc(var(--cube-context-title-size, 17px) * 26 / 17)}.cc-l0 .cc-m{font-size:calc(var(--cube-context-line-size, 13px) * 16 / 13)}.cc-l0 .cc-icon{--cube-icon-size: 64px}.cc-tile.cc-l0.cc-adds .cc-icon{width:96px;height:96px;--cube-icon-size: 40px}.cc-tile.cc-l2{border-radius:16px;padding:10px 6px;gap:5px}.cc-l2 .cc-t{font-size:calc(var(--cube-context-title-size, 17px) * 14 / 17)}.cc-l2 .cc-m{font-size:calc(var(--cube-context-line-size, 13px) * 12 / 13)}.cc-tile.cc-l3{border-radius:12px;padding:6px 4px;gap:3px}.cc-l3 .cc-t{font-size:calc(var(--cube-context-title-size, 17px) * 12 / 17)}.cc-tile.cc-l4{border-radius:9px;padding:2px;gap:0}.cc-l3 .cc-icon,.cc-l4 .cc-icon{--cube-icon-size: 24px}.cc-tile.cc-l3.cc-adds .cc-icon,.cc-tile.cc-l4.cc-adds .cc-icon{width:30px;height:30px;--cube-icon-size: 18px}\n"]
2923
+ styles: [":host{display:block;font:inherit;color:var(--cube-context-ink, #1f2a26);--cube-square-place: color-mix(in srgb, var(--cube-context-line, #dae0d9) 55%, transparent);--cube-square-place-dashed: var(--cube-context-line, #dae0d9);--cube-square-radius: var(--cube-context-radius, 20px)}.cc-cell{position:relative;height:100%;min-width:0;min-height:0;display:grid}.cc-go{all:unset;cursor:pointer;position:absolute;top:6px;right:6px;width:32px;height:32px;display:grid;place-items:center;border-radius:50%;color:var(--cube-context-ink, #1f2a26);background:var( --cube-context-go, color-mix(in srgb, var(--cube-context-line, #dae0d9) 60%, transparent) )}.cc-go:focus-visible{outline:3px solid var(--cube-context-focus, #5f9a80);outline-offset:2px}.cc-go:disabled{cursor:default}.cc-tile{all:unset;cursor:pointer;box-sizing:border-box;min-width:0;min-height:0;height:100%;overflow:hidden;display:grid;justify-items:center;align-content:center;gap:6px;padding:14px 10px 12px;text-align:center;background:var(--cube-context-tile, #ffffff);border:1px solid var(--cube-context-line, #dae0d9);border-radius:var(--cube-context-radius, 20px);user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;transition:transform .16s}.cc-tile:active:not(:disabled){transform:scale(.97)}.cc-tile:focus-visible{outline:3px solid var(--cube-context-focus, #5f9a80);outline-offset:2px}.cc-tile.cc-in-use{border:2px solid var(--cube-context-in-use, #3b5a4c)}.cc-tile.cc-pale{background:transparent;border:2px dashed var(--cube-context-line, #dae0d9);color:var(--cube-context-quiet, #5d6a64)}.cc-tile.cc-adds{border:2px solid var(--cube-context-adds, #c8693f)}.cc-tile.cc-busy{opacity:.6;cursor:progress}.cc-tile:disabled:not(.cc-busy){cursor:default}.cc-icon{display:grid;place-items:center;line-height:0}.cc-tile.cc-adds .cc-icon{width:52px;height:52px;border-radius:50%;background:var(--cube-context-adds-bg, #f3e3d6);--cube-icon-stroke: var(--cube-context-adds-ink, #7a4a2b);--cube-icon-size: 26px}.cc-t,.cc-m{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}.cc-t{-webkit-line-clamp:var(--cube-context-title-lines, 2);line-clamp:var(--cube-context-title-lines, 2)}.cc-m{-webkit-line-clamp:var(--cube-context-line-lines, 2);line-clamp:var(--cube-context-line-lines, 2)}.cc-t{font-size:var(--cube-context-title-size, 17px);font-weight:700;line-height:1.2}.cc-m{font-size:var(--cube-context-line-size, 13px);line-height:1.3;color:var(--cube-context-quiet, #5d6a64)}.cc-tick{font-size:var(--cube-context-line-size, 13px);font-weight:800;color:var(--cube-context-in-use, #3b5a4c)}.cc-tile.cc-l0{border-radius:28px;padding:24px;gap:10px}.cc-l0 .cc-t{font-size:calc(var(--cube-context-title-size, 17px) * 26 / 17)}.cc-l0 .cc-m{font-size:calc(var(--cube-context-line-size, 13px) * 16 / 13)}.cc-l0 .cc-icon{--cube-icon-size: 64px}.cc-tile.cc-l0.cc-adds .cc-icon{width:96px;height:96px;--cube-icon-size: 40px}.cc-tile.cc-l2{border-radius:16px;padding:10px 6px;gap:5px}.cc-l2 .cc-t{font-size:calc(var(--cube-context-title-size, 17px) * 14 / 17)}.cc-l2 .cc-m{font-size:calc(var(--cube-context-line-size, 13px) * 12 / 13)}.cc-tile.cc-l3{border-radius:12px;padding:6px 4px;gap:3px}.cc-l3 .cc-t{font-size:calc(var(--cube-context-title-size, 17px) * 12 / 17)}.cc-tile.cc-l4{border-radius:9px;padding:2px;gap:0}.cc-l3 .cc-icon,.cc-l4 .cc-icon{--cube-icon-size: 24px}.cc-tile.cc-l3.cc-adds .cc-icon,.cc-tile.cc-l4.cc-adds .cc-icon{width:30px;height:30px;--cube-icon-size: 18px}\n"]
2052
2924
  }]
2053
2925
  }],
2054
2926
  ctorParameters: () => [],
@@ -2093,6 +2965,14 @@ i0.ɵɵngDeclareClassMetadata({
2093
2965
  required: false
2094
2966
  }]
2095
2967
  }],
2968
+ heldKey: [{
2969
+ type: i0.Input,
2970
+ args: [{
2971
+ isSignal: true,
2972
+ alias: "heldKey",
2973
+ required: false
2974
+ }]
2975
+ }],
2096
2976
  enter: [{
2097
2977
  type: i0.Output,
2098
2978
  args: ["enter"]
@@ -2111,6 +2991,287 @@ i0.ɵɵngDeclareClassMetadata({
2111
2991
  }]
2112
2992
  }
2113
2993
  });
2114
- export { CONTEXT_CUBE_SOURCE, CONTEXT_CUBE_WORDS, CONTEXT_PART_ORDER, CUBE_HOLD_MS, CUBE_HOLD_SLOP, CUBE_ICON_NAMES, CubeContext, CubeHold, CubeIcon, CubePicture, CubeSquare, CubeSquareTile, PART_ICONS, SQUARE_LIST_ROW, SQUARE_MAX_SIDE, TURNING_BELOW, TURNING_NUDGE_UNTIL, TURNING_SIDES, VIEW_KEYS, contextIcon, contextLevelFor, contextSquare, cubeIconCells, directionWords, drawCube, gridFor, hideLevel, isView, namesLevel, orderParts, partsLevel, sizeFor, sortDirectionsLevel, sortItems, sortLevel, squareGap, squareLayout, squareLevelFor, turningFront, turningRows, viewLevel };
2994
+ const CUBE_LOADING_WAYS = ["fill", "turn"];
2995
+ const CUBE_LOADING_LEVELS = [
2996
+ "page",
2997
+ "cube",
2998
+ "piece"
2999
+ ];
3000
+ function loadingWayFor(level) {
3001
+ return level === "piece" ? "turn" : "fill";
3002
+ }
3003
+ const CUBE_LOADING_STEP_MS = {
3004
+ fill: 150,
3005
+ turn: 180
3006
+ };
3007
+ const CUBE_LOADING_WIDTH = {
3008
+ page: 96,
3009
+ cube: 64,
3010
+ piece: 20
3011
+ };
3012
+ const CUBE_LOADING_COLOURS = [
3013
+ "#5f9a80",
3014
+ "#c8693f",
3015
+ "#e0b44c",
3016
+ "#4f7cac",
3017
+ "#9b6bb3"
3018
+ ];
3019
+ const CUBE_LOADING_STICKERS = 12;
3020
+ function loadingStickers(way, step, palette = CUBE_LOADING_COLOURS, stickers = 12) {
3021
+ const n = Math.max(1, Math.floor(stickers));
3022
+ const s = Math.max(0, Math.floor(step));
3023
+ const colour = (i) => palette.length ? palette[i % palette.length] : null;
3024
+ if (way === "fill") {
3025
+ const k = s % (n + 1);
3026
+ return Array.from({ length: n }, (_, i) => i < k ? colour(i) : null);
3027
+ }
3028
+ const base = Array.from({ length: n }, (_, i) => i % 3 === 0 ? colour(i / 3) : null);
3029
+ return Array.from({ length: n }, (_, i) => base[((i - s) % n + n) % n]);
3030
+ }
3031
+ function stillStep(way, stickers = 12) {
3032
+ return way === "fill" ? Math.floor(stickers / 2) : 0;
3033
+ }
3034
+ const reducedMotion = () => typeof matchMedia === "function" ? matchMedia("(prefers-reduced-motion: reduce)") : null;
3035
+ var CubeLoading = class CubeLoading {
3036
+ level = input("page", ...ngDevMode ? [{ debugName: "level" }] : /* istanbul ignore next */ []);
3037
+ way = input(null, ...ngDevMode ? [{ debugName: "way" }] : /* istanbul ignore next */ []);
3038
+ count = input(9, ...ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []);
3039
+ failed = input(false, ...ngDevMode ? [{ debugName: "failed" }] : /* istanbul ignore next */ []);
3040
+ colours = input(CUBE_LOADING_COLOURS, ...ngDevMode ? [{ debugName: "colours" }] : /* istanbul ignore next */ []);
3041
+ width = input(null, ...ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []);
3042
+ wayInUse = computed(() => this.way() ?? loadingWayFor(this.level()), ...ngDevMode ? [{ debugName: "wayInUse" }] : /* istanbul ignore next */ []);
3043
+ widthInUse = computed(() => this.width() ?? CUBE_LOADING_WIDTH[this.level()], ...ngDevMode ? [{ debugName: "widthInUse" }] : /* istanbul ignore next */ []);
3044
+ places = computed(() => Array.from({ length: Math.max(0, Math.floor(this.count())) }, (_, i) => i), ...ngDevMode ? [{ debugName: "places" }] : /* istanbul ignore next */ []);
3045
+ step = signal(0, ...ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []);
3046
+ still = signal(reducedMotion()?.matches ?? false, ...ngDevMode ? [{ debugName: "still" }] : /* istanbul ignore next */ []);
3047
+ stickers = computed(() => {
3048
+ if (this.failed()) return [];
3049
+ const way = this.wayInUse();
3050
+ return loadingStickers(way, this.still() ? stillStep(way) : this.step(), this.colours());
3051
+ }, ...ngDevMode ? [{ debugName: "stickers" }] : /* istanbul ignore next */ []);
3052
+ constructor() {
3053
+ if (!isPlatformBrowser(inject(PLATFORM_ID))) return;
3054
+ const mq = reducedMotion();
3055
+ const change = (e) => this.still.set(e.matches);
3056
+ mq?.addEventListener?.("change", change);
3057
+ inject(DestroyRef).onDestroy(() => mq?.removeEventListener?.("change", change));
3058
+ effect((onCleanup) => {
3059
+ if (this.failed() || this.still()) return;
3060
+ const timer = setInterval(() => this.step.update((s) => s + 1), CUBE_LOADING_STEP_MS[this.wayInUse()]);
3061
+ onCleanup(() => clearInterval(timer));
3062
+ });
3063
+ }
3064
+ static ɵfac = i0.ɵɵngDeclareFactory({
3065
+ minVersion: "12.0.0",
3066
+ version: "22.2.4",
3067
+ ngImport: i0,
3068
+ type: CubeLoading,
3069
+ deps: [],
3070
+ target: i0.ɵɵFactoryTarget.Component
3071
+ });
3072
+ static ɵcmp = i0.ɵɵngDeclareComponent({
3073
+ minVersion: "17.0.0",
3074
+ version: "22.2.4",
3075
+ type: CubeLoading,
3076
+ isStandalone: true,
3077
+ selector: "cube-loading",
3078
+ inputs: {
3079
+ level: {
3080
+ classPropertyName: "level",
3081
+ publicName: "level",
3082
+ isSignal: true,
3083
+ isRequired: false,
3084
+ transformFunction: null
3085
+ },
3086
+ way: {
3087
+ classPropertyName: "way",
3088
+ publicName: "way",
3089
+ isSignal: true,
3090
+ isRequired: false,
3091
+ transformFunction: null
3092
+ },
3093
+ count: {
3094
+ classPropertyName: "count",
3095
+ publicName: "count",
3096
+ isSignal: true,
3097
+ isRequired: false,
3098
+ transformFunction: null
3099
+ },
3100
+ failed: {
3101
+ classPropertyName: "failed",
3102
+ publicName: "failed",
3103
+ isSignal: true,
3104
+ isRequired: false,
3105
+ transformFunction: null
3106
+ },
3107
+ colours: {
3108
+ classPropertyName: "colours",
3109
+ publicName: "colours",
3110
+ isSignal: true,
3111
+ isRequired: false,
3112
+ transformFunction: null
3113
+ },
3114
+ width: {
3115
+ classPropertyName: "width",
3116
+ publicName: "width",
3117
+ isSignal: true,
3118
+ isRequired: false,
3119
+ transformFunction: null
3120
+ }
3121
+ },
3122
+ host: { properties: {
3123
+ "class": "'cl-' + level()",
3124
+ "class.cl-failed": "failed()",
3125
+ "attr.aria-busy": "failed() ? \"false\" : \"true\"",
3126
+ "attr.data-way": "wayInUse()"
3127
+ } },
3128
+ ngImport: i0,
3129
+ template: `
3130
+ <span class="cl-cube">
3131
+ <cube-picture [count]="8" [colours]="stickers()" [width]="widthInUse()" />
3132
+ </span>
3133
+ <span class="cl-line" role="status" aria-live="polite"><ng-content /></span>
3134
+ @if (failed()) {
3135
+ <span class="cl-retry"><ng-content select="[cubeLoadingRetry]" /></span>
3136
+ } @else if (level() === 'page' && places().length) {
3137
+ <cube-square class="cl-square" [tiles]="places()">
3138
+ <ng-template [cubeSquareTile]="places()"><span class="cl-place"></span></ng-template>
3139
+ </cube-square>
3140
+ }
3141
+ `,
3142
+ isInline: true,
3143
+ styles: [":host{display:flex;flex-direction:column;align-items:center;gap:var(--cube-loading-gap, 12px);text-align:center;color:var(--cube-loading-line, inherit)}:host(.cl-page){width:100%}:host(.cl-piece){display:inline-flex;flex-direction:row;gap:.5em;vertical-align:middle}.cl-cube{display:inline-flex;line-height:0}.cl-line:empty,.cl-retry:empty{display:none}.cl-square{display:block;width:100%;margin-top:var(--cube-loading-gap, 12px)}.cl-place{display:block;width:100%;height:100%;box-sizing:border-box;border-radius:var(--cs-radius, var(--cube-square-radius, 20px));background:var(--cube-loading-place, var(--cube-unknown, #e3e7e1))}\n"],
3144
+ dependencies: [
3145
+ {
3146
+ kind: "component",
3147
+ type: CubePicture,
3148
+ selector: "cube-picture",
3149
+ inputs: [
3150
+ "count",
3151
+ "colours",
3152
+ "width",
3153
+ "hint",
3154
+ "whole",
3155
+ "rot"
3156
+ ]
3157
+ },
3158
+ {
3159
+ kind: "component",
3160
+ type: CubeSquare,
3161
+ selector: "cube-square",
3162
+ inputs: [
3163
+ "tiles",
3164
+ "view",
3165
+ "maxSide",
3166
+ "listRow",
3167
+ "dashed",
3168
+ "keyOf",
3169
+ "turning",
3170
+ "turnBelow",
3171
+ "across",
3172
+ "isOwn",
3173
+ "nudgeKey"
3174
+ ]
3175
+ },
3176
+ {
3177
+ kind: "directive",
3178
+ type: CubeSquareTile,
3179
+ selector: "ng-template[cubeSquareTile]",
3180
+ inputs: ["cubeSquareTile"]
3181
+ }
3182
+ ],
3183
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
3184
+ });
3185
+ };
3186
+ i0.ɵɵngDeclareClassMetadata({
3187
+ minVersion: "12.0.0",
3188
+ version: "22.2.4",
3189
+ ngImport: i0,
3190
+ type: CubeLoading,
3191
+ decorators: [{
3192
+ type: Component,
3193
+ args: [{
3194
+ selector: "cube-loading",
3195
+ imports: [
3196
+ CubePicture,
3197
+ CubeSquare,
3198
+ CubeSquareTile
3199
+ ],
3200
+ host: {
3201
+ "[class]": "'cl-' + level()",
3202
+ "[class.cl-failed]": "failed()",
3203
+ "[attr.aria-busy]": "failed() ? \"false\" : \"true\"",
3204
+ "[attr.data-way]": "wayInUse()"
3205
+ },
3206
+ template: `
3207
+ <span class="cl-cube">
3208
+ <cube-picture [count]="8" [colours]="stickers()" [width]="widthInUse()" />
3209
+ </span>
3210
+ <span class="cl-line" role="status" aria-live="polite"><ng-content /></span>
3211
+ @if (failed()) {
3212
+ <span class="cl-retry"><ng-content select="[cubeLoadingRetry]" /></span>
3213
+ } @else if (level() === 'page' && places().length) {
3214
+ <cube-square class="cl-square" [tiles]="places()">
3215
+ <ng-template [cubeSquareTile]="places()"><span class="cl-place"></span></ng-template>
3216
+ </cube-square>
3217
+ }
3218
+ `,
3219
+ changeDetection: ChangeDetectionStrategy.OnPush,
3220
+ styles: [":host{display:flex;flex-direction:column;align-items:center;gap:var(--cube-loading-gap, 12px);text-align:center;color:var(--cube-loading-line, inherit)}:host(.cl-page){width:100%}:host(.cl-piece){display:inline-flex;flex-direction:row;gap:.5em;vertical-align:middle}.cl-cube{display:inline-flex;line-height:0}.cl-line:empty,.cl-retry:empty{display:none}.cl-square{display:block;width:100%;margin-top:var(--cube-loading-gap, 12px)}.cl-place{display:block;width:100%;height:100%;box-sizing:border-box;border-radius:var(--cs-radius, var(--cube-square-radius, 20px));background:var(--cube-loading-place, var(--cube-unknown, #e3e7e1))}\n"]
3221
+ }]
3222
+ }],
3223
+ ctorParameters: () => [],
3224
+ propDecorators: {
3225
+ level: [{
3226
+ type: i0.Input,
3227
+ args: [{
3228
+ isSignal: true,
3229
+ alias: "level",
3230
+ required: false
3231
+ }]
3232
+ }],
3233
+ way: [{
3234
+ type: i0.Input,
3235
+ args: [{
3236
+ isSignal: true,
3237
+ alias: "way",
3238
+ required: false
3239
+ }]
3240
+ }],
3241
+ count: [{
3242
+ type: i0.Input,
3243
+ args: [{
3244
+ isSignal: true,
3245
+ alias: "count",
3246
+ required: false
3247
+ }]
3248
+ }],
3249
+ failed: [{
3250
+ type: i0.Input,
3251
+ args: [{
3252
+ isSignal: true,
3253
+ alias: "failed",
3254
+ required: false
3255
+ }]
3256
+ }],
3257
+ colours: [{
3258
+ type: i0.Input,
3259
+ args: [{
3260
+ isSignal: true,
3261
+ alias: "colours",
3262
+ required: false
3263
+ }]
3264
+ }],
3265
+ width: [{
3266
+ type: i0.Input,
3267
+ args: [{
3268
+ isSignal: true,
3269
+ alias: "width",
3270
+ required: false
3271
+ }]
3272
+ }]
3273
+ }
3274
+ });
3275
+ export { CONTEXT_CUBE_SOURCE, CONTEXT_CUBE_WORDS, CONTEXT_PART_ORDER, CUBE_CARRY_CLASSES, CUBE_CARRY_MOVE, CUBE_DROP_OUT, CUBE_HOLD_MS, CUBE_HOLD_SLOP, CUBE_ICON_NAMES, CUBE_LOADING_COLOURS, CUBE_LOADING_LEVELS, CUBE_LOADING_STEP_MS, CUBE_LOADING_STICKERS, CUBE_LOADING_WAYS, CUBE_LOADING_WIDTH, CUBE_PINCH_APART, CUBE_PINCH_TOGETHER, CUBE_WHEEL_QUIET_MS, CubeCarry, CubeContext, CubeHold, CubeIcon, CubeLoading, CubePicture, CubePinch, CubeSquare, CubeSquareTile, PART_ICONS, SQUARE_LIST_ROW, SQUARE_MAX_SIDE, TEXT_ORDERS, TURNING_BELOW, TURNING_NUDGE_UNTIL, TURNING_SIDES, VIEW_KEYS, contextIcon, contextLevelFor, contextSquare, cubeIconCells, directionWords, drawCube, gridFor, hideLevel, insideOf, isView, loadingStickers, loadingWayFor, namesLevel, orderParts, partsLevel, placesOf, refusalOf, sizeFor, sortDirectionsLevel, sortItems, sortLevel, squareGap, squareLayout, squareLevelFor, startsWheelGesture, stillStep, turningFront, turningRows, viewLevel, whereLevel, wouldLoop };
2115
3276
 
2116
3277
  //# sourceMappingURL=selimssevgi-cube-design-angular.mjs.map