@macolmenerori/component-library 1.2.0 → 1.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 +39 -3
- package/dist/MonthlyCalendar-D-tD_2xK.cjs +2 -0
- package/dist/MonthlyCalendar-D-tD_2xK.cjs.map +1 -0
- package/dist/MonthlyCalendar-D9jC2b2L.js +116 -0
- package/dist/MonthlyCalendar-D9jC2b2L.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/monthly-calendar.cjs +2 -0
- package/dist/monthly-calendar.cjs.map +1 -0
- package/dist/monthly-calendar.js +5 -0
- package/dist/monthly-calendar.js.map +1 -0
- package/dist/types/components/MonthlyCalendar/MonthlyCalendar.d.ts +54 -0
- package/dist/types/components/MonthlyCalendar/index.d.ts +2 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +11 -1
package/README.md
CHANGED
|
@@ -40,9 +40,10 @@ Import components from the library. You can use the main entry point or subpath
|
|
|
40
40
|
|
|
41
41
|
| Import Path | Components | Dependencies Required |
|
|
42
42
|
| -------------------------------------------------- | -------------- | --------------------------------- |
|
|
43
|
-
| `@macolmenerori/component-library`
|
|
44
|
-
| `@macolmenerori/component-library/theme-switch`
|
|
45
|
-
| `@macolmenerori/component-library/
|
|
43
|
+
| `@macolmenerori/component-library` | All | react, react-markdown, remark-gfm |
|
|
44
|
+
| `@macolmenerori/component-library/theme-switch` | ThemeSwitch | react |
|
|
45
|
+
| `@macolmenerori/component-library/monthly-calendar` | MonthlyCalendar | react |
|
|
46
|
+
| `@macolmenerori/component-library/markdown-render` | MarkdownRender | react, react-markdown, remark-gfm |
|
|
46
47
|
|
|
47
48
|
### Available Components
|
|
48
49
|
|
|
@@ -81,6 +82,40 @@ function App() {
|
|
|
81
82
|
|
|
82
83
|
</details>
|
|
83
84
|
|
|
85
|
+
<details>
|
|
86
|
+
<summary><strong>MonthlyCalendar</strong> - A monthly calendar grid with annotation support</summary>
|
|
87
|
+
|
|
88
|
+
A zero-dependency monthly calendar component rendered as a semantic HTML table. Supports per-day annotations (any ReactNode), customizable headers, inline style overrides, and built-in light/dark themes.
|
|
89
|
+
|
|
90
|
+
**Props:**
|
|
91
|
+
|
|
92
|
+
- `year` (number, required): Full four-digit year (e.g. 2026)
|
|
93
|
+
- `month` (number, required): Month to display, 1-based (1 = January, 12 = December)
|
|
94
|
+
- `annotations` ((ReactNode | null | undefined)[], optional): Array of content per day. `annotations[0]` maps to Day 1
|
|
95
|
+
- `headers` (string[7], optional): Array of 7 weekday labels. Omit to hide the header row
|
|
96
|
+
- `style` (CSSProperties, optional): Inline styles merged onto the `<table>` element
|
|
97
|
+
- `darkMode` (boolean, optional): Enables dark color theme (default: `false`)
|
|
98
|
+
|
|
99
|
+
**Example:**
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
import { MonthlyCalendar } from '@macolmenerori/component-library/monthly-calendar';
|
|
103
|
+
|
|
104
|
+
function App() {
|
|
105
|
+
return (
|
|
106
|
+
<MonthlyCalendar
|
|
107
|
+
year={2026}
|
|
108
|
+
month={2}
|
|
109
|
+
headers={['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']}
|
|
110
|
+
/>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
> **Note:** No CSS import is needed. MonthlyCalendar uses inline styles only.
|
|
116
|
+
|
|
117
|
+
</details>
|
|
118
|
+
|
|
84
119
|
<details>
|
|
85
120
|
<summary><strong>MarkdownRender</strong> - A component for rendering markdown strings as HTML</summary>
|
|
86
121
|
|
|
@@ -183,6 +218,7 @@ This will generate multiple entry points:
|
|
|
183
218
|
|
|
184
219
|
- `dist/index.js` / `dist/index.cjs` - Main entry (all components)
|
|
185
220
|
- `dist/theme-switch.js` / `dist/theme-switch.cjs` - ThemeSwitch only
|
|
221
|
+
- `dist/monthly-calendar.js` / `dist/monthly-calendar.cjs` - MonthlyCalendar only
|
|
186
222
|
- `dist/markdown-render.js` / `dist/markdown-render.cjs` - MarkdownRender only
|
|
187
223
|
- `dist/types/` - TypeScript declarations
|
|
188
224
|
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";const e=require("react/jsx-runtime"),C=require("react"),j={dayColor:"#222",headerColor:"#555",annotationColor:"inherit"},b={dayColor:"#f0f0f0",headerColor:"#a0a0b8",annotationColor:"#d0d0e0"},w={borderCollapse:"collapse",border:"none",width:"100%",tableLayout:"fixed",fontFamily:"sans-serif"},y={border:"none",verticalAlign:"top",padding:0,position:"relative",textAlign:"center"},v=({year:s,month:i,annotations:d=[],headers:c,style:p={},darkMode:x=!1})=>{const a=x?b:j,g=C.useMemo(()=>{const t=new Date(s,i,0).getDate(),n=new Date(s,i-1,1).getDay(),o=Math.ceil((n+t)/7)*7,l=[];let r=1-n;for(let h=0;h<o/7;h++){const f=[];for(let u=0;u<7;u++)f.push(r>=1&&r<=t?r:null),r++;l.push(f)}return l},[s,i]),m={...w,...p};return e.jsxs("table",{style:m,children:[c&&e.jsx("thead",{children:e.jsx("tr",{children:c.map((t,n)=>e.jsx("th",{style:{...y,fontWeight:600,fontSize:"0.85rem",paddingBottom:6,color:a.headerColor},children:t},n))})}),e.jsx("tbody",{children:g.map((t,n)=>e.jsx("tr",{children:t.map((o,l)=>e.jsx("td",{style:y,children:e.jsx("div",{style:{width:"100%",paddingBottom:"100%",position:"relative"},children:e.jsx("div",{style:{position:"absolute",inset:0,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"flex-start",paddingTop:6,gap:4,overflow:"hidden"},children:o!==null&&e.jsxs(e.Fragment,{children:[e.jsx("span",{style:{fontFamily:"sans-serif",fontSize:"0.95rem",fontWeight:500,color:a.dayColor},children:o}),d[o-1]!=null&&e.jsx("div",{style:{fontSize:"0.75rem",lineHeight:1.2,overflow:"hidden",width:"100%",textAlign:"center",color:a.annotationColor},children:d[o-1]})]})})})},l))},n))})]})};exports.MonthlyCalendar=v;
|
|
2
|
+
//# sourceMappingURL=MonthlyCalendar-D-tD_2xK.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MonthlyCalendar-D-tD_2xK.cjs","sources":["../src/components/MonthlyCalendar/MonthlyCalendar.tsx"],"sourcesContent":["import React, { CSSProperties, ReactNode, useMemo } from 'react';\n\n/**\n * Props for the MonthlyCalendar component\n */\nexport interface MonthlyCalendarProps {\n /** Full four-digit year (e.g. 2026) */\n year: number;\n /** Month to display, 1-based: 1 = January, 12 = December */\n month: number;\n /**\n * Array of React nodes, one per day of the month.\n * annotations[0] maps to Day 1, annotations[1] maps to Day 2, etc.\n * Use null or undefined for days with no annotation.\n */\n annotations?: (ReactNode | null | undefined)[];\n /**\n * Array of exactly 7 strings for the weekday header labels.\n * Omit to hide the header row entirely.\n */\n headers?: [string, string, string, string, string, string, string];\n /**\n * Inline styles merged onto the table element, overriding defaults via shallow spread.\n */\n style?: CSSProperties;\n /**\n * Enables the dark color theme for day numbers, headers, and annotation text.\n * The component does not set its own background — wrap it in a dark container when enabled.\n * @default false\n */\n darkMode?: boolean;\n}\n\n// ─── Theme definitions ───\n\nconst LIGHT_THEME = {\n dayColor: '#222',\n headerColor: '#555',\n annotationColor: 'inherit'\n};\n\nconst DARK_THEME = {\n dayColor: '#f0f0f0',\n headerColor: '#a0a0b8',\n annotationColor: '#d0d0e0'\n};\n\n// ─── Static style objects ───\n\nconst defaultTableStyle: CSSProperties = {\n borderCollapse: 'collapse',\n border: 'none',\n width: '100%',\n tableLayout: 'fixed',\n fontFamily: 'sans-serif'\n};\n\nconst defaultCellStyle: CSSProperties = {\n border: 'none',\n verticalAlign: 'top',\n padding: 0,\n position: 'relative',\n textAlign: 'center'\n};\n\n/**\n * MonthlyCalendar Component\n *\n * A zero-dependency monthly calendar grid rendered as a semantic HTML table.\n * Each day occupies a square cell with an optional annotation slot that accepts\n * any ReactNode (text, images, badges, icons, or entire sub-components).\n *\n * Features built-in light and dark themes, customizable headers, and\n * table-level style overrides. All styling is inline — no CSS files required.\n *\n * @component\n * @example\n * ```tsx\n * <MonthlyCalendar\n * year={2026}\n * month={2}\n * headers={['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']}\n * darkMode={false}\n * />\n * ```\n */\nconst MonthlyCalendar: React.FC<MonthlyCalendarProps> = ({\n year,\n month,\n annotations = [],\n headers,\n style = {},\n darkMode = false\n}) => {\n const theme = darkMode ? DARK_THEME : LIGHT_THEME;\n\n const weeks = useMemo(() => {\n const daysInMonth = new Date(year, month, 0).getDate();\n const startDay = new Date(year, month - 1, 1).getDay(); // 0=Sun\n const totalCells = Math.ceil((startDay + daysInMonth) / 7) * 7;\n const result: (number | null)[][] = [];\n let currentDay = 1 - startDay;\n\n for (let w = 0; w < totalCells / 7; w++) {\n const week: (number | null)[] = [];\n for (let d = 0; d < 7; d++) {\n week.push(currentDay >= 1 && currentDay <= daysInMonth ? currentDay : null);\n currentDay++;\n }\n result.push(week);\n }\n return result;\n }, [year, month]);\n\n const mergedTableStyle = { ...defaultTableStyle, ...style };\n\n return (\n <table style={mergedTableStyle}>\n {headers && (\n <thead>\n <tr>\n {headers.map((h, i) => (\n <th\n key={i}\n style={{\n ...defaultCellStyle,\n fontWeight: 600,\n fontSize: '0.85rem',\n paddingBottom: 6,\n color: theme.headerColor\n }}\n >\n {h}\n </th>\n ))}\n </tr>\n </thead>\n )}\n <tbody>\n {weeks.map((week, wi) => (\n <tr key={wi}>\n {week.map((day, di) => (\n <td key={di} style={defaultCellStyle}>\n <div\n style={{\n width: '100%',\n paddingBottom: '100%',\n position: 'relative'\n }}\n >\n <div\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'flex-start',\n paddingTop: 6,\n gap: 4,\n overflow: 'hidden'\n }}\n >\n {day !== null && (\n <>\n <span\n style={{\n fontFamily: 'sans-serif',\n fontSize: '0.95rem',\n fontWeight: 500,\n color: theme.dayColor\n }}\n >\n {day}\n </span>\n {annotations[day - 1] != null && (\n <div\n style={{\n fontSize: '0.75rem',\n lineHeight: 1.2,\n overflow: 'hidden',\n width: '100%',\n textAlign: 'center',\n color: theme.annotationColor\n }}\n >\n {annotations[day - 1]}\n </div>\n )}\n </>\n )}\n </div>\n </div>\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n );\n};\n\nexport default MonthlyCalendar;\n"],"names":["LIGHT_THEME","DARK_THEME","defaultTableStyle","defaultCellStyle","MonthlyCalendar","year","month","annotations","headers","style","darkMode","theme","weeks","useMemo","daysInMonth","startDay","totalCells","result","currentDay","w","week","d","mergedTableStyle","jsxs","jsx","h","i","wi","day","di","Fragment"],"mappings":"qEAmCMA,EAAc,CAClB,SAAU,OACV,YAAa,OACb,gBAAiB,SACnB,EAEMC,EAAa,CACjB,SAAU,UACV,YAAa,UACb,gBAAiB,SACnB,EAIMC,EAAmC,CACvC,eAAgB,WAChB,OAAQ,OACR,MAAO,OACP,YAAa,QACb,WAAY,YACd,EAEMC,EAAkC,CACtC,OAAQ,OACR,cAAe,MACf,QAAS,EACT,SAAU,WACV,UAAW,QACb,EAuBMC,EAAkD,CAAC,CACvD,KAAAC,EACA,MAAAC,EACA,YAAAC,EAAc,CAAA,EACd,QAAAC,EACA,MAAAC,EAAQ,CAAA,EACR,SAAAC,EAAW,EACb,IAAM,CACJ,MAAMC,EAAQD,EAAWT,EAAaD,EAEhCY,EAAQC,EAAAA,QAAQ,IAAM,CAC1B,MAAMC,EAAc,IAAI,KAAKT,EAAMC,EAAO,CAAC,EAAE,QAAA,EACvCS,EAAW,IAAI,KAAKV,EAAMC,EAAQ,EAAG,CAAC,EAAE,OAAA,EACxCU,EAAa,KAAK,MAAMD,EAAWD,GAAe,CAAC,EAAI,EACvDG,EAA8B,CAAA,EACpC,IAAIC,EAAa,EAAIH,EAErB,QAASI,EAAI,EAAGA,EAAIH,EAAa,EAAGG,IAAK,CACvC,MAAMC,EAA0B,CAAA,EAChC,QAASC,EAAI,EAAGA,EAAI,EAAGA,IACrBD,EAAK,KAAKF,GAAc,GAAKA,GAAcJ,EAAcI,EAAa,IAAI,EAC1EA,IAEFD,EAAO,KAAKG,CAAI,CAClB,CACA,OAAOH,CACT,EAAG,CAACZ,EAAMC,CAAK,CAAC,EAEVgB,EAAmB,CAAE,GAAGpB,EAAmB,GAAGO,CAAA,EAEpD,OACEc,EAAAA,KAAC,QAAA,CAAM,MAAOD,EACX,SAAA,CAAAd,GACCgB,EAAAA,IAAC,SACC,SAAAA,EAAAA,IAAC,KAAA,CACE,WAAQ,IAAI,CAACC,EAAGC,IACfF,EAAAA,IAAC,KAAA,CAEC,MAAO,CACL,GAAGrB,EACH,WAAY,IACZ,SAAU,UACV,cAAe,EACf,MAAOQ,EAAM,WAAA,EAGd,SAAAc,CAAA,EATIC,CAAA,CAWR,EACH,CAAA,CACF,QAED,QAAA,CACE,SAAAd,EAAM,IAAI,CAACQ,EAAMO,IAChBH,EAAAA,IAAC,KAAA,CACE,SAAAJ,EAAK,IAAI,CAACQ,EAAKC,IACdL,EAAAA,IAAC,KAAA,CAAY,MAAOrB,EAClB,SAAAqB,EAAAA,IAAC,MAAA,CACC,MAAO,CACL,MAAO,OACP,cAAe,OACf,SAAU,UAAA,EAGZ,SAAAA,EAAAA,IAAC,MAAA,CACC,MAAO,CACL,SAAU,WACV,MAAO,EACP,QAAS,OACT,cAAe,SACf,WAAY,SACZ,eAAgB,aAChB,WAAY,EACZ,IAAK,EACL,SAAU,QAAA,EAGX,SAAAI,IAAQ,MACPL,EAAAA,KAAAO,EAAAA,SAAA,CACE,SAAA,CAAAN,EAAAA,IAAC,OAAA,CACC,MAAO,CACL,WAAY,aACZ,SAAU,UACV,WAAY,IACZ,MAAOb,EAAM,QAAA,EAGd,SAAAiB,CAAA,CAAA,EAEFrB,EAAYqB,EAAM,CAAC,GAAK,MACvBJ,EAAAA,IAAC,MAAA,CACC,MAAO,CACL,SAAU,UACV,WAAY,IACZ,SAAU,SACV,MAAO,OACP,UAAW,SACX,MAAOb,EAAM,eAAA,EAGd,SAAAJ,EAAYqB,EAAM,CAAC,CAAA,CAAA,CACtB,CAAA,CAEJ,CAAA,CAAA,CAEJ,CAAA,GAjDKC,CAmDT,CACD,GAtDMF,CAuDT,CACD,CAAA,CACH,CAAA,EACF,CAEJ"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { jsxs as y, jsx as e, Fragment as w } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo as x } from "react";
|
|
3
|
+
const v = {
|
|
4
|
+
dayColor: "#222",
|
|
5
|
+
headerColor: "#555",
|
|
6
|
+
annotationColor: "inherit"
|
|
7
|
+
}, D = {
|
|
8
|
+
dayColor: "#f0f0f0",
|
|
9
|
+
headerColor: "#a0a0b8",
|
|
10
|
+
annotationColor: "#d0d0e0"
|
|
11
|
+
}, M = {
|
|
12
|
+
borderCollapse: "collapse",
|
|
13
|
+
border: "none",
|
|
14
|
+
width: "100%",
|
|
15
|
+
tableLayout: "fixed",
|
|
16
|
+
fontFamily: "sans-serif"
|
|
17
|
+
}, m = {
|
|
18
|
+
border: "none",
|
|
19
|
+
verticalAlign: "top",
|
|
20
|
+
padding: 0,
|
|
21
|
+
position: "relative",
|
|
22
|
+
textAlign: "center"
|
|
23
|
+
}, A = ({
|
|
24
|
+
year: i,
|
|
25
|
+
month: a,
|
|
26
|
+
annotations: d = [],
|
|
27
|
+
headers: c,
|
|
28
|
+
style: g = {},
|
|
29
|
+
darkMode: u = !1
|
|
30
|
+
}) => {
|
|
31
|
+
const s = u ? D : v, C = x(() => {
|
|
32
|
+
const t = new Date(i, a, 0).getDate(), o = new Date(i, a - 1, 1).getDay(), l = Math.ceil((o + t) / 7) * 7, n = [];
|
|
33
|
+
let r = 1 - o;
|
|
34
|
+
for (let h = 0; h < l / 7; h++) {
|
|
35
|
+
const f = [];
|
|
36
|
+
for (let p = 0; p < 7; p++)
|
|
37
|
+
f.push(r >= 1 && r <= t ? r : null), r++;
|
|
38
|
+
n.push(f);
|
|
39
|
+
}
|
|
40
|
+
return n;
|
|
41
|
+
}, [i, a]), b = { ...M, ...g };
|
|
42
|
+
return /* @__PURE__ */ y("table", { style: b, children: [
|
|
43
|
+
c && /* @__PURE__ */ e("thead", { children: /* @__PURE__ */ e("tr", { children: c.map((t, o) => /* @__PURE__ */ e(
|
|
44
|
+
"th",
|
|
45
|
+
{
|
|
46
|
+
style: {
|
|
47
|
+
...m,
|
|
48
|
+
fontWeight: 600,
|
|
49
|
+
fontSize: "0.85rem",
|
|
50
|
+
paddingBottom: 6,
|
|
51
|
+
color: s.headerColor
|
|
52
|
+
},
|
|
53
|
+
children: t
|
|
54
|
+
},
|
|
55
|
+
o
|
|
56
|
+
)) }) }),
|
|
57
|
+
/* @__PURE__ */ e("tbody", { children: C.map((t, o) => /* @__PURE__ */ e("tr", { children: t.map((l, n) => /* @__PURE__ */ e("td", { style: m, children: /* @__PURE__ */ e(
|
|
58
|
+
"div",
|
|
59
|
+
{
|
|
60
|
+
style: {
|
|
61
|
+
width: "100%",
|
|
62
|
+
paddingBottom: "100%",
|
|
63
|
+
position: "relative"
|
|
64
|
+
},
|
|
65
|
+
children: /* @__PURE__ */ e(
|
|
66
|
+
"div",
|
|
67
|
+
{
|
|
68
|
+
style: {
|
|
69
|
+
position: "absolute",
|
|
70
|
+
inset: 0,
|
|
71
|
+
display: "flex",
|
|
72
|
+
flexDirection: "column",
|
|
73
|
+
alignItems: "center",
|
|
74
|
+
justifyContent: "flex-start",
|
|
75
|
+
paddingTop: 6,
|
|
76
|
+
gap: 4,
|
|
77
|
+
overflow: "hidden"
|
|
78
|
+
},
|
|
79
|
+
children: l !== null && /* @__PURE__ */ y(w, { children: [
|
|
80
|
+
/* @__PURE__ */ e(
|
|
81
|
+
"span",
|
|
82
|
+
{
|
|
83
|
+
style: {
|
|
84
|
+
fontFamily: "sans-serif",
|
|
85
|
+
fontSize: "0.95rem",
|
|
86
|
+
fontWeight: 500,
|
|
87
|
+
color: s.dayColor
|
|
88
|
+
},
|
|
89
|
+
children: l
|
|
90
|
+
}
|
|
91
|
+
),
|
|
92
|
+
d[l - 1] != null && /* @__PURE__ */ e(
|
|
93
|
+
"div",
|
|
94
|
+
{
|
|
95
|
+
style: {
|
|
96
|
+
fontSize: "0.75rem",
|
|
97
|
+
lineHeight: 1.2,
|
|
98
|
+
overflow: "hidden",
|
|
99
|
+
width: "100%",
|
|
100
|
+
textAlign: "center",
|
|
101
|
+
color: s.annotationColor
|
|
102
|
+
},
|
|
103
|
+
children: d[l - 1]
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
] })
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
) }, n)) }, o)) })
|
|
111
|
+
] });
|
|
112
|
+
};
|
|
113
|
+
export {
|
|
114
|
+
A as M
|
|
115
|
+
};
|
|
116
|
+
//# sourceMappingURL=MonthlyCalendar-D9jC2b2L.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MonthlyCalendar-D9jC2b2L.js","sources":["../src/components/MonthlyCalendar/MonthlyCalendar.tsx"],"sourcesContent":["import React, { CSSProperties, ReactNode, useMemo } from 'react';\n\n/**\n * Props for the MonthlyCalendar component\n */\nexport interface MonthlyCalendarProps {\n /** Full four-digit year (e.g. 2026) */\n year: number;\n /** Month to display, 1-based: 1 = January, 12 = December */\n month: number;\n /**\n * Array of React nodes, one per day of the month.\n * annotations[0] maps to Day 1, annotations[1] maps to Day 2, etc.\n * Use null or undefined for days with no annotation.\n */\n annotations?: (ReactNode | null | undefined)[];\n /**\n * Array of exactly 7 strings for the weekday header labels.\n * Omit to hide the header row entirely.\n */\n headers?: [string, string, string, string, string, string, string];\n /**\n * Inline styles merged onto the table element, overriding defaults via shallow spread.\n */\n style?: CSSProperties;\n /**\n * Enables the dark color theme for day numbers, headers, and annotation text.\n * The component does not set its own background — wrap it in a dark container when enabled.\n * @default false\n */\n darkMode?: boolean;\n}\n\n// ─── Theme definitions ───\n\nconst LIGHT_THEME = {\n dayColor: '#222',\n headerColor: '#555',\n annotationColor: 'inherit'\n};\n\nconst DARK_THEME = {\n dayColor: '#f0f0f0',\n headerColor: '#a0a0b8',\n annotationColor: '#d0d0e0'\n};\n\n// ─── Static style objects ───\n\nconst defaultTableStyle: CSSProperties = {\n borderCollapse: 'collapse',\n border: 'none',\n width: '100%',\n tableLayout: 'fixed',\n fontFamily: 'sans-serif'\n};\n\nconst defaultCellStyle: CSSProperties = {\n border: 'none',\n verticalAlign: 'top',\n padding: 0,\n position: 'relative',\n textAlign: 'center'\n};\n\n/**\n * MonthlyCalendar Component\n *\n * A zero-dependency monthly calendar grid rendered as a semantic HTML table.\n * Each day occupies a square cell with an optional annotation slot that accepts\n * any ReactNode (text, images, badges, icons, or entire sub-components).\n *\n * Features built-in light and dark themes, customizable headers, and\n * table-level style overrides. All styling is inline — no CSS files required.\n *\n * @component\n * @example\n * ```tsx\n * <MonthlyCalendar\n * year={2026}\n * month={2}\n * headers={['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']}\n * darkMode={false}\n * />\n * ```\n */\nconst MonthlyCalendar: React.FC<MonthlyCalendarProps> = ({\n year,\n month,\n annotations = [],\n headers,\n style = {},\n darkMode = false\n}) => {\n const theme = darkMode ? DARK_THEME : LIGHT_THEME;\n\n const weeks = useMemo(() => {\n const daysInMonth = new Date(year, month, 0).getDate();\n const startDay = new Date(year, month - 1, 1).getDay(); // 0=Sun\n const totalCells = Math.ceil((startDay + daysInMonth) / 7) * 7;\n const result: (number | null)[][] = [];\n let currentDay = 1 - startDay;\n\n for (let w = 0; w < totalCells / 7; w++) {\n const week: (number | null)[] = [];\n for (let d = 0; d < 7; d++) {\n week.push(currentDay >= 1 && currentDay <= daysInMonth ? currentDay : null);\n currentDay++;\n }\n result.push(week);\n }\n return result;\n }, [year, month]);\n\n const mergedTableStyle = { ...defaultTableStyle, ...style };\n\n return (\n <table style={mergedTableStyle}>\n {headers && (\n <thead>\n <tr>\n {headers.map((h, i) => (\n <th\n key={i}\n style={{\n ...defaultCellStyle,\n fontWeight: 600,\n fontSize: '0.85rem',\n paddingBottom: 6,\n color: theme.headerColor\n }}\n >\n {h}\n </th>\n ))}\n </tr>\n </thead>\n )}\n <tbody>\n {weeks.map((week, wi) => (\n <tr key={wi}>\n {week.map((day, di) => (\n <td key={di} style={defaultCellStyle}>\n <div\n style={{\n width: '100%',\n paddingBottom: '100%',\n position: 'relative'\n }}\n >\n <div\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'flex-start',\n paddingTop: 6,\n gap: 4,\n overflow: 'hidden'\n }}\n >\n {day !== null && (\n <>\n <span\n style={{\n fontFamily: 'sans-serif',\n fontSize: '0.95rem',\n fontWeight: 500,\n color: theme.dayColor\n }}\n >\n {day}\n </span>\n {annotations[day - 1] != null && (\n <div\n style={{\n fontSize: '0.75rem',\n lineHeight: 1.2,\n overflow: 'hidden',\n width: '100%',\n textAlign: 'center',\n color: theme.annotationColor\n }}\n >\n {annotations[day - 1]}\n </div>\n )}\n </>\n )}\n </div>\n </div>\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n );\n};\n\nexport default MonthlyCalendar;\n"],"names":["LIGHT_THEME","DARK_THEME","defaultTableStyle","defaultCellStyle","MonthlyCalendar","year","month","annotations","headers","style","darkMode","theme","weeks","useMemo","daysInMonth","startDay","totalCells","result","currentDay","w","week","d","mergedTableStyle","jsxs","jsx","h","i","wi","day","di","Fragment"],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./MarkdownRender-BOGosy9w.cjs"),r=require("./ThemeSwitch-C7k1_MA4.cjs");exports.MarkdownRender=e.MarkdownRender;exports.
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./MarkdownRender-BOGosy9w.cjs"),r=require("./MonthlyCalendar-D-tD_2xK.cjs"),n=require("./ThemeSwitch-C7k1_MA4.cjs");exports.MarkdownRender=e.MarkdownRender;exports.MonthlyCalendar=r.MonthlyCalendar;exports.ThemeSwitch=n.ThemeSwitch;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { M as o } from "./MarkdownRender-BmrS3q0l.js";
|
|
2
|
-
import {
|
|
2
|
+
import { M as t } from "./MonthlyCalendar-D9jC2b2L.js";
|
|
3
|
+
import { T as n } from "./ThemeSwitch-DbaEio36.js";
|
|
3
4
|
export {
|
|
4
5
|
o as MarkdownRender,
|
|
5
|
-
|
|
6
|
+
t as MonthlyCalendar,
|
|
7
|
+
n as ThemeSwitch
|
|
6
8
|
};
|
|
7
9
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monthly-calendar.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monthly-calendar.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { default as React, CSSProperties, ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Props for the MonthlyCalendar component
|
|
4
|
+
*/
|
|
5
|
+
export interface MonthlyCalendarProps {
|
|
6
|
+
/** Full four-digit year (e.g. 2026) */
|
|
7
|
+
year: number;
|
|
8
|
+
/** Month to display, 1-based: 1 = January, 12 = December */
|
|
9
|
+
month: number;
|
|
10
|
+
/**
|
|
11
|
+
* Array of React nodes, one per day of the month.
|
|
12
|
+
* annotations[0] maps to Day 1, annotations[1] maps to Day 2, etc.
|
|
13
|
+
* Use null or undefined for days with no annotation.
|
|
14
|
+
*/
|
|
15
|
+
annotations?: (ReactNode | null | undefined)[];
|
|
16
|
+
/**
|
|
17
|
+
* Array of exactly 7 strings for the weekday header labels.
|
|
18
|
+
* Omit to hide the header row entirely.
|
|
19
|
+
*/
|
|
20
|
+
headers?: [string, string, string, string, string, string, string];
|
|
21
|
+
/**
|
|
22
|
+
* Inline styles merged onto the table element, overriding defaults via shallow spread.
|
|
23
|
+
*/
|
|
24
|
+
style?: CSSProperties;
|
|
25
|
+
/**
|
|
26
|
+
* Enables the dark color theme for day numbers, headers, and annotation text.
|
|
27
|
+
* The component does not set its own background — wrap it in a dark container when enabled.
|
|
28
|
+
* @default false
|
|
29
|
+
*/
|
|
30
|
+
darkMode?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* MonthlyCalendar Component
|
|
34
|
+
*
|
|
35
|
+
* A zero-dependency monthly calendar grid rendered as a semantic HTML table.
|
|
36
|
+
* Each day occupies a square cell with an optional annotation slot that accepts
|
|
37
|
+
* any ReactNode (text, images, badges, icons, or entire sub-components).
|
|
38
|
+
*
|
|
39
|
+
* Features built-in light and dark themes, customizable headers, and
|
|
40
|
+
* table-level style overrides. All styling is inline — no CSS files required.
|
|
41
|
+
*
|
|
42
|
+
* @component
|
|
43
|
+
* @example
|
|
44
|
+
* ```tsx
|
|
45
|
+
* <MonthlyCalendar
|
|
46
|
+
* year={2026}
|
|
47
|
+
* month={2}
|
|
48
|
+
* headers={['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']}
|
|
49
|
+
* darkMode={false}
|
|
50
|
+
* />
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
declare const MonthlyCalendar: React.FC<MonthlyCalendarProps>;
|
|
54
|
+
export default MonthlyCalendar;
|
package/dist/types/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@macolmenerori/component-library",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "",
|
|
6
6
|
"keywords": [],
|
|
@@ -47,6 +47,16 @@
|
|
|
47
47
|
"types": "./dist/types/components/MarkdownRender/index.d.ts",
|
|
48
48
|
"default": "./dist/markdown-render.cjs"
|
|
49
49
|
}
|
|
50
|
+
},
|
|
51
|
+
"./monthly-calendar": {
|
|
52
|
+
"import": {
|
|
53
|
+
"types": "./dist/types/components/MonthlyCalendar/index.d.ts",
|
|
54
|
+
"default": "./dist/monthly-calendar.js"
|
|
55
|
+
},
|
|
56
|
+
"require": {
|
|
57
|
+
"types": "./dist/types/components/MonthlyCalendar/index.d.ts",
|
|
58
|
+
"default": "./dist/monthly-calendar.cjs"
|
|
59
|
+
}
|
|
50
60
|
}
|
|
51
61
|
},
|
|
52
62
|
"sideEffects": [
|