@nadicodeai/ui 10.0.1 → 10.1.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.
@@ -17,11 +17,20 @@ import * as React from "react";
17
17
  * live timer — no client JS in this pass). Token-only; the root sets its own `dark`
18
18
  * class (an accepted ancestor-class remap), never `dark:` utilities.
19
19
  */
20
- declare function Footer({ className, variant, ...props }: React.ComponentProps<"footer"> & {
20
+ /**
21
+ * `width="page"` puts the footer's content on the website's one column
22
+ * (`.nc-page`, the design system's), so its columns align with every section
23
+ * above it; the footer then carries no inset of its own, because the column
24
+ * brings the gutters. The default keeps the Portal's own measure.
25
+ */
26
+ type FooterWidth = "content" | "page";
27
+ declare function Footer({ className, variant, width, ...props }: React.ComponentProps<"footer"> & {
21
28
  variant?: "flat" | "mega";
29
+ width?: FooterWidth;
22
30
  }): React.JSX.Element;
23
- declare function FooterInner({ className, variant, ...props }: React.ComponentProps<"div"> & {
31
+ declare function FooterInner({ className, variant, width, ...props }: React.ComponentProps<"div"> & {
24
32
  variant?: "flat" | "mega";
33
+ width?: FooterWidth;
25
34
  }): React.JSX.Element;
26
35
  declare function FooterBrand({ className, ...props }: React.ComponentProps<"a">): React.JSX.Element;
27
36
  declare function FooterIdentity({ className, ...props }: React.ComponentProps<"p">): React.JSX.Element;
@@ -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;;;;;;;;;;;;;;;;;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,qBAYhE;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
+ {"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;;;;;GAKG;AACH,KAAK,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC;AAEtC,iBAAS,MAAM,CAAC,EACd,SAAS,EACT,OAAgB,EAChB,KAAiB,EACjB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,WAAW,CAAA;CAAE,qBAcrF;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,OAAgB,EAChB,KAAiB,EACjB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,WAAW,CAAA;CAAE,qBAalF;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,28 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cn } from "../lib/utils.js";
3
- /**
4
- * footer — the always-dark site footer (V5 · B20).
5
- *
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`).
11
- *
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.
20
- */
21
- function Footer({ className, variant = "flat", ...props }) {
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", className), ...props }));
23
- }
24
- function FooterInner({ className, variant = "flat", ...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 }));
3
+ function Footer({ className, variant = "flat", width = "content", ...props }) {
4
+ return (_jsx("footer", { "data-slot": "footer", "data-variant": variant, "data-width": width, className: cn("dark relative isolate overflow-hidden border-t border-border bg-card py-12 text-foreground [&_a]:no-underline", width === "content" && "px-6", className), ...props }));
5
+ }
6
+ function FooterInner({ className, variant = "flat", width = "content", ...props }) {
7
+ return (_jsx("div", { "data-slot": "footer-inner", className: cn("relative z-10", width === "page" ? "nc-page" : "mx-auto w-full max-w-[1200px]", variant === "mega" ? "grid gap-8" : "flex flex-wrap items-center justify-between gap-4", className), ...props }));
26
8
  }
27
9
  function FooterBrand({ className, ...props }) {
28
10
  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 }));
@@ -101,6 +101,6 @@ function ModelMark({ author, name, size = MODEL_MARK_SIZE, label, className, ...
101
101
  : label?.trim()
102
102
  ? { role: "img", "aria-label": label }
103
103
  : {};
104
- return (_jsxs("span", { "data-slot": "model-mark", "data-author": author, "data-resolved-author": slug, className: cn("inline-flex min-w-0 items-center gap-1.5", className), ...props, ...labelling, children: [_jsx("span", { "data-slot": "model-mark-tile", "data-mark": Mark ? "brand" : "monogram", "data-mark-source": definition?.source, "aria-hidden": "true", className: "inline-flex shrink-0 items-center justify-center rounded-md border border-border bg-background text-foreground", style: { width: size, height: size }, children: Mark ? (_jsx(Mark, { size: Math.round(size * MODEL_MARK_GLYPH_RATIO) })) : (_jsx("span", { "aria-hidden": "true", className: "font-semibold leading-none text-muted-foreground", "data-slot": "model-author-monogram", style: { fontSize: Math.max(8, Math.round(size * 0.32)) }, children: authorInitials(slug) })) }), name ? (_jsxs("span", { className: "min-w-0 truncate", children: [_jsx("span", { className: "font-medium", children: name }), " ", _jsx("span", { className: "text-xs text-muted-foreground", children: author })] })) : null] }));
104
+ return (_jsxs("span", { "data-slot": "model-mark", "data-author": author, "data-resolved-author": slug, className: cn("inline-flex min-w-0 max-w-full items-center gap-1.5", className), ...props, ...labelling, children: [_jsx("span", { "data-slot": "model-mark-tile", "data-mark": Mark ? "brand" : "monogram", "data-mark-source": definition?.source, "aria-hidden": "true", className: "inline-flex shrink-0 items-center justify-center rounded-md border border-border bg-background text-foreground", style: { width: size, height: size }, children: Mark ? (_jsx(Mark, { size: Math.round(size * MODEL_MARK_GLYPH_RATIO) })) : (_jsx("span", { "aria-hidden": "true", className: "font-semibold leading-none text-muted-foreground", "data-slot": "model-author-monogram", style: { fontSize: Math.max(8, Math.round(size * 0.32)) }, children: authorInitials(slug) })) }), name ? (_jsxs("span", { className: "min-w-0 truncate", children: [_jsx("span", { className: "font-medium", children: name }), " ", _jsx("span", { className: "text-xs text-muted-foreground", children: author })] })) : null] }));
105
105
  }
106
106
  export { ModelMark };
@@ -27,7 +27,7 @@ function TableCell({ className, ...props }) {
27
27
  return (_jsx("td", { "data-slot": "table-cell", className: cn("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0", className), ...props }));
28
28
  }
29
29
  function TableDetailRow({ colSpan, facts, layout = "standard", }) {
30
- return (_jsx(TableRow, { "data-slot": "table-detail-row", className: tableCompactLayouts[layout].details, children: _jsx(TableCell, { colSpan: colSpan, className: "px-2 pt-0 pb-3 whitespace-normal", children: _jsx("dl", { className: cn("grid min-w-0 grid-cols-2 gap-x-4 gap-y-2", facts.length > 2 && "@lg/table:grid-cols-3"), children: facts.map((fact) => (_jsxs("div", { className: cn("min-w-0 last:odd:col-span-2", facts.length > 2 && "@lg/table:last:odd:col-span-1"), children: [_jsx("dt", { className: "text-xs text-muted-foreground", children: fact.label }), _jsx("dd", { className: cn("min-w-0", fact.numeric ? "tabular-nums wrap-normal" : "wrap-anywhere"), children: fact.value })] }, fact.id))) }) }) }));
30
+ return (_jsx(TableRow, { "data-slot": "table-detail-row", className: tableCompactLayouts[layout].details, children: _jsx(TableCell, { colSpan: colSpan, className: "px-2 pt-0 pb-3 whitespace-normal", children: _jsx("dl", { className: cn("grid min-w-0 grid-cols-1 gap-x-4 gap-y-2 @sm/table:grid-cols-2", facts.length > 2 && "@lg/table:grid-cols-3"), children: facts.map((fact) => (_jsxs("div", { className: cn("min-w-0 @sm/table:last:odd:col-span-2", facts.length > 2 && "@lg/table:last:odd:col-span-1"), children: [_jsx("dt", { className: "text-xs text-muted-foreground", children: fact.label }), _jsx("dd", { className: cn("min-w-0", fact.numeric ? "tabular-nums wrap-normal" : "wrap-anywhere"), children: fact.value })] }, fact.id))) }) }) }));
31
31
  }
32
32
  function TableCaption({ className, ...props }) {
33
33
  return (_jsx("caption", { "data-slot": "table-caption", className: cn("mt-4 text-sm text-muted-foreground", className), ...props }));
@@ -11,8 +11,8 @@ copy, and behavior.
11
11
 
12
12
  | Removed API | Registry source to use instead | Reason |
13
13
  | --- | --- | --- |
14
- | `DataTable`, `DataTableColumnControls`, `DataTableEmptyState`, `DataTableState` | `@shadcn/data-table-demo` or the `DataTable` inside `@shadcn/dashboard-01` | shadcn already ships first-party data-table examples with sorting, selection, visibility, filtering, and pagination patterns. |
15
- | `CommandPalette`, `ModelPickerCommand`, `SessionPickerCommand` | `@shadcn/command`, `@shadcn/command-demo`, `@shadcn/command-dialog` | shadcn already ships the command primitives and command-dialog example; model/session execution is app behavior. |
14
+ | Package-level `DataTable`, `DataTableColumnControls`, `DataTableEmptyState`, `DataTableState` | [shadcn Data Table guide](https://ui.shadcn.com/docs/components/base/data-table), `@shadcn/table`, and the table in `@shadcn/dashboard-01` | These are first-party composition sources for sorting, visibility, filtering, and pagination. Portal retains its app-owned `DataTable` adapter for registry and URL behavior. |
15
+ | `CommandPalette`, `ModelPickerCommand`, `SessionPickerCommand` | `@shadcn/command` and its `CommandDialog` export ([Command guide](https://ui.shadcn.com/docs/components/base/command)) | The command primitive and dialog composition are already supplied; model/session execution is app behavior. |
16
16
  | `ChartCard`, `MetricChart`, `semanticChartColors` | The package chart kit, owned by [`contract.md`](contract.md) | shadcn already ships the chart primitives and blocks the kit is pulled from; metric aggregation and chart choice are app behavior. |
17
17
 
18
18
  ## Retained Package Compositions
package/docs/contract.md CHANGED
@@ -205,6 +205,8 @@ content, and a chart names a model through the label in its `ChartConfig`. A
205
205
  model's row in a table or a ranked list is where `ModelMark` belongs. A mark is
206
206
  decoration beside the label that already names it; one standing alone takes
207
207
  `label` (`role="img"` with an accessible name) or stays hidden.
208
+ Named marks stay within their containing cell, shortening the visible text when
209
+ space is tight; callers with long model IDs provide the full ID in `title`.
208
210
 
209
211
  The package owns the reviewed author-to-mark mapping and its generated artwork;
210
212
  the live catalog remains the source of which authors exist. The consuming app
@@ -298,7 +300,8 @@ highlights one record. A consumer does not render the two rows as independent
298
300
  siblings. Portal `DataTable` chooses a layout from its column count by default;
299
301
  a comparison whose columns remain readable longer may select one of these
300
302
  shared layouts instead of adding route-owned width rules.
301
- Two supporting facts use two columns; additional facts can use three when they fit.
303
+ Supporting facts stack below 384px of table width, use two columns when they
304
+ fit, and use three for additional facts at the larger container breakpoint.
302
305
  The cell renderer supplies the value, leaving the label to the detail row.
303
306
 
304
307
  ### Missing table values
@@ -25,6 +25,22 @@ Fixtures live in:
25
25
  | `SettingsSection` / `SettingsField` | Header, divided save footer, field layout, labels, descriptions, errors, and control associations. | Form state, validation, submission, persistence, settings taxonomy, and save/cancel behavior. |
26
26
  | `FeedbackState` | Shared empty, loading, saving, error, permission, offline, no-results, and fatal state presentation. | Recovery actions, retry behavior, permission escalation, app-specific state language. |
27
27
 
28
+ ## Collection and command recipes
29
+
30
+ Portal's [`DataTable`](../../../apps/portal/src/components/kit/data-table.tsx) is
31
+ the existing app owner for collection interaction, URL state, and registry
32
+ behavior. It composes the shared `Table` and `TableDetailRow` with TanStack
33
+ Table, following the [shadcn Data Table guide](https://ui.shadcn.com/docs/components/base/data-table)
34
+ and the `@shadcn/dashboard-01` table block. The shared row owns compact fact
35
+ geometry; a caller supplies its labels and values. Keep Portal's adapter for
36
+ its existing consumers instead of introducing a second package table API.
37
+
38
+ The shared [`command`](../src/components/command.tsx) component includes
39
+ `CommandDialog`, as the [shadcn Command guide](https://ui.shadcn.com/docs/components/base/command)
40
+ documents. A product composes its commands there and owns search data,
41
+ selection effects, shortcuts, routing, and permission checks. The Portal
42
+ command dialog is the current app owner for Portal navigation commands.
43
+
28
44
  ## SettingsSection
29
45
 
30
46
  Use `SettingsSection` and `SettingsField` for horizontal settings rows that need consistent label, description, error, and control alignment.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nadicodeai/ui",
3
- "version": "10.0.1",
3
+ "version": "10.1.0",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -72,7 +72,7 @@
72
72
  "@assistant-ui/react": "0.15.21",
73
73
  "@assistant-ui/react-markdown": "0.14.16",
74
74
  "@base-ui/react": "^1.8.0",
75
- "@nadicodeai/design-system": "10.0.1",
75
+ "@nadicodeai/design-system": "10.1.0",
76
76
  "class-variance-authority": "^0.7.1",
77
77
  "clsx": "^2.1.1",
78
78
  "cmdk": "^1.1.1",