@selimssevgi/cube-design-angular 0.2.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/README.md +118 -4
- package/fesm2022/selimssevgi-cube-design-angular.mjs +1225 -64
- 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 +479 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# changelog
|
|
2
2
|
|
|
3
|
+
## next (not released yet)
|
|
4
|
+
|
|
5
|
+
nothing yet.
|
|
6
|
+
|
|
7
|
+
## 0.4.0 (4 november 2026: released so mosaic's home grouped my way draws its context cube with `<cube-context>`)
|
|
8
|
+
|
|
9
|
+
- `ContextTile.attrs`: the app's own `data-*` attributes on a tile's cell (`cc-cell`, which holds the tile and its ›), so a test or a use-case runner finds the context cube's tiles by the app's own handles (`data-name`, `data-kind`, `data-ticked`). only `data-*` names are set, a null leaves one out, and one a later tile no longer gives is taken off. found moving mosaic's home grouped my way onto `<cube-context>` (4 november 2026): it drew its context cube with its own square only to carry the runner's handles, and so it had no view (selim: "whenever there is a solution in the library, we should make use of it").
|
|
10
|
+
|
|
11
|
+
## 0.3.0 (3 november 2026: released so cubes, anlat and mosaic take the pinch and the loading look; selim, "the rest can be done")
|
|
12
|
+
|
|
13
|
+
- **on its way**, `<cube-loading>` (`CubeLoading`, `CubeLoadingWay`, `CUBE_LOADING_WAYS`, `CubeLoadingLevel`, `CUBE_LOADING_LEVELS`, `loadingWayFor`, `loadingStickers`, `stillStep`, `CUBE_LOADING_STEP_MS`, `CUBE_LOADING_WIDTH`, `CUBE_LOADING_COLOURS`, `CUBE_LOADING_STICKERS`): something on its way, the cube design way (selim's decision of 3 november 2026, the study `studies/loading-pieces.md`, finding G3). a page or a cube shows the picture's pale stickers taking colour one by one (`fill`), with the square's places pale below on a page; a piece (a tile, a button saving) shows a small cube whose colours turn round its stickers (`turn`), in place of a ring. `level` (`page`, `cube`, `piece`), `way` (null is the level's), `count`, `colours`, `width`, and `failed`: the picture rests pale, never red, beside the app's own retry (`[cubeLoadingRetry]`). no words: the app projects its line. `prefers-reduced-motion` stops it; `aria-busy` and a polite live line. `--cube-loading-place` and `--cube-loading-gap` in both token files. the places wait and the cube grows stay options to add.
|
|
14
|
+
- `cubePinch` (`CubePinch`, `CubePinched`, `CUBE_PINCH_APART`, `CUBE_PINCH_TOGETHER`, `CUBE_WHEEL_QUIET_MS`, `startsWheelGesture`): the pinch, which mosaic, cubes and anlat each wrote by hand. two fingers apart or together, a trackpad's pinch (ctrl and the wheel, or safari's gesture events) raise one `cubePinched` with `way` (`in`, `out`), `at` (the element under it) and `via`; where it goes stays in the app. a trackpad's pinch is a stream of wheel events; it is one pinch until the wheel has been quiet 250 ms (`cubePinchQuietMs`), and the stream is kept for the whole page, so the level a pinch steps to does not take the rest of it as a second step. found in mosaic on 3 november 2026: on a mac one pinch out stepped two levels (lang-app-fe PR #157); cubes, anlat and cube design's own sites pause a fixed 650 ms, which a long pinch outlasts. the page hears the stream too (one listener on the window), so the events that land outside every directive while the next screen comes in (a view transition) keep it one pinch and keep the page zoom away; found adopting it in anlat, where one long pinch stepped three levels.
|
|
15
|
+
- **where** (`placesOf`, `whereLevel`, `WhereSource`, `CubePlace`, `PlacesOptions`, `WhereWords`, `WhereRefusal`, `insideOf`, `wouldLoop`, `refusalOf`): one piece in many places at once, never copied (the study *one piece in many places, once*). `placesOf(source, held, { at })` gives the places the held piece could stand in, as one level that looks inside one place (the grouping prototype's shape, a › for a place with places inside it) or, with `flat`, as one list (cubes' and the todarch cube's); each says whether it stands there, its last or given place, what a tap asks (`stand`, `take-out`) and why it would be refused (`inside-itself`, `given-place`, `last-place`, or the app's own key). `whereLevel` makes them context tiles, the app's words through `ContextWords.where`. taken from cubes' `placesFor`, the todarch cube's `placesFor`/`whereLevel` and the prototype's `whereLevel`. 0.3.0 waits until mosaic's new home has used it.
|
|
16
|
+
- **carry and drop**, `cubeCarry` (`CubeCarry`, `CubeLifted`, `CubeCarriedOver`, `CubeDropped`, `CubeCarryEnd`, `CUBE_CARRY_CLASSES`, `CUBE_DROP_OUT`, `CUBE_CARRY_MOVE`): hold a piece and it lifts (520 ms), a ghost follows the finger, the `[data-drop]` element under it is marked, and letting go there says `(cubeDropped)` with `{ piece, onto }` (`onto: 'out'` for the ‹). a still hold is still `(cubeHeld)`, said on letting go; a tap stays a tap; two fingers or escape cancel. it replaces `cubeHold` on a piece that can be carried. mouse and touch. the `--cube-carry-*` variables in both token files. from the grouping prototype (mosaic's home, round 2: a drop asks what i mean).
|
|
17
|
+
- the context cube knows **where**: `ContextPartKey` and `CONTEXT_PART_ORDER` have `where` (after move, before whose and hide), drawn as a place (`PART_ICONS`); `ContextWords.where`; `ContextTile.zoom` and `zoomLabel`, for which `<cube-context>` draws a › that enters that path without asking `pick` (`cc-cell`, `cc-go`, `--cube-context-go`). an app that adds none of them sees no change, but a tile now sits in a `cc-cell`.
|
|
18
|
+
- `sortItems(items, by, dir, text?)` compares text in natural order by default: numbers inside text are numbers, so `moment 2` comes before `moment 10`, as the readme always said. the letter-by-letter order before stays as an option, `text: 'plain'` (`TextOrder`, `TEXT_ORDERS`), so an app may offer both (decision of 2026-11-02). a `NaN` is now not known yet and comes last, where before it kept its place wherever it met another item. found writing the package's docs (wave 1, the context cube pages).
|
|
19
|
+
- `<cube-context [heldKey]>`: what keeps the held thing the same thing while a pick is answered (itself by default). an app whose store shows a change at once gives a new object for the same piece (a rename, a hide), and 0.2.0 dropped that pick's answer as if the person had walked to another piece; with `heldKey` (its id) the answer comes through. found adopting 0.2.0 in mosaic's todarch cube.
|
|
20
|
+
|
|
3
21
|
## 0.2.1
|
|
4
22
|
|
|
5
23
|
- `<cube-context>`'s words take their size from `--cube-context-title-size` (17px) and `--cube-context-line-size` (13px, the line and the in-use word), set in both token files; the other steps keep their ratio to them. before, the sizes were fixed, so an app could not reach them through variables. found taking 0.2.0 into anlat, whose text is never under 19px. nothing changes for an app that does not set them.
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ it and its cube design decision is kept; then it moves in here.
|
|
|
11
11
|
## install
|
|
12
12
|
|
|
13
13
|
```shell
|
|
14
|
-
npm install @selimssevgi/cube-design-angular@0.
|
|
14
|
+
npm install @selimssevgi/cube-design-angular@0.3.0 --save-exact
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
pin the exact version: a new version changes nothing in an app until that app takes it in its own
|
|
@@ -90,6 +90,102 @@ export class Tile {
|
|
|
90
90
|
- on its element it sets `user-select: none` and `-webkit-touch-callout: none`, so no selection or
|
|
91
91
|
callout gets in the way; no other styles.
|
|
92
92
|
|
|
93
|
+
## the pinch
|
|
94
|
+
|
|
95
|
+
two fingers together is one level out, apart on a piece is into it (principle 25). `cubePinch` is
|
|
96
|
+
that gesture and nothing more: where it goes stays in the app.
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
import { CubePinch, CubePinched } from '@selimssevgi/cube-design-angular';
|
|
100
|
+
|
|
101
|
+
@Component({
|
|
102
|
+
imports: [CubePinch],
|
|
103
|
+
template: `<main cubePinch (cubePinched)="pinched($event)">…</main>`,
|
|
104
|
+
})
|
|
105
|
+
export class Level {
|
|
106
|
+
pinched(p: CubePinched) {
|
|
107
|
+
if (p.way === 'out') this.zoom.out();
|
|
108
|
+
else p.at?.closest<HTMLElement>('[data-zoom]')?.click();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
| input | what it is |
|
|
114
|
+
| ------------------- | -------------------------------------------------------------------------- |
|
|
115
|
+
| `cubePinchDisabled` | no pinch at all; ctrl and the wheel zoom the page again (`false`) |
|
|
116
|
+
| `cubePinchQuietMs` | how long the wheel is quiet before a new pinch starts, in ms (`250`) |
|
|
117
|
+
|
|
118
|
+
`cubePinched` gives `{ way: 'in' | 'out', at, via: 'touch' | 'wheel' | 'gesture', event }`.
|
|
119
|
+
|
|
120
|
+
- two fingers that end 1.25 times further apart (`CUBE_PINCH_APART`) are `in`, 0.8 times or closer
|
|
121
|
+
(`CUBE_PINCH_TOGETHER`) are `out`, decided when the first lifts.
|
|
122
|
+
- a trackpad's pinch reaches chrome, edge and firefox as a stream of ctrl + wheel events: the first
|
|
123
|
+
decides (`deltaY` below 0 is `in`), and the stream is one pinch until the wheel has been quiet
|
|
124
|
+
250 ms (`CUBE_WHEEL_QUIET_MS`). the stream is kept for the whole page, so the level a pinch steps
|
|
125
|
+
to never takes the rest of it as a second step (two levels out for one pinch on a mac, found in
|
|
126
|
+
mosaic). `startsWheelGesture(lastAt, now)` is the rule alone. safari's gesture events count too.
|
|
127
|
+
- it keeps the browser's page zoom away from a ctrl + wheel and safari's gestures on its element,
|
|
128
|
+
and never stops pointer events, so a hold or turning rows on the same screen keep working.
|
|
129
|
+
|
|
130
|
+
## on its way (since 0.3.0)
|
|
131
|
+
|
|
132
|
+
`<cube-loading>` is what an app shows while something is on its way: the cube picture whose pale
|
|
133
|
+
stickers take colour one by one (`fill`, a page or a cube), or whose colours turn round its
|
|
134
|
+
stickers (`turn`, a piece: a tile, a button saving, in place of a ring). picked by selim on
|
|
135
|
+
3 november 2026 (the study `studies/loading-pieces.md`). it says no word: the app projects its line,
|
|
136
|
+
and its retry as an element marked `cubeLoadingRetry`.
|
|
137
|
+
|
|
138
|
+
```html
|
|
139
|
+
<cube-loading [failed]="failed()" [count]="9">
|
|
140
|
+
{{ failed() ? 'my recipes did not come yet.' : 'bringing my recipes…' }}
|
|
141
|
+
<button cubeLoadingRetry type="button" (click)="load()">i ask again</button>
|
|
142
|
+
</cube-loading>
|
|
143
|
+
|
|
144
|
+
<button type="button"><cube-loading level="piece" [width]="18" /> saving my recipe</button>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
| input | what it is |
|
|
148
|
+
| --------- | --------------------------------------------------------------------------------------- |
|
|
149
|
+
| `level` | `page` (the picture, the line, the square's pale places), `cube`, `piece` (`page`) |
|
|
150
|
+
| `way` | `fill` or `turn`; null is the level's: a page or a cube fills, a piece turns (`null`) |
|
|
151
|
+
| `count` | how many pale places the square on a page holds, a complete square (`9`) |
|
|
152
|
+
| `failed` | it did not come: the picture rests pale, never red, and the retry shows (`false`) |
|
|
153
|
+
| `colours` | the colours the stickers take (`CUBE_LOADING_COLOURS`, cube design's sample palette) |
|
|
154
|
+
| `width` | the picture's width in px; null is the level's: 96, 64, 20 (`null`) |
|
|
155
|
+
|
|
156
|
+
- `prefers-reduced-motion`: nothing moves. `aria-busy` while it waits; the line is a polite status.
|
|
157
|
+
- `loadingStickers(way, step, palette?)` and `stillStep(way)` are the drawing alone.
|
|
158
|
+
- `--cube-loading-place` and `--cube-loading-gap` are in both token files.
|
|
159
|
+
|
|
160
|
+
## carry and drop (since 0.3.0)
|
|
161
|
+
|
|
162
|
+
on main, not released yet: 0.3.0 waits until mosaic's new home has used it. hold a piece and it
|
|
163
|
+
lifts; carry it onto another and let go, and the app asks what the drop means. `cubeCarry` replaces
|
|
164
|
+
`cubeHold` on a piece that can be carried (one of the two on an element, never both): it says the
|
|
165
|
+
same `(cubeHeld)`.
|
|
166
|
+
|
|
167
|
+
```html
|
|
168
|
+
<button id="back" [attr.data-drop]="'out'">‹</button>
|
|
169
|
+
<div class="tile" [attr.data-drop]="p.id" [cubeCarry]="p.id" (click)="open(p)"
|
|
170
|
+
(cubeHeld)="own(p, $event)" (cubeLifted)="hint = true" (cubeCarryEnd)="hint = false"
|
|
171
|
+
(cubeDropped)="ask($event)">…</div>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
| output | when |
|
|
175
|
+
| ------------------- | ------------------------------------------------------------------------------------ |
|
|
176
|
+
| `cubeLifted` | the hold time (520 ms): `{ piece, element, ghost }`; show a hint, rename the ‹ |
|
|
177
|
+
| `cubeCarriedOver` | the `[data-drop]` under the finger changed: `{ piece, onto, target }`, onto null |
|
|
178
|
+
| `cubeDropped` | let go over a `[data-drop]`: `{ piece, onto, target }`, `onto: 'out'` for the ‹ |
|
|
179
|
+
| `cubeHeld` | let go without moving (said then), a right click or the menu key |
|
|
180
|
+
| `cubeCarryEnd` | every lift ends once: `dropped`, `held`, `nowhere` or `cancelled` |
|
|
181
|
+
|
|
182
|
+
inputs: `cubeCarry` (the piece's key; empty is a plain hold), `cubeCarryDisabled`, `cubeHoldMs`,
|
|
183
|
+
`cubeHoldSlop`, `cubeHoldBuzz`. a tap stays a tap; two fingers or escape cancel; the ghost is a copy
|
|
184
|
+
of the element on the body (`cube-carry-ghost`), the element stays faded (`cube-carry-lifted`), the
|
|
185
|
+
target is marked `cube-carry-over` for the app to style; the `--cube-carry-*` variables are in both
|
|
186
|
+
token files. touch events on a phone, the mouse's own elsewhere. keep the tiles while carrying (a
|
|
187
|
+
`track` by id): a carried tile drawn anew cancels the carry.
|
|
188
|
+
|
|
93
189
|
## the context cube's model
|
|
94
190
|
|
|
95
191
|
behind every piece sits a second cube, the app's, where it keeps how the piece is named, shown and
|
|
@@ -128,8 +224,24 @@ providers: [
|
|
|
128
224
|
|
|
129
225
|
the shared levels are `partsLevel`, `namesLevel`, `hideLevel`, `viewLevel`, `sortLevel` and
|
|
130
226
|
`sortDirectionsLevel`; each tile's `data` says what it stands for, so `pick` reads it from there.
|
|
131
|
-
`gridFor(view, count)` lays out a level or a cube, and `sortItems(items, by, dir)` orders items with
|
|
132
|
-
what is not known yet last both ways.
|
|
227
|
+
`gridFor(view, count)` lays out a level or a cube, and `sortItems(items, by, dir, text?)` orders items with
|
|
228
|
+
what is not known yet (nothing, empty text, `NaN`) last both ways. numbers are compared as numbers;
|
|
229
|
+
text by default in natural order, numbers inside it as numbers (`moment 2` before `moment 10`), and
|
|
230
|
+
with `text: 'plain'` letter by letter (`moment 10` first). both are kept (`TEXT_ORDERS`), so an app
|
|
231
|
+
may offer the other one to its people. `<cube-context>` draws a level (below).
|
|
232
|
+
|
|
233
|
+
### where (since 0.3.0)
|
|
234
|
+
|
|
235
|
+
one piece in many places at once, never copied. `placesOf(source, held, { at?, flat? })` gives the
|
|
236
|
+
places the held piece could stand in from a `WhereSource` the app fills (`top`, `partsOf`,
|
|
237
|
+
`placesOf`, `nameOf`, and optionally `givenPlaceOf`, `hidden`, `refuses`): one level looking inside
|
|
238
|
+
`at` (the top by default), the held piece and what is inside it pale, a place with places inside it
|
|
239
|
+
`deeper` (a ›), or with `flat` every place at once. each `CubePlace` says `in`, `last`, `given`,
|
|
240
|
+
what a tap asks (`tap`: `stand` or `take-out`) and why it would be refused (`refused`:
|
|
241
|
+
`inside-itself`, `given-place`, `last-place`, or the app's own key). `whereLevel(places, words.where)`
|
|
242
|
+
makes context tiles of them (`zoom` on the deeper ones, which `<cube-context>` draws as a › that
|
|
243
|
+
enters that path without asking `pick`). `insideOf`, `wouldLoop` and `refusalOf` are exported for an
|
|
244
|
+
app's own drop sheet. the part is `where`, after move, before whose and hide.
|
|
133
245
|
|
|
134
246
|
## the context cube
|
|
135
247
|
|
|
@@ -261,7 +373,9 @@ export class TodoContextScreen {
|
|
|
261
373
|
```
|
|
262
374
|
|
|
263
375
|
a screen that holds a different source or other words passes `[source]` and `[words]` instead of
|
|
264
|
-
the tokens.
|
|
376
|
+
the tokens. an app whose store gives a new object for the same piece when a pick changes it (a
|
|
377
|
+
rename, a hide) passes `[heldKey]` (its id, say), or the pick's answer is dropped as if another
|
|
378
|
+
piece were held. `[maxSide]` (880) caps the square on a wide screen; on a phone it is the host's width,
|
|
265
379
|
and never taller than the window less 48px. `level` is read inside a computed, so a source that
|
|
266
380
|
reads signals redraws by itself; one that does not is read again after every pick.
|
|
267
381
|
|