@yo-yo.art/ui 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -43,7 +43,7 @@ Wrap the interactive components (`ThemeToggle`, `LoadingScreen`,
43
43
 
44
44
  ```text
45
45
  @yo-yo.art/ui components and tokens
46
- @yo-yo.art/ui/gallery loading cover, home button and setup notice
46
+ @yo-yo.art/ui/gallery loading cover, home button, setup notice and artwork panel
47
47
  @yo-yo.art/ui/styles.css design tokens and Tailwind source
48
48
  @yo-yo.art/ui/scenography.css compatibility layer for the overlay presets
49
49
  ```
@@ -0,0 +1,92 @@
1
+ require("../../components/Badge/index.cjs");
2
+ const require_Badge = require("../../components/Badge/Badge.cjs");
3
+ require("../../components/Button/index.cjs");
4
+ const require_Button = require("../../components/Button/Button.cjs");
5
+ require("../../components/Eyebrow/index.cjs");
6
+ const require_Eyebrow = require("../../components/Eyebrow/Eyebrow.cjs");
7
+ require("../../components/IconButton/index.cjs");
8
+ const require_IconButton = require("../../components/IconButton/IconButton.cjs");
9
+ require("../../components/Link/index.cjs");
10
+ const require_Link = require("../../components/Link/Link.cjs");
11
+ const require_cn = require("../../lib/cn.cjs");
12
+ let react_jsx_runtime = require("react/jsx-runtime");
13
+ let lucide_react = require("lucide-react");
14
+ // src/gallery/ArtworkPanel/ArtworkPanel.tsx
15
+ const DEFAULT_LABELS = {
16
+ close: "Cerrar",
17
+ prev: "Anterior",
18
+ next: "Siguiente",
19
+ view: "Ver obra",
20
+ forSale: "En venta",
21
+ privateCollection: "Colección privada"
22
+ };
23
+ const pad = (value) => String(value).padStart(2, "0");
24
+ const ArtworkPanel = ({ artwork, index, count, side = "left", labels, onClose, onPrev, onNext, className }) => {
25
+ const text = {
26
+ ...DEFAULT_LABELS,
27
+ ...labels
28
+ };
29
+ const authorYear = [artwork.author, artwork.year?.toString()].filter(Boolean).join(", ");
30
+ const techniqueDimensions = [artwork.technique, artwork.dimensions].filter(Boolean).join(", ");
31
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
32
+ "aria-label": artwork.title ?? "Ficha de la obra",
33
+ className: require_cn.cn("fixed inset-y-0 z-[9990] flex w-[38.1966%] flex-col gap-4 overflow-y-auto border-base-content/12 bg-base-100 px-6 pb-6 pt-16 text-base-content", side === "left" ? "left-0 border-r" : "right-0 border-l", className),
34
+ children: [
35
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
36
+ className: "flex items-start justify-between gap-4",
37
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_Eyebrow.Eyebrow, { children: [
38
+ "Obra ",
39
+ pad(index + 1),
40
+ " / ",
41
+ pad(count)
42
+ ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_IconButton.IconButton, {
43
+ label: text.close,
44
+ variant: "ghost",
45
+ size: "sm",
46
+ onClick: onClose,
47
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.X, { className: "size-4" })
48
+ })]
49
+ }),
50
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
51
+ className: "text-2xl font-semibold leading-[1.05] tracking-[-0.03em] text-balance",
52
+ children: artwork.title ?? "Sin título"
53
+ }),
54
+ (authorYear || techniqueDimensions) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
55
+ className: "flex flex-col gap-1 font-mono text-xs uppercase tracking-[0.12em] text-base-content/60",
56
+ children: [authorYear && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: authorYear }), techniqueDimensions && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: techniqueDimensions })]
57
+ }),
58
+ artwork.availability && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Badge.Badge, {
59
+ tone: artwork.availability === "for-sale" ? "accent" : "neutral",
60
+ children: artwork.availability === "for-sale" ? text.forSale : text.privateCollection
61
+ }),
62
+ artwork.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
63
+ className: "text-sm leading-relaxed whitespace-pre-line text-base-content/70",
64
+ children: artwork.description
65
+ }),
66
+ artwork.href && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Link.Link, {
67
+ href: artwork.href,
68
+ external: true,
69
+ arrow: true,
70
+ className: "mt-1",
71
+ children: text.view
72
+ }),
73
+ count > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
74
+ className: "mt-auto flex gap-2 border-t border-base-content/12 pt-4",
75
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_Button.Button, {
76
+ variant: "ghost",
77
+ className: "flex-1",
78
+ onClick: onPrev,
79
+ children: ["‹ ", text.prev]
80
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_Button.Button, {
81
+ variant: "ghost",
82
+ className: "flex-1",
83
+ onClick: onNext,
84
+ children: [text.next, " ›"]
85
+ })]
86
+ })
87
+ ]
88
+ });
89
+ };
90
+ exports.ArtworkPanel = ArtworkPanel;
91
+
92
+ //# sourceMappingURL=ArtworkPanel.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArtworkPanel.cjs","names":["cn","Eyebrow","IconButton","X","Badge","Link","Button"],"sources":["../../../src/gallery/ArtworkPanel/ArtworkPanel.tsx"],"sourcesContent":["import { X } from \"lucide-react\";\nimport { Badge } from \"../../components/Badge\";\nimport { Button } from \"../../components/Button\";\nimport { Eyebrow } from \"../../components/Eyebrow\";\nimport { IconButton } from \"../../components/IconButton\";\nimport { Link } from \"../../components/Link\";\nimport { cn } from \"../../lib/cn\";\n\nexport type ArtworkPanelSide = \"left\" | \"right\";\nexport type ArtworkPanelAvailability = \"for-sale\" | \"sold\" | \"not-for-sale\";\n\nexport type ArtworkPanelArtwork = {\n id: string;\n title?: string;\n author?: string;\n year?: number;\n technique?: string;\n dimensions?: string;\n description?: string;\n href?: string;\n availability?: ArtworkPanelAvailability;\n};\n\nexport type ArtworkPanelLabels = {\n close?: string;\n prev?: string;\n next?: string;\n view?: string;\n forSale?: string;\n privateCollection?: string;\n};\n\nexport type ArtworkPanelProps = {\n artwork: ArtworkPanelArtwork;\n index: number;\n count: number;\n side?: ArtworkPanelSide;\n labels?: ArtworkPanelLabels;\n onClose: () => void;\n onPrev: () => void;\n onNext: () => void;\n className?: string;\n};\n\nconst DEFAULT_LABELS: Required<ArtworkPanelLabels> = {\n close: \"Cerrar\",\n prev: \"Anterior\",\n next: \"Siguiente\",\n view: \"Ver obra\",\n forSale: \"En venta\",\n privateCollection: \"Colección privada\",\n};\n\nconst pad = (value: number): string => String(value).padStart(2, \"0\");\n\nexport const ArtworkPanel = ({\n artwork,\n index,\n count,\n side = \"left\",\n labels,\n onClose,\n onPrev,\n onNext,\n className,\n}: ArtworkPanelProps) => {\n const text = { ...DEFAULT_LABELS, ...labels };\n const authorYear = [artwork.author, artwork.year?.toString()]\n .filter(Boolean)\n .join(\", \");\n const techniqueDimensions = [artwork.technique, artwork.dimensions]\n .filter(Boolean)\n .join(\", \");\n\n return (\n <aside\n aria-label={artwork.title ?? \"Ficha de la obra\"}\n className={cn(\n \"fixed inset-y-0 z-[9990] flex w-[38.1966%] flex-col gap-4 overflow-y-auto border-base-content/12 bg-base-100 px-6 pb-6 pt-16 text-base-content\",\n side === \"left\" ? \"left-0 border-r\" : \"right-0 border-l\",\n className,\n )}\n >\n <div className=\"flex items-start justify-between gap-4\">\n <Eyebrow>\n Obra {pad(index + 1)} / {pad(count)}\n </Eyebrow>\n <IconButton\n label={text.close}\n variant=\"ghost\"\n size=\"sm\"\n onClick={onClose}\n >\n <X className=\"size-4\" />\n </IconButton>\n </div>\n\n <h2 className=\"text-2xl font-semibold leading-[1.05] tracking-[-0.03em] text-balance\">\n {artwork.title ?? \"Sin título\"}\n </h2>\n\n {(authorYear || techniqueDimensions) && (\n <div className=\"flex flex-col gap-1 font-mono text-xs uppercase tracking-[0.12em] text-base-content/60\">\n {authorYear && <span>{authorYear}</span>}\n {techniqueDimensions && <span>{techniqueDimensions}</span>}\n </div>\n )}\n\n {artwork.availability && (\n <Badge\n tone={artwork.availability === \"for-sale\" ? \"accent\" : \"neutral\"}\n >\n {artwork.availability === \"for-sale\"\n ? text.forSale\n : text.privateCollection}\n </Badge>\n )}\n\n {artwork.description && (\n <p className=\"text-sm leading-relaxed whitespace-pre-line text-base-content/70\">\n {artwork.description}\n </p>\n )}\n\n {artwork.href && (\n <Link href={artwork.href} external arrow className=\"mt-1\">\n {text.view}\n </Link>\n )}\n\n {count > 1 && (\n <div className=\"mt-auto flex gap-2 border-t border-base-content/12 pt-4\">\n <Button variant=\"ghost\" className=\"flex-1\" onClick={onPrev}>\n ‹ {text.prev}\n </Button>\n <Button variant=\"ghost\" className=\"flex-1\" onClick={onNext}>\n {text.next} ›\n </Button>\n </div>\n )}\n </aside>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;AA4CA,MAAM,iBAA+C;CACnD,OAAO;CACP,MAAM;CACN,MAAM;CACN,MAAM;CACN,SAAS;CACT,mBAAmB;AACrB;AAEA,MAAM,OAAO,UAA0B,OAAO,KAAK,CAAC,CAAC,SAAS,GAAG,GAAG;AAEpE,MAAa,gBAAgB,EAC3B,SACA,OACA,OACA,OAAO,QACP,QACA,SACA,QACA,QACA,gBACuB;CACvB,MAAM,OAAO;EAAE,GAAG;EAAgB,GAAG;CAAO;CAC5C,MAAM,aAAa,CAAC,QAAQ,QAAQ,QAAQ,MAAM,SAAS,CAAC,CAAC,CAC1D,OAAO,OAAO,CAAC,CACf,KAAK,IAAI;CACZ,MAAM,sBAAsB,CAAC,QAAQ,WAAW,QAAQ,UAAU,CAAC,CAChE,OAAO,OAAO,CAAC,CACf,KAAK,IAAI;CAEZ,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,SAAD;EACE,cAAY,QAAQ,SAAS;EAC7B,WAAWA,WAAAA,GACT,kJACA,SAAS,SAAS,oBAAoB,oBACtC,SACF;EANF,UAAA;GAQE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAACC,gBAAAA,SAAD,EAAA,UAAA;KAAS;KACD,IAAI,QAAQ,CAAC;KAAE;KAAI,IAAI,KAAK;IAC3B,EAAA,CAAA,GACT,iBAAA,GAAA,kBAAA,IAAA,CAACC,mBAAAA,YAAD;KACE,OAAO,KAAK;KACZ,SAAQ;KACR,MAAK;KACL,SAAS;KAET,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACC,aAAAA,GAAD,EAAG,WAAU,SAAU,CAAA;IACb,CAAA,CACT;;GAEL,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;IAAI,WAAU;IACX,UAAA,QAAQ,SAAS;GAChB,CAAA;IAEF,cAAc,wBACd,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACG,cAAc,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,WAAiB,CAAA,GACtC,uBAAuB,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,oBAA0B,CAAA,CACtD;;GAGN,QAAQ,gBACP,iBAAA,GAAA,kBAAA,IAAA,CAACC,cAAAA,OAAD;IACE,MAAM,QAAQ,iBAAiB,aAAa,WAAW;IAEtD,UAAA,QAAQ,iBAAiB,aACtB,KAAK,UACL,KAAK;GACJ,CAAA;GAGR,QAAQ,eACP,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;IAAG,WAAU;IACV,UAAA,QAAQ;GACR,CAAA;GAGJ,QAAQ,QACP,iBAAA,GAAA,kBAAA,IAAA,CAACC,aAAAA,MAAD;IAAM,MAAM,QAAQ;IAAM,UAAA;IAAS,OAAA;IAAM,WAAU;IAChD,UAAA,KAAK;GACF,CAAA;GAGP,QAAQ,KACP,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAACC,eAAAA,QAAD;KAAQ,SAAQ;KAAQ,WAAU;KAAS,SAAS;KAApD,UAAA,CAA4D,MACvD,KAAK,IACF;IACR,CAAA,GAAA,iBAAA,GAAA,kBAAA,KAAA,CAACA,eAAAA,QAAD;KAAQ,SAAQ;KAAQ,WAAU;KAAS,SAAS;KAApD,UAAA,CACG,KAAK,MAAK,IACL;IACL,CAAA,CAAA;;EAEF;;AAEX"}
@@ -0,0 +1,35 @@
1
+ type ArtworkPanelSide = "left" | "right";
2
+ type ArtworkPanelAvailability = "for-sale" | "sold" | "not-for-sale";
3
+ type ArtworkPanelArtwork = {
4
+ id: string;
5
+ title?: string;
6
+ author?: string;
7
+ year?: number;
8
+ technique?: string;
9
+ dimensions?: string;
10
+ description?: string;
11
+ href?: string;
12
+ availability?: ArtworkPanelAvailability;
13
+ };
14
+ type ArtworkPanelLabels = {
15
+ close?: string;
16
+ prev?: string;
17
+ next?: string;
18
+ view?: string;
19
+ forSale?: string;
20
+ privateCollection?: string;
21
+ };
22
+ type ArtworkPanelProps = {
23
+ artwork: ArtworkPanelArtwork;
24
+ index: number;
25
+ count: number;
26
+ side?: ArtworkPanelSide;
27
+ labels?: ArtworkPanelLabels;
28
+ onClose: () => void;
29
+ onPrev: () => void;
30
+ onNext: () => void;
31
+ className?: string;
32
+ };
33
+ declare const ArtworkPanel: ({ artwork, index, count, side, labels, onClose, onPrev, onNext, className }: ArtworkPanelProps) => import("react").JSX.Element;
34
+ export { ArtworkPanel, ArtworkPanelArtwork, ArtworkPanelAvailability, ArtworkPanelLabels, ArtworkPanelProps, ArtworkPanelSide };
35
+ //# sourceMappingURL=ArtworkPanel.d.cts.map
@@ -0,0 +1,35 @@
1
+ type ArtworkPanelSide = "left" | "right";
2
+ type ArtworkPanelAvailability = "for-sale" | "sold" | "not-for-sale";
3
+ type ArtworkPanelArtwork = {
4
+ id: string;
5
+ title?: string;
6
+ author?: string;
7
+ year?: number;
8
+ technique?: string;
9
+ dimensions?: string;
10
+ description?: string;
11
+ href?: string;
12
+ availability?: ArtworkPanelAvailability;
13
+ };
14
+ type ArtworkPanelLabels = {
15
+ close?: string;
16
+ prev?: string;
17
+ next?: string;
18
+ view?: string;
19
+ forSale?: string;
20
+ privateCollection?: string;
21
+ };
22
+ type ArtworkPanelProps = {
23
+ artwork: ArtworkPanelArtwork;
24
+ index: number;
25
+ count: number;
26
+ side?: ArtworkPanelSide;
27
+ labels?: ArtworkPanelLabels;
28
+ onClose: () => void;
29
+ onPrev: () => void;
30
+ onNext: () => void;
31
+ className?: string;
32
+ };
33
+ declare const ArtworkPanel: ({ artwork, index, count, side, labels, onClose, onPrev, onNext, className }: ArtworkPanelProps) => import("react").JSX.Element;
34
+ export { ArtworkPanel, ArtworkPanelArtwork, ArtworkPanelAvailability, ArtworkPanelLabels, ArtworkPanelProps, ArtworkPanelSide };
35
+ //# sourceMappingURL=ArtworkPanel.d.mts.map
@@ -0,0 +1,92 @@
1
+ import "../../components/Badge/index.mjs";
2
+ import { Badge } from "../../components/Badge/Badge.mjs";
3
+ import "../../components/Button/index.mjs";
4
+ import { Button } from "../../components/Button/Button.mjs";
5
+ import "../../components/Eyebrow/index.mjs";
6
+ import { Eyebrow } from "../../components/Eyebrow/Eyebrow.mjs";
7
+ import "../../components/IconButton/index.mjs";
8
+ import { IconButton } from "../../components/IconButton/IconButton.mjs";
9
+ import "../../components/Link/index.mjs";
10
+ import { Link } from "../../components/Link/Link.mjs";
11
+ import { cn } from "../../lib/cn.mjs";
12
+ import { jsx, jsxs } from "react/jsx-runtime";
13
+ import { X } from "lucide-react";
14
+ // src/gallery/ArtworkPanel/ArtworkPanel.tsx
15
+ const DEFAULT_LABELS = {
16
+ close: "Cerrar",
17
+ prev: "Anterior",
18
+ next: "Siguiente",
19
+ view: "Ver obra",
20
+ forSale: "En venta",
21
+ privateCollection: "Colección privada"
22
+ };
23
+ const pad = (value) => String(value).padStart(2, "0");
24
+ const ArtworkPanel = ({ artwork, index, count, side = "left", labels, onClose, onPrev, onNext, className }) => {
25
+ const text = {
26
+ ...DEFAULT_LABELS,
27
+ ...labels
28
+ };
29
+ const authorYear = [artwork.author, artwork.year?.toString()].filter(Boolean).join(", ");
30
+ const techniqueDimensions = [artwork.technique, artwork.dimensions].filter(Boolean).join(", ");
31
+ return /* @__PURE__ */ jsxs("aside", {
32
+ "aria-label": artwork.title ?? "Ficha de la obra",
33
+ className: cn("fixed inset-y-0 z-[9990] flex w-[38.1966%] flex-col gap-4 overflow-y-auto border-base-content/12 bg-base-100 px-6 pb-6 pt-16 text-base-content", side === "left" ? "left-0 border-r" : "right-0 border-l", className),
34
+ children: [
35
+ /* @__PURE__ */ jsxs("div", {
36
+ className: "flex items-start justify-between gap-4",
37
+ children: [/* @__PURE__ */ jsxs(Eyebrow, { children: [
38
+ "Obra ",
39
+ pad(index + 1),
40
+ " / ",
41
+ pad(count)
42
+ ] }), /* @__PURE__ */ jsx(IconButton, {
43
+ label: text.close,
44
+ variant: "ghost",
45
+ size: "sm",
46
+ onClick: onClose,
47
+ children: /* @__PURE__ */ jsx(X, { className: "size-4" })
48
+ })]
49
+ }),
50
+ /* @__PURE__ */ jsx("h2", {
51
+ className: "text-2xl font-semibold leading-[1.05] tracking-[-0.03em] text-balance",
52
+ children: artwork.title ?? "Sin título"
53
+ }),
54
+ (authorYear || techniqueDimensions) && /* @__PURE__ */ jsxs("div", {
55
+ className: "flex flex-col gap-1 font-mono text-xs uppercase tracking-[0.12em] text-base-content/60",
56
+ children: [authorYear && /* @__PURE__ */ jsx("span", { children: authorYear }), techniqueDimensions && /* @__PURE__ */ jsx("span", { children: techniqueDimensions })]
57
+ }),
58
+ artwork.availability && /* @__PURE__ */ jsx(Badge, {
59
+ tone: artwork.availability === "for-sale" ? "accent" : "neutral",
60
+ children: artwork.availability === "for-sale" ? text.forSale : text.privateCollection
61
+ }),
62
+ artwork.description && /* @__PURE__ */ jsx("p", {
63
+ className: "text-sm leading-relaxed whitespace-pre-line text-base-content/70",
64
+ children: artwork.description
65
+ }),
66
+ artwork.href && /* @__PURE__ */ jsx(Link, {
67
+ href: artwork.href,
68
+ external: true,
69
+ arrow: true,
70
+ className: "mt-1",
71
+ children: text.view
72
+ }),
73
+ count > 1 && /* @__PURE__ */ jsxs("div", {
74
+ className: "mt-auto flex gap-2 border-t border-base-content/12 pt-4",
75
+ children: [/* @__PURE__ */ jsxs(Button, {
76
+ variant: "ghost",
77
+ className: "flex-1",
78
+ onClick: onPrev,
79
+ children: ["‹ ", text.prev]
80
+ }), /* @__PURE__ */ jsxs(Button, {
81
+ variant: "ghost",
82
+ className: "flex-1",
83
+ onClick: onNext,
84
+ children: [text.next, " ›"]
85
+ })]
86
+ })
87
+ ]
88
+ });
89
+ };
90
+ export { ArtworkPanel };
91
+
92
+ //# sourceMappingURL=ArtworkPanel.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArtworkPanel.mjs","names":[],"sources":["../../../src/gallery/ArtworkPanel/ArtworkPanel.tsx"],"sourcesContent":["import { X } from \"lucide-react\";\nimport { Badge } from \"../../components/Badge\";\nimport { Button } from \"../../components/Button\";\nimport { Eyebrow } from \"../../components/Eyebrow\";\nimport { IconButton } from \"../../components/IconButton\";\nimport { Link } from \"../../components/Link\";\nimport { cn } from \"../../lib/cn\";\n\nexport type ArtworkPanelSide = \"left\" | \"right\";\nexport type ArtworkPanelAvailability = \"for-sale\" | \"sold\" | \"not-for-sale\";\n\nexport type ArtworkPanelArtwork = {\n id: string;\n title?: string;\n author?: string;\n year?: number;\n technique?: string;\n dimensions?: string;\n description?: string;\n href?: string;\n availability?: ArtworkPanelAvailability;\n};\n\nexport type ArtworkPanelLabels = {\n close?: string;\n prev?: string;\n next?: string;\n view?: string;\n forSale?: string;\n privateCollection?: string;\n};\n\nexport type ArtworkPanelProps = {\n artwork: ArtworkPanelArtwork;\n index: number;\n count: number;\n side?: ArtworkPanelSide;\n labels?: ArtworkPanelLabels;\n onClose: () => void;\n onPrev: () => void;\n onNext: () => void;\n className?: string;\n};\n\nconst DEFAULT_LABELS: Required<ArtworkPanelLabels> = {\n close: \"Cerrar\",\n prev: \"Anterior\",\n next: \"Siguiente\",\n view: \"Ver obra\",\n forSale: \"En venta\",\n privateCollection: \"Colección privada\",\n};\n\nconst pad = (value: number): string => String(value).padStart(2, \"0\");\n\nexport const ArtworkPanel = ({\n artwork,\n index,\n count,\n side = \"left\",\n labels,\n onClose,\n onPrev,\n onNext,\n className,\n}: ArtworkPanelProps) => {\n const text = { ...DEFAULT_LABELS, ...labels };\n const authorYear = [artwork.author, artwork.year?.toString()]\n .filter(Boolean)\n .join(\", \");\n const techniqueDimensions = [artwork.technique, artwork.dimensions]\n .filter(Boolean)\n .join(\", \");\n\n return (\n <aside\n aria-label={artwork.title ?? \"Ficha de la obra\"}\n className={cn(\n \"fixed inset-y-0 z-[9990] flex w-[38.1966%] flex-col gap-4 overflow-y-auto border-base-content/12 bg-base-100 px-6 pb-6 pt-16 text-base-content\",\n side === \"left\" ? \"left-0 border-r\" : \"right-0 border-l\",\n className,\n )}\n >\n <div className=\"flex items-start justify-between gap-4\">\n <Eyebrow>\n Obra {pad(index + 1)} / {pad(count)}\n </Eyebrow>\n <IconButton\n label={text.close}\n variant=\"ghost\"\n size=\"sm\"\n onClick={onClose}\n >\n <X className=\"size-4\" />\n </IconButton>\n </div>\n\n <h2 className=\"text-2xl font-semibold leading-[1.05] tracking-[-0.03em] text-balance\">\n {artwork.title ?? \"Sin título\"}\n </h2>\n\n {(authorYear || techniqueDimensions) && (\n <div className=\"flex flex-col gap-1 font-mono text-xs uppercase tracking-[0.12em] text-base-content/60\">\n {authorYear && <span>{authorYear}</span>}\n {techniqueDimensions && <span>{techniqueDimensions}</span>}\n </div>\n )}\n\n {artwork.availability && (\n <Badge\n tone={artwork.availability === \"for-sale\" ? \"accent\" : \"neutral\"}\n >\n {artwork.availability === \"for-sale\"\n ? text.forSale\n : text.privateCollection}\n </Badge>\n )}\n\n {artwork.description && (\n <p className=\"text-sm leading-relaxed whitespace-pre-line text-base-content/70\">\n {artwork.description}\n </p>\n )}\n\n {artwork.href && (\n <Link href={artwork.href} external arrow className=\"mt-1\">\n {text.view}\n </Link>\n )}\n\n {count > 1 && (\n <div className=\"mt-auto flex gap-2 border-t border-base-content/12 pt-4\">\n <Button variant=\"ghost\" className=\"flex-1\" onClick={onPrev}>\n ‹ {text.prev}\n </Button>\n <Button variant=\"ghost\" className=\"flex-1\" onClick={onNext}>\n {text.next} ›\n </Button>\n </div>\n )}\n </aside>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;AA4CA,MAAM,iBAA+C;CACnD,OAAO;CACP,MAAM;CACN,MAAM;CACN,MAAM;CACN,SAAS;CACT,mBAAmB;AACrB;AAEA,MAAM,OAAO,UAA0B,OAAO,KAAK,CAAC,CAAC,SAAS,GAAG,GAAG;AAEpE,MAAa,gBAAgB,EAC3B,SACA,OACA,OACA,OAAO,QACP,QACA,SACA,QACA,QACA,gBACuB;CACvB,MAAM,OAAO;EAAE,GAAG;EAAgB,GAAG;CAAO;CAC5C,MAAM,aAAa,CAAC,QAAQ,QAAQ,QAAQ,MAAM,SAAS,CAAC,CAAC,CAC1D,OAAO,OAAO,CAAC,CACf,KAAK,IAAI;CACZ,MAAM,sBAAsB,CAAC,QAAQ,WAAW,QAAQ,UAAU,CAAC,CAChE,OAAO,OAAO,CAAC,CACf,KAAK,IAAI;CAEZ,OACE,qBAAC,SAAD;EACE,cAAY,QAAQ,SAAS;EAC7B,WAAW,GACT,kJACA,SAAS,SAAS,oBAAoB,oBACtC,SACF;EANF,UAAA;GAQE,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,qBAAC,SAAD,EAAA,UAAA;KAAS;KACD,IAAI,QAAQ,CAAC;KAAE;KAAI,IAAI,KAAK;IAC3B,EAAA,CAAA,GACT,oBAAC,YAAD;KACE,OAAO,KAAK;KACZ,SAAQ;KACR,MAAK;KACL,SAAS;KAET,UAAA,oBAAC,GAAD,EAAG,WAAU,SAAU,CAAA;IACb,CAAA,CACT;;GAEL,oBAAC,MAAD;IAAI,WAAU;IACX,UAAA,QAAQ,SAAS;GAChB,CAAA;IAEF,cAAc,wBACd,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACG,cAAc,oBAAC,QAAD,EAAA,UAAO,WAAiB,CAAA,GACtC,uBAAuB,oBAAC,QAAD,EAAA,UAAO,oBAA0B,CAAA,CACtD;;GAGN,QAAQ,gBACP,oBAAC,OAAD;IACE,MAAM,QAAQ,iBAAiB,aAAa,WAAW;IAEtD,UAAA,QAAQ,iBAAiB,aACtB,KAAK,UACL,KAAK;GACJ,CAAA;GAGR,QAAQ,eACP,oBAAC,KAAD;IAAG,WAAU;IACV,UAAA,QAAQ;GACR,CAAA;GAGJ,QAAQ,QACP,oBAAC,MAAD;IAAM,MAAM,QAAQ;IAAM,UAAA;IAAS,OAAA;IAAM,WAAU;IAChD,UAAA,KAAK;GACF,CAAA;GAGP,QAAQ,KACP,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,qBAAC,QAAD;KAAQ,SAAQ;KAAQ,WAAU;KAAS,SAAS;KAApD,UAAA,CAA4D,MACvD,KAAK,IACF;IACR,CAAA,GAAA,qBAAC,QAAD;KAAQ,SAAQ;KAAQ,WAAU;KAAS,SAAS;KAApD,UAAA,CACG,KAAK,MAAK,IACL;IACL,CAAA,CAAA;;EAEF;;AAEX"}
@@ -0,0 +1,2 @@
1
+ const require_ArtworkPanel = require("./ArtworkPanel.cjs");
2
+ exports.ArtworkPanel = require_ArtworkPanel.ArtworkPanel;
@@ -0,0 +1 @@
1
+ export { ArtworkPanel } from "./ArtworkPanel.mjs";
package/dist/gallery.cjs CHANGED
@@ -1,10 +1,13 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_ArtworkPanel = require("./gallery/ArtworkPanel/ArtworkPanel.cjs");
3
+ require("./gallery/ArtworkPanel/index.cjs");
2
4
  const require_LoadingScreen = require("./gallery/LoadingScreen/LoadingScreen.cjs");
