@selimssevgi/cube-design-angular 0.0.0-stage → 0.2.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.
@@ -0,0 +1,2116 @@
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";
4
+ function sizeFor(count) {
5
+ let s = 1;
6
+ while (s * s * s < count && s < 7) s++;
7
+ return s;
8
+ }
9
+ const C30 = Math.cos(Math.PI / 6);
10
+ function poly(pts, k) {
11
+ const cx = pts.reduce((a, q) => a + q[0], 0) / pts.length;
12
+ const cy = pts.reduce((a, q) => a + q[1], 0) / pts.length;
13
+ return pts.map(([x, y]) => `${(cx + (x - cx) * k).toFixed(1)},${(cy + (y - cy) * k).toFixed(1)}`).join(" ");
14
+ }
15
+ function squares(n, s, shift) {
16
+ const ox = n * s * C30;
17
+ const oy = n * s;
18
+ const p = (x, y, z) => [shift[0] + ox + (x - y) * C30 * s, shift[1] + oy + (x + y) * .5 * s - z * s];
19
+ const out = [];
20
+ for (let a = 0; a < n; a++) for (let b = n - 1; b >= 0; b--) out.push({
21
+ face: "left",
22
+ pts: [
23
+ p(a, n, b + 1),
24
+ p(a + 1, n, b + 1),
25
+ p(a + 1, n, b),
26
+ p(a, n, b)
27
+ ]
28
+ });
29
+ for (let a = 0; a < n; a++) for (let b = n - 1; b >= 0; b--) out.push({
30
+ face: "right",
31
+ pts: [
32
+ p(n, a, b + 1),
33
+ p(n, a + 1, b + 1),
34
+ p(n, a + 1, b),
35
+ p(n, a, b)
36
+ ]
37
+ });
38
+ for (let a = 0; a < n; a++) for (let b = 0; b < n; b++) out.push({
39
+ face: "top",
40
+ pts: [
41
+ p(a, b, n),
42
+ p(a + 1, b, n),
43
+ p(a + 1, b + 1, n),
44
+ p(a, b + 1, n)
45
+ ]
46
+ });
47
+ return out;
48
+ }
49
+ function drawCube(count, colours, width, options = {}) {
50
+ const n = sizeFor(Math.max(1, count));
51
+ const hinted = !!options.hint && count < 9;
52
+ const big = hinted ? n + 1 : n;
53
+ const s = width / (2 * big * C30);
54
+ const hint = hinted ? squares(big, s, [0, 0]).map((q) => poly(q.pts, .86)) : [];
55
+ const shift = hinted ? [(big - n) * s * C30, (big - n) * s * 2] : [0, 0];
56
+ const k = colours.length ? (options.rot ?? 0) % colours.length : 0;
57
+ const turned = colours.slice(k).concat(colours.slice(0, k));
58
+ const stickers = squares(n, s, shift).map((q, i) => ({
59
+ face: q.face,
60
+ outer: poly(q.pts, 1),
61
+ inner: poly(q.pts, .86),
62
+ colour: options.whole ? colours[0] ?? null : turned[i] ?? null
63
+ }));
64
+ const height = 2 * big * s;
65
+ return {
66
+ width,
67
+ height: Math.round(height),
68
+ viewBox: `-2 -2 ${(width + 4).toFixed(1)} ${(height + 4).toFixed(1)}`,
69
+ hint,
70
+ stickers
71
+ };
72
+ }
73
+ var CubePicture = class CubePicture {
74
+ count = input(1, ...ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []);
75
+ colours = input([], ...ngDevMode ? [{ debugName: "colours" }] : /* istanbul ignore next */ []);
76
+ width = input(64, ...ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []);
77
+ hint = input(false, ...ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []);
78
+ whole = input(false, ...ngDevMode ? [{ debugName: "whole" }] : /* istanbul ignore next */ []);
79
+ rot = input(0, ...ngDevMode ? [{ debugName: "rot" }] : /* istanbul ignore next */ []);
80
+ drawing = computed(() => drawCube(this.count(), this.colours(), this.width(), {
81
+ hint: this.hint(),
82
+ whole: this.whole(),
83
+ rot: this.rot()
84
+ }), ...ngDevMode ? [{ debugName: "drawing" }] : /* istanbul ignore next */ []);
85
+ static ɵfac = i0.ɵɵngDeclareFactory({
86
+ minVersion: "12.0.0",
87
+ version: "22.2.4",
88
+ ngImport: i0,
89
+ type: CubePicture,
90
+ deps: [],
91
+ target: i0.ɵɵFactoryTarget.Component
92
+ });
93
+ static ɵcmp = i0.ɵɵngDeclareComponent({
94
+ minVersion: "17.0.0",
95
+ version: "22.2.4",
96
+ type: CubePicture,
97
+ isStandalone: true,
98
+ selector: "cube-picture",
99
+ inputs: {
100
+ count: {
101
+ classPropertyName: "count",
102
+ publicName: "count",
103
+ isSignal: true,
104
+ isRequired: false,
105
+ transformFunction: null
106
+ },
107
+ colours: {
108
+ classPropertyName: "colours",
109
+ publicName: "colours",
110
+ isSignal: true,
111
+ isRequired: false,
112
+ transformFunction: null
113
+ },
114
+ width: {
115
+ classPropertyName: "width",
116
+ publicName: "width",
117
+ isSignal: true,
118
+ isRequired: false,
119
+ transformFunction: null
120
+ },
121
+ hint: {
122
+ classPropertyName: "hint",
123
+ publicName: "hint",
124
+ isSignal: true,
125
+ isRequired: false,
126
+ transformFunction: null
127
+ },
128
+ whole: {
129
+ classPropertyName: "whole",
130
+ publicName: "whole",
131
+ isSignal: true,
132
+ isRequired: false,
133
+ transformFunction: null
134
+ },
135
+ rot: {
136
+ classPropertyName: "rot",
137
+ publicName: "rot",
138
+ isSignal: true,
139
+ isRequired: false,
140
+ transformFunction: null
141
+ }
142
+ },
143
+ ngImport: i0,
144
+ template: `
145
+ @let d = drawing();
146
+ <svg
147
+ [attr.viewBox]="d.viewBox"
148
+ [attr.width]="d.width"
149
+ [attr.height]="d.height"
150
+ aria-hidden="true"
151
+ >
152
+ @for (q of d.hint; track $index) {
153
+ <polygon class="hint" [attr.points]="q" />
154
+ }
155
+ @for (q of d.stickers; track $index) {
156
+ <polygon [attr.points]="q.outer" [attr.class]="'side ' + q.face" />
157
+ }
158
+ @for (q of d.stickers; track $index) {
159
+ <polygon
160
+ [attr.points]="q.inner"
161
+ [attr.class]="q.colour ? 'sticker' : 'sticker unknown'"
162
+ [attr.fill]="q.colour"
163
+ />
164
+ }
165
+ </svg>
166
+ `,
167
+ isInline: true,
168
+ styles: [":host{display:inline-block;line-height:0}svg{overflow:visible}.hint{fill:none;stroke:var(--cube-hint, #87938c);stroke-width:1;stroke-dasharray:3 3;opacity:var(--cube-hint-opacity, .5)}.side{stroke:var(--cube-edge, #cdd8d0);stroke-width:var(--cube-edge-width, .6)}.top{fill:var(--cube-top, #f9fbf8)}.left{fill:var(--cube-left, #e9eee9)}.right{fill:var(--cube-right, #dfe6e0)}.sticker{stroke:var(--cube-sticker-edge, rgba(31, 45, 39, .28));stroke-width:1}.unknown{fill:var(--cube-unknown, #e3e7e1);stroke:var(--cube-unknown-edge, none)}\n"],
169
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
170
+ });
171
+ };
172
+ i0.ɵɵngDeclareClassMetadata({
173
+ minVersion: "12.0.0",
174
+ version: "22.2.4",
175
+ ngImport: i0,
176
+ type: CubePicture,
177
+ decorators: [{
178
+ type: Component,
179
+ args: [{
180
+ selector: "cube-picture",
181
+ template: `
182
+ @let d = drawing();
183
+ <svg
184
+ [attr.viewBox]="d.viewBox"
185
+ [attr.width]="d.width"
186
+ [attr.height]="d.height"
187
+ aria-hidden="true"
188
+ >
189
+ @for (q of d.hint; track $index) {
190
+ <polygon class="hint" [attr.points]="q" />
191
+ }
192
+ @for (q of d.stickers; track $index) {
193
+ <polygon [attr.points]="q.outer" [attr.class]="'side ' + q.face" />
194
+ }
195
+ @for (q of d.stickers; track $index) {
196
+ <polygon
197
+ [attr.points]="q.inner"
198
+ [attr.class]="q.colour ? 'sticker' : 'sticker unknown'"
199
+ [attr.fill]="q.colour"
200
+ />
201
+ }
202
+ </svg>
203
+ `,
204
+ changeDetection: ChangeDetectionStrategy.OnPush,
205
+ styles: [":host{display:inline-block;line-height:0}svg{overflow:visible}.hint{fill:none;stroke:var(--cube-hint, #87938c);stroke-width:1;stroke-dasharray:3 3;opacity:var(--cube-hint-opacity, .5)}.side{stroke:var(--cube-edge, #cdd8d0);stroke-width:var(--cube-edge-width, .6)}.top{fill:var(--cube-top, #f9fbf8)}.left{fill:var(--cube-left, #e9eee9)}.right{fill:var(--cube-right, #dfe6e0)}.sticker{stroke:var(--cube-sticker-edge, rgba(31, 45, 39, .28));stroke-width:1}.unknown{fill:var(--cube-unknown, #e3e7e1);stroke:var(--cube-unknown-edge, none)}\n"]
206
+ }]
207
+ }],
208
+ propDecorators: {
209
+ count: [{
210
+ type: i0.Input,
211
+ args: [{
212
+ isSignal: true,
213
+ alias: "count",
214
+ required: false
215
+ }]
216
+ }],
217
+ colours: [{
218
+ type: i0.Input,
219
+ args: [{
220
+ isSignal: true,
221
+ alias: "colours",
222
+ required: false
223
+ }]
224
+ }],
225
+ width: [{
226
+ type: i0.Input,
227
+ args: [{
228
+ isSignal: true,
229
+ alias: "width",
230
+ required: false
231
+ }]
232
+ }],
233
+ hint: [{
234
+ type: i0.Input,
235
+ args: [{
236
+ isSignal: true,
237
+ alias: "hint",
238
+ required: false
239
+ }]
240
+ }],
241
+ whole: [{
242
+ type: i0.Input,
243
+ args: [{
244
+ isSignal: true,
245
+ alias: "whole",
246
+ required: false
247
+ }]
248
+ }],
249
+ rot: [{
250
+ type: i0.Input,
251
+ args: [{
252
+ isSignal: true,
253
+ alias: "rot",
254
+ required: false
255
+ }]
256
+ }]
257
+ }
258
+ });
259
+ const CUBE_HOLD_MS = 520;
260
+ const CUBE_HOLD_SLOP = 10;
261
+ var CubeHold = class CubeHold {
262
+ cubeHoldDisabled = input(false, ...ngDevMode ? [{ debugName: "cubeHoldDisabled" }] : /* istanbul ignore next */ []);
263
+ cubeHoldMs = input(520, ...ngDevMode ? [{ debugName: "cubeHoldMs" }] : /* istanbul ignore next */ []);
264
+ cubeHoldSlop = input(10, ...ngDevMode ? [{ debugName: "cubeHoldSlop" }] : /* istanbul ignore next */ []);
265
+ cubeHoldBuzz = input(true, ...ngDevMode ? [{ debugName: "cubeHoldBuzz" }] : /* istanbul ignore next */ []);
266
+ cubeHeld = output();
267
+ element = inject(ElementRef).nativeElement;
268
+ timer;
269
+ start = null;
270
+ pointers = /* @__PURE__ */ new Set();
271
+ pressFired = false;
272
+ swallow = false;
273
+ constructor() {
274
+ const swallow = (e) => {
275
+ if (!this.swallow) return;
276
+ this.swallow = false;
277
+ e.preventDefault();
278
+ e.stopImmediatePropagation();
279
+ };
280
+ this.element.addEventListener("click", swallow, true);
281
+ inject(DestroyRef).onDestroy(() => {
282
+ clearTimeout(this.timer);
283
+ this.element.removeEventListener("click", swallow, true);
284
+ });
285
+ }
286
+ press(e) {
287
+ this.pointers.add(e.pointerId);
288
+ this.cancel();
289
+ this.pressFired = false;
290
+ this.swallow = false;
291
+ if (this.cubeHoldDisabled() || this.pointers.size > 1 || e.button > 0) return;
292
+ this.start = {
293
+ x: e.clientX,
294
+ y: e.clientY
295
+ };
296
+ this.timer = setTimeout(() => this.fire("press", e), this.cubeHoldMs());
297
+ }
298
+ moved(e) {
299
+ if (!this.start) return;
300
+ if (Math.hypot(e.clientX - this.start.x, e.clientY - this.start.y) > this.cubeHoldSlop()) this.cancel();
301
+ }
302
+ lift(e) {
303
+ this.pointers.delete(e.pointerId);
304
+ this.cancel();
305
+ }
306
+ menu(e) {
307
+ if (this.cubeHoldDisabled()) return;
308
+ e.preventDefault();
309
+ if (this.pressFired) return;
310
+ this.fire("menu", e);
311
+ }
312
+ fire(via, event) {
313
+ this.cancel();
314
+ if (this.cubeHoldDisabled()) return;
315
+ this.pressFired = via === "press";
316
+ this.swallow = true;
317
+ if (this.cubeHoldBuzz()) globalThis.navigator?.vibrate?.(12);
318
+ this.cubeHeld.emit({
319
+ via,
320
+ element: this.element,
321
+ event
322
+ });
323
+ }
324
+ cancel() {
325
+ clearTimeout(this.timer);
326
+ this.timer = void 0;
327
+ this.start = null;
328
+ }
329
+ static ɵfac = i0.ɵɵngDeclareFactory({
330
+ minVersion: "12.0.0",
331
+ version: "22.2.4",
332
+ ngImport: i0,
333
+ type: CubeHold,
334
+ deps: [],
335
+ target: i0.ɵɵFactoryTarget.Directive
336
+ });
337
+ static ɵdir = i0.ɵɵngDeclareDirective({
338
+ minVersion: "17.1.0",
339
+ version: "22.2.4",
340
+ type: CubeHold,
341
+ isStandalone: true,
342
+ selector: "[cubeHold]",
343
+ inputs: {
344
+ cubeHoldDisabled: {
345
+ classPropertyName: "cubeHoldDisabled",
346
+ publicName: "cubeHoldDisabled",
347
+ isSignal: true,
348
+ isRequired: false,
349
+ transformFunction: null
350
+ },
351
+ cubeHoldMs: {
352
+ classPropertyName: "cubeHoldMs",
353
+ publicName: "cubeHoldMs",
354
+ isSignal: true,
355
+ isRequired: false,
356
+ transformFunction: null
357
+ },
358
+ cubeHoldSlop: {
359
+ classPropertyName: "cubeHoldSlop",
360
+ publicName: "cubeHoldSlop",
361
+ isSignal: true,
362
+ isRequired: false,
363
+ transformFunction: null
364
+ },
365
+ cubeHoldBuzz: {
366
+ classPropertyName: "cubeHoldBuzz",
367
+ publicName: "cubeHoldBuzz",
368
+ isSignal: true,
369
+ isRequired: false,
370
+ transformFunction: null
371
+ }
372
+ },
373
+ outputs: { cubeHeld: "cubeHeld" },
374
+ host: {
375
+ listeners: {
376
+ "pointerdown": "press($event)",
377
+ "pointermove": "moved($event)",
378
+ "pointerup": "lift($event)",
379
+ "pointercancel": "lift($event)",
380
+ "pointerleave": "lift($event)",
381
+ "contextmenu": "menu($event)",
382
+ "keydown": "pressFired = false; swallow = false"
383
+ },
384
+ properties: {
385
+ "style.user-select": "cubeHoldDisabled() ? null : \"none\"",
386
+ "style.-webkit-user-select": "cubeHoldDisabled() ? null : \"none\"",
387
+ "style.-webkit-touch-callout": "cubeHoldDisabled() ? null : \"none\""
388
+ }
389
+ },
390
+ ngImport: i0
391
+ });
392
+ };
393
+ i0.ɵɵngDeclareClassMetadata({
394
+ minVersion: "12.0.0",
395
+ version: "22.2.4",
396
+ ngImport: i0,
397
+ type: CubeHold,
398
+ decorators: [{
399
+ type: Directive,
400
+ args: [{
401
+ selector: "[cubeHold]",
402
+ host: {
403
+ "[style.user-select]": "cubeHoldDisabled() ? null : \"none\"",
404
+ "[style.-webkit-user-select]": "cubeHoldDisabled() ? null : \"none\"",
405
+ "[style.-webkit-touch-callout]": "cubeHoldDisabled() ? null : \"none\"",
406
+ "(pointerdown)": "press($event)",
407
+ "(pointermove)": "moved($event)",
408
+ "(pointerup)": "lift($event)",
409
+ "(pointercancel)": "lift($event)",
410
+ "(pointerleave)": "lift($event)",
411
+ "(contextmenu)": "menu($event)",
412
+ "(keydown)": "pressFired = false; swallow = false"
413
+ }
414
+ }]
415
+ }],
416
+ ctorParameters: () => [],
417
+ propDecorators: {
418
+ cubeHoldDisabled: [{
419
+ type: i0.Input,
420
+ args: [{
421
+ isSignal: true,
422
+ alias: "cubeHoldDisabled",
423
+ required: false
424
+ }]
425
+ }],
426
+ cubeHoldMs: [{
427
+ type: i0.Input,
428
+ args: [{
429
+ isSignal: true,
430
+ alias: "cubeHoldMs",
431
+ required: false
432
+ }]
433
+ }],
434
+ cubeHoldSlop: [{
435
+ type: i0.Input,
436
+ args: [{
437
+ isSignal: true,
438
+ alias: "cubeHoldSlop",
439
+ required: false
440
+ }]
441
+ }],
442
+ cubeHoldBuzz: [{
443
+ type: i0.Input,
444
+ args: [{
445
+ isSignal: true,
446
+ alias: "cubeHoldBuzz",
447
+ required: false
448
+ }]
449
+ }],
450
+ cubeHeld: [{
451
+ type: i0.Output,
452
+ args: ["cubeHeld"]
453
+ }]
454
+ }
455
+ });
456
+ const CUBE_ICON_NAMES = [
457
+ "names",
458
+ "name",
459
+ "change",
460
+ "move",
461
+ "place",
462
+ "whose",
463
+ "library",
464
+ "mine",
465
+ "shown",
466
+ "hidden",
467
+ "view",
468
+ "sort",
469
+ "kept",
470
+ "face",
471
+ "added",
472
+ "up",
473
+ "down",
474
+ "plus",
475
+ "square",
476
+ "one",
477
+ "two",
478
+ "three",
479
+ "four",
480
+ "grid-4x5",
481
+ "grid-3x6"
482
+ ];
483
+ const SHAPES = {
484
+ square: {
485
+ cols: 3,
486
+ rows: 3
487
+ },
488
+ one: {
489
+ cols: 1,
490
+ rows: 3
491
+ },
492
+ two: {
493
+ cols: 2,
494
+ rows: 3
495
+ },
496
+ three: {
497
+ cols: 3,
498
+ rows: 3
499
+ },
500
+ four: {
501
+ cols: 4,
502
+ rows: 3
503
+ },
504
+ "grid-4x5": {
505
+ cols: 4,
506
+ rows: 5
507
+ },
508
+ "grid-3x6": {
509
+ cols: 3,
510
+ rows: 6
511
+ }
512
+ };
513
+ function cubeIconCells(icon) {
514
+ const shape = SHAPES[icon];
515
+ if (!shape) return null;
516
+ const { cols, rows } = shape;
517
+ const gap = 1.6;
518
+ const size = Math.min((17 - gap * (cols - 1)) / cols, (17 - gap * (rows - 1)) / rows);
519
+ const w = cols * size + gap * (cols - 1);
520
+ const h = rows * size + gap * (rows - 1);
521
+ const out = [];
522
+ for (let r = 0; r < rows; r++) for (let c = 0; c < cols; c++) out.push({
523
+ x: cols === 1 ? 3.5 : 12 - w / 2 + c * (size + gap),
524
+ y: 12 - h / 2 + r * (size + gap),
525
+ w: cols === 1 ? 17 : size,
526
+ h: size
527
+ });
528
+ return out;
529
+ }
530
+ var CubeIcon = class CubeIcon {
531
+ icon = input.required(...ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []);
532
+ inUse = input(false, ...ngDevMode ? [{ debugName: "inUse" }] : /* istanbul ignore next */ []);
533
+ cells = computed(() => cubeIconCells(this.icon()), ...ngDevMode ? [{ debugName: "cells" }] : /* istanbul ignore next */ []);
534
+ static ɵfac = i0.ɵɵngDeclareFactory({
535
+ minVersion: "12.0.0",
536
+ version: "22.2.4",
537
+ ngImport: i0,
538
+ type: CubeIcon,
539
+ deps: [],
540
+ target: i0.ɵɵFactoryTarget.Component
541
+ });
542
+ static ɵcmp = i0.ɵɵngDeclareComponent({
543
+ minVersion: "17.0.0",
544
+ version: "22.2.4",
545
+ type: CubeIcon,
546
+ isStandalone: true,
547
+ selector: "cube-icon",
548
+ inputs: {
549
+ icon: {
550
+ classPropertyName: "icon",
551
+ publicName: "icon",
552
+ isSignal: true,
553
+ isRequired: true,
554
+ transformFunction: null
555
+ },
556
+ inUse: {
557
+ classPropertyName: "inUse",
558
+ publicName: "inUse",
559
+ isSignal: true,
560
+ isRequired: false,
561
+ transformFunction: null
562
+ }
563
+ },
564
+ host: { properties: { "class.in-use": "inUse()" } },
565
+ ngImport: i0,
566
+ template: `
567
+ <svg viewBox="0 0 24 24" aria-hidden="true">
568
+ @if (cells(); as cs) {
569
+ @for (c of cs; track $index) {
570
+ <rect
571
+ class="cell"
572
+ [attr.x]="c.x"
573
+ [attr.y]="c.y"
574
+ [attr.width]="c.w"
575
+ [attr.height]="c.h"
576
+ rx="0.8"
577
+ />
578
+ }
579
+ }
580
+ @switch (icon()) {
581
+ @case ('view') {
582
+ <rect x="4" y="4" width="7" height="7" rx="1.5" />
583
+ <rect x="13" y="4" width="7" height="7" rx="1.5" />
584
+ <rect x="4" y="13" width="7" height="7" rx="1.5" />
585
+ <rect x="13" y="13" width="7" height="7" rx="1.5" />
586
+ }
587
+ @case ('sort') {
588
+ <path d="M8 19V5M4.5 8.5 8 5l3.5 3.5M16 5v14M12.5 15.5 16 19l3.5-3.5" />
589
+ }
590
+ @case ('kept') {
591
+ <path d="M5 7h14M5 12h14M5 17h9" />
592
+ }
593
+ @case ('face') {
594
+ <path d="M12 3.5 20 8v8l-8 4.5L4 16V8Z" />
595
+ <path d="M4 8l8 4.5L20 8M12 12.5v8" />
596
+ }
597
+ @case ('added') {
598
+ <circle cx="12" cy="12" r="8" />
599
+ <path d="M12 7.5V12l3 2" />
600
+ }
601
+ @case ('up') {
602
+ <path d="M12 19V5M6.5 10.5 12 5l5.5 5.5" />
603
+ }
604
+ @case ('plus') {
605
+ <path d="M12 5v14M5 12h14" />
606
+ }
607
+ @case ('down') {
608
+ <path d="M12 5v14M6.5 13.5 12 19l5.5-5.5" />
609
+ }
610
+ @case ('names') {
611
+ <path d="M3.5 12.5 11 5h8v8l-7.5 7.5a1.5 1.5 0 0 1-2.1 0L3.5 14.6a1.5 1.5 0 0 1 0-2.1Z" />
612
+ <circle cx="15.2" cy="8.8" r="1.4" />
613
+ }
614
+ @case ('name') {
615
+ <path d="M5 18 9.5 6h1L15 18M6.6 14h6.8" />
616
+ <path
617
+ d="M17 11.5c1.6-1.2 3.5-.5 3.5 1.4V18M20.5 14.6c-2.6-.3-4 .4-4 1.8 0 1.9 2.7 2 4 .3"
618
+ />
619
+ }
620
+ @case ('change') {
621
+ <path d="M4 20h4L19 9a2.8 2.8 0 0 0-4-4L4 16v4Z" />
622
+ <path d="M13.5 6.5l4 4" />
623
+ }
624
+ @case ('move') {
625
+ <path
626
+ d="M4 8V6a2 2 0 0 1 2-2h4l2 2h6a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-1"
627
+ />
628
+ <path d="M2.5 13H12M9 10l3 3-3 3" />
629
+ }
630
+ @case ('place') {
631
+ <path
632
+ d="M4 8V6a2 2 0 0 1 2-2h4l2 2h6a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8Z"
633
+ />
634
+ }
635
+ @case ('whose') {
636
+ <circle cx="9" cy="8" r="3.2" />
637
+ <path d="M3 19c.6-3.4 3-5.2 6-5.2s5.4 1.8 6 5.2" />
638
+ <path d="M16 5.5a3 3 0 0 1 0 5.6M18.5 14.4c1.4.8 2.3 2.4 2.5 4.6" />
639
+ }
640
+ @case ('library') {
641
+ <path d="M4 5h4v15H4zM10 5h4v15h-4z" />
642
+ <path d="m16 6 3.6-1 3 14.4-3.6 1z" />
643
+ }
644
+ @case ('mine') {
645
+ <circle cx="12" cy="8" r="3.4" />
646
+ <path d="M5 20c.7-4 3.5-6 7-6s6.3 2 7 6" />
647
+ }
648
+ @case ('shown') {
649
+ <path d="M3 12s3.2-6 9-6 9 6 9 6-3.2 6-9 6-9-6-9-6Z" />
650
+ <circle cx="12" cy="12" r="2.6" />
651
+ }
652
+ @case ('hidden') {
653
+ <path d="M3 12s3.2-6 9-6c1.6 0 3 .45 4.2 1.1M21 12s-3.2 6-9 6c-1.6 0-3-.45-4.2-1.1" />
654
+ <path d="M4.5 19.5 19.5 4.5" />
655
+ }
656
+ }
657
+ </svg>
658
+ `,
659
+ isInline: true,
660
+ styles: [":host{display:inline-block;width:var(--cube-icon-size, 34px);height:var(--cube-icon-size, 34px);line-height:0}svg{width:100%;height:100%;fill:none;stroke:var(--cube-icon-stroke, #1f2a26);stroke-width:var(--cube-icon-stroke-width, 1.7);stroke-linecap:round;stroke-linejoin:round}.cell{fill:var(--cube-icon-stroke, #1f2a26);stroke:none;opacity:var(--cube-icon-cell-opacity, .8)}:host(.in-use) svg{stroke:var(--cube-icon-in-use, #3b5a4c)}:host(.in-use) .cell{fill:var(--cube-icon-in-use, #3b5a4c)}\n"],
661
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
662
+ });
663
+ };
664
+ i0.ɵɵngDeclareClassMetadata({
665
+ minVersion: "12.0.0",
666
+ version: "22.2.4",
667
+ ngImport: i0,
668
+ type: CubeIcon,
669
+ decorators: [{
670
+ type: Component,
671
+ args: [{
672
+ selector: "cube-icon",
673
+ template: `
674
+ <svg viewBox="0 0 24 24" aria-hidden="true">
675
+ @if (cells(); as cs) {
676
+ @for (c of cs; track $index) {
677
+ <rect
678
+ class="cell"
679
+ [attr.x]="c.x"
680
+ [attr.y]="c.y"
681
+ [attr.width]="c.w"
682
+ [attr.height]="c.h"
683
+ rx="0.8"
684
+ />
685
+ }
686
+ }
687
+ @switch (icon()) {
688
+ @case ('view') {
689
+ <rect x="4" y="4" width="7" height="7" rx="1.5" />
690
+ <rect x="13" y="4" width="7" height="7" rx="1.5" />
691
+ <rect x="4" y="13" width="7" height="7" rx="1.5" />
692
+ <rect x="13" y="13" width="7" height="7" rx="1.5" />
693
+ }
694
+ @case ('sort') {
695
+ <path d="M8 19V5M4.5 8.5 8 5l3.5 3.5M16 5v14M12.5 15.5 16 19l3.5-3.5" />
696
+ }
697
+ @case ('kept') {
698
+ <path d="M5 7h14M5 12h14M5 17h9" />
699
+ }
700
+ @case ('face') {
701
+ <path d="M12 3.5 20 8v8l-8 4.5L4 16V8Z" />
702
+ <path d="M4 8l8 4.5L20 8M12 12.5v8" />
703
+ }
704
+ @case ('added') {
705
+ <circle cx="12" cy="12" r="8" />
706
+ <path d="M12 7.5V12l3 2" />
707
+ }
708
+ @case ('up') {
709
+ <path d="M12 19V5M6.5 10.5 12 5l5.5 5.5" />
710
+ }
711
+ @case ('plus') {
712
+ <path d="M12 5v14M5 12h14" />
713
+ }
714
+ @case ('down') {
715
+ <path d="M12 5v14M6.5 13.5 12 19l5.5-5.5" />
716
+ }
717
+ @case ('names') {
718
+ <path d="M3.5 12.5 11 5h8v8l-7.5 7.5a1.5 1.5 0 0 1-2.1 0L3.5 14.6a1.5 1.5 0 0 1 0-2.1Z" />
719
+ <circle cx="15.2" cy="8.8" r="1.4" />
720
+ }
721
+ @case ('name') {
722
+ <path d="M5 18 9.5 6h1L15 18M6.6 14h6.8" />
723
+ <path
724
+ d="M17 11.5c1.6-1.2 3.5-.5 3.5 1.4V18M20.5 14.6c-2.6-.3-4 .4-4 1.8 0 1.9 2.7 2 4 .3"
725
+ />
726
+ }
727
+ @case ('change') {
728
+ <path d="M4 20h4L19 9a2.8 2.8 0 0 0-4-4L4 16v4Z" />
729
+ <path d="M13.5 6.5l4 4" />
730
+ }
731
+ @case ('move') {
732
+ <path
733
+ d="M4 8V6a2 2 0 0 1 2-2h4l2 2h6a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-1"
734
+ />
735
+ <path d="M2.5 13H12M9 10l3 3-3 3" />
736
+ }
737
+ @case ('place') {
738
+ <path
739
+ d="M4 8V6a2 2 0 0 1 2-2h4l2 2h6a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8Z"
740
+ />
741
+ }
742
+ @case ('whose') {
743
+ <circle cx="9" cy="8" r="3.2" />
744
+ <path d="M3 19c.6-3.4 3-5.2 6-5.2s5.4 1.8 6 5.2" />
745
+ <path d="M16 5.5a3 3 0 0 1 0 5.6M18.5 14.4c1.4.8 2.3 2.4 2.5 4.6" />
746
+ }
747
+ @case ('library') {
748
+ <path d="M4 5h4v15H4zM10 5h4v15h-4z" />
749
+ <path d="m16 6 3.6-1 3 14.4-3.6 1z" />
750
+ }
751
+ @case ('mine') {
752
+ <circle cx="12" cy="8" r="3.4" />
753
+ <path d="M5 20c.7-4 3.5-6 7-6s6.3 2 7 6" />
754
+ }
755
+ @case ('shown') {
756
+ <path d="M3 12s3.2-6 9-6 9 6 9 6-3.2 6-9 6-9-6-9-6Z" />
757
+ <circle cx="12" cy="12" r="2.6" />
758
+ }
759
+ @case ('hidden') {
760
+ <path d="M3 12s3.2-6 9-6c1.6 0 3 .45 4.2 1.1M21 12s-3.2 6-9 6c-1.6 0-3-.45-4.2-1.1" />
761
+ <path d="M4.5 19.5 19.5 4.5" />
762
+ }
763
+ }
764
+ </svg>
765
+ `,
766
+ host: { "[class.in-use]": "inUse()" },
767
+ changeDetection: ChangeDetectionStrategy.OnPush,
768
+ styles: [":host{display:inline-block;width:var(--cube-icon-size, 34px);height:var(--cube-icon-size, 34px);line-height:0}svg{width:100%;height:100%;fill:none;stroke:var(--cube-icon-stroke, #1f2a26);stroke-width:var(--cube-icon-stroke-width, 1.7);stroke-linecap:round;stroke-linejoin:round}.cell{fill:var(--cube-icon-stroke, #1f2a26);stroke:none;opacity:var(--cube-icon-cell-opacity, .8)}:host(.in-use) svg{stroke:var(--cube-icon-in-use, #3b5a4c)}:host(.in-use) .cell{fill:var(--cube-icon-in-use, #3b5a4c)}\n"]
769
+ }]
770
+ }],
771
+ propDecorators: {
772
+ icon: [{
773
+ type: i0.Input,
774
+ args: [{
775
+ isSignal: true,
776
+ alias: "icon",
777
+ required: true
778
+ }]
779
+ }],
780
+ inUse: [{
781
+ type: i0.Input,
782
+ args: [{
783
+ isSignal: true,
784
+ alias: "inUse",
785
+ required: false
786
+ }]
787
+ }]
788
+ }
789
+ });
790
+ const CONTEXT_PART_ORDER = [
791
+ "names",
792
+ "change",
793
+ "view",
794
+ "sort",
795
+ "move",
796
+ "whose",
797
+ "hide"
798
+ ];
799
+ function orderParts(parts) {
800
+ const unique = [...new Set(parts)];
801
+ return [...CONTEXT_PART_ORDER.filter((p) => unique.includes(p)), ...unique.filter((p) => !CONTEXT_PART_ORDER.includes(p))];
802
+ }
803
+ const CONTEXT_CUBE_SOURCE = new InjectionToken("CONTEXT_CUBE_SOURCE");
804
+ const CONTEXT_CUBE_WORDS = new InjectionToken("CONTEXT_CUBE_WORDS");
805
+ const PART_ICONS = { hide: "shown" };
806
+ function partsLevel(parts, words, now = {}) {
807
+ return orderParts(parts).map((p) => ({
808
+ key: p,
809
+ title: words.parts[p]?.title ?? "",
810
+ line: now[p]?.line !== void 0 ? now[p]?.line : words.parts[p]?.line ?? null,
811
+ icon: now[p]?.icon ?? PART_ICONS[p] ?? p,
812
+ data: p
813
+ }));
814
+ }
815
+ const VIEW_KEYS = [
816
+ "square",
817
+ "one",
818
+ "two",
819
+ "three",
820
+ "four",
821
+ "grid-4x5",
822
+ "grid-3x6"
823
+ ];
824
+ const isView = (v) => VIEW_KEYS.includes(v);
825
+ function gridFor(view, count) {
826
+ const n = Math.max(1, count);
827
+ switch (view) {
828
+ case "square": {
829
+ const side = Math.max(1, Math.ceil(Math.sqrt(n)));
830
+ return {
831
+ cols: side,
832
+ rows: side
833
+ };
834
+ }
835
+ case "one":
836
+ case "two":
837
+ case "three":
838
+ case "four": {
839
+ const cols = {
840
+ one: 1,
841
+ two: 2,
842
+ three: 3,
843
+ four: 4
844
+ }[view];
845
+ return {
846
+ cols,
847
+ rows: Math.ceil(n / cols)
848
+ };
849
+ }
850
+ case "grid-4x5":
851
+ case "grid-3x6": {
852
+ const [cols, rows] = view === "grid-4x5" ? [4, 5] : [3, 6];
853
+ return {
854
+ cols,
855
+ rows: rows * Math.ceil(n / (cols * rows))
856
+ };
857
+ }
858
+ }
859
+ }
860
+ function sortItems(items, by, dir) {
861
+ const sign = dir === "down" ? -1 : 1;
862
+ const known = (v) => v !== null && v !== void 0 && v !== "";
863
+ return items.map((item, at) => ({
864
+ item,
865
+ at,
866
+ value: by(item)
867
+ })).sort((a, b) => {
868
+ const ka = known(a.value);
869
+ const kb = known(b.value);
870
+ if (!ka || !kb) return Number(!ka) - Number(!kb) || a.at - b.at;
871
+ return sign * compare(a.value, b.value) || a.at - b.at;
872
+ }).map((x) => x.item);
873
+ }
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
+ function namesLevel(names, words, opts = {}) {
879
+ const tiles = [...names.filter((n) => n.current), ...names.filter((n) => !n.current).reverse()].map((n, i) => ({
880
+ key: `name:${i}:${n.name}`,
881
+ title: n.name,
882
+ line: words.names.line?.(n) ?? null,
883
+ icon: "name",
884
+ inUse: n.current,
885
+ data: { name: n }
886
+ }));
887
+ if (opts.canAdd) tiles.push({
888
+ key: "name:+",
889
+ title: words.names.another.title,
890
+ line: words.names.another.line ?? null,
891
+ icon: "plus",
892
+ adds: true,
893
+ data: { another: true }
894
+ });
895
+ return tiles;
896
+ }
897
+ function hideLevel(hidden, words) {
898
+ return [{
899
+ key: "hide:shown",
900
+ title: words.hide.shown.title,
901
+ line: words.hide.shown.line ?? null,
902
+ icon: "shown",
903
+ inUse: !hidden,
904
+ data: false
905
+ }, {
906
+ key: "hide:hidden",
907
+ title: words.hide.hidden.title,
908
+ line: words.hide.hidden.line ?? null,
909
+ icon: "hidden",
910
+ inUse: hidden,
911
+ data: true
912
+ }];
913
+ }
914
+ function viewLevel(now, words, views = VIEW_KEYS) {
915
+ return views.map((v) => ({
916
+ key: "view:" + v,
917
+ title: words.views[v]?.title ?? "",
918
+ line: v === now ? null : words.views[v]?.line ?? null,
919
+ icon: v,
920
+ inUse: v === now,
921
+ data: v
922
+ }));
923
+ }
924
+ function directionWords(option, words) {
925
+ return {
926
+ up: option.up ?? words.directions.up,
927
+ down: option.down ?? words.directions.down
928
+ };
929
+ }
930
+ function sortLevel(options, now, words) {
931
+ return options.map((o) => {
932
+ const inUse = now.by === o.by;
933
+ const directed = o.directed !== false;
934
+ return {
935
+ key: "sort:" + o.by,
936
+ title: o.title,
937
+ line: inUse && directed ? directionWords(o, words)[now.dir].title : o.line ?? null,
938
+ icon: o.icon,
939
+ inUse,
940
+ data: o
941
+ };
942
+ });
943
+ }
944
+ function sortDirectionsLevel(option, now, words) {
945
+ const w = directionWords(option, words);
946
+ return ["up", "down"].map((dir) => ({
947
+ key: "dir:" + dir,
948
+ title: w[dir].title,
949
+ line: w[dir].line ?? null,
950
+ icon: dir,
951
+ inUse: now.by === option.by && now.dir === dir,
952
+ data: dir
953
+ }));
954
+ }
955
+ const TURNING_SIDES = 4;
956
+ function turningRows(pieces, own, cols = 3, rows = cols) {
957
+ const across = Math.max(1, Math.floor(cols));
958
+ const down = Math.max(1, Math.floor(rows));
959
+ const count = pieces.length + (own !== null ? 1 : 0);
960
+ const perRow = across * 4;
961
+ const rowCount = Math.max(down, Math.ceil(count / perRow));
962
+ const grid = Array.from({ length: rowCount }, () => Array.from({ length: 4 }, () => Array.from({ length: across }).fill(null)));
963
+ const front = [];
964
+ for (let r = 0; r < rowCount; r++) for (let c = 0; c < across; c++) front.push([r, c]);
965
+ const frontForPieces = own !== null ? front.slice(0, -1) : front;
966
+ if (own !== null) grid[rowCount - 1][0][across - 1] = own;
967
+ let next = 0;
968
+ for (const [r, c] of frontForPieces) {
969
+ if (next >= pieces.length) break;
970
+ grid[r][0][c] = pieces[next++];
971
+ }
972
+ for (let r = 0; r < rowCount && next < pieces.length; r++) for (let s = 1; s < 4 && next < pieces.length; s++) for (let c = 0; c < across && next < pieces.length; c++) grid[r][s][c] = pieces[next++];
973
+ return {
974
+ rows: grid,
975
+ sides: grid.map((row) => 1 + row.slice(1).filter((side) => side.some((t) => t !== null)).length)
976
+ };
977
+ }
978
+ function squareLevelFor(cell) {
979
+ return cell >= 280 ? 0 : cell >= 150 ? 1 : cell >= 100 ? 2 : cell >= 70 ? 3 : 4;
980
+ }
981
+ function squareGap(n) {
982
+ return n <= 2 ? 12 : n === 3 ? 10 : n === 4 ? 8 : 5;
983
+ }
984
+ const SQUARE_MAX_SIDE = 880;
985
+ const SQUARE_LIST_ROW = 76;
986
+ function squareLayout(view, count, room, opts = {}) {
987
+ const n = Math.max(0, count);
988
+ const grid = gridFor(view, n);
989
+ const cols = grid.cols;
990
+ const rows = view === "square" ? grid.rows : Math.max(1, Math.ceil(n / cols));
991
+ const width = Math.max(0, Math.min(view === "square" ? Math.min(room.width, room.tall) : room.width, opts.maxSide ?? 880));
992
+ const list = view === "one";
993
+ const gap = list ? 8 : squareGap(Math.max(cols, Math.min(rows, 5)));
994
+ const cell = Math.max(0, (width - gap * (cols - 1)) / cols);
995
+ const rowHeight = list ? opts.listRow ?? 76 : cell;
996
+ return {
997
+ cols,
998
+ rows,
999
+ width,
1000
+ height: rows * rowHeight + gap * (rows - 1),
1001
+ gap,
1002
+ cell,
1003
+ rowHeight,
1004
+ level: list ? 1 : squareLevelFor(cell),
1005
+ list,
1006
+ open: cols * rows - n
1007
+ };
1008
+ }
1009
+ var CubeSquareTile = class CubeSquareTile {
1010
+ template = inject(TemplateRef);
1011
+ cubeSquareTile = input(...ngDevMode ? [void 0, { debugName: "cubeSquareTile" }] : /* istanbul ignore next */ []);
1012
+ static ngTemplateContextGuard(_dir, ctx) {
1013
+ return true;
1014
+ }
1015
+ static ɵfac = i0.ɵɵngDeclareFactory({
1016
+ minVersion: "12.0.0",
1017
+ version: "22.2.4",
1018
+ ngImport: i0,
1019
+ type: CubeSquareTile,
1020
+ deps: [],
1021
+ target: i0.ɵɵFactoryTarget.Directive
1022
+ });
1023
+ static ɵdir = i0.ɵɵngDeclareDirective({
1024
+ minVersion: "17.1.0",
1025
+ version: "22.2.4",
1026
+ type: CubeSquareTile,
1027
+ isStandalone: true,
1028
+ selector: "ng-template[cubeSquareTile]",
1029
+ inputs: { cubeSquareTile: {
1030
+ classPropertyName: "cubeSquareTile",
1031
+ publicName: "cubeSquareTile",
1032
+ isSignal: true,
1033
+ isRequired: false,
1034
+ transformFunction: null
1035
+ } },
1036
+ ngImport: i0
1037
+ });
1038
+ };
1039
+ i0.ɵɵngDeclareClassMetadata({
1040
+ minVersion: "12.0.0",
1041
+ version: "22.2.4",
1042
+ ngImport: i0,
1043
+ type: CubeSquareTile,
1044
+ decorators: [{
1045
+ type: Directive,
1046
+ args: [{ selector: "ng-template[cubeSquareTile]" }]
1047
+ }],
1048
+ propDecorators: { cubeSquareTile: [{
1049
+ type: i0.Input,
1050
+ args: [{
1051
+ isSignal: true,
1052
+ alias: "cubeSquareTile",
1053
+ required: false
1054
+ }]
1055
+ }] }
1056
+ });
1057
+ function turningFront(view, across = 3) {
1058
+ if (view === "square") return {
1059
+ cols: across,
1060
+ rows: across
1061
+ };
1062
+ if (view === "grid-4x5") return {
1063
+ cols: 4,
1064
+ rows: 5
1065
+ };
1066
+ if (view === "grid-3x6") return {
1067
+ cols: 3,
1068
+ rows: 6
1069
+ };
1070
+ return null;
1071
+ }
1072
+ const TURNING_BELOW = 640;
1073
+ const TURNING_NUDGE_UNTIL = 3;
1074
+ let turnedHere = 0;
1075
+ const readTurned = (key) => {
1076
+ if (!key) return turnedHere;
1077
+ try {
1078
+ return Number(localStorage.getItem(key)) || 0;
1079
+ } catch {
1080
+ return turnedHere;
1081
+ }
1082
+ };
1083
+ const noteTurned = (key) => {
1084
+ turnedHere++;
1085
+ if (!key) return;
1086
+ try {
1087
+ localStorage.setItem(key, String(readTurned(key) + 1));
1088
+ } catch {}
1089
+ };
1090
+ const reducedMotion = () => typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
1091
+ var CubeSquare = class CubeSquare {
1092
+ tiles = input.required(...ngDevMode ? [{ debugName: "tiles" }] : /* istanbul ignore next */ []);
1093
+ view = input("square", ...ngDevMode ? [{ debugName: "view" }] : /* istanbul ignore next */ []);
1094
+ maxSide = input(880, ...ngDevMode ? [{ debugName: "maxSide" }] : /* istanbul ignore next */ []);
1095
+ listRow = input(76, ...ngDevMode ? [{ debugName: "listRow" }] : /* istanbul ignore next */ []);
1096
+ dashed = input(false, ...ngDevMode ? [{ debugName: "dashed" }] : /* istanbul ignore next */ []);
1097
+ keyOf = input((_, i) => i, ...ngDevMode ? [{ debugName: "keyOf" }] : /* istanbul ignore next */ []);
1098
+ turning = input(false, ...ngDevMode ? [{ debugName: "turning" }] : /* istanbul ignore next */ []);
1099
+ turnBelow = input(640, ...ngDevMode ? [{ debugName: "turnBelow" }] : /* istanbul ignore next */ []);
1100
+ across = input(3, ...ngDevMode ? [{ debugName: "across" }] : /* istanbul ignore next */ []);
1101
+ isOwn = input(null, ...ngDevMode ? [{ debugName: "isOwn" }] : /* istanbul ignore next */ []);
1102
+ nudgeKey = input(null, ...ngDevMode ? [{ debugName: "nudgeKey" }] : /* istanbul ignore next */ []);
1103
+ tile = contentChild(CubeSquareTile, ...ngDevMode ? [{ debugName: "tile" }] : /* istanbul ignore next */ []);
1104
+ grid = viewChild("grid", ...ngDevMode ? [{ debugName: "grid" }] : /* istanbul ignore next */ []);
1105
+ room = signal({
1106
+ width: 0,
1107
+ tall: 0
1108
+ }, ...ngDevMode ? [{ debugName: "room" }] : /* istanbul ignore next */ []);
1109
+ front = computed(() => {
1110
+ if (!this.turning()) return null;
1111
+ if ((this.room().width || 354) >= this.turnBelow()) return null;
1112
+ const front = turningFront(this.view(), Math.max(1, Math.floor(this.across())));
1113
+ return front && this.tiles().length > front.cols * front.rows ? front : null;
1114
+ }, ...ngDevMode ? [{ debugName: "front" }] : /* istanbul ignore next */ []);
1115
+ layout = computed(() => {
1116
+ const r = this.room();
1117
+ const width = r.width || 354;
1118
+ const room = {
1119
+ width,
1120
+ tall: r.tall || width
1121
+ };
1122
+ const opts = {
1123
+ maxSide: this.maxSide(),
1124
+ listRow: this.listRow()
1125
+ };
1126
+ const front = this.front();
1127
+ if (!front) return squareLayout(this.view(), this.tiles().length, room, opts);
1128
+ const full = squareLayout(this.view(), front.cols * front.rows, room, opts);
1129
+ const rows = this.rings()?.rows.length ?? front.rows;
1130
+ return {
1131
+ ...full,
1132
+ rows,
1133
+ height: rows * full.rowHeight + full.gap * (rows - 1),
1134
+ open: 0
1135
+ };
1136
+ }, ...ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []);
1137
+ rings = computed(() => {
1138
+ const front = this.front();
1139
+ if (!front) return null;
1140
+ const isOwn = this.isOwn();
1141
+ const tiles = this.tiles();
1142
+ const own = isOwn ? tiles.find((t) => isOwn(t)) ?? null : null;
1143
+ return turningRows(own === null ? tiles : tiles.filter((t) => t !== own), own, front.cols, front.rows);
1144
+ }, ...ngDevMode ? [{ debugName: "rings" }] : /* istanbul ignore next */ []);
1145
+ indexes = computed(() => new Map(this.tiles().map((t, i) => [t, i])), ...ngDevMode ? [{ debugName: "indexes" }] : /* istanbul ignore next */ []);
1146
+ indexOf(t) {
1147
+ return this.indexes().get(t) ?? 0;
1148
+ }
1149
+ openPlaces = computed(() => Array.from({ length: this.layout().open }, (_, i) => i), ...ngDevMode ? [{ debugName: "openPlaces" }] : /* istanbul ignore next */ []);
1150
+ angles = signal({}, ...ngDevMode ? [{ debugName: "angles" }] : /* istanbul ignore next */ []);
1151
+ dragging = signal(null, ...ngDevMode ? [{ debugName: "dragging" }] : /* istanbul ignore next */ []);
1152
+ still = signal(reducedMotion(), ...ngDevMode ? [{ debugName: "still" }] : /* istanbul ignore next */ []);
1153
+ nudging = signal(false, ...ngDevMode ? [{ debugName: "nudging" }] : /* istanbul ignore next */ []);
1154
+ drag = null;
1155
+ fingers = /* @__PURE__ */ new Set();
1156
+ suppressClick = false;
1157
+ nudged = false;
1158
+ timers = [];
1159
+ host = inject(ElementRef).nativeElement;
1160
+ angle(row) {
1161
+ return this.angles()[row] ?? 0;
1162
+ }
1163
+ sideOf(row) {
1164
+ const sides = 4;
1165
+ return (Math.round(-this.angle(row) / 90) % sides + sides) % sides;
1166
+ }
1167
+ filled(row) {
1168
+ return this.rings()?.sides[row] ?? 1;
1169
+ }
1170
+ down(row, e) {
1171
+ this.fingers.add(e.pointerId);
1172
+ if (this.fingers.size > 1) {
1173
+ this.cancelDrag();
1174
+ return;
1175
+ }
1176
+ if (this.filled(row) <= 1) return;
1177
+ this.drag = {
1178
+ row,
1179
+ id: e.pointerId,
1180
+ x: e.clientX,
1181
+ y: e.clientY,
1182
+ base: this.angle(row),
1183
+ moved: false
1184
+ };
1185
+ }
1186
+ move(row, e) {
1187
+ const drag = this.drag;
1188
+ if (!drag || drag.row !== row || drag.id !== e.pointerId) return;
1189
+ const dx = e.clientX - drag.x;
1190
+ const dy = e.clientY - drag.y;
1191
+ if (!drag.moved) {
1192
+ if (Math.abs(dx) < 8 || Math.abs(dx) < Math.abs(dy)) return;
1193
+ drag.moved = true;
1194
+ this.dragging.set(row);
1195
+ e.currentTarget?.setPointerCapture?.(e.pointerId);
1196
+ }
1197
+ const width = this.layout().width || 354;
1198
+ this.angles.update((a) => ({
1199
+ ...a,
1200
+ [row]: drag.base + dx / width * 90
1201
+ }));
1202
+ }
1203
+ up(row, e) {
1204
+ this.fingers.delete(e.pointerId);
1205
+ const drag = this.drag;
1206
+ if (!drag || drag.row !== row || drag.id !== e.pointerId) return;
1207
+ this.drag = null;
1208
+ if (!drag.moved) return;
1209
+ this.dragging.set(null);
1210
+ this.suppressClick = true;
1211
+ setTimeout(() => this.suppressClick = false);
1212
+ const moved = this.angle(row) - drag.base;
1213
+ const steps = Math.abs(moved) > 12 ? Math.sign(moved) * Math.max(1, Math.round(Math.abs(moved) / 90)) : 0;
1214
+ this.settle(row, drag.base, steps);
1215
+ }
1216
+ cancelDrag() {
1217
+ const drag = this.drag;
1218
+ this.drag = null;
1219
+ if (!drag?.moved) return;
1220
+ this.dragging.set(null);
1221
+ this.angles.update((a) => ({
1222
+ ...a,
1223
+ [drag.row]: drag.base
1224
+ }));
1225
+ }
1226
+ settle(row, base, steps) {
1227
+ const filled = this.filled(row);
1228
+ const sideAt = (s) => (Math.round(-(base + s * 90) / 90) % 4 + 4) % 4;
1229
+ let n = steps;
1230
+ while (n !== 0 && sideAt(n) >= filled) n += Math.sign(n);
1231
+ this.angles.update((a) => ({
1232
+ ...a,
1233
+ [row]: base + n * 90
1234
+ }));
1235
+ if (n !== 0) noteTurned(this.nudgeKey());
1236
+ }
1237
+ key(row, e) {
1238
+ if (e.key !== "ArrowRight" && e.key !== "ArrowLeft") return;
1239
+ if (this.filled(row) <= 1) return;
1240
+ e.preventDefault();
1241
+ const col = this.focusedColumn(e.target);
1242
+ this.settle(row, this.angle(row), e.key === "ArrowRight" ? -1 : 1);
1243
+ setTimeout(() => this.focusSide(row, col));
1244
+ }
1245
+ focusedColumn(target) {
1246
+ const cell = target?.closest(".cs-cell, .cs-place");
1247
+ const side = cell?.parentElement;
1248
+ return cell && side ? Array.from(side.children).indexOf(cell) : 0;
1249
+ }
1250
+ focusSide(row, col) {
1251
+ const side = this.host.querySelector(`.cs-row[data-row="${row}"] .cs-side[data-side="${this.sideOf(row)}"]`);
1252
+ if (!side) return;
1253
+ const cells = Array.from(side.children);
1254
+ const order = [cells[col], ...cells].filter(Boolean);
1255
+ const focusable = "button, a[href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])";
1256
+ for (const cell of order) {
1257
+ const el = cell.matches(focusable) ? cell : cell.querySelector(focusable);
1258
+ if (el) {
1259
+ el.focus();
1260
+ return;
1261
+ }
1262
+ }
1263
+ side.closest(".cs-row")?.focus();
1264
+ }
1265
+ nudge() {
1266
+ const rings = this.rings();
1267
+ if (this.nudged || !rings || reducedMotion()) return;
1268
+ if (readTurned(this.nudgeKey()) >= 3) return;
1269
+ const rows = rings.sides.flatMap((s, i) => s > 1 ? [i] : []);
1270
+ if (!rows.length) return;
1271
+ this.nudged = true;
1272
+ this.nudging.set(true);
1273
+ const set = (row, angle) => {
1274
+ if (this.drag || this.dragging() !== null) return;
1275
+ this.angles.update((a) => ({
1276
+ ...a,
1277
+ [row]: angle
1278
+ }));
1279
+ };
1280
+ rows.forEach((row, i) => {
1281
+ this.timers.push(setTimeout(() => set(row, -22), 500 + i * 180), setTimeout(() => set(row, 0), 1020 + i * 180));
1282
+ });
1283
+ this.timers.push(setTimeout(() => this.nudging.set(false), 1600 + rows.length * 180));
1284
+ }
1285
+ constructor() {
1286
+ const host = this.host;
1287
+ const destroy = inject(DestroyRef);
1288
+ const swallow = (e) => {
1289
+ if (!this.suppressClick) return;
1290
+ e.stopPropagation();
1291
+ e.preventDefault();
1292
+ };
1293
+ host.addEventListener("click", swallow, true);
1294
+ destroy.onDestroy(() => {
1295
+ host.removeEventListener("click", swallow, true);
1296
+ this.timers.forEach(clearTimeout);
1297
+ });
1298
+ effect(() => {
1299
+ if (this.rings()) untracked(() => this.timers.push(setTimeout(() => this.nudge())));
1300
+ });
1301
+ afterNextRender(() => {
1302
+ const measure = () => this.room.set({
1303
+ width: host.clientWidth,
1304
+ tall: Math.max(320, window.innerHeight - 48)
1305
+ });
1306
+ measure();
1307
+ const watch = typeof ResizeObserver === "function" ? new ResizeObserver(measure) : null;
1308
+ watch?.observe(host);
1309
+ window.addEventListener("resize", measure);
1310
+ destroy.onDestroy(() => {
1311
+ watch?.disconnect();
1312
+ window.removeEventListener("resize", measure);
1313
+ });
1314
+ });
1315
+ let before = 0;
1316
+ let beforeView = null;
1317
+ effect(() => {
1318
+ const { cols, list } = this.layout();
1319
+ const view = this.view();
1320
+ 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" }], {
1322
+ duration: 420,
1323
+ easing: "cubic-bezier(.2,.7,.2,1)"
1324
+ });
1325
+ before = cols;
1326
+ beforeView = view;
1327
+ });
1328
+ }
1329
+ static ɵfac = i0.ɵɵngDeclareFactory({
1330
+ minVersion: "12.0.0",
1331
+ version: "22.2.4",
1332
+ ngImport: i0,
1333
+ type: CubeSquare,
1334
+ deps: [],
1335
+ target: i0.ɵɵFactoryTarget.Component
1336
+ });
1337
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1338
+ minVersion: "17.0.0",
1339
+ version: "22.2.4",
1340
+ type: CubeSquare,
1341
+ isStandalone: true,
1342
+ selector: "cube-square",
1343
+ inputs: {
1344
+ tiles: {
1345
+ classPropertyName: "tiles",
1346
+ publicName: "tiles",
1347
+ isSignal: true,
1348
+ isRequired: true,
1349
+ transformFunction: null
1350
+ },
1351
+ view: {
1352
+ classPropertyName: "view",
1353
+ publicName: "view",
1354
+ isSignal: true,
1355
+ isRequired: false,
1356
+ transformFunction: null
1357
+ },
1358
+ maxSide: {
1359
+ classPropertyName: "maxSide",
1360
+ publicName: "maxSide",
1361
+ isSignal: true,
1362
+ isRequired: false,
1363
+ transformFunction: null
1364
+ },
1365
+ listRow: {
1366
+ classPropertyName: "listRow",
1367
+ publicName: "listRow",
1368
+ isSignal: true,
1369
+ isRequired: false,
1370
+ transformFunction: null
1371
+ },
1372
+ dashed: {
1373
+ classPropertyName: "dashed",
1374
+ publicName: "dashed",
1375
+ isSignal: true,
1376
+ isRequired: false,
1377
+ transformFunction: null
1378
+ },
1379
+ keyOf: {
1380
+ classPropertyName: "keyOf",
1381
+ publicName: "keyOf",
1382
+ isSignal: true,
1383
+ isRequired: false,
1384
+ transformFunction: null
1385
+ },
1386
+ turning: {
1387
+ classPropertyName: "turning",
1388
+ publicName: "turning",
1389
+ isSignal: true,
1390
+ isRequired: false,
1391
+ transformFunction: null
1392
+ },
1393
+ turnBelow: {
1394
+ classPropertyName: "turnBelow",
1395
+ publicName: "turnBelow",
1396
+ isSignal: true,
1397
+ isRequired: false,
1398
+ transformFunction: null
1399
+ },
1400
+ across: {
1401
+ classPropertyName: "across",
1402
+ publicName: "across",
1403
+ isSignal: true,
1404
+ isRequired: false,
1405
+ transformFunction: null
1406
+ },
1407
+ isOwn: {
1408
+ classPropertyName: "isOwn",
1409
+ publicName: "isOwn",
1410
+ isSignal: true,
1411
+ isRequired: false,
1412
+ transformFunction: null
1413
+ },
1414
+ nudgeKey: {
1415
+ classPropertyName: "nudgeKey",
1416
+ publicName: "nudgeKey",
1417
+ isSignal: true,
1418
+ isRequired: false,
1419
+ transformFunction: null
1420
+ }
1421
+ },
1422
+ queries: [{
1423
+ propertyName: "tile",
1424
+ first: true,
1425
+ predicate: CubeSquareTile,
1426
+ descendants: true,
1427
+ isSignal: true
1428
+ }],
1429
+ viewQueries: [{
1430
+ propertyName: "grid",
1431
+ first: true,
1432
+ predicate: ["grid"],
1433
+ descendants: true,
1434
+ isSignal: true
1435
+ }],
1436
+ ngImport: i0,
1437
+ template: `
1438
+ @let sq = layout();
1439
+ @if (rings(); as r) {
1440
+ <div
1441
+ class="cs-turning"
1442
+ [class]="'cs-turning cs-l' + sq.level"
1443
+ [class.cs-dashed]="dashed()"
1444
+ [attr.data-level]="sq.level"
1445
+ [style.width.px]="sq.width"
1446
+ [style.--cs-gap.px]="sq.gap"
1447
+ >
1448
+ @for (row of r.rows; track ri; let ri = $index) {
1449
+ <div
1450
+ class="cs-row"
1451
+ [class.cs-turns]="r.sides[ri] > 1"
1452
+ [attr.data-row]="ri"
1453
+ [style.height.px]="sq.rowHeight"
1454
+ (pointerdown)="down(ri, $event)"
1455
+ (pointermove)="move(ri, $event)"
1456
+ (pointerup)="up(ri, $event)"
1457
+ (pointercancel)="up(ri, $event)"
1458
+ (keydown)="key(ri, $event)"
1459
+ >
1460
+ @if (r.sides[ri] > 1) {
1461
+ <span class="cs-edge" aria-hidden="true"></span>
1462
+ }
1463
+ <div
1464
+ class="cs-band"
1465
+ [class.cs-still]="dragging() === ri || still()"
1466
+ [class.cs-nudging]="nudging()"
1467
+ [style.transform]="
1468
+ 'translateZ(' + -sq.width / 2 + 'px) rotateY(' + angle(ri) + 'deg)'
1469
+ "
1470
+ >
1471
+ @for (side of row; track si; let si = $index) {
1472
+ <div
1473
+ class="cs-side"
1474
+ [attr.data-side]="si"
1475
+ [style.grid-template-columns]="'repeat(' + sq.cols + ', minmax(0, 1fr))'"
1476
+ [style.transform]="
1477
+ 'rotateY(' + si * 90 + 'deg) translateZ(' + sq.width / 2 + 'px)'
1478
+ "
1479
+ [attr.aria-hidden]="sideOf(ri) === si ? null : 'true'"
1480
+ [attr.inert]="sideOf(ri) === si ? null : ''"
1481
+ >
1482
+ @for (t of side; track ci; let ci = $index) {
1483
+ @if (t !== null) {
1484
+ <div class="cs-cell">
1485
+ @if (tile(); as tpl) {
1486
+ <ng-container
1487
+ [ngTemplateOutlet]="tpl.template"
1488
+ [ngTemplateOutletContext]="{
1489
+ $implicit: t,
1490
+ index: indexOf(t),
1491
+ level: sq.level,
1492
+ cell: sq.cell,
1493
+ rowHeight: sq.rowHeight,
1494
+ list: false,
1495
+ }"
1496
+ />
1497
+ }
1498
+ </div>
1499
+ } @else if (si < r.sides[ri]) {
1500
+ <div class="cs-place" aria-hidden="true"></div>
1501
+ }
1502
+ }
1503
+ </div>
1504
+ }
1505
+ </div>
1506
+ </div>
1507
+ }
1508
+ </div>
1509
+ } @else {
1510
+ <div
1511
+ #grid
1512
+ [class]="'cs-square cs-l' + sq.level"
1513
+ [class.cs-list]="sq.list"
1514
+ [class.cs-dashed]="dashed()"
1515
+ [attr.data-level]="sq.level"
1516
+ [style.width.px]="sq.width"
1517
+ [style.height.px]="sq.height"
1518
+ [style.--cs-gap.px]="sq.gap"
1519
+ [style.grid-template-columns]="'repeat(' + sq.cols + ', minmax(0, 1fr))'"
1520
+ [style.grid-template-rows]="'repeat(' + sq.rows + ', minmax(0, 1fr))'"
1521
+ >
1522
+ @for (t of tiles(); track keyOf()(t, $index); let i = $index) {
1523
+ <div class="cs-cell">
1524
+ @if (tile(); as tpl) {
1525
+ <ng-container
1526
+ [ngTemplateOutlet]="tpl.template"
1527
+ [ngTemplateOutletContext]="{
1528
+ $implicit: t,
1529
+ index: i,
1530
+ level: sq.level,
1531
+ cell: sq.cell,
1532
+ rowHeight: sq.rowHeight,
1533
+ list: sq.list,
1534
+ }"
1535
+ />
1536
+ }
1537
+ </div>
1538
+ }
1539
+ @for (i of openPlaces(); track i) {
1540
+ <div class="cs-place" aria-hidden="true"></div>
1541
+ }
1542
+ </div>
1543
+ }
1544
+ `,
1545
+ isInline: true,
1546
+ styles: [":host{display:block}.cs-square{display:grid;gap:calc(var(--cs-gap) * var(--cube-square-gap-scale, 1));--cs-radius: var(--cube-square-radius, 20px)}.cs-cell{display:grid;min-width:0;min-height:0}.cs-place{box-sizing:border-box;border:var(--cube-square-place-width, 1.5px) solid var(--cube-square-place, color-mix(in srgb, #dae0d9 55%, transparent));border-radius:var(--cs-radius)}.cs-dashed .cs-place{border-style:dashed;border-color:var(--cube-square-place-dashed, #dae0d9)}.cs-l0{--cs-radius: 28px}.cs-l2{--cs-radius: 16px}.cs-l3{--cs-radius: 12px}.cs-l4{--cs-radius: 9px}.cs-l4 .cs-place{border-width:1px}.cs-turning{display:flex;flex-direction:column;gap:calc(var(--cs-gap) * var(--cube-square-gap-scale, 1));--cs-radius: var(--cube-square-radius, 20px)}.cs-row{position:relative;perspective:1400px;touch-action:pan-y;user-select:none;-webkit-user-select:none;outline:none}.cs-row:focus-visible{outline:2px solid var(--cube-square-focus, #5f9a80);outline-offset:3px;border-radius:var(--cs-radius)}.cs-band{position:absolute;inset:0;transform-style:preserve-3d;transition:transform .38s cubic-bezier(.2,.8,.2,1)}.cs-band.cs-nudging{transition:transform .52s cubic-bezier(.4,0,.2,1)}.cs-band.cs-still{transition:none}.cs-side{position:absolute;inset:0;display:grid;gap:calc(var(--cs-gap) * var(--cube-square-gap-scale, 1));backface-visibility:hidden}.cs-edge{pointer-events:none;position:absolute;top:18%;bottom:18%;right:calc(-1*max(4px,var(--cs-gap) - 2px));z-index:1;width:3px;border-radius:999px;background:var(--cube-square-edge, color-mix(in srgb, #5f9a80 45%, transparent))}\n"],
1547
+ dependencies: [{
1548
+ kind: "directive",
1549
+ type: NgTemplateOutlet,
1550
+ selector: "[ngTemplateOutlet]",
1551
+ inputs: [
1552
+ "ngTemplateOutletContext",
1553
+ "ngTemplateOutlet",
1554
+ "ngTemplateOutletInjector"
1555
+ ]
1556
+ }],
1557
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
1558
+ });
1559
+ };
1560
+ i0.ɵɵngDeclareClassMetadata({
1561
+ minVersion: "12.0.0",
1562
+ version: "22.2.4",
1563
+ ngImport: i0,
1564
+ type: CubeSquare,
1565
+ decorators: [{
1566
+ type: Component,
1567
+ args: [{
1568
+ selector: "cube-square",
1569
+ imports: [NgTemplateOutlet],
1570
+ template: `
1571
+ @let sq = layout();
1572
+ @if (rings(); as r) {
1573
+ <div
1574
+ class="cs-turning"
1575
+ [class]="'cs-turning cs-l' + sq.level"
1576
+ [class.cs-dashed]="dashed()"
1577
+ [attr.data-level]="sq.level"
1578
+ [style.width.px]="sq.width"
1579
+ [style.--cs-gap.px]="sq.gap"
1580
+ >
1581
+ @for (row of r.rows; track ri; let ri = $index) {
1582
+ <div
1583
+ class="cs-row"
1584
+ [class.cs-turns]="r.sides[ri] > 1"
1585
+ [attr.data-row]="ri"
1586
+ [style.height.px]="sq.rowHeight"
1587
+ (pointerdown)="down(ri, $event)"
1588
+ (pointermove)="move(ri, $event)"
1589
+ (pointerup)="up(ri, $event)"
1590
+ (pointercancel)="up(ri, $event)"
1591
+ (keydown)="key(ri, $event)"
1592
+ >
1593
+ @if (r.sides[ri] > 1) {
1594
+ <span class="cs-edge" aria-hidden="true"></span>
1595
+ }
1596
+ <div
1597
+ class="cs-band"
1598
+ [class.cs-still]="dragging() === ri || still()"
1599
+ [class.cs-nudging]="nudging()"
1600
+ [style.transform]="
1601
+ 'translateZ(' + -sq.width / 2 + 'px) rotateY(' + angle(ri) + 'deg)'
1602
+ "
1603
+ >
1604
+ @for (side of row; track si; let si = $index) {
1605
+ <div
1606
+ class="cs-side"
1607
+ [attr.data-side]="si"
1608
+ [style.grid-template-columns]="'repeat(' + sq.cols + ', minmax(0, 1fr))'"
1609
+ [style.transform]="
1610
+ 'rotateY(' + si * 90 + 'deg) translateZ(' + sq.width / 2 + 'px)'
1611
+ "
1612
+ [attr.aria-hidden]="sideOf(ri) === si ? null : 'true'"
1613
+ [attr.inert]="sideOf(ri) === si ? null : ''"
1614
+ >
1615
+ @for (t of side; track ci; let ci = $index) {
1616
+ @if (t !== null) {
1617
+ <div class="cs-cell">
1618
+ @if (tile(); as tpl) {
1619
+ <ng-container
1620
+ [ngTemplateOutlet]="tpl.template"
1621
+ [ngTemplateOutletContext]="{
1622
+ $implicit: t,
1623
+ index: indexOf(t),
1624
+ level: sq.level,
1625
+ cell: sq.cell,
1626
+ rowHeight: sq.rowHeight,
1627
+ list: false,
1628
+ }"
1629
+ />
1630
+ }
1631
+ </div>
1632
+ } @else if (si < r.sides[ri]) {
1633
+ <div class="cs-place" aria-hidden="true"></div>
1634
+ }
1635
+ }
1636
+ </div>
1637
+ }
1638
+ </div>
1639
+ </div>
1640
+ }
1641
+ </div>
1642
+ } @else {
1643
+ <div
1644
+ #grid
1645
+ [class]="'cs-square cs-l' + sq.level"
1646
+ [class.cs-list]="sq.list"
1647
+ [class.cs-dashed]="dashed()"
1648
+ [attr.data-level]="sq.level"
1649
+ [style.width.px]="sq.width"
1650
+ [style.height.px]="sq.height"
1651
+ [style.--cs-gap.px]="sq.gap"
1652
+ [style.grid-template-columns]="'repeat(' + sq.cols + ', minmax(0, 1fr))'"
1653
+ [style.grid-template-rows]="'repeat(' + sq.rows + ', minmax(0, 1fr))'"
1654
+ >
1655
+ @for (t of tiles(); track keyOf()(t, $index); let i = $index) {
1656
+ <div class="cs-cell">
1657
+ @if (tile(); as tpl) {
1658
+ <ng-container
1659
+ [ngTemplateOutlet]="tpl.template"
1660
+ [ngTemplateOutletContext]="{
1661
+ $implicit: t,
1662
+ index: i,
1663
+ level: sq.level,
1664
+ cell: sq.cell,
1665
+ rowHeight: sq.rowHeight,
1666
+ list: sq.list,
1667
+ }"
1668
+ />
1669
+ }
1670
+ </div>
1671
+ }
1672
+ @for (i of openPlaces(); track i) {
1673
+ <div class="cs-place" aria-hidden="true"></div>
1674
+ }
1675
+ </div>
1676
+ }
1677
+ `,
1678
+ changeDetection: ChangeDetectionStrategy.OnPush,
1679
+ styles: [":host{display:block}.cs-square{display:grid;gap:calc(var(--cs-gap) * var(--cube-square-gap-scale, 1));--cs-radius: var(--cube-square-radius, 20px)}.cs-cell{display:grid;min-width:0;min-height:0}.cs-place{box-sizing:border-box;border:var(--cube-square-place-width, 1.5px) solid var(--cube-square-place, color-mix(in srgb, #dae0d9 55%, transparent));border-radius:var(--cs-radius)}.cs-dashed .cs-place{border-style:dashed;border-color:var(--cube-square-place-dashed, #dae0d9)}.cs-l0{--cs-radius: 28px}.cs-l2{--cs-radius: 16px}.cs-l3{--cs-radius: 12px}.cs-l4{--cs-radius: 9px}.cs-l4 .cs-place{border-width:1px}.cs-turning{display:flex;flex-direction:column;gap:calc(var(--cs-gap) * var(--cube-square-gap-scale, 1));--cs-radius: var(--cube-square-radius, 20px)}.cs-row{position:relative;perspective:1400px;touch-action:pan-y;user-select:none;-webkit-user-select:none;outline:none}.cs-row:focus-visible{outline:2px solid var(--cube-square-focus, #5f9a80);outline-offset:3px;border-radius:var(--cs-radius)}.cs-band{position:absolute;inset:0;transform-style:preserve-3d;transition:transform .38s cubic-bezier(.2,.8,.2,1)}.cs-band.cs-nudging{transition:transform .52s cubic-bezier(.4,0,.2,1)}.cs-band.cs-still{transition:none}.cs-side{position:absolute;inset:0;display:grid;gap:calc(var(--cs-gap) * var(--cube-square-gap-scale, 1));backface-visibility:hidden}.cs-edge{pointer-events:none;position:absolute;top:18%;bottom:18%;right:calc(-1*max(4px,var(--cs-gap) - 2px));z-index:1;width:3px;border-radius:999px;background:var(--cube-square-edge, color-mix(in srgb, #5f9a80 45%, transparent))}\n"]
1680
+ }]
1681
+ }],
1682
+ ctorParameters: () => [],
1683
+ propDecorators: {
1684
+ tiles: [{
1685
+ type: i0.Input,
1686
+ args: [{
1687
+ isSignal: true,
1688
+ alias: "tiles",
1689
+ required: true
1690
+ }]
1691
+ }],
1692
+ view: [{
1693
+ type: i0.Input,
1694
+ args: [{
1695
+ isSignal: true,
1696
+ alias: "view",
1697
+ required: false
1698
+ }]
1699
+ }],
1700
+ maxSide: [{
1701
+ type: i0.Input,
1702
+ args: [{
1703
+ isSignal: true,
1704
+ alias: "maxSide",
1705
+ required: false
1706
+ }]
1707
+ }],
1708
+ listRow: [{
1709
+ type: i0.Input,
1710
+ args: [{
1711
+ isSignal: true,
1712
+ alias: "listRow",
1713
+ required: false
1714
+ }]
1715
+ }],
1716
+ dashed: [{
1717
+ type: i0.Input,
1718
+ args: [{
1719
+ isSignal: true,
1720
+ alias: "dashed",
1721
+ required: false
1722
+ }]
1723
+ }],
1724
+ keyOf: [{
1725
+ type: i0.Input,
1726
+ args: [{
1727
+ isSignal: true,
1728
+ alias: "keyOf",
1729
+ required: false
1730
+ }]
1731
+ }],
1732
+ turning: [{
1733
+ type: i0.Input,
1734
+ args: [{
1735
+ isSignal: true,
1736
+ alias: "turning",
1737
+ required: false
1738
+ }]
1739
+ }],
1740
+ turnBelow: [{
1741
+ type: i0.Input,
1742
+ args: [{
1743
+ isSignal: true,
1744
+ alias: "turnBelow",
1745
+ required: false
1746
+ }]
1747
+ }],
1748
+ across: [{
1749
+ type: i0.Input,
1750
+ args: [{
1751
+ isSignal: true,
1752
+ alias: "across",
1753
+ required: false
1754
+ }]
1755
+ }],
1756
+ isOwn: [{
1757
+ type: i0.Input,
1758
+ args: [{
1759
+ isSignal: true,
1760
+ alias: "isOwn",
1761
+ required: false
1762
+ }]
1763
+ }],
1764
+ nudgeKey: [{
1765
+ type: i0.Input,
1766
+ args: [{
1767
+ isSignal: true,
1768
+ alias: "nudgeKey",
1769
+ required: false
1770
+ }]
1771
+ }],
1772
+ tile: [{
1773
+ type: i0.ContentChild,
1774
+ args: [i0.forwardRef(() => CubeSquareTile), { isSignal: true }]
1775
+ }],
1776
+ grid: [{
1777
+ type: i0.ViewChild,
1778
+ args: ["grid", { isSignal: true }]
1779
+ }]
1780
+ }
1781
+ });
1782
+ const contextLevelFor = squareLevelFor;
1783
+ function contextSquare(count, room, maxSide = 880) {
1784
+ const { cols: n, rows } = gridFor("square", count);
1785
+ const side = Math.max(0, Math.min(room, maxSide));
1786
+ const gap = squareGap(n);
1787
+ const cell = (side - gap * (n - 1)) / n;
1788
+ return {
1789
+ n,
1790
+ side,
1791
+ gap,
1792
+ level: contextLevelFor(cell),
1793
+ open: n * rows - Math.max(0, count)
1794
+ };
1795
+ }
1796
+ function contextIcon(tile) {
1797
+ if (CUBE_ICON_NAMES.includes(tile.icon)) return tile.icon;
1798
+ if (tile.adds) return "plus";
1799
+ if (tile.icon === "hide") return "shown";
1800
+ return "face";
1801
+ }
1802
+ var CubeContext = class CubeContext {
1803
+ held = input.required(...ngDevMode ? [{ debugName: "held" }] : /* istanbul ignore next */ []);
1804
+ path = input([], ...ngDevMode ? [{ debugName: "path" }] : /* istanbul ignore next */ []);
1805
+ source = input(null, ...ngDevMode ? [{ debugName: "source" }] : /* istanbul ignore next */ []);
1806
+ words = input(null, ...ngDevMode ? [{ debugName: "words" }] : /* istanbul ignore next */ []);
1807
+ maxSide = input(880, ...ngDevMode ? [{ debugName: "maxSide" }] : /* istanbul ignore next */ []);
1808
+ enter = output();
1809
+ out = output();
1810
+ done = output();
1811
+ tapped = output();
1812
+ given = inject(CONTEXT_CUBE_SOURCE, { optional: true });
1813
+ givenWords = inject(CONTEXT_CUBE_WORDS, { optional: true });
1814
+ busy = signal(null, ...ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []);
1815
+ again = signal(0, ...ngDevMode ? [{ debugName: "again" }] : /* istanbul ignore next */ []);
1816
+ from = computed(() => {
1817
+ const s = this.source() ?? this.given;
1818
+ if (!s) throw new Error("cube-context: provide CONTEXT_CUBE_SOURCE or pass [source]");
1819
+ return s;
1820
+ }, ...ngDevMode ? [{ debugName: "from" }] : /* istanbul ignore next */ []);
1821
+ where = computed(() => this.path().join("\0"), ...ngDevMode ? [{ debugName: "where" }] : /* istanbul ignore next */ []);
1822
+ level = computed(() => {
1823
+ this.again();
1824
+ return this.from().level(this.held(), this.path());
1825
+ }, ...ngDevMode ? [{ debugName: "level" }] : /* istanbul ignore next */ []);
1826
+ tiles = computed(() => this.level() ?? [], ...ngDevMode ? [{ debugName: "tiles" }] : /* istanbul ignore next */ []);
1827
+ adds = computed(() => this.tiles().some((t) => !!t.adds), ...ngDevMode ? [{ debugName: "adds" }] : /* istanbul ignore next */ []);
1828
+ keyOf = (t) => t.key;
1829
+ inUseWord = computed(() => (this.words() ?? this.givenWords)?.inUse ?? null, ...ngDevMode ? [{ debugName: "inUseWord" }] : /* istanbul ignore next */ []);
1830
+ iconOf = contextIcon;
1831
+ constructor() {
1832
+ effect(() => {
1833
+ if (this.level() === null) untracked(() => this.out.emit());
1834
+ });
1835
+ effect(() => {
1836
+ this.where();
1837
+ this.held();
1838
+ untracked(() => this.busy.set(null));
1839
+ });
1840
+ }
1841
+ async tap(tile, element) {
1842
+ if (this.busy() !== null) return;
1843
+ if (element) this.tapped.emit({
1844
+ tile,
1845
+ element
1846
+ });
1847
+ const held = this.held();
1848
+ const path = this.path();
1849
+ const where = this.where();
1850
+ const here = () => this.held() === held && this.where() === where;
1851
+ this.busy.set(tile.key);
1852
+ try {
1853
+ const picked = await this.from().pick(held, path, tile);
1854
+ if (!here()) return;
1855
+ switch (picked.kind) {
1856
+ case "enter":
1857
+ this.enter.emit(picked.path);
1858
+ break;
1859
+ case "done":
1860
+ this.done.emit(tile);
1861
+ break;
1862
+ case "out": this.out.emit();
1863
+ }
1864
+ } finally {
1865
+ if (here()) this.busy.set(null);
1866
+ this.again.update((n) => n + 1);
1867
+ }
1868
+ }
1869
+ static ɵfac = i0.ɵɵngDeclareFactory({
1870
+ minVersion: "12.0.0",
1871
+ version: "22.2.4",
1872
+ ngImport: i0,
1873
+ type: CubeContext,
1874
+ deps: [],
1875
+ target: i0.ɵɵFactoryTarget.Component
1876
+ });
1877
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1878
+ minVersion: "17.0.0",
1879
+ version: "22.2.4",
1880
+ type: CubeContext,
1881
+ isStandalone: true,
1882
+ selector: "cube-context",
1883
+ inputs: {
1884
+ held: {
1885
+ classPropertyName: "held",
1886
+ publicName: "held",
1887
+ isSignal: true,
1888
+ isRequired: true,
1889
+ transformFunction: null
1890
+ },
1891
+ path: {
1892
+ classPropertyName: "path",
1893
+ publicName: "path",
1894
+ isSignal: true,
1895
+ isRequired: false,
1896
+ transformFunction: null
1897
+ },
1898
+ source: {
1899
+ classPropertyName: "source",
1900
+ publicName: "source",
1901
+ isSignal: true,
1902
+ isRequired: false,
1903
+ transformFunction: null
1904
+ },
1905
+ words: {
1906
+ classPropertyName: "words",
1907
+ publicName: "words",
1908
+ isSignal: true,
1909
+ isRequired: false,
1910
+ transformFunction: null
1911
+ },
1912
+ maxSide: {
1913
+ classPropertyName: "maxSide",
1914
+ publicName: "maxSide",
1915
+ isSignal: true,
1916
+ isRequired: false,
1917
+ transformFunction: null
1918
+ }
1919
+ },
1920
+ outputs: {
1921
+ enter: "enter",
1922
+ out: "out",
1923
+ done: "done",
1924
+ tapped: "tapped"
1925
+ },
1926
+ ngImport: i0,
1927
+ template: `
1928
+ <cube-square
1929
+ [tiles]="tiles()"
1930
+ [dashed]="adds()"
1931
+ [maxSide]="maxSide()"
1932
+ [keyOf]="keyOf"
1933
+ [class.cc-adds]="adds()"
1934
+ >
1935
+ <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>
1958
+ }
1959
+ </button>
1960
+ </ng-template>
1961
+ </cube-square>
1962
+ `,
1963
+ 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;-webkit-line-clamp:2;line-clamp:2;overflow:hidden;overflow-wrap:anywhere}.cc-t{font-size:17px;font-weight:700;line-height:1.2}.cc-m{font-size:13px;line-height:1.3;color:var(--cube-context-quiet, #5d6a64)}.cc-tick{font-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:26px}.cc-l0 .cc-m{font-size:16px}.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:14px}.cc-l2 .cc-m{font-size:12px}.cc-tile.cc-l3{border-radius:12px;padding:6px 4px;gap:3px}.cc-l3 .cc-t{font-size:12px}.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
+ dependencies: [
1966
+ {
1967
+ kind: "component",
1968
+ type: CubeIcon,
1969
+ selector: "cube-icon",
1970
+ inputs: ["icon", "inUse"]
1971
+ },
1972
+ {
1973
+ kind: "component",
1974
+ type: CubeSquare,
1975
+ selector: "cube-square",
1976
+ inputs: [
1977
+ "tiles",
1978
+ "view",
1979
+ "maxSide",
1980
+ "listRow",
1981
+ "dashed",
1982
+ "keyOf",
1983
+ "turning",
1984
+ "turnBelow",
1985
+ "across",
1986
+ "isOwn",
1987
+ "nudgeKey"
1988
+ ]
1989
+ },
1990
+ {
1991
+ kind: "directive",
1992
+ type: CubeSquareTile,
1993
+ selector: "ng-template[cubeSquareTile]",
1994
+ inputs: ["cubeSquareTile"]
1995
+ }
1996
+ ],
1997
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
1998
+ });
1999
+ };
2000
+ i0.ɵɵngDeclareClassMetadata({
2001
+ minVersion: "12.0.0",
2002
+ version: "22.2.4",
2003
+ ngImport: i0,
2004
+ type: CubeContext,
2005
+ decorators: [{
2006
+ type: Component,
2007
+ args: [{
2008
+ selector: "cube-context",
2009
+ imports: [
2010
+ CubeIcon,
2011
+ CubeSquare,
2012
+ CubeSquareTile
2013
+ ],
2014
+ template: `
2015
+ <cube-square
2016
+ [tiles]="tiles()"
2017
+ [dashed]="adds()"
2018
+ [maxSide]="maxSide()"
2019
+ [keyOf]="keyOf"
2020
+ [class.cc-adds]="adds()"
2021
+ >
2022
+ <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>
2045
+ }
2046
+ </button>
2047
+ </ng-template>
2048
+ </cube-square>
2049
+ `,
2050
+ 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;-webkit-line-clamp:2;line-clamp:2;overflow:hidden;overflow-wrap:anywhere}.cc-t{font-size:17px;font-weight:700;line-height:1.2}.cc-m{font-size:13px;line-height:1.3;color:var(--cube-context-quiet, #5d6a64)}.cc-tick{font-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:26px}.cc-l0 .cc-m{font-size:16px}.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:14px}.cc-l2 .cc-m{font-size:12px}.cc-tile.cc-l3{border-radius:12px;padding:6px 4px;gap:3px}.cc-l3 .cc-t{font-size:12px}.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
+ }]
2053
+ }],
2054
+ ctorParameters: () => [],
2055
+ propDecorators: {
2056
+ held: [{
2057
+ type: i0.Input,
2058
+ args: [{
2059
+ isSignal: true,
2060
+ alias: "held",
2061
+ required: true
2062
+ }]
2063
+ }],
2064
+ path: [{
2065
+ type: i0.Input,
2066
+ args: [{
2067
+ isSignal: true,
2068
+ alias: "path",
2069
+ required: false
2070
+ }]
2071
+ }],
2072
+ source: [{
2073
+ type: i0.Input,
2074
+ args: [{
2075
+ isSignal: true,
2076
+ alias: "source",
2077
+ required: false
2078
+ }]
2079
+ }],
2080
+ words: [{
2081
+ type: i0.Input,
2082
+ args: [{
2083
+ isSignal: true,
2084
+ alias: "words",
2085
+ required: false
2086
+ }]
2087
+ }],
2088
+ maxSide: [{
2089
+ type: i0.Input,
2090
+ args: [{
2091
+ isSignal: true,
2092
+ alias: "maxSide",
2093
+ required: false
2094
+ }]
2095
+ }],
2096
+ enter: [{
2097
+ type: i0.Output,
2098
+ args: ["enter"]
2099
+ }],
2100
+ out: [{
2101
+ type: i0.Output,
2102
+ args: ["out"]
2103
+ }],
2104
+ done: [{
2105
+ type: i0.Output,
2106
+ args: ["done"]
2107
+ }],
2108
+ tapped: [{
2109
+ type: i0.Output,
2110
+ args: ["tapped"]
2111
+ }]
2112
+ }
2113
+ });
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 };
2115
+
2116
+ //# sourceMappingURL=selimssevgi-cube-design-angular.mjs.map