@mediquo/medicore 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,15 +2,17 @@ import { type ComponentProps } from "react";
2
2
  export interface BrandBubblesProps extends Omit<ComponentProps<"svg">, "children"> {
3
3
  }
4
4
  /**
5
- * mediQuo's brand backdrop on a dark brand surface: soft translucent bubbles, a
6
- * small constellation and the cross, drifting slowly. The same language as the
7
- * portal's home hero, for the `AuthPanel` and any other full-bleed brand surface.
5
+ * mediQuo's brand backdrop on a dark brand surface: translucent bubbles that float and
6
+ * rise, breathing glows, a twinkling constellation and the cross. A seamless loop that
7
+ * reads like a short video, in the same language as the portal's home hero, for the
8
+ * `AuthPanel` and any other full-bleed brand surface.
8
9
  *
9
10
  * - Decorative: `aria-hidden`, no pointer events, never carries meaning.
10
11
  * - Fills its parent (`absolute inset-0`, `slice`), so the parent is `relative`
11
12
  * and clips overflow.
12
13
  * - Coloured with tokens (`text-inverse`, `brand`), so it follows a clinic's brand.
13
14
  * - Motion only under `prefers-reduced-motion: no-preference`; otherwise it is a
14
- * still composition. Nothing moves fast or far: 14–22s cycles, a few pixels.
15
+ * still composition. Transforms and opacity only, with gradients instead of blur
16
+ * filters, so it stays smooth on large panels.
15
17
  */
16
18
  export declare function BrandBubbles({ className, ...props }: BrandBubblesProps): React.JSX.Element;
@@ -1,8 +1,28 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { useId } from "react";
3
3
  import { cn } from "../../lib/cn.js";
