[{"data":1,"prerenderedAt":435},["ShallowReactive",2],{"blog-slugs":3,"project-taqwim-en":8},{"en":4,"ar":7},[5,6],"dynamic-generic-slots","from-renderless-component-to-composable-function",[5,6],{"id":9,"title":10,"body":11,"description":428,"extension":429,"meta":430,"navigation":80,"path":431,"seo":432,"stem":433,"__hash__":434},"projects/projects/en/taqwim.md","Taqwim",{"type":12,"value":13,"toc":421},"minimark",[14,19,23,27,222,229,233,244,385,388,392,399,403,414,417],[15,16,18],"h2",{"id":17},"the-problem","The problem",[20,21,22],"p",{},"The Umm al-Qura calendar uses a table of dates; arithmetic shortcuts can land on the wrong day. Building a calendar separately for each framework also duplicates selection, paging and keyboard logic.",[15,24,26],{"id":25},"date-conversion-and-formatting","Date conversion and formatting",[28,29,34],"pre",{"className":30,"code":31,"language":32,"meta":33,"style":33},"language-ts shiki shiki-themes site-light site-light site-dark","import { formatHijriDate, toGregorian, toHijri } from '@taqwim/core'\n\ntoHijri(new Date('2024-03-11'))\n// => { hy: 1445, hm: 9, hd: 1 }\n\ntoGregorian({ hy: 1445, hm: 9, hd: 1 })\n// => Mon Mar 11 2024\n\nformatHijriDate({ hy: 1445, hm: 9, hd: 1 }, 'iYYYY/iMM/iDD', 'ar')\n// => ١٤٤٥/٠٩/٠١\n","ts","",[35,36,37,75,82,106,113,118,161,167,172,216],"code",{"__ignoreMap":33},[38,39,42,46,50,54,57,60,62,65,68,71],"span",{"class":40,"line":41},"line",1,[38,43,45],{"class":44},"sZ9Zp","import",[38,47,49],{"class":48},"sXnUm"," {",[38,51,53],{"class":52},"sBiod"," formatHijriDate",[38,55,56],{"class":48},",",[38,58,59],{"class":52}," toGregorian",[38,61,56],{"class":48},[38,63,64],{"class":52}," toHijri ",[38,66,67],{"class":48},"}",[38,69,70],{"class":44}," from",[38,72,74],{"class":73},"sgVH1"," '@taqwim/core'\n",[38,76,78],{"class":40,"line":77},2,[38,79,81],{"emptyLinePlaceholder":80},true,"\n",[38,83,85,89,92,95,98,100,103],{"class":40,"line":84},3,[38,86,88],{"class":87},"sUqqj","toHijri",[38,90,91],{"class":48},"(",[38,93,94],{"class":44},"new",[38,96,97],{"class":87}," Date",[38,99,91],{"class":48},[38,101,102],{"class":73},"'2024-03-11'",[38,104,105],{"class":48},"))\n",[38,107,109],{"class":40,"line":108},4,[38,110,112],{"class":111},"s5c__","// => { hy: 1445, hm: 9, hd: 1 }\n",[38,114,116],{"class":40,"line":115},5,[38,117,81],{"emptyLinePlaceholder":80},[38,119,121,124,127,131,134,138,140,143,145,148,150,153,155,158],{"class":40,"line":120},6,[38,122,123],{"class":87},"toGregorian",[38,125,126],{"class":48},"({",[38,128,130],{"class":129},"snYWn"," hy",[38,132,133],{"class":48},":",[38,135,137],{"class":136},"sJ-0L"," 1445",[38,139,56],{"class":48},[38,141,142],{"class":129}," hm",[38,144,133],{"class":48},[38,146,147],{"class":136}," 9",[38,149,56],{"class":48},[38,151,152],{"class":129}," hd",[38,154,133],{"class":48},[38,156,157],{"class":136}," 1",[38,159,160],{"class":48}," })\n",[38,162,164],{"class":40,"line":163},7,[38,165,166],{"class":111},"// => Mon Mar 11 2024\n",[38,168,170],{"class":40,"line":169},8,[38,171,81],{"emptyLinePlaceholder":80},[38,173,175,178,180,182,184,186,188,190,192,194,196,198,200,202,205,208,210,213],{"class":40,"line":174},9,[38,176,177],{"class":87},"formatHijriDate",[38,179,126],{"class":48},[38,181,130],{"class":129},[38,183,133],{"class":48},[38,185,137],{"class":136},[38,187,56],{"class":48},[38,189,142],{"class":129},[38,191,133],{"class":48},[38,193,147],{"class":136},[38,195,56],{"class":48},[38,197,152],{"class":129},[38,199,133],{"class":48},[38,201,157],{"class":136},[38,203,204],{"class":48}," },",[38,206,207],{"class":73}," 'iYYYY/iMM/iDD'",[38,209,56],{"class":48},[38,211,212],{"class":73}," 'ar'",[38,214,215],{"class":48},")\n",[38,217,219],{"class":40,"line":218},10,[38,220,221],{"class":111},"// => ١٤٤٥/٠٩/٠١\n",[20,223,224,225,228],{},"The default Umm al-Qura conversion is table-driven and covers 1343 to 1500 AH, 1924 to 2077 CE. Outside that range it throws a ",[35,226,227],{},"HijriRangeError"," instead of returning a silently wrong date. Islamic Civil and Islamic TBLA are optional strategies you import and pass explicitly, and business-day arithmetic defaults to a Friday and Saturday weekend, overridable per call.",[15,230,232],{"id":231},"one-state-machine-five-frameworks","One state machine, five frameworks",[20,234,235,236,239,240,243],{},"Grid building, selection, paging and keyboard navigation live in one framework-independent state machine. It also defines the ",[35,237,238],{},"data-*"," and ",[35,241,242],{},"aria-*"," attributes used by the Vue, React, Svelte, Solid and Angular bindings. A fix in this shared core can be made once for all five bindings. The end-to-end suite checks the rendered DOM.",[28,245,249],{"className":246,"code":247,"language":248,"meta":33,"style":33},"language-vue shiki shiki-themes site-light site-light site-dark","\u003Cscript setup lang=\"ts\">\nimport { HijriCalendar } from '@taqwim/vue-styled'\nimport { ref } from 'vue'\n\nconst date = ref()\n\u003C/script>\n\n\u003Ctemplate>\n  \u003CHijriCalendar v-model=\"date\" theme=\"islamic\" locale=\"ar\" dir=\"rtl\" />\n\u003C/template>\n","vue",[35,250,251,272,288,304,308,326,331,335,340,380],{"__ignoreMap":33},[38,252,253,256,260,263,266,269],{"class":40,"line":41},[38,254,255],{"class":44},"\u003Cscript",[38,257,259],{"class":258},"sSzyk"," setup",[38,261,262],{"class":258}," lang",[38,264,265],{"class":48},"=",[38,267,268],{"class":73},"\"ts\"",[38,270,271],{"class":44},">\n",[38,273,274,276,278,281,283,285],{"class":40,"line":77},[38,275,45],{"class":44},[38,277,49],{"class":48},[38,279,280],{"class":52}," HijriCalendar ",[38,282,67],{"class":48},[38,284,70],{"class":44},[38,286,287],{"class":73}," '@taqwim/vue-styled'\n",[38,289,290,292,294,297,299,301],{"class":40,"line":84},[38,291,45],{"class":44},[38,293,49],{"class":48},[38,295,296],{"class":52}," ref ",[38,298,67],{"class":48},[38,300,70],{"class":44},[38,302,303],{"class":73}," 'vue'\n",[38,305,306],{"class":40,"line":108},[38,307,81],{"emptyLinePlaceholder":80},[38,309,310,313,316,320,323],{"class":40,"line":115},[38,311,312],{"class":44},"const",[38,314,315],{"class":136}," date",[38,317,319],{"class":318},"sZ7qJ"," =",[38,321,322],{"class":87}," ref",[38,324,325],{"class":48},"()\n",[38,327,328],{"class":40,"line":120},[38,329,330],{"class":44},"\u003C/script>\n",[38,332,333],{"class":40,"line":163},[38,334,81],{"emptyLinePlaceholder":80},[38,336,337],{"class":40,"line":169},[38,338,339],{"class":44},"\u003Ctemplate>\n",[38,341,342,345,348,350,353,356,358,361,364,366,369,372,374,377],{"class":40,"line":174},[38,343,344],{"class":44},"  \u003CHijriCalendar",[38,346,347],{"class":258}," v-model",[38,349,265],{"class":48},[38,351,352],{"class":73},"\"date\"",[38,354,355],{"class":258}," theme",[38,357,265],{"class":48},[38,359,360],{"class":73},"\"islamic\"",[38,362,363],{"class":258}," locale",[38,365,265],{"class":48},[38,367,368],{"class":73},"\"ar\"",[38,370,371],{"class":258}," dir",[38,373,265],{"class":48},[38,375,376],{"class":73},"\"rtl\"",[38,378,379],{"class":44}," />\n",[38,381,382],{"class":40,"line":218},[38,383,384],{"class":44},"\u003C/template>\n",[20,386,387],{},"Each framework gets a headless package with the behaviour and ARIA attributes, and a styled package built from its public parts. The thirteen packages are released together under one version.",[15,389,391],{"id":390},"theming","Theming",[20,393,394,395,398],{},"Thirty-three themes sit on a custom-property contract and are selected with ",[35,396,397],{},"data-taqwim-theme",", not by importing another stylesheet. One page can host several, and switching at runtime is a state change.",[15,400,402],{"id":401},"accessibility","Accessibility",[20,404,405,406,409,410,413],{},"The calendar uses ",[35,407,408],{},"role=\"grid\""," and a roving tabindex. Tab enters and leaves the grid; arrow keys move between dates, with navigation mirrored under ",[35,411,412],{},"dir=\"rtl\"",". Unit tests check the bundled themes' contrast against WCAG AA thresholds, and axe checks the rendered calendar end to end.",[20,415,416],{},"One known gap: Angular is not yet covered by the end-to-end suite.",[418,419,420],"style",{},"html pre.shiki code .sZ9Zp, html code.shiki .sZ9Zp{--shiki-light:#994920;--shiki-default:#994920;--shiki-dark:#ECA457}html pre.shiki code .sXnUm, html code.shiki .sXnUm{--shiki-light:#6D6863;--shiki-default:#6D6863;--shiki-dark:#96918C}html pre.shiki code .sBiod, html code.shiki .sBiod{--shiki-light:#322C28;--shiki-default:#322C28;--shiki-dark:#DBD7D0}html pre.shiki code .sgVH1, html code.shiki .sgVH1{--shiki-light:#3A6830;--shiki-default:#3A6830;--shiki-dark:#A5CF93}html pre.shiki code .sUqqj, html code.shiki .sUqqj{--shiki-light:#4A3170;--shiki-default:#4A3170;--shiki-dark:#D9BDF0}html pre.shiki code .s5c__, html code.shiki .s5c__{--shiki-light:#736D67;--shiki-light-font-style:italic;--shiki-default:#736D67;--shiki-default-font-style:italic;--shiki-dark:#979189;--shiki-dark-font-style:italic}html pre.shiki code .snYWn, html code.shiki .snYWn{--shiki-light:#624727;--shiki-default:#624727;--shiki-dark:#E2C69F}html pre.shiki code .sJ-0L, html code.shiki .sJ-0L{--shiki-light:#2D54A0;--shiki-default:#2D54A0;--shiki-dark:#93BDF5}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sSzyk, html code.shiki .sSzyk{--shiki-light:#5E4784;--shiki-default:#5E4784;--shiki-dark:#CFB0EA}html pre.shiki code .sZ7qJ, html code.shiki .sZ7qJ{--shiki-light:#6D6863;--shiki-default:#6D6863;--shiki-dark:#A39E98}",{"title":33,"searchDepth":77,"depth":77,"links":422},[423,424,425,426,427],{"id":17,"depth":77,"text":18},{"id":25,"depth":77,"text":26},{"id":231,"depth":77,"text":232},{"id":390,"depth":77,"text":391},{"id":401,"depth":77,"text":402},"Hijri date utilities and an accessible calendar for Vue, React, Svelte, Solid and Angular.","md",{},"/projects/en/taqwim",{"title":10,"description":428},"projects/en/taqwim","PeXQ3pBO608i1OzXlxt5VdiTkF_edHLhej2u3feMs8c",1791794146650]