@veluai/velu 0.1.13 → 0.1.15

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.
Files changed (98) hide show
  1. package/README.md +80 -80
  2. package/dist/cli.js +21 -21
  3. package/package.json +3 -2
  4. package/runtime/velu-ui/components/Accordion.jsx +64 -64
  5. package/runtime/velu-ui/components/ApiClient.jsx +121 -121
  6. package/runtime/velu-ui/components/ApiField.jsx +87 -87
  7. package/runtime/velu-ui/components/ApiPath.jsx +63 -63
  8. package/runtime/velu-ui/components/ApiSidebar.jsx +122 -122
  9. package/runtime/velu-ui/components/AskBar.jsx +71 -71
  10. package/runtime/velu-ui/components/Callout.jsx +114 -114
  11. package/runtime/velu-ui/components/Card.jsx +131 -131
  12. package/runtime/velu-ui/components/Chatbot.jsx +596 -596
  13. package/runtime/velu-ui/components/CodeBlock.jsx +375 -375
  14. package/runtime/velu-ui/components/Columns.jsx +56 -56
  15. package/runtime/velu-ui/components/ErrorCard.jsx +138 -138
  16. package/runtime/velu-ui/components/Field.jsx +81 -81
  17. package/runtime/velu-ui/components/Image.jsx +163 -163
  18. package/runtime/velu-ui/components/Logo.jsx +31 -0
  19. package/runtime/velu-ui/components/MethodBadge.jsx +31 -31
  20. package/runtime/velu-ui/components/NavSelect.jsx +108 -108
  21. package/runtime/velu-ui/components/PageFeedback.jsx +219 -219
  22. package/runtime/velu-ui/components/PageFooter.jsx +145 -213
  23. package/runtime/velu-ui/components/PageHeader.jsx +422 -414
  24. package/runtime/velu-ui/components/PageNav.jsx +77 -77
  25. package/runtime/velu-ui/components/PoweredBy.jsx +51 -51
  26. package/runtime/velu-ui/components/Prompt.jsx +115 -115
  27. package/runtime/velu-ui/components/Search.jsx +411 -366
  28. package/runtime/velu-ui/components/Sidebar.jsx +191 -191
  29. package/runtime/velu-ui/components/SocialLinks.jsx +90 -0
  30. package/runtime/velu-ui/components/Steps.jsx +65 -65
  31. package/runtime/velu-ui/components/ThemeToggle.jsx +48 -48
  32. package/runtime/velu-ui/components/Toc.jsx +537 -537
  33. package/runtime/velu-ui/components/TocBar.jsx +195 -195
  34. package/runtime/velu-ui/components/Tree.jsx +87 -87
  35. package/runtime/velu-ui/components/TryItBar.jsx +90 -90
  36. package/runtime/velu-ui/components/accordion.css +92 -92
  37. package/runtime/velu-ui/components/api.css +479 -479
  38. package/runtime/velu-ui/components/ask-bar.css +94 -94
  39. package/runtime/velu-ui/components/card.css +105 -105
  40. package/runtime/velu-ui/components/chatbot.css +617 -617
  41. package/runtime/velu-ui/components/code-block.css +263 -263
  42. package/runtime/velu-ui/components/docs-layout.css +784 -775
  43. package/runtime/velu-ui/components/field.css +82 -82
  44. package/runtime/velu-ui/components/image.css +237 -237
  45. package/runtime/velu-ui/components/nav-select.css +157 -157
  46. package/runtime/velu-ui/components/page-feedback.css +241 -241
  47. package/runtime/velu-ui/components/page-footer.css +130 -130
  48. package/runtime/velu-ui/components/page-header.css +557 -520
  49. package/runtime/velu-ui/components/page-nav.css +50 -50
  50. package/runtime/velu-ui/components/powered-by.css +86 -66
  51. package/runtime/velu-ui/components/prompt.css +99 -99
  52. package/runtime/velu-ui/components/search.css +307 -307
  53. package/runtime/velu-ui/components/sidebar.css +144 -144
  54. package/runtime/velu-ui/components/steps.css +77 -77
  55. package/runtime/velu-ui/components/theme-toggle.css +101 -101
  56. package/runtime/velu-ui/components/toc-bar.css +234 -234
  57. package/runtime/velu-ui/components/tree.css +49 -49
  58. package/runtime/velu-ui/index.js +48 -46
  59. package/runtime/velu-ui/lib/component-schemas.js +100 -100
  60. package/runtime/velu-ui/lib/copyText.js +64 -64
  61. package/runtime/velu-ui/lib/lang-icons.jsx +147 -147
  62. package/runtime/velu-ui/lib/prism-langs.js +957 -957
  63. package/runtime/velu-ui/lib/prism-loader.js +74 -74
  64. package/runtime/velu-ui/lib/resolveIcon.jsx +29 -29
  65. package/runtime/velu-ui/lib/scrollIntoNearestView.js +66 -66
  66. package/runtime/velu-ui/mdx-components.jsx +105 -105
  67. package/runtime/velu-ui/primitives/Cluster.jsx +49 -49
  68. package/runtime/velu-ui/primitives/Stack.jsx +63 -63
  69. package/runtime/velu-ui/primitives/Switcher.jsx +57 -57
  70. package/runtime/velu-ui/primitives/stack.css +3 -3
  71. package/runtime/velu-ui/primitives/switcher.css +25 -25
  72. package/runtime/velu-ui/styles.css +43 -43
  73. package/runtime/velu-ui/tokens.css +4 -4
  74. package/schema/velu.schema.json +281 -167
  75. package/src/lib/extract-mdx-error.js +170 -170
  76. package/src/lib/issues.js +159 -159
  77. package/src/lib/known-components.js +34 -34
  78. package/src/navigation.js +434 -434
  79. package/src/runtime/App.jsx +1506 -1476
  80. package/src/runtime/ErrorBoundary.jsx +54 -54
  81. package/src/runtime/client-entry.jsx +22 -22
  82. package/src/runtime/server-entry.jsx +16 -16
  83. package/src/template.html +48 -48
  84. package/templates/starter/ai-tools/claude-code.mdx +26 -26
  85. package/templates/starter/ai-tools/cursor.mdx +17 -17
  86. package/templates/starter/api-reference/endpoint/create.mdx +24 -24
  87. package/templates/starter/api-reference/endpoint/get.mdx +27 -27
  88. package/templates/starter/api-reference/introduction.mdx +28 -28
  89. package/templates/starter/development.mdx +19 -19
  90. package/templates/starter/essentials/code.mdx +29 -29
  91. package/templates/starter/essentials/images.mdx +29 -29
  92. package/templates/starter/essentials/markdown.mdx +25 -25
  93. package/templates/starter/essentials/navigation.mdx +39 -39
  94. package/templates/starter/essentials/settings.mdx +30 -30
  95. package/templates/starter/favicon.svg +6 -6
  96. package/templates/starter/index.mdx +31 -31
  97. package/templates/starter/quickstart.mdx +31 -31
  98. package/templates/starter/velu.json +33 -33