3
5
  require("./gallery/LoadingScreen/index.cjs");
4
6
  const require_HomeButton = require("./gallery/HomeButton/HomeButton.cjs");
5
7
  require("./gallery/HomeButton/index.cjs");
6
8
  const require_SetupNotice = require("./gallery/SetupNotice/SetupNotice.cjs");
7
9
  require("./gallery/SetupNotice/index.cjs");
10
+ exports.ArtworkPanel = require_ArtworkPanel.ArtworkPanel;
8
11
  exports.HomeButton = require_HomeButton.HomeButton;
9
12
  exports.LoadingScreen = require_LoadingScreen.LoadingScreen;
10
13
  exports.SetupNotice = require_SetupNotice.SetupNotice;
@@ -1,4 +1,5 @@
1
+ import { ArtworkPanel, ArtworkPanelArtwork, ArtworkPanelAvailability, ArtworkPanelLabels, ArtworkPanelProps, ArtworkPanelSide } from "./gallery/ArtworkPanel/ArtworkPanel.cjs";
1
2
  import { LoadingGallery, LoadingScreen, LoadingScreenProps, LoadingState } from "./gallery/LoadingScreen/LoadingScreen.cjs";
2
3
  import { HomeButton, HomeButtonProps } from "./gallery/HomeButton/HomeButton.cjs";
