@selimssevgi/cube-design-angular 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +118 -4
- package/fesm2022/selimssevgi-cube-design-angular.mjs +1159 -63
- package/fesm2022/selimssevgi-cube-design-angular.mjs.map +1 -1
- package/package.json +1 -1
- package/tokens/dark.css +11 -1
- package/tokens/light.css +11 -1
- package/types/selimssevgi-cube-design-angular.d.ts +473 -11
package/package.json
CHANGED
package/tokens/dark.css
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* cube design's dark dialect (mosaic; cube design `
|
|
2
|
+
* cube design's dark dialect (mosaic; cube design `04-screens.md`): black plastic with one light
|
|
3
3
|
* source. import it once in an app's global styles, or set the same variables yourself.
|
|
4
4
|
*/
|
|
5
5
|
:root {
|
|
@@ -32,6 +32,13 @@
|
|
|
32
32
|
--cube-context-line-size: 13px;
|
|
33
33
|
--cube-context-title-lines: 2;
|
|
34
34
|
--cube-context-line-lines: 2;
|
|
35
|
+
--cube-context-go: #374151;
|
|
36
|
+
/* the carry (cubeCarry): the ghost that follows the finger, the piece left behind */
|
|
37
|
+
--cube-carry-ghost-transform: scale(1.08) rotate(-2deg);
|
|
38
|
+
--cube-carry-ghost-shadow: 0 14px 32px rgb(0 0 0 / 0.5);
|
|
39
|
+
--cube-carry-ghost-opacity: 0.95;
|
|
40
|
+
--cube-carry-ghost-z: 1000;
|
|
41
|
+
--cube-carry-lifted-opacity: 0.3;
|
|
35
42
|
--cube-square-place: color-mix(in srgb, #4b5563 55%, transparent);
|
|
36
43
|
--cube-square-place-dashed: #4b5563;
|
|
37
44
|
--cube-square-place-width: 1.5px;
|
|
@@ -39,4 +46,7 @@
|
|
|
39
46
|
--cube-square-gap-scale: 1;
|
|
40
47
|
--cube-square-edge: color-mix(in srgb, #7dd3fc 45%, transparent);
|
|
41
48
|
--cube-square-focus: #7dd3fc;
|
|
49
|
+
/* something on its way (<cube-loading>) */
|
|
50
|
+
--cube-loading-place: rgba(156, 163, 175, 0.1);
|
|
51
|
+
--cube-loading-gap: 12px;
|
|
42
52
|
}
|
package/tokens/light.css
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* cube design's light dialect (cubes, anlat; cube design `
|
|
2
|
+
* cube design's light dialect (cubes, anlat; cube design `04-screens.md`): import it once in an
|
|
3
3
|
* app's global styles, or set the same variables yourself.
|
|
4
4
|
*/
|
|
5
5
|
:root {
|
|
@@ -32,6 +32,13 @@
|
|
|
32
32
|
--cube-context-line-size: 13px;
|
|
33
33
|
--cube-context-title-lines: 2;
|
|
34
34
|
--cube-context-line-lines: 2;
|
|
35
|
+
--cube-context-go: #edf0ec;
|
|
36
|
+
/* the carry (cubeCarry): the ghost that follows the finger, the piece left behind */
|
|
37
|
+
--cube-carry-ghost-transform: scale(1.08) rotate(-2deg);
|
|
38
|
+
--cube-carry-ghost-shadow: 0 14px 32px rgb(31 42 38 / 0.22);
|
|
39
|
+
--cube-carry-ghost-opacity: 0.95;
|
|
40
|
+
--cube-carry-ghost-z: 1000;
|
|
41
|
+
--cube-carry-lifted-opacity: 0.3;
|
|
35
42
|
--cube-square-place: color-mix(in srgb, #dae0d9 55%, transparent);
|
|
36
43
|
--cube-square-place-dashed: #dae0d9;
|
|
37
44
|
--cube-square-place-width: 1.5px;
|
|
@@ -39,4 +46,7 @@
|
|
|
39
46
|
--cube-square-gap-scale: 1;
|
|
40
47
|
--cube-square-edge: color-mix(in srgb, #5f9a80 45%, transparent);
|
|
41
48
|
--cube-square-focus: #5f9a80;
|
|
49
|
+
/* something on its way (<cube-loading>) */
|
|
50
|
+
--cube-loading-place: #e3e7e1;
|
|
51
|
+
--cube-loading-gap: 12px;
|
|
42
52
|
}
|
|
@@ -5,7 +5,7 @@ import { InjectionToken, TemplateRef } from "@angular/core";
|
|
|
5
5
|
* n × n stickers. a sticker is coloured by a piece, or pale while nothing is known for it.
|
|
6
6
|
*
|
|
7
7
|
* the same projection anlat, mosaic and cubes drew by hand before this package (cube design,
|
|
8
|
-
* `
|
|
8
|
+
* `04-screens.md`). pure functions, no angular: they can be used anywhere.
|
|
9
9
|
*/
|
|
10
10
|
/** The side of the smallest cube that holds this many pieces, up to 7 × 7 × 7. */
|
|
11
11
|
export declare function sizeFor(count: number): number;
|
|
@@ -167,6 +167,232 @@ export declare class CubeHold {
|
|
|
167
167
|
"cubeHeld": "cubeHeld";
|
|
168
168
|
}, never, never, true, never>;
|
|
169
169
|
}
|
|
170
|
+
/** what a pinch reports: which way the fingers went, where, how it came and the event that ended it. */
|
|
171
|
+
export interface CubePinched {
|
|
172
|
+
/** `in`: fingers apart, going into the piece under them; `out`: fingers together, one level out. */
|
|
173
|
+
way: 'in' | 'out';
|
|
174
|
+
/** the element under the pinch (between two fingers, under the pointer); null when none. */
|
|
175
|
+
at: Element | null;
|
|
176
|
+
/**
|
|
177
|
+
* `touch`: two fingers on a screen; `wheel`: ctrl and the wheel, which is how chrome, edge and
|
|
178
|
+
* firefox send a trackpad's pinch; `gesture`: safari's own gesture events for a trackpad's pinch.
|
|
179
|
+
*/
|
|
180
|
+
via: 'touch' | 'wheel' | 'gesture';
|
|
181
|
+
/** the event that decided it: the `pointerup`, the first `wheel` of the stream, the `gestureend`. */
|
|
182
|
+
event: Event;
|
|
183
|
+
}
|
|
184
|
+
/** two fingers this much further apart than they started is a pinch in (cubes', mosaic's, anlat's). */
|
|
185
|
+
export declare const CUBE_PINCH_APART = 1.25;
|
|
186
|
+
/** two fingers this much closer than they started is a pinch out. */
|
|
187
|
+
export declare const CUBE_PINCH_TOGETHER = 0.8;
|
|
188
|
+
/**
|
|
189
|
+
* a trackpad's pinch is a stream of ctrl + wheel events for as long as the fingers move; the stream
|
|
190
|
+
* is one gesture until the wheel has been quiet this long, in milliseconds (mosaic's, 3 nov 2026).
|
|
191
|
+
*/
|
|
192
|
+
export declare const CUBE_WHEEL_QUIET_MS = 250;
|
|
193
|
+
/**
|
|
194
|
+
* whether a ctrl + wheel event at `now` starts a new gesture, given when the last one of the stream
|
|
195
|
+
* came (`-Infinity` for never). pure, so an app with a wheel of its own (a puzzle, a canvas) keeps
|
|
196
|
+
* the same rule.
|
|
197
|
+
*/
|
|
198
|
+
export declare function startsWheelGesture(lastAt: number, now: number, quietMs?: number): boolean;
|
|
199
|
+
/**
|
|
200
|
+
* the pinch (principle 25, two fingers together is one level out): fingers apart on a piece raise
|
|
201
|
+
* one `cubePinched` with `way: 'in'`, fingers together one with `way: 'out'`. on a computer a
|
|
202
|
+
* trackpad's pinch or ctrl and the wheel do the same, one level for one pinch however long it lasts.
|
|
203
|
+
*
|
|
204
|
+
* it only reports. it never routes or zooms: what `in` opens (most often a tap on the tile at `at`)
|
|
205
|
+
* and where `out` goes (the way i came) stay in the app. it keeps the browser's own page zoom away
|
|
206
|
+
* from a ctrl + wheel and a safari gesture on its element, and lets every other event through.
|
|
207
|
+
*/
|
|
208
|
+
export declare class CubePinch {
|
|
209
|
+
/** no pinch at all: the listeners do nothing and the browser zooms the page again. */
|
|
210
|
+
readonly cubePinchDisabled: import("@angular/core").InputSignal<boolean>;
|
|
211
|
+
/** how quiet the wheel must be before a new pinch starts, in milliseconds. */
|
|
212
|
+
readonly cubePinchQuietMs: import("@angular/core").InputSignal<number>;
|
|
213
|
+
/** the fingers went apart (`in`) or together (`out`): once a pinch. */
|
|
214
|
+
readonly cubePinched: import("@angular/core").OutputEmitterRef<CubePinched>;
|
|
215
|
+
constructor();
|
|
216
|
+
/** the pointers down on the element, by id, with where each is now. */
|
|
217
|
+
private readonly pointers;
|
|
218
|
+
/** a two-finger pinch under way: how far apart the fingers started and what was between them. */
|
|
219
|
+
private pinch;
|
|
220
|
+
protected down(e: PointerEvent): void;
|
|
221
|
+
protected move(e: PointerEvent): void;
|
|
222
|
+
/** the first finger to lift decides; the second has nothing left to say. */
|
|
223
|
+
protected up(e: PointerEvent): void;
|
|
224
|
+
protected cancel(e: PointerEvent): void;
|
|
225
|
+
protected wheel(e: WheelEvent): void;
|
|
226
|
+
protected gestureStart(e: Event): void;
|
|
227
|
+
protected gestureChange(e: Event): void;
|
|
228
|
+
/** safari decides at the end of its gesture; a wheel stream that already decided wins. */
|
|
229
|
+
protected gestureEnd(e: Event): void;
|
|
230
|
+
private emit;
|
|
231
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<CubePinch, never>;
|
|
232
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<CubePinch, "[cubePinch]", never, {
|
|
233
|
+
"cubePinchDisabled": {
|
|
234
|
+
"alias": "cubePinchDisabled";
|
|
235
|
+
"required": false;
|
|
236
|
+
"isSignal": true;
|
|
237
|
+
};
|
|
238
|
+
"cubePinchQuietMs": {
|
|
239
|
+
"alias": "cubePinchQuietMs";
|
|
240
|
+
"required": false;
|
|
241
|
+
"isSignal": true;
|
|
242
|
+
};
|
|
243
|
+
}, {
|
|
244
|
+
"cubePinched": "cubePinched";
|
|
245
|
+
}, never, never, true, never>;
|
|
246
|
+
}
|
|
247
|
+
/** the `data-drop` value of the element that means out: one level up (the app's ‹). */
|
|
248
|
+
export declare const CUBE_DROP_OUT = "out";
|
|
249
|
+
/** how far a lifted piece must travel before letting go is a drop, not a hold, in pixels. */
|
|
250
|
+
export declare const CUBE_CARRY_MOVE = 12;
|
|
251
|
+
/** a piece lifted: the press was held, and it may now be carried. */
|
|
252
|
+
export interface CubeLifted {
|
|
253
|
+
/** the carried piece, as `[cubeCarry]` names it. */
|
|
254
|
+
piece: string;
|
|
255
|
+
/** the element holding the directive (the tile left behind, faded). */
|
|
256
|
+
element: HTMLElement;
|
|
257
|
+
/** the ghost following the finger: a copy of the element, on `document.body`. */
|
|
258
|
+
ghost: HTMLElement;
|
|
259
|
+
}
|
|
260
|
+
/** what the carried piece is over now: a `[data-drop]` element, or nothing. */
|
|
261
|
+
export interface CubeCarriedOver {
|
|
262
|
+
piece: string;
|
|
263
|
+
/** its `data-drop`, `'out'` for the ‹; null when over nothing a piece may land on. */
|
|
264
|
+
onto: string | null;
|
|
265
|
+
/** the `[data-drop]` element it is over, marked meanwhile; null over nothing. */
|
|
266
|
+
target: HTMLElement | null;
|
|
267
|
+
}
|
|
268
|
+
/** a carried piece let go over a `[data-drop]` element. */
|
|
269
|
+
export interface CubeDropped {
|
|
270
|
+
piece: string;
|
|
271
|
+
/** the target's `data-drop`: a piece's key, or `'out'` (`CUBE_DROP_OUT`) for the ‹. */
|
|
272
|
+
onto: string;
|
|
273
|
+
/** the element it was let go over. */
|
|
274
|
+
target: HTMLElement;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* how a carry ended: `dropped` (on a target), `held` (let go without moving: a hold), `nowhere`
|
|
278
|
+
* (let go over nothing a piece lands on: it goes back), `cancelled` (two fingers, escape, a
|
|
279
|
+
* cancelled touch, or the directive went away).
|
|
280
|
+
*/
|
|
281
|
+
export type CubeCarryEnd = 'dropped' | 'held' | 'nowhere' | 'cancelled';
|
|
282
|
+
/** the classes and attributes the carry puts on the page while it carries; the app styles them. */
|
|
283
|
+
export declare const CUBE_CARRY_CLASSES: {
|
|
284
|
+
/** on `document.body` while a piece is lifted. */
|
|
285
|
+
readonly carrying: "cube-carrying";
|
|
286
|
+
/** on the lifted piece's own element, which stays where it was. */
|
|
287
|
+
readonly lifted: "cube-carry-lifted";
|
|
288
|
+
/** on the ghost that follows the finger. */
|
|
289
|
+
readonly ghost: "cube-carry-ghost";
|
|
290
|
+
/** on the `[data-drop]` element the piece is over. */
|
|
291
|
+
readonly over: "cube-carry-over";
|
|
292
|
+
};
|
|
293
|
+
/**
|
|
294
|
+
* carry and drop (selim, 3 november 2026, the grouping prototype's round 2): press and hold a piece,
|
|
295
|
+
* and it lifts; carry it onto another piece and let go, and the app asks what the drop means (drop
|
|
296
|
+
* it in, make them one). a hold that does not move is still a hold (`cubeHeld`, the context cube),
|
|
297
|
+
* a tap stays a tap, and two fingers (a pinch) cancel.
|
|
298
|
+
*
|
|
299
|
+
* it holds as `cubeHold` does (`cubeHeld`, the same `CubeHeld`), so it replaces `cubeHold` on a
|
|
300
|
+
* piece that can be carried: put one of the two on an element, never both. what it adds: at the
|
|
301
|
+
* hold time (520 ms) the piece lifts, and a ghost of it follows the finger; the `[data-drop]`
|
|
302
|
+
* element under the finger is marked; letting go there emits `cubeDropped` with `{ piece, onto }`,
|
|
303
|
+
* where `onto` is that element's `data-drop` (`'out'` for the app's ‹). letting go without moving
|
|
304
|
+
* the piece is the hold, said then. with `[cubeCarry]` empty (null or '') nothing lifts and it is
|
|
305
|
+
* `cubeHold`: the hold is said at the hold time.
|
|
306
|
+
*
|
|
307
|
+
* mouse and touch both: touch events on a phone, as the prototype (pointer events lose the finger
|
|
308
|
+
* to the page's scroll), the mouse's own events elsewhere. it says no words and draws only the
|
|
309
|
+
* ghost; the hint, the sheet and the marks' look are the app's.
|
|
310
|
+
*/
|
|
311
|
+
export declare class CubeCarry {
|
|
312
|
+
/** the piece this element carries (its key, as the app's `data-drop` names pieces); empty: none. */
|
|
313
|
+
readonly cubeCarry: import("@angular/core").InputSignal<string | null | undefined>;
|
|
314
|
+
/** no hold and no carry: the listeners do nothing and the browser's own menu stays. */
|
|
315
|
+
readonly cubeCarryDisabled: import("@angular/core").InputSignal<boolean>;
|
|
316
|
+
/** how long a press is held before it lifts (or holds), in milliseconds. */
|
|
317
|
+
readonly cubeHoldMs: import("@angular/core").InputSignal<number>;
|
|
318
|
+
/** how far the press may move before the hold time and still hold, in pixels. */
|
|
319
|
+
readonly cubeHoldSlop: import("@angular/core").InputSignal<number>;
|
|
320
|
+
/** a short buzz when it lifts or holds, where the device can. */
|
|
321
|
+
readonly cubeHoldBuzz: import("@angular/core").InputSignal<boolean>;
|
|
322
|
+
/** a hold: let go without moving after the hold time, a right click or the menu key. */
|
|
323
|
+
readonly cubeHeld: import("@angular/core").OutputEmitterRef<CubeHeld>;
|
|
324
|
+
/** the piece lifted at the hold time; the app shows its hint and names its ‹ the way out. */
|
|
325
|
+
readonly cubeLifted: import("@angular/core").OutputEmitterRef<CubeLifted>;
|
|
326
|
+
/** the piece is over another `[data-drop]` element now, or over none. */
|
|
327
|
+
readonly cubeCarriedOver: import("@angular/core").OutputEmitterRef<CubeCarriedOver>;
|
|
328
|
+
/** the piece was let go over a `[data-drop]` element. */
|
|
329
|
+
readonly cubeDropped: import("@angular/core").OutputEmitterRef<CubeDropped>;
|
|
330
|
+
/** a lift ended, however it ended: the app takes its hint away. after `cubeDropped` or `cubeHeld`. */
|
|
331
|
+
readonly cubeCarryEnd: import("@angular/core").OutputEmitterRef<CubeCarryEnd>;
|
|
332
|
+
private readonly element;
|
|
333
|
+
private press;
|
|
334
|
+
private lastTouch;
|
|
335
|
+
/** the click after a hold or a carry is swallowed, so the piece does not also open. */
|
|
336
|
+
protected swallow: boolean;
|
|
337
|
+
private readonly doc;
|
|
338
|
+
private readonly listening;
|
|
339
|
+
constructor();
|
|
340
|
+
/** whether a piece is being carried (lifted) by this element now. */
|
|
341
|
+
get carrying(): boolean;
|
|
342
|
+
protected touchStart(e: TouchEvent): void;
|
|
343
|
+
protected mouseDown(e: MouseEvent): void;
|
|
344
|
+
/** a right click, the menu key or shift+f10 hold at once; a phone's own long press is ours. */
|
|
345
|
+
protected menu(e: Event): void;
|
|
346
|
+
/** the browser's own drag of a link or a picture would take the mouse away from the carry. */
|
|
347
|
+
protected noDrag(e: Event): void;
|
|
348
|
+
private begin;
|
|
349
|
+
private touchMove;
|
|
350
|
+
private touchEnd;
|
|
351
|
+
private lift;
|
|
352
|
+
private moveTo;
|
|
353
|
+
private end;
|
|
354
|
+
/** two fingers, escape, a cancelled touch: whatever was lifted goes back, nothing is said but the end. */
|
|
355
|
+
cancel(): void;
|
|
356
|
+
private clean;
|
|
357
|
+
/** the press is over: its timer and the page's listeners go. */
|
|
358
|
+
private forget;
|
|
359
|
+
private listen;
|
|
360
|
+
private fireHeld;
|
|
361
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<CubeCarry, never>;
|
|
362
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<CubeCarry, "[cubeCarry]", never, {
|
|
363
|
+
"cubeCarry": {
|
|
364
|
+
"alias": "cubeCarry";
|
|
365
|
+
"required": false;
|
|
366
|
+
"isSignal": true;
|
|
367
|
+
};
|
|
368
|
+
"cubeCarryDisabled": {
|
|
369
|
+
"alias": "cubeCarryDisabled";
|
|
370
|
+
"required": false;
|
|
371
|
+
"isSignal": true;
|
|
372
|
+
};
|
|
373
|
+
"cubeHoldMs": {
|
|
374
|
+
"alias": "cubeHoldMs";
|
|
375
|
+
"required": false;
|
|
376
|
+
"isSignal": true;
|
|
377
|
+
};
|
|
378
|
+
"cubeHoldSlop": {
|
|
379
|
+
"alias": "cubeHoldSlop";
|
|
380
|
+
"required": false;
|
|
381
|
+
"isSignal": true;
|
|
382
|
+
};
|
|
383
|
+
"cubeHoldBuzz": {
|
|
384
|
+
"alias": "cubeHoldBuzz";
|
|
385
|
+
"required": false;
|
|
386
|
+
"isSignal": true;
|
|
387
|
+
};
|
|
388
|
+
}, {
|
|
389
|
+
"cubeHeld": "cubeHeld";
|
|
390
|
+
"cubeLifted": "cubeLifted";
|
|
391
|
+
"cubeCarriedOver": "cubeCarriedOver";
|
|
392
|
+
"cubeDropped": "cubeDropped";
|
|
393
|
+
"cubeCarryEnd": "cubeCarryEnd";
|
|
394
|
+
}, never, never, true, never>;
|
|
395
|
+
}
|
|
170
396
|
/** the views a cube can be shown in, each drawn as its own shape. */
|
|
171
397
|
export type CubeIconView = 'square' | 'one' | 'two' | 'three' | 'four' | 'grid-4x5' | 'grid-3x6';
|
|
172
398
|
/** what a tile of a cube the app keeps is about (a context cube's parts and their choices). */
|
|
@@ -227,17 +453,131 @@ export type Direction = 'up' | 'down';
|
|
|
227
453
|
/** what an item is sorted by: text, a number, or nothing found (not known yet). */
|
|
228
454
|
export type SortValue = string | number | null | undefined;
|
|
229
455
|
/**
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
456
|
+
* how text is compared: `natural` reads numbers inside text as numbers (`moment 2` before
|
|
457
|
+
* `moment 10`), as a person reads them; `plain` compares letter by letter (`moment 10` first).
|
|
458
|
+
* both are kept: natural is the default, an app may offer plain (decision of 2026-11-02).
|
|
233
459
|
*/
|
|
234
|
-
export
|
|
460
|
+
export type TextOrder = 'natural' | 'plain';
|
|
461
|
+
/** the ways text can be compared, the default first. */
|
|
462
|
+
export declare const TEXT_ORDERS: readonly TextOrder[];
|
|
235
463
|
/**
|
|
236
|
-
* the
|
|
237
|
-
*
|
|
464
|
+
* items in the order a sort asks for. `by` reads what each item is sorted by; numbers are compared
|
|
465
|
+
* as numbers, text in the reader's language, numbers inside it as numbers (`text`, natural by
|
|
466
|
+
* default; `plain` compares letter by letter). an item with nothing found (empty text, `NaN`) is
|
|
467
|
+
* not known yet and comes last in both directions (empty is the point, never hidden). ties keep
|
|
468
|
+
* the items' own order.
|
|
469
|
+
*/
|
|
470
|
+
export declare function sortItems<T>(items: readonly T[], by: (item: T) => SortValue, dir: Direction, text?: TextOrder): T[];
|
|
471
|
+
/** what an app gives for where: its places and how they hold each other, from its own world. */
|
|
472
|
+
export interface WhereSource {
|
|
473
|
+
/** the place everything stands in at last: the top (mine, mosaic, my to-dos). */
|
|
474
|
+
readonly top: string;
|
|
475
|
+
/** what stands in a place, in its order, hidden ones too (they still count for loops). */
|
|
476
|
+
partsOf(place: string): readonly string[];
|
|
477
|
+
/** every place a piece stands in now (its live rows). */
|
|
478
|
+
placesOf(piece: string): readonly string[];
|
|
479
|
+
/** a place's name as the app shows it (data, not a word of the package). */
|
|
480
|
+
nameOf(place: string): string;
|
|
481
|
+
/** the place the app put it in, which it never leaves; none by default. */
|
|
482
|
+
givenPlaceOf?(piece: string): string | null;
|
|
483
|
+
/** left out of a level (hidden there); nothing by default. */
|
|
484
|
+
hidden?(id: string): boolean;
|
|
485
|
+
/**
|
|
486
|
+
* why the piece may not stand in the place, by the app's own rules (a screen that holds nothing,
|
|
487
|
+
* a given piece into another given one), as the app's refusal key; null when it may. the package
|
|
488
|
+
* checks "inside itself" on its own first.
|
|
489
|
+
*/
|
|
490
|
+
refuses?(piece: string, place: string): string | null;
|
|
491
|
+
}
|
|
492
|
+
/** the refusals the package finds by itself; every other one is the app's (`WhereSource.refuses`). */
|
|
493
|
+
export type WhereRefusal = 'inside-itself' | 'given-place' | 'last-place' | (string & {});
|
|
494
|
+
/** one place, as a where level shows it. the words for it are the app's. */
|
|
495
|
+
export interface CubePlace {
|
|
496
|
+
/** the place's key, as the app's source knows it. */
|
|
497
|
+
key: string;
|
|
498
|
+
/** its name, from the source's `nameOf`. */
|
|
499
|
+
title: string;
|
|
500
|
+
/** the place this level looks inside, listed first ("mosaic, the top", "kitchen itself"). */
|
|
501
|
+
at: boolean;
|
|
502
|
+
/** the top, the place everything stands in at last. */
|
|
503
|
+
top: boolean;
|
|
504
|
+
/** the held piece stands here (ticked). */
|
|
505
|
+
in: boolean;
|
|
506
|
+
/** here is its only place: it never leaves it. */
|
|
507
|
+
last: boolean;
|
|
508
|
+
/** the app put it here: it never leaves it. */
|
|
509
|
+
given: boolean;
|
|
510
|
+
/** the held piece itself, listed pale where it stands among the others. */
|
|
511
|
+
self: boolean;
|
|
512
|
+
/** a place inside the held piece, listed pale: standing there would put it inside itself. */
|
|
513
|
+
inside: boolean;
|
|
514
|
+
/** what a tap asks for: stand it here too, or take it out of here; null for itself or inside it. */
|
|
515
|
+
tap: 'stand' | 'take-out' | null;
|
|
516
|
+
/** why that tap would be refused, or null when it would be done. */
|
|
517
|
+
refused: WhereRefusal | null;
|
|
518
|
+
/** what is shown in it now, the held piece left out, in order: for the app's line. */
|
|
519
|
+
holds: string[];
|
|
520
|
+
/** nothing shown in it yet but the held piece. */
|
|
521
|
+
empty: boolean;
|
|
522
|
+
/** inside it are places worth looking into (›): it can stand somewhere in there. */
|
|
523
|
+
deeper: boolean;
|
|
524
|
+
}
|
|
525
|
+
/** how `placesOf` lists: one level, as the prototype (the default), or every place at once. */
|
|
526
|
+
export interface PlacesOptions {
|
|
527
|
+
/** the place to look inside; the source's top by default. */
|
|
528
|
+
at?: string;
|
|
529
|
+
/**
|
|
530
|
+
* every place it could stand in or stands in, under `at`, as one list (cubes' and the todarch
|
|
531
|
+
* cube's flat list): no ›, and itself and what is inside it are left out instead of pale.
|
|
532
|
+
*/
|
|
533
|
+
flat?: boolean;
|
|
534
|
+
}
|
|
535
|
+
/** everything standing inside a piece, at any depth and through every place (never the piece). */
|
|
536
|
+
export declare function insideOf(source: WhereSource, piece: string): Set<string>;
|
|
537
|
+
/** standing the piece in the place would put it inside itself (the place is it, or inside it). */
|
|
538
|
+
export declare function wouldLoop(source: WhereSource, piece: string, place: string): boolean;
|
|
539
|
+
/**
|
|
540
|
+
* why the piece may not stand in the place: `inside-itself`, or the app's own refusal; null when
|
|
541
|
+
* it may. a place it already stands in is never refused.
|
|
542
|
+
*/
|
|
543
|
+
export declare function refusalOf(source: WhereSource, piece: string, place: string): WhereRefusal | null;
|
|
544
|
+
/**
|
|
545
|
+
* the places the held piece could stand in, as one level of where: the place looked inside (`at`,
|
|
546
|
+
* the top by default) first when it may stand there, then what stands in it, in its order, each
|
|
547
|
+
* place it could stand in or stands in, or that has such places deeper inside (`deeper`, ›); the
|
|
548
|
+
* held piece and what is inside it come pale (`self`, `inside`). with `flat`, every such place under
|
|
549
|
+
* `at` at once, breadth first, with no › and nothing pale.
|
|
550
|
+
*
|
|
551
|
+
* a tap on a place it stands in takes it out, refused on its given place and on its last; a tap on
|
|
552
|
+
* one it does not stand in stands it there too, refused when inside itself or by the app's rules.
|
|
553
|
+
*/
|
|
554
|
+
export declare function placesOf(source: WhereSource, held: string, opts?: PlacesOptions): CubePlace[];
|
|
555
|
+
/** the words of where, the app's: a place's title and line (both from the place). */
|
|
556
|
+
export interface WhereWords {
|
|
557
|
+
/** its title; the place's name by default (the app says "mosaic, the top", "kitchen itself"). */
|
|
558
|
+
title?(place: CubePlace): string;
|
|
559
|
+
/** the line under it: where the app put it, what it holds, itself, inside it. */
|
|
560
|
+
line?(place: CubePlace): string | null;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* where as context tiles: every place, ticked (`inUse`) where it stands; pale where a tap can do
|
|
564
|
+
* nothing (itself, inside it, a place it may not stand in). each tile's `data` is its `CubePlace`,
|
|
565
|
+
* so the app's `pick` reads `tap` and `refused`, and a place with `deeper` gets `zoom`, the path that
|
|
566
|
+
* looks inside it (`['where', key]` by default), which `<cube-context>` draws as a ›. the words are
|
|
567
|
+
* the app's: `ContextWords.where`.
|
|
568
|
+
*/
|
|
569
|
+
export declare function whereLevel(places: readonly CubePlace[], words?: WhereWords, opts?: {
|
|
570
|
+
pathOf?: (place: CubePlace) => string[];
|
|
571
|
+
}): ContextTile<CubePlace>[];
|
|
572
|
+
/**
|
|
573
|
+
* the parts a context cube can have. the seven are the ones cubes found, and where (one piece in
|
|
574
|
+
* many places, 0.3.0); an app may add its own, any string, and they come after the known ones.
|
|
575
|
+
*/
|
|
576
|
+
export type ContextPartKey = 'names' | 'change' | 'view' | 'sort' | 'move' | 'where' | 'whose' | 'hide' | (string & {});
|
|
577
|
+
/**
|
|
578
|
+
* cubes' rows: how it is called (names, change), how it is shown (view, sort), what i do with it
|
|
579
|
+
* (move, where, whose, hide).
|
|
238
580
|
*/
|
|
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
581
|
export declare const CONTEXT_PART_ORDER: readonly ContextPartKey[];
|
|
242
582
|
/** the parts in their rows; parts an app added come last, in the order it gave them. twice is once. */
|
|
243
583
|
export declare function orderParts(parts: readonly ContextPartKey[]): ContextPartKey[];
|
|
@@ -257,6 +597,14 @@ export interface ContextTile<D = unknown> {
|
|
|
257
597
|
adds?: boolean;
|
|
258
598
|
/** what the tile stands for, for the app's own `pick`. */
|
|
259
599
|
data?: D;
|
|
600
|
+
/**
|
|
601
|
+
* a way inside it beside the tap (›): the path `<cube-context>` enters when the › is pressed,
|
|
602
|
+
* while a tap on the tile still asks the source's `pick` (where: a tap stands it there, › looks
|
|
603
|
+
* inside). none by default.
|
|
604
|
+
*/
|
|
605
|
+
zoom?: string[] | null;
|
|
606
|
+
/** the ›'s label for a screen reader, the app's words; the tile's title by default. */
|
|
607
|
+
zoomLabel?: string | null;
|
|
260
608
|
}
|
|
261
609
|
/** where in the context cube one is: [] is its top (its parts), ['names'] a part, ['sort', by] deeper. */
|
|
262
610
|
export type ContextPath = readonly string[];
|
|
@@ -317,6 +665,8 @@ export interface ContextWords {
|
|
|
317
665
|
};
|
|
318
666
|
/** said on the one in use, when the app wants it said. */
|
|
319
667
|
inUse?: string;
|
|
668
|
+
/** where's title and line for each place (`whereLevel`); the place's name and no line without. */
|
|
669
|
+
where?: WhereWords;
|
|
320
670
|
}
|
|
321
671
|
/** the app's source of context cubes. */
|
|
322
672
|
export declare const CONTEXT_CUBE_SOURCE: InjectionToken<ContextCubeSource<any>>;
|
|
@@ -330,7 +680,8 @@ export interface PartNow {
|
|
|
330
680
|
/**
|
|
331
681
|
* the icon a part's tile shows when the app gives none of what it holds now. most parts are drawn
|
|
332
682
|
* 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.
|
|
683
|
+
* sight until it is hidden. an app passes `now.hide.icon` (`shown` or `hidden`) to say which. where
|
|
684
|
+
* is drawn as a place.
|
|
334
685
|
*/
|
|
335
686
|
export declare const PART_ICONS: Partial<Record<ContextPartKey, string>>;
|
|
336
687
|
/** the top of a context cube: its parts in rows, each with its word and, when given, what it holds now. */
|
|
@@ -665,6 +1016,12 @@ export declare class CubeContext {
|
|
|
665
1016
|
readonly words: import("@angular/core").InputSignal<ContextWords | null>;
|
|
666
1017
|
/** the largest side the square takes on a wide screen, in px. */
|
|
667
1018
|
readonly maxSide: import("@angular/core").InputSignal<number>;
|
|
1019
|
+
/**
|
|
1020
|
+
* what keeps the held thing the same thing while a pick is answered (itself by default). an app
|
|
1021
|
+
* whose store gives a new object when the pick changes it (a rename, a hide) passes its id here, or
|
|
1022
|
+
* the answer would be dropped as if the person had walked to another thing.
|
|
1023
|
+
*/
|
|
1024
|
+
readonly heldKey: import("@angular/core").InputSignal<(held: unknown) => unknown>;
|
|
668
1025
|
/** walk into a deeper level: the app puts this path in its own route. */
|
|
669
1026
|
readonly enter: import("@angular/core").OutputEmitterRef<string[]>;
|
|
670
1027
|
/** step one level out (or out of the context cube, from its top). */
|
|
@@ -693,6 +1050,8 @@ export declare class CubeContext {
|
|
|
693
1050
|
protected readonly inUseWord: import("@angular/core").Signal<string | null>;
|
|
694
1051
|
protected readonly iconOf: typeof contextIcon;
|
|
695
1052
|
constructor();
|
|
1053
|
+
/** the › of a tile with a way inside: walks into its path, without asking the source. */
|
|
1054
|
+
protected zoomInto(tile: ContextTile, element?: HTMLElement): void;
|
|
696
1055
|
protected tap(tile: ContextTile, element?: HTMLElement): Promise<void>;
|
|
697
1056
|
static ɵfac: i0.ɵɵFactoryDeclaration<CubeContext, never>;
|
|
698
1057
|
static ɵcmp: i0.ɵɵComponentDeclaration<CubeContext, "cube-context", never, {
|
|
@@ -721,6 +1080,11 @@ export declare class CubeContext {
|
|
|
721
1080
|
"required": false;
|
|
722
1081
|
"isSignal": true;
|
|
723
1082
|
};
|
|
1083
|
+
"heldKey": {
|
|
1084
|
+
"alias": "heldKey";
|
|
1085
|
+
"required": false;
|
|
1086
|
+
"isSignal": true;
|
|
1087
|
+
};
|
|
724
1088
|
}, {
|
|
725
1089
|
"enter": "enter";
|
|
726
1090
|
"out": "out";
|
|
@@ -747,4 +1111,102 @@ export interface TurningRows<T> {
|
|
|
747
1111
|
}
|
|
748
1112
|
/** the sides of one row: its front and the three behind it. */
|
|
749
1113
|
export declare const TURNING_SIDES = 4;
|
|
750
|
-
export declare function turningRows<T>(pieces: readonly T[], own: T | null, cols?: number, rows?: number): TurningRows<T>;
|
|
1114
|
+
export declare function turningRows<T>(pieces: readonly T[], own: T | null, cols?: number, rows?: number): TurningRows<T>;
|
|
1115
|
+
/**
|
|
1116
|
+
* something on its way, the cube design way: the cube picture's pale stickers take colour (a page,
|
|
1117
|
+
* a cube) or its colours turn round the stickers (a piece: a tile, a button saving). picked by selim
|
|
1118
|
+
* on 3 november 2026 (cube design's `08-decisions.md`, the study `studies/loading-pieces.md`), in
|
|
1119
|
+
* place of grey pulsing cards and primeng's ring. it says no word: the app's own line is projected.
|
|
1120
|
+
*/
|
|
1121
|
+
/**
|
|
1122
|
+
* the ways something on its way is shown. `fill`: the picture's pale stickers take colour one by
|
|
1123
|
+
* one, then start again (a page or a cube). `turn`: the colours turn round the stickers, the way
|
|
1124
|
+
* `rot` turns a cube (a piece). the places wait and the cube grows (the study's b and d) are not in
|
|
1125
|
+
* yet: options to add when an app asks.
|
|
1126
|
+
*/
|
|
1127
|
+
export type CubeLoadingWay = 'fill' | 'turn';
|
|
1128
|
+
export declare const CUBE_LOADING_WAYS: readonly CubeLoadingWay[];
|
|
1129
|
+
/**
|
|
1130
|
+
* how much is on its way. `page`: a whole screen, the picture over the line and the square's pale
|
|
1131
|
+
* places. `cube`: a part of a screen, the picture over the line. `piece`: a tile or a button, a small
|
|
1132
|
+
* cube beside the line, on one line with the words around it.
|
|
1133
|
+
*/
|
|
1134
|
+
export type CubeLoadingLevel = 'page' | 'cube' | 'piece';
|
|
1135
|
+
export declare const CUBE_LOADING_LEVELS: readonly CubeLoadingLevel[];
|
|
1136
|
+
/** the way picked for each level (selim, 3 november 2026): a page or a cube fills, a piece turns. */
|
|
1137
|
+
export declare function loadingWayFor(level: CubeLoadingLevel): CubeLoadingWay;
|
|
1138
|
+
/** how long one step lasts, in milliseconds: the prototype's pace. */
|
|
1139
|
+
export declare const CUBE_LOADING_STEP_MS: Readonly<Record<CubeLoadingWay, number>>;
|
|
1140
|
+
/** the picture's width for each level, in pixels, when the app sets none. */
|
|
1141
|
+
export declare const CUBE_LOADING_WIDTH: Readonly<Record<CubeLoadingLevel, number>>;
|
|
1142
|
+
/** the colours the stickers take when the app gives none: cube design's sample palette. */
|
|
1143
|
+
export declare const CUBE_LOADING_COLOURS: readonly string[];
|
|
1144
|
+
/** the picture is a 2 × 2 × 2 cube: three faces of four stickers. */
|
|
1145
|
+
export declare const CUBE_LOADING_STICKERS = 12;
|
|
1146
|
+
/**
|
|
1147
|
+
* the stickers' colours at a step of a way (null is pale). `fill`: the first `step` stickers are
|
|
1148
|
+
* coloured, all twelve, then none again. `turn`: every third sticker coloured, moved on one sticker
|
|
1149
|
+
* a step. with no palette every sticker is pale.
|
|
1150
|
+
*/
|
|
1151
|
+
export declare function loadingStickers(way: CubeLoadingWay, step: number, palette?: readonly string[], stickers?: number): (string | null)[];
|
|
1152
|
+
/** the step drawn when nothing may move (reduced motion): half filled, or the turn at rest. */
|
|
1153
|
+
export declare function stillStep(way: CubeLoadingWay, stickers?: number): number;
|
|
1154
|
+
/**
|
|
1155
|
+
* `<cube-loading>`: something on its way. the app projects its own line ("bringing my recipes…")
|
|
1156
|
+
* and, when it failed, its own retry (`[cubeLoadingRetry]`). it is never red: a failed load is the
|
|
1157
|
+
* picture at rest, pale, over the app's words.
|
|
1158
|
+
*/
|
|
1159
|
+
export declare class CubeLoading {
|
|
1160
|
+
/** how much is on its way: a page (the default), a cube or a piece. */
|
|
1161
|
+
readonly level: import("@angular/core").InputSignal<CubeLoadingLevel>;
|
|
1162
|
+
/** the way it is shown; null is the one picked for its level (`loadingWayFor`). */
|
|
1163
|
+
readonly way: import("@angular/core").InputSignal<CubeLoadingWay | null>;
|
|
1164
|
+
/** how many places the square on a page has: its pale places, a complete square. 0 draws none. */
|
|
1165
|
+
readonly count: import("@angular/core").InputSignal<number>;
|
|
1166
|
+
/** it did not come: the picture rests, pale; the line is the app's and its retry is projected. */
|
|
1167
|
+
readonly failed: import("@angular/core").InputSignal<boolean>;
|
|
1168
|
+
/** the colours the stickers take; cube design's sample palette when not set. */
|
|
1169
|
+
readonly colours: import("@angular/core").InputSignal<readonly string[]>;
|
|
1170
|
+
/** the picture's width in pixels; null is its level's (`CUBE_LOADING_WIDTH`). */
|
|
1171
|
+
readonly width: import("@angular/core").InputSignal<number | null>;
|
|
1172
|
+
protected readonly wayInUse: import("@angular/core").Signal<CubeLoadingWay>;
|
|
1173
|
+
protected readonly widthInUse: import("@angular/core").Signal<number>;
|
|
1174
|
+
protected readonly places: import("@angular/core").Signal<number[]>;
|
|
1175
|
+
private readonly step;
|
|
1176
|
+
private readonly still;
|
|
1177
|
+
protected readonly stickers: import("@angular/core").Signal<(string | null)[]>;
|
|
1178
|
+
constructor();
|
|
1179
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<CubeLoading, never>;
|
|
1180
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<CubeLoading, "cube-loading", never, {
|
|
1181
|
+
"level": {
|
|
1182
|
+
"alias": "level";
|
|
1183
|
+
"required": false;
|
|
1184
|
+
"isSignal": true;
|
|
1185
|
+
};
|
|
1186
|
+
"way": {
|
|
1187
|
+
"alias": "way";
|
|
1188
|
+
"required": false;
|
|
1189
|
+
"isSignal": true;
|
|
1190
|
+
};
|
|
1191
|
+
"count": {
|
|
1192
|
+
"alias": "count";
|
|
1193
|
+
"required": false;
|
|
1194
|
+
"isSignal": true;
|
|
1195
|
+
};
|
|
1196
|
+
"failed": {
|
|
1197
|
+
"alias": "failed";
|
|
1198
|
+
"required": false;
|
|
1199
|
+
"isSignal": true;
|
|
1200
|
+
};
|
|
1201
|
+
"colours": {
|
|
1202
|
+
"alias": "colours";
|
|
1203
|
+
"required": false;
|
|
1204
|
+
"isSignal": true;
|
|
1205
|
+
};
|
|
1206
|
+
"width": {
|
|
1207
|
+
"alias": "width";
|
|
1208
|
+
"required": false;
|
|
1209
|
+
"isSignal": true;
|
|
1210
|
+
};
|
|
1211
|
+
}, {}, never, ["*", "[cubeLoadingRetry]"], true, never>;
|
|
1212
|
+
}
|