@cssints/data 0.0.0-stage → 0.33.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/LICENSE +21 -0
- package/README.md +174 -2
- package/dist/index.d.mts +14 -0
- package/dist/index.mjs +17 -0
- package/package.json +30 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alexei Accio
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,175 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @cssints/data
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Statistics over runtime values, computed by the browser's layout for [cssints](../../README.md): `max`, `sum` and
|
|
4
|
+
`count` of a list, the [dCSS](https://noscript.ing/compute) idea as one call member of `cssints/plugin` `scope()`. It
|
|
5
|
+
prints a small global rig and no class; there is no runtime. The browser lays the values out as widths, reads the
|
|
6
|
+
resulting width back as a number with a container query, and prints it with a counter.
|
|
7
|
+
|
|
8
|
+
```ts
|
|
9
|
+
import { data } from "@cssints/data" with { type: "cssints" };
|
|
10
|
+
|
|
11
|
+
// at a module's top level, once: the rig, and no class
|
|
12
|
+
data();
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```css
|
|
16
|
+
@layer _.k {
|
|
17
|
+
[data-data] {
|
|
18
|
+
display: inline-grid;
|
|
19
|
+
grid-template-columns: auto;
|
|
20
|
+
width: max-content;
|
|
21
|
+
overflow: clip;
|
|
22
|
+
}
|
|
23
|
+
[data-data] > ul {
|
|
24
|
+
margin: 0;
|
|
25
|
+
padding: 0;
|
|
26
|
+
list-style: none;
|
|
27
|
+
height: 0;
|
|
28
|
+
}
|
|
29
|
+
[data-data="max"] > ul {
|
|
30
|
+
display: grid;
|
|
31
|
+
}
|
|
32
|
+
[data-data="max"] > ul > li {
|
|
33
|
+
width: calc(var(--value) * 1px);
|
|
34
|
+
height: 0;
|
|
35
|
+
}
|
|
36
|
+
[data-data="sum"] > ul {
|
|
37
|
+
display: flex;
|
|
38
|
+
width: max-content;
|
|
39
|
+
}
|
|
40
|
+
[data-data="sum"] > ul > li {
|
|
41
|
+
flex: none;
|
|
42
|
+
width: calc(var(--value) * 1px);
|
|
43
|
+
height: 0;
|
|
44
|
+
}
|
|
45
|
+
[data-data="count"] > ul {
|
|
46
|
+
display: flex;
|
|
47
|
+
width: max-content;
|
|
48
|
+
}
|
|
49
|
+
[data-data="count"] > ul > li {
|
|
50
|
+
width: 1px;
|
|
51
|
+
height: 0;
|
|
52
|
+
}
|
|
53
|
+
[data-read] {
|
|
54
|
+
display: block;
|
|
55
|
+
container-type: inline-size;
|
|
56
|
+
}
|
|
57
|
+
[data-read] > * {
|
|
58
|
+
--data-result: round(100cqw / 1px);
|
|
59
|
+
}
|
|
60
|
+
[data-data="max"] [data-read] output::after,
|
|
61
|
+
[data-data="sum"] [data-read] output::after,
|
|
62
|
+
[data-data="count"] [data-read] output::after {
|
|
63
|
+
counter-reset: out var(--data-result);
|
|
64
|
+
content: counter(out);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## The DOM contract
|
|
70
|
+
|
|
71
|
+
```html
|
|
72
|
+
<figure data-data="max">
|
|
73
|
+
<ul aria-hidden="true">
|
|
74
|
+
<li style="--value: 12"></li>
|
|
75
|
+
<li style="--value: 40"></li>
|
|
76
|
+
<li style="--value: 30"></li>
|
|
77
|
+
</ul>
|
|
78
|
+
<b data-read><output></output></b>
|
|
79
|
+
</figure>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- **The figure** picks the statistic with `data-data`: `max`, `sum` or `count`. Any other value matches no statistic
|
|
83
|
+
rule and prints nothing.
|
|
84
|
+
- **The measuring list** is a ruler, not content: it is `aria-hidden` and has no height. Each `<li>` carries `--value`,
|
|
85
|
+
a unitless number of pixels. Nothing reads the list's text; the rig reads its widths.
|
|
86
|
+
- **The reader** is a `<b data-read>` (any element): a block that fills the figure's single auto column and is a
|
|
87
|
+
`container-type: inline-size` size container. Its children get `--data-result`, the reader's width in pixels as a
|
|
88
|
+
number; its `<output>` prints that number with a counter. Put the output inside the reader: CSS cannot hand a number
|
|
89
|
+
to a sibling.
|
|
90
|
+
|
|
91
|
+
## A worked example
|
|
92
|
+
|
|
93
|
+
`max` of 12, 40 and 30:
|
|
94
|
+
|
|
95
|
+
- the list is a grid of one implicit column, so its width is its widest item;
|
|
96
|
+
- each `<li>` is `calc(var(--value) * 1px)` wide and `0` tall: 12px, 40px, 30px, so the column is **40px**;
|
|
97
|
+
- the reader is a block in that column, so it is 40px wide; `round(100cqw / 1px)` is `40`;
|
|
98
|
+
- `counter-reset: out var(--data-result)` sets the counter to 40, and `content: counter(out)` paints `40`.
|
|
99
|
+
|
|
100
|
+
`sum` makes the list a hug-width flex row instead, so the row is `12 + 40 + 30 = 82px` and the counter prints `82`.
|
|
101
|
+
`count` is a row of `1px` items, so its width is the number of items: `3`.
|
|
102
|
+
|
|
103
|
+
## What layout computes
|
|
104
|
+
|
|
105
|
+
| `data-data` | The layout that is the answer | A list of 12, 40, 30 |
|
|
106
|
+
| ----------- | -------------------------------------- | -------------------- |
|
|
107
|
+
| `max` | the widest item (one auto grid column) | `40` |
|
|
108
|
+
| `sum` | the total (a hug-width flex row) | `82` |
|
|
109
|
+
| `count` | the number of items (a row of 1px) | `3` |
|
|
110
|
+
|
|
111
|
+
The reader's inline size is its width in the figure's column. Because it is `container-type: inline-size` (size
|
|
112
|
+
containment on the inline axis), its own contents cannot widen it: it is sized by the measuring list, not by the printed
|
|
113
|
+
answer. `round(100cqw / 1px)` divides the container width by a pixel, so the result is the width as a unitless number,
|
|
114
|
+
rounded to an integer.
|
|
115
|
+
|
|
116
|
+
## The rules
|
|
117
|
+
|
|
118
|
+
- **One member, no arguments.** `data()` is called at a module's top level; it prints no class and no import.
|
|
119
|
+
- **Once per sheet.** Each rule is a global identified by its text: `data()` in two modules, or twice in one, prints the
|
|
120
|
+
rig once.
|
|
121
|
+
- **The three names.** The statistic rules match only `max`, `sum` and `count`; the counter rule only applies inside
|
|
122
|
+
those figures. An unknown `data-data` gets the base figure and the measuring list, and prints nothing.
|
|
123
|
+
- **In `_.k`.** The rules are global rules, in the engine's kernel layer, like `global()`. A class layer beats them; do
|
|
124
|
+
not style the rig's own elements.
|
|
125
|
+
|
|
126
|
+
## Accessibility
|
|
127
|
+
|
|
128
|
+
The measuring list is `aria-hidden="true"`: it is a ruler, not content, and a reader should not hear three empty items.
|
|
129
|
+
The printed answer is **generated content** (`output::after`): no screen reader reads it as text, find-in-page does not
|
|
130
|
+
find it, and it is not copied. Do not make it the only place the number exists. Put the number in a `<figcaption>`, as
|
|
131
|
+
[dCSS](https://noscript.ing/compute) does, so the figure has a name and a value a reader and a search can reach:
|
|
132
|
+
|
|
133
|
+
```html
|
|
134
|
+
<figure data-data="max">
|
|
135
|
+
<ul aria-hidden="true">
|
|
136
|
+
<li style="--value: 12"></li>
|
|
137
|
+
<li style="--value: 40"></li>
|
|
138
|
+
<li style="--value: 30"></li>
|
|
139
|
+
</ul>
|
|
140
|
+
<b data-read><output></output></b>
|
|
141
|
+
<figcaption>Busiest hour: 40 requests</figcaption>
|
|
142
|
+
</figure>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The caption is text; keep it in step with the same values. When the host can render both (server-side or at the same
|
|
146
|
+
moment it writes `--value`), write the number there too.
|
|
147
|
+
|
|
148
|
+
## Limits
|
|
149
|
+
|
|
150
|
+
- **Needs container query units and `round()`.** `cqw` is Chrome 105, Firefox 110 and Safari 16; `round()` is Chrome
|
|
151
|
+
125, Firefox 118 and Safari 15.4. A browser without them prints nothing or an empty answer.
|
|
152
|
+
- **The answer only reaches the reader's subtree.** `--data-result` is a custom property on the reader's children; CSS
|
|
153
|
+
cannot hand a number to a sibling or to the figure. A `<figcaption>` outside the reader cannot read it. To show the
|
|
154
|
+
number elsewhere, put another reader there or use a script.
|
|
155
|
+
- **Pixels.** `--value` is a unitless, non-negative number that the rig multiplies by `1px`; widths cannot be negative
|
|
156
|
+
(a max of negatives is `0`), and the printed answer is a whole pixel because `round()` rounds it.
|
|
157
|
+
- **`count` counts `<li>` elements**, whether or not they carry `--value`. `max` and `sum` read `--value` only.
|
|
158
|
+
- **No median, average or sort.** This is the three primitives: a maximum, a sum and a count. The article's sorting,
|
|
159
|
+
`anchor()` and `sibling-index()` are not here.
|
|
160
|
+
- **The rig is global.** Its selectors target `[data-data]` and `[data-read]`, which a page may use for its own
|
|
161
|
+
content; do not repurpose those attributes. One figure per statistic.
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
cd packages/data && bun run test # the sheet through the engine: the rig once for two calls, no class, the rules
|
|
165
|
+
cd packages/data && bun run test:browsers # Chromium through playwright-core: 40, 82 and 3, then a changed value
|
|
166
|
+
cd packages/data && bun run typecheck
|
|
167
|
+
cd packages/data && bun run build
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Credits
|
|
171
|
+
|
|
172
|
+
The idea and the DOM contract are [Computing with CSS Layout](https://noscript.ing/compute) by Agustin Capeletto and
|
|
173
|
+
[dCSS](https://github.com/noscripting/dCSS): an auto grid column is a maximum, a hug-width flex row is a sum, a row of
|
|
174
|
+
1px items is a count, and a container query read back through `round(100cqw / 1px)` is the number, printed by a counter.
|
|
175
|
+
The rules are written here, as globals of `scope()`; no code is copied.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
declare const dataScope: import("cssints/plugin").Scope<"data", {
|
|
2
|
+
readonly data: {
|
|
3
|
+
readonly args: readonly [];
|
|
4
|
+
};
|
|
5
|
+
}>;
|
|
6
|
+
type Members = ReturnType<typeof dataScope.export>;
|
|
7
|
+
/**
|
|
8
|
+
* `data()`: prints the rig that computes `max`, `sum` or `count` of the `--value`s of a `<li>` list by layout and prints
|
|
9
|
+
* the answer with a counter. The figure picks the statistic with `data-data`; the answer reaches what lives inside
|
|
10
|
+
* `[data-read]` (CSS cannot hand a number to a sibling). No arguments, no class; call it at a module's top level. See
|
|
11
|
+
* the README for the DOM contract and the accessibility note.
|
|
12
|
+
*/
|
|
13
|
+
export declare const data: Members["data"];
|
|
14
|
+
export {};
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { scope } from "cssints/plugin";
|
|
2
|
+
// src/index.ts
|
|
3
|
+
const RULES = [
|
|
4
|
+
"[data-data] { display: inline-grid; grid-template-columns: auto; width: max-content; overflow: clip } [data-data] > ul { margin: 0; padding: 0; list-style: none; height: 0 }",
|
|
5
|
+
"[data-data=\"max\"] > ul { display: grid } [data-data=\"max\"] > ul > li { width: calc(var(--value) * 1px); height: 0 }",
|
|
6
|
+
"[data-data=\"sum\"] > ul { display: flex; width: max-content } [data-data=\"sum\"] > ul > li { flex: none; width: calc(var(--value) * 1px); height: 0 }",
|
|
7
|
+
"[data-data=\"count\"] > ul { display: flex; width: max-content } [data-data=\"count\"] > ul > li { width: 1px; height: 0 }",
|
|
8
|
+
"[data-read] { display: block; container-type: inline-size } [data-read] > * { --data-result: round(100cqw / 1px) } [data-data=\"max\"] [data-read] output::after, [data-data=\"sum\"] [data-read] output::after, [data-data=\"count\"] [data-read] output::after { counter-reset: out var(--data-result); content: counter(out) }"
|
|
9
|
+
];
|
|
10
|
+
/**
|
|
11
|
+
* `data()`: prints the rig that computes `max`, `sum` or `count` of the `--value`s of a `<li>` list by layout and prints
|
|
12
|
+
* the answer with a counter. The figure picks the statistic with `data-data`; the answer reaches what lives inside
|
|
13
|
+
* `[data-read]` (CSS cannot hand a number to a sibling). No arguments, no class; call it at a module's top level. See
|
|
14
|
+
* the README for the DOM contract and the accessibility note.
|
|
15
|
+
*/
|
|
16
|
+
const data = scope("data", { data: { args: [] } }).build({ data: () => ({ globals: RULES.map((css) => ({ css })) }) }).export().data;
|
|
17
|
+
export { data };
|
package/package.json
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cssints/data",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.33.0",
|
|
4
|
+
"description": "Statistics over runtime values, computed by the browser's layout for cssints: max, sum and count, printed by a counter",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/alexeiaccio/css-in-ts-compiler.git",
|
|
9
|
+
"directory": "packages/data"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://cssints.dev",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"type": "module",
|
|
16
|
+
"sideEffects": false,
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.mts",
|
|
20
|
+
"default": "./dist/index.mjs"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"cssints": "^0.33.0"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=22"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
}
|
|
32
|
+
}
|