tutuca 0.9.113 → 0.9.115

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tutuca",
3
- "version": "0.9.113",
3
+ "version": "0.9.115",
4
4
  "type": "module",
5
5
  "description": "SPA framework with immutable state and virtual DOM; dependency-free browser bundle",
6
6
  "main": "./dist/tutuca.js",
@@ -24,27 +24,28 @@
24
24
  },
25
25
  "scripts": {
26
26
  "clean": "rm -rf dist skill",
27
- "dist": "bun scripts/dist.js",
28
- "dist-ext": "bun scripts/dist-ext.js",
29
- "dist-immutable": "bun scripts/dist-immutable.js",
30
- "dist-all": "bun run dist-immutable && bun run dist && bun run dist-ext && bun run smoke",
27
+ "dist": "node scripts/dist.js",
28
+ "dist-ext": "node scripts/dist-ext.js",
29
+ "dist-immutable": "node scripts/dist-immutable.js",
30
+ "dist-all": "npm run dist-immutable && npm run dist && npm run dist-ext && npm run smoke",
31
31
  "smoke": "node scripts/smoke.js",
32
- "release": "bun run dist-all && bun run sync-docs-storybook && bun run build-skill && (npm publish --access public; bun run clean-skill)",
33
- "release-dry": "bun run dist-all && bun run sync-docs-storybook && bun run build-skill && (npm publish --dry-run; bun run clean-skill)",
34
- "sync-docs-storybook": "bun scripts/sync-docs-storybook.js",
35
- "build-skill": "bun scripts/build-skill.js",
32
+ "release": "npm run dist-all && npm run sync-docs-storybook && npm run build-skill && (npm publish --access public; npm run clean-skill)",
33
+ "release-dry": "npm run dist-all && npm run sync-docs-storybook && npm run build-skill && (npm publish --dry-run; npm run clean-skill)",
34
+ "sync-docs-storybook": "node scripts/sync-docs-storybook.js",
35
+ "build-skill": "node scripts/build-skill.js",
36
36
  "clean-skill": "rm -rf skill",
37
- "test": "bun run dist && bun run dist-ext && bun test test/*.test.js",
38
- "test-watch": "bun test --watch test/*.test.js",
39
- "format": "bunx @biomejs/biome format --write",
40
- "lint": "bunx @biomejs/biome lint",
41
- "lint-fix": "bunx @biomejs/biome lint --write",
42
- "fix": "bunx @biomejs/biome check --write",
43
- "tutuca": "bun tools/tutuca.js",
44
- "storybook": "bun scripts/serve-storybook.js",
45
- "storybook:examples": "bun scripts/storybook-examples.js",
46
- "stresstest": "bun scripts/stresstest.js",
47
- "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"
37
+ "pretest": "npm run dist && npm run dist-ext",
38
+ "test": "vitest run",
39
+ "test-watch": "vitest",
40
+ "format": "biome format --write",
41
+ "lint": "biome lint",
42
+ "lint-fix": "biome lint --write",
43
+ "fix": "biome check --write",
44
+ "tutuca": "node tools/tutuca.js",
45
+ "storybook": "node scripts/serve-storybook.js",
46
+ "storybook:examples": "node scripts/storybook-examples.js",
47
+ "stresstest": "node scripts/stresstest.js",
48
+ "smoke-test": "node tools/tutuca.js lint ./test/todo.js && node tools/tutuca.js render ./test/todo.js && node tools/tutuca.js test ./test/todo.js && node tools/tutuca.js lint ./test/json.js && node tools/tutuca.js render ./test/json.js"
48
49
  },
49
50
  "sideEffects": [
50
51
  "./deps/chai.js"
@@ -92,7 +93,9 @@
92
93
  "devDependencies": {
93
94
  "@biomejs/biome": "^2.5.1",
94
95
  "chai": "^6.2.2",
96
+ "esbuild": "^0.28.1",
95
97
  "fast-check": "^4.8.0",
96
- "htmlparser2": "^12.0.0"
98
+ "htmlparser2": "^12.0.0",
99
+ "vitest": "^4.1.10"
97
100
  }
98
101
  }
@@ -10,10 +10,11 @@ Versatile nav list for sidebars, sub-menus, mega-menus, file trees.
10
10
 
11
11
  - Sidebars, dropdown contents, mobile drawer contents.
12
12
  - For a large horizontal nav bar with per-item popover panels, use **megamenu** instead.
13
+ - `menu-paged` turns `li > details > summary` submenus into drill-down pages: the open branch replaces the list and its summary becomes a "Back" row (label it with `aria-label`).
13
14
 
14
15
  ## Core classes
15
16
 
16
- `menu`; orientation `menu-vertical|horizontal`; size `menu-xs|sm|md|lg|xl`; child states `menu-active|disabled|title`.
17
+ `menu`; orientation `menu-vertical|horizontal`; navigation `menu-paged`; size `menu-xs|sm|md|lg|xl`; child states `menu-active|disabled|title`.
17
18
 
18
19
  ## Examples
19
20
 
@@ -819,6 +820,35 @@ Source: `playground/components/menu/menu-without-padding-and-border-radius.html`
819
820
  </ul>
