@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,750 @@
1
+ import * as i0 from "@angular/core";
2
+ import { InjectionToken, TemplateRef } from "@angular/core";
3
+ /**
4
+ * drawing a cube of small cubes in isometric view: the left, right and top faces, each split into
5
+ * n × n stickers. a sticker is coloured by a piece, or pale while nothing is known for it.
6
+ *
7
+ * the same projection anlat, mosaic and cubes drew by hand before this package (cube design,
8
+ * `07-visual.md`). pure functions, no angular: they can be used anywhere.
9
+ */
10
+ /** The side of the smallest cube that holds this many pieces, up to 7 × 7 × 7. */
11
+ export declare function sizeFor(count: number): number;
12
+ export type Face = 'top' | 'left' | 'right';
13
+ export interface Sticker {
14
+ face: Face;
15
+ /** The sticker's square, as SVG points. */
16
+ outer: string;
17
+ /** The coloured inset inside it. */
18
+ inner: string;
19
+ colour: string | null;
20
+ }
21
+ export interface Drawing {
22
+ width: number;
23
+ height: number;
24
+ viewBox: string;
25
+ /** The faint bigger cube it can grow into, as dashed outlines. */
26
+ hint: string[];
27
+ stickers: Sticker[];
28
+ }
29
+ export interface DrawOptions {
30
+ /** Show the next size as a faint cube behind (only while it is small). */
31
+ hint?: boolean;
32
+ /** A value: one colour on every sticker. */
33
+ whole?: boolean;
34
+ /** How many times it has been turned: shifts the colours round the stickers. */
35
+ rot?: number;
36
+ }
37
+ /** A cube for `count` pieces, `width` wide, coloured by `colours` in sticker order. */
38
+ export declare function drawCube(count: number, colours: (string | null)[], width: number, options?: DrawOptions): Drawing;
39
+ /**
40
+ * a cube of small cubes, one per piece: coloured where something is known, pale where not.
41
+ *
42
+ * its look comes from css variables, so each app keeps its own dialect (the light one of cubes and
43
+ * anlat, the dark one of mosaic). every variable has a light fallback, so it draws without any;
44
+ * `tokens/light.css` and `tokens/dark.css` set them all.
45
+ */
46
+ export declare class CubePicture {
47
+ /** how many pieces: the cube is the smallest n × n × n that holds them. */
48
+ readonly count: import("@angular/core").InputSignal<number>;
49
+ /** the stickers' colours in order; null is a sticker not known yet. */
50
+ readonly colours: import("@angular/core").InputSignal<(string | null)[]>;
51
+ /** the width in pixels. */
52
+ readonly width: import("@angular/core").InputSignal<number>;
53
+ /** show the bigger cube it can grow into, faintly, while it is small. */
54
+ readonly hint: import("@angular/core").InputSignal<boolean>;
55
+ /** one colour on every sticker (a value). */
56
+ readonly whole: import("@angular/core").InputSignal<boolean>;
57
+ /** how many times it was turned: shifts the colours round the stickers. */
58
+ readonly rot: import("@angular/core").InputSignal<number>;
59
+ protected readonly drawing: import("@angular/core").Signal<import("@selimssevgi/cube-design-angular").Drawing>;
60
+ static ɵfac: i0.ɵɵFactoryDeclaration<CubePicture, never>;
61
+ static ɵcmp: i0.ɵɵComponentDeclaration<CubePicture, "cube-picture", never, {
62
+ "count": {
63
+ "alias": "count";
64
+ "required": false;
65
+ "isSignal": true;
66
+ };
67
+ "colours": {
68
+ "alias": "colours";
69
+ "required": false;
70
+ "isSignal": true;
71
+ };
72
+ "width": {
73
+ "alias": "width";
74
+ "required": false;
75
+ "isSignal": true;
76
+ };
77
+ "hint": {
78
+ "alias": "hint";
79
+ "required": false;
80
+ "isSignal": true;
81
+ };
82
+ "whole": {
83
+ "alias": "whole";
84
+ "required": false;
85
+ "isSignal": true;
86
+ };
87
+ "rot": {
88
+ "alias": "rot";
89
+ "required": false;
90
+ "isSignal": true;
91
+ };
92
+ }, {}, never, never, true, never>;
93
+ }
94
+ /** what a hold reports: how it came, on which element, and the event that ended it. */
95
+ export interface CubeHeld {
96
+ /** `press`: a finger, pen or the main mouse button stayed put; `menu`: a contextmenu event. */
97
+ via: 'press' | 'menu';
98
+ /** the element holding the directive. */
99
+ element: HTMLElement;
100
+ /** the pointerdown that was held, or the contextmenu. */
101
+ event: Event;
102
+ }
103
+ /** how long a press is held before it is a hold (cubes' value; each app may set its own). */
104
+ export declare const CUBE_HOLD_MS = 520;
105
+ /** how far a finger may move while pressing before it is a drag, in pixels. */
106
+ export declare const CUBE_HOLD_SLOP = 10;
107
+ /**
108
+ * pressing and holding a piece (principle 31): a long press, a right click or the menu key raise
109
+ * one `cubeHeld`. a second finger (a pinch) or a drag never does, and the click that follows a hold
110
+ * is swallowed so the piece does not also open. what a hold opens is the app's.
111
+ *
112
+ * it only reports: it never stops or prevents the pointer events, so a swipe or a pinch on the same
113
+ * element keeps working.
114
+ */
115
+ export declare class CubeHold {
116
+ /** no hold at all: the listeners do nothing and the browser's own menu stays. */
117
+ readonly cubeHoldDisabled: import("@angular/core").InputSignal<boolean>;
118
+ /** how long a press is held before it is a hold, in milliseconds. */
119
+ readonly cubeHoldMs: import("@angular/core").InputSignal<number>;
120
+ /** how far the press may move before it is a drag instead, in pixels. */
121
+ readonly cubeHoldSlop: import("@angular/core").InputSignal<number>;
122
+ /** a short buzz (`navigator.vibrate(12)`) when it holds, where the device can. */
123
+ readonly cubeHoldBuzz: import("@angular/core").InputSignal<boolean>;
124
+ /** the piece was held. */
125
+ readonly cubeHeld: import("@angular/core").OutputEmitterRef<CubeHeld>;
126
+ private readonly element;
127
+ private timer;
128
+ /** where the press started; null while nothing may become a hold. */
129
+ private start;
130
+ /** the pointers down on the element: two or more are a pinch. */
131
+ private readonly pointers;
132
+ /** this press already held, so the phone's own contextmenu after it is not a second hold. */
133
+ protected pressFired: boolean;
134
+ /** a hold swallows the one click that follows it. */
135
+ protected swallow: boolean;
136
+ constructor();
137
+ protected press(e: PointerEvent): void;
138
+ protected moved(e: PointerEvent): void;
139
+ protected lift(e: PointerEvent): void;
140
+ /** a right click, a phone's own long press, the menu key or shift+f10. */
141
+ protected menu(e: Event): void;
142
+ private fire;
143
+ private cancel;
144
+ static ɵfac: i0.ɵɵFactoryDeclaration<CubeHold, never>;
145
+ static ɵdir: i0.ɵɵDirectiveDeclaration<CubeHold, "[cubeHold]", never, {
146
+ "cubeHoldDisabled": {
147
+ "alias": "cubeHoldDisabled";
148
+ "required": false;
149
+ "isSignal": true;
150
+ };
151
+ "cubeHoldMs": {
152
+ "alias": "cubeHoldMs";
153
+ "required": false;
154
+ "isSignal": true;
155
+ };
156
+ "cubeHoldSlop": {
157
+ "alias": "cubeHoldSlop";
158
+ "required": false;
159
+ "isSignal": true;
160
+ };
161
+ "cubeHoldBuzz": {
162
+ "alias": "cubeHoldBuzz";
163
+ "required": false;
164
+ "isSignal": true;
165
+ };
166
+ }, {
167
+ "cubeHeld": "cubeHeld";
168
+ }, never, never, true, never>;
169
+ }
170
+ /** the views a cube can be shown in, each drawn as its own shape. */
171
+ export type CubeIconView = 'square' | 'one' | 'two' | 'three' | 'four' | 'grid-4x5' | 'grid-3x6';
172
+ /** what a tile of a cube the app keeps is about (a context cube's parts and their choices). */
173
+ export type CubeIconName = 'names' | 'name' | 'change' | 'move' | 'place' | 'whose' | 'library' | 'mine' | 'shown' | 'hidden' | 'view' | 'sort' | 'kept' | 'face' | 'added' | 'up' | 'down' | 'plus' | CubeIconView;
174
+ /** every icon, in the order above. */
175
+ export declare const CUBE_ICON_NAMES: readonly CubeIconName[];
176
+ export interface CubeIconCell {
177
+ x: number;
178
+ y: number;
179
+ w: number;
180
+ h: number;
181
+ }
182
+ /**
183
+ * the cells a view's icon draws in its 24 × 24 box, or null when the icon is not a view. one across
184
+ * is a list, so its cells are rows.
185
+ */
186
+ export declare function cubeIconCells(icon: CubeIconName): CubeIconCell[] | null;
187
+ /**
188
+ * an icon on a tile of a cube the app keeps (a context cube and its parts), in place of a small
189
+ * cube: such cubes hold no pieces, so their tiles show what they are about.
190
+ *
191
+ * its look comes from css variables (`--cube-icon-*`), each with a light fallback; `tokens/light.css`
192
+ * and `tokens/dark.css` set them all. it says nothing: the tile's words come from the app.
193
+ */
194
+ export declare class CubeIcon {
195
+ /** what the tile is about. */
196
+ readonly icon: import("@angular/core").InputSignal<CubeIconName>;
197
+ /** the one in use among its siblings: drawn in the in-use colour. */
198
+ readonly inUse: import("@angular/core").InputSignal<boolean>;
199
+ protected readonly cells: import("@angular/core").Signal<CubeIconCell[] | null>;
200
+ static ɵfac: i0.ɵɵFactoryDeclaration<CubeIcon, never>;
201
+ static ɵcmp: i0.ɵɵComponentDeclaration<CubeIcon, "cube-icon", never, {
202
+ "icon": {
203
+ "alias": "icon";
204
+ "required": true;
205
+ "isSignal": true;
206
+ };
207
+ "inUse": {
208
+ "alias": "inUse";
209
+ "required": false;
210
+ "isSignal": true;
211
+ };
212
+ }, {}, never, never, true, never>;
213
+ }
214
+ /** the ways a cube's square can be laid out: the square first (cubes decision 23), then the rest. */
215
+ export type ViewKey = 'square' | 'one' | 'two' | 'three' | 'four' | 'grid-4x5' | 'grid-3x6';
216
+ /** every view, in the order they are offered. */
217
+ export declare const VIEW_KEYS: readonly ViewKey[];
218
+ export declare const isView: (v: unknown) => v is ViewKey;
219
+ /** columns and rows of a layout holding this many; every row is full, open places outlined. */
220
+ export interface Grid {
221
+ cols: number;
222
+ rows: number;
223
+ }
224
+ export declare function gridFor(view: ViewKey, count: number): Grid;
225
+ /** up is the face's own order (a to z, oldest first, its first colour first); down the other way. */
226
+ export type Direction = 'up' | 'down';
227
+ /** what an item is sorted by: text, a number, or nothing found (not known yet). */
228
+ export type SortValue = string | number | null | undefined;
229
+ /**
230
+ * items in the order a sort asks for. `by` reads what each item is sorted by; text is compared as
231
+ * a person reads it, numbers as numbers. an item with nothing found is not known yet and comes last
232
+ * in both directions (empty is the point, never hidden). ties keep the items' own order.
233
+ */
234
+ export declare function sortItems<T>(items: readonly T[], by: (item: T) => SortValue, dir: Direction): T[];
235
+ /**
236
+ * the parts a context cube can have. the seven are the ones cubes found; an app may add its own,
237
+ * any string, and they come after the known ones.
238
+ */
239
+ export type ContextPartKey = 'names' | 'change' | 'view' | 'sort' | 'move' | 'whose' | 'hide' | (string & {});
240
+ /** cubes' rows: how it is called (names, change), how it is shown (view, sort), what i do with it. */
241
+ export declare const CONTEXT_PART_ORDER: readonly ContextPartKey[];
242
+ /** the parts in their rows; parts an app added come last, in the order it gave them. twice is once. */
243
+ export declare function orderParts(parts: readonly ContextPartKey[]): ContextPartKey[];
244
+ /** one tile of a level. its title and line always come from the app. */
245
+ export interface ContextTile<D = unknown> {
246
+ /** unique among its level. */
247
+ key: string;
248
+ title: string;
249
+ line?: string | null;
250
+ /** the icon's name: a part, a view key, a direction, or one of the app's. */
251
+ icon: string;
252
+ /** the one in use among its siblings (the name in use, shown or hidden, the view). */
253
+ inUse?: boolean;
254
+ /** drawn quietly: something that can be read but not used. */
255
+ pale?: boolean;
256
+ /** the plus: keeps something new beside the others, always last. */
257
+ adds?: boolean;
258
+ /** what the tile stands for, for the app's own `pick`. */
259
+ data?: D;
260
+ }
261
+ /** where in the context cube one is: [] is its top (its parts), ['names'] a part, ['sort', by] deeper. */
262
+ export type ContextPath = readonly string[];
263
+ /** what a pick does: walk into a deeper level, end the journey, step one level out, or nothing. */
264
+ export type ContextPick = {
265
+ kind: 'enter';
266
+ path: string[];
267
+ } | {
268
+ kind: 'done';
269
+ } | {
270
+ kind: 'out';
271
+ } | {
272
+ kind: 'stay';
273
+ };
274
+ /** what an app gives for its own held type `T`: a piece, a cube, a to-do, a level. */
275
+ export interface ContextCubeSource<T = unknown> {
276
+ /** the parts this held thing has, in any order (`orderParts` puts them in rows). */
277
+ parts(held: T): ContextPartKey[];
278
+ /** the tiles of one level, or null when that path does not exist for it. */
279
+ level(held: T, path: ContextPath): ContextTile[] | null;
280
+ /** a tile was tapped at that path. */
281
+ pick(held: T, path: ContextPath, tile: ContextTile): ContextPick | Promise<ContextPick>;
282
+ }
283
+ /** a title and its line, in the app's language. */
284
+ export interface ContextWord {
285
+ title: string;
286
+ line?: string | null;
287
+ }
288
+ /** a name a piece has had, as the names level lists it. */
289
+ export interface ContextName {
290
+ name: string;
291
+ /** the one in use. */
292
+ current: boolean;
293
+ /** the day it was given, as the app keeps it. */
294
+ on?: string | null;
295
+ /** whose hands gave it. */
296
+ by?: string | null;
297
+ /** whether it was ever in use, or only kept beside. */
298
+ used?: boolean;
299
+ }
300
+ /** every word the context cube shows. the package ships none. */
301
+ export interface ContextWords {
302
+ /** each part's title and line; a part with no word has an empty title. */
303
+ parts: Partial<Record<ContextPartKey, ContextWord>>;
304
+ /** each view's name. */
305
+ views: Partial<Record<ViewKey, ContextWord>>;
306
+ /** the two directions of a sort, when a sort option has none of its own. */
307
+ directions: Record<Direction, ContextWord>;
308
+ /** the two pieces of hide. */
309
+ hide: {
310
+ shown: ContextWord;
311
+ hidden: ContextWord;
312
+ };
313
+ /** the plus among the names, and the line under each name (its day and hands). */
314
+ names: {
315
+ another: ContextWord;
316
+ line?: (name: ContextName) => string | null;
317
+ };
318
+ /** said on the one in use, when the app wants it said. */
319
+ inUse?: string;
320
+ }
321
+ /** the app's source of context cubes. */
322
+ export declare const CONTEXT_CUBE_SOURCE: InjectionToken<ContextCubeSource<any>>;
323
+ /** the app's words for the context cube. */
324
+ export declare const CONTEXT_CUBE_WORDS: InjectionToken<ContextWords>;
325
+ /** what the top level shows of a part now: the view in use, the name, shown or hidden. */
326
+ export interface PartNow {
327
+ line?: string | null;
328
+ icon?: string;
329
+ }
330
+ /**
331
+ * the icon a part's tile shows when the app gives none of what it holds now. most parts are drawn
332
+ * by their own name; hide has no icon of its own and shows shown (the eye), since a piece is in
333
+ * sight until it is hidden. an app passes `now.hide.icon` (`shown` or `hidden`) to say which.
334
+ */
335
+ export declare const PART_ICONS: Partial<Record<ContextPartKey, string>>;
336
+ /** the top of a context cube: its parts in rows, each with its word and, when given, what it holds now. */
337
+ export declare function partsLevel(parts: readonly ContextPartKey[], words: ContextWords, now?: Partial<Record<ContextPartKey, PartNow>>): ContextTile<ContextPartKey>[];
338
+ /** what a names tile holds: a name, or the plus. */
339
+ export type NamesData = {
340
+ name: ContextName;
341
+ } | {
342
+ another: true;
343
+ };
344
+ /**
345
+ * every name it has had: the one in use first, then the rest newest first (the names come oldest
346
+ * first, as they were given). when the app allows it, a plus keeps a new one beside it without
347
+ * using it.
348
+ */
349
+ export declare function namesLevel(names: readonly ContextName[], words: ContextWords, opts?: {
350
+ canAdd?: boolean;
351
+ }): ContextTile<NamesData>[];
352
+ /** hide: a cube of two pieces, shown and hidden, one in use; `data` is whether it hides. */
353
+ export declare function hideLevel(hidden: boolean, words: ContextWords): ContextTile<boolean>[];
354
+ /**
355
+ * view: every way to lay the cube out, its icon its own shape. the one in use says so in place of
356
+ * its line, so both fit a small tile.
357
+ */
358
+ export declare function viewLevel(now: ViewKey, words: ContextWords, views?: readonly ViewKey[]): ContextTile<ViewKey>[];
359
+ /** what a cube can be sorted by, given by the app: as kept, names, when added, each face. */
360
+ export interface SortOption {
361
+ /** the app's own key: `kept`, `names`, `added`, a face's id. */
362
+ by: string;
363
+ title: string;
364
+ line?: string | null;
365
+ icon: string;
366
+ /** false for an order with no two ways (as kept): picking it uses it at once. */
367
+ directed?: boolean;
368
+ /** this option's two directions in its own words (a to z, oldest first, small first). */
369
+ up?: ContextWord;
370
+ down?: ContextWord;
371
+ }
372
+ /** a sort in use. */
373
+ export interface SortNow {
374
+ by: string;
375
+ dir: Direction;
376
+ }
377
+ /** the two directions of an option, in its own words or else the app's general ones. */
378
+ export declare function directionWords(option: SortOption, words: ContextWords): Record<Direction, ContextWord>;
379
+ /**
380
+ * sort: the options, the one in use marked; a directed option in use says its direction in place
381
+ * of its line. picking a directed option walks into its two directions (`sortDirectionsLevel`).
382
+ */
383
+ export declare function sortLevel(options: readonly SortOption[], now: SortNow, words: ContextWords): ContextTile<SortOption>[];
384
+ /**
385
+ * inside one sort option: its two directions, up first. whatever direction, an item with nothing
386
+ * found is not known yet and comes last (`sortItems`); the words say so in their lines.
387
+ */
388
+ export declare function sortDirectionsLevel(option: SortOption, now: SortNow, words: ContextWords): ContextTile<Direction>[];
389
+ /** how close a square's places are: from one big tile (0) to only its icon or small cube (4). */
390
+ export type SquareLevel = 0 | 1 | 2 | 3 | 4;
391
+ /** cubes' steps (`levelFor`), by a cell's side in px: a tile says less as the square fills. */
392
+ export declare function squareLevelFor(cell: number): SquareLevel;
393
+ /** places still open keep their outline; the fuller the square, the closer its places. */
394
+ export declare function squareGap(n: number): number;
395
+ /** the room a square may take: the width it is given, and the window's height for the square. */
396
+ export interface SquareRoom {
397
+ width: number;
398
+ /** the window's height less a head (48 px); only the square view is held to it, so it is seen whole. */
399
+ tall: number;
400
+ }
401
+ /** one square laid out: its columns and rows, its size, and how much each tile says. */
402
+ export interface SquareLayout {
403
+ cols: number;
404
+ rows: number;
405
+ /** the square's width and height, in px. */
406
+ width: number;
407
+ height: number;
408
+ gap: number;
409
+ /** a cell's width, in px. */
410
+ cell: number;
411
+ /** a row's height: the cell, or a list row's own height in one across. */
412
+ rowHeight: number;
413
+ level: SquareLevel;
414
+ /** one across is a list: each row as tall as a tile with its name and line, not a square. */
415
+ list: boolean;
416
+ /** places not filled, outlined; they only ever finish the last row. */
417
+ open: number;
418
+ }
419
+ /** the largest side a square takes on a wide screen, in px (cubes', mosaic's). */
420
+ export declare const SQUARE_MAX_SIDE = 880;
421
+ /** a row's height in one across, the list (cubes'). */
422
+ export declare const SQUARE_LIST_ROW = 76;
423
+ /**
424
+ * how this many tiles are laid out in a view, in this much room. the square view is the smallest
425
+ * n × n that holds them, as wide as the room and the window's height allow; the other views are as
426
+ * long as they need and scroll. open places only finish the last row, so a view never draws a whole
427
+ * empty row (decision of 2026-11-01): three pieces in 4 × 5 are one row of four. the square keeps
428
+ * its own rule, its size coming from the pieces.
429
+ */
430
+ export declare function squareLayout(view: ViewKey, count: number, room: SquareRoom, opts?: {
431
+ maxSide?: number;
432
+ listRow?: number;
433
+ }): SquareLayout;
434
+ /** what a tile's template is given. */
435
+ export interface CubeSquareTileContext<T> {
436
+ /** the tile, as the app gave it. */
437
+ $implicit: T;
438
+ index: number;
439
+ /** how much it says (0 everything … 4 only its icon or small cube). */
440
+ level: SquareLevel;
441
+ /** its cell's width and height, in px, for a picture sized to it. */
442
+ cell: number;
443
+ rowHeight: number;
444
+ /** one across: a list row, not a square cell. */
445
+ list: boolean;
446
+ }
447
+ /**
448
+ * `<ng-template cubeSquareTile let-tile let-level="level">`: how the app draws one tile inside a
449
+ * `<cube-square>`. the square only places it; the template fills its cell.
450
+ */
451
+ export declare class CubeSquareTile<T> {
452
+ readonly template: TemplateRef<CubeSquareTileContext<T>>;
453
+ /** the tiles' type, for the template's checks: `[cubeSquareTile]="tiles()"`. */
454
+ readonly cubeSquareTile: import("@angular/core").InputSignal<"" | readonly T[] | undefined>;
455
+ static ngTemplateContextGuard<T>(_dir: CubeSquareTile<T>, ctx: unknown): ctx is CubeSquareTileContext<T>;
456
+ static ɵfac: i0.ɵɵFactoryDeclaration<CubeSquareTile<any>, never>;
457
+ static ɵdir: i0.ɵɵDirectiveDeclaration<CubeSquareTile<any>, "ng-template[cubeSquareTile]", never, {
458
+ "cubeSquareTile": {
459
+ "alias": "cubeSquareTile";
460
+ "required": false;
461
+ "isSignal": true;
462
+ };
463
+ }, {}, never, never, true, never>;
464
+ }
465
+ /** the front a view keeps when its rows turn: the square's `across` × `across`, a fixed grid's page. */
466
+ export declare function turningFront(view: ViewKey, across?: number): {
467
+ cols: number;
468
+ rows: number;
469
+ } | null;
470
+ /** narrower than this (a phone), a full square turns its rows, when `turning` is on. */
471
+ export declare const TURNING_BELOW = 640;
472
+ /** turns after which a row with more stops nudging when the square opens. */
473
+ export declare const TURNING_NUDGE_UNTIL = 3;
474
+ /**
475
+ * `<cube-square [tiles] [view]>`: the tiles an app gives, laid out as a complete square or another
476
+ * view, each drawn by the app's `cubeSquareTile` template and told its level. it measures its own
477
+ * width (up to the window's height for the square, at most `maxSide`), outlines its open places and
478
+ * zooms a step when it has to hold more. it says no word and draws no tile. its look is css
479
+ * variables (`--cube-square-*`), set in both token files.
480
+ */
481
+ export declare class CubeSquare<T> {
482
+ /** the tiles, in the order they are placed. */
483
+ readonly tiles: import("@angular/core").InputSignal<readonly T[]>;
484
+ /** how they are laid out: the square (the default), one to four across, 4 × 5, 3 × 6. */
485
+ readonly view: import("@angular/core").InputSignal<ViewKey>;
486
+ /** the largest side the square takes on a wide screen, in px. */
487
+ readonly maxSide: import("@angular/core").InputSignal<number>;
488
+ /** a row's height in one across, in px. */
489
+ readonly listRow: import("@angular/core").InputSignal<number>;
490
+ /** open places dashed, where something could come (a cube of mine, a level with a plus). */
491
+ readonly dashed: import("@angular/core").InputSignal<boolean>;
492
+ /** what keeps a tile the same tile across changes, so it is not drawn anew; its place by default. */
493
+ readonly keyOf: import("@angular/core").InputSignal<(tile: T, index: number) => unknown>;
494
+ /**
495
+ * turning rows (selim: row rotation, first in mosaic's todarch cube), off unless the app turns
496
+ * them on: on a phone, a square or fixed grid holding more than its front keeps its size, and each
497
+ * row becomes a band of four sides that a finger (or the arrow keys on a focused row) turns, bringing
498
+ * in the pieces past the front (`turningRows`).
499
+ */
500
+ readonly turning: import("@angular/core").InputSignal<boolean>;
501
+ /** rows turn only on a screen narrower than this, in px; a wide screen shows the whole square. */
502
+ readonly turnBelow: import("@angular/core").InputSignal<number>;
503
+ /** the square's front when its rows turn: `across` × `across` (3 × 3). */
504
+ readonly across: import("@angular/core").InputSignal<number>;
505
+ /** which tile is my own box: it keeps the front's last place while the rows turn. */
506
+ readonly isOwn: import("@angular/core").InputSignal<((tile: T) => boolean) | null>;
507
+ /** where the turns are counted on this phone (localStorage), so the nudge stops after a few. */
508
+ readonly nudgeKey: import("@angular/core").InputSignal<string | null>;
509
+ protected readonly tile: import("@angular/core").Signal<CubeSquareTile<T> | undefined>;
510
+ private readonly grid;
511
+ /** the host's width and the window's height, followed as either changes. */
512
+ private readonly room;
513
+ /** the layout now: columns, rows, size, gap, level and open places. */
514
+ /** the front kept while the rows turn, or null when they do not (off, a wide screen, all fit). */
515
+ readonly front: import("@angular/core").Signal<{
516
+ cols: number;
517
+ rows: number;
518
+ } | null>;
519
+ /** the layout now: columns, rows, size, gap, level and open places. */
520
+ readonly layout: import("@angular/core").Signal<SquareLayout>;
521
+ /** the turning rows: rows × four sides × cols, and how many sides of each hold something. */
522
+ protected readonly rings: import("@angular/core").Signal<import("@selimssevgi/cube-design-angular").TurningRows<T> | null>;
523
+ private readonly indexes;
524
+ protected indexOf(t: T): number;
525
+ protected readonly openPlaces: import("@angular/core").Signal<number[]>;
526
+ /** each row's turn in degrees, and the row a finger is turning now. */
527
+ private readonly angles;
528
+ protected readonly dragging: import("@angular/core").WritableSignal<number | null>;
529
+ /** turns that should not animate (reduced motion). */
530
+ protected readonly still: import("@angular/core").WritableSignal<boolean>;
531
+ protected readonly nudging: import("@angular/core").WritableSignal<boolean>;
532
+ private drag;
533
+ /** fingers on the square now: a second one is a pinch, never a turn. */
534
+ private readonly fingers;
535
+ private suppressClick;
536
+ private nudged;
537
+ private readonly timers;
538
+ private readonly host;
539
+ protected angle(row: number): number;
540
+ /** the side of a row facing me (0 to 3). */
541
+ protected sideOf(row: number): number;
542
+ private filled;
543
+ protected down(row: number, e: PointerEvent): void;
544
+ protected move(row: number, e: PointerEvent): void;
545
+ protected up(row: number, e: PointerEvent): void;
546
+ private cancelDrag;
547
+ /** turns a row `steps` sides from `base`, passing the sides with nothing on them. */
548
+ private settle;
549
+ /** the arrow keys on a focused row turn it, so a keyboard reaches every piece too. */
550
+ protected key(row: number, e: KeyboardEvent): void;
551
+ private focusedColumn;
552
+ /** after a turn by the keys, focus goes to the same place on the side now facing me. */
553
+ private focusSide;
554
+ /** the nudge: rows with more turn a little and back, one after another, until i turned a few. */
555
+ private nudge;
556
+ constructor();
557
+ static ɵfac: i0.ɵɵFactoryDeclaration<CubeSquare<any>, never>;
558
+ static ɵcmp: i0.ɵɵComponentDeclaration<CubeSquare<any>, "cube-square", never, {
559
+ "tiles": {
560
+ "alias": "tiles";
561
+ "required": true;
562
+ "isSignal": true;
563
+ };
564
+ "view": {
565
+ "alias": "view";
566
+ "required": false;
567
+ "isSignal": true;
568
+ };
569
+ "maxSide": {
570
+ "alias": "maxSide";
571
+ "required": false;
572
+ "isSignal": true;
573
+ };
574
+ "listRow": {
575
+ "alias": "listRow";
576
+ "required": false;
577
+ "isSignal": true;
578
+ };
579
+ "dashed": {
580
+ "alias": "dashed";
581
+ "required": false;
582
+ "isSignal": true;
583
+ };
584
+ "keyOf": {
585
+ "alias": "keyOf";
586
+ "required": false;
587
+ "isSignal": true;
588
+ };
589
+ "turning": {
590
+ "alias": "turning";
591
+ "required": false;
592
+ "isSignal": true;
593
+ };
594
+ "turnBelow": {
595
+ "alias": "turnBelow";
596
+ "required": false;
597
+ "isSignal": true;
598
+ };
599
+ "across": {
600
+ "alias": "across";
601
+ "required": false;
602
+ "isSignal": true;
603
+ };
604
+ "isOwn": {
605
+ "alias": "isOwn";
606
+ "required": false;
607
+ "isSignal": true;
608
+ };
609
+ "nudgeKey": {
610
+ "alias": "nudgeKey";
611
+ "required": false;
612
+ "isSignal": true;
613
+ };
614
+ }, {}, ["tile"], never, true, never>;
615
+ }
616
+ /** how close a square's places are: from one big tile (0) to only its icon (4). */
617
+ export type ContextLevel = SquareLevel;
618
+ /** cubes' steps, now the square's (`squareLevelFor`); kept under its first name. */
619
+ export declare const contextLevelFor: (cell: number) => ContextLevel;
620
+ /** a level's square: n × n places, how far apart, and how much each tile says. */
621
+ export interface ContextSquare {
622
+ /** places on a side. */
623
+ n: number;
624
+ /** the square's side, in px. */
625
+ side: number;
626
+ gap: number;
627
+ level: ContextLevel;
628
+ /** the places not filled, outlined so the square stays whole. */
629
+ open: number;
630
+ }
631
+ /**
632
+ * the square for this many tiles in this much room: the smallest n × n that holds them all
633
+ * (`gridFor('square', count)`), as wide as the room, at most `maxSide`.
634
+ */
635
+ export declare function contextSquare(count: number, room: number, maxSide?: number): ContextSquare;
636
+ /**
637
+ * the icon a tile is drawn with: its own when `cube-icon` draws it, shown for `hide` (it has no icon
638
+ * of its own), the plus for a tile that adds, and else a face (an app's own part with an icon the
639
+ * package does not have).
640
+ */
641
+ export declare function contextIcon(tile: Pick<ContextTile, 'icon' | 'adds'>): CubeIconName;
642
+ /** a tapped tile and the element it is drawn in. */
643
+ export interface ContextTapped {
644
+ tile: ContextTile;
645
+ element: HTMLElement;
646
+ }
647
+ /**
648
+ * `<cube-context [held] [path]>`: one level of the held thing's context cube, as a complete square
649
+ * of icon tiles. a tap asks the source's `pick`, and the answer comes out as `enter` (a deeper
650
+ * path), `done` (the journey ends: a name, a view, shown or hidden was used) or `out` (one level
651
+ * up); `stay` redraws the level where it is. a level the source does not have (null) is `out` too.
652
+ *
653
+ * the source and the words come from `CONTEXT_CUBE_SOURCE` and `CONTEXT_CUBE_WORDS`, or from the
654
+ * `source` and `words` inputs when one screen holds a different one. its look is css variables
655
+ * (`--cube-context-*`, `--cube-icon-*`), set in both token files.
656
+ */
657
+ export declare class CubeContext {
658
+ /** what was held: a piece, a cube, a to-do, a level, as the app's source knows it. */
659
+ readonly held: import("@angular/core").InputSignal<unknown>;
660
+ /** where in its context cube: [] is its top (the parts), ['names'] a part, ['sort', by] deeper. */
661
+ readonly path: import("@angular/core").InputSignal<ContextPath>;
662
+ /** a source for this screen alone; else `CONTEXT_CUBE_SOURCE`. */
663
+ readonly source: import("@angular/core").InputSignal<ContextCubeSource<any> | null>;
664
+ /** words for this screen alone; else `CONTEXT_CUBE_WORDS`. */
665
+ readonly words: import("@angular/core").InputSignal<ContextWords | null>;
666
+ /** the largest side the square takes on a wide screen, in px. */
667
+ readonly maxSide: import("@angular/core").InputSignal<number>;
668
+ /** walk into a deeper level: the app puts this path in its own route. */
669
+ readonly enter: import("@angular/core").OutputEmitterRef<string[]>;
670
+ /** step one level out (or out of the context cube, from its top). */
671
+ readonly out: import("@angular/core").OutputEmitterRef<void>;
672
+ /** the journey ends: the tile that was used. */
673
+ readonly done: import("@angular/core").OutputEmitterRef<ContextTile<unknown>>;
674
+ /**
675
+ * a tile was tapped, before the source answers: the tile and its element, so the app can grow the
676
+ * next level (or whatever the pick opens) out of the tile, as it zooms into any other piece.
677
+ */
678
+ readonly tapped: import("@angular/core").OutputEmitterRef<ContextTapped>;
679
+ private readonly given;
680
+ private readonly givenWords;
681
+ /** the tile whose pick is still being answered; every tile waits meanwhile. */
682
+ protected readonly busy: import("@angular/core").WritableSignal<string | null>;
683
+ /** bumped after a pick, so a source that keeps its data outside signals is read again. */
684
+ private readonly again;
685
+ private readonly from;
686
+ /** the path as one key, so the same path given anew is the same level. */
687
+ private readonly where;
688
+ private readonly level;
689
+ protected readonly tiles: import("@angular/core").Signal<ContextTile<unknown>[]>;
690
+ protected readonly adds: import("@angular/core").Signal<boolean>;
691
+ /** a tile stays the same tile across levels by its key. */
692
+ protected readonly keyOf: (t: ContextTile) => string;
693
+ protected readonly inUseWord: import("@angular/core").Signal<string | null>;
694
+ protected readonly iconOf: typeof contextIcon;
695
+ constructor();
696
+ protected tap(tile: ContextTile, element?: HTMLElement): Promise<void>;
697
+ static ɵfac: i0.ɵɵFactoryDeclaration<CubeContext, never>;
698
+ static ɵcmp: i0.ɵɵComponentDeclaration<CubeContext, "cube-context", never, {
699
+ "held": {
700
+ "alias": "held";
701
+ "required": true;
702
+ "isSignal": true;
703
+ };
704
+ "path": {
705
+ "alias": "path";
706
+ "required": false;
707
+ "isSignal": true;
708
+ };
709
+ "source": {
710
+ "alias": "source";
711
+ "required": false;
712
+ "isSignal": true;
713
+ };
714
+ "words": {
715
+ "alias": "words";
716
+ "required": false;
717
+ "isSignal": true;
718
+ };
719
+ "maxSide": {
720
+ "alias": "maxSide";
721
+ "required": false;
722
+ "isSignal": true;
723
+ };
724
+ }, {
725
+ "enter": "enter";
726
+ "out": "out";
727
+ "done": "done";
728
+ "tapped": "tapped";
729
+ }, never, never, true, never>;
730
+ }
731
+ /**
732
+ * turning rows (selim: row rotation), first tried in mosaic's todarch cube: a square of more
733
+ * pieces than its front holds keeps its front full and turns its rows like the layers of a puzzle
734
+ * cube. each row is a band of four sides; the pieces past the front fill the first row's other
735
+ * sides, then the second row's, and so on, so the open places gather at the very end and a row
736
+ * with nothing behind its front does not turn.
737
+ *
738
+ * this is only the layout, pure and without angular: which piece sits on which side of which row.
739
+ * the front is cols × rows (3 × 3 as mosaic draws it, 4 × 5 and 3 × 6 for cubes' fixed grids).
740
+ * when four sides a row are still not enough, rows are added below, as mosaic does.
741
+ */
742
+ export interface TurningRows<T> {
743
+ /** rows × 4 sides × cols places; null is an open place. side 0 is the front. */
744
+ rows: (T | null)[][][];
745
+ /** how many sides of each row hold something (1: only its front, it does not turn). */
746
+ sides: number[];
747
+ }
748
+ /** the sides of one row: its front and the three behind it. */
749
+ export declare const TURNING_SIDES = 4;
750
+ export declare function turningRows<T>(pieces: readonly T[], own: T | null, cols?: number, rows?: number): TurningRows<T>;