package/README.md CHANGED
@@ -1,80 +1,80 @@
1
- # Velu
2
-
3
- A documentation-site generator with live preview. Scaffold a docs project
4
- and run it locally with two commands — author your pages in Markdown +
5
- components, configure the site with a single `velu.json`.
6
-
7
- ```bash
8
- npm install -g @veluai/velu
9
- velu init my-docs
10
- velu dev my-docs
11
- ```
12
-
13
- Then open <http://localhost:8358>. Editing any `.mdx` page or `velu.json`
14
- reloads the browser automatically.
15
-
16
- > Requires **Node.js 18+**. Prefer not to install globally? Use
17
- > `npx @veluai/velu init my-docs` and `npx @veluai/velu dev my-docs`.
18
-
19
- ## Commands
20
-
21
- | Command | What it does |
22
- | --- | --- |
23
- | `velu init <dir>` | Scaffold a new docs project into `<dir>` (creates `velu.json`, a favicon, and a set of starter `.mdx` pages). |
24
- | `velu dev [dir]` | Start the live-preview dev server for the project in `<dir>` (defaults to the current directory). |
25
-
26
- Set a custom port with the `PORT` env var:
27
-
28
- ```bash
29
- PORT=5180 velu dev my-docs
30
- ```
31
-
32
- ## Project layout
33
-
34
- `velu init` produces a project shaped like this:
35
-
36
- ```
37
- my-docs/
38
- ├─ velu.json # site config: name, colors, font, favicon, navigation
39
- ├─ favicon.svg
40
- ├─ index.mdx # pages, organized however your navigation references them
41
- ├─ quickstart.mdx
42
- └─ …
43
- ```
44
-
45
- ## `velu.json`
46
-
47
- `velu.json` drives the whole site — branding and navigation:
48
-
49
- ```json
50
- {
51
- "$schema": "https://veluai.com/velu.schema.json",
52
- "name": "My Docs",
53
- "colors": { "primary": "#dc143c" },
54
- "favicon": "/favicon.svg",
55
- "font": { "family": "Inter" },
56
- "navigation": {
57
- "tabs": [
58
- {
59
- "tab": "Guides",
60
- "groups": [
61
- { "group": "Getting started", "pages": ["index", "quickstart"] }
62
- ]
63
- }
64
- ]
65
- }
66
- }
67
- ```
68
-
69
- - **`colors`** — `primary` is required; `light` and `dark` default to `primary`.
70
- - **`navigation`** — Mintlify-compatible: `products → versions → languages →
71
- tabs → anchors → groups → pages`. Switchable axes (products, versions,
72
- languages) become URL path prefixes; the default value of each axis is
73
- unprefixed. Languages are stored as ISO 639-1 codes and shown with their
74
- native name.
75
-
76
- Page labels come from each page's frontmatter `title`.
77
-
78
- ## License
79
-
80
- Proprietary. © Velu.
1
+ # Velu
2
+
3
+ A documentation-site generator with live preview. Scaffold a docs project
4
+ and run it locally with two commands — author your pages in Markdown +
5
+ components, configure the site with a single `velu.json`.
6
+
7
+ ```bash
8
+ npm install -g @veluai/velu
9
+ velu init my-docs
10
+ velu dev my-docs
11
+ ```
12
+
13
+ Then open <http://localhost:8358>. Editing any `.mdx` page or `velu.json`
14
+ reloads the browser automatically.
15
+
16
+ > Requires **Node.js 18+**. Prefer not to install globally? Use
17
+ > `npx @veluai/velu init my-docs` and `npx @veluai/velu dev my-docs`.
18
+
19
+ ## Commands
20
+
21
+ | Command | What it does |
22
+ | --- | --- |
23
+ | `velu init <dir>` | Scaffold a new docs project into `<dir>` (creates `velu.json`, a favicon, and a set of starter `.mdx` pages). |
24
+ | `velu dev [dir]` | Start the live-preview dev server for the project in `<dir>` (defaults to the current directory). |
25
+
26
+ Set a custom port with the `PORT` env var:
27
+
28
+ ```bash
29
+ PORT=5180 velu dev my-docs
30
+ ```
31
+
32
+ ## Project layout
33
+
34
+ `velu init` produces a project shaped like this:
35
+
36
+ ```
37
+ my-docs/
38
+ ├─ velu.json # site config: name, colors, font, favicon, navigation
39
+ ├─ favicon.svg
40
+ ├─ index.mdx # pages, organized however your navigation references them
41
+ ├─ quickstart.mdx
42
+ └─ …
43
+ ```
44
+
45
+ ## `velu.json`
46
+
47
+ `velu.json` drives the whole site — branding and navigation:
48
+
49
+ ```json
50
+ {
51
+ "$schema": "https://veluai.com/velu.schema.json",
52
+ "name": "My Docs",
53
+ "colors": { "primary": "#dc143c" },
54
+ "favicon": "/favicon.svg",
55
+ "font": { "family": "Inter" },
56
+ "navigation": {
57
+ "tabs": [
58
+ {
59
+ "tab": "Guides",
60
+ "groups": [
61
+ { "group": "Getting started", "pages": ["index", "quickstart"] }
62
+ ]
63
+ }
64
+ ]
65
+ }
66
+ }
67
+ ```
68
+
69
+ - **`colors`** — `primary` is required; `light` and `dark` default to `primary`.
70
+ - **`navigation`** — Mintlify-compatible: `products → versions → languages →
71
+ tabs → anchors → groups → pages`. Switchable axes (products, versions,
72
+ languages) become URL path prefixes; the default value of each axis is
73
+ unprefixed. Languages are stored as ISO 639-1 codes and shown with their
74
+ native name.
75
+
76
+ Page labels come from each page's frontmatter `title`.
77
+
78
+ ## License
79
+
80
+ Proprietary. © Velu.
package/dist/cli.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
- var ft=Object.defineProperty;var k=(e,t)=>()=>(e&&(t=e(e=0)),t);var ue=(e,t)=>{for(var o in t)ft(e,o,{get:t[o],enumerable:!0})};var Ae={};ue(Ae,{initProject:()=>gt});import z from"node:fs/promises";import V from"node:path";import{fileURLToPath as pt}from"node:url";async function gt(e,t){try{if((await z.readdir(e)).length>0)throw new Error(`Directory "${t}" already exists and is not empty. Choose a different name or remove the folder first.`)}catch(s){if(s.code!=="ENOENT")throw s}await z.mkdir(e,{recursive:!0}),await z.cp(dt,e,{recursive:!0});let o=V.join(e,"velu.json"),n=JSON.parse(await z.readFile(o,"utf-8"));n.name=t,await z.writeFile(o,JSON.stringify(n,null,2)+`
3
- `,"utf-8");let r=await je(e);console.log(`[velu] created ${t}/`);for(let s of r)console.log(` ${s}`);console.log(""),console.log("Next steps:"),console.log(` cd ${t}`),console.log(" velu dev")}async function je(e,t=e,o=[]){let n=await z.readdir(e,{withFileTypes:!0});for(let r of n){let s=V.join(e,r.name);r.isDirectory()?await je(s,t,o):o.push(V.relative(t,s).split(V.sep).join("/"))}return o.sort()}var mt,dt,Pe=k(()=>{mt=V.dirname(pt(import.meta.url)),dt=V.resolve(mt,"..","templates","starter")});import{visit as ht}from"unist-util-visit";import{toString as vt}from"mdast-util-to-string";import yt from"github-slugger";import{valueToEstree as xt}from"estree-util-value-to-estree";function Y(){return e=>{let t=new yt,o=[];ht(e,"heading",i=>{let a=vt(i);o.push({depth:i.depth,id:t.slug(a),label:a})});let n={children:[]},r=[{node:n,depth:0}];for(let i of o){for(;r.length>1&&r[r.length-1].depth>=i.depth;)r.pop();let a={id:i.id,label:i.label},l=r[r.length-1].node;l.children||(l.children=[]),l.children.push(a),r.push({node:a,depth:i.depth})}let s=n.children;e.children.unshift({type:"mdxjsEsm",value:"",data:{estree:{type:"Program",sourceType:"module",body:[{type:"ExportNamedDeclaration",specifiers:[],declaration:{type:"VariableDeclaration",kind:"const",declarations:[{type:"VariableDeclarator",id:{type:"Identifier",name:"toc"},init:xt(s)}]}}]}}})}}var fe=k(()=>{});import wt from"node:fs/promises";import Ce from"node:path";function pe(e={},t){let o=e.colors?.primary??bt;return{name:e.name??t??"docs",colors:{primary:o,light:e.colors?.light??o,dark:e.colors?.dark??o},favicon:e.favicon??null,font:{family:e.font?.family??kt},navigation:e.navigation??null}}async function Ee(e){let t=Ce.join(e,"velu.json"),o;try{o=await wt.readFile(t,"utf-8")}catch(r){throw r.code==="ENOENT"?new Error(`No velu.json found in ${e}. Run \`velu init <name>\` to scaffold one.`):r}let n;try{n=JSON.parse(o)}catch(r){throw new Error(`velu.json is not valid JSON: ${r.message}`)}return pe(n,Ce.basename(e))}function Te(e){let{colors:t,font:o}=e;return[":root:root {",` --accent-color: ${t.light};`,` --font-sans: "${o.family}", sans-serif;`,"}",':root:root[data-theme="dark"] {',` --accent-color: ${t.dark};`,"}"].join(`
4
- `)}var bt,kt,_e=k(()=>{bt="#dc143c",kt="Google Sans Flex"});import St from"github-slugger";import $t from"iso-639-1";function At(e){let t=String(e).toLowerCase();return $t.getNativeName(t)||e}function ee(e){return new St().slug(String(e??""))}function Pt(e){let t=String(e).replace(/^\/+|\/+$/g,"").split("/").filter(Boolean);return t[t.length-1]==="index"&&t.pop(),"/"+t.join("/")}function B(e){let t={kind:"root",children:H(e??{})};return Le(t.children),t}function H(e){let t=Array.isArray(e.anchors)?e.anchors.map(Ot):[];if(Array.isArray(e.products))return[...t,...e.products.map(Ct)];if(Array.isArray(e.versions))return[...t,...e.versions.map(Et)];if(Array.isArray(e.languages))return[...t,...e.languages.map(Tt)];if(Array.isArray(e.tabs))return[...t,...e.tabs.map(_t)];let o=[...t];return Array.isArray(e.groups)&&o.push(...e.groups.map(Oe)),Array.isArray(e.pages)&&o.push(...e.pages.map(Ne)),o}function Ct(e){return{kind:"product",label:e.name??e.product,slug:ee(e.product),icon:e.icon,color:e.color,default:!!e.default,children:H(e)}}function Et(e){return{kind:"version",label:e.version,slug:ee(e.version),default:!!e.default,children:H(e)}}function Tt(e){let t=String(e.language);return{kind:"language",code:t,label:At(t),slug:ee(t),default:!!e.default,children:H(e)}}function _t(e){return{kind:"tab",label:e.tab,slug:ee(e.tab),icon:e.icon,href:e.href,children:H(e)}}function Ot(e){return{kind:"anchor",label:e.anchor,icon:e.icon,href:e.href,color:e.color}}function Oe(e){let t=(e.pages??[]).map(Ne);return e.root&&t.unshift({kind:"page",pagePath:e.root}),{kind:"group",label:e.group,icon:e.icon,expanded:!!e.expanded,root:e.root,children:t}}function Ne(e){return typeof e=="string"?{kind:"page",pagePath:e}:Oe(e)}function Le(e){for(let t of jt){let o=e.filter(n=>n.kind===t);o.length&&!o.some(n=>n.default)&&(o[0].default=!0)}for(let t of e)t.children&&Le(t.children)}function Fe(e){let t=[],o=(n,r,s)=>{if(n.kind==="page"){t.push({pagePath:n.pagePath,url:Nt(n.pagePath,r),ctx:{...r},ancestors:s,node:n});return}let i=r;n.kind==="product"?i={...r,product:n.default?null:n.slug}:n.kind==="version"?i={...r,version:n.default?null:n.slug}:n.kind==="language"&&(i={...r,language:n.default?null:n.slug});let a=n.kind==="root"?s:[...s,n];for(let l of n.children??[])o(l,i,a)};return o(e,{product:null,version:null,language:null},[]),t}function Nt(e,t){let o=[t.product,t.version,t.language].filter(Boolean),n=Pt(e).split("/").filter(Boolean);return"/"+[...o,...n].join("/")}var jt,W=k(()=>{jt=["product","version","language"]});import Lt from"node:fs";import Ie from"node:path";function G(e,t){let o=[],n=[],r=new Set;for(let s of Fe(e)){if(r.has(s.url)){o.push(`duplicate URL "${s.url}" (page "${s.pagePath}") \u2014 keeping the first occurrence`);continue}r.add(s.url);let i=s.pagePath.replace(/^\/+|\/+$/g,""),a=Ie.join(t,...i.split("/"))+".mdx",l=Lt.existsSync(a);l||o.push(`page "${s.pagePath}" \u2192 ${Ie.relative(t,a)} not found`),n.push({pagePath:s.pagePath,url:s.url,fileAbsPath:a,exists:l})}return{pageEntries:n,warnings:o}}var te=k(()=>{W()});import Ft from"node:fs";import ne from"node:path";function Ue(e){return{name:"velu-site",resolveId(t){return t===Me?Re:null},load(t){return t!==Re?null:It(e)}}}function It(e){let t={};try{t=JSON.parse(Ft.readFileSync(ne.join(e,"velu.json"),"utf-8"))}catch{}let o=B(t.navigation??{}),{pageEntries:n,warnings:r}=G(o,e);for(let l of r)console.warn(`[velu] nav: ${l}`);let s=[],i=[],a=0;for(let l of n)if(l.exists){let u=JSON.stringify(l.fileAbsPath.split(ne.sep).join("/")),c=JSON.stringify(ne.relative(e,l.fileAbsPath).split(ne.sep).join("/")),f=`__p${a++}`;s.push(`import * as ${f} from ${u};`),i.push(` ${JSON.stringify(l.url)}: { Component: ${f}.default, frontmatter: ${f}.frontmatter, toc: ${f}.toc, relPath: ${c} },`)}else i.push(` ${JSON.stringify(l.url)}: { missing: true },`);return["// AUTO-GENERATED by vite-plugin-velu-site. Do not edit.",s.join(`
5
- `),"","export const pages = {",i.join(`
6
- `),"};",`export const navigation = ${JSON.stringify(o)};`,""].join(`
7
- `)}var Me,Re,ze=k(()=>{W();te();Me="virtual:velu-site",Re="\0"+Me});function h(e){return{category:"render-crash",severity:"error",file:null,line:null,column:null,frame:null,title:"Something went wrong",detail:"",hint:"",suggestion:null,...e}}function Rt(e,t){if(e=String(e),t=String(t),e===t)return 0;if(!e.length)return t.length;if(!t.length)return e.length;let o=Array.from({length:t.length+1},(r,s)=>s),n=new Array(t.length+1);for(let r=1;r<=e.length;r++){n[0]=r;for(let s=1;s<=t.length;s++){let i=e[r-1]===t[s-1]?0:1;n[s]=Math.min(n[s-1]+1,o[s]+1,o[s-1]+i)}[o,n]=[n,o]}return o[t.length]}function oe(e,t=[]){if(!e)return null;let o=String(e).toLowerCase(),n=null,r=1/0;for(let i of t){let a=Rt(o,String(i).toLowerCase());a<r&&(r=a,n=i)}let s=Math.min(3,Math.max(2,Math.floor(o.length/4)));return r<=s?n:null}function Mt(e,t){return e==="warning"?P(t,$.yellow,"\u26A0"):e==="info"?P(t,$.cyan,"\u2139"):P(t,$.red,"\u2716")}function de(e,{color:t=!1}={}){let o=me[e.category]||e.category,n=e.line?`${e.line}${e.column?`:${e.column}`:""}`:"",r=e.file?`${e.file}${n?`:${n}`:""}`:n,s=[];if(s.push(`${Mt(e.severity,t)} ${P(t,$.bold,o)}`+(r?` ${P(t,$.dim,r)}`:"")),e.title&&s.push(` ${e.title}`),e.detail&&e.detail!==e.title&&s.push(` ${P(t,$.dim,e.detail)}`),e.frame)for(let i of String(e.frame).split(`
8
- `))s.push(` ${i}`);return e.suggestion&&s.push(` ${P(t,$.cyan,`Did you mean <${e.suggestion}>?`)}`),e.hint&&s.push(` ${P(t,$.dim,`\u2192 ${e.hint}`)}`),s.join(`
9
- `)}function re(e,{color:t=!1}={}){if(!e.length)return P(t,$.cyan,"\u2713 No issues found.");let o=new Map;for(let a of e){let l=a.file||"velu.json";o.has(l)||o.set(l,[]),o.get(l).push(a)}let n=[];for(let[a,l]of o){n.push(P(t,$.bold,a));for(let u of l)n.push(de({...u,file:null},{color:t}).replace(/^/gm," "));n.push("")}let r=e.filter(a=>a.severity!=="warning"&&a.severity!=="info").length,s=e.length-r,i=`${r} error${r===1?"":"s"}`+(s?`, ${s} warning${s===1?"":"s"}`:"");return n.push(P(t,r?$.red:$.yellow,i)),n.join(`
10
- `)}var me,$,P,I=k(()=>{me={"mdx-syntax":"MDX syntax",frontmatter:"Frontmatter","unknown-component":"Unknown component","invalid-props":"Invalid options","render-crash":"Render error","config-json":"velu.json","config-schema":"velu.json","config-nav":"Navigation","config-asset":"Asset"};$={reset:"\x1B[0m",red:"\x1B[31m",yellow:"\x1B[33m",cyan:"\x1B[36m",dim:"\x1B[2m",bold:"\x1B[1m"},P=(e,t,o)=>e?`${t}${o}${$.reset}`:o});function Ut(e){let t=e,o=0;for(;t&&t.cause&&o<3&&!(t.loc||t.line||/`[^`]+` to be defined/.test(t.message||""));)t=t.cause,o+=1;return t||e}function ge(e,t){if(!e)return null;let o=Ve(e).replace(/[?#].*$/,""),n=t?Ve(t).replace(/\/+$/,""):"";return n&&o.toLowerCase().startsWith(n.toLowerCase())?o.slice(n.length).replace(/^\/+/,""):!/^([a-zA-Z]:\/|\/)/.test(o)&&!/node_modules/.test(o)?o:null}function zt(e){return e?String(e).replace(/([a-zA-Z]:\\|\/)[^\s'"()]+/g,t=>/node_modules|[\\/]vite[\\/]|@veluai|velu-cli|velu-ui/.test(t)?"\u2026":t).trim():""}function Vt(e){let t=/\((\d+):(\d+)(?:-\d+:\d+)?\)\s*$/.exec(String(e||""));return t?{line:Number(t[1]),column:Number(t[2])}:null}function Bt(e){return String(e||"").replace(/\s*\(\d+:\d+(?:-\d+:\d+)?\)\s*$/,"").trim()}function Jt(e,t){if(!e||!t)return null;let o=String(e);return/node_modules|[\\/]vite[\\/]|@veluai[\\/]/.test(o)?null:o}function K(e,t={}){let{projectDir:o="",knownComponents:n=[],file:r=null}=t,s=null;for(let C=e,E=0;C&&E<6;C=C.cause,E+=1)if(C.veluIssue){s=C.veluIssue;break}if(s)return h({...s,file:s.file||r});let i=Ut(e)||{},a=i.message||String(e||""),l=/Expected component `([^`]+)` to be defined/.exec(a);if(l){let C=l[1],E=/referenced in your code at `(\d+):(\d+)/.exec(a),F=/\bin `([^`]+)`/.exec(a),X=F?ge(F[1],o):null;return h({category:"unknown-component",file:X||r,line:E?Number(E[1]):null,column:E?Number(E[2]):null,title:`<${C}> is not a built-in component`,detail:"",hint:"Components are built in \u2014 check the spelling and capitalization (you don\u2019t import them).",suggestion:oe(C,n)})}let u=i.loc||(i.line!=null?{line:i.line,column:i.column,file:i.file}:null)||Vt(i.reason||a),c=i.id||u&&u.file||i.file||null,f=ge(c,o)||r,_=!!f&&ge(c,o)!=null,d=Jt(i.frame,_||!!r),j=zt(Bt(i.reason||a)),m=Gt.test(a),L=i.source==="remark-frontmatter"||/\byaml\b|frontmatter/i.test(a)||u&&u.line===1&&/unexpected|expected/i.test(a)&&/---/.test(a);return u||m||d&&_?h({category:L?"frontmatter":"mdx-syntax",file:f,line:u?u.line:null,column:u?u.column:null,frame:d,title:j||(L?"Invalid frontmatter":"MDX syntax error"),detail:"",hint:L?"Check the YAML between the --- markers \u2014 indentation, quotes, and colons.":"Make sure every <Component> has a matching closing tag and that { } braces are balanced."}):/\.map is not a function|is not iterable|reading '|undefined \(reading/i.test(a)?h({category:"invalid-props",file:f,title:"A component received an invalid value",detail:j,hint:"Check the props/options you passed to a component on this page."}):h({category:"render-crash",file:f,title:"This page failed to render",detail:j,hint:"Set VELU_DEBUG=1 for the full stack trace."})}var Ve,Gt,he=k(()=>{I();Ve=e=>String(e).replace(/\\/g,"/");Gt=/closing tag|unexpected closing|could not parse (?:expression|import|export)|unexpected character|unexpected end of|expected a closing|expected the closing|unexpected `|in expression|misnested|before name/i});function qt(e){let t=me[e.category]||e.category,o=e.file?`${e.file}${e.line?`:${e.line}${e.column?`:${e.column}`:""}`:""}`:"",n=[];return n.push('<div class="velu-err-card">'),n.push('<div class="velu-err-head">'),n.push(`<span class="velu-err-pill">${O(t)}</span>`),n.push("</div>"),e.title&&n.push(`<div class="velu-err-title">${O(e.title)}</div>`),o&&n.push(`<a class="velu-err-loc" title="${O(o)}">${O(o)}</a>`),e.detail&&n.push(`<div class="velu-err-detail">${O(e.detail)}</div>`),e.frame&&n.push(`<pre class="velu-err-frame">${O(e.frame)}</pre>`),e.suggestion&&n.push(`<div class="velu-err-suggest">Did you mean <code>&lt;${O(e.suggestion)}&gt;</code>?</div>`),e.hint&&n.push(`<div class="velu-err-hint">${O(e.hint)}</div>`),n.push("</div>"),n.join("")}function ve(e,t={}){let o=Array.isArray(e)?e:[e],n=t.title||(o.length>1?`${o.length} problems to fix`:"There\u2019s a problem to fix"),r=o.map(qt).join(`
2
+ var vt=Object.defineProperty;var k=(e,t)=>()=>(e&&(t=e(e=0)),t);var de=(e,t)=>{for(var o in t)vt(e,o,{get:t[o],enumerable:!0})};var Ne={};de(Ne,{initProject:()=>wt});import z from"node:fs/promises";import G from"node:path";import{fileURLToPath as yt}from"node:url";async function wt(e,t){try{if((await z.readdir(e)).length>0)throw new Error(`Directory "${t}" already exists and is not empty. Choose a different name or remove the folder first.`)}catch(i){if(i.code!=="ENOENT")throw i}await z.mkdir(e,{recursive:!0}),await z.cp(bt,e,{recursive:!0});let o=G.join(e,"velu.json"),n=JSON.parse(await z.readFile(o,"utf-8"));n.name=t,await z.writeFile(o,JSON.stringify(n,null,2)+`
3
+ `,"utf-8");let r=await Ee(e);console.log(`[velu] created ${t}/`);for(let i of r)console.log(` ${i}`);console.log(""),console.log("Next steps:"),console.log(` cd ${t}`),console.log(" velu dev")}async function Ee(e,t=e,o=[]){let n=await z.readdir(e,{withFileTypes:!0});for(let r of n){let i=G.join(e,r.name);r.isDirectory()?await Ee(i,t,o):o.push(G.relative(t,i).split(G.sep).join("/"))}return o.sort()}var xt,bt,Fe=k(()=>{xt=G.dirname(yt(import.meta.url)),bt=G.resolve(xt,"..","templates","starter")});import{visit as kt}from"unist-util-visit";import{toString as St}from"mdast-util-to-string";import $t from"github-slugger";import{valueToEstree as jt}from"estree-util-value-to-estree";function D(){return e=>{let t=new $t,o=[];kt(e,"heading",a=>{let s=St(a);o.push({depth:a.depth,id:t.slug(s),label:s})});let n={children:[]},r=[{node:n,depth:0}];for(let a of o){for(;r.length>1&&r[r.length-1].depth>=a.depth;)r.pop();let s={id:a.id,label:a.label},l=r[r.length-1].node;l.children||(l.children=[]),l.children.push(s),r.push({node:s,depth:a.depth})}let i=n.children;e.children.unshift({type:"mdxjsEsm",value:"",data:{estree:{type:"Program",sourceType:"module",body:[{type:"ExportNamedDeclaration",specifiers:[],declaration:{type:"VariableDeclaration",kind:"const",declarations:[{type:"VariableDeclarator",id:{type:"Identifier",name:"toc"},init:jt(i)}]}}]}}})}}var ge=k(()=>{});import At from"node:fs/promises";import Ie from"node:path";function Y(e){if(typeof e=="string"){let t=e.trim();return t?{light:t,dark:t,href:"/"}:null}if(e&&typeof e=="object"){let t=(e.light??e.dark)?.trim?.(),o=(e.dark??e.light)?.trim?.();return!t||!o?null:{light:t,dark:o,href:e.href?.trim?.()||"/"}}return null}function ve(e){if(!e||typeof e!="object")return null;let t=[];if(e.socials&&typeof e.socials=="object")for(let[n,r]of Object.entries(e.socials))typeof r!="string"||!r.trim()||t.push({kind:_t[n]??n,href:r.trim()});let o=Array.isArray(e.links)?e.links.filter(n=>n&&typeof n=="object").map(n=>({title:(n.header??n.title??"").trim(),items:(Array.isArray(n.items)?n.items:[]).filter(r=>r&&r.label).map(r=>({label:r.label,href:r.href??"#"}))})).filter(n=>n.title||n.items.length):[];return!t.length&&!o.length?null:{socials:t,links:o}}function he(e){return/^(https?:)?\/\//.test(e)||/^(mailto|tel):/.test(e)}function ye(e){if(!e||typeof e!="object")return null;let t=(Array.isArray(e.links)?e.links:[]).filter(r=>r&&typeof r.href=="string"&&r.href.trim()).map(r=>({label:r.label??"",href:r.href.trim(),icon:r.icon??null,external:he(r.href.trim())})),o=null,n=e.primary;if(n&&typeof n=="object"&&typeof n.href=="string"&&n.href.trim()){let r=n.href.trim();o=n.type==="github"?{kind:"github",label:n.label??"GitHub",href:r,external:he(r)}:{kind:"button",label:n.label??"",href:r,external:he(r)}}return!t.length&&!o?null:{links:t,primary:o}}function xe(e={},t){let o=e.colors?.primary??Lt;return{name:e.name??t??"docs",colors:{primary:o,light:e.colors?.light??o,dark:e.colors?.dark??o},favicon:e.favicon??null,logo:Y(e.logo),footer:ve(e.footer),navbar:ye(e.navbar),font:{family:e.font?.family??Ot},navigation:e.navigation??null}}async function Re(e){let t=Ie.join(e,"velu.json"),o;try{o=await At.readFile(t,"utf-8")}catch(r){throw r.code==="ENOENT"?new Error(`No velu.json found in ${e}. Run \`velu init <name>\` to scaffold one.`):r}let n;try{n=JSON.parse(o)}catch(r){throw new Error(`velu.json is not valid JSON: ${r.message}`)}return xe(n,Ie.basename(e))}function Me(e){let{colors:t,font:o}=e;return[":root:root {",` --accent-color: ${t.light};`,` --font-sans: "${o.family}", sans-serif;`,"}",':root:root[data-theme="dark"] {',` --accent-color: ${t.dark};`,"}"].join(`
4
+ `)}var Lt,Ot,ne,oe,_t,re=k(()=>{Lt="#dc143c",Ot="Google Sans Flex",ne="/@velu-logo-light",oe="/@velu-logo-dark";_t={twitter:"x","x-twitter":"x"}});import Pt from"github-slugger";import Ct from"iso-639-1";function Et(e){let t=String(e).toLowerCase();return Ct.getNativeName(t)||e}function ie(e){return new Pt().slug(String(e??""))}function Nt(e){let t=String(e).replace(/^\/+|\/+$/g,"").split("/").filter(Boolean);return t[t.length-1]==="index"&&t.pop(),"/"+t.join("/")}function V(e){let t={kind:"root",children:K(e??{})};return Ge(t.children),t}function K(e){let t=Array.isArray(e.anchors)?e.anchors.map(Ut):[];if(Array.isArray(e.products))return[...t,...e.products.map(Ft)];if(Array.isArray(e.versions))return[...t,...e.versions.map(It)];if(Array.isArray(e.languages))return[...t,...e.languages.map(Rt)];if(Array.isArray(e.tabs))return[...t,...e.tabs.map(Mt)];let o=[...t];return Array.isArray(e.groups)&&o.push(...e.groups.map(Ue)),Array.isArray(e.pages)&&o.push(...e.pages.map(ze)),o}function Ft(e){return{kind:"product",label:e.name??e.product,slug:ie(e.product),icon:e.icon,color:e.color,default:!!e.default,children:K(e)}}function It(e){return{kind:"version",label:e.version,slug:ie(e.version),default:!!e.default,children:K(e)}}function Rt(e){let t=String(e.language);return{kind:"language",code:t,label:Et(t),slug:ie(t),default:!!e.default,children:K(e)}}function Mt(e){return{kind:"tab",label:e.tab,slug:ie(e.tab),icon:e.icon,href:e.href,children:K(e)}}function Ut(e){return{kind:"anchor",label:e.anchor,icon:e.icon,href:e.href,color:e.color}}function Ue(e){let t=(e.pages??[]).map(ze);return e.root&&t.unshift({kind:"page",pagePath:e.root}),{kind:"group",label:e.group,icon:e.icon,expanded:!!e.expanded,root:e.root,children:t}}function ze(e){return typeof e=="string"?{kind:"page",pagePath:e}:Ue(e)}function Ge(e){for(let t of Tt){let o=e.filter(n=>n.kind===t);o.length&&!o.some(n=>n.default)&&(o[0].default=!0)}for(let t of e)t.children&&Ge(t.children)}function Ve(e){let t=[],o=(n,r,i)=>{if(n.kind==="page"){t.push({pagePath:n.pagePath,url:zt(n.pagePath,r),ctx:{...r},ancestors:i,node:n});return}let a=r;n.kind==="product"?a={...r,product:n.default?null:n.slug}:n.kind==="version"?a={...r,version:n.default?null:n.slug}:n.kind==="language"&&(a={...r,language:n.default?null:n.slug});let s=n.kind==="root"?i:[...i,n];for(let l of n.children??[])o(l,a,s)};return o(e,{product:null,version:null,language:null},[]),t}function zt(e,t){let o=[t.product,t.version,t.language].filter(Boolean),n=Nt(e).split("/").filter(Boolean);return"/"+[...o,...n].join("/")}var Tt,W=k(()=>{Tt=["product","version","language"]});import Gt from"node:fs";import Be from"node:path";function B(e,t){let o=[],n=[],r=new Set;for(let i of Ve(e)){if(r.has(i.url)){o.push(`duplicate URL "${i.url}" (page "${i.pagePath}") \u2014 keeping the first occurrence`);continue}r.add(i.url);let a=i.pagePath.replace(/^\/+|\/+$/g,""),s=Be.join(t,...a.split("/"))+".mdx",l=Gt.existsSync(s);l||o.push(`page "${i.pagePath}" \u2192 ${Be.relative(t,s)} not found`),n.push({pagePath:i.pagePath,url:i.url,fileAbsPath:s,exists:l})}return{pageEntries:n,warnings:o}}var se=k(()=>{W()});import Vt from"node:fs";import Z from"node:path";function He(e){return{name:"velu-site",resolveId(t){return t===qe?Je:null},load(t){return t!==Je?null:Bt(e)}}}function Bt(e){let t={};try{t=JSON.parse(Vt.readFileSync(Z.join(e,"velu.json"),"utf-8"))}catch{}let o=V(t.navigation??{}),{pageEntries:n,warnings:r}=B(o,e);for(let c of r)console.warn(`[velu] nav: ${c}`);let i=Y(t.logo),a={name:t.name??Z.basename(e),logo:i?{light:ne,dark:oe,href:i.href,mono:i.light===i.dark}:null,footer:ve(t.footer),navbar:ye(t.navbar)},s=[],l=[],u=0;for(let c of n)if(c.exists){let f=JSON.stringify(c.fileAbsPath.split(Z.sep).join("/")),A=JSON.stringify(Z.relative(e,c.fileAbsPath).split(Z.sep).join("/")),p=`__p${u++}`;s.push(`import * as ${p} from ${f};`),l.push(` ${JSON.stringify(c.url)}: { Component: ${p}.default, frontmatter: ${p}.frontmatter, toc: ${p}.toc, relPath: ${A} },`)}else l.push(` ${JSON.stringify(c.url)}: { missing: true },`);return["// AUTO-GENERATED by vite-plugin-velu-site. Do not edit.",s.join(`
5
+ `),"","export const pages = {",l.join(`
6
+ `),"};",`export const navigation = ${JSON.stringify(o)};`,`export const site = ${JSON.stringify(a)};`,""].join(`
7
+ `)}var qe,Je,De=k(()=>{W();se();re();qe="virtual:velu-site",Je="\0"+qe});function v(e){return{category:"render-crash",severity:"error",file:null,line:null,column:null,frame:null,title:"Something went wrong",detail:"",hint:"",suggestion:null,...e}}function Jt(e,t){if(e=String(e),t=String(t),e===t)return 0;if(!e.length)return t.length;if(!t.length)return e.length;let o=Array.from({length:t.length+1},(r,i)=>i),n=new Array(t.length+1);for(let r=1;r<=e.length;r++){n[0]=r;for(let i=1;i<=t.length;i++){let a=e[r-1]===t[i-1]?0:1;n[i]=Math.min(n[i-1]+1,o[i]+1,o[i-1]+a)}[o,n]=[n,o]}return o[t.length]}function le(e,t=[]){if(!e)return null;let o=String(e).toLowerCase(),n=null,r=1/0;for(let a of t){let s=Jt(o,String(a).toLowerCase());s<r&&(r=s,n=a)}let i=Math.min(3,Math.max(2,Math.floor(o.length/4)));return r<=i?n:null}function qt(e,t){return e==="warning"?P(t,j.yellow,"\u26A0"):e==="info"?P(t,j.cyan,"\u2139"):P(t,j.red,"\u2716")}function we(e,{color:t=!1}={}){let o=be[e.category]||e.category,n=e.line?`${e.line}${e.column?`:${e.column}`:""}`:"",r=e.file?`${e.file}${n?`:${n}`:""}`:n,i=[];if(i.push(`${qt(e.severity,t)} ${P(t,j.bold,o)}`+(r?` ${P(t,j.dim,r)}`:"")),e.title&&i.push(` ${e.title}`),e.detail&&e.detail!==e.title&&i.push(` ${P(t,j.dim,e.detail)}`),e.frame)for(let a of String(e.frame).split(`
8
+ `))i.push(` ${a}`);return e.suggestion&&i.push(` ${P(t,j.cyan,`Did you mean <${e.suggestion}>?`)}`),e.hint&&i.push(` ${P(t,j.dim,`\u2192 ${e.hint}`)}`),i.join(`
9
+ `)}function ae(e,{color:t=!1}={}){if(!e.length)return P(t,j.cyan,"\u2713 No issues found.");let o=new Map;for(let s of e){let l=s.file||"velu.json";o.has(l)||o.set(l,[]),o.get(l).push(s)}let n=[];for(let[s,l]of o){n.push(P(t,j.bold,s));for(let u of l)n.push(we({...u,file:null},{color:t}).replace(/^/gm," "));n.push("")}let r=e.filter(s=>s.severity!=="warning"&&s.severity!=="info").length,i=e.length-r,a=`${r} error${r===1?"":"s"}`+(i?`, ${i} warning${i===1?"":"s"}`:"");return n.push(P(t,r?j.red:j.yellow,a)),n.join(`
10
+ `)}var be,j,P,F=k(()=>{be={"mdx-syntax":"MDX syntax",frontmatter:"Frontmatter","unknown-component":"Unknown component","invalid-props":"Invalid options","render-crash":"Render error","config-json":"velu.json","config-schema":"velu.json","config-nav":"Navigation","config-asset":"Asset"};j={reset:"\x1B[0m",red:"\x1B[31m",yellow:"\x1B[33m",cyan:"\x1B[36m",dim:"\x1B[2m",bold:"\x1B[1m"},P=(e,t,o)=>e?`${t}${o}${j.reset}`:o});function Ht(e){let t=e,o=0;for(;t&&t.cause&&o<3&&!(t.loc||t.line||/`[^`]+` to be defined/.test(t.message||""));)t=t.cause,o+=1;return t||e}function ke(e,t){if(!e)return null;let o=Ye(e).replace(/[?#].*$/,""),n=t?Ye(t).replace(/\/+$/,""):"";return n&&o.toLowerCase().startsWith(n.toLowerCase())?o.slice(n.length).replace(/^\/+/,""):!/^([a-zA-Z]:\/|\/)/.test(o)&&!/node_modules/.test(o)?o:null}function Dt(e){return e?String(e).replace(/([a-zA-Z]:\\|\/)[^\s'"()]+/g,t=>/node_modules|[\\/]vite[\\/]|@veluai|velu-cli|velu-ui/.test(t)?"\u2026":t).trim():""}function Yt(e){let t=/\((\d+):(\d+)(?:-\d+:\d+)?\)\s*$/.exec(String(e||""));return t?{line:Number(t[1]),column:Number(t[2])}:null}function Kt(e){return String(e||"").replace(/\s*\(\d+:\d+(?:-\d+:\d+)?\)\s*$/,"").trim()}function Zt(e,t){if(!e||!t)return null;let o=String(e);return/node_modules|[\\/]vite[\\/]|@veluai[\\/]/.test(o)?null:o}function X(e,t={}){let{projectDir:o="",knownComponents:n=[],file:r=null}=t,i=null;for(let C=e,S=0;C&&S<6;C=C.cause,S+=1)if(C.veluIssue){i=C.veluIssue;break}if(i)return v({...i,file:i.file||r});let a=Ht(e)||{},s=a.message||String(e||""),l=/Expected component `([^`]+)` to be defined/.exec(s);if(l){let C=l[1],S=/referenced in your code at `(\d+):(\d+)/.exec(s),q=/\bin `([^`]+)`/.exec(s),y=q?ke(q[1],o):null;return v({category:"unknown-component",file:y||r,line:S?Number(S[1]):null,column:S?Number(S[2]):null,title:`<${C}> is not a built-in component`,detail:"",hint:"Components are built in \u2014 check the spelling and capitalization (you don\u2019t import them).",suggestion:le(C,n)})}let u=a.loc||(a.line!=null?{line:a.line,column:a.column,file:a.file}:null)||Yt(a.reason||s),c=a.id||u&&u.file||a.file||null,f=ke(c,o)||r,A=!!f&&ke(c,o)!=null,p=Zt(a.frame,A||!!r),L=Dt(Kt(a.reason||s)),d=Wt.test(s),N=a.source==="remark-frontmatter"||/\byaml\b|frontmatter/i.test(s)||u&&u.line===1&&/unexpected|expected/i.test(s)&&/---/.test(s);return u||d||p&&A?v({category:N?"frontmatter":"mdx-syntax",file:f,line:u?u.line:null,column:u?u.column:null,frame:p,title:L||(N?"Invalid frontmatter":"MDX syntax error"),detail:"",hint:N?"Check the YAML between the --- markers \u2014 indentation, quotes, and colons.":"Make sure every <Component> has a matching closing tag and that { } braces are balanced."}):/\.map is not a function|is not iterable|reading '|undefined \(reading/i.test(s)?v({category:"invalid-props",file:f,title:"A component received an invalid value",detail:L,hint:"Check the props/options you passed to a component on this page."}):v({category:"render-crash",file:f,title:"This page failed to render",detail:L,hint:"Set VELU_DEBUG=1 for the full stack trace."})}var Ye,Wt,Se=k(()=>{F();Ye=e=>String(e).replace(/\\/g,"/");Wt=/closing tag|unexpected closing|could not parse (?:expression|import|export)|unexpected character|unexpected end of|expected a closing|expected the closing|unexpected `|in expression|misnested|before name/i});function Xt(e){let t=be[e.category]||e.category,o=e.file?`${e.file}${e.line?`:${e.line}${e.column?`:${e.column}`:""}`:""}`:"",n=[];return n.push('<div class="velu-err-card">'),n.push('<div class="velu-err-head">'),n.push(`<span class="velu-err-pill">${T(t)}</span>`),n.push("</div>"),e.title&&n.push(`<div class="velu-err-title">${T(e.title)}</div>`),o&&n.push(`<a class="velu-err-loc" title="${T(o)}">${T(o)}</a>`),e.detail&&n.push(`<div class="velu-err-detail">${T(e.detail)}</div>`),e.frame&&n.push(`<pre class="velu-err-frame">${T(e.frame)}</pre>`),e.suggestion&&n.push(`<div class="velu-err-suggest">Did you mean <code>&lt;${T(e.suggestion)}&gt;</code>?</div>`),e.hint&&n.push(`<div class="velu-err-hint">${T(e.hint)}</div>`),n.push("</div>"),n.join("")}function $e(e,t={}){let o=Array.isArray(e)?e:[e],n=t.title||(o.length>1?`${o.length} problems to fix`:"There\u2019s a problem to fix"),r=o.map(Xt).join(`
11
11
  `);return`<!doctype html>
12
12
  <html lang="en">
13
13
  <head>
@@ -74,20 +74,20 @@ var ft=Object.defineProperty;var k=(e,t)=>()=>(e&&(t=e(e=0)),t);var ue=(e,t)=>{f
74
74
  <body>
75
75
  <div class="velu-err-wrap">
76
76
  <div class="velu-err-brand">velu</div>
77
- <h1 class="velu-err-h">${O(n)}</h1>
77
+ <h1 class="velu-err-h">${T(n)}</h1>
78
78
  ${r}
79
79
  <div class="velu-err-foot">Fix the file and save \u2014 this page reloads automatically.</div>
80
80
  </div>
81
81
  </body>
82
- </html>`}var O,Be=k(()=>{I();O=e=>String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")});var R,ye=k(()=>{R=["Callout","Card","CardGroup","Accordion","AccordionGroup","Columns","Field","Prompt","Steps","Step","Tree","Folder","File","Image","CodeBlock","CodeGroup","MethodBadge","ApiPath","TryItBar","ApiField","ApiClient","ApiSidebar"]});import xe from"node:fs";import ie from"node:path";import{fileURLToPath as Dt}from"node:url";import Yt from"iso-639-1";function Z(e,t){if(!t)return null;let o=e.indexOf(`"${t}"`);return o===-1?null:e.slice(0,o).split(`
83
- `).length}function Kt(e,t){return t==null||t<0?null:e.slice(0,t).split(`
84
- `).length}function Ge(e,t){if(!t)return null;let o=e.indexOf(`"${t}"`);return o===-1?null:e.slice(0,o).split(`
85
- `).length}function Zt(e,t,o){let n=[];return a(e,t,"",null),n;function r(l){if(l&&l.$ref){let u=l.$ref.replace(/^#\//,"").split("/"),c=o;for(let f of u)c=c?.[f];return c||{}}return l}function s(l){return Array.isArray(l)?"array":l===null?"null":typeof l}function i(l,u){let c=n.length;a(l,u,"",null,!0);let f=n.length===c;return f||(n.length=c),f}function a(l,u,c,f,_){let d=r(u);if(d){if(d.oneOf){d.oneOf.some(m=>i(l,m))||n.push({path:c,key:f,message:"value does not match any allowed shape"});return}if(d.type&&s(l)!==d.type){n.push({path:c,key:f,message:`expected ${d.type}, got ${s(l)}`});return}if(d.type==="string"&&d.minLength!=null&&l.length<d.minLength&&n.push({path:c,key:f,message:"must not be empty"}),d.type==="object"&&s(l)==="object"){for(let m of d.required||[])m in l||n.push({path:c?`${c}.${m}`:m,key:m,message:`missing required "${m}"`});let j=d.properties||{};if(d.additionalProperties===!1)for(let m of Object.keys(l))m in j||n.push({path:c?`${c}.${m}`:m,key:m,message:`unknown field "${m}"`});for(let[m,L]of Object.entries(j))m in l&&a(l[m],L,c?`${c}.${m}`:m,m,_)}d.type==="array"&&Array.isArray(l)&&d.items&&l.forEach((j,m)=>a(j,d.items,`${c}[${m}]`,f,_))}}}function Xt(e){if(typeof e!="string")return!1;let t=e.trim();return/^#([0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(t)||/^(rgb|rgba|hsl|hsla|color|oklch|lab|lch)\(/i.test(t)||/^[a-z][a-z0-9-]*$/i.test(t)}function se(e){let t=[],o=ie.join(e,"velu.json"),n;try{n=xe.readFileSync(o,"utf-8")}catch(i){return i.code==="ENOENT"?t.push(h({category:"config-json",file:"velu.json",title:"No velu.json found",hint:"Run `velu init <name>` to scaffold a project."})):t.push(h({category:"config-json",file:"velu.json",title:"Could not read velu.json"})),t}let r;try{r=JSON.parse(n)}catch(i){let a=/position (\d+)/.exec(i.message||""),l=a?Kt(n,Number(a[1])):null;return t.push(h({category:"config-json",file:"velu.json",line:l,title:"velu.json is not valid JSON",detail:String(i.message||"").replace(/\s+in JSON.*$/,""),hint:"Check for a trailing comma, a missing quote, or an unclosed brace."})),t}let s=null;try{s=JSON.parse(xe.readFileSync(Wt,"utf-8"))}catch{}if(s)for(let i of Zt(r,s,s)){let a=/^unknown field/.test(i.message);t.push(h({category:"config-schema",severity:a?"warning":"error",file:"velu.json",line:Z(n,i.key),title:i.path?`${i.path}: ${i.message}`:i.message,hint:a?"Remove it, or check the spelling against the velu.json schema.":""}))}for(let i of["primary","light","dark"]){let a=r.colors?.[i];a!=null&&!Xt(a)&&t.push(h({category:"config-schema",severity:"warning",file:"velu.json",line:Z(n,i),title:`colors.${i}: "${a}" doesn\u2019t look like a CSS color`,hint:"Use a hex value like #dc143c, an rgb()/hsl() function, or a CSS color name."}))}if(typeof r.favicon=="string"&&r.favicon.trim()){let i=ie.resolve(e,r.favicon.replace(/^\/+/,""));xe.existsSync(i)||t.push(h({category:"config-asset",file:"velu.json",line:Z(n,"favicon"),title:`favicon not found: ${r.favicon}`,hint:"The path is relative to the project root."}))}if(r.navigation&&typeof r.navigation=="object"){let i;try{i=B(r.navigation)}catch(a){t.push(h({category:"config-nav",file:"velu.json",line:Z(n,"navigation"),title:"navigation could not be processed",detail:String(a.message||"")})),i=null}if(i){let{pageEntries:a,warnings:l}=G(i,e);for(let u of l){let c=/not found$/.test(u),f=/page "([^"]+)"/.exec(u),_=f?Ge(n,f[1]):null;t.push(h({category:"config-nav",severity:c?"error":"warning",file:"velu.json",line:_,title:u,hint:c?"Create the .mdx file, or remove the page from navigation.":""}))}Qt(i,n,t)}}return t}function Qt(e,t,o){let n=new Set,r=s=>{if(!(!s||typeof s!="object")){if(s.language&&!n.has(s.language)){n.add(s.language);let i=String(s.language).toLowerCase();Yt.validate(i)||o.push(h({category:"config-nav",severity:"warning",file:"velu.json",line:Ge(t,s.language)||Z(t,"language"),title:`"${s.language}" is not a valid ISO 639-1 language code`,hint:'Use a two-letter code like "en", "fr", or "ja".'}))}for(let i of Object.values(s))Array.isArray(i)?i.forEach(r):i&&typeof i=="object"&&r(i)}};r(e)}var Ht,Wt,we=k(()=>{I();W();te();Ht=ie.dirname(Dt(import.meta.url)),Wt=ie.resolve(Ht,"..","..","schema","velu.schema.json")});import en from"node:fs/promises";import tn from"node:fs";import M from"node:path";import{fileURLToPath as nn,pathToFileURL as on}from"node:url";import{compile as rn}from"@mdx-js/mdx";import sn from"remark-frontmatter";import an from"remark-mdx-frontmatter";import ln from"remark-gfm";import cn from"rehype-slug";import{visit as un}from"unist-util-visit";function be(){if(ae)return ae;let e=M.dirname(nn(import.meta.url)),t=[M.resolve(e,"..","runtime","velu-ui"),M.resolve(e,"..","..","runtime","velu-ui"),M.resolve(e,"..","..","..","velu-ui","src")],o=null;for(let n of t){let r=M.join(n,"lib","component-schemas.js");if(tn.existsSync(r)){o=r;break}}return ae=o?import(on(o).href).then(n=>n.validateProps).catch(()=>null):Promise.resolve(null),ae}function fn(e){let t={};for(let o of e.attributes||[])o.type==="mdxJsxAttribute"&&(o.value==null?t[o.name]=!0:typeof o.value=="string"&&(t[o.name]=o.value));return t}function pn(e,t){return()=>o=>{un(o,n=>{if((n.type==="mdxJsxFlowElement"||n.type==="mdxJsxTextElement")&&typeof n.name=="string"&&/^[A-Z]/.test(n.name)&&!n.name.includes(".")&&e.push({name:n.name,props:fn(n),line:n.position?.start?.line??null,column:n.position?.start?.column??null}),n.type==="mdxjsEsm"&&typeof n.value=="string")for(let r of n.value.matchAll(/\b([A-Z][A-Za-z0-9_]*)\b/g))t.add(r[1])})}}async function mn(e,t){let o=[],n;try{n=await en.readFile(t.fileAbsPath,"utf-8")}catch{return o}let r=M.relative(e,t.fileAbsPath).split(M.sep).join("/"),s=[],i=new Set;try{await rn({value:n,path:t.fileAbsPath},{remarkPlugins:[sn,an,ln,Y,pn(s,i)],rehypePlugins:[cn],providerImportSource:"@mdx-js/react"})}catch(c){return o.push(K(c,{projectDir:e,knownComponents:R,file:r})),o}let a=new Set(R),l=await be(),u=new Set;for(let c of s)if(!i.has(c.name)){if(!a.has(c.name)){if(u.has(c.name))continue;u.add(c.name),o.push(h({category:"unknown-component",file:r,line:c.line,column:c.column,title:`<${c.name}> is not a built-in component`,hint:"Components are built in \u2014 check the spelling and capitalization (you don\u2019t import them).",suggestion:oe(c.name,R)}));continue}if(l){let f=l(c.name,c.props,{checkRequired:!1});f&&o.push(h({...f,file:r,line:c.line,column:c.column}))}}return o}async function Je(e,t){let o=t.filter(a=>a.exists),n=[],r=8,s=0;async function i(){for(;s<o.length;){let a=o[s++],l=await mn(e,a);for(let u of l)n.push(u)}}return await Promise.all(Array.from({length:Math.min(r,o.length)},i)),n}var ae,ke=k(()=>{fe();I();he();ye()});import{visit as dn}from"unist-util-visit";function gn(e,t){let o=qe(e).replace(/[?#].*$/,""),n=qe(t).replace(/\/+$/,"");return n&&o.toLowerCase().startsWith(n.toLowerCase())?o.slice(n.length).replace(/^\/+/,""):null}function De(e,t){return()=>(o,n)=>{typeof e=="function"&&dn(o,r=>{if(r.type!=="mdxJsxFlowElement"&&r.type!=="mdxJsxTextElement"||typeof r.name!="string"||!/^[A-Z]/.test(r.name)||r.name.includes("."))return;let s={};for(let a of r.attributes||[])a.type==="mdxJsxAttribute"&&(a.value==null?s[a.name]=!0:typeof a.value=="string"&&(s[a.name]=a.value));let i=e(r.name,s,{checkRequired:!1});if(i){let a=new Error(i.title);throw a.veluIssue={...i,file:gn(n?.path,t),line:r.position?.start?.line??null,column:r.position?.start?.column??null},a.loc={line:a.veluIssue.line,column:a.veluIssue.column},a}})}}var qe,Ye=k(()=>{qe=e=>String(e||"").replace(/\\/g,"/")});var et={};ue(et,{startDevServer:()=>Vn});import He from"node:fs/promises";import q from"node:fs";import hn from"node:http";import{spawn as vn}from"node:child_process";import b from"node:path";import{fileURLToPath as yn}from"node:url";import{createRequire as xn}from"node:module";import wn from"chokidar";import bn from"express";import kn from"@tailwindcss/vite";import Sn from"@vitejs/plugin-react";import $n from"@mdx-js/rollup";import jn from"remark-frontmatter";import An from"remark-mdx-frontmatter";import Pn from"remark-gfm";import Cn from"rehype-slug";import{createServer as En,searchForWorkspaceRoot as Tn}from"vite";function Fn(e){return`<link rel="stylesheet" href="${`https://fonts.googleapis.com/css2?family=${encodeURIComponent(e).replace(/%20/g,"+")}:wght@300;400;500;600;700&display=swap`}" />`}function Ke(e,t){let o=de(e,{color:!!process.stderr.isTTY});console.error(`
82
+ </html>`}var T,Ke=k(()=>{F();T=e=>String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")});var I,je=k(()=>{I=["Callout","Card","CardGroup","Accordion","AccordionGroup","Columns","Field","Prompt","Steps","Step","Tree","Folder","File","Image","CodeBlock","CodeGroup","MethodBadge","ApiPath","TryItBar","ApiField","ApiClient","ApiSidebar"]});import ce from"node:fs";import ee from"node:path";import{fileURLToPath as Qt}from"node:url";import en from"iso-639-1";function Q(e,t){if(!t)return null;let o=e.indexOf(`"${t}"`);return o===-1?null:e.slice(0,o).split(`
83
+ `).length}function on(e,t){return t==null||t<0?null:e.slice(0,t).split(`
84
+ `).length}function Ae(e,t){if(!t)return null;let o=e.indexOf(`"${t}"`);return o===-1?null:e.slice(0,o).split(`
85
+ `).length}function rn(e,t,o){let n=[];return s(e,t,"",null),n;function r(l){if(l&&l.$ref){let u=l.$ref.replace(/^#\//,"").split("/"),c=o;for(let f of u)c=c?.[f];return c||{}}return l}function i(l){return Array.isArray(l)?"array":l===null?"null":typeof l}function a(l,u){let c=n.length;s(l,u,"",null,!0);let f=n.length===c;return f||(n.length=c),f}function s(l,u,c,f,A){let p=r(u);if(p){if(p.oneOf){p.oneOf.some(d=>a(l,d))||n.push({path:c,key:f,message:"value does not match any allowed shape"});return}if(p.type&&i(l)!==p.type){n.push({path:c,key:f,message:`expected ${p.type}, got ${i(l)}`});return}if(p.type==="string"&&p.minLength!=null&&l.length<p.minLength&&n.push({path:c,key:f,message:"must not be empty"}),p.type==="object"&&i(l)==="object"){for(let d of p.required||[])d in l||n.push({path:c?`${c}.${d}`:d,key:d,message:`missing required "${d}"`});let L=p.properties||{};if(p.additionalProperties===!1)for(let d of Object.keys(l))d in L||n.push({path:c?`${c}.${d}`:d,key:d,message:`unknown field "${d}"`});for(let[d,N]of Object.entries(L))d in l&&s(l[d],N,c?`${c}.${d}`:d,d,A)}p.type==="array"&&Array.isArray(l)&&p.items&&l.forEach((L,d)=>s(L,p.items,`${c}[${d}]`,f,A))}}}function sn(e){if(typeof e!="string")return!1;let t=e.trim();return/^#([0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(t)||/^(rgb|rgba|hsl|hsla|color|oklch|lab|lch)\(/i.test(t)||/^[a-z][a-z0-9-]*$/i.test(t)}function ue(e){let t=[],o=ee.join(e,"velu.json"),n;try{n=ce.readFileSync(o,"utf-8")}catch(s){return s.code==="ENOENT"?t.push(v({category:"config-json",file:"velu.json",title:"No velu.json found",hint:"Run `velu init <name>` to scaffold a project."})):t.push(v({category:"config-json",file:"velu.json",title:"Could not read velu.json"})),t}let r;try{r=JSON.parse(n)}catch(s){let l=/position (\d+)/.exec(s.message||""),u=l?on(n,Number(l[1])):null;return t.push(v({category:"config-json",file:"velu.json",line:u,title:"velu.json is not valid JSON",detail:String(s.message||"").replace(/\s+in JSON.*$/,""),hint:"Check for a trailing comma, a missing quote, or an unclosed brace."})),t}let i=null;try{i=JSON.parse(ce.readFileSync(nn,"utf-8"))}catch{}if(i)for(let s of rn(r,i,i)){let l=/^unknown field/.test(s.message);t.push(v({category:"config-schema",severity:l?"warning":"error",file:"velu.json",line:Q(n,s.key),title:s.path?`${s.path}: ${s.message}`:s.message,hint:l?"Remove it, or check the spelling against the velu.json schema.":""}))}for(let s of["primary","light","dark"]){let l=r.colors?.[s];l!=null&&!sn(l)&&t.push(v({category:"config-schema",severity:"warning",file:"velu.json",line:Q(n,s),title:`colors.${s}: "${l}" doesn\u2019t look like a CSS color`,hint:"Use a hex value like #dc143c, an rgb()/hsl() function, or a CSS color name."}))}if(typeof r.favicon=="string"&&r.favicon.trim()){let s=ee.resolve(e,r.favicon.replace(/^\/+/,""));ce.existsSync(s)||t.push(v({category:"config-asset",file:"velu.json",line:Q(n,"favicon"),title:`favicon not found: ${r.favicon}`,hint:"The path is relative to the project root."}))}let a=Y(r.logo);if(a){let s=new Map;for(let l of["light","dark"]){let u=a[l];u&&s.set(u,[...s.get(u)||[],l])}for(let[l,u]of s)if(!ce.existsSync(ee.resolve(e,l.replace(/^\/+/,"")))){let c=u.length===2?"logo":`logo (${u[0]})`;t.push(v({category:"config-asset",file:"velu.json",line:Ae(n,l),title:`${c} not found: ${l}`,hint:"The path is relative to the project root."}))}}if(r.navigation&&typeof r.navigation=="object"){let s;try{s=V(r.navigation)}catch(l){t.push(v({category:"config-nav",file:"velu.json",line:Q(n,"navigation"),title:"navigation could not be processed",detail:String(l.message||"")})),s=null}if(s){let{pageEntries:l,warnings:u}=B(s,e);for(let c of u){let f=/not found$/.test(c),A=/page "([^"]+)"/.exec(c),p=A?Ae(n,A[1]):null;t.push(v({category:"config-nav",severity:f?"error":"warning",file:"velu.json",line:p,title:c,hint:f?"Create the .mdx file, or remove the page from navigation.":""}))}ln(s,n,t)}}return t}function ln(e,t,o){let n=new Set,r=i=>{if(!(!i||typeof i!="object")){if(i.language&&!n.has(i.language)){n.add(i.language);let a=String(i.language).toLowerCase();en.validate(a)||o.push(v({category:"config-nav",severity:"warning",file:"velu.json",line:Ae(t,i.language)||Q(t,"language"),title:`"${i.language}" is not a valid ISO 639-1 language code`,hint:'Use a two-letter code like "en", "fr", or "ja".'}))}for(let a of Object.values(i))Array.isArray(a)?a.forEach(r):a&&typeof a=="object"&&r(a)}};r(e)}var tn,nn,Le=k(()=>{F();W();se();re();tn=ee.dirname(Qt(import.meta.url)),nn=ee.resolve(tn,"..","..","schema","velu.schema.json")});import an from"node:fs/promises";import cn from"node:fs";import R from"node:path";import{fileURLToPath as un,pathToFileURL as fn}from"node:url";import{compile as pn}from"@mdx-js/mdx";import mn from"remark-frontmatter";import dn from"remark-mdx-frontmatter";import gn from"remark-gfm";import hn from"rehype-slug";import{visit as vn}from"unist-util-visit";function Oe(){if(fe)return fe;let e=R.dirname(un(import.meta.url)),t=[R.resolve(e,"..","runtime","velu-ui"),R.resolve(e,"..","..","runtime","velu-ui"),R.resolve(e,"..","..","..","velu-ui","src")],o=null;for(let n of t){let r=R.join(n,"lib","component-schemas.js");if(cn.existsSync(r)){o=r;break}}return fe=o?import(fn(o).href).then(n=>n.validateProps).catch(()=>null):Promise.resolve(null),fe}function yn(e){let t={};for(let o of e.attributes||[])o.type==="mdxJsxAttribute"&&(o.value==null?t[o.name]=!0:typeof o.value=="string"&&(t[o.name]=o.value));return t}function xn(e,t){return()=>o=>{vn(o,n=>{if((n.type==="mdxJsxFlowElement"||n.type==="mdxJsxTextElement")&&typeof n.name=="string"&&/^[A-Z]/.test(n.name)&&!n.name.includes(".")&&e.push({name:n.name,props:yn(n),line:n.position?.start?.line??null,column:n.position?.start?.column??null}),n.type==="mdxjsEsm"&&typeof n.value=="string")for(let r of n.value.matchAll(/\b([A-Z][A-Za-z0-9_]*)\b/g))t.add(r[1])})}}async function bn(e,t){let o=[],n;try{n=await an.readFile(t.fileAbsPath,"utf-8")}catch{return o}let r=R.relative(e,t.fileAbsPath).split(R.sep).join("/"),i=[],a=new Set;try{await pn({value:n,path:t.fileAbsPath},{remarkPlugins:[mn,dn,gn,D,xn(i,a)],rehypePlugins:[hn],providerImportSource:"@mdx-js/react"})}catch(c){return o.push(X(c,{projectDir:e,knownComponents:I,file:r})),o}let s=new Set(I),l=await Oe(),u=new Set;for(let c of i)if(!a.has(c.name)){if(!s.has(c.name)){if(u.has(c.name))continue;u.add(c.name),o.push(v({category:"unknown-component",file:r,line:c.line,column:c.column,title:`<${c.name}> is not a built-in component`,hint:"Components are built in \u2014 check the spelling and capitalization (you don\u2019t import them).",suggestion:le(c.name,I)}));continue}if(l){let f=l(c.name,c.props,{checkRequired:!1});f&&o.push(v({...f,file:r,line:c.line,column:c.column}))}}return o}async function We(e,t){let o=t.filter(s=>s.exists),n=[],r=8,i=0;async function a(){for(;i<o.length;){let s=o[i++],l=await bn(e,s);for(let u of l)n.push(u)}}return await Promise.all(Array.from({length:Math.min(r,o.length)},a)),n}var fe,_e=k(()=>{ge();F();Se();je()});import{visit as wn}from"unist-util-visit";function kn(e,t){let o=Ze(e).replace(/[?#].*$/,""),n=Ze(t).replace(/\/+$/,"");return n&&o.toLowerCase().startsWith(n.toLowerCase())?o.slice(n.length).replace(/^\/+/,""):null}function Xe(e,t){return()=>(o,n)=>{typeof e=="function"&&wn(o,r=>{if(r.type!=="mdxJsxFlowElement"&&r.type!=="mdxJsxTextElement"||typeof r.name!="string"||!/^[A-Z]/.test(r.name)||r.name.includes("."))return;let i={};for(let s of r.attributes||[])s.type==="mdxJsxAttribute"&&(s.value==null?i[s.name]=!0:typeof s.value=="string"&&(i[s.name]=s.value));let a=e(r.name,i,{checkRequired:!1});if(a){let s=new Error(a.title);throw s.veluIssue={...a,file:kn(n?.path,t),line:r.position?.start?.line??null,column:r.position?.start?.column??null},s.loc={line:s.veluIssue.line,column:s.veluIssue.column},s}})}}var Ze,Qe=k(()=>{Ze=e=>String(e||"").replace(/\\/g,"/")});var st={};de(st,{startDevServer:()=>Yn});import et from"node:fs/promises";import M from"node:fs";import Sn from"node:http";import{spawn as $n}from"node:child_process";import w from"node:path";import{fileURLToPath as jn}from"node:url";import{createRequire as An}from"node:module";import Ln from"chokidar";import On from"express";import _n from"@tailwindcss/vite";import Pn from"@vitejs/plugin-react";import Cn from"@mdx-js/rollup";import Tn from"remark-frontmatter";import En from"remark-mdx-frontmatter";import Nn from"remark-gfm";import Fn from"rehype-slug";import{createServer as In,searchForWorkspaceRoot as Rn}from"vite";function Vn(e){return`<link rel="stylesheet" href="${`https://fonts.googleapis.com/css2?family=${encodeURIComponent(e).replace(/%20/g,"+")}:wght@300;400;500;600;700&display=swap`}" />`}function nt(e,t){let o=we(e,{color:!!process.stderr.isTTY});console.error(`
86
86
  `+o+`
87
- `),process.env.VELU_DEBUG&&t&&console.error(t)}function In(){try{return JSON.parse(q.readFileSync(b.join(J,"package.json"),"utf8")).version||"unknown"}catch{return"unknown"}}function Rn(e,t){let o=b.resolve(e,".velu",".velu-version"),n=null;try{n=q.readFileSync(o,"utf8").trim()}catch{}if(n===t)return!1;try{q.mkdirSync(b.dirname(o),{recursive:!0}),q.writeFileSync(o,t)}catch{}return!0}async function Ze(e){try{return await Ee(e)}catch{return pe({},b.basename(e))}}async function Xe(e,t){let o=await e.moduleGraph.getModuleByUrl(t,!0),n=new Map,r=new Set;async function s(i){if(!(!i||r.has(i.url))){if(r.add(i.url),i.id&&On.test(i.id)){let a=i.url.includes("?")?"&":"?",l=await e.transformRequest(`${i.url}${a}direct`);l?.code&&n.set(i.url,l.code)}for(let a of i.importedModules)await s(a)}}return await s(o),[...n.values()].join(`
88
- `)}function zn(e,t){let o=()=>{process.stdout.isTTY&&!process.env.VELU_NO_BELL&&process.stdout.write("\x07")},n=process.stdout.isTTY,r=f=>n&&process.stdout.write(`\x1B]${f}\x1B\\`),s=()=>{r(`0;\u23F3 ${t}`),r("9;4;3;0")},i=()=>{r(`0;${t}`),r("9;4;0;0")};if(n&&process.once("exit",()=>r("9;4;0;0")),s(),!e)return console.log("Starting Velu\u2026"),{ready:f=>{console.log(`Velu ready \u2192 ${f}`),i(),o()}};let a="\x1B[38;2;220;20;60m",l="\x1B[0m";console.log("");for(let f of Mn)console.log(`${a}${f}${l}`);console.log("");let u=null;try{u=vn(process.execPath,["-e",Un],{stdio:["ignore","inherit","ignore"]}),u.on("error",()=>{})}catch{}let c=()=>{if(u){try{u.kill()}catch{}u=null}};return process.once("exit",c),{ready:f=>{c(),process.stdout.write("\x1B[2K\r"),console.log(` \x1B[32m\u2713${l} Velu ready \u2192 \x1B[36m${f}${l}`),i(),o()}}}async function Vn(e){let t=!!process.env.VELU_PROFILE,o=performance.now(),n=(x,p)=>t&&console.log(`[velu-profile] ${x}: ${(performance.now()-p).toFixed(0)}ms`),r=zn(!!process.stdout.isTTY&&!t,b.basename(e)),s=await Ze(e),i=a();function a(){let p=se(e).filter(w=>w.severity==="error"&&(w.category==="config-json"||w.category==="config-schema"));return p.length&&console.error(`
89
- `+re(p,{color:!!process.stderr.isTTY})+`
90
- `),p}let l=e;try{l=q.realpathSync(e)}catch{}let u=0,c=x=>{let p=performance.now();if(p-u<500)return;u=p;let w=K(x,{projectDir:l,knownComponents:R});Ke(w,x)};process.on("unhandledRejection",c),process.on("uncaughtException",c);let _=xn(import.meta.url).resolve("@mdx-js/react"),d=b.resolve(J,"runtime","velu-ui"),j=q.existsSync(d)?d:b.resolve(J,"..","velu-ui","src"),m=[{find:"@mdx-js/react",replacement:_},{find:/^velu-ui$/,replacement:b.join(j,"index.js")},{find:/^velu-ui\//,replacement:j+"/"}],L=Number(process.env.PORT)||8358,C=await be(),E=Rn(e,In());E&&console.log("[velu] new version detected \u2014 refreshing the preview cache\u2026");let F=bn(),X=hn.createServer(F),y=await En({root:J,appType:"custom",logLevel:t?"info":"warn",plugins:[Ue(e),$n({remarkPlugins:[jn,An,Pn,Y,De(C,e)],rehypePlugins:[Cn],providerImportSource:"@mdx-js/react"}),Sn(),kn()],cacheDir:b.resolve(e,".velu","vite-cache"),optimizeDeps:{force:E,include:["react","react-dom","react-dom/client","react-router-dom","@mdx-js/react","lucide-react","prism-react-renderer","iso-639-1","github-slugger"],esbuildOptions:{loader:{".mdx":"jsx"}}},resolve:{alias:m,dedupe:["react","react-dom","@mdx-js/react"]},server:{middlewareMode:!0,fs:{allow:[Tn(J),e,l]},hmr:{server:X}}});n("vite server created",o),F.use(y.middlewares),F.get(We,async(x,p,w)=>{if(!s.favicon)return p.status(404).end();let g=b.resolve(e,s.favicon.replace(/^\//,""));p.sendFile(g,T=>{T&&p.status(404).end()})}),F.use("*",async(x,p,w)=>{let g=x.originalUrl,T=performance.now();if(i.length)return p.status(200).set({"Content-Type":"text/html"}).end(ve(i,{title:"Fix velu.json to continue"}));try{let v=performance.now(),A=await He.readFile(Qe,"utf-8");A=await y.transformIndexHtml(g,A),n(`transformIndexHtml ${g}`,v);let U="/src/runtime/server-entry.jsx";v=performance.now();let{render:Q}=await y.ssrLoadModule(U);n(`ssrLoadModule ${g} (1st req includes dep pre-bundle)`,v),v=performance.now();let S=await Q(g);n(`render ${g}`,v),v=performance.now();let D=await Xe(y,U);n(`collectSsrCss ${g}`,v);let ce=D?`<style data-velu-ssr>${D}</style>`:"",st=`<style data-velu-config>
91
- ${Te(s)}
92
- </style>`,at=Nn.has(s.font.family)?"":Fn(s.font.family),lt=s.favicon?`<link rel="icon" href="${We}" />`:"",ct=[ce,st,at,lt].filter(Boolean).join(`
93
- `),ut=A.replace("<!--app-title-->",Ln(s.name)).replace("<!--app-head-->",ct).replace("<!--app-html-->",S);p.status(200).set({"Content-Type":"text/html"}).end(ut),n(`TOTAL ${g}`,T)}catch(v){y.ssrFixStacktrace(v);let A=K(v,{projectDir:l,knownComponents:R});Ke(A,v),p.status(200).set({"Content-Type":"text/html"}).end(ve([A]))}}),wn.watch(e,{ignoreInitial:!0,ignored:/(^|[\\/])(node_modules|\.git|\.velu)([\\/]|$)/,awaitWriteFinish:{stabilityThreshold:100,pollInterval:20}}).on("all",async(x,p)=>{console.log(`[velu-cli] content ${x}: ${b.relative(e,p)}`);let w=b.basename(p)==="velu.json",g=p.endsWith(".mdx"),T=w||g&&(x==="add"||x==="unlink");if(w&&(s=await Ze(e),i=a()),T)y.moduleGraph.invalidateAll();else if(g){let v=p.split(b.sep).join("/"),A=y.moduleGraph.getModulesByFile(v);if(A)for(let U of A)y.moduleGraph.invalidateModule(U)}y.ws.send({type:"full-reload"})});async function $e(x){let p=new Set,w=12,g=0,T=[],v=()=>g<w?(g+=1,Promise.resolve()):new Promise(S=>T.push(S)).then(()=>{g+=1}),A=()=>{g-=1,T.shift()?.()},U=S=>/[\\/]\.velu[\\/]vite-cache[\\/]|[\\/]deps[\\/]/.test(S)||/[\\/]node_modules[\\/]/.test(S)&&!/velu-ui/.test(S);async function Q(S){if(!(!S||p.has(S)||U(S))){p.add(S);try{await v();try{await y.transformRequest(S,{ssr:!1})}finally{A()}let D=await y.moduleGraph.getModuleByUrl(S,!1);D?.importedModules?.size&&await Promise.all([...D.importedModules].map(ce=>Q(ce.url)))}catch{}}}return await Q(x),p.size}X.listen(L,async()=>{let x=performance.now(),p=0;try{let{render:w}=await y.ssrLoadModule("/src/runtime/server-entry.jsx");await $e("/src/runtime/client-entry.jsx"),typeof y.waitForRequestsIdle=="function"&&await y.waitForRequestsIdle();let[g]=await Promise.allSettled([$e("/src/runtime/client-entry.jsx"),w("/"),y.transformIndexHtml("/",await He.readFile(Qe,"utf-8")),Xe(y,"/src/runtime/server-entry.jsx")]).then(T=>T.map(v=>v.status==="fulfilled"?v.value:0));p=g}catch(w){t&&console.log("[velu-profile] warmup error:",w?.message)}n(`cold-start warm-up (${p} client modules)`,x),r.ready(`http://localhost:${L}`)})}var _n,On,Nn,We,Ln,J,Qe,Mn,Un,tt=k(()=>{fe();_e();ze();he();Be();I();ye();we();ke();Ye();_n=b.dirname(yn(import.meta.url)),On=/\.(css|less|sass|scss|styl|stylus|pcss|postcss)(\?|$)/,Nn=new Set(["Google Sans Flex","Google Sans Code","Outfit"]),We="/@velu-favicon",Ln=e=>String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");J=b.resolve(_n,".."),Qe=b.resolve(J,"src","template.html"),Mn=[" _ __ __","| | / /__ / /_ __","| | / / _ \\/ / / / /","| |/ / __/ / /_/ /","|___/\\___/_/\\__,_/"],Un="const F=['\u280B','\u2819','\u2839','\u2838','\u283C','\u2834','\u2826','\u2827','\u2807','\u280F'],M=['Starting Velu','Setting up your preview','Preparing your docs','Warming things up','Almost ready'];let f=0,m=0;const t=Date.now();const C='\\x1b[38;2;220;20;60m',R='\\x1b[0m',D='\\x1b[2m';const d=()=>{const s=(Date.now()-t)/1000|0;process.stdout.write('\\x1b[2K\\r '+C+F[f]+R+' '+M[m]+'\\u2026 '+D+s+'s'+R);f=(f+1)%F.length;};d();setInterval(d,90);setInterval(()=>{if(m<M.length-1)m++;},4000);"});var ot={};ue(ot,{default:()=>qn,runValidate:()=>nt});import Bn from"node:fs";import Gn from"node:path";function Jn(e){try{let t=JSON.parse(Bn.readFileSync(Gn.join(e,"velu.json"),"utf-8"));if(!t.navigation||typeof t.navigation!="object")return[];let o=B(t.navigation);return G(o,e).pageEntries}catch{return[]}}async function nt(e){let t=se(e),o=Jn(e),n=await Je(e,o),r=[...t,...n],s=!!process.stdout.isTTY;return console.log(re(r,{color:s})),r.some(a=>a.severity!=="warning"&&a.severity!=="info")?1:0}var qn,rt=k(()=>{W();te();we();ke();I();qn=nt});import Se from"node:path";import N from"node:process";import{readFileSync as Dn}from"node:fs";var[,,it,le]=N.argv;function Yn(){try{return JSON.parse(Dn(new URL("../package.json",import.meta.url),"utf8")).version}catch{return"unknown"}}async function Hn(){switch(it){case"--version":case"-v":case"version":{console.log(Yn());break}case"init":{le||(console.error("Usage: velu init <project-name>"),N.exit(1));let e=le,t=Se.resolve(N.cwd(),e),{initProject:o}=await Promise.resolve().then(()=>(Pe(),Ae));await o(t,e);break}case"dev":{let e=Se.resolve(N.cwd(),le??"."),{startDevServer:t}=await Promise.resolve().then(()=>(tt(),et));await t(e);break}case"validate":{let e=Se.resolve(N.cwd(),le??"."),{runValidate:t}=await Promise.resolve().then(()=>(rt(),ot)),o=await t(e);N.exit(o);break}default:console.log("Usage:"),console.log(" velu init <project-name> scaffold a new docs project"),console.log(" velu dev [dir] start the dev preview server"),console.log(" velu validate [dir] check velu.json + content for problems"),N.exit(it?1:0)}}Hn().catch(e=>{console.error(N.env.VELU_DEBUG?e:`Error: ${e.message}`),N.exit(1)});
87
+ `),process.env.VELU_DEBUG&&t&&console.error(t)}function Bn(){try{return JSON.parse(M.readFileSync(w.join(J,"package.json"),"utf8")).version||"unknown"}catch{return"unknown"}}function Jn(e,t){let o=w.resolve(e,".velu"),n=w.resolve(o,".velu-version"),r=null;try{r=M.readFileSync(n,"utf8").trim()}catch{}if(r!==t){if(r!==null)try{M.rmSync(w.join(o,"vite-cache"),{recursive:!0,force:!0}),console.log("[velu] new version detected \u2014 refreshing the preview cache\u2026")}catch{}try{M.mkdirSync(o,{recursive:!0}),M.writeFileSync(n,t)}catch{}}}async function ot(e){try{return await Re(e)}catch{return xe({},w.basename(e))}}async function rt(e,t){let o=await e.moduleGraph.getModuleByUrl(t,!0),n=new Map,r=new Set;async function i(a){if(!(!a||r.has(a.url))){if(r.add(a.url),a.id&&Un.test(a.id)){let s=a.url.includes("?")?"&":"?",l=await e.transformRequest(`${a.url}${s}direct`);l?.code&&n.set(a.url,l.code)}for(let s of a.importedModules)await i(s)}}return await i(o),[...n.values()].join(`
88
+ `)}function Dn(e,t){let o=()=>{process.stdout.isTTY&&!process.env.VELU_NO_BELL&&process.stdout.write("\x07")},n=process.stdout.isTTY,r=f=>n&&process.stdout.write(`\x1B]${f}\x1B\\`),i=()=>{r(`0;\u23F3 ${t}`),r("9;4;3;0")},a=()=>{r(`0;${t}`),r("9;4;0;0")};if(n&&process.once("exit",()=>r("9;4;0;0")),i(),!e)return console.log("Starting Velu\u2026"),{ready:f=>{console.log(`Velu ready \u2192 ${f}`),a(),o()}};let s="\x1B[38;2;220;20;60m",l="\x1B[0m";console.log("");for(let f of qn)console.log(`${s}${f}${l}`);console.log("");let u=null;try{u=$n(process.execPath,["-e",Hn],{stdio:["ignore","inherit","ignore"]}),u.on("error",()=>{})}catch{}let c=()=>{if(u){try{u.kill()}catch{}u=null}};return process.once("exit",c),{ready:f=>{c(),process.stdout.write("\x1B[2K\r"),console.log(` \x1B[32m\u2713${l} Velu ready \u2192 \x1B[36m${f}${l}`),a(),o()}}}async function Yn(e){let t=!!process.env.VELU_PROFILE,o=performance.now(),n=(x,m)=>t&&console.log(`[velu-profile] ${x}: ${(performance.now()-m).toFixed(0)}ms`),r=Dn(!!process.stdout.isTTY&&!t,w.basename(e)),i=await ot(e),a=s();function s(){let m=ue(e).filter(h=>h.severity==="error"&&(h.category==="config-json"||h.category==="config-schema"));return m.length&&console.error(`
89
+ `+ae(m,{color:!!process.stderr.isTTY})+`
90
+ `),m}let l=e;try{l=M.realpathSync(e)}catch{}let u=0,c=x=>{let m=performance.now();if(m-u<500)return;u=m;let h=X(x,{projectDir:l,knownComponents:I});nt(h,x)};process.on("unhandledRejection",c),process.on("uncaughtException",c);let A=An(import.meta.url).resolve("@mdx-js/react"),p=w.resolve(J,"runtime","velu-ui"),L=M.existsSync(p)?p:w.resolve(J,"..","velu-ui","src"),d=[{find:"@mdx-js/react",replacement:A},{find:/^velu-ui$/,replacement:w.join(L,"index.js")},{find:/^velu-ui\//,replacement:L+"/"}],N=Number(process.env.PORT)||8358,C=await Oe();Jn(e,Bn());let S=On(),q=Sn.createServer(S),y=await In({root:J,appType:"custom",logLevel:t?"info":"warn",plugins:[He(e),Cn({remarkPlugins:[Tn,En,Nn,D,Xe(C,e)],rehypePlugins:[Fn],providerImportSource:"@mdx-js/react"}),Pn(),_n()],cacheDir:w.resolve(e,".velu","vite-cache"),optimizeDeps:{include:["react","react-dom","react-dom/client","react-router-dom","@mdx-js/react","lucide-react","prism-react-renderer","iso-639-1","github-slugger"],exclude:["tailwindcss","@tailwindcss/oxide","playwright","playwright-core"],esbuildOptions:{loader:{".mdx":"jsx"}}},resolve:{alias:d,dedupe:["react","react-dom","@mdx-js/react"]},server:{middlewareMode:!0,fs:{allow:[Rn(J),e,l]},hmr:{server:q}}});n("vite server created",o),S.use(y.middlewares),S.get(tt,async(x,m,h)=>{if(!i.favicon)return m.status(404).end();let g=w.resolve(e,i.favicon.replace(/^\//,""));m.sendFile(g,O=>{O&&m.status(404).end()})});let Ce=x=>(m,h)=>{let g=i.logo?.[x];if(!g)return h.status(404).end();h.sendFile(w.resolve(e,g.replace(/^\//,"")),O=>{O&&h.status(404).end()})};S.get(ne,Ce("light")),S.get(oe,Ce("dark")),S.use("*",async(x,m,h)=>{let g=x.originalUrl,O=performance.now();if(a.length)return m.status(200).set({"Content-Type":"text/html"}).end($e(a,{title:"Fix velu.json to continue"}));try{let b=performance.now(),_=await et.readFile(it,"utf-8");_=await y.transformIndexHtml(g,_),n(`transformIndexHtml ${g}`,b);let U="/src/runtime/server-entry.jsx";b=performance.now();let{render:te}=await y.ssrLoadModule(U);n(`ssrLoadModule ${g} (1st req includes dep pre-bundle)`,b),b=performance.now();let $=await te(g);n(`render ${g}`,b),b=performance.now();let H=await rt(y,U);n(`collectSsrCss ${g}`,b);let me=H?`<style data-velu-ssr>${H}</style>`:"",pt=`<style data-velu-config>
91
+ ${Me(i)}
92
+ </style>`,mt=zn.has(i.font.family)?"":Vn(i.font.family),dt=i.favicon?`<link rel="icon" href="${tt}" />`:"",gt=[me,pt,mt,dt].filter(Boolean).join(`
93
+ `),ht=_.replace("<!--app-title-->",Gn(i.name)).replace("<!--app-head-->",gt).replace("<!--app-html-->",$);m.status(200).set({"Content-Type":"text/html"}).end(ht),n(`TOTAL ${g}`,O)}catch(b){y.ssrFixStacktrace(b);let _=X(b,{projectDir:l,knownComponents:I});nt(_,b),m.status(200).set({"Content-Type":"text/html"}).end($e([_]))}}),Ln.watch(e,{ignoreInitial:!0,ignored:/(^|[\\/])(node_modules|\.git|\.velu)([\\/]|$)/,awaitWriteFinish:{stabilityThreshold:100,pollInterval:20}}).on("all",async(x,m)=>{console.log(`[velu-cli] content ${x}: ${w.relative(e,m)}`);let h=w.basename(m)==="velu.json",g=m.endsWith(".mdx"),O=h||g&&(x==="add"||x==="unlink");if(h&&(i=await ot(e),a=s()),O)y.moduleGraph.invalidateAll();else if(g){let b=m.split(w.sep).join("/"),_=y.moduleGraph.getModulesByFile(b);if(_)for(let U of _)y.moduleGraph.invalidateModule(U)}y.ws.send({type:"full-reload"})});async function Te(x){let m=new Set,h=12,g=0,O=[],b=()=>g<h?(g+=1,Promise.resolve()):new Promise($=>O.push($)).then(()=>{g+=1}),_=()=>{g-=1,O.shift()?.()},U=$=>/[\\/]\.velu[\\/]vite-cache[\\/]|[\\/]deps[\\/]/.test($)||/[\\/]node_modules[\\/]/.test($)&&!/velu-ui/.test($);async function te($){if(!(!$||m.has($)||U($))){m.add($);try{await b();try{await y.transformRequest($,{ssr:!1})}finally{_()}let H=await y.moduleGraph.getModuleByUrl($,!1);H?.importedModules?.size&&await Promise.all([...H.importedModules].map(me=>te(me.url)))}catch{}}}return await te(x),m.size}q.listen(N,async()=>{let x=performance.now(),m=0;try{let{render:h}=await y.ssrLoadModule("/src/runtime/server-entry.jsx");await Te("/src/runtime/client-entry.jsx"),typeof y.waitForRequestsIdle=="function"&&await y.waitForRequestsIdle();let[g]=await Promise.allSettled([Te("/src/runtime/client-entry.jsx"),h("/"),y.transformIndexHtml("/",await et.readFile(it,"utf-8")),rt(y,"/src/runtime/server-entry.jsx")]).then(O=>O.map(b=>b.status==="fulfilled"?b.value:0));m=g}catch(h){t&&console.log("[velu-profile] warmup error:",h?.message)}n(`cold-start warm-up (${m} client modules)`,x),r.ready(`http://localhost:${N}`)})}var Mn,Un,zn,tt,Gn,J,it,qn,Hn,lt=k(()=>{ge();re();De();Se();Ke();F();je();Le();_e();Qe();Mn=w.dirname(jn(import.meta.url)),Un=/\.(css|less|sass|scss|styl|stylus|pcss|postcss)(\?|$)/,zn=new Set(["Google Sans Flex","Google Sans Code","Outfit"]),tt="/@velu-favicon",Gn=e=>String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");J=w.resolve(Mn,".."),it=w.resolve(J,"src","template.html"),qn=[" _ __ __","| | / /__ / /_ __","| | / / _ \\/ / / / /","| |/ / __/ / /_/ /","|___/\\___/_/\\__,_/"],Hn="const F=['\u280B','\u2819','\u2839','\u2838','\u283C','\u2834','\u2826','\u2827','\u2807','\u280F'],M=['Starting Velu','Setting up your preview','Preparing your docs','Warming things up','Almost ready'];let f=0,m=0;const t=Date.now();const C='\\x1b[38;2;220;20;60m',R='\\x1b[0m',D='\\x1b[2m';const d=()=>{const s=(Date.now()-t)/1000|0;process.stdout.write('\\x1b[2K\\r '+C+F[f]+R+' '+M[m]+'\\u2026 '+D+s+'s'+R);f=(f+1)%F.length;};d();setInterval(d,90);setInterval(()=>{if(m<M.length-1)m++;},4000);"});var ct={};de(ct,{default:()=>Xn,runValidate:()=>at});import Kn from"node:fs";import Wn from"node:path";function Zn(e){try{let t=JSON.parse(Kn.readFileSync(Wn.join(e,"velu.json"),"utf-8"));if(!t.navigation||typeof t.navigation!="object")return[];let o=V(t.navigation);return B(o,e).pageEntries}catch{return[]}}async function at(e){let t=ue(e),o=Zn(e),n=await We(e,o),r=[...t,...n],i=!!process.stdout.isTTY;return console.log(ae(r,{color:i})),r.some(s=>s.severity!=="warning"&&s.severity!=="info")?1:0}var Xn,ut=k(()=>{W();se();Le();_e();F();Xn=at});import Pe from"node:path";import E from"node:process";import{readFileSync as Qn}from"node:fs";var[,,ft,pe]=E.argv;function eo(){try{return JSON.parse(Qn(new URL("../package.json",import.meta.url),"utf8")).version}catch{return"unknown"}}async function to(){switch(ft){case"--version":case"-v":case"version":{console.log(eo());break}case"init":{pe||(console.error("Usage: velu init <project-name>"),E.exit(1));let e=pe,t=Pe.resolve(E.cwd(),e),{initProject:o}=await Promise.resolve().then(()=>(Fe(),Ne));await o(t,e);break}case"dev":{let e=Pe.resolve(E.cwd(),pe??"."),{startDevServer:t}=await Promise.resolve().then(()=>(lt(),st));await t(e);break}case"validate":{let e=Pe.resolve(E.cwd(),pe??"."),{runValidate:t}=await Promise.resolve().then(()=>(ut(),ct)),o=await t(e);E.exit(o);break}default:console.log("Usage:"),console.log(" velu init <project-name> scaffold a new docs project"),console.log(" velu dev [dir] start the dev preview server"),console.log(" velu validate [dir] check velu.json + content for problems"),E.exit(ft?1:0)}}to().catch(e=>{console.error(E.env.VELU_DEBUG?e:`Error: ${e.message}`),E.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veluai/velu",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "type": "module",
5
5
  "bin": "./dist/cli.js",
6
6
  "publishConfig": {
@@ -50,6 +50,7 @@
50
50
  "vite": "^5.4.11"
51
51
  },
52
52
  "devDependencies": {
53
- "esbuild": "^0.28.0"
53
+ "esbuild": "^0.28.0",
54
+ "playwright": "^1.48.0"
54
55
  }
55
56
  }
@@ -1,64 +1,64 @@
1
- import React from 'react';
2
- import resolveIcon from '../lib/resolveIcon.jsx';
3
-
4
- /**
5
- * Accordion + AccordionGroup — collapsible disclosure.
6
- *
7
- * Native <details>/<summary>: zero JS, SSR-safe, accessible, chevron rotates
8
- * via CSS on [open] (same pattern as Sidebar). Fully tokenized — border /
9
- * hover / expanded surface / radius / spacing / type all from base.css
10
- * tokens, so light + dark theme automatically via [data-theme].
11
- *
12
- * - <Accordion title=… defaultOpen?>content</Accordion> — standalone bordered
13
- * rounded box.
14
- * - <AccordionGroup><Accordion/>…</AccordionGroup> — items joined into ONE
15
- * bordered box with dividers between them (no per-item border/radius). A
16
- * context tells nested Accordions they're grouped so they drop their own
17
- * chrome; the group container owns the border + radius + dividers.
18
- *
19
- * @param {{ title: React.ReactNode, defaultOpen?: boolean,
20
- * children: React.ReactNode, className?: string }} props
21
- */
22
-
23
- const GroupCtx = React.createContext(false);
24
-
25
- export function Accordion({
26
- title,
27
- defaultOpen = false,
28
- children,
29
- className = '',
30
- ...rest
31
- }) {
32
- const inGroup = React.useContext(GroupCtx);
33
- const cls = [
34
- 'velu-accordion',
35
- inGroup ? 'velu-accordion--in-group' : '',
36
- className,
37
- ]
38
- .filter(Boolean)
39
- .join(' ');
40
-
41
- return (
42
- <details className={cls} open={defaultOpen || undefined} {...rest}>
43
- <summary className="velu-accordion__summary">
44
- <span className="velu-accordion__chevron" aria-hidden="true">
45
- {resolveIcon('chevron-right', { size: '1em' })}
46
- </span>
47
- <span className="velu-accordion__title">{title}</span>
48
- </summary>
49
- <div className="velu-accordion__content">{children}</div>
50
- </details>
51
- );
52
- }
53
-
54
- export function AccordionGroup({ children, className = '', ...rest }) {
55
- return (
56
- <GroupCtx.Provider value={true}>
57
- <div className={`velu-accordion-group ${className}`.trim()} {...rest}>
58
- {children}
59
- </div>
60
- </GroupCtx.Provider>
61
- );
62
- }
63
-
64
- export default Accordion;
1
+ import React from 'react';
2
+ import resolveIcon from '../lib/resolveIcon.jsx';
3
+
4
+ /**
5
+ * Accordion + AccordionGroup — collapsible disclosure.
6
+ *
7
+ * Native <details>/<summary>: zero JS, SSR-safe, accessible, chevron rotates
8
+ * via CSS on [open] (same pattern as Sidebar). Fully tokenized — border /
9
+ * hover / expanded surface / radius / spacing / type all from base.css
10
+ * tokens, so light + dark theme automatically via [data-theme].
11
+ *
12
+ * - <Accordion title=… defaultOpen?>content</Accordion> — standalone bordered
13
+ * rounded box.
14
+ * - <AccordionGroup><Accordion/>…</AccordionGroup> — items joined into ONE
15
+ * bordered box with dividers between them (no per-item border/radius). A
16
+ * context tells nested Accordions they're grouped so they drop their own
17
+ * chrome; the group container owns the border + radius + dividers.
18
+ *
19
+ * @param {{ title: React.ReactNode, defaultOpen?: boolean,
20
+ * children: React.ReactNode, className?: string }} props
21
+ */
22
+
23
+ const GroupCtx = React.createContext(false);
24
+
25
+ export function Accordion({
26
+ title,
27
+ defaultOpen = false,
28
+ children,
29
+ className = '',
30
+ ...rest
31
+ }) {
32
+ const inGroup = React.useContext(GroupCtx);
33
+ const cls = [
34
+ 'velu-accordion',
35
+ inGroup ? 'velu-accordion--in-group' : '',
36
+ className,
37
+ ]
38
+ .filter(Boolean)
39
+ .join(' ');
40
+
41
+ return (
42
+ <details className={cls} open={defaultOpen || undefined} {...rest}>
43
+ <summary className="velu-accordion__summary">
44
+ <span className="velu-accordion__chevron" aria-hidden="true">
45
+ {resolveIcon('chevron-right', { size: '1em' })}
46
+ </span>
47
+ <span className="velu-accordion__title">{title}</span>
48
+ </summary>
49
+ <div className="velu-accordion__content">{children}</div>
50
+ </details>
51
+ );
52
+ }
53
+
54
+ export function AccordionGroup({ children, className = '', ...rest }) {
55
+ return (
56
+ <GroupCtx.Provider value={true}>
57
+ <div className={`velu-accordion-group ${className}`.trim()} {...rest}>
58
+ {children}
59
+ </div>
60
+ </GroupCtx.Provider>
61
+ );
62
+ }
63
+
64
+ export default Accordion;