820
821
  ```
821
822
 
823
+ ### Paged menu
824
+
825
+ Source: `playground/components/menu/paged-menu.html`
826
+
827
+ ```html
828
+ <ul class="menu menu-paged bg-base-200 rounded-box w-56">
829
+ <li><a>Item 1</a></li>
830
+ <li>
831
+ <details>
832
+ <summary>Parent</summary>
833
+ <ul>
834
+ <li><a>Submenu 1</a></li>
835
+ <li><a>Submenu 2</a></li>
836
+ <li>
837
+ <details>
838
+ <summary aria-label="Back to Parent">Nested parent</summary>
839
+ <ul>
840
+ <li><a>Nested 1</a></li>
841
+ <li><a>Nested 2</a></li>
842
+ </ul>
843
+ </details>
844
+ </li>
845
+ </ul>
846
+ </details>
847
+ </li>
848
+ <li><a>Item 3</a></li>
849
+ </ul>
850
+ ```
851
+
822
852
  ### Responsive vertical on small screen horizontal on large screen
823
853
 
824
854
  Source: `playground/components/menu/responsive-vertical-on-small-screen-horizontal-on-large-screen.html`
@@ -20,7 +20,7 @@ npm i -g tutuca
20
20
  tutuca <command> <module-path> [name] [flags]
21
21
 
22
22
  # from a checkout of this repo
23
- bun tools/tutuca.js <command> <module-path> [name] [flags]
23
+ node tools/tutuca.js <command> <module-path> [name] [flags]
24
24
  ```
25
25
 
26
26
  The command comes **first**, the module path second, an optional component
@@ -599,14 +599,32 @@ plain literal. (Genuine exceptions exist — e.g. a file input needs
599
599
 
600
600
  `@on.<event>+<mod>+<mod>=...`
601
601
 
602
+ Guards — run the handler only when they hold:
603
+
602
604
  - All events: `+ctrl`, `+cmd`/`+meta`, `+alt`
603
605
  - `keydown` only: `+send` (Enter), `+cancel` (Escape)
604
606
 
607
+ Effects — act on the DOM event, on all events:
608
+
609
+ - `+prevent` → `event.preventDefault()`
610
+ - `+stop` → `event.stopPropagation()`
611
+
605
612
  ```html
606
613
  <input @on.keydown+send="$submit value" @on.keydown+cancel="$reset" />
607
614
  <button @on.click+ctrl="$soloOnly">ctrl-click</button>
615
+ <form @on.submit+prevent="$save">…</form>
616
+ <input @on.keydown+send+prevent="$submit value" />
608
617
  ```
609
618
 
619
+ Effects apply only when every guard on the same handler passed, whatever
620
+ order they are written in: `+send+prevent` prevents on Enter and nothing
621
+ else. They run from the app's root listener, which is where tutuca listens
622
+ — that is invisible to `+prevent` (the default action happens after the
623
+ event finishes propagating) but it makes `+stop` narrower than it looks:
624
+ it stops listeners *outside* the app root only. DOM ancestors between the
625
+ target and the root have already seen the event, and tutuca runs a single
626
+ handler per event anyway, so `+stop` never suppresses another `@on`.
627
+
610
628
  ### Web Components & Custom Events
611
629
 
612
630
  Custom elements just work, and any `CustomEvent` they fire is reachable
@@ -11,9 +11,12 @@
11
11
  <input @on.input="$setN valueAsInt" />
12
12
  <button @on.click="$addItem JsonSelector">+</button>
13
13
 
14
- <!-- modifiers: keydown +send (Enter) / +cancel (Esc), and +ctrl/+cmd/+alt -->
14
+ <!-- guards: keydown +send (Enter) / +cancel (Esc), and +ctrl/+cmd/+alt -->
15
15
  <input @on.keydown+send="$submit value" @on.keydown+cancel="$reset" />
16
16
 
17
+ <!-- effects on any event: +prevent, +stop (applied only if the guards passed) -->
18
+ <form @on.submit+prevent="$save">…</form>
19
+
17
20
  <!-- custom elements: any CustomEvent reaches @on.<name>, detail is `value` -->
18
21
  <emoji-picker @on.emoji-click="onPick value"></emoji-picker>
19
22
  ```
@@ -30,7 +30,8 @@ export function getTests({ describe, test, expect }) {
30
30
  (`expect.objectContaining`, `toHaveBeenCalled…`, `toMatchSnapshot`) are
31
31
  **not** available — tutuca has no mocking layer.
32
32
  - `test` and `describe` are **Tutuca's own** subset of the common
33
- Mocha/Bun-style API, injected by `tutuca test` — not Bun's built-ins.
33
+ Mocha/Jest-style API, injected by `tutuca test` — they are not imported
34
+ from a test runner, so don't reach for one's extras.
34
35
  Available calls: `describe(title, fn)`, `describe(Component, fn)`,
35
36
  `describe(title, { component }, fn)`, and `test(title, fn)`. There is
36
37
  no `before` / `after` / `beforeEach` / `it` / skip-flag — don't reach
@@ -183,9 +184,9 @@ const r = collectIterBindings(MyComp, c, c.items, {
183
184
  `MyComp.make({ field: ... })` so handlers that read `this.field` see
184
185
  the value you want.
185
186
  - The redirect uses Node's `module.register`, which is how the `tutuca`
186
- bin runs. Under a Bun-driven CLI it degrades to the no-op stub — if you
187
- see `collectIterBindings` return `[]`, import it from `tutuca/dev`
188
- explicitly.
187
+ bin runs. On a runtime without loader-hook support it degrades to the
188
+ no-op stub — if you see `collectIterBindings` return `[]`, import it
189
+ from `tutuca/dev` explicitly.
189
190
 
190
191
  Example:
191
192