tutuca 0.9.82 → 0.9.84
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/README.md +5 -3
- package/dist/tutuca-cli.js +13259 -12909
- package/dist/tutuca-dev.ext.js +551 -629
- package/dist/tutuca-dev.js +481 -570
- package/dist/tutuca-dev.min.js +2 -2
- package/dist/tutuca-extra.ext.js +333 -432
- package/dist/tutuca-extra.js +266 -365
- package/dist/tutuca-extra.min.js +2 -2
- package/dist/tutuca-storybook.js +283 -0
- package/dist/tutuca.ext.js +274 -280
- package/dist/tutuca.js +253 -259
- package/dist/tutuca.min.js +2 -2
- package/package.json +6 -2
- package/skill/tutuca/SKILL.md +2 -2
- package/skill/tutuca/advanced.md +14 -4
- package/skill/tutuca/cli.md +1 -0
- package/skill/tutuca/component-design.md +1 -1
- package/skill/tutuca/core.md +11 -0
- package/skill/tutuca/patterns/README.md +1 -0
- package/skill/tutuca/patterns/file-input.md +39 -0
- package/skill/tutuca-source/tutuca.ext.js +274 -280
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tutuca",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.84",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Zero-dependency SPA framework with immutable state and virtual DOM",
|
|
6
6
|
"main": "./dist/tutuca.js",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"./ext": "./dist/tutuca.ext.js",
|
|
14
14
|
"./extra-ext": "./dist/tutuca-extra.ext.js",
|
|
15
15
|
"./dev-ext": "./dist/tutuca-dev.ext.js",
|
|
16
|
+
"./storybook": "./dist/tutuca-storybook.js",
|
|
16
17
|
"./immutable": "./dist/immutable.js",
|
|
17
18
|
"./chai": "./dist/chai.js",
|
|
18
19
|
"./package.json": "./package.json"
|
|
@@ -40,7 +41,9 @@
|
|
|
40
41
|
"stresstest": "bun scripts/stresstest.js",
|
|
41
42
|
"smoke-test": "bun tools/tutuca.js lint ./test/todo.js && bun tools/tutuca.js render ./test/todo.js && bun tools/tutuca.js test ./test/todo.js && bun tools/tutuca.js lint ./test/json.js && bun tools/tutuca.js render ./test/json.js"
|
|
42
43
|
},
|
|
43
|
-
"sideEffects":
|
|
44
|
+
"sideEffects": [
|
|
45
|
+
"./deps/chai.js"
|
|
46
|
+
],
|
|
44
47
|
"files": [
|
|
45
48
|
"dist/tutuca.js",
|
|
46
49
|
"dist/tutuca.min.js",
|
|
@@ -52,6 +55,7 @@
|
|
|
52
55
|
"dist/tutuca.ext.js",
|
|
53
56
|
"dist/tutuca-extra.ext.js",
|
|
54
57
|
"dist/tutuca-dev.ext.js",
|
|
58
|
+
"dist/tutuca-storybook.js",
|
|
55
59
|
"dist/immutable.js",
|
|
56
60
|
"dist/chai.js",
|
|
57
61
|
"skill"
|
package/skill/tutuca/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tutuca
|
|
3
|
-
description: Use when authoring or reviewing tutuca modules — `component({...})` definitions, `html`...`` views, `@`-directives, `input` / `bubble` / `receive` / `response` / `alter` handlers, macros, or `getTests` exports — or when running the `tutuca` CLI (`lint` / `test` / `render` / `
|
|
3
|
+
description: Use when authoring or reviewing tutuca modules — `component({...})` definitions, `html`...`` views, `@`-directives, `input` / `bubble` / `receive` / `response` / `alter` handlers, macros, or `getTests` exports — or when running the `tutuca` CLI (`lint` / `test` / `render` / `show`). Covers the post-edit `tutuca lint <module>` → `test` → `render --title "<example>"` verification recipe.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
<!-- Source of truth: docs/skill/. The skill/tutuca/ copy is generated by scripts/build-skill.js — edit docs/skill/, not skill/. -->
|
|
@@ -9,7 +9,7 @@ description: Use when authoring or reviewing tutuca modules — `component({...}
|
|
|
9
9
|
|
|
10
10
|
Tutuca is an immutable-state SPA framework. See [core.md](./core.md)
|
|
11
11
|
for the framework primer and the post-edit verification recipe
|
|
12
|
-
(`tutuca <module
|
|
12
|
+
(`tutuca lint <module>` → `test` → `render --title "<example>"`).
|
|
13
13
|
|
|
14
14
|
## Companion skills
|
|
15
15
|
|
package/skill/tutuca/advanced.md
CHANGED
|
@@ -165,8 +165,8 @@ import { SEQ_INFO } from "tutuca";
|
|
|
165
165
|
class MyClass {
|
|
166
166
|
// ...
|
|
167
167
|
}
|
|
168
|
-
MyClass.prototype[SEQ_INFO] = (seq, visit) => {
|
|
169
|
-
for (const [k, v] of seq.entries()) visit(k, v, "
|
|
168
|
+
MyClass.prototype[SEQ_INFO] = (seq, visit, start, end) => {
|
|
169
|
+
for (const [k, v] of seq.entries()) visit(k, v, "sk");
|
|
170
170
|
};
|
|
171
171
|
```
|
|
172
172
|
|
|
@@ -175,8 +175,18 @@ is shared across module graphs (source vs. bundled tutuca). The
|
|
|
175
175
|
renderer reads `seq[SEQ_INFO]` directly (no `.constructor` lookup),
|
|
176
176
|
which is why the walker goes on the prototype, not as a static.
|
|
177
177
|
|
|
178
|
-
The third arg to `visit`
|
|
179
|
-
|
|
178
|
+
The third arg to `visit` must be `"sk"` (keyed entries) or `"si"`
|
|
179
|
+
(positional indexes): it is the meta key event-path reconstruction
|
|
180
|
+
reads to resolve an event back to its entry — any other value means
|
|
181
|
+
`@key` and keyed steps silently stop resolving inside `@each`.
|
|
182
|
+
|
|
183
|
+
`start`/`end` are an optional `[start, end)` slice produced by
|
|
184
|
+
`@loop-with` (Array.slice semantics). Walkers may ignore them, in
|
|
185
|
+
which case `@loop-with` ranges simply don't apply to that type.
|
|
186
|
+
|
|
187
|
+
See `docs/examples/custom-collection.js` for a complete worked
|
|
188
|
+
example: an immutable keyed list whose walker supports slicing and
|
|
189
|
+
whose entries resolve `@key` in event handlers.
|
|
180
190
|
|
|
181
191
|
## Tailwind / MargaUI Class Compilation (extra build)
|
|
182
192
|
|
package/skill/tutuca/cli.md
CHANGED
|
@@ -42,6 +42,7 @@ Use `--module=<path>` if the path conflicts with positional parsing.
|
|
|
42
42
|
| `test <module> [name]` | Run tests defined by `getTests({ describe, test, expect })`. Filter by component name, `--grep <pattern>`, or `--bail`. Exits **4** on any failure |
|
|
43
43
|
| `help [cmd]` | Show usage. No module path needed |
|
|
44
44
|
| `feedback [message]` | Append a feedback note (positional or stdin) to `~/.tutuca/feedback.jsonl`. No module path needed |
|
|
45
|
+
| `install-skill [name]` | Copy a bundled skill (`tutuca`, `margaui`, `immutable-js`, or `--all`) into `.claude/skills/`. No module path needed |
|
|
45
46
|
| `agent-context` | Print a versioned JSON schema of every command, flag, exit code, and error code. No module path needed |
|
|
46
47
|
|
|
47
48
|
## Global flags
|
|
@@ -119,7 +119,7 @@ A compact worked version of the first four (`method`, `bubble`, `send`/`receive`
|
|
|
119
119
|
→ [advanced.md](./advanced.md) "Pitfall: `@if.class` payloads are invisible to
|
|
120
120
|
the scanner", and the worked decoy view in `personal-site.js`.
|
|
121
121
|
|
|
122
|
-
- **Do close the loop after every change** with `tutuca <module
|
|
122
|
+
- **Do close the loop after every change** with `tutuca lint <module>` → `test` →
|
|
123
123
|
`render`. → [core.md](./core.md) "Verifying changes"
|
|
124
124
|
|
|
125
125
|
## Smells & refactors
|
package/skill/tutuca/core.md
CHANGED
|
@@ -977,6 +977,17 @@ export function getExamples() {
|
|
|
977
977
|
export function getTests({ describe, test, expect }) { /*...*/ } // optional — see cli.md
|
|
978
978
|
```
|
|
979
979
|
|
|
980
|
+
Best practice: have `getComponents()` return **every** component the module
|
|
981
|
+
defines — child and helper components included — and give each one at least
|
|
982
|
+
one item in `getExamples()`. A component left out of `getComponents()` is
|
|
983
|
+
invisible to `tutuca lint`/`render`/`test`, so it silently loses linting and
|
|
984
|
+
render coverage. If your components already live behind a differently named
|
|
985
|
+
export, alias it instead of teaching tools a new name:
|
|
986
|
+
|
|
987
|
+
```js
|
|
988
|
+
export { allMyComponents as getComponents } from "./app.js";
|
|
989
|
+
```
|
|
990
|
+
|
|
980
991
|
## See also
|
|
981
992
|
|
|
982
993
|
- [component-design.md](./component-design.md) — design judgment for shaping a
|
|
@@ -36,6 +36,7 @@ task.
|
|
|
36
36
|
|
|
37
37
|
- [Bind text and attributes](bind-text-and-attributes.md) — `@text`, `:attr`, `$'…'` templates, scope enrichment.
|
|
38
38
|
- [Handle events](handle-events.md) — `@on.<event>`, handler args, modifiers, custom events.
|
|
39
|
+
- [Read a picked file](file-input.md) — `@on.change="… event"` and reading `event.target.files`.
|
|
39
40
|
|
|
40
41
|
## Component communication
|
|
41
42
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Read a picked file
|
|
2
|
+
|
|
3
|
+
**Problem:** let the user pick a file and show its metadata.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
component({
|
|
7
|
+
name: "FilePicker",
|
|
8
|
+
fields: { name: "", size: 0, type: "", hasFile: false },
|
|
9
|
+
input: {
|
|
10
|
+
// `event` is the raw DOM event; the File is on event.target.files
|
|
11
|
+
onPickFile(event) {
|
|
12
|
+
const file = event.target.files?.[0];
|
|
13
|
+
if (!file) return this.setHasFile(false);
|
|
14
|
+
return this.setName(file.name)
|
|
15
|
+
.setSize(file.size)
|
|
16
|
+
.setType(file.type)
|
|
17
|
+
.setHasFile(true);
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
view: html`<section>
|
|
21
|
+
<input type="file" @on.change="onPickFile event" />
|
|
22
|
+
<p @hide=".hasFile">No file selected yet.</p>
|
|
23
|
+
<dl @show=".hasFile">
|
|
24
|
+
<dt>Name</dt><dd @text=".name"></dd>
|
|
25
|
+
<dt>Size</dt><dd @text=".size"></dd>
|
|
26
|
+
<dt>Type</dt><dd @text=".type"></dd>
|
|
27
|
+
</dl>
|
|
28
|
+
</section>`,
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Pass `event` (not `value`) to the handler: for a file input `value` is just the
|
|
33
|
+
fake `C:\fakepath\…` string, while `event.target.files` holds the real `File`
|
|
34
|
+
objects. The metadata (`name`/`size`/`type`/`lastModified`) is available
|
|
35
|
+
synchronously; the *contents* are not — read those with the async `File` API
|
|
36
|
+
(`file.text()`, `file.arrayBuffer()`) and feed the result back in through a
|
|
37
|
+
`request`/`response` or a follow-up `send`. Flatten what you need into fields so
|
|
38
|
+
the view can bind each piece; gate the summary on a `hasFile` flag with
|
|
39
|
+
`@show`/`@hide`.
|