@particle-academy/react-fancy 5.29.1 → 5.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +1722 -0
  2. package/dist/Card-CuRZivBz.d.cts +136 -0
  3. package/dist/Card-CuRZivBz.d.ts +136 -0
  4. package/dist/card.cjs +12 -6
  5. package/dist/card.d.cts +50 -3
  6. package/dist/card.d.ts +50 -3
  7. package/dist/card.js +3 -1
  8. package/dist/chunk-5F6V5HHT.cjs +399 -0
  9. package/dist/chunk-5F6V5HHT.cjs.map +1 -0
  10. package/dist/{chunk-Y3T7WMT6.cjs → chunk-65HKNZFG.cjs} +2 -2
  11. package/dist/{chunk-Y3T7WMT6.cjs.map → chunk-65HKNZFG.cjs.map} +1 -1
  12. package/dist/chunk-7MSIREUY.cjs +186 -0
  13. package/dist/chunk-7MSIREUY.cjs.map +1 -0
  14. package/dist/{chunk-2HGYDDIQ.js → chunk-ASCATIDJ.js} +3 -3
  15. package/dist/{chunk-2HGYDDIQ.js.map → chunk-ASCATIDJ.js.map} +1 -1
  16. package/dist/{chunk-6GWOB2Z4.js → chunk-CESGP5AF.js} +2 -2
  17. package/dist/{chunk-6GWOB2Z4.js.map → chunk-CESGP5AF.js.map} +1 -1
  18. package/dist/chunk-CF2U25LM.js +392 -0
  19. package/dist/chunk-CF2U25LM.js.map +1 -0
  20. package/dist/chunk-CFH6CJQG.js +3 -0
  21. package/dist/chunk-CFH6CJQG.js.map +1 -0
  22. package/dist/chunk-FJKZ5NOA.cjs +4 -0
  23. package/dist/chunk-FJKZ5NOA.cjs.map +1 -0
  24. package/dist/chunk-NH5XJ6VD.js +184 -0
  25. package/dist/chunk-NH5XJ6VD.js.map +1 -0
  26. package/dist/{chunk-FEUAZW3X.cjs → chunk-SCGE6DCE.cjs} +3 -3
  27. package/dist/{chunk-FEUAZW3X.cjs.map → chunk-SCGE6DCE.cjs.map} +1 -1
  28. package/dist/composer.cjs +2 -2
  29. package/dist/composer.d.cts +34 -1
  30. package/dist/composer.d.ts +34 -1
  31. package/dist/composer.js +1 -1
  32. package/dist/heading.cjs +3 -2
  33. package/dist/heading.js +2 -1
  34. package/dist/index.cjs +28 -27
  35. package/dist/index.d.cts +2 -2
  36. package/dist/index.d.ts +2 -2
  37. package/dist/index.js +6 -5
  38. package/dist/json-editor.cjs +13 -13
  39. package/dist/json-editor.js +2 -2
  40. package/docs/Card.md +170 -20
  41. package/package.json +6 -3
  42. package/dist/Card-BZ5F6-wd.d.cts +0 -50
  43. package/dist/Card-BZ5F6-wd.d.ts +0 -50
  44. package/dist/chunk-5DQ2XUJI.cjs +0 -173
  45. package/dist/chunk-5DQ2XUJI.cjs.map +0 -1
  46. package/dist/chunk-OGEE23SP.cjs +0 -83
  47. package/dist/chunk-OGEE23SP.cjs.map +0 -1
  48. package/dist/chunk-VVL5LMLW.js +0 -81
  49. package/dist/chunk-VVL5LMLW.js.map +0 -1
  50. package/dist/chunk-ZIDBI6JX.js +0 -167
  51. package/dist/chunk-ZIDBI6JX.js.map +0 -1
package/docs/Card.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Card
2
2
 
3
- A container component with optional header, body, and footer sections. Uses `Object.assign` to expose compound sub-components.
3
+ A container with optional media, header, body and footer sections. `Object.assign` exposes the sub-components as compound members (`Card.Header`, `Card.Bleed`, …).
4
4
 
5
5
  ## Import
6
6
 
@@ -16,53 +16,203 @@ import { Card } from "@particle-academy/react-fancy";
16
16
  </Card>
