@kanzo-tech/ui 0.1.0 → 0.2.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/dist/charts/chart-marks.d.ts +22 -3
- package/dist/charts/chart-marks.d.ts.map +1 -1
- package/dist/charts/chart-marks.js.map +1 -1
- package/dist/composites/sidebar.d.ts.map +1 -1
- package/dist/composites/sidebar.js +6 -0
- package/dist/composites/sidebar.js.map +1 -1
- package/dist/guard-corpus.d.ts.map +1 -1
- package/dist/simples/button.d.ts +25 -18
- package/dist/simples/button.d.ts.map +1 -1
- package/dist/simples/button.js +74 -32
- package/dist/simples/button.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +3 -3
|
@@ -2,9 +2,28 @@ import { Selection } from '@uwdata/mosaic-core';
|
|
|
2
2
|
import { ChartDescriptor } from './chart-spec.js';
|
|
3
3
|
/**
|
|
4
4
|
* The mark vocabulary. Every component here renders `null` — `ChartRoot` reads the `__chart`
|
|
5
|
-
* static off the element type and compiles it.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* static off the element type and compiles it.
|
|
6
|
+
*
|
|
7
|
+
* This file carries no `"use client"`, and the docblock claimed the opposite for as long as it
|
|
8
|
+
* existed: "load-bearing even though nothing here uses a hook". The rule the repo actually
|
|
9
|
+
* enforces is in `client-boundary.test.ts` — a file declares the directive **iff it is itself
|
|
10
|
+
* stateful** — and nothing here is, so the guard would reject it. The claim and the code were
|
|
11
|
+
* never both true.
|
|
12
|
+
*
|
|
13
|
+
* What the claim got right is the mechanism, and it is worth keeping: a descriptor rendered on the
|
|
14
|
+
* server DOES collapse to `null` before `ChartRoot` sees the element, because the `__chart` static
|
|
15
|
+
* lives on the element *type* and a Server Component is invoked before serialisation. What it got
|
|
16
|
+
* wrong is what prevents it. Not a directive here — the consumer. Every chart is written inside a
|
|
17
|
+
* client component, necessarily: `MosaicProvider` is one, and there is no coordinator without it.
|
|
18
|
+
* All 38 chart examples in `docs/examples` open with `"use client"`.
|
|
19
|
+
*
|
|
20
|
+
* So the trap is real and it belongs to a CONSUMER who writes a chart in a Server Component: the
|
|
21
|
+
* marks vanish and the plot renders empty, with no error anywhere. Nothing catches that today —
|
|
22
|
+
* `client-boundary.test.ts` matches shape and this file's shape is pure, `pnpm smoke` compares
|
|
23
|
+
* built bytes against source, and the docs RSC build only exercises the client path our own
|
|
24
|
+
* examples take. Fixing it properly means either the directive plus an exception in that guard for
|
|
25
|
+
* descriptor modules, or a check that a `chartDescriptor` element type survives the boundary. Both
|
|
26
|
+
* are decisions rather than edits, so this says what is true instead of pretending it is handled.
|
|
8
27
|
*/
|
|
9
28
|
export interface ChartMarkProps {
|
|
10
29
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-marks.d.ts","sourceRoot":"","sources":["../../src/charts/chart-marks.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAEL,KAAK,eAAe,EAIrB,MAAM,iBAAiB,CAAC;AAEzB
|
|
1
|
+
{"version":3,"file":"chart-marks.d.ts","sourceRoot":"","sources":["../../src/charts/chart-marks.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-marks.js","sources":["../../src/charts/chart-marks.tsx"],"sourcesContent":["import type { Selection } from \"@uwdata/mosaic-core\";\nimport { isColorToken, isColorValue } from \"./chart-config.js\";\nimport {\n chartDescriptor,\n type ChartDescriptor,\n type ChartMarkDirective,\n type ChartMarkSource,\n type ChartSpecContext,\n} from \"./chart-spec.js\";\n\n/**\n * The mark vocabulary. Every component here renders `null` — `ChartRoot` reads the `__chart`\n * static off the element type and compiles it. `\"use client\"` is load-bearing even though nothing\n * here uses a hook: a server-rendered descriptor would collapse to `null` before `ChartRoot`\n * ever sees it.\n */\n\nexport interface ChartMarkProps {\n /**\n * The selection this mark filters by. Defaults to `ChartRoot`'s; `null` draws the full relation\n * — the dimmed background layer of a crossfilter pair.\n */\n filterBy?: Selection | null;\n /**\n * A different relation for this mark alone. The root's `table` is the default, which is right\n * until a plot needs two — a node-link view draws nodes from one relation and edges from\n * another, and both still filter by the same selection.\n */\n table?: string;\n /** Literal rows instead of the root's table. */\n data?: readonly unknown[];\n /** Positions a rule/tick without a table: `at={0}` is the zero line. */\n at?: unknown;\n /** Observable Plot's per-mark hover tooltip. */\n tip?: boolean;\n x?: unknown;\n y?: unknown;\n z?: unknown;\n r?: unknown;\n /** Facet the plot horizontally by this column — one panel per distinct value. */\n fx?: unknown;\n /** Facet the plot vertically by this column. */\n fy?: unknown;\n /** A column name, or a colour — `var(--chart-1)` / `--primary` tokens are resolved for Plot. */\n fill?: unknown;\n /** A column name, or a colour; tokens are resolved the same way. */\n stroke?: unknown;\n opacity?: unknown;\n fillOpacity?: unknown;\n strokeOpacity?: unknown;\n strokeWidth?: unknown;\n sort?: unknown;\n reverse?: boolean;\n limit?: number;\n inset?: number;\n /** Any other vgplot / Observable Plot mark option. */\n [option: string]: unknown;\n}\n\n/** Only these two channels can hold a colour; everything else keeps its column name. */\nconst COLOR_CHANNELS = [\"fill\", \"stroke\"] as const;\n\n/**\n * Marks that stack, and therefore need a series key.\n *\n * In Observable Plot `z` defaults to `fill`, so a stacked bar coloured by a column just works.\n * Through Mosaic it does not: the fill arrives as `{ value, scale: \"color\" }`, `maybeZ` cannot\n * pull a series name out of that object, and `stackY` silently stacks every row on the previous\n * one — a chart that renders, looks plausible and is wrong, which is worse than one that throws.\n * So we restore Plot's own default: a column-valued `fill`/`stroke` becomes `z` unless the caller\n * set one. `z={null}` opts out (Plot's own way of saying \"do not group\").\n */\nconst STACKING_MARKS = new Set([\n \"barY\", \"barX\", \"areaY\", \"areaX\", \"area\", \"rectY\", \"rectX\", \"rect\", \"waffleY\", \"waffleX\",\n]);\n\nfunction markSource(props: ChartMarkProps, ctx: ChartSpecContext, decorator: boolean): ChartMarkSource {\n if (decorator) return null;\n if (props.data !== undefined) return { kind: \"values\", values: props.data };\n if (props.at !== undefined) return { kind: \"values\", values: Array.isArray(props.at) ? props.at : [props.at] };\n const table = props.table ?? ctx.table;\n if (table === undefined) return { kind: \"values\", values: [{}] };\n return {\n kind: \"table\",\n table,\n filterBy: props.filterBy === undefined ? ctx.filterBy : props.filterBy,\n };\n}\n\nfunction markDirective(mark: string, props: ChartMarkProps, ctx: ChartSpecContext, decorator: boolean): ChartMarkDirective {\n const channels: Record<string, unknown> = { ...props };\n // `filterBy` / `data` / `at` are our sugar; they choose the source, they are never mark options.\n delete channels.filterBy;\n delete channels.data;\n delete channels.at;\n delete channels.table;\n // Read the series key before the colour channels are resolved to `rgb(...)` strings.\n if (STACKING_MARKS.has(mark) && !(\"z\" in channels)) {\n const series = [channels.fill, channels.stroke].find(\n (v) => typeof v === \"string\" && !isColorValue(v),\n );\n if (series !== undefined) channels.z = series;\n }\n for (const channel of COLOR_CHANNELS) {\n const value = channels[channel];\n // `fill=\"host\"` is the *column* host; only a token reference is a colour we must resolve.\n if (typeof value === \"string\" && isColorToken(value)) channels[channel] = ctx.resolveColor(value);\n }\n return { kind: \"mark\", mark, source: markSource(props, ctx, decorator), options: channels };\n}\n\nfunction mark(displayName: string, type: string, decorator = false): ChartDescriptor<ChartMarkProps> {\n return chartDescriptor<ChartMarkProps>(displayName, (props, ctx) => markDirective(type, props, ctx, decorator));\n}\n\nexport const ChartBarY = mark(\"ChartBarY\", \"barY\");\nexport const ChartBarX = mark(\"ChartBarX\", \"barX\");\nexport const ChartWaffleY = mark(\"ChartWaffleY\", \"waffleY\");\nexport const ChartWaffleX = mark(\"ChartWaffleX\", \"waffleX\");\n\nexport const ChartLine = mark(\"ChartLine\", \"line\");\nexport const ChartLineY = mark(\"ChartLineY\", \"lineY\");\nexport const ChartLineX = mark(\"ChartLineX\", \"lineX\");\nexport const ChartArea = mark(\"ChartArea\", \"area\");\nexport const ChartAreaY = mark(\"ChartAreaY\", \"areaY\");\nexport const ChartAreaX = mark(\"ChartAreaX\", \"areaX\");\n\nexport const ChartDot = mark(\"ChartDot\", \"dot\");\nexport const ChartDotX = mark(\"ChartDotX\", \"dotX\");\nexport const ChartDotY = mark(\"ChartDotY\", \"dotY\");\nexport const ChartCircle = mark(\"ChartCircle\", \"circle\");\nexport const ChartHexagon = mark(\"ChartHexagon\", \"hexagon\");\nexport const ChartImage = mark(\"ChartImage\", \"image\");\n\nexport const ChartRect = mark(\"ChartRect\", \"rect\");\nexport const ChartRectY = mark(\"ChartRectY\", \"rectY\");\nexport const ChartRectX = mark(\"ChartRectX\", \"rectX\");\nexport const ChartCell = mark(\"ChartCell\", \"cell\");\nexport const ChartCellX = mark(\"ChartCellX\", \"cellX\");\nexport const ChartCellY = mark(\"ChartCellY\", \"cellY\");\n\nexport const ChartRuleY = mark(\"ChartRuleY\", \"ruleY\");\nexport const ChartRuleX = mark(\"ChartRuleX\", \"ruleX\");\nexport const ChartTickX = mark(\"ChartTickX\", \"tickX\");\nexport const ChartTickY = mark(\"ChartTickY\", \"tickY\");\nexport const ChartText = mark(\"ChartText\", \"text\");\nexport const ChartTextX = mark(\"ChartTextX\", \"textX\");\nexport const ChartTextY = mark(\"ChartTextY\", \"textY\");\n\nexport const ChartVector = mark(\"ChartVector\", \"vector\");\n// vgplot 0.29.2 builds this one with the mark type `vectoX`, which Observable Plot has no\n// function for. Wrapped for symmetry; use `<ChartVector>` until upstream fixes the typo.\nexport const ChartVectorX = mark(\"ChartVectorX\", \"vectorX\");\nexport const ChartVectorY = mark(\"ChartVectorY\", \"vectorY\");\nexport const ChartSpike = mark(\"ChartSpike\", \"spike\");\nexport const ChartArrow = mark(\"ChartArrow\", \"arrow\");\nexport const ChartLink = mark(\"ChartLink\", \"link\");\n\nexport const ChartHeatmap = mark(\"ChartHeatmap\", \"heatmap\");\nexport const ChartRaster = mark(\"ChartRaster\", \"raster\");\nexport const ChartRasterTile = mark(\"ChartRasterTile\", \"rasterTile\");\nexport const ChartContour = mark(\"ChartContour\", \"contour\");\nexport const ChartDenseLine = mark(\"ChartDenseLine\", \"denseLine\");\nexport const ChartDensity = mark(\"ChartDensity\", \"density\");\nexport const ChartDensityY = mark(\"ChartDensityY\", \"densityY\");\nexport const ChartDensityX = mark(\"ChartDensityX\", \"densityX\");\nexport const ChartHexbin = mark(\"ChartHexbin\", \"hexbin\");\nexport const ChartRegressionY = mark(\"ChartRegressionY\", \"regressionY\");\nexport const ChartErrorbarY = mark(\"ChartErrorbarY\", \"errorbarY\");\nexport const ChartErrorbarX = mark(\"ChartErrorbarX\", \"errorbarX\");\n\nexport const ChartVoronoi = mark(\"ChartVoronoi\", \"voronoi\");\nexport const ChartVoronoiMesh = mark(\"ChartVoronoiMesh\", \"voronoiMesh\");\nexport const ChartDelaunayLink = mark(\"ChartDelaunayLink\", \"delaunayLink\");\nexport const ChartDelaunayMesh = mark(\"ChartDelaunayMesh\", \"delaunayMesh\");\nexport const ChartHull = mark(\"ChartHull\", \"hull\");\nexport const ChartGeo = mark(\"ChartGeo\", \"geo\");\n\n// Decorators: they draw the frame, not the data, so vgplot gives them options and no source.\nexport const ChartFrame = mark(\"ChartFrame\", \"frame\", true);\nexport const ChartGridX = mark(\"ChartGridX\", \"gridX\", true);\nexport const ChartGridY = mark(\"ChartGridY\", \"gridY\", true);\nexport const ChartHexgrid = mark(\"ChartHexgrid\", \"hexgrid\", true);\nexport const ChartSphere = mark(\"ChartSphere\", \"sphere\", true);\nexport const ChartGraticule = mark(\"ChartGraticule\", \"graticule\", true);\n\nexport interface ChartRawProps {\n /** A `vg.*` directive, or several — `vg.axisFx({ anchor: \"top\" })`. */\n spec: unknown;\n}\n\n/**\n * The escape hatch. The wrappers above cover vgplot's mark vocabulary, but not its ~250 attributes\n * nor the `axisX`/`axisFy` decorator marks the axis descriptors deliberately compile away from.\n * Anything unwrapped goes in here, in source order, with the same interactor-binding semantics as\n * a wrapped mark:\n *\n * ```tsx\n * <ChartRaw spec={vg.axisFy({ anchor: \"right\", tickRotate: 45 })} />\n * ```\n */\nexport const ChartRaw = chartDescriptor<ChartRawProps>(\"ChartRaw\", (props) =>\n Array.isArray(props.spec)\n ? props.spec.map((value: unknown) => ({ kind: \"raw\" as const, value }))\n : { kind: \"raw\", value: props.spec },\n);\n"],"names":["COLOR_CHANNELS","STACKING_MARKS","markSource","props","ctx","decorator","table","markDirective","mark","channels","series","v","isColorValue","channel","value","isColorToken","displayName","type","chartDescriptor","ChartBarY","ChartBarX","ChartWaffleY","ChartWaffleX","ChartLine","ChartLineY","ChartLineX","ChartArea","ChartAreaY","ChartAreaX","ChartDot","ChartDotX","ChartDotY","ChartCircle","ChartHexagon","ChartImage","ChartRect","ChartRectY","ChartRectX","ChartCell","ChartCellX","ChartCellY","ChartRuleY","ChartRuleX","ChartTickX","ChartTickY","ChartText","ChartTextX","ChartTextY","ChartVector","ChartVectorX","ChartVectorY","ChartSpike","ChartArrow","ChartLink","ChartHeatmap","ChartRaster","ChartRasterTile","ChartContour","ChartDenseLine","ChartDensity","ChartDensityY","ChartDensityX","ChartHexbin","ChartRegressionY","ChartErrorbarY","ChartErrorbarX","ChartVoronoi","ChartVoronoiMesh","ChartDelaunayLink","ChartDelaunayMesh","ChartHull","ChartGeo","ChartFrame","ChartGridX","ChartGridY","ChartHexgrid","ChartSphere","ChartGraticule","ChartRaw"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chart-marks.js","sources":["../../src/charts/chart-marks.tsx"],"sourcesContent":["import type { Selection } from \"@uwdata/mosaic-core\";\nimport { isColorToken, isColorValue } from \"./chart-config.js\";\nimport {\n chartDescriptor,\n type ChartDescriptor,\n type ChartMarkDirective,\n type ChartMarkSource,\n type ChartSpecContext,\n} from \"./chart-spec.js\";\n\n/**\n * The mark vocabulary. Every component here renders `null` — `ChartRoot` reads the `__chart`\n * static off the element type and compiles it.\n *\n * This file carries no `\"use client\"`, and the docblock claimed the opposite for as long as it\n * existed: \"load-bearing even though nothing here uses a hook\". The rule the repo actually\n * enforces is in `client-boundary.test.ts` — a file declares the directive **iff it is itself\n * stateful** — and nothing here is, so the guard would reject it. The claim and the code were\n * never both true.\n *\n * What the claim got right is the mechanism, and it is worth keeping: a descriptor rendered on the\n * server DOES collapse to `null` before `ChartRoot` sees the element, because the `__chart` static\n * lives on the element *type* and a Server Component is invoked before serialisation. What it got\n * wrong is what prevents it. Not a directive here — the consumer. Every chart is written inside a\n * client component, necessarily: `MosaicProvider` is one, and there is no coordinator without it.\n * All 38 chart examples in `docs/examples` open with `\"use client\"`.\n *\n * So the trap is real and it belongs to a CONSUMER who writes a chart in a Server Component: the\n * marks vanish and the plot renders empty, with no error anywhere. Nothing catches that today —\n * `client-boundary.test.ts` matches shape and this file's shape is pure, `pnpm smoke` compares\n * built bytes against source, and the docs RSC build only exercises the client path our own\n * examples take. Fixing it properly means either the directive plus an exception in that guard for\n * descriptor modules, or a check that a `chartDescriptor` element type survives the boundary. Both\n * are decisions rather than edits, so this says what is true instead of pretending it is handled.\n */\n\nexport interface ChartMarkProps {\n /**\n * The selection this mark filters by. Defaults to `ChartRoot`'s; `null` draws the full relation\n * — the dimmed background layer of a crossfilter pair.\n */\n filterBy?: Selection | null;\n /**\n * A different relation for this mark alone. The root's `table` is the default, which is right\n * until a plot needs two — a node-link view draws nodes from one relation and edges from\n * another, and both still filter by the same selection.\n */\n table?: string;\n /** Literal rows instead of the root's table. */\n data?: readonly unknown[];\n /** Positions a rule/tick without a table: `at={0}` is the zero line. */\n at?: unknown;\n /** Observable Plot's per-mark hover tooltip. */\n tip?: boolean;\n x?: unknown;\n y?: unknown;\n z?: unknown;\n r?: unknown;\n /** Facet the plot horizontally by this column — one panel per distinct value. */\n fx?: unknown;\n /** Facet the plot vertically by this column. */\n fy?: unknown;\n /** A column name, or a colour — `var(--chart-1)` / `--primary` tokens are resolved for Plot. */\n fill?: unknown;\n /** A column name, or a colour; tokens are resolved the same way. */\n stroke?: unknown;\n opacity?: unknown;\n fillOpacity?: unknown;\n strokeOpacity?: unknown;\n strokeWidth?: unknown;\n sort?: unknown;\n reverse?: boolean;\n limit?: number;\n inset?: number;\n /** Any other vgplot / Observable Plot mark option. */\n [option: string]: unknown;\n}\n\n/** Only these two channels can hold a colour; everything else keeps its column name. */\nconst COLOR_CHANNELS = [\"fill\", \"stroke\"] as const;\n\n/**\n * Marks that stack, and therefore need a series key.\n *\n * In Observable Plot `z` defaults to `fill`, so a stacked bar coloured by a column just works.\n * Through Mosaic it does not: the fill arrives as `{ value, scale: \"color\" }`, `maybeZ` cannot\n * pull a series name out of that object, and `stackY` silently stacks every row on the previous\n * one — a chart that renders, looks plausible and is wrong, which is worse than one that throws.\n * So we restore Plot's own default: a column-valued `fill`/`stroke` becomes `z` unless the caller\n * set one. `z={null}` opts out (Plot's own way of saying \"do not group\").\n */\nconst STACKING_MARKS = new Set([\n \"barY\", \"barX\", \"areaY\", \"areaX\", \"area\", \"rectY\", \"rectX\", \"rect\", \"waffleY\", \"waffleX\",\n]);\n\nfunction markSource(props: ChartMarkProps, ctx: ChartSpecContext, decorator: boolean): ChartMarkSource {\n if (decorator) return null;\n if (props.data !== undefined) return { kind: \"values\", values: props.data };\n if (props.at !== undefined) return { kind: \"values\", values: Array.isArray(props.at) ? props.at : [props.at] };\n const table = props.table ?? ctx.table;\n if (table === undefined) return { kind: \"values\", values: [{}] };\n return {\n kind: \"table\",\n table,\n filterBy: props.filterBy === undefined ? ctx.filterBy : props.filterBy,\n };\n}\n\nfunction markDirective(mark: string, props: ChartMarkProps, ctx: ChartSpecContext, decorator: boolean): ChartMarkDirective {\n const channels: Record<string, unknown> = { ...props };\n // `filterBy` / `data` / `at` are our sugar; they choose the source, they are never mark options.\n delete channels.filterBy;\n delete channels.data;\n delete channels.at;\n delete channels.table;\n // Read the series key before the colour channels are resolved to `rgb(...)` strings.\n if (STACKING_MARKS.has(mark) && !(\"z\" in channels)) {\n const series = [channels.fill, channels.stroke].find(\n (v) => typeof v === \"string\" && !isColorValue(v),\n );\n if (series !== undefined) channels.z = series;\n }\n for (const channel of COLOR_CHANNELS) {\n const value = channels[channel];\n // `fill=\"host\"` is the *column* host; only a token reference is a colour we must resolve.\n if (typeof value === \"string\" && isColorToken(value)) channels[channel] = ctx.resolveColor(value);\n }\n return { kind: \"mark\", mark, source: markSource(props, ctx, decorator), options: channels };\n}\n\nfunction mark(displayName: string, type: string, decorator = false): ChartDescriptor<ChartMarkProps> {\n return chartDescriptor<ChartMarkProps>(displayName, (props, ctx) => markDirective(type, props, ctx, decorator));\n}\n\nexport const ChartBarY = mark(\"ChartBarY\", \"barY\");\nexport const ChartBarX = mark(\"ChartBarX\", \"barX\");\nexport const ChartWaffleY = mark(\"ChartWaffleY\", \"waffleY\");\nexport const ChartWaffleX = mark(\"ChartWaffleX\", \"waffleX\");\n\nexport const ChartLine = mark(\"ChartLine\", \"line\");\nexport const ChartLineY = mark(\"ChartLineY\", \"lineY\");\nexport const ChartLineX = mark(\"ChartLineX\", \"lineX\");\nexport const ChartArea = mark(\"ChartArea\", \"area\");\nexport const ChartAreaY = mark(\"ChartAreaY\", \"areaY\");\nexport const ChartAreaX = mark(\"ChartAreaX\", \"areaX\");\n\nexport const ChartDot = mark(\"ChartDot\", \"dot\");\nexport const ChartDotX = mark(\"ChartDotX\", \"dotX\");\nexport const ChartDotY = mark(\"ChartDotY\", \"dotY\");\nexport const ChartCircle = mark(\"ChartCircle\", \"circle\");\nexport const ChartHexagon = mark(\"ChartHexagon\", \"hexagon\");\nexport const ChartImage = mark(\"ChartImage\", \"image\");\n\nexport const ChartRect = mark(\"ChartRect\", \"rect\");\nexport const ChartRectY = mark(\"ChartRectY\", \"rectY\");\nexport const ChartRectX = mark(\"ChartRectX\", \"rectX\");\nexport const ChartCell = mark(\"ChartCell\", \"cell\");\nexport const ChartCellX = mark(\"ChartCellX\", \"cellX\");\nexport const ChartCellY = mark(\"ChartCellY\", \"cellY\");\n\nexport const ChartRuleY = mark(\"ChartRuleY\", \"ruleY\");\nexport const ChartRuleX = mark(\"ChartRuleX\", \"ruleX\");\nexport const ChartTickX = mark(\"ChartTickX\", \"tickX\");\nexport const ChartTickY = mark(\"ChartTickY\", \"tickY\");\nexport const ChartText = mark(\"ChartText\", \"text\");\nexport const ChartTextX = mark(\"ChartTextX\", \"textX\");\nexport const ChartTextY = mark(\"ChartTextY\", \"textY\");\n\nexport const ChartVector = mark(\"ChartVector\", \"vector\");\n// vgplot 0.29.2 builds this one with the mark type `vectoX`, which Observable Plot has no\n// function for. Wrapped for symmetry; use `<ChartVector>` until upstream fixes the typo.\nexport const ChartVectorX = mark(\"ChartVectorX\", \"vectorX\");\nexport const ChartVectorY = mark(\"ChartVectorY\", \"vectorY\");\nexport const ChartSpike = mark(\"ChartSpike\", \"spike\");\nexport const ChartArrow = mark(\"ChartArrow\", \"arrow\");\nexport const ChartLink = mark(\"ChartLink\", \"link\");\n\nexport const ChartHeatmap = mark(\"ChartHeatmap\", \"heatmap\");\nexport const ChartRaster = mark(\"ChartRaster\", \"raster\");\nexport const ChartRasterTile = mark(\"ChartRasterTile\", \"rasterTile\");\nexport const ChartContour = mark(\"ChartContour\", \"contour\");\nexport const ChartDenseLine = mark(\"ChartDenseLine\", \"denseLine\");\nexport const ChartDensity = mark(\"ChartDensity\", \"density\");\nexport const ChartDensityY = mark(\"ChartDensityY\", \"densityY\");\nexport const ChartDensityX = mark(\"ChartDensityX\", \"densityX\");\nexport const ChartHexbin = mark(\"ChartHexbin\", \"hexbin\");\nexport const ChartRegressionY = mark(\"ChartRegressionY\", \"regressionY\");\nexport const ChartErrorbarY = mark(\"ChartErrorbarY\", \"errorbarY\");\nexport const ChartErrorbarX = mark(\"ChartErrorbarX\", \"errorbarX\");\n\nexport const ChartVoronoi = mark(\"ChartVoronoi\", \"voronoi\");\nexport const ChartVoronoiMesh = mark(\"ChartVoronoiMesh\", \"voronoiMesh\");\nexport const ChartDelaunayLink = mark(\"ChartDelaunayLink\", \"delaunayLink\");\nexport const ChartDelaunayMesh = mark(\"ChartDelaunayMesh\", \"delaunayMesh\");\nexport const ChartHull = mark(\"ChartHull\", \"hull\");\nexport const ChartGeo = mark(\"ChartGeo\", \"geo\");\n\n// Decorators: they draw the frame, not the data, so vgplot gives them options and no source.\nexport const ChartFrame = mark(\"ChartFrame\", \"frame\", true);\nexport const ChartGridX = mark(\"ChartGridX\", \"gridX\", true);\nexport const ChartGridY = mark(\"ChartGridY\", \"gridY\", true);\nexport const ChartHexgrid = mark(\"ChartHexgrid\", \"hexgrid\", true);\nexport const ChartSphere = mark(\"ChartSphere\", \"sphere\", true);\nexport const ChartGraticule = mark(\"ChartGraticule\", \"graticule\", true);\n\nexport interface ChartRawProps {\n /** A `vg.*` directive, or several — `vg.axisFx({ anchor: \"top\" })`. */\n spec: unknown;\n}\n\n/**\n * The escape hatch. The wrappers above cover vgplot's mark vocabulary, but not its ~250 attributes\n * nor the `axisX`/`axisFy` decorator marks the axis descriptors deliberately compile away from.\n * Anything unwrapped goes in here, in source order, with the same interactor-binding semantics as\n * a wrapped mark:\n *\n * ```tsx\n * <ChartRaw spec={vg.axisFy({ anchor: \"right\", tickRotate: 45 })} />\n * ```\n */\nexport const ChartRaw = chartDescriptor<ChartRawProps>(\"ChartRaw\", (props) =>\n Array.isArray(props.spec)\n ? props.spec.map((value: unknown) => ({ kind: \"raw\" as const, value }))\n : { kind: \"raw\", value: props.spec },\n);\n"],"names":["COLOR_CHANNELS","STACKING_MARKS","markSource","props","ctx","decorator","table","markDirective","mark","channels","series","v","isColorValue","channel","value","isColorToken","displayName","type","chartDescriptor","ChartBarY","ChartBarX","ChartWaffleY","ChartWaffleX","ChartLine","ChartLineY","ChartLineX","ChartArea","ChartAreaY","ChartAreaX","ChartDot","ChartDotX","ChartDotY","ChartCircle","ChartHexagon","ChartImage","ChartRect","ChartRectY","ChartRectX","ChartCell","ChartCellX","ChartCellY","ChartRuleY","ChartRuleX","ChartTickX","ChartTickY","ChartText","ChartTextX","ChartTextY","ChartVector","ChartVectorX","ChartVectorY","ChartSpike","ChartArrow","ChartLink","ChartHeatmap","ChartRaster","ChartRasterTile","ChartContour","ChartDenseLine","ChartDensity","ChartDensityY","ChartDensityX","ChartHexbin","ChartRegressionY","ChartErrorbarY","ChartErrorbarX","ChartVoronoi","ChartVoronoiMesh","ChartDelaunayLink","ChartDelaunayMesh","ChartHull","ChartGeo","ChartFrame","ChartGridX","ChartGridY","ChartHexgrid","ChartSphere","ChartGraticule","ChartRaw"],"mappings":";;AA+EA,MAAMA,IAAiB,CAAC,QAAQ,QAAQ,GAYlCC,wBAAqB,IAAI;AAAA,EAC7B;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAS;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAS;AAAA,EAAQ;AAAA,EAAW;AACjF,CAAC;AAED,SAASC,EAAWC,GAAuBC,GAAuBC,GAAqC;AACrG,MAAIA,EAAW,QAAO;AACtB,MAAIF,EAAM,SAAS,OAAW,QAAO,EAAE,MAAM,UAAU,QAAQA,EAAM,KAAA;AACrE,MAAIA,EAAM,OAAO,eAAkB,EAAE,MAAM,UAAU,QAAQ,MAAM,QAAQA,EAAM,EAAE,IAAIA,EAAM,KAAK,CAACA,EAAM,EAAE,EAAA;AAC3G,QAAMG,IAAQH,EAAM,SAASC,EAAI;AACjC,SAAIE,MAAU,SAAkB,EAAE,MAAM,UAAU,QAAQ,CAAC,CAAA,CAAE,EAAA,IACtD;AAAA,IACL,MAAM;AAAA,IACN,OAAAA;AAAA,IACA,UAAUH,EAAM,aAAa,SAAYC,EAAI,WAAWD,EAAM;AAAA,EAAA;AAElE;AAEA,SAASI,EAAcC,GAAcL,GAAuBC,GAAuBC,GAAwC;AACzH,QAAMI,IAAoC,EAAE,GAAGN,EAAA;AAO/C,MALA,OAAOM,EAAS,UAChB,OAAOA,EAAS,MAChB,OAAOA,EAAS,IAChB,OAAOA,EAAS,OAEZR,EAAe,IAAIO,CAAI,KAAK,EAAE,OAAOC,IAAW;AAClD,UAAMC,IAAS,CAACD,EAAS,MAAMA,EAAS,MAAM,EAAE;AAAA,MAC9C,CAACE,MAAM,OAAOA,KAAM,YAAY,CAACC,EAAaD,CAAC;AAAA,IAAA;AAEjD,IAAID,MAAW,WAAWD,EAAS,IAAIC;AAAA,EACzC;AACA,aAAWG,KAAWb,GAAgB;AACpC,UAAMc,IAAQL,EAASI,CAAO;AAE9B,IAAI,OAAOC,KAAU,YAAYC,EAAaD,CAAK,MAAGL,EAASI,CAAO,IAAIT,EAAI,aAAaU,CAAK;AAAA,EAClG;AACA,SAAO,EAAE,MAAM,QAAQ,MAAAN,GAAM,QAAQN,EAAWC,GAAOC,GAAKC,CAAS,GAAG,SAASI,EAAA;AACnF;AAEA,SAASD,EAAKQ,GAAqBC,GAAcZ,IAAY,IAAwC;AACnG,SAAOa,EAAgCF,GAAa,CAACb,GAAOC,MAAQG,EAAcU,GAAMd,GAAOC,GAAKC,CAAS,CAAC;AAChH;AAEO,MAAMc,IAAYX,EAAK,aAAa,MAAM,GACpCY,IAAYZ,EAAK,aAAa,MAAM,GACpCa,IAAeb,EAAK,gBAAgB,SAAS,GAC7Cc,IAAed,EAAK,gBAAgB,SAAS,GAE7Ce,IAAYf,EAAK,aAAa,MAAM,GACpCgB,IAAahB,EAAK,cAAc,OAAO,GACvCiB,IAAajB,EAAK,cAAc,OAAO,GACvCkB,IAAYlB,EAAK,aAAa,MAAM,GACpCmB,IAAanB,EAAK,cAAc,OAAO,GACvCoB,IAAapB,EAAK,cAAc,OAAO,GAEvCqB,IAAWrB,EAAK,YAAY,KAAK,GACjCsB,IAAYtB,EAAK,aAAa,MAAM,GACpCuB,IAAYvB,EAAK,aAAa,MAAM,GACpCwB,IAAcxB,EAAK,eAAe,QAAQ,GAC1CyB,IAAezB,EAAK,gBAAgB,SAAS,GAC7C0B,IAAa1B,EAAK,cAAc,OAAO,GAEvC2B,IAAY3B,EAAK,aAAa,MAAM,GACpC4B,IAAa5B,EAAK,cAAc,OAAO,GACvC6B,IAAa7B,EAAK,cAAc,OAAO,GACvC8B,IAAY9B,EAAK,aAAa,MAAM,GACpC+B,IAAa/B,EAAK,cAAc,OAAO,GACvCgC,IAAahC,EAAK,cAAc,OAAO,GAEvCiC,IAAajC,EAAK,cAAc,OAAO,GACvCkC,IAAalC,EAAK,cAAc,OAAO,GACvCmC,IAAanC,EAAK,cAAc,OAAO,GACvCoC,IAAapC,EAAK,cAAc,OAAO,GACvCqC,IAAYrC,EAAK,aAAa,MAAM,GACpCsC,IAAatC,EAAK,cAAc,OAAO,GACvCuC,IAAavC,EAAK,cAAc,OAAO,GAEvCwC,IAAcxC,EAAK,eAAe,QAAQ,GAG1CyC,IAAezC,EAAK,gBAAgB,SAAS,GAC7C0C,IAAe1C,EAAK,gBAAgB,SAAS,GAC7C2C,IAAa3C,EAAK,cAAc,OAAO,GACvC4C,IAAa5C,EAAK,cAAc,OAAO,GACvC6C,IAAY7C,EAAK,aAAa,MAAM,GAEpC8C,IAAe9C,EAAK,gBAAgB,SAAS,GAC7C+C,IAAc/C,EAAK,eAAe,QAAQ,GAC1CgD,KAAkBhD,EAAK,mBAAmB,YAAY,GACtDiD,KAAejD,EAAK,gBAAgB,SAAS,GAC7CkD,KAAiBlD,EAAK,kBAAkB,WAAW,GACnDmD,KAAenD,EAAK,gBAAgB,SAAS,GAC7CoD,KAAgBpD,EAAK,iBAAiB,UAAU,GAChDqD,KAAgBrD,EAAK,iBAAiB,UAAU,GAChDsD,KAActD,EAAK,eAAe,QAAQ,GAC1CuD,KAAmBvD,EAAK,oBAAoB,aAAa,GACzDwD,KAAiBxD,EAAK,kBAAkB,WAAW,GACnDyD,KAAiBzD,EAAK,kBAAkB,WAAW,GAEnD0D,KAAe1D,EAAK,gBAAgB,SAAS,GAC7C2D,KAAmB3D,EAAK,oBAAoB,aAAa,GACzD4D,KAAoB5D,EAAK,qBAAqB,cAAc,GAC5D6D,KAAoB7D,EAAK,qBAAqB,cAAc,GAC5D8D,KAAY9D,EAAK,aAAa,MAAM,GACpC+D,KAAW/D,EAAK,YAAY,KAAK,GAGjCgE,KAAahE,EAAK,cAAc,SAAS,EAAI,GAC7CiE,KAAajE,EAAK,cAAc,SAAS,EAAI,GAC7CkE,KAAalE,EAAK,cAAc,SAAS,EAAI,GAC7CmE,KAAenE,EAAK,gBAAgB,WAAW,EAAI,GACnDoE,KAAcpE,EAAK,eAAe,UAAU,EAAI,GAChDqE,KAAiBrE,EAAK,kBAAkB,aAAa,EAAI,GAiBzDsE,KAAW5D;AAAA,EAA+B;AAAA,EAAY,CAACf,MAClE,MAAM,QAAQA,EAAM,IAAI,IACpBA,EAAM,KAAK,IAAI,CAACW,OAAoB,EAAE,MAAM,OAAgB,OAAAA,EAAA,EAAQ,IACpE,EAAE,MAAM,OAAO,OAAOX,EAAM,KAAA;AAClC;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../src/composites/sidebar.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../src/composites/sidebar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -453,6 +453,12 @@ const le = (e) => {
|
|
|
453
453
|
// light and 1.42–1.46 in dark against the surfaces the sidebar sits on, against 4.54 and
|
|
454
454
|
// 3.89–4.18 solid. Nothing else here changes on focus, so the ring is the whole indicator.
|
|
455
455
|
"outline-none focus-visible:ring-[3px] focus-visible:ring-sidebar-ring",
|
|
456
|
+
// The resting ink is stated rather than inherited. `variant="ghost"` sets
|
|
457
|
+
// `--btn-fg: var(--foreground)` and the recipe's base reads it, so a menu button that said
|
|
458
|
+
// nothing would answer to the document's ink instead of the sidebar's — invisible while the
|
|
459
|
+
// two agree, wrong the moment a theme parts them. Eight other parts in this file already
|
|
460
|
+
// spell it exactly this way.
|
|
461
|
+
"text-sidebar-foreground",
|
|
456
462
|
"active:bg-sidebar-accent active:text-sidebar-accent-foreground",
|
|
457
463
|
"data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground",
|
|
458
464
|
"group-has-data-[sidebar=menu-action]/menu-item:pe-8",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidebar.js","sources":["../../src/composites/sidebar.tsx"],"sourcesContent":["\"use client\";\n\nimport { ark } from \"@ark-ui/react/factory\";\nimport { PanelLeftIcon } from \"lucide-react\";\nimport React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\nimport { cn } from \"../lib/cn\";\nimport { Button, buttonVariants } from \"../simples/button\";\nimport { Input } from \"../simples/input\";\nimport { ScrollArea } from \"../simples/scroll-area\";\nimport { Separator } from \"../simples/separator\";\nimport {\n Sheet,\n SheetContent,\n SheetHeader,\n} from \"../simples/sheet\";\nimport { Skeleton } from \"../simples/skeleton\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../simples/tooltip\";\nimport { useIsMobile } from \"../lib/use-is-mobile.js\";\n\nconst SIDEBAR_COOKIE_NAME = \"sidebar_state\";\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;\nconst SIDEBAR_WIDTH = \"16rem\";\nconst SIDEBAR_WIDTH_MOBILE = \"18rem\";\nconst SIDEBAR_WIDTH_ICON = \"3rem\";\nconst SIDEBAR_KEYBOARD_SHORTCUT = \"b\";\n\ninterface SidebarContextProps {\n isMobile: boolean;\n open: boolean;\n openMobile: boolean;\n setOpen: (open: boolean) => void;\n setOpenMobile: (open: boolean) => void;\n state: \"expanded\" | \"collapsed\";\n toggleSidebar: () => void;\n}\n\nconst SidebarContext = React.createContext<SidebarContextProps | null>(null);\nSidebarContext.displayName = \"SidebarContext\";\n\ninterface SidebarProviderProps extends React.ComponentProps<\"div\"> {\n /**\n * The default open state of the sidebar.\n *\n * @default true\n */\n defaultOpen?: boolean;\n /**\n * The function to call when the open state of the sidebar changes.\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * The open state of the sidebar.\n */\n open?: boolean;\n}\n\nexport const SidebarProvider = (props: SidebarProviderProps) => {\n const {\n defaultOpen = true,\n open: openProp,\n onOpenChange: setOpenProp,\n className,\n style,\n slot,\n ...rest\n } = props;\n\n const isMobile = useIsMobile();\n const [openMobile, setOpenMobile] = React.useState(false);\n\n const [_open, _setOpen] = React.useState(defaultOpen);\n const open = openProp ?? _open;\n const setOpen = React.useCallback(\n (value: boolean | ((value: boolean) => boolean)) => {\n const openState = typeof value === \"function\" ? value(open) : value;\n if (setOpenProp) {\n setOpenProp(openState);\n } else {\n _setOpen(openState);\n }\n\n // biome-ignore lint/suspicious/noDocumentCookie: Persist the sidebar state across reloads.\n document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;\n },\n [setOpenProp, open]\n );\n\n const toggleSidebar = React.useCallback(() => {\n if (isMobile) {\n setOpenMobile((open) => !open);\n } else {\n setOpen((open) => !open);\n }\n }, [isMobile, setOpen]);\n\n React.useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (\n event.key === SIDEBAR_KEYBOARD_SHORTCUT &&\n (event.metaKey || event.ctrlKey)\n ) {\n event.preventDefault();\n toggleSidebar();\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [toggleSidebar]);\n\n const state = open ? \"expanded\" : \"collapsed\";\n\n const contextValue = React.useMemo<SidebarContextProps>(\n () => ({\n state,\n open,\n setOpen,\n isMobile,\n openMobile,\n setOpenMobile,\n toggleSidebar,\n }),\n [state, open, setOpen, isMobile, openMobile, toggleSidebar]\n );\n\n return (\n <SidebarContext.Provider value={contextValue}>\n <ark.div\n className={cn(\n \"group/sidebar-wrapper\",\n \"flex\",\n \"min-h-svh w-full\",\n \"has-data-[variant=inset]:bg-sidebar\",\n className\n )}\n style={\n {\n \"--sidebar-width\": SIDEBAR_WIDTH,\n \"--sidebar-width-icon\": SIDEBAR_WIDTH_ICON,\n ...style,\n } as React.CSSProperties\n }\n {...rest}\n data-slot={slot ?? \"sidebar-wrapper\"}\n />\n </SidebarContext.Provider>\n );\n};\n\ninterface SidebarProps extends React.ComponentProps<typeof Sheet> {\n className?: string;\n slot?: string;\n collapsible?: \"offcanvas\" | \"icon\" | \"none\";\n placement?: \"left\" | \"right\";\n variant?: \"sidebar\" | \"floating\" | \"inset\";\n}\n\nexport const Sidebar = (props: SidebarProps) => {\n const {\n collapsible = \"offcanvas\",\n placement = \"left\",\n variant = \"sidebar\",\n className,\n children,\n slot,\n ...rest\n } = props;\n\n const { isMobile, state, openMobile, setOpenMobile } = useSidebar();\n\n if (collapsible === \"none\") {\n return (\n <ark.aside\n className={cn(\n \"h-full w-(--sidebar-width)\",\n \"flex flex-col\",\n \"bg-sidebar\",\n \"text-sidebar-foreground\",\n className\n )}\n {...rest}\n data-slot={slot ?? \"sidebar\"}\n >\n {children}\n </ark.aside>\n );\n }\n\n if (isMobile) {\n return (\n <Sheet\n {...rest}\n onOpenChange={({ open }) => setOpenMobile(open)}\n open={openMobile}\n >\n <SheetContent\n className={cn(\n \"w-(--sidebar-width)\",\n \"p-0\",\n \"bg-sidebar\",\n \"text-sidebar-foreground\",\n \"[&>button]:hidden\"\n )}\n data-mobile=\"true\"\n data-sidebar=\"sidebar\"\n slot={slot ?? \"sidebar\"}\n placement={placement === \"left\" ? \"left\" : \"right\"}\n style={\n {\n \"--sidebar-width\": SIDEBAR_WIDTH_MOBILE,\n } as React.CSSProperties\n }\n >\n <SheetHeader\n className=\"sr-only\"\n description=\"Displays the mobile sidebar.\"\n title=\"Sidebar\"\n />\n <ark.div className=\"flex size-full flex-col\">{children}</ark.div>\n </SheetContent>\n </Sheet>\n );\n }\n\n return (\n <ark.div\n className={cn(\"group peer\", \"hidden md:block\", \"text-sidebar-foreground\")}\n data-collapsible={state === \"collapsed\" ? collapsible : \"\"}\n data-placement={placement}\n data-slot={slot ?? \"sidebar\"}\n data-state={state}\n data-variant={variant}\n >\n <ark.div\n className={cn(\n \"relative\",\n \"w-(--sidebar-width)\",\n \"bg-transparent\",\n \"transition-[width] duration-200 ease-linear\",\n \"group-data-[collapsible=offcanvas]:w-0\",\n \"group-data-[placement=right]:rotate-180\",\n variant === \"floating\" || variant === \"inset\"\n ? \"group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]\"\n : \"group-data-[collapsible=icon]:w-(--sidebar-width-icon)\",\n \"motion-reduce:transition-none!\"\n )}\n data-slot=\"sidebar-gap\"\n />\n <ark.div\n className={cn(\n \"fixed inset-y-0 z-10\",\n \"w-(--sidebar-width)\",\n \"hidden md:flex\",\n \"h-svh\",\n \"transition-[inset-inline-start,inset-inline-end,width] duration-200 ease-linear\",\n placement === \"left\"\n ? \"inset-s-0 group-data-[collapsible=offcanvas]:-inset-s-(--sidebar-width)\"\n : \"inset-e-0 group-data-[collapsible=offcanvas]:-inset-e-(--sidebar-width)\",\n variant === \"floating\" || variant === \"inset\"\n ? \"p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]\"\n : \"group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[placement=right]:border-s group-data-[placement=left]:border-e\",\n \"motion-reduce:transition-none!\",\n className\n )}\n {...rest}\n data-slot=\"sidebar-container\"\n >\n <ark.aside\n className={cn(\n \"size-full\",\n \"flex flex-col\",\n \"bg-sidebar\",\n \"group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow-sm\"\n )}\n data-sidebar=\"sidebar\"\n data-slot=\"sidebar-inner\"\n >\n {children}\n </ark.aside>\n </ark.div>\n </ark.div>\n );\n};\n\nexport const SidebarTrigger = (props: React.ComponentProps<typeof Button>) => {\n const { className, onClick, slot, ...rest } = props;\n\n const { toggleSidebar } = useSidebar();\n\n return (\n <Button\n className={cn(\"size-7\", className)}\n data-sidebar=\"trigger\"\n onClick={(event) => {\n onClick?.(event);\n toggleSidebar();\n }}\n size=\"icon-md\"\n variant=\"ghost\"\n {...rest}\n slot={slot ?? \"sidebar-trigger\"}\n >\n <PanelLeftIcon className=\"rtl:rotate-180\" />\n <ark.span className=\"sr-only\">Toggle Sidebar</ark.span>\n </Button>\n );\n};\n\nexport const SidebarRail = (props: React.ComponentProps<typeof ark.button>) => {\n const { className, slot, ...rest } = props;\n\n const { toggleSidebar } = useSidebar();\n\n return (\n <ark.button\n aria-label=\"Toggle Sidebar\"\n className={cn(\n \"absolute inset-y-0 z-20 -translate-x-1/2\",\n \"w-4\",\n \"hidden sm:flex\",\n \"transition-all ease-linear\",\n \"after:absolute after:inset-s-1/2 after:inset-y-0 after:w-[2px]\",\n \"hover:after:bg-sidebar-border\",\n \"group-data-[placement=left]:-inset-e-4 group-data-[placement=right]:inset-s-0\",\n \"in-data-[placement=left]:cursor-w-resize in-data-[placement=right]:cursor-e-resize\",\n \"[[data-placement=left][data-state=collapsed]_&]:cursor-e-resize [[data-placement=right][data-state=collapsed]_&]:cursor-w-resize\",\n \"group-data-[collapsible=offcanvas]:translate-x-0 hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:after:inset-s-full\",\n \"[[data-placement=left][data-collapsible=offcanvas]_&]:-inset-e-2\",\n \"[[data-placement=right][data-collapsible=offcanvas]_&]:-inset-s-2\",\n \"motion-reduce:transition-none!\",\n className\n )}\n data-sidebar=\"rail\"\n onClick={toggleSidebar}\n tabIndex={-1}\n title=\"Toggle Sidebar\"\n type=\"button\"\n {...rest}\n data-slot={slot ?? \"sidebar-rail\"}\n />\n );\n};\n\n// A neutral offset column, not `<main>`: the content shell goes inside it and `ShellMain` owns\n// the landmark (one `<main>` per page; a region declares no role).\nexport const SidebarInset = (props: React.ComponentProps<typeof ark.div>) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.div\n className={cn(\n \"relative flex w-full min-w-0 flex-1 flex-col bg-background\",\n \"md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ms-2\",\n \"md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ms-0\",\n \"md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm\",\n className\n )}\n {...rest}\n data-slot={slot ?? \"sidebar-inset\"}\n />\n );\n};\n\nexport const SidebarInput = (props: React.ComponentProps<typeof Input>) => {\n const { className, slot, ...rest } = props;\n\n return (\n <Input\n className={cn(\"h-8 w-full bg-background shadow-none\", className)}\n data-sidebar=\"input\"\n {...rest}\n slot={slot ?? \"sidebar-input\"}\n />\n );\n};\n\nexport const SidebarHeader = (props: React.ComponentProps<typeof ark.div>) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.div\n className={cn(\"flex flex-col gap-2 p-2\", className)}\n data-sidebar=\"header\"\n {...rest}\n data-slot={slot ?? \"sidebar-header\"}\n />\n );\n};\n\nexport const SidebarFooter = (props: React.ComponentProps<typeof ark.div>) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.div\n className={cn(\"flex flex-col gap-2 p-2\", className)}\n data-sidebar=\"footer\"\n {...rest}\n data-slot={slot ?? \"sidebar-footer\"}\n />\n );\n};\n\nexport const SidebarSeparator = (\n props: React.ComponentProps<typeof Separator>\n) => {\n const { className, slot, ...rest } = props;\n\n return (\n <Separator\n className={cn(\"mx-2 w-auto bg-sidebar-border\", className)}\n data-sidebar=\"separator\"\n {...rest}\n slot={slot ?? \"sidebar-separator\"}\n />\n );\n};\n\ninterface SidebarContentProps extends React.ComponentProps<\"div\"> {\n /**\n * Whether to add a scroll fade effect to the sidebar content.\n *\n * @default false\n */\n scrollFade?: boolean;\n}\nexport const SidebarContent = (props: SidebarContentProps) => {\n const { scrollFade = false, className, slot, ...rest } = props;\n\n return (\n <ScrollArea\n className=\"[--fade-size:3rem] **:data-[slot=scroll-area-scrollbar]:hidden\"\n scrollFade={scrollFade}\n >\n <ark.div\n className={cn(\n \"min-h-0\",\n \"flex flex-1 flex-col gap-0\",\n \"overflow-auto\",\n \"group-data-[collapsible=icon]:overflow-hidden\",\n className\n )}\n data-sidebar=\"content\"\n {...rest}\n data-slot={slot ?? \"sidebar-content\"}\n />\n </ScrollArea>\n );\n};\n\nexport const SidebarGroup = (props: React.ComponentProps<typeof ark.div>) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.div\n className={cn(\"relative flex w-full min-w-0 flex-col p-2\", className)}\n data-sidebar=\"group\"\n {...rest}\n data-slot={slot ?? \"sidebar-group\"}\n />\n );\n};\n\nexport const SidebarGroupLabel = (\n props: React.ComponentProps<typeof ark.div>\n) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.div\n className={cn(\n \"h-8\",\n \"px-2\",\n \"flex shrink-0 items-center\",\n \"font-medium text-sidebar-foreground/70 text-xs\",\n \"rounded-md\",\n \"transition-[margin,opacity] duration-200 ease-linear\",\n \"outline-hidden ring-sidebar-ring focus-visible:ring-2\",\n \"[&_svg]:size-4 [&_svg]:shrink-0\",\n \"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0\",\n \"motion-reduce:transition-none!\",\n className\n )}\n data-sidebar=\"group-label\"\n {...rest}\n data-slot={slot ?? \"sidebar-group-label\"}\n />\n );\n};\n\nexport const SidebarGroupAction = (\n props: React.ComponentProps<typeof ark.button>\n) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.button\n className={cn(\n buttonVariants({\n variant: \"ghost\",\n size: \"icon-sm\",\n clickEffect: false,\n }),\n \"absolute inset-e-3 top-3.5\",\n \"text-sidebar-foreground\",\n \"transition-transform\",\n \"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n \"[&_svg]:size-4 [&_svg]:shrink-0\",\n \"after:absolute after:-inset-2 md:after:hidden\",\n \"group-data-[collapsible=icon]:hidden\",\n \"motion-reduce:transition-none!\",\n className\n )}\n data-sidebar=\"group-action\"\n type=\"button\"\n {...rest}\n data-slot={slot ?? \"sidebar-group-action\"}\n />\n );\n};\n\nexport const SidebarGroupContent = (\n props: React.ComponentProps<typeof ark.div>\n) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.div\n className={cn(\"w-full text-sm\", className)}\n data-sidebar=\"group-content\"\n {...rest}\n data-slot={slot ?? \"sidebar-group-content\"}\n />\n );\n};\n\nexport const SidebarMenu = (props: React.ComponentProps<typeof ark.ul>) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.ul\n className={cn(\"w-full min-w-0\", \"flex flex-col gap-0\", className)}\n data-sidebar=\"menu\"\n {...rest}\n data-slot={slot ?? \"sidebar-menu\"}\n />\n );\n};\n\nexport const SidebarMenuItem = (props: React.ComponentProps<typeof ark.li>) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.li\n className={cn(\"group/menu-item relative\", className)}\n data-sidebar=\"menu-item\"\n {...rest}\n data-slot={slot ?? \"sidebar-menu-item\"}\n />\n );\n};\n\ninterface SidebarMenuButtonProps extends React.ComponentProps<typeof Button> {\n /**\n * Whether the button is active.\n *\n * @default false\n */\n isActive?: boolean;\n /**\n * The tooltip to display when hovering over the button.\n *\n */\n tooltip?: string | React.ComponentProps<typeof TooltipContent>;\n}\n\nexport const SidebarMenuButton = ({\n tooltip,\n ...props\n}: SidebarMenuButtonProps) => {\n const {\n isActive = false,\n size = \"md\",\n variant = \"ghost\",\n className,\n slot,\n ...rest\n } = props;\n\n const { isMobile, state } = useSidebar();\n\n const button = (\n <Button\n className={cn(\n \"peer/menu-button group/menu-button\",\n \"w-full\",\n \"justify-start gap-2\",\n \"p-2\",\n \"overflow-hidden\",\n \"transition-[width,height,padding]\",\n \"data-[size=sm]:text-xs\",\n \"data-[size=lg]:h-12\",\n \"group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2!\",\n \"data-[size=lg]:group-data-[collapsible=icon]:p-0!\",\n \"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n // Upstream spells the width `sidebar-ring-[3px]`, which is not a utility — Tailwind emits\n // nothing for it, so these two buttons set a ring colour and no ring, and the focus\n // indicator never renders. The colour was the banned dilution besides: measured 1.49:1 in\n // light and 1.42–1.46 in dark against the surfaces the sidebar sits on, against 4.54 and\n // 3.89–4.18 solid. Nothing else here changes on focus, so the ring is the whole indicator.\n \"outline-none focus-visible:ring-[3px] focus-visible:ring-sidebar-ring\",\n \"active:bg-sidebar-accent active:text-sidebar-accent-foreground\",\n \"data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground\",\n \"group-has-data-[sidebar=menu-action]/menu-item:pe-8\",\n \"[&>span:last-child]:truncate\",\n \"motion-reduce:transition-none!\",\n className\n )}\n clickEffect={false}\n data-active={isActive}\n data-sidebar=\"menu-button\"\n data-size={size}\n size={size}\n variant={variant}\n {...rest}\n slot={slot ?? \"sidebar-menu-button\"}\n />\n );\n\n if (!tooltip) {\n return button;\n }\n\n if (typeof tooltip === \"string\") {\n tooltip = {\n children: tooltip,\n };\n }\n\n return (\n <Tooltip positioning={{ placement: \"right\" }}>\n <TooltipTrigger asChild>{button}</TooltipTrigger>\n <TooltipContent hidden={state !== \"collapsed\" || isMobile} {...tooltip} />\n </Tooltip>\n );\n};\n\ninterface SidebarMenuActionProps\n extends React.ComponentProps<typeof ark.button> {\n showOnHover?: boolean;\n}\n\nexport const SidebarMenuAction = (props: SidebarMenuActionProps) => {\n const { className, showOnHover = false, slot, ...rest } = props;\n\n return (\n <ark.button\n className={cn(\n buttonVariants({\n variant: \"ghost\",\n size: \"icon-sm\",\n clickEffect: false,\n }),\n \"absolute inset-e-1 top-1.5\",\n \"text-sidebar-foreground\",\n \"transition-transform\",\n \"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n \"peer-hover/menu-button:text-sidebar-accent-foreground\",\n \"after:absolute after:-inset-2 md:after:hidden\",\n \"peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=md]/menu-button:top-1.5 peer-data-[size=sm]/menu-button:top-1\",\n \"group-data-[collapsible=icon]:hidden\",\n \"[&_svg]:size-4 [&_svg]:shrink-0\",\n !showOnHover &&\n \"group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:opacity-0\",\n \"motion-reduce:transition-none!\",\n className\n )}\n data-sidebar=\"menu-action\"\n type=\"button\"\n {...rest}\n data-slot={slot ?? \"sidebar-menu-action\"}\n />\n );\n};\n\nconst sidebarMenuBadgeVariants = tv({\n base: [\n \"flex items-center justify-center\",\n \"px-1\",\n \"h-5 min-w-5\",\n \"rounded-md\",\n \"select-none font-medium text-sidebar-foreground text-xs tabular-nums\",\n \"group-data-[collapsible=icon]:hidden\",\n ],\n variants: {\n placement: {\n /** Overlaid on the row's trailing edge, sized off the peer button (Shark/shadcn default). */\n overlay: [\n \"pointer-events-none absolute inset-e-1\",\n \"peer-hover/menu-button:text-sidebar-accent-foreground\",\n \"peer-data-[active=true]/menu-button:text-sidebar-accent-foreground\",\n \"peer-data-[size=lg]/menu-button:top-2.5\",\n \"peer-data-[size=md]/menu-button:top-1.5\",\n \"peer-data-[size=sm]/menu-button:top-1\",\n ],\n /**\n * In the flow, INSIDE the row. Required whenever the row already ends in something else\n * (a chevron, a `SidebarMenuAction`): the overlay placement would stack on top of it.\n */\n inline: \"ms-auto shrink-0\",\n },\n },\n defaultVariants: { placement: \"overlay\" },\n});\n\nexport interface SidebarMenuBadgeProps\n extends React.ComponentProps<typeof ark.div>,\n VariantProps<typeof sidebarMenuBadgeVariants> {}\n\nexport const SidebarMenuBadge = (props: SidebarMenuBadgeProps) => {\n const { className, placement = \"overlay\", slot, ...rest } = props;\n\n return (\n <ark.div\n className={cn(sidebarMenuBadgeVariants({ placement }), className)}\n data-placement={placement}\n data-sidebar=\"menu-badge\"\n {...rest}\n data-slot={slot ?? \"sidebar-menu-badge\"}\n />\n );\n};\n\ninterface SidebarMenuSkeletonProps\n extends React.ComponentProps<typeof ark.div> {\n showIcon?: boolean;\n}\n\nexport const SidebarMenuSkeleton = (props: SidebarMenuSkeletonProps) => {\n const { className, showIcon = false, slot, ...rest } = props;\n\n const width = React.useMemo(\n () => `${Math.floor(Math.random() * 40) + 50}%`,\n []\n );\n\n return (\n <ark.div\n className={cn(\"flex h-8 items-center gap-2 rounded-md px-2\", className)}\n data-sidebar=\"menu-skeleton\"\n {...rest}\n data-slot={slot ?? \"sidebar-menu-skeleton\"}\n >\n {!!showIcon && (\n <Skeleton\n className=\"size-4 rounded-md\"\n data-sidebar=\"menu-skeleton-icon\"\n />\n )}\n <Skeleton\n className=\"h-4 max-w-(--skeleton-width) flex-1\"\n data-sidebar=\"menu-skeleton-text\"\n style={\n {\n \"--skeleton-width\": width,\n } as React.CSSProperties\n }\n />\n </ark.div>\n );\n};\n\nexport const SidebarMenuSub = (props: React.ComponentProps<typeof ark.ul>) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.ul\n className={cn(\n \"mx-3.5 flex min-w-0 flex-col gap-1 px-2.5 py-0.5 ltr:translate-x-px rtl:-translate-x-px\",\n \"border-sidebar-border border-s\",\n \"group-data-[collapsible=icon]:hidden\",\n className\n )}\n data-sidebar=\"menu-sub\"\n {...rest}\n data-slot={slot ?? \"sidebar-menu-sub\"}\n />\n );\n};\n\nexport const SidebarMenuSubItem = ({\n className,\n slot,\n ...props\n}: React.ComponentProps<typeof ark.li>) => (\n <ark.li\n className={cn(\"group/menu-sub-item relative\", className)}\n data-sidebar=\"menu-sub-item\"\n {...props}\n data-slot={slot ?? \"sidebar-menu-sub-item\"}\n />\n);\n\ninterface SidebarMenuSubButtonProps\n extends React.ComponentProps<typeof ark.a>,\n VariantProps<typeof buttonVariants> {\n isActive?: boolean;\n}\n\nexport const SidebarMenuSubButton = (props: SidebarMenuSubButtonProps) => {\n const { size = \"md\", isActive = false, className, slot, ...rest } = props;\n\n return (\n <ark.a\n className={cn(\n buttonVariants({ size, variant: \"ghost\", clickEffect: false }),\n \"w-full min-w-0\",\n \"justify-start\",\n \"px-2\",\n \"text-sidebar-foreground\",\n \"overflow-hidden\",\n \"ltr:-translate-x-px rtl:translate-x-px\",\n \"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n \"active:bg-sidebar-accent active:text-sidebar-accent-foreground\",\n \"data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground\",\n // Same non-utility width and same diluted ring as SidebarMenuButton — see the note there.\n \"outline-none focus-visible:ring-[3px] focus-visible:ring-sidebar-ring\",\n \"[&>span:last-child]:truncate\",\n \"[&_svg]:text-sidebar-accent-foreground\",\n className\n )}\n data-active={isActive}\n data-sidebar=\"menu-sub-button\"\n data-size={size}\n {...rest}\n data-slot={slot ?? \"sidebar-menu-sub-button\"}\n />\n );\n};\n\nexport const useSidebar = () => {\n const context = React.useContext(SidebarContext);\n\n if (context === null) {\n throw new Error(\"useSidebar must be used within a SidebarProvider.\");\n }\n\n return context;\n};\n"],"names":["SidebarContext","React"],"mappings":";;;;;;;;;;;;;;;AAwBA;AAkBAA;AAmBO;AACL;AAAM;AACU;AACR;AACQ;AACd;AACA;AACA;AACG;AAQiB;AAElB;AACA;AAOgG;AAClG;AACkB;AAIlB;AAGyB;AAI3BC;AACE;AACE;AAKE;AAIJ;AAEgE;AAGlE;AAE2B;AAClB;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEwD;AAG5D;AAEI;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AACA;AAAA;AAGA;AACqB;AACK;AACrB;AAAA;AAGH;AACe;AAAA;AAI3B;AAWE;AAAM;AACU;AACF;AACF;AACV;AACA;AACA;AACG;AAKL;AAEI;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AACA;AAAA;AAEE;AACe;AAElB;AAAA;AAOH;AAAC;AAAA;AACK;AAC0C;AACxC;AAEN;AAAC;AAAA;AACY;AACT;AACA;AACA;AACA;AACA;AAAA;AAEU;AACC;AACC;AAC6B;AAEzC;AACqB;AAAA;AAIvB;AAAA;AAAC;AAAA;AACW;AACE;AACN;AAAA;AAAA;AAE+C;AAAA;AAAA;AAAA;AACzD;AAMJ;AAAK;AAAJ;AACyE;AAChB;AACxC;AACG;AACP;AACE;AAEd;AAAA;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AACA;AACA;AAGI;AACJ;AAAA;AAEQ;AAAA;AAAA;AAEZ;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AACA;AAGI;AAGA;AACJ;AACA;AAAA;AAEE;AACM;AAEV;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AAAA;AAEW;AACH;AAET;AAAA;AAAA;AACH;AAAA;AACF;AAAA;AAGN;AAGE;AAIA;AACE;AAAC;AAAA;AACkC;AACpB;AAEX;AACA;AACF;AACK;AACG;AACJ;AACU;AAEd;AAA0C;AACE;AAAA;AAAA;AAGlD;AAGE;AAIA;AACE;AAAK;AAAJ;AACY;AACA;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEW;AACJ;AACC;AACJ;AACD;AACD;AACe;AAAA;AAGzB;AAKE;AAEA;AACE;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AACA;AAAA;AAEE;AACe;AAAA;AAGzB;AAGE;AAEA;AACE;AAAC;AAAA;AACgE;AAClD;AACT;AACU;AAAA;AAGpB;AAGE;AAEA;AACE;AAAK;AAAJ;AACmD;AACrC;AACT;AACe;AAAA;AAGzB;AAGE;AAEA;AACE;AAAK;AAAJ;AACmD;AACrC;AACT;AACe;AAAA;AAGzB;AAKE;AAEA;AACE;AAAC;AAAA;AACyD;AAC3C;AACT;AACU;AAAA;AAGpB;AAWE;AAEA;AACE;AAAC;AAAA;AACW;AACV;AAEA;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AACA;AAAA;AAEW;AACT;AACe;AAAA;AAAA;AACrB;AAGN;AAGE;AAEA;AACE;AAAK;AAAJ;AACqE;AACvD;AACT;AACe;AAAA;AAGzB;AAKE;AAEA;AACE;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEW;AACT;AACe;AAAA;AAGzB;AAKE;AAEA;AACE;AAAK;AAAJ;AACY;AACM;AACJ;AACH;AACO;AACd;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEW;AACR;AACD;AACe;AAAA;AAGzB;AAKE;AAEA;AACE;AAAK;AAAJ;AAC0C;AAC5B;AACT;AACe;AAAA;AAGzB;AAGE;AAEA;AACE;AAAK;AAAJ;AACiE;AACnD;AACT;AACe;AAAA;AAGzB;AAGE;AAEA;AACE;AAAK;AAAJ;AACoD;AACtC;AACT;AACe;AAAA;AAGzB;AAgBkC;AAChC;AAEF;AACE;AAAM;AACO;AACJ;AACG;AACV;AACA;AACG;AAMH;AAAC;AAAA;AACY;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEW;AACA;AACA;AACF;AACX;AACA;AACI;AACU;AAAA;AAIlB;AAKY;AACE;AAMV;AAAgC;AACwC;AAG9E;AAQE;AAEA;AACE;AAAK;AAAJ;AACY;AACM;AACJ;AACH;AACO;AACd;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEE;AACF;AACA;AAAA;AAEW;AACR;AACD;AACe;AAAA;AAGzB;AAEoC;AAC5B;AACJ;AACA;AACA;AACA;AACA;AACA;AAAA;AAEQ;AACG;AAAA;AAEA;AACP;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMM;AAAA;AACV;AAGJ;AAOE;AAEA;AACE;AAAK;AAAJ;AACiE;AAChD;AACH;AACT;AACe;AAAA;AAGzB;AAQE;AAEoB;AAC0B;AAC5C;AAGF;AACE;AAAK;AAAJ;AACuE;AACzD;AACT;AACe;AAElB;AACC;AAAC;AAAA;AACW;AACG;AAAA;AAAA;AAGjB;AAAC;AAAA;AACW;AACG;AAEX;AACsB;AAAA;AACtB;AAAA;AAEJ;AAAA;AAGN;AAGE;AAEA;AACE;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AAAA;AAEW;AACT;AACe;AAAA;AAGzB;AAEmC;AACjC;AACA;AAEF;AACE;AAAK;AAAJ;AACwD;AAC1C;AACT;AACe;AACrB;AAUA;AAEA;AACE;AAAK;AAAJ;AACY;AACoD;AAC7D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AAAA;AAEW;AACA;AACF;AACP;AACe;AAAA;AAGzB;AAGE;AAEA;AACE;AAGF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"sidebar.js","sources":["../../src/composites/sidebar.tsx"],"sourcesContent":["\"use client\";\n\nimport { ark } from \"@ark-ui/react/factory\";\nimport { PanelLeftIcon } from \"lucide-react\";\nimport React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\nimport { cn } from \"../lib/cn\";\nimport { Button, buttonVariants } from \"../simples/button\";\nimport { Input } from \"../simples/input\";\nimport { ScrollArea } from \"../simples/scroll-area\";\nimport { Separator } from \"../simples/separator\";\nimport {\n Sheet,\n SheetContent,\n SheetHeader,\n} from \"../simples/sheet\";\nimport { Skeleton } from \"../simples/skeleton\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../simples/tooltip\";\nimport { useIsMobile } from \"../lib/use-is-mobile.js\";\n\nconst SIDEBAR_COOKIE_NAME = \"sidebar_state\";\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;\nconst SIDEBAR_WIDTH = \"16rem\";\nconst SIDEBAR_WIDTH_MOBILE = \"18rem\";\nconst SIDEBAR_WIDTH_ICON = \"3rem\";\nconst SIDEBAR_KEYBOARD_SHORTCUT = \"b\";\n\ninterface SidebarContextProps {\n isMobile: boolean;\n open: boolean;\n openMobile: boolean;\n setOpen: (open: boolean) => void;\n setOpenMobile: (open: boolean) => void;\n state: \"expanded\" | \"collapsed\";\n toggleSidebar: () => void;\n}\n\nconst SidebarContext = React.createContext<SidebarContextProps | null>(null);\nSidebarContext.displayName = \"SidebarContext\";\n\ninterface SidebarProviderProps extends React.ComponentProps<\"div\"> {\n /**\n * The default open state of the sidebar.\n *\n * @default true\n */\n defaultOpen?: boolean;\n /**\n * The function to call when the open state of the sidebar changes.\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * The open state of the sidebar.\n */\n open?: boolean;\n}\n\nexport const SidebarProvider = (props: SidebarProviderProps) => {\n const {\n defaultOpen = true,\n open: openProp,\n onOpenChange: setOpenProp,\n className,\n style,\n slot,\n ...rest\n } = props;\n\n const isMobile = useIsMobile();\n const [openMobile, setOpenMobile] = React.useState(false);\n\n const [_open, _setOpen] = React.useState(defaultOpen);\n const open = openProp ?? _open;\n const setOpen = React.useCallback(\n (value: boolean | ((value: boolean) => boolean)) => {\n const openState = typeof value === \"function\" ? value(open) : value;\n if (setOpenProp) {\n setOpenProp(openState);\n } else {\n _setOpen(openState);\n }\n\n // biome-ignore lint/suspicious/noDocumentCookie: Persist the sidebar state across reloads.\n document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;\n },\n [setOpenProp, open]\n );\n\n const toggleSidebar = React.useCallback(() => {\n if (isMobile) {\n setOpenMobile((open) => !open);\n } else {\n setOpen((open) => !open);\n }\n }, [isMobile, setOpen]);\n\n React.useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (\n event.key === SIDEBAR_KEYBOARD_SHORTCUT &&\n (event.metaKey || event.ctrlKey)\n ) {\n event.preventDefault();\n toggleSidebar();\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [toggleSidebar]);\n\n const state = open ? \"expanded\" : \"collapsed\";\n\n const contextValue = React.useMemo<SidebarContextProps>(\n () => ({\n state,\n open,\n setOpen,\n isMobile,\n openMobile,\n setOpenMobile,\n toggleSidebar,\n }),\n [state, open, setOpen, isMobile, openMobile, toggleSidebar]\n );\n\n return (\n <SidebarContext.Provider value={contextValue}>\n <ark.div\n className={cn(\n \"group/sidebar-wrapper\",\n \"flex\",\n \"min-h-svh w-full\",\n \"has-data-[variant=inset]:bg-sidebar\",\n className\n )}\n style={\n {\n \"--sidebar-width\": SIDEBAR_WIDTH,\n \"--sidebar-width-icon\": SIDEBAR_WIDTH_ICON,\n ...style,\n } as React.CSSProperties\n }\n {...rest}\n data-slot={slot ?? \"sidebar-wrapper\"}\n />\n </SidebarContext.Provider>\n );\n};\n\ninterface SidebarProps extends React.ComponentProps<typeof Sheet> {\n className?: string;\n slot?: string;\n collapsible?: \"offcanvas\" | \"icon\" | \"none\";\n placement?: \"left\" | \"right\";\n variant?: \"sidebar\" | \"floating\" | \"inset\";\n}\n\nexport const Sidebar = (props: SidebarProps) => {\n const {\n collapsible = \"offcanvas\",\n placement = \"left\",\n variant = \"sidebar\",\n className,\n children,\n slot,\n ...rest\n } = props;\n\n const { isMobile, state, openMobile, setOpenMobile } = useSidebar();\n\n if (collapsible === \"none\") {\n return (\n <ark.aside\n className={cn(\n \"h-full w-(--sidebar-width)\",\n \"flex flex-col\",\n \"bg-sidebar\",\n \"text-sidebar-foreground\",\n className\n )}\n {...rest}\n data-slot={slot ?? \"sidebar\"}\n >\n {children}\n </ark.aside>\n );\n }\n\n if (isMobile) {\n return (\n <Sheet\n {...rest}\n onOpenChange={({ open }) => setOpenMobile(open)}\n open={openMobile}\n >\n <SheetContent\n className={cn(\n \"w-(--sidebar-width)\",\n \"p-0\",\n \"bg-sidebar\",\n \"text-sidebar-foreground\",\n \"[&>button]:hidden\"\n )}\n data-mobile=\"true\"\n data-sidebar=\"sidebar\"\n slot={slot ?? \"sidebar\"}\n placement={placement === \"left\" ? \"left\" : \"right\"}\n style={\n {\n \"--sidebar-width\": SIDEBAR_WIDTH_MOBILE,\n } as React.CSSProperties\n }\n >\n <SheetHeader\n className=\"sr-only\"\n description=\"Displays the mobile sidebar.\"\n title=\"Sidebar\"\n />\n <ark.div className=\"flex size-full flex-col\">{children}</ark.div>\n </SheetContent>\n </Sheet>\n );\n }\n\n return (\n <ark.div\n className={cn(\"group peer\", \"hidden md:block\", \"text-sidebar-foreground\")}\n data-collapsible={state === \"collapsed\" ? collapsible : \"\"}\n data-placement={placement}\n data-slot={slot ?? \"sidebar\"}\n data-state={state}\n data-variant={variant}\n >\n <ark.div\n className={cn(\n \"relative\",\n \"w-(--sidebar-width)\",\n \"bg-transparent\",\n \"transition-[width] duration-200 ease-linear\",\n \"group-data-[collapsible=offcanvas]:w-0\",\n \"group-data-[placement=right]:rotate-180\",\n variant === \"floating\" || variant === \"inset\"\n ? \"group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]\"\n : \"group-data-[collapsible=icon]:w-(--sidebar-width-icon)\",\n \"motion-reduce:transition-none!\"\n )}\n data-slot=\"sidebar-gap\"\n />\n <ark.div\n className={cn(\n \"fixed inset-y-0 z-10\",\n \"w-(--sidebar-width)\",\n \"hidden md:flex\",\n \"h-svh\",\n \"transition-[inset-inline-start,inset-inline-end,width] duration-200 ease-linear\",\n placement === \"left\"\n ? \"inset-s-0 group-data-[collapsible=offcanvas]:-inset-s-(--sidebar-width)\"\n : \"inset-e-0 group-data-[collapsible=offcanvas]:-inset-e-(--sidebar-width)\",\n variant === \"floating\" || variant === \"inset\"\n ? \"p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]\"\n : \"group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[placement=right]:border-s group-data-[placement=left]:border-e\",\n \"motion-reduce:transition-none!\",\n className\n )}\n {...rest}\n data-slot=\"sidebar-container\"\n >\n <ark.aside\n className={cn(\n \"size-full\",\n \"flex flex-col\",\n \"bg-sidebar\",\n \"group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow-sm\"\n )}\n data-sidebar=\"sidebar\"\n data-slot=\"sidebar-inner\"\n >\n {children}\n </ark.aside>\n </ark.div>\n </ark.div>\n );\n};\n\nexport const SidebarTrigger = (props: React.ComponentProps<typeof Button>) => {\n const { className, onClick, slot, ...rest } = props;\n\n const { toggleSidebar } = useSidebar();\n\n return (\n <Button\n className={cn(\"size-7\", className)}\n data-sidebar=\"trigger\"\n onClick={(event) => {\n onClick?.(event);\n toggleSidebar();\n }}\n size=\"icon-md\"\n variant=\"ghost\"\n {...rest}\n slot={slot ?? \"sidebar-trigger\"}\n >\n <PanelLeftIcon className=\"rtl:rotate-180\" />\n <ark.span className=\"sr-only\">Toggle Sidebar</ark.span>\n </Button>\n );\n};\n\nexport const SidebarRail = (props: React.ComponentProps<typeof ark.button>) => {\n const { className, slot, ...rest } = props;\n\n const { toggleSidebar } = useSidebar();\n\n return (\n <ark.button\n aria-label=\"Toggle Sidebar\"\n className={cn(\n \"absolute inset-y-0 z-20 -translate-x-1/2\",\n \"w-4\",\n \"hidden sm:flex\",\n \"transition-all ease-linear\",\n \"after:absolute after:inset-s-1/2 after:inset-y-0 after:w-[2px]\",\n \"hover:after:bg-sidebar-border\",\n \"group-data-[placement=left]:-inset-e-4 group-data-[placement=right]:inset-s-0\",\n \"in-data-[placement=left]:cursor-w-resize in-data-[placement=right]:cursor-e-resize\",\n \"[[data-placement=left][data-state=collapsed]_&]:cursor-e-resize [[data-placement=right][data-state=collapsed]_&]:cursor-w-resize\",\n \"group-data-[collapsible=offcanvas]:translate-x-0 hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:after:inset-s-full\",\n \"[[data-placement=left][data-collapsible=offcanvas]_&]:-inset-e-2\",\n \"[[data-placement=right][data-collapsible=offcanvas]_&]:-inset-s-2\",\n \"motion-reduce:transition-none!\",\n className\n )}\n data-sidebar=\"rail\"\n onClick={toggleSidebar}\n tabIndex={-1}\n title=\"Toggle Sidebar\"\n type=\"button\"\n {...rest}\n data-slot={slot ?? \"sidebar-rail\"}\n />\n );\n};\n\n// A neutral offset column, not `<main>`: the content shell goes inside it and `ShellMain` owns\n// the landmark (one `<main>` per page; a region declares no role).\nexport const SidebarInset = (props: React.ComponentProps<typeof ark.div>) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.div\n className={cn(\n \"relative flex w-full min-w-0 flex-1 flex-col bg-background\",\n \"md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ms-2\",\n \"md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ms-0\",\n \"md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm\",\n className\n )}\n {...rest}\n data-slot={slot ?? \"sidebar-inset\"}\n />\n );\n};\n\nexport const SidebarInput = (props: React.ComponentProps<typeof Input>) => {\n const { className, slot, ...rest } = props;\n\n return (\n <Input\n className={cn(\"h-8 w-full bg-background shadow-none\", className)}\n data-sidebar=\"input\"\n {...rest}\n slot={slot ?? \"sidebar-input\"}\n />\n );\n};\n\nexport const SidebarHeader = (props: React.ComponentProps<typeof ark.div>) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.div\n className={cn(\"flex flex-col gap-2 p-2\", className)}\n data-sidebar=\"header\"\n {...rest}\n data-slot={slot ?? \"sidebar-header\"}\n />\n );\n};\n\nexport const SidebarFooter = (props: React.ComponentProps<typeof ark.div>) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.div\n className={cn(\"flex flex-col gap-2 p-2\", className)}\n data-sidebar=\"footer\"\n {...rest}\n data-slot={slot ?? \"sidebar-footer\"}\n />\n );\n};\n\nexport const SidebarSeparator = (\n props: React.ComponentProps<typeof Separator>\n) => {\n const { className, slot, ...rest } = props;\n\n return (\n <Separator\n className={cn(\"mx-2 w-auto bg-sidebar-border\", className)}\n data-sidebar=\"separator\"\n {...rest}\n slot={slot ?? \"sidebar-separator\"}\n />\n );\n};\n\ninterface SidebarContentProps extends React.ComponentProps<\"div\"> {\n /**\n * Whether to add a scroll fade effect to the sidebar content.\n *\n * @default false\n */\n scrollFade?: boolean;\n}\nexport const SidebarContent = (props: SidebarContentProps) => {\n const { scrollFade = false, className, slot, ...rest } = props;\n\n return (\n <ScrollArea\n className=\"[--fade-size:3rem] **:data-[slot=scroll-area-scrollbar]:hidden\"\n scrollFade={scrollFade}\n >\n <ark.div\n className={cn(\n \"min-h-0\",\n \"flex flex-1 flex-col gap-0\",\n \"overflow-auto\",\n \"group-data-[collapsible=icon]:overflow-hidden\",\n className\n )}\n data-sidebar=\"content\"\n {...rest}\n data-slot={slot ?? \"sidebar-content\"}\n />\n </ScrollArea>\n );\n};\n\nexport const SidebarGroup = (props: React.ComponentProps<typeof ark.div>) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.div\n className={cn(\"relative flex w-full min-w-0 flex-col p-2\", className)}\n data-sidebar=\"group\"\n {...rest}\n data-slot={slot ?? \"sidebar-group\"}\n />\n );\n};\n\nexport const SidebarGroupLabel = (\n props: React.ComponentProps<typeof ark.div>\n) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.div\n className={cn(\n \"h-8\",\n \"px-2\",\n \"flex shrink-0 items-center\",\n \"font-medium text-sidebar-foreground/70 text-xs\",\n \"rounded-md\",\n \"transition-[margin,opacity] duration-200 ease-linear\",\n \"outline-hidden ring-sidebar-ring focus-visible:ring-2\",\n \"[&_svg]:size-4 [&_svg]:shrink-0\",\n \"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0\",\n \"motion-reduce:transition-none!\",\n className\n )}\n data-sidebar=\"group-label\"\n {...rest}\n data-slot={slot ?? \"sidebar-group-label\"}\n />\n );\n};\n\nexport const SidebarGroupAction = (\n props: React.ComponentProps<typeof ark.button>\n) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.button\n className={cn(\n buttonVariants({\n variant: \"ghost\",\n size: \"icon-sm\",\n clickEffect: false,\n }),\n \"absolute inset-e-3 top-3.5\",\n \"text-sidebar-foreground\",\n \"transition-transform\",\n \"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n \"[&_svg]:size-4 [&_svg]:shrink-0\",\n \"after:absolute after:-inset-2 md:after:hidden\",\n \"group-data-[collapsible=icon]:hidden\",\n \"motion-reduce:transition-none!\",\n className\n )}\n data-sidebar=\"group-action\"\n type=\"button\"\n {...rest}\n data-slot={slot ?? \"sidebar-group-action\"}\n />\n );\n};\n\nexport const SidebarGroupContent = (\n props: React.ComponentProps<typeof ark.div>\n) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.div\n className={cn(\"w-full text-sm\", className)}\n data-sidebar=\"group-content\"\n {...rest}\n data-slot={slot ?? \"sidebar-group-content\"}\n />\n );\n};\n\nexport const SidebarMenu = (props: React.ComponentProps<typeof ark.ul>) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.ul\n className={cn(\"w-full min-w-0\", \"flex flex-col gap-0\", className)}\n data-sidebar=\"menu\"\n {...rest}\n data-slot={slot ?? \"sidebar-menu\"}\n />\n );\n};\n\nexport const SidebarMenuItem = (props: React.ComponentProps<typeof ark.li>) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.li\n className={cn(\"group/menu-item relative\", className)}\n data-sidebar=\"menu-item\"\n {...rest}\n data-slot={slot ?? \"sidebar-menu-item\"}\n />\n );\n};\n\ninterface SidebarMenuButtonProps extends React.ComponentProps<typeof Button> {\n /**\n * Whether the button is active.\n *\n * @default false\n */\n isActive?: boolean;\n /**\n * The tooltip to display when hovering over the button.\n *\n */\n tooltip?: string | React.ComponentProps<typeof TooltipContent>;\n}\n\nexport const SidebarMenuButton = ({\n tooltip,\n ...props\n}: SidebarMenuButtonProps) => {\n const {\n isActive = false,\n size = \"md\",\n variant = \"ghost\",\n className,\n slot,\n ...rest\n } = props;\n\n const { isMobile, state } = useSidebar();\n\n const button = (\n <Button\n className={cn(\n \"peer/menu-button group/menu-button\",\n \"w-full\",\n \"justify-start gap-2\",\n \"p-2\",\n \"overflow-hidden\",\n \"transition-[width,height,padding]\",\n \"data-[size=sm]:text-xs\",\n \"data-[size=lg]:h-12\",\n \"group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2!\",\n \"data-[size=lg]:group-data-[collapsible=icon]:p-0!\",\n \"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n // Upstream spells the width `sidebar-ring-[3px]`, which is not a utility — Tailwind emits\n // nothing for it, so these two buttons set a ring colour and no ring, and the focus\n // indicator never renders. The colour was the banned dilution besides: measured 1.49:1 in\n // light and 1.42–1.46 in dark against the surfaces the sidebar sits on, against 4.54 and\n // 3.89–4.18 solid. Nothing else here changes on focus, so the ring is the whole indicator.\n \"outline-none focus-visible:ring-[3px] focus-visible:ring-sidebar-ring\",\n // The resting ink is stated rather than inherited. `variant=\"ghost\"` sets\n // `--btn-fg: var(--foreground)` and the recipe's base reads it, so a menu button that said\n // nothing would answer to the document's ink instead of the sidebar's — invisible while the\n // two agree, wrong the moment a theme parts them. Eight other parts in this file already\n // spell it exactly this way.\n \"text-sidebar-foreground\",\n \"active:bg-sidebar-accent active:text-sidebar-accent-foreground\",\n \"data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground\",\n \"group-has-data-[sidebar=menu-action]/menu-item:pe-8\",\n \"[&>span:last-child]:truncate\",\n \"motion-reduce:transition-none!\",\n className\n )}\n clickEffect={false}\n data-active={isActive}\n data-sidebar=\"menu-button\"\n data-size={size}\n size={size}\n variant={variant}\n {...rest}\n slot={slot ?? \"sidebar-menu-button\"}\n />\n );\n\n if (!tooltip) {\n return button;\n }\n\n if (typeof tooltip === \"string\") {\n tooltip = {\n children: tooltip,\n };\n }\n\n return (\n <Tooltip positioning={{ placement: \"right\" }}>\n <TooltipTrigger asChild>{button}</TooltipTrigger>\n <TooltipContent hidden={state !== \"collapsed\" || isMobile} {...tooltip} />\n </Tooltip>\n );\n};\n\ninterface SidebarMenuActionProps\n extends React.ComponentProps<typeof ark.button> {\n showOnHover?: boolean;\n}\n\nexport const SidebarMenuAction = (props: SidebarMenuActionProps) => {\n const { className, showOnHover = false, slot, ...rest } = props;\n\n return (\n <ark.button\n className={cn(\n buttonVariants({\n variant: \"ghost\",\n size: \"icon-sm\",\n clickEffect: false,\n }),\n \"absolute inset-e-1 top-1.5\",\n \"text-sidebar-foreground\",\n \"transition-transform\",\n \"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n \"peer-hover/menu-button:text-sidebar-accent-foreground\",\n \"after:absolute after:-inset-2 md:after:hidden\",\n \"peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=md]/menu-button:top-1.5 peer-data-[size=sm]/menu-button:top-1\",\n \"group-data-[collapsible=icon]:hidden\",\n \"[&_svg]:size-4 [&_svg]:shrink-0\",\n !showOnHover &&\n \"group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:opacity-0\",\n \"motion-reduce:transition-none!\",\n className\n )}\n data-sidebar=\"menu-action\"\n type=\"button\"\n {...rest}\n data-slot={slot ?? \"sidebar-menu-action\"}\n />\n );\n};\n\nconst sidebarMenuBadgeVariants = tv({\n base: [\n \"flex items-center justify-center\",\n \"px-1\",\n \"h-5 min-w-5\",\n \"rounded-md\",\n \"select-none font-medium text-sidebar-foreground text-xs tabular-nums\",\n \"group-data-[collapsible=icon]:hidden\",\n ],\n variants: {\n placement: {\n /** Overlaid on the row's trailing edge, sized off the peer button (Shark/shadcn default). */\n overlay: [\n \"pointer-events-none absolute inset-e-1\",\n \"peer-hover/menu-button:text-sidebar-accent-foreground\",\n \"peer-data-[active=true]/menu-button:text-sidebar-accent-foreground\",\n \"peer-data-[size=lg]/menu-button:top-2.5\",\n \"peer-data-[size=md]/menu-button:top-1.5\",\n \"peer-data-[size=sm]/menu-button:top-1\",\n ],\n /**\n * In the flow, INSIDE the row. Required whenever the row already ends in something else\n * (a chevron, a `SidebarMenuAction`): the overlay placement would stack on top of it.\n */\n inline: \"ms-auto shrink-0\",\n },\n },\n defaultVariants: { placement: \"overlay\" },\n});\n\nexport interface SidebarMenuBadgeProps\n extends React.ComponentProps<typeof ark.div>,\n VariantProps<typeof sidebarMenuBadgeVariants> {}\n\nexport const SidebarMenuBadge = (props: SidebarMenuBadgeProps) => {\n const { className, placement = \"overlay\", slot, ...rest } = props;\n\n return (\n <ark.div\n className={cn(sidebarMenuBadgeVariants({ placement }), className)}\n data-placement={placement}\n data-sidebar=\"menu-badge\"\n {...rest}\n data-slot={slot ?? \"sidebar-menu-badge\"}\n />\n );\n};\n\ninterface SidebarMenuSkeletonProps\n extends React.ComponentProps<typeof ark.div> {\n showIcon?: boolean;\n}\n\nexport const SidebarMenuSkeleton = (props: SidebarMenuSkeletonProps) => {\n const { className, showIcon = false, slot, ...rest } = props;\n\n const width = React.useMemo(\n () => `${Math.floor(Math.random() * 40) + 50}%`,\n []\n );\n\n return (\n <ark.div\n className={cn(\"flex h-8 items-center gap-2 rounded-md px-2\", className)}\n data-sidebar=\"menu-skeleton\"\n {...rest}\n data-slot={slot ?? \"sidebar-menu-skeleton\"}\n >\n {!!showIcon && (\n <Skeleton\n className=\"size-4 rounded-md\"\n data-sidebar=\"menu-skeleton-icon\"\n />\n )}\n <Skeleton\n className=\"h-4 max-w-(--skeleton-width) flex-1\"\n data-sidebar=\"menu-skeleton-text\"\n style={\n {\n \"--skeleton-width\": width,\n } as React.CSSProperties\n }\n />\n </ark.div>\n );\n};\n\nexport const SidebarMenuSub = (props: React.ComponentProps<typeof ark.ul>) => {\n const { className, slot, ...rest } = props;\n\n return (\n <ark.ul\n className={cn(\n \"mx-3.5 flex min-w-0 flex-col gap-1 px-2.5 py-0.5 ltr:translate-x-px rtl:-translate-x-px\",\n \"border-sidebar-border border-s\",\n \"group-data-[collapsible=icon]:hidden\",\n className\n )}\n data-sidebar=\"menu-sub\"\n {...rest}\n data-slot={slot ?? \"sidebar-menu-sub\"}\n />\n );\n};\n\nexport const SidebarMenuSubItem = ({\n className,\n slot,\n ...props\n}: React.ComponentProps<typeof ark.li>) => (\n <ark.li\n className={cn(\"group/menu-sub-item relative\", className)}\n data-sidebar=\"menu-sub-item\"\n {...props}\n data-slot={slot ?? \"sidebar-menu-sub-item\"}\n />\n);\n\ninterface SidebarMenuSubButtonProps\n extends React.ComponentProps<typeof ark.a>,\n VariantProps<typeof buttonVariants> {\n isActive?: boolean;\n}\n\nexport const SidebarMenuSubButton = (props: SidebarMenuSubButtonProps) => {\n const { size = \"md\", isActive = false, className, slot, ...rest } = props;\n\n return (\n <ark.a\n className={cn(\n buttonVariants({ size, variant: \"ghost\", clickEffect: false }),\n \"w-full min-w-0\",\n \"justify-start\",\n \"px-2\",\n \"text-sidebar-foreground\",\n \"overflow-hidden\",\n \"ltr:-translate-x-px rtl:translate-x-px\",\n \"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n \"active:bg-sidebar-accent active:text-sidebar-accent-foreground\",\n \"data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground\",\n // Same non-utility width and same diluted ring as SidebarMenuButton — see the note there.\n \"outline-none focus-visible:ring-[3px] focus-visible:ring-sidebar-ring\",\n \"[&>span:last-child]:truncate\",\n \"[&_svg]:text-sidebar-accent-foreground\",\n className\n )}\n data-active={isActive}\n data-sidebar=\"menu-sub-button\"\n data-size={size}\n {...rest}\n data-slot={slot ?? \"sidebar-menu-sub-button\"}\n />\n );\n};\n\nexport const useSidebar = () => {\n const context = React.useContext(SidebarContext);\n\n if (context === null) {\n throw new Error(\"useSidebar must be used within a SidebarProvider.\");\n }\n\n return context;\n};\n"],"names":["SidebarContext","React"],"mappings":";;;;;;;;;;;;;;;AAwBA;AAkBAA;AAmBO;AACL;AAAM;AACU;AACR;AACQ;AACd;AACA;AACA;AACG;AAQiB;AAElB;AACA;AAOgG;AAClG;AACkB;AAIlB;AAGyB;AAI3BC;AACE;AACE;AAKE;AAIJ;AAEgE;AAGlE;AAE2B;AAClB;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEwD;AAG5D;AAEI;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AACA;AAAA;AAGA;AACqB;AACK;AACrB;AAAA;AAGH;AACe;AAAA;AAI3B;AAWE;AAAM;AACU;AACF;AACF;AACV;AACA;AACA;AACG;AAKL;AAEI;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AACA;AAAA;AAEE;AACe;AAElB;AAAA;AAOH;AAAC;AAAA;AACK;AAC0C;AACxC;AAEN;AAAC;AAAA;AACY;AACT;AACA;AACA;AACA;AACA;AAAA;AAEU;AACC;AACC;AAC6B;AAEzC;AACqB;AAAA;AAIvB;AAAA;AAAC;AAAA;AACW;AACE;AACN;AAAA;AAAA;AAE+C;AAAA;AAAA;AAAA;AACzD;AAMJ;AAAK;AAAJ;AACyE;AAChB;AACxC;AACG;AACP;AACE;AAEd;AAAA;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AACA;AACA;AAGI;AACJ;AAAA;AAEQ;AAAA;AAAA;AAEZ;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AACA;AAGI;AAGA;AACJ;AACA;AAAA;AAEE;AACM;AAEV;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AAAA;AAEW;AACH;AAET;AAAA;AAAA;AACH;AAAA;AACF;AAAA;AAGN;AAGE;AAIA;AACE;AAAC;AAAA;AACkC;AACpB;AAEX;AACA;AACF;AACK;AACG;AACJ;AACU;AAEd;AAA0C;AACE;AAAA;AAAA;AAGlD;AAGE;AAIA;AACE;AAAK;AAAJ;AACY;AACA;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEW;AACJ;AACC;AACJ;AACD;AACD;AACe;AAAA;AAGzB;AAKE;AAEA;AACE;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AACA;AAAA;AAEE;AACe;AAAA;AAGzB;AAGE;AAEA;AACE;AAAC;AAAA;AACgE;AAClD;AACT;AACU;AAAA;AAGpB;AAGE;AAEA;AACE;AAAK;AAAJ;AACmD;AACrC;AACT;AACe;AAAA;AAGzB;AAGE;AAEA;AACE;AAAK;AAAJ;AACmD;AACrC;AACT;AACe;AAAA;AAGzB;AAKE;AAEA;AACE;AAAC;AAAA;AACyD;AAC3C;AACT;AACU;AAAA;AAGpB;AAWE;AAEA;AACE;AAAC;AAAA;AACW;AACV;AAEA;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AACA;AAAA;AAEW;AACT;AACe;AAAA;AAAA;AACrB;AAGN;AAGE;AAEA;AACE;AAAK;AAAJ;AACqE;AACvD;AACT;AACe;AAAA;AAGzB;AAKE;AAEA;AACE;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEW;AACT;AACe;AAAA;AAGzB;AAKE;AAEA;AACE;AAAK;AAAJ;AACY;AACM;AACJ;AACH;AACO;AACd;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEW;AACR;AACD;AACe;AAAA;AAGzB;AAKE;AAEA;AACE;AAAK;AAAJ;AAC0C;AAC5B;AACT;AACe;AAAA;AAGzB;AAGE;AAEA;AACE;AAAK;AAAJ;AACiE;AACnD;AACT;AACe;AAAA;AAGzB;AAGE;AAEA;AACE;AAAK;AAAJ;AACoD;AACtC;AACT;AACe;AAAA;AAGzB;AAgBkC;AAChC;AAEF;AACE;AAAM;AACO;AACJ;AACG;AACV;AACA;AACG;AAMH;AAAC;AAAA;AACY;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEW;AACA;AACA;AACF;AACX;AACA;AACI;AACU;AAAA;AAIlB;AAKY;AACE;AAMV;AAAgC;AACwC;AAG9E;AAQE;AAEA;AACE;AAAK;AAAJ;AACY;AACM;AACJ;AACH;AACO;AACd;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEE;AACF;AACA;AAAA;AAEW;AACR;AACD;AACe;AAAA;AAGzB;AAEoC;AAC5B;AACJ;AACA;AACA;AACA;AACA;AACA;AAAA;AAEQ;AACG;AAAA;AAEA;AACP;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMM;AAAA;AACV;AAGJ;AAOE;AAEA;AACE;AAAK;AAAJ;AACiE;AAChD;AACH;AACT;AACe;AAAA;AAGzB;AAQE;AAEoB;AAC0B;AAC5C;AAGF;AACE;AAAK;AAAJ;AACuE;AACzD;AACT;AACe;AAElB;AACC;AAAC;AAAA;AACW;AACG;AAAA;AAAA;AAGjB;AAAC;AAAA;AACW;AACG;AAEX;AACsB;AAAA;AACtB;AAAA;AAEJ;AAAA;AAGN;AAGE;AAEA;AACE;AAAK;AAAJ;AACY;AACT;AACA;AACA;AACA;AAAA;AAEW;AACT;AACe;AAAA;AAGzB;AAEmC;AACjC;AACA;AAEF;AACE;AAAK;AAAJ;AACwD;AAC1C;AACT;AACe;AACrB;AAUA;AAEA;AACE;AAAK;AAAJ;AACY;AACoD;AAC7D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AAAA;AAEW;AACA;AACF;AACP;AACe;AAAA;AAGzB;AAGE;AAEA;AACE;AAGF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guard-corpus.d.ts","sourceRoot":"","sources":["../src/guard-corpus.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"guard-corpus.d.ts","sourceRoot":"","sources":["../src/guard-corpus.ts"],"names":[],"mappings":"AAqEA,eAAO,MAAM,IAAI,QAA4B,CAAC;AAE9C,MAAM,WAAW,IAAI;IACnB,kGAAkG;IAClG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8CAA8C;IAC9C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAOD;;;;;GAKG;AACH,eAAO,MAAM,KAAK,EAAE,SAAS,IAAI,EA6B7B,CAAC;AA0BL,8FAA8F;AAC9F,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI1C;AAED,6FAA6F;AAC7F,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUpD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,UAAU,SAAY,GAAG,MAAM,EAAE,CAY5D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,QAAQ,IAAI,MAAM,EAAE,CAYnC;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAKjF;AASD;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,MAAM,CAAC;AAEhC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/simples/button.d.ts
CHANGED
|
@@ -2,16 +2,23 @@ import { ark } from '@ark-ui/react/factory';
|
|
|
2
2
|
import { default as React } from 'react';
|
|
3
3
|
import { VariantProps } from 'tailwind-variants';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* locals, and this file assigns those three.
|
|
5
|
+
* The whole control: the fill, the ink, the edge, the lift, both washes and the height, all on the
|
|
6
|
+
* `base` and all written once in terms of three locals a variant assigns.
|
|
8
7
|
*
|
|
9
|
-
* **
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
8
|
+
* **The shape is daisyUI's.** Their `.btn-primary` is two custom-property assignments over a `.btn`
|
|
9
|
+
* that derives every state; ours was six variants of five to six utilities each, naming eight
|
|
10
|
+
* different tokens between them, with the hover of each written separately. A hover rule that lives
|
|
11
|
+
* in six places is a hover rule that drifts in six places.
|
|
12
|
+
*
|
|
13
|
+
* **The placement is daisyUI's too, and that half arrived late.** The derivations sat in
|
|
14
|
+
* `styles.css` under `[data-slot="button"]`, which is the one attribute this library invites a
|
|
15
|
+
* caller to RENAME — every part takes `slot?: string`. So every component of ours that renames a
|
|
16
|
+
* `Button` got the variant's three assignments and no rule that read them: `AlertDialogAction` and
|
|
17
|
+
* `AlertDialogCancel` reported their `data-variant` correctly and `background-color:
|
|
18
|
+
* rgba(0, 0, 0, 0)` in a live document, and twenty-nine more call sites sat on the same fault.
|
|
19
|
+
* `05f3a0a` had already moved the *height* here for exactly this reason and left the colour behind,
|
|
20
|
+
* on the argument that losing a colour on a rename is a caller asking for a different look — which
|
|
21
|
+
* is true of a caller and was never true of us. `no-paint-on-a-renameable-slot.test.ts` holds it.
|
|
15
22
|
*
|
|
16
23
|
* What a variant may set: `--btn-bg`, `--btn-fg`, `--btn-bd`. Nothing else here paints.
|
|
17
24
|
*/
|
|
@@ -25,9 +32,9 @@ export declare const buttonVariants: import('tailwind-variants').TVReturnType<{
|
|
|
25
32
|
link: string[];
|
|
26
33
|
};
|
|
27
34
|
/**
|
|
28
|
-
* Padding, gaps and icon sizes.
|
|
29
|
-
*
|
|
30
|
-
*
|
|
35
|
+
* Padding, gaps and icon sizes. A size variant only **moves `--size`** — the height that reads
|
|
36
|
+
* it is on the `base` — so a tenant can ask for compact controls, through `--size-field`,
|
|
37
|
+
* without asking for tighter text.
|
|
31
38
|
*
|
|
32
39
|
* The floor is still measured rather than chosen. `xs` and `icon-xs` were both `1.5rem`, and
|
|
33
40
|
* every size is a `rem` against a root the density axis sets — 16px default, 14px compact, 18px
|
|
@@ -63,9 +70,9 @@ export declare const buttonVariants: import('tailwind-variants').TVReturnType<{
|
|
|
63
70
|
link: string[];
|
|
64
71
|
};
|
|
65
72
|
/**
|
|
66
|
-
* Padding, gaps and icon sizes.
|
|
67
|
-
*
|
|
68
|
-
*
|
|
73
|
+
* Padding, gaps and icon sizes. A size variant only **moves `--size`** — the height that reads
|
|
74
|
+
* it is on the `base` — so a tenant can ask for compact controls, through `--size-field`,
|
|
75
|
+
* without asking for tighter text.
|
|
69
76
|
*
|
|
70
77
|
* The floor is still measured rather than chosen. `xs` and `icon-xs` were both `1.5rem`, and
|
|
71
78
|
* every size is a `rem` against a root the density axis sets — 16px default, 14px compact, 18px
|
|
@@ -101,9 +108,9 @@ export declare const buttonVariants: import('tailwind-variants').TVReturnType<{
|
|
|
101
108
|
link: string[];
|
|
102
109
|
};
|
|
103
110
|
/**
|
|
104
|
-
* Padding, gaps and icon sizes.
|
|
105
|
-
*
|
|
106
|
-
*
|
|
111
|
+
* Padding, gaps and icon sizes. A size variant only **moves `--size`** — the height that reads
|
|
112
|
+
* it is on the `base` — so a tenant can ask for compact controls, through `--size-field`,
|
|
113
|
+
* without asking for tighter text.
|
|
107
114
|
*
|
|
108
115
|
* The floor is still measured rather than chosen. `xs` and `icon-xs` were both `1.5rem`, and
|
|
109
116
|
* every size is a `rem` against a root the density axis sets — 16px default, 14px compact, 18px
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/simples/button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AAC5C,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAM,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAI1D
|
|
1
|
+
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/simples/button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AAC5C,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAM,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAI1D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,cAAc;;;;;;;;;IAyGvB;;;;;;;;;;;;OAYG;;;;;;;;;;;;;;;;;;;;;;;;;;IAZH;;;;;;;;;;;;OAYG;;;;;;;;;;;;;;;;;;;;;;;;;;IAZH;;;;;;;;;;;;OAYG;;;;;;;;;;;;;;;;;qDAqCL,CAAC;AAEH,MAAM,WAAW,WACf,SAAQ,KAAK,CAAC,cAAc,CAAC,OAAO,GAAG,CAAC,MAAM,CAAC,EAC7C,YAAY,CAAC,OAAO,cAAc,CAAC;IACrC;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,MAAM,GAAI,OAAO,WAAW,sBA6CxC,CAAC"}
|
package/dist/simples/button.js
CHANGED
|
@@ -1,17 +1,58 @@
|
|
|
1
|
-
import { jsx as e, jsxs as
|
|
1
|
+
import { jsx as e, jsxs as b, Fragment as v } from "react/jsx-runtime";
|
|
2
2
|
import { ark as p } from "@ark-ui/react/factory";
|
|
3
3
|
import { tv as f } from "tailwind-variants";
|
|
4
|
-
import { cn as
|
|
5
|
-
import { Spinner as
|
|
4
|
+
import { cn as g } from "../lib/cn.js";
|
|
5
|
+
import { Spinner as u } from "./spinner.js";
|
|
6
6
|
const m = f({
|
|
7
7
|
base: [
|
|
8
8
|
"relative",
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// attribute this library lets a caller rename, and a renamed part silently lost its height:
|
|
12
|
-
// `ConversationScrollButton` measured 16×16 against a 24×24 floor. daisyUI's `.btn` does it
|
|
13
|
-
// this way for the same reason, and `no-measurement-on-a-renameable-slot.test.ts` holds it.
|
|
9
|
+
// Nothing below may be keyed on `data-slot`. See the docblock: `--size` was moved here first,
|
|
10
|
+
// in `05f3a0a`, and the paint followed it once the same rename was measured against the colour.
|
|
14
11
|
"h-(--size)",
|
|
12
|
+
// The only one of the three locals a variant may leave unset — `outline` is the sole variant
|
|
13
|
+
// that assigns `--btn-bd`, while all six assign the fill and the ink. A default for those two
|
|
14
|
+
// would be a line that is overwritten every single render.
|
|
15
|
+
"[--btn-bd:transparent]",
|
|
16
|
+
// Derived, never assigned by a variant. `--depth: 0` collapses the edge and the lift to
|
|
17
|
+
// nothing, which is what the library looks like today; `1` gives it relief. Same classes.
|
|
18
|
+
//
|
|
19
|
+
// daisyUI darkens a fill with `color-mix(in oklab, var(--btn-bg), #000 5%)`. Mixing toward
|
|
20
|
+
// `--foreground` instead is a divergence taken on a reason: `black` is only "darker" in a light
|
|
21
|
+
// theme, and on a dark one the hover of a pale button should move toward white. One formula
|
|
22
|
+
// reads as "push this fill away from the page and toward the ink" in both, and it follows a
|
|
23
|
+
// tenant's document instead of a constant — which is also why `--depth` can be a single number.
|
|
24
|
+
// Their half-pixel inset gloss needs a colour that is toward the light side in both modes and
|
|
25
|
+
// neither `--foreground` nor `--background` is that, so it waits for a reason to exist.
|
|
26
|
+
"[--btn-edge:color-mix(in_oklab,var(--btn-bd),var(--foreground)_calc(var(--depth)*8%))]",
|
|
27
|
+
"[--btn-lift:color-mix(in_oklab,var(--btn-bg)_calc(var(--depth)*30%),transparent)]",
|
|
28
|
+
"bg-(--btn-bg) text-(--btn-fg)",
|
|
29
|
+
// The grain, and the whole of the conditional that switches it off: at `--noise: 0` the layer
|
|
30
|
+
// is sized to zero and never painted, at `1` it tiles. No variant — which is the property that
|
|
31
|
+
// lets it be a value a tenant sets rather than a look somebody has to write. It defaults to `0`
|
|
32
|
+
// here rather than in every theme, because a theme that wants no texture is saying nothing.
|
|
33
|
+
"bg-(image:--fx-noise) bg-size-[calc(var(--noise,0)*100%)]",
|
|
34
|
+
// `rounded-[var(--radius-field)]` and not `rounded-field`, which is the same radius and the
|
|
35
|
+
// spelling every other recipe here uses: `tailwind-merge` knows nothing about a theme key it
|
|
36
|
+
// was never configured with, so `rounded-field` and a caller's `rounded-full` both survive the
|
|
37
|
+
// merge and the winner is whichever Tailwind happened to emit last. The `pill` variant is that
|
|
38
|
+
// caller. An arbitrary value is in a group the merge does know.
|
|
39
|
+
"border-[length:var(--stroke)] border-(--btn-edge) rounded-[var(--radius-field)]",
|
|
40
|
+
// As `shadow-*` rather than a raw `box-shadow`, so it composes with `focus-visible:ring-[3px]`
|
|
41
|
+
// through Tailwind's shadow chain instead of being replaced by it. At `--depth: 0` the lift is
|
|
42
|
+
// transparent and nothing is drawn either way, which is why that was invisible before.
|
|
43
|
+
"shadow-[0_3px_2px_-2px_var(--btn-lift),0_4px_3px_-2px_var(--btn-lift)]",
|
|
44
|
+
// One hover and one active for every variant, solid and transparent alike — and the transparent
|
|
45
|
+
// case is the tell that the formula is right. Mixing `transparent` with the foreground at 10%
|
|
46
|
+
// IS the foreground at 10% alpha, which is exactly the wash a ghost button wants.
|
|
47
|
+
//
|
|
48
|
+
// The CSS rule guarded these with `:not(:disabled, [aria-disabled="true"], [data-disabled])`.
|
|
49
|
+
// All three spellings already carry `pointer-events-none` on this same base and an element with
|
|
50
|
+
// `pointer-events: none` can match neither `:hover` nor `:active`, so the guard was
|
|
51
|
+
// belt-and-braces. Dropping it is not tidiness: with the plain modifier, `tailwind-merge` can
|
|
52
|
+
// see a variant's own `hover:bg-*` as the same utility and let it win — which is how `link`
|
|
53
|
+
// opts out in one class, instead of losing to a longer selector on specificity.
|
|
54
|
+
"hover:bg-[color-mix(in_oklab,var(--btn-bg),var(--foreground)_10%)]",
|
|
55
|
+
"active:bg-[color-mix(in_oklab,var(--btn-bg),var(--foreground)_16%)]",
|
|
15
56
|
"inline-flex shrink-0 items-center justify-center gap-2",
|
|
16
57
|
"whitespace-nowrap font-medium text-sm",
|
|
17
58
|
"border-solid",
|
|
@@ -56,8 +97,9 @@ const m = f({
|
|
|
56
97
|
"focus-visible:border-primary"
|
|
57
98
|
],
|
|
58
99
|
// The one variant that opts OUT of the shared hover, because a link's hover is an underline
|
|
59
|
-
// and not a wash.
|
|
60
|
-
//
|
|
100
|
+
// and not a wash. Same modifier and same utility group as the base's wash, so
|
|
101
|
+
// `tailwind-variants` merges the two and the variant wins — which is what makes opting out
|
|
102
|
+
// one class rather than an exception somewhere else.
|
|
61
103
|
link: [
|
|
62
104
|
"[--btn-bg:transparent]",
|
|
63
105
|
"[--btn-fg:var(--primary)]",
|
|
@@ -67,9 +109,9 @@ const m = f({
|
|
|
67
109
|
]
|
|
68
110
|
},
|
|
69
111
|
/**
|
|
70
|
-
* Padding, gaps and icon sizes.
|
|
71
|
-
*
|
|
72
|
-
*
|
|
112
|
+
* Padding, gaps and icon sizes. A size variant only **moves `--size`** — the height that reads
|
|
113
|
+
* it is on the `base` — so a tenant can ask for compact controls, through `--size-field`,
|
|
114
|
+
* without asking for tighter text.
|
|
73
115
|
*
|
|
74
116
|
* The floor is still measured rather than chosen. `xs` and `icon-xs` were both `1.5rem`, and
|
|
75
117
|
* every size is a `rem` against a root the density axis sets — 16px default, 14px compact, 18px
|
|
@@ -115,43 +157,43 @@ const m = f({
|
|
|
115
157
|
clickEffect: !0,
|
|
116
158
|
pill: !1
|
|
117
159
|
}
|
|
118
|
-
}),
|
|
160
|
+
}), k = (s) => {
|
|
119
161
|
const {
|
|
120
|
-
variant:
|
|
121
|
-
size:
|
|
162
|
+
variant: r = "default",
|
|
163
|
+
size: t = "md",
|
|
122
164
|
clickEffect: n = !0,
|
|
123
165
|
pill: o = !1,
|
|
124
|
-
isLoading:
|
|
166
|
+
isLoading: a = !1,
|
|
125
167
|
className: l,
|
|
126
|
-
children:
|
|
168
|
+
children: i,
|
|
127
169
|
slot: d,
|
|
128
170
|
...c
|
|
129
|
-
} =
|
|
171
|
+
} = s;
|
|
130
172
|
return /* @__PURE__ */ e(
|
|
131
173
|
p.button,
|
|
132
174
|
{
|
|
133
|
-
className:
|
|
134
|
-
m({ variant:
|
|
175
|
+
className: g(
|
|
176
|
+
m({ variant: r, size: t, clickEffect: n, pill: o }),
|
|
135
177
|
l
|
|
136
178
|
),
|
|
137
|
-
"data-size":
|
|
138
|
-
"data-state":
|
|
139
|
-
"data-variant":
|
|
179
|
+
"data-size": t,
|
|
180
|
+
"data-state": a ? "loading" : "idle",
|
|
181
|
+
"data-variant": r,
|
|
140
182
|
type: "button",
|
|
141
183
|
...c,
|
|
142
184
|
"data-slot": d ?? "button",
|
|
143
|
-
"aria-busy":
|
|
144
|
-
"aria-disabled":
|
|
145
|
-
children:
|
|
146
|
-
/* @__PURE__ */ e("span", { "aria-hidden": !0, className: "invisible", children:
|
|
147
|
-
/* @__PURE__ */ e("span", { className: "sr-only", children:
|
|
148
|
-
/* @__PURE__ */ e("span", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ e(
|
|
149
|
-
] }) :
|
|
185
|
+
"aria-busy": a,
|
|
186
|
+
"aria-disabled": a,
|
|
187
|
+
children: a ? /* @__PURE__ */ b(v, { children: [
|
|
188
|
+
/* @__PURE__ */ e("span", { "aria-hidden": !0, className: "invisible", children: i }),
|
|
189
|
+
/* @__PURE__ */ e("span", { className: "sr-only", children: i }),
|
|
190
|
+
/* @__PURE__ */ e("span", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ e(u, { "aria-hidden": !0 }) })
|
|
191
|
+
] }) : i
|
|
150
192
|
}
|
|
151
193
|
);
|
|
152
194
|
};
|
|
153
195
|
export {
|
|
154
|
-
|
|
196
|
+
k as Button,
|
|
155
197
|
m as buttonVariants
|
|
156
198
|
};
|
|
157
199
|
//# sourceMappingURL=button.js.map
|