@elmeragroup/fuse 0.1.0-canary.113 → 0.1.0-canary.115

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/README.md CHANGED
@@ -66,6 +66,8 @@ A `Card` and a `card` Accordion item draw their edge in `--card-border`. Without
66
66
  }
67
67
  ```
68
68
 
69
+ The line between a card's stacked `Card.Section` and `Card.SectionButton` parts is `--card-section-divider`. Without it, it takes your `--border`. External themes draw it in the page tint, `var(--background)`.
70
+
69
71
  A `RadioItem` or `CheckboxItem` row draws its edge in `--selection-border`, and a checked row in `--selection-checked-border`. The line between stacked rows reads `--selection-divider`, and above and below a checked row `--selection-checked-divider`. Without them the row and its dividers take your `--border` and a checked row your `--primary`, as internal themes do. For the external themes' look, where stacked rows keep a grey separator but no outer edge and the control alone shows the selection, set the edge to a transparent colour, point the checked edge at it, and draw both dividers in `--border`. The border keeps its 1px width, so rows join and inset as before, but a row on a `--card`-coloured surface has no outline:
70
72
 
71
73
  ```css
@@ -0,0 +1,23 @@
1
+ import { ReactElement } from "react";
2
+ import { useRender } from "@base-ui/react/use-render";
3
+ //#region src/components/card/card-section-button.d.ts
4
+ export type CardSectionButtonProps = useRender.ComponentProps<"button">;
5
+ /**
6
+ * A whole stacked section of a vertical card as one button, such as "No thanks, continue
7
+ * without" with a trailing caret. It stacks, divides and rounds like a `Card.Section`, and adds
8
+ * a hover fill, a pointer cursor, the state face and a focus ring drawn inside its own edges, so
9
+ * the sections around it cannot cover it. It renders `<button type="button">`, the type
10
+ * `useRender` gives its default button, so it never submits a form it sits in.
11
+ *
12
+ * `render={<a href="/terms" />}` makes it a link, which keeps its link semantics and takes no
13
+ * `type`. A trigger composes it as it composes `Button`:
14
+ * `<Dialog.Trigger render={<Card.SectionButton />}>Change plan</Dialog.Trigger>`. Hold phrasing
15
+ * content only, such as text, an icon and a `Card.SectionMedia`, and no other control. Client
16
+ * only because polymorphism is `useRender`; the rest of the Card compound stays server.
17
+ */
18
+ export declare function CardSectionButton({ className, render, ...props }: CardSectionButtonProps): ReactElement;
19
+ export declare namespace CardSectionButton {
20
+ var displayName: string;
21
+ }
22
+ //#endregion
23
+ //# sourceMappingURL=card-section-button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-section-button.d.ts","names":[],"sources":["../../../src/components/card/card-section-button.tsx"],"mappings":";;;YAWY,yBAAyB,UAAU;;;;;;;;;;;;;;wBAe/B,oBAAoB,WAAW,WAAW,SAAS,yBAAyB;yBAA5E;MAAA"}
@@ -0,0 +1,35 @@
1
+ "use client";
2
+ import { cn } from "../../styles/cn.js";
3
+ import { definedProps } from "../../internal/defined-props.js";
4
+ import { cardSectionVariants } from "./card-variants.js";
5
+ import { mergeProps } from "@base-ui/react/merge-props";
6
+ import { useRender } from "@base-ui/react/use-render";
7
+ //#region src/components/card/card-section-button.tsx
8
+ /**
9
+ * A whole stacked section of a vertical card as one button, such as "No thanks, continue
10
+ * without" with a trailing caret. It stacks, divides and rounds like a `Card.Section`, and adds
11
+ * a hover fill, a pointer cursor, the state face and a focus ring drawn inside its own edges, so
12
+ * the sections around it cannot cover it. It renders `<button type="button">`, the type
13
+ * `useRender` gives its default button, so it never submits a form it sits in.
14
+ *
15
+ * `render={<a href="/terms" />}` makes it a link, which keeps its link semantics and takes no
16
+ * `type`. A trigger composes it as it composes `Button`:
17
+ * `<Dialog.Trigger render={<Card.SectionButton />}>Change plan</Dialog.Trigger>`. Hold phrasing
18
+ * content only, such as text, an icon and a `Card.SectionMedia`, and no other control. Client
19
+ * only because polymorphism is `useRender`; the rest of the Card compound stays server.
20
+ */
21
+ function CardSectionButton({ className, render, ...props }) {
22
+ return useRender({
23
+ defaultTagName: "button",
24
+ props: {
25
+ "data-slot": "card-section-button",
26
+ ...mergeProps({ className: cn(cardSectionVariants().button(), className) }, definedProps(props))
27
+ },
28
+ render
29
+ });
30
+ }
31
+ CardSectionButton.displayName = "Card.SectionButton";
32
+ //#endregion
33
+ export { CardSectionButton };
34
+
35
+ //# sourceMappingURL=card-section-button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-section-button.js","names":[],"sources":["../../../src/components/card/card-section-button.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ReactElement } from \"react\";\n\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\n\nimport { definedProps } from \"../../internal/defined-props\";\nimport { cn } from \"../../styles/cn\";\nimport { cardSectionVariants } from \"./card-variants\";\n\nexport type CardSectionButtonProps = useRender.ComponentProps<\"button\">;\n\n/**\n * A whole stacked section of a vertical card as one button, such as \"No thanks, continue\n * without\" with a trailing caret. It stacks, divides and rounds like a `Card.Section`, and adds\n * a hover fill, a pointer cursor, the state face and a focus ring drawn inside its own edges, so\n * the sections around it cannot cover it. It renders `<button type=\"button\">`, the type\n * `useRender` gives its default button, so it never submits a form it sits in.\n *\n * `render={<a href=\"/terms\" />}` makes it a link, which keeps its link semantics and takes no\n * `type`. A trigger composes it as it composes `Button`:\n * `<Dialog.Trigger render={<Card.SectionButton />}>Change plan</Dialog.Trigger>`. Hold phrasing\n * content only, such as text, an icon and a `Card.SectionMedia`, and no other control. Client\n * only because polymorphism is `useRender`; the rest of the Card compound stays server.\n */\nexport function CardSectionButton({ className, render, ...props }: CardSectionButtonProps): ReactElement {\n return useRender({\n defaultTagName: \"button\",\n props: {\n \"data-slot\": \"card-section-button\",\n // Filtered, as Button filters, so a forwarded `type={undefined}` cannot erase the default\n // button's `type=\"button\"`.\n ...mergeProps<\"button\">(\n { className: cn(cardSectionVariants().button(), className) },\n definedProps(props)\n ),\n },\n render,\n });\n}\n\nCardSectionButton.displayName = \"Card.SectionButton\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,kBAAkB,EAAE,WAAW,QAAQ,GAAG,SAA+C;CACvG,OAAO,UAAU;EACf,gBAAgB;EAChB,OAAO;GACL,aAAa;GAGb,GAAG,WACD,EAAE,WAAW,GAAG,oBAAoB,CAAC,CAAC,OAAO,GAAG,SAAS,EAAE,GAC3D,aAAa,KAAK,CACpB;EACF;EACA;CACF,CAAC;AACH;AAEA,kBAAkB,cAAc"}
@@ -112,6 +112,53 @@ export declare const cardVariants: import("tailwind-variants").TVReturnType<{
112
112
  cardContent: string;
113
113
  cardFooter: string;
114
114
  }>>;