17
17
  ```
18
18
 
19
+ ## Padding sits on the children, not the card
20
+
21
+ This is the one thing worth knowing before anything else, because most of the
22
+ rest follows from it. `padding` compiles to `[&>*]:px-4 [&>*]:py-3` — an inset
23
+ on every **direct child** of the card, not on the card itself.
24
+
25
+ That is why a full-bleed child (`Card.Media`, `Card.Bleed`) can opt out with
26
+ `!px-0` instead of having to undo padding already baked into the frame, and why
27
+ there is no `gap` prop: each child carries its own `py-*`, so two adjacent
28
+ sections already have twice that between their content.
29
+
30
+ It also means anything that must line up with the content's edge — an inset
31
+ divider, a bleed — is derived from the **padding step**, never from `size`.
32
+ `size` only picks the default step; `padding` overrides it.
33
+
19
34
  ## Card Props
20
35
 
21
36
  | Prop | Type | Default | Description |
22
37
  |------|------|---------|-------------|
23
- | variant | `"outlined" \| "elevated" \| "flat"` | `"outlined"` | Visual variant |
24
- | padding | `"none" \| "sm" \| "md" \| "lg"` | `"md"` | Padding applied to child sections |
38
+ | variant | `"outlined" \| "elevated" \| "flat" \| "muted" \| "soft"` | `"outlined"` | Surface treatment. `outlined` is untinted with a border; `elevated` adds `shadow-md`; `soft` → `flat` → `muted` is a ramp of increasingly strong tints, all borderless |
39
+ | size | `"xs" \| "sm" \| "md" \| "lg"` | `"md"` | Scales padding and corner radius together, and is inherited by `Card.Media` and `Card.Bleed` |
40
+ | padding | `"none" \| "xs" \| "sm" \| "md" \| "lg"` | the step `size` implies | The inset applied to every direct child. Pass it to override `size`, including `"none"` |
41
+ | sections | `"divided" \| "plain" \| "banded"` | `"divided"` | How `Card.Header` / `Card.Footer` are set apart: a hairline rule, nothing, or a tinted band |
42
+ | dividerInset | `boolean` | `false` | With `sections="divided"`, stop the rules at the content's edge instead of running them across the card |
43
+ | highlight | `boolean` | `false` | A 1px hairline just inside the top edge — white at 70% in light mode, white at 10% in dark. Reads on a tinted or elevated surface; invisible on an untinted white one |
44
+ | interactive | `boolean` | `false` | Card is a link or a grid tile: hover lift, border and shadow response, and `overflow-hidden` so a `Card.Media` is clipped to the rounded corners |
25
45
 
26
46
  Also extends all native `<div>` HTML attributes.
27
47
 
48
+ `sections`, `size`, `padding` and `dividerInset` are passed down through context,
49
+ so the sub-components never need them repeated.
50
+
28
51
  ## Sub-Components
29
52
 
30
- ### Card.Header
53
+ ### Card.Media
54
+
55
+ The fixed-ratio media region at the top of a card: a thumbnail, gradient or
56
+ solid swatch, with slots pinned to its corners. Opts out of the card's padding,
57
+ and rounds its top corners to match the card's `size`.
58
+
59
+ | Prop | Type | Default | Description |
60
+ |------|------|---------|-------------|
61
+ | src | `string` | - | Image URL. Omit for a pure colour or gradient tile |
62
+ | alt | `string` | `""` | Alt text for the image |
63
+ | ratio | `string` | `"16/9"` | CSS `aspect-ratio`. Ignored when `height` is set |
64
+ | height | `number \| string` | - | Fixed height instead of an aspect ratio |
65
+ | background | `string` | - | Any CSS background value. Shows **under** the image — while it loads, and permanently if it never arrives, so a missing thumbnail degrades to a colour rather than a hole |
66
+ | objectPosition | `string` | `"center"` | `object-position` for the image |
67
+ | loading | `"lazy" \| "eager"` | `"lazy"` | Image loading strategy |
68
+ | topLeft / topRight / bottomLeft / bottomRight | `ReactNode` | - | Slots pinned to the media's corners — a number chip, a status pill |
69
+
70
+ ### Card.Header / Card.Footer
71
+
72
+ The same component with the rule on opposite edges. Either can be composed from
73
+ props, or given `children` for full control.
74
+
75
+ | Prop | Type | Default | Description |
76
+ |------|------|---------|-------------|
77
+ | heading | `ReactNode` | - | The title. Rendered through `<Heading>` and tagged `data-react-fancy-card-heading` |
78
+ | headingLevel | `"h1"…"h6"` | `"h3"` | Which heading element to render |
79
+ | description | `ReactNode` | - | Supporting line under the heading. Rendered through a muted `<Text>`, tagged `data-react-fancy-card-description` |
80
+ | actions | `ReactNode` | - | Controls pushed to the far end, vertically centred on the heading. Tagged `data-react-fancy-card-actions` |
81
+ | size | `"xs" \| "sm" \| "md" \| "lg"` | `"md"` | **Only used with no `Card` above** — a standalone section has no card to inherit a size from |
82
+ | children | `ReactNode` | - | Full control. **Wins over** `heading` / `description` / `actions` rather than rendering alongside them |
31
83
 
32
- Renders a section with a bottom border. Accepts all `<div>` HTML attributes.
84
+ Both work **standalone**, outside a `Card`, as a section heading above one. A
85
+ standalone section pads itself and draws no rule — there is no card whose edge
86
+ it could be dividing.
33
87
 
34
88
  ### Card.Body
35
89
 
36
- Renders a plain content section. Accepts all `<div>` HTML attributes.
90
+ A plain content section. Carries no classes of its own: the card pads it through
91
+ `[&>*]`. Accepts all `<div>` HTML attributes.
37
92
 
38
- ### Card.Footer
93
+ ### Card.Bleed
39
94
 
40
- Renders a section with a top border. Accepts all `<div>` HTML attributes.
95
+ Runs content out to the card's edges — an image, a table, a chart strip.
96
+
97
+ | Prop | Type | Default | Description |
98
+ |------|------|---------|-------------|
99
+ | edges | `"x" \| "top" \| "bottom" \| "all"` | `"x"` | Which edges to reach. `"x"` is the sides only, which is what an inline image or table wants |
100
+
101
+ Two cases, handled automatically:
102
+
103
+ - **Inside a `Card.Header` / `Card.Body` / `Card.Footer`** — the padding is on
104
+ that section, so the bleed escapes it with a negative margin.
105
+ - **As a direct child of `Card`** — the bleed *is* the padded element, so it
106
+ zeroes its own padding instead. A negative margin here would pull the content
107
+ clean outside the card.
108
+
109
+ `edges` cancels the padding of **the element the bleed sits in**, which is the
110
+ card's edge only when the bleed is actually at that edge. `edges="top"` on a
111
+ bleed halfway down a body pulls it up over the preceding content instead — use
112
+ `"top"` when the bleed is the first thing in the card, `"bottom"` when it is the
113
+ last, and `"x"` everywhere in between.
114
+
115
+ Corners are rounded only where the content meets the card, so a mid-body strip
116
+ stays square while one at the top follows the card's radius.
41
117
 
42
118
  ## Examples
43
119
 
44
- ### Full card with sections
120
+ ### Full card with a composed header
121
+
122
+ No layout wrapper from the caller — `heading` / `description` / `actions` lay
123
+ themselves out.
45
124
 
46
125
  ```tsx
