@adea-ai/ui 0.134.0 → 0.135.1

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.
@@ -24,8 +24,20 @@ export type StatProps = ComponentProps<'div'> & {
24
24
  accent?: boolean;
25
25
  };
26
26
  export declare function Stat(props: StatProps): JSX.Element;
27
- /** A row of stats that shares one gap and wraps as the window narrows. */
28
- export declare function StatGroup(props: ComponentProps<'div'>): JSX.Element;
27
+ /**
28
+ * A row of stats that shares one gap and wraps as the window narrows.
29
+ *
30
+ * By default the column count steps with the *viewport* (two from `sm`, four from
31
+ * `lg`), which is right for a group that spans the page. A group inside a pane
32
+ * whose width is not the window's (a docked panel, a resizable column, a view
33
+ * beside a sidebar) gets the wrong count from a viewport breakpoint. `fit` sizes
34
+ * from the group's own width instead: as many tiles per row as fit at the
35
+ * minimum tile width, each growing to share the remainder, however many stats
36
+ * there are.
37
+ */
38
+ export declare function StatGroup(props: ComponentProps<'div'> & {
39
+ fit?: boolean;
40
+ }): JSX.Element;
29
41
  /**
30
42
  * PropertyList.
31
43
  *
@@ -1 +1 @@
1
- {"version":3,"file":"stat.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/stat/stat.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAMnD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG;IAC9C,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,GAAG,CAAC,OAAO,CAAA;IAClB,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,8EAA8E;IAC9E,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAA;IACrC,wEAAwE;IACxE,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,eAmDpC;AAED,0EAA0E;AAC1E,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,eASrD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC,eASvD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC,eASvD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC,eASxD;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,eAa1E"}
1
+ {"version":3,"file":"stat.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/stat/stat.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAMnD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG;IAC9C,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,GAAG,CAAC,OAAO,CAAA;IAClB,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,8EAA8E;IAC9E,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAA;IACrC,wEAAwE;IACxE,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,eAmDpC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,eAiBzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC,eASvD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC,eASvD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC,eASxD;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,eAa1E"}
@@ -83,13 +83,23 @@ function Stat(props) {
83
83
  return _el$;
84
84
  })();
85
85
  }
86
- /** A row of stats that shares one gap and wraps as the window narrows. */
86
+ /**
87
+ * A row of stats that shares one gap and wraps as the window narrows.
88
+ *
89
+ * By default the column count steps with the *viewport* (two from `sm`, four from
90
+ * `lg`), which is right for a group that spans the page. A group inside a pane
91
+ * whose width is not the window's (a docked panel, a resizable column, a view
92
+ * beside a sidebar) gets the wrong count from a viewport breakpoint. `fit` sizes
93
+ * from the group's own width instead: as many tiles per row as fit at the
94
+ * minimum tile width, each growing to share the remainder, however many stats
95
+ * there are.
96
+ */
87
97
  function StatGroup(props) {
88
- const [local, rest] = splitProps(props, ["class"]);
98
+ const [local, rest] = splitProps(props, ["class", "fit"]);
89
99
  return (() => {
90
100
  var _el$6 = _tmpl$3();
91
101
  spread(_el$6, mergeProps({ get ["class"]() {
92
- return cn("grid gap-3 sm:grid-cols-2 lg:grid-cols-4", local.class);
102
+ return cn("grid gap-3", local.fit ? "grid-cols-[repeat(auto-fill,minmax(9.375rem,1fr))]" : "sm:grid-cols-2 lg:grid-cols-4", local.class);
93
103
  } }, rest), false, false);
94
104
  return _el$6;
95
105
  })();
@@ -1 +1 @@
1
- {"version":3,"file":"stat.js","names":["ArrowDownRight","ArrowUpRight","ComponentProps","JSX","Show","splitProps","Dynamic","cn","Heading","Text","StatProps","label","value","Element","unit","delta","deltaTone","accent","Stat","props","local","rest","_el$","_tmpl$2","_el$2","firstChild","_el$3","nextSibling","_$spread","_$mergeProps","class","_$insert","_$createComponent","as","size","numeric","children","when","variant","tone","_el$4","_tmpl$","_el$5","component","StatGroup","_el$6","_tmpl$3","PropertyList","_el$7","_tmpl$4","PropertyTerm","_el$8","_tmpl$5","PropertyValue","_el$9","_tmpl$6","PropertyRow","term","_el$0","_tmpl$7","_el$1","_el$10","_$mergeProps","_$createComponent"],"sources":["../../../../src/components/composites/stat/stat.tsx"],"sourcesContent":["import { ArrowDownRight, ArrowUpRight } from 'lucide-solid'\nimport type { ComponentProps, JSX } from 'solid-js'\nimport { Show, splitProps } from 'solid-js'\nimport { Dynamic } from 'solid-js/web'\nimport { cn } from '#lib/utils'\nimport { Heading, Text } from '../../ui/typography'\n\n/**\n * Stat.\n *\n * A single measured number with its label and, optionally, its change. The\n * whole component is a decision about honesty: a value shown without its\n * comparison is not information, so `delta` carries the direction, the amount\n * and — through `deltaTone` — whether the direction is *good*. A rising number\n * is not always a rising outcome, and only the caller knows which way is which.\n *\n * `tabular-nums` on the value is what lets two stats in a row be compared\n * without the digits shifting under the reader.\n */\nexport type StatProps = ComponentProps<'div'> & {\n label: string\n value: JSX.Element\n /** A unit or qualifier after the value, e.g. \"ms\", \"of 10\". */\n unit?: string\n /** The change, e.g. \"+12% from last week\". */\n delta?: string\n /** Whether the change is an improvement. Decides the arrow and the colour. */\n deltaTone?: 'up' | 'down' | 'neutral'\n /** Draws the leading accent rule used for a row of headline numbers. */\n accent?: boolean\n}\n\nexport function Stat(props: StatProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'label',\n 'value',\n 'unit',\n 'delta',\n 'deltaTone',\n 'accent',\n 'children',\n ])\n\n return (\n <div\n data-slot=\"stat\"\n class={cn(\n 'flex min-w-0 flex-col gap-1 rounded-lg border border-border bg-card p-3',\n { 'border-t-2 border-t-primary': local.accent },\n local.class\n )}\n {...rest}\n >\n <div class=\"text-muted-foreground truncate text-xs font-medium\">{local.label}</div>\n <div class=\"flex items-baseline gap-1\">\n <Heading as=\"span\" size=\"page\" numeric>\n {local.value}\n </Heading>\n <Show when={local.unit}>\n <Text variant=\"caption\" tone=\"muted\">\n {local.unit}\n </Text>\n </Show>\n </div>\n <Show when={local.delta}>\n <div class=\"text-foreground flex items-center gap-1 text-xs\">\n <Show when={local.deltaTone === 'up' || local.deltaTone === 'down'}>\n <Dynamic\n component={local.deltaTone === 'down' ? ArrowDownRight : ArrowUpRight}\n aria-hidden=\"true\"\n class={cn('size-3', {\n 'text-success': local.deltaTone === 'up',\n 'text-destructive': local.deltaTone === 'down',\n })}\n />\n </Show>\n <span class=\"tabular-nums\">{local.delta}</span>\n </div>\n </Show>\n {local.children}\n </div>\n )\n}\n\n/** A row of stats that shares one gap and wraps as the window narrows. */\nexport function StatGroup(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"stat-group\"\n class={cn('grid gap-3 sm:grid-cols-2 lg:grid-cols-4', local.class)}\n {...rest}\n />\n )\n}\n\n/**\n * PropertyList.\n *\n * A definition list for read-only metadata: the details of a file, a session, a\n * build. This is a `<dl>`, not a table and not a grid of divs, because the\n * relationship being expressed is term-and-definition and the platform has an\n * element for exactly that.\n *\n * Values are selectable by default. Metadata is the thing users copy most and\n * get the least often: a commit hash behind a drag-to-select gesture is a small\n * daily failure.\n */\nexport function PropertyList(props: ComponentProps<'dl'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <dl\n data-slot=\"property-list\"\n class={cn('grid grid-cols-[auto_1fr] items-baseline gap-x-4 gap-y-2 text-sm', local.class)}\n {...rest}\n />\n )\n}\n\nexport function PropertyTerm(props: ComponentProps<'dt'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <dt\n data-slot=\"property-term\"\n class={cn('text-muted-foreground whitespace-nowrap', local.class)}\n {...rest}\n />\n )\n}\n\nexport function PropertyValue(props: ComponentProps<'dd'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <dd\n data-slot=\"property-value\"\n class={cn('min-w-0 break-words select-text', local.class)}\n {...rest}\n />\n )\n}\n\n/** A single term/value pair, for a list built one row at a time. */\nexport function PropertyRow(props: ComponentProps<'div'> & { term: string }) {\n const [local, rest] = splitProps(props, ['class', 'term', 'children'])\n\n return (\n <div\n data-slot=\"property-row\"\n class={cn('flex items-baseline justify-between gap-4 text-sm', local.class)}\n {...rest}\n >\n <span class=\"text-muted-foreground shrink-0\">{local.term}</span>\n <span class=\"min-w-0 truncate text-end select-text\">{local.children}</span>\n </div>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"stat.js","names":["ArrowDownRight","ArrowUpRight","ComponentProps","JSX","Show","splitProps","Dynamic","cn","Heading","Text","StatProps","label","value","Element","unit","delta","deltaTone","accent","Stat","props","local","rest","_el$","_tmpl$2","_el$2","firstChild","_el$3","nextSibling","_$spread","_$mergeProps","class","_$insert","_$createComponent","as","size","numeric","children","when","variant","tone","_el$4","_tmpl$","_el$5","component","StatGroup","fit","_el$6","_tmpl$3","PropertyList","_el$7","_tmpl$4","PropertyTerm","_el$8","_tmpl$5","PropertyValue","_el$9","_tmpl$6","PropertyRow","term","_el$0","_tmpl$7","_el$1","_el$10","_$mergeProps","_$createComponent"],"sources":["../../../../src/components/composites/stat/stat.tsx"],"sourcesContent":["import { ArrowDownRight, ArrowUpRight } from 'lucide-solid'\nimport type { ComponentProps, JSX } from 'solid-js'\nimport { Show, splitProps } from 'solid-js'\nimport { Dynamic } from 'solid-js/web'\nimport { cn } from '#lib/utils'\nimport { Heading, Text } from '../../ui/typography'\n\n/**\n * Stat.\n *\n * A single measured number with its label and, optionally, its change. The\n * whole component is a decision about honesty: a value shown without its\n * comparison is not information, so `delta` carries the direction, the amount\n * and — through `deltaTone` — whether the direction is *good*. A rising number\n * is not always a rising outcome, and only the caller knows which way is which.\n *\n * `tabular-nums` on the value is what lets two stats in a row be compared\n * without the digits shifting under the reader.\n */\nexport type StatProps = ComponentProps<'div'> & {\n label: string\n value: JSX.Element\n /** A unit or qualifier after the value, e.g. \"ms\", \"of 10\". */\n unit?: string\n /** The change, e.g. \"+12% from last week\". */\n delta?: string\n /** Whether the change is an improvement. Decides the arrow and the colour. */\n deltaTone?: 'up' | 'down' | 'neutral'\n /** Draws the leading accent rule used for a row of headline numbers. */\n accent?: boolean\n}\n\nexport function Stat(props: StatProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'label',\n 'value',\n 'unit',\n 'delta',\n 'deltaTone',\n 'accent',\n 'children',\n ])\n\n return (\n <div\n data-slot=\"stat\"\n class={cn(\n 'flex min-w-0 flex-col gap-1 rounded-lg border border-border bg-card p-3',\n { 'border-t-2 border-t-primary': local.accent },\n local.class\n )}\n {...rest}\n >\n <div class=\"text-muted-foreground truncate text-xs font-medium\">{local.label}</div>\n <div class=\"flex items-baseline gap-1\">\n <Heading as=\"span\" size=\"page\" numeric>\n {local.value}\n </Heading>\n <Show when={local.unit}>\n <Text variant=\"caption\" tone=\"muted\">\n {local.unit}\n </Text>\n </Show>\n </div>\n <Show when={local.delta}>\n <div class=\"text-foreground flex items-center gap-1 text-xs\">\n <Show when={local.deltaTone === 'up' || local.deltaTone === 'down'}>\n <Dynamic\n component={local.deltaTone === 'down' ? ArrowDownRight : ArrowUpRight}\n aria-hidden=\"true\"\n class={cn('size-3', {\n 'text-success': local.deltaTone === 'up',\n 'text-destructive': local.deltaTone === 'down',\n })}\n />\n </Show>\n <span class=\"tabular-nums\">{local.delta}</span>\n </div>\n </Show>\n {local.children}\n </div>\n )\n}\n\n/**\n * A row of stats that shares one gap and wraps as the window narrows.\n *\n * By default the column count steps with the *viewport* (two from `sm`, four from\n * `lg`), which is right for a group that spans the page. A group inside a pane\n * whose width is not the window's (a docked panel, a resizable column, a view\n * beside a sidebar) gets the wrong count from a viewport breakpoint. `fit` sizes\n * from the group's own width instead: as many tiles per row as fit at the\n * minimum tile width, each growing to share the remainder, however many stats\n * there are.\n */\nexport function StatGroup(props: ComponentProps<'div'> & { fit?: boolean }) {\n const [local, rest] = splitProps(props, ['class', 'fit'])\n return (\n <div\n data-slot=\"stat-group\"\n class={cn(\n 'grid gap-3',\n // 9.375rem is 150px at the default root size: room for a label of about\n // twenty characters and a six-digit value before the tile truncates.\n local.fit\n ? 'grid-cols-[repeat(auto-fill,minmax(9.375rem,1fr))]'\n : 'sm:grid-cols-2 lg:grid-cols-4',\n local.class\n )}\n {...rest}\n />\n )\n}\n\n/**\n * PropertyList.\n *\n * A definition list for read-only metadata: the details of a file, a session, a\n * build. This is a `<dl>`, not a table and not a grid of divs, because the\n * relationship being expressed is term-and-definition and the platform has an\n * element for exactly that.\n *\n * Values are selectable by default. Metadata is the thing users copy most and\n * get the least often: a commit hash behind a drag-to-select gesture is a small\n * daily failure.\n */\nexport function PropertyList(props: ComponentProps<'dl'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <dl\n data-slot=\"property-list\"\n class={cn('grid grid-cols-[auto_1fr] items-baseline gap-x-4 gap-y-2 text-sm', local.class)}\n {...rest}\n />\n )\n}\n\nexport function PropertyTerm(props: ComponentProps<'dt'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <dt\n data-slot=\"property-term\"\n class={cn('text-muted-foreground whitespace-nowrap', local.class)}\n {...rest}\n />\n )\n}\n\nexport function PropertyValue(props: ComponentProps<'dd'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <dd\n data-slot=\"property-value\"\n class={cn('min-w-0 break-words select-text', local.class)}\n {...rest}\n />\n )\n}\n\n/** A single term/value pair, for a list built one row at a time. */\nexport function PropertyRow(props: ComponentProps<'div'> & { term: string }) {\n const [local, rest] = splitProps(props, ['class', 'term', 'children'])\n\n return (\n <div\n data-slot=\"property-row\"\n class={cn('flex items-baseline justify-between gap-4 text-sm', local.class)}\n {...rest}\n >\n <span class=\"text-muted-foreground shrink-0\">{local.term}</span>\n <span class=\"min-w-0 truncate text-end select-text\">{local.children}</span>\n </div>\n )\n}\n"],"mappings":"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"}
@@ -24,6 +24,15 @@ export declare const cardVariants: (props?: ({
24
24
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
25
25
  export type CardProps = ComponentProps<'div'> & VariantProps<typeof cardVariants>;
26
26
  export declare function Card(props: CardProps): import("solid-js").JSX.Element;
27
+ /**
28
+ * The header is a grid so that `CardAction` has tracks to be placed in: the
29
+ * action is a direct child that takes a second column spanning the title and
30
+ * description rows. A flex column gives `col-start-2` nothing to land on and
31
+ * the action would simply stack under the copy. The extra column exists only
32
+ * for a direct-child action: a wrapper around it is then the header's single
33
+ * grid item, so it keeps the full width. A header without an action lays out as
34
+ * it always did (one full-width column, 4px between its children).
35
+ */
27
36
  export declare function CardHeader(props: ComponentProps<'div'>): import("solid-js").JSX.Element;
28
37
  export declare function CardTitle(props: ComponentProps<'div'>): import("solid-js").JSX.Element;
29
38
  export declare function CardDescription(props: ComponentProps<'div'>): import("solid-js").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/card/card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAE9C,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AAItD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,YAAY;;8EAexB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,OAAO,YAAY,CAAC,CAAA;AAEjF,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,kCAKpC;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,kCAKtD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,kCASrD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,kCAS3D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,kCAStD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,kCAGvD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,kCAGtD"}
1
+ {"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/card/card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAE9C,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AAItD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,YAAY;;8EAexB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,OAAO,YAAY,CAAC,CAAA;AAEjF,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,kCAKpC;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,kCAYtD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,kCASrD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,kCAS3D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,kCAStD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,kCAGvD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,kCAGtD"}
@@ -51,12 +51,21 @@ function Card(props) {
51
51
  return _el$;
52
52
  })();
53
53
  }
54
+ /**
55
+ * The header is a grid so that `CardAction` has tracks to be placed in: the
56
+ * action is a direct child that takes a second column spanning the title and
57
+ * description rows. A flex column gives `col-start-2` nothing to land on and
58
+ * the action would simply stack under the copy. The extra column exists only
59
+ * for a direct-child action: a wrapper around it is then the header's single
60
+ * grid item, so it keeps the full width. A header without an action lays out as
61
+ * it always did (one full-width column, 4px between its children).
62
+ */
54
63
  function CardHeader(props) {
55
64
  const [local, rest] = splitProps(props, ["class"]);
56
65
  return (() => {
57
66
  var _el$2 = _tmpl$2();
58
67
  spread(_el$2, mergeProps({ get ["class"]() {
59
- return cn("flex flex-col gap-1 px-4", local.class);
68
+ return cn("grid grid-cols-1 auto-rows-min gap-x-4 gap-y-1 px-4 has-[>[data-slot=card-action]]:grid-cols-[minmax(0,1fr)_auto]", local.class);
60
69
  } }, rest), false, false);
61
70
  return _el$2;
62
71
  })();
@@ -1 +1 @@
1
- {"version":3,"file":"card.js","names":["ComponentProps","splitProps","cva","VariantProps","cn","headingVariants","cardVariants","variants","size","default","sm","flush","defaultVariants","CardProps","Card","props","local","rest","_el$","_tmpl$","_$spread","_$mergeProps","class","CardHeader","_el$2","_tmpl$2","CardTitle","_el$3","_tmpl$3","leading","CardDescription","_el$4","_tmpl$4","CardAction","_el$5","_tmpl$5","CardContent","_el$6","_tmpl$6","CardFooter","_el$7","_tmpl$7","_$mergeProps"],"sources":["../../../../src/components/ui/card/card.tsx"],"sourcesContent":["import type { ComponentProps } from 'solid-js'\nimport { splitProps } from 'solid-js'\nimport { cva, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\nimport { headingVariants } from '../typography'\n\n/**\n * Card.\n *\n * A surface that sits on the canvas. Every card carries its own edge — a\n * border — because in the light theme `--card` is one faint step off a white\n * `--background`, and a borderless card there all but disappears. Making the border\n * structural rather than optional is what stops one app's cards from reading\n * as floating panels and another's as nothing at all.\n *\n * The parts are separate components rather than a template because a card's\n * header, content and footer have different padding on purpose: the header and\n * footer are tight, the content breathes.\n *\n * `size` is the card's padding rung, so a caller never sets `p-*` or `gap-*` on\n * a card to make it denser. `sm` tightens the card and its header, content and\n * footer together (the parts' inline padding follows the card, so they stay\n * aligned with each other); `flush` removes the block padding and gap for a\n * card whose body is a list of rows or a scroll area that runs edge to edge.\n */\nexport const cardVariants = cva(\n 'bg-card text-card-foreground flex flex-col rounded-xl border border-border shadow-xs',\n {\n variants: {\n size: {\n /** 16px block padding and gap; the parts carry 16px inline padding. */\n default: 'gap-4 py-4',\n /** 12px everywhere: a dense settings or status card. */\n sm: 'gap-3 py-3 *:data-[slot=card-content]:px-3 *:data-[slot=card-footer]:px-3 *:data-[slot=card-header]:px-3',\n /** No block padding or gap: the card hosts a row list or a scroller. */\n flush: 'gap-0 py-0',\n },\n },\n defaultVariants: { size: 'default' },\n }\n)\n\nexport type CardProps = ComponentProps<'div'> & VariantProps<typeof cardVariants>\n\nexport function Card(props: CardProps) {\n const [local, rest] = splitProps(props, ['class', 'size'])\n return (\n <div data-slot=\"card\" class={cn(cardVariants({ size: local.size }), local.class)} {...rest} />\n )\n}\n\nexport function CardHeader(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div data-slot=\"card-header\" class={cn('flex flex-col gap-1 px-4', local.class)} {...rest} />\n )\n}\n\nexport function CardTitle(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"card-title\"\n class={cn(headingVariants({ size: 'card', leading: 'none' }), local.class)}\n {...rest}\n />\n )\n}\n\nexport function CardDescription(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"card-description\"\n class={cn('text-muted-foreground text-sm', local.class)}\n {...rest}\n />\n )\n}\n\nexport function CardAction(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"card-action\"\n class={cn('col-start-2 row-span-2 row-start-1 self-start justify-self-end', local.class)}\n {...rest}\n />\n )\n}\n\nexport function CardContent(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return <div data-slot=\"card-content\" class={cn('px-4', local.class)} {...rest} />\n}\n\nexport function CardFooter(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return <div data-slot=\"card-footer\" class={cn('flex items-center px-4', local.class)} {...rest} />\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"card.js","names":["ComponentProps","splitProps","cva","VariantProps","cn","headingVariants","cardVariants","variants","size","default","sm","flush","defaultVariants","CardProps","Card","props","local","rest","_el$","_tmpl$","_$spread","_$mergeProps","class","CardHeader","_el$2","_tmpl$2","CardTitle","_el$3","_tmpl$3","leading","CardDescription","_el$4","_tmpl$4","CardAction","_el$5","_tmpl$5","CardContent","_el$6","_tmpl$6","CardFooter","_el$7","_tmpl$7","_$mergeProps"],"sources":["../../../../src/components/ui/card/card.tsx"],"sourcesContent":["import type { ComponentProps } from 'solid-js'\nimport { splitProps } from 'solid-js'\nimport { cva, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\nimport { headingVariants } from '../typography'\n\n/**\n * Card.\n *\n * A surface that sits on the canvas. Every card carries its own edge — a\n * border — because in the light theme `--card` is one faint step off a white\n * `--background`, and a borderless card there all but disappears. Making the border\n * structural rather than optional is what stops one app's cards from reading\n * as floating panels and another's as nothing at all.\n *\n * The parts are separate components rather than a template because a card's\n * header, content and footer have different padding on purpose: the header and\n * footer are tight, the content breathes.\n *\n * `size` is the card's padding rung, so a caller never sets `p-*` or `gap-*` on\n * a card to make it denser. `sm` tightens the card and its header, content and\n * footer together (the parts' inline padding follows the card, so they stay\n * aligned with each other); `flush` removes the block padding and gap for a\n * card whose body is a list of rows or a scroll area that runs edge to edge.\n */\nexport const cardVariants = cva(\n 'bg-card text-card-foreground flex flex-col rounded-xl border border-border shadow-xs',\n {\n variants: {\n size: {\n /** 16px block padding and gap; the parts carry 16px inline padding. */\n default: 'gap-4 py-4',\n /** 12px everywhere: a dense settings or status card. */\n sm: 'gap-3 py-3 *:data-[slot=card-content]:px-3 *:data-[slot=card-footer]:px-3 *:data-[slot=card-header]:px-3',\n /** No block padding or gap: the card hosts a row list or a scroller. */\n flush: 'gap-0 py-0',\n },\n },\n defaultVariants: { size: 'default' },\n }\n)\n\nexport type CardProps = ComponentProps<'div'> & VariantProps<typeof cardVariants>\n\nexport function Card(props: CardProps) {\n const [local, rest] = splitProps(props, ['class', 'size'])\n return (\n <div data-slot=\"card\" class={cn(cardVariants({ size: local.size }), local.class)} {...rest} />\n )\n}\n\n/**\n * The header is a grid so that `CardAction` has tracks to be placed in: the\n * action is a direct child that takes a second column spanning the title and\n * description rows. A flex column gives `col-start-2` nothing to land on and\n * the action would simply stack under the copy. The extra column exists only\n * for a direct-child action: a wrapper around it is then the header's single\n * grid item, so it keeps the full width. A header without an action lays out as\n * it always did (one full-width column, 4px between its children).\n */\nexport function CardHeader(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"card-header\"\n class={cn(\n 'grid grid-cols-1 auto-rows-min gap-x-4 gap-y-1 px-4 has-[>[data-slot=card-action]]:grid-cols-[minmax(0,1fr)_auto]',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function CardTitle(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"card-title\"\n class={cn(headingVariants({ size: 'card', leading: 'none' }), local.class)}\n {...rest}\n />\n )\n}\n\nexport function CardDescription(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"card-description\"\n class={cn('text-muted-foreground text-sm', local.class)}\n {...rest}\n />\n )\n}\n\nexport function CardAction(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"card-action\"\n class={cn('col-start-2 row-span-2 row-start-1 self-start justify-self-end', local.class)}\n {...rest}\n />\n )\n}\n\nexport function CardContent(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return <div data-slot=\"card-content\" class={cn('px-4', local.class)} {...rest} />\n}\n\nexport function CardFooter(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return <div data-slot=\"card-footer\" class={cn('flex items-center px-4', local.class)} {...rest} />\n}\n"],"mappings":"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"}
@@ -83,13 +83,31 @@ export function Stat(props: StatProps) {
83
83
  )
84
84
  }
85
85
 
86
- /** A row of stats that shares one gap and wraps as the window narrows. */
87
- export function StatGroup(props: ComponentProps<'div'>) {
88
- const [local, rest] = splitProps(props, ['class'])
86
+ /**
87
+ * A row of stats that shares one gap and wraps as the window narrows.
88
+ *
89
+ * By default the column count steps with the *viewport* (two from `sm`, four from
90
+ * `lg`), which is right for a group that spans the page. A group inside a pane
91
+ * whose width is not the window's (a docked panel, a resizable column, a view
92
+ * beside a sidebar) gets the wrong count from a viewport breakpoint. `fit` sizes
93
+ * from the group's own width instead: as many tiles per row as fit at the
94
+ * minimum tile width, each growing to share the remainder, however many stats
95
+ * there are.
96
+ */
97
+ export function StatGroup(props: ComponentProps<'div'> & { fit?: boolean }) {
98
+ const [local, rest] = splitProps(props, ['class', 'fit'])
89
99
  return (
90
100
  <div
91
101
  data-slot="stat-group"
92
- class={cn('grid gap-3 sm:grid-cols-2 lg:grid-cols-4', local.class)}
102
+ class={cn(
103
+ 'grid gap-3',
104
+ // 9.375rem is 150px at the default root size: room for a label of about
105
+ // twenty characters and a six-digit value before the tile truncates.
106
+ local.fit
107
+ ? 'grid-cols-[repeat(auto-fill,minmax(9.375rem,1fr))]'
108
+ : 'sm:grid-cols-2 lg:grid-cols-4',
109
+ local.class
110
+ )}
93
111
  {...rest}
94
112
  />
95
113
  )
@@ -49,10 +49,26 @@ export function Card(props: CardProps) {
49
49
  )
50
50
  }
51
51
 
52
+ /**
53
+ * The header is a grid so that `CardAction` has tracks to be placed in: the
54
+ * action is a direct child that takes a second column spanning the title and
55
+ * description rows. A flex column gives `col-start-2` nothing to land on and
56
+ * the action would simply stack under the copy. The extra column exists only
57
+ * for a direct-child action: a wrapper around it is then the header's single
58
+ * grid item, so it keeps the full width. A header without an action lays out as
59
+ * it always did (one full-width column, 4px between its children).
60
+ */
52
61
  export function CardHeader(props: ComponentProps<'div'>) {
53
62
  const [local, rest] = splitProps(props, ['class'])
54
63
  return (
55
- <div data-slot="card-header" class={cn('flex flex-col gap-1 px-4', local.class)} {...rest} />
64
+ <div
65
+ data-slot="card-header"
66
+ class={cn(
67
+ 'grid grid-cols-1 auto-rows-min gap-x-4 gap-y-1 px-4 has-[>[data-slot=card-action]]:grid-cols-[minmax(0,1fr)_auto]',
68
+ local.class
69
+ )}
70
+ {...rest}
71
+ />
56
72
  )
57
73
  }
58
74
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adea-ai/ui",
3
- "version": "0.134.0",
3
+ "version": "0.135.1",
4
4
  "description": "The Adea design system: Kobalte-backed Solid components, semantic OKLCH tokens, and the app-shell layout primitives shared by Adea and Cortana.",
5
5
  "keywords": [
6
6
  "adea",
@@ -83,13 +83,31 @@ export function Stat(props: StatProps) {
83
83
  )
84
84
  }
85
85
 
86
- /** A row of stats that shares one gap and wraps as the window narrows. */
87
- export function StatGroup(props: ComponentProps<'div'>) {
88
- const [local, rest] = splitProps(props, ['class'])
86
+ /**
87
+ * A row of stats that shares one gap and wraps as the window narrows.
88
+ *
89
+ * By default the column count steps with the *viewport* (two from `sm`, four from
90
+ * `lg`), which is right for a group that spans the page. A group inside a pane
91
+ * whose width is not the window's (a docked panel, a resizable column, a view
92
+ * beside a sidebar) gets the wrong count from a viewport breakpoint. `fit` sizes
93
+ * from the group's own width instead: as many tiles per row as fit at the
94
+ * minimum tile width, each growing to share the remainder, however many stats
95
+ * there are.
96
+ */
97
+ export function StatGroup(props: ComponentProps<'div'> & { fit?: boolean }) {
98
+ const [local, rest] = splitProps(props, ['class', 'fit'])
89
99
  return (
90
100
  <div
91
101
  data-slot="stat-group"
92
- class={cn('grid gap-3 sm:grid-cols-2 lg:grid-cols-4', local.class)}
102
+ class={cn(
103
+ 'grid gap-3',
104
+ // 9.375rem is 150px at the default root size: room for a label of about
105
+ // twenty characters and a six-digit value before the tile truncates.
106
+ local.fit
107
+ ? 'grid-cols-[repeat(auto-fill,minmax(9.375rem,1fr))]'
108
+ : 'sm:grid-cols-2 lg:grid-cols-4',
109
+ local.class
110
+ )}
93
111
  {...rest}
94
112
  />
95
113
  )
@@ -49,10 +49,26 @@ export function Card(props: CardProps) {
49
49
  )
50
50
  }
51
51
 
52
+ /**
53
+ * The header is a grid so that `CardAction` has tracks to be placed in: the
54
+ * action is a direct child that takes a second column spanning the title and
55
+ * description rows. A flex column gives `col-start-2` nothing to land on and
56
+ * the action would simply stack under the copy. The extra column exists only
57
+ * for a direct-child action: a wrapper around it is then the header's single
58
+ * grid item, so it keeps the full width. A header without an action lays out as
59
+ * it always did (one full-width column, 4px between its children).
60
+ */
52
61
  export function CardHeader(props: ComponentProps<'div'>) {
53
62
  const [local, rest] = splitProps(props, ['class'])
54
63
  return (
55
- <div data-slot="card-header" class={cn('flex flex-col gap-1 px-4', local.class)} {...rest} />
64
+ <div
65
+ data-slot="card-header"
66
+ class={cn(
67
+ 'grid grid-cols-1 auto-rows-min gap-x-4 gap-y-1 px-4 has-[>[data-slot=card-action]]:grid-cols-[minmax(0,1fr)_auto]',
68
+ local.class
69
+ )}
70
+ {...rest}
71
+ />
56
72
  )
57
73
  }
58
74