4
- const drift = "motion-safe:animate-drift";
5
- const breathe = "motion-safe:animate-breathe origin-center [transform-box:fill-box]";
4
+ const float = "motion-safe:animate-float";
5
+ const rise = "motion-safe:animate-rise";
6
+ const scaled = "origin-center [transform-box:fill-box]";
7
+ const breathe = cn("motion-safe:animate-breathe", scaled);
8
+ const twinkle = cn("motion-safe:animate-twinkle", scaled);
9
+ const RISING_BUBBLES = [
10
+ { cx: 70, r: 10, timing: "[animation-duration:15s]" },
11
+ { cx: 150, r: 22, timing: "[animation-duration:19s] [animation-delay:-11s]" },
12
+ { cx: 235, r: 7, timing: "[animation-duration:13s] [animation-delay:-4s]" },
13
+ { cx: 300, r: 16, timing: "[animation-duration:17s] [animation-delay:-8s]" },
14
+ { cx: 380, r: 9, timing: "[animation-duration:14s] [animation-delay:-2s]" },
15
+ { cx: 445, r: 26, timing: "[animation-duration:21s] [animation-delay:-15s]" },
16
+ { cx: 510, r: 12, timing: "[animation-duration:16s] [animation-delay:-6s]" },
17
+ { cx: 110, r: 6, timing: "[animation-duration:12s] [animation-delay:-9s]" },
18
+ { cx: 345, r: 5, timing: "[animation-duration:11s] [animation-delay:-5s]" }
19
+ ];
20
+ const CONSTELLATION = [
21
+ { cx: 120, cy: 330, timing: "[animation-delay:0s]" },
22
+ { cx: 300, cy: 520, timing: "[animation-delay:-0.8s]" },
23
+ { cx: 380, cy: 420, timing: "[animation-delay:-1.6s]" },
24
+ { cx: 180, cy: 700, timing: "[animation-delay:-2.4s]" }
25
+ ];
6
26
  function BrandBubbles({
7
27
  className,
8
28
  ...props
@@ -22,43 +42,53 @@ function BrandBubbles({
22
42
  ),
23
43
  ...props,
24
44
  children: [
25
- /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("filter", { id: glowId, x: "-50%", y: "-50%", width: "200%", height: "200%", children: /* @__PURE__ */ jsx("feGaussianBlur", { stdDeviation: "70" }) }) }),
26
- /* @__PURE__ */ jsxs("g", { filter: `url(#${glowId})`, children: [
45
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("radialGradient", { id: glowId, children: [
27
46
  /* @__PURE__ */ jsx(
28
- "circle",
47
+ "stop",
29
48
  {
30
- cx: "440",
31
- cy: "180",
32
- r: "220",
33
- className: cn(
34
- "fill-brand opacity-50",
35
- breathe,
36
- "[animation-duration:22s]"
37
- )
49
+ offset: "0%",
50
+ className: "[stop-color:var(--color-brand)] [stop-opacity:0.6]"
38
51
  }
39
52
  ),
40
53
  /* @__PURE__ */ jsx(
41
- "circle",
54
+ "stop",
42
55
  {
43
- cx: "90",
44
- cy: "880",
45
- r: "190",
46
- className: cn(
47
- "fill-brand opacity-40",
48
- breathe,
49
- "[animation-duration:18s] [animation-delay:-7s]"
50
- )
56
+ offset: "100%",
57
+ className: "[stop-color:var(--color-brand)] [stop-opacity:0]"
51
58
  }
52
59
  )
53
- ] }),
54
- /* @__PURE__ */ jsxs("g", { className: cn(drift, "[animation-duration:16s]"), children: [
60
+ ] }) }),
61
+ /* @__PURE__ */ jsx(
62
+ "circle",
63
+ {
64
+ cx: "440",
65
+ cy: "180",
66
+ r: "320",
67
+ fill: `url(#${glowId})`,
68
+ className: cn(breathe, "[animation-duration:11s]")
69
+ }
70
+ ),
71
+ /* @__PURE__ */ jsx(
72
+ "circle",
73
+ {
74
+ cx: "90",
75
+ cy: "860",
76
+ r: "300",
77
+ fill: `url(#${glowId})`,
78
+ className: cn(
79
+ breathe,
80
+ "[animation-duration:13s] [animation-delay:-5s]"
81
+ )
82
+ }
83
+ ),
84
+ /* @__PURE__ */ jsxs("g", { className: "fill-text-inverse/5", children: [
55
85
  /* @__PURE__ */ jsx(
56
86
  "circle",
57
87
  {
58
88
  cx: "430",
59
89
  cy: "150",
60
90
  r: "92",
61
- className: "fill-text-inverse opacity-5"
91
+ className: cn(float, "[animation-duration:12s]")
62
92
  }
63
93
  ),
64
94
  /* @__PURE__ */ jsx(
@@ -67,71 +97,56 @@ function BrandBubbles({
67
97
  cx: "470",
68
98
  cy: "760",
69
99
  r: "140",
70
- className: "fill-text-inverse opacity-5"
100
+ className: cn(
101
+ float,
102
+ "[animation-duration:16s] [animation-delay:-6s]"
103
+ )
71
104
  }
72
105
  ),
73
106
  /* @__PURE__ */ jsx(
74
107
  "circle",
75
108
  {
76
- cx: "300",
77
- cy: "520",
78
- r: "42",
79
- className: "fill-text-inverse opacity-10"
109
+ cx: "120",
110
+ cy: "330",
111
+ r: "62",
112
+ className: cn(
113
+ float,
114
+ "[animation-duration:10s] [animation-delay:-3s]"
115
+ )
80
116
  }
81
117
  )
82
118
  ] }),
83
- /* @__PURE__ */ jsxs(
84
- "g",
119
+ /* @__PURE__ */ jsx("g", { "data-slot": "brand-bubbles-rising", className: "fill-text-inverse/15", children: RISING_BUBBLES.map((bubble) => /* @__PURE__ */ jsx(
120
+ "circle",
85
121
  {
86
- className: cn(drift, "[animation-duration:20s] [animation-delay:-9s]"),
87
- children: [
88
- /* @__PURE__ */ jsx(
89
- "circle",
90
- {
91
- cx: "120",
92
- cy: "330",
93
- r: "62",
94
- className: "fill-text-inverse opacity-5"
95
- }
96
- ),
97
- /* @__PURE__ */ jsx(
98
- "circle",
99
- {
100
- cx: "180",
101
- cy: "700",
102
- r: "24",
103
- className: "fill-text-inverse opacity-10"
104
- }
105
- ),
106
- /* @__PURE__ */ jsx(
107
- "circle",
108
- {
109
- cx: "380",
110
- cy: "420",
111
- r: "14",
112
- className: "fill-text-inverse opacity-15"
113
- }
114
- )
115
- ]
116
- }
117
- ),
122
+ cx: bubble.cx,
123
+ cy: "1080",
124
+ r: bubble.r,
125
+ className: cn(rise, bubble.timing)
126
+ },
127
+ bubble.cx
128
+ )) }),
118
129
  /* @__PURE__ */ jsxs(
119
130
  "g",
120
131
  {
121
- className: cn(drift, "[animation-duration:14s] [animation-delay:-3s]"),
132
+ className: cn(float, "[animation-duration:18s] [animation-delay:-4s]"),
122
133
  children: [
123
- /* @__PURE__ */ jsxs("g", { className: "stroke-text-inverse opacity-10", strokeWidth: "1", children: [
134
+ /* @__PURE__ */ jsxs("g", { className: "stroke-text-inverse opacity-15", strokeWidth: "1", children: [
124
135
  /* @__PURE__ */ jsx("path", { d: "M120 330 L300 520" }),
125
136
  /* @__PURE__ */ jsx("path", { d: "M300 520 L380 420" }),
126
137
  /* @__PURE__ */ jsx("path", { d: "M300 520 L180 700" })
127
138
  ] }),
128
- /* @__PURE__ */ jsxs("g", { className: "fill-text-inverse opacity-25", children: [
129
- /* @__PURE__ */ jsx("circle", { cx: "120", cy: "330", r: "5" }),
130
- /* @__PURE__ */ jsx("circle", { cx: "300", cy: "520", r: "5" }),
131
- /* @__PURE__ */ jsx("circle", { cx: "380", cy: "420", r: "5" }),
132
- /* @__PURE__ */ jsx("circle", { cx: "180", cy: "700", r: "5" })
133
- ] }),
134
- /* @__PURE__ */ jsxs("g", { className: "fill-text-inverse opacity-25", children: [
139
+ /* @__PURE__ */ jsx("g", { className: "fill-text-inverse/40", children: CONSTELLATION.map((dot) => /* @__PURE__ */ jsx(
140
+ "circle",
141
+ {
142
+ cx: dot.cx,
143
+ cy: dot.cy,
144
+ r: "5",
145
+ className: cn(twinkle, dot.timing)
146
+ },
147
+ `${dot.cx}-${dot.cy}`
148
+ )) }),
149
+ /* @__PURE__ */ jsxs("g", { className: "fill-text-inverse/25", children: [
135
150
  /* @__PURE__ */ jsx("rect", { x: "412", y: "258", width: "36", height: "10", rx: "5" }),
136
151
  /* @__PURE__ */ jsx("rect", { x: "425", y: "245", width: "10", height: "36", rx: "5" })
137
152
  ] })
@@ -1 +1 @@
1
- {"version":3,"file":"brand-bubbles.js","sources":["../../../src/components/brand-bubbles/brand-bubbles.tsx"],"sourcesContent":["import { type ComponentProps, useId } from \"react\";\n\nimport { cn } from \"../../lib/cn\";\n\nexport interface BrandBubblesProps\n extends Omit<ComponentProps<\"svg\">, \"children\"> {}\n\nconst drift = \"motion-safe:animate-drift\";\nconst breathe =\n \"motion-safe:animate-breathe origin-center [transform-box:fill-box]\";\n\n/**\n * mediQuo's brand backdrop on a dark brand surface: soft translucent bubbles, a\n * small constellation and the cross, drifting slowly. The same language as the\n * portal's home hero, for the `AuthPanel` and any other full-bleed brand surface.\n *\n * - Decorative: `aria-hidden`, no pointer events, never carries meaning.\n * - Fills its parent (`absolute inset-0`, `slice`), so the parent is `relative`\n * and clips overflow.\n * - Coloured with tokens (`text-inverse`, `brand`), so it follows a clinic's brand.\n * - Motion only under `prefers-reduced-motion: no-preference`; otherwise it is a\n * still composition. Nothing moves fast or far: 14–22s cycles, a few pixels.\n */\nexport function BrandBubbles({\n className,\n ...props\n}: BrandBubblesProps): React.JSX.Element {\n const glowId = useId();\n\n return (\n <svg\n viewBox=\"0 0 560 1024\"\n preserveAspectRatio=\"xMidYMid slice\"\n aria-hidden=\"true\"\n focusable=\"false\"\n data-slot=\"brand-bubbles\"\n className={cn(\n \"pointer-events-none absolute inset-0 size-full select-none\",\n className,\n )}\n {...props}\n >\n <defs>\n <filter id={glowId} x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\">\n <feGaussianBlur stdDeviation=\"70\" />\n </filter>\n </defs>\n\n <g filter={`url(#${glowId})`}>\n <circle\n cx=\"440\"\n cy=\"180\"\n r=\"220\"\n className={cn(\n \"fill-brand opacity-50\",\n breathe,\n \"[animation-duration:22s]\",\n )}\n />\n <circle\n cx=\"90\"\n cy=\"880\"\n r=\"190\"\n className={cn(\n \"fill-brand opacity-40\",\n breathe,\n \"[animation-duration:18s] [animation-delay:-7s]\",\n )}\n />\n </g>\n\n <g className={cn(drift, \"[animation-duration:16s]\")}>\n <circle\n cx=\"430\"\n cy=\"150\"\n r=\"92\"\n className=\"fill-text-inverse opacity-5\"\n />\n <circle\n cx=\"470\"\n cy=\"760\"\n r=\"140\"\n className=\"fill-text-inverse opacity-5\"\n />\n <circle\n cx=\"300\"\n cy=\"520\"\n r=\"42\"\n className=\"fill-text-inverse opacity-10\"\n />\n </g>\n\n <g\n className={cn(drift, \"[animation-duration:20s] [animation-delay:-9s]\")}\n >\n <circle\n cx=\"120\"\n cy=\"330\"\n r=\"62\"\n className=\"fill-text-inverse opacity-5\"\n />\n <circle\n cx=\"180\"\n cy=\"700\"\n r=\"24\"\n className=\"fill-text-inverse opacity-10\"\n />\n <circle\n cx=\"380\"\n cy=\"420\"\n r=\"14\"\n className=\"fill-text-inverse opacity-15\"\n />\n </g>\n\n <g\n className={cn(drift, \"[animation-duration:14s] [animation-delay:-3s]\")}\n >\n <g className=\"stroke-text-inverse opacity-10\" strokeWidth=\"1\">\n <path d=\"M120 330 L300 520\" />\n <path d=\"M300 520 L380 420\" />\n <path d=\"M300 520 L180 700\" />\n </g>\n <g className=\"fill-text-inverse opacity-25\">\n <circle cx=\"120\" cy=\"330\" r=\"5\" />\n <circle cx=\"300\" cy=\"520\" r=\"5\" />\n <circle cx=\"380\" cy=\"420\" r=\"5\" />\n <circle cx=\"180\" cy=\"700\" r=\"5\" />\n </g>\n <g className=\"fill-text-inverse opacity-25\">\n <rect x=\"412\" y=\"258\" width=\"36\" height=\"10\" rx=\"5\" />\n <rect x=\"425\" y=\"245\" width=\"10\" height=\"36\" rx=\"5\" />\n </g>\n </g>\n </svg>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"brand-bubbles.js","sources":["../../../src/components/brand-bubbles/brand-bubbles.tsx"],"sourcesContent":["import { type ComponentProps, useId } from \"react\";\n\nimport { cn } from \"../../lib/cn\";\n\nexport interface BrandBubblesProps\n extends Omit<ComponentProps<\"svg\">, \"children\"> {}\n\nconst float = \"motion-safe:animate-float\";\nconst rise = \"motion-safe:animate-rise\";\nconst scaled = \"origin-center [transform-box:fill-box]\";\nconst breathe = cn(\"motion-safe:animate-breathe\", scaled);\nconst twinkle = cn(\"motion-safe:animate-twinkle\", scaled);\n\nconst RISING_BUBBLES = [\n { cx: 70, r: 10, timing: \"[animation-duration:15s]\" },\n { cx: 150, r: 22, timing: \"[animation-duration:19s] [animation-delay:-11s]\" },\n { cx: 235, r: 7, timing: \"[animation-duration:13s] [animation-delay:-4s]\" },\n { cx: 300, r: 16, timing: \"[animation-duration:17s] [animation-delay:-8s]\" },\n { cx: 380, r: 9, timing: \"[animation-duration:14s] [animation-delay:-2s]\" },\n { cx: 445, r: 26, timing: \"[animation-duration:21s] [animation-delay:-15s]\" },\n { cx: 510, r: 12, timing: \"[animation-duration:16s] [animation-delay:-6s]\" },\n { cx: 110, r: 6, timing: \"[animation-duration:12s] [animation-delay:-9s]\" },\n { cx: 345, r: 5, timing: \"[animation-duration:11s] [animation-delay:-5s]\" },\n] as const;\n\nconst CONSTELLATION = [\n { cx: 120, cy: 330, timing: \"[animation-delay:0s]\" },\n { cx: 300, cy: 520, timing: \"[animation-delay:-0.8s]\" },\n { cx: 380, cy: 420, timing: \"[animation-delay:-1.6s]\" },\n { cx: 180, cy: 700, timing: \"[animation-delay:-2.4s]\" },\n] as const;\n\n/**\n * mediQuo's brand backdrop on a dark brand surface: translucent bubbles that float and\n * rise, breathing glows, a twinkling constellation and the cross. A seamless loop that\n * reads like a short video, in the same language as the portal's home hero, for the\n * `AuthPanel` and any other full-bleed brand surface.\n *\n * - Decorative: `aria-hidden`, no pointer events, never carries meaning.\n * - Fills its parent (`absolute inset-0`, `slice`), so the parent is `relative`\n * and clips overflow.\n * - Coloured with tokens (`text-inverse`, `brand`), so it follows a clinic's brand.\n * - Motion only under `prefers-reduced-motion: no-preference`; otherwise it is a\n * still composition. Transforms and opacity only, with gradients instead of blur\n * filters, so it stays smooth on large panels.\n */\nexport function BrandBubbles({\n className,\n ...props\n}: BrandBubblesProps): React.JSX.Element {\n const glowId = useId();\n\n return (\n <svg\n viewBox=\"0 0 560 1024\"\n preserveAspectRatio=\"xMidYMid slice\"\n aria-hidden=\"true\"\n focusable=\"false\"\n data-slot=\"brand-bubbles\"\n className={cn(\n \"pointer-events-none absolute inset-0 size-full select-none\",\n className,\n )}\n {...props}\n >\n <defs>\n <radialGradient id={glowId}>\n <stop\n offset=\"0%\"\n className=\"[stop-color:var(--color-brand)] [stop-opacity:0.6]\"\n />\n <stop\n offset=\"100%\"\n className=\"[stop-color:var(--color-brand)] [stop-opacity:0]\"\n />\n </radialGradient>\n </defs>\n\n <circle\n cx=\"440\"\n cy=\"180\"\n r=\"320\"\n fill={`url(#${glowId})`}\n className={cn(breathe, \"[animation-duration:11s]\")}\n />\n <circle\n cx=\"90\"\n cy=\"860\"\n r=\"300\"\n fill={`url(#${glowId})`}\n className={cn(\n breathe,\n \"[animation-duration:13s] [animation-delay:-5s]\",\n )}\n />\n\n <g className=\"fill-text-inverse/5\">\n <circle\n cx=\"430\"\n cy=\"150\"\n r=\"92\"\n className={cn(float, \"[animation-duration:12s]\")}\n />\n <circle\n cx=\"470\"\n cy=\"760\"\n r=\"140\"\n className={cn(\n float,\n \"[animation-duration:16s] [animation-delay:-6s]\",\n )}\n />\n <circle\n cx=\"120\"\n cy=\"330\"\n r=\"62\"\n className={cn(\n float,\n \"[animation-duration:10s] [animation-delay:-3s]\",\n )}\n />\n </g>\n\n <g data-slot=\"brand-bubbles-rising\" className=\"fill-text-inverse/15\">\n {RISING_BUBBLES.map((bubble) => (\n <circle\n key={bubble.cx}\n cx={bubble.cx}\n cy=\"1080\"\n r={bubble.r}\n className={cn(rise, bubble.timing)}\n />\n ))}\n </g>\n\n <g\n className={cn(float, \"[animation-duration:18s] [animation-delay:-4s]\")}\n >\n <g className=\"stroke-text-inverse opacity-15\" strokeWidth=\"1\">\n <path d=\"M120 330 L300 520\" />\n <path d=\"M300 520 L380 420\" />\n <path d=\"M300 520 L180 700\" />\n </g>\n <g className=\"fill-text-inverse/40\">\n {CONSTELLATION.map((dot) => (\n <circle\n key={`${dot.cx}-${dot.cy}`}\n cx={dot.cx}\n cy={dot.cy}\n r=\"5\"\n className={cn(twinkle, dot.timing)}\n />\n ))}\n </g>\n <g className=\"fill-text-inverse/25\">\n <rect x=\"412\" y=\"258\" width=\"36\" height=\"10\" rx=\"5\" />\n <rect x=\"425\" y=\"245\" width=\"10\" height=\"36\" rx=\"5\" />\n </g>\n </g>\n </svg>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -51,27 +51,72 @@
51
51
  --shadow-xl: 0 16px 32px -4px rgb(10 10 34 / 0.12);
52
52
 
53
53
  /*
54
- * Motion for brand backdrops (BrandBubbles): a slow drift of a few pixels and a
55
- * slow breathe of a few percent. Always behind `motion-safe:`.
54
+ * Motion for brand backdrops (BrandBubbles), a seamless loop like a short video:
55
+ * bubbles float on a wide path, small ones rise through the panel, glows breathe and
56
+ * the constellation twinkles. Transforms and opacity only. Always behind `motion-safe:`.
56
57
  */
57
- --animate-drift: drift 16s ease-in-out infinite alternate;
58
- --animate-breathe: breathe 20s ease-in-out infinite alternate;
58
+ --animate-drift: float 16s ease-in-out infinite;
59
+ --animate-float: float 12s ease-in-out infinite;
60
+ --animate-rise: rise 16s linear infinite;
61
+ --animate-breathe: breathe 10s ease-in-out infinite alternate;
62
+ --animate-twinkle: twinkle 3s ease-in-out infinite;
63
+
64
+ @keyframes float {
65
+ 0%,
66
+ 100% {
67
+ transform: translate3d(0, 0, 0);
68
+ }
69
+ 25% {
70
+ transform: translate3d(16px, -28px, 0);
71
+ }
72
+ 50% {
73
+ transform: translate3d(-8px, -48px, 0);
74
+ }
75
+ 75% {
76
+ transform: translate3d(-20px, -20px, 0);
77
+ }
78
+ }
59
79
 
60
- @keyframes drift {
61
- from {
80
+ @keyframes rise {
81
+ 0% {
62
82
  transform: translate3d(0, 0, 0);
83
+ opacity: 0;
63
84
  }
64
- to {
65
- transform: translate3d(0, -18px, 0);
85
+ 12% {
86
+ opacity: 1;
87
+ }
88
+ 50% {
89
+ transform: translate3d(24px, -600px, 0);
90
+ }
91
+ 88% {
92
+ opacity: 1;
93
+ }
94
+ 100% {
95
+ transform: translate3d(0, -1200px, 0);
96
+ opacity: 0;
66
97
  }
67
98
  }
68
99
 
69
100
  @keyframes breathe {
70
101
  from {
71
102
  transform: scale(1);
103
+ opacity: 0.7;
72
104
  }
73
105
  to {
74
- transform: scale(1.08);
106
+ transform: scale(1.3);
107
+ opacity: 1;
108
+ }
109
+ }
110
+
111
+ @keyframes twinkle {
112
+ 0%,
113
+ 100% {
114
+ transform: scale(1);
115
+ opacity: 1;
116
+ }
117
+ 50% {
118
+ transform: scale(1.8);
119
+ opacity: 0.4;
75
120
  }
76
121
  }
77
122
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mediquo/medicore",
3
3
  "description": "MediCore — design system de las plataformas web de mediQuo",
4
- "version": "0.4.0",
4
+ "version": "0.4.1",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
7
7
  "sideEffects": [