47
- <Card variant="elevated" padding="lg">
48
- <Card.Header>
49
- <h3 className="font-semibold">Settings</h3>
50
- </Card.Header>
126
+ <Card variant="elevated" size="lg">
127
+ <Card.Header
128
+ heading="Billing"
129
+ description="Cards, invoices and receipts"
130
+ actions={<Button size="sm">Edit</Button>}
131
+ />
51
132
  <Card.Body>
52
- <p>Configure your preferences below.</p>
133
+ <Text>Configure your preferences below.</Text>
53
134
  </Card.Body>
54
- <Card.Footer>
55
- <button>Save</button>
56
- </Card.Footer>
135
+ <Card.Footer actions={<Button>Save</Button>} />
57
136
  </Card>
58
137
  ```
59
138
 
60
- ### Flat card without header
139
+ ### A media card
61
140
 
62
141
  ```tsx
63
- <Card variant="flat">
142
+ <Card interactive>
143
+ <Card.Media
144
+ src="/covers/atlas.jpg"
145
+ alt="Atlas"
146
+ background="linear-gradient(135deg,#6366f1,#8b5cf6)"
147
+ topRight={<Badge>new</Badge>}
148
+ />
149
+ <Card.Header heading="Atlas" description="Updated 2 days ago" />
150
+ </Card>
151
+ ```
152
+
153
+ `background` is not decoration: it shows while the image loads and stays if the
154
+ image never arrives.
155
+
156
+ ### Seamless sections
157
+
158
+ ```tsx
159
+ <Card sections="plain">
160
+ <Card.Header heading="No rules" />
161
+ <Card.Body>…</Card.Body>
162
+ </Card>
163
+ ```
164
+
165
+ `"banded"` tints the header and footer instead; `dividerInset` keeps the rules
166
+ but stops them at the content's edge.
167
+
168
+ ### A full-bleed table
169
+
170
+ ```tsx
171
+ <Card>
172
+ <Card.Header heading="Invoices" />
64
173
  <Card.Body>
65
- <p>A simple flat card.</p>
174
+ <Card.Bleed>
175
+ <Table data={invoices} />
176
+ </Card.Bleed>
66
177
  </Card.Body>
67
178
  </Card>