3
4
  import { SetupNotice, SetupNoticeProps } from "./gallery/SetupNotice/SetupNotice.cjs";
4
- export { HomeButton, type HomeButtonProps, type LoadingGallery, LoadingScreen, type LoadingScreenProps, type LoadingState, SetupNotice, type SetupNoticeProps };
5
+ export { ArtworkPanel, type ArtworkPanelArtwork, type ArtworkPanelAvailability, type ArtworkPanelLabels, type ArtworkPanelProps, type ArtworkPanelSide, HomeButton, type HomeButtonProps, type LoadingGallery, LoadingScreen, type LoadingScreenProps, type LoadingState, SetupNotice, type SetupNoticeProps };
@@ -1,4 +1,5 @@
1
+ import { ArtworkPanel, ArtworkPanelArtwork, ArtworkPanelAvailability, ArtworkPanelLabels, ArtworkPanelProps, ArtworkPanelSide } from "./gallery/ArtworkPanel/ArtworkPanel.mjs";
1
2
  import { LoadingGallery, LoadingScreen, LoadingScreenProps, LoadingState } from "./gallery/LoadingScreen/LoadingScreen.mjs";
2
3
  import { HomeButton, HomeButtonProps } from "./gallery/HomeButton/HomeButton.mjs";
3
4
  import { SetupNotice, SetupNoticeProps } from "./gallery/SetupNotice/SetupNotice.mjs";
