tutuca 0.9.103 → 0.9.104

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.
@@ -16170,7 +16170,24 @@ function tutucaSource(base) {
16170
16170
  return "node_modules";
16171
16171
  return "local dist";
16172
16172
  }
16173
- function buildImports(base, { margaui }) {
16173
+ function resolveMargaui(projectDir, { forCdn, override }) {
16174
+ if (override) {
16175
+ const jsUrl = override.startsWith("http") ? override : `/${relative2(projectDir, resolve5(projectDir, override)).split(sep).join("/")}`;
16176
+ return { jsUrl, themeUrl: MARGAUI_THEME, source: "override" };
16177
+ }
16178
+ if (!forCdn) {
16179
+ const localJs = resolve5(projectDir, "node_modules", "margaui", "dist", "margaui.min.js");
16180
+ if (existsSync4(localJs)) {
16181
+ return {
16182
+ jsUrl: "/node_modules/margaui/dist/margaui.min.js",
16183
+ themeUrl: "/node_modules/margaui/dist/themes/theme.css",
16184
+ source: "node_modules"
16185
+ };
16186
+ }
16187
+ }
16188
+ return { jsUrl: MARGAUI_CDN, themeUrl: MARGAUI_THEME, source: "CDN" };
16189
+ }
16190
+ function buildImports(base, { margauiEnabled, margauiJsUrl }) {
16174
16191
  const dev = `${base}/tutuca-dev.js`;
16175
16192
  const imports = {
16176
16193
  tutuca: dev,
@@ -16179,13 +16196,13 @@ function buildImports(base, { margaui }) {
16179
16196
  "tutuca/storybook": `${base}/tutuca-storybook.js`,
16180
16197
  "tutuca/components": `${base}/tutuca-components.js`
16181
16198
  };
16182
- if (margaui)
16183
- imports.margaui = MARGAUI_CDN;
16199
+ if (margauiEnabled)
16200
+ imports.margaui = margauiJsUrl;
16184
16201
  return imports;
16185
16202
  }
16186
- function renderIndexHtml(imports, { margaui, bootstrapUrl }) {
16187
- const theme = margaui ? `
16188
- <link rel="stylesheet" href="${MARGAUI_THEME}" />` : "";
16203
+ function renderIndexHtml(imports, { margauiEnabled, margauiThemeUrl, bootstrapUrl }) {
16204
+ const theme = margauiEnabled ? `
16205
+ <link rel="stylesheet" href="${margauiThemeUrl}" />` : "";
16189
16206
  return `<!doctype html>
16190
16207
  <html lang="en">
16191
16208
  <head>
@@ -16203,9 +16220,9 @@ ${JSON.stringify({ imports }, null, 6)}
16203
16220
  </html>
16204
16221
  `;
16205
16222
  }
16206
- function renderBootstrap(devModuleUrls, { margaui, check, inspect: inspect3, noCache }) {
16223
+ function renderBootstrap(devModuleUrls, { margauiEnabled, check, inspect: inspect3, noCache }) {
16207
16224
  const lines = ['import { mountStorybook } from "tutuca/storybook";'];
16208
- if (margaui) {
16225
+ if (margauiEnabled) {
16209
16226
  lines.push('import { compileClassesToStyleText } from "tutuca/extra";');
16210
16227
  lines.push('import { compile } from "margaui";');
16211
16228
  }
@@ -16219,7 +16236,7 @@ function renderBootstrap(devModuleUrls, { margaui, check, inspect: inspect3, noC
16219
16236
  });
16220
16237
  const modules = devModuleUrls.map((_, i) => `m${i}`).join(", ");
16221
16238
  const optParts = [];
16222
- if (margaui)
16239
+ if (margauiEnabled)
16223
16240
  optParts.push("compileCss: (app) => compileClassesToStyleText(app, compile)");
16224
16241
  if (inspect3)
16225
16242
  optParts.push("dev: { shadowCheckComponent, runTests, expect }");
@@ -16354,6 +16371,8 @@ async function run4(argv, opts = {}) {
16354
16371
  options: {
16355
16372
  port: { type: "string" },
16356
16373
  out: { type: "string" },
16374
+ margaui: { type: "string" },
16375
+ "margaui-cdn": { type: "boolean", default: false },
16357
16376
  "no-margaui": { type: "boolean", default: false },
16358
16377
  "no-check": { type: "boolean", default: false },
16359
16378
  "no-inspect": { type: "boolean", default: false },
@@ -16366,20 +16385,27 @@ async function run4(argv, opts = {}) {
16366
16385
  });
16367
16386
  if (parsed.values.help) {
16368
16387
  process.stdout.write(`tutuca storybook [dir] [--port <n>] [--out <dir>] [--dry-run]
16369
- [--no-margaui] [--no-check] [--no-inspect] [--no-tests]
16370
- [--no-cache]
16388
+ [--margaui <url|path>] [--margaui-cdn] [--no-margaui]
16389
+ [--no-check] [--no-inspect] [--no-tests] [--no-cache]
16371
16390
 
16372
16391
  Auto-discovers co-located *.dev.js modules (recursively, skipping
16373
16392
  node_modules/dotdirs) and serves a live storybook that mounts them via
16374
16393
  the tutuca/storybook library. Zero setup.
16375
16394
 
16395
+ margaui styling loads local-first: it's used from node_modules/margaui
16396
+ when installed (offline-capable), else from the CDN.
16397
+
16376
16398
  [dir] project root to scan and serve (default: cwd)
16377
16399
  --port <n> preferred port (default 4321; falls back to a free port)
16378
- --out <dir> write a static index.html + bootstrap (CDN import map)
16379
- instead of serving; host it from the project root
16400
+ --out <dir> write a static index.html + bootstrap (CDN import map for
16401
+ both tutuca and margaui) instead of serving; host it from
16402
+ the project root
16380
16403
  --dry-run do all the prep (discover, import and normalize modules,
16381
16404
  resolve the runtime, run tests) and print what would be
16382
16405
  shown instead of serving; pass --json for structured output
16406
+ --margaui <url|path> use a specific margaui build (URL, or path inside
16407
+ the project) instead of auto-detecting / the CDN
16408
+ --margaui-cdn force the margaui CDN even if node_modules/margaui exists
16383
16409
  --no-margaui skip margaui styling (renders functional but unstyled)
16384
16410
  --no-check skip the in-browser check(app) dev validation
16385
16411
  --no-inspect skip the per-example Component/Instance/Data/Lint/Test tabs
@@ -16404,7 +16430,9 @@ async function run4(argv, opts = {}) {
16404
16430
  hint: "Create a co-located <name>.dev.js exporting getComponents() and getExamples()."
16405
16431
  });
16406
16432
  }
16407
- const margaui = !parsed.values["no-margaui"];
16433
+ const margauiEnabled = !parsed.values["no-margaui"];
16434
+ const margauiOverride = parsed.values.margaui;
16435
+ const forceMargauiCdn = parsed.values["margaui-cdn"];
16408
16436
  const check = !parsed.values["no-check"];
16409
16437
  const inspect3 = !parsed.values["no-inspect"];
16410
16438
  const noCache = parsed.values["no-cache"];
@@ -16413,10 +16441,15 @@ async function run4(argv, opts = {}) {
16413
16441
  const outDir = resolve5(parsed.values.out);
16414
16442
  mkdirSync3(outDir, { recursive: true });
16415
16443
  const { base: base2 } = resolveTutucaBase(projectDir, self, true);
16416
- const imports2 = buildImports(base2, { margaui });
16444
+ const mg2 = resolveMargaui(projectDir, { forCdn: true, override: margauiOverride });
16445
+ const imports2 = buildImports(base2, { margauiEnabled, margauiJsUrl: mg2.jsUrl });
16417
16446
  const bootstrapName = "tutuca-storybook.bootstrap.js";
16418
- writeFileSync(resolve5(outDir, "index.html"), renderIndexHtml(imports2, { margaui, bootstrapUrl: `./${bootstrapName}` }));
16419
- writeFileSync(resolve5(outDir, bootstrapName), renderBootstrap(devModuleUrls, { margaui, check, inspect: inspect3, noCache }));
16447
+ writeFileSync(resolve5(outDir, "index.html"), renderIndexHtml(imports2, {
16448
+ margauiEnabled,
16449
+ margauiThemeUrl: mg2.themeUrl,
16450
+ bootstrapUrl: `./${bootstrapName}`
16451
+ }));
16452
+ writeFileSync(resolve5(outDir, bootstrapName), renderBootstrap(devModuleUrls, { margauiEnabled, check, inspect: inspect3, noCache }));
16420
16453
  process.stdout.write(`wrote static storybook → ${relative2(process.cwd(), outDir) || "."}/
16421
16454
  index.html + ${bootstrapName} (${devModuleUrls.length} dev modules, CDN import map)
16422
16455
  Host it from the project root so /*.dev.js paths resolve.
@@ -16425,7 +16458,8 @@ async function run4(argv, opts = {}) {
16425
16458
  }
16426
16459
  if (parsed.values["dry-run"]) {
16427
16460
  const { base: base2 } = resolveTutucaBase(projectDir, self, false);
16428
- const imports2 = buildImports(base2, { margaui });
16461
+ const mg2 = resolveMargaui(projectDir, { forCdn: forceMargauiCdn, override: margauiOverride });
16462
+ const imports2 = buildImports(base2, { margauiEnabled, margauiJsUrl: mg2.jsUrl });
16429
16463
  const modules = await discoverModules(projectDir, devModuleUrls);
16430
16464
  const tests = parsed.values["no-tests"] ? null : await runDevTests(projectDir, devModuleUrls);
16431
16465
  const componentNameConflicts = await checkComponentNameConflicts(projectDir, devModuleUrls);
@@ -16433,7 +16467,8 @@ async function run4(argv, opts = {}) {
16433
16467
  const result = {
16434
16468
  projectDir,
16435
16469
  tutuca: { source, base: base2, version: self.version },
16436
- options: { margaui, check, noCache, runTests: !parsed.values["no-tests"] },
16470
+ margaui: margauiEnabled ? { source: mg2.source, jsUrl: mg2.jsUrl, themeUrl: mg2.themeUrl } : null,
16471
+ options: { margaui: margauiEnabled, check, noCache, runTests: !parsed.values["no-tests"] },
16437
16472
  imports: imports2,
16438
16473
  modules,
16439
16474
  tests,
@@ -16447,7 +16482,7 @@ async function run4(argv, opts = {}) {
16447
16482
  process.stdout.write(`tutuca storybook dry run (no server started)
16448
16483
  project: ${projectDir}
16449
16484
  tutuca runtime: ${source} (${base2}, version ${self.version})
16450
- margaui: ${margaui ? "on" : "off"}, in-browser check: ${check ? "on" : "off"}, cache: ${noCache ? "off" : "on"}
16485
+ margaui: ${margauiEnabled ? `on (${mg2.source})` : "off"}, in-browser check: ${check ? "on" : "off"}, cache: ${noCache ? "off" : "on"}
16451
16486
  ${modules.length} dev module(s):
16452
16487
  `);
16453
16488
  for (const m of modules) {
@@ -16507,9 +16542,14 @@ async function run4(argv, opts = {}) {
16507
16542
  process.stdout.write(formatComponentNameConflict(c));
16508
16543
  }
16509
16544
  const { base, serveDist } = resolveTutucaBase(projectDir, self, false);
16510
- const imports = buildImports(base, { margaui });
16511
- const indexHtml = renderIndexHtml(imports, { margaui, bootstrapUrl: BOOTSTRAP_URL });
16512
- const bootstrapJs = renderBootstrap(devModuleUrls, { margaui, check, inspect: inspect3, noCache });
16545
+ const mg = resolveMargaui(projectDir, { forCdn: forceMargauiCdn, override: margauiOverride });
16546
+ const imports = buildImports(base, { margauiEnabled, margauiJsUrl: mg.jsUrl });
16547
+ const indexHtml = renderIndexHtml(imports, {
16548
+ margauiEnabled,
16549
+ margauiThemeUrl: mg.themeUrl,
16550
+ bootstrapUrl: BOOTSTRAP_URL
16551
+ });
16552
+ const bootstrapJs = renderBootstrap(devModuleUrls, { margauiEnabled, check, inspect: inspect3, noCache });
16513
16553
  const server = createServer((req, res) => {
16514
16554
  const path = req.url.split("?")[0];
16515
16555
  if (path === "/" || path === "/index.html") {
@@ -16539,7 +16579,8 @@ async function run4(argv, opts = {}) {
16539
16579
  server.on("listening", () => {
16540
16580
  const actual = server.address().port;
16541
16581
  const where = tutucaSource(base);
16542
- process.stdout.write(`tutuca storybook: http://localhost:${actual}/ (${devModuleUrls.length} dev modules, tutuca from ${where})
16582
+ const margauiFrom = margauiEnabled ? `, margaui from ${mg.source}` : "";
16583
+ process.stdout.write(`tutuca storybook: http://localhost:${actual}/ (${devModuleUrls.length} dev modules, tutuca from ${where}${margauiFrom})
16543
16584
  `);
16544
16585
  });
16545
16586
  server.listen(preferred);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tutuca",
3
- "version": "0.9.103",
3
+ "version": "0.9.104",
4
4
  "type": "module",
5
5
  "description": "Zero-dependency SPA framework with immutable state and virtual DOM",
6
6
  "main": "./dist/tutuca.js",
@@ -5,11 +5,11 @@ description: Use when writing HTML/CSS that uses the margaui component library
5
5
 
6
6
  # margaui
7
7
 
8
- margaui is a Tailwind v4–native CSS component library: 65 components defined as Tailwind v4 `@utility` classes, plus 35 themes selected via `data-theme` on any ancestor element.
8
+ margaui is a Tailwind v4–native CSS component library: 68 components defined as Tailwind v4 `@utility` classes, plus 35 themes selected via `data-theme` on any ancestor element.
9
9
 
10
10
  ## Relationship to daisyUI
11
11
 
12
- margaui is **API-compatible with [daisyUI](https://daisyui.com/)**. The class names (`btn`, `btn-primary`, `card`, `card-body`, `alert-info`, `modal-box`, `dropdown-content`, …), modifier vocabulary, and DOM structure mirror daisyUI. Differences are implementation-level (Tailwind v4 native, in-browser compiler, `@supports` fallbacks for `color-mix`), not API-level.
12
+ margaui is **API-compatible with [daisyUI](https://daisyui.com/)** and currently tracks **daisyUI v5.6.6**. The class names (`btn`, `btn-primary`, `card`, `card-body`, `alert-info`, `modal-box`, `dropdown-content`, …), modifier vocabulary, and DOM structure mirror daisyUI. Differences are implementation-level (Tailwind v4 native, in-browser compiler, `@supports` fallbacks for `color-mix`), not API-level.
13
13
 
14
14
  Practical implication: **daisyUI documentation and examples are valid references** when this skill doesn't cover something. If a component is documented for daisyUI, the same markup works in margaui.
15
15
 
@@ -29,6 +29,7 @@ Set on any element (most often `<html>` or `<body>`):
29
29
  - **Modifier suffixes are consistent.** Most components share the same vocabulary: color (`-primary`, `-secondary`, `-accent`, `-info`, `-success`, `-warning`, `-error`, `-neutral`, `-ghost`), style (`-outline`, `-soft`, `-dash`), size (`-xs`, `-sm`, `-md`, `-lg`, `-xl`), state (`-active`, `-disabled`).
30
30
  - **Tailwind utilities work normally.** Responsive prefixes (`sm:`, `md:`, …), state variants (`hover:`, `focus:`, …), and arbitrary values all compose with margaui classes.
31
31
  - **`@utility` classes, not `@apply`.** Internally components are defined with Tailwind v4's `@utility` directive, so they tree-shake on demand and can be combined freely.
32
+ - **Color modifiers are generated, not hand-written.** A component's color variants (`btn-primary`, `badge-success`, `alert-info`, …) resolve from the theme's 16 semantic colors via Tailwind v4's `--value(--color-*)`, so one definition per component covers every color and tracks the active `data-theme`.
32
33
 
33
34
  ## Component index
34
35
 
@@ -36,6 +37,7 @@ Read the linked file when the user's task involves that component. Each file has
36
37
 
37
38
  - [accordion](components/accordion.md) — collapsible sections (single-open via radio, free via details)
38
39
  - [alert](components/alert.md) — inline notification box (info / success / warning / error)
40
+ - [aura](components/aura.md) — animated glowing border wrapper (rainbow, holo, dual, silver, gold, glow)
39
41
  - [avatar](components/avatar.md) — user picture / placeholder, with optional ring, mask, presence
40
42
  - [badge](components/badge.md) — small label / counter chip
41
43
  - [breadcrumbs](components/breadcrumbs.md) — path-style navigation trail
@@ -69,6 +71,7 @@ Read the linked file when the user's task involves that component. Each file has
69
71
  - [list](components/list.md) — vertical list with grid-style columns
70
72
  - [loading](components/loading.md) — loading spinner / dots / bars / ring / ball / infinity
71
73
  - [mask](components/mask.md) — clip an element to a shape (circle, hex, star, …)
74
+ - [megamenu](components/megamenu.md) — large horizontal nav bar whose items open big popover panels
72
75
  - [menu](components/menu.md) — vertical/horizontal nav list (sidebar, sub-menus)
73
76
  - [mockup-browser](components/mockup-browser.md) — browser-window chrome wrapper for screenshots
74
77
  - [mockup-code](components/mockup-code.md) — terminal/code-block visual
@@ -76,6 +79,7 @@ Read the linked file when the user's task involves that component. Each file has
76
79
  - [mockup-window](components/mockup-window.md) — OS-window chrome wrapper for screenshots
77
80
  - [modal](components/modal.md) — dialog / pop-up (native `<dialog>` or checkbox-driven)
78
81
  - [navbar](components/navbar.md) — top navigation bar with start/center/end slots
82
+ - [otp](components/otp.md) — one-time-password digit input (2FA / verification codes)
79
83
  - [pagination](components/pagination.md) — paged-navigation button row
80
84
  - [progress](components/progress.md) — linear progress bar (`<progress>`)
81
85
  - [radial-progress](components/radial-progress.md) — circular progress indicator
@@ -0,0 +1,97 @@
1
+ # aura
2
+
3
+ _animated glowing border wrapper (rainbow, holo, dual, silver, gold, glow)_
4
+
5
+ ## What it does
6
+
7
+ Wraps any element in an animated conic-gradient border light. Auto-picks corner radius when wrapping a card/alert/button/input/select/checkbox/toggle/badge.
8
+
9
+ ## When to use
10
+
11
+ - Highlighting the single most important button, card, or promo element on a page.
12
+ - Not for general emphasis — use sparingly, it's an eye-catching animated effect.
13
+
14
+ ## Core classes
15
+
16
+ `aura`; style `aura-rainbow|holo|dual|silver|gold|glow`; size `aura-xs|sm|md|lg|xl`.
17
+
18
+ ## Examples
19
+
20
+ ### Aura sizes
21
+
22
+ Source: `playground/components/aura/aura-sizes.html`
23
+
24
+ ```html
25
+ <div class="flex flex-wrap gap-6 items-center">
26
+ <div class="aura aura-xs">
27
+ <button class="btn btn-primary">xs</button>
28
+ </div>
29
+ <div class="aura aura-sm">
30
+ <button class="btn btn-primary">sm</button>
31
+ </div>
32
+ <div class="aura aura-md">
33
+ <button class="btn btn-primary">md</button>
34
+ </div>
35
+ <div class="aura aura-lg">
36
+ <button class="btn btn-primary">lg</button>
37
+ </div>
38
+ <div class="aura aura-xl">
39
+ <button class="btn btn-primary">xl</button>
40
+ </div>
41
+ </div>
42
+ ```
43
+
44
+ ### Aura styles
45
+
46
+ Source: `playground/components/aura/aura-styles.html`
47
+
48
+ ```html
49
+ <div class="flex flex-wrap gap-6 items-center">
50
+ <div class="aura">
51
+ <button class="btn">default</button>
52
+ </div>
53
+ <div class="aura aura-rainbow">
54
+ <button class="btn">rainbow</button>
55
+ </div>
56
+ <div class="aura aura-holo">
57
+ <button class="btn">holo</button>
58
+ </div>
59
+ <div class="aura aura-dual">
60
+ <button class="btn">dual</button>
61
+ </div>
62
+ <div class="aura aura-silver">
63
+ <button class="btn">silver</button>
64
+ </div>
65
+ <div class="aura aura-gold">
66
+ <button class="btn">gold</button>
67
+ </div>
68
+ <div class="aura aura-glow">
69
+ <button class="btn">glow</button>
70
+ </div>
71
+ </div>
72
+ ```
73
+
74
+ ### Aura wrapping a button
75
+
76
+ Source: `playground/components/aura/aura-wrapping-a-button.html`
77
+
78
+ ```html
79
+ <div class="aura">
80
+ <button class="btn btn-primary">Buy now</button>
81
+ </div>
82
+ ```
83
+
84
+ ### Aura wrapping a card
85
+
86
+ Source: `playground/components/aura/aura-wrapping-a-card.html`
87
+
88
+ ```html
89
+ <div class="aura aura-rainbow">
90
+ <div class="card bg-base-100 w-64 shadow-sm">
91
+ <div class="card-body">
92
+ <h2 class="card-title">Featured</h2>
93
+ <p>This card is wrapped in an aura effect.</p>
94
+ </div>
95
+ </div>
96
+ </div>
97
+ ```
@@ -0,0 +1,131 @@
1
+ # megamenu
2
+
3
+ _large horizontal nav bar whose items open big popover panels_
4
+
5
+ ## What it does
6
+
7
+ Top-of-page horizontal menu where each item opens a popover (via the native Popover API) containing a menu or arbitrary content. Collapses to a vertical popover on small screens via `megamenu-vertical`.
8
+
9
+ ## When to use
10
+
11
+ - Large-screen primary navigation with rich per-item content (site-wide nav with categorized links).
12
+ - For a simple sidebar/dropdown list without per-item popovers, use **menu** instead.
13
+ - Requires a browser with Popover API + CSS anchor positioning support.
14
+
15
+ ## Core classes
16
+
17
+ `megamenu` on the container (a `popover` element); `megamenu-active` on the sliding indicator `<span>`; width `megamenu-wide|full`; direction `megamenu-vertical`; size `megamenu-xs|sm|md|lg|xl`.
18
+
19
+ ## Examples
20
+
21
+ ### Megamenu
22
+
23
+ Source: `playground/components/megamenu/megamenu.html`
24
+
25
+ ```html
26
+ <!-- popovertarget must match the id of the corresponding popover, and each id must be unique -->
27
+ <button class="btn sm:hidden" popovertarget="my-megamenu-1">Menu</button>
28
+
29
+ <div class="megamenu max-sm:megamenu-vertical p-2 border border-base-300" id="my-megamenu-1" popover>
30
+ <span class="megamenu-active"></span>
31
+
32
+ <button popovertarget="a1">Services</button>
33
+ <div id="a1" popover>
34
+ <ul class="menu">
35
+ <li><a>Enterprise</a></li>
36
+ <li><a>CRM software</a></li>
37
+ <li><a>Security</a></li>
38
+ <li><a>Consulting</a></li>
39
+ </ul>
40
+ </div>
41
+
42
+ <button popovertarget="a2">AI</button>
43
+ <div id="a2" popover>
44
+ <ul class="menu">
45
+ <li><a>AI infrastructure</a></li>
46
+ <li><a>Image generation</a></li>
47
+ <li><a>MCP servers</a></li>
48
+ </ul>
49
+ </div>
50
+
51
+ <button popovertarget="a3">Cloud Solutions</button>
52
+ <div id="a3" popover>
53
+ <ul class="menu">
54
+ <li><a>Cloud computing</a></li>
55
+ <li><a>Storage solutions</a></li>
56
+ <li><a>Database services</a></li>
57
+ <li><a>CDN performance</a></li>
58
+ </ul>
59
+ </div>
60
+ </div>
61
+ ```
62
+
63
+ ### Megamenu sizes
64
+
65
+ Source: `playground/components/megamenu/megamenu-sizes.html`
66
+
67
+ ```html
68
+ <div class="flex flex-col gap-2">
69
+ <div class="megamenu megamenu-sm p-2 border border-base-300" id="my-megamenu-sm" popover="manual">
70
+ <span class="megamenu-active"></span>
71
+ <button popovertarget="c1">One</button>
72
+ <div id="c1" popover>
73
+ <ul class="menu">
74
+ <li><a>Link</a></li>
75
+ </ul>
76
+ </div>
77
+ <button popovertarget="c2">Two</button>
78
+ <div id="c2" popover>
79
+ <ul class="menu">
80
+ <li><a>Link</a></li>
81
+ </ul>
82
+ </div>
83
+ </div>
84
+
85
+ <div class="megamenu megamenu-lg p-2 border border-base-300" id="my-megamenu-lg" popover="manual">
86
+ <span class="megamenu-active"></span>
87
+ <button popovertarget="c3">One</button>
88
+ <div id="c3" popover>
89
+ <ul class="menu">
90
+ <li><a>Link</a></li>
91
+ </ul>
92
+ </div>
93
+ <button popovertarget="c4">Two</button>
94
+ <div id="c4" popover>
95
+ <ul class="menu">
96
+ <li><a>Link</a></li>
97
+ </ul>
98
+ </div>
99
+ </div>
100
+ </div>
101
+ ```
102
+
103
+ ### Megamenu wide
104
+
105
+ Source: `playground/components/megamenu/megamenu-wide.html`
106
+
107
+ ```html
108
+ <button class="btn sm:hidden" popovertarget="my-megamenu-2">Menu</button>
109
+
110
+ <div class="megamenu megamenu-wide max-sm:megamenu-vertical p-2 border border-base-300" id="my-megamenu-2" popover>
111
+ <span class="megamenu-active"></span>
112
+
113
+ <button popovertarget="b1">Products</button>
114
+ <div id="b1" popover>
115
+ <ul class="menu md:menu-horizontal">
116
+ <li><a>Analytics</a></li>
117
+ <li><a>Automation</a></li>
118
+ <li><a>Reporting</a></li>
119
+ </ul>
120
+ </div>
121
+
122
+ <button popovertarget="b2">Pricing</button>
123
+ <div id="b2" popover>
124
+ <ul class="menu md:menu-horizontal">
125
+ <li><a>Starter</a></li>
126
+ <li><a>Team</a></li>
127
+ <li><a>Enterprise</a></li>
128
+ </ul>
129
+ </div>
130
+ </div>
131
+ ```
@@ -9,6 +9,7 @@ Versatile nav list for sidebars, sub-menus, mega-menus, file trees.
9
9
  ## When to use
10
10
 
11
11
  - Sidebars, dropdown contents, mobile drawer contents.
12
+ - For a large horizontal nav bar with per-item popover panels, use **megamenu** instead.
12
13
 
13
14
  ## Core classes
14
15
 
@@ -0,0 +1,171 @@
1
+ # otp
2
+
3
+ _one-time-password digit input (2FA / verification codes)_
4
+
5
+ ## What it does
6
+
7
+ A `<label class="otp">` wrapping N empty `<span>` boxes (one per digit) plus a single real `<input>`; the spans render as the visual digit boxes overlaying the input.
8
+
9
+ ## When to use
10
+
11
+ - 2FA / passwordless-login verification code entry.
12
+ - Number of `<span>` elements must match the input's `maxlength`/`pattern`.
13
+
14
+ ## Core classes
15
+
16
+ `otp`; modifier `otp-joined`; size `otp-xs|sm|md|lg|xl`; color `otp-neutral|primary|secondary|accent|info|success|warning|error`.
17
+
18
+ ## Examples
19
+
20
+ ### Otp
21
+
22
+ Source: `playground/components/otp/otp.html`
23
+
24
+ ```html
25
+ <label class="otp">
26
+ <span></span>
27
+ <span></span>
28
+ <span></span>
29
+ <span></span>
30
+ <input type="text" autocomplete="one-time-code" inputmode="numeric" maxlength="4" pattern="[0-9]{4}" required />
31
+ </label>
32
+ ```
33
+
34
+ ### Otp joined
35
+
36
+ Source: `playground/components/otp/otp-joined.html`
37
+
38
+ ```html
39
+ <label class="otp otp-joined">
40
+ <span></span>
41
+ <span></span>
42
+ <span></span>
43
+ <span></span>
44
+ <input type="text" autocomplete="one-time-code" inputmode="numeric" maxlength="4" pattern="[0-9]{4}" required />
45
+ </label>
46
+ ```
47
+
48
+ ### Otp sizes
49
+
50
+ Source: `playground/components/otp/otp-sizes.html`
51
+
52
+ ```html
53
+ <div class="flex flex-col gap-4 items-center">
54
+ <label class="otp otp-xs">
55
+ <span></span>
56
+ <span></span>
57
+ <span></span>
58
+ <span></span>
59
+ <input type="text" autocomplete="one-time-code" inputmode="numeric" maxlength="4" pattern="[0-9]{4}" required />
60
+ </label>
61
+ <label class="otp otp-sm">
62
+ <span></span>
63
+ <span></span>
64
+ <span></span>
65
+ <span></span>
66
+ <input type="text" autocomplete="one-time-code" inputmode="numeric" maxlength="4" pattern="[0-9]{4}" required />
67
+ </label>
68
+ <label class="otp otp-md">
69
+ <span></span>
70
+ <span></span>
71
+ <span></span>
72
+ <span></span>
73
+ <input type="text" autocomplete="one-time-code" inputmode="numeric" maxlength="4" pattern="[0-9]{4}" required />
74
+ </label>
75
+ <label class="otp otp-lg">
76
+ <span></span>
77
+ <span></span>
78
+ <span></span>
79
+ <span></span>
80
+ <input type="text" autocomplete="one-time-code" inputmode="numeric" maxlength="4" pattern="[0-9]{4}" required />
81
+ </label>
82
+ <label class="otp otp-xl">
83
+ <span></span>
84
+ <span></span>
85
+ <span></span>
86
+ <span></span>
87
+ <input type="text" autocomplete="one-time-code" inputmode="numeric" maxlength="4" pattern="[0-9]{4}" required />
88
+ </label>
89
+ </div>
90
+ ```
91
+
92
+ ### Otp with 6 digits
93
+
94
+ Source: `playground/components/otp/otp-with-6-digits.html`
95
+
96
+ ```html
97
+ <label class="otp">
98
+ <span></span>
99
+ <span></span>
100
+ <span></span>
101
+ <span></span>
102
+ <span></span>
103
+ <span></span>
104
+ <input type="text" autocomplete="one-time-code" inputmode="numeric" maxlength="6" pattern="[0-9]{6}" required />
105
+ </label>
106
+ ```
107
+
108
+ ### Otp with colors
109
+
110
+ Source: `playground/components/otp/otp-with-colors.html`
111
+
112
+ ```html
113
+ <div class="flex flex-col gap-4 items-center">
114
+ <label class="otp otp-neutral">
115
+ <span></span>
116
+ <span></span>
117
+ <span></span>
118
+ <span></span>
119
+ <input type="text" autocomplete="one-time-code" inputmode="numeric" maxlength="4" pattern="[0-9]{4}" required />
120
+ </label>
121
+ <label class="otp otp-primary">
122
+ <span></span>
123
+ <span></span>
124
+ <span></span>
125
+ <span></span>
126
+ <input type="text" autocomplete="one-time-code" inputmode="numeric" maxlength="4" pattern="[0-9]{4}" required />
127
+ </label>
128
+ <label class="otp otp-secondary">
129
+ <span></span>
130
+ <span></span>
131
+ <span></span>
132
+ <span></span>
133
+ <input type="text" autocomplete="one-time-code" inputmode="numeric" maxlength="4" pattern="[0-9]{4}" required />
134
+ </label>
135
+ <label class="otp otp-accent">
136
+ <span></span>
137
+ <span></span>
138
+ <span></span>
139
+ <span></span>
140
+ <input type="text" autocomplete="one-time-code" inputmode="numeric" maxlength="4" pattern="[0-9]{4}" required />
141
+ </label>
142
+ <label class="otp otp-info">
143
+ <span></span>
144
+ <span></span>
145
+ <span></span>
146
+ <span></span>
147
+ <input type="text" autocomplete="one-time-code" inputmode="numeric" maxlength="4" pattern="[0-9]{4}" required />
148
+ </label>
149
+ <label class="otp otp-success">
150
+ <span></span>
151
+ <span></span>
152
+ <span></span>
153
+ <span></span>
154
+ <input type="text" autocomplete="one-time-code" inputmode="numeric" maxlength="4" pattern="[0-9]{4}" required />
155
+ </label>
156
+ <label class="otp otp-warning">
157
+ <span></span>
158
+ <span></span>
159
+ <span></span>
160
+ <span></span>
161
+ <input type="text" autocomplete="one-time-code" inputmode="numeric" maxlength="4" pattern="[0-9]{4}" required />
162
+ </label>
163
+ <label class="otp otp-error">
164
+ <span></span>
165
+ <span></span>
166
+ <span></span>
167
+ <span></span>
168
+ <input type="text" autocomplete="one-time-code" inputmode="numeric" maxlength="4" pattern="[0-9]{4}" required />
169
+ </label>
170
+ </div>
171
+ ```
@@ -12,7 +12,7 @@ Themed range slider.
12
12
 
13
13
  ## Core classes
14
14
 
15
- `range`; color `range-primary|secondary|accent|info|success|warning|error|neutral`; size `range-xs|sm|md|lg|xl`.
15
+ `range`; color `range-primary|secondary|accent|info|success|warning|error|neutral`; size `range-xs|sm|md|lg|xl`; orientation `range-vertical`.
16
16
 
17
17
  ## Examples
18
18
 
@@ -12,7 +12,7 @@ Stacks children on top of each other (Z-axis), with optional offset/spread for c
12
12
 
13
13
  ## Core classes
14
14
 
15
- `stack`; modifiers `stack-top|start|end` and shadow modifiers.
15
+ `stack`; modifiers `stack-top|bottom|start|end` and shadow modifiers.
16
16
 
17
17
  ## Examples
18
18
 
@@ -13,7 +13,7 @@ Hover/focus tooltip; content from `data-tip` or a child `tooltip-content` elemen
13
13
 
14
14
  ## Core classes
15
15
 
16
- `tooltip`; position `tooltip-top|bottom|left|right`; color `tooltip-primary|…`; modifier `tooltip-open` to force-show; `data-tip="…"` for text content.
16
+ `tooltip`; position `tooltip-top|bottom|left|right`; align `tooltip-start|center|end`; color `tooltip-primary|…`; modifier `tooltip-open` to force-show; `data-tip="…"` for text content.
17
17
 
18
18
  ## Examples
19
19