@selimssevgi/cube-design-angular 0.2.1 → 0.3.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, 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
  });
@@ -1805,6 +2551,7 @@ var CubeContext = class CubeContext {
1805
2551
  source = input(null, ...ngDevMode ? [{ debugName: "source" }] : /* istanbul ignore next */ []);
1806
2552
  words = input(null, ...ngDevMode ? [{ debugName: "words" }] : /* istanbul ignore next */ []);
1807
2553
  maxSide = input(880, ...ngDevMode ? [{ debugName: "maxSide" }] : /* istanbul ignore next */ []);
2554
+ heldKey = input((held) => held, ...ngDevMode ? [{ debugName: "heldKey" }] : /* istanbul ignore next */ []);
1808
2555
  enter = output();
1809
2556
  out = output();
1810
2557
  done = output();
@@ -1838,6 +2585,14 @@ var CubeContext = class CubeContext {
1838
2585
  untracked(() => this.busy.set(null));
1839
2586
  });
1840
2587
  }
2588
+ zoomInto(tile, element) {
2589
+ if (this.busy() !== null || !tile.zoom?.length) return;
2590
+ if (element) this.tapped.emit({
2591
+ tile,
2592
+ element
2593
+ });
2594
+ this.enter.emit([...tile.zoom]);
2595
+ }
1841
2596
  async tap(tile, element) {
1842
2597
  if (this.busy() !== null) return;
1843
2598
  if (element) this.tapped.emit({
@@ -1847,7 +2602,8 @@ var CubeContext = class CubeContext {
1847
2602
  const held = this.held();
1848
2603
  const path = this.path();
1849
2604
  const where = this.where();
1850
- const here = () => this.held() === held && this.where() === where;
2605
+ const key = this.heldKey();
2606
+ const here = () => key(this.held()) === key(held) && this.where() === where;
1851
2607
  this.busy.set(tile.key);
1852
2608
  try {
1853
2609
  const picked = await this.from().pick(held, path, tile);
@@ -1915,6 +2671,13 @@ var CubeContext = class CubeContext {
1915
2671
  isSignal: true,
1916
2672
  isRequired: false,
1917
2673
  transformFunction: null
2674
+ },
2675
+ heldKey: {
2676
+ classPropertyName: "heldKey",
2677
+ publicName: "heldKey",
2678
+ isSignal: true,
2679
+ isRequired: false,
2680
+ transformFunction: null
1918
2681
  }
1919
2682
  },
1920
2683
  outputs: {
@@ -1933,35 +2696,57 @@ var CubeContext = class CubeContext {
1933
2696
  [class.cc-adds]="adds()"
1934
2697
  >
1935
2698
  <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>
2699
+ <div class="cc-cell">
2700
+ <button
2701
+ type="button"
2702
+ [class]="'cc-tile cc-l' + level"
2703
+ [class.cc-in-use]="!!t.inUse"
2704
+ [class.cc-pale]="!!t.pale"
2705
+ [class.cc-adds]="!!t.adds"
2706
+ [class.cc-busy]="busy() === t.key"
2707
+ [disabled]="busy() !== null"
2708
+ [attr.aria-label]="level >= 4 ? t.title : null"
2709
+ [attr.aria-current]="t.inUse ? 'true' : null"
2710
+ [attr.title]="level >= 3 ? t.title : null"
2711
+ (click)="tap(t, $any($event.currentTarget))"
2712
+ >
2713
+ <span class="cc-icon"><cube-icon [icon]="iconOf(t)" [inUse]="!!t.inUse" /></span>
2714
+ @if (level < 4) {
2715
+ <span class="cc-t">{{ t.title }}</span>
2716
+ }
2717
+ @if (t.line && level < 3) {
2718
+ <span class="cc-m">{{ t.line }}</span>
2719
+ }
2720
+ @if (t.inUse && inUseWord() && level < 3) {
2721
+ <span class="cc-tick">{{ inUseWord() }}</span>
2722
+ }
2723
+ </button>
2724
+ @if (t.zoom?.length) {
2725
+ <button
2726
+ type="button"
2727
+ class="cc-go"
2728
+ [disabled]="busy() !== null"
2729
+ [attr.aria-label]="t.zoomLabel || t.title"
2730
+ (click)="zoomInto(t, $any($event.currentTarget))"
2731
+ >
2732
+ <svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
2733
+ <path
2734
+ d="M6 3l5 5-5 5"
2735
+ fill="none"
2736
+ stroke="currentColor"
2737
+ stroke-width="2"
2738
+ stroke-linecap="round"
2739
+ stroke-linejoin="round"
2740
+ />
2741
+ </svg>
2742
+ </button>
1958
2743
  }
1959
- </button>
2744
+ </div>
1960
2745
  </ng-template>
1961
2746
  </cube-square>
1962
2747
  `,
1963
2748
  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"],
2749
+ 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
2750
  dependencies: [
1966
2751
  {
1967
2752
  kind: "component",
@@ -2020,35 +2805,57 @@ i0.ɵɵngDeclareClassMetadata({
2020
2805
  [class.cc-adds]="adds()"
2021
2806
  >
2022
2807
  <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>
2808
+ <div class="cc-cell">
2809
+ <button
2810
+ type="button"
2811
+ [class]="'cc-tile cc-l' + level"
2812
+ [class.cc-in-use]="!!t.inUse"
2813
+ [class.cc-pale]="!!t.pale"
2814
+ [class.cc-adds]="!!t.adds"
2815
+ [class.cc-busy]="busy() === t.key"
2816
+ [disabled]="busy() !== null"
2817
+ [attr.aria-label]="level >= 4 ? t.title : null"
2818
+ [attr.aria-current]="t.inUse ? 'true' : null"
2819
+ [attr.title]="level >= 3 ? t.title : null"
2820
+ (click)="tap(t, $any($event.currentTarget))"
2821
+ >
2822
+ <span class="cc-icon"><cube-icon [icon]="iconOf(t)" [inUse]="!!t.inUse" /></span>
2823
+ @if (level < 4) {
2824
+ <span class="cc-t">{{ t.title }}</span>
2825
+ }
2826
+ @if (t.line && level < 3) {
2827
+ <span class="cc-m">{{ t.line }}</span>
2828
+ }
2829
+ @if (t.inUse && inUseWord() && level < 3) {
2830
+ <span class="cc-tick">{{ inUseWord() }}</span>
2831
+ }
2832
+ </button>
2833
+ @if (t.zoom?.length) {
2834
+ <button
2835
+ type="button"
2836
+ class="cc-go"
2837
+ [disabled]="busy() !== null"
2838
+ [attr.aria-label]="t.zoomLabel || t.title"
2839
+ (click)="zoomInto(t, $any($event.currentTarget))"
2840
+ >
2841
+ <svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
2842
+ <path
2843
+ d="M6 3l5 5-5 5"
2844
+ fill="none"
2845
+ stroke="currentColor"
2846
+ stroke-width="2"
2847
+ stroke-linecap="round"
2848
+ stroke-linejoin="round"
2849
+ />
2850
+ </svg>
2851
+ </button>
2045
2852
  }
2046
- </button>
2853
+ </div>
2047
2854
  </ng-template>
2048
2855
  </cube-square>
2049
2856
  `,
2050
2857
  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"]
2858
+ 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
2859
  }]
2053
2860
  }],
2054
2861
  ctorParameters: () => [],
@@ -2093,6 +2900,14 @@ i0.ɵɵngDeclareClassMetadata({
2093
2900
  required: false
2094
2901
  }]
2095
2902
  }],