68
179
  ```
180
+
181
+ ### A heading above a card
182
+
183
+ ```tsx
184
+ <Card.Header heading="Team" description="4 members" actions={<Button size="sm">Invite</Button>} />
185
+ <Card>
186
+ <Card.Body>…</Card.Body>
187
+ </Card>
188
+ ```
189
+
190
+ ### An escape hatch
191
+
192
+ `children` wins over the composition props, so an unusual header is still a
193
+ `Card.Header`:
194
+
195
+ ```tsx
196
+ <Card>
197
+ <Card.Header>
198
+ <Profile name="Ada" role="Owner" />
199
+ </Card.Header>
200
+ <Card.Body>…</Card.Body>
201
+ </Card>
202
+ ```
203
+
204
+ ## Data attributes
205
+
206
+ | Selector | Element |
207
+ |----------|---------|
208
+ | `[data-react-fancy-card]` | the card |
209
+ | `[data-react-fancy-card-media]` | `Card.Media` |
210
+ | `[data-react-fancy-card-header]` | `Card.Header` |
211
+ | `[data-react-fancy-card-body]` | `Card.Body` |
212
+ | `[data-react-fancy-card-footer]` | `Card.Footer` |
213
+ | `[data-react-fancy-card-bleed]` | `Card.Bleed` |
214
+ | `[data-react-fancy-card-heading]` | the `heading` a section rendered |
215
+ | `[data-react-fancy-card-description]` | the `description` a section rendered |
216
+ | `[data-react-fancy-card-actions]` | the `actions` a section rendered |
217
+
218
+ See [STYLE.md](../STYLE.md) for theming through these.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@particle-academy/react-fancy",
3
- "version": "5.29.1",
3
+ "version": "5.31.0",
4
4
  "description": "React UI component library for Human+ UX — controlled, agent-bridgeable primitives",
5
5
  "repository": {
6
6
  "type": "git",
@@ -928,7 +928,8 @@
928
928
  "files": [
929
929
  "dist",
930
930
  "docs",
931
- "README.md"
931
+ "README.md",
932
+ "CHANGELOG.md"
932
933
  ],
933
934
  "scripts": {
934
935
  "build": "node --max-old-space-size=8192 ./node_modules/tsup/dist/cli-default.js",
@@ -979,7 +980,9 @@
979
980
  "**/*.css"
980
981
  ],
981
982
  "overrides": {
982
- "esbuild": "^0.28.1"
983
+ "esbuild": "^0.28.1",
984
+ "brace-expansion": "^5.0.12",
985
+ "undici": "^7.29.1"
983
986
  },
984
987
  "engines": {
985
988
  "node": ">=22"
@@ -1,50 +0,0 @@
1
- import * as react from 'react';
2
- import { HTMLAttributes, ReactNode } from 'react';
3
-
4
- interface CardProps extends HTMLAttributes<HTMLDivElement> {
5
- variant?: "outlined" | "elevated" | "flat";
6
- padding?: "none" | "sm" | "md" | "lg";
7
- /**
8
- * Card is a link or a grid tile: adds the hover lift + border/shadow
9
- * response, and clips children to the rounded corners so a `Card.Media`
10
- * sits flush.
11
- */
12
- interactive?: boolean;
13
- }
14
- interface CardMediaProps extends HTMLAttributes<HTMLDivElement> {
15
- /** Image URL. Omit for a pure colour/gradient tile. */
16
- src?: string;
17
- alt?: string;
18
- /** CSS `aspect-ratio`. Default `"16/9"`. Ignored when `height` is set. */
19
- ratio?: string;
20
- /** Fixed height instead of an aspect ratio. */
21
- height?: number | string;
22
- /**
23
- * Shown UNDER the image — while it loads, and permanently if it never
24
- * arrives. Any CSS background value, so a gradient works.
25
- */
26
- background?: string;
27
- /** `object-position` for the image. Default `"center"`. */
28
- objectPosition?: string;
29
- loading?: "lazy" | "eager";
30
- /** Slots pinned to the media's corners — a number chip, a status pill. */
31
- topLeft?: ReactNode;
32
- topRight?: ReactNode;
33
- bottomLeft?: ReactNode;
34
- bottomRight?: ReactNode;
35
- }
36
- interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {
37
- }
38
- interface CardBodyProps extends HTMLAttributes<HTMLDivElement> {
39
- }
40
- interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {
41
- }
42
-
43
- declare const Card: react.ForwardRefExoticComponent<CardProps & react.RefAttributes<HTMLDivElement>> & {
44
- Media: react.ForwardRefExoticComponent<CardMediaProps & react.RefAttributes<HTMLDivElement>>;
45
- Header: react.ForwardRefExoticComponent<CardHeaderProps & react.RefAttributes<HTMLDivElement>>;
46
- Body: react.ForwardRefExoticComponent<CardBodyProps & react.RefAttributes<HTMLDivElement>>;
47
- Footer: react.ForwardRefExoticComponent<CardFooterProps & react.RefAttributes<HTMLDivElement>>;
48
- };
49
-
50
- export { type CardHeaderProps as C, type CardBodyProps as a, type CardFooterProps as b, type CardMediaProps as c, Card as d, type CardProps as e };
@@ -1,50 +0,0 @@
1
- import * as react from 'react';
2
- import { HTMLAttributes, ReactNode } from 'react';
3
-
4
- interface CardProps extends HTMLAttributes<HTMLDivElement> {
5
- variant?: "outlined" | "elevated" | "flat";
6
- padding?: "none" | "sm" | "md" | "lg";
7
- /**
8
- * Card is a link or a grid tile: adds the hover lift + border/shadow
9
- * response, and clips children to the rounded corners so a `Card.Media`
10
- * sits flush.
11
- */
12
- interactive?: boolean;
13
- }
14
- interface CardMediaProps extends HTMLAttributes<HTMLDivElement> {
15
- /** Image URL. Omit for a pure colour/gradient tile. */
16
- src?: string;
17
- alt?: string;
18
- /** CSS `aspect-ratio`. Default `"16/9"`. Ignored when `height` is set. */
19
- ratio?: string;
20
- /** Fixed height instead of an aspect ratio. */
21
- height?: number | string;
22
- /**
23
- * Shown UNDER the image — while it loads, and permanently if it never
24
- * arrives. Any CSS background value, so a gradient works.
25
- */
26
- background?: string;
27
- /** `object-position` for the image. Default `"center"`. */
28
- objectPosition?: string;
29
- loading?: "lazy" | "eager";
30
- /** Slots pinned to the media's corners — a number chip, a status pill. */
31
- topLeft?: ReactNode;
32
- topRight?: ReactNode;
33
- bottomLeft?: ReactNode;
34
- bottomRight?: ReactNode;
35
- }
36
- interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {
37
- }
38
- interface CardBodyProps extends HTMLAttributes<HTMLDivElement> {
39
- }
40
- interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {
41
- }
42
-
43
- declare const Card: react.ForwardRefExoticComponent<CardProps & react.RefAttributes<HTMLDivElement>> & {
44
- Media: react.ForwardRefExoticComponent<CardMediaProps & react.RefAttributes<HTMLDivElement>>;
45
- Header: react.ForwardRefExoticComponent<CardHeaderProps & react.RefAttributes<HTMLDivElement>>;
46
- Body: react.ForwardRefExoticComponent<CardBodyProps & react.RefAttributes<HTMLDivElement>>;
47
- Footer: react.ForwardRefExoticComponent<CardFooterProps & react.RefAttributes<HTMLDivElement>>;
48
- };
49
-
50
- export { type CardHeaderProps as C, type CardBodyProps as a, type CardFooterProps as b, type CardMediaProps as c, Card as d, type CardProps as e };
@@ -1,173 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkZU5Q77OT_cjs = require('./chunk-ZU5Q77OT.cjs');
4
- var react = require('react');
5
- var jsxRuntime = require('react/jsx-runtime');
6
-
7
- var CardHeader = react.forwardRef(
8
- ({ className, children, ...props }, ref) => {
9
- return /* @__PURE__ */ jsxRuntime.jsx(
10
- "div",
11
- {
12
- ref,
13
- "data-react-fancy-card-header": "",
14
- className: chunkZU5Q77OT_cjs.cn(
15
- "border-b border-zinc-200 dark:border-zinc-700",
16
- className
17
- ),
18
- ...props,
19
- children
20
- }
21
- );
22
- }
23
- );
24
- CardHeader.displayName = "CardHeader";
25
- var CardBody = react.forwardRef(
26
- ({ className, children, ...props }, ref) => {
27
- return /* @__PURE__ */ jsxRuntime.jsx(
28
- "div",
29
- {
30
- ref,
31
- "data-react-fancy-card-body": "",
32
- className: chunkZU5Q77OT_cjs.cn(className),
33
- ...props,
34
- children
35
- }
36
- );
37
- }
38
- );
39
- CardBody.displayName = "CardBody";
40
- var CardFooter = react.forwardRef(
41
- ({ className, children, ...props }, ref) => {
42
- return /* @__PURE__ */ jsxRuntime.jsx(
43
- "div",
44
- {
45
- ref,
46
- "data-react-fancy-card-footer": "",
47
- className: chunkZU5Q77OT_cjs.cn(
48
- "border-t border-zinc-200 dark:border-zinc-700",
49
- className
50
- ),
51
- ...props,
52
- children
53
- }
54
- );
55
- }
56
- );
57
- CardFooter.displayName = "CardFooter";
58
- var CardMedia = react.forwardRef(
59
- ({
60
- src,
61
- alt = "",
62
- ratio = "16/9",
63
- height,
64
- background,
65
- objectPosition = "center",
66
- loading = "lazy",
67
- topLeft,
68
- topRight,
69
- bottomLeft,
70
- bottomRight,
71
- className,
72
- style,
73
- children,
74
- ...props
75
- }, ref) => {
76
- return /* @__PURE__ */ jsxRuntime.jsxs(
77
- "div",
78
- {
79
- ref,
80
- "data-react-fancy-card-media": "",
81
- className: chunkZU5Q77OT_cjs.cn(
82
- "relative overflow-hidden rounded-t-lg",
83
- // Card's `padding` prop pads EVERY direct child
84
- // (`[&>*]:px-4 …`), which would inset the media and break the
85
- // flush-to-the-edge look every caller wants. `!` wins regardless of
86
- // stylesheet order, which plain `p-0` would not.
87
- "!px-0 !py-0",
88
- className
89
- ),
90
- style: {
91
- ...height === void 0 ? { aspectRatio: ratio } : { height },
92
- ...background ? { background } : null,
93
- ...style
94
- },
95
- ...props,
96
- children: [
97
- src ? /* @__PURE__ */ jsxRuntime.jsx(
98
- "img",
99
- {
100
- src,
101
- alt,
102
- loading,
103
- className: "absolute inset-0 h-full w-full object-cover",
104
- style: { objectPosition }
105
- }
106
- ) : null,
107
- children,
108
- topLeft ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-2 top-2 z-10", children: topLeft }) : null,
109
- topRight ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute right-2 top-2 z-10", children: topRight }) : null,
110
- bottomLeft ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute bottom-2 left-2 z-10", children: bottomLeft }) : null,
111
- bottomRight ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute bottom-2 right-2 z-10", children: bottomRight }) : null
112
- ]
113
- }
114
- );
115
- }
116
- );
117
- CardMedia.displayName = "CardMedia";
118
- var variantClasses = {
119
- outlined: "border border-zinc-200 dark:border-zinc-700",
120
- elevated: "shadow-md border border-zinc-100 dark:border-zinc-800",
121
- flat: "bg-zinc-50 dark:bg-zinc-800/50"
122
- };
123
- var paddingClasses = {
124
- none: "",
125
- sm: "[&>*]:px-3 [&>*]:py-2",
126
- md: "[&>*]:px-4 [&>*]:py-3",
127
- lg: "[&>*]:px-6 [&>*]:py-4"
128
- };
129
- var CardRoot = react.forwardRef(
130
- ({
131
- variant = "outlined",
132
- padding = "md",
133
- interactive = false,
134
- className,
135
- children,
136
- ...props
137
- }, ref) => {
138
- return /* @__PURE__ */ jsxRuntime.jsx(
139
- "div",
140
- {
141
- ref,
142
- "data-react-fancy-card": "",
143
- className: chunkZU5Q77OT_cjs.cn(
144
- "rounded-lg bg-white dark:bg-zinc-900",
145
- variantClasses[variant],
146
- // `overflow-hidden` is part of `interactive` rather than always-on:
147
- // clipping unconditionally would cut off popovers and dropdowns that
148
- // legitimately overflow a static card.
149
- interactive && "overflow-hidden transition hover:-translate-y-0.5 hover:shadow-lg hover:border-zinc-300 dark:hover:border-zinc-600",
150
- paddingClasses[padding],
151
- className
152
- ),
153
- ...props,
154
- children
155
- }
156
- );
157
- }
158
- );
159
- CardRoot.displayName = "Card";
160
- var Card = Object.assign(CardRoot, {
161
- Media: CardMedia,
162
- Header: CardHeader,
163
- Body: CardBody,
164
- Footer: CardFooter
165
- });
166
-
167
- exports.Card = Card;
168
- exports.CardBody = CardBody;
169
- exports.CardFooter = CardFooter;
170
- exports.CardHeader = CardHeader;
171
- exports.CardMedia = CardMedia;
172
- //# sourceMappingURL=chunk-5DQ2XUJI.cjs.map
173
- //# sourceMappingURL=chunk-5DQ2XUJI.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/Card/CardHeader.tsx","../src/components/Card/CardBody.tsx","../src/components/Card/CardFooter.tsx","../src/components/Card/CardMedia.tsx","../src/components/Card/Card.tsx"],"names":["forwardRef","jsx","cn","jsxs"],"mappings":"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","file":"chunk-5DQ2XUJI.cjs","sourcesContent":["import { forwardRef } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport type { CardHeaderProps } from \"./Card.types\";\n\nexport const CardHeader = forwardRef<HTMLDivElement, CardHeaderProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <div\n ref={ref}\n data-react-fancy-card-header=\"\"\n className={cn(\n \"border-b border-zinc-200 dark:border-zinc-700\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n },\n);\n\nCardHeader.displayName = \"CardHeader\";\n","import { forwardRef } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport type { CardBodyProps } from \"./Card.types\";\n\nexport const CardBody = forwardRef<HTMLDivElement, CardBodyProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <div\n ref={ref}\n data-react-fancy-card-body=\"\"\n className={cn(className)}\n {...props}\n >\n {children}\n </div>\n );\n },\n);\n\nCardBody.displayName = \"CardBody\";\n","import { forwardRef } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport type { CardFooterProps } from \"./Card.types\";\n\nexport const CardFooter = forwardRef<HTMLDivElement, CardFooterProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <div\n ref={ref}\n data-react-fancy-card-footer=\"\"\n className={cn(\n \"border-t border-zinc-200 dark:border-zinc-700\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n },\n);\n\nCardFooter.displayName = \"CardFooter\";\n","import { forwardRef } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport type { CardMediaProps } from \"./Card.types\";\n\n/**\n * The fixed-ratio media region at the top of a card: a thumbnail, gradient or\n * solid swatch, with slots pinned to its corners.\n *\n * This is `Card.Media` rather than a separate `<MediaCard>` because the thing\n * being asked for was never a different card — it was a card with a picture in\n * it. Four surfaces had each rebuilt exactly this (a gallery index, a package\n * grid, a starter-kit grid and a showcase grid) and one of them was already\n * wrapping `Card` and hand-rolling only this region.\n *\n * ## The `background` is not decoration\n *\n * It shows through while the image loads and stays visible if the image never\n * arrives. The gallery relied on that: each style card is keyed to a swatch, so\n * a missing screenshot degrades to the right colour rather than to a hole.\n */\nexport const CardMedia = forwardRef<HTMLDivElement, CardMediaProps>(\n (\n {\n src,\n alt = \"\",\n ratio = \"16/9\",\n height,\n background,\n objectPosition = \"center\",\n loading = \"lazy\",\n topLeft,\n topRight,\n bottomLeft,\n bottomRight,\n className,\n style,\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n data-react-fancy-card-media=\"\"\n className={cn(\n \"relative overflow-hidden rounded-t-lg\",\n // Card's `padding` prop pads EVERY direct child\n // (`[&>*]:px-4 …`), which would inset the media and break the\n // flush-to-the-edge look every caller wants. `!` wins regardless of\n // stylesheet order, which plain `p-0` would not.\n \"!px-0 !py-0\",\n className,\n )}\n style={{\n ...(height === undefined ? { aspectRatio: ratio } : { height }),\n ...(background ? { background } : null),\n ...style,\n }}\n {...props}\n >\n {src ? (\n <img\n src={src}\n alt={alt}\n loading={loading}\n className=\"absolute inset-0 h-full w-full object-cover\"\n style={{ objectPosition }}\n />\n ) : null}\n\n {children}\n\n {topLeft ? <span className=\"absolute left-2 top-2 z-10\">{topLeft}</span> : null}\n {topRight ? <span className=\"absolute right-2 top-2 z-10\">{topRight}</span> : null}\n {bottomLeft ? <span className=\"absolute bottom-2 left-2 z-10\">{bottomLeft}</span> : null}\n {bottomRight ? <span className=\"absolute bottom-2 right-2 z-10\">{bottomRight}</span> : null}\n </div>\n );\n },\n);\n\nCardMedia.displayName = \"CardMedia\";\n","import { forwardRef } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { CardHeader } from \"./CardHeader\";\nimport { CardBody } from \"./CardBody\";\nimport { CardFooter } from \"./CardFooter\";\nimport { CardMedia } from \"./CardMedia\";\nimport type { CardProps } from \"./Card.types\";\n\nconst variantClasses: Record<NonNullable<CardProps[\"variant\"]>, string> = {\n outlined: \"border border-zinc-200 dark:border-zinc-700\",\n elevated: \"shadow-md border border-zinc-100 dark:border-zinc-800\",\n flat: \"bg-zinc-50 dark:bg-zinc-800/50\",\n};\n\n/**\n * Padding is applied to the card's DIRECT CHILDREN rather than the card\n * itself, so a full-bleed child (`Card.Media`) can opt out with `!px-0`\n * without having to undo a padding that is already baked into the frame.\n *\n * The selector is `&>*`, not `&>div`. It was `&>div` until 5.24.0, which meant\n * the tag a caller happened to choose silently decided whether that child was\n * padded: `<Card><div>a</div><p>b</p></Card>` inset the div and left the\n * paragraph hard against the border. Nothing in the caller's code hinted at\n * the rule, and the result read as a bug in the card.\n */\nconst paddingClasses: Record<NonNullable<CardProps[\"padding\"]>, string> = {\n none: \"\",\n sm: \"[&>*]:px-3 [&>*]:py-2\",\n md: \"[&>*]:px-4 [&>*]:py-3\",\n lg: \"[&>*]:px-6 [&>*]:py-4\",\n};\n\nconst CardRoot = forwardRef<HTMLDivElement, CardProps>(\n (\n {\n variant = \"outlined\",\n padding = \"md\",\n interactive = false,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n data-react-fancy-card=\"\"\n className={cn(\n \"rounded-lg bg-white dark:bg-zinc-900\",\n variantClasses[variant],\n // `overflow-hidden` is part of `interactive` rather than always-on:\n // clipping unconditionally would cut off popovers and dropdowns that\n // legitimately overflow a static card.\n interactive &&\n \"overflow-hidden transition hover:-translate-y-0.5 hover:shadow-lg hover:border-zinc-300 dark:hover:border-zinc-600\",\n paddingClasses[padding],\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n },\n);\n\nCardRoot.displayName = \"Card\";\n\nexport const Card = Object.assign(CardRoot, {\n Media: CardMedia,\n Header: CardHeader,\n Body: CardBody,\n Footer: CardFooter,\n});\n"]}
@@ -1,83 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkOUOEQZHY_cjs = require('./chunk-OUOEQZHY.cjs');
4
- var chunkZU5Q77OT_cjs = require('./chunk-ZU5Q77OT.cjs');
5
- var react = require('react');
6
- var jsxRuntime = require('react/jsx-runtime');
7
-
8
- var Composer = react.forwardRef(
9
- function Composer2({
10
- value: controlledValue,
11
- defaultValue = "",
12
- onChange,
13
- onSubmit,
14
- placeholder = "Type a message...",
15
- actions,
16
- disabled = false,
17
- className
18
- }, ref) {
19
- const [value, setValue] = chunkOUOEQZHY_cjs.useControllableState(
20
- controlledValue,
21
- defaultValue,
22
- onChange
23
- );
24
- const textareaRef = react.useRef(null);
25
- const handleSubmit = react.useCallback(() => {
26
- if (!value.trim() || disabled) return;
27
- onSubmit?.(value);
28
- setValue("");
29
- textareaRef.current?.focus();
30
- }, [value, disabled, onSubmit, setValue]);
31
- const handleKeyDown = (e) => {
32
- if (e.key === "Enter" && !e.shiftKey) {
33
- e.preventDefault();
34
- handleSubmit();
35
- }
36
- };
37
- return /* @__PURE__ */ jsxRuntime.jsxs(
38
- "div",
39
- {
40
- "data-react-fancy-composer": "",
41
- ref,
42
- className: chunkZU5Q77OT_cjs.cn(
43
- "rounded-xl border border-zinc-200 bg-white dark:border-zinc-700 dark:bg-zinc-900",
44
- disabled && "opacity-50",
45
- className
46
- ),
47
- children: [
48
- /* @__PURE__ */ jsxRuntime.jsx(
49
- "textarea",
50
- {
51
- ref: textareaRef,
52
- value,
53
- onChange: (e) => setValue(e.target.value),
54
- onKeyDown: handleKeyDown,
55
- placeholder,
56
- disabled,
57
- rows: 3,
58
- className: "w-full resize-none bg-transparent px-4 pt-3 text-sm outline-none placeholder:text-zinc-400"
59
- }
60
- ),
61
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between border-t border-zinc-100 px-3 py-2 dark:border-zinc-800", children: [
62
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: actions }),
63
- /* @__PURE__ */ jsxRuntime.jsx(
64
- "button",
65
- {
66
- type: "button",
67
- onClick: handleSubmit,
68
- disabled: disabled || !value.trim(),
69
- className: "rounded-lg bg-zinc-900 px-3 py-1.5 text-sm font-medium text-white transition-colors hover:bg-zinc-800 disabled:opacity-50 dark:bg-white dark:text-zinc-900 dark:hover:bg-zinc-100",
70
- children: "Send"
71
- }
72
- )
73
- ] })
74
- ]
75
- }
76
- );
77
- }
78
- );
79
- Composer.displayName = "Composer";
80
-
81
- exports.Composer = Composer;
82
- //# sourceMappingURL=chunk-OGEE23SP.cjs.map
83
- //# sourceMappingURL=chunk-OGEE23SP.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/Composer/Composer.tsx"],"names":["forwardRef","Composer","useControllableState","useRef","useCallback","jsxs","cn","jsx"],"mappings":";;;;;;;AAKO,IAAM,QAAA,GAAWA,gBAAA;AAAA,EACtB,SAASC,SAAAA,CACP;AAAA,IACE,KAAA,EAAO,eAAA;AAAA,IACP,YAAA,GAAe,EAAA;AAAA,IACf,QAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA,GAAc,mBAAA;AAAA,IACd,OAAA;AAAA,IACA,QAAA,GAAW,KAAA;AAAA,IACX;AAAA,KAEF,GAAA,EACA;AACA,IAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIC,sCAAA;AAAA,MACxB,eAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,MAAM,WAAA,GAAcC,aAA4B,IAAI,CAAA;AAEpD,IAAA,MAAM,YAAA,GAAeC,kBAAY,MAAM;AACrC,MAAA,IAAI,CAAC,KAAA,CAAM,IAAA,EAAK,IAAK,QAAA,EAAU;AAC/B,MAAA,QAAA,GAAW,KAAK,CAAA;AAChB,MAAA,QAAA,CAAS,EAAE,CAAA;AACX,MAAA,WAAA,CAAY,SAAS,KAAA,EAAM;AAAA,IAC7B,GAAG,CAAC,KAAA,EAAO,QAAA,EAAU,QAAA,EAAU,QAAQ,CAAC,CAAA;AAExC,IAAA,MAAM,aAAA,GAAgB,CAAC,CAAA,KAAgD;AACrE,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,OAAA,IAAW,CAAC,EAAE,QAAA,EAAU;AACpC,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,YAAA,EAAa;AAAA,MACf;AAAA,IACF,CAAA;AAEA,IAAA,uBACEC,eAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,2BAAA,EAA0B,EAAA;AAAA,QAC1B,GAAA;AAAA,QACA,SAAA,EAAWC,oBAAA;AAAA,UACT,kFAAA;AAAA,UACA,QAAA,IAAY,YAAA;AAAA,UACZ;AAAA,SACF;AAAA,QAEA,QAAA,EAAA;AAAA,0BAAAC,cAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,GAAA,EAAK,WAAA;AAAA,cACL,KAAA;AAAA,cACA,UAAU,CAAC,CAAA,KAAM,QAAA,CAAS,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,cACxC,SAAA,EAAW,aAAA;AAAA,cACX,WAAA;AAAA,cACA,QAAA;AAAA,cACA,IAAA,EAAM,CAAA;AAAA,cACN,SAAA,EAAU;AAAA;AAAA,WACZ;AAAA,0BACAF,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,2FAAA,EACb,QAAA,EAAA;AAAA,4BAAAE,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yBAAA,EAA2B,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,4BAClDA,cAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAK,QAAA;AAAA,gBACL,OAAA,EAAS,YAAA;AAAA,gBACT,QAAA,EAAU,QAAA,IAAY,CAAC,KAAA,CAAM,IAAA,EAAK;AAAA,gBAClC,SAAA,EAAU,mLAAA;AAAA,gBACX,QAAA,EAAA;AAAA;AAAA;AAED,WAAA,EACF;AAAA;AAAA;AAAA,KACF;AAAA,EAEJ;AACF;AAEA,QAAA,CAAS,WAAA,GAAc,UAAA","file":"chunk-OGEE23SP.cjs","sourcesContent":["import { forwardRef, useCallback, useRef } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { useControllableState } from \"../../hooks/use-controllable-state\";\nimport type { ComposerProps } from \"./Composer.types\";\n\nexport const Composer = forwardRef<HTMLDivElement, ComposerProps>(\n function Composer(\n {\n value: controlledValue,\n defaultValue = \"\",\n onChange,\n onSubmit,\n placeholder = \"Type a message...\",\n actions,\n disabled = false,\n className,\n },\n ref,\n ) {\n const [value, setValue] = useControllableState(\n controlledValue,\n defaultValue,\n onChange,\n );\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n const handleSubmit = useCallback(() => {\n if (!value.trim() || disabled) return;\n onSubmit?.(value);\n setValue(\"\");\n textareaRef.current?.focus();\n }, [value, disabled, onSubmit, setValue]);\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n };\n\n return (\n <div\n data-react-fancy-composer=\"\"\n ref={ref}\n className={cn(\n \"rounded-xl border border-zinc-200 bg-white dark:border-zinc-700 dark:bg-zinc-900\",\n disabled && \"opacity-50\",\n className,\n )}\n >\n <textarea\n ref={textareaRef}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n rows={3}\n className=\"w-full resize-none bg-transparent px-4 pt-3 text-sm outline-none placeholder:text-zinc-400\"\n />\n <div className=\"flex items-center justify-between border-t border-zinc-100 px-3 py-2 dark:border-zinc-800\">\n <div className=\"flex items-center gap-1\">{actions}</div>\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={disabled || !value.trim()}\n className=\"rounded-lg bg-zinc-900 px-3 py-1.5 text-sm font-medium text-white transition-colors hover:bg-zinc-800 disabled:opacity-50 dark:bg-white dark:text-zinc-900 dark:hover:bg-zinc-100\"\n >\n Send\n </button>\n </div>\n </div>\n );\n },\n);\n\nComposer.displayName = \"Composer\";\n"]}