4
- export { HomeButton, type HomeButtonProps, type LoadingGallery, LoadingScreen, type LoadingScreenProps, type LoadingState, SetupNotice, type SetupNoticeProps };
5
+ export { ArtworkPanel, type ArtworkPanelArtwork, type ArtworkPanelAvailability, type ArtworkPanelLabels, type ArtworkPanelProps, type ArtworkPanelSide, HomeButton, type HomeButtonProps, type LoadingGallery, LoadingScreen, type LoadingScreenProps, type LoadingState, SetupNotice, type SetupNoticeProps };
package/dist/gallery.mjs CHANGED
@@ -1,7 +1,9 @@
1
+ import { ArtworkPanel } from "./gallery/ArtworkPanel/ArtworkPanel.mjs";
2
+ import "./gallery/ArtworkPanel/index.mjs";
1
3
  import { LoadingScreen } from "./gallery/LoadingScreen/LoadingScreen.mjs";
2
4
  import "./gallery/LoadingScreen/index.mjs";
3
5
  import { HomeButton } from "./gallery/HomeButton/HomeButton.mjs";
4
6
  import "./gallery/HomeButton/index.mjs";
5
7
  import { SetupNotice } from "./gallery/SetupNotice/SetupNotice.mjs";
6
8
  import "./gallery/SetupNotice/index.mjs";
