@nadicodeai/ui 0.10.1 → 0.11.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/AGENTS.md +23 -135
- package/README.md +39 -110
- package/dist/components/action-band.d.ts +5 -3
- package/dist/components/action-band.d.ts.map +1 -1
- package/dist/components/action-band.js +35 -21
- package/dist/components/agent-chat.d.ts.map +1 -1
- package/dist/components/agent-chat.js +1 -1
- package/dist/components/agent-composer.d.ts.map +1 -1
- package/dist/components/agent-composer.js +1 -1
- package/dist/components/ai-elements/code-block.d.ts.map +1 -1
- package/dist/components/ai-elements/code-block.js +9 -23
- package/dist/components/ai-elements/commit.d.ts.map +1 -1
- package/dist/components/ai-elements/commit.js +9 -23
- package/dist/components/ai-elements/environment-variables.d.ts.map +1 -1
- package/dist/components/ai-elements/environment-variables.js +4 -29
- package/dist/components/ai-elements/snippet.d.ts.map +1 -1
- package/dist/components/ai-elements/snippet.js +9 -23
- package/dist/components/ai-elements/stack-trace.d.ts.map +1 -1
- package/dist/components/ai-elements/stack-trace.js +8 -21
- package/dist/components/ai-elements/terminal.d.ts.map +1 -1
- package/dist/components/ai-elements/terminal.js +16 -29
- package/dist/components/alert-dialog.d.ts.map +1 -1
- package/dist/components/alert-dialog.js +3 -2
- package/dist/components/artifact-panel.d.ts.map +1 -1
- package/dist/components/artifact-panel.js +5 -5
- package/dist/components/badge.js +1 -1
- package/dist/components/bento.d.ts +14 -3
- package/dist/components/bento.d.ts.map +1 -1
- package/dist/components/bento.js +26 -5
- package/dist/components/brand.d.ts.map +1 -1
- package/dist/components/brand.js +29 -3
- package/dist/components/button.js +1 -1
- package/dist/components/chart-time-series.d.ts.map +1 -1
- package/dist/components/chart-time-series.js +2 -2
- package/dist/components/chart.js +1 -1
- package/dist/components/contact.d.ts +22 -10
- package/dist/components/contact.d.ts.map +1 -1
- package/dist/components/contact.js +34 -12
- package/dist/components/dialog.d.ts.map +1 -1
- package/dist/components/dialog.js +3 -2
- package/dist/components/diff-count.js +1 -1
- package/dist/components/dropdown-menu.d.ts.map +1 -1
- package/dist/components/dropdown-menu.js +2 -1
- package/dist/components/faq-item.js +2 -2
- package/dist/components/faq.d.ts +4 -1
- package/dist/components/faq.d.ts.map +1 -1
- package/dist/components/faq.js +5 -2
- package/dist/components/feature-grid.d.ts +23 -0
- package/dist/components/feature-grid.d.ts.map +1 -0
- package/dist/components/feature-grid.js +33 -0
- package/dist/components/feature-rows.d.ts +23 -0
- package/dist/components/feature-rows.d.ts.map +1 -0
- package/dist/components/feature-rows.js +27 -0
- package/dist/components/footer.d.ts +18 -12
- package/dist/components/footer.d.ts.map +1 -1
- package/dist/components/footer.js +32 -20
- package/dist/components/hero.d.ts +28 -0
- package/dist/components/hero.d.ts.map +1 -0
- package/dist/components/hero.js +45 -0
- package/dist/components/input-otp.js +1 -1
- package/dist/components/integration-flow.d.ts +36 -0
- package/dist/components/integration-flow.d.ts.map +1 -0
- package/dist/components/integration-flow.js +36 -0
- package/dist/components/live-demo.d.ts +31 -0
- package/dist/components/live-demo.d.ts.map +1 -0
- package/dist/components/live-demo.js +30 -0
- package/dist/components/logo-band.d.ts +12 -2
- package/dist/components/logo-band.d.ts.map +1 -1
- package/dist/components/logo-band.js +16 -1
- package/dist/components/logo-tile.d.ts.map +1 -1
- package/dist/components/logo-tile.js +5 -2
- package/dist/components/nav-bar.d.ts +14 -8
- package/dist/components/nav-bar.d.ts.map +1 -1
- package/dist/components/nav-bar.js +19 -13
- package/dist/components/popover.d.ts.map +1 -1
- package/dist/components/popover.js +2 -1
- package/dist/components/pricing-card.d.ts +10 -15
- package/dist/components/pricing-card.d.ts.map +1 -1
- package/dist/components/pricing-card.js +18 -29
- package/dist/components/pricing.d.ts +11 -14
- package/dist/components/pricing.d.ts.map +1 -1
- package/dist/components/pricing.js +5 -15
- package/dist/components/quote-card.d.ts +10 -2
- package/dist/components/quote-card.d.ts.map +1 -1
- package/dist/components/quote-card.js +15 -3
- package/dist/components/security-grid.d.ts +25 -0
- package/dist/components/security-grid.d.ts.map +1 -0
- package/dist/components/security-grid.js +31 -0
- package/dist/components/select.d.ts.map +1 -1
- package/dist/components/select.js +2 -1
- package/dist/components/sheet.d.ts.map +1 -1
- package/dist/components/sheet.js +3 -2
- package/dist/components/sidebar.js +1 -1
- package/dist/components/stat-block.d.ts +9 -5
- package/dist/components/stat-block.d.ts.map +1 -1
- package/dist/components/stat-block.js +12 -6
- package/dist/components/statement.d.ts +32 -0
- package/dist/components/statement.d.ts.map +1 -0
- package/dist/components/statement.js +40 -0
- package/dist/components/stats-band.d.ts +6 -2
- package/dist/components/stats-band.d.ts.map +1 -1
- package/dist/components/stats-band.js +10 -3
- package/dist/components/status-dot.js +4 -4
- package/dist/components/steps.d.ts +34 -0
- package/dist/components/steps.d.ts.map +1 -0
- package/dist/components/steps.js +40 -0
- package/dist/components/team-grid.d.ts +27 -0
- package/dist/components/team-grid.d.ts.map +1 -0
- package/dist/components/team-grid.js +30 -0
- package/dist/components/testimonials.d.ts +39 -12
- package/dist/components/testimonials.d.ts.map +1 -1
- package/dist/components/testimonials.js +46 -13
- package/dist/components/texture-strip.d.ts +22 -0
- package/dist/components/texture-strip.d.ts.map +1 -0
- package/dist/components/texture-strip.js +29 -0
- package/dist/components/toggle.js +1 -1
- package/dist/components/tooltip.d.ts.map +1 -1
- package/dist/components/tooltip.js +2 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/lib/message-scroller-primitive/geometry.d.ts +1 -5
- package/dist/lib/message-scroller-primitive/geometry.d.ts.map +1 -1
- package/dist/lib/message-scroller-primitive/geometry.js +1 -1
- package/dist/lib/message-scroller-primitive/stores.d.ts +2 -3
- package/dist/lib/message-scroller-primitive/stores.d.ts.map +1 -1
- package/dist/lib/message-scroller-primitive/stores.js +1 -1
- package/dist/lib/message-scroller-primitive/types.d.ts +1 -2
- package/dist/lib/message-scroller-primitive/types.d.ts.map +1 -1
- package/dist/lib/message-scroller-primitive/types.js +1 -1
- package/dist/lib/motion.d.ts +12 -0
- package/dist/lib/motion.d.ts.map +1 -0
- package/dist/lib/motion.js +11 -0
- package/dist/lib/use-copy-to-clipboard.d.ts +11 -0
- package/dist/lib/use-copy-to-clipboard.d.ts.map +1 -0
- package/dist/lib/use-copy-to-clipboard.js +27 -0
- package/dist/styles/globals.css +175 -300
- package/docs/agent-work-surfaces.md +6 -5
- package/docs/agents/nadicodeai-ui.md +42 -273
- package/docs/consuming-cross-repo.md +26 -33
- package/docs/contract.md +43 -0
- package/docs/migration/nadia-consumer-readiness.md +5 -10
- package/docs/terminal-tui-semantics.md +142 -181
- package/llms.txt +49 -84
- package/package.json +2 -3
- package/skills/nadicodeai-ui/SKILL.md +6 -30
|
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { Button as ButtonPrimitive } from "@base-ui/react/button";
|
|
3
3
|
import { cva } from "class-variance-authority";
|
|
4
4
|
import { cn } from "../lib/utils.js";
|
|
5
|
-
const buttonVariants = cva("group/button inline-flex min-h-touch-target min-w-touch-target shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-
|
|
5
|
+
const buttonVariants = cva("group/button inline-flex min-h-touch-target min-w-touch-target shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-[background-color,border-color,color] duration-[var(--nc-duration-confirm)] ease-[var(--nc-ease-out-strong)] outline-none select-none focus-visible:border-ring focus-visible:ring-focus focus-visible:ring-ring active:not-aria-[haspopup]:opacity-90 motion-reduce:transition-none disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-focus aria-invalid:ring-destructive [@media(hover:hover)_and_(pointer:fine)]:min-h-0 [@media(hover:hover)_and_(pointer:fine)]:min-w-0 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
|
|
6
6
|
variants: {
|
|
7
7
|
variant: {
|
|
8
8
|
default: "bg-primary text-primary-foreground hover:bg-primary-hover active:bg-primary-active",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-time-series.d.ts","sourceRoot":"","sources":["../../src/components/chart-time-series.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kCAAkC,CAAC;AAsD1C,KAAK,gBAAgB,GAAG;IACtB,2EAA2E;IAC3E,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAEvD,KAAK,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,GAAG;IACxE,IAAI,EAAE,SAAS,eAAe,EAAE,CAAC;IACjC,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACpC,2DAA2D;IAC3D,cAAc,EAAE,cAAc,CAAC;IAC/B,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3C;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAsJF,iBAAS,cAAc,CAAC,EACtB,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,cAAc,EACd,KAAK,EACL,MAAiB,EACjB,cAA8B,EAC9B,UAAU,EACV,UAAoB,EACpB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"chart-time-series.d.ts","sourceRoot":"","sources":["../../src/components/chart-time-series.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kCAAkC,CAAC;AAsD1C,KAAK,gBAAgB,GAAG;IACtB,2EAA2E;IAC3E,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAEvD,KAAK,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,GAAG;IACxE,IAAI,EAAE,SAAS,eAAe,EAAE,CAAC;IACjC,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACpC,2DAA2D;IAC3D,cAAc,EAAE,cAAc,CAAC;IAC/B,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3C;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAsJF,iBAAS,cAAc,CAAC,EACtB,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,cAAc,EACd,KAAK,EACL,MAAiB,EACjB,cAA8B,EAC9B,UAAU,EACV,UAAoB,EACpB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,eAAe,qBA+CjB;AAED,iBAAS,cAAc,CAAC,EACtB,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,cAAc,EACd,KAAK,EACL,MAAiB,EACjB,cAA8B,EAC9B,UAAU,EACV,UAAoB,EACpB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,eAAe,qBAwDjB;AAED,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -114,14 +114,14 @@ function TimeSeriesFrame({ label, className, children, ...props }) {
|
|
|
114
114
|
function TimeSeriesBars({ data, xKey, series, entityColorMap, label, xLabel = "Period", valueFormatter = defaultFormat, yAxisWidth, otherLabel = "Other", className, ...props }) {
|
|
115
115
|
const folded = foldNeutralSeries(series, entityColorMap, data, otherLabel);
|
|
116
116
|
const config = seriesChartConfig(folded.series, entityColorMap);
|
|
117
|
-
return (_jsxs(TimeSeriesFrame, { "data-slot": "time-series-bars", label: label, className: className, ...props, children: [_jsx(ChartContainer, { config: config, className: cn("w-full", CHART_SURFACE_FOCUS_CLASS), children: _jsxs(BarChart, { accessibilityLayer: true, title: label, data: folded.data, children: [_jsx(CartesianGrid, { vertical: false }), _jsx(XAxis, { dataKey: xKey, tickLine: false, axisLine: false, tickMargin: 8 }), _jsx(YAxis, { tickLine: false, axisLine: false, width: yAxisWidth ?? "auto", tickFormatter: (value) => valueFormatter(Number(value)) }), _jsx(ChartTooltip, { content: _jsx(ChartTooltipContent, { formatter: tooltipRowFormatter(folded.series, valueFormatter) }) }), folded.series.length > 1 ? _jsx(ChartLegend, { content: _jsx(ChartLegendContent, {}) }) : null, _jsx(BarStack, { stackId: "stacked", radius: [4, 4, 0, 0], children: folded.series.map((entry) => (_jsx(Bar, { dataKey: entry.id, maxBarSize: 24, fill: entityColor(entityColorMap, entry.id), stroke: "var(--background)", strokeWidth: 2 }, entry.id))) })] }) }), _jsx(TimeSeriesTableAlternative, { data: folded.data, xKey: xKey, xLabel: xLabel, series: folded.series, label: label, valueFormatter: valueFormatter })] }));
|
|
117
|
+
return (_jsxs(TimeSeriesFrame, { "data-slot": "time-series-bars", label: label, className: className, ...props, children: [_jsx(ChartContainer, { config: config, className: cn("w-full", CHART_SURFACE_FOCUS_CLASS), children: _jsxs(BarChart, { accessibilityLayer: true, title: label, data: folded.data, children: [_jsx(CartesianGrid, { vertical: false }), _jsx(XAxis, { dataKey: xKey, tickLine: false, axisLine: false, tickMargin: 8 }), _jsx(YAxis, { tickLine: false, axisLine: false, width: yAxisWidth ?? "auto", tickFormatter: (value) => valueFormatter(Number(value)) }), _jsx(ChartTooltip, { content: _jsx(ChartTooltipContent, { formatter: tooltipRowFormatter(folded.series, valueFormatter) }) }), folded.series.length > 1 ? _jsx(ChartLegend, { content: _jsx(ChartLegendContent, {}) }) : null, _jsx(BarStack, { stackId: "stacked", radius: [4, 4, 0, 0], children: folded.series.map((entry) => (_jsx(Bar, { dataKey: entry.id, isAnimationActive: false, maxBarSize: 24, fill: entityColor(entityColorMap, entry.id), stroke: "var(--background)", strokeWidth: 2 }, entry.id))) })] }) }), _jsx(TimeSeriesTableAlternative, { data: folded.data, xKey: xKey, xLabel: xLabel, series: folded.series, label: label, valueFormatter: valueFormatter })] }));
|
|
118
118
|
}
|
|
119
119
|
function TimeSeriesArea({ data, xKey, series, entityColorMap, label, xLabel = "Period", valueFormatter = defaultFormat, yAxisWidth, otherLabel = "Other", className, ...props }) {
|
|
120
120
|
const folded = foldNeutralSeries(series, entityColorMap, data, otherLabel);
|
|
121
121
|
const config = seriesChartConfig(folded.series, entityColorMap);
|
|
122
122
|
return (_jsxs(TimeSeriesFrame, { "data-slot": "time-series-area", label: label, className: className, ...props, children: [_jsx(ChartContainer, { config: config, className: cn("w-full", CHART_SURFACE_FOCUS_CLASS), children: _jsxs(AreaChart, { accessibilityLayer: true, title: label, data: folded.data, children: [_jsx(CartesianGrid, { vertical: false }), _jsx(XAxis, { dataKey: xKey, tickLine: false, axisLine: false, tickMargin: 8 }), _jsx(YAxis, { tickLine: false, axisLine: false, width: yAxisWidth ?? "auto", tickFormatter: (value) => valueFormatter(Number(value)) }), _jsx(ChartTooltip, { content: _jsx(ChartTooltipContent, { formatter: tooltipRowFormatter(folded.series, valueFormatter) }) }), folded.series.length > 1 ? _jsx(ChartLegend, { content: _jsx(ChartLegendContent, {}) }) : null, folded.series.map((entry) => {
|
|
123
123
|
const color = entityColor(entityColorMap, entry.id);
|
|
124
|
-
return (_jsx(Area, { type: "monotone", dataKey: entry.id, stackId: "stacked", stroke: color, strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", fill: color, fillOpacity: 0.1,
|
|
124
|
+
return (_jsx(Area, { type: "monotone", dataKey: entry.id, isAnimationActive: false, stackId: "stacked", stroke: color, strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", fill: color, fillOpacity: 0.1,
|
|
125
125
|
// Recharts' default activeDot ring is stroke #fff, which the
|
|
126
126
|
// chart foundation remaps to transparent — an explicit surface
|
|
127
127
|
// ring keeps the DESIGN.md 2px marker-ring spec on hover/focus.
|
package/dist/components/chart.js
CHANGED
|
@@ -8,7 +8,7 @@ const THEMES = { light: "", dark: ".dark" };
|
|
|
8
8
|
const INITIAL_DIMENSION = { width: 320, height: 200 };
|
|
9
9
|
// Deviates from stock base-nova (raw interpolation): chart id and color values
|
|
10
10
|
// are sanitized before they reach the injected <style> tag, closing the CSS
|
|
11
|
-
// injection surface.
|
|
11
|
+
// injection surface. Exercised through hostile-input rendering tests; see ADR 0010.
|
|
12
12
|
function sanitizeChartToken(value) {
|
|
13
13
|
const sanitized = value
|
|
14
14
|
.trim()
|
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
/**
|
|
3
|
-
* contact — contact
|
|
4
|
-
* coupled form controls).
|
|
3
|
+
* contact — the closing contact section (V5 B18).
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* is
|
|
5
|
+
* A 5fr / 7fr split: a text column (`ContactIntro` — eyebrow/title/body/location)
|
|
6
|
+
* beside a form column (`ContactForm`) that sits on its own soft, bordered panel.
|
|
7
|
+
* The split is a whitespace gap, never a hairline, so `Contact` owns NO structural
|
|
8
|
+
* seam — the frame/lane/row perimeter is owned by the kept geometry layer this
|
|
9
|
+
* composes inside, and every visible border is a control/panel perimeter.
|
|
10
|
+
*
|
|
11
|
+
* The form is presentational only (no submit wiring): consumers own the action and
|
|
12
|
+
* state. Fields use the package `Input`/`Textarea` primitives; labels use the mono
|
|
13
|
+
* uppercase `ContactLabel`. `ContactFieldRow` is the 2-up Name/Company row.
|
|
14
|
+
* Token-only; no `dark:` styling.
|
|
13
15
|
*/
|
|
14
16
|
declare function Contact({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
17
|
+
/** ContactIntro — the text column: eyebrow/title/body/location, centered vertically. */
|
|
18
|
+
declare function ContactIntro({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
19
|
+
/** ContactLocation — the mono location line under the intro body. */
|
|
20
|
+
declare function ContactLocation({ className, ...props }: React.ComponentProps<"p">): React.JSX.Element;
|
|
15
21
|
declare function ContactForm({ className, columns, ...props }: React.ComponentProps<"form"> & {
|
|
16
22
|
columns?: 1 | 2;
|
|
17
23
|
}): React.JSX.Element;
|
|
24
|
+
/** ContactFieldRow — the 2-up Name/Company row inside a single-column form. */
|
|
25
|
+
declare function ContactFieldRow({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
26
|
+
/** ContactField — one label-over-control field cell. */
|
|
27
|
+
declare function ContactField({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
28
|
+
/** ContactLabel — mono uppercase form label (server-safe plain `<label>`). */
|
|
29
|
+
declare function ContactLabel({ className, ...props }: React.ComponentProps<"label">): React.JSX.Element;
|
|
18
30
|
declare function ContactActions({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
19
|
-
export { Contact, ContactForm, ContactActions };
|
|
31
|
+
export { Contact, ContactIntro, ContactLocation, ContactForm, ContactFieldRow, ContactField, ContactLabel, ContactActions, };
|
|
20
32
|
//# sourceMappingURL=contact.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contact.d.ts","sourceRoot":"","sources":["../../src/components/contact.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B
|
|
1
|
+
{"version":3,"file":"contact.d.ts","sourceRoot":"","sources":["../../src/components/contact.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B;;;;;;;;;;;;;GAaG;AAEH,iBAAS,OAAO,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWpE;AAED,wFAAwF;AACxF,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQzE;AAED,qEAAqE;AACrE,iBAAS,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,qBAW1E;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,OAAW,EACX,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;CAAE,qBAapD;AAED,+EAA+E;AAC/E,iBAAS,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQ5E;AAED,wDAAwD;AACxD,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAIzE;AAED,8EAA8E;AAC9E,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,qBAW3E;AAED,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQ3E;AAED,OAAO,EACL,OAAO,EACP,YAAY,EACZ,eAAe,EACf,WAAW,EACX,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,cAAc,GACf,CAAC"}
|
|
@@ -1,24 +1,46 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { cn } from "../lib/utils.js";
|
|
3
3
|
/**
|
|
4
|
-
* contact — contact
|
|
5
|
-
* coupled form controls).
|
|
4
|
+
* contact — the closing contact section (V5 B18).
|
|
6
5
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* is
|
|
6
|
+
* A 5fr / 7fr split: a text column (`ContactIntro` — eyebrow/title/body/location)
|
|
7
|
+
* beside a form column (`ContactForm`) that sits on its own soft, bordered panel.
|
|
8
|
+
* The split is a whitespace gap, never a hairline, so `Contact` owns NO structural
|
|
9
|
+
* seam — the frame/lane/row perimeter is owned by the kept geometry layer this
|
|
10
|
+
* composes inside, and every visible border is a control/panel perimeter.
|
|
11
|
+
*
|
|
12
|
+
* The form is presentational only (no submit wiring): consumers own the action and
|
|
13
|
+
* state. Fields use the package `Input`/`Textarea` primitives; labels use the mono
|
|
14
|
+
* uppercase `ContactLabel`. `ContactFieldRow` is the 2-up Name/Company row.
|
|
15
|
+
* Token-only; no `dark:` styling.
|
|
14
16
|
*/
|
|
15
17
|
function Contact({ className, ...props }) {
|
|
16
|
-
return (_jsx("div", { "data-slot": "contact", className: cn("grid min-
|
|
18
|
+
return (_jsx("div", { "data-slot": "contact", className: cn("grid min-w-0 grid-cols-1 items-stretch gap-x-[clamp(32px,5vw,72px)] gap-y-10 lg:grid-cols-[5fr_7fr]", className), ...props }));
|
|
19
|
+
}
|
|
20
|
+
/** ContactIntro — the text column: eyebrow/title/body/location, centered vertically. */
|
|
21
|
+
function ContactIntro({ className, ...props }) {
|
|
22
|
+
return (_jsx("div", { "data-slot": "contact-intro", className: cn("grid min-w-0 content-center gap-4", className), ...props }));
|
|
23
|
+
}
|
|
24
|
+
/** ContactLocation — the mono location line under the intro body. */
|
|
25
|
+
function ContactLocation({ className, ...props }) {
|
|
26
|
+
return (_jsx("p", { "data-slot": "contact-location", className: cn("m-0 font-mono text-xs uppercase tracking-[0.1em] text-muted-foreground", className), ...props }));
|
|
17
27
|
}
|
|
18
28
|
function ContactForm({ className, columns = 1, ...props }) {
|
|
19
|
-
return (_jsx("form", { "data-slot": "contact-form", "data-columns": columns, className: cn("
|
|
29
|
+
return (_jsx("form", { "data-slot": "contact-form", "data-columns": columns, className: cn("grid min-w-0 gap-4 rounded-md border border-border bg-muted p-[clamp(20px,3vw,32px)] text-left", columns === 2 && "sm:grid-cols-2", className), ...props }));
|
|
30
|
+
}
|
|
31
|
+
/** ContactFieldRow — the 2-up Name/Company row inside a single-column form. */
|
|
32
|
+
function ContactFieldRow({ className, ...props }) {
|
|
33
|
+
return (_jsx("div", { "data-slot": "contact-field-row", className: cn("grid grid-cols-1 gap-4 sm:grid-cols-2", className), ...props }));
|
|
34
|
+
}
|
|
35
|
+
/** ContactField — one label-over-control field cell. */
|
|
36
|
+
function ContactField({ className, ...props }) {
|
|
37
|
+
return (_jsx("div", { "data-slot": "contact-field", className: cn("grid min-w-0 gap-1.5", className), ...props }));
|
|
38
|
+
}
|
|
39
|
+
/** ContactLabel — mono uppercase form label (server-safe plain `<label>`). */
|
|
40
|
+
function ContactLabel({ className, ...props }) {
|
|
41
|
+
return (_jsx("label", { "data-slot": "contact-label", className: cn("font-mono text-[9.5px] font-medium uppercase tracking-[0.12em] text-muted-foreground", className), ...props }));
|
|
20
42
|
}
|
|
21
43
|
function ContactActions({ className, ...props }) {
|
|
22
44
|
return (_jsx("div", { "data-slot": "contact-actions", className: cn("mt-1 grid sm:col-span-2 [&>button]:w-full", className), ...props }));
|
|
23
45
|
}
|
|
24
|
-
export { Contact, ContactForm, ContactActions };
|
|
46
|
+
export { Contact, ContactIntro, ContactLocation, ContactForm, ContactFieldRow, ContactField, ContactLabel, ContactActions, };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../src/components/dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../src/components/dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAOlE,iBAAS,MAAM,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,IAAI,CAAC,KAAK,qBAEvD;AAED,iBAAS,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,qBAEjE;AAED,iBAAS,YAAY,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,MAAM,CAAC,KAAK,qBAE/D;AAED,iBAAS,WAAW,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,qBAE7D;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,QAAQ,CAAC,KAAK,qBAQ7E;AAED,KAAK,kBAAkB,GAAG,eAAe,CAAC,KAAK,CAAC,KAAK,GAAG;IACtD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC9B,CAAC;AAEF,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,QAAQ,EACR,eAAsB,EACtB,UAAoB,EACpB,GAAG,KAAK,EACT,EAAE,kBAAkB,qBAgCpB;AAED,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAIzE;AAED,KAAK,iBAAiB,GAAG,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IACrD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC9B,CAAC;AAEF,iBAAS,YAAY,CAAC,EACpB,SAAS,EACT,eAAuB,EACvB,UAAoB,EACpB,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,iBAAiB,qBAkBnB;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,qBAQxE;AAED,iBAAS,iBAAiB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,WAAW,CAAC,KAAK,qBAWpF;AAED,OAAO,EACL,MAAM,EACN,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,WAAW,EACX,aAAa,GACd,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
|
|
3
3
|
import { cn } from "../lib/utils.js";
|
|
4
|
+
import { modalOverlayMotion, overlayBackdropMotion } from "../lib/motion.js";
|
|
4
5
|
import { Button } from "./button.js";
|
|
5
6
|
import { XIcon } from "lucide-react";
|
|
6
7
|
function Dialog({ ...props }) {
|
|
@@ -16,10 +17,10 @@ function DialogClose({ ...props }) {
|
|
|
16
17
|
return _jsx(DialogPrimitive.Close, { "data-slot": "dialog-close", ...props });
|
|
17
18
|
}
|
|
18
19
|
function DialogOverlay({ className, ...props }) {
|
|
19
|
-
return (_jsx(DialogPrimitive.Backdrop, { "data-slot": "dialog-overlay", className: cn("fixed inset-0 isolate z-50 bg-scrim/scrim
|
|
20
|
+
return (_jsx(DialogPrimitive.Backdrop, { "data-slot": "dialog-overlay", className: cn("fixed inset-0 isolate z-50 bg-scrim/scrim", overlayBackdropMotion, className), ...props }));
|
|
20
21
|
}
|
|
21
22
|
function DialogContent({ className, children, showCloseButton = true, closeLabel = "Close", ...props }) {
|
|
22
|
-
return (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Popup, { "data-slot": "dialog-content", className: cn("fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-var(--nc-xl))] -translate-x-1/2 -translate-y-1/2 gap-nadicode-md rounded-2xl border border-border bg-popover p-nadicode-lg text-sm text-popover-foreground shadow-dialog
|
|
23
|
+
return (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Popup, { "data-slot": "dialog-content", className: cn("fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-var(--nc-xl))] -translate-x-1/2 -translate-y-1/2 gap-nadicode-md rounded-2xl border border-border bg-popover p-nadicode-lg text-sm text-popover-foreground shadow-dialog outline-none sm:max-w-sm", modalOverlayMotion, className), ...props, children: [children, showCloseButton && (_jsxs(DialogPrimitive.Close, { "data-slot": "dialog-close", render: _jsx(Button, { variant: "ghost", className: "absolute top-nadicode-md right-nadicode-md", size: "icon-sm" }), children: [_jsx(XIcon, {}), _jsx("span", { className: "sr-only", children: closeLabel })] }))] })] }));
|
|
23
24
|
}
|
|
24
25
|
function DialogHeader({ className, ...props }) {
|
|
25
26
|
return (_jsx("div", { "data-slot": "dialog-header", className: cn("flex flex-col gap-2", className), ...props }));
|
|
@@ -21,6 +21,6 @@ function AnimatedInt({ value }) {
|
|
|
21
21
|
function DiffCount({ added, removed, className, ...props }) {
|
|
22
22
|
if (!added && !removed)
|
|
23
23
|
return null;
|
|
24
|
-
return (_jsxs("span", { className: cn("flex shrink-0 items-center gap-1 tabular-nums", className), "data-slot": "diff-count", ...props, children: [added > 0 ? (_jsxs("span", { className: "text-(--nc-
|
|
24
|
+
return (_jsxs("span", { className: cn("flex shrink-0 items-center gap-1 tabular-nums", className), "data-slot": "diff-count", ...props, children: [added > 0 ? (_jsxs("span", { className: "text-[var(--nc-link-deep)]", children: ["+", _jsx(AnimatedInt, { value: added })] })) : null, removed > 0 ? (_jsxs("span", { className: "text-[var(--nc-error-deep)]", children: ["\u2212", _jsx(AnimatedInt, { value: removed })] })) : null] }));
|
|
25
25
|
}
|
|
26
26
|
export { DiffCount };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dropdown-menu.d.ts","sourceRoot":"","sources":["../../src/components/dropdown-menu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,IAAI,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"dropdown-menu.d.ts","sourceRoot":"","sources":["../../src/components/dropdown-menu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,IAAI,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAM5D,iBAAS,YAAY,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,qBAE3D;AAED,iBAAS,kBAAkB,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,CAAC,MAAM,CAAC,KAAK,qBAEnE;AAED,iBAAS,mBAAmB,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,CAAC,OAAO,CAAC,KAAK,qBAErE;AAED,iBAAS,mBAAmB,CAAC,EAC3B,KAAe,EACf,WAAe,EACf,IAAe,EACf,UAAc,EACd,SAAS,EACT,GAAG,KAAK,EACT,EAAE,aAAa,CAAC,KAAK,CAAC,KAAK,GAC1B,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,GAAG,MAAM,GAAG,YAAY,CAAC,qBAsBtF;AAED,iBAAS,iBAAiB,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,CAAC,KAAK,CAAC,KAAK,qBAEjE;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,KAAK,EACL,GAAG,KAAK,EACT,EAAE,aAAa,CAAC,UAAU,CAAC,KAAK,GAAG;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,qBAYA;AAED,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,KAAK,EACL,OAAmB,EACnB,GAAG,KAAK,EACT,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,GAAG;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC;CACrC,qBAaA;AAED,iBAAS,eAAe,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,CAAC,WAAW,CAAC,KAAK,qBAErE;AAED,iBAAS,sBAAsB,CAAC,EAC9B,SAAS,EACT,KAAK,EACL,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,aAAa,CAAC,cAAc,CAAC,KAAK,GAAG;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,qBAeA;AAED,iBAAS,sBAAsB,CAAC,EAC9B,KAAe,EACf,WAAgB,EAChB,IAAc,EACd,UAAc,EACd,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,mBAAmB,CAAC,qBAYlD;AAED,iBAAS,wBAAwB,CAAC,EAChC,SAAS,EACT,QAAQ,EACR,OAAO,EACP,KAAK,EACL,GAAG,KAAK,EACT,EAAE,aAAa,CAAC,YAAY,CAAC,KAAK,GAAG;IACpC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,qBAuBA;AAED,iBAAS,sBAAsB,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,CAAC,UAAU,CAAC,KAAK,qBAE3E;AAED,iBAAS,qBAAqB,CAAC,EAC7B,SAAS,EACT,QAAQ,EACR,KAAK,EACL,GAAG,KAAK,EACT,EAAE,aAAa,CAAC,SAAS,CAAC,KAAK,GAAG;IACjC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,qBAsBA;AAED,iBAAS,qBAAqB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,CAAC,SAAS,CAAC,KAAK,qBAQpF;AAED,iBAAS,oBAAoB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,qBAWlF;AAED,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,eAAe,EACf,sBAAsB,EACtB,sBAAsB,GACvB,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Menu as MenuPrimitive } from "@base-ui/react/menu";
|
|
3
3
|
import { cn } from "../lib/utils.js";
|
|
4
|
+
import { anchoredOverlayMotion } from "../lib/motion.js";
|
|
4
5
|
import { ChevronRightIcon, CheckIcon } from "lucide-react";
|
|
5
6
|
function DropdownMenu({ ...props }) {
|
|
6
7
|
return _jsx(MenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
|
|
@@ -12,7 +13,7 @@ function DropdownMenuTrigger({ ...props }) {
|
|
|
12
13
|
return _jsx(MenuPrimitive.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
13
14
|
}
|
|
14
15
|
function DropdownMenuContent({ align = "start", alignOffset = 0, side = "bottom", sideOffset = 4, className, ...props }) {
|
|
15
|
-
return (_jsx(MenuPrimitive.Portal, { children: _jsx(MenuPrimitive.Positioner, { className: "isolate z-50 outline-none", align: align, alignOffset: alignOffset, side: side, sideOffset: sideOffset, children: _jsx(MenuPrimitive.Popup, { "data-slot": "dropdown-menu-content", className: cn("z-50 max-h-(--available-height) w-(--anchor-width) min-w-32
|
|
16
|
+
return (_jsx(MenuPrimitive.Portal, { children: _jsx(MenuPrimitive.Positioner, { className: "isolate z-50 outline-none", align: align, alignOffset: alignOffset, side: side, sideOffset: sideOffset, children: _jsx(MenuPrimitive.Popup, { "data-slot": "dropdown-menu-content", className: cn("z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 overflow-x-hidden overflow-y-auto rounded-2xl border border-border bg-popover p-nadicode-xxs text-popover-foreground shadow-menu outline-none data-closed:overflow-hidden", anchoredOverlayMotion, className), ...props }) }) }));
|
|
16
17
|
}
|
|
17
18
|
function DropdownMenuGroup({ ...props }) {
|
|
18
19
|
return _jsx(MenuPrimitive.Group, { "data-slot": "dropdown-menu-group", ...props });
|
|
@@ -18,8 +18,8 @@ import { cn } from "../lib/utils.js";
|
|
|
18
18
|
* no `dark:` styling.
|
|
19
19
|
*/
|
|
20
20
|
function FaqItem({ className, question, name, open, children, ...props }) {
|
|
21
|
-
return (_jsxs("details", { "data-slot": "faq-item", name: name, open: open, className: cn("group bg-
|
|
21
|
+
return (_jsxs("details", { "data-slot": "faq-item", name: name, open: open, className: cn("group bg-muted [&_summary::-webkit-details-marker]:hidden", className), ...props, children: [_jsx("summary", { className: cn("flex min-h-16 cursor-pointer list-none items-center justify-between gap-4 px-5 py-[18px]", "text-base font-medium text-foreground transition-colors hover:text-[var(--nc-link)]", "outline-none focus-visible:outline-2 focus-visible:[outline-color:var(--ring)] focus-visible:-outline-offset-2",
|
|
22
22
|
// +/- marker: two crossed bars; the vertical bar hides when open (+ -> -)
|
|
23
|
-
"after:size-3 after:flex-none after:bg-[length:12px_1px,1px_12px] after:bg-center after:bg-no-repeat", "after:[background-image:linear-gradient(var(--
|
|
23
|
+
"after:size-3 after:flex-none after:bg-[length:12px_1px,1px_12px] after:bg-center after:bg-no-repeat", "after:[background-image:linear-gradient(var(--muted-foreground),var(--muted-foreground)),linear-gradient(var(--muted-foreground),var(--muted-foreground))]", "group-open:after:bg-[length:12px_1px] group-open:after:[background-image:linear-gradient(var(--muted-foreground),var(--muted-foreground))]"), children: question }), _jsx("div", { "data-slot": "faq-item-answer", className: "border-t border-border px-5 pt-4 pb-5 text-sm text-muted-foreground", children: children })] }));
|
|
24
24
|
}
|
|
25
25
|
export { FaqItem };
|
package/dist/components/faq.d.ts
CHANGED
|
@@ -10,7 +10,10 @@ import * as React from "react";
|
|
|
10
10
|
* not here). A faq is one column at every breakpoint — no column count, no dark
|
|
11
11
|
* inversion (matching the retired section's variants:none).
|
|
12
12
|
*
|
|
13
|
-
*
|
|
13
|
+
* READING COLUMN (V5 B16): the faq is centered in a narrow 760px reading column
|
|
14
|
+
* (`max-w-[760px] mx-auto`) rather than spanning the full lane. The soft surface is
|
|
15
|
+
* carried by the `FaqItem` fills (`bg-muted`), so the column reads as a soft stack of
|
|
16
|
+
* hairline-separated questions. Token-only; no `dark:` styling.
|
|
14
17
|
*/
|
|
15
18
|
declare function Faq({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
16
19
|
export { Faq };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"faq.d.ts","sourceRoot":"","sources":["../../src/components/faq.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B
|
|
1
|
+
{"version":3,"file":"faq.d.ts","sourceRoot":"","sources":["../../src/components/faq.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B;;;;;;;;;;;;;;;GAeG;AAEH,iBAAS,GAAG,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQhE;AAED,OAAO,EAAE,GAAG,EAAE,CAAC"}
|
package/dist/components/faq.js
CHANGED
|
@@ -12,9 +12,12 @@ import { SeamGrid } from "./seam-grid.js";
|
|
|
12
12
|
* not here). A faq is one column at every breakpoint — no column count, no dark
|
|
13
13
|
* inversion (matching the retired section's variants:none).
|
|
14
14
|
*
|
|
15
|
-
*
|
|
15
|
+
* READING COLUMN (V5 B16): the faq is centered in a narrow 760px reading column
|
|
16
|
+
* (`max-w-[760px] mx-auto`) rather than spanning the full lane. The soft surface is
|
|
17
|
+
* carried by the `FaqItem` fills (`bg-muted`), so the column reads as a soft stack of
|
|
18
|
+
* hairline-separated questions. Token-only; no `dark:` styling.
|
|
16
19
|
*/
|
|
17
20
|
function Faq({ className, ...props }) {
|
|
18
|
-
return _jsx(SeamGrid, { "data-slot": "faq", className: cn("h-full grid-cols-1", className), ...props });
|
|
21
|
+
return (_jsx(SeamGrid, { "data-slot": "faq", className: cn("mx-auto h-full max-w-[760px] grid-cols-1", className), ...props }));
|
|
19
22
|
}
|
|
20
23
|
export { Faq };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
declare function FeatureGrid({ eyebrow, intro, closing, link, columns, children, className, ...props }: React.ComponentProps<"div"> & {
|
|
3
|
+
eyebrow?: React.ReactNode;
|
|
4
|
+
intro?: React.ReactNode;
|
|
5
|
+
closing?: React.ReactNode;
|
|
6
|
+
link?: React.ReactNode;
|
|
7
|
+
columns?: 2 | 3 | 4;
|
|
8
|
+
}): React.JSX.Element;
|
|
9
|
+
/**
|
|
10
|
+
* FeatureCard — one peer card: a verde-accent index chip using the canonical
|
|
11
|
+
* `--nc-link-deep` pair (deep verde on light, bright verde on dark), a title, a body
|
|
12
|
+
* paragraph, and an optional bottom visual slot pinned to the card's foot
|
|
13
|
+
* (`mt-auto`). Every part renders only when its content is present; with no visual
|
|
14
|
+
* the card sizes to its copy over a modest min-height so a peer row stays balanced
|
|
15
|
+
* (no cavernous empty foot).
|
|
16
|
+
*/
|
|
17
|
+
declare function FeatureCard({ index, title, visual, children, className, ...props }: React.ComponentProps<"div"> & {
|
|
18
|
+
index?: React.ReactNode;
|
|
19
|
+
title?: React.ReactNode;
|
|
20
|
+
visual?: React.ReactNode;
|
|
21
|
+
}): React.JSX.Element;
|
|
22
|
+
export { FeatureGrid, FeatureCard };
|
|
23
|
+
//# sourceMappingURL=feature-grid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature-grid.d.ts","sourceRoot":"","sources":["../../src/components/feature-grid.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAsB/B,iBAAS,WAAW,CAAC,EACnB,OAAO,EACP,KAAK,EACL,OAAO,EACP,IAAI,EACJ,OAAW,EACX,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAC/B,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CACrB,qBA+BA;AAED;;;;;;;GAOG;AACH,iBAAS,WAAW,CAAC,EACnB,KAAK,EACL,KAAK,EACL,MAAM,EACN,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAC/B,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC1B,qBAmCA;AAED,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { SeamGrid } from "./seam-grid.js";
|
|
4
|
+
/**
|
|
5
|
+
* feature-grid — an indexed head row over a wall of seamed peer cards, closed by
|
|
6
|
+
* a line of copy and an arrow-link slot (V5 B06).
|
|
7
|
+
*
|
|
8
|
+
* The head (mono eyebrow + intro paragraph) and the close (a trailing line plus a
|
|
9
|
+
* caller-supplied link) are optional slots; absent, they render nothing. The cards
|
|
10
|
+
* are `FeatureCard` peers laid in a SINGLE-OWNER SEAM grid (`SeamGrid`, `gap-px
|
|
11
|
+
* bg-border`), so every divider is owned once and the cards stay borderless fills.
|
|
12
|
+
* Token-only; no `dark:` styling.
|
|
13
|
+
*/
|
|
14
|
+
const columnClasses = {
|
|
15
|
+
2: "grid-cols-1 md:grid-cols-2",
|
|
16
|
+
3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
|
|
17
|
+
4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4",
|
|
18
|
+
};
|
|
19
|
+
function FeatureGrid({ eyebrow, intro, closing, link, columns = 3, children, className, ...props }) {
|
|
20
|
+
return (_jsxs("div", { "data-slot": "feature-grid", className: cn("grid gap-8", className), ...props, children: [eyebrow != null || intro != null ? (_jsxs("div", { "data-slot": "feature-grid-head", className: "grid gap-3", children: [eyebrow != null ? (_jsx("p", { className: "nc-type-caption-mono uppercase text-muted-foreground", children: eyebrow })) : null, intro != null ? (_jsx("p", { className: "nc-type-body-md max-w-[64ch] text-muted-foreground", children: intro })) : null] })) : null, _jsx(SeamGrid, { "data-slot": "feature-grid-cards", className: columnClasses[columns], children: children }), closing != null || link != null ? (_jsxs("div", { "data-slot": "feature-grid-close", className: "flex flex-wrap items-baseline gap-x-3 gap-y-2", children: [closing != null ? (_jsx("span", { className: "nc-type-body-md text-muted-foreground", children: closing })) : null, link] })) : null] }));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* FeatureCard — one peer card: a verde-accent index chip using the canonical
|
|
24
|
+
* `--nc-link-deep` pair (deep verde on light, bright verde on dark), a title, a body
|
|
25
|
+
* paragraph, and an optional bottom visual slot pinned to the card's foot
|
|
26
|
+
* (`mt-auto`). Every part renders only when its content is present; with no visual
|
|
27
|
+
* the card sizes to its copy over a modest min-height so a peer row stays balanced
|
|
28
|
+
* (no cavernous empty foot).
|
|
29
|
+
*/
|
|
30
|
+
function FeatureCard({ index, title, visual, children, className, ...props }) {
|
|
31
|
+
return (_jsxs("div", { "data-slot": "feature-card", className: cn("flex min-h-[200px] flex-col gap-4 bg-card p-[clamp(20px,2.4vw,32px)]", className), ...props, children: [index != null ? (_jsx("span", { "data-slot": "feature-card-index", className: "nc-type-caption-mono text-[var(--nc-link-deep)]", children: index })) : null, title != null ? (_jsx("h3", { "data-slot": "feature-card-title", className: "nc-type-title-sm text-foreground", children: title })) : null, children != null ? (_jsx("p", { "data-slot": "feature-card-body", className: "nc-type-body-sm text-muted-foreground", children: children })) : null, visual != null ? (_jsx("div", { "data-slot": "feature-card-visual", className: "mt-auto", children: visual })) : null] }));
|
|
32
|
+
}
|
|
33
|
+
export { FeatureGrid, FeatureCard };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* feature-rows — alternating text↔art rows (V5 B07).
|
|
4
|
+
*
|
|
5
|
+
* Each `FeatureRow` is a two-cell split: a copy cell and a dotted-texture art
|
|
6
|
+
* panel. The default row runs text (narrow, 5fr) beside art (wide, 7fr); `flip`
|
|
7
|
+
* swaps the visual order so the art sits on the wide left track and the text on
|
|
8
|
+
* the narrow right — while text always leads in the DOM so it reads first when the
|
|
9
|
+
* row stacks to one column.
|
|
10
|
+
*
|
|
11
|
+
* SINGLE-OWNER SEAM: the split divider is the `SeamGrid` gap-as-seam. The art panel
|
|
12
|
+
* is a container-only slot — the chat/export specimens are caller content, never
|
|
13
|
+
* baked in; an empty panel is just the dotted texture. Token-only; no `dark:`
|
|
14
|
+
* styling.
|
|
15
|
+
*/
|
|
16
|
+
declare function FeatureRows({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
17
|
+
declare function FeatureRow({ flip, text, art, className, ...props }: React.ComponentProps<"div"> & {
|
|
18
|
+
flip?: boolean;
|
|
19
|
+
text?: React.ReactNode;
|
|
20
|
+
art?: React.ReactNode;
|
|
21
|
+
}): React.JSX.Element;
|
|
22
|
+
export { FeatureRows, FeatureRow };
|
|
23
|
+
//# sourceMappingURL=feature-rows.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature-rows.d.ts","sourceRoot":"","sources":["../../src/components/feature-rows.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B;;;;;;;;;;;;;GAaG;AAEH,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAExE;AAED,iBAAS,UAAU,CAAC,EAClB,IAAY,EACZ,IAAI,EACJ,GAAG,EACH,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAC/B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,GAAG,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACvB,qBA+BA;AAED,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { SeamGrid } from "./seam-grid.js";
|
|
4
|
+
/**
|
|
5
|
+
* feature-rows — alternating text↔art rows (V5 B07).
|
|
6
|
+
*
|
|
7
|
+
* Each `FeatureRow` is a two-cell split: a copy cell and a dotted-texture art
|
|
8
|
+
* panel. The default row runs text (narrow, 5fr) beside art (wide, 7fr); `flip`
|
|
9
|
+
* swaps the visual order so the art sits on the wide left track and the text on
|
|
10
|
+
* the narrow right — while text always leads in the DOM so it reads first when the
|
|
11
|
+
* row stacks to one column.
|
|
12
|
+
*
|
|
13
|
+
* SINGLE-OWNER SEAM: the split divider is the `SeamGrid` gap-as-seam. The art panel
|
|
14
|
+
* is a container-only slot — the chat/export specimens are caller content, never
|
|
15
|
+
* baked in; an empty panel is just the dotted texture. Token-only; no `dark:`
|
|
16
|
+
* styling.
|
|
17
|
+
*/
|
|
18
|
+
function FeatureRows({ className, ...props }) {
|
|
19
|
+
return _jsx("div", { "data-slot": "feature-rows", className: cn("grid", className), ...props });
|
|
20
|
+
}
|
|
21
|
+
function FeatureRow({ flip = false, text, art, className, ...props }) {
|
|
22
|
+
return (_jsxs(SeamGrid, { "data-slot": "feature-row", "data-flip": flip || undefined, className: cn("min-h-[520px] grid-cols-1", flip ? "lg:grid-cols-[7fr_5fr]" : "lg:grid-cols-[5fr_7fr]", className), ...props, children: [_jsx("div", { "data-slot": "feature-row-text", className: cn("nc-panel-cell bg-card", flip && "lg:order-2"), children: text }), _jsx("div", { "data-slot": "feature-row-art", className: cn(
|
|
23
|
+
// The semantic card fill and the raw `--nc-*` tokens used by
|
|
24
|
+
// `nc-dotted-field` both flip under any `.dark` ancestor.
|
|
25
|
+
"nc-dotted-field grid place-items-center overflow-hidden bg-card p-[clamp(24px,4vw,56px)]", flip && "lg:order-1"), children: art })] }));
|
|
26
|
+
}
|
|
27
|
+
export { FeatureRows, FeatureRow };
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
/**
|
|
3
|
-
* footer —
|
|
4
|
-
* + its `data-variant="mega"`).
|
|
3
|
+
* footer — the always-dark site footer (V5 · B20).
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
* (
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* (`FooterMegaMeta`'s top border) — owned once there; the link columns separate by
|
|
12
|
-
* whitespace gaps, never rails, so no coordinate carries two borders.
|
|
5
|
+
* A brandline + identity paragraph beside two link columns, a meta row
|
|
6
|
+
* (copyright · clock slot · locations), and a giant faint ghost wordmark behind it
|
|
7
|
+
* all. The footer is ALWAYS dark, so the root carries its own `dark` ancestor class
|
|
8
|
+
* and resolves every colour from semantic roles (`bg-card`, `text-foreground`,
|
|
9
|
+
* `text-muted-foreground`, `border-border`, `text-primary`).
|
|
13
10
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
11
|
+
* SINGLE-OWNER SEAM: the footer owns its top border (`border-t border-border`); the
|
|
12
|
+
* `mega` variant adds exactly ONE inner seam, the hairline above the meta strip
|
|
13
|
+
* (`FooterMegaMeta`). Link columns separate by whitespace, never rails.
|
|
14
|
+
*
|
|
15
|
+
* The ghost wordmark and clock are CONTENT slots: `FooterGhost` takes the wordmark
|
|
16
|
+
* text/renderer, `FooterClock` takes a pre-formatted time string (a value, not a
|
|
17
|
+
* live timer — no client JS in this pass). Token-only; the root sets its own `dark`
|
|
18
|
+
* class (an accepted ancestor-class remap), never `dark:` utilities.
|
|
16
19
|
*/
|
|
17
20
|
declare function Footer({ className, variant, ...props }: React.ComponentProps<"footer"> & {
|
|
18
21
|
variant?: "flat" | "mega";
|
|
@@ -21,12 +24,15 @@ declare function FooterInner({ className, variant, ...props }: React.ComponentPr
|
|
|
21
24
|
variant?: "flat" | "mega";
|
|
22
25
|
}): React.JSX.Element;
|
|
23
26
|
declare function FooterBrand({ className, ...props }: React.ComponentProps<"a">): React.JSX.Element;
|
|
27
|
+
declare function FooterIdentity({ className, ...props }: React.ComponentProps<"p">): React.JSX.Element;
|
|
24
28
|
declare function FooterNav({ className, ...props }: React.ComponentProps<"nav">): React.JSX.Element;
|
|
25
29
|
declare function FooterMeta({ className, ...props }: React.ComponentProps<"p">): React.JSX.Element;
|
|
30
|
+
declare function FooterClock({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
|
|
31
|
+
declare function FooterGhost({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
|
|
26
32
|
declare function FooterMegaTop({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
27
33
|
declare function FooterMegaCols({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
28
34
|
declare function FooterMegaCol({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
29
35
|
declare function FooterMegaColTitle({ className, ...props }: React.ComponentProps<"p">): React.JSX.Element;
|
|
30
36
|
declare function FooterMegaMeta({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
31
|
-
export { Footer, FooterInner, FooterBrand, FooterNav, FooterMeta, FooterMegaTop, FooterMegaCols, FooterMegaCol, FooterMegaColTitle, FooterMegaMeta, };
|
|
37
|
+
export { Footer, FooterInner, FooterBrand, FooterIdentity, FooterNav, FooterMeta, FooterClock, FooterGhost, FooterMegaTop, FooterMegaCols, FooterMegaCol, FooterMegaColTitle, FooterMegaMeta, };
|
|
32
38
|
//# sourceMappingURL=footer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../src/components/footer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B
|
|
1
|
+
{"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../src/components/footer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B;;;;;;;;;;;;;;;;;GAiBG;AAEH,iBAAS,MAAM,CAAC,EACd,SAAS,EACT,OAAgB,EAChB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,qBAahE;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,OAAgB,EAChB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,qBAY7D;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,qBAWtE;AAED,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,qBAQzE;AAED,iBAAS,SAAS,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWtE;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,qBAQrE;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,qBAQzE;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,qBAYzE;AAID,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAW1E;AAED,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAW3E;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAW1E;AAED,iBAAS,kBAAkB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,qBAQ7E;AAED,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAY3E;AAED,OAAO,EACL,MAAM,EACN,WAAW,EACX,WAAW,EACX,cAAc,EACd,SAAS,EACT,UAAU,EACV,WAAW,EACX,WAAW,EACX,aAAa,EACb,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,cAAc,GACf,CAAC"}
|
|
@@ -1,51 +1,63 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { cn } from "../lib/utils.js";
|
|
3
3
|
/**
|
|
4
|
-
* footer —
|
|
5
|
-
* + its `data-variant="mega"`).
|
|
4
|
+
* footer — the always-dark site footer (V5 · B20).
|
|
6
5
|
*
|
|
7
|
-
*
|
|
8
|
-
* (
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* (`FooterMegaMeta`'s top border) — owned once there; the link columns separate by
|
|
13
|
-
* whitespace gaps, never rails, so no coordinate carries two borders.
|
|
6
|
+
* A brandline + identity paragraph beside two link columns, a meta row
|
|
7
|
+
* (copyright · clock slot · locations), and a giant faint ghost wordmark behind it
|
|
8
|
+
* all. The footer is ALWAYS dark, so the root carries its own `dark` ancestor class
|
|
9
|
+
* and resolves every colour from semantic roles (`bg-card`, `text-foreground`,
|
|
10
|
+
* `text-muted-foreground`, `border-border`, `text-primary`).
|
|
14
11
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
12
|
+
* SINGLE-OWNER SEAM: the footer owns its top border (`border-t border-border`); the
|
|
13
|
+
* `mega` variant adds exactly ONE inner seam, the hairline above the meta strip
|
|
14
|
+
* (`FooterMegaMeta`). Link columns separate by whitespace, never rails.
|
|
15
|
+
*
|
|
16
|
+
* The ghost wordmark and clock are CONTENT slots: `FooterGhost` takes the wordmark
|
|
17
|
+
* text/renderer, `FooterClock` takes a pre-formatted time string (a value, not a
|
|
18
|
+
* live timer — no client JS in this pass). Token-only; the root sets its own `dark`
|
|
19
|
+
* class (an accepted ancestor-class remap), never `dark:` utilities.
|
|
17
20
|
*/
|
|
18
21
|
function Footer({ className, variant = "flat", ...props }) {
|
|
19
|
-
return (_jsx("footer", { "data-slot": "footer", "data-variant": variant, className: cn("border-t border-border bg-card px-6 py-
|
|
22
|
+
return (_jsx("footer", { "data-slot": "footer", "data-variant": variant, className: cn("dark relative isolate overflow-hidden border-t border-border bg-card px-6 py-12 text-foreground [&_a]:no-underline", "[&_a:focus-visible]:outline [&_a:focus-visible]:outline-1 [&_a:focus-visible]:[outline-color:var(--ring)] [&_a:focus-visible]:outline-offset-2", className), ...props }));
|
|
20
23
|
}
|
|
21
24
|
function FooterInner({ className, variant = "flat", ...props }) {
|
|
22
|
-
return (_jsx("div", { "data-slot": "footer-inner", className: cn("mx-auto w-full max-w-[1200px]", variant === "mega" ? "grid gap-8" : "flex flex-wrap items-center justify-between gap-4", className), ...props }));
|
|
25
|
+
return (_jsx("div", { "data-slot": "footer-inner", className: cn("relative z-10 mx-auto w-full max-w-[1200px]", variant === "mega" ? "grid gap-8" : "flex flex-wrap items-center justify-between gap-4", className), ...props }));
|
|
23
26
|
}
|
|
24
27
|
function FooterBrand({ className, ...props }) {
|
|
25
28
|
return (_jsx("a", { "data-slot": "footer-brand", className: cn("inline-flex items-center gap-2.5 text-sm font-semibold text-foreground [&_img]:block [&_img]:h-6 [&_img]:w-auto [&_svg]:block [&_svg]:h-6 [&_svg]:w-auto", className), ...props }));
|
|
26
29
|
}
|
|
30
|
+
function FooterIdentity({ className, ...props }) {
|
|
31
|
+
return (_jsx("p", { "data-slot": "footer-identity", className: cn("nc-type-body-md m-0 max-w-[52ch] text-muted-foreground", className), ...props }));
|
|
32
|
+
}
|
|
27
33
|
function FooterNav({ className, ...props }) {
|
|
28
|
-
return (_jsx("nav", { "data-slot": "footer-nav", className: cn("flex flex-wrap gap-3 text-sm text-
|
|
34
|
+
return (_jsx("nav", { "data-slot": "footer-nav", className: cn("flex flex-wrap gap-3 text-sm text-muted-foreground [&_a]:text-inherit [&_a:hover]:text-foreground", className), ...props }));
|
|
29
35
|
}
|
|
30
36
|
function FooterMeta({ className, ...props }) {
|
|
31
37
|
return (_jsx("p", { "data-slot": "footer-meta", className: cn("m-0 text-sm text-muted-foreground", className), ...props }));
|
|
32
38
|
}
|
|
39
|
+
function FooterClock({ className, ...props }) {
|
|
40
|
+
return (_jsx("span", { "data-slot": "footer-clock", className: cn("nc-type-caption-mono text-primary", className), ...props }));
|
|
41
|
+
}
|
|
42
|
+
function FooterGhost({ className, ...props }) {
|
|
43
|
+
return (_jsx("span", { "data-slot": "footer-ghost", "aria-hidden": "true", className: cn("pointer-events-none absolute inset-x-0 bottom-0 z-0 select-none overflow-hidden whitespace-nowrap text-[clamp(90px,14vw,210px)] font-semibold leading-[0.8] tracking-tight text-foreground/5", className), ...props }));
|
|
44
|
+
}
|
|
33
45
|
/* ── mega variant slots ────────────────────────────────────────────────── */
|
|
34
46
|
function FooterMegaTop({ className, ...props }) {
|
|
35
|
-
return (_jsx("div", { "data-slot": "footer-mega-top", className: cn("grid grid-cols-1 items-start gap-8 sm:grid-cols-[minmax(0,
|
|
47
|
+
return (_jsx("div", { "data-slot": "footer-mega-top", className: cn("grid grid-cols-1 items-start gap-8 sm:grid-cols-[minmax(0,7fr)_minmax(0,5fr)] sm:gap-x-12", className), ...props }));
|
|
36
48
|
}
|
|
37
49
|
function FooterMegaCols({ className, ...props }) {
|
|
38
|
-
return (_jsx("div", { "data-slot": "footer-mega-cols", className: cn("grid grid-cols-1 gap-6 sm:grid-cols-[repeat(auto-fit,minmax(140px,1fr))] sm:gap-x-8", className), ...props }));
|
|
50
|
+
return (_jsx("div", { "data-slot": "footer-mega-cols", className: cn("grid grid-cols-1 gap-6 sm:grid-cols-[repeat(auto-fit,minmax(140px,1fr))] sm:justify-end sm:gap-x-8", className), ...props }));
|
|
39
51
|
}
|
|
40
52
|
function FooterMegaCol({ className, ...props }) {
|
|
41
|
-
return (_jsx("div", { "data-slot": "footer-mega-col", className: cn("grid content-start gap-2 [&_a]:text-sm [&_a]:text-
|
|
53
|
+
return (_jsx("div", { "data-slot": "footer-mega-col", className: cn("grid content-start gap-2 [&_a]:text-sm [&_a]:text-muted-foreground [&_a:hover]:text-foreground", className), ...props }));
|
|
42
54
|
}
|
|
43
55
|
function FooterMegaColTitle({ className, ...props }) {
|
|
44
|
-
return (_jsx("p", { "data-slot": "footer-mega-col-title", className: cn("
|
|
56
|
+
return (_jsx("p", { "data-slot": "footer-mega-col-title", className: cn("nc-type-caption-mono m-0 uppercase text-muted-foreground", className), ...props }));
|
|
45
57
|
}
|
|
46
58
|
function FooterMegaMeta({ className, ...props }) {
|
|
47
59
|
return (_jsx("div", { "data-slot": "footer-mega-meta", className: cn(
|
|
48
60
|
// the single inner seam the mega variant adds: a top hairline, owned once.
|
|
49
|
-
"flex flex-wrap items-center justify-between gap-x-6 gap-y-3 border-t border-border pt-6", className), ...props }));
|
|
61
|
+
"flex flex-wrap items-center justify-between gap-x-6 gap-y-3 border-t border-border pt-6 text-muted-foreground", className), ...props }));
|
|
50
62
|
}
|
|
51
|
-
export { Footer, FooterInner, FooterBrand, FooterNav, FooterMeta, FooterMegaTop, FooterMegaCols, FooterMegaCol, FooterMegaColTitle, FooterMegaMeta, };
|
|
63
|
+
export { Footer, FooterInner, FooterBrand, FooterIdentity, FooterNav, FooterMeta, FooterClock, FooterGhost, FooterMegaTop, FooterMegaCols, FooterMegaCol, FooterMegaColTitle, FooterMegaMeta, };
|