@santi020k/lumen-mcp 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/lumen-mcp-local.mjs +3 -2
- package/data/lumen-data.json +342 -15
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +39 -35
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +70 -54
- package/package.json +1 -1
package/bin/lumen-mcp-local.mjs
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
1
|
import { spawnSync } from 'node:child_process'
|
|
3
|
-
import * as fs from 'node:fs/promises'
|
|
4
2
|
import { dirname, join, resolve } from 'node:path'
|
|
5
3
|
import { fileURLToPath } from 'node:url'
|
|
6
4
|
|
|
@@ -9,6 +7,7 @@ const repoRoot = resolve(packageRoot, '../..')
|
|
|
9
7
|
const distEntry = join(packageRoot, 'dist/index.js')
|
|
10
8
|
|
|
11
9
|
const filesIn = async (directory) => {
|
|
10
|
+
const fs = await import('node:fs/promises')
|
|
12
11
|
const entries = await fs.readdir(directory, { withFileTypes: true })
|
|
13
12
|
|
|
14
13
|
const nested = await Promise.all(entries.map((entry) => {
|
|
@@ -21,6 +20,8 @@ const filesIn = async (directory) => {
|
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
const needsBuild = async () => {
|
|
23
|
+
const fs = await import('node:fs/promises')
|
|
24
|
+
|
|
24
25
|
try {
|
|
25
26
|
await fs.access(distEntry)
|
|
26
27
|
} catch {
|
package/data/lumen-data.json
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"Checkbox": "d971d97482ba924a07d4891cc782dd14c87b9f8bdb7b4070181b2189748b8be1",
|
|
24
24
|
"Collapsible": "7652876be7a40fc2451168ea8220c49a5ef0fcfddc04d6d5ff424e6d2d26a04a",
|
|
25
25
|
"Code": "e2f5eea415e1d2212dcb782487b417806f7ba6a7b1469f1b74a082fe35523275",
|
|
26
|
+
"CodeTabs": "2fc520388101b91ed507df0bc2d26cd97cb45cdf7510017d81c6fb4c85e7d51a",
|
|
26
27
|
"Combobox": "93821fbc97e296cf426a53f52eda225b0361fba9c22a2f612436008be8efe4e2",
|
|
27
28
|
"Command": "41c6175a15f7267bbf42fd00b74127571875e80a79d3f6700fad0abc3ccde09a",
|
|
28
29
|
"ContextMenu": "93130a486b3e5c33c3ba05c510069bb51ab7be4a37ab0f1d45c50064527e8512",
|
|
@@ -30,7 +31,7 @@
|
|
|
30
31
|
"DataTable": "98b6681fe1324a2367d47cac7a406b9ad85fc2c04746ff1c5b0fe7bc7c9fea68",
|
|
31
32
|
"DatePicker": "6a70845a80a56e740a6a9dd8958d20255812e4dde78ace4beb86338a08f9bcae",
|
|
32
33
|
"DateRangePicker": "e4d2f62fac35eda4d7662a745b0121bfa1aa995658cd51f8203836298a4028a8",
|
|
33
|
-
"Dialog": "
|
|
34
|
+
"Dialog": "35302b79415111b97316bf2590e1b50d25f4ab606705e4a51feb768b5c79e8c5",
|
|
34
35
|
"Direction": "ceba5f37b9f7a2e8f0b0d70175b1dc161bfe0674db962adc837838f2f20de51c",
|
|
35
36
|
"Drawer": "8ef5a38b8fbcce6a27b10523b57cfd30728ec2f902515ada9566a2f21b2ec302",
|
|
36
37
|
"DropdownMenu": "104ffe49547e89a91d312d9bdfcbab4ec76188decbad8140ef920bfe91804d7c",
|
|
@@ -4281,6 +4282,309 @@
|
|
|
4281
4282
|
"recipes": [],
|
|
4282
4283
|
"runtimeEvents": []
|
|
4283
4284
|
},
|
|
4285
|
+
{
|
|
4286
|
+
"apiReference": [
|
|
4287
|
+
{
|
|
4288
|
+
"attribute": "items",
|
|
4289
|
+
"defaultValue": "required",
|
|
4290
|
+
"description": "Defines the labelled code examples and their stable selection values.",
|
|
4291
|
+
"values": "Array<{ code, label, language?, value }>"
|
|
4292
|
+
},
|
|
4293
|
+
{
|
|
4294
|
+
"attribute": "ariaLabel",
|
|
4295
|
+
"defaultValue": "\"Code examples\"",
|
|
4296
|
+
"description": "Names the tab list for assistive technology.",
|
|
4297
|
+
"values": "string"
|
|
4298
|
+
},
|
|
4299
|
+
{
|
|
4300
|
+
"attribute": "initialValue",
|
|
4301
|
+
"defaultValue": "first item value",
|
|
4302
|
+
"description": "Selects the matching code example before interaction.",
|
|
4303
|
+
"values": "string"
|
|
4304
|
+
},
|
|
4305
|
+
{
|
|
4306
|
+
"attribute": "storageKey",
|
|
4307
|
+
"defaultValue": "-",
|
|
4308
|
+
"description": "Persists selection and synchronizes CodeTabs instances that share this key.",
|
|
4309
|
+
"values": "string"
|
|
4310
|
+
},
|
|
4311
|
+
{
|
|
4312
|
+
"attribute": "copy",
|
|
4313
|
+
"defaultValue": "true",
|
|
4314
|
+
"description": "Shows a copy button for each code example.",
|
|
4315
|
+
"values": "boolean"
|
|
4316
|
+
},
|
|
4317
|
+
{
|
|
4318
|
+
"attribute": "theme",
|
|
4319
|
+
"defaultValue": "\"auto\"",
|
|
4320
|
+
"description": "Selects the code palette family.",
|
|
4321
|
+
"values": "\"auto\" | \"lumen\" | \"santi020k\""
|
|
4322
|
+
},
|
|
4323
|
+
{
|
|
4324
|
+
"attribute": "wrap",
|
|
4325
|
+
"defaultValue": "true",
|
|
4326
|
+
"description": "Wraps long code lines instead of requiring horizontal scrolling.",
|
|
4327
|
+
"values": "boolean"
|
|
4328
|
+
},
|
|
4329
|
+
{
|
|
4330
|
+
"attribute": "class, className",
|
|
4331
|
+
"defaultValue": "\"\"",
|
|
4332
|
+
"description": "Merges custom classes with the generated ui-* root classes.",
|
|
4333
|
+
"values": "string"
|
|
4334
|
+
},
|
|
4335
|
+
{
|
|
4336
|
+
"attribute": "...native attributes",
|
|
4337
|
+
"defaultValue": "-",
|
|
4338
|
+
"description": "Forwards standard attributes to the root element unless the component consumes them.",
|
|
4339
|
+
"values": "HTML attributes"
|
|
4340
|
+
}
|
|
4341
|
+
],
|
|
4342
|
+
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\nimport Code from './Code.astro'\nimport Tabs from './Tabs.astro'\n\ntype CodeTheme = 'auto' | 'lumen' | 'santi020k'\n\nexport interface CodeTabItem {\n code: string\n label: string\n language?: string\n value: string\n}\n\ninterface Props extends HTMLAttributes<'div'> {\n ariaLabel?: string\n class?: string | null\n className?: string\n copy?: boolean\n initialValue?: string\n items: readonly CodeTabItem[]\n storageKey?: string\n theme?: CodeTheme\n wrap?: boolean\n}\n\nconst {\n ariaLabel = 'Code examples',\n class: classProp = '',\n className = '',\n copy = true,\n initialValue,\n items,\n storageKey,\n theme = 'auto',\n wrap = true,\n ...rest\n} = Astro.props\n\nconst selectedValue = initialValue ?? items[0]?.value\nconst tabsStateProps = {\n ...(selectedValue === undefined ? {} : { initialValue: selectedValue }),\n ...(storageKey === undefined ? {} : { storageKey })\n}\nconst { classList, passthrough } = resolveLumenAstroProps(\n rest,\n ['ui-code-tabs'],\n classProp ?? '',\n className\n)\n---\n\n<Tabs\n class:list={classList}\n {...tabsStateProps}\n {...passthrough}\n>\n <div class=\"ui-code-tabs__list\" role=\"tablist\" aria-label={ariaLabel}>\n {items.map(item => (\n <button\n aria-selected={item.value === selectedValue ? 'true' : 'false'}\n class=\"ui-code-tabs__tab\"\n data-value={item.value}\n role=\"tab\"\n type=\"button\"\n >\n {item.label}\n </button>\n ))}\n </div>\n\n {items.map(item => (\n <div\n class=\"ui-code-tabs__panel\"\n data-value={item.value}\n hidden={item.value !== selectedValue}\n role=\"tabpanel\"\n >\n <Code\n code={item.code}\n copy={copy}\n {...(item.language === undefined ? {} : { language: item.language })}\n theme={theme}\n variant=\"block\"\n wrap={wrap}\n />\n </div>\n ))}\n</Tabs>\n",
|
|
4343
|
+
"category": "Data display",
|
|
4344
|
+
"collections": [],
|
|
4345
|
+
"dependencies": [
|
|
4346
|
+
"Code",
|
|
4347
|
+
"Tabs",
|
|
4348
|
+
"styles",
|
|
4349
|
+
"runtime"
|
|
4350
|
+
],
|
|
4351
|
+
"description": "Groups related code examples into accessible, persistent tabs.",
|
|
4352
|
+
"files": [
|
|
4353
|
+
"packages/astro/components/CodeTabs.astro",
|
|
4354
|
+
"packages/astro/components/Code.astro",
|
|
4355
|
+
"packages/astro/components/Tabs.astro",
|
|
4356
|
+
"packages/astro/styles/lumen.css",
|
|
4357
|
+
"packages/astro/runtime/UIPrimitives.astro"
|
|
4358
|
+
],
|
|
4359
|
+
"frameworkDetails": {
|
|
4360
|
+
"astro": {
|
|
4361
|
+
"available": true,
|
|
4362
|
+
"behavior": {
|
|
4363
|
+
"mode": "runtime",
|
|
4364
|
+
"setup": "Mount UIPrimitives once in the application's root layout; do not mount it beside each component."
|
|
4365
|
+
},
|
|
4366
|
+
"example": "<CodeTabs ariaLabel=\"Package manager\" items={[{ value: \"pnpm\", label: \"pnpm\", code: \"pnpm add @santi020k/lumen-astro\", language: \"bash\" }, { value: \"npm\", label: \"npm\", code: \"npm install @santi020k/lumen-astro\", language: \"bash\" }]} storageKey=\"preferred-package-manager\" />",
|
|
4367
|
+
"importStatement": "import { CodeTabs } from '@santi020k/lumen-astro'",
|
|
4368
|
+
"language": "astro",
|
|
4369
|
+
"packageName": "@santi020k/lumen-astro",
|
|
4370
|
+
"props": [
|
|
4371
|
+
{
|
|
4372
|
+
"name": "ariaLabel",
|
|
4373
|
+
"optional": true,
|
|
4374
|
+
"type": "string"
|
|
4375
|
+
},
|
|
4376
|
+
{
|
|
4377
|
+
"name": "class",
|
|
4378
|
+
"optional": true,
|
|
4379
|
+
"type": "string | null"
|
|
4380
|
+
},
|
|
4381
|
+
{
|
|
4382
|
+
"name": "className",
|
|
4383
|
+
"optional": true,
|
|
4384
|
+
"type": "string"
|
|
4385
|
+
},
|
|
4386
|
+
{
|
|
4387
|
+
"name": "copy",
|
|
4388
|
+
"optional": true,
|
|
4389
|
+
"type": "boolean"
|
|
4390
|
+
},
|
|
4391
|
+
{
|
|
4392
|
+
"name": "initialValue",
|
|
4393
|
+
"optional": true,
|
|
4394
|
+
"type": "string"
|
|
4395
|
+
},
|
|
4396
|
+
{
|
|
4397
|
+
"name": "items",
|
|
4398
|
+
"optional": false,
|
|
4399
|
+
"type": "readonly CodeTabItem[]"
|
|
4400
|
+
},
|
|
4401
|
+
{
|
|
4402
|
+
"name": "storageKey",
|
|
4403
|
+
"optional": true,
|
|
4404
|
+
"type": "string"
|
|
4405
|
+
},
|
|
4406
|
+
{
|
|
4407
|
+
"name": "theme",
|
|
4408
|
+
"optional": true,
|
|
4409
|
+
"type": "CodeTheme"
|
|
4410
|
+
},
|
|
4411
|
+
{
|
|
4412
|
+
"name": "wrap",
|
|
4413
|
+
"optional": true,
|
|
4414
|
+
"type": "boolean"
|
|
4415
|
+
}
|
|
4416
|
+
],
|
|
4417
|
+
"propsExtends": "HTMLAttributes<'div'>",
|
|
4418
|
+
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\nimport Code from './Code.astro'\nimport Tabs from './Tabs.astro'\n\ntype CodeTheme = 'auto' | 'lumen' | 'santi020k'\n\nexport interface CodeTabItem {\n code: string\n label: string\n language?: string\n value: string\n}\n\ninterface Props extends HTMLAttributes<'div'> {\n ariaLabel?: string\n class?: string | null\n className?: string\n copy?: boolean\n initialValue?: string\n items: readonly CodeTabItem[]\n storageKey?: string\n theme?: CodeTheme\n wrap?: boolean\n}\n\nconst {\n ariaLabel = 'Code examples',\n class: classProp = '',\n className = '',\n copy = true,\n initialValue,\n items,\n storageKey,\n theme = 'auto',\n wrap = true,\n ...rest\n} = Astro.props\n\nconst selectedValue = initialValue ?? items[0]?.value\nconst tabsStateProps = {\n ...(selectedValue === undefined ? {} : { initialValue: selectedValue }),\n ...(storageKey === undefined ? {} : { storageKey })\n}\nconst { classList, passthrough } = resolveLumenAstroProps(\n rest,\n ['ui-code-tabs'],\n classProp ?? '',\n className\n)\n---\n\n<Tabs\n class:list={classList}\n {...tabsStateProps}\n {...passthrough}\n>\n <div class=\"ui-code-tabs__list\" role=\"tablist\" aria-label={ariaLabel}>\n {items.map(item => (\n <button\n aria-selected={item.value === selectedValue ? 'true' : 'false'}\n class=\"ui-code-tabs__tab\"\n data-value={item.value}\n role=\"tab\"\n type=\"button\"\n >\n {item.label}\n </button>\n ))}\n </div>\n\n {items.map(item => (\n <div\n class=\"ui-code-tabs__panel\"\n data-value={item.value}\n hidden={item.value !== selectedValue}\n role=\"tabpanel\"\n >\n <Code\n code={item.code}\n copy={copy}\n {...(item.language === undefined ? {} : { language: item.language })}\n theme={theme}\n variant=\"block\"\n wrap={wrap}\n />\n </div>\n ))}\n</Tabs>\n",
|
|
4419
|
+
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
4420
|
+
},
|
|
4421
|
+
"elements": {
|
|
4422
|
+
"attributes": [
|
|
4423
|
+
"data-ui-tabs",
|
|
4424
|
+
"items",
|
|
4425
|
+
"ariaLabel",
|
|
4426
|
+
"initialValue",
|
|
4427
|
+
"storageKey",
|
|
4428
|
+
"copy",
|
|
4429
|
+
"theme",
|
|
4430
|
+
"wrap",
|
|
4431
|
+
"class, className",
|
|
4432
|
+
"...native attributes"
|
|
4433
|
+
],
|
|
4434
|
+
"available": true,
|
|
4435
|
+
"behavior": {
|
|
4436
|
+
"mode": "registration",
|
|
4437
|
+
"setup": "Call defineLumenElements() once before rendering Lumen custom elements. Registration includes this component’s interactive behavior."
|
|
4438
|
+
},
|
|
4439
|
+
"example": "<lumen-code-tabs></lumen-code-tabs>",
|
|
4440
|
+
"importStatement": "import { defineLumenElements } from '@santi020k/lumen-elements/define'",
|
|
4441
|
+
"language": "html",
|
|
4442
|
+
"packageName": "@santi020k/lumen-elements",
|
|
4443
|
+
"props": [],
|
|
4444
|
+
"propsExtends": "HTMLElement attributes",
|
|
4445
|
+
"registration": "defineLumenElements()",
|
|
4446
|
+
"source": "CodeTabs: {\n baseClassName: 'ui-code-tabs',\n defaults: { 'data-ui-tabs': '' },\n tagName: 'lumen-code-tabs'\n }",
|
|
4447
|
+
"styleImport": "import '@santi020k/lumen-elements/styles.css'",
|
|
4448
|
+
"tagName": "lumen-code-tabs"
|
|
4449
|
+
},
|
|
4450
|
+
"react": {
|
|
4451
|
+
"available": true,
|
|
4452
|
+
"behavior": {
|
|
4453
|
+
"mode": "built-in",
|
|
4454
|
+
"setup": "Interactive behavior is implemented by the React component; do not mount Astro UIPrimitives."
|
|
4455
|
+
},
|
|
4456
|
+
"example": "<CodeTabs ariaLabel=\"Package manager\" items={[{ value: \"pnpm\", label: \"pnpm\", code: \"pnpm add @santi020k/lumen-astro\", language: \"bash\" }, { value: \"npm\", label: \"npm\", code: \"npm install @santi020k/lumen-astro\", language: \"bash\" }]} storageKey=\"preferred-package-manager\" />",
|
|
4457
|
+
"importStatement": "import { CodeTabs } from '@santi020k/lumen-react'",
|
|
4458
|
+
"language": "tsx",
|
|
4459
|
+
"packageName": "@santi020k/lumen-react",
|
|
4460
|
+
"props": [
|
|
4461
|
+
{
|
|
4462
|
+
"name": "ariaLabel",
|
|
4463
|
+
"optional": true,
|
|
4464
|
+
"type": "string"
|
|
4465
|
+
},
|
|
4466
|
+
{
|
|
4467
|
+
"name": "copy",
|
|
4468
|
+
"optional": true,
|
|
4469
|
+
"type": "boolean"
|
|
4470
|
+
},
|
|
4471
|
+
{
|
|
4472
|
+
"name": "initialValue",
|
|
4473
|
+
"optional": true,
|
|
4474
|
+
"type": "string"
|
|
4475
|
+
},
|
|
4476
|
+
{
|
|
4477
|
+
"name": "items",
|
|
4478
|
+
"optional": true,
|
|
4479
|
+
"type": "readonly CodeTabItem[]"
|
|
4480
|
+
},
|
|
4481
|
+
{
|
|
4482
|
+
"name": "storageKey",
|
|
4483
|
+
"optional": true,
|
|
4484
|
+
"type": "string"
|
|
4485
|
+
},
|
|
4486
|
+
{
|
|
4487
|
+
"name": "theme",
|
|
4488
|
+
"optional": true,
|
|
4489
|
+
"type": "CodeTheme"
|
|
4490
|
+
},
|
|
4491
|
+
{
|
|
4492
|
+
"name": "wrap",
|
|
4493
|
+
"optional": true,
|
|
4494
|
+
"type": "boolean"
|
|
4495
|
+
}
|
|
4496
|
+
],
|
|
4497
|
+
"propsExtends": "Omit<ComponentPropsWithoutRef<'div'>, 'children' | 'defaultValue'>",
|
|
4498
|
+
"source": "export interface CodeTabsProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children' | 'defaultValue'> {\n ariaLabel?: string\n copy?: boolean\n initialValue?: string\n items?: readonly CodeTabItem[]\n storageKey?: string\n theme?: CodeTheme\n wrap?: boolean\n}\n\nexport const CodeTabs = ({\n ariaLabel = 'Code examples',\n className,\n copy = true,\n initialValue,\n items = emptyCodeTabItems,\n storageKey,\n theme = 'auto',\n wrap = true,\n ...props\n}: CodeTabsProps) => {\n const selectedValue = initialValue ?? items[0]?.value\n\n const [value, setValue] = useState(() => {\n let storedValue: string | null = null\n\n if (storageKey && typeof localStorage !== 'undefined') {\n try {\n storedValue = localStorage.getItem(storageKey)\n } catch {\n // Storage can be unavailable in privacy modes; tab selection should still work.\n }\n }\n\n return storedValue && items.some(item => item.value === storedValue)\n ? storedValue\n : (selectedValue ?? '')\n })\n\n useEffect(() => {\n const synchronize = (event: Event) => {\n const detail = (event as CustomEvent<{ storageKey?: string; value?: string }>).detail\n\n if (\n storageKey &&\n detail.storageKey === storageKey &&\n detail.value &&\n items.some(item => item.value === detail.value)\n ) {\n setValue(detail.value)\n }\n }\n\n document.addEventListener('ui:tabs-change', synchronize)\n\n return () => {\n document.removeEventListener('ui:tabs-change', synchronize)\n }\n }, [items, storageKey])\n\n const selectValue = (nextValue: string) => {\n setValue(nextValue)\n\n if (storageKey) {\n try {\n localStorage.setItem(storageKey, nextValue)\n } catch {\n // Storage can be unavailable in privacy modes; tab selection should still work.\n }\n }\n\n document.dispatchEvent(new CustomEvent('ui:tabs-change', {\n detail: { storageKey, value: nextValue }\n }))\n }\n\n return (\n <Tabs\n className={composeClassName('ui-code-tabs', className)}\n data-storage-key={storageKey}\n onValueChange={selectValue}\n value={value}\n {...props}\n >\n <TabsList aria-label={ariaLabel} className=\"ui-code-tabs__list\">\n {items.map(item => (\n <TabsTrigger className=\"ui-code-tabs__tab\" key={item.value} value={item.value}>\n {item.label}\n </TabsTrigger>\n ))}\n </TabsList>\n {items.map(item => (\n <TabsPanel className=\"ui-code-tabs__panel\" key={item.value} value={item.value}>\n <Code\n code={item.code}\n copy={copy}\n {...(item.language === undefined ? {} : { language: item.language })}\n theme={theme}\n variant=\"block\"\n wrap={wrap}\n />\n </TabsPanel>\n ))}\n </Tabs>\n )\n}",
|
|
4499
|
+
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
4500
|
+
}
|
|
4501
|
+
},
|
|
4502
|
+
"frameworks": {
|
|
4503
|
+
"astro": true,
|
|
4504
|
+
"elements": true,
|
|
4505
|
+
"react": true
|
|
4506
|
+
},
|
|
4507
|
+
"guidance": null,
|
|
4508
|
+
"kebab": "code-tabs",
|
|
4509
|
+
"keyboardInteractions": [
|
|
4510
|
+
{
|
|
4511
|
+
"action": "Activate and focus the next code example, wrapping at the end.",
|
|
4512
|
+
"key": "ArrowRight"
|
|
4513
|
+
},
|
|
4514
|
+
{
|
|
4515
|
+
"action": "Activate and focus the previous code example, wrapping at the start.",
|
|
4516
|
+
"key": "ArrowLeft"
|
|
4517
|
+
},
|
|
4518
|
+
{
|
|
4519
|
+
"action": "Activate and focus the first or last code example.",
|
|
4520
|
+
"key": "Home, End"
|
|
4521
|
+
}
|
|
4522
|
+
],
|
|
4523
|
+
"keywords": [
|
|
4524
|
+
"accessible",
|
|
4525
|
+
"code",
|
|
4526
|
+
"codetabs",
|
|
4527
|
+
"data",
|
|
4528
|
+
"display",
|
|
4529
|
+
"examples",
|
|
4530
|
+
"groups",
|
|
4531
|
+
"into",
|
|
4532
|
+
"persistent",
|
|
4533
|
+
"related",
|
|
4534
|
+
"tabs"
|
|
4535
|
+
],
|
|
4536
|
+
"name": "CodeTabs",
|
|
4537
|
+
"props": [
|
|
4538
|
+
{
|
|
4539
|
+
"name": "ariaLabel",
|
|
4540
|
+
"optional": true,
|
|
4541
|
+
"type": "string"
|
|
4542
|
+
},
|
|
4543
|
+
{
|
|
4544
|
+
"name": "class",
|
|
4545
|
+
"optional": true,
|
|
4546
|
+
"type": "string | null"
|
|
4547
|
+
},
|
|
4548
|
+
{
|
|
4549
|
+
"name": "className",
|
|
4550
|
+
"optional": true,
|
|
4551
|
+
"type": "string"
|
|
4552
|
+
},
|
|
4553
|
+
{
|
|
4554
|
+
"name": "copy",
|
|
4555
|
+
"optional": true,
|
|
4556
|
+
"type": "boolean"
|
|
4557
|
+
},
|
|
4558
|
+
{
|
|
4559
|
+
"name": "initialValue",
|
|
4560
|
+
"optional": true,
|
|
4561
|
+
"type": "string"
|
|
4562
|
+
},
|
|
4563
|
+
{
|
|
4564
|
+
"name": "items",
|
|
4565
|
+
"optional": false,
|
|
4566
|
+
"type": "readonly CodeTabItem[]"
|
|
4567
|
+
},
|
|
4568
|
+
{
|
|
4569
|
+
"name": "storageKey",
|
|
4570
|
+
"optional": true,
|
|
4571
|
+
"type": "string"
|
|
4572
|
+
},
|
|
4573
|
+
{
|
|
4574
|
+
"name": "theme",
|
|
4575
|
+
"optional": true,
|
|
4576
|
+
"type": "CodeTheme"
|
|
4577
|
+
},
|
|
4578
|
+
{
|
|
4579
|
+
"name": "wrap",
|
|
4580
|
+
"optional": true,
|
|
4581
|
+
"type": "boolean"
|
|
4582
|
+
}
|
|
4583
|
+
],
|
|
4584
|
+
"propsExtends": "HTMLAttributes<'div'>",
|
|
4585
|
+
"recipes": [],
|
|
4586
|
+
"runtimeEvents": []
|
|
4587
|
+
},
|
|
4284
4588
|
{
|
|
4285
4589
|
"apiReference": [
|
|
4286
4590
|
{
|
|
@@ -5877,6 +6181,12 @@
|
|
|
5877
6181
|
"description": "Deprecated alias for glass; surface=\"glass\" maps to glass={true}.",
|
|
5878
6182
|
"values": "\"default\" | \"glass\""
|
|
5879
6183
|
},
|
|
6184
|
+
{
|
|
6185
|
+
"attribute": "layout",
|
|
6186
|
+
"defaultValue": "\"centered\"",
|
|
6187
|
+
"description": "Uses the standard centered panel or a viewport-filling native dialog shell.",
|
|
6188
|
+
"values": "\"centered\" | \"fullscreen\""
|
|
6189
|
+
},
|
|
5880
6190
|
{
|
|
5881
6191
|
"attribute": "id",
|
|
5882
6192
|
"defaultValue": "-",
|
|
@@ -5908,7 +6218,7 @@
|
|
|
5908
6218
|
"values": "HTML attributes"
|
|
5909
6219
|
}
|
|
5910
6220
|
],
|
|
5911
|
-
"astroSource": "---\nimport { resolveLumenAstroProps, resolveLumenGlass } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'dialog'> {\n class?: string | null\n className?: string\n glass?: boolean | 'subtle' | 'strong'\n /**\n * @deprecated Use `glass` instead. `surface=\"glass\"` maps to `glass={true}`.\n */\n surface?: 'default' | 'glass'\n}\n\nconst {\n class: classProp = '',\n className = '',\n glass = false,\n surface = 'default',\n ...rest\n} = Astro.props\n\nconst resolvedGlass = resolveLumenGlass(glass, surface)\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-dialog',\n resolvedGlass && 'ui-dialog--glass',\n glass === 'subtle' && 'ui-glass-subtle',\n glass === 'strong' && 'ui-glass-strong'\n], classProp, className)\n---\n\n<dialog\n data-surface={resolvedGlass ? 'glass' : 'default'}\n data-ui-dialog\n class:list={classList}\n {...passthrough}\n>\n <slot />\n</dialog>\n",
|
|
6221
|
+
"astroSource": "---\nimport { resolveLumenAstroProps, resolveLumenGlass } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'dialog'> {\n class?: string | null\n className?: string\n glass?: boolean | 'subtle' | 'strong'\n layout?: 'centered' | 'fullscreen'\n /**\n * @deprecated Use `glass` instead. `surface=\"glass\"` maps to `glass={true}`.\n */\n surface?: 'default' | 'glass'\n}\n\nconst {\n class: classProp = '',\n className = '',\n glass = false,\n layout = 'centered',\n surface = 'default',\n ...rest\n} = Astro.props\n\nconst resolvedGlass = resolveLumenGlass(glass, surface)\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-dialog',\n layout === 'fullscreen' && 'ui-dialog--fullscreen',\n resolvedGlass && 'ui-dialog--glass',\n glass === 'subtle' && 'ui-glass-subtle',\n glass === 'strong' && 'ui-glass-strong'\n], classProp, className)\n---\n\n<dialog\n data-surface={resolvedGlass ? 'glass' : 'default'}\n data-layout={layout}\n data-ui-dialog\n class:list={classList}\n {...passthrough}\n>\n <slot />\n</dialog>\n",
|
|
5912
6222
|
"category": "Overlays",
|
|
5913
6223
|
"collections": [
|
|
5914
6224
|
"Dialogs and contextual layers"
|
|
@@ -5952,6 +6262,11 @@
|
|
|
5952
6262
|
"optional": true,
|
|
5953
6263
|
"type": "boolean | 'subtle' | 'strong'"
|
|
5954
6264
|
},
|
|
6265
|
+
{
|
|
6266
|
+
"name": "layout",
|
|
6267
|
+
"optional": true,
|
|
6268
|
+
"type": "'centered' | 'fullscreen'"
|
|
6269
|
+
},
|
|
5955
6270
|
{
|
|
5956
6271
|
"name": "surface",
|
|
5957
6272
|
"optional": true,
|
|
@@ -5959,13 +6274,14 @@
|
|
|
5959
6274
|
}
|
|
5960
6275
|
],
|
|
5961
6276
|
"propsExtends": "HTMLAttributes<'dialog'>",
|
|
5962
|
-
"source": "---\nimport { resolveLumenAstroProps, resolveLumenGlass } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'dialog'> {\n class?: string | null\n className?: string\n glass?: boolean | 'subtle' | 'strong'\n /**\n * @deprecated Use `glass` instead. `surface=\"glass\"` maps to `glass={true}`.\n */\n surface?: 'default' | 'glass'\n}\n\nconst {\n class: classProp = '',\n className = '',\n glass = false,\n surface = 'default',\n ...rest\n} = Astro.props\n\nconst resolvedGlass = resolveLumenGlass(glass, surface)\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-dialog',\n resolvedGlass && 'ui-dialog--glass',\n glass === 'subtle' && 'ui-glass-subtle',\n glass === 'strong' && 'ui-glass-strong'\n], classProp, className)\n---\n\n<dialog\n data-surface={resolvedGlass ? 'glass' : 'default'}\n data-ui-dialog\n class:list={classList}\n {...passthrough}\n>\n <slot />\n</dialog>\n",
|
|
6277
|
+
"source": "---\nimport { resolveLumenAstroProps, resolveLumenGlass } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'dialog'> {\n class?: string | null\n className?: string\n glass?: boolean | 'subtle' | 'strong'\n layout?: 'centered' | 'fullscreen'\n /**\n * @deprecated Use `glass` instead. `surface=\"glass\"` maps to `glass={true}`.\n */\n surface?: 'default' | 'glass'\n}\n\nconst {\n class: classProp = '',\n className = '',\n glass = false,\n layout = 'centered',\n surface = 'default',\n ...rest\n} = Astro.props\n\nconst resolvedGlass = resolveLumenGlass(glass, surface)\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-dialog',\n layout === 'fullscreen' && 'ui-dialog--fullscreen',\n resolvedGlass && 'ui-dialog--glass',\n glass === 'subtle' && 'ui-glass-subtle',\n glass === 'strong' && 'ui-glass-strong'\n], classProp, className)\n---\n\n<dialog\n data-surface={resolvedGlass ? 'glass' : 'default'}\n data-layout={layout}\n data-ui-dialog\n class:list={classList}\n {...passthrough}\n>\n <slot />\n</dialog>\n",
|
|
5963
6278
|
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
5964
6279
|
},
|
|
5965
6280
|
"elements": {
|
|
5966
6281
|
"attributes": [
|
|
5967
6282
|
"data-ui-dialog",
|
|
5968
6283
|
"glass",
|
|
6284
|
+
"layout",
|
|
5969
6285
|
"surface",
|
|
5970
6286
|
"id",
|
|
5971
6287
|
"data-ui-dialog-trigger",
|
|
@@ -5985,7 +6301,7 @@
|
|
|
5985
6301
|
"props": [],
|
|
5986
6302
|
"propsExtends": "HTMLElement attributes",
|
|
5987
6303
|
"registration": "defineLumenElements()",
|
|
5988
|
-
"source": "Dialog: {\n attributeClasses: {\n glass: { strong: 'ui-dialog--glass ui-glass-strong', subtle: 'ui-dialog--glass ui-glass-subtle', true: 'ui-dialog--glass' },\n surface: { glass: 'ui-dialog--glass' }\n },\n baseClassName: 'ui-dialog',\n defaults: { 'data-ui-dialog': '', surface: 'default' },\n tagName: 'lumen-dialog'\n }",
|
|
6304
|
+
"source": "Dialog: {\n attributeClasses: {\n glass: { strong: 'ui-dialog--glass ui-glass-strong', subtle: 'ui-dialog--glass ui-glass-subtle', true: 'ui-dialog--glass' },\n layout: { fullscreen: 'ui-dialog--fullscreen' },\n surface: { glass: 'ui-dialog--glass' }\n },\n baseClassName: 'ui-dialog',\n defaults: { 'data-ui-dialog': '', layout: 'centered', surface: 'default' },\n tagName: 'lumen-dialog'\n }",
|
|
5989
6305
|
"styleImport": "import '@santi020k/lumen-elements/styles.css'",
|
|
5990
6306
|
"tagName": "lumen-dialog"
|
|
5991
6307
|
},
|
|
@@ -6083,9 +6399,15 @@
|
|
|
6083
6399
|
"importStatement": "import { Button, Dialog, Card } from '@santi020k/lumen-react'\nimport { useDialog } from '@santi020k/lumen-react'",
|
|
6084
6400
|
"language": "tsx",
|
|
6085
6401
|
"packageName": "@santi020k/lumen-react",
|
|
6086
|
-
"props": [
|
|
6402
|
+
"props": [
|
|
6403
|
+
{
|
|
6404
|
+
"name": "layout",
|
|
6405
|
+
"optional": true,
|
|
6406
|
+
"type": "'centered' | 'fullscreen'"
|
|
6407
|
+
}
|
|
6408
|
+
],
|
|
6087
6409
|
"propsExtends": "Omit<ComponentPropsWithoutRef<'dialog'>, 'open'> & SurfaceProps & Omit<DialogOptions, 'id'>",
|
|
6088
|
-
"source": "export type DialogProps = Omit<ComponentPropsWithoutRef<'dialog'>, 'open'> & SurfaceProps & Omit<DialogOptions, 'id'
|
|
6410
|
+
"source": "export type DialogProps = Omit<ComponentPropsWithoutRef<'dialog'>, 'open'> & SurfaceProps & Omit<DialogOptions, 'id'> & {\n layout?: 'centered' | 'fullscreen'\n}\n\nexport const Dialog = ({\n className,\n defaultOpen,\n glass = false,\n layout = 'centered',\n onClick,\n onClose,\n onOpenChange,\n open,\n surface = 'default',\n ...props\n}: DialogProps) => {\n const dialog = useDialog({ defaultOpen, onOpenChange, open })\n\n return (\n <dialog\n {...dialog.dialogProps}\n {...props}\n className={composeClassName(\n 'ui-dialog',\n layout === 'fullscreen' && 'ui-dialog--fullscreen',\n glassSurfaceClass('ui-dialog', surface, glass),\n className\n )}\n data-layout={layout}\n data-surface={resolveSurface(surface, glass)}\n onClick={composeHandlers(onClick, dialog.dialogProps.onClick)}\n onClose={composeHandlers(onClose, dialog.dialogProps.onClose)}\n />\n )\n}",
|
|
6089
6411
|
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
6090
6412
|
}
|
|
6091
6413
|
},
|
|
@@ -6156,6 +6478,11 @@
|
|
|
6156
6478
|
"optional": true,
|
|
6157
6479
|
"type": "boolean | 'subtle' | 'strong'"
|
|
6158
6480
|
},
|
|
6481
|
+
{
|
|
6482
|
+
"name": "layout",
|
|
6483
|
+
"optional": true,
|
|
6484
|
+
"type": "'centered' | 'fullscreen'"
|
|
6485
|
+
},
|
|
6159
6486
|
{
|
|
6160
6487
|
"name": "surface",
|
|
6161
6488
|
"optional": true,
|
|
@@ -24564,11 +24891,11 @@
|
|
|
24564
24891
|
],
|
|
24565
24892
|
"docs": {
|
|
24566
24893
|
"aiUsage": "# AI Usage Guide\n\nUse this guide when an AI agent is building an app with Lumen or updating examples that teach\nanother agent how to use the library.\n\n## Install the Lumen Agent Skill\n\nLumen ships a portable Agent Skill for AI coding tools that support the open `SKILL.md` format:\n\n```bash\nnpx skills add santi020k/lumen --skill lumen-ui\n```\n\nThe source lives in [`skills/lumen-ui`](../skills/lumen-ui). The skill provides the durable\nframework-selection, component-composition, theming, accessibility, and verification workflow.\nUse it by naming `$lumen-ui` in a prompt, or let a compatible agent trigger it from Lumen-specific\nrequests.\n\nThe skill and MCP server complement each other: the skill explains how to work, while\n`@santi020k/lumen-mcp` supplies structured catalog search, framework-specific contracts, recipes,\nsource, tokens, resources, and rules.\n\n## Pick the Right Package\n\nUse the framework requested by the user. Every adapter shares the same Lumen foundation.\n\n| App Target | Install | Import Components From | Load Styles From |\n| --- | --- | --- | --- |\n| Astro | `@santi020k/lumen-astro` | `@santi020k/lumen-astro` | `@santi020k/lumen-astro/styles.css` |\n| React | `@santi020k/lumen-react` | `@santi020k/lumen-react` | `@santi020k/lumen-react/styles.css` |\n| Web Components | `@santi020k/lumen-elements` | `@santi020k/lumen-elements/define` | `@santi020k/lumen-elements/styles.css` |\n| Package metadata | `@santi020k/lumen-core` | `@santi020k/lumen-core` | Not applicable |\n\nEach framework package includes the shared foundation. Install `@santi020k/lumen` separately only\nwhen you need its framework-neutral CLI or registry metadata.\n\n## MCP-Assisted Workflow\n\nConnect `@santi020k/lumen-mcp` when the agent supports Model Context Protocol. The server returns\nvalidated structured content as well as readable text, so agents can select components without\nscraping documentation.\n\n```bash\ncodex mcp add lumen -- npx -y @santi020k/lumen-mcp\n```\n\nFor Codex project configuration:\n\n```toml\n[mcp_servers.lumen]\nenabled = true\ncommand = \"npx\"\nargs = [\"-y\", \"@santi020k/lumen-mcp\"]\n```\n\nUse this sequence:\n\n1. Read `lumen://meta` and `lumen://diagnostics` to identify and verify the snapshot.\n2. Read `lumen://rules`.\n3. Search for the use case with `lumen_search`, passing the target `framework` when known.\n4. Inspect the selected framework with `lumen_get_component` and `detail: \"usage\"`.\n5. Follow its framework behavior setup and hook/controller contract.\n6. Read related multi-component guidance with `lumen_get_recipe`.\n7. Request `detail: \"source\"` only when the usage contract is insufficient.\n8. Read `lumen://tokens` before introducing custom styling.\n9. Retain `lumen://catalog-manifest` and use `lumen_diff_catalog` after upgrades to identify contracts that need refreshing.\n\nExample framework-aware component request:\n\n```json\n{\n \"name\": \"lumen_get_component\",\n \"arguments\": {\n \"name\": \"DateRangePicker\",\n \"framework\": \"react\",\n \"detail\": \"usage\"\n }\n}\n```\n\nStable resources are available at `lumen://rules`, `lumen://tokens`, `lumen://components`,\n`lumen://meta`, `lumen://catalog-manifest`, `lumen://diagnostics`,\n`lumen://components/{name}`, and `lumen://recipes/{name}`. See\n[`packages/mcp/README.md`](../packages/mcp/README.md) for Claude Desktop, Cursor, generic stdio,\nlocal repository, and programmatic examples.\n\n## Minimal Setup\n\nImport the stylesheet once in the app's global CSS, root layout, or app entry.\n\n```css\n@import \"@santi020k/lumen-react/styles.css\";\n```\n\nIf Tailwind is present, keep both imports in the same shared CSS entry.\n\n```css\n@import \"@santi020k/lumen-react/layers.css\";\n@import \"tailwindcss\";\n@import \"@santi020k/lumen-react/styles.css\";\n```\n\nKeep the layer prelude first. It places Tailwind base styles below Lumen components and Tailwind\nutilities above them, so consumer spacing, display, radius, width, and responsive visibility\nclasses override Lumen defaults predictably.\n\nAstro apps should mount `UIPrimitives` once in the root layout when using interactive primitives\nsuch as dialogs, menus, popovers, tabs, carousels, command lists, toggles, validated forms, or\ntoasts. Do not place `UIPrimitives` in each component example or next to each primitive instance;\none root include enhances all matching `data-ui-*` markup on the page.\n\n```astro\n---\nimport { UIPrimitives } from '@santi020k/lumen-astro'\n---\n\n<UIPrimitives />\n```\n\n## Astro\n\nUse direct named imports from `@santi020k/lumen-astro`.\n\n```astro\n---\nimport { Button, Card, Input, Label } from '@santi020k/lumen-astro'\n---\n\n<Card>\n <Label for=\"email\">Email</Label>\n <Input id=\"email\" type=\"email\" placeholder=\"you@example.com\" />\n <Button type=\"submit\">Subscribe</Button>\n</Card>\n```\n\n## React\n\nReact components share the same visual classes and data attributes as Astro components. For\nbehavior-heavy primitives, use the React behavior hooks from `@santi020k/lumen-react` (`useDialog`,\n`usePopover`, `useDropdownMenu`, `useTabs`, `useSelect`, `useToast`, and `useTooltip`), which track\nthe Astro runtime's ARIA, keyboard, Escape, dismissal, and toast controller semantics.\n\nThe React package entry is a client boundary. In Next.js, it can be imported by a Server Component\nwithout evaluating Lumen's contexts and hooks in the React server runtime; the rendered Lumen\nsubtree becomes a Client Component boundary. Vite and other client-rendered React applications use\nthe same entry without additional setup.\n`Button`, `Link`, `ButtonLink`, and `Input` accept React 19 DOM refs directly as props.\n`Button asChild` composes the button contract onto one child element, while `Input visualSize` controls\npresentation without shadowing the native numeric `size` attribute.\n\n```tsx\nimport '@santi020k/lumen-react/styles.css'\nimport { Button, Card, Input, Label } from '@santi020k/lumen-react'\n\nexport function SubscribeForm() {\n return (\n <Card>\n <Label htmlFor=\"email\">Email</Label>\n <Input id=\"email\" type=\"email\" placeholder=\"you@example.com\" />\n <Button type=\"submit\">Subscribe</Button>\n </Card>\n )\n}\n```\n\n## Web Components\n\nRegister custom elements once, then use `lumen-*` tags in HTML. The elements adapter includes\ninteractive behavior parity for DataTable, Dialog, Popover, DropdownMenu, ContextMenu, Tabs,\nSelect, ThemeBuilder, Toast, Tooltip, forms, RichTextEditor, Schedule, and VirtualList: selection,\nvalidation, rich text command, context menu, schedule drag/drop, theme, and range events, ARIA\nstate, roving/listbox keyboard paths, Escape/outside dismissal, focus return/trapping, native\nselect form participation, and the same toast controller events as the Astro runtime.\n\n```html\n<script type=\"module\">\n import { defineLumenElements } from '@santi020k/lumen-elements/define'\n\n defineLumenElements()\n</script>\n\n<lumen-card>\n <label for=\"email\">Email</label>\n <lumen-input id=\"email\" type=\"email\" placeholder=\"you@example.com\"></lumen-input>\n <lumen-button type=\"submit\">Subscribe</lumen-button>\n</lumen-card>\n```\n\n## Component Selection\n\nThe shared catalog includes:\n\n`Accordion`, `Alert`, `AlertDialog`, `Agenda`, `AspectRatio`, `Attachment`, `Autocomplete`,\n`Avatar`, `Badge`, `Breadcrumb`, `Bubble`, `Button`, `ButtonGroup`, `Calendar`, `Card`,\n`Carousel`, `Chart`, `Checkbox`, `Collapsible`, `Code`, `Combobox`, `Command`, `ColorPicker`,\n`ContextMenu`, `DataTable`, `DatePicker`, `DateRangePicker`, `Dialog`, `Direction`, `Drawer`,\n`DropdownMenu`, `Empty`, `Field`, `HoverCard`, `Icon`, `Input`, `InputGroup`, `InputOTP`, `Item`, `Kbd`,\n`Label`, `Marker`, `Menubar`, `Message`, `MessageScroller`, `NativeSelect`, `NavigationMenu`,\n`NumberField`, `Pagination`, `Popover`, `Progress`, `RadioGroup`, `Resizable`, `RichTextEditor`,\n`ScrollArea`, `Schedule`, `SearchField`, `Select`, `Separator`, `Sheet`, `Sidebar`, `Skeleton`,\n`Slider`, `Spinner`, `Switch`, `Table`, `Tabs`, `TagGroup`, `Textarea`, `ThemeBuilder`,\n`TimeField`, `Toast`, `Toggle`, `ToggleGroup`, `Tooltip`, `Tree`, `TreeGrid`, `Typography`, and\n`VirtualList`.\n\n## Product Recipes\n\n- Use `Icon name=\"search\"` or any Lucide icon name for standard interface pictograms. Kebab-case\n names and Lucide aliases work. Pair decorative icons with `decorative`, and pass `label` only\n when the icon carries meaning on its own. Lucide does not include brand marks such as GitHub;\n render a project-owned SVG through the default `Icon` slot for brand and custom icons. Astro\n reports unknown named icons during development instead of failing silently.\n- Use `Schedule` with `Agenda`, `Calendar`, and `DatePicker` for booking, CRM, content calendar, and\n event planning screens. Mark slots with `data-ui-schedule-slot` and events with\n `data-ui-schedule-event`; the runtime emits `ui:schedule-change` when a draggable event is moved.\n `Calendar` renders a hidden input plus selectable date grid; Astro `UIPrimitives` and registered\n Web Components wire month navigation and roving keyboard focus directly, while React apps can use\n the `Calendar` component or `useCalendar` for the same date selection contract.\n Astro `UIPrimitives` and registered Web Components bind schedule drag/drop directly; React apps\n can use `useSchedule` for `rootProps`, `getEventProps`, `getSlotProps`, and `ui:schedule-change`\n parity. Use `createScheduleSlots`, `moveScheduleEvent`, and `expandRecurringScheduleEvent` from\n `@santi020k/lumen-core` for reusable schedule state; use `getScheduleConflicts` and\n `canPlaceScheduleEvent` before committing drag/drop changes. Persist local schedule edits with\n `createScheduleStorageKey`, `saveScheduleEvents`, and `loadScheduleEvents` against any\n `localStorage`-compatible adapter. Use `resizeScheduleEvent` and `resizeScheduleEvents` for\n snap-to-grid resize handles.\n- Use `DataTable`, `Tree`, `TreeGrid`, `VirtualList`, `Pagination`, and `Command` for dense data\n collection workflows. Astro and Elements wire selectable/sortable `DataTable` behavior and\n `VirtualList` range events; React emits the same data attributes for app-level adapters. `Tree`\n and `TreeGrid` use roving keyboard focus, and `VirtualList` emits `ui:virtual-list-range` as the\n rendered range changes. Use `createDataViewState`,\n `serializeDataViewState`, `parseDataViewState`, `applyDataViewState`, and `getVirtualRange` for\n saved views, filtering, sorting, pagination, and virtualization math. Use\n `createDataViewStorageKey`, `saveDataViewState`, and `loadDataViewState` when saved views should\n survive navigation or reloads. Use `pinDataViewColumn`, `unpinDataViewColumn`,\n `toggleDataViewSelection`, `createDataViewSearchParams`, and `createDataViewServerRequest` when\n connecting dense views to router state or server-backed data.\n- Use `Resizable` for split-pane editors, dashboards, inspectors, and side-by-side review layouts.\n Astro `UIPrimitives` and registered Web Components generate separator handles and pane sizing\n directly; React apps can use the `Resizable` component or `useResizable` for pointer, keyboard,\n min/max, and double-click reset parity.\n- Use `ThemeBuilder`, `ColorPicker`, `Card`, `Button`, and `Input` to build token preview and export\n tools. Add `data-ui-theme-brand-hue`, `data-ui-theme-accent-hue`, `data-ui-theme-scheme`,\n `data-ui-theme-mode`, manual color inputs such as `data-ui-theme-primary-hex`, and\n `data-ui-theme-target` for scoped live previews. Add `data-ui-theme-export-format`,\n `data-ui-theme-export`, and `data-ui-theme-output` to copy CSS, Figma variable JSON, or design\n token JSON. Astro `UIPrimitives` and registered Web Components wire those controls directly;\n React apps can use `useThemeBuilder` for the same tokens, exports, and control props. Use\n `createThemePalette`, `createThemeBuilderTokens`, `exportThemeBuilderValue`, `exportThemeCss`,\n `parseThemeCss`, and `scoreThemeContrast`\n for theme import/export and accessibility checks. Use `suggestReadableInk`, `mergeThemeTokens`,\n and `tuneThemeContrast` when generated palettes need readable foreground repair.\n- Use `RichTextEditor` with `ButtonGroup`, `ToggleGroup`, and `Textarea` for editor compositions.\n Controls with `data-ui-editor-command` dispatch browser editing commands and emit\n `ui:editor-command`; use `data-ui-editor-value` for headings, links, and other value-bearing\n commands. Editable surfaces support common formatting shortcuts, synchronize toggle\n `aria-pressed` state, and emit `ui:editor-change` with HTML and plain text. Astro `UIPrimitives`\n and registered Web Components bind those controls directly; React apps can use\n `useRichTextEditor` for `rootProps`, `getCommandProps`, `getEditableProps`, and `executeCommand`.\n For Tiptap, ProseMirror, Lexical, or Markdown engines, keep the external editor\n package in the app and bridge toolbar buttons through the emitted command event instead of adding\n the editor engine to Lumen.\n- Use `Autocomplete`, `SearchField`, `NumberField`, `TimeField`, `DateRangePicker`, `ColorPicker`,\n and `TagGroup` when forms need more than plain text inputs. Add `data-ui-form` to forms that\n should reflect native Constraint Validation API state into `Field` error slots on blur and submit.\n For `InputOTP`, Astro `UIPrimitives` and registered Web Components render/sync a real native input\n with visual OTP segments; React apps can use the `InputOTP` component or `useInputOTP` for the\n same sanitization, paste handling, and caret navigation.\n For `DateRangePicker`, Astro `UIPrimitives` and registered Web Components sync the paired native\n date input `min`/`max` constraints directly; React apps can use `useDateRangePicker` for the same\n start/end syncing props.\n Use native attributes such as `required`, `pattern`, `min`, `max`, and `type`; add\n `data-error-required`, `data-error-pattern`, `data-error-min`, `data-error-max`, or\n `data-error-custom` when a control needs custom copy. Listen for `ui:validate` to call\n `control.setCustomValidity(message)` before the runtime reads validity, and listen for\n `ui:invalid` or `ui:valid` on the form for submission state. Astro `UIPrimitives` and registered\n Web Components bind `data-ui-form` directly; React apps can use `useFormValidation` with `Field`\n to get the same control props, CustomEvents, and error slot updates.\n- Use `Toast` for transient feedback. Static `<Toast>` markup works without\n JavaScript. With Astro `UIPrimitives` or registered Web Components, create toasts with\n `window.LumenToast.create(detail)`, `LumenToast.create(detail)` from `@santi020k/lumen-elements`,\n or `document.dispatchEvent(new CustomEvent('ui:toast', { detail }))`; update them with\n `.update(id, detail)` or `ui:toast-update`; and dismiss them with `.dismiss(id?)` or\n `ui:toast-dismiss`. `detail` supports `title`, `description`, `variant`, `duration`, `placement`,\n `max`, and `action: { label, value }`. Destructive toasts use `role=\"alert\"`; other variants use\n `role=\"status\"`. Runtime toasts pause their timeout on hover or focus, and Escape dismisses the\n focused toast.\n\n## Runtime CustomEvents\n\nWhen `UIPrimitives` is mounted, or when Web Components are registered for matching behavior, Lumen\nuses these CustomEvents:\n\n| Event | Target | Detail | Fires When |\n| --- | --- | --- | --- |\n| `ui:data-table-selection-change` | `DataTable` root `[data-ui-datatable]` | `{ values: string[] }` | Selectable row checkboxes, the select-all checkbox, or form reset changes selected row values. |\n| `ui:schedule-change` | `Schedule` root `[data-ui-schedule]` | `{ eventId?: string, slot?: string }` | A draggable schedule event is dropped on a `[data-ui-schedule-slot]`. |\n| `ui:virtual-list-range` | `VirtualList` root `[data-ui-virtual-list]` | `{ startIndex: number, endIndex: number }` | The virtual list calculates its visible range on init or scroll. |\n| `ui:tag-remove` | `TagGroup` root `.ui-tag-group` or `[data-ui-tag-group]` | `{ value?: string }` | A `[data-ui-tag-remove]` control removes its closest tag or list item. |\n| `ui:editor-command` | `RichTextEditor` root `[data-ui-rich-text-editor]` | `{ command: string, executed: boolean, value?: string }` | A toolbar control or keyboard shortcut runs an editor command. |\n| `ui:editor-change` | `RichTextEditor` root `[data-ui-rich-text-editor]` | `{ html: string, text: string }` | Editable content changes or an editor command runs. |\n| `ui:theme-change` | `ThemeBuilder` root `[data-ui-theme-builder]` | `{ hue: number, accentHue: number, mode: 'generated' \\| 'manual', scheme: 'dark' \\| 'light', tokens: Record<string, string> }` | Hue, manual color, mode, or scheme controls update generated tokens. |\n| `ui:theme-export` | `ThemeBuilder` root `[data-ui-theme-builder]` | `{ css?: string, format: 'css' \\| 'figma' \\| 'tokens', tokens: Record<string, string> \\| null, value: string }` | A `[data-ui-theme-export]` control writes the selected export to the output and clipboard when available. |\n| `ui:validate` | Form `[data-ui-form]` | `{ control, form, value }` | Before validation state is read, so custom code can call `control.setCustomValidity(message)`. |\n| `ui:invalid` | Form `[data-ui-form]` | `{ control?, controls?, form }` | Blur or submit validation finds invalid controls. Failed submits focus the first invalid control. |\n| `ui:valid` | Form `[data-ui-form]` | `{ control?, controls?, form }` | Blur or submit validation finds the checked control or form valid. |\n| `ui:toast` | `document` | `{ id?, title?, description?, variant?, duration?, placement?, action? }` | Creates a runtime toast in the matching notification viewport. |\n| `ui:toast-update` | `document` | `{ id, title?, description?, variant?, duration? }` | Updates a runtime toast. |\n| `ui:toast-dismiss` | `document` | `{ id? }` | Dismisses one runtime toast, or all runtime toasts when `id` is omitted. |\n| `ui:toast-action` | Toast `[data-ui-toast]` | `{ id, value? }` | A runtime toast action button is pressed, unless the action specifies a custom event name. |\n\n## Registry Helper\n\n`@santi020k/lumen` exports typed component, recipe, and documentation metadata from\n`@santi020k/lumen/registry`. The package also ships a small `lumen` binary. Individual components\nare addressable by name, including kebab-case aliases such as `data-table`:\n\n```bash\nlumen list\nlumen show Button\nlumen show data-table\nlumen add Button\nlumen add Button --target react\nlumen add Button --target elements\nlumen add data-table\nlumen show scheduler\nlumen add scheduler\nlumen add scheduler --target react\nlumen add scheduler --target elements\nlumen add scheduler --dry-run\nlumen add scheduler --fail-on-conflict\nlumen add scheduler --force\nlumen add scheduler --merge\nlumen list --registry ./registry/lumen.registry.json\nlumen add custom-recipe --registry ./registry/custom.registry.json\nlumen add private-recipe --registry https://example.com/lumen.registry.json --registry-token \"$TOKEN\"\nlumen install\n```\n\n`lumen add <component>` defaults to an Astro wrapper. Use `--target react` for a local React wrapper\nor `--target elements` for a custom-elements starter. Bundled recipes also accept `--target astro`,\n`--target react`, and `--target elements`; external registry inline files keep their authored paths\nand sources.\n\nBefore inventing a wrapper or custom class pattern, check the component source in\n`packages/astro/components`. Astro is the reference implementation for props, class names, data\nattributes, and accessible markup.\n\n## Styling Rules for Generated Code\n\n- Do not require consumers to configure Tailwind for Lumen components.\n- Prefer component props and composition before adding custom CSS.\n- Use the shared token names for custom surfaces: `canvas`, `surface`, `surface-muted`,\n `surface-strong`, `line`, `ink`, `ink-soft`, `ink-muted`, `brand`, `brand-solid`, `brand-soft`,\n `accent`, `success`, `warning`, and `danger`.\n- Use `glass` as a boolean prop or attribute for glass surfaces when supported.\n- Do not generate `surface=\"glass\"` for overlays; it is a deprecated alias that maps to `glass`.\n- Preserve semantic labels, keyboard paths, focus states, and native form attributes.\n\n## Figma Handoff\n\nUse `exportThemeFigmaVariables` from `@santi020k/lumen-core/figma` when a design workflow needs\nFigma variable-friendly color values, and `exportThemeDesignTokens` when exporting standard design\ntoken JSON for token importers. See [docs/figma.md](figma.md) for the recommended Figma workflow.\n\n## When Editing This Repo\n\n- Shared contracts belong in `packages/core`.\n- Astro implementation and standalone CSS belong in `packages/astro`.\n- React-specific primitives belong in `packages/react`.\n- Web Component-specific primitives belong in `packages/elements`.\n- Update the relevant package README when public usage changes.\n- Add tests beside package code as `*.test.ts` when behavior, exported metadata, or component\n contracts change.\n",
|
|
24567
|
-
"readme": "
|
|
24894
|
+
"readme": "<p align=\"center\">\n <a href=\"https://lumen.santi020k.com\">\n <img src=\"./apps/docs/public/logo.svg\" alt=\"Lumen UI\" width=\"239\" height=\"60\">\n </a>\n</p>\n\n<h1 align=\"center\">Lumen UI</h1>\n\n<p align=\"center\">\n A multi-framework UI system with 123 accessible primitives for Astro, React, and Web Components.\n</p>\n\n<p align=\"center\">\n <a href=\"https://lumen.santi020k.com\">Documentation</a>\n ·\n <a href=\"https://lumen.santi020k.com/docs/components\">Components</a>\n ·\n <a href=\"https://www.figma.com/community/file/1662337342676541513\">Figma library</a>\n ·\n <a href=\"https://github.com/santi020k/lumen/issues\">Issues</a>\n</p>\n\n<p align=\"center\">\n <a href=\"https://github.com/santi020k/lumen/actions\"><img alt=\"GitHub Actions\" src=\"https://img.shields.io/github/actions/workflow/status/santi020k/lumen/ci.yml?branch=main&style=flat-square\"></a>\n <a href=\"https://www.npmjs.com/package/@santi020k/lumen-astro\"><img alt=\"npm version\" src=\"https://img.shields.io/npm/v/@santi020k/lumen-astro?style=flat-square&label=npm\"></a>\n <a href=\"./LICENSE\"><img alt=\"MIT license\" src=\"https://img.shields.io/badge/license-MIT-111827?style=flat-square\"></a>\n</p>\n\nLumen gives applications a consistent visual language without tying them to one rendering model.\nIts packages share tokens, component contracts, styles, and interaction patterns while keeping each\nframework's native authoring experience.\n\n- **Framework native:** Astro components, React primitives, and standards-based custom elements.\n- **Accessible by default:** semantic markup, keyboard paths, focus management, and reduced-motion\n support are built into the primitives.\n- **Standalone CSS:** no Tailwind configuration is required. Tailwind users get an explicit layer\n integration.\n- **Progressively enhanced:** Astro interactions use a small client runtime instead of requiring an\n application framework.\n- **Ready for design and AI workflows:** published Figma resources, a portable agent skill, an MCP\n server, `llms.txt`, and a machine-readable registry ship alongside the component system.\n\n## Quick start\n\nInstall the package for your framework:\n\n```bash\n# Astro\npnpm add @santi020k/lumen-astro\n\n# React\npnpm add @santi020k/lumen-react\n\n# Web Components\npnpm add @santi020k/lumen-elements\n```\n\n### Astro\n\nImport the stylesheet and mount `UIPrimitives` once in your root layout. The runtime enhances all\ninteractive Lumen markup on the page.\n\n```astro\n---\nimport '@santi020k/lumen-astro/styles.css'\nimport { UIPrimitives } from '@santi020k/lumen-astro'\n---\n\n<html lang=\"en\">\n <body>\n <slot />\n <UIPrimitives />\n </body>\n</html>\n```\n\n```astro\n---\nimport { Button, Card, Input } from '@santi020k/lumen-astro'\n---\n\n<Card>\n <label for=\"email\">Email</label>\n <Input id=\"email\" name=\"email\" type=\"email\" placeholder=\"you@example.com\" />\n <Button>Subscribe</Button>\n</Card>\n```\n\n### React\n\nLoad the stylesheet once from your app entry or global CSS:\n\n```tsx\nimport '@santi020k/lumen-react/styles.css'\nimport { Button, Card, Input } from '@santi020k/lumen-react'\n\nexport function SubscribeForm() {\n return (\n <Card>\n <label htmlFor=\"email\">Email</label>\n <Input id=\"email\" name=\"email\" type=\"email\" placeholder=\"you@example.com\" />\n <Button>Subscribe</Button>\n </Card>\n )\n}\n```\n\n### Web Components\n\nImport the styles and register the elements once:\n\n```html\n<style>\n @import \"@santi020k/lumen-elements/styles.css\";\n</style>\n\n<script type=\"module\">\n import { defineLumenElements } from '@santi020k/lumen-elements/define'\n\n defineLumenElements()\n</script>\n\n<lumen-card>\n <label for=\"email\">Email</label>\n <lumen-input id=\"email\" name=\"email\" type=\"email\" placeholder=\"you@example.com\"></lumen-input>\n <lumen-button>Subscribe</lumen-button>\n</lumen-card>\n```\n\nSee the [documentation](https://lumen.santi020k.com/docs) for installation, theming, component\nexamples, and API details.\n\n## Tailwind CSS\n\nKeep the layer prelude, Tailwind import, and Lumen stylesheet in the same shared CSS entry. Replace\n`lumen-astro` with the package for your framework.\n\n```css\n@import \"@santi020k/lumen-astro/layers.css\";\n@import \"tailwindcss\";\n@import \"@santi020k/lumen-astro/styles.css\";\n```\n\nThis order places Tailwind base styles before Lumen components and Tailwind utilities above Lumen\ncomponent defaults.\n\n## Packages\n\n| Package | Purpose |\n| --- | --- |\n| [`@santi020k/lumen-astro`](./packages/astro) | Reference implementation, Astro components, and progressive-enhancement runtime |\n| [`@santi020k/lumen-react`](./packages/react) | React components and behavior hooks |\n| [`@santi020k/lumen-elements`](./packages/elements) | Standards-based Web Components |\n| [`@santi020k/lumen-core`](./packages/core) | Shared tokens, metadata, class helpers, and behavior contracts |\n| [`@santi020k/lumen`](./packages/lumen) | Umbrella package, CLI, registry metadata, and public package map |\n| [`@santi020k/lumen-mcp`](./packages/mcp) | MCP server for component discovery and source retrieval |\n\n## AI and design workflows\n\nInstall the portable Lumen skill in Codex, Claude Code, Cursor, Windsurf, and other compatible\ncoding agents:\n\n```bash\nnpx skills add santi020k/lumen --skill lumen-ui\n```\n\nThe skill teaches agents how to select, compose, theme, and verify Lumen primitives. Pair it with\n[`@santi020k/lumen-mcp`](./packages/mcp) when an agent needs to search the live catalog or retrieve\ncurrent source, props, tokens, and usage rules.\n\nAdditional machine-readable surfaces include:\n\n- [`llms.txt`](./llms.txt) for a concise project map.\n- [`docs/ai-usage.md`](./docs/ai-usage.md) for downstream generation examples.\n- [`registry/lumen.registry.json`](./registry/lumen.registry.json) for recipes and installable file\n groups.\n- [`docs/figma.md`](./docs/figma.md) for Figma variables and Code Connect workflows.\n\n## Contributing\n\nLumen is a pnpm workspace. Astro is the reference implementation; shared contracts belong in\n`packages/core`, while framework-specific behavior stays in its adapter package.\n\n```bash\npnpm install\npnpm run dev\npnpm run validate\n```\n\nRead [`CONTRIBUTING.md`](./CONTRIBUTING.md) before opening a pull request. User-visible package\nchanges require a changeset.\n\n## License\n\nLumen is available under the [MIT License](./LICENSE).\n"
|
|
24568
24895
|
},
|
|
24569
24896
|
"meta": {
|
|
24570
|
-
"catalogHash": "
|
|
24571
|
-
"componentCount":
|
|
24897
|
+
"catalogHash": "fe40e1272c32ff21e23f31007bf371c3f667aec69779a3af0f34b397a151cc4f",
|
|
24898
|
+
"componentCount": 124,
|
|
24572
24899
|
"packages": [
|
|
24573
24900
|
"@santi020k/lumen-astro",
|
|
24574
24901
|
"@santi020k/lumen-react",
|
|
@@ -24576,16 +24903,16 @@
|
|
|
24576
24903
|
"@santi020k/lumen-core"
|
|
24577
24904
|
],
|
|
24578
24905
|
"packageVersions": {
|
|
24579
|
-
"@santi020k/lumen-astro": "0.
|
|
24580
|
-
"@santi020k/lumen-core": "0.
|
|
24581
|
-
"@santi020k/lumen-elements": "0.
|
|
24582
|
-
"@santi020k/lumen-mcp": "0.
|
|
24583
|
-
"@santi020k/lumen-react": "0.
|
|
24906
|
+
"@santi020k/lumen-astro": "0.3.0",
|
|
24907
|
+
"@santi020k/lumen-core": "0.3.0",
|
|
24908
|
+
"@santi020k/lumen-elements": "0.3.0",
|
|
24909
|
+
"@santi020k/lumen-mcp": "0.3.0",
|
|
24910
|
+
"@santi020k/lumen-react": "0.3.0"
|
|
24584
24911
|
},
|
|
24585
24912
|
"registryName": "lumen",
|
|
24586
24913
|
"registryVersion": 1,
|
|
24587
24914
|
"schemaVersion": 3,
|
|
24588
|
-
"serverVersion": "0.
|
|
24915
|
+
"serverVersion": "0.3.0"
|
|
24589
24916
|
},
|
|
24590
24917
|
"recipes": [
|
|
24591
24918
|
{
|
package/dist/data.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"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"}
|
package/dist/data.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
const dataUrl = new URL('../data/lumen-data.json', import.meta.url);
|
|
4
4
|
let cached;
|
|
5
5
|
export const loadLumenData = () => {
|
|
6
6
|
if (cached)
|
|
7
7
|
return cached;
|
|
8
|
+
const readFsFile = Reflect.get(fs, 'readFileSync');
|
|
8
9
|
const raw = readFsFile(fileURLToPath(dataUrl), 'utf8');
|
|
9
10
|
cached = JSON.parse(raw);
|
|
10
11
|
return cached;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAA;AAYrD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,cAAc,YAAY,CAAA;AAE1B,4EAA4E;AAC5E,eAAO,MAAM,aAAa,QAAa,OAAO,CAAC,IAAI,CAKlD,CAAA;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,UAAU,EAAE,UAAU,CAAA;IACtB,GAAG,EAAE,GAAG,CAAA;CACT;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAA;AAYrD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,cAAc,YAAY,CAAA;AAE1B,4EAA4E;AAC5E,eAAO,MAAM,aAAa,QAAa,OAAO,CAAC,IAAI,CAKlD,CAAA;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,UAAU,EAAE,UAAU,CAAA;IACtB,GAAG,EAAE,GAAG,CAAA;CACT;AAoDD,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,GAC5B,UAAS,mBAAwB,KAChC,OAAO,CAAC,kBAAkB,CA+F5B,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,43 @@ export const startLumenMcp = async () => {
|
|
|
11
11
|
const transport = new StdioServerTransport();
|
|
12
12
|
await server.connect(transport);
|
|
13
13
|
};
|
|
14
|
+
const toWebRequest = (request, host, options) => {
|
|
15
|
+
const headers = new Headers();
|
|
16
|
+
for (const [name, value] of Object.entries(request.headers)) {
|
|
17
|
+
for (const item of Array.isArray(value) ? value : [value]) {
|
|
18
|
+
if (item !== undefined)
|
|
19
|
+
headers.append(name, item);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const hostHeader = request.headers.host ?? `${host}:${options.port ?? 3000}`;
|
|
23
|
+
const method = request.method;
|
|
24
|
+
return new Request(`http://${hostHeader}${request.url}`, {
|
|
25
|
+
headers,
|
|
26
|
+
method,
|
|
27
|
+
...(['GET', 'HEAD'].includes(method) ? {} : { body: JSON.stringify(request.body) })
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
const streamResponse = async (webResponse, response) => {
|
|
31
|
+
response.statusCode = webResponse.status;
|
|
32
|
+
for (const [name, value] of webResponse.headers.entries())
|
|
33
|
+
response.setHeader(name, value);
|
|
34
|
+
if (!webResponse.body) {
|
|
35
|
+
response.end();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const reader = webResponse.body.getReader();
|
|
39
|
+
response.once('close', () => {
|
|
40
|
+
reader.cancel().catch(() => { });
|
|
41
|
+
});
|
|
42
|
+
while (!response.destroyed) {
|
|
43
|
+
const chunk = await reader.read();
|
|
44
|
+
if (chunk.done)
|
|
45
|
+
break;
|
|
46
|
+
response.write(Buffer.from(chunk.value));
|
|
47
|
+
}
|
|
48
|
+
if (!response.writableEnded)
|
|
49
|
+
response.end();
|
|
50
|
+
};
|
|
14
51
|
/** Start a self-hostable Streamable HTTP transport. Defaults to loopback for safety. */
|
|
15
52
|
export const startLumenMcpHttp = async (options = {}) => {
|
|
16
53
|
const host = options.host ?? '127.0.0.1';
|
|
@@ -28,44 +65,11 @@ export const startLumenMcpHttp = async (options = {}) => {
|
|
|
28
65
|
activeServers.add(mcpServer);
|
|
29
66
|
try {
|
|
30
67
|
await mcpServer.connect(transport);
|
|
31
|
-
const
|
|
32
|
-
for (const [name, value] of Object.entries(request.headers)) {
|
|
33
|
-
for (const item of Array.isArray(value) ? value : [value]) {
|
|
34
|
-
if (item !== undefined)
|
|
35
|
-
headers.append(name, item);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
const hostHeader = request.headers.host ?? `${host}:${options.port ?? 3000}`;
|
|
39
|
-
const method = request.method;
|
|
40
|
-
const webRequest = new Request(`http://${hostHeader}${request.url}`, {
|
|
41
|
-
headers,
|
|
42
|
-
method,
|
|
43
|
-
...(['GET', 'HEAD'].includes(method)
|
|
44
|
-
? {}
|
|
45
|
-
: { body: JSON.stringify(request.body) })
|
|
46
|
-
});
|
|
68
|
+
const webRequest = toWebRequest(request, host, options);
|
|
47
69
|
const webResponse = await transport.handleRequest(webRequest, {
|
|
48
70
|
parsedBody: request.body
|
|
49
71
|
});
|
|
50
|
-
|
|
51
|
-
for (const [name, value] of webResponse.headers.entries())
|
|
52
|
-
response.setHeader(name, value);
|
|
53
|
-
if (!webResponse.body) {
|
|
54
|
-
response.end();
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
const reader = webResponse.body.getReader();
|
|
58
|
-
response.once('close', () => {
|
|
59
|
-
reader.cancel().catch(() => { });
|
|
60
|
-
});
|
|
61
|
-
while (!response.destroyed) {
|
|
62
|
-
const chunk = await reader.read();
|
|
63
|
-
if (chunk.done)
|
|
64
|
-
break;
|
|
65
|
-
response.write(Buffer.from(chunk.value));
|
|
66
|
-
}
|
|
67
|
-
if (!response.writableEnded)
|
|
68
|
-
response.end();
|
|
72
|
+
await streamResponse(webResponse, response);
|
|
69
73
|
}
|
|
70
74
|
catch (error) {
|
|
71
75
|
if (response.headersSent)
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EACpB,sBAAsB,EACtB,SAAS,EACT,cAAc,EAEd,mBAAmB,EACpB,MAAM,WAAW,CAAA;AAGlB,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,EAAE,MAAM,EAAE,CAAA;CACpB;AACD,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAA;AAEjE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,cAAc,EAAE,CAAA;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,MAAM,MAAM,eAAe,GAAG,cAAc,CAAA;AAE5C,MAAM,WAAW,eAAe,CAAC,IAAI,GAAG,OAAO;IAC7C,IAAI,EAAE,IAAI,CAAA;IACV,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,cAAc,EAAE,CAAA;IAC7B,IAAI,EAAE,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAA;IAC/C,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd;AA4CD,eAAO,MAAM,gBAAgB,GAC3B,MAAM,MAAM,EACZ,OAAM,SAA2B,KAChC,sBAAsB,GAAG,SAM3B,CAAA;AAED,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EACZ,OAAM,SAA2B,KAChC,mBAAmB,GAAG,SAIxB,CAAA;
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EACpB,sBAAsB,EACtB,SAAS,EACT,cAAc,EAEd,mBAAmB,EACpB,MAAM,WAAW,CAAA;AAGlB,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,EAAE,MAAM,EAAE,CAAA;CACpB;AACD,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAA;AAEjE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,cAAc,EAAE,CAAA;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,MAAM,MAAM,eAAe,GAAG,cAAc,CAAA;AAE5C,MAAM,WAAW,eAAe,CAAC,IAAI,GAAG,OAAO;IAC7C,IAAI,EAAE,IAAI,CAAA;IACV,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,cAAc,EAAE,CAAA;IAC7B,IAAI,EAAE,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAA;IAC/C,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd;AA4CD,eAAO,MAAM,gBAAgB,GAC3B,MAAM,MAAM,EACZ,OAAM,SAA2B,KAChC,sBAAsB,GAAG,SAM3B,CAAA;AAED,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EACZ,OAAM,SAA2B,KAChC,mBAAmB,GAAG,SAIxB,CAAA;AAkLD,eAAO,MAAM,cAAc,GACzB,OAAM;IACJ,SAAS,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;IACvC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACvB,EACN,OAAM,SAA2B,KAChC,eAAe,CAAC;IAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAgDnE,CAAA;AAwBD,QAAA,MAAM,eAAe,GACnB,WAAW,sBAAsB,EACjC,WAAW,cAAc,EACzB,QAAQ,oBAAoB;;;;;;;;;;;;;sBA1SP,CAAC;;;;;;uBAKV,CAAC;gBAAiB,CAAC;;mBACO,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAvD5B,MAAM;iBACH,MAAM,EAAE;iBACR,MAAM;gBACP,cAAc,EAAE;WACrB,MAAM;UACP,MAAM;aACH,MAAM,EAAE;;;;;;;;;;;;cANP,MAAM;iBACH,MAAM,EAAE;iBACR,MAAM;gBACP,cAAc,EAAE;WACrB,MAAM;UACP,MAAM;aACH,MAAM,EAAE;CAqXlB,CAAA;AAiID,eAAO,MAAM,YAAY,GACvB,MAAM;IACJ,MAAM,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAA;IACzC,SAAS,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;IACvC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IACnC,IAAI,EAAE,MAAM,CAAA;CACb,EACD,OAAM,SAA2B,KAChC,eAAe,CAAC;IACf,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAA;IAC9C,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAkCF,CAAA;AAED,eAAO,MAAM,SAAS,GACpB,MAAM;IAAE,SAAS,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAC/D,OAAM,SAA2B,KAChC,eAAe,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,mBAAmB,CAAA;CAAE,CAkCpF,CAAA;AAED,eAAO,MAAM,MAAM,GACjB,MAAM;IACJ,SAAS,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;IACvC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAA;CACd,EACD,OAAM,SAA2B,KAChC,eAAe,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,YAAY,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAkD3E,CAAA;AAED,eAAO,MAAM,OAAO,GAClB,OAAM,SAA2B,KAChC,eAAe,CAAC;IAAE,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,CAAA;CAAE,CAY5C,CAAA;AAmBF,eAAO,MAAM,kBAAkB,GAC7B,OAAM,SAA2B,KAChC,eAAe,CAAC;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,oBAAoB,CAAA;IAC9B,aAAa,EAAE,MAAM,CAAA;CACtB,CAcD,CAAA;AAEF,eAAO,MAAM,WAAW,GACtB,MAAM;IACJ,QAAQ,EAAE,oBAAoB,CAAA;IAC9B,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACzC,EACD,OAAM,SAA2B,KAChC,eAAe,CAAC;IACf,UAAU,EAAE,cAAc,CAAA;IAC1B,kBAAkB,EAAE,MAAM,CAAA;IAC1B,OAAO,EAAE,cAAc,CAAA;IACzB,SAAS,EAAE,OAAO,CAAA;CACnB,CAqCA,CAAA;AAED,eAAO,MAAM,QAAQ,GACnB,OAAM,SAA2B,KAChC,eAAe,CAAC;IACf,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,EAAE,CAAA;IACpE,iBAAiB,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;IACjD,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAA;CAC7B,CAuDF,CAAA;AAED,eAAO,MAAM,SAAS,GACpB,OAAM,SAA2B,KAChC,eAAe,CAAC;IAAE,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAA;CAAE,CAwBjD,CAAA;AAED,eAAO,MAAM,QAAQ,GACnB,OAAM,SAA2B,KAChC,eAAe,CAAC;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAanC,CAAA"}
|
package/dist/tools.js
CHANGED
|
@@ -40,21 +40,25 @@ export const resolveRecipe = (name, data = loadLumenData()) => {
|
|
|
40
40
|
const target = normalize(name);
|
|
41
41
|
return data.recipes.find((recipe) => normalize(recipe.name) === target);
|
|
42
42
|
};
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
const frameworkBehaviorSearchText = (behavior) => [
|
|
44
|
+
behavior?.description ?? '',
|
|
45
|
+
behavior?.hook ?? '',
|
|
46
|
+
behavior?.mode ?? '',
|
|
47
|
+
behavior?.setup ?? ''
|
|
48
|
+
];
|
|
49
|
+
const frameworkDetailsSearchText = (framework) => [
|
|
47
50
|
framework.packageName,
|
|
48
|
-
framework.behavior
|
|
49
|
-
framework.behavior?.hook ?? '',
|
|
50
|
-
framework.behavior?.mode ?? '',
|
|
51
|
-
framework.behavior?.setup ?? '',
|
|
51
|
+
...frameworkBehaviorSearchText(framework.behavior),
|
|
52
52
|
framework.example,
|
|
53
53
|
framework.propsExtends ?? '',
|
|
54
54
|
framework.props.map((prop) => `${prop.name} ${prop.type}`).join(' '),
|
|
55
55
|
framework.attributes?.join(' ') ?? '',
|
|
56
56
|
framework.tagName ?? ''
|
|
57
|
-
]
|
|
57
|
+
];
|
|
58
|
+
const frameworkSearchText = (component, framework) => (framework
|
|
59
|
+
? [Reflect.get(component.frameworkDetails, framework)]
|
|
60
|
+
: Object.values(component.frameworkDetails))
|
|
61
|
+
.flatMap(frameworkDetailsSearchText)
|
|
58
62
|
.join(' ');
|
|
59
63
|
const componentSearchText = (component, framework) => [
|
|
60
64
|
component.name,
|
|
@@ -74,13 +78,13 @@ const componentSearchText = (component, framework) => [
|
|
|
74
78
|
].join(' ');
|
|
75
79
|
const scoreCandidate = (query, terms, searchableText, primaryName = '') => {
|
|
76
80
|
const normalizedText = normalize(searchableText);
|
|
77
|
-
const matchedTerms = terms.filter((term) => (searchTermAliases
|
|
81
|
+
const matchedTerms = terms.filter((term) => (Reflect.get(searchTermAliases, term) ?? [term]).some((candidate) => normalizedText.includes(candidate)));
|
|
78
82
|
if (matchedTerms.length === 0)
|
|
79
83
|
return { matchedTerms, score: 0 };
|
|
80
84
|
const normalizedQuery = terms.join('-');
|
|
81
85
|
const normalizedName = normalize(primaryName);
|
|
82
86
|
const coverage = matchedTerms.length / terms.length;
|
|
83
|
-
let score = matchedTerms.reduce((total, term) => total + ((searchTermAliases
|
|
87
|
+
let score = matchedTerms.reduce((total, term) => total + ((Reflect.get(searchTermAliases, term) ?? [term]).some((candidate) => normalizedName.includes(candidate))
|
|
84
88
|
? 20
|
|
85
89
|
: 5), 0);
|
|
86
90
|
score += Math.round(coverage * 80);
|
|
@@ -101,7 +105,7 @@ const appendSearchResult = (results, candidate, query, terms, searchableText) =>
|
|
|
101
105
|
const collectSearchResults = (query, terms, data, framework) => {
|
|
102
106
|
const results = [];
|
|
103
107
|
for (const component of data.components) {
|
|
104
|
-
if (framework && !component.frameworks
|
|
108
|
+
if (framework && !Reflect.get(component.frameworks, framework))
|
|
105
109
|
continue;
|
|
106
110
|
appendSearchResult(results, {
|
|
107
111
|
category: component.category,
|
|
@@ -231,38 +235,35 @@ const formatProps = (framework) => {
|
|
|
231
235
|
: 'Props:';
|
|
232
236
|
return `${header}\n${lines.join('\n')}`;
|
|
233
237
|
};
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
if (
|
|
254
|
-
sections.push(
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
sections.push('', 'Hook options:', ...framework.behavior.options.map((option) => `- ${option.name}: ${option.type} — ${option.description}`));
|
|
261
|
-
}
|
|
262
|
-
if (framework.behavior.controller && framework.behavior.controller.length > 0) {
|
|
263
|
-
sections.push('', 'Controller values:', ...framework.behavior.controller.map((value) => `- ${value.name}: ${value.type} — ${value.description}`));
|
|
264
|
-
}
|
|
238
|
+
const buildSummarySections = (component, frameworkName, framework) => [
|
|
239
|
+
`# ${component.name}`,
|
|
240
|
+
component.description,
|
|
241
|
+
`Category: ${component.category}`,
|
|
242
|
+
`Framework: ${frameworkName}`,
|
|
243
|
+
`Package: ${framework.packageName}`,
|
|
244
|
+
`Import: ${framework.importStatement}`,
|
|
245
|
+
`Styles: ${framework.styleImport}`,
|
|
246
|
+
framework.tagName ? `Custom element: <${framework.tagName}>` : '',
|
|
247
|
+
component.recipes.length > 0
|
|
248
|
+
? `Recipes: ${component.recipes.map((recipe) => recipe.name).join(', ')}`
|
|
249
|
+
: 'Recipes: none'
|
|
250
|
+
].filter(Boolean);
|
|
251
|
+
const appendBehaviorSections = (sections, behavior) => {
|
|
252
|
+
if (!behavior)
|
|
253
|
+
return;
|
|
254
|
+
sections.push('', '## Framework behavior', behavior.setup);
|
|
255
|
+
if (behavior.hook)
|
|
256
|
+
sections.push(`Hook: ${behavior.hook}`);
|
|
257
|
+
if (behavior.description)
|
|
258
|
+
sections.push(behavior.description);
|
|
259
|
+
if (behavior.options && behavior.options.length > 0) {
|
|
260
|
+
sections.push('', 'Hook options:', ...behavior.options.map((option) => `- ${option.name}: ${option.type} — ${option.description}`));
|
|
261
|
+
}
|
|
262
|
+
if (behavior.controller && behavior.controller.length > 0) {
|
|
263
|
+
sections.push('', 'Controller values:', ...behavior.controller.map((value) => `- ${value.name}: ${value.type} — ${value.description}`));
|
|
265
264
|
}
|
|
265
|
+
};
|
|
266
|
+
const appendGuidanceSections = (sections, component) => {
|
|
266
267
|
if (component.guidance) {
|
|
267
268
|
sections.push('', '## Guidance', component.guidance.when);
|
|
268
269
|
if (component.guidance.distinction)
|
|
@@ -270,15 +271,27 @@ const formatComponentUsage = (component, frameworkName, detail) => {
|
|
|
270
271
|
}
|
|
271
272
|
if (component.keyboardInteractions.length > 0) {
|
|
272
273
|
sections.push('', '## Keyboard interactions');
|
|
273
|
-
sections.push(...component.keyboardInteractions.map((
|
|
274
|
+
sections.push(...component.keyboardInteractions.map((interaction) => `- ${interaction.key}: ${interaction.action}`));
|
|
275
|
+
}
|
|
276
|
+
if (component.apiReference.length > 0) {
|
|
277
|
+
sections.push('', '## API reference');
|
|
278
|
+
sections.push(...component.apiReference.map((row) => `- \`${row.attribute}\` ${row.values} — ${row.description}`));
|
|
274
279
|
}
|
|
275
280
|
if (component.runtimeEvents.length > 0) {
|
|
276
281
|
sections.push('', '## Runtime events');
|
|
277
282
|
sections.push(...component.runtimeEvents.map((event) => `- ${event.name}: ${event.when}`));
|
|
278
283
|
}
|
|
284
|
+
};
|
|
285
|
+
const formatComponentUsage = (component, frameworkName, detail) => {
|
|
286
|
+
const framework = getFrameworkDetail(component.frameworkDetails, frameworkName);
|
|
287
|
+
const sections = buildSummarySections(component, frameworkName, framework);
|
|
288
|
+
if (detail === 'summary')
|
|
289
|
+
return sections.join('\n');
|
|
290
|
+
sections.push('', formatProps(framework), '', '## Example', `\`\`\`${framework.language}`, framework.example, '```');
|
|
291
|
+
appendBehaviorSections(sections, framework.behavior);
|
|
292
|
+
appendGuidanceSections(sections, component);
|
|
279
293
|
if (detail === 'source') {
|
|
280
|
-
sections.push('', `## ${frameworkName} reference source
|
|
281
|
-
sections.push(`\`\`\`${framework.language}`, framework.source.trimEnd(), '```');
|
|
294
|
+
sections.push('', `## ${frameworkName} reference source`, `\`\`\`${framework.language}`, framework.source.trimEnd(), '```');
|
|
282
295
|
}
|
|
283
296
|
return sections.join('\n');
|
|
284
297
|
};
|
|
@@ -389,12 +402,12 @@ const diffManifestSection = (current, baseline) => {
|
|
|
389
402
|
const currentNames = Object.keys(current);
|
|
390
403
|
const baselineNames = Object.keys(baseline);
|
|
391
404
|
return {
|
|
392
|
-
added: currentNames.filter((name) => baseline
|
|
405
|
+
added: currentNames.filter((name) => Reflect.get(baseline, name) === undefined).sort(),
|
|
393
406
|
changed: currentNames
|
|
394
|
-
.filter((name) => baseline
|
|
407
|
+
.filter((name) => Reflect.get(baseline, name) !== undefined && Reflect.get(baseline, name) !== Reflect.get(current, name))
|
|
395
408
|
.sort(),
|
|
396
|
-
removed: baselineNames.filter((name) => current
|
|
397
|
-
unchanged: currentNames.filter((name) => baseline
|
|
409
|
+
removed: baselineNames.filter((name) => Reflect.get(current, name) === undefined).sort(),
|
|
410
|
+
unchanged: currentNames.filter((name) => Reflect.get(baseline, name) === Reflect.get(current, name)).sort()
|
|
398
411
|
};
|
|
399
412
|
};
|
|
400
413
|
export const getCatalogManifest = (data = loadLumenData()) => ({
|
|
@@ -465,14 +478,17 @@ export const diagnose = (data = loadLumenData()) => {
|
|
|
465
478
|
{
|
|
466
479
|
message: 'Every component has a manifest fingerprint.',
|
|
467
480
|
name: 'component-manifest',
|
|
468
|
-
status: componentNames.every((name) => data.catalogManifest.components
|
|
481
|
+
status: componentNames.every((name) => Reflect.get(data.catalogManifest.components, name)) ? 'pass' : 'fail'
|
|
469
482
|
},
|
|
470
483
|
{
|
|
471
484
|
message: 'Every available framework contract has an example and import statement.',
|
|
472
485
|
name: 'framework-contracts',
|
|
473
|
-
status: data.components.every((component) => Object.entries(component.frameworks).every(([framework, available]) =>
|
|
474
|
-
|
|
475
|
-
|
|
486
|
+
status: data.components.every((component) => Object.entries(component.frameworks).every(([framework, available]) => {
|
|
487
|
+
if (!available)
|
|
488
|
+
return true;
|
|
489
|
+
const details = Reflect.get(component.frameworkDetails, framework);
|
|
490
|
+
return Boolean(details?.example.trim()) && Boolean(details?.importStatement.trim());
|
|
491
|
+
})) ? 'pass' : 'fail'
|
|
476
492
|
}
|
|
477
493
|
];
|
|
478
494
|
const status = checks.every((check) => check.status === 'pass') ? 'healthy' : 'issues';
|