115
+ /**
116
+ * Module-private recipe for the stacked section parts, kept off the public `cardVariants`.
117
+ * `section` is the static `Card.Section` and `button` the interactive `Card.SectionButton`; both
118
+ * take the stacked shell, and a `Card.SectionMedia` child makes either a two-column grid.
119
+ * Fuse ships no preflight, so `button` resets a native button's face, font and alignment itself.
120
+ * The typed `*-[…:inherit]` font utilities, as on Button's `icon-inline`, let tailwind-merge
121
+ * replace them with a consumer's `text-*`, `font-*` or `leading-*` class. The button takes Item's
122
+ * anchor hover fill, a pointer cursor, the state face and the self focus ring drawn inset, which
123
+ * the sections around it cannot paint over.
124
+ */
125
+ export declare const cardSectionVariants: import("tailwind-variants").TVReturnType<{
126
+ [key: string]: {
127
+ [key: string]: {
128
+ button?: import("tailwind-variants").ClassValue;
129
+ media?: import("tailwind-variants").ClassValue;
130
+ section?: import("tailwind-variants").ClassValue;
131
+ } | import("tailwind-variants").ClassValue;
132
+ };
133
+ } | {
134
+ [x: string]: {
135
+ [x: string]: {
136
+ button?: import("tailwind-variants").ClassValue;
137
+ media?: import("tailwind-variants").ClassValue;
138
+ section?: import("tailwind-variants").ClassValue;
139
+ } | import("tailwind-variants").ClassValue;
140
+ };
141
+ } | {}, {
142
+ section: string[];
143
+ button: string[];
144
+ media: string;
145
+ }, undefined, {
146
+ [key: string]: {
147
+ [key: string]: {
148
+ button?: import("tailwind-variants").ClassValue;
149
+ media?: import("tailwind-variants").ClassValue;
150
+ section?: import("tailwind-variants").ClassValue;
151
+ } | import("tailwind-variants").ClassValue;
152
+ };
153
+ } | {}, {
154
+ section: string[];
155
+ button: string[];
156
+ media: string;
157
+ }, import("tailwind-variants").TVReturnTypeLike<unknown, {
158
+ section: string[];
159
+ button: string[];
160
+ media: string;
161
+ }>>;
115
162
  /**
116
163
  * Module-private type-scale recipes for `Card.Title` / `Card.Description`.
117
164
  * Not exported from `@elmeragroup/fuse/card` — there is no borrow
@@ -1 +1 @@
1
- {"version":3,"file":"card-variants.d.ts","names":[],"sources":["../../../src/components/card/card-variants.ts"],"mappings":";;;;;;;;;;;;;;;;;qBAyBa,0CAAY;;IAcnB;MACE;MACA;MACA;;IAEF;MACE;MAIA;MACA;MACA;MACA;;;;IAIF;MAAW;;IACX;MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAiBC,+CAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAmBjB,qDAAuB"}
1
+ {"version":3,"file":"card-variants.d.ts","names":[],"sources":["../../../src/components/card/card-variants.ts"],"mappings":";;;;;;;;;;;;;;;;;qBA6Ba,0CAAY;;IAcnB;MACE;MAGA;MACA;;IAEF;MACE;MAIA;MACA;MACA;MACA;;;;IAIF;MAAW;;IACX;MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAwBC,iDAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA0BnB,+CAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAmBjB,qDAAuB"}
@@ -1,5 +1,8 @@
1
+ import { cn } from "../../styles/cn.js";
1
2
  import { tv } from "../../styles/tv.js";
2
- import { cardDefaultTierClass, cardHorizontalShellClass, cardLargeTierClass, cardSectionShellClass, cardShellClass } from "../../styles/inner-corner/card.js";
3
+ import { selfFocusRingClass } from "../../styles/utils.js";
4
+ import { nativeStateFaceClass } from "../../styles/state-face.js";
5
+ import { cardDefaultTierClass, cardHorizontalShellClass, cardLargeTierClass, cardSectionShellClass, cardShellClass, cardStackedSectionShellClass } from "../../styles/inner-corner/card.js";
3
6
  //#region src/components/card/card-variants.ts
4
7
  /**
5
8
  * PUBLIC slot recipe. `text-field`'s `card` variant and
@@ -32,7 +35,11 @@ const cardVariants = tv({
32
35
  direction: {
33
36
  vertical: {
34
37
  cardHeader: cardSectionShellClass,
35
- cardContent: [cardSectionShellClass, "not-first:pt-0"],
38
+ cardContent: [
39
+ cardSectionShellClass,
40
+ "not-first:pt-0",
41
+ "[:where([data-slot=card-section])>&]:p-0"
42
+ ],
36
43
  cardFooter: [cardSectionShellClass, "not-first:pt-0"]
37
44
  },
38
45
  horizontal: {
@@ -53,6 +60,29 @@ const cardVariants = tv({
53
60
  size: "default"
54
61
  }
55
62
  });
63
+ const sectionMediaGridClass = cn("has-[>[data-slot=card-section-media]]:grid has-[>[data-slot=card-section-media]]:grid-cols-[auto_minmax(0,1fr)] has-[>[data-slot=card-section-media]]:items-center has-[>[data-slot=card-section-media]]:gap-x-(--surface-gap-md)");
64
+ /**
65
+ * Module-private recipe for the stacked section parts, kept off the public `cardVariants`.
66
+ * `section` is the static `Card.Section` and `button` the interactive `Card.SectionButton`; both
67
+ * take the stacked shell, and a `Card.SectionMedia` child makes either a two-column grid.
68
+ * Fuse ships no preflight, so `button` resets a native button's face, font and alignment itself.
69
+ * The typed `*-[…:inherit]` font utilities, as on Button's `icon-inline`, let tailwind-merge
70
+ * replace them with a consumer's `text-*`, `font-*` or `leading-*` class. The button takes Item's
71
+ * anchor hover fill, a pointer cursor, the state face and the self focus ring drawn inset, which
72
+ * the sections around it cannot paint over.
73
+ */
74
+ const cardSectionVariants = tv({ slots: {
75
+ section: [cardStackedSectionShellClass, sectionMediaGridClass],
76
+ button: [
77
+ cardStackedSectionShellClass,
78
+ sectionMediaGridClass,
79
+ "box-border block w-full cursor-pointer bg-transparent text-start text-inherit no-underline transition-colors duration-100 enabled-hover:bg-muted",
80
+ "font-[family-name:inherit] text-[length:inherit] leading-[inherit] font-[weight:inherit]",
81
+ cn(selfFocusRingClass, "focus-visible:ring-inset"),
82
+ nativeStateFaceClass
83
+ ],
84
+ media: "flex shrink-0 items-center justify-center [&>svg]:size-5 [&[hidden]:not([hidden=until-found])]:hidden"
85
+ } });
56
86
  /**
57
87
  * Module-private type-scale recipes for `Card.Title` / `Card.Description`.
58
88
  * Not exported from `@elmeragroup/fuse/card` — there is no borrow
@@ -87,6 +117,6 @@ const cardDescriptionVariants = tv({
87
117
  defaultVariants: { size: "sm" }
88
118
  });
89
119
  //#endregion
90
- export { cardDescriptionVariants, cardTitleVariants, cardVariants };
120
+ export { cardDescriptionVariants, cardSectionVariants, cardTitleVariants, cardVariants };
91
121
 
92
122
  //# sourceMappingURL=card-variants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"card-variants.js","names":[],"sources":["../../../src/components/card/card-variants.ts"],"sourcesContent":["import {\n cardDefaultTierClass,\n cardHorizontalShellClass,\n cardLargeTierClass,\n cardSectionShellClass,\n cardShellClass,\n} from \"../../styles/inner-corner/card\";\nimport { tv } from \"../../styles/tv\";\n\n/**\n * PUBLIC slot recipe. `text-field`'s `card` variant and\n * `CheckboxCard` compose it, so it ships from `@elmeragroup/fuse/card`.\n * The base draws its edge in `--card-border`, which external themes make transparent; both\n * composers pin `border-border` over it, since a field box and a control keep a visible edge.\n * Horizontal cards keep their header text in a grid and wrap whole sections when\n * the container cannot fit them side by side.\n * The external ref's surface/padding axes are decomposed away into `direction` and `size`.\n * `size` sets the card's surface tier on the base as `--card-pad`: the medium tier,\n * `--surface-pad-md`, by default and the large tier, `--surface-pad-lg`, at `lg`. Sections pad\n * with it, and a content or footer below another section drops its top padding, so the tier is\n * also the gap between sections. A content or footer that opens the card keeps it. A horizontal\n * card pads and gaps its sections with the same tier.\n * The title is `leading-snug` in both directions, as `Heading` and `Item.Title` are, so a title\n * that wraps keeps space between its lines.\n */\nexport const cardVariants = tv({\n slots: {\n base: [cardShellClass, \"shadow-xs flex flex-col border-card-border bg-card text-card-foreground\"],\n cardHeader:\n \"@container/card-header grid auto-rows-min items-start gap-1.5 has-data-[slot=card-action]:grid-cols-[1fr_auto]\",\n cardTag: \"text-sm font-semibold text-muted-foreground\",\n cardTitle: \"font-semibold leading-snug\",\n cardDescription: \"text-muted-foreground\",\n cardAction: \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n cardContent: \"\",\n cardFooter: \"flex items-center\",\n },\n variants: {\n direction: {\n vertical: {\n cardHeader: cardSectionShellClass,\n cardContent: [cardSectionShellClass, \"not-first:pt-0\"],\n cardFooter: [cardSectionShellClass, \"not-first:pt-0\"],\n },\n horizontal: {\n base: [\n cardHorizontalShellClass,\n \"flex-row flex-wrap items-start gap-[var(--card-pad,var(--surface-pad-md))]\",\n ],\n cardHeader: \"min-w-0 flex-[2_1_16rem] wrap-anywhere\",\n cardContent: \"min-w-0 flex-[1_1_12rem] wrap-anywhere\",\n cardFooter: \"min-w-0 flex-[1_1_8rem] wrap-anywhere\",\n cardTitle: \"text-xl/snug\",\n },\n },\n size: {\n default: { base: cardDefaultTierClass },\n lg: { base: cardLargeTierClass },\n },\n },\n defaultVariants: {\n direction: \"vertical\",\n size: \"default\",\n },\n});\n\n/**\n * Module-private type-scale recipes for `Card.Title` / `Card.Description`.\n * Not exported from `@elmeragroup/fuse/card` — there is no borrow\n * pattern. Kept off `cardVariants` because `direction=\"horizontal\"` already\n * sets `cardTitle: \"text-xl/snug\"`; a second `size` axis on that slot would fight\n * through twMerge. `size` is a type-scale axis, not a density control-box rung:\n * it does not read `--control-*`.\n */\nexport const cardTitleVariants = tv({\n variants: {\n size: {\n default: \"text-base\",\n sm: \"text-sm\",\n lg: \"text-lg\",\n xl: \"text-xl\",\n \"2xl\": \"text-2xl\",\n \"3xl\": \"text-3xl\",\n \"4xl\": \"text-4xl\",\n \"5xl\": \"text-5xl\",\n \"6xl\": \"text-6xl\",\n },\n },\n defaultVariants: {\n size: \"2xl\",\n },\n});\n\nexport const cardDescriptionVariants = tv({\n variants: {\n size: {\n xs: \"text-xs\",\n sm: \"text-sm\",\n default: \"text-base\",\n lg: \"text-lg\",\n xl: \"text-xl\",\n \"2xl\": \"text-2xl\",\n },\n },\n defaultVariants: {\n size: \"sm\",\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAyBA,MAAa,eAAe,GAAG;CAC7B,OAAO;EACL,MAAM,CAAC,gBAAgB,yEAAyE;EAChG,YACE;EACF,SAAS;EACT,WAAW;EACX,iBAAiB;EACjB,YAAY;EACZ,aAAa;EACb,YAAY;CACd;CACA,UAAU;EACR,WAAW;GACT,UAAU;IACR,YAAY;IACZ,aAAa,CAAC,uBAAuB,gBAAgB;IACrD,YAAY,CAAC,uBAAuB,gBAAgB;GACtD;GACA,YAAY;IACV,MAAM,CACJ,0BACA,4EACF;IACA,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,WAAW;GACb;EACF;EACA,MAAM;GACJ,SAAS,EAAE,MAAM,qBAAqB;GACtC,IAAI,EAAE,MAAM,mBAAmB;EACjC;CACF;CACA,iBAAiB;EACf,WAAW;EACX,MAAM;CACR;AACF,CAAC;;;;;;;;;AAUD,MAAa,oBAAoB,GAAG;CAClC,UAAU,EACR,MAAM;EACJ,SAAS;EACT,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;CACT,EACF;CACA,iBAAiB,EACf,MAAM,MACR;AACF,CAAC;AAED,MAAa,0BAA0B,GAAG;CACxC,UAAU,EACR,MAAM;EACJ,IAAI;EACJ,IAAI;EACJ,SAAS;EACT,IAAI;EACJ,IAAI;EACJ,OAAO;CACT,EACF;CACA,iBAAiB,EACf,MAAM,KACR;AACF,CAAC"}
1
+ {"version":3,"file":"card-variants.js","names":[],"sources":["../../../src/components/card/card-variants.ts"],"sourcesContent":["import { cn } from \"../../styles/cn\";\nimport {\n cardDefaultTierClass,\n cardHorizontalShellClass,\n cardLargeTierClass,\n cardSectionShellClass,\n cardShellClass,\n cardStackedSectionShellClass,\n} from \"../../styles/inner-corner/card\";\nimport { nativeStateFaceClass } from \"../../styles/state-face\";\nimport { tv } from \"../../styles/tv\";\nimport { selfFocusRingClass } from \"../../styles/utils\";\n\n/**\n * PUBLIC slot recipe. `text-field`'s `card` variant and\n * `CheckboxCard` compose it, so it ships from `@elmeragroup/fuse/card`.\n * The base draws its edge in `--card-border`, which external themes make transparent; both\n * composers pin `border-border` over it, since a field box and a control keep a visible edge.\n * Horizontal cards keep their header text in a grid and wrap whole sections when\n * the container cannot fit them side by side.\n * The external ref's surface/padding axes are decomposed away into `direction` and `size`.\n * `size` sets the card's surface tier on the base as `--card-pad`: the medium tier,\n * `--surface-pad-md`, by default and the large tier, `--surface-pad-lg`, at `lg`. Sections pad\n * with it, and a content or footer below another section drops its top padding, so the tier is\n * also the gap between sections. A content or footer that opens the card keeps it. A horizontal\n * card pads and gaps its sections with the same tier.\n * The title is `leading-snug` in both directions, as `Heading` and `Item.Title` are, so a title\n * that wraps keeps space between its lines.\n */\nexport const cardVariants = tv({\n slots: {\n base: [cardShellClass, \"shadow-xs flex flex-col border-card-border bg-card text-card-foreground\"],\n cardHeader:\n \"@container/card-header grid auto-rows-min items-start gap-1.5 has-data-[slot=card-action]:grid-cols-[1fr_auto]\",\n cardTag: \"text-sm font-semibold text-muted-foreground\",\n cardTitle: \"font-semibold leading-snug\",\n cardDescription: \"text-muted-foreground\",\n cardAction: \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n cardContent: \"\",\n cardFooter: \"flex items-center\",\n },\n variants: {\n direction: {\n vertical: {\n cardHeader: cardSectionShellClass,\n // Inside a `Card.Section` the content is the section's column and the section pads, so\n // the content drops its own tier there.\n cardContent: [cardSectionShellClass, \"not-first:pt-0\", \"[:where([data-slot=card-section])>&]:p-0\"],\n cardFooter: [cardSectionShellClass, \"not-first:pt-0\"],\n },\n horizontal: {\n base: [\n cardHorizontalShellClass,\n \"flex-row flex-wrap items-start gap-[var(--card-pad,var(--surface-pad-md))]\",\n ],\n cardHeader: \"min-w-0 flex-[2_1_16rem] wrap-anywhere\",\n cardContent: \"min-w-0 flex-[1_1_12rem] wrap-anywhere\",\n cardFooter: \"min-w-0 flex-[1_1_8rem] wrap-anywhere\",\n cardTitle: \"text-xl/snug\",\n },\n },\n size: {\n default: { base: cardDefaultTierClass },\n lg: { base: cardLargeTierClass },\n },\n },\n defaultVariants: {\n direction: \"vertical\",\n size: \"default\",\n },\n});\n\n// A `Card.SectionMedia` child makes a section a two-column grid, the media centred beside the content.\nconst sectionMediaGridClass = cn(\n \"has-[>[data-slot=card-section-media]]:grid has-[>[data-slot=card-section-media]]:grid-cols-[auto_minmax(0,1fr)] has-[>[data-slot=card-section-media]]:items-center has-[>[data-slot=card-section-media]]:gap-x-(--surface-gap-md)\"\n);\n\n/**\n * Module-private recipe for the stacked section parts, kept off the public `cardVariants`.\n * `section` is the static `Card.Section` and `button` the interactive `Card.SectionButton`; both\n * take the stacked shell, and a `Card.SectionMedia` child makes either a two-column grid.\n * Fuse ships no preflight, so `button` resets a native button's face, font and alignment itself.\n * The typed `*-[…:inherit]` font utilities, as on Button's `icon-inline`, let tailwind-merge\n * replace them with a consumer's `text-*`, `font-*` or `leading-*` class. The button takes Item's\n * anchor hover fill, a pointer cursor, the state face and the self focus ring drawn inset, which\n * the sections around it cannot paint over.\n */\nexport const cardSectionVariants = tv({\n slots: {\n section: [cardStackedSectionShellClass, sectionMediaGridClass],\n button: [\n cardStackedSectionShellClass,\n sectionMediaGridClass,\n \"box-border block w-full cursor-pointer bg-transparent text-start text-inherit no-underline transition-colors duration-100 enabled-hover:bg-muted\",\n \"font-[family-name:inherit] text-[length:inherit] leading-[inherit] font-[weight:inherit]\",\n // oxlint-disable-next-line elmera/no-local-focus-ring -- the shared self ring, drawn inset\n cn(selfFocusRingClass, \"focus-visible:ring-inset\"),\n nativeStateFaceClass,\n ],\n // Without preflight the media's own `flex` beats the user-agent `[hidden]` rule.\n media:\n \"flex shrink-0 items-center justify-center [&>svg]:size-5 [&[hidden]:not([hidden=until-found])]:hidden\",\n },\n});\n\n/**\n * Module-private type-scale recipes for `Card.Title` / `Card.Description`.\n * Not exported from `@elmeragroup/fuse/card` — there is no borrow\n * pattern. Kept off `cardVariants` because `direction=\"horizontal\"` already\n * sets `cardTitle: \"text-xl/snug\"`; a second `size` axis on that slot would fight\n * through twMerge. `size` is a type-scale axis, not a density control-box rung:\n * it does not read `--control-*`.\n */\nexport const cardTitleVariants = tv({\n variants: {\n size: {\n default: \"text-base\",\n sm: \"text-sm\",\n lg: \"text-lg\",\n xl: \"text-xl\",\n \"2xl\": \"text-2xl\",\n \"3xl\": \"text-3xl\",\n \"4xl\": \"text-4xl\",\n \"5xl\": \"text-5xl\",\n \"6xl\": \"text-6xl\",\n },\n },\n defaultVariants: {\n size: \"2xl\",\n },\n});\n\nexport const cardDescriptionVariants = tv({\n variants: {\n size: {\n xs: \"text-xs\",\n sm: \"text-sm\",\n default: \"text-base\",\n lg: \"text-lg\",\n xl: \"text-xl\",\n \"2xl\": \"text-2xl\",\n },\n },\n defaultVariants: {\n size: \"sm\",\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA6BA,MAAa,eAAe,GAAG;CAC7B,OAAO;EACL,MAAM,CAAC,gBAAgB,yEAAyE;EAChG,YACE;EACF,SAAS;EACT,WAAW;EACX,iBAAiB;EACjB,YAAY;EACZ,aAAa;EACb,YAAY;CACd;CACA,UAAU;EACR,WAAW;GACT,UAAU;IACR,YAAY;IAGZ,aAAa;KAAC;KAAuB;KAAkB;IAA0C;IACjG,YAAY,CAAC,uBAAuB,gBAAgB;GACtD;GACA,YAAY;IACV,MAAM,CACJ,0BACA,4EACF;IACA,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,WAAW;GACb;EACF;EACA,MAAM;GACJ,SAAS,EAAE,MAAM,qBAAqB;GACtC,IAAI,EAAE,MAAM,mBAAmB;EACjC;CACF;CACA,iBAAiB;EACf,WAAW;EACX,MAAM;CACR;AACF,CAAC;AAGD,MAAM,wBAAwB,GAC5B,mOACF;;;;;;;;;;;AAYA,MAAa,sBAAsB,GAAG,EACpC,OAAO;CACL,SAAS,CAAC,8BAA8B,qBAAqB;CAC7D,QAAQ;EACN;EACA;EACA;EACA;EAEA,GAAG,oBAAoB,0BAA0B;EACjD;CACF;CAEA,OACE;AACJ,EACF,CAAC;;;;;;;;;AAUD,MAAa,oBAAoB,GAAG;CAClC,UAAU,EACR,MAAM;EACJ,SAAS;EACT,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;CACT,EACF;CACA,iBAAiB,EACf,MAAM,MACR;AACF,CAAC;AAED,MAAa,0BAA0B,GAAG;CACxC,UAAU,EACR,MAAM;EACJ,IAAI;EACJ,IAAI;EACJ,SAAS;EACT,IAAI;EACJ,IAAI;EACJ,OAAO;CACT,EACF;CACA,iBAAiB,EACf,MAAM,KACR;AACF,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { CardSectionButton } from "./card-section-button.js";
1
2
  import { cardDescriptionVariants, cardTitleVariants, cardVariants } from "./card-variants.js";
2
3
  import { HTMLAttributes, ReactElement, ReactNode } from "react";
3
4
  import { VariantProps } from "tailwind-variants";
@@ -46,8 +47,29 @@ declare function CardTag({ className, direction, ...props }: CardDivProps): Reac
46
47
  declare function CardTitle({ children, className, direction, level, size, icon, ...props }: CardTitleProps): ReactElement;
47
48
  declare function CardDescription({ className, direction, size, ...props }: CardDescriptionProps): ReactElement;
48
49
  declare function CardAction({ className, direction, ...props }: CardDivProps): ReactElement;
50
+ /**
51
+ * A card's body. Inside a `Card.Section` it is the section's content column, beside a
52
+ * `Card.SectionMedia`, and drops its own padding, since the section pads.
53
+ */
49
54
  declare function CardContent({ className, direction, ...props }: CardDivProps): ReactElement;
50
55
  declare function CardFooter({ className, direction, ...props }: CardDivProps): ReactElement;
56
+ /**
57
+ * One of a vertical card's stacked sections of equal weight. Sections form the card's body under
58
+ * one optional `Card.Header`: a `Card.Content` or `Card.Footer` beside them takes no divider, so
59
+ * put that content in a section instead. A section pads every side with the card's tier, a 1px
60
+ * `--card-section-divider` line separates it from the part above, and the first and last
61
+ * sections round with the card's corners. A `Card.SectionMedia` as its first child makes it a
62
+ * two-column grid with the media centred beside a `Card.Content`, the unpadded content column.
63
+ * A horizontal card pads itself, so sections take no `direction` and belong in a vertical card.
64
+ * A whole section that acts is a `Card.SectionButton`.
65
+ */
66
+ declare function CardSection({ className, ...props }: HTMLAttributes<HTMLDivElement>): ReactElement;
67
+ /**
68
+ * The icon column of a `Card.Section` or `Card.SectionButton`. The section becomes a two-column
69
+ * grid, this column and the content, with the icon centred on the section's height. An `svg` is
70
+ * sized to `5`. It is a `span`, so it is phrasing content inside a section button.
71
+ */
72
+ declare function CardSectionMedia({ className, ...props }: HTMLAttributes<HTMLSpanElement>): ReactElement;
51
73
  export declare const Card: {
52
74
  Root: typeof CardRoot;
53
75
  Header: typeof CardHeader;
@@ -57,6 +79,9 @@ export declare const Card: {
57
79
  Action: typeof CardAction;
58
80
  Content: typeof CardContent;
59
81
  Footer: typeof CardFooter;
82
+ Section: typeof CardSection;
83
+ SectionButton: typeof CardSectionButton;
84
+ SectionMedia: typeof CardSectionMedia;
60
85
  };
61
86
  //#endregion
62
87
  //# sourceMappingURL=card.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"card.d.ts","names":[],"sources":["../../../src/components/card/card.tsx"],"mappings":";;;;KASK,mBAAmB,KAAK,oBAAoB;KAE5C,eAAe,eAAe,kBAAkB;KAEhD,gBAAgB;;;;;;;EAOnB,oBAAoB,aAAa,SAAS;;KAGvC;KAEA,iBAAiB,eAAe,sBACnC;;;;;EAKE,QAAQ;;EAER,OAAO,YAAY,oBAAoB;;;;;EAKvC,OAAO;;KAGN,uBAAuB,eAAe,wBACzC;;EAEE,OAAO,YAAY,oBAAoB;;;;;;;;;;iBAWlC,WAAW,WAAW,WAAW,SAAqB,SAAS,gBAAgB;iBAc/E,aAAa,WAAW,cAAc,SAAS,eAAe;iBAa9D,UAAU,WAAW,cAAc,SAAS,eAAe;iBAM3D,YACP,UACA,WACA,WACA,OACA,MACA,SACG,SACF,iBAAiB;iBAuBX,kBACP,WACA,WACA,SACG,SACF,uBAAuB;iBAYjB,aAAa,WAAW,cAAc,SAAS,eAAe;iBAM9D,cAAc,WAAW,cAAc,SAAS,eAAe;iBAa/D,aAAa,WAAW,cAAc,SAAS,eAAe;qBAsB1D;EACX,aAAI;EACJ,eAAM;EACN,YAAG;EACH,cAAK;EACL,oBAAW;EACX,eAAM;EACN,gBAAO;EACP,eAAM"}
1
+ {"version":3,"file":"card.d.ts","names":[],"sources":["../../../src/components/card/card.tsx"],"mappings":";;;;;KAeK,mBAAmB,KAAK,oBAAoB;KAE5C,eAAe,eAAe,kBAAkB;KAEhD,gBAAgB;;;;;;;EAOnB,oBAAoB,aAAa,SAAS;;KAGvC;KAEA,iBAAiB,eAAe,sBACnC;;;;;EAKE,QAAQ;;EAER,OAAO,YAAY,oBAAoB;;;;;EAKvC,OAAO;;KAGN,uBAAuB,eAAe,wBACzC;;EAEE,OAAO,YAAY,oBAAoB;;;;;;;;;;iBAWlC,WAAW,WAAW,WAAW,SAAqB,SAAS,gBAAgB;iBAc/E,aAAa,WAAW,cAAc,SAAS,eAAe;iBAa9D,UAAU,WAAW,cAAc,SAAS,eAAe;iBAM3D,YACP,UACA,WACA,WACA,OACA,MACA,SACG,SACF,iBAAiB;iBAuBX,kBACP,WACA,WACA,SACG,SACF,uBAAuB;iBAYjB,aAAa,WAAW,cAAc,SAAS,eAAe;;;;;iBAU9D,cAAc,WAAW,cAAc,SAAS,eAAe;iBAa/D,aAAa,WAAW,cAAc,SAAS,eAAe;;;;;;;;;;;iBAuB9D,cAAc,cAAc,SAAS,eAAe,kBAAkB;;;;;;iBAWtE,mBAAmB,cAAc,SAAS,eAAe,mBAAmB;qBAiBxE;EACX,aAAI;EACJ,eAAM;EACN,YAAG;EACH,cAAK;EACL,oBAAW;EACX,eAAM;EACN,gBAAO;EACP,eAAM;EACN,gBAAO;EACP,sBAAa;EACb,qBAAY"}
@@ -1,5 +1,6 @@
1
1
  import { cn } from "../../styles/cn.js";
2
- import { cardDescriptionVariants, cardTitleVariants, cardVariants } from "./card-variants.js";
2
+ import { cardDescriptionVariants, cardSectionVariants, cardTitleVariants, cardVariants } from "./card-variants.js";
3
+ import { CardSectionButton } from "./card-section-button.js";
3
4
  import { jsx, jsxs } from "react/jsx-runtime";
4
5
  //#region src/components/card/card.tsx
5
6
  /**
@@ -66,6 +67,10 @@ function CardAction({ className, direction, ...props }) {
66
67
  ...props
67
68
  });
68
69
  }
70
+ /**
71
+ * A card's body. Inside a `Card.Section` it is the section's content column, beside a
72
+ * `Card.SectionMedia`, and drops its own padding, since the section pads.
73
+ */
69
74
  function CardContent({ className, direction, ...props }) {
70
75
  const { cardContent } = cardVariants({ direction });
71
76
  return /* @__PURE__ */ jsx("div", {
@@ -84,6 +89,37 @@ function CardFooter({ className, direction, ...props }) {
84
89
  ...props
85
90
  });
86
91
  }
92
+ /**
93
+ * One of a vertical card's stacked sections of equal weight. Sections form the card's body under
94
+ * one optional `Card.Header`: a `Card.Content` or `Card.Footer` beside them takes no divider, so
95
+ * put that content in a section instead. A section pads every side with the card's tier, a 1px
96
+ * `--card-section-divider` line separates it from the part above, and the first and last
97
+ * sections round with the card's corners. A `Card.SectionMedia` as its first child makes it a
98
+ * two-column grid with the media centred beside a `Card.Content`, the unpadded content column.
99
+ * A horizontal card pads itself, so sections take no `direction` and belong in a vertical card.
100
+ * A whole section that acts is a `Card.SectionButton`.
101
+ */
102
+ function CardSection({ className, ...props }) {
103
+ const { section } = cardSectionVariants();
104
+ return /* @__PURE__ */ jsx("div", {
105
+ "data-slot": "card-section",
106
+ className: cn(section(), className),
107
+ ...props
108
+ });
109
+ }
110
+ /**
111
+ * The icon column of a `Card.Section` or `Card.SectionButton`. The section becomes a two-column
112
+ * grid, this column and the content, with the icon centred on the section's height. An `svg` is
113
+ * sized to `5`. It is a `span`, so it is phrasing content inside a section button.
114
+ */
115
+ function CardSectionMedia({ className, ...props }) {
116
+ const { media } = cardSectionVariants();
117
+ return /* @__PURE__ */ jsx("span", {
118
+ "data-slot": "card-section-media",
119
+ className: cn(media(), className),
120
+ ...props
121
+ });
122
+ }
87
123
  CardRoot.displayName = "Card.Root";
88
124
  CardHeader.displayName = "Card.Header";
89
125
  CardTag.displayName = "Card.Tag";
@@ -92,6 +128,8 @@ CardDescription.displayName = "Card.Description";
92
128
  CardAction.displayName = "Card.Action";
93
129
  CardContent.displayName = "Card.Content";
94
130
  CardFooter.displayName = "Card.Footer";
131
+ CardSection.displayName = "Card.Section";
132
+ CardSectionMedia.displayName = "Card.SectionMedia";
95
133
  const Card = {
96
134
  Root: CardRoot,
97
135
  Header: CardHeader,
@@ -100,7 +138,10 @@ const Card = {
100
138
  Description: CardDescription,
101
139
  Action: CardAction,
102
140
  Content: CardContent,
103
- Footer: CardFooter
141
+ Footer: CardFooter,
142
+ Section: CardSection,
143
+ SectionButton: CardSectionButton,
144
+ SectionMedia: CardSectionMedia
104
145
  };
105
146
  //#endregion
106
147
  export { Card };
@@ -1 +1 @@
1
- {"version":3,"file":"card.js","names":[],"sources":["../../../src/components/card/card.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactElement, ReactNode } from \"react\";\n\nimport type { VariantProps } from \"tailwind-variants\";\n\nimport { cn } from \"../../styles/cn\";\nimport { cardDescriptionVariants, cardTitleVariants, cardVariants } from \"./card-variants\";\n\n// Every part takes `direction`; only the root takes the card's `size`, so the typography `size`\n// of `Card.Title` and `Card.Description` stays their own.\ntype CardVariantProps = Pick<VariantProps<typeof cardVariants>, \"direction\">;\n\ntype CardDivProps = HTMLAttributes<HTMLDivElement> & CardVariantProps;\n\ntype CardRootProps = CardDivProps & {\n /**\n * The card's surface tier, which pads its sections, gaps them and sets their inner corner.\n * `default` takes the medium tier, `--surface-pad-md`, which Items and Accordion items pad with\n * too, so the card's text starts on their edge. `lg` takes the large\n * tier, `--surface-pad-lg`, for a card that holds long prose or acts as a page's main panel.\n */\n size?: keyof typeof cardVariants.variants.size;\n};\n\ntype CardTitleLevel = 1 | 2 | 3 | 4 | 5 | 6;\n\ntype CardTitleProps = HTMLAttributes<HTMLHeadingElement> &\n CardVariantProps & {\n /**\n * Heading element level — `1`–`6` picks the rendered `h1`–`h6`. Defaults to `3`, so\n * a card titles itself without assuming its place in the document outline.\n */\n level?: CardTitleLevel;\n /** Typography size for the title, mapped to a `text-{size}` class. Defaults to `2xl`. */\n size?: NonNullable<VariantProps<typeof cardTitleVariants>[\"size\"]>;\n /**\n * Rendered before `children` — the title becomes a flex row (`items-center gap-x-1.5`)\n * and any `svg` is sized to `5`.\n */\n icon?: ReactNode;\n };\n\ntype CardDescriptionProps = HTMLAttributes<HTMLParagraphElement> &\n CardVariantProps & {\n /** Typography size for the description, mapped to a `text-{size}` class. Defaults to `sm`. */\n size?: NonNullable<VariantProps<typeof cardDescriptionVariants>[\"size\"]>;\n };\n\n/**\n * The Card surface. It publishes `--inner-corner`, its corner less its border, and its header,\n * content and footer publish it less their padding too. The root and its sections write their\n * `direction` as `data-direction`: a vertical card pads its sections, a horizontal one pads itself.\n * The root writes its `size` as `data-size` and publishes its tier to the sections it holds.\n * Its 1px edge is the theme's `--card-border`: `--border` in internal themes and a zero-alpha\n * colour in external ones. A border colour class still wins.\n */\nfunction CardRoot({ className, direction, size = \"default\", ...props }: CardRootProps): ReactElement {\n const { base } = cardVariants({ direction, size });\n\n return (\n <div\n data-slot=\"card\"\n data-direction={direction ?? \"vertical\"}\n data-size={size}\n className={cn(base(), className)}\n {...props}\n />\n );\n}\n\nfunction CardHeader({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardHeader } = cardVariants({ direction });\n\n return (\n <div\n data-slot=\"card-header\"\n data-direction={direction ?? \"vertical\"}\n className={cn(cardHeader(), className)}\n {...props}\n />\n );\n}\n\nfunction CardTag({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardTag } = cardVariants({ direction });\n\n return <div data-slot=\"card-tag\" className={cn(cardTag(), className)} {...props} />;\n}\n\nfunction CardTitle({\n children,\n className,\n direction,\n level = 3,\n size = \"2xl\",\n icon,\n ...props\n}: CardTitleProps): ReactElement {\n const { cardTitle } = cardVariants({ direction });\n const Heading = `h${level}` as const;\n\n return (\n <Heading\n data-slot=\"card-title\"\n className={cn(\n cardTitleVariants({ size }),\n cardTitle({\n // `direction=\"horizontal\"` pins `text-xl/snug` here, so the size class must come first,\n // and the slot's leading must follow it: a font size drops a line height before it.\n className: icon ? \"flex items-center gap-x-1.5 [&>svg]:size-5\" : undefined,\n }),\n className\n )}\n {...props}>\n {icon ?? null}\n {children}\n </Heading>\n );\n}\n\nfunction CardDescription({\n className,\n direction,\n size = \"sm\",\n ...props\n}: CardDescriptionProps): ReactElement {\n const { cardDescription } = cardVariants({ direction });\n\n return (\n <p\n data-slot=\"card-description\"\n className={cn(cardDescriptionVariants({ size }), cardDescription(), className)}\n {...props}\n />\n );\n}\n\nfunction CardAction({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardAction } = cardVariants({ direction });\n\n return <div data-slot=\"card-action\" className={cn(cardAction(), className)} {...props} />;\n}\n\nfunction CardContent({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardContent } = cardVariants({ direction });\n\n return (\n <div\n data-slot=\"card-content\"\n data-direction={direction ?? \"vertical\"}\n className={cn(cardContent(), className)}\n {...props}\n />\n );\n}\n\nfunction CardFooter({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardFooter } = cardVariants({ direction });\n\n return (\n <div\n data-slot=\"card-footer\"\n data-direction={direction ?? \"vertical\"}\n className={cn(cardFooter(), className)}\n {...props}\n />\n );\n}\n\nCardRoot.displayName = \"Card.Root\";\nCardHeader.displayName = \"Card.Header\";\nCardTag.displayName = \"Card.Tag\";\nCardTitle.displayName = \"Card.Title\";\nCardDescription.displayName = \"Card.Description\";\nCardAction.displayName = \"Card.Action\";\nCardContent.displayName = \"Card.Content\";\nCardFooter.displayName = \"Card.Footer\";\n\nexport const Card = {\n Root: CardRoot,\n Header: CardHeader,\n Tag: CardTag,\n Title: CardTitle,\n Description: CardDescription,\n Action: CardAction,\n Content: CardContent,\n Footer: CardFooter,\n};\n"],"mappings":";;;;;;;;;;;;AAuDA,SAAS,SAAS,EAAE,WAAW,WAAW,OAAO,WAAW,GAAG,SAAsC;CACnG,MAAM,EAAE,SAAS,aAAa;EAAE;EAAW;CAAK,CAAC;CAEjD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,kBAAgB,aAAa;EAC7B,aAAW;EACX,WAAW,GAAG,KAAK,GAAG,SAAS;EAC/B,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,WAAW,GAAG,SAAqC;CAClF,MAAM,EAAE,eAAe,aAAa,EAAE,UAAU,CAAC;CAEjD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,kBAAgB,aAAa;EAC7B,WAAW,GAAG,WAAW,GAAG,SAAS;EACrC,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,QAAQ,EAAE,WAAW,WAAW,GAAG,SAAqC;CAC/E,MAAM,EAAE,YAAY,aAAa,EAAE,UAAU,CAAC;CAE9C,OAAO,oBAAC,OAAD;EAAK,aAAU;EAAW,WAAW,GAAG,QAAQ,GAAG,SAAS;EAAG,GAAI;CAAQ,CAAA;AACpF;AAEA,SAAS,UAAU,EACjB,UACA,WACA,WACA,QAAQ,GACR,OAAO,OACP,MACA,GAAG,SAC4B;CAC/B,MAAM,EAAE,cAAc,aAAa,EAAE,UAAU,CAAC;CAChD,MAAM,UAAU,IAAI;CAEpB,OACE,qBAAC,SAAD;EACE,aAAU;EACV,WAAW,GACT,kBAAkB,EAAE,KAAK,CAAC,GAC1B,UAAU,EAGR,WAAW,OAAO,+CAA+C,KAAA,EACnE,CAAC,GACD,SACF;EACA,GAAI;EAXN,UAAA,CAYG,QAAQ,MACR,QACM;;AAEb;AAEA,SAAS,gBAAgB,EACvB,WACA,WACA,OAAO,MACP,GAAG,SACkC;CACrC,MAAM,EAAE,oBAAoB,aAAa,EAAE,UAAU,CAAC;CAEtD,OACE,oBAAC,KAAD;EACE,aAAU;EACV,WAAW,GAAG,wBAAwB,EAAE,KAAK,CAAC,GAAG,gBAAgB,GAAG,SAAS;EAC7E,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,WAAW,GAAG,SAAqC;CAClF,MAAM,EAAE,eAAe,aAAa,EAAE,UAAU,CAAC;CAEjD,OAAO,oBAAC,OAAD;EAAK,aAAU;EAAc,WAAW,GAAG,WAAW,GAAG,SAAS;EAAG,GAAI;CAAQ,CAAA;AAC1F;AAEA,SAAS,YAAY,EAAE,WAAW,WAAW,GAAG,SAAqC;CACnF,MAAM,EAAE,gBAAgB,aAAa,EAAE,UAAU,CAAC;CAElD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,kBAAgB,aAAa;EAC7B,WAAW,GAAG,YAAY,GAAG,SAAS;EACtC,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,WAAW,GAAG,SAAqC;CAClF,MAAM,EAAE,eAAe,aAAa,EAAE,UAAU,CAAC;CAEjD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,kBAAgB,aAAa;EAC7B,WAAW,GAAG,WAAW,GAAG,SAAS;EACrC,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,cAAc;AACvB,WAAW,cAAc;AACzB,QAAQ,cAAc;AACtB,UAAU,cAAc;AACxB,gBAAgB,cAAc;AAC9B,WAAW,cAAc;AACzB,YAAY,cAAc;AAC1B,WAAW,cAAc;AAEzB,MAAa,OAAO;CAClB,MAAM;CACN,QAAQ;CACR,KAAK;CACL,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS;CACT,QAAQ;AACV"}
1
+ {"version":3,"file":"card.js","names":[],"sources":["../../../src/components/card/card.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactElement, ReactNode } from \"react\";\n\nimport type { VariantProps } from \"tailwind-variants\";\n\nimport { cn } from \"../../styles/cn\";\nimport { CardSectionButton } from \"./card-section-button\";\nimport {\n cardDescriptionVariants,\n cardSectionVariants,\n cardTitleVariants,\n cardVariants,\n} from \"./card-variants\";\n\n// Every part takes `direction`; only the root takes the card's `size`, so the typography `size`\n// of `Card.Title` and `Card.Description` stays their own.\ntype CardVariantProps = Pick<VariantProps<typeof cardVariants>, \"direction\">;\n\ntype CardDivProps = HTMLAttributes<HTMLDivElement> & CardVariantProps;\n\ntype CardRootProps = CardDivProps & {\n /**\n * The card's surface tier, which pads its sections, gaps them and sets their inner corner.\n * `default` takes the medium tier, `--surface-pad-md`, which Items and Accordion items pad with\n * too, so the card's text starts on their edge. `lg` takes the large\n * tier, `--surface-pad-lg`, for a card that holds long prose or acts as a page's main panel.\n */\n size?: keyof typeof cardVariants.variants.size;\n};\n\ntype CardTitleLevel = 1 | 2 | 3 | 4 | 5 | 6;\n\ntype CardTitleProps = HTMLAttributes<HTMLHeadingElement> &\n CardVariantProps & {\n /**\n * Heading element level — `1`–`6` picks the rendered `h1`–`h6`. Defaults to `3`, so\n * a card titles itself without assuming its place in the document outline.\n */\n level?: CardTitleLevel;\n /** Typography size for the title, mapped to a `text-{size}` class. Defaults to `2xl`. */\n size?: NonNullable<VariantProps<typeof cardTitleVariants>[\"size\"]>;\n /**\n * Rendered before `children` — the title becomes a flex row (`items-center gap-x-1.5`)\n * and any `svg` is sized to `5`.\n */\n icon?: ReactNode;\n };\n\ntype CardDescriptionProps = HTMLAttributes<HTMLParagraphElement> &\n CardVariantProps & {\n /** Typography size for the description, mapped to a `text-{size}` class. Defaults to `sm`. */\n size?: NonNullable<VariantProps<typeof cardDescriptionVariants>[\"size\"]>;\n };\n\n/**\n * The Card surface. It publishes `--inner-corner`, its corner less its border, and its header,\n * content and footer publish it less their padding too. The root and its sections write their\n * `direction` as `data-direction`: a vertical card pads its sections, a horizontal one pads itself.\n * The root writes its `size` as `data-size` and publishes its tier to the sections it holds.\n * Its 1px edge is the theme's `--card-border`: `--border` in internal themes and a zero-alpha\n * colour in external ones. A border colour class still wins.\n */\nfunction CardRoot({ className, direction, size = \"default\", ...props }: CardRootProps): ReactElement {\n const { base } = cardVariants({ direction, size });\n\n return (\n <div\n data-slot=\"card\"\n data-direction={direction ?? \"vertical\"}\n data-size={size}\n className={cn(base(), className)}\n {...props}\n />\n );\n}\n\nfunction CardHeader({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardHeader } = cardVariants({ direction });\n\n return (\n <div\n data-slot=\"card-header\"\n data-direction={direction ?? \"vertical\"}\n className={cn(cardHeader(), className)}\n {...props}\n />\n );\n}\n\nfunction CardTag({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardTag } = cardVariants({ direction });\n\n return <div data-slot=\"card-tag\" className={cn(cardTag(), className)} {...props} />;\n}\n\nfunction CardTitle({\n children,\n className,\n direction,\n level = 3,\n size = \"2xl\",\n icon,\n ...props\n}: CardTitleProps): ReactElement {\n const { cardTitle } = cardVariants({ direction });\n const Heading = `h${level}` as const;\n\n return (\n <Heading\n data-slot=\"card-title\"\n className={cn(\n cardTitleVariants({ size }),\n cardTitle({\n // `direction=\"horizontal\"` pins `text-xl/snug` here, so the size class must come first,\n // and the slot's leading must follow it: a font size drops a line height before it.\n className: icon ? \"flex items-center gap-x-1.5 [&>svg]:size-5\" : undefined,\n }),\n className\n )}\n {...props}>\n {icon ?? null}\n {children}\n </Heading>\n );\n}\n\nfunction CardDescription({\n className,\n direction,\n size = \"sm\",\n ...props\n}: CardDescriptionProps): ReactElement {\n const { cardDescription } = cardVariants({ direction });\n\n return (\n <p\n data-slot=\"card-description\"\n className={cn(cardDescriptionVariants({ size }), cardDescription(), className)}\n {...props}\n />\n );\n}\n\nfunction CardAction({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardAction } = cardVariants({ direction });\n\n return <div data-slot=\"card-action\" className={cn(cardAction(), className)} {...props} />;\n}\n\n/**\n * A card's body. Inside a `Card.Section` it is the section's content column, beside a\n * `Card.SectionMedia`, and drops its own padding, since the section pads.\n */\nfunction CardContent({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardContent } = cardVariants({ direction });\n\n return (\n <div\n data-slot=\"card-content\"\n data-direction={direction ?? \"vertical\"}\n className={cn(cardContent(), className)}\n {...props}\n />\n );\n}\n\nfunction CardFooter({ className, direction, ...props }: CardDivProps): ReactElement {\n const { cardFooter } = cardVariants({ direction });\n\n return (\n <div\n data-slot=\"card-footer\"\n data-direction={direction ?? \"vertical\"}\n className={cn(cardFooter(), className)}\n {...props}\n />\n );\n}\n\n/**\n * One of a vertical card's stacked sections of equal weight. Sections form the card's body under\n * one optional `Card.Header`: a `Card.Content` or `Card.Footer` beside them takes no divider, so\n * put that content in a section instead. A section pads every side with the card's tier, a 1px\n * `--card-section-divider` line separates it from the part above, and the first and last\n * sections round with the card's corners. A `Card.SectionMedia` as its first child makes it a\n * two-column grid with the media centred beside a `Card.Content`, the unpadded content column.\n * A horizontal card pads itself, so sections take no `direction` and belong in a vertical card.\n * A whole section that acts is a `Card.SectionButton`.\n */\nfunction CardSection({ className, ...props }: HTMLAttributes<HTMLDivElement>): ReactElement {\n const { section } = cardSectionVariants();\n\n return <div data-slot=\"card-section\" className={cn(section(), className)} {...props} />;\n}\n\n/**\n * The icon column of a `Card.Section` or `Card.SectionButton`. The section becomes a two-column\n * grid, this column and the content, with the icon centred on the section's height. An `svg` is\n * sized to `5`. It is a `span`, so it is phrasing content inside a section button.\n */\nfunction CardSectionMedia({ className, ...props }: HTMLAttributes<HTMLSpanElement>): ReactElement {\n const { media } = cardSectionVariants();\n\n return <span data-slot=\"card-section-media\" className={cn(media(), className)} {...props} />;\n}\n\nCardRoot.displayName = \"Card.Root\";\nCardHeader.displayName = \"Card.Header\";\nCardTag.displayName = \"Card.Tag\";\nCardTitle.displayName = \"Card.Title\";\nCardDescription.displayName = \"Card.Description\";\nCardAction.displayName = \"Card.Action\";\nCardContent.displayName = \"Card.Content\";\nCardFooter.displayName = \"Card.Footer\";\nCardSection.displayName = \"Card.Section\";\nCardSectionMedia.displayName = \"Card.SectionMedia\";\n\nexport const Card = {\n Root: CardRoot,\n Header: CardHeader,\n Tag: CardTag,\n Title: CardTitle,\n Description: CardDescription,\n Action: CardAction,\n Content: CardContent,\n Footer: CardFooter,\n Section: CardSection,\n SectionButton: CardSectionButton,\n SectionMedia: CardSectionMedia,\n};\n"],"mappings":";;;;;;;;;;;;;AA6DA,SAAS,SAAS,EAAE,WAAW,WAAW,OAAO,WAAW,GAAG,SAAsC;CACnG,MAAM,EAAE,SAAS,aAAa;EAAE;EAAW;CAAK,CAAC;CAEjD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,kBAAgB,aAAa;EAC7B,aAAW;EACX,WAAW,GAAG,KAAK,GAAG,SAAS;EAC/B,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,WAAW,GAAG,SAAqC;CAClF,MAAM,EAAE,eAAe,aAAa,EAAE,UAAU,CAAC;CAEjD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,kBAAgB,aAAa;EAC7B,WAAW,GAAG,WAAW,GAAG,SAAS;EACrC,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,QAAQ,EAAE,WAAW,WAAW,GAAG,SAAqC;CAC/E,MAAM,EAAE,YAAY,aAAa,EAAE,UAAU,CAAC;CAE9C,OAAO,oBAAC,OAAD;EAAK,aAAU;EAAW,WAAW,GAAG,QAAQ,GAAG,SAAS;EAAG,GAAI;CAAQ,CAAA;AACpF;AAEA,SAAS,UAAU,EACjB,UACA,WACA,WACA,QAAQ,GACR,OAAO,OACP,MACA,GAAG,SAC4B;CAC/B,MAAM,EAAE,cAAc,aAAa,EAAE,UAAU,CAAC;CAChD,MAAM,UAAU,IAAI;CAEpB,OACE,qBAAC,SAAD;EACE,aAAU;EACV,WAAW,GACT,kBAAkB,EAAE,KAAK,CAAC,GAC1B,UAAU,EAGR,WAAW,OAAO,+CAA+C,KAAA,EACnE,CAAC,GACD,SACF;EACA,GAAI;EAXN,UAAA,CAYG,QAAQ,MACR,QACM;;AAEb;AAEA,SAAS,gBAAgB,EACvB,WACA,WACA,OAAO,MACP,GAAG,SACkC;CACrC,MAAM,EAAE,oBAAoB,aAAa,EAAE,UAAU,CAAC;CAEtD,OACE,oBAAC,KAAD;EACE,aAAU;EACV,WAAW,GAAG,wBAAwB,EAAE,KAAK,CAAC,GAAG,gBAAgB,GAAG,SAAS;EAC7E,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,WAAW,GAAG,SAAqC;CAClF,MAAM,EAAE,eAAe,aAAa,EAAE,UAAU,CAAC;CAEjD,OAAO,oBAAC,OAAD;EAAK,aAAU;EAAc,WAAW,GAAG,WAAW,GAAG,SAAS;EAAG,GAAI;CAAQ,CAAA;AAC1F;;;;;AAMA,SAAS,YAAY,EAAE,WAAW,WAAW,GAAG,SAAqC;CACnF,MAAM,EAAE,gBAAgB,aAAa,EAAE,UAAU,CAAC;CAElD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,kBAAgB,aAAa;EAC7B,WAAW,GAAG,YAAY,GAAG,SAAS;EACtC,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAAE,WAAW,WAAW,GAAG,SAAqC;CAClF,MAAM,EAAE,eAAe,aAAa,EAAE,UAAU,CAAC;CAEjD,OACE,oBAAC,OAAD;EACE,aAAU;EACV,kBAAgB,aAAa;EAC7B,WAAW,GAAG,WAAW,GAAG,SAAS;EACrC,GAAI;CACL,CAAA;AAEL;;;;;;;;;;;AAYA,SAAS,YAAY,EAAE,WAAW,GAAG,SAAuD;CAC1F,MAAM,EAAE,YAAY,oBAAoB;CAExC,OAAO,oBAAC,OAAD;EAAK,aAAU;EAAe,WAAW,GAAG,QAAQ,GAAG,SAAS;EAAG,GAAI;CAAQ,CAAA;AACxF;;;;;;AAOA,SAAS,iBAAiB,EAAE,WAAW,GAAG,SAAwD;CAChG,MAAM,EAAE,UAAU,oBAAoB;CAEtC,OAAO,oBAAC,QAAD;EAAM,aAAU;EAAqB,WAAW,GAAG,MAAM,GAAG,SAAS;EAAG,GAAI;CAAQ,CAAA;AAC7F;AAEA,SAAS,cAAc;AACvB,WAAW,cAAc;AACzB,QAAQ,cAAc;AACtB,UAAU,cAAc;AACxB,gBAAgB,cAAc;AAC9B,WAAW,cAAc;AACzB,YAAY,cAAc;AAC1B,WAAW,cAAc;AACzB,YAAY,cAAc;AAC1B,iBAAiB,cAAc;AAE/B,MAAa,OAAO;CAClB,MAAM;CACN,QAAQ;CACR,KAAK;CACL,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,SAAS;CACT,eAAe;CACf,cAAc;AAChB"}
@@ -2,7 +2,19 @@ import { DescriptionListHeading, DescriptionListHeadingProps } from "./descripti
2
2
  import { ComponentProps, ReactElement } from "react";
3
3
  //#region src/components/description-list/description-list.d.ts
4
4
  export type DescriptionListRootProps = ComponentProps<"div">;
5
- export type DescriptionListContentProps = ComponentProps<"dl">;
5
+ export type DescriptionListContentProps = ComponentProps<"dl"> & {
6
+ /**
7
+ * How terms and details sit. `responsive` stacks each details under its term on phones and
8
+ * sets them in two columns, with a rule between rows, from `sm` up. `inline` keeps each term
9
+ * and its details on one row at every width, for label/value rows in cards and summaries: the
10
+ * details align to the end, a short one never wraps and a long one wraps within 60% of the
11
+ * row. Inline rows take the label type, have no rules and space with the small surface gap,
12
+ * and the term is not muted. A colour class on a cell wins in both layouts. The inline cells'
13
+ * padding, rules, column and alignment come from the list, so override them with a
14
+ * `[:where([data-layout=inline])>&]:` class or a CSS rule. Defaults to `responsive`.
15
+ */
16
+ layout?: "responsive" | "inline";
17
+ };
6
18
  export type DescriptionListTermProps = ComponentProps<"dt">;
7
19
  export type DescriptionListDetailsProps = ComponentProps<"dd">;
8
20
  /**
@@ -11,7 +23,7 @@ export type DescriptionListDetailsProps = ComponentProps<"dd">;
11
23
  * possible without making this module a client boundary.
12
24
  */
13
25
  declare function DescriptionListRoot(props: DescriptionListRootProps): ReactElement;
14
- declare function DescriptionListContent({ className, ...props }: DescriptionListContentProps): ReactElement;
26
+ declare function DescriptionListContent({ className, layout, ...props }: DescriptionListContentProps): ReactElement;
15
27
  declare function DescriptionListTerm({ className, ...props }: DescriptionListTermProps): ReactElement;
16
28
  declare function DescriptionListDetails({ className, ...props }: DescriptionListDetailsProps): ReactElement;
17
29
  export declare const DescriptionList: {
@@ -1 +1 @@
1
- {"version":3,"file":"description-list.d.ts","names":[],"sources":["../../../src/components/description-list/description-list.tsx"],"mappings":";;;YAKY,2BAA2B;YAC3B,8BAA8B;YAC9B,2BAA2B;YAC3B,8BAA8B;;;;;;iBAQjC,oBAAoB,OAAO,2BAA2B;iBAItD,yBAAyB,cAAc,SAAS,8BAA8B;iBAa9E,sBAAsB,cAAc,SAAS,2BAA2B;iBAaxE,yBAAyB,cAAc,SAAS,8BAA8B;qBAe1E;EACX,aAAI;EACJ,gBAAO;EACP,gBAAO;EACP,aAAI;EACJ,gBAAO"}
1
+ {"version":3,"file":"description-list.d.ts","names":[],"sources":["../../../src/components/description-list/description-list.tsx"],"mappings":";;;YAMY,2BAA2B;YAC3B,8BAA8B;;;;;;;;;;;EAWxC;;YAEU,2BAA2B;YAC3B,8BAA8B;;;;;;iBAQjC,oBAAoB,OAAO,2BAA2B;iBA8BtD,yBACP,WACA,WACG,SACF,8BAA8B;iBAWxB,sBAAsB,cAAc,SAAS,2BAA2B;iBAcxE,yBAAyB,cAAc,SAAS,8BAA8B;qBAmB1E;EACX,aAAI;EACJ,gBAAO;EACP,gBAAO;EACP,aAAI;EACJ,gBAAO"}
@@ -1,4 +1,5 @@
1
1
  import { cn } from "../../styles/cn.js";
2
+ import { labelTypeClass } from "../../styles/label-type.js";
2
3
  import { DescriptionListHeading } from "./description-list-heading.js";
3
4
  import { jsx } from "react/jsx-runtime";
4
5
  //#region src/components/description-list/description-list.tsx
@@ -13,24 +14,33 @@ function DescriptionListRoot(props) {
13
14
  ...props
14
15
  });
15
16
  }
16
- function DescriptionListContent({ className, ...props }) {
17
+ /** The responsive list: one column on phones, then a term column capped at min(50%, 20rem). */
18
+ const responsiveContentClass = cn("text-base/6 sm:grid-cols-[min(50%,calc(var(--spacing)*80))_auto] sm:text-sm/6 grid grid-cols-1 [--description-list-details:initial] [--description-list-term:initial]");
19
+ /**
20
+ * The inline list: `minmax(0,1fr)` for the terms and `fit-content(60%)` for the details, rows
21
+ * spaced by the small surface gap, the label type set here for the cells to inherit, and
22
+ * consecutive inline lists spaced by the large surface gap.
23
+ */
24
+ const inlineContentClass = cn("grid grid-cols-[minmax(0,1fr)_fit-content(60%)] gap-x-(--surface-gap-md) gap-y-(--surface-gap-sm)", labelTypeClass, "[--description-list-details:currentColor] [--description-list-term:currentColor]", "[&+&]:mt-(--surface-gap-lg)");
25
+ function DescriptionListContent({ className, layout = "responsive", ...props }) {
17
26
  return /* @__PURE__ */ jsx("dl", {
18
27
  "data-slot": "description-list-content",
19
- className: cn("text-base/6 sm:grid-cols-[min(50%,calc(var(--spacing)*80))_auto] sm:text-sm/6 grid grid-cols-1", className),
28
+ "data-layout": layout,
29
+ className: cn(layout === "inline" ? inlineContentClass : responsiveContentClass, className),
20
30
  ...props
21
31
  });
22
32
  }
23
33
  function DescriptionListTerm({ className, ...props }) {
24
34
  return /* @__PURE__ */ jsx("dt", {
25
35
  "data-slot": "description-list-term",
26
- className: cn("col-start-1 border-t py-(--row-py) pr-(--row-px) text-muted-foreground first-of-type:border-none", className),
36
+ className: cn("col-start-1 border-t py-(--row-py) pr-(--row-px) text-[color:var(--description-list-term,var(--muted-foreground))] first-of-type:border-none", "[:where([data-layout=inline])>&]:min-w-0 [:where([data-layout=inline])>&]:border-none [:where([data-layout=inline])>&]:p-0 [:where([data-layout=inline])>&]:wrap-anywhere", className),
27
37
  ...props
28
38
  });
29
39
  }
30
40
  function DescriptionListDetails({ className, ...props }) {
31
41
  return /* @__PURE__ */ jsx("dd", {
32
42
  "data-slot": "description-list-details",
33
- className: cn("sm:border-t py-(--row-py) text-foreground first-of-type:border-none", className),
43
+ className: cn("sm:border-t py-(--row-py) text-[color:var(--description-list-details,var(--foreground))] first-of-type:border-none", "[:where([data-layout=inline])>&]:col-start-2 [:where([data-layout=inline])>&]:min-w-0 [:where([data-layout=inline])>&]:border-none [:where([data-layout=inline])>&]:py-0 [:where([data-layout=inline])>&]:text-end [:where([data-layout=inline])>&]:wrap-anywhere", className),
34
44
  ...props
35
45
  });
36
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"description-list.js","names":[],"sources":["../../../src/components/description-list/description-list.tsx"],"sourcesContent":["import type { ComponentProps, ReactElement } from \"react\";\n\nimport { cn } from \"../../styles/cn\";\nimport { DescriptionListHeading } from \"./description-list-heading\";\n\nexport type DescriptionListRootProps = ComponentProps<\"div\">;\nexport type DescriptionListContentProps = ComponentProps<\"dl\">;\nexport type DescriptionListTermProps = ComponentProps<\"dt\">;\nexport type DescriptionListDetailsProps = ComponentProps<\"dd\">;\nexport type { DescriptionListHeadingProps } from \"./description-list-heading\";\n\n/**\n * Semantic `<dl>/<dt>/<dd>` composite. A server compound: it owns no state, handlers or\n * browser APIs. `Heading` is a client `useRender` island, so other outline levels stay\n * possible without making this module a client boundary.\n */\nfunction DescriptionListRoot(props: DescriptionListRootProps): ReactElement {\n return <div data-slot=\"description-list\" {...props} />;\n}\n\nfunction DescriptionListContent({ className, ...props }: DescriptionListContentProps): ReactElement {\n return (\n <dl\n data-slot=\"description-list-content\"\n className={cn(\n \"text-base/6 sm:grid-cols-[min(50%,calc(var(--spacing)*80))_auto] sm:text-sm/6 grid grid-cols-1\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction DescriptionListTerm({ className, ...props }: DescriptionListTermProps): ReactElement {\n return (\n <dt\n data-slot=\"description-list-term\"\n className={cn(\n \"col-start-1 border-t py-(--row-py) pr-(--row-px) text-muted-foreground first-of-type:border-none\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction DescriptionListDetails({ className, ...props }: DescriptionListDetailsProps): ReactElement {\n return (\n <dd\n data-slot=\"description-list-details\"\n className={cn(\"sm:border-t py-(--row-py) text-foreground first-of-type:border-none\", className)}\n {...props}\n />\n );\n}\n\nDescriptionListRoot.displayName = \"DescriptionList.Root\";\nDescriptionListContent.displayName = \"DescriptionList.Content\";\nDescriptionListTerm.displayName = \"DescriptionList.Term\";\nDescriptionListDetails.displayName = \"DescriptionList.Details\";\n\nexport const DescriptionList = {\n Root: DescriptionListRoot,\n Heading: DescriptionListHeading,\n Content: DescriptionListContent,\n Term: DescriptionListTerm,\n Details: DescriptionListDetails,\n};\n"],"mappings":";;;;;;;;;AAgBA,SAAS,oBAAoB,OAA+C;CAC1E,OAAO,oBAAC,OAAD;EAAK,aAAU;EAAmB,GAAI;CAAQ,CAAA;AACvD;AAEA,SAAS,uBAAuB,EAAE,WAAW,GAAG,SAAoD;CAClG,OACE,oBAAC,MAAD;EACE,aAAU;EACV,WAAW,GACT,kGACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,oBAAoB,EAAE,WAAW,GAAG,SAAiD;CAC5F,OACE,oBAAC,MAAD;EACE,aAAU;EACV,WAAW,GACT,oGACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,uBAAuB,EAAE,WAAW,GAAG,SAAoD;CAClG,OACE,oBAAC,MAAD;EACE,aAAU;EACV,WAAW,GAAG,uEAAuE,SAAS;EAC9F,GAAI;CACL,CAAA;AAEL;AAEA,oBAAoB,cAAc;AAClC,uBAAuB,cAAc;AACrC,oBAAoB,cAAc;AAClC,uBAAuB,cAAc;AAErC,MAAa,kBAAkB;CAC7B,MAAM;CACN,SAAS;CACT,SAAS;CACT,MAAM;CACN,SAAS;AACX"}
1
+ {"version":3,"file":"description-list.js","names":[],"sources":["../../../src/components/description-list/description-list.tsx"],"sourcesContent":["import type { ComponentProps, ReactElement } from \"react\";\n\nimport { cn } from \"../../styles/cn\";\nimport { labelTypeClass } from \"../../styles/label-type\";\nimport { DescriptionListHeading } from \"./description-list-heading\";\n\nexport type DescriptionListRootProps = ComponentProps<\"div\">;\nexport type DescriptionListContentProps = ComponentProps<\"dl\"> & {\n /**\n * How terms and details sit. `responsive` stacks each details under its term on phones and\n * sets them in two columns, with a rule between rows, from `sm` up. `inline` keeps each term\n * and its details on one row at every width, for label/value rows in cards and summaries: the\n * details align to the end, a short one never wraps and a long one wraps within 60% of the\n * row. Inline rows take the label type, have no rules and space with the small surface gap,\n * and the term is not muted. A colour class on a cell wins in both layouts. The inline cells'\n * padding, rules, column and alignment come from the list, so override them with a\n * `[:where([data-layout=inline])>&]:` class or a CSS rule. Defaults to `responsive`.\n */\n layout?: \"responsive\" | \"inline\";\n};\nexport type DescriptionListTermProps = ComponentProps<\"dt\">;\nexport type DescriptionListDetailsProps = ComponentProps<\"dd\">;\nexport type { DescriptionListHeadingProps } from \"./description-list-heading\";\n\n/**\n * Semantic `<dl>/<dt>/<dd>` composite. A server compound: it owns no state, handlers or\n * browser APIs. `Heading` is a client `useRender` island, so other outline levels stay\n * possible without making this module a client boundary.\n */\nfunction DescriptionListRoot(props: DescriptionListRootProps): ReactElement {\n return <div data-slot=\"description-list\" {...props} />;\n}\n\n// The inline layout publishes the term and details colours as the private `--description-list-term`\n// and `--description-list-details`, and the responsive one resets them, so its cells fall back to\n// `--muted-foreground` and `--foreground` read in their own theme scope. A nested list resets them\n// too, and a consumer colour class on a cell still wins in both layouts. Inline cells take the\n// surrounding text colour, such as a card's. The term and details style the rest of the inline\n// layout from their own list's `data-layout`, as its direct children, so a responsive list nested\n// in an inline one keeps its own layout. Plain `cn` constants rather than a `tv` recipe keep\n// tailwind-variants out of this entry's size budget.\n\n/** The responsive list: one column on phones, then a term column capped at min(50%, 20rem). */\nconst responsiveContentClass = cn(\n \"text-base/6 sm:grid-cols-[min(50%,calc(var(--spacing)*80))_auto] sm:text-sm/6 grid grid-cols-1 [--description-list-details:initial] [--description-list-term:initial]\"\n);\n\n/**\n * The inline list: `minmax(0,1fr)` for the terms and `fit-content(60%)` for the details, rows\n * spaced by the small surface gap, the label type set here for the cells to inherit, and\n * consecutive inline lists spaced by the large surface gap.\n */\nconst inlineContentClass = cn(\n \"grid grid-cols-[minmax(0,1fr)_fit-content(60%)] gap-x-(--surface-gap-md) gap-y-(--surface-gap-sm)\",\n labelTypeClass,\n \"[--description-list-details:currentColor] [--description-list-term:currentColor]\",\n \"[&+&]:mt-(--surface-gap-lg)\"\n);\n\nfunction DescriptionListContent({\n className,\n layout = \"responsive\",\n ...props\n}: DescriptionListContentProps): ReactElement {\n return (\n <dl\n data-slot=\"description-list-content\"\n data-layout={layout}\n className={cn(layout === \"inline\" ? inlineContentClass : responsiveContentClass, className)}\n {...props}\n />\n );\n}\n\nfunction DescriptionListTerm({ className, ...props }: DescriptionListTermProps): ReactElement {\n return (\n <dt\n data-slot=\"description-list-term\"\n className={cn(\n \"col-start-1 border-t py-(--row-py) pr-(--row-px) text-[color:var(--description-list-term,var(--muted-foreground))] first-of-type:border-none\",\n \"[:where([data-layout=inline])>&]:min-w-0 [:where([data-layout=inline])>&]:border-none [:where([data-layout=inline])>&]:p-0 [:where([data-layout=inline])>&]:wrap-anywhere\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction DescriptionListDetails({ className, ...props }: DescriptionListDetailsProps): ReactElement {\n return (\n <dd\n data-slot=\"description-list-details\"\n className={cn(\n \"sm:border-t py-(--row-py) text-[color:var(--description-list-details,var(--foreground))] first-of-type:border-none\",\n \"[:where([data-layout=inline])>&]:col-start-2 [:where([data-layout=inline])>&]:min-w-0 [:where([data-layout=inline])>&]:border-none [:where([data-layout=inline])>&]:py-0 [:where([data-layout=inline])>&]:text-end [:where([data-layout=inline])>&]:wrap-anywhere\",\n className\n )}\n {...props}\n />\n );\n}\n\nDescriptionListRoot.displayName = \"DescriptionList.Root\";\nDescriptionListContent.displayName = \"DescriptionList.Content\";\nDescriptionListTerm.displayName = \"DescriptionList.Term\";\nDescriptionListDetails.displayName = \"DescriptionList.Details\";\n\nexport const DescriptionList = {\n Root: DescriptionListRoot,\n Heading: DescriptionListHeading,\n Content: DescriptionListContent,\n Term: DescriptionListTerm,\n Details: DescriptionListDetails,\n};\n"],"mappings":";;;;;;;;;;AA6BA,SAAS,oBAAoB,OAA+C;CAC1E,OAAO,oBAAC,OAAD;EAAK,aAAU;EAAmB,GAAI;CAAQ,CAAA;AACvD;;AAYA,MAAM,yBAAyB,GAC7B,uKACF;;;;;;AAOA,MAAM,qBAAqB,GACzB,qGACA,gBACA,oFACA,6BACF;AAEA,SAAS,uBAAuB,EAC9B,WACA,SAAS,cACT,GAAG,SACyC;CAC5C,OACE,oBAAC,MAAD;EACE,aAAU;EACV,eAAa;EACb,WAAW,GAAG,WAAW,WAAW,qBAAqB,wBAAwB,SAAS;EAC1F,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,oBAAoB,EAAE,WAAW,GAAG,SAAiD;CAC5F,OACE,oBAAC,MAAD;EACE,aAAU;EACV,WAAW,GACT,gJACA,6KACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,uBAAuB,EAAE,WAAW,GAAG,SAAoD;CAClG,OACE,oBAAC,MAAD;EACE,aAAU;EACV,WAAW,GACT,sHACA,qQACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,oBAAoB,cAAc;AAClC,uBAAuB,cAAc;AACrC,oBAAoB,cAAc;AAClC,uBAAuB,cAAc;AAErC,MAAa,kBAAkB;CAC7B,MAAM;CACN,SAAS;CACT,SAAS;CACT,MAAM;CACN,SAAS;AACX"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elmeragroup/fuse",
3
- "version": "0.1.0-canary.113",
3
+ "version": "0.1.0-canary.115",
4
4
  "description": "Fuse — whitelabel React components for Elmera Group's energy brands. One package, twenty theme permutations, ESM-only.",
5
5
  "keywords": [
6
6
  "react",
@@ -391,7 +391,7 @@
391
391
  "access": "public"
392
392
  },
393
393
  "elmeraRelease": {
394
- "commit": "310567f81f5a9145e45c2704bb8f8876f61a2f13",
394
+ "commit": "41bf4f22a1422017b8b35588da5c3acfc285e646",
395
395
  "channel": "canary"
396
396
  }
397
397
  }
package/styles/fuse.css CHANGED
@@ -146,6 +146,7 @@
146
146
  --color-input: var(--input);
147
147
  --color-ring: var(--ring);
148
148
  --color-card-border: var(--card-border, var(--border));
149
+ --color-card-section-divider: var(--card-section-divider, var(--border));
149
150
  --color-button-outline: var(--button-outline, var(--border));
150
151
  --color-selection-border: var(--selection-border, var(--border));
151
152
  --color-selection-checked-border: var(--selection-checked-border, var(--primary));
@@ -1,6 +1,11 @@
1
1
  //#region src/styles/inner-corner/card.d.ts
2
2
  /**
3
- * The Card root: `rounded-lg` behind a 1px border.
3
+ * The Card root: `rounded-lg` behind a 1px border. It hands every direct child the corner a
4
+ * stacked section rounds with, its own less the border, as the private `--card-section-corner`,
5
+ * as Frame does with `--frame-corner`. It keys on no slot, because a `Card.SectionButton` a
6
+ * trigger renders carries the trigger's `data-slot`. Every section resets the property, and the
7
+ * root's child rule comes later in the sheet at the same specificity, so only a card's direct
8
+ * section holds a value and one nested deeper is square.
4
9
  */
5
10
  export declare const cardShellClass: string;
6
11
  /**
@@ -33,5 +38,13 @@ export declare const textFieldCardShellClass: string;
33
38
  * block axis.
34
39
  */
35
40
  export declare const checkboxCardContentShellClass: string;
41
+ /**
42
+ * A stacked `Card.Section` or `Card.SectionButton`: it pads every side with the card's tier,
43
+ * `--card-pad`, and publishes the same inner corner as the other sections. A 1px
44
+ * `--card-section-divider` line runs above every section but the first. The first and last sections round their outer corners with the corner the
45
+ * card hands them, so a fill or a hover fill follows the card's corners. Both skip `hidden`
46
+ * siblings, and middle sections stay square. Outside a card the section is square.
47
+ */
48
+ export declare const cardStackedSectionShellClass: string;
36
49
  //#endregion
37
50
  //# sourceMappingURL=card.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"card.d.ts","names":[],"sources":["../../../src/styles/inner-corner/card.ts"],"mappings":";;;;qBASa;;;;;;qBAUA;;;;;qBAMA;;;;qBAgBA;;;;;qBASA;;;;;qBAMA;;;;;qBASA"}
1
+ {"version":3,"file":"card.d.ts","names":[],"sources":["../../../src/styles/inner-corner/card.ts"],"mappings":";;;;;;;;;qBAca;;;;;;qBAUA;;;;;qBAMA;;;;qBAgBA;;;;;qBASA;;;;;qBAMA;;;;;qBASA;;;;;;;;qBAYA"}
@@ -2,9 +2,14 @@ import { cn } from "../cn.js";
2
2
  import { publishShellBoundary } from "../corner-radius.js";
3
3
  //#region src/styles/inner-corner/card.ts
4
4
  /**
5
- * The Card root: `rounded-lg` behind a 1px border.
5
+ * The Card root: `rounded-lg` behind a 1px border. It hands every direct child the corner a
6
+ * stacked section rounds with, its own less the border, as the private `--card-section-corner`,
7
+ * as Frame does with `--frame-corner`. It keys on no slot, because a `Card.SectionButton` a
8
+ * trigger renders carries the trigger's `data-slot`. Every section resets the property, and the
9
+ * root's child rule comes later in the sheet at the same specificity, so only a card's direct
10
+ * section holds a value and one nested deeper is square.
6
11
  */
7
- const cardShellClass = cn("rounded-lg border [--shell-inner:max(0px,--theme(--radius-lg)-1px)]", publishShellBoundary);
12
+ const cardShellClass = cn("rounded-lg border [--shell-inner:max(0px,--theme(--radius-lg)-1px)] *:[--card-section-corner:max(0px,--theme(--radius-lg)-1px)]", publishShellBoundary);
8
13
  /**
9
14
  * A default Card's tier, published on the root as the private `--card-pad`: the medium surface
10
15
  * tier, `--surface-pad-md`, which Items and Accordion items pad with too, so a card's text starts
@@ -42,7 +47,15 @@ const textFieldCardShellClass = cn("px-[var(--card-pad,var(--surface-pad-md))] p
42
47
  * block axis.
43
48
  */
44
49
  const checkboxCardContentShellClass = cn("px-[var(--card-pad,var(--surface-pad-md))] py-3", cardTierBoundaryClass);
50
+ /**
51
+ * A stacked `Card.Section` or `Card.SectionButton`: it pads every side with the card's tier,
52
+ * `--card-pad`, and publishes the same inner corner as the other sections. A 1px
53
+ * `--card-section-divider` line runs above every section but the first. The first and last sections round their outer corners with the corner the
54
+ * card hands them, so a fill or a hover fill follows the card's corners. Both skip `hidden`
55
+ * siblings, and middle sections stay square. Outside a card the section is square.
56
+ */
57
+ const cardStackedSectionShellClass = cn("border-0 border-t border-card-section-divider p-[var(--card-pad,var(--surface-pad-md))] [--card-section-corner:initial] [&:nth-child(1_of_:not([hidden]))]:rounded-t-[var(--card-section-corner,0px)] [&:nth-child(1_of_:not([hidden]))]:border-t-0 [&:nth-last-child(1_of_:not([hidden]))]:rounded-b-[var(--card-section-corner,0px)]", "[&[hidden]:not([hidden=until-found])]:hidden", cardTierBoundaryClass);
45
58
  //#endregion
46
- export { cardDefaultTierClass, cardHorizontalShellClass, cardLargeTierClass, cardSectionShellClass, cardShellClass, checkboxCardContentShellClass, textFieldCardShellClass };
59
+ export { cardDefaultTierClass, cardHorizontalShellClass, cardLargeTierClass, cardSectionShellClass, cardShellClass, cardStackedSectionShellClass, checkboxCardContentShellClass, textFieldCardShellClass };
47
60
 
48
61
  //# sourceMappingURL=card.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"card.js","names":[],"sources":["../../../src/styles/inner-corner/card.ts"],"sourcesContent":["import { cn } from \"../cn\";\nimport { publishShellBoundary } from \"../corner-radius\";\n\n// The inner-corner shells of Card and the parts built on it. The rules every shell follows are in\n// `corner-radius.ts`. Each constant pairs a part's rung or padding with the corner it publishes.\n\n/**\n * The Card root: `rounded-lg` behind a 1px border.\n */\nexport const cardShellClass = cn(\n \"rounded-lg border [--shell-inner:max(0px,--theme(--radius-lg)-1px)]\",\n publishShellBoundary\n);\n\n/**\n * A default Card's tier, published on the root as the private `--card-pad`: the medium surface\n * tier, `--surface-pad-md`, which Items and Accordion items pad with too, so a card's text starts\n * on their edge. Every root sets it, so a nested card resets it.\n */\nexport const cardDefaultTierClass = cn(\"[--card-pad:var(--surface-pad-md)]\");\n\n/**\n * A large Card's tier: the large surface tier, `--surface-pad-lg`, for a card that holds long\n * prose or acts as a page's main panel.\n */\nexport const cardLargeTierClass = cn(\"[--card-pad:var(--surface-pad-lg)]\");\n\n/**\n * The boundary every padded part inside a Card's border publishes: the card's `rounded-lg` less\n * its 1px border and the card's tier, `--card-pad`, its inline padding. Each padded part falls\n * back to the default tier outside a card root, so a section recipe used on its own pads as one\n * inside a default card.\n */\nconst cardTierBoundaryClass = cn(\n \"[--shell-inner:max(0px,--theme(--radius-lg)-1px-var(--card-pad,var(--surface-pad-md)))]\",\n publishShellBoundary\n);\n\n/**\n * A horizontal Card root, which pads its sections itself with the card's tier, `--card-pad`.\n */\nexport const cardHorizontalShellClass = cn(\n \"p-[var(--card-pad,var(--surface-pad-md))]\",\n cardTierBoundaryClass\n);\n\n/**\n * A vertical Card's header, content or footer, which pads with the card's tier, `--card-pad`,\n * inside the card.\n */\nexport const cardSectionShellClass = cn(\"p-[var(--card-pad,var(--surface-pad-md))]\", cardTierBoundaryClass);\n\n/**\n * The TextField `card` box: a default Card root that pads inline with its tier and 16px on the\n * block axis.\n */\nexport const textFieldCardShellClass = cn(\n \"px-[var(--card-pad,var(--surface-pad-md))] py-4\",\n cardTierBoundaryClass\n);\n\n/**\n * The CheckboxCard content: a default Card's section that pads inline with its tier and 12px on the\n * block axis.\n */\nexport const checkboxCardContentShellClass = cn(\n \"px-[var(--card-pad,var(--surface-pad-md))] py-3\",\n cardTierBoundaryClass\n);\n"],"mappings":";;;;;;AASA,MAAa,iBAAiB,GAC5B,uEACA,oBACF;;;;;;AAOA,MAAa,uBAAuB,GAAG,oCAAoC;;;;;AAM3E,MAAa,qBAAqB,GAAG,oCAAoC;;;;;;;AAQzE,MAAM,wBAAwB,GAC5B,2FACA,oBACF;;;;AAKA,MAAa,2BAA2B,GACtC,6CACA,qBACF;;;;;AAMA,MAAa,wBAAwB,GAAG,6CAA6C,qBAAqB;;;;;AAM1G,MAAa,0BAA0B,GACrC,mDACA,qBACF;;;;;AAMA,MAAa,gCAAgC,GAC3C,mDACA,qBACF"}
1
+ {"version":3,"file":"card.js","names":[],"sources":["../../../src/styles/inner-corner/card.ts"],"sourcesContent":["import { cn } from \"../cn\";\nimport { publishShellBoundary } from \"../corner-radius\";\n\n// The inner-corner shells of Card and the parts built on it. The rules every shell follows are in\n// `corner-radius.ts`. Each constant pairs a part's rung or padding with the corner it publishes.\n\n/**\n * The Card root: `rounded-lg` behind a 1px border. It hands every direct child the corner a\n * stacked section rounds with, its own less the border, as the private `--card-section-corner`,\n * as Frame does with `--frame-corner`. It keys on no slot, because a `Card.SectionButton` a\n * trigger renders carries the trigger's `data-slot`. Every section resets the property, and the\n * root's child rule comes later in the sheet at the same specificity, so only a card's direct\n * section holds a value and one nested deeper is square.\n */\nexport const cardShellClass = cn(\n \"rounded-lg border [--shell-inner:max(0px,--theme(--radius-lg)-1px)] *:[--card-section-corner:max(0px,--theme(--radius-lg)-1px)]\",\n publishShellBoundary\n);\n\n/**\n * A default Card's tier, published on the root as the private `--card-pad`: the medium surface\n * tier, `--surface-pad-md`, which Items and Accordion items pad with too, so a card's text starts\n * on their edge. Every root sets it, so a nested card resets it.\n */\nexport const cardDefaultTierClass = cn(\"[--card-pad:var(--surface-pad-md)]\");\n\n/**\n * A large Card's tier: the large surface tier, `--surface-pad-lg`, for a card that holds long\n * prose or acts as a page's main panel.\n */\nexport const cardLargeTierClass = cn(\"[--card-pad:var(--surface-pad-lg)]\");\n\n/**\n * The boundary every padded part inside a Card's border publishes: the card's `rounded-lg` less\n * its 1px border and the card's tier, `--card-pad`, its inline padding. Each padded part falls\n * back to the default tier outside a card root, so a section recipe used on its own pads as one\n * inside a default card.\n */\nconst cardTierBoundaryClass = cn(\n \"[--shell-inner:max(0px,--theme(--radius-lg)-1px-var(--card-pad,var(--surface-pad-md)))]\",\n publishShellBoundary\n);\n\n/**\n * A horizontal Card root, which pads its sections itself with the card's tier, `--card-pad`.\n */\nexport const cardHorizontalShellClass = cn(\n \"p-[var(--card-pad,var(--surface-pad-md))]\",\n cardTierBoundaryClass\n);\n\n/**\n * A vertical Card's header, content or footer, which pads with the card's tier, `--card-pad`,\n * inside the card.\n */\nexport const cardSectionShellClass = cn(\"p-[var(--card-pad,var(--surface-pad-md))]\", cardTierBoundaryClass);\n\n/**\n * The TextField `card` box: a default Card root that pads inline with its tier and 16px on the\n * block axis.\n */\nexport const textFieldCardShellClass = cn(\n \"px-[var(--card-pad,var(--surface-pad-md))] py-4\",\n cardTierBoundaryClass\n);\n\n/**\n * The CheckboxCard content: a default Card's section that pads inline with its tier and 12px on the\n * block axis.\n */\nexport const checkboxCardContentShellClass = cn(\n \"px-[var(--card-pad,var(--surface-pad-md))] py-3\",\n cardTierBoundaryClass\n);\n\n/**\n * A stacked `Card.Section` or `Card.SectionButton`: it pads every side with the card's tier,\n * `--card-pad`, and publishes the same inner corner as the other sections. A 1px\n * `--card-section-divider` line runs above every section but the first. The first and last sections round their outer corners with the corner the\n * card hands them, so a fill or a hover fill follows the card's corners. Both skip `hidden`\n * siblings, and middle sections stay square. Outside a card the section is square.\n */\nexport const cardStackedSectionShellClass = cn(\n \"border-0 border-t border-card-section-divider p-[var(--card-pad,var(--surface-pad-md))] [--card-section-corner:initial] [&:nth-child(1_of_:not([hidden]))]:rounded-t-[var(--card-section-corner,0px)] [&:nth-child(1_of_:not([hidden]))]:border-t-0 [&:nth-last-child(1_of_:not([hidden]))]:rounded-b-[var(--card-section-corner,0px)]\",\n // Without preflight a section's own `block` or `grid` beats the user-agent `[hidden]` rule.\n \"[&[hidden]:not([hidden=until-found])]:hidden\",\n cardTierBoundaryClass\n);\n"],"mappings":";;;;;;;;;;;AAcA,MAAa,iBAAiB,GAC5B,mIACA,oBACF;;;;;;AAOA,MAAa,uBAAuB,GAAG,oCAAoC;;;;;AAM3E,MAAa,qBAAqB,GAAG,oCAAoC;;;;;;;AAQzE,MAAM,wBAAwB,GAC5B,2FACA,oBACF;;;;AAKA,MAAa,2BAA2B,GACtC,6CACA,qBACF;;;;;AAMA,MAAa,wBAAwB,GAAG,6CAA6C,qBAAqB;;;;;AAM1G,MAAa,0BAA0B,GACrC,mDACA,qBACF;;;;;AAMA,MAAa,gCAAgC,GAC3C,mDACA,qBACF;;;;;;;;AASA,MAAa,+BAA+B,GAC1C,0UAEA,gDACA,qBACF"}
package/styles.css CHANGED
@@ -964,6 +964,9 @@
964
964
  .grid-cols-\[minmax\(0\,1fr\)_auto\] {
965
965
  grid-template-columns: minmax(0,1fr) auto;
966
966
  }
967
+ .grid-cols-\[minmax\(0\,1fr\)_fit-content\(60\%\)\] {
968
+ grid-template-columns: minmax(0,1fr) fit-content(60%);
969
+ }
967
970
  .grid-cols-subgrid {
968
971
  grid-template-columns: subgrid;
969
972
  }
@@ -1081,6 +1084,9 @@
1081
1084
  margin-block-start: calc(calc(0.25rem * 4) * var(--tw-space-y-reverse));
1082
1085
  margin-block-end: calc(calc(0.25rem * 4) * calc(1 - var(--tw-space-y-reverse)));
1083
1086
  }
1087
+ .gap-x-\(--surface-gap-md\) {
1088
+ column-gap: var(--surface-gap-md);
1089
+ }
1084
1090
  .gap-x-1\.5 {
1085
1091
  column-gap: calc(0.25rem * 1.5);
1086
1092
  }
@@ -1101,6 +1107,9 @@
1101
1107
  margin-inline-start: calc(calc(0.25rem * -2) * var(--tw-space-x-reverse));
1102
1108
  margin-inline-end: calc(calc(0.25rem * -2) * calc(1 - var(--tw-space-x-reverse)));
1103
1109
  }
1110
+ .gap-y-\(--surface-gap-sm\) {
1111
+ row-gap: var(--surface-gap-sm);
1112
+ }
1104
1113
  .gap-y-1 {
1105
1114
  row-gap: 0.25rem;
1106
1115
  }
@@ -1258,6 +1267,9 @@
1258
1267
  .border-card-border {
1259
1268
  border-color: var(--card-border, var(--border));
1260
1269
  }
1270
+ .border-card-section-divider {
1271
+ border-color: var(--card-section-divider, var(--border));
1272
+ }
1261
1273
  .border-error {
1262
1274
  border-color: var(--error);
1263
1275
  }
@@ -1899,6 +1911,12 @@
1899
1911
  .whitespace-nowrap {
1900
1912
  white-space: nowrap;
1901
1913
  }
1914
+ .text-\[color\:var\(--description-list-details\,var\(--foreground\)\)\] {
1915
+ color: var(--description-list-details,var(--foreground));
1916
+ }
1917
+ .text-\[color\:var\(--description-list-term\,var\(--muted-foreground\)\)\] {
1918
+ color: var(--description-list-term,var(--muted-foreground));
1919
+ }
1902
1920
  .text-\[var\(--toast-copy\,var\(--muted-foreground\)\)\] {
1903
1921
  color: var(--toast-copy,var(--muted-foreground));
1904
1922
  }
@@ -2364,6 +2382,9 @@
2364
2382
  .\[--card-pad\:var\(--surface-pad-md\)\] {
2365
2383
  --card-pad: var(--surface-pad-md);
2366
2384
  }
2385
+ .\[--card-section-corner\:initial\] {
2386
+ --card-section-corner: initial;
2387
+ }
2367
2388
  .\[--checkbox-color\:var\(--border\)\] {
2368
2389
  --checkbox-color: var(--border);
2369
2390
  }
@@ -2376,6 +2397,18 @@
2376
2397
  .\[--checkbox-color\:var\(--primary\)\] {
2377
2398
  --checkbox-color: var(--primary);
2378
2399
  }
2400
+ .\[--description-list-details\:currentColor\] {
2401
+ --description-list-details: currentColor;
2402
+ }
2403
+ .\[--description-list-details\:initial\] {
2404
+ --description-list-details: initial;
2405
+ }
2406
+ .\[--description-list-term\:currentColor\] {
2407
+ --description-list-term: currentColor;
2408
+ }
2409
+ .\[--description-list-term\:initial\] {
2410
+ --description-list-term: initial;
2411
+ }
2379
2412
  .\[--field-corner\:clamp\(var\(--radius\)-1000\*var\(--radius-step\,0px\)\,var\(--radius-field\,var\(--radius\)\)\,var\(--radius\)\+1000\*var\(--radius-step\,0px\)\)\] {
2380
2413
  --field-corner: clamp(var(--radius) - 1000 * var(--radius-step,0px), var(--radius-field,var(--radius)), var(--radius) + 1000 * var(--radius-step,0px));
2381
2414
  }
@@ -2616,6 +2649,9 @@
2616
2649
  font-size: var(--text-xs);
2617
2650
  line-height: var(--tw-leading, var(--text-xs--line-height));
2618
2651
  }
2652
+ :is(.\*\:\[--card-section-corner\:max\(0px\,--theme\(--radius-lg\)-1px\)\] > *) {
2653
+ --card-section-corner: max(0px, var(--radius) - 1px);
2654
+ }
2619
2655
  :is(.\*\*\:text-2xl *) {
2620
2656
  font-size: var(--text-2xl);
2621
2657
  line-height: var(--tw-leading, var(--text-2xl--line-height));
@@ -3318,6 +3354,9 @@
3318
3354
  --tw-outline-style: none;
3319
3355
  outline-style: none;
3320
3356
  }
3357
+ .focus-visible\:ring-inset:is(:where([data-rac])[data-focus-visible], :where(:not([data-rac])):focus-visible) {
3358
+ --tw-ring-inset: inset;
3359
+ }
3321
3360
  :is(.\*\:focus-visible\:relative > *):is(:where([data-rac])[data-focus-visible], :where(:not([data-rac])):focus-visible) {
3322
3361
  position: relative;
3323
3362
  }
@@ -3625,6 +3664,18 @@
3625
3664
  .has-\[\>\[data-slot\=button-group\]\]\:gap-2:has( > [data-slot=button-group]) {
3626
3665
  gap: calc(0.25rem * 2);
3627
3666
  }
3667
+ .has-\[\>\[data-slot\=card-section-media\]\]\:grid:has( > [data-slot=card-section-media]) {
3668
+ display: grid;
3669
+ }
3670
+ .has-\[\>\[data-slot\=card-section-media\]\]\:grid-cols-\[auto_minmax\(0\,1fr\)\]:has( > [data-slot=card-section-media]) {
3671
+ grid-template-columns: auto minmax(0,1fr);
3672
+ }
3673
+ .has-\[\>\[data-slot\=card-section-media\]\]\:items-center:has( > [data-slot=card-section-media]) {
3674
+ align-items: center;
3675
+ }
3676
+ .has-\[\>\[data-slot\=card-section-media\]\]\:gap-x-\(--surface-gap-md\):has( > [data-slot=card-section-media]) {
3677
+ column-gap: var(--surface-gap-md);
3678
+ }
3628
3679
  .has-\[\>\[data-slot\=checkbox-group\]\]\:gap-\(--surface-gap-md\):has( > [data-slot=checkbox-group]) {
3629
3680
  gap: var(--surface-gap-md);
3630
3681
  }
@@ -5034,6 +5085,9 @@
5034
5085
  border-style: var(--tw-border-style);
5035
5086
  border-width: 0px;
5036
5087
  }
5088
+ .\[\&\+\&\]\:mt-\(--surface-gap-lg\) + .\[\&\+\&\]\:mt-\(--surface-gap-lg\) {
5089
+ margin-top: var(--surface-gap-lg);
5090
+ }
5037
5091
  .\[\&\+\[data-slot\=item-content\]\]\:flex-none + [data-slot=item-content] {
5038
5092
  flex: none;
5039
5093
  }
@@ -5155,6 +5209,18 @@
5155
5209
  background-color: color-mix(in oklab, var(--muted) 72%, transparent);
5156
5210
  }
5157
5211
  }
5212
+ .\[\&\:nth-child\(1_of_\:not\(\[hidden\]\)\)\]\:rounded-t-\[var\(--card-section-corner\,0px\)\]:nth-child(1 of :not([hidden])) {
5213
+ border-top-left-radius: var(--card-section-corner,0px);
5214
+ border-top-right-radius: var(--card-section-corner,0px);
5215
+ }
5216
+ .\[\&\:nth-child\(1_of_\:not\(\[hidden\]\)\)\]\:border-t-0:nth-child(1 of :not([hidden])) {
5217
+ border-top-style: var(--tw-border-style);
5218
+ border-top-width: 0px;
5219
+ }
5220
+ .\[\&\:nth-last-child\(1_of_\:not\(\[hidden\]\)\)\]\:rounded-b-\[var\(--card-section-corner\,0px\)\]:nth-last-child(1 of :not([hidden])) {
5221
+ border-bottom-right-radius: var(--card-section-corner,0px);
5222
+ border-bottom-left-radius: var(--card-section-corner,0px);
5223
+ }
5158
5224
  .\[\&\>\.sr-only\]\:w-auto > .sr-only {
5159
5225
  width: auto;
5160
5226
  }
@@ -5316,6 +5382,9 @@
5316
5382
  .\[\&\[data-ending-style\]\:not\(\[data-limited\]\)\:not\(\[data-swipe-direction\]\)\]\:\[transform\:translateY\(calc\(var\(--side\)\*150\%\)\)\][data-ending-style]:not([data-limited]):not([data-swipe-direction]) {
5317
5383
  transform: translateY(calc(var(--side) * 150%));
5318
5384
  }
5385
+ .\[\&\[hidden\]\:not\(\[hidden\=until-found\]\)\]\:hidden[hidden]:not([hidden=until-found]) {
5386
+ display: none;
5387
+ }
5319
5388
  .\[\&\[readonly\]\:not\(\:disabled\)\]\:bg-muted[readonly]:not(:disabled) {
5320
5389
  background-color: var(--muted);
5321
5390
  }
@@ -5365,6 +5434,31 @@
5365
5434
  :where(.\[\:where\(\&\>\*\)\]\:ring-background > *) {
5366
5435
  --tw-ring-color: var(--background);
5367
5436
  }
5437
+ :where([data-layout=inline]) > .\[\:where\(\[data-layout\=inline\]\)\>\&\]\:col-start-2 {
5438
+ grid-column-start: 2;
5439
+ }
5440
+ :where([data-layout=inline]) > .\[\:where\(\[data-layout\=inline\]\)\>\&\]\:min-w-0 {
5441
+ min-width: 0px;
5442
+ }
5443
+ :where([data-layout=inline]) > .\[\:where\(\[data-layout\=inline\]\)\>\&\]\:border-none {
5444
+ --tw-border-style: none;
5445
+ border-style: none;
5446
+ }
5447
+ :where([data-layout=inline]) > .\[\:where\(\[data-layout\=inline\]\)\>\&\]\:p-0 {
5448
+ padding: 0px;
5449
+ }
5450
+ :where([data-layout=inline]) > .\[\:where\(\[data-layout\=inline\]\)\>\&\]\:py-0 {
5451
+ padding-block: 0px;
5452
+ }
5453
+ :where([data-layout=inline]) > .\[\:where\(\[data-layout\=inline\]\)\>\&\]\:text-end {
5454
+ text-align: end;
5455
+ }
5456
+ :where([data-layout=inline]) > .\[\:where\(\[data-layout\=inline\]\)\>\&\]\:wrap-anywhere {
5457
+ overflow-wrap: anywhere;
5458
+ }
5459
+ :where([data-slot=card-section]) > .\[\:where\(\[data-slot\=card-section\]\)\>\&\]\:p-0 {
5460
+ padding: 0px;
5461
+ }
5368
5462
  [data-placement] > .\[\[data-placement\]\>\&\]\:p-0 {
5369
5463
  padding: 0px;
5370
5464
  }
package/themes.css CHANGED
@@ -80,6 +80,7 @@
80
80
  --input: oklch(0.9219 0 0);
81
81
  --ring: oklch(0.6 0 0);
82
82
  --card-border: var(--border);
83
+ --card-section-divider: var(--border);
83
84
  --button-outline: var(--border);
84
85
  --selection-border: var(--border);
85
86
  --selection-checked-border: var(--primary);
@@ -201,6 +202,7 @@
201
202
  --input: oklch(0.9219 0 0);
202
203
  --ring: oklch(0.6 0 0);
203
204
  --card-border: var(--border);
205
+ --card-section-divider: var(--border);
204
206
  --button-outline: var(--border);
205
207
  --selection-border: var(--border);
206
208
  --selection-checked-border: var(--primary);
@@ -247,6 +249,7 @@
247
249
  --input: oklch(0.9232 0.0026 48.72);
248
250
  --ring: oklch(0.6 0 0);
249
251
  --card-border: oklch(0 0 0 / 0);
252
+ --card-section-divider: var(--background);
250
253
  --button-outline: var(--foreground);
251
254
  --selection-border: oklch(0 0 0 / 0);
252
255
  --selection-checked-border: var(--selection-border);
@@ -313,6 +316,7 @@
313
316
  --input: oklch(0.929 0.0126 255.53);
314
317
  --ring: oklch(0.6 0 0);
315
318
  --card-border: oklch(0 0 0 / 0);
319
+ --card-section-divider: var(--background);
316
320
  --button-outline: var(--foreground);
317
321
  --selection-border: oklch(0 0 0 / 0);
318
322
  --selection-checked-border: var(--selection-border);
@@ -359,6 +363,7 @@
359
363
  --input: oklch(0.929 0.0126 255.53);
360
364
  --ring: oklch(0.6 0 0);
361
365
  --card-border: oklch(0 0 0 / 0);
366
+ --card-section-divider: var(--background);
362
367
  --button-outline: var(--foreground);
363
368
  --selection-border: oklch(0 0 0 / 0);
364
369
  --selection-checked-border: var(--selection-border);
@@ -405,6 +410,7 @@
405
410
  --input: oklch(0.9232 0.0026 48.72);
406
411
  --ring: oklch(0.6 0 0);
407
412
  --card-border: oklch(0 0 0 / 0);
413
+ --card-section-divider: var(--background);
408
414
  --button-outline: var(--foreground);
409
415
  --selection-border: oklch(0 0 0 / 0);
410
416
  --selection-checked-border: var(--selection-border);
@@ -451,6 +457,7 @@
451
457
  --input: oklch(0.9232 0.0026 48.72);
452
458
  --ring: oklch(0.6 0 0);
453
459
  --card-border: oklch(0 0 0 / 0);
460
+ --card-section-divider: var(--background);
454
461
  --button-outline: var(--foreground);
455
462
  --selection-border: oklch(0 0 0 / 0);
456
463
  --selection-checked-border: var(--selection-border);
@@ -497,6 +504,7 @@
497
504
  --input: oklch(0.9219 0 0);
498
505
  --ring: oklch(0.6 0 0);
499
506
  --card-border: oklch(0 0 0 / 0);
507
+ --card-section-divider: var(--background);
500
508
  --button-outline: var(--foreground);
501
509
  --selection-border: oklch(0 0 0 / 0);
502
510
  --selection-checked-border: var(--selection-border);
@@ -543,6 +551,7 @@
543
551
  --input: oklch(0.8256644 0.0145962 162.3965393);
544
552
  --ring: oklch(0.6 0 0);
545
553
  --card-border: oklch(0 0 0 / 0);
554
+ --card-section-divider: var(--background);
546
555
  --button-outline: var(--foreground);
547
556
  --selection-border: oklch(0 0 0 / 0);
548
557
  --selection-checked-border: var(--selection-border);
@@ -612,6 +621,7 @@
612
621
  --input: oklch(1 0 0 / 40%);
613
622
  --ring: oklch(0.6 0 0);
614
623
  --card-border: var(--border);
624
+ --card-section-divider: var(--border);
615
625
  --button-outline: var(--border);
616
626
  --selection-border: var(--border);
617
627
  --selection-checked-border: var(--primary);
@@ -747,6 +757,7 @@
747
757
  --input: oklch(0.6543689 0.0037291 145.5328);
748
758
  --ring: oklch(0.6 0 0);
749
759
  --card-border: oklch(0 0 0 / 0);
760
+ --card-section-divider: var(--background);
750
761
  --button-outline: var(--foreground);
751
762
  --selection-border: oklch(0 0 0 / 0);
752
763
  --selection-checked-border: var(--selection-border);
@@ -846,6 +857,7 @@
846
857
  --input: oklch(0.6543689 0.0037291 145.5328);
847
858
  --ring: oklch(0.6 0 0);
848
859
  --card-border: oklch(0 0 0 / 0);
860
+ --card-section-divider: var(--background);
849
861
  --button-outline: var(--foreground);
850
862
  --selection-border: oklch(0 0 0 / 0);
851
863
  --selection-checked-border: var(--selection-border);
@@ -945,6 +957,7 @@
945
957
  --input: oklch(0.6543689 0.0037291 145.5328);
946
958
  --ring: oklch(0.6 0 0);
947
959
  --card-border: oklch(0 0 0 / 0);
960
+ --card-section-divider: var(--background);
948
961
  --button-outline: var(--foreground);
949
962
  --selection-border: oklch(0 0 0 / 0);
950
963
  --selection-checked-border: var(--selection-border);
@@ -1044,6 +1057,7 @@
1044
1057
  --input: oklch(0.6543689 0.0037291 145.5328);
1045
1058
  --ring: oklch(0.6 0 0);
1046
1059
  --card-border: oklch(0 0 0 / 0);
1060
+ --card-section-divider: var(--background);
1047
1061
  --button-outline: var(--foreground);
1048
1062
  --selection-border: oklch(0 0 0 / 0);
1049
1063
  --selection-checked-border: var(--selection-border);
@@ -1143,6 +1157,7 @@
1143
1157
  --input: oklch(0.6543689 0.0037291 145.5328);
1144
1158
  --ring: oklch(0.6 0 0);
1145
1159
  --card-border: oklch(0 0 0 / 0);
1160
+ --card-section-divider: var(--background);
1146
1161
  --button-outline: var(--foreground);
1147
1162
  --selection-border: oklch(0 0 0 / 0);
1148
1163
  --selection-checked-border: var(--selection-border);
@@ -1242,6 +1257,7 @@
1242
1257
  --input: oklch(0.6543689 0.0037291 145.5328);
1243
1258
  --ring: oklch(0.6 0 0);
1244
1259
  --card-border: oklch(0 0 0 / 0);
1260
+ --card-section-divider: var(--background);
1245
1261
  --button-outline: var(--foreground);
1246
1262
  --selection-border: oklch(0 0 0 / 0);
1247
1263
  --selection-checked-border: var(--selection-border);
@@ -1341,6 +1357,7 @@
1341
1357
  --input: oklch(0.6543689 0.0037291 145.5328);
1342
1358
  --ring: oklch(0.6 0 0);
1343
1359
  --card-border: oklch(0 0 0 / 0);
1360
+ --card-section-divider: var(--background);
1344
1361
  --button-outline: var(--foreground);
1345
1362
  --selection-border: oklch(0 0 0 / 0);
1346
1363
  --selection-checked-border: var(--selection-border);
@@ -1440,6 +1457,7 @@
1440
1457
  --input: oklch(0.6543689 0.0037291 145.5328);
1441
1458
  --ring: oklch(0.6 0 0);
1442
1459
  --card-border: oklch(0 0 0 / 0);
1460
+ --card-section-divider: var(--background);
1443
1461
  --button-outline: var(--foreground);
1444
1462
  --selection-border: oklch(0 0 0 / 0);
1445
1463
  --selection-checked-border: var(--selection-border);