@santi020k/lumen-mcp 0.3.0 → 0.4.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/data/lumen-data.json +2074 -282
- package/dist/data.d.ts +1 -0
- package/dist/data.d.ts.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +4 -0
- package/package.json +1 -1
package/data/lumen-data.json
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"Avatar": "8919014913a38d94a33da2898d775feb109770345ed33fe4184fea34ad7162e3",
|
|
12
12
|
"BackToTop": "1c53e690626c2e9eaed71fafde5ec065b39a943b63048ad9ccf24f0c16edaa68",
|
|
13
13
|
"Badge": "7e2d3cafb52609251056230c8389c731acfdf55895b8cf5e7712b138ad05e09b",
|
|
14
|
+
"BarChart": "c58fadb0fe2335edbf022a6c0fa11cb77c474830ccc2fb97a775595054653f7b",
|
|
14
15
|
"Breadcrumb": "07e39012551d5916abd2ae7f8266386907b889ddba41da2eee34af7f6fea6673",
|
|
15
16
|
"Bubble": "40e168ca39bac88b431e6104659c315a85bedd6198dd59f3f26582021df538b4",
|
|
16
17
|
"Button": "ec006af669eecd5011afabeaaf244eab3f090e9858e368d13109232a2ae26d06",
|
|
@@ -19,7 +20,7 @@
|
|
|
19
20
|
"Callout": "c13fbded24bcea45c0a9f9ddccef8cec4f4ed39e07809d5ff2a850485397eb51",
|
|
20
21
|
"Card": "e50266a9cf255a7a1706373b5859272dd17ba0e57fd7aff37f2a7ac35797c669",
|
|
21
22
|
"Carousel": "811a7ca777563b88766a6ae97a796ba789c7fb22ab06f253773e280ba5804a38",
|
|
22
|
-
"Chart": "
|
|
23
|
+
"Chart": "473c4e02c80803565f0409e4e4024c2e06c09f476a8bd13a118e75f2b2ddce1b",
|
|
23
24
|
"Checkbox": "d971d97482ba924a07d4891cc782dd14c87b9f8bdb7b4070181b2189748b8be1",
|
|
24
25
|
"Collapsible": "7652876be7a40fc2451168ea8220c49a5ef0fcfddc04d6d5ff424e6d2d26a04a",
|
|
25
26
|
"Code": "e2f5eea415e1d2212dcb782487b417806f7ba6a7b1469f1b74a082fe35523275",
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
"FloatingBadge": "db0fb0b64ba740b195c7ddebd6f0573ce3da25dbca7e80eb82fe0fb425e15d04",
|
|
42
43
|
"FormattedDate": "c4f24887c4746220a641e34590e22434d08f02345abde6316246d76e77bacfb6",
|
|
43
44
|
"HoverCard": "7600efb83ed7b3d71b8a12d073a408d8663fb0b644b64e35d2c9b113a4130473",
|
|
44
|
-
"Icon": "
|
|
45
|
+
"Icon": "a8957b7c35f2bce93c240e7a420e96fecdd47f548583f9a87808fb2a8a152e09",
|
|
45
46
|
"Image": "ae96c90e196f84f026fc0298a29b167a31b04599a5d229bccd01e6118f811649",
|
|
46
47
|
"Input": "a928bc600c02646eae2162bb4ebe292d54a30a13107dda6c5b1152fa47619340",
|
|
47
48
|
"InputGroup": "ce2011ca129f23c62f0dd34e75d2b8f15437fbc72bd95d77ad1e4d7de1124754",
|
|
@@ -50,6 +51,7 @@
|
|
|
50
51
|
"Kbd": "28e109087067cc5c71a4fd84c9add36be7de7a39ce376d3ef59fc8d9465ecee1",
|
|
51
52
|
"Label": "e76c47b92db619d66ce76c15f10e440c599c2759cb96c328d2bbd0d75659ef92",
|
|
52
53
|
"Link": "c3e950ce51c641e6593868d99aea43936cd35b8559127dd3b881b04f4aa565a0",
|
|
54
|
+
"LineChart": "b4f03a5cd9bd8bfff94d4182163630af5939ba6b67508b778d9422a51620617b",
|
|
53
55
|
"Marker": "4875fd7e8792aac78bb6b3733a48d0a2f1c298d812db89c0680d736bf4c07a15",
|
|
54
56
|
"Menubar": "5450c01fa81f0b9dce4d1f39ce7507f6d744b2147cfa68d859e8e02714e2f16c",
|
|
55
57
|
"Message": "f7f25f4c9e727d83af8b4c42751d024f7de418d45771ba3a975ac229d332cb7c",
|
|
@@ -59,14 +61,16 @@
|
|
|
59
61
|
"NumberField": "97db5294f8232c25958c15bf93e2c78caf55651a5cc9439e3de6eb58e727e9bf",
|
|
60
62
|
"Pagination": "79afd85add73b34c6c6f954b7755ee8e795b8836bee6193efc22910bdeb9f333",
|
|
61
63
|
"PhoneInput": "585a257a1cc654fa653c7bd81a400ce8991f71a9d67596c3b2511ea9b8d83614",
|
|
62
|
-
"
|
|
64
|
+
"PieChart": "19eae80895734a9f5be30f8ff66ba87b7d1e7b438df3195efcd738e7f82a932c",
|
|
65
|
+
"Pill": "bbab3e93037d35258eff820a57892bf6002dd2cbcebb8241866da89e30d8b52c",
|
|
63
66
|
"Popover": "a596714668a14c81c2e6edf7666ca2cc17939c057470cc90c10a18a13924c401",
|
|
64
|
-
"Progress": "
|
|
67
|
+
"Progress": "405786d7a0e5681adfa520df338957d6d486db14006e5aab652b1822a78bc26d",
|
|
65
68
|
"Prose": "14454809f9ae5e0b509418fa1d74d00af480b5ce2d289e7c608c1ad78ef93eff",
|
|
66
69
|
"RadioGroup": "5f9bd9181f6fd47d3c168846cc21eed2308064535bc527e8fc1a60460b3138fb",
|
|
67
70
|
"Resizable": "36d3a5b19ec3eb74e8ebfdd92a7e0105a1deb115142c76df1784ce5a8f4bdb61",
|
|
68
71
|
"RichTextEditor": "dbc639a21744cf725ae78c3dfe90c310285c34034f1a59ce42969f46d651539f",
|
|
69
72
|
"ScrollArea": "a0b2ea629429009e7b51bf33ab256150f320c5704370347ce16a70a84d627c55",
|
|
73
|
+
"ScrollProgress": "071a889086890c45934369fbb85c65a49cefc238c522aadd4723cb48505ad01e",
|
|
70
74
|
"Schedule": "d1cb86cb6132a0352c75eaf3413d204dba48832ab385ce205c1e61d59633139c",
|
|
71
75
|
"SearchField": "561a310b3c8b112ed1baa7a01783be4471d73b47f3f2800460b4ccc23ca7bf42",
|
|
72
76
|
"Select": "2986d0d3dd9def947c418df15758bff6881d2a81fe1e1e68b6ef15d9b0dd19bc",
|
|
@@ -77,6 +81,7 @@
|
|
|
77
81
|
"SkipLink": "d660feaa0edbfdbb72d6da0c2bb62e725448ee4ff75ac1b34588cf4ceb3dbcd8",
|
|
78
82
|
"Slider": "cca90425ee92d9710e7b31d815d58027f2c3bcbd372282d20b6ef2fbd0aadb27",
|
|
79
83
|
"Sonner": "a7767b9f7a4d5d8b7263c19a9833336ef965c8a697ae6607ccd5fee9a69c0529",
|
|
84
|
+
"Sparkline": "d3d21505eae092a9161a82c30599d30f86246c1c45e2c0755bf1ae323a02e5fe",
|
|
80
85
|
"Spinner": "f5817573620b0fd870b2f0cca52c2baa1f00eb2f6d6a8087fe2f2db3e0051ff2",
|
|
81
86
|
"Switch": "046af1a323a3f49f7e83cae17c9eceac80afb8fa5afe91478bd10a1f65e33e5a",
|
|
82
87
|
"Table": "8481dc8028e49bae10d46ce66c29fb0fe06154ebbb7d66724749ff8d6f881d98",
|
|
@@ -95,12 +100,12 @@
|
|
|
95
100
|
"Typography": "0bc81b7dd562a010f8a4892370fd7a4382e929cc3c9e504126d65c4d3da2c040",
|
|
96
101
|
"VirtualList": "9f9277e3cc92a61cf35d2959a5ee08f01f627aee71fd9c3f1ffafb206b1f07e9",
|
|
97
102
|
"LanguageToggle": "8f3cd99de808d9983e1ad304a7867d55505d51c7867e04ce7ba155aea59afb23",
|
|
98
|
-
"Particles": "
|
|
103
|
+
"Particles": "06b1b05dea30b0d0992835599ac18101b6d08c28bbe9e39139562d30db1c973f",
|
|
99
104
|
"AnimatedNumber": "afbf3dfadcd3338199dbdc2d2e6c80182b90a3b6741ae4009f2ab68cf326235a",
|
|
100
105
|
"RevealGroup": "57ef595e6aff5c7a2843054d18639466022b2bebad2da2ce6b14a4970757c484",
|
|
101
106
|
"ScrollReveal": "940d69fc6bf5427c8bece747727872a8707c5b0c7fbefe60dad65d3b066ab35d",
|
|
102
|
-
"Stat": "
|
|
103
|
-
"Meter": "
|
|
107
|
+
"Stat": "b46bde93ea058c24fb0a685b48ba3c85915e3506c6dfb0ba21e373619230b0b1",
|
|
108
|
+
"Meter": "19a209d62f2f68750bb4092130fbc9e8d1c33a11132eb5871110eba45f93af9f",
|
|
104
109
|
"Note": "17c44fe3a3b08193ebba56b20d3d04f90f906b477e24a21c059b8531eac1aa16",
|
|
105
110
|
"Rating": "ec00e1b7f39a38884922bd48490b1dd5625b2eb41ed5265cf83600f7705180b5",
|
|
106
111
|
"Timeline": "93ffea4de7b9007c8a2badc99cf965fe7d974ae4ba5ad01c275183af5c3d6d79",
|
|
@@ -112,7 +117,7 @@
|
|
|
112
117
|
"Stepper": "3974df2b0c0be37a1e0c1f69dd7ce77bd6655d0f7b03a86a8dbf61191193598d",
|
|
113
118
|
"FileUpload": "91fa5aea1c3318c9b255ce2c700c014bc3ca98a54a2dfd599f7e3bfd5a0e5558",
|
|
114
119
|
"Tour": "4a294319873159d566d1dfc1878937fd2338629f2c57702daa822c275de80110",
|
|
115
|
-
"Anchor": "
|
|
120
|
+
"Anchor": "eb86f012637c44fba25025ceb667aec83899decd5e4833ff92e33e75090642b5",
|
|
116
121
|
"Segmented": "fea2f68a5935678aa892e39ae4808dd2fc36be992215a1665e321594d4cd8755",
|
|
117
122
|
"Toolbar": "eb3d645b5f843ad028122d6d5244b3c1eab8b4b6a25f2cec1ae4f56e72f009b8",
|
|
118
123
|
"Descriptions": "5e1a8991654626fbe3fe541f299be774dfc2801313a49cbd4b11cf4eb31de983",
|
|
@@ -122,7 +127,7 @@
|
|
|
122
127
|
"TreeSelect": "8d4b1475eab41f4e41b632dc535f31d6fe6fa44cbb6bbbebbdfed73eaefd3d35",
|
|
123
128
|
"Mentions": "bf9b8f29f881ebe7022a28744ae8fcc63329e887f3bfd6d660708192e9f912cd",
|
|
124
129
|
"QRCode": "ecd8c0488bc4ef147208627cc6d4298be62633e9293a0c5cd7f0835594c85d71",
|
|
125
|
-
"Watermark": "
|
|
130
|
+
"Watermark": "4e942660bb7dee0623c4d41553fd0e162b1e1f04f195e5a0b55eddae18bdbee3",
|
|
126
131
|
"Affix": "4215241a8b0633eb191a00b50a875e10cb226ab7ef21f2f6842431d8f6acc3be",
|
|
127
132
|
"SpeedDial": "b6a51b1715c92c4a2860759b146b4ceeab01acf326faeeb1e023a01e8b811fc9"
|
|
128
133
|
},
|
|
@@ -132,7 +137,8 @@
|
|
|
132
137
|
"scheduler": "fe25905d95e8d4294df9075e47ee9257d7db8e6542a3ac81272c4dee2ea1fdc0",
|
|
133
138
|
"data-collections": "fbbc09e60caed2449b5b904f9f1432278b52c8d28e7fe22de30af21208a4dfaf",
|
|
134
139
|
"theme-builder": "8de1d5f902b728af947f57e0f3667a5a8991ef71755bca7d985cdcaec9572252",
|
|
135
|
-
"rich-text-editor": "3c47135e8e10890e1d41b1878fdd497a5c87c34c5663821cf4005602cd7adbc9"
|
|
140
|
+
"rich-text-editor": "3c47135e8e10890e1d41b1878fdd497a5c87c34c5663821cf4005602cd7adbc9",
|
|
141
|
+
"data-visualization": "97f8f447cd36dfe026478f3eea379abe0907d5094f06285ec351c14a62908259"
|
|
136
142
|
}
|
|
137
143
|
},
|
|
138
144
|
"components": [
|
|
@@ -1936,6 +1942,335 @@
|
|
|
1936
1942
|
"recipes": [],
|
|
1937
1943
|
"runtimeEvents": []
|
|
1938
1944
|
},
|
|
1945
|
+
{
|
|
1946
|
+
"apiReference": [
|
|
1947
|
+
{
|
|
1948
|
+
"attribute": "glass",
|
|
1949
|
+
"defaultValue": "false",
|
|
1950
|
+
"description": "Applies the tokenized liquid-glass surface treatment with backdrop-filter fallbacks; \"subtle\" and \"strong\" adjust the fill intensity.",
|
|
1951
|
+
"values": "boolean | \"subtle\" | \"strong\""
|
|
1952
|
+
},
|
|
1953
|
+
{
|
|
1954
|
+
"attribute": "series",
|
|
1955
|
+
"defaultValue": "required",
|
|
1956
|
+
"description": "Provides already-aggregated categorical values and stable series metadata.",
|
|
1957
|
+
"values": "LumenChartSeries[]"
|
|
1958
|
+
},
|
|
1959
|
+
{
|
|
1960
|
+
"attribute": "orientation",
|
|
1961
|
+
"defaultValue": "\"vertical\"",
|
|
1962
|
+
"description": "Controls whether values extend across the x or y axis.",
|
|
1963
|
+
"values": "\"horizontal\" | \"vertical\""
|
|
1964
|
+
},
|
|
1965
|
+
{
|
|
1966
|
+
"attribute": "layout",
|
|
1967
|
+
"defaultValue": "\"grouped\"",
|
|
1968
|
+
"description": "Places series beside one another or combines their positive and negative totals.",
|
|
1969
|
+
"values": "\"grouped\" | \"stacked\""
|
|
1970
|
+
},
|
|
1971
|
+
{
|
|
1972
|
+
"attribute": "showLegend",
|
|
1973
|
+
"defaultValue": "true for multiple series",
|
|
1974
|
+
"description": "Shows the color-independent series key.",
|
|
1975
|
+
"values": "boolean"
|
|
1976
|
+
},
|
|
1977
|
+
{
|
|
1978
|
+
"attribute": "showTable",
|
|
1979
|
+
"defaultValue": "true",
|
|
1980
|
+
"description": "Provides a revealable semantic table containing every plotted value.",
|
|
1981
|
+
"values": "boolean"
|
|
1982
|
+
},
|
|
1983
|
+
{
|
|
1984
|
+
"attribute": "heading, description, caption",
|
|
1985
|
+
"defaultValue": "-",
|
|
1986
|
+
"description": "Adds visible chart context without replacing the accessible name.",
|
|
1987
|
+
"values": "string"
|
|
1988
|
+
},
|
|
1989
|
+
{
|
|
1990
|
+
"attribute": "class, className",
|
|
1991
|
+
"defaultValue": "\"\"",
|
|
1992
|
+
"description": "Merges custom classes with the generated ui-* root classes.",
|
|
1993
|
+
"values": "string"
|
|
1994
|
+
},
|
|
1995
|
+
{
|
|
1996
|
+
"attribute": "...native attributes",
|
|
1997
|
+
"defaultValue": "-",
|
|
1998
|
+
"description": "Forwards standard attributes to the root element unless the component consumes them.",
|
|
1999
|
+
"values": "HTML attributes"
|
|
2000
|
+
}
|
|
2001
|
+
],
|
|
2002
|
+
"astroSource": "---\nimport {\n createLumenBarGeometry,\n getLumenChartTicks,\n hasLumenChartData,\n type LumenBarChartLayout,\n type LumenChartOrientation,\n type LumenChartSeries,\n resolveLumenChartTone,\n scaleLumenChartValue\n} from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\nimport Chart from './Chart.astro'\n\ninterface Props extends HTMLAttributes<'figure'> {\n caption?: string\n class?: string | null\n className?: string\n description?: string\n glass?: boolean | 'subtle' | 'strong'\n heading?: string\n layout?: LumenBarChartLayout\n orientation?: LumenChartOrientation\n series: readonly LumenChartSeries[]\n showLegend?: boolean\n showTable?: boolean\n}\n\nconst {\n caption,\n class: classProp = '',\n className = '',\n description,\n glass = false,\n heading,\n layout = 'grouped',\n orientation = 'vertical',\n series,\n showLegend = series.length > 1,\n showTable = true,\n ...rest\n} = Astro.props\nconst geometry = createLumenBarGeometry(series, { layout, orientation })\nconst hasData = hasLumenChartData(series)\nconst ticks = getLumenChartTicks(geometry.domain)\nconst categories = geometry.categories.map(category => category.label)\nconst valueFor = (item: LumenChartSeries, category: number | string) =>\n item.data.find(datum => datum.x === category)?.y ?? null\nconst labelFor = (item: LumenChartSeries, category: number | string) =>\n item.data.find(datum => datum.x === category)?.label\nconst margin = orientation === 'horizontal'\n ? { bottom: 24, left: 112, right: 20, top: 16 }\n : { bottom: 52, left: 52, right: 16, top: 16 }\n---\n\n<Chart\n class:list={['ui-bar-chart', classProp, className]}\n {caption}\n {description}\n {glass}\n {heading}\n {...rest}\n>\n {\n showLegend && hasData && (\n <ul class=\"ui-chart__legend\" aria-label=\"Chart legend\">\n {series.map((item, index) => (\n <li class={`ui-chart-tone--${resolveLumenChartTone(item.tone, index)}`}>\n <span aria-hidden=\"true\" />\n {item.label}\n </li>\n ))}\n </ul>\n )\n }\n {!hasData && <p class=\"ui-chart__empty\" role=\"status\">No chart data available.</p>}\n <div class=\"ui-chart__plot\" hidden={!hasData}>\n <svg\n aria-hidden=\"true\"\n preserveAspectRatio=\"xMidYMid meet\"\n viewBox={`0 0 ${geometry.width} ${geometry.height}`}\n >\n <g class=\"ui-chart__grid\">\n {\n ticks.map((tick) => {\n const coordinate =\n orientation === 'horizontal'\n ? scaleLumenChartValue(\n tick,\n geometry.domain,\n margin.left,\n geometry.width - margin.right\n )\n : scaleLumenChartValue(\n tick,\n geometry.domain,\n geometry.height - margin.bottom,\n margin.top\n )\n\n return orientation === 'horizontal' ? (\n <line\n x1={coordinate}\n x2={coordinate}\n y1={margin.top}\n y2={geometry.height - margin.bottom}\n />\n ) : (\n <line\n x1={margin.left}\n x2={geometry.width - margin.right}\n y1={coordinate}\n y2={coordinate}\n />\n )\n })\n }\n </g>\n <g class=\"ui-chart__axis-labels\">\n {\n geometry.categories.map((category) => (\n <text\n dominant-baseline={orientation === 'horizontal' ? 'middle' : undefined}\n text-anchor={orientation === 'horizontal' ? 'end' : 'middle'}\n x={category.x}\n y={category.y}\n >\n {String(category.label)}\n </text>\n ))\n }\n </g>\n <g class=\"ui-bar-chart__marks\">\n {\n geometry.marks.map((mark) => (\n <rect\n class={`ui-chart-tone--${mark.tone}`}\n height={mark.height}\n rx=\"4\"\n width={mark.width}\n x={mark.x}\n y={mark.y}\n >\n <title>\n {`${String(mark.category)} · ${mark.seriesLabel}: ${mark.value}`}\n </title>\n </rect>\n ))\n }\n </g>\n </svg>\n </div>\n {\n showTable && hasData && (\n <details class=\"ui-chart__data\">\n <summary>View chart data</summary>\n <div>\n <table>\n <thead>\n <tr>\n <th scope=\"col\">Category</th>\n {series.map(item => <th scope=\"col\">{item.label}</th>)}\n </tr>\n </thead>\n <tbody>\n {categories.map(category => (\n <tr>\n <th scope=\"row\">{String(category)}</th>\n {series.map(item => (\n <td>\n {labelFor(item, category) ??\n String(valueFor(item, category) ?? 'Not available')}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </details>\n )\n }\n</Chart>\n",
|
|
2003
|
+
"category": "Data display",
|
|
2004
|
+
"collections": [
|
|
2005
|
+
"Data visualization"
|
|
2006
|
+
],
|
|
2007
|
+
"dependencies": [
|
|
2008
|
+
"Chart",
|
|
2009
|
+
"styles"
|
|
2010
|
+
],
|
|
2011
|
+
"description": "Compares categorical or discrete-period values with grouped and stacked bars.",
|
|
2012
|
+
"files": [
|
|
2013
|
+
"packages/astro/components/BarChart.astro",
|
|
2014
|
+
"packages/astro/components/Chart.astro",
|
|
2015
|
+
"packages/astro/styles/lumen.css"
|
|
2016
|
+
],
|
|
2017
|
+
"frameworkDetails": {
|
|
2018
|
+
"astro": {
|
|
2019
|
+
"available": true,
|
|
2020
|
+
"example": "<BarChart aria-label=\"Downloads by project\" heading=\"Package downloads\" orientation=\"horizontal\" series={[{ id: \"downloads\", label: \"Downloads\", data: [{ x: \"Lumen\", y: 18420 }, { x: \"Observatory\", y: 6320 }] }]} />",
|
|
2021
|
+
"importStatement": "import { BarChart } from '@santi020k/lumen-astro'",
|
|
2022
|
+
"language": "astro",
|
|
2023
|
+
"packageName": "@santi020k/lumen-astro",
|
|
2024
|
+
"props": [
|
|
2025
|
+
{
|
|
2026
|
+
"name": "caption",
|
|
2027
|
+
"optional": true,
|
|
2028
|
+
"type": "string"
|
|
2029
|
+
},
|
|
2030
|
+
{
|
|
2031
|
+
"name": "class",
|
|
2032
|
+
"optional": true,
|
|
2033
|
+
"type": "string | null"
|
|
2034
|
+
},
|
|
2035
|
+
{
|
|
2036
|
+
"name": "className",
|
|
2037
|
+
"optional": true,
|
|
2038
|
+
"type": "string"
|
|
2039
|
+
},
|
|
2040
|
+
{
|
|
2041
|
+
"name": "description",
|
|
2042
|
+
"optional": true,
|
|
2043
|
+
"type": "string"
|
|
2044
|
+
},
|
|
2045
|
+
{
|
|
2046
|
+
"name": "glass",
|
|
2047
|
+
"optional": true,
|
|
2048
|
+
"type": "boolean | 'subtle' | 'strong'"
|
|
2049
|
+
},
|
|
2050
|
+
{
|
|
2051
|
+
"name": "heading",
|
|
2052
|
+
"optional": true,
|
|
2053
|
+
"type": "string"
|
|
2054
|
+
},
|
|
2055
|
+
{
|
|
2056
|
+
"name": "layout",
|
|
2057
|
+
"optional": true,
|
|
2058
|
+
"type": "LumenBarChartLayout"
|
|
2059
|
+
},
|
|
2060
|
+
{
|
|
2061
|
+
"name": "orientation",
|
|
2062
|
+
"optional": true,
|
|
2063
|
+
"type": "LumenChartOrientation"
|
|
2064
|
+
},
|
|
2065
|
+
{
|
|
2066
|
+
"name": "series",
|
|
2067
|
+
"optional": false,
|
|
2068
|
+
"type": "readonly LumenChartSeries[]"
|
|
2069
|
+
},
|
|
2070
|
+
{
|
|
2071
|
+
"name": "showLegend",
|
|
2072
|
+
"optional": true,
|
|
2073
|
+
"type": "boolean"
|
|
2074
|
+
},
|
|
2075
|
+
{
|
|
2076
|
+
"name": "showTable",
|
|
2077
|
+
"optional": true,
|
|
2078
|
+
"type": "boolean"
|
|
2079
|
+
}
|
|
2080
|
+
],
|
|
2081
|
+
"propsExtends": "HTMLAttributes<'figure'>",
|
|
2082
|
+
"source": "---\nimport {\n createLumenBarGeometry,\n getLumenChartTicks,\n hasLumenChartData,\n type LumenBarChartLayout,\n type LumenChartOrientation,\n type LumenChartSeries,\n resolveLumenChartTone,\n scaleLumenChartValue\n} from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\nimport Chart from './Chart.astro'\n\ninterface Props extends HTMLAttributes<'figure'> {\n caption?: string\n class?: string | null\n className?: string\n description?: string\n glass?: boolean | 'subtle' | 'strong'\n heading?: string\n layout?: LumenBarChartLayout\n orientation?: LumenChartOrientation\n series: readonly LumenChartSeries[]\n showLegend?: boolean\n showTable?: boolean\n}\n\nconst {\n caption,\n class: classProp = '',\n className = '',\n description,\n glass = false,\n heading,\n layout = 'grouped',\n orientation = 'vertical',\n series,\n showLegend = series.length > 1,\n showTable = true,\n ...rest\n} = Astro.props\nconst geometry = createLumenBarGeometry(series, { layout, orientation })\nconst hasData = hasLumenChartData(series)\nconst ticks = getLumenChartTicks(geometry.domain)\nconst categories = geometry.categories.map(category => category.label)\nconst valueFor = (item: LumenChartSeries, category: number | string) =>\n item.data.find(datum => datum.x === category)?.y ?? null\nconst labelFor = (item: LumenChartSeries, category: number | string) =>\n item.data.find(datum => datum.x === category)?.label\nconst margin = orientation === 'horizontal'\n ? { bottom: 24, left: 112, right: 20, top: 16 }\n : { bottom: 52, left: 52, right: 16, top: 16 }\n---\n\n<Chart\n class:list={['ui-bar-chart', classProp, className]}\n {caption}\n {description}\n {glass}\n {heading}\n {...rest}\n>\n {\n showLegend && hasData && (\n <ul class=\"ui-chart__legend\" aria-label=\"Chart legend\">\n {series.map((item, index) => (\n <li class={`ui-chart-tone--${resolveLumenChartTone(item.tone, index)}`}>\n <span aria-hidden=\"true\" />\n {item.label}\n </li>\n ))}\n </ul>\n )\n }\n {!hasData && <p class=\"ui-chart__empty\" role=\"status\">No chart data available.</p>}\n <div class=\"ui-chart__plot\" hidden={!hasData}>\n <svg\n aria-hidden=\"true\"\n preserveAspectRatio=\"xMidYMid meet\"\n viewBox={`0 0 ${geometry.width} ${geometry.height}`}\n >\n <g class=\"ui-chart__grid\">\n {\n ticks.map((tick) => {\n const coordinate =\n orientation === 'horizontal'\n ? scaleLumenChartValue(\n tick,\n geometry.domain,\n margin.left,\n geometry.width - margin.right\n )\n : scaleLumenChartValue(\n tick,\n geometry.domain,\n geometry.height - margin.bottom,\n margin.top\n )\n\n return orientation === 'horizontal' ? (\n <line\n x1={coordinate}\n x2={coordinate}\n y1={margin.top}\n y2={geometry.height - margin.bottom}\n />\n ) : (\n <line\n x1={margin.left}\n x2={geometry.width - margin.right}\n y1={coordinate}\n y2={coordinate}\n />\n )\n })\n }\n </g>\n <g class=\"ui-chart__axis-labels\">\n {\n geometry.categories.map((category) => (\n <text\n dominant-baseline={orientation === 'horizontal' ? 'middle' : undefined}\n text-anchor={orientation === 'horizontal' ? 'end' : 'middle'}\n x={category.x}\n y={category.y}\n >\n {String(category.label)}\n </text>\n ))\n }\n </g>\n <g class=\"ui-bar-chart__marks\">\n {\n geometry.marks.map((mark) => (\n <rect\n class={`ui-chart-tone--${mark.tone}`}\n height={mark.height}\n rx=\"4\"\n width={mark.width}\n x={mark.x}\n y={mark.y}\n >\n <title>\n {`${String(mark.category)} · ${mark.seriesLabel}: ${mark.value}`}\n </title>\n </rect>\n ))\n }\n </g>\n </svg>\n </div>\n {\n showTable && hasData && (\n <details class=\"ui-chart__data\">\n <summary>View chart data</summary>\n <div>\n <table>\n <thead>\n <tr>\n <th scope=\"col\">Category</th>\n {series.map(item => <th scope=\"col\">{item.label}</th>)}\n </tr>\n </thead>\n <tbody>\n {categories.map(category => (\n <tr>\n <th scope=\"row\">{String(category)}</th>\n {series.map(item => (\n <td>\n {labelFor(item, category) ??\n String(valueFor(item, category) ?? 'Not available')}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </details>\n )\n }\n</Chart>\n",
|
|
2083
|
+
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
2084
|
+
},
|
|
2085
|
+
"elements": {
|
|
2086
|
+
"attributes": [
|
|
2087
|
+
"layout",
|
|
2088
|
+
"orientation",
|
|
2089
|
+
"glass",
|
|
2090
|
+
"series",
|
|
2091
|
+
"showLegend",
|
|
2092
|
+
"showTable",
|
|
2093
|
+
"heading, description, caption",
|
|
2094
|
+
"class, className",
|
|
2095
|
+
"...native attributes"
|
|
2096
|
+
],
|
|
2097
|
+
"available": true,
|
|
2098
|
+
"behavior": {
|
|
2099
|
+
"mode": "registration",
|
|
2100
|
+
"setup": "Call defineLumenElements() once before rendering Lumen custom elements."
|
|
2101
|
+
},
|
|
2102
|
+
"example": "<lumen-bar-chart></lumen-bar-chart>",
|
|
2103
|
+
"importStatement": "import { defineLumenElements } from '@santi020k/lumen-elements/define'",
|
|
2104
|
+
"language": "html",
|
|
2105
|
+
"packageName": "@santi020k/lumen-elements",
|
|
2106
|
+
"props": [],
|
|
2107
|
+
"propsExtends": "HTMLElement attributes",
|
|
2108
|
+
"registration": "defineLumenElements()",
|
|
2109
|
+
"source": "BarChart: {\n attributeClasses: glassAttributeClasses('ui-chart--glass'),\n baseClassName: 'ui-chart ui-bar-chart',\n defaults: { layout: 'grouped', orientation: 'vertical' },\n role: 'figure',\n tagName: 'lumen-bar-chart'\n }",
|
|
2110
|
+
"styleImport": "import '@santi020k/lumen-elements/styles.css'",
|
|
2111
|
+
"tagName": "lumen-bar-chart"
|
|
2112
|
+
},
|
|
2113
|
+
"react": {
|
|
2114
|
+
"available": true,
|
|
2115
|
+
"example": "<BarChart aria-label=\"Downloads by project\" heading=\"Package downloads\" orientation=\"horizontal\" series={[{ id: \"downloads\", label: \"Downloads\", data: [{ x: \"Lumen\", y: 18420 }, { x: \"Observatory\", y: 6320 }] }]} />",
|
|
2116
|
+
"importStatement": "import { BarChart } from '@santi020k/lumen-react'",
|
|
2117
|
+
"language": "tsx",
|
|
2118
|
+
"packageName": "@santi020k/lumen-react",
|
|
2119
|
+
"props": [
|
|
2120
|
+
{
|
|
2121
|
+
"name": "layout",
|
|
2122
|
+
"optional": true,
|
|
2123
|
+
"type": "LumenBarChartLayout"
|
|
2124
|
+
},
|
|
2125
|
+
{
|
|
2126
|
+
"name": "orientation",
|
|
2127
|
+
"optional": true,
|
|
2128
|
+
"type": "LumenChartOrientation"
|
|
2129
|
+
},
|
|
2130
|
+
{
|
|
2131
|
+
"name": "series",
|
|
2132
|
+
"optional": true,
|
|
2133
|
+
"type": "readonly LumenChartSeries[]"
|
|
2134
|
+
},
|
|
2135
|
+
{
|
|
2136
|
+
"name": "showLegend",
|
|
2137
|
+
"optional": true,
|
|
2138
|
+
"type": "boolean"
|
|
2139
|
+
},
|
|
2140
|
+
{
|
|
2141
|
+
"name": "showTable",
|
|
2142
|
+
"optional": true,
|
|
2143
|
+
"type": "boolean"
|
|
2144
|
+
}
|
|
2145
|
+
],
|
|
2146
|
+
"propsExtends": "Omit<ChartProps, 'children'>",
|
|
2147
|
+
"source": "export interface BarChartProps extends Omit<ChartProps, 'children'> {\n layout?: LumenBarChartLayout\n orientation?: LumenChartOrientation\n series?: readonly LumenChartSeries[]\n showLegend?: boolean\n showTable?: boolean\n}\n\nexport const BarChart = ({\n className,\n layout = 'grouped',\n orientation = 'vertical',\n series = emptyChartSeries,\n showLegend = series.length > 1,\n showTable = true,\n ...props\n}: BarChartProps) => {\n const geometry = createLumenBarGeometry(series, { layout, orientation })\n const hasData = hasLumenChartData(series)\n const ticks = getLumenChartTicks(geometry.domain)\n const categories = geometry.categories.map(category => category.label)\n\n const margin = orientation === 'horizontal'\n ? { bottom: 24, left: 112, right: 20, top: 16 }\n : { bottom: 52, left: 52, right: 16, top: 16 }\n\n return (\n <Chart className={composeClassName('ui-bar-chart', className)} {...props}>\n {showLegend && hasData && <ChartLegend series={series} />}\n {!hasData && (\n <p className=\"ui-chart__empty\" role=\"status\">No chart data available.</p>\n )}\n <div className=\"ui-chart__plot\" hidden={!hasData}>\n <svg\n aria-hidden=\"true\"\n preserveAspectRatio=\"xMidYMid meet\"\n viewBox={`0 0 ${geometry.width} ${geometry.height}`}\n >\n <g className=\"ui-chart__grid\">\n {ticks.map(tick => {\n const coordinate = orientation === 'horizontal'\n ? scaleLumenChartValue(\n tick,\n geometry.domain,\n margin.left,\n geometry.width - margin.right\n )\n : scaleLumenChartValue(\n tick,\n geometry.domain,\n geometry.height - margin.bottom,\n margin.top\n )\n\n return orientation === 'horizontal' ? (\n <line\n key={tick}\n x1={coordinate}\n x2={coordinate}\n y1={margin.top}\n y2={geometry.height - margin.bottom}\n />\n ) : (\n <line\n key={tick}\n x1={margin.left}\n x2={geometry.width - margin.right}\n y1={coordinate}\n y2={coordinate}\n />\n )\n })}\n </g>\n <g className=\"ui-chart__axis-labels\">\n {geometry.categories.map(category => (\n <text\n dominantBaseline={orientation === 'horizontal' ? 'middle' : undefined}\n key={`${typeof category.label}:${String(category.label)}`}\n textAnchor={orientation === 'horizontal' ? 'end' : 'middle'}\n x={category.x}\n y={category.y}\n >\n {String(category.label)}\n </text>\n ))}\n </g>\n <g className=\"ui-bar-chart__marks\">\n {geometry.marks.map(mark => (\n <rect\n className={`ui-chart-tone--${mark.tone}`}\n height={mark.height}\n key={`${mark.seriesId}:${String(mark.category)}`}\n rx=\"4\"\n width={mark.width}\n x={mark.x}\n y={mark.y}\n >\n <title>{`${String(mark.category)} · ${mark.seriesLabel}: ${mark.value}`}</title>\n </rect>\n ))}\n </g>\n </svg>\n </div>\n {showTable && hasData && (\n <ChartDataTable categories={categories} series={series} />\n )}\n </Chart>\n )\n}",
|
|
2148
|
+
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
2149
|
+
}
|
|
2150
|
+
},
|
|
2151
|
+
"frameworks": {
|
|
2152
|
+
"astro": true,
|
|
2153
|
+
"elements": true,
|
|
2154
|
+
"react": true
|
|
2155
|
+
},
|
|
2156
|
+
"guidance": {
|
|
2157
|
+
"when": "Use to compare categories, rankings, or discrete periods from already-aggregated values.",
|
|
2158
|
+
"distinction": "Use LineChart for continuous ordered trends and Sparkline for a compact trend attached to one metric."
|
|
2159
|
+
},
|
|
2160
|
+
"kebab": "bar-chart",
|
|
2161
|
+
"keyboardInteractions": [],
|
|
2162
|
+
"keywords": [
|
|
2163
|
+
"aggregated",
|
|
2164
|
+
"already",
|
|
2165
|
+
"and",
|
|
2166
|
+
"attached",
|
|
2167
|
+
"barchart",
|
|
2168
|
+
"bars",
|
|
2169
|
+
"breakdowns",
|
|
2170
|
+
"categorical",
|
|
2171
|
+
"categories",
|
|
2172
|
+
"compact",
|
|
2173
|
+
"compare",
|
|
2174
|
+
"compares",
|
|
2175
|
+
"comparisons",
|
|
2176
|
+
"continuous",
|
|
2177
|
+
"custom",
|
|
2178
|
+
"data",
|
|
2179
|
+
"discrete",
|
|
2180
|
+
"display",
|
|
2181
|
+
"for",
|
|
2182
|
+
"from",
|
|
2183
|
+
"grouped",
|
|
2184
|
+
"linechart",
|
|
2185
|
+
"match",
|
|
2186
|
+
"metric",
|
|
2187
|
+
"metrics",
|
|
2188
|
+
"one",
|
|
2189
|
+
"ordered",
|
|
2190
|
+
"part",
|
|
2191
|
+
"period",
|
|
2192
|
+
"periods",
|
|
2193
|
+
"plots",
|
|
2194
|
+
"question",
|
|
2195
|
+
"rankings",
|
|
2196
|
+
"sparkline",
|
|
2197
|
+
"stacked",
|
|
2198
|
+
"the",
|
|
2199
|
+
"trend",
|
|
2200
|
+
"trends",
|
|
2201
|
+
"use",
|
|
2202
|
+
"values",
|
|
2203
|
+
"visualization",
|
|
2204
|
+
"whole",
|
|
2205
|
+
"with"
|
|
2206
|
+
],
|
|
2207
|
+
"name": "BarChart",
|
|
2208
|
+
"props": [
|
|
2209
|
+
{
|
|
2210
|
+
"name": "caption",
|
|
2211
|
+
"optional": true,
|
|
2212
|
+
"type": "string"
|
|
2213
|
+
},
|
|
2214
|
+
{
|
|
2215
|
+
"name": "class",
|
|
2216
|
+
"optional": true,
|
|
2217
|
+
"type": "string | null"
|
|
2218
|
+
},
|
|
2219
|
+
{
|
|
2220
|
+
"name": "className",
|
|
2221
|
+
"optional": true,
|
|
2222
|
+
"type": "string"
|
|
2223
|
+
},
|
|
2224
|
+
{
|
|
2225
|
+
"name": "description",
|
|
2226
|
+
"optional": true,
|
|
2227
|
+
"type": "string"
|
|
2228
|
+
},
|
|
2229
|
+
{
|
|
2230
|
+
"name": "glass",
|
|
2231
|
+
"optional": true,
|
|
2232
|
+
"type": "boolean | 'subtle' | 'strong'"
|
|
2233
|
+
},
|
|
2234
|
+
{
|
|
2235
|
+
"name": "heading",
|
|
2236
|
+
"optional": true,
|
|
2237
|
+
"type": "string"
|
|
2238
|
+
},
|
|
2239
|
+
{
|
|
2240
|
+
"name": "layout",
|
|
2241
|
+
"optional": true,
|
|
2242
|
+
"type": "LumenBarChartLayout"
|
|
2243
|
+
},
|
|
2244
|
+
{
|
|
2245
|
+
"name": "orientation",
|
|
2246
|
+
"optional": true,
|
|
2247
|
+
"type": "LumenChartOrientation"
|
|
2248
|
+
},
|
|
2249
|
+
{
|
|
2250
|
+
"name": "series",
|
|
2251
|
+
"optional": false,
|
|
2252
|
+
"type": "readonly LumenChartSeries[]"
|
|
2253
|
+
},
|
|
2254
|
+
{
|
|
2255
|
+
"name": "showLegend",
|
|
2256
|
+
"optional": true,
|
|
2257
|
+
"type": "boolean"
|
|
2258
|
+
},
|
|
2259
|
+
{
|
|
2260
|
+
"name": "showTable",
|
|
2261
|
+
"optional": true,
|
|
2262
|
+
"type": "boolean"
|
|
2263
|
+
}
|
|
2264
|
+
],
|
|
2265
|
+
"propsExtends": "HTMLAttributes<'figure'>",
|
|
2266
|
+
"recipes": [
|
|
2267
|
+
{
|
|
2268
|
+
"name": "data-visualization",
|
|
2269
|
+
"type": "recipe"
|
|
2270
|
+
}
|
|
2271
|
+
],
|
|
2272
|
+
"runtimeEvents": []
|
|
2273
|
+
},
|
|
1939
2274
|
{
|
|
1940
2275
|
"apiReference": [
|
|
1941
2276
|
{
|
|
@@ -3533,8 +3868,20 @@
|
|
|
3533
3868
|
{
|
|
3534
3869
|
"attribute": "children",
|
|
3535
3870
|
"defaultValue": "required",
|
|
3536
|
-
"description": "Composes
|
|
3537
|
-
"values": "
|
|
3871
|
+
"description": "Composes a specialized visualization while the consumer owns its data and accessible description.",
|
|
3872
|
+
"values": "custom SVG, canvas, HTML plot, and optional table"
|
|
3873
|
+
},
|
|
3874
|
+
{
|
|
3875
|
+
"attribute": "heading, description, value",
|
|
3876
|
+
"defaultValue": "-",
|
|
3877
|
+
"description": "Builds the standard visible chart header without consuming the native title attribute.",
|
|
3878
|
+
"values": "string"
|
|
3879
|
+
},
|
|
3880
|
+
{
|
|
3881
|
+
"attribute": "caption",
|
|
3882
|
+
"defaultValue": "-",
|
|
3883
|
+
"description": "Adds a semantic figcaption after the custom plot.",
|
|
3884
|
+
"values": "string"
|
|
3538
3885
|
},
|
|
3539
3886
|
{
|
|
3540
3887
|
"attribute": "class, className",
|
|
@@ -3549,9 +3896,11 @@
|
|
|
3549
3896
|
"values": "HTML attributes"
|
|
3550
3897
|
}
|
|
3551
3898
|
],
|
|
3552
|
-
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'figure'> {\n class?: string | null\n className?: string\n glass?: boolean | 'subtle' | 'strong'\n}\n\nconst {\n class: classProp = '',\n className = '',\n glass = false,\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-chart',\n glass && 'ui-chart--glass',\n glass === 'subtle' && 'ui-glass-subtle',\n glass === 'strong' && 'ui-glass-strong'\n], classProp, className)\n---\n\n<figure\n class:list={classList}\n {...passthrough}\n>\n <slot />\n</figure>\n",
|
|
3899
|
+
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'figure'> {\n caption?: string\n class?: string | null\n className?: string\n description?: string\n glass?: boolean | 'subtle' | 'strong'\n heading?: string\n value?: string\n}\n\nconst {\n caption,\n class: classProp = '',\n className = '',\n description,\n glass = false,\n heading,\n value,\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-chart',\n glass && 'ui-chart--glass',\n glass === 'subtle' && 'ui-glass-subtle',\n glass === 'strong' && 'ui-glass-strong'\n], classProp, className)\n---\n\n<figure\n class:list={classList}\n {...passthrough}\n>\n {\n (heading || description || value || Astro.slots.has('header')) && (\n <header>\n <slot name=\"header\">\n <div class=\"ui-chart__heading\">\n {heading && <h3>{heading}</h3>}\n {description && <p>{description}</p>}\n </div>\n {value && <strong data-ui-chart-value>{value}</strong>}\n </slot>\n <slot name=\"actions\" />\n </header>\n )\n }\n <slot />\n {caption && <figcaption>{caption}</figcaption>}\n</figure>\n",
|
|
3553
3900
|
"category": "Data display",
|
|
3554
|
-
"collections": [
|
|
3901
|
+
"collections": [
|
|
3902
|
+
"Data visualization"
|
|
3903
|
+
],
|
|
3555
3904
|
"dependencies": [
|
|
3556
3905
|
"styles"
|
|
3557
3906
|
],
|
|
@@ -3569,7 +3918,12 @@
|
|
|
3569
3918
|
"packageName": "@santi020k/lumen-astro",
|
|
3570
3919
|
"props": [
|
|
3571
3920
|
{
|
|
3572
|
-
"name": "
|
|
3921
|
+
"name": "caption",
|
|
3922
|
+
"optional": true,
|
|
3923
|
+
"type": "string"
|
|
3924
|
+
},
|
|
3925
|
+
{
|
|
3926
|
+
"name": "class",
|
|
3573
3927
|
"optional": true,
|
|
3574
3928
|
"type": "string | null"
|
|
3575
3929
|
},
|
|
@@ -3578,20 +3932,37 @@
|
|
|
3578
3932
|
"optional": true,
|
|
3579
3933
|
"type": "string"
|
|
3580
3934
|
},
|
|
3935
|
+
{
|
|
3936
|
+
"name": "description",
|
|
3937
|
+
"optional": true,
|
|
3938
|
+
"type": "string"
|
|
3939
|
+
},
|
|
3581
3940
|
{
|
|
3582
3941
|
"name": "glass",
|
|
3583
3942
|
"optional": true,
|
|
3584
3943
|
"type": "boolean | 'subtle' | 'strong'"
|
|
3944
|
+
},
|
|
3945
|
+
{
|
|
3946
|
+
"name": "heading",
|
|
3947
|
+
"optional": true,
|
|
3948
|
+
"type": "string"
|
|
3949
|
+
},
|
|
3950
|
+
{
|
|
3951
|
+
"name": "value",
|
|
3952
|
+
"optional": true,
|
|
3953
|
+
"type": "string"
|
|
3585
3954
|
}
|
|
3586
3955
|
],
|
|
3587
3956
|
"propsExtends": "HTMLAttributes<'figure'>",
|
|
3588
|
-
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'figure'> {\n class?: string | null\n className?: string\n glass?: boolean | 'subtle' | 'strong'\n}\n\nconst {\n class: classProp = '',\n className = '',\n glass = false,\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-chart',\n glass && 'ui-chart--glass',\n glass === 'subtle' && 'ui-glass-subtle',\n glass === 'strong' && 'ui-glass-strong'\n], classProp, className)\n---\n\n<figure\n class:list={classList}\n {...passthrough}\n>\n <slot />\n</figure>\n",
|
|
3957
|
+
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'figure'> {\n caption?: string\n class?: string | null\n className?: string\n description?: string\n glass?: boolean | 'subtle' | 'strong'\n heading?: string\n value?: string\n}\n\nconst {\n caption,\n class: classProp = '',\n className = '',\n description,\n glass = false,\n heading,\n value,\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-chart',\n glass && 'ui-chart--glass',\n glass === 'subtle' && 'ui-glass-subtle',\n glass === 'strong' && 'ui-glass-strong'\n], classProp, className)\n---\n\n<figure\n class:list={classList}\n {...passthrough}\n>\n {\n (heading || description || value || Astro.slots.has('header')) && (\n <header>\n <slot name=\"header\">\n <div class=\"ui-chart__heading\">\n {heading && <h3>{heading}</h3>}\n {description && <p>{description}</p>}\n </div>\n {value && <strong data-ui-chart-value>{value}</strong>}\n </slot>\n <slot name=\"actions\" />\n </header>\n )\n }\n <slot />\n {caption && <figcaption>{caption}</figcaption>}\n</figure>\n",
|
|
3589
3958
|
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
3590
3959
|
},
|
|
3591
3960
|
"elements": {
|
|
3592
3961
|
"attributes": [
|
|
3593
3962
|
"glass",
|
|
3594
3963
|
"children",
|
|
3964
|
+
"heading, description, value",
|
|
3965
|
+
"caption",
|
|
3595
3966
|
"class, className",
|
|
3596
3967
|
"...native attributes"
|
|
3597
3968
|
],
|
|
@@ -3618,14 +3989,34 @@
|
|
|
3618
3989
|
"language": "tsx",
|
|
3619
3990
|
"packageName": "@santi020k/lumen-react",
|
|
3620
3991
|
"props": [
|
|
3992
|
+
{
|
|
3993
|
+
"name": "caption",
|
|
3994
|
+
"optional": true,
|
|
3995
|
+
"type": "ReactNode"
|
|
3996
|
+
},
|
|
3997
|
+
{
|
|
3998
|
+
"name": "description",
|
|
3999
|
+
"optional": true,
|
|
4000
|
+
"type": "ReactNode"
|
|
4001
|
+
},
|
|
3621
4002
|
{
|
|
3622
4003
|
"name": "glass",
|
|
3623
4004
|
"optional": true,
|
|
3624
4005
|
"type": "LumenGlassProp"
|
|
4006
|
+
},
|
|
4007
|
+
{
|
|
4008
|
+
"name": "heading",
|
|
4009
|
+
"optional": true,
|
|
4010
|
+
"type": "ReactNode"
|
|
4011
|
+
},
|
|
4012
|
+
{
|
|
4013
|
+
"name": "value",
|
|
4014
|
+
"optional": true,
|
|
4015
|
+
"type": "ReactNode"
|
|
3625
4016
|
}
|
|
3626
4017
|
],
|
|
3627
4018
|
"propsExtends": "ComponentPropsWithoutRef<'figure'>",
|
|
3628
|
-
"source": "export interface ChartProps extends ComponentPropsWithoutRef<'figure'> {\n glass?: LumenGlassProp\n}\n\nexport const Chart = ({
|
|
4019
|
+
"source": "export interface ChartProps extends ComponentPropsWithoutRef<'figure'> {\n caption?: ReactNode\n description?: ReactNode\n glass?: LumenGlassProp\n heading?: ReactNode\n value?: ReactNode\n}\n\nexport const Chart = ({\n caption,\n children,\n className,\n description,\n glass = false,\n heading,\n value,\n ...props\n}: ChartProps) => (\n <figure className={composeClassName('ui-chart', glassClass('ui-chart', glass), className)} {...props}>\n {(heading || description || value) && (\n <header>\n <div className=\"ui-chart__heading\">\n {heading && <h3>{heading}</h3>}\n {description && <p>{description}</p>}\n </div>\n {value && <strong data-ui-chart-value>{value}</strong>}\n </header>\n )}\n {children}\n {caption && <figcaption>{caption}</figcaption>}\n </figure>\n)",
|
|
3629
4020
|
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
3630
4021
|
}
|
|
3631
4022
|
},
|
|
@@ -3639,21 +4030,39 @@
|
|
|
3639
4030
|
"keyboardInteractions": [],
|
|
3640
4031
|
"keywords": [
|
|
3641
4032
|
"and",
|
|
4033
|
+
"breakdowns",
|
|
3642
4034
|
"captions",
|
|
4035
|
+
"categorical",
|
|
3643
4036
|
"chart",
|
|
4037
|
+
"compact",
|
|
4038
|
+
"comparisons",
|
|
4039
|
+
"custom",
|
|
3644
4040
|
"data",
|
|
3645
4041
|
"display",
|
|
3646
4042
|
"for",
|
|
3647
4043
|
"frames",
|
|
3648
4044
|
"headers",
|
|
3649
4045
|
"lightweight",
|
|
4046
|
+
"match",
|
|
3650
4047
|
"metric",
|
|
4048
|
+
"metrics",
|
|
4049
|
+
"ordered",
|
|
4050
|
+
"part",
|
|
3651
4051
|
"plots",
|
|
4052
|
+
"question",
|
|
3652
4053
|
"svg",
|
|
3653
|
-
"
|
|
4054
|
+
"the",
|
|
4055
|
+
"trends",
|
|
4056
|
+
"visualization",
|
|
4057
|
+
"whole"
|
|
3654
4058
|
],
|
|
3655
4059
|
"name": "Chart",
|
|
3656
4060
|
"props": [
|
|
4061
|
+
{
|
|
4062
|
+
"name": "caption",
|
|
4063
|
+
"optional": true,
|
|
4064
|
+
"type": "string"
|
|
4065
|
+
},
|
|
3657
4066
|
{
|
|
3658
4067
|
"name": "class",
|
|
3659
4068
|
"optional": true,
|
|
@@ -3664,14 +4073,34 @@
|
|
|
3664
4073
|
"optional": true,
|
|
3665
4074
|
"type": "string"
|
|
3666
4075
|
},
|
|
4076
|
+
{
|
|
4077
|
+
"name": "description",
|
|
4078
|
+
"optional": true,
|
|
4079
|
+
"type": "string"
|
|
4080
|
+
},
|
|
3667
4081
|
{
|
|
3668
4082
|
"name": "glass",
|
|
3669
4083
|
"optional": true,
|
|
3670
4084
|
"type": "boolean | 'subtle' | 'strong'"
|
|
4085
|
+
},
|
|
4086
|
+
{
|
|
4087
|
+
"name": "heading",
|
|
4088
|
+
"optional": true,
|
|
4089
|
+
"type": "string"
|
|
4090
|
+
},
|
|
4091
|
+
{
|
|
4092
|
+
"name": "value",
|
|
4093
|
+
"optional": true,
|
|
4094
|
+
"type": "string"
|
|
3671
4095
|
}
|
|
3672
4096
|
],
|
|
3673
4097
|
"propsExtends": "HTMLAttributes<'figure'>",
|
|
3674
|
-
"recipes": [
|
|
4098
|
+
"recipes": [
|
|
4099
|
+
{
|
|
4100
|
+
"name": "data-visualization",
|
|
4101
|
+
"type": "recipe"
|
|
4102
|
+
}
|
|
4103
|
+
],
|
|
3675
4104
|
"runtimeEvents": []
|
|
3676
4105
|
},
|
|
3677
4106
|
{
|
|
@@ -8338,7 +8767,7 @@
|
|
|
8338
8767
|
"values": "HTML attributes"
|
|
8339
8768
|
}
|
|
8340
8769
|
],
|
|
8341
|
-
"astroSource": "---\nimport {\n renderLumenIconSvg,\n resolveLumenAstroProps,\n type LumenIconName\n} from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ntype IconSize = 'default' | 'lg' | 'sm' | 'xl'\n\ninterface Props extends HTMLAttributes<'span'> {\n class?: string | null\n className?: string\n decorative?: boolean\n label?: string\n name?: LumenIconName\n size?: IconSize\n}\n\nconst {\n class: classProp = '',\n className = '',\n decorative,\n label,\n name,\n size = 'default',\n ...rest\n} = Astro.props\n\nconst isDecorative = decorative ?? !label\nconst iconSvg = name ? renderLumenIconSvg(name) : ''\n\nif (name && !iconSvg && import.meta.env.DEV) {\n console.warn(`[Lumen Icon] Unknown
|
|
8770
|
+
"astroSource": "---\nimport {\n renderLumenIconSvg,\n resolveLumenAstroProps,\n type LumenIconName\n} from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ntype IconSize = 'default' | 'lg' | 'sm' | 'xl'\n\ninterface Props extends HTMLAttributes<'span'> {\n class?: string | null\n className?: string\n decorative?: boolean\n label?: string\n name?: LumenIconName\n size?: IconSize\n}\n\nconst {\n class: classProp = '',\n className = '',\n decorative,\n label,\n name,\n size = 'default',\n ...rest\n} = Astro.props\n\nconst isDecorative = decorative ?? !label\nconst iconSvg = name ? renderLumenIconSvg(name) : ''\n\nif (name && !iconSvg && import.meta.env.DEV) {\n console.warn(`[Lumen Icon] Unknown icon \"${name}\". Register an icon pack or use the default slot for project-specific SVGs.`)\n}\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-icon',\n size === 'sm' && 'ui-icon--sm',\n size === 'lg' && 'ui-icon--lg',\n size === 'xl' && 'ui-icon--xl'\n], classProp, className)\n---\n\n<span\n aria-hidden={isDecorative ? 'true' : undefined}\n aria-label={!isDecorative ? label : undefined}\n class:list={classList}\n role={!isDecorative ? 'img' : undefined}\n {...passthrough}\n>\n {name ? <Fragment set:html={iconSvg} /> : <slot />}\n</span>\n",
|
|
8342
8771
|
"category": "Data display",
|
|
8343
8772
|
"collections": [],
|
|
8344
8773
|
"dependencies": [
|
|
@@ -8390,7 +8819,7 @@
|
|
|
8390
8819
|
}
|
|
8391
8820
|
],
|
|
8392
8821
|
"propsExtends": "HTMLAttributes<'span'>",
|
|
8393
|
-
"source": "---\nimport {\n renderLumenIconSvg,\n resolveLumenAstroProps,\n type LumenIconName\n} from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ntype IconSize = 'default' | 'lg' | 'sm' | 'xl'\n\ninterface Props extends HTMLAttributes<'span'> {\n class?: string | null\n className?: string\n decorative?: boolean\n label?: string\n name?: LumenIconName\n size?: IconSize\n}\n\nconst {\n class: classProp = '',\n className = '',\n decorative,\n label,\n name,\n size = 'default',\n ...rest\n} = Astro.props\n\nconst isDecorative = decorative ?? !label\nconst iconSvg = name ? renderLumenIconSvg(name) : ''\n\nif (name && !iconSvg && import.meta.env.DEV) {\n console.warn(`[Lumen Icon] Unknown
|
|
8822
|
+
"source": "---\nimport {\n renderLumenIconSvg,\n resolveLumenAstroProps,\n type LumenIconName\n} from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ntype IconSize = 'default' | 'lg' | 'sm' | 'xl'\n\ninterface Props extends HTMLAttributes<'span'> {\n class?: string | null\n className?: string\n decorative?: boolean\n label?: string\n name?: LumenIconName\n size?: IconSize\n}\n\nconst {\n class: classProp = '',\n className = '',\n decorative,\n label,\n name,\n size = 'default',\n ...rest\n} = Astro.props\n\nconst isDecorative = decorative ?? !label\nconst iconSvg = name ? renderLumenIconSvg(name) : ''\n\nif (name && !iconSvg && import.meta.env.DEV) {\n console.warn(`[Lumen Icon] Unknown icon \"${name}\". Register an icon pack or use the default slot for project-specific SVGs.`)\n}\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-icon',\n size === 'sm' && 'ui-icon--sm',\n size === 'lg' && 'ui-icon--lg',\n size === 'xl' && 'ui-icon--xl'\n], classProp, className)\n---\n\n<span\n aria-hidden={isDecorative ? 'true' : undefined}\n aria-label={!isDecorative ? label : undefined}\n class:list={classList}\n role={!isDecorative ? 'img' : undefined}\n {...passthrough}\n>\n {name ? <Fragment set:html={iconSvg} /> : <slot />}\n</span>\n",
|
|
8394
8823
|
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
8395
8824
|
},
|
|
8396
8825
|
"elements": {
|
|
@@ -9971,10 +10400,46 @@
|
|
|
9971
10400
|
{
|
|
9972
10401
|
"apiReference": [
|
|
9973
10402
|
{
|
|
9974
|
-
"attribute": "
|
|
9975
|
-
"defaultValue": "
|
|
9976
|
-
"description": "
|
|
9977
|
-
"values": "
|
|
10403
|
+
"attribute": "glass",
|
|
10404
|
+
"defaultValue": "false",
|
|
10405
|
+
"description": "Applies the tokenized liquid-glass surface treatment with backdrop-filter fallbacks; \"subtle\" and \"strong\" adjust the fill intensity.",
|
|
10406
|
+
"values": "boolean | \"subtle\" | \"strong\""
|
|
10407
|
+
},
|
|
10408
|
+
{
|
|
10409
|
+
"attribute": "series",
|
|
10410
|
+
"defaultValue": "required",
|
|
10411
|
+
"description": "Provides ordered, already-aggregated points; null y values create visible gaps.",
|
|
10412
|
+
"values": "LumenChartSeries[]"
|
|
10413
|
+
},
|
|
10414
|
+
{
|
|
10415
|
+
"attribute": "area",
|
|
10416
|
+
"defaultValue": "false",
|
|
10417
|
+
"description": "Adds a tokenized fill between each line segment and the zero or domain baseline.",
|
|
10418
|
+
"values": "boolean"
|
|
10419
|
+
},
|
|
10420
|
+
{
|
|
10421
|
+
"attribute": "markers",
|
|
10422
|
+
"defaultValue": "true",
|
|
10423
|
+
"description": "Shows point markers as a second visual cue and exposes per-point SVG titles.",
|
|
10424
|
+
"values": "boolean"
|
|
10425
|
+
},
|
|
10426
|
+
{
|
|
10427
|
+
"attribute": "referenceValue",
|
|
10428
|
+
"defaultValue": "-",
|
|
10429
|
+
"description": "Draws a dashed threshold or comparison line across the plot.",
|
|
10430
|
+
"values": "number"
|
|
10431
|
+
},
|
|
10432
|
+
{
|
|
10433
|
+
"attribute": "showLegend",
|
|
10434
|
+
"defaultValue": "true for multiple series",
|
|
10435
|
+
"description": "Shows the color-independent series key.",
|
|
10436
|
+
"values": "boolean"
|
|
10437
|
+
},
|
|
10438
|
+
{
|
|
10439
|
+
"attribute": "showTable",
|
|
10440
|
+
"defaultValue": "true",
|
|
10441
|
+
"description": "Provides a revealable semantic table containing every plotted value.",
|
|
10442
|
+
"values": "boolean"
|
|
9978
10443
|
},
|
|
9979
10444
|
{
|
|
9980
10445
|
"attribute": "class, className",
|
|
@@ -9989,25 +10454,39 @@
|
|
|
9989
10454
|
"values": "HTML attributes"
|
|
9990
10455
|
}
|
|
9991
10456
|
],
|
|
9992
|
-
"astroSource": "---\nimport {
|
|
10457
|
+
"astroSource": "---\nimport {\n alignLumenChartSeries,\n createLumenLineGeometry,\n getLumenChartCategories,\n getLumenChartDomain,\n getLumenChartTicks,\n hasLumenChartData,\n type LumenChartSeries,\n resolveLumenChartTone,\n scaleLumenChartValue\n} from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\nimport Chart from './Chart.astro'\n\ninterface Props extends HTMLAttributes<'figure'> {\n area?: boolean\n caption?: string\n class?: string | null\n className?: string\n description?: string\n glass?: boolean | 'subtle' | 'strong'\n heading?: string\n markers?: boolean\n referenceValue?: number\n series: readonly LumenChartSeries[]\n showLegend?: boolean\n showTable?: boolean\n}\n\nconst {\n area = false,\n caption,\n class: classProp = '',\n className = '',\n description,\n glass = false,\n heading,\n markers = true,\n referenceValue,\n series,\n showLegend = series.length > 1,\n showTable = true,\n ...rest\n} = Astro.props\nconst width = 640\nconst height = 320\nconst padding = 44\nconst categories = getLumenChartCategories(series)\nconst hasData = hasLumenChartData(series)\nconst alignedSeries = series.map(item => alignLumenChartSeries(item, categories))\nconst domain = getLumenChartDomain([\n ...alignedSeries.flatMap(item => item.data.map(datum => datum.y)),\n referenceValue ?? null\n], false)\nconst geometries = alignedSeries.map(item =>\n createLumenLineGeometry(item.data, {\n domain,\n height,\n includeZero: false,\n padding,\n width\n })\n)\nconst ticks = getLumenChartTicks(domain)\nconst labelStep = Math.max(1, Math.ceil(categories.length / 8))\nconst valueFor = (item: LumenChartSeries, category: number | string) =>\n item.data.find(datum => datum.x === category)\nconst referenceY =\n referenceValue === undefined\n ? undefined\n : scaleLumenChartValue(referenceValue, domain, height - padding, padding)\n---\n\n<Chart\n class:list={['ui-line-chart', classProp, className]}\n {caption}\n {description}\n {glass}\n {heading}\n {...rest}\n>\n {\n showLegend && hasData && (\n <ul class=\"ui-chart__legend\" aria-label=\"Chart legend\">\n {series.map((item, index) => (\n <li class={`ui-chart-tone--${resolveLumenChartTone(item.tone, index)}`}>\n <span aria-hidden=\"true\" />\n {item.label}\n </li>\n ))}\n </ul>\n )\n }\n {!hasData && <p class=\"ui-chart__empty\" role=\"status\">No chart data available.</p>}\n <div class=\"ui-chart__plot\" hidden={!hasData}>\n <svg\n aria-hidden=\"true\"\n preserveAspectRatio=\"xMidYMid meet\"\n viewBox={`0 0 ${width} ${height}`}\n >\n <g class=\"ui-chart__grid\">\n {\n ticks.map((tick) => {\n const y = scaleLumenChartValue(\n tick,\n domain,\n height - padding,\n padding\n )\n\n return (\n <>\n <line x1={padding} x2={width - padding} y1={y} y2={y} />\n <text x={padding - 8} y={y}>\n {Number(tick.toPrecision(4))}\n </text>\n </>\n )\n })\n }\n </g>\n <g class=\"ui-chart__axis-labels\">\n {\n categories.map((category, index) => {\n if (\n index % labelStep !== 0 &&\n index !== categories.length - 1\n )\n return null\n\n const denominator = Math.max(1, categories.length - 1)\n const x =\n padding + (index / denominator) * (width - padding * 2)\n\n return (\n <text text-anchor=\"middle\" x={x} y={height - 14}>\n {String(category)}\n </text>\n )\n })\n }\n </g>\n {\n referenceY !== undefined && (\n <line\n class=\"ui-chart__reference\"\n x1={padding}\n x2={width - padding}\n y1={referenceY}\n y2={referenceY}\n />\n )\n }\n {\n geometries.map((geometry, index) => {\n const item = series[index]\n\n if (!item) return null\n\n const tone = resolveLumenChartTone(item.tone, index)\n\n return (\n <g class={`ui-line-chart__series ui-chart-tone--${tone}`}>\n {area &&\n geometry.areaPaths.map(path => (\n <path class=\"ui-line-chart__area\" d={path} />\n ))}\n <path class=\"ui-line-chart__line\" d={geometry.path} />\n {markers &&\n geometry.points.map(point => (\n <circle\n class=\"ui-line-chart__point\"\n cx={point.xCoordinate}\n cy={point.yCoordinate}\n r=\"3\"\n >\n <title>\n {`${point.label ?? String(point.x)} · ${item.label}: ${point.y}`}\n </title>\n </circle>\n ))}\n </g>\n )\n })\n }\n </svg>\n </div>\n {\n showTable && hasData && (\n <details class=\"ui-chart__data\">\n <summary>View chart data</summary>\n <div>\n <table>\n <thead>\n <tr>\n <th scope=\"col\">Category</th>\n {series.map(item => <th scope=\"col\">{item.label}</th>)}\n </tr>\n </thead>\n <tbody>\n {categories.map(category => (\n <tr>\n <th scope=\"row\">{String(category)}</th>\n {series.map(item => {\n const datum = valueFor(item, category)\n\n return (\n <td>\n {datum?.label ??\n (datum?.y === null || datum === undefined\n ? 'Not available'\n : String(datum.y))}\n </td>\n )\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </details>\n )\n }\n</Chart>\n",
|
|
9993
10458
|
"category": "Data display",
|
|
9994
|
-
"collections": [
|
|
10459
|
+
"collections": [
|
|
10460
|
+
"Data visualization"
|
|
10461
|
+
],
|
|
9995
10462
|
"dependencies": [
|
|
10463
|
+
"Chart",
|
|
9996
10464
|
"styles"
|
|
9997
10465
|
],
|
|
9998
|
-
"description": "
|
|
10466
|
+
"description": "Shows ordered trends, multiple series, missing-value gaps, areas, markers, and reference values.",
|
|
9999
10467
|
"files": [
|
|
10000
|
-
"packages/astro/components/
|
|
10468
|
+
"packages/astro/components/LineChart.astro",
|
|
10469
|
+
"packages/astro/components/Chart.astro",
|
|
10001
10470
|
"packages/astro/styles/lumen.css"
|
|
10002
10471
|
],
|
|
10003
10472
|
"frameworkDetails": {
|
|
10004
10473
|
"astro": {
|
|
10005
10474
|
"available": true,
|
|
10006
|
-
"example": "<
|
|
10007
|
-
"importStatement": "import {
|
|
10475
|
+
"example": "<LineChart aria-label=\"Website traffic\" heading=\"Page views and visits\" series={[{ id: \"views\", label: \"Page views\", data: [{ x: \"Mon\", y: 120 }, { x: \"Tue\", y: 168 }] }, { id: \"visits\", label: \"Visits\", data: [{ x: \"Mon\", y: 82 }, { x: \"Tue\", y: 104 }] }]} />",
|
|
10476
|
+
"importStatement": "import { LineChart } from '@santi020k/lumen-astro'",
|
|
10008
10477
|
"language": "astro",
|
|
10009
10478
|
"packageName": "@santi020k/lumen-astro",
|
|
10010
10479
|
"props": [
|
|
10480
|
+
{
|
|
10481
|
+
"name": "area",
|
|
10482
|
+
"optional": true,
|
|
10483
|
+
"type": "boolean"
|
|
10484
|
+
},
|
|
10485
|
+
{
|
|
10486
|
+
"name": "caption",
|
|
10487
|
+
"optional": true,
|
|
10488
|
+
"type": "string"
|
|
10489
|
+
},
|
|
10011
10490
|
{
|
|
10012
10491
|
"name": "class",
|
|
10013
10492
|
"optional": true,
|
|
@@ -10019,18 +10498,59 @@
|
|
|
10019
10498
|
"type": "string"
|
|
10020
10499
|
},
|
|
10021
10500
|
{
|
|
10022
|
-
"name": "
|
|
10501
|
+
"name": "description",
|
|
10023
10502
|
"optional": true,
|
|
10024
|
-
"type": "
|
|
10503
|
+
"type": "string"
|
|
10504
|
+
},
|
|
10505
|
+
{
|
|
10506
|
+
"name": "glass",
|
|
10507
|
+
"optional": true,
|
|
10508
|
+
"type": "boolean | 'subtle' | 'strong'"
|
|
10509
|
+
},
|
|
10510
|
+
{
|
|
10511
|
+
"name": "heading",
|
|
10512
|
+
"optional": true,
|
|
10513
|
+
"type": "string"
|
|
10514
|
+
},
|
|
10515
|
+
{
|
|
10516
|
+
"name": "markers",
|
|
10517
|
+
"optional": true,
|
|
10518
|
+
"type": "boolean"
|
|
10519
|
+
},
|
|
10520
|
+
{
|
|
10521
|
+
"name": "referenceValue",
|
|
10522
|
+
"optional": true,
|
|
10523
|
+
"type": "number"
|
|
10524
|
+
},
|
|
10525
|
+
{
|
|
10526
|
+
"name": "series",
|
|
10527
|
+
"optional": false,
|
|
10528
|
+
"type": "readonly LumenChartSeries[]"
|
|
10529
|
+
},
|
|
10530
|
+
{
|
|
10531
|
+
"name": "showLegend",
|
|
10532
|
+
"optional": true,
|
|
10533
|
+
"type": "boolean"
|
|
10534
|
+
},
|
|
10535
|
+
{
|
|
10536
|
+
"name": "showTable",
|
|
10537
|
+
"optional": true,
|
|
10538
|
+
"type": "boolean"
|
|
10025
10539
|
}
|
|
10026
10540
|
],
|
|
10027
|
-
"propsExtends": "HTMLAttributes<'
|
|
10028
|
-
"source": "---\nimport {
|
|
10541
|
+
"propsExtends": "HTMLAttributes<'figure'>",
|
|
10542
|
+
"source": "---\nimport {\n alignLumenChartSeries,\n createLumenLineGeometry,\n getLumenChartCategories,\n getLumenChartDomain,\n getLumenChartTicks,\n hasLumenChartData,\n type LumenChartSeries,\n resolveLumenChartTone,\n scaleLumenChartValue\n} from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\nimport Chart from './Chart.astro'\n\ninterface Props extends HTMLAttributes<'figure'> {\n area?: boolean\n caption?: string\n class?: string | null\n className?: string\n description?: string\n glass?: boolean | 'subtle' | 'strong'\n heading?: string\n markers?: boolean\n referenceValue?: number\n series: readonly LumenChartSeries[]\n showLegend?: boolean\n showTable?: boolean\n}\n\nconst {\n area = false,\n caption,\n class: classProp = '',\n className = '',\n description,\n glass = false,\n heading,\n markers = true,\n referenceValue,\n series,\n showLegend = series.length > 1,\n showTable = true,\n ...rest\n} = Astro.props\nconst width = 640\nconst height = 320\nconst padding = 44\nconst categories = getLumenChartCategories(series)\nconst hasData = hasLumenChartData(series)\nconst alignedSeries = series.map(item => alignLumenChartSeries(item, categories))\nconst domain = getLumenChartDomain([\n ...alignedSeries.flatMap(item => item.data.map(datum => datum.y)),\n referenceValue ?? null\n], false)\nconst geometries = alignedSeries.map(item =>\n createLumenLineGeometry(item.data, {\n domain,\n height,\n includeZero: false,\n padding,\n width\n })\n)\nconst ticks = getLumenChartTicks(domain)\nconst labelStep = Math.max(1, Math.ceil(categories.length / 8))\nconst valueFor = (item: LumenChartSeries, category: number | string) =>\n item.data.find(datum => datum.x === category)\nconst referenceY =\n referenceValue === undefined\n ? undefined\n : scaleLumenChartValue(referenceValue, domain, height - padding, padding)\n---\n\n<Chart\n class:list={['ui-line-chart', classProp, className]}\n {caption}\n {description}\n {glass}\n {heading}\n {...rest}\n>\n {\n showLegend && hasData && (\n <ul class=\"ui-chart__legend\" aria-label=\"Chart legend\">\n {series.map((item, index) => (\n <li class={`ui-chart-tone--${resolveLumenChartTone(item.tone, index)}`}>\n <span aria-hidden=\"true\" />\n {item.label}\n </li>\n ))}\n </ul>\n )\n }\n {!hasData && <p class=\"ui-chart__empty\" role=\"status\">No chart data available.</p>}\n <div class=\"ui-chart__plot\" hidden={!hasData}>\n <svg\n aria-hidden=\"true\"\n preserveAspectRatio=\"xMidYMid meet\"\n viewBox={`0 0 ${width} ${height}`}\n >\n <g class=\"ui-chart__grid\">\n {\n ticks.map((tick) => {\n const y = scaleLumenChartValue(\n tick,\n domain,\n height - padding,\n padding\n )\n\n return (\n <>\n <line x1={padding} x2={width - padding} y1={y} y2={y} />\n <text x={padding - 8} y={y}>\n {Number(tick.toPrecision(4))}\n </text>\n </>\n )\n })\n }\n </g>\n <g class=\"ui-chart__axis-labels\">\n {\n categories.map((category, index) => {\n if (\n index % labelStep !== 0 &&\n index !== categories.length - 1\n )\n return null\n\n const denominator = Math.max(1, categories.length - 1)\n const x =\n padding + (index / denominator) * (width - padding * 2)\n\n return (\n <text text-anchor=\"middle\" x={x} y={height - 14}>\n {String(category)}\n </text>\n )\n })\n }\n </g>\n {\n referenceY !== undefined && (\n <line\n class=\"ui-chart__reference\"\n x1={padding}\n x2={width - padding}\n y1={referenceY}\n y2={referenceY}\n />\n )\n }\n {\n geometries.map((geometry, index) => {\n const item = series[index]\n\n if (!item) return null\n\n const tone = resolveLumenChartTone(item.tone, index)\n\n return (\n <g class={`ui-line-chart__series ui-chart-tone--${tone}`}>\n {area &&\n geometry.areaPaths.map(path => (\n <path class=\"ui-line-chart__area\" d={path} />\n ))}\n <path class=\"ui-line-chart__line\" d={geometry.path} />\n {markers &&\n geometry.points.map(point => (\n <circle\n class=\"ui-line-chart__point\"\n cx={point.xCoordinate}\n cy={point.yCoordinate}\n r=\"3\"\n >\n <title>\n {`${point.label ?? String(point.x)} · ${item.label}: ${point.y}`}\n </title>\n </circle>\n ))}\n </g>\n )\n })\n }\n </svg>\n </div>\n {\n showTable && hasData && (\n <details class=\"ui-chart__data\">\n <summary>View chart data</summary>\n <div>\n <table>\n <thead>\n <tr>\n <th scope=\"col\">Category</th>\n {series.map(item => <th scope=\"col\">{item.label}</th>)}\n </tr>\n </thead>\n <tbody>\n {categories.map(category => (\n <tr>\n <th scope=\"row\">{String(category)}</th>\n {series.map(item => {\n const datum = valueFor(item, category)\n\n return (\n <td>\n {datum?.label ??\n (datum?.y === null || datum === undefined\n ? 'Not available'\n : String(datum.y))}\n </td>\n )\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </details>\n )\n }\n</Chart>\n",
|
|
10029
10543
|
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
10030
10544
|
},
|
|
10031
10545
|
"elements": {
|
|
10032
10546
|
"attributes": [
|
|
10033
|
-
"
|
|
10547
|
+
"glass",
|
|
10548
|
+
"series",
|
|
10549
|
+
"area",
|
|
10550
|
+
"markers",
|
|
10551
|
+
"referenceValue",
|
|
10552
|
+
"showLegend",
|
|
10553
|
+
"showTable",
|
|
10034
10554
|
"class, className",
|
|
10035
10555
|
"...native attributes"
|
|
10036
10556
|
],
|
|
@@ -10039,32 +10559,57 @@
|
|
|
10039
10559
|
"mode": "registration",
|
|
10040
10560
|
"setup": "Call defineLumenElements() once before rendering Lumen custom elements."
|
|
10041
10561
|
},
|
|
10042
|
-
"example": "<lumen-
|
|
10562
|
+
"example": "<lumen-line-chart></lumen-line-chart>",
|
|
10043
10563
|
"importStatement": "import { defineLumenElements } from '@santi020k/lumen-elements/define'",
|
|
10044
10564
|
"language": "html",
|
|
10045
10565
|
"packageName": "@santi020k/lumen-elements",
|
|
10046
10566
|
"props": [],
|
|
10047
10567
|
"propsExtends": "HTMLElement attributes",
|
|
10048
10568
|
"registration": "defineLumenElements()",
|
|
10049
|
-
"source": "
|
|
10569
|
+
"source": "LineChart: {\n attributeClasses: glassAttributeClasses('ui-chart--glass'),\n baseClassName: 'ui-chart ui-line-chart',\n role: 'figure',\n tagName: 'lumen-line-chart'\n }",
|
|
10050
10570
|
"styleImport": "import '@santi020k/lumen-elements/styles.css'",
|
|
10051
|
-
"tagName": "lumen-
|
|
10571
|
+
"tagName": "lumen-line-chart"
|
|
10052
10572
|
},
|
|
10053
10573
|
"react": {
|
|
10054
10574
|
"available": true,
|
|
10055
|
-
"example": "<
|
|
10056
|
-
"importStatement": "import {
|
|
10575
|
+
"example": "<LineChart aria-label=\"Website traffic\" heading=\"Page views and visits\" series={[{ id: \"views\", label: \"Page views\", data: [{ x: \"Mon\", y: 120 }, { x: \"Tue\", y: 168 }] }, { id: \"visits\", label: \"Visits\", data: [{ x: \"Mon\", y: 82 }, { x: \"Tue\", y: 104 }] }]} />",
|
|
10576
|
+
"importStatement": "import { LineChart } from '@santi020k/lumen-react'",
|
|
10057
10577
|
"language": "tsx",
|
|
10058
10578
|
"packageName": "@santi020k/lumen-react",
|
|
10059
10579
|
"props": [
|
|
10060
10580
|
{
|
|
10061
|
-
"name": "
|
|
10581
|
+
"name": "area",
|
|
10062
10582
|
"optional": true,
|
|
10063
|
-
"type": "
|
|
10583
|
+
"type": "boolean"
|
|
10584
|
+
},
|
|
10585
|
+
{
|
|
10586
|
+
"name": "markers",
|
|
10587
|
+
"optional": true,
|
|
10588
|
+
"type": "boolean"
|
|
10589
|
+
},
|
|
10590
|
+
{
|
|
10591
|
+
"name": "referenceValue",
|
|
10592
|
+
"optional": true,
|
|
10593
|
+
"type": "number"
|
|
10594
|
+
},
|
|
10595
|
+
{
|
|
10596
|
+
"name": "series",
|
|
10597
|
+
"optional": true,
|
|
10598
|
+
"type": "readonly LumenChartSeries[]"
|
|
10599
|
+
},
|
|
10600
|
+
{
|
|
10601
|
+
"name": "showLegend",
|
|
10602
|
+
"optional": true,
|
|
10603
|
+
"type": "boolean"
|
|
10604
|
+
},
|
|
10605
|
+
{
|
|
10606
|
+
"name": "showTable",
|
|
10607
|
+
"optional": true,
|
|
10608
|
+
"type": "boolean"
|
|
10064
10609
|
}
|
|
10065
10610
|
],
|
|
10066
|
-
"propsExtends": "
|
|
10067
|
-
"source": "export interface
|
|
10611
|
+
"propsExtends": "Omit<ChartProps, 'children'>",
|
|
10612
|
+
"source": "export interface LineChartProps extends Omit<ChartProps, 'children'> {\n area?: boolean\n markers?: boolean\n referenceValue?: number\n series?: readonly LumenChartSeries[]\n showLegend?: boolean\n showTable?: boolean\n}\n\nexport const LineChart = ({\n area = false,\n className,\n markers = true,\n referenceValue,\n series = emptyChartSeries,\n showLegend = series.length > 1,\n showTable = true,\n ...props\n}: LineChartProps) => {\n const width = 640\n const height = 320\n const padding = 44\n const categories = getLumenChartCategories(series)\n const hasData = hasLumenChartData(series)\n const alignedSeries = series.map(item => alignLumenChartSeries(item, categories))\n\n const domain = getLumenChartDomain([\n ...alignedSeries.flatMap(item => item.data.map(datum => datum.y)),\n referenceValue ?? null\n ], false)\n\n const geometries = alignedSeries.map(item =>\n createLumenLineGeometry(item.data, {\n domain,\n height,\n includeZero: false,\n padding,\n width\n })\n )\n\n const ticks = getLumenChartTicks(domain)\n const labelStep = Math.max(1, Math.ceil(categories.length / 8))\n\n const referenceY = referenceValue === undefined\n ? undefined\n : scaleLumenChartValue(referenceValue, domain, height - padding, padding)\n\n return (\n <Chart className={composeClassName('ui-line-chart', className)} {...props}>\n {showLegend && hasData && <ChartLegend series={series} />}\n {!hasData && (\n <p className=\"ui-chart__empty\" role=\"status\">No chart data available.</p>\n )}\n <div className=\"ui-chart__plot\" hidden={!hasData}>\n <svg\n aria-hidden=\"true\"\n preserveAspectRatio=\"xMidYMid meet\"\n viewBox={`0 0 ${width} ${height}`}\n >\n <g className=\"ui-chart__grid\">\n {ticks.map(tick => {\n const y = scaleLumenChartValue(tick, domain, height - padding, padding)\n\n return (\n <Fragment key={tick}>\n <line x1={padding} x2={width - padding} y1={y} y2={y} />\n <text x={padding - 8} y={y}>{Number(tick.toPrecision(4))}</text>\n </Fragment>\n )\n })}\n </g>\n <g className=\"ui-chart__axis-labels\">\n {categories.map((category, index) => {\n if (index % labelStep !== 0 && index !== categories.length - 1) return null\n\n const denominator = Math.max(1, categories.length - 1)\n const x = padding + (index / denominator) * (width - padding * 2)\n\n return (\n <text\n key={`${typeof category}:${String(category)}`}\n textAnchor=\"middle\"\n x={x}\n y={height - 14}\n >\n {String(category)}\n </text>\n )\n })}\n </g>\n {referenceY !== undefined && (\n <line\n className=\"ui-chart__reference\"\n x1={padding}\n x2={width - padding}\n y1={referenceY}\n y2={referenceY}\n />\n )}\n {geometries.map((geometry, index) => {\n const item = series[index]\n\n if (!item) return null\n\n const tone = resolveLumenChartTone(item.tone, index)\n\n return (\n <g\n className={`ui-line-chart__series ui-chart-tone--${tone}`}\n key={item.id}\n >\n {area && geometry.areaPaths.map(path => (\n <path className=\"ui-line-chart__area\" d={path} key={path} />\n ))}\n <path className=\"ui-line-chart__line\" d={geometry.path} />\n {markers && geometry.points.map(point => (\n <circle\n className=\"ui-line-chart__point\"\n cx={point.xCoordinate}\n cy={point.yCoordinate}\n key={`${typeof point.x}:${String(point.x)}`}\n r=\"3\"\n >\n <title>\n {`${point.label ?? String(point.x)} · ${item.label}: ${String(point.y)}`}\n </title>\n </circle>\n ))}\n </g>\n )\n })}\n </svg>\n </div>\n {showTable && hasData && (\n <ChartDataTable categories={categories} series={series} />\n )}\n </Chart>\n )\n}",
|
|
10068
10613
|
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
10069
10614
|
}
|
|
10070
10615
|
},
|
|
@@ -10074,43 +10619,71 @@
|
|
|
10074
10619
|
"react": true
|
|
10075
10620
|
},
|
|
10076
10621
|
"guidance": {
|
|
10077
|
-
"when": "Use
|
|
10078
|
-
"distinction": "Use
|
|
10622
|
+
"when": "Use to show how one or more ordered series change, including missing values and thresholds.",
|
|
10623
|
+
"distinction": "Use BarChart for categorical magnitude comparisons and Sparkline when axes and exact values are unnecessary."
|
|
10079
10624
|
},
|
|
10080
|
-
"kebab": "
|
|
10625
|
+
"kebab": "line-chart",
|
|
10081
10626
|
"keyboardInteractions": [],
|
|
10082
10627
|
"keywords": [
|
|
10083
10628
|
"and",
|
|
10084
|
-
"
|
|
10085
|
-
"
|
|
10086
|
-
"
|
|
10087
|
-
"
|
|
10629
|
+
"are",
|
|
10630
|
+
"areas",
|
|
10631
|
+
"axes",
|
|
10632
|
+
"barchart",
|
|
10633
|
+
"breakdowns",
|
|
10634
|
+
"categorical",
|
|
10635
|
+
"change",
|
|
10088
10636
|
"compact",
|
|
10089
|
-
"
|
|
10637
|
+
"comparisons",
|
|
10638
|
+
"custom",
|
|
10090
10639
|
"data",
|
|
10091
10640
|
"display",
|
|
10092
|
-
"
|
|
10093
|
-
"filled",
|
|
10641
|
+
"exact",
|
|
10094
10642
|
"for",
|
|
10095
|
-
"
|
|
10096
|
-
"
|
|
10097
|
-
"
|
|
10098
|
-
"
|
|
10099
|
-
"
|
|
10100
|
-
"
|
|
10101
|
-
"
|
|
10102
|
-
"
|
|
10103
|
-
"
|
|
10104
|
-
"
|
|
10105
|
-
"
|
|
10643
|
+
"gaps",
|
|
10644
|
+
"how",
|
|
10645
|
+
"including",
|
|
10646
|
+
"linechart",
|
|
10647
|
+
"magnitude",
|
|
10648
|
+
"markers",
|
|
10649
|
+
"match",
|
|
10650
|
+
"metrics",
|
|
10651
|
+
"missing",
|
|
10652
|
+
"more",
|
|
10653
|
+
"multiple",
|
|
10654
|
+
"one",
|
|
10655
|
+
"ordered",
|
|
10656
|
+
"part",
|
|
10657
|
+
"plots",
|
|
10658
|
+
"question",
|
|
10659
|
+
"reference",
|
|
10660
|
+
"series",
|
|
10661
|
+
"show",
|
|
10662
|
+
"shows",
|
|
10663
|
+
"sparkline",
|
|
10106
10664
|
"the",
|
|
10665
|
+
"thresholds",
|
|
10666
|
+
"trends",
|
|
10667
|
+
"unnecessary",
|
|
10107
10668
|
"use",
|
|
10108
|
-
"
|
|
10109
|
-
"
|
|
10110
|
-
"
|
|
10669
|
+
"value",
|
|
10670
|
+
"values",
|
|
10671
|
+
"visualization",
|
|
10672
|
+
"when",
|
|
10673
|
+
"whole"
|
|
10111
10674
|
],
|
|
10112
|
-
"name": "
|
|
10675
|
+
"name": "LineChart",
|
|
10113
10676
|
"props": [
|
|
10677
|
+
{
|
|
10678
|
+
"name": "area",
|
|
10679
|
+
"optional": true,
|
|
10680
|
+
"type": "boolean"
|
|
10681
|
+
},
|
|
10682
|
+
{
|
|
10683
|
+
"name": "caption",
|
|
10684
|
+
"optional": true,
|
|
10685
|
+
"type": "string"
|
|
10686
|
+
},
|
|
10114
10687
|
{
|
|
10115
10688
|
"name": "class",
|
|
10116
10689
|
"optional": true,
|
|
@@ -10122,37 +10695,240 @@
|
|
|
10122
10695
|
"type": "string"
|
|
10123
10696
|
},
|
|
10124
10697
|
{
|
|
10125
|
-
"name": "
|
|
10698
|
+
"name": "description",
|
|
10126
10699
|
"optional": true,
|
|
10127
|
-
"type": "
|
|
10128
|
-
}
|
|
10129
|
-
],
|
|
10130
|
-
"propsExtends": "HTMLAttributes<'span'>",
|
|
10131
|
-
"recipes": [],
|
|
10132
|
-
"runtimeEvents": []
|
|
10133
|
-
},
|
|
10134
|
-
{
|
|
10135
|
-
"apiReference": [
|
|
10136
|
-
{
|
|
10137
|
-
"attribute": "glass",
|
|
10138
|
-
"defaultValue": "false",
|
|
10139
|
-
"description": "Applies the tokenized liquid-glass surface treatment with backdrop-filter fallbacks; \"subtle\" and \"strong\" adjust the fill intensity.",
|
|
10140
|
-
"values": "boolean | \"subtle\" | \"strong\""
|
|
10700
|
+
"type": "string"
|
|
10141
10701
|
},
|
|
10142
10702
|
{
|
|
10143
|
-
"
|
|
10144
|
-
"
|
|
10145
|
-
"
|
|
10146
|
-
"values": "\"default\" | \"glass\""
|
|
10703
|
+
"name": "glass",
|
|
10704
|
+
"optional": true,
|
|
10705
|
+
"type": "boolean | 'subtle' | 'strong'"
|
|
10147
10706
|
},
|
|
10148
10707
|
{
|
|
10149
|
-
"
|
|
10150
|
-
"
|
|
10151
|
-
"
|
|
10152
|
-
"values": "string"
|
|
10708
|
+
"name": "heading",
|
|
10709
|
+
"optional": true,
|
|
10710
|
+
"type": "string"
|
|
10153
10711
|
},
|
|
10154
10712
|
{
|
|
10155
|
-
"
|
|
10713
|
+
"name": "markers",
|
|
10714
|
+
"optional": true,
|
|
10715
|
+
"type": "boolean"
|
|
10716
|
+
},
|
|
10717
|
+
{
|
|
10718
|
+
"name": "referenceValue",
|
|
10719
|
+
"optional": true,
|
|
10720
|
+
"type": "number"
|
|
10721
|
+
},
|
|
10722
|
+
{
|
|
10723
|
+
"name": "series",
|
|
10724
|
+
"optional": false,
|
|
10725
|
+
"type": "readonly LumenChartSeries[]"
|
|
10726
|
+
},
|
|
10727
|
+
{
|
|
10728
|
+
"name": "showLegend",
|
|
10729
|
+
"optional": true,
|
|
10730
|
+
"type": "boolean"
|
|
10731
|
+
},
|
|
10732
|
+
{
|
|
10733
|
+
"name": "showTable",
|
|
10734
|
+
"optional": true,
|
|
10735
|
+
"type": "boolean"
|
|
10736
|
+
}
|
|
10737
|
+
],
|
|
10738
|
+
"propsExtends": "HTMLAttributes<'figure'>",
|
|
10739
|
+
"recipes": [
|
|
10740
|
+
{
|
|
10741
|
+
"name": "data-visualization",
|
|
10742
|
+
"type": "recipe"
|
|
10743
|
+
}
|
|
10744
|
+
],
|
|
10745
|
+
"runtimeEvents": []
|
|
10746
|
+
},
|
|
10747
|
+
{
|
|
10748
|
+
"apiReference": [
|
|
10749
|
+
{
|
|
10750
|
+
"attribute": "variant",
|
|
10751
|
+
"defaultValue": "\"default\"",
|
|
10752
|
+
"description": "Controls the marker tone.",
|
|
10753
|
+
"values": "\"default\" | \"success\" | \"warning\" | \"danger\""
|
|
10754
|
+
},
|
|
10755
|
+
{
|
|
10756
|
+
"attribute": "class, className",
|
|
10757
|
+
"defaultValue": "\"\"",
|
|
10758
|
+
"description": "Merges custom classes with the generated ui-* root classes.",
|
|
10759
|
+
"values": "string"
|
|
10760
|
+
},
|
|
10761
|
+
{
|
|
10762
|
+
"attribute": "...native attributes",
|
|
10763
|
+
"defaultValue": "-",
|
|
10764
|
+
"description": "Forwards standard attributes to the root element unless the component consumes them.",
|
|
10765
|
+
"values": "HTML attributes"
|
|
10766
|
+
}
|
|
10767
|
+
],
|
|
10768
|
+
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'span'> {\n class?: string | null\n className?: string\n variant?: 'default' | 'success' | 'warning' | 'danger'\n}\n\nconst {\n class: classProp = '',\n className = '',\n variant = 'default',\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-marker',\n variant === 'success' && 'ui-marker--success',\n variant === 'warning' && 'ui-marker--warning',\n variant === 'danger' && 'ui-marker--danger'\n], classProp, className)\n---\n\n<span\n data-variant={variant}\n class:list={classList}\n {...passthrough}\n>\n <slot />\n</span>\n",
|
|
10769
|
+
"category": "Data display",
|
|
10770
|
+
"collections": [],
|
|
10771
|
+
"dependencies": [
|
|
10772
|
+
"styles"
|
|
10773
|
+
],
|
|
10774
|
+
"description": "Highlights status, position, or annotations.",
|
|
10775
|
+
"files": [
|
|
10776
|
+
"packages/astro/components/Marker.astro",
|
|
10777
|
+
"packages/astro/styles/lumen.css"
|
|
10778
|
+
],
|
|
10779
|
+
"frameworkDetails": {
|
|
10780
|
+
"astro": {
|
|
10781
|
+
"available": true,
|
|
10782
|
+
"example": "<Marker variant=\"success\">Live</Marker>",
|
|
10783
|
+
"importStatement": "import { Marker } from '@santi020k/lumen-astro'",
|
|
10784
|
+
"language": "astro",
|
|
10785
|
+
"packageName": "@santi020k/lumen-astro",
|
|
10786
|
+
"props": [
|
|
10787
|
+
{
|
|
10788
|
+
"name": "class",
|
|
10789
|
+
"optional": true,
|
|
10790
|
+
"type": "string | null"
|
|
10791
|
+
},
|
|
10792
|
+
{
|
|
10793
|
+
"name": "className",
|
|
10794
|
+
"optional": true,
|
|
10795
|
+
"type": "string"
|
|
10796
|
+
},
|
|
10797
|
+
{
|
|
10798
|
+
"name": "variant",
|
|
10799
|
+
"optional": true,
|
|
10800
|
+
"type": "'default' | 'success' | 'warning' | 'danger'"
|
|
10801
|
+
}
|
|
10802
|
+
],
|
|
10803
|
+
"propsExtends": "HTMLAttributes<'span'>",
|
|
10804
|
+
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'span'> {\n class?: string | null\n className?: string\n variant?: 'default' | 'success' | 'warning' | 'danger'\n}\n\nconst {\n class: classProp = '',\n className = '',\n variant = 'default',\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-marker',\n variant === 'success' && 'ui-marker--success',\n variant === 'warning' && 'ui-marker--warning',\n variant === 'danger' && 'ui-marker--danger'\n], classProp, className)\n---\n\n<span\n data-variant={variant}\n class:list={classList}\n {...passthrough}\n>\n <slot />\n</span>\n",
|
|
10805
|
+
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
10806
|
+
},
|
|
10807
|
+
"elements": {
|
|
10808
|
+
"attributes": [
|
|
10809
|
+
"variant",
|
|
10810
|
+
"class, className",
|
|
10811
|
+
"...native attributes"
|
|
10812
|
+
],
|
|
10813
|
+
"available": true,
|
|
10814
|
+
"behavior": {
|
|
10815
|
+
"mode": "registration",
|
|
10816
|
+
"setup": "Call defineLumenElements() once before rendering Lumen custom elements."
|
|
10817
|
+
},
|
|
10818
|
+
"example": "<lumen-marker variant=\"success\">Live</lumen-marker>",
|
|
10819
|
+
"importStatement": "import { defineLumenElements } from '@santi020k/lumen-elements/define'",
|
|
10820
|
+
"language": "html",
|
|
10821
|
+
"packageName": "@santi020k/lumen-elements",
|
|
10822
|
+
"props": [],
|
|
10823
|
+
"propsExtends": "HTMLElement attributes",
|
|
10824
|
+
"registration": "defineLumenElements()",
|
|
10825
|
+
"source": "Marker: {\n attributeClasses: {\n variant: {\n danger: 'ui-marker--danger',\n success: 'ui-marker--success',\n warning: 'ui-marker--warning'\n }\n },\n baseClassName: 'ui-marker',\n defaults: { variant: 'default' },\n tagName: 'lumen-marker'\n }",
|
|
10826
|
+
"styleImport": "import '@santi020k/lumen-elements/styles.css'",
|
|
10827
|
+
"tagName": "lumen-marker"
|
|
10828
|
+
},
|
|
10829
|
+
"react": {
|
|
10830
|
+
"available": true,
|
|
10831
|
+
"example": "<Marker variant=\"success\">Live</Marker>",
|
|
10832
|
+
"importStatement": "import { Marker } from '@santi020k/lumen-react'",
|
|
10833
|
+
"language": "tsx",
|
|
10834
|
+
"packageName": "@santi020k/lumen-react",
|
|
10835
|
+
"props": [
|
|
10836
|
+
{
|
|
10837
|
+
"name": "variant",
|
|
10838
|
+
"optional": true,
|
|
10839
|
+
"type": "MarkerVariant"
|
|
10840
|
+
}
|
|
10841
|
+
],
|
|
10842
|
+
"propsExtends": "ComponentPropsWithoutRef<'span'>",
|
|
10843
|
+
"source": "export interface MarkerProps extends ComponentPropsWithoutRef<'span'> {\n variant?: MarkerVariant\n}\n\nexport const Marker = ({ className, variant = 'default', ...props }: MarkerProps) => (\n <span\n className={composeClassName('ui-marker', variantClass('ui-marker', variant), className)}\n data-variant={variant}\n {...props}\n />\n)",
|
|
10844
|
+
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
10845
|
+
}
|
|
10846
|
+
},
|
|
10847
|
+
"frameworks": {
|
|
10848
|
+
"astro": true,
|
|
10849
|
+
"elements": true,
|
|
10850
|
+
"react": true
|
|
10851
|
+
},
|
|
10852
|
+
"guidance": {
|
|
10853
|
+
"when": "Use for compact operational status where a colored dot should carry the visual signal.",
|
|
10854
|
+
"distinction": "Use Badge for a filled metadata label and Pill for a label paired with a count."
|
|
10855
|
+
},
|
|
10856
|
+
"kebab": "marker",
|
|
10857
|
+
"keyboardInteractions": [],
|
|
10858
|
+
"keywords": [
|
|
10859
|
+
"and",
|
|
10860
|
+
"annotations",
|
|
10861
|
+
"badge",
|
|
10862
|
+
"carry",
|
|
10863
|
+
"colored",
|
|
10864
|
+
"compact",
|
|
10865
|
+
"count",
|
|
10866
|
+
"data",
|
|
10867
|
+
"display",
|
|
10868
|
+
"dot",
|
|
10869
|
+
"filled",
|
|
10870
|
+
"for",
|
|
10871
|
+
"highlights",
|
|
10872
|
+
"label",
|
|
10873
|
+
"marker",
|
|
10874
|
+
"metadata",
|
|
10875
|
+
"operational",
|
|
10876
|
+
"paired",
|
|
10877
|
+
"pill",
|
|
10878
|
+
"position",
|
|
10879
|
+
"should",
|
|
10880
|
+
"signal",
|
|
10881
|
+
"status",
|
|
10882
|
+
"the",
|
|
10883
|
+
"use",
|
|
10884
|
+
"visual",
|
|
10885
|
+
"where",
|
|
10886
|
+
"with"
|
|
10887
|
+
],
|
|
10888
|
+
"name": "Marker",
|
|
10889
|
+
"props": [
|
|
10890
|
+
{
|
|
10891
|
+
"name": "class",
|
|
10892
|
+
"optional": true,
|
|
10893
|
+
"type": "string | null"
|
|
10894
|
+
},
|
|
10895
|
+
{
|
|
10896
|
+
"name": "className",
|
|
10897
|
+
"optional": true,
|
|
10898
|
+
"type": "string"
|
|
10899
|
+
},
|
|
10900
|
+
{
|
|
10901
|
+
"name": "variant",
|
|
10902
|
+
"optional": true,
|
|
10903
|
+
"type": "'default' | 'success' | 'warning' | 'danger'"
|
|
10904
|
+
}
|
|
10905
|
+
],
|
|
10906
|
+
"propsExtends": "HTMLAttributes<'span'>",
|
|
10907
|
+
"recipes": [],
|
|
10908
|
+
"runtimeEvents": []
|
|
10909
|
+
},
|
|
10910
|
+
{
|
|
10911
|
+
"apiReference": [
|
|
10912
|
+
{
|
|
10913
|
+
"attribute": "glass",
|
|
10914
|
+
"defaultValue": "false",
|
|
10915
|
+
"description": "Applies the tokenized liquid-glass surface treatment with backdrop-filter fallbacks; \"subtle\" and \"strong\" adjust the fill intensity.",
|
|
10916
|
+
"values": "boolean | \"subtle\" | \"strong\""
|
|
10917
|
+
},
|
|
10918
|
+
{
|
|
10919
|
+
"attribute": "surface",
|
|
10920
|
+
"defaultValue": "\"default\"",
|
|
10921
|
+
"description": "Deprecated alias for glass; surface=\"glass\" maps to glass={true}.",
|
|
10922
|
+
"values": "\"default\" | \"glass\""
|
|
10923
|
+
},
|
|
10924
|
+
{
|
|
10925
|
+
"attribute": "class, className",
|
|
10926
|
+
"defaultValue": "\"\"",
|
|
10927
|
+
"description": "Merges custom classes with the generated ui-* root classes.",
|
|
10928
|
+
"values": "string"
|
|
10929
|
+
},
|
|
10930
|
+
{
|
|
10931
|
+
"attribute": "...native attributes",
|
|
10156
10932
|
"defaultValue": "-",
|
|
10157
10933
|
"description": "Forwards standard attributes to the root element unless the component consumes them.",
|
|
10158
10934
|
"values": "HTML attributes"
|
|
@@ -11519,23 +12295,340 @@
|
|
|
11519
12295
|
"type": "string"
|
|
11520
12296
|
},
|
|
11521
12297
|
{
|
|
11522
|
-
"name": "name",
|
|
12298
|
+
"name": "name",
|
|
12299
|
+
"optional": true,
|
|
12300
|
+
"type": "string"
|
|
12301
|
+
},
|
|
12302
|
+
{
|
|
12303
|
+
"name": "placeholder",
|
|
12304
|
+
"optional": true,
|
|
12305
|
+
"type": "string"
|
|
12306
|
+
},
|
|
12307
|
+
{
|
|
12308
|
+
"name": "size",
|
|
12309
|
+
"optional": true,
|
|
12310
|
+
"type": "'default' | 'lg' | 'sm'"
|
|
12311
|
+
}
|
|
12312
|
+
],
|
|
12313
|
+
"propsExtends": "Omit<ComponentPropsWithoutRef<'div'>, 'defaultValue'>",
|
|
12314
|
+
"source": "export interface PhoneInputProps extends Omit<ComponentPropsWithoutRef<'div'>, 'defaultValue'> {\n countries?: SelectOption[]\n countryLabel?: string\n countryName?: string\n defaultCountryValue?: string\n defaultValue?: string\n name?: string\n placeholder?: string\n size?: 'default' | 'lg' | 'sm'\n}\n\nexport const PhoneInput = ({\n className,\n countries = emptyOptions,\n countryLabel = 'Country code',\n countryName = 'country',\n defaultCountryValue,\n defaultValue,\n name = 'phone',\n placeholder = 'Phone number',\n size = 'default',\n ...props\n}: PhoneInputProps) => {\n const { selectClass, inputClass } = phoneInputSizeModifiers(size)\n\n return (\n <div className={composeClassName('ui-phone-input ui-input-group', className)} {...props}>\n <select\n aria-label={countryLabel}\n className={composeClassName('ui-select ui-phone-input__country', selectClass)}\n defaultValue={defaultCountryValue}\n name={countryName}\n >\n {countries.map(normalizeOption).map(option => (\n <option disabled={option.disabled} key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n <input\n autoComplete=\"tel\"\n className={composeClassName('ui-input ui-phone-input__number', inputClass)}\n defaultValue={defaultValue}\n inputMode=\"tel\"\n name={name}\n placeholder={placeholder}\n type=\"tel\"\n />\n </div>\n )\n}",
|
|
12315
|
+
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
12316
|
+
}
|
|
12317
|
+
},
|
|
12318
|
+
"frameworks": {
|
|
12319
|
+
"astro": true,
|
|
12320
|
+
"elements": true,
|
|
12321
|
+
"react": true
|
|
12322
|
+
},
|
|
12323
|
+
"guidance": null,
|
|
12324
|
+
"kebab": "phone-input",
|
|
12325
|
+
"keyboardInteractions": [],
|
|
12326
|
+
"keywords": [
|
|
12327
|
+
"built",
|
|
12328
|
+
"choose",
|
|
12329
|
+
"code",
|
|
12330
|
+
"country",
|
|
12331
|
+
"data",
|
|
12332
|
+
"dial",
|
|
12333
|
+
"entry",
|
|
12334
|
+
"field",
|
|
12335
|
+
"forms",
|
|
12336
|
+
"input",
|
|
12337
|
+
"needs",
|
|
12338
|
+
"number",
|
|
12339
|
+
"only",
|
|
12340
|
+
"pairs",
|
|
12341
|
+
"phoneinput",
|
|
12342
|
+
"purpose",
|
|
12343
|
+
"select",
|
|
12344
|
+
"start",
|
|
12345
|
+
"telephone",
|
|
12346
|
+
"text",
|
|
12347
|
+
"the",
|
|
12348
|
+
"then",
|
|
12349
|
+
"when",
|
|
12350
|
+
"with"
|
|
12351
|
+
],
|
|
12352
|
+
"name": "PhoneInput",
|
|
12353
|
+
"props": [
|
|
12354
|
+
{
|
|
12355
|
+
"name": "class",
|
|
12356
|
+
"optional": true,
|
|
12357
|
+
"type": "string | null"
|
|
12358
|
+
},
|
|
12359
|
+
{
|
|
12360
|
+
"name": "className",
|
|
12361
|
+
"optional": true,
|
|
12362
|
+
"type": "string"
|
|
12363
|
+
},
|
|
12364
|
+
{
|
|
12365
|
+
"name": "countries",
|
|
12366
|
+
"optional": true,
|
|
12367
|
+
"type": "Country[]"
|
|
12368
|
+
},
|
|
12369
|
+
{
|
|
12370
|
+
"name": "countryLabel",
|
|
12371
|
+
"optional": true,
|
|
12372
|
+
"type": "string"
|
|
12373
|
+
},
|
|
12374
|
+
{
|
|
12375
|
+
"name": "countryName",
|
|
12376
|
+
"optional": true,
|
|
12377
|
+
"type": "string"
|
|
12378
|
+
},
|
|
12379
|
+
{
|
|
12380
|
+
"name": "countryValue",
|
|
12381
|
+
"optional": true,
|
|
12382
|
+
"type": "string"
|
|
12383
|
+
},
|
|
12384
|
+
{
|
|
12385
|
+
"name": "name",
|
|
12386
|
+
"optional": true,
|
|
12387
|
+
"type": "string"
|
|
12388
|
+
},
|
|
12389
|
+
{
|
|
12390
|
+
"name": "placeholder",
|
|
12391
|
+
"optional": true,
|
|
12392
|
+
"type": "string"
|
|
12393
|
+
},
|
|
12394
|
+
{
|
|
12395
|
+
"name": "size",
|
|
12396
|
+
"optional": true,
|
|
12397
|
+
"type": "'default' | 'lg' | 'sm'"
|
|
12398
|
+
},
|
|
12399
|
+
{
|
|
12400
|
+
"name": "value",
|
|
12401
|
+
"optional": true,
|
|
12402
|
+
"type": "string"
|
|
12403
|
+
}
|
|
12404
|
+
],
|
|
12405
|
+
"propsExtends": "Omit<HTMLAttributes<'div'>, 'size'>",
|
|
12406
|
+
"recipes": [],
|
|
12407
|
+
"runtimeEvents": []
|
|
12408
|
+
},
|
|
12409
|
+
{
|
|
12410
|
+
"apiReference": [
|
|
12411
|
+
{
|
|
12412
|
+
"attribute": "glass",
|
|
12413
|
+
"defaultValue": "false",
|
|
12414
|
+
"description": "Applies the tokenized liquid-glass surface treatment with backdrop-filter fallbacks; \"subtle\" and \"strong\" adjust the fill intensity.",
|
|
12415
|
+
"values": "boolean | \"subtle\" | \"strong\""
|
|
12416
|
+
},
|
|
12417
|
+
{
|
|
12418
|
+
"attribute": "series",
|
|
12419
|
+
"defaultValue": "required",
|
|
12420
|
+
"description": "Provides one already-aggregated series whose positive finite data points become slices.",
|
|
12421
|
+
"values": "LumenChartSeries"
|
|
12422
|
+
},
|
|
12423
|
+
{
|
|
12424
|
+
"attribute": "variant",
|
|
12425
|
+
"defaultValue": "\"donut\"",
|
|
12426
|
+
"description": "Uses a center opening by default or renders a traditional pie.",
|
|
12427
|
+
"values": "\"donut\" | \"pie\""
|
|
12428
|
+
},
|
|
12429
|
+
{
|
|
12430
|
+
"attribute": "centerLabel, centerValue",
|
|
12431
|
+
"defaultValue": "-",
|
|
12432
|
+
"description": "Adds optional visual summary content in the donut center.",
|
|
12433
|
+
"values": "string | ReactNode"
|
|
12434
|
+
},
|
|
12435
|
+
{
|
|
12436
|
+
"attribute": "showLegend",
|
|
12437
|
+
"defaultValue": "true",
|
|
12438
|
+
"description": "Shows the color-independent category key.",
|
|
12439
|
+
"values": "boolean"
|
|
12440
|
+
},
|
|
12441
|
+
{
|
|
12442
|
+
"attribute": "showTable",
|
|
12443
|
+
"defaultValue": "true",
|
|
12444
|
+
"description": "Provides a revealable semantic table with category, value, and share columns.",
|
|
12445
|
+
"values": "boolean"
|
|
12446
|
+
},
|
|
12447
|
+
{
|
|
12448
|
+
"attribute": "valueFormatter",
|
|
12449
|
+
"defaultValue": "String",
|
|
12450
|
+
"description": "Formats values in SVG titles and the semantic table for Astro and React; Web Components expose the equivalent JavaScript property.",
|
|
12451
|
+
"values": "(value: number) => string"
|
|
12452
|
+
},
|
|
12453
|
+
{
|
|
12454
|
+
"attribute": "class, className",
|
|
12455
|
+
"defaultValue": "\"\"",
|
|
12456
|
+
"description": "Merges custom classes with the generated ui-* root classes.",
|
|
12457
|
+
"values": "string"
|
|
12458
|
+
},
|
|
12459
|
+
{
|
|
12460
|
+
"attribute": "...native attributes",
|
|
12461
|
+
"defaultValue": "-",
|
|
12462
|
+
"description": "Forwards standard attributes to the root element unless the component consumes them.",
|
|
12463
|
+
"values": "HTML attributes"
|
|
12464
|
+
}
|
|
12465
|
+
],
|
|
12466
|
+
"astroSource": "---\nimport {\n createLumenPieGeometry,\n hasLumenPieData,\n type LumenChartSeries,\n type LumenPieChartVariant\n} from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\nimport Chart from './Chart.astro'\n\ninterface Props extends HTMLAttributes<'figure'> {\n caption?: string\n centerLabel?: string\n centerValue?: string\n class?: string | null\n className?: string\n description?: string\n glass?: boolean | 'subtle' | 'strong'\n heading?: string\n series: LumenChartSeries\n showLegend?: boolean\n showTable?: boolean\n valueFormatter?: (value: number) => string\n variant?: LumenPieChartVariant\n}\n\nconst {\n caption,\n centerLabel,\n centerValue,\n class: classProp = '',\n className = '',\n description,\n glass = false,\n heading,\n series,\n showLegend = true,\n showTable = true,\n valueFormatter = String,\n variant = 'donut',\n ...rest\n} = Astro.props\nconst geometry = createLumenPieGeometry(series.data, { variant })\nconst hasData = hasLumenPieData(series.data)\nconst percentageFor = (percentage: number) =>\n new Intl.NumberFormat(undefined, {\n maximumFractionDigits: percentage < 0.01 ? 1 : 0,\n style: 'percent'\n }).format(percentage)\n---\n\n<Chart\n class:list={['ui-pie-chart', `ui-pie-chart--${variant}`, classProp, className]}\n {caption}\n {description}\n {glass}\n {heading}\n {...rest}\n>\n {\n showLegend && hasData && (\n <ul class=\"ui-chart__legend\" aria-label=\"Chart legend\">\n {geometry.slices.map(slice => (\n <li class={`ui-chart-tone--${slice.tone}`}>\n <span aria-hidden=\"true\" />\n {slice.label}\n </li>\n ))}\n </ul>\n )\n }\n {!hasData && <p class=\"ui-chart__empty\" role=\"status\">No chart data available.</p>}\n <div class=\"ui-chart__plot ui-pie-chart__plot\" hidden={!hasData}>\n <svg\n aria-hidden=\"true\"\n preserveAspectRatio=\"xMidYMid meet\"\n viewBox={`0 0 ${geometry.size} ${geometry.size}`}\n >\n <g class=\"ui-pie-chart__slices\">\n {\n geometry.slices.map(slice => (\n <path\n class={`ui-chart-tone--${slice.tone}`}\n d={slice.path}\n fill-rule=\"evenodd\"\n >\n <title>\n {`${slice.label}: ${valueFormatter(slice.value)} (${percentageFor(slice.percentage)})`}\n </title>\n </path>\n ))\n }\n </g>\n </svg>\n {\n variant === 'donut' && (centerLabel != null || centerValue != null) && (\n <>\n <div class=\"ui-pie-chart__center\" aria-hidden=\"true\">\n {centerValue != null && <strong>{centerValue}</strong>}\n {centerLabel != null && <span>{centerLabel}</span>}\n </div>\n <div class=\"ui-sr-only\">\n {centerValue} {centerLabel}\n </div>\n </>\n )\n }\n </div>\n {\n showTable && hasData && (\n <details class=\"ui-chart__data\">\n <summary>View chart data</summary>\n <div>\n <table>\n <thead>\n <tr>\n <th scope=\"col\">Category</th>\n <th scope=\"col\">Value</th>\n <th scope=\"col\">Share</th>\n </tr>\n </thead>\n <tbody>\n {geometry.slices.map(slice => (\n <tr>\n <th scope=\"row\">{slice.label}</th>\n <td>{valueFormatter(slice.value)}</td>\n <td>{percentageFor(slice.percentage)}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </details>\n )\n }\n</Chart>\n",
|
|
12467
|
+
"category": "Data display",
|
|
12468
|
+
"collections": [
|
|
12469
|
+
"Data visualization"
|
|
12470
|
+
],
|
|
12471
|
+
"dependencies": [
|
|
12472
|
+
"Chart",
|
|
12473
|
+
"styles"
|
|
12474
|
+
],
|
|
12475
|
+
"description": "Shows part-to-whole relationships as an accessible donut or pie chart.",
|
|
12476
|
+
"files": [
|
|
12477
|
+
"packages/astro/components/PieChart.astro",
|
|
12478
|
+
"packages/astro/components/Chart.astro",
|
|
12479
|
+
"packages/astro/styles/lumen.css"
|
|
12480
|
+
],
|
|
12481
|
+
"frameworkDetails": {
|
|
12482
|
+
"astro": {
|
|
12483
|
+
"available": true,
|
|
12484
|
+
"example": "<PieChart aria-label=\"Framework share\" centerLabel=\"Projects\" centerValue=\"2,480\" heading=\"Framework usage\" series={{ id: \"frameworks\", label: \"Framework share\", data: [{ label: \"Astro\", x: \"astro\", y: 46 }, { label: \"React\", x: \"react\", y: 31 }, { label: \"Web Components\", x: \"elements\", y: 23 }] }} />",
|
|
12485
|
+
"importStatement": "import { PieChart } from '@santi020k/lumen-astro'",
|
|
12486
|
+
"language": "astro",
|
|
12487
|
+
"packageName": "@santi020k/lumen-astro",
|
|
12488
|
+
"props": [
|
|
12489
|
+
{
|
|
12490
|
+
"name": "caption",
|
|
12491
|
+
"optional": true,
|
|
12492
|
+
"type": "string"
|
|
12493
|
+
},
|
|
12494
|
+
{
|
|
12495
|
+
"name": "centerLabel",
|
|
12496
|
+
"optional": true,
|
|
12497
|
+
"type": "string"
|
|
12498
|
+
},
|
|
12499
|
+
{
|
|
12500
|
+
"name": "centerValue",
|
|
12501
|
+
"optional": true,
|
|
12502
|
+
"type": "string"
|
|
12503
|
+
},
|
|
12504
|
+
{
|
|
12505
|
+
"name": "class",
|
|
12506
|
+
"optional": true,
|
|
12507
|
+
"type": "string | null"
|
|
12508
|
+
},
|
|
12509
|
+
{
|
|
12510
|
+
"name": "className",
|
|
12511
|
+
"optional": true,
|
|
12512
|
+
"type": "string"
|
|
12513
|
+
},
|
|
12514
|
+
{
|
|
12515
|
+
"name": "description",
|
|
12516
|
+
"optional": true,
|
|
12517
|
+
"type": "string"
|
|
12518
|
+
},
|
|
12519
|
+
{
|
|
12520
|
+
"name": "glass",
|
|
12521
|
+
"optional": true,
|
|
12522
|
+
"type": "boolean | 'subtle' | 'strong'"
|
|
12523
|
+
},
|
|
12524
|
+
{
|
|
12525
|
+
"name": "heading",
|
|
12526
|
+
"optional": true,
|
|
12527
|
+
"type": "string"
|
|
12528
|
+
},
|
|
12529
|
+
{
|
|
12530
|
+
"name": "series",
|
|
12531
|
+
"optional": false,
|
|
12532
|
+
"type": "LumenChartSeries"
|
|
12533
|
+
},
|
|
12534
|
+
{
|
|
12535
|
+
"name": "showLegend",
|
|
12536
|
+
"optional": true,
|
|
12537
|
+
"type": "boolean"
|
|
12538
|
+
},
|
|
12539
|
+
{
|
|
12540
|
+
"name": "showTable",
|
|
12541
|
+
"optional": true,
|
|
12542
|
+
"type": "boolean"
|
|
12543
|
+
},
|
|
12544
|
+
{
|
|
12545
|
+
"name": "valueFormatter",
|
|
12546
|
+
"optional": true,
|
|
12547
|
+
"type": "(value: number) => string"
|
|
12548
|
+
},
|
|
12549
|
+
{
|
|
12550
|
+
"name": "variant",
|
|
12551
|
+
"optional": true,
|
|
12552
|
+
"type": "LumenPieChartVariant"
|
|
12553
|
+
}
|
|
12554
|
+
],
|
|
12555
|
+
"propsExtends": "HTMLAttributes<'figure'>",
|
|
12556
|
+
"source": "---\nimport {\n createLumenPieGeometry,\n hasLumenPieData,\n type LumenChartSeries,\n type LumenPieChartVariant\n} from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\nimport Chart from './Chart.astro'\n\ninterface Props extends HTMLAttributes<'figure'> {\n caption?: string\n centerLabel?: string\n centerValue?: string\n class?: string | null\n className?: string\n description?: string\n glass?: boolean | 'subtle' | 'strong'\n heading?: string\n series: LumenChartSeries\n showLegend?: boolean\n showTable?: boolean\n valueFormatter?: (value: number) => string\n variant?: LumenPieChartVariant\n}\n\nconst {\n caption,\n centerLabel,\n centerValue,\n class: classProp = '',\n className = '',\n description,\n glass = false,\n heading,\n series,\n showLegend = true,\n showTable = true,\n valueFormatter = String,\n variant = 'donut',\n ...rest\n} = Astro.props\nconst geometry = createLumenPieGeometry(series.data, { variant })\nconst hasData = hasLumenPieData(series.data)\nconst percentageFor = (percentage: number) =>\n new Intl.NumberFormat(undefined, {\n maximumFractionDigits: percentage < 0.01 ? 1 : 0,\n style: 'percent'\n }).format(percentage)\n---\n\n<Chart\n class:list={['ui-pie-chart', `ui-pie-chart--${variant}`, classProp, className]}\n {caption}\n {description}\n {glass}\n {heading}\n {...rest}\n>\n {\n showLegend && hasData && (\n <ul class=\"ui-chart__legend\" aria-label=\"Chart legend\">\n {geometry.slices.map(slice => (\n <li class={`ui-chart-tone--${slice.tone}`}>\n <span aria-hidden=\"true\" />\n {slice.label}\n </li>\n ))}\n </ul>\n )\n }\n {!hasData && <p class=\"ui-chart__empty\" role=\"status\">No chart data available.</p>}\n <div class=\"ui-chart__plot ui-pie-chart__plot\" hidden={!hasData}>\n <svg\n aria-hidden=\"true\"\n preserveAspectRatio=\"xMidYMid meet\"\n viewBox={`0 0 ${geometry.size} ${geometry.size}`}\n >\n <g class=\"ui-pie-chart__slices\">\n {\n geometry.slices.map(slice => (\n <path\n class={`ui-chart-tone--${slice.tone}`}\n d={slice.path}\n fill-rule=\"evenodd\"\n >\n <title>\n {`${slice.label}: ${valueFormatter(slice.value)} (${percentageFor(slice.percentage)})`}\n </title>\n </path>\n ))\n }\n </g>\n </svg>\n {\n variant === 'donut' && (centerLabel != null || centerValue != null) && (\n <>\n <div class=\"ui-pie-chart__center\" aria-hidden=\"true\">\n {centerValue != null && <strong>{centerValue}</strong>}\n {centerLabel != null && <span>{centerLabel}</span>}\n </div>\n <div class=\"ui-sr-only\">\n {centerValue} {centerLabel}\n </div>\n </>\n )\n }\n </div>\n {\n showTable && hasData && (\n <details class=\"ui-chart__data\">\n <summary>View chart data</summary>\n <div>\n <table>\n <thead>\n <tr>\n <th scope=\"col\">Category</th>\n <th scope=\"col\">Value</th>\n <th scope=\"col\">Share</th>\n </tr>\n </thead>\n <tbody>\n {geometry.slices.map(slice => (\n <tr>\n <th scope=\"row\">{slice.label}</th>\n <td>{valueFormatter(slice.value)}</td>\n <td>{percentageFor(slice.percentage)}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </details>\n )\n }\n</Chart>\n",
|
|
12557
|
+
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
12558
|
+
},
|
|
12559
|
+
"elements": {
|
|
12560
|
+
"attributes": [
|
|
12561
|
+
"variant",
|
|
12562
|
+
"glass",
|
|
12563
|
+
"series",
|
|
12564
|
+
"centerLabel, centerValue",
|
|
12565
|
+
"showLegend",
|
|
12566
|
+
"showTable",
|
|
12567
|
+
"valueFormatter",
|
|
12568
|
+
"class, className",
|
|
12569
|
+
"...native attributes"
|
|
12570
|
+
],
|
|
12571
|
+
"available": true,
|
|
12572
|
+
"behavior": {
|
|
12573
|
+
"mode": "registration",
|
|
12574
|
+
"setup": "Call defineLumenElements() once before rendering Lumen custom elements."
|
|
12575
|
+
},
|
|
12576
|
+
"example": "<lumen-pie-chart></lumen-pie-chart>",
|
|
12577
|
+
"importStatement": "import { defineLumenElements } from '@santi020k/lumen-elements/define'",
|
|
12578
|
+
"language": "html",
|
|
12579
|
+
"packageName": "@santi020k/lumen-elements",
|
|
12580
|
+
"props": [],
|
|
12581
|
+
"propsExtends": "HTMLElement attributes",
|
|
12582
|
+
"registration": "defineLumenElements()",
|
|
12583
|
+
"source": "PieChart: {\n attributeClasses: {\n ...glassAttributeClasses('ui-chart--glass'),\n variant: {\n donut: 'ui-pie-chart--donut',\n pie: 'ui-pie-chart--pie'\n }\n },\n baseClassName: 'ui-chart ui-pie-chart',\n defaults: { variant: 'donut' },\n role: 'figure',\n tagName: 'lumen-pie-chart'\n }",
|
|
12584
|
+
"styleImport": "import '@santi020k/lumen-elements/styles.css'",
|
|
12585
|
+
"tagName": "lumen-pie-chart"
|
|
12586
|
+
},
|
|
12587
|
+
"react": {
|
|
12588
|
+
"available": true,
|
|
12589
|
+
"example": "<PieChart aria-label=\"Framework share\" centerLabel=\"Projects\" centerValue=\"2,480\" heading=\"Framework usage\" series={{ id: \"frameworks\", label: \"Framework share\", data: [{ label: \"Astro\", x: \"astro\", y: 46 }, { label: \"React\", x: \"react\", y: 31 }, { label: \"Web Components\", x: \"elements\", y: 23 }] }} />",
|
|
12590
|
+
"importStatement": "import { PieChart } from '@santi020k/lumen-react'",
|
|
12591
|
+
"language": "tsx",
|
|
12592
|
+
"packageName": "@santi020k/lumen-react",
|
|
12593
|
+
"props": [
|
|
12594
|
+
{
|
|
12595
|
+
"name": "centerLabel",
|
|
12596
|
+
"optional": true,
|
|
12597
|
+
"type": "ReactNode"
|
|
12598
|
+
},
|
|
12599
|
+
{
|
|
12600
|
+
"name": "centerValue",
|
|
12601
|
+
"optional": true,
|
|
12602
|
+
"type": "ReactNode"
|
|
12603
|
+
},
|
|
12604
|
+
{
|
|
12605
|
+
"name": "series",
|
|
12606
|
+
"optional": true,
|
|
12607
|
+
"type": "LumenChartSeries"
|
|
12608
|
+
},
|
|
12609
|
+
{
|
|
12610
|
+
"name": "showLegend",
|
|
12611
|
+
"optional": true,
|
|
12612
|
+
"type": "boolean"
|
|
12613
|
+
},
|
|
12614
|
+
{
|
|
12615
|
+
"name": "showTable",
|
|
11523
12616
|
"optional": true,
|
|
11524
|
-
"type": "
|
|
12617
|
+
"type": "boolean"
|
|
11525
12618
|
},
|
|
11526
12619
|
{
|
|
11527
|
-
"name": "
|
|
12620
|
+
"name": "valueFormatter",
|
|
11528
12621
|
"optional": true,
|
|
11529
|
-
"type": "string"
|
|
12622
|
+
"type": "(value: number) => string"
|
|
11530
12623
|
},
|
|
11531
12624
|
{
|
|
11532
|
-
"name": "
|
|
12625
|
+
"name": "variant",
|
|
11533
12626
|
"optional": true,
|
|
11534
|
-
"type": "
|
|
12627
|
+
"type": "LumenPieChartVariant"
|
|
11535
12628
|
}
|
|
11536
12629
|
],
|
|
11537
|
-
"propsExtends": "Omit<
|
|
11538
|
-
"source": "export interface
|
|
12630
|
+
"propsExtends": "Omit<ChartProps, 'children'>",
|
|
12631
|
+
"source": "export interface PieChartProps extends Omit<ChartProps, 'children'> {\n centerLabel?: ReactNode\n centerValue?: ReactNode\n series?: LumenChartSeries\n showLegend?: boolean\n showTable?: boolean\n valueFormatter?: (value: number) => string\n variant?: LumenPieChartVariant\n}\n\nexport const PieChart = ({\n centerLabel,\n centerValue,\n className,\n series = emptyPieSeries,\n showLegend = true,\n showTable = true,\n valueFormatter = String,\n variant = 'donut',\n ...props\n}: PieChartProps) => {\n const geometry = createLumenPieGeometry(series.data, { variant })\n const hasData = hasLumenPieData(series.data)\n\n return (\n <Chart\n className={composeClassName('ui-pie-chart', `ui-pie-chart--${variant}`, className)}\n {...props}\n >\n {showLegend && hasData && (\n <ul aria-label=\"Chart legend\" className=\"ui-chart__legend\">\n {geometry.slices.map(slice => (\n <li\n className={`ui-chart-tone--${slice.tone}`}\n key={`${typeof slice.x}:${String(slice.x)}`}\n >\n <span aria-hidden=\"true\" />\n {slice.label}\n </li>\n ))}\n </ul>\n )}\n {!hasData && (\n <p className=\"ui-chart__empty\" role=\"status\">No chart data available.</p>\n )}\n <div\n className=\"ui-chart__plot ui-pie-chart__plot\"\n hidden={!hasData}\n >\n <svg\n aria-hidden=\"true\"\n preserveAspectRatio=\"xMidYMid meet\"\n viewBox={`0 0 ${geometry.size} ${geometry.size}`}\n >\n <g className=\"ui-pie-chart__slices\">\n {geometry.slices.map(slice => (\n <path\n className={`ui-chart-tone--${slice.tone}`}\n d={slice.path}\n fillRule=\"evenodd\"\n key={`${typeof slice.x}:${String(slice.x)}`}\n >\n <title>\n {`${slice.label}: ${valueFormatter(slice.value)} (${formatChartPercentage(slice.percentage)})`}\n </title>\n </path>\n ))}\n </g>\n </svg>\n {variant === 'donut' && (centerLabel != null || centerValue != null) && (\n <>\n <div aria-hidden=\"true\" className=\"ui-pie-chart__center\">\n {centerValue != null && <strong>{centerValue}</strong>}\n {centerLabel != null && <span>{centerLabel}</span>}\n </div>\n <div className=\"ui-sr-only\">\n {centerValue} {centerLabel}\n </div>\n </>\n )}\n </div>\n {showTable && hasData && (\n <details className=\"ui-chart__data\">\n <summary>View chart data</summary>\n <div>\n <table>\n <thead>\n <tr>\n <th scope=\"col\">Category</th>\n <th scope=\"col\">Value</th>\n <th scope=\"col\">Share</th>\n </tr>\n </thead>\n <tbody>\n {geometry.slices.map(slice => (\n <tr key={`${typeof slice.x}:${String(slice.x)}`}>\n <th scope=\"row\">{slice.label}</th>\n <td>{valueFormatter(slice.value)}</td>\n <td>{formatChartPercentage(slice.percentage)}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </details>\n )}\n </Chart>\n )\n}",
|
|
11539
12632
|
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
11540
12633
|
}
|
|
11541
12634
|
},
|
|
@@ -11544,90 +12637,144 @@
|
|
|
11544
12637
|
"elements": true,
|
|
11545
12638
|
"react": true
|
|
11546
12639
|
},
|
|
11547
|
-
"guidance":
|
|
11548
|
-
|
|
12640
|
+
"guidance": {
|
|
12641
|
+
"when": "Use for a part-to-whole breakdown with one series, non-negative values, and a small number of meaningful categories.",
|
|
12642
|
+
"distinction": "Prefer the default donut for a center total. Use BarChart when precise comparison or more than roughly seven categories matters, and do not use PieChart for negative values or change over time."
|
|
12643
|
+
},
|
|
12644
|
+
"kebab": "pie-chart",
|
|
11549
12645
|
"keyboardInteractions": [],
|
|
11550
12646
|
"keywords": [
|
|
11551
|
-
"
|
|
11552
|
-
"
|
|
11553
|
-
"
|
|
11554
|
-
"
|
|
12647
|
+
"accessible",
|
|
12648
|
+
"and",
|
|
12649
|
+
"barchart",
|
|
12650
|
+
"breakdown",
|
|
12651
|
+
"breakdowns",
|
|
12652
|
+
"categorical",
|
|
12653
|
+
"categories",
|
|
12654
|
+
"center",
|
|
12655
|
+
"change",
|
|
12656
|
+
"chart",
|
|
12657
|
+
"compact",
|
|
12658
|
+
"comparison",
|
|
12659
|
+
"comparisons",
|
|
12660
|
+
"custom",
|
|
11555
12661
|
"data",
|
|
11556
|
-
"
|
|
11557
|
-
"
|
|
11558
|
-
"
|
|
11559
|
-
"
|
|
11560
|
-
"
|
|
11561
|
-
"
|
|
12662
|
+
"default",
|
|
12663
|
+
"display",
|
|
12664
|
+
"donut",
|
|
12665
|
+
"for",
|
|
12666
|
+
"match",
|
|
12667
|
+
"matters",
|
|
12668
|
+
"meaningful",
|
|
12669
|
+
"metrics",
|
|
12670
|
+
"more",
|
|
12671
|
+
"negative",
|
|
12672
|
+
"non",
|
|
12673
|
+
"not",
|
|
11562
12674
|
"number",
|
|
11563
|
-
"
|
|
11564
|
-
"
|
|
11565
|
-
"
|
|
11566
|
-
"
|
|
11567
|
-
"
|
|
11568
|
-
"
|
|
11569
|
-
"
|
|
11570
|
-
"
|
|
12675
|
+
"one",
|
|
12676
|
+
"ordered",
|
|
12677
|
+
"over",
|
|
12678
|
+
"part",
|
|
12679
|
+
"pie",
|
|
12680
|
+
"piechart",
|
|
12681
|
+
"plots",
|
|
12682
|
+
"precise",
|
|
12683
|
+
"prefer",
|
|
12684
|
+
"question",
|
|
12685
|
+
"relationships",
|
|
12686
|
+
"roughly",
|
|
12687
|
+
"series",
|
|
12688
|
+
"seven",
|
|
12689
|
+
"shows",
|
|
12690
|
+
"small",
|
|
12691
|
+
"than",
|
|
11571
12692
|
"the",
|
|
11572
|
-
"
|
|
12693
|
+
"time",
|
|
12694
|
+
"total",
|
|
12695
|
+
"trends",
|
|
12696
|
+
"use",
|
|
12697
|
+
"values",
|
|
12698
|
+
"visualization",
|
|
11573
12699
|
"when",
|
|
12700
|
+
"whole",
|
|
11574
12701
|
"with"
|
|
11575
12702
|
],
|
|
11576
|
-
"name": "
|
|
12703
|
+
"name": "PieChart",
|
|
11577
12704
|
"props": [
|
|
11578
12705
|
{
|
|
11579
|
-
"name": "
|
|
12706
|
+
"name": "caption",
|
|
11580
12707
|
"optional": true,
|
|
11581
|
-
"type": "string
|
|
12708
|
+
"type": "string"
|
|
11582
12709
|
},
|
|
11583
12710
|
{
|
|
11584
|
-
"name": "
|
|
12711
|
+
"name": "centerLabel",
|
|
11585
12712
|
"optional": true,
|
|
11586
12713
|
"type": "string"
|
|
11587
12714
|
},
|
|
11588
12715
|
{
|
|
11589
|
-
"name": "
|
|
12716
|
+
"name": "centerValue",
|
|
11590
12717
|
"optional": true,
|
|
11591
|
-
"type": "
|
|
12718
|
+
"type": "string"
|
|
11592
12719
|
},
|
|
11593
12720
|
{
|
|
11594
|
-
"name": "
|
|
12721
|
+
"name": "class",
|
|
11595
12722
|
"optional": true,
|
|
11596
|
-
"type": "string"
|
|
12723
|
+
"type": "string | null"
|
|
11597
12724
|
},
|
|
11598
12725
|
{
|
|
11599
|
-
"name": "
|
|
12726
|
+
"name": "className",
|
|
11600
12727
|
"optional": true,
|
|
11601
12728
|
"type": "string"
|
|
11602
12729
|
},
|
|
11603
12730
|
{
|
|
11604
|
-
"name": "
|
|
12731
|
+
"name": "description",
|
|
11605
12732
|
"optional": true,
|
|
11606
12733
|
"type": "string"
|
|
11607
12734
|
},
|
|
11608
12735
|
{
|
|
11609
|
-
"name": "
|
|
12736
|
+
"name": "glass",
|
|
11610
12737
|
"optional": true,
|
|
11611
|
-
"type": "
|
|
12738
|
+
"type": "boolean | 'subtle' | 'strong'"
|
|
11612
12739
|
},
|
|
11613
12740
|
{
|
|
11614
|
-
"name": "
|
|
12741
|
+
"name": "heading",
|
|
11615
12742
|
"optional": true,
|
|
11616
12743
|
"type": "string"
|
|
11617
12744
|
},
|
|
11618
12745
|
{
|
|
11619
|
-
"name": "
|
|
12746
|
+
"name": "series",
|
|
12747
|
+
"optional": false,
|
|
12748
|
+
"type": "LumenChartSeries"
|
|
12749
|
+
},
|
|
12750
|
+
{
|
|
12751
|
+
"name": "showLegend",
|
|
11620
12752
|
"optional": true,
|
|
11621
|
-
"type": "
|
|
12753
|
+
"type": "boolean"
|
|
11622
12754
|
},
|
|
11623
12755
|
{
|
|
11624
|
-
"name": "
|
|
12756
|
+
"name": "showTable",
|
|
11625
12757
|
"optional": true,
|
|
11626
|
-
"type": "
|
|
12758
|
+
"type": "boolean"
|
|
12759
|
+
},
|
|
12760
|
+
{
|
|
12761
|
+
"name": "valueFormatter",
|
|
12762
|
+
"optional": true,
|
|
12763
|
+
"type": "(value: number) => string"
|
|
12764
|
+
},
|
|
12765
|
+
{
|
|
12766
|
+
"name": "variant",
|
|
12767
|
+
"optional": true,
|
|
12768
|
+
"type": "LumenPieChartVariant"
|
|
12769
|
+
}
|
|
12770
|
+
],
|
|
12771
|
+
"propsExtends": "HTMLAttributes<'figure'>",
|
|
12772
|
+
"recipes": [
|
|
12773
|
+
{
|
|
12774
|
+
"name": "data-visualization",
|
|
12775
|
+
"type": "recipe"
|
|
11627
12776
|
}
|
|
11628
12777
|
],
|
|
11629
|
-
"propsExtends": "Omit<HTMLAttributes<'div'>, 'size'>",
|
|
11630
|
-
"recipes": [],
|
|
11631
12778
|
"runtimeEvents": []
|
|
11632
12779
|
},
|
|
11633
12780
|
{
|
|
@@ -11644,6 +12791,12 @@
|
|
|
11644
12791
|
"description": "Renders the pill as a focusable anchor when it represents a destination.",
|
|
11645
12792
|
"values": "string"
|
|
11646
12793
|
},
|
|
12794
|
+
{
|
|
12795
|
+
"attribute": "variant",
|
|
12796
|
+
"defaultValue": "\"neutral\"",
|
|
12797
|
+
"description": "Controls the pill emphasis without changing its metadata semantics.",
|
|
12798
|
+
"values": "\"neutral\" | \"brand\" | \"outline\""
|
|
12799
|
+
},
|
|
11647
12800
|
{
|
|
11648
12801
|
"attribute": "class, className",
|
|
11649
12802
|
"defaultValue": "\"\"",
|
|
@@ -11657,7 +12810,7 @@
|
|
|
11657
12810
|
"values": "HTML attributes"
|
|
11658
12811
|
}
|
|
11659
12812
|
],
|
|
11660
|
-
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'span'> {\n class?: string | null\n className?: string\n count?: number | string\n href?: string\n}\n\nconst {\n class: classProp = '',\n className = '',\n count,\n href,\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-pill'
|
|
12813
|
+
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'span'> {\n class?: string | null\n className?: string\n count?: number | string\n href?: string\n variant?: 'brand' | 'neutral' | 'outline'\n}\n\nconst {\n class: classProp = '',\n className = '',\n count,\n href,\n variant = 'neutral',\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-pill',\n variant !== 'neutral' && `ui-pill--${variant}`\n], classProp, className)\n---\n\n{href\n ? <a class:list={classList} data-variant={variant} href={href} {...passthrough}>\n <slot />\n {count != null && <span class=\"ui-pill__count\">{count}</span>}\n </a>\n : <span class:list={classList} data-variant={variant} {...passthrough}>\n <slot />\n {count != null && <span class=\"ui-pill__count\">{count}</span>}\n </span>\n}\n",
|
|
11661
12814
|
"category": "Data display",
|
|
11662
12815
|
"collections": [],
|
|
11663
12816
|
"dependencies": [
|
|
@@ -11671,7 +12824,7 @@
|
|
|
11671
12824
|
"frameworkDetails": {
|
|
11672
12825
|
"astro": {
|
|
11673
12826
|
"available": true,
|
|
11674
|
-
"example": "<Pill count={12}>Notifications</Pill>",
|
|
12827
|
+
"example": "<Pill count={12} variant=\"brand\">Notifications</Pill>",
|
|
11675
12828
|
"importStatement": "import { Pill } from '@santi020k/lumen-astro'",
|
|
11676
12829
|
"language": "astro",
|
|
11677
12830
|
"packageName": "@santi020k/lumen-astro",
|
|
@@ -11695,14 +12848,20 @@
|
|
|
11695
12848
|
"name": "href",
|
|
11696
12849
|
"optional": true,
|
|
11697
12850
|
"type": "string"
|
|
12851
|
+
},
|
|
12852
|
+
{
|
|
12853
|
+
"name": "variant",
|
|
12854
|
+
"optional": true,
|
|
12855
|
+
"type": "'brand' | 'neutral' | 'outline'"
|
|
11698
12856
|
}
|
|
11699
12857
|
],
|
|
11700
12858
|
"propsExtends": "HTMLAttributes<'span'>",
|
|
11701
|
-
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'span'> {\n class?: string | null\n className?: string\n count?: number | string\n href?: string\n}\n\nconst {\n class: classProp = '',\n className = '',\n count,\n href,\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-pill'
|
|
12859
|
+
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'span'> {\n class?: string | null\n className?: string\n count?: number | string\n href?: string\n variant?: 'brand' | 'neutral' | 'outline'\n}\n\nconst {\n class: classProp = '',\n className = '',\n count,\n href,\n variant = 'neutral',\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-pill',\n variant !== 'neutral' && `ui-pill--${variant}`\n], classProp, className)\n---\n\n{href\n ? <a class:list={classList} data-variant={variant} href={href} {...passthrough}>\n <slot />\n {count != null && <span class=\"ui-pill__count\">{count}</span>}\n </a>\n : <span class:list={classList} data-variant={variant} {...passthrough}>\n <slot />\n {count != null && <span class=\"ui-pill__count\">{count}</span>}\n </span>\n}\n",
|
|
11702
12860
|
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
11703
12861
|
},
|
|
11704
12862
|
"elements": {
|
|
11705
12863
|
"attributes": [
|
|
12864
|
+
"variant",
|
|
11706
12865
|
"count",
|
|
11707
12866
|
"href",
|
|
11708
12867
|
"class, className",
|
|
@@ -11713,20 +12872,20 @@
|
|
|
11713
12872
|
"mode": "registration",
|
|
11714
12873
|
"setup": "Call defineLumenElements() once before rendering Lumen custom elements."
|
|
11715
12874
|
},
|
|
11716
|
-
"example": "<lumen-pill count=\"12\">Notifications</lumen-pill>",
|
|
12875
|
+
"example": "<lumen-pill count=\"12\" variant=\"brand\">Notifications</lumen-pill>",
|
|
11717
12876
|
"importStatement": "import { defineLumenElements } from '@santi020k/lumen-elements/define'",
|
|
11718
12877
|
"language": "html",
|
|
11719
12878
|
"packageName": "@santi020k/lumen-elements",
|
|
11720
12879
|
"props": [],
|
|
11721
12880
|
"propsExtends": "HTMLElement attributes",
|
|
11722
12881
|
"registration": "defineLumenElements()",
|
|
11723
|
-
"source": "Pill: { baseClassName: 'ui-pill'
|
|
12882
|
+
"source": "Pill: {\n attributeClasses: {\n variant: {\n brand: 'ui-pill--brand',\n outline: 'ui-pill--outline'\n }\n },\n baseClassName: 'ui-pill',\n defaults: { variant: 'neutral' },\n tagName: 'lumen-pill'\n }",
|
|
11724
12883
|
"styleImport": "import '@santi020k/lumen-elements/styles.css'",
|
|
11725
12884
|
"tagName": "lumen-pill"
|
|
11726
12885
|
},
|
|
11727
12886
|
"react": {
|
|
11728
12887
|
"available": true,
|
|
11729
|
-
"example": "<Pill count={12}>Notifications</Pill>",
|
|
12888
|
+
"example": "<Pill count={12} variant=\"brand\">Notifications</Pill>",
|
|
11730
12889
|
"importStatement": "import { Pill } from '@santi020k/lumen-react'",
|
|
11731
12890
|
"language": "tsx",
|
|
11732
12891
|
"packageName": "@santi020k/lumen-react",
|
|
@@ -11740,10 +12899,15 @@
|
|
|
11740
12899
|
"name": "href",
|
|
11741
12900
|
"optional": true,
|
|
11742
12901
|
"type": "string"
|
|
12902
|
+
},
|
|
12903
|
+
{
|
|
12904
|
+
"name": "variant",
|
|
12905
|
+
"optional": true,
|
|
12906
|
+
"type": "'brand' | 'neutral' | 'outline'"
|
|
11743
12907
|
}
|
|
11744
12908
|
],
|
|
11745
12909
|
"propsExtends": "ComponentPropsWithoutRef<'span'>",
|
|
11746
|
-
"source": "export type PillProps = ComponentPropsWithoutRef<'span'> & {\n count?: number | string\n href?: string\n}\n\nexport const Pill = ({
|
|
12910
|
+
"source": "export type PillProps = ComponentPropsWithoutRef<'span'> & {\n count?: number | string\n href?: string\n variant?: 'brand' | 'neutral' | 'outline'\n}\n\nexport const Pill = ({\n className,\n count,\n children,\n href,\n variant = 'neutral',\n ...props\n}: PillProps) => {\n const content = (\n <>\n {children}\n {count !== undefined && <span className=\"ui-pill__count\">{count}</span>}\n </>\n )\n\n return href\n ? (\n <a\n className={composeClassName('ui-pill', variantClass('ui-pill', variant, 'neutral'), className)}\n data-variant={variant}\n href={href}\n {...props}\n >\n {content}\n </a>\n )\n : (\n <span\n className={composeClassName('ui-pill', variantClass('ui-pill', variant, 'neutral'), className)}\n data-variant={variant}\n {...props}\n >\n {content}\n </span>\n )\n}",
|
|
11747
12911
|
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
11748
12912
|
}
|
|
11749
12913
|
},
|
|
@@ -11808,6 +12972,11 @@
|
|
|
11808
12972
|
"name": "href",
|
|
11809
12973
|
"optional": true,
|
|
11810
12974
|
"type": "string"
|
|
12975
|
+
},
|
|
12976
|
+
{
|
|
12977
|
+
"name": "variant",
|
|
12978
|
+
"optional": true,
|
|
12979
|
+
"type": "'brand' | 'neutral' | 'outline'"
|
|
11811
12980
|
}
|
|
11812
12981
|
],
|
|
11813
12982
|
"propsExtends": "HTMLAttributes<'span'>",
|
|
@@ -12233,7 +13402,7 @@
|
|
|
12233
13402
|
},
|
|
12234
13403
|
"guidance": {
|
|
12235
13404
|
"when": "Use to communicate how much of a task, upload, or process has completed.",
|
|
12236
|
-
"distinction": "Use Meter for a stable measurement, Spinner for indeterminate short waits, or Skeleton while page structure is loading."
|
|
13405
|
+
"distinction": "Use ScrollProgress for document position, Meter for a stable measurement, Spinner for indeterminate short waits, or Skeleton while page structure is loading."
|
|
12237
13406
|
},
|
|
12238
13407
|
"kebab": "progress",
|
|
12239
13408
|
"keyboardInteractions": [],
|
|
@@ -12241,6 +13410,7 @@
|
|
|
12241
13410
|
"communicate",
|
|
12242
13411
|
"completed",
|
|
12243
13412
|
"completion",
|
|
13413
|
+
"document",
|
|
12244
13414
|
"feedback",
|
|
12245
13415
|
"for",
|
|
12246
13416
|
"has",
|
|
@@ -12251,9 +13421,11 @@
|
|
|
12251
13421
|
"meter",
|
|
12252
13422
|
"much",
|
|
12253
13423
|
"page",
|
|
13424
|
+
"position",
|
|
12254
13425
|
"process",
|
|
12255
13426
|
"progress",
|
|
12256
13427
|
"quota",
|
|
13428
|
+
"scrollprogress",
|
|
12257
13429
|
"short",
|
|
12258
13430
|
"shows",
|
|
12259
13431
|
"skeleton",
|
|
@@ -13215,22 +14387,175 @@
|
|
|
13215
14387
|
"values": "HTML attributes"
|
|
13216
14388
|
}
|
|
13217
14389
|
],
|
|
13218
|
-
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n glass?: boolean | 'subtle' | 'strong'\n}\n\nconst {\n class: classProp = '',\n className = '',\n glass = false,\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-scroll-area',\n glass && 'ui-scroll-area--glass',\n glass === 'subtle' && 'ui-glass-subtle',\n glass === 'strong' && 'ui-glass-strong'\n], classProp, className)\n---\n\n<div\n class:list={classList}\n {...passthrough}\n>\n <slot />\n</div>\n",
|
|
13219
|
-
"category": "Layout",
|
|
13220
|
-
"collections": [],
|
|
14390
|
+
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n glass?: boolean | 'subtle' | 'strong'\n}\n\nconst {\n class: classProp = '',\n className = '',\n glass = false,\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-scroll-area',\n glass && 'ui-scroll-area--glass',\n glass === 'subtle' && 'ui-glass-subtle',\n glass === 'strong' && 'ui-glass-strong'\n], classProp, className)\n---\n\n<div\n class:list={classList}\n {...passthrough}\n>\n <slot />\n</div>\n",
|
|
14391
|
+
"category": "Layout",
|
|
14392
|
+
"collections": [],
|
|
14393
|
+
"dependencies": [
|
|
14394
|
+
"styles"
|
|
14395
|
+
],
|
|
14396
|
+
"description": "Provides a styled scroll container.",
|
|
14397
|
+
"files": [
|
|
14398
|
+
"packages/astro/components/ScrollArea.astro",
|
|
14399
|
+
"packages/astro/styles/lumen.css"
|
|
14400
|
+
],
|
|
14401
|
+
"frameworkDetails": {
|
|
14402
|
+
"astro": {
|
|
14403
|
+
"available": true,
|
|
14404
|
+
"example": "<ScrollArea style=\"max-height: 18rem\"><p>Long release notes...</p></ScrollArea>",
|
|
14405
|
+
"importStatement": "import { ScrollArea } from '@santi020k/lumen-astro'",
|
|
14406
|
+
"language": "astro",
|
|
14407
|
+
"packageName": "@santi020k/lumen-astro",
|
|
14408
|
+
"props": [
|
|
14409
|
+
{
|
|
14410
|
+
"name": "class",
|
|
14411
|
+
"optional": true,
|
|
14412
|
+
"type": "string | null"
|
|
14413
|
+
},
|
|
14414
|
+
{
|
|
14415
|
+
"name": "className",
|
|
14416
|
+
"optional": true,
|
|
14417
|
+
"type": "string"
|
|
14418
|
+
},
|
|
14419
|
+
{
|
|
14420
|
+
"name": "glass",
|
|
14421
|
+
"optional": true,
|
|
14422
|
+
"type": "boolean | 'subtle' | 'strong'"
|
|
14423
|
+
}
|
|
14424
|
+
],
|
|
14425
|
+
"propsExtends": "HTMLAttributes<'div'>",
|
|
14426
|
+
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n glass?: boolean | 'subtle' | 'strong'\n}\n\nconst {\n class: classProp = '',\n className = '',\n glass = false,\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-scroll-area',\n glass && 'ui-scroll-area--glass',\n glass === 'subtle' && 'ui-glass-subtle',\n glass === 'strong' && 'ui-glass-strong'\n], classProp, className)\n---\n\n<div\n class:list={classList}\n {...passthrough}\n>\n <slot />\n</div>\n",
|
|
14427
|
+
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
14428
|
+
},
|
|
14429
|
+
"elements": {
|
|
14430
|
+
"attributes": [
|
|
14431
|
+
"glass",
|
|
14432
|
+
"children",
|
|
14433
|
+
"class, className",
|
|
14434
|
+
"...native attributes"
|
|
14435
|
+
],
|
|
14436
|
+
"available": true,
|
|
14437
|
+
"behavior": {
|
|
14438
|
+
"mode": "registration",
|
|
14439
|
+
"setup": "Call defineLumenElements() once before rendering Lumen custom elements."
|
|
14440
|
+
},
|
|
14441
|
+
"example": "<lumen-scroll-area style=\"max-height: 18rem\"><p>Long release notes...</p></lumen-scroll-area>",
|
|
14442
|
+
"importStatement": "import { defineLumenElements } from '@santi020k/lumen-elements/define'",
|
|
14443
|
+
"language": "html",
|
|
14444
|
+
"packageName": "@santi020k/lumen-elements",
|
|
14445
|
+
"props": [],
|
|
14446
|
+
"propsExtends": "HTMLElement attributes",
|
|
14447
|
+
"registration": "defineLumenElements()",
|
|
14448
|
+
"source": "ScrollArea: { attributeClasses: glassAttributeClasses('ui-scroll-area--glass'), baseClassName: 'ui-scroll-area', tagName: 'lumen-scroll-area' }",
|
|
14449
|
+
"styleImport": "import '@santi020k/lumen-elements/styles.css'",
|
|
14450
|
+
"tagName": "lumen-scroll-area"
|
|
14451
|
+
},
|
|
14452
|
+
"react": {
|
|
14453
|
+
"available": true,
|
|
14454
|
+
"example": "<ScrollArea style={{ maxHeight: '18rem' }}><p>Long release notes...</p></ScrollArea>",
|
|
14455
|
+
"importStatement": "import { ScrollArea } from '@santi020k/lumen-react'",
|
|
14456
|
+
"language": "tsx",
|
|
14457
|
+
"packageName": "@santi020k/lumen-react",
|
|
14458
|
+
"props": [
|
|
14459
|
+
{
|
|
14460
|
+
"name": "glass",
|
|
14461
|
+
"optional": true,
|
|
14462
|
+
"type": "LumenGlassProp"
|
|
14463
|
+
}
|
|
14464
|
+
],
|
|
14465
|
+
"propsExtends": "ComponentPropsWithoutRef<'div'>",
|
|
14466
|
+
"source": "export interface ScrollAreaProps extends ComponentPropsWithoutRef<'div'> {\n glass?: LumenGlassProp\n}\n\nexport const ScrollArea = ({ className, glass = false, ...props }: ScrollAreaProps) => (\n <div className={composeClassName('ui-scroll-area', glassClass('ui-scroll-area', glass), className)} {...props} />\n)",
|
|
14467
|
+
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
14468
|
+
}
|
|
14469
|
+
},
|
|
14470
|
+
"frameworks": {
|
|
14471
|
+
"astro": true,
|
|
14472
|
+
"elements": true,
|
|
14473
|
+
"react": true
|
|
14474
|
+
},
|
|
14475
|
+
"guidance": null,
|
|
14476
|
+
"kebab": "scroll-area",
|
|
14477
|
+
"keyboardInteractions": [],
|
|
14478
|
+
"keywords": [
|
|
14479
|
+
"container",
|
|
14480
|
+
"layout",
|
|
14481
|
+
"provides",
|
|
14482
|
+
"scroll",
|
|
14483
|
+
"scrollarea",
|
|
14484
|
+
"styled"
|
|
14485
|
+
],
|
|
14486
|
+
"name": "ScrollArea",
|
|
14487
|
+
"props": [
|
|
14488
|
+
{
|
|
14489
|
+
"name": "class",
|
|
14490
|
+
"optional": true,
|
|
14491
|
+
"type": "string | null"
|
|
14492
|
+
},
|
|
14493
|
+
{
|
|
14494
|
+
"name": "className",
|
|
14495
|
+
"optional": true,
|
|
14496
|
+
"type": "string"
|
|
14497
|
+
},
|
|
14498
|
+
{
|
|
14499
|
+
"name": "glass",
|
|
14500
|
+
"optional": true,
|
|
14501
|
+
"type": "boolean | 'subtle' | 'strong'"
|
|
14502
|
+
}
|
|
14503
|
+
],
|
|
14504
|
+
"propsExtends": "HTMLAttributes<'div'>",
|
|
14505
|
+
"recipes": [],
|
|
14506
|
+
"runtimeEvents": []
|
|
14507
|
+
},
|
|
14508
|
+
{
|
|
14509
|
+
"apiReference": [
|
|
14510
|
+
{
|
|
14511
|
+
"attribute": "position",
|
|
14512
|
+
"defaultValue": "\"top\"",
|
|
14513
|
+
"description": "Pins the progress indicator to a viewport edge.",
|
|
14514
|
+
"values": "\"top\" | \"bottom\""
|
|
14515
|
+
},
|
|
14516
|
+
{
|
|
14517
|
+
"attribute": "aria-label",
|
|
14518
|
+
"defaultValue": "\"Reading progress\"",
|
|
14519
|
+
"description": "Names the live document-progress indicator for assistive technology.",
|
|
14520
|
+
"values": "string"
|
|
14521
|
+
},
|
|
14522
|
+
{
|
|
14523
|
+
"attribute": "class, className",
|
|
14524
|
+
"defaultValue": "\"\"",
|
|
14525
|
+
"description": "Merges custom classes with the generated ui-* root classes.",
|
|
14526
|
+
"values": "string"
|
|
14527
|
+
},
|
|
14528
|
+
{
|
|
14529
|
+
"attribute": "...native attributes",
|
|
14530
|
+
"defaultValue": "-",
|
|
14531
|
+
"description": "Forwards standard attributes to the root element unless the component consumes them.",
|
|
14532
|
+
"values": "HTML attributes"
|
|
14533
|
+
}
|
|
14534
|
+
],
|
|
14535
|
+
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n position?: 'bottom' | 'top'\n}\n\nconst {\n 'aria-label': ariaLabel = 'Reading progress',\n class: classProp = '',\n className = '',\n position = 'top',\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-scroll-progress',\n position === 'bottom' && 'ui-scroll-progress--bottom'\n], classProp, className)\n---\n\n<div\n aria-label={ariaLabel}\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n aria-valuenow=\"0\"\n class:list={classList}\n data-position={position}\n data-ui-scroll-progress\n role=\"progressbar\"\n {...passthrough}\n>\n <span class=\"ui-scroll-progress__bar\"></span>\n</div>\n",
|
|
14536
|
+
"category": "Feedback",
|
|
14537
|
+
"collections": [
|
|
14538
|
+
"Status and messaging"
|
|
14539
|
+
],
|
|
13221
14540
|
"dependencies": [
|
|
13222
|
-
"styles"
|
|
14541
|
+
"styles",
|
|
14542
|
+
"runtime"
|
|
13223
14543
|
],
|
|
13224
|
-
"description": "
|
|
14544
|
+
"description": "Shows the reader’s current position in a long document.",
|
|
13225
14545
|
"files": [
|
|
13226
|
-
"packages/astro/components/
|
|
13227
|
-
"packages/astro/styles/lumen.css"
|
|
14546
|
+
"packages/astro/components/ScrollProgress.astro",
|
|
14547
|
+
"packages/astro/styles/lumen.css",
|
|
14548
|
+
"packages/astro/runtime/UIPrimitives.astro"
|
|
13228
14549
|
],
|
|
13229
14550
|
"frameworkDetails": {
|
|
13230
14551
|
"astro": {
|
|
13231
14552
|
"available": true,
|
|
13232
|
-
"
|
|
13233
|
-
|
|
14553
|
+
"behavior": {
|
|
14554
|
+
"mode": "runtime",
|
|
14555
|
+
"setup": "Mount UIPrimitives once in the application's root layout; do not mount it beside each component."
|
|
14556
|
+
},
|
|
14557
|
+
"example": "<ScrollProgress aria-label=\"Article reading progress\" />",
|
|
14558
|
+
"importStatement": "import { ScrollProgress } from '@santi020k/lumen-astro'",
|
|
13234
14559
|
"language": "astro",
|
|
13235
14560
|
"packageName": "@santi020k/lumen-astro",
|
|
13236
14561
|
"props": [
|
|
@@ -13245,53 +14570,62 @@
|
|
|
13245
14570
|
"type": "string"
|
|
13246
14571
|
},
|
|
13247
14572
|
{
|
|
13248
|
-
"name": "
|
|
14573
|
+
"name": "position",
|
|
13249
14574
|
"optional": true,
|
|
13250
|
-
"type": "
|
|
14575
|
+
"type": "'bottom' | 'top'"
|
|
13251
14576
|
}
|
|
13252
14577
|
],
|
|
13253
14578
|
"propsExtends": "HTMLAttributes<'div'>",
|
|
13254
|
-
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n
|
|
14579
|
+
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n position?: 'bottom' | 'top'\n}\n\nconst {\n 'aria-label': ariaLabel = 'Reading progress',\n class: classProp = '',\n className = '',\n position = 'top',\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-scroll-progress',\n position === 'bottom' && 'ui-scroll-progress--bottom'\n], classProp, className)\n---\n\n<div\n aria-label={ariaLabel}\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n aria-valuenow=\"0\"\n class:list={classList}\n data-position={position}\n data-ui-scroll-progress\n role=\"progressbar\"\n {...passthrough}\n>\n <span class=\"ui-scroll-progress__bar\"></span>\n</div>\n",
|
|
13255
14580
|
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
13256
14581
|
},
|
|
13257
14582
|
"elements": {
|
|
13258
14583
|
"attributes": [
|
|
13259
|
-
"
|
|
13260
|
-
"
|
|
14584
|
+
"aria-label",
|
|
14585
|
+
"aria-valuemax",
|
|
14586
|
+
"aria-valuemin",
|
|
14587
|
+
"aria-valuenow",
|
|
14588
|
+
"data-ui-scroll-progress",
|
|
14589
|
+
"position",
|
|
14590
|
+
"role",
|
|
13261
14591
|
"class, className",
|
|
13262
14592
|
"...native attributes"
|
|
13263
14593
|
],
|
|
13264
14594
|
"available": true,
|
|
13265
14595
|
"behavior": {
|
|
13266
14596
|
"mode": "registration",
|
|
13267
|
-
"setup": "Call defineLumenElements() once before rendering Lumen custom elements."
|
|
14597
|
+
"setup": "Call defineLumenElements() once before rendering Lumen custom elements. Registration includes this component’s interactive behavior."
|
|
13268
14598
|
},
|
|
13269
|
-
"example": "<lumen-scroll-
|
|
14599
|
+
"example": "<lumen-scroll-progress aria-label=\"Article reading progress\"></lumen-scroll-progress>",
|
|
13270
14600
|
"importStatement": "import { defineLumenElements } from '@santi020k/lumen-elements/define'",
|
|
13271
14601
|
"language": "html",
|
|
13272
14602
|
"packageName": "@santi020k/lumen-elements",
|
|
13273
14603
|
"props": [],
|
|
13274
14604
|
"propsExtends": "HTMLElement attributes",
|
|
13275
14605
|
"registration": "defineLumenElements()",
|
|
13276
|
-
"source": "
|
|
14606
|
+
"source": "ScrollProgress: {\n attributeClasses: {\n position: { bottom: 'ui-scroll-progress--bottom' }\n },\n baseClassName: 'ui-scroll-progress',\n defaults: {\n 'aria-label': 'Reading progress',\n 'aria-valuemax': '100',\n 'aria-valuemin': '0',\n 'aria-valuenow': '0',\n 'data-ui-scroll-progress': '',\n position: 'top',\n role: 'progressbar'\n },\n tagName: 'lumen-scroll-progress'\n }",
|
|
13277
14607
|
"styleImport": "import '@santi020k/lumen-elements/styles.css'",
|
|
13278
|
-
"tagName": "lumen-scroll-
|
|
14608
|
+
"tagName": "lumen-scroll-progress"
|
|
13279
14609
|
},
|
|
13280
14610
|
"react": {
|
|
13281
14611
|
"available": true,
|
|
13282
|
-
"
|
|
13283
|
-
|
|
14612
|
+
"behavior": {
|
|
14613
|
+
"mode": "built-in",
|
|
14614
|
+
"setup": "Interactive behavior is implemented by the React component; do not mount Astro UIPrimitives."
|
|
14615
|
+
},
|
|
14616
|
+
"example": "<ScrollProgress aria-label=\"Article reading progress\" />",
|
|
14617
|
+
"importStatement": "import { ScrollProgress } from '@santi020k/lumen-react'",
|
|
13284
14618
|
"language": "tsx",
|
|
13285
14619
|
"packageName": "@santi020k/lumen-react",
|
|
13286
14620
|
"props": [
|
|
13287
14621
|
{
|
|
13288
|
-
"name": "
|
|
14622
|
+
"name": "position",
|
|
13289
14623
|
"optional": true,
|
|
13290
|
-
"type": "
|
|
14624
|
+
"type": "'bottom' | 'top'"
|
|
13291
14625
|
}
|
|
13292
14626
|
],
|
|
13293
14627
|
"propsExtends": "ComponentPropsWithoutRef<'div'>",
|
|
13294
|
-
"source": "export interface
|
|
14628
|
+
"source": "export interface ScrollProgressProps extends ComponentPropsWithoutRef<'div'> {\n position?: 'bottom' | 'top'\n}\n\nexport const ScrollProgress = ({\n 'aria-label': ariaLabel = 'Reading progress',\n className,\n position = 'top',\n ...props\n}: ScrollProgressProps) => {\n const rootRef = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n const root = rootRef.current\n\n if (!root) return\n\n let frame = 0\n\n const update = () => {\n frame = 0\n\n const scrollingElement = document.scrollingElement ?? document.documentElement\n const maximum = scrollingElement.scrollHeight - scrollingElement.clientHeight\n\n const percentage = maximum > 0\n ? Math.min(100, Math.max(0, (scrollingElement.scrollTop / maximum) * 100))\n : 0\n\n const bar = root.querySelector<HTMLElement>('.ui-scroll-progress__bar')\n\n root.setAttribute('aria-valuenow', `${Math.round(percentage)}`)\n\n if (bar) bar.style.transform = `scaleX(${percentage / 100})`\n }\n\n const scheduleUpdate = () => {\n if (frame) return\n\n frame = window.requestAnimationFrame(update)\n }\n\n scheduleUpdate()\n\n window.addEventListener('resize', scheduleUpdate, { passive: true })\n\n window.addEventListener('scroll', scheduleUpdate, { passive: true })\n\n return () => {\n if (frame) window.cancelAnimationFrame(frame)\n\n window.removeEventListener('resize', scheduleUpdate)\n\n window.removeEventListener('scroll', scheduleUpdate)\n }\n }, [])\n\n return (\n <div\n aria-label={ariaLabel}\n aria-valuemax={100}\n aria-valuemin={0}\n aria-valuenow={0}\n className={composeClassName(\n 'ui-scroll-progress',\n position === 'bottom' && 'ui-scroll-progress--bottom',\n className\n )}\n data-position={position}\n data-ui-scroll-progress\n ref={rootRef}\n role=\"progressbar\"\n {...props}\n >\n <span className=\"ui-scroll-progress__bar\" />\n </div>\n )\n}",
|
|
13295
14629
|
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
13296
14630
|
}
|
|
13297
14631
|
},
|
|
@@ -13300,18 +14634,60 @@
|
|
|
13300
14634
|
"elements": true,
|
|
13301
14635
|
"react": true
|
|
13302
14636
|
},
|
|
13303
|
-
"guidance":
|
|
13304
|
-
|
|
14637
|
+
"guidance": {
|
|
14638
|
+
"when": "Use on long reading surfaces when readers benefit from knowing how far they have moved through the current document.",
|
|
14639
|
+
"distinction": "Use Progress for task completion supplied by application state. ScrollProgress derives its value from the document scroll position."
|
|
14640
|
+
},
|
|
14641
|
+
"kebab": "scroll-progress",
|
|
13305
14642
|
"keyboardInteractions": [],
|
|
13306
14643
|
"keywords": [
|
|
13307
|
-
"
|
|
13308
|
-
"
|
|
13309
|
-
"
|
|
14644
|
+
"and",
|
|
14645
|
+
"application",
|
|
14646
|
+
"benefit",
|
|
14647
|
+
"completion",
|
|
14648
|
+
"current",
|
|
14649
|
+
"derives",
|
|
14650
|
+
"document",
|
|
14651
|
+
"empty",
|
|
14652
|
+
"far",
|
|
14653
|
+
"feedback",
|
|
14654
|
+
"for",
|
|
14655
|
+
"from",
|
|
14656
|
+
"guidance",
|
|
14657
|
+
"have",
|
|
14658
|
+
"how",
|
|
14659
|
+
"inline",
|
|
14660
|
+
"its",
|
|
14661
|
+
"knowing",
|
|
14662
|
+
"long",
|
|
14663
|
+
"messaging",
|
|
14664
|
+
"moved",
|
|
14665
|
+
"notifications",
|
|
14666
|
+
"persistent",
|
|
14667
|
+
"position",
|
|
14668
|
+
"progress",
|
|
14669
|
+
"reader",
|
|
14670
|
+
"readers",
|
|
14671
|
+
"reading",
|
|
13310
14672
|
"scroll",
|
|
13311
|
-
"
|
|
13312
|
-
"
|
|
14673
|
+
"scrollprogress",
|
|
14674
|
+
"separate",
|
|
14675
|
+
"shows",
|
|
14676
|
+
"state",
|
|
14677
|
+
"states",
|
|
14678
|
+
"status",
|
|
14679
|
+
"supplied",
|
|
14680
|
+
"surfaces",
|
|
14681
|
+
"task",
|
|
14682
|
+
"the",
|
|
14683
|
+
"they",
|
|
14684
|
+
"through",
|
|
14685
|
+
"transient",
|
|
14686
|
+
"use",
|
|
14687
|
+
"value",
|
|
14688
|
+
"when"
|
|
13313
14689
|
],
|
|
13314
|
-
"name": "
|
|
14690
|
+
"name": "ScrollProgress",
|
|
13315
14691
|
"props": [
|
|
13316
14692
|
{
|
|
13317
14693
|
"name": "class",
|
|
@@ -13324,9 +14700,9 @@
|
|
|
13324
14700
|
"type": "string"
|
|
13325
14701
|
},
|
|
13326
14702
|
{
|
|
13327
|
-
"name": "
|
|
14703
|
+
"name": "position",
|
|
13328
14704
|
"optional": true,
|
|
13329
|
-
"type": "
|
|
14705
|
+
"type": "'bottom' | 'top'"
|
|
13330
14706
|
}
|
|
13331
14707
|
],
|
|
13332
14708
|
"propsExtends": "HTMLAttributes<'div'>",
|
|
@@ -15199,47 +16575,224 @@
|
|
|
15199
16575
|
"name": "Slider",
|
|
15200
16576
|
"props": [
|
|
15201
16577
|
{
|
|
15202
|
-
"name": "class",
|
|
15203
|
-
"optional": true,
|
|
15204
|
-
"type": "string | null"
|
|
16578
|
+
"name": "class",
|
|
16579
|
+
"optional": true,
|
|
16580
|
+
"type": "string | null"
|
|
16581
|
+
},
|
|
16582
|
+
{
|
|
16583
|
+
"name": "className",
|
|
16584
|
+
"optional": true,
|
|
16585
|
+
"type": "string"
|
|
16586
|
+
}
|
|
16587
|
+
],
|
|
16588
|
+
"propsExtends": "HTMLAttributes<'input'>",
|
|
16589
|
+
"recipes": [],
|
|
16590
|
+
"runtimeEvents": []
|
|
16591
|
+
},
|
|
16592
|
+
{
|
|
16593
|
+
"apiReference": [],
|
|
16594
|
+
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n maxCount?: number\n placement?: 'bottom-center' | 'bottom-left' | 'bottom-right' | 'top-center' | 'top-left' | 'top-right'\n}\n\nconst {\n 'aria-atomic': ariaAtomic = 'false',\n 'aria-live': ariaLive = 'polite',\n class: classProp = '',\n className = '',\n maxCount,\n placement = 'bottom-right',\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-sonner'\n], classProp, className)\n---\n\n<div\n aria-atomic={ariaAtomic}\n aria-live={ariaLive}\n data-ui-sonner\n data-ui-toast-max={maxCount}\n data-placement={placement}\n class:list={classList}\n {...passthrough}\n>\n <slot />\n</div>\n",
|
|
16595
|
+
"category": "Feedback",
|
|
16596
|
+
"collections": [],
|
|
16597
|
+
"dependencies": [
|
|
16598
|
+
"styles",
|
|
16599
|
+
"runtime"
|
|
16600
|
+
],
|
|
16601
|
+
"description": "Provides the toast viewport for notifications.",
|
|
16602
|
+
"files": [
|
|
16603
|
+
"packages/astro/components/Sonner.astro",
|
|
16604
|
+
"packages/astro/styles/lumen.css",
|
|
16605
|
+
"packages/astro/runtime/UIPrimitives.astro"
|
|
16606
|
+
],
|
|
16607
|
+
"frameworkDetails": {
|
|
16608
|
+
"astro": {
|
|
16609
|
+
"available": true,
|
|
16610
|
+
"behavior": {
|
|
16611
|
+
"mode": "runtime",
|
|
16612
|
+
"setup": "Mount UIPrimitives once in the application's root layout; do not mount it beside each component."
|
|
16613
|
+
},
|
|
16614
|
+
"example": "<Sonner />",
|
|
16615
|
+
"importStatement": "import { Sonner } from '@santi020k/lumen-astro'",
|
|
16616
|
+
"language": "astro",
|
|
16617
|
+
"packageName": "@santi020k/lumen-astro",
|
|
16618
|
+
"props": [
|
|
16619
|
+
{
|
|
16620
|
+
"name": "class",
|
|
16621
|
+
"optional": true,
|
|
16622
|
+
"type": "string | null"
|
|
16623
|
+
},
|
|
16624
|
+
{
|
|
16625
|
+
"name": "className",
|
|
16626
|
+
"optional": true,
|
|
16627
|
+
"type": "string"
|
|
16628
|
+
},
|
|
16629
|
+
{
|
|
16630
|
+
"name": "maxCount",
|
|
16631
|
+
"optional": true,
|
|
16632
|
+
"type": "number"
|
|
16633
|
+
},
|
|
16634
|
+
{
|
|
16635
|
+
"name": "placement",
|
|
16636
|
+
"optional": true,
|
|
16637
|
+
"type": "'bottom-center' | 'bottom-left' | 'bottom-right' | 'top-center' | 'top-left' | 'top-right'"
|
|
16638
|
+
}
|
|
16639
|
+
],
|
|
16640
|
+
"propsExtends": "HTMLAttributes<'div'>",
|
|
16641
|
+
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n maxCount?: number\n placement?: 'bottom-center' | 'bottom-left' | 'bottom-right' | 'top-center' | 'top-left' | 'top-right'\n}\n\nconst {\n 'aria-atomic': ariaAtomic = 'false',\n 'aria-live': ariaLive = 'polite',\n class: classProp = '',\n className = '',\n maxCount,\n placement = 'bottom-right',\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-sonner'\n], classProp, className)\n---\n\n<div\n aria-atomic={ariaAtomic}\n aria-live={ariaLive}\n data-ui-sonner\n data-ui-toast-max={maxCount}\n data-placement={placement}\n class:list={classList}\n {...passthrough}\n>\n <slot />\n</div>\n",
|
|
16642
|
+
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
16643
|
+
},
|
|
16644
|
+
"elements": {
|
|
16645
|
+
"attributes": [
|
|
16646
|
+
"data-ui-sonner"
|
|
16647
|
+
],
|
|
16648
|
+
"available": true,
|
|
16649
|
+
"behavior": {
|
|
16650
|
+
"mode": "registration",
|
|
16651
|
+
"setup": "Call defineLumenElements() once before rendering Lumen custom elements. Registration includes this component’s interactive behavior."
|
|
16652
|
+
},
|
|
16653
|
+
"example": "<lumen-sonner></lumen-sonner>",
|
|
16654
|
+
"importStatement": "import { defineLumenElements } from '@santi020k/lumen-elements/define'",
|
|
16655
|
+
"language": "html",
|
|
16656
|
+
"packageName": "@santi020k/lumen-elements",
|
|
16657
|
+
"props": [],
|
|
16658
|
+
"propsExtends": "HTMLElement attributes",
|
|
16659
|
+
"registration": "defineLumenElements()",
|
|
16660
|
+
"source": "Sonner: { baseClassName: 'ui-sonner', defaults: { 'data-ui-sonner': '' }, tagName: 'lumen-sonner' }",
|
|
16661
|
+
"styleImport": "import '@santi020k/lumen-elements/styles.css'",
|
|
16662
|
+
"tagName": "lumen-sonner"
|
|
16663
|
+
},
|
|
16664
|
+
"react": {
|
|
16665
|
+
"available": true,
|
|
16666
|
+
"behavior": {
|
|
16667
|
+
"mode": "adapter",
|
|
16668
|
+
"setup": "The React component exposes the documented data attributes; app-level state must implement the documented interactive and event behavior. Do not mount Astro UIPrimitives."
|
|
16669
|
+
},
|
|
16670
|
+
"example": "<Sonner />",
|
|
16671
|
+
"importStatement": "import { Sonner } from '@santi020k/lumen-react'",
|
|
16672
|
+
"language": "tsx",
|
|
16673
|
+
"packageName": "@santi020k/lumen-react",
|
|
16674
|
+
"props": [],
|
|
16675
|
+
"propsExtends": "ComponentPropsWithoutRef<'div'>",
|
|
16676
|
+
"source": "export type SonnerProps = ComponentPropsWithoutRef<'div'>\n\nexport const Sonner = ({ className, ...props }: SonnerProps) => (\n <div className={composeClassName('ui-sonner', className)} data-ui-sonner {...props} />\n)",
|
|
16677
|
+
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
16678
|
+
}
|
|
16679
|
+
},
|
|
16680
|
+
"frameworks": {
|
|
16681
|
+
"astro": true,
|
|
16682
|
+
"elements": true,
|
|
16683
|
+
"react": true
|
|
16684
|
+
},
|
|
16685
|
+
"guidance": null,
|
|
16686
|
+
"kebab": "sonner",
|
|
16687
|
+
"keyboardInteractions": [],
|
|
16688
|
+
"keywords": [
|
|
16689
|
+
"feedback",
|
|
16690
|
+
"for",
|
|
16691
|
+
"notifications",
|
|
16692
|
+
"provides",
|
|
16693
|
+
"sonner",
|
|
16694
|
+
"the",
|
|
16695
|
+
"toast",
|
|
16696
|
+
"viewport"
|
|
16697
|
+
],
|
|
16698
|
+
"name": "Sonner",
|
|
16699
|
+
"props": [
|
|
16700
|
+
{
|
|
16701
|
+
"name": "class",
|
|
16702
|
+
"optional": true,
|
|
16703
|
+
"type": "string | null"
|
|
16704
|
+
},
|
|
16705
|
+
{
|
|
16706
|
+
"name": "className",
|
|
16707
|
+
"optional": true,
|
|
16708
|
+
"type": "string"
|
|
16709
|
+
},
|
|
16710
|
+
{
|
|
16711
|
+
"name": "maxCount",
|
|
16712
|
+
"optional": true,
|
|
16713
|
+
"type": "number"
|
|
16714
|
+
},
|
|
16715
|
+
{
|
|
16716
|
+
"name": "placement",
|
|
16717
|
+
"optional": true,
|
|
16718
|
+
"type": "'bottom-center' | 'bottom-left' | 'bottom-right' | 'top-center' | 'top-left' | 'top-right'"
|
|
16719
|
+
}
|
|
16720
|
+
],
|
|
16721
|
+
"propsExtends": "HTMLAttributes<'div'>",
|
|
16722
|
+
"recipes": [],
|
|
16723
|
+
"runtimeEvents": []
|
|
16724
|
+
},
|
|
16725
|
+
{
|
|
16726
|
+
"apiReference": [
|
|
16727
|
+
{
|
|
16728
|
+
"attribute": "values",
|
|
16729
|
+
"defaultValue": "required",
|
|
16730
|
+
"description": "Provides ordered values for the compact trend.",
|
|
16731
|
+
"values": "number[]"
|
|
16732
|
+
},
|
|
16733
|
+
{
|
|
16734
|
+
"attribute": "label",
|
|
16735
|
+
"defaultValue": "required",
|
|
16736
|
+
"description": "Communicates the trend in text because the SVG is intentionally decorative.",
|
|
16737
|
+
"values": "string"
|
|
16738
|
+
},
|
|
16739
|
+
{
|
|
16740
|
+
"attribute": "area",
|
|
16741
|
+
"defaultValue": "false",
|
|
16742
|
+
"description": "Adds a subtle tokenized fill below the line.",
|
|
16743
|
+
"values": "boolean"
|
|
15205
16744
|
},
|
|
15206
16745
|
{
|
|
15207
|
-
"
|
|
15208
|
-
"
|
|
15209
|
-
"
|
|
16746
|
+
"attribute": "showEndpoint",
|
|
16747
|
+
"defaultValue": "true",
|
|
16748
|
+
"description": "Marks the latest value with a color-independent endpoint.",
|
|
16749
|
+
"values": "boolean"
|
|
16750
|
+
},
|
|
16751
|
+
{
|
|
16752
|
+
"attribute": "tone",
|
|
16753
|
+
"defaultValue": "\"series-1\"",
|
|
16754
|
+
"description": "Selects a categorical or explicitly semantic chart tone.",
|
|
16755
|
+
"values": "LumenChartTone"
|
|
16756
|
+
},
|
|
16757
|
+
{
|
|
16758
|
+
"attribute": "class, className",
|
|
16759
|
+
"defaultValue": "\"\"",
|
|
16760
|
+
"description": "Merges custom classes with the generated ui-* root classes.",
|
|
16761
|
+
"values": "string"
|
|
16762
|
+
},
|
|
16763
|
+
{
|
|
16764
|
+
"attribute": "...native attributes",
|
|
16765
|
+
"defaultValue": "-",
|
|
16766
|
+
"description": "Forwards standard attributes to the root element unless the component consumes them.",
|
|
16767
|
+
"values": "HTML attributes"
|
|
15210
16768
|
}
|
|
15211
16769
|
],
|
|
15212
|
-
"
|
|
15213
|
-
"
|
|
15214
|
-
"
|
|
15215
|
-
|
|
15216
|
-
|
|
15217
|
-
"apiReference": [],
|
|
15218
|
-
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n maxCount?: number\n placement?: 'bottom-center' | 'bottom-left' | 'bottom-right' | 'top-center' | 'top-left' | 'top-right'\n}\n\nconst {\n 'aria-atomic': ariaAtomic = 'false',\n 'aria-live': ariaLive = 'polite',\n class: classProp = '',\n className = '',\n maxCount,\n placement = 'bottom-right',\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-sonner'\n], classProp, className)\n---\n\n<div\n aria-atomic={ariaAtomic}\n aria-live={ariaLive}\n data-ui-sonner\n data-ui-toast-max={maxCount}\n data-placement={placement}\n class:list={classList}\n {...passthrough}\n>\n <slot />\n</div>\n",
|
|
15219
|
-
"category": "Feedback",
|
|
15220
|
-
"collections": [],
|
|
16770
|
+
"astroSource": "---\nimport {\n composeClassName,\n createLumenLineGeometry,\n type LumenChartTone,\n resolveLumenChartTone\n} from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'span'> {\n area?: boolean\n class?: string | null\n className?: string\n label: string\n showEndpoint?: boolean\n tone?: LumenChartTone\n values: readonly number[]\n}\n\nconst {\n area = false,\n class: classProp = '',\n className = '',\n label,\n showEndpoint = true,\n tone,\n values,\n ...rest\n} = Astro.props\nconst data = values.map((value, index) => ({ x: index, y: value }))\nconst geometry = createLumenLineGeometry(data, {\n height: 40,\n padding: 3,\n width: 120\n})\nconst resolvedTone = resolveLumenChartTone(tone)\nconst endpoint = geometry.points[geometry.points.length - 1]\n---\n\n<span\n aria-label={label}\n class={composeClassName(\n 'ui-sparkline',\n `ui-chart-tone--${resolvedTone}`,\n classProp,\n className\n )}\n role=\"img\"\n {...rest}\n>\n <svg aria-hidden=\"true\" preserveAspectRatio=\"none\" viewBox=\"0 0 120 40\">\n {\n area &&\n geometry.areaPaths.map((path) => (\n <path class=\"ui-sparkline__area\" d={path} />\n ))\n }\n <path class=\"ui-sparkline__line\" d={geometry.path} />\n {\n showEndpoint && endpoint && (\n <circle\n class=\"ui-sparkline__endpoint\"\n cx={endpoint.xCoordinate}\n cy={endpoint.yCoordinate}\n r=\"2.5\"\n />\n )\n }\n </svg>\n <span class=\"ui-sr-only\">{label}</span>\n</span>\n",
|
|
16771
|
+
"category": "Data display",
|
|
16772
|
+
"collections": [
|
|
16773
|
+
"Data visualization"
|
|
16774
|
+
],
|
|
15221
16775
|
"dependencies": [
|
|
15222
|
-
"styles"
|
|
15223
|
-
"runtime"
|
|
16776
|
+
"styles"
|
|
15224
16777
|
],
|
|
15225
|
-
"description": "
|
|
16778
|
+
"description": "Shows a compact, text-labelled trend beside an existing metric.",
|
|
15226
16779
|
"files": [
|
|
15227
|
-
"packages/astro/components/
|
|
15228
|
-
"packages/astro/styles/lumen.css"
|
|
15229
|
-
"packages/astro/runtime/UIPrimitives.astro"
|
|
16780
|
+
"packages/astro/components/Sparkline.astro",
|
|
16781
|
+
"packages/astro/styles/lumen.css"
|
|
15230
16782
|
],
|
|
15231
16783
|
"frameworkDetails": {
|
|
15232
16784
|
"astro": {
|
|
15233
16785
|
"available": true,
|
|
15234
|
-
"
|
|
15235
|
-
|
|
15236
|
-
"setup": "Mount UIPrimitives once in the application's root layout; do not mount it beside each component."
|
|
15237
|
-
},
|
|
15238
|
-
"example": "<Sonner />",
|
|
15239
|
-
"importStatement": "import { Sonner } from '@santi020k/lumen-astro'",
|
|
16786
|
+
"example": "<Sparkline label=\"Downloads increased from 42 to 91\" values={[42, 48, 63, 58, 74, 91]} area />",
|
|
16787
|
+
"importStatement": "import { Sparkline } from '@santi020k/lumen-astro'",
|
|
15240
16788
|
"language": "astro",
|
|
15241
16789
|
"packageName": "@santi020k/lumen-astro",
|
|
15242
16790
|
"props": [
|
|
16791
|
+
{
|
|
16792
|
+
"name": "area",
|
|
16793
|
+
"optional": true,
|
|
16794
|
+
"type": "boolean"
|
|
16795
|
+
},
|
|
15243
16796
|
{
|
|
15244
16797
|
"name": "class",
|
|
15245
16798
|
"optional": true,
|
|
@@ -15251,53 +16804,91 @@
|
|
|
15251
16804
|
"type": "string"
|
|
15252
16805
|
},
|
|
15253
16806
|
{
|
|
15254
|
-
"name": "
|
|
16807
|
+
"name": "label",
|
|
16808
|
+
"optional": false,
|
|
16809
|
+
"type": "string"
|
|
16810
|
+
},
|
|
16811
|
+
{
|
|
16812
|
+
"name": "showEndpoint",
|
|
15255
16813
|
"optional": true,
|
|
15256
|
-
"type": "
|
|
16814
|
+
"type": "boolean"
|
|
15257
16815
|
},
|
|
15258
16816
|
{
|
|
15259
|
-
"name": "
|
|
16817
|
+
"name": "tone",
|
|
15260
16818
|
"optional": true,
|
|
15261
|
-
"type": "
|
|
16819
|
+
"type": "LumenChartTone"
|
|
16820
|
+
},
|
|
16821
|
+
{
|
|
16822
|
+
"name": "values",
|
|
16823
|
+
"optional": false,
|
|
16824
|
+
"type": "readonly number[]"
|
|
15262
16825
|
}
|
|
15263
16826
|
],
|
|
15264
|
-
"propsExtends": "HTMLAttributes<'
|
|
15265
|
-
"source": "---\nimport {
|
|
16827
|
+
"propsExtends": "HTMLAttributes<'span'>",
|
|
16828
|
+
"source": "---\nimport {\n composeClassName,\n createLumenLineGeometry,\n type LumenChartTone,\n resolveLumenChartTone\n} from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'span'> {\n area?: boolean\n class?: string | null\n className?: string\n label: string\n showEndpoint?: boolean\n tone?: LumenChartTone\n values: readonly number[]\n}\n\nconst {\n area = false,\n class: classProp = '',\n className = '',\n label,\n showEndpoint = true,\n tone,\n values,\n ...rest\n} = Astro.props\nconst data = values.map((value, index) => ({ x: index, y: value }))\nconst geometry = createLumenLineGeometry(data, {\n height: 40,\n padding: 3,\n width: 120\n})\nconst resolvedTone = resolveLumenChartTone(tone)\nconst endpoint = geometry.points[geometry.points.length - 1]\n---\n\n<span\n aria-label={label}\n class={composeClassName(\n 'ui-sparkline',\n `ui-chart-tone--${resolvedTone}`,\n classProp,\n className\n )}\n role=\"img\"\n {...rest}\n>\n <svg aria-hidden=\"true\" preserveAspectRatio=\"none\" viewBox=\"0 0 120 40\">\n {\n area &&\n geometry.areaPaths.map((path) => (\n <path class=\"ui-sparkline__area\" d={path} />\n ))\n }\n <path class=\"ui-sparkline__line\" d={geometry.path} />\n {\n showEndpoint && endpoint && (\n <circle\n class=\"ui-sparkline__endpoint\"\n cx={endpoint.xCoordinate}\n cy={endpoint.yCoordinate}\n r=\"2.5\"\n />\n )\n }\n </svg>\n <span class=\"ui-sr-only\">{label}</span>\n</span>\n",
|
|
15266
16829
|
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
15267
16830
|
},
|
|
15268
16831
|
"elements": {
|
|
15269
16832
|
"attributes": [
|
|
15270
|
-
"
|
|
16833
|
+
"values",
|
|
16834
|
+
"label",
|
|
16835
|
+
"area",
|
|
16836
|
+
"showEndpoint",
|
|
16837
|
+
"tone",
|
|
16838
|
+
"class, className",
|
|
16839
|
+
"...native attributes"
|
|
15271
16840
|
],
|
|
15272
16841
|
"available": true,
|
|
15273
16842
|
"behavior": {
|
|
15274
16843
|
"mode": "registration",
|
|
15275
|
-
"setup": "Call defineLumenElements() once before rendering Lumen custom elements.
|
|
16844
|
+
"setup": "Call defineLumenElements() once before rendering Lumen custom elements."
|
|
15276
16845
|
},
|
|
15277
|
-
"example": "<lumen-
|
|
16846
|
+
"example": "<lumen-sparkline></lumen-sparkline>",
|
|
15278
16847
|
"importStatement": "import { defineLumenElements } from '@santi020k/lumen-elements/define'",
|
|
15279
16848
|
"language": "html",
|
|
15280
16849
|
"packageName": "@santi020k/lumen-elements",
|
|
15281
16850
|
"props": [],
|
|
15282
16851
|
"propsExtends": "HTMLElement attributes",
|
|
15283
16852
|
"registration": "defineLumenElements()",
|
|
15284
|
-
"source": "
|
|
16853
|
+
"source": "Sparkline: { baseClassName: 'ui-sparkline', tagName: 'lumen-sparkline' }",
|
|
15285
16854
|
"styleImport": "import '@santi020k/lumen-elements/styles.css'",
|
|
15286
|
-
"tagName": "lumen-
|
|
16855
|
+
"tagName": "lumen-sparkline"
|
|
15287
16856
|
},
|
|
15288
16857
|
"react": {
|
|
15289
16858
|
"available": true,
|
|
15290
|
-
"
|
|
15291
|
-
|
|
15292
|
-
"setup": "The React component exposes the documented data attributes; app-level state must implement the documented interactive and event behavior. Do not mount Astro UIPrimitives."
|
|
15293
|
-
},
|
|
15294
|
-
"example": "<Sonner />",
|
|
15295
|
-
"importStatement": "import { Sonner } from '@santi020k/lumen-react'",
|
|
16859
|
+
"example": "<Sparkline label=\"Downloads increased from 42 to 91\" values={[42, 48, 63, 58, 74, 91]} area />",
|
|
16860
|
+
"importStatement": "import { Sparkline } from '@santi020k/lumen-react'",
|
|
15296
16861
|
"language": "tsx",
|
|
15297
16862
|
"packageName": "@santi020k/lumen-react",
|
|
15298
|
-
"props": [
|
|
15299
|
-
|
|
15300
|
-
|
|
16863
|
+
"props": [
|
|
16864
|
+
{
|
|
16865
|
+
"name": "area",
|
|
16866
|
+
"optional": true,
|
|
16867
|
+
"type": "boolean"
|
|
16868
|
+
},
|
|
16869
|
+
{
|
|
16870
|
+
"name": "label",
|
|
16871
|
+
"optional": true,
|
|
16872
|
+
"type": "string"
|
|
16873
|
+
},
|
|
16874
|
+
{
|
|
16875
|
+
"name": "showEndpoint",
|
|
16876
|
+
"optional": true,
|
|
16877
|
+
"type": "boolean"
|
|
16878
|
+
},
|
|
16879
|
+
{
|
|
16880
|
+
"name": "tone",
|
|
16881
|
+
"optional": true,
|
|
16882
|
+
"type": "LumenChartTone"
|
|
16883
|
+
},
|
|
16884
|
+
{
|
|
16885
|
+
"name": "values",
|
|
16886
|
+
"optional": true,
|
|
16887
|
+
"type": "readonly number[]"
|
|
16888
|
+
}
|
|
16889
|
+
],
|
|
16890
|
+
"propsExtends": "Omit<ComponentPropsWithoutRef<'span'>, 'children'>",
|
|
16891
|
+
"source": "export interface SparklineProps extends Omit<ComponentPropsWithoutRef<'span'>, 'children'> {\n area?: boolean\n label?: string\n showEndpoint?: boolean\n tone?: LumenChartTone\n values?: readonly number[]\n}\n\nexport const Sparkline = ({\n area = false,\n className,\n label = 'Trend',\n showEndpoint = true,\n tone,\n values = emptyChartValues,\n ...props\n}: SparklineProps) => {\n const geometry = createLumenLineGeometry(\n values.map((value, index) => ({ x: index, y: value })),\n { height: 40, padding: 3, width: 120 }\n )\n\n const resolvedTone = resolveLumenChartTone(tone)\n const endpoint = geometry.points.at(-1)\n\n return (\n <span\n aria-label={label}\n className={composeClassName('ui-sparkline', `ui-chart-tone--${resolvedTone}`, className)}\n role=\"img\"\n {...props}\n >\n <svg aria-hidden=\"true\" preserveAspectRatio=\"none\" viewBox=\"0 0 120 40\">\n {area && geometry.areaPaths.map(path => (\n <path className=\"ui-sparkline__area\" d={path} key={path} />\n ))}\n <path className=\"ui-sparkline__line\" d={geometry.path} />\n {showEndpoint && endpoint && (\n <circle\n className=\"ui-sparkline__endpoint\"\n cx={endpoint.xCoordinate}\n cy={endpoint.yCoordinate}\n r=\"2.5\"\n />\n )}\n </svg>\n <span className=\"ui-sr-only\">{label}</span>\n </span>\n )\n}",
|
|
15301
16892
|
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
15302
16893
|
}
|
|
15303
16894
|
},
|
|
@@ -15306,21 +16897,66 @@
|
|
|
15306
16897
|
"elements": true,
|
|
15307
16898
|
"react": true
|
|
15308
16899
|
},
|
|
15309
|
-
"guidance":
|
|
15310
|
-
|
|
16900
|
+
"guidance": {
|
|
16901
|
+
"when": "Use beside a metric when a compact trend adds meaning and at least two valid samples exist.",
|
|
16902
|
+
"distinction": "Use LineChart when axes, multiple series, thresholds, exact values, or a data table are important."
|
|
16903
|
+
},
|
|
16904
|
+
"kebab": "sparkline",
|
|
15311
16905
|
"keyboardInteractions": [],
|
|
15312
16906
|
"keywords": [
|
|
15313
|
-
"
|
|
15314
|
-
"
|
|
15315
|
-
"
|
|
15316
|
-
"
|
|
15317
|
-
"
|
|
16907
|
+
"adds",
|
|
16908
|
+
"and",
|
|
16909
|
+
"are",
|
|
16910
|
+
"axes",
|
|
16911
|
+
"beside",
|
|
16912
|
+
"breakdowns",
|
|
16913
|
+
"categorical",
|
|
16914
|
+
"compact",
|
|
16915
|
+
"comparisons",
|
|
16916
|
+
"custom",
|
|
16917
|
+
"data",
|
|
16918
|
+
"display",
|
|
16919
|
+
"exact",
|
|
16920
|
+
"exist",
|
|
16921
|
+
"existing",
|
|
16922
|
+
"important",
|
|
16923
|
+
"labelled",
|
|
16924
|
+
"least",
|
|
16925
|
+
"linechart",
|
|
16926
|
+
"match",
|
|
16927
|
+
"meaning",
|
|
16928
|
+
"metric",
|
|
16929
|
+
"metrics",
|
|
16930
|
+
"multiple",
|
|
16931
|
+
"ordered",
|
|
16932
|
+
"part",
|
|
16933
|
+
"plots",
|
|
16934
|
+
"question",
|
|
16935
|
+
"samples",
|
|
16936
|
+
"series",
|
|
16937
|
+
"shows",
|
|
16938
|
+
"sparkline",
|
|
16939
|
+
"table",
|
|
16940
|
+
"text",
|
|
15318
16941
|
"the",
|
|
15319
|
-
"
|
|
15320
|
-
"
|
|
16942
|
+
"thresholds",
|
|
16943
|
+
"trend",
|
|
16944
|
+
"trends",
|
|
16945
|
+
"two",
|
|
16946
|
+
"use",
|
|
16947
|
+
"valid",
|
|
16948
|
+
"values",
|
|
16949
|
+
"visualization",
|
|
16950
|
+
"when",
|
|
16951
|
+
"whole"
|
|
15321
16952
|
],
|
|
15322
|
-
"name": "
|
|
16953
|
+
"name": "Sparkline",
|
|
15323
16954
|
"props": [
|
|
16955
|
+
{
|
|
16956
|
+
"name": "area",
|
|
16957
|
+
"optional": true,
|
|
16958
|
+
"type": "boolean"
|
|
16959
|
+
},
|
|
15324
16960
|
{
|
|
15325
16961
|
"name": "class",
|
|
15326
16962
|
"optional": true,
|
|
@@ -15332,18 +16968,33 @@
|
|
|
15332
16968
|
"type": "string"
|
|
15333
16969
|
},
|
|
15334
16970
|
{
|
|
15335
|
-
"name": "
|
|
16971
|
+
"name": "label",
|
|
16972
|
+
"optional": false,
|
|
16973
|
+
"type": "string"
|
|
16974
|
+
},
|
|
16975
|
+
{
|
|
16976
|
+
"name": "showEndpoint",
|
|
15336
16977
|
"optional": true,
|
|
15337
|
-
"type": "
|
|
16978
|
+
"type": "boolean"
|
|
15338
16979
|
},
|
|
15339
16980
|
{
|
|
15340
|
-
"name": "
|
|
16981
|
+
"name": "tone",
|
|
15341
16982
|
"optional": true,
|
|
15342
|
-
"type": "
|
|
16983
|
+
"type": "LumenChartTone"
|
|
16984
|
+
},
|
|
16985
|
+
{
|
|
16986
|
+
"name": "values",
|
|
16987
|
+
"optional": false,
|
|
16988
|
+
"type": "readonly number[]"
|
|
16989
|
+
}
|
|
16990
|
+
],
|
|
16991
|
+
"propsExtends": "HTMLAttributes<'span'>",
|
|
16992
|
+
"recipes": [
|
|
16993
|
+
{
|
|
16994
|
+
"name": "data-visualization",
|
|
16995
|
+
"type": "recipe"
|
|
15343
16996
|
}
|
|
15344
16997
|
],
|
|
15345
|
-
"propsExtends": "HTMLAttributes<'div'>",
|
|
15346
|
-
"recipes": [],
|
|
15347
16998
|
"runtimeEvents": []
|
|
15348
16999
|
},
|
|
15349
17000
|
{
|
|
@@ -18889,7 +20540,7 @@
|
|
|
18889
20540
|
"values": "HTML attributes"
|
|
18890
20541
|
}
|
|
18891
20542
|
],
|
|
18892
|
-
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n density?: 'low' | 'medium' | 'high'\n}\n\nconst {\n class: classProp = '',\n className = '',\n density = 'medium',\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-particles'\n], classProp, className)\n---\n\n<div\n aria-hidden=\"true\"\n class:list={classList}\n data-ui-particles={density}\n {...passthrough}\n>\n <slot />\n</div>\n",
|
|
20543
|
+
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n density?: 'low' | 'medium' | 'high'\n}\n\nconst {\n class: classProp = '',\n className = '',\n density = 'medium',\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-particles'\n], classProp, className)\n---\n\n<div\n aria-hidden=\"true\"\n class:list={classList}\n data-ui-particles={density}\n {...passthrough}\n>\n <slot />\n</div>\n\n<script>\n type ParticleDensity = 'low' | 'medium' | 'high'\n\n const densityConfig: Record<ParticleDensity, number> = {\n low: 15,\n medium: 25,\n high: 40\n }\n\n const particleTones = [\n 'var(--brand)',\n 'var(--accent)',\n 'var(--glow, var(--brand))'\n ]\n\n const initParticles = (scope: ParentNode = document) => {\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return\n\n for (const container of scope.querySelectorAll<HTMLElement>('[data-ui-particles]')) {\n if (container.hasAttribute('data-ui-particles-initialized')) continue\n\n container.setAttribute('data-ui-particles-initialized', '')\n\n const density = (container.dataset.uiParticles || 'medium') as ParticleDensity\n const count = densityConfig[density]\n\n for (let index = 0; index < count; index++) {\n const particle = document.createElement('span')\n const size = Math.random() * 12 + 8\n\n particle.className = 'ui-particles__particle'\n particle.style.setProperty('--ui-particle-delay', `${Math.random() * 8}s`)\n particle.style.setProperty('--ui-particle-duration', `${20 + Math.random() * 15}s`)\n particle.style.setProperty('--ui-particle-left', `${Math.random() * 100}%`)\n particle.style.setProperty('--ui-particle-size', `${size}px`)\n particle.style.setProperty('--ui-particle-tone', particleTones[Math.floor(Math.random() * particleTones.length)])\n particle.style.setProperty('--ui-particle-top', `${Math.random() * 100}%`)\n container.appendChild(particle)\n }\n }\n }\n\n initParticles()\n document.addEventListener('astro:after-swap', () => initParticles())\n</script>\n",
|
|
18893
20544
|
"category": "Layout",
|
|
18894
20545
|
"collections": [],
|
|
18895
20546
|
"dependencies": [],
|
|
@@ -18923,7 +20574,7 @@
|
|
|
18923
20574
|
}
|
|
18924
20575
|
],
|
|
18925
20576
|
"propsExtends": "HTMLAttributes<'div'>",
|
|
18926
|
-
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n density?: 'low' | 'medium' | 'high'\n}\n\nconst {\n class: classProp = '',\n className = '',\n density = 'medium',\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-particles'\n], classProp, className)\n---\n\n<div\n aria-hidden=\"true\"\n class:list={classList}\n data-ui-particles={density}\n {...passthrough}\n>\n <slot />\n</div>\n",
|
|
20577
|
+
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n density?: 'low' | 'medium' | 'high'\n}\n\nconst {\n class: classProp = '',\n className = '',\n density = 'medium',\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-particles'\n], classProp, className)\n---\n\n<div\n aria-hidden=\"true\"\n class:list={classList}\n data-ui-particles={density}\n {...passthrough}\n>\n <slot />\n</div>\n\n<script>\n type ParticleDensity = 'low' | 'medium' | 'high'\n\n const densityConfig: Record<ParticleDensity, number> = {\n low: 15,\n medium: 25,\n high: 40\n }\n\n const particleTones = [\n 'var(--brand)',\n 'var(--accent)',\n 'var(--glow, var(--brand))'\n ]\n\n const initParticles = (scope: ParentNode = document) => {\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return\n\n for (const container of scope.querySelectorAll<HTMLElement>('[data-ui-particles]')) {\n if (container.hasAttribute('data-ui-particles-initialized')) continue\n\n container.setAttribute('data-ui-particles-initialized', '')\n\n const density = (container.dataset.uiParticles || 'medium') as ParticleDensity\n const count = densityConfig[density]\n\n for (let index = 0; index < count; index++) {\n const particle = document.createElement('span')\n const size = Math.random() * 12 + 8\n\n particle.className = 'ui-particles__particle'\n particle.style.setProperty('--ui-particle-delay', `${Math.random() * 8}s`)\n particle.style.setProperty('--ui-particle-duration', `${20 + Math.random() * 15}s`)\n particle.style.setProperty('--ui-particle-left', `${Math.random() * 100}%`)\n particle.style.setProperty('--ui-particle-size', `${size}px`)\n particle.style.setProperty('--ui-particle-tone', particleTones[Math.floor(Math.random() * particleTones.length)])\n particle.style.setProperty('--ui-particle-top', `${Math.random() * 100}%`)\n container.appendChild(particle)\n }\n }\n }\n\n initParticles()\n document.addEventListener('astro:after-swap', () => initParticles())\n</script>\n",
|
|
18927
20578
|
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
18928
20579
|
},
|
|
18929
20580
|
"elements": {
|
|
@@ -18962,7 +20613,7 @@
|
|
|
18962
20613
|
}
|
|
18963
20614
|
],
|
|
18964
20615
|
"propsExtends": "ComponentPropsWithoutRef<'div'>",
|
|
18965
|
-
"source": "export interface ParticlesProps extends ComponentPropsWithoutRef<'div'> {\n density?: 'low' | 'medium' | 'high'\n}\n\nexport const Particles = ({ className, density = 'medium', ...props }: ParticlesProps) => (\n <div aria-hidden=\"true\" className={composeClassName('ui-particles', className)} data-ui-particles={density} {...props}
|
|
20616
|
+
"source": "export interface ParticlesProps extends ComponentPropsWithoutRef<'div'> {\n density?: 'low' | 'medium' | 'high'\n}\n\nexport const Particles = ({ children, className, density = 'medium', ...props }: ParticlesProps) => {\n const [particles, setParticles] = useState<ParticleItem[]>([])\n\n useEffect(() => {\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return\n\n // Particle geometry is client-only to keep SSR output stable while retaining per-load variation.\n // eslint-disable-next-line @eslint-react/set-state-in-effect\n setParticles(createParticles(density))\n }, [density])\n\n return (\n <div aria-hidden=\"true\" className={composeClassName('ui-particles', className)} data-ui-particles={density} {...props}>\n {children}\n {particles.map(particle => <span className=\"ui-particles__particle\" key={particle.id} style={particle.style} />)}\n </div>\n )\n}",
|
|
18966
20617
|
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
18967
20618
|
}
|
|
18968
20619
|
},
|
|
@@ -19796,6 +21447,18 @@
|
|
|
19796
21447
|
},
|
|
19797
21448
|
{
|
|
19798
21449
|
"apiReference": [
|
|
21450
|
+
{
|
|
21451
|
+
"attribute": "as",
|
|
21452
|
+
"defaultValue": "\"div\"",
|
|
21453
|
+
"description": "Changes the root element when the statistic is a standalone semantic region.",
|
|
21454
|
+
"values": "\"article\" | \"div\" | \"section\""
|
|
21455
|
+
},
|
|
21456
|
+
{
|
|
21457
|
+
"attribute": "variant",
|
|
21458
|
+
"defaultValue": "\"default\"",
|
|
21459
|
+
"description": "Changes the surface treatment while preserving the same metric structure.",
|
|
21460
|
+
"values": "\"accent\" | \"default\" | \"glass\""
|
|
21461
|
+
},
|
|
19799
21462
|
{
|
|
19800
21463
|
"attribute": "label",
|
|
19801
21464
|
"defaultValue": "-",
|
|
@@ -19821,9 +21484,11 @@
|
|
|
19821
21484
|
"values": "HTML attributes"
|
|
19822
21485
|
}
|
|
19823
21486
|
],
|
|
19824
|
-
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n label?: string\n value?: string\n}\n\nconst {\n class: classProp = '',\n className = '',\n label,\n value,\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-stat'
|
|
21487
|
+
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n as?: 'article' | 'div' | 'section'\n class?: string | null\n className?: string\n label?: string\n value?: string\n variant?: 'accent' | 'default' | 'glass'\n}\n\nconst {\n as: Tag = 'div',\n class: classProp = '',\n className = '',\n label,\n value,\n variant = 'default',\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-stat',\n variant !== 'default' && `ui-stat--${variant}`\n], classProp, className)\n---\n\n<Tag\n class:list={classList}\n data-variant={variant}\n {...passthrough}\n>\n {label && <div class=\"ui-stat-label\">{label}</div>}\n {value && <div class=\"ui-stat-value\">{value}</div>}\n <slot />\n</Tag>\n",
|
|
19825
21488
|
"category": "Data display",
|
|
19826
|
-
"collections": [
|
|
21489
|
+
"collections": [
|
|
21490
|
+
"Data visualization"
|
|
21491
|
+
],
|
|
19827
21492
|
"dependencies": [],
|
|
19828
21493
|
"description": "Pairs one prominent metric with a concise descriptive label.",
|
|
19829
21494
|
"files": [
|
|
@@ -19833,11 +21498,16 @@
|
|
|
19833
21498
|
"frameworkDetails": {
|
|
19834
21499
|
"astro": {
|
|
19835
21500
|
"available": true,
|
|
19836
|
-
"example": "<Stat label=\"Active workspaces\" value=\"1,234\" />",
|
|
21501
|
+
"example": "<Stat label=\"Active workspaces\" value=\"1,234\" variant=\"accent\" />",
|
|
19837
21502
|
"importStatement": "import { Stat } from '@santi020k/lumen-astro'",
|
|
19838
21503
|
"language": "astro",
|
|
19839
21504
|
"packageName": "@santi020k/lumen-astro",
|
|
19840
21505
|
"props": [
|
|
21506
|
+
{
|
|
21507
|
+
"name": "as",
|
|
21508
|
+
"optional": true,
|
|
21509
|
+
"type": "'article' | 'div' | 'section'"
|
|
21510
|
+
},
|
|
19841
21511
|
{
|
|
19842
21512
|
"name": "class",
|
|
19843
21513
|
"optional": true,
|
|
@@ -19857,14 +21527,21 @@
|
|
|
19857
21527
|
"name": "value",
|
|
19858
21528
|
"optional": true,
|
|
19859
21529
|
"type": "string"
|
|
21530
|
+
},
|
|
21531
|
+
{
|
|
21532
|
+
"name": "variant",
|
|
21533
|
+
"optional": true,
|
|
21534
|
+
"type": "'accent' | 'default' | 'glass'"
|
|
19860
21535
|
}
|
|
19861
21536
|
],
|
|
19862
21537
|
"propsExtends": "HTMLAttributes<'div'>",
|
|
19863
|
-
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n label?: string\n value?: string\n}\n\nconst {\n class: classProp = '',\n className = '',\n label,\n value,\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-stat'
|
|
21538
|
+
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n as?: 'article' | 'div' | 'section'\n class?: string | null\n className?: string\n label?: string\n value?: string\n variant?: 'accent' | 'default' | 'glass'\n}\n\nconst {\n as: Tag = 'div',\n class: classProp = '',\n className = '',\n label,\n value,\n variant = 'default',\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-stat',\n variant !== 'default' && `ui-stat--${variant}`\n], classProp, className)\n---\n\n<Tag\n class:list={classList}\n data-variant={variant}\n {...passthrough}\n>\n {label && <div class=\"ui-stat-label\">{label}</div>}\n {value && <div class=\"ui-stat-value\">{value}</div>}\n <slot />\n</Tag>\n",
|
|
19864
21539
|
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
19865
21540
|
},
|
|
19866
21541
|
"elements": {
|
|
19867
21542
|
"attributes": [
|
|
21543
|
+
"variant",
|
|
21544
|
+
"as",
|
|
19868
21545
|
"label",
|
|
19869
21546
|
"value",
|
|
19870
21547
|
"class, className",
|
|
@@ -19875,24 +21552,29 @@
|
|
|
19875
21552
|
"mode": "registration",
|
|
19876
21553
|
"setup": "Call defineLumenElements() once before rendering Lumen custom elements."
|
|
19877
21554
|
},
|
|
19878
|
-
"example": "<lumen-stat label=\"Active workspaces\" value=\"1,234\"></lumen-stat>",
|
|
21555
|
+
"example": "<lumen-stat label=\"Active workspaces\" value=\"1,234\" variant=\"accent\"></lumen-stat>",
|
|
19879
21556
|
"importStatement": "import { defineLumenElements } from '@santi020k/lumen-elements/define'",
|
|
19880
21557
|
"language": "html",
|
|
19881
21558
|
"packageName": "@santi020k/lumen-elements",
|
|
19882
21559
|
"props": [],
|
|
19883
21560
|
"propsExtends": "HTMLElement attributes",
|
|
19884
21561
|
"registration": "defineLumenElements()",
|
|
19885
|
-
"source": "Stat: { baseClassName: 'ui-stat'
|
|
21562
|
+
"source": "Stat: {\n attributeClasses: {\n variant: {\n accent: 'ui-stat--accent',\n glass: 'ui-stat--glass'\n }\n },\n baseClassName: 'ui-stat',\n defaults: { variant: 'default' },\n tagName: 'lumen-stat'\n }",
|
|
19886
21563
|
"styleImport": "import '@santi020k/lumen-elements/styles.css'",
|
|
19887
21564
|
"tagName": "lumen-stat"
|
|
19888
21565
|
},
|
|
19889
21566
|
"react": {
|
|
19890
21567
|
"available": true,
|
|
19891
|
-
"example": "<Stat label=\"Active workspaces\" value=\"1,234\" />",
|
|
21568
|
+
"example": "<Stat label=\"Active workspaces\" value=\"1,234\" variant=\"accent\" />",
|
|
19892
21569
|
"importStatement": "import { Stat } from '@santi020k/lumen-react'",
|
|
19893
21570
|
"language": "tsx",
|
|
19894
21571
|
"packageName": "@santi020k/lumen-react",
|
|
19895
21572
|
"props": [
|
|
21573
|
+
{
|
|
21574
|
+
"name": "as",
|
|
21575
|
+
"optional": true,
|
|
21576
|
+
"type": "T"
|
|
21577
|
+
},
|
|
19896
21578
|
{
|
|
19897
21579
|
"name": "label",
|
|
19898
21580
|
"optional": true,
|
|
@@ -19902,10 +21584,15 @@
|
|
|
19902
21584
|
"name": "value",
|
|
19903
21585
|
"optional": true,
|
|
19904
21586
|
"type": "string"
|
|
21587
|
+
},
|
|
21588
|
+
{
|
|
21589
|
+
"name": "variant",
|
|
21590
|
+
"optional": true,
|
|
21591
|
+
"type": "'accent' | 'default' | 'glass'"
|
|
19905
21592
|
}
|
|
19906
21593
|
],
|
|
19907
|
-
"propsExtends": "
|
|
19908
|
-
"source": "export
|
|
21594
|
+
"propsExtends": "PrimitiveProps",
|
|
21595
|
+
"source": "export type StatProps<T extends ElementType = 'div'> = PrimitiveProps & {\n as?: T\n label?: string\n value?: string\n variant?: 'accent' | 'default' | 'glass'\n}\n\nexport const Stat = <T extends ElementType = 'div'>({\n as,\n className,\n label,\n value,\n variant = 'default',\n children,\n ...props\n}: StatProps<T>) => (\n <Primitive\n {...(as ? { as } : {})}\n className={composeClassName(variant !== 'default' && `ui-stat--${variant}`, className)}\n data-variant={variant}\n {...props}\n uiClassName=\"ui-stat\"\n >\n {label && <div className=\"ui-stat-label\">{label}</div>}\n {value && <div className=\"ui-stat-value\">{value}</div>}\n {children}\n </Primitive>\n)",
|
|
19909
21596
|
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
19910
21597
|
}
|
|
19911
21598
|
},
|
|
@@ -19916,42 +21603,74 @@
|
|
|
19916
21603
|
},
|
|
19917
21604
|
"guidance": {
|
|
19918
21605
|
"when": "Use to pair one prominent metric with its concise label.",
|
|
19919
|
-
"distinction": "Use Chart when the trend or relationship matters, or Descriptions for several equally weighted key–value facts."
|
|
21606
|
+
"distinction": "Use as=\"article\" when the metric and its supporting content stand alone. Use variant=\"accent\" for a featured metric and variant=\"glass\" on a selective translucent surface. Use Chart when the trend or relationship matters, or Descriptions for several equally weighted key–value facts."
|
|
19920
21607
|
},
|
|
19921
21608
|
"kebab": "stat",
|
|
19922
21609
|
"keyboardInteractions": [],
|
|
19923
21610
|
"keywords": [
|
|
21611
|
+
"accent",
|
|
21612
|
+
"alone",
|
|
21613
|
+
"and",
|
|
21614
|
+
"article",
|
|
21615
|
+
"breakdowns",
|
|
21616
|
+
"categorical",
|
|
19924
21617
|
"chart",
|
|
21618
|
+
"compact",
|
|
21619
|
+
"comparisons",
|
|
19925
21620
|
"concise",
|
|
21621
|
+
"content",
|
|
21622
|
+
"custom",
|
|
19926
21623
|
"data",
|
|
19927
21624
|
"descriptions",
|
|
19928
21625
|
"descriptive",
|
|
19929
21626
|
"display",
|
|
19930
21627
|
"equally",
|
|
19931
21628
|
"facts",
|
|
21629
|
+
"featured",
|
|
19932
21630
|
"for",
|
|
21631
|
+
"glass",
|
|
19933
21632
|
"its",
|
|
19934
21633
|
"key",
|
|
19935
21634
|
"label",
|
|
21635
|
+
"match",
|
|
19936
21636
|
"matters",
|
|
19937
21637
|
"metric",
|
|
21638
|
+
"metrics",
|
|
19938
21639
|
"one",
|
|
21640
|
+
"ordered",
|
|
19939
21641
|
"pair",
|
|
19940
21642
|
"pairs",
|
|
21643
|
+
"part",
|
|
21644
|
+
"plots",
|
|
19941
21645
|
"prominent",
|
|
21646
|
+
"question",
|
|
19942
21647
|
"relationship",
|
|
21648
|
+
"selective",
|
|
19943
21649
|
"several",
|
|
21650
|
+
"stand",
|
|
19944
21651
|
"stat",
|
|
21652
|
+
"supporting",
|
|
21653
|
+
"surface",
|
|
19945
21654
|
"the",
|
|
21655
|
+
"translucent",
|
|
19946
21656
|
"trend",
|
|
21657
|
+
"trends",
|
|
19947
21658
|
"use",
|
|
19948
21659
|
"value",
|
|
21660
|
+
"variant",
|
|
21661
|
+
"visualization",
|
|
19949
21662
|
"weighted",
|
|
19950
21663
|
"when",
|
|
21664
|
+
"whole",
|
|
19951
21665
|
"with"
|
|
19952
21666
|
],
|
|
19953
21667
|
"name": "Stat",
|
|
19954
21668
|
"props": [
|
|
21669
|
+
{
|
|
21670
|
+
"name": "as",
|
|
21671
|
+
"optional": true,
|
|
21672
|
+
"type": "'article' | 'div' | 'section'"
|
|
21673
|
+
},
|
|
19955
21674
|
{
|
|
19956
21675
|
"name": "class",
|
|
19957
21676
|
"optional": true,
|
|
@@ -19971,10 +21690,20 @@
|
|
|
19971
21690
|
"name": "value",
|
|
19972
21691
|
"optional": true,
|
|
19973
21692
|
"type": "string"
|
|
21693
|
+
},
|
|
21694
|
+
{
|
|
21695
|
+
"name": "variant",
|
|
21696
|
+
"optional": true,
|
|
21697
|
+
"type": "'accent' | 'default' | 'glass'"
|
|
19974
21698
|
}
|
|
19975
21699
|
],
|
|
19976
21700
|
"propsExtends": "HTMLAttributes<'div'>",
|
|
19977
|
-
"recipes": [
|
|
21701
|
+
"recipes": [
|
|
21702
|
+
{
|
|
21703
|
+
"name": "data-visualization",
|
|
21704
|
+
"type": "recipe"
|
|
21705
|
+
}
|
|
21706
|
+
],
|
|
19978
21707
|
"runtimeEvents": []
|
|
19979
21708
|
},
|
|
19980
21709
|
{
|
|
@@ -20012,7 +21741,9 @@
|
|
|
20012
21741
|
],
|
|
20013
21742
|
"astroSource": "---\nimport type { HTMLAttributes } from 'astro/types'\nimport { composeClassName } from '@santi020k/lumen-core'\n\nexport interface Props extends HTMLAttributes<'meter'> {\n value: number\n min?: number\n max?: number\n low?: number\n high?: number\n optimum?: number\n}\n\nconst {\n class: className,\n value,\n min = 0,\n max = 100,\n ...props\n} = Astro.props\n---\n\n<meter\n class={composeClassName('ui-meter', className)}\n value={value}\n min={min}\n max={max}\n {...props}\n>\n <slot>{value}</slot>\n</meter>\n",
|
|
20014
21743
|
"category": "Data display",
|
|
20015
|
-
"collections": [
|
|
21744
|
+
"collections": [
|
|
21745
|
+
"Data visualization"
|
|
21746
|
+
],
|
|
20016
21747
|
"dependencies": [],
|
|
20017
21748
|
"description": "Displays a scalar value within a known range.",
|
|
20018
21749
|
"files": [
|
|
@@ -20111,18 +21842,30 @@
|
|
|
20111
21842
|
"keyboardInteractions": [],
|
|
20112
21843
|
"keywords": [
|
|
20113
21844
|
"advancing",
|
|
21845
|
+
"and",
|
|
21846
|
+
"breakdowns",
|
|
21847
|
+
"categorical",
|
|
21848
|
+
"compact",
|
|
21849
|
+
"comparisons",
|
|
20114
21850
|
"completion",
|
|
20115
21851
|
"current",
|
|
21852
|
+
"custom",
|
|
20116
21853
|
"data",
|
|
20117
21854
|
"display",
|
|
20118
21855
|
"displays",
|
|
20119
21856
|
"for",
|
|
20120
21857
|
"known",
|
|
21858
|
+
"match",
|
|
20121
21859
|
"measurement",
|
|
20122
21860
|
"meter",
|
|
21861
|
+
"metrics",
|
|
20123
21862
|
"not",
|
|
21863
|
+
"ordered",
|
|
21864
|
+
"part",
|
|
21865
|
+
"plots",
|
|
20124
21866
|
"progress",
|
|
20125
21867
|
"quantity",
|
|
21868
|
+
"question",
|
|
20126
21869
|
"range",
|
|
20127
21870
|
"represents",
|
|
20128
21871
|
"scalar",
|
|
@@ -20132,9 +21875,13 @@
|
|
|
20132
21875
|
"storage",
|
|
20133
21876
|
"such",
|
|
20134
21877
|
"task",
|
|
21878
|
+
"the",
|
|
20135
21879
|
"toward",
|
|
21880
|
+
"trends",
|
|
20136
21881
|
"use",
|
|
20137
21882
|
"value",
|
|
21883
|
+
"visualization",
|
|
21884
|
+
"whole",
|
|
20138
21885
|
"within",
|
|
20139
21886
|
"work"
|
|
20140
21887
|
],
|
|
@@ -20172,7 +21919,12 @@
|
|
|
20172
21919
|
}
|
|
20173
21920
|
],
|
|
20174
21921
|
"propsExtends": "HTMLAttributes<'meter'>",
|
|
20175
|
-
"recipes": [
|
|
21922
|
+
"recipes": [
|
|
21923
|
+
{
|
|
21924
|
+
"name": "data-visualization",
|
|
21925
|
+
"type": "recipe"
|
|
21926
|
+
}
|
|
21927
|
+
],
|
|
20176
21928
|
"runtimeEvents": []
|
|
20177
21929
|
},
|
|
20178
21930
|
{
|
|
@@ -22295,8 +24047,8 @@
|
|
|
22295
24047
|
{
|
|
22296
24048
|
"attribute": "items",
|
|
22297
24049
|
"defaultValue": "[]",
|
|
22298
|
-
"description": "Defines the in-page navigation targets and
|
|
22299
|
-
"values": "Array<{ href, label }>"
|
|
24050
|
+
"description": "Defines the in-page navigation targets, labels, and optional heading depth from 1 through 6.",
|
|
24051
|
+
"values": "Array<{ href, label, depth? }>"
|
|
22300
24052
|
},
|
|
22301
24053
|
{
|
|
22302
24054
|
"attribute": "class, className",
|
|
@@ -22311,7 +24063,7 @@
|
|
|
22311
24063
|
"values": "HTML attributes"
|
|
22312
24064
|
}
|
|
22313
24065
|
],
|
|
22314
|
-
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ntype AnchorLink = { href: string
|
|
24066
|
+
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ntype AnchorDepth = 1 | 2 | 3 | 4 | 5 | 6\n\ntype AnchorLink = {\n depth?: AnchorDepth\n href: string\n label: string\n}\n\nexport interface Props extends HTMLAttributes<'nav'> {\n class?: string | null\n className?: string\n items?: AnchorLink[]\n}\n\nconst {\n 'aria-label': ariaLabel = 'On this page',\n class: classProp = '',\n className = '',\n items = [],\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-anchor'\n], classProp, className)\n---\n\n<nav\n aria-label={ariaLabel}\n class:list={classList}\n data-ui-anchor\n {...passthrough}\n>\n {items.length > 0 && (\n <ol>\n {items.map((item, index) => (\n <li>\n <a\n data-active={index === 0 ? 'true' : 'false'}\n data-depth={item.depth}\n href={item.href}\n >\n {item.label}\n </a>\n </li>\n ))}\n </ol>\n )}\n <slot />\n</nav>\n",
|
|
22315
24067
|
"category": "Navigation",
|
|
22316
24068
|
"collections": [
|
|
22317
24069
|
"Disclosure and navigation"
|
|
@@ -22325,7 +24077,7 @@
|
|
|
22325
24077
|
"frameworkDetails": {
|
|
22326
24078
|
"astro": {
|
|
22327
24079
|
"available": true,
|
|
22328
|
-
"example": "<Anchor items={[{ href: \"#installation\", label: \"Installation\" }, { href: \"#usage\", label: \"Usage\" }]} />",
|
|
24080
|
+
"example": "<Anchor items={[{ href: \"#installation\", label: \"Installation\", depth: 2 }, { href: \"#usage\", label: \"Usage\", depth: 3 }]} />",
|
|
22329
24081
|
"importStatement": "import { Anchor } from '@santi020k/lumen-astro'",
|
|
22330
24082
|
"language": "astro",
|
|
22331
24083
|
"packageName": "@santi020k/lumen-astro",
|
|
@@ -22347,7 +24099,7 @@
|
|
|
22347
24099
|
}
|
|
22348
24100
|
],
|
|
22349
24101
|
"propsExtends": "HTMLAttributes<'nav'>",
|
|
22350
|
-
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ntype AnchorLink = { href: string
|
|
24102
|
+
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ntype AnchorDepth = 1 | 2 | 3 | 4 | 5 | 6\n\ntype AnchorLink = {\n depth?: AnchorDepth\n href: string\n label: string\n}\n\nexport interface Props extends HTMLAttributes<'nav'> {\n class?: string | null\n className?: string\n items?: AnchorLink[]\n}\n\nconst {\n 'aria-label': ariaLabel = 'On this page',\n class: classProp = '',\n className = '',\n items = [],\n ...rest\n} = Astro.props\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-anchor'\n], classProp, className)\n---\n\n<nav\n aria-label={ariaLabel}\n class:list={classList}\n data-ui-anchor\n {...passthrough}\n>\n {items.length > 0 && (\n <ol>\n {items.map((item, index) => (\n <li>\n <a\n data-active={index === 0 ? 'true' : 'false'}\n data-depth={item.depth}\n href={item.href}\n >\n {item.label}\n </a>\n </li>\n ))}\n </ol>\n )}\n <slot />\n</nav>\n",
|
|
22351
24103
|
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
22352
24104
|
},
|
|
22353
24105
|
"elements": {
|
|
@@ -22376,7 +24128,7 @@
|
|
|
22376
24128
|
},
|
|
22377
24129
|
"react": {
|
|
22378
24130
|
"available": true,
|
|
22379
|
-
"example": "<Anchor items={[{ href: \"#installation\", label: \"Installation\" }, { href: \"#usage\", label: \"Usage\" }]} />",
|
|
24131
|
+
"example": "<Anchor items={[{ href: \"#installation\", label: \"Installation\", depth: 2 }, { href: \"#usage\", label: \"Usage\", depth: 3 }]} />",
|
|
22380
24132
|
"importStatement": "import { Anchor } from '@santi020k/lumen-react'",
|
|
22381
24133
|
"language": "tsx",
|
|
22382
24134
|
"packageName": "@santi020k/lumen-react",
|
|
@@ -22388,7 +24140,7 @@
|
|
|
22388
24140
|
}
|
|
22389
24141
|
],
|
|
22390
24142
|
"propsExtends": "ComponentPropsWithoutRef<'nav'>",
|
|
22391
|
-
"source": "export interface AnchorProps extends ComponentPropsWithoutRef<'nav'> {\n items?: AnchorLink[]\n}\n\nexport const Anchor = ({ 'aria-label': ariaLabel = 'On this page', children, className, items = emptyAnchorLinks, ...props }: AnchorProps) => (\n <nav aria-label={ariaLabel} className={composeClassName('ui-anchor', className)} data-ui-anchor {...props}>\n {items.length > 0 && (\n <ol>\n {items.map((item, index) => (\n <li key={item.href}>\n <a
|
|
24143
|
+
"source": "export interface AnchorProps extends ComponentPropsWithoutRef<'nav'> {\n items?: AnchorLink[]\n}\n\nexport const Anchor = ({ 'aria-label': ariaLabel = 'On this page', children, className, items = emptyAnchorLinks, ...props }: AnchorProps) => (\n <nav aria-label={ariaLabel} className={composeClassName('ui-anchor', className)} data-ui-anchor {...props}>\n {items.length > 0 && (\n <ol>\n {items.map((item, index) => (\n <li key={item.href}>\n <a\n data-active={index === 0 ? 'true' : 'false'}\n data-depth={item.depth}\n href={item.href}\n >\n {item.label}\n </a>\n </li>\n ))}\n </ol>\n )}\n {children}\n </nav>\n)",
|
|
22392
24144
|
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
22393
24145
|
}
|
|
22394
24146
|
},
|
|
@@ -24287,7 +26039,7 @@
|
|
|
24287
26039
|
"values": "HTML attributes"
|
|
24288
26040
|
}
|
|
24289
26041
|
],
|
|
24290
|
-
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n content?: string\n gap?: number\n rotate?: number\n text?: string\n}\n\nconst {\n class: classProp = '',\n className = '',\n content,\n gap = 120,\n rotate = -22,\n text = 'Confidential',\n ...rest\n} = Astro.props\n\nconst watermarkText = content ?? text\nconst tileSize = Math.max(1, gap)\nconst watermarkXmlEntities: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n}\nconst escapedWatermarkText = watermarkText.replaceAll(\n /[&<>\"']/g,\n character => watermarkXmlEntities[character] ?? character\n)\nconst watermarkSvg = [\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${tileSize}\" height=\"${tileSize}\" viewBox=\"0 0 ${tileSize} ${tileSize}\">`,\n `<text x=\"${tileSize / 2}\" y=\"${tileSize / 2}\" dominant-baseline=\"middle\" text-anchor=\"middle\"`,\n ` transform=\"rotate(${rotate} ${tileSize / 2} ${tileSize / 2})\"`,\n ' fill=\"black\" font-family=\"
|
|
26042
|
+
"astroSource": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n content?: string\n gap?: number\n rotate?: number\n text?: string\n}\n\nconst {\n class: classProp = '',\n className = '',\n content,\n gap = 120,\n rotate = -22,\n text = 'Confidential',\n ...rest\n} = Astro.props\n\nconst watermarkText = content ?? text\nconst tileSize = Math.max(1, gap)\nconst watermarkXmlEntities: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n}\nconst escapedWatermarkText = watermarkText.replaceAll(\n /[&<>\"']/g,\n character => watermarkXmlEntities[character] ?? character\n)\nconst watermarkSvg = [\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${tileSize}\" height=\"${tileSize}\" viewBox=\"0 0 ${tileSize} ${tileSize}\">`,\n `<text x=\"${tileSize / 2}\" y=\"${tileSize / 2}\" dominant-baseline=\"middle\" text-anchor=\"middle\"`,\n ` transform=\"rotate(${rotate} ${tileSize / 2} ${tileSize / 2})\"`,\n ' fill=\"black\" font-family=\"Montserrat, Avenir Next, Segoe UI, sans-serif\" font-size=\"16\" font-weight=\"500\" letter-spacing=\"1.6\">',\n `${escapedWatermarkText}</text></svg>`\n].join('')\nconst watermarkImage = `url(\"data:image/svg+xml,${encodeURIComponent(watermarkSvg)}\")`\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-watermark'\n], classProp, className)\n---\n\n<div\n class:list={classList}\n data-ui-watermark\n style={`--ui-watermark-gap:${tileSize}px;--ui-watermark-image:${watermarkImage}`}\n {...passthrough}\n>\n <slot />\n <div aria-hidden=\"true\" class=\"ui-watermark__overlay\" data-text={watermarkText}></div>\n</div>\n",
|
|
24291
26043
|
"category": "Layout",
|
|
24292
26044
|
"collections": [],
|
|
24293
26045
|
"dependencies": [],
|
|
@@ -24336,7 +26088,7 @@
|
|
|
24336
26088
|
}
|
|
24337
26089
|
],
|
|
24338
26090
|
"propsExtends": "HTMLAttributes<'div'>",
|
|
24339
|
-
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n content?: string\n gap?: number\n rotate?: number\n text?: string\n}\n\nconst {\n class: classProp = '',\n className = '',\n content,\n gap = 120,\n rotate = -22,\n text = 'Confidential',\n ...rest\n} = Astro.props\n\nconst watermarkText = content ?? text\nconst tileSize = Math.max(1, gap)\nconst watermarkXmlEntities: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n}\nconst escapedWatermarkText = watermarkText.replaceAll(\n /[&<>\"']/g,\n character => watermarkXmlEntities[character] ?? character\n)\nconst watermarkSvg = [\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${tileSize}\" height=\"${tileSize}\" viewBox=\"0 0 ${tileSize} ${tileSize}\">`,\n `<text x=\"${tileSize / 2}\" y=\"${tileSize / 2}\" dominant-baseline=\"middle\" text-anchor=\"middle\"`,\n ` transform=\"rotate(${rotate} ${tileSize / 2} ${tileSize / 2})\"`,\n ' fill=\"black\" font-family=\"
|
|
26091
|
+
"source": "---\nimport { resolveLumenAstroProps } from '@santi020k/lumen-core'\n\nimport type { HTMLAttributes } from 'astro/types'\n\ninterface Props extends HTMLAttributes<'div'> {\n class?: string | null\n className?: string\n content?: string\n gap?: number\n rotate?: number\n text?: string\n}\n\nconst {\n class: classProp = '',\n className = '',\n content,\n gap = 120,\n rotate = -22,\n text = 'Confidential',\n ...rest\n} = Astro.props\n\nconst watermarkText = content ?? text\nconst tileSize = Math.max(1, gap)\nconst watermarkXmlEntities: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n}\nconst escapedWatermarkText = watermarkText.replaceAll(\n /[&<>\"']/g,\n character => watermarkXmlEntities[character] ?? character\n)\nconst watermarkSvg = [\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${tileSize}\" height=\"${tileSize}\" viewBox=\"0 0 ${tileSize} ${tileSize}\">`,\n `<text x=\"${tileSize / 2}\" y=\"${tileSize / 2}\" dominant-baseline=\"middle\" text-anchor=\"middle\"`,\n ` transform=\"rotate(${rotate} ${tileSize / 2} ${tileSize / 2})\"`,\n ' fill=\"black\" font-family=\"Montserrat, Avenir Next, Segoe UI, sans-serif\" font-size=\"16\" font-weight=\"500\" letter-spacing=\"1.6\">',\n `${escapedWatermarkText}</text></svg>`\n].join('')\nconst watermarkImage = `url(\"data:image/svg+xml,${encodeURIComponent(watermarkSvg)}\")`\n\nconst { classList, passthrough } = resolveLumenAstroProps(rest, [\n 'ui-watermark'\n], classProp, className)\n---\n\n<div\n class:list={classList}\n data-ui-watermark\n style={`--ui-watermark-gap:${tileSize}px;--ui-watermark-image:${watermarkImage}`}\n {...passthrough}\n>\n <slot />\n <div aria-hidden=\"true\" class=\"ui-watermark__overlay\" data-text={watermarkText}></div>\n</div>\n",
|
|
24340
26092
|
"styleImport": "import '@santi020k/lumen-astro/styles.css'"
|
|
24341
26093
|
},
|
|
24342
26094
|
"elements": {
|
|
@@ -24393,7 +26145,7 @@
|
|
|
24393
26145
|
}
|
|
24394
26146
|
],
|
|
24395
26147
|
"propsExtends": "ComponentPropsWithoutRef<'div'>",
|
|
24396
|
-
"source": "export interface WatermarkProps extends ComponentPropsWithoutRef<'div'> {\n content?: string\n gap?: number\n rotate?: number\n text?: string\n}\n\nexport const Watermark = ({ children, className, content, gap = 120, rotate = -22, style, text = 'Confidential', ...props }: WatermarkProps) => {\n const watermarkText = content ?? text\n const tileSize = Math.max(1, gap)\n\n const watermarkXmlEntities: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n }\n\n const escapedWatermarkText = watermarkText.replaceAll(\n /[&<>\"']/g,\n character => watermarkXmlEntities[character] ?? character\n )\n\n const watermarkSvg = [\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${tileSize}\" height=\"${tileSize}\" viewBox=\"0 0 ${tileSize} ${tileSize}\">`,\n `<text x=\"${tileSize / 2}\" y=\"${tileSize / 2}\" dominant-baseline=\"middle\" text-anchor=\"middle\"`,\n ` transform=\"rotate(${rotate} ${tileSize / 2} ${tileSize / 2})\"`,\n ' fill=\"black\" font-family=\"
|
|
26148
|
+
"source": "export interface WatermarkProps extends ComponentPropsWithoutRef<'div'> {\n content?: string\n gap?: number\n rotate?: number\n text?: string\n}\n\nexport const Watermark = ({ children, className, content, gap = 120, rotate = -22, style, text = 'Confidential', ...props }: WatermarkProps) => {\n const watermarkText = content ?? text\n const tileSize = Math.max(1, gap)\n\n const watermarkXmlEntities: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n }\n\n const escapedWatermarkText = watermarkText.replaceAll(\n /[&<>\"']/g,\n character => watermarkXmlEntities[character] ?? character\n )\n\n const watermarkSvg = [\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${tileSize}\" height=\"${tileSize}\" viewBox=\"0 0 ${tileSize} ${tileSize}\">`,\n `<text x=\"${tileSize / 2}\" y=\"${tileSize / 2}\" dominant-baseline=\"middle\" text-anchor=\"middle\"`,\n ` transform=\"rotate(${rotate} ${tileSize / 2} ${tileSize / 2})\"`,\n ' fill=\"black\" font-family=\"Montserrat, Avenir Next, Segoe UI, sans-serif\" font-size=\"16\" font-weight=\"500\" letter-spacing=\"1.6\">',\n `${escapedWatermarkText}</text></svg>`\n ].join('')\n\n const watermarkImage = `url(\"data:image/svg+xml,${encodeURIComponent(watermarkSvg)}\")`\n\n return (\n <div\n className={composeClassName('ui-watermark', className)}\n data-ui-watermark\n style={{\n ['--ui-watermark-gap' as string]: `${tileSize}px`,\n ['--ui-watermark-image' as string]: watermarkImage,\n ...style\n }}\n {...props}\n >\n {children}\n <div aria-hidden=\"true\" className=\"ui-watermark__overlay\" data-text={watermarkText} />\n </div>\n )\n}",
|
|
24397
26149
|
"styleImport": "import '@santi020k/lumen-react/styles.css'"
|
|
24398
26150
|
}
|
|
24399
26151
|
},
|
|
@@ -24890,12 +26642,12 @@
|
|
|
24890
26642
|
}
|
|
24891
26643
|
],
|
|
24892
26644
|
"docs": {
|
|
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",
|
|
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"
|
|
26645
|
+
"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| Optional brand icons | `@santi020k/lumen-icons-brand` | Register once, then use the framework `Icon` | Uses framework styles |\n\nEach framework package includes the shared foundation. Install `@santi020k/lumen` separately only\nwhen you need its framework-neutral CLI or registry metadata.\n\nBrand marks are intentionally excluded from the default Lucide catalog. When a product needs them,\ninstall and register the optional pack once before rendering a namespaced icon:\n\n```ts\nimport { registerLumenBrandIcons } from '@santi020k/lumen-icons-brand'\n\nregisterLumenBrandIcons()\n```\n\nThen use any canonical Font Awesome Free brand name, such as `brand:github`, `brand:discord`,\n`brand:figma`, `brand:linkedin`, `brand:whatsapp`, or `brand:youtube`, through the existing Astro,\nReact, or Web Component `Icon` API. The package also provides `brand:x` as an alias for\n`brand:x-twitter`.\n\nBrand marks keep their recognizable filled geometry instead of being redrawn as Lucide outlines.\nThey still inherit the same Lumen size, alignment, `currentColor`, and accessible-label behavior as\nthe default icon catalog.\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`Stat` defaults to a `div`. Choose `as=\"article\"` for a self-contained metric with supporting\ncontent, or `as=\"section\"` for a labeled region. Do not use a semantic root solely for styling.\nIts visual variants are `default`, `accent`, and `glass`; reserve `accent` for featured metrics and\nkeep glass selective.\n\nFor long reading surfaces, use `Anchor` for local section navigation and pass each item’s optional\nheading `depth` when hierarchy matters. Use `ScrollProgress` for document position; keep `Progress`\nfor application-controlled task completion. `Pill` accepts `neutral`, `brand`, and `outline`\nvariants, plus native link and count composition.\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`Stat as` and `variant` follow the same semantic-root and visual guidance as the Astro component.\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`, `BarChart`, `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`, `LineChart`, `Marker`, `Menubar`, `Message`, `MessageScroller`, `NativeSelect`, `NavigationMenu`,\n`NumberField`, `Pagination`, `PieChart`, `Popover`, `Progress`, `RadioGroup`, `Resizable`, `RichTextEditor`,\n`ScrollArea`, `Schedule`, `SearchField`, `Select`, `Separator`, `Sheet`, `Sidebar`, `Skeleton`,\n`Slider`, `Sparkline`, `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 `Sparkline` for a compact trend beside a labelled metric, `BarChart` for categorical\n comparison, `LineChart` for ordered or time-series data, and `PieChart` for a small\n part-to-whole breakdown. Pass already-aggregated `LumenChartSeries` data; keep statistics,\n resampling, model evaluation, and domain calculations in application code. Keep `showTable`\n enabled unless the same values are already available in a nearby semantic table. Prefer a bar\n chart when precise slice comparison matters or the pie would exceed roughly seven categories.\n Use `Chart` as the custom SVG/canvas escape hatch.\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. Install and register\n `@santi020k/lumen-icons-brand` for supported brand marks, then use names such as\n `brand:github`. Render project-specific or unsupported brand SVGs through the default `Icon`\n slot. Astro 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",
|
|
26646
|
+
"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-icons-brand`](./packages/icons-brand) | Optional namespaced brand icons for the shared `Icon` API |\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"
|
|
24895
26647
|
},
|
|
24896
26648
|
"meta": {
|
|
24897
|
-
"catalogHash": "
|
|
24898
|
-
"componentCount":
|
|
26649
|
+
"catalogHash": "d823f5c7ed0ee5c370cf78381b622ef60046afe977464a75f93e6464db4f037d",
|
|
26650
|
+
"componentCount": 129,
|
|
24899
26651
|
"packages": [
|
|
24900
26652
|
"@santi020k/lumen-astro",
|
|
24901
26653
|
"@santi020k/lumen-react",
|
|
@@ -24903,16 +26655,16 @@
|
|
|
24903
26655
|
"@santi020k/lumen-core"
|
|
24904
26656
|
],
|
|
24905
26657
|
"packageVersions": {
|
|
24906
|
-
"@santi020k/lumen-astro": "0.
|
|
24907
|
-
"@santi020k/lumen-core": "0.
|
|
24908
|
-
"@santi020k/lumen-elements": "0.
|
|
24909
|
-
"@santi020k/lumen-mcp": "0.
|
|
24910
|
-
"@santi020k/lumen-react": "0.
|
|
26658
|
+
"@santi020k/lumen-astro": "0.4.0",
|
|
26659
|
+
"@santi020k/lumen-core": "0.4.0",
|
|
26660
|
+
"@santi020k/lumen-elements": "0.4.0",
|
|
26661
|
+
"@santi020k/lumen-mcp": "0.4.0",
|
|
26662
|
+
"@santi020k/lumen-react": "0.4.0"
|
|
24911
26663
|
},
|
|
24912
26664
|
"registryName": "lumen",
|
|
24913
26665
|
"registryVersion": 1,
|
|
24914
26666
|
"schemaVersion": 3,
|
|
24915
|
-
"serverVersion": "0.
|
|
26667
|
+
"serverVersion": "0.4.0"
|
|
24916
26668
|
},
|
|
24917
26669
|
"recipes": [
|
|
24918
26670
|
{
|
|
@@ -25038,10 +26790,50 @@
|
|
|
25038
26790
|
"elements": "lumen add rich-text-editor --target elements",
|
|
25039
26791
|
"react": "lumen add rich-text-editor --target react"
|
|
25040
26792
|
}
|
|
26793
|
+
},
|
|
26794
|
+
{
|
|
26795
|
+
"name": "data-visualization",
|
|
26796
|
+
"type": "recipe",
|
|
26797
|
+
"components": [
|
|
26798
|
+
"Chart",
|
|
26799
|
+
"Sparkline",
|
|
26800
|
+
"BarChart",
|
|
26801
|
+
"LineChart",
|
|
26802
|
+
"PieChart",
|
|
26803
|
+
"Stat",
|
|
26804
|
+
"Meter"
|
|
26805
|
+
],
|
|
26806
|
+
"categories": [
|
|
26807
|
+
"Data display"
|
|
26808
|
+
],
|
|
26809
|
+
"description": "A data visualization composition using Chart, Sparkline, BarChart, LineChart, PieChart, Stat, Meter.",
|
|
26810
|
+
"install": {
|
|
26811
|
+
"astro": "lumen add data-visualization --target astro",
|
|
26812
|
+
"elements": "lumen add data-visualization --target elements",
|
|
26813
|
+
"react": "lumen add data-visualization --target react"
|
|
26814
|
+
}
|
|
25041
26815
|
}
|
|
25042
26816
|
],
|
|
25043
26817
|
"rules": "# Lumen UI\n\nLumen is a multi-framework primitive UI system with Astro as the reference implementation.\n\nUse these files first when generating, reviewing, or migrating apps that use Lumen:\n\n- README.md: public overview and package strategy.\n- docs/ai-usage.md: AI-focused setup, package selection, and component selection.\n- skills/lumen-ui/SKILL.md: portable Agent Skill for building, reviewing, and theming Lumen interfaces.\n- docs/feature-roadmap.md: competitor-informed gaps and implementation priorities.\n- registry/lumen.registry.json: installable component, recipe, and documentation manifest.\n- packages/core/src/components.ts: authoritative shared component catalog.\n- packages/astro/components: reference component markup and prop shapes.\n- packages/astro/styles/lumen.css: standalone CSS contract for all frameworks.\n- @santi020k/lumen-mcp: Model Context Protocol server exposing snapshot provenance, structured component discovery, framework-aware usage/source, recipes, tolerant search, tokens, rules, and lumen:// resources for AI agents.\n\nInstall the portable Lumen Agent Skill:\n\n```bash\nnpx skills add santi020k/lumen --skill lumen-ui\n```\n\nDefault usage:\n\n```astro\n---\nimport { Button, Card, Input } from '@santi020k/lumen-astro'\nimport { UIPrimitives } from '@santi020k/lumen-astro'\nimport '@santi020k/lumen-astro/styles.css'\n---\n\n<UIPrimitives />\n<Card>\n <label for=\"email\">Email</label>\n <Input id=\"email\" type=\"email\" />\n <Button>Subscribe</Button>\n</Card>\n```\n\nRules for agents:\n\n- When Lumen MCP is connected, read `lumen://meta`, `lumen://diagnostics`, and `lumen://rules`, pass the target framework to `lumen_search`, and follow the framework behavior returned by `lumen_get_component`. Retain `lumen://catalog-manifest` and use `lumen_diff_catalog` after upgrades when the client supports cached context.\n- Prefer Astro unless the user explicitly targets React or Web Components.\n- In React, use the visual components with behavior hooks for Dialog, Popover, DropdownMenu, Tabs, Select, Toast, and Tooltip instead of mounting the Astro runtime.\n- In Web Components, registered `lumen-*` elements include behavior parity for Dialog, Popover, DropdownMenu, Tabs, Select, Toast, and Tooltip, including ARIA state, keyboard paths, Escape/outside dismissal, focus handling, native select form participation, and the shared toast controller.\n- Do not require Tailwind configuration for Lumen components.\n- Use public tokens: canvas, surface, surface-muted, surface-strong, line, ink, ink-soft, ink-muted, brand, brand-solid, brand-soft, accent, success, warning, danger.\n- Mount `UIPrimitives` once for interactive Astro primitives.\n- Use `glass` for glass surfaces. Overlay `surface=\"glass\"` is a deprecated compatibility alias that maps to `glass`.\n- Treat schedule, data collection, rich text, theme builder, and advanced fields as supported surfaces with progressively enhanced behavior.\n- Use `lumen list`, `lumen show <component>`, and `lumen add <component>` for individually addressable registry components; component names also resolve from kebab-case aliases such as `data-table`.\n- Runtime CustomEvents used by `UIPrimitives`: `ui:data-table-selection-change` from `[data-ui-datatable]` with `{ values }` (`ui:datatable-selection-change` remains a deprecated alias until 1.0); `ui:schedule-change` from `[data-ui-schedule]` with `{ eventId, slot }`; `ui:virtual-list-range` from `[data-ui-virtual-list]` with `{ startIndex, endIndex }`; `ui:tag-remove` from tag groups with `{ value }`; `ui:editor-command` from rich text editors with `{ command }`; `ui:theme-change` from theme builders with `{ hue, tokens }`; `ui:theme-export` from theme builders with `{ css }`; `ui:validate`, `ui:invalid`, and `ui:valid` from `[data-ui-form]` for native Constraint Validation API enhancement; document-level `ui:toast`, `ui:toast-update`, and `ui:toast-dismiss` for runtime toasts; `ui:toast-action` from `[data-ui-toast]` when an action button is pressed.\n- Add `data-ui-form` to forms that should reflect `required`, `pattern`, `min`, `max`, `type`, and custom `setCustomValidity()` state into Field error slots on blur and submit. Use `data-error-required`, `data-error-pattern`, `data-error-min`, `data-error-max`, or `data-error-custom` to override browser validation messages.\n- Toasts use `Sonner` viewports with `placement` and `maxCount`. With `UIPrimitives` or registered Web Components, use `window.LumenToast.create(detail)`, `.update(id, detail)`, and `.dismiss(id?)`, import `LumenToast` from `@santi020k/lumen-elements`, or dispatch the matching document events. Runtime toast `detail` supports `title`, `description`, `variant`, `duration`, `placement`, `max`, and `action`.\n",
|
|
25044
26818
|
"tokens": {
|
|
26819
|
+
"chart": {
|
|
26820
|
+
"axis": "var(--ink-muted)",
|
|
26821
|
+
"divergingMid": "220 13% 91%",
|
|
26822
|
+
"divergingNegative": "0 84% 60%",
|
|
26823
|
+
"divergingPositive": "221 83% 53%",
|
|
26824
|
+
"grid": "var(--line)",
|
|
26825
|
+
"sequentialHigh": "221 83% 40%",
|
|
26826
|
+
"sequentialLow": "218 100% 97%",
|
|
26827
|
+
"sequentialMid": "221 83% 67%",
|
|
26828
|
+
"series1": "221 83% 53%",
|
|
26829
|
+
"series2": "168 76% 36%",
|
|
26830
|
+
"series3": "280 72% 56%",
|
|
26831
|
+
"series4": "25 95% 53%",
|
|
26832
|
+
"series5": "340 82% 55%",
|
|
26833
|
+
"series6": "190 82% 42%",
|
|
26834
|
+
"series7": "52 92% 45%",
|
|
26835
|
+
"series8": "215 16% 47%"
|
|
26836
|
+
},
|
|
25045
26837
|
"colors": {
|
|
25046
26838
|
"accent": "264 95% 57%",
|
|
25047
26839
|
"brand": "264 92% 47%",
|