7
- export { HomeButton, LoadingScreen, SetupNotice };
9
+ export { ArtworkPanel, HomeButton, LoadingScreen, SetupNotice };
@@ -332,80 +332,5 @@
332
332
  text-decoration-line: underline;
333
333
  }
334
334
 
335
- /*
336
- * The artwork panel ships its own white-on-black controls. Restyle its
337
- * navigation and close buttons with the design system's square chips.
338
- */
339
- .sg-artwork-panel .sg-artwork-panel__navbtn {
340
- flex: 1;
341
- display: inline-flex;
342
- align-items: center;
343
- justify-content: center;
344
- gap: 0.375rem;
345
- padding: 0.5rem 0.75rem;
346
- border: 1px solid
347
- color-mix(in oklab, var(--color-base-content) 12%, transparent);
348
- border-radius: 0;
349
- background-color: color-mix(
350
- in oklab,
351
- var(--color-base-100) 80%,
352
- transparent
353
- );
354
- color: var(--color-base-content);
355
- font-family: var(--font-sans);
356
- font-size: 0.875rem;
357
- font-weight: 500;
358
- cursor: pointer;
359
- backdrop-filter: blur(8px);
360
- transition:
361
- background-color 150ms ease,
362
- color 150ms ease,
363
- border-color 150ms ease;
364
- }
365
-
366
- .sg-artwork-panel .sg-artwork-panel__navbtn:hover {
367
- background-color: var(--color-base-200);
368
- }
369
-
370
- .sg-artwork-panel .sg-artwork-panel__navbtn:focus-visible {
371
- outline: 2px solid var(--color-accent);
372
- outline-offset: 2px;
373
- }
374
335
 