2903
+ heldKey: [{
2904
+ type: i0.Input,
2905
+ args: [{
2906
+ isSignal: true,
2907
+ alias: "heldKey",
2908
+ required: false
2909
+ }]
2910
+ }],
2096
2911
  enter: [{
2097
2912
  type: i0.Output,
2098
2913
  args: ["enter"]
@@ -2111,6 +2926,287 @@ i0.ɵɵngDeclareClassMetadata({
2111
2926
  }]
2112
2927
  }
2113
2928
  });
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 };
2929
+ const CUBE_LOADING_WAYS = ["fill", "turn"];
2930
+ const CUBE_LOADING_LEVELS = [
2931
+ "page",
2932
+ "cube",
2933
+ "piece"
2934
+ ];
2935
+ function loadingWayFor(level) {
2936
+ return level === "piece" ? "turn" : "fill";
2937
+ }
2938
+ const CUBE_LOADING_STEP_MS = {
2939
+ fill: 150,
2940
+ turn: 180
2941
+ };
2942
+ const CUBE_LOADING_WIDTH = {
2943
+ page: 96,
2944
+ cube: 64,
2945
+ piece: 20
2946
+ };
2947
+ const CUBE_LOADING_COLOURS = [
2948
+ "#5f9a80",
2949
+ "#c8693f",
2950
+ "#e0b44c",
2951
+ "#4f7cac",
2952
+ "#9b6bb3"
2953
+ ];
2954
+ const CUBE_LOADING_STICKERS = 12;
2955
+ function loadingStickers(way, step, palette = CUBE_LOADING_COLOURS, stickers = 12) {
2956
+ const n = Math.max(1, Math.floor(stickers));
2957
+ const s = Math.max(0, Math.floor(step));
2958
+ const colour = (i) => palette.length ? palette[i % palette.length] : null;
2959
+ if (way === "fill") {
2960
+ const k = s % (n + 1);
2961
+ return Array.from({ length: n }, (_, i) => i < k ? colour(i) : null);
2962
+ }
2963
+ const base = Array.from({ length: n }, (_, i) => i % 3 === 0 ? colour(i / 3) : null);
2964
+ return Array.from({ length: n }, (_, i) => base[((i - s) % n + n) % n]);
2965
+ }
2966
+ function stillStep(way, stickers = 12) {
2967
+ return way === "fill" ? Math.floor(stickers / 2) : 0;
2968
+ }
2969
+ const reducedMotion = () => typeof matchMedia === "function" ? matchMedia("(prefers-reduced-motion: reduce)") : null;
2970
+ var CubeLoading = class CubeLoading {
2971
+ level = input("page", ...ngDevMode ? [{ debugName: "level" }] : /* istanbul ignore next */ []);
2972
+ way = input(null, ...ngDevMode ? [{ debugName: "way" }] : /* istanbul ignore next */ []);
2973
+ count = input(9, ...ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []);
2974
+ failed = input(false, ...ngDevMode ? [{ debugName: "failed" }] : /* istanbul ignore next */ []);
2975
+ colours = input(CUBE_LOADING_COLOURS, ...ngDevMode ? [{ debugName: "colours" }] : /* istanbul ignore next */ []);
2976
+ width = input(null, ...ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []);
2977
+ wayInUse = computed(() => this.way() ?? loadingWayFor(this.level()), ...ngDevMode ? [{ debugName: "wayInUse" }] : /* istanbul ignore next */ []);
2978
+ widthInUse = computed(() => this.width() ?? CUBE_LOADING_WIDTH[this.level()], ...ngDevMode ? [{ debugName: "widthInUse" }] : /* istanbul ignore next */ []);
2979
+ places = computed(() => Array.from({ length: Math.max(0, Math.floor(this.count())) }, (_, i) => i), ...ngDevMode ? [{ debugName: "places" }] : /* istanbul ignore next */ []);
2980
+ step = signal(0, ...ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []);
2981
+ still = signal(reducedMotion()?.matches ?? false, ...ngDevMode ? [{ debugName: "still" }] : /* istanbul ignore next */ []);
2982
+ stickers = computed(() => {
2983
+ if (this.failed()) return [];
2984
+ const way = this.wayInUse();
2985
+ return loadingStickers(way, this.still() ? stillStep(way) : this.step(), this.colours());
2986
+ }, ...ngDevMode ? [{ debugName: "stickers" }] : /* istanbul ignore next */ []);
2987
+ constructor() {
2988
+ if (!isPlatformBrowser(inject(PLATFORM_ID))) return;
2989
+ const mq = reducedMotion();
2990
+ const change = (e) => this.still.set(e.matches);
2991
+ mq?.addEventListener?.("change", change);
2992
+ inject(DestroyRef).onDestroy(() => mq?.removeEventListener?.("change", change));
2993
+ effect((onCleanup) => {
2994
+ if (this.failed() || this.still()) return;
2995
+ const timer = setInterval(() => this.step.update((s) => s + 1), CUBE_LOADING_STEP_MS[this.wayInUse()]);
2996
+ onCleanup(() => clearInterval(timer));
2997
+ });
2998
+ }
2999
+ static ɵfac = i0.ɵɵngDeclareFactory({
3000
+ minVersion: "12.0.0",
3001
+ version: "22.2.4",
3002
+ ngImport: i0,
3003
+ type: CubeLoading,
3004
+ deps: [],
3005
+ target: i0.ɵɵFactoryTarget.Component
3006
+ });
3007
+ static ɵcmp = i0.ɵɵngDeclareComponent({
3008
+ minVersion: "17.0.0",
3009
+ version: "22.2.4",
3010
+ type: CubeLoading,
3011
+ isStandalone: true,
3012
+ selector: "cube-loading",
3013
+ inputs: {
3014
+ level: {
3015
+ classPropertyName: "level",
3016
+ publicName: "level",
3017
+ isSignal: true,
3018
+ isRequired: false,
3019
+ transformFunction: null
3020
+ },
3021
+ way: {
3022
+ classPropertyName: "way",
3023
+ publicName: "way",
3024
+ isSignal: true,
3025
+ isRequired: false,
3026
+ transformFunction: null
3027
+ },
3028
+ count: {
3029
+ classPropertyName: "count",
3030
+ publicName: "count",
3031
+ isSignal: true,
3032
+ isRequired: false,
3033
+ transformFunction: null
3034
+ },
3035
+ failed: {
3036
+ classPropertyName: "failed",
3037
+ publicName: "failed",
3038
+ isSignal: true,
3039
+ isRequired: false,
3040
+ transformFunction: null
3041
+ },
3042
+ colours: {
3043
+ classPropertyName: "colours",
3044
+ publicName: "colours",
3045
+ isSignal: true,
3046
+ isRequired: false,
3047
+ transformFunction: null
3048
+ },
3049
+ width: {
3050
+ classPropertyName: "width",
3051
+ publicName: "width",
3052
+ isSignal: true,
3053
+ isRequired: false,
3054
+ transformFunction: null
3055
+ }
3056
+ },
3057
+ host: { properties: {
3058
+ "class": "'cl-' + level()",
3059
+ "class.cl-failed": "failed()",
3060
+ "attr.aria-busy": "failed() ? \"false\" : \"true\"",
3061
+ "attr.data-way": "wayInUse()"
3062
+ } },
3063
+ ngImport: i0,
3064
+ template: `
3065
+ <span class="cl-cube">
3066
+ <cube-picture [count]="8" [colours]="stickers()" [width]="widthInUse()" />
3067
+ </span>
3068
+ <span class="cl-line" role="status" aria-live="polite"><ng-content /></span>
3069
+ @if (failed()) {
3070
+ <span class="cl-retry"><ng-content select="[cubeLoadingRetry]" /></span>
3071
+ } @else if (level() === 'page' && places().length) {
3072
+ <cube-square class="cl-square" [tiles]="places()">
3073
+ <ng-template [cubeSquareTile]="places()"><span class="cl-place"></span></ng-template>
3074
+ </cube-square>
3075
+ }
3076
+ `,
3077
+ isInline: true,
3078
+ 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"],
3079
+ dependencies: [
3080
+ {
3081
+ kind: "component",
3082
+ type: CubePicture,
3083
+ selector: "cube-picture",
3084
+ inputs: [
3085
+ "count",
3086
+ "colours",
3087
+ "width",
3088
+ "hint",
3089
+ "whole",
3090
+ "rot"
3091
+ ]
3092
+ },
3093
+ {
3094
+ kind: "component",
3095
+ type: CubeSquare,
3096
+ selector: "cube-square",
3097
+ inputs: [
3098
+ "tiles",
3099
+ "view",
3100
+ "maxSide",
3101
+ "listRow",
3102
+ "dashed",
3103
+ "keyOf",
3104
+ "turning",
3105
+ "turnBelow",
3106
+ "across",
3107
+ "isOwn",
3108
+ "nudgeKey"
3109
+ ]
3110
+ },
3111
+ {
3112
+ kind: "directive",
3113
+ type: CubeSquareTile,
3114
+ selector: "ng-template[cubeSquareTile]",
3115
+ inputs: ["cubeSquareTile"]
3116
+ }
3117
+ ],
3118
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
3119
+ });
3120
+ };
3121
+ i0.ɵɵngDeclareClassMetadata({
3122
+ minVersion: "12.0.0",
3123
+ version: "22.2.4",
3124
+ ngImport: i0,
3125
+ type: CubeLoading,
3126
+ decorators: [{
3127
+ type: Component,
3128
+ args: [{
3129
+ selector: "cube-loading",
3130
+ imports: [
3131
+ CubePicture,
3132
+ CubeSquare,
3133
+ CubeSquareTile
3134
+ ],
3135
+ host: {
3136
+ "[class]": "'cl-' + level()",
3137
+ "[class.cl-failed]": "failed()",
3138
+ "[attr.aria-busy]": "failed() ? \"false\" : \"true\"",
3139
+ "[attr.data-way]": "wayInUse()"
3140
+ },
3141
+ template: `
3142
+ <span class="cl-cube">
3143
+ <cube-picture [count]="8" [colours]="stickers()" [width]="widthInUse()" />
3144
+ </span>
3145
+ <span class="cl-line" role="status" aria-live="polite"><ng-content /></span>
3146
+ @if (failed()) {
3147
+ <span class="cl-retry"><ng-content select="[cubeLoadingRetry]" /></span>
3148
+ } @else if (level() === 'page' && places().length) {
3149
+ <cube-square class="cl-square" [tiles]="places()">
3150
+ <ng-template [cubeSquareTile]="places()"><span class="cl-place"></span></ng-template>
3151
+ </cube-square>
3152
+ }
3153
+ `,
3154
+ changeDetection: ChangeDetectionStrategy.OnPush,
3155
+ 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"]
3156
+ }]
3157
+ }],
3158
+ ctorParameters: () => [],
3159
+ propDecorators: {
3160
+ level: [{
3161
+ type: i0.Input,
3162
+ args: [{
3163
+ isSignal: true,
3164
+ alias: "level",
3165
+ required: false
3166
+ }]
3167
+ }],
3168
+ way: [{
3169
+ type: i0.Input,
3170
+ args: [{
3171
+ isSignal: true,
3172
+ alias: "way",
3173
+ required: false
3174
+ }]
3175
+ }],
3176
+ count: [{
3177
+ type: i0.Input,
3178
+ args: [{
3179
+ isSignal: true,
3180
+ alias: "count",
3181
+ required: false
3182
+ }]
3183
+ }],
3184
+ failed: [{
3185
+ type: i0.Input,
3186
+ args: [{
3187
+ isSignal: true,
3188
+ alias: "failed",
3189
+ required: false
3190
+ }]
3191
+ }],
3192
+ colours: [{
3193
+ type: i0.Input,
3194
+ args: [{
3195
+ isSignal: true,
3196
+ alias: "colours",
3197
+ required: false
3198
+ }]
3199
+ }],
3200
+ width: [{
3201
+ type: i0.Input,
3202
+ args: [{
3203
+ isSignal: true,
3204
+ alias: "width",
3205
+ required: false
3206
+ }]
3207
+ }]
3208
+ }
3209
+ });
3210
+ 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
3211
 
2116
3212
  //# sourceMappingURL=selimssevgi-cube-design-angular.mjs.map