375
- .sg-artwork-panel .sg-artwork-panel__close {
376
- display: inline-flex;
377
- align-items: center;
378
- justify-content: center;
379
- width: 2rem;
380
- height: 2rem;
381
- padding: 0;
382
- border: 1px solid
383
- color-mix(in oklab, var(--color-base-content) 12%, transparent);
384
- border-radius: 0;
385
- background-color: color-mix(
386
- in oklab,
387
- var(--color-base-100) 80%,
388
- transparent
389
- );
390
- color: var(--color-base-content);
391
- font-family: var(--font-sans);
392
- font-size: 1rem;
393
- line-height: 1;
394
- opacity: 1;
395
- cursor: pointer;
396
- backdrop-filter: blur(8px);
397
- transition:
398
- background-color 150ms ease,
399
- color 150ms ease,
400
- border-color 150ms ease;
401
- }
402
-
403
- .sg-artwork-panel .sg-artwork-panel__close:hover {
404
- background-color: var(--color-base-200);
405
- }
406
-
407
- .sg-artwork-panel .sg-artwork-panel__close:focus-visible {
408
- outline: 2px solid var(--color-accent);
409
- outline-offset: 2px;
410
- }
411
336
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yo-yo.art/ui",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "The Grupo Yo-Yo design system: shared React components and tokens.",
5
5
  "keywords": [
6
6
  "design-system",