[{"data":1,"prerenderedAt":4871},["ShallowReactive",2],{"categories":3,"registry-index":322,"registry-item-event-calendar":4789},[4,9,14,19,24,29,34,39,44,49,54,59,64,68,72,77,82,87,91,95,100,105,109,114,118,122,126,130,134,138,143,147,151,156,161,166,171,175,179,183,187,192,196,200,204,208,212,216,220,224,228,233,237,241,246,251,255,259,263,267,272,276,280,284,288,292,296,300,304,308,313,317],{"name":5,"label":6,"description":7,"count":8},"accordion","Accordion","Open-source shadcn accordion components for FAQ layouts, settings panels, and help sections.",11,{"name":10,"label":11,"description":12,"count":13},"alert","Alert","Open-source shadcn alert components for status messages, warning banners, and destructive notices.",20,{"name":15,"label":16,"description":17,"count":18},"alert-dialog","Alert Dialog","Open-source shadcn alert dialog components for delete confirmations, destructive actions, and critical decisions.",14,{"name":20,"label":21,"description":22,"count":23},"aspect-ratio","Aspect Ratio","Open-source shadcn aspect ratio components for responsive media, image galleries, and video previews.",8,{"name":25,"label":26,"description":27,"count":28},"autocomplete","Autocomplete","Open-source shadcn autocomplete components for smart search, typeahead inputs, and suggestion lists.",12,{"name":30,"label":31,"description":32,"count":33},"avatar","Avatar","Open-source shadcn avatar components for user profiles, team directories, and comment threads.",35,{"name":35,"label":36,"description":37,"count":38},"badge","Badge","Open-source shadcn badge components for status labels, feature tags, and count indicators.",25,{"name":40,"label":41,"description":42,"count":43},"breadcrumb","Breadcrumb","Open-source shadcn breadcrumb components for navigation trails, docs hierarchy, and app wayfinding.",15,{"name":45,"label":46,"description":47,"count":48},"button","Button","Open-source shadcn button components for primary actions, form submissions, and toolbar controls.",61,{"name":50,"label":51,"description":52,"count":53},"button-group","Button Group","Open-source shadcn button group components for segmented controls, toolbar actions, and view switchers.",57,{"name":55,"label":56,"description":57,"count":58},"calendar","Calendar","Open-source shadcn calendar components for date picking, scheduling flows, and booking interfaces.",30,{"name":60,"label":61,"description":62,"count":63},"card","Card","Open-source shadcn card components for content previews, dashboard widgets, and product summaries.",18,{"name":65,"label":66,"description":67,"count":8},"carousel","Carousel","Open-source shadcn carousel components for image galleries, feature showcases, and testimonials.",{"name":69,"label":70,"description":71,"count":38},"chart","Chart","Open-source shadcn chart components for analytics dashboards, KPI tracking, and reports.",{"name":73,"label":74,"description":75,"count":76},"checkbox","Checkbox","Open-source shadcn checkbox components for multi-select forms, settings preferences, and table selection.",22,{"name":78,"label":79,"description":80,"count":81},"collapsible","Collapsible","Open-source shadcn collapsible components for expandable sections, detail rows, and progressive disclosure.",10,{"name":83,"label":84,"description":85,"count":86},"combobox","Combobox","Open-source shadcn combobox components for searchable selection, async lookup, and command menus.",28,{"name":88,"label":89,"description":90,"count":23},"command","Command","Open-source shadcn command menu components for command palettes, global search, and power-user navigation.",{"name":92,"label":93,"description":94,"count":81},"context-menu","Context Menu","Open-source shadcn context menu components for right-click menus, file actions, and table row actions.",{"name":96,"label":97,"description":98,"count":99},"data-grid","Data Grid","Open-source shadcn data grid components for sorting and filtering, virtualized tables, and admin dashboards.",29,{"name":101,"label":102,"description":103,"count":104},"date-selector","Date Selector","Open-source shadcn date selector components for date range picking, booking windows, and calendar filters.",4,{"name":106,"label":107,"description":108,"count":81},"dialog","Dialog","Open-source shadcn dialog components for modal forms, focused tasks, and confirmations.",{"name":110,"label":111,"description":112,"count":113},"drawer","Drawer","Open-source shadcn drawer components for mobile panels, slide-over forms, and secondary workflows.",5,{"name":115,"label":116,"description":117,"count":63},"dropdown-menu","Dropdown Menu","Open-source shadcn dropdown menu components for action menus, profile menus, and toolbar menus.",{"name":119,"label":120,"description":121,"count":13},"empty","Empty","Open-source shadcn empty state components for zero-data screens, first-run onboarding, and guided next steps.",{"name":123,"label":124,"description":125,"count":113},"event-calendar","Event Calendar","Open-source shadcn event calendar components with month, week, day and agenda views, and drag-and-drop scheduling.",{"name":127,"label":128,"description":129,"count":8},"field","Field","Open-source shadcn form field components for form composition, validated inputs, and helper text.",{"name":131,"label":132,"description":133,"count":81},"file-upload","File Upload","Open-source shadcn file upload components for drag-and-drop uploads, multi-file flows, and upload progress.",{"name":135,"label":136,"description":137,"count":28},"filters","Filters","Open-source shadcn filters components for filter bars, faceted search, and dashboard filtering.",{"name":139,"label":140,"description":141,"count":142},"frame","Frame","Open-source shadcn frame components for embedded previews, app shells, and device mockups.",19,{"name":144,"label":145,"description":146,"count":113},"gantt","Gantt","Open-source shadcn gantt components with split tree and timeline panes, drag scheduling, and progress rollups.",{"name":148,"label":149,"description":150,"count":23},"hover-card","Hover Card","Open-source shadcn hover card components for profile previews, rich link previews, and contextual details.",{"name":152,"label":153,"description":154,"count":155},"icon-stack","Icon Stack","",6,{"name":157,"label":158,"description":159,"count":160},"icon-tile","Icon Tile","Open-source shadcn icon tile components for list row media, feature cards, empty states, and dashboard tiles.",17,{"name":162,"label":163,"description":164,"count":165},"input","Input","Open-source shadcn input components for form entry, search fields, and auth screens.",31,{"name":167,"label":168,"description":169,"count":170},"input-group","Input Group","Open-source shadcn input group components for prefixed inputs, suffixed actions, and combined form controls.",40,{"name":172,"label":173,"description":174,"count":155},"input-otp","Input Otp","Open-source shadcn OTP input components for verification codes, 2FA flows, and secure confirmation screens.",{"name":176,"label":177,"description":178,"count":28},"item","Item","Open-source shadcn item row components for list rows, settings items, and action rows.",{"name":180,"label":181,"description":182,"count":155},"kanban","Kanban","Open-source shadcn kanban components for task boards, workflow pipelines, and drag-and-drop planning.",{"name":184,"label":185,"description":186,"count":155},"kbd","Kbd","Open-source shadcn keyboard shortcut components for hotkey hints, command docs, and shortcut legends.",{"name":188,"label":189,"description":190,"count":191},"label","Label","Open-source shadcn label components for form labels, accessible inputs, and field pairing.",13,{"name":193,"label":194,"description":195,"count":113},"menubar","Menubar","Open-source shadcn menubar components for desktop navigation, editor menus, and app commands.",{"name":197,"label":198,"description":199,"count":155},"native-select","Native Select","Open-source shadcn native select components for lightweight selects, mobile-friendly forms, and basic option picking.",{"name":201,"label":202,"description":203,"count":104},"navigation-menu","Navigation Menu","Open-source shadcn navigation menu components for site navigation, mega menus, and product navigation.",{"name":205,"label":206,"description":207,"count":155},"number-field","Number Field","Open-source shadcn number field components for quantity pickers, pricing inputs, and step controls.",{"name":209,"label":210,"description":211,"count":43},"pagination","Pagination","Open-source shadcn pagination components for table pagination, search results, and content archives.",{"name":213,"label":214,"description":215,"count":23},"phone-input","Phone Input","Open-source shadcn phone input components for international signup, contact forms, and country codes.",{"name":217,"label":218,"description":219,"count":8},"popover","Popover","Open-source shadcn popover components for inline settings, contextual actions, and lightweight overlays.",{"name":221,"label":222,"description":223,"count":23},"progress","Progress","Open-source shadcn progress components for upload progress, goal tracking, and setup steps.",{"name":225,"label":226,"description":227,"count":160},"radio-group","Radio Group","Open-source shadcn radio group components for single-choice forms, plan selection, and settings preferences.",{"name":229,"label":230,"description":231,"count":232},"rating","Rating","Open-source shadcn rating components for product reviews, feedback forms, and satisfaction scores.",9,{"name":234,"label":235,"description":236,"count":81},"resizable","Resizable","Open-source shadcn resizable components for split panes, workspace layouts, and draggable dividers.",{"name":238,"label":239,"description":240,"count":113},"scroll-area","Scroll Area","Open-source shadcn scroll area components for custom scroll regions, sidebar panes, and dense lists.",{"name":242,"label":243,"description":244,"count":245},"scrollspy","Scrollspy","Open-source shadcn scrollspy components for docs navigation, active table of contents, and long-form sections.",2,{"name":247,"label":248,"description":249,"count":250},"select","Select","Open-source shadcn select components for form selection, settings menus, and filter controls.",33,{"name":252,"label":253,"description":254,"count":155},"separator","Separator","Open-source shadcn separator components for content grouping, toolbar dividers, and section breaks.",{"name":256,"label":257,"description":258,"count":104},"sheet","Sheet","Open-source shadcn sheet components for slide-over details, side panels, and task flows.",{"name":260,"label":261,"description":262,"count":81},"skeleton","Skeleton","Open-source shadcn skeleton components for loading placeholders, perceived performance, and content previews.",{"name":264,"label":265,"description":266,"count":28},"slider","Slider","Open-source shadcn slider components for range filters, pricing controls, and media settings.",{"name":268,"label":269,"description":270,"count":271},"sonner","Sonner","Open-source shadcn Sonner toast components for success feedback, error states, and non-blocking updates.",21,{"name":273,"label":274,"description":275,"count":23},"sortable","Sortable","Open-source shadcn sortable components for drag-and-drop lists, priority ranking, and reordering rows.",{"name":277,"label":278,"description":279,"count":28},"spinner","Spinner","Open-source shadcn spinner components for loading indicators, async actions, and button states.",{"name":281,"label":282,"description":283,"count":43},"stepper","Stepper","Open-source shadcn stepper components for multi-step forms, checkout flows, and onboarding.",{"name":285,"label":286,"description":287,"count":18},"switch","Switch","Open-source shadcn switch components for settings toggles, preferences, and binary choices.",{"name":289,"label":290,"description":291,"count":160},"table","Table","Open-source shadcn table components for admin tables, data display, and responsive lists.",{"name":293,"label":294,"description":295,"count":232},"tabs","Tabs","Open-source shadcn tabs components for segmented content, settings views, and dashboard sections.",{"name":297,"label":298,"description":299,"count":155},"textarea","Textarea","Open-source shadcn textarea components for comments, long-form input, and support tickets.",{"name":301,"label":302,"description":303,"count":28},"timeline","Timeline","Open-source shadcn timeline components for activity feeds, roadmaps, and event history.",{"name":305,"label":306,"description":307,"count":18},"toggle","Toggle","Open-source shadcn toggle components for formatting controls, compact actions, and binary UI states.",{"name":309,"label":310,"description":311,"count":312},"toggle-group","Toggle Group","Open-source shadcn toggle group components for view switches, toolbar options, and mutually exclusive actions.",16,{"name":314,"label":315,"description":316,"count":312},"tooltip","Tooltip","Open-source shadcn tooltip components for inline hints, contextual guidance, and helper text.",{"name":318,"label":319,"description":320,"count":321},"tree","Tree","Open-source shadcn tree components for file explorers, nested navigation, and hierarchical data.",7,{"$schema":323,"name":324,"homepage":325,"items":326},"https:\u002F\u002Fshadcn-vue.com\u002Fschema\u002Fregistry.json","revueui","https:\u002F\u002Frevueui.io",[327,332,335,338,341,344,347,350,353,356,359,362,365,368,371,374,377,380,383,386,389,392,395,398,401,404,407,410,413,416,419,422,425,428,431,434,437,440,443,446,449,452,455,458,461,464,467,470,473,476,479,484,487,490,493,496,499,502,505,508,511,514,517,520,523,526,529,532,535,538,541,548,553,559,564,569,574,579,583,587,591,595,599,603,607,611,615,619,623,627,631,635,639,643,647,651,655,659,663,667,671,675,679,683,687,691,695,699,703,707,711,714,718,722,726,730,734,738,742,746,750,753,757,761,765,769,773,777,781,785,789,793,797,801,805,809,813,817,821,825,829,833,837,841,845,849,853,857,861,865,868,872,876,880,884,888,892,896,900,904,908,912,916,920,924,928,931,935,939,943,947,951,955,959,963,967,971,975,979,983,987,991,995,999,1003,1007,1011,1015,1019,1023,1027,1031,1035,1039,1043,1047,1051,1055,1059,1063,1067,1071,1075,1079,1083,1087,1091,1095,1099,1103,1107,1111,1115,1119,1123,1127,1131,1135,1139,1143,1147,1151,1155,1159,1163,1167,1171,1175,1179,1183,1187,1191,1195,1199,1203,1207,1211,1214,1218,1222,1226,1230,1234,1238,1242,1246,1250,1254,1258,1262,1266,1270,1274,1278,1282,1286,1290,1294,1298,1302,1306,1310,1314,1318,1322,1326,1330,1334,1338,1342,1346,1350,1354,1358,1362,1366,1370,1374,1378,1382,1386,1390,1394,1398,1402,1406,1410,1414,1418,1422,1426,1430,1434,1438,1442,1446,1450,1454,1458,1462,1466,1470,1474,1478,1482,1486,1490,1493,1497,1501,1505,1509,1513,1517,1521,1525,1529,1533,1537,1541,1545,1549,1553,1557,1561,1565,1569,1573,1577,1581,1585,1589,1593,1597,1601,1605,1609,1613,1617,1621,1625,1629,1633,1637,1641,1645,1649,1653,1657,1661,1665,1669,1672,1676,1680,1684,1688,1692,1696,1700,1704,1708,1712,1716,1720,1724,1728,1732,1736,1740,1744,1748,1752,1756,1760,1764,1768,1772,1776,1780,1784,1788,1792,1796,1800,1804,1808,1812,1816,1820,1824,1828,1832,1836,1840,1844,1848,1852,1856,1860,1864,1868,1872,1876,1880,1884,1888,1892,1896,1900,1904,1908,1912,1916,1920,1924,1928,1932,1936,1940,1944,1948,1952,1956,1960,1964,1968,1972,1976,1980,1983,1987,1990,1994,1998,2002,2006,2010,2013,2017,2021,2025,2029,2033,2037,2041,2045,2049,2053,2057,2061,2065,2069,2073,2077,2081,2085,2089,2093,2097,2101,2105,2109,2113,2117,2121,2125,2129,2133,2137,2141,2145,2149,2153,2157,2161,2165,2169,2173,2177,2181,2185,2189,2193,2197,2201,2205,2209,2213,2217,2221,2225,2229,2233,2237,2241,2245,2249,2253,2257,2261,2265,2269,2273,2277,2281,2285,2289,2293,2297,2301,2305,2309,2313,2317,2321,2325,2329,2333,2337,2341,2345,2349,2353,2357,2361,2365,2369,2373,2377,2381,2385,2389,2393,2397,2401,2405,2409,2413,2417,2421,2425,2429,2433,2437,2441,2445,2449,2453,2457,2461,2465,2469,2473,2477,2481,2485,2489,2493,2497,2501,2505,2509,2513,2517,2521,2525,2529,2533,2537,2541,2545,2549,2553,2557,2561,2565,2569,2573,2577,2581,2585,2589,2593,2597,2602,2606,2610,2614,2618,2622,2626,2630,2634,2638,2642,2646,2650,2654,2658,2662,2666,2670,2674,2678,2682,2686,2690,2694,2698,2702,2706,2710,2714,2718,2722,2726,2730,2734,2738,2742,2746,2750,2754,2758,2762,2766,2770,2773,2777,2781,2785,2789,2793,2797,2801,2805,2809,2813,2817,2821,2825,2830,2834,2838,2842,2846,2850,2854,2858,2862,2866,2870,2875,2880,2885,2890,2895,2900,2904,2909,2914,2919,2924,2929,2934,2939,2944,2949,2954,2959,2964,2969,2974,2979,2984,2988,2992,2996,3000,3004,3008,3012,3016,3020,3024,3028,3032,3036,3040,3044,3048,3052,3056,3060,3064,3068,3072,3076,3080,3084,3088,3092,3096,3100,3104,3108,3112,3116,3120,3124,3128,3132,3136,3140,3144,3148,3152,3156,3160,3164,3168,3172,3176,3180,3184,3188,3192,3196,3200,3204,3208,3212,3216,3220,3224,3228,3232,3236,3240,3244,3248,3252,3256,3260,3264,3268,3272,3276,3280,3284,3288,3292,3296,3300,3304,3308,3312,3316,3320,3324,3328,3332,3336,3340,3344,3348,3352,3356,3360,3365,3369,3373,3377,3381,3385,3389,3393,3397,3401,3405,3409,3413,3417,3421,3425,3429,3433,3437,3441,3445,3449,3453,3457,3461,3465,3469,3473,3477,3481,3485,3489,3493,3497,3501,3505,3508,3511,3515,3519,3523,3527,3531,3535,3539,3543,3547,3551,3555,3559,3563,3567,3571,3575,3579,3583,3587,3591,3595,3599,3603,3607,3611,3615,3619,3623,3627,3631,3635,3639,3643,3647,3651,3655,3659,3663,3667,3671,3675,3679,3683,3687,3691,3695,3699,3703,3707,3711,3715,3719,3723,3727,3731,3735,3739,3743,3747,3751,3755,3759,3763,3767,3771,3775,3779,3783,3787,3791,3795,3799,3803,3807,3811,3815,3819,3823,3827,3831,3835,3839,3843,3847,3851,3855,3859,3862,3866,3870,3874,3878,3882,3886,3890,3894,3898,3902,3906,3910,3914,3918,3922,3926,3930,3934,3938,3942,3946,3950,3954,3958,3962,3966,3970,3974,3978,3982,3986,3990,3994,3998,4002,4006,4010,4014,4018,4022,4025,4029,4033,4037,4041,4045,4049,4053,4057,4061,4065,4069,4073,4077,4081,4085,4089,4093,4097,4101,4105,4109,4113,4117,4121,4125,4129,4133,4137,4141,4145,4149,4153,4157,4161,4165,4169,4173,4177,4181,4185,4189,4193,4197,4201,4205,4209,4213,4217,4221,4225,4229,4233,4238,4242,4246,4250,4254,4258,4262,4266,4270,4274,4278,4282,4286,4290,4294,4298,4302,4306,4310,4314,4318,4322,4326,4330,4334,4338,4342,4346,4350,4354,4358,4362,4366,4370,4374,4378,4382,4386,4390,4394,4398,4402,4406,4410,4414,4418,4422,4426,4430,4434,4438,4442,4446,4450,4454,4458,4462,4466,4470,4474,4478,4482,4486,4490,4494,4498,4502,4506,4510,4514,4518,4522,4526,4530,4534,4538,4542,4546,4550,4554,4558,4562,4566,4570,4574,4578,4582,4586,4590,4594,4598,4602,4606,4610,4614,4618,4622,4626,4630,4634,4638,4642,4646,4650,4654,4658,4662,4666,4670,4674,4678,4682,4686,4690,4694,4698,4702,4706,4710,4714,4718,4722,4726,4730,4734,4738,4742,4746,4750,4754,4758,4762,4766,4770,4774,4777,4781,4785],{"name":5,"type":328,"title":6,"description":329,"categories":330},"registry:ui","Accordion — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],"primitives",{"name":15,"type":328,"title":16,"description":333,"categories":334},"Alert Dialog — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":20,"type":328,"title":21,"description":336,"categories":337},"Aspect Ratio — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":30,"type":328,"title":31,"description":339,"categories":340},"Avatar — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":40,"type":328,"title":41,"description":342,"categories":343},"Breadcrumb — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":45,"type":328,"title":46,"description":345,"categories":346},"Button — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":50,"type":328,"title":51,"description":348,"categories":349},"Button Group — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":55,"type":328,"title":56,"description":351,"categories":352},"Calendar — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":60,"type":328,"title":61,"description":354,"categories":355},"Card — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":65,"type":328,"title":66,"description":357,"categories":358},"Carousel — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":69,"type":328,"title":70,"description":360,"categories":361},"Chart — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":73,"type":328,"title":74,"description":363,"categories":364},"Checkbox — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":78,"type":328,"title":79,"description":366,"categories":367},"Collapsible — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":83,"type":328,"title":84,"description":369,"categories":370},"Combobox — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":88,"type":328,"title":89,"description":372,"categories":373},"Command — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":92,"type":328,"title":93,"description":375,"categories":376},"Context Menu — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":106,"type":328,"title":107,"description":378,"categories":379},"Dialog — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":110,"type":328,"title":111,"description":381,"categories":382},"Drawer — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":115,"type":328,"title":116,"description":384,"categories":385},"Dropdown Menu — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":119,"type":328,"title":120,"description":387,"categories":388},"Empty — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":127,"type":328,"title":128,"description":390,"categories":391},"Field — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":148,"type":328,"title":149,"description":393,"categories":394},"Hover Card — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":162,"type":328,"title":163,"description":396,"categories":397},"Input — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":167,"type":328,"title":168,"description":399,"categories":400},"Input Group — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":172,"type":328,"title":173,"description":402,"categories":403},"Input Otp — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":176,"type":328,"title":177,"description":405,"categories":406},"Item — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":184,"type":328,"title":185,"description":408,"categories":409},"Kbd — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":188,"type":328,"title":189,"description":411,"categories":412},"Label — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":193,"type":328,"title":194,"description":414,"categories":415},"Menubar — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":197,"type":328,"title":198,"description":417,"categories":418},"Native Select — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":201,"type":328,"title":202,"description":420,"categories":421},"Navigation Menu — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":209,"type":328,"title":210,"description":423,"categories":424},"Pagination — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":217,"type":328,"title":218,"description":426,"categories":427},"Popover — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":221,"type":328,"title":222,"description":429,"categories":430},"Progress — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":225,"type":328,"title":226,"description":432,"categories":433},"Radio Group — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":234,"type":328,"title":235,"description":435,"categories":436},"Resizable — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":238,"type":328,"title":239,"description":438,"categories":439},"Scroll Area — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":247,"type":328,"title":248,"description":441,"categories":442},"Select — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":252,"type":328,"title":253,"description":444,"categories":445},"Separator — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":256,"type":328,"title":257,"description":447,"categories":448},"Sheet — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":260,"type":328,"title":261,"description":450,"categories":451},"Skeleton — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":264,"type":328,"title":265,"description":453,"categories":454},"Slider — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":277,"type":328,"title":278,"description":456,"categories":457},"Spinner — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":285,"type":328,"title":286,"description":459,"categories":460},"Switch — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":289,"type":328,"title":290,"description":462,"categories":463},"Table — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":293,"type":328,"title":294,"description":465,"categories":466},"Tabs — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":297,"type":328,"title":298,"description":468,"categories":469},"Textarea — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":305,"type":328,"title":306,"description":471,"categories":472},"Toggle — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":309,"type":328,"title":310,"description":474,"categories":475},"Toggle Group — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":314,"type":328,"title":315,"description":477,"categories":478},"Tooltip — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).",[331],{"name":10,"type":480,"title":11,"description":481,"categories":482},"registry:component","Alert — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],"reui",{"name":25,"type":480,"title":26,"description":485,"categories":486},"Autocomplete — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":35,"type":480,"title":36,"description":488,"categories":489},"Badge — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":96,"type":480,"title":97,"description":491,"categories":492},"Data Grid — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":101,"type":480,"title":102,"description":494,"categories":495},"Date Selector — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":123,"type":480,"title":124,"description":497,"categories":498},"Event Calendar — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":135,"type":480,"title":136,"description":500,"categories":501},"Filters — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":139,"type":480,"title":140,"description":503,"categories":504},"Frame — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":144,"type":480,"title":145,"description":506,"categories":507},"Gantt — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":152,"type":480,"title":153,"description":509,"categories":510},"Icon Stack — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":157,"type":480,"title":158,"description":512,"categories":513},"Icon Tile — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":180,"type":480,"title":181,"description":515,"categories":516},"Kanban — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":205,"type":480,"title":206,"description":518,"categories":519},"Number Field — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":213,"type":480,"title":214,"description":521,"categories":522},"Phone Input — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":229,"type":480,"title":230,"description":524,"categories":525},"Rating — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":242,"type":480,"title":243,"description":527,"categories":528},"Scrollspy — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":273,"type":480,"title":274,"description":530,"categories":531},"Sortable — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":281,"type":480,"title":282,"description":533,"categories":534},"Stepper — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":301,"type":480,"title":302,"description":536,"categories":537},"Timeline — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":318,"type":480,"title":319,"description":539,"categories":540},"Tree — кастомный компонент, портированный из ReUI (keenthemes\u002Freui, MIT).",[483],{"name":542,"type":543,"title":544,"description":545,"categories":546},"utils","registry:lib","Utils","Утилита cn() (clsx + tailwind-merge) — используется практически всеми компонентами.",[547],"internals",{"name":549,"type":543,"title":550,"description":551,"categories":552},"dnd","Drag and Drop helpers","Общие помощники Pragmatic Drag and Drop (клавиатурный drag, reorder, прозрачный пиксель) — см. ADR-002.",[547],{"name":554,"type":555,"title":556,"description":557,"categories":558},"use-copy-to-clipboard","registry:hook","Use copy To Clipboard","Composable use-copy-to-clipboard() — VueUse-порт одноимённого хука ReUI.",[547],{"name":560,"type":555,"title":561,"description":562,"categories":563},"use-file-upload","Use file Upload","Composable use-file-upload() — VueUse-порт одноимённого хука ReUI.",[547],{"name":565,"type":555,"title":566,"description":567,"categories":568},"use-scroll-position","Use scroll Position","Composable use-scroll-position() — VueUse-порт одноимённого хука ReUI.",[547],{"name":570,"type":555,"title":571,"description":572,"categories":573},"use-slider-input","Use slider Input","Composable use-slider-input() — VueUse-порт одноимённого хука ReUI.",[547],{"name":575,"type":576,"title":577,"description":577,"categories":578},"c-accordion-1","registry:block","A basic single-expand accordion",[5],{"name":580,"type":576,"title":581,"description":581,"categories":582},"c-accordion-2","Accordion with plus\u002Fminus indicators",[5],{"name":584,"type":576,"title":585,"description":585,"categories":586},"c-accordion-3","Accordion with borders and rounded corners",[5],{"name":588,"type":576,"title":589,"description":589,"categories":590},"c-accordion-4","Accordion embedded within a Card",[5],{"name":592,"type":576,"title":593,"description":593,"categories":594},"c-accordion-5","Accordion with disabled items and highlighted state",[5],{"name":596,"type":576,"title":597,"description":597,"categories":598},"c-accordion-6","Advanced accordion with custom icons and badges",[5],{"name":600,"type":576,"title":601,"description":601,"categories":602},"c-accordion-7","Accordion items integrated within Frame and FramePanel",[5],{"name":604,"type":576,"title":605,"description":605,"categories":606},"c-accordion-8","Nested accordion example with bordered items",[5],{"name":608,"type":576,"title":609,"description":609,"categories":610},"c-accordion-9","User list accordion with avatars and role indicators",[5],{"name":612,"type":576,"title":613,"description":613,"categories":614},"c-accordion-10","Accordion with rotating arrow indicator",[5],{"name":616,"type":576,"title":617,"description":617,"categories":618},"c-accordion-11","Accordion pattern for onboarding or setup steps with icons, badges, and QR codes",[5],{"name":620,"type":576,"title":621,"description":621,"categories":622},"c-alert-dialog-1","Basic alert dialog with title, description, and action buttons",[15],{"name":624,"type":576,"title":625,"description":625,"categories":626},"c-alert-dialog-2","Small size alert dialog for quick confirmations",[15],{"name":628,"type":576,"title":629,"description":629,"categories":630},"c-alert-dialog-3","Alert dialog with icon",[15],{"name":632,"type":576,"title":633,"description":633,"categories":634},"c-alert-dialog-4","Small size alert dialog with media (icon)",[15],{"name":636,"type":576,"title":637,"description":637,"categories":638},"c-alert-dialog-5","Destructive alert dialog for irreversible actions like deletion",[15],{"name":640,"type":576,"title":641,"description":641,"categories":642},"c-alert-dialog-6","Alert dialog nested within a standard Dialog component",[15],{"name":644,"type":576,"title":645,"description":645,"categories":646},"c-alert-dialog-7","Task success confirmation",[15],{"name":648,"type":576,"title":649,"description":649,"categories":650},"c-alert-dialog-8","Account deactivation confirmation",[15],{"name":652,"type":576,"title":653,"description":653,"categories":654},"c-alert-dialog-9","Warning for unsaved changes when navigating away",[15],{"name":656,"type":576,"title":657,"description":657,"categories":658},"c-alert-dialog-10","Confirmation for successful e-ticket registration",[15],{"name":660,"type":576,"title":661,"description":661,"categories":662},"c-alert-dialog-11","System update notification requiring application restart",[15],{"name":664,"type":576,"title":665,"description":665,"categories":666},"c-alert-dialog-12","Billing warning for expired subscriptions or failed payments",[15],{"name":668,"type":576,"title":669,"description":669,"categories":670},"c-alert-dialog-13","Logout confirmation dialog",[15],{"name":672,"type":576,"title":673,"description":673,"categories":674},"c-alert-dialog-14","Advanced security audit confirmation",[15],{"name":676,"type":576,"title":677,"description":677,"categories":678},"c-alert-1","Basic alert",[10],{"name":680,"type":576,"title":681,"description":681,"categories":682},"c-alert-2","Alert with icon",[10],{"name":684,"type":576,"title":685,"description":685,"categories":686},"c-alert-3","Alert with icon and action buttons",[10],{"name":688,"type":576,"title":689,"description":689,"categories":690},"c-alert-4","Destructive alert with icon and action buttons",[10],{"name":692,"type":576,"title":693,"description":693,"categories":694},"c-alert-5","Info alert with icon and action buttons",[10],{"name":696,"type":576,"title":697,"description":697,"categories":698},"c-alert-6","Success alert",[10],{"name":700,"type":576,"title":701,"description":701,"categories":702},"c-alert-7","Warning alert",[10],{"name":704,"type":576,"title":705,"description":705,"categories":706},"c-alert-8","Error alert",[10],{"name":708,"type":576,"title":709,"description":709,"categories":710},"c-alert-9","Invert alert",[10],{"name":712,"type":576,"title":685,"description":685,"categories":713},"c-alert-10",[10],{"name":715,"type":576,"title":716,"description":716,"categories":717},"c-alert-11","Alert with description and action buttons",[10],{"name":719,"type":576,"title":720,"description":720,"categories":721},"c-alert-12","Alert integrated within a Frame with reset borders",[10],{"name":723,"type":576,"title":724,"description":724,"categories":725},"c-alert-13","Stacked alerts within a Frame",[10],{"name":727,"type":576,"title":728,"description":728,"categories":729},"c-alert-14","Alert with actions integrated within a Frame",[10],{"name":731,"type":576,"title":732,"description":732,"categories":733},"c-alert-15","Inverted alert variant",[10],{"name":735,"type":576,"title":736,"description":736,"categories":737},"c-alert-16","Urgent billing notice",[10],{"name":739,"type":576,"title":740,"description":740,"categories":741},"c-alert-17","Service status summary stacked within a frame",[10],{"name":743,"type":576,"title":744,"description":744,"categories":745},"c-alert-18","Feature discovery alert",[10],{"name":747,"type":576,"title":748,"description":748,"categories":749},"c-alert-19","User message notification alert",[10],{"name":751,"type":576,"title":748,"description":748,"categories":752},"c-alert-20",[10],{"name":754,"type":576,"title":755,"description":755,"categories":756},"c-aspect-ratio-1","16:9 widescreen aspect ratio",[20],{"name":758,"type":576,"title":759,"description":759,"categories":760},"c-aspect-ratio-2","4:3 standard aspect ratio",[20],{"name":762,"type":576,"title":763,"description":763,"categories":764},"c-aspect-ratio-3","1:1 square aspect ratio",[20],{"name":766,"type":576,"title":767,"description":767,"categories":768},"c-aspect-ratio-4","21:9 ultrawide aspect ratio",[20],{"name":770,"type":576,"title":771,"description":771,"categories":772},"c-aspect-ratio-5","9:16 portrait aspect ratio",[20],{"name":774,"type":576,"title":775,"description":775,"categories":776},"c-aspect-ratio-6","3:2 classic photography aspect ratio",[20],{"name":778,"type":576,"title":779,"description":779,"categories":780},"c-aspect-ratio-7","4:5 social media portrait aspect ratio",[20],{"name":782,"type":576,"title":783,"description":783,"categories":784},"c-aspect-ratio-8","16:10 computer monitor aspect ratio",[20],{"name":786,"type":576,"title":787,"description":787,"categories":788},"c-autocomplete-1","Basic autocomplete control",[25],{"name":790,"type":576,"title":791,"description":791,"categories":792},"c-autocomplete-2","Disabled state",[25],{"name":794,"type":576,"title":795,"description":795,"categories":796},"c-autocomplete-3","Auto highlight option as you type",[25],{"name":798,"type":576,"title":799,"description":799,"categories":800},"c-autocomplete-4","Control with label",[25],{"name":802,"type":576,"title":803,"description":803,"categories":804},"c-autocomplete-5","With clear button",[25],{"name":806,"type":576,"title":807,"description":807,"categories":808},"c-autocomplete-6","With trigger button",[25],{"name":810,"type":576,"title":811,"description":811,"categories":812},"c-autocomplete-7","With clear and trigger buttons",[25],{"name":814,"type":576,"title":815,"description":815,"categories":816},"c-autocomplete-8","With groups and labels",[25],{"name":818,"type":576,"title":819,"description":819,"categories":820},"c-autocomplete-9","With search results",[25],{"name":822,"type":576,"title":823,"description":823,"categories":824},"c-autocomplete-10","Small autocomplete",[25],{"name":826,"type":576,"title":827,"description":827,"categories":828},"c-autocomplete-11","Large autocomplete",[25],{"name":830,"type":576,"title":831,"description":831,"categories":832},"c-autocomplete-12","Form integration",[25],{"name":834,"type":576,"title":835,"description":835,"categories":836},"c-avatar-1","Basic avatar",[30],{"name":838,"type":576,"title":839,"description":839,"categories":840},"c-avatar-2","Avatar with fallback",[30],{"name":842,"type":576,"title":843,"description":843,"categories":844},"c-avatar-3","Avatars with different sizes",[30],{"name":846,"type":576,"title":847,"description":847,"categories":848},"c-avatar-4","Avatars with different border radiuses",[30],{"name":850,"type":576,"title":851,"description":851,"categories":852},"c-avatar-5","Avatars with custom sizes",[30],{"name":854,"type":576,"title":855,"description":855,"categories":856},"c-avatar-6","Avatar with an online status badge",[30],{"name":858,"type":576,"title":859,"description":859,"categories":860},"c-avatar-7","Avatar with badge icon",[30],{"name":862,"type":576,"title":863,"description":863,"categories":864},"c-avatar-8","Avatar with different badge positions",[30],{"name":866,"type":576,"title":863,"description":863,"categories":867},"c-avatar-9",[30],{"name":869,"type":576,"title":870,"description":870,"categories":871},"c-avatar-10","Basic avatar group",[30],{"name":873,"type":576,"title":874,"description":874,"categories":875},"c-avatar-11","Avatar group with numerical count",[30],{"name":877,"type":576,"title":878,"description":878,"categories":879},"c-avatar-12","Avatar group with an icon count",[30],{"name":881,"type":576,"title":882,"description":882,"categories":883},"c-avatar-13","Avatar with a distinct border ring",[30],{"name":885,"type":576,"title":886,"description":886,"categories":887},"c-avatar-14","Avatar with light background color fallback",[30],{"name":889,"type":576,"title":890,"description":890,"categories":891},"c-avatar-15","Avatar with a solid background color fallback",[30],{"name":893,"type":576,"title":894,"description":894,"categories":895},"c-avatar-16","Avatar with user details and badge",[30],{"name":897,"type":576,"title":898,"description":898,"categories":899},"c-avatar-17","Avatar with grayscale image filter",[30],{"name":901,"type":576,"title":902,"description":902,"categories":903},"c-avatar-18","Avatar group with online status on one",[30],{"name":905,"type":576,"title":906,"description":906,"categories":907},"c-avatar-19","Avatar inside small outline button",[30],{"name":909,"type":576,"title":910,"description":910,"categories":911},"c-avatar-20","Avatar social proof with text label",[30],{"name":913,"type":576,"title":914,"description":914,"categories":915},"c-avatar-21","Compact social proof with initials",[30],{"name":917,"type":576,"title":918,"description":918,"categories":919},"c-avatar-22","Avatar group with hover tooltips and lift effect",[30],{"name":921,"type":576,"title":922,"description":922,"categories":923},"c-avatar-23","Avatar group with hover effect",[30],{"name":925,"type":576,"title":926,"description":926,"categories":927},"c-avatar-24","Avatar group with hover effect and tooltips",[30],{"name":929,"type":576,"title":874,"description":874,"categories":930},"c-avatar-25",[30],{"name":932,"type":576,"title":933,"description":933,"categories":934},"c-avatar-26","Pilled small outline button with avatar",[30],{"name":936,"type":576,"title":937,"description":937,"categories":938},"c-avatar-27","Pilled small button with avatar",[30],{"name":940,"type":576,"title":941,"description":941,"categories":942},"c-avatar-28","Avatar inside an empty state example",[30],{"name":944,"type":576,"title":945,"description":945,"categories":946},"c-avatar-29","Avatar group with icon count and button",[30],{"name":948,"type":576,"title":949,"description":949,"categories":950},"c-avatar-30","Avatar with loading state demonstration",[30],{"name":952,"type":576,"title":953,"description":953,"categories":954},"c-avatar-31","Avatar with custom badge",[30],{"name":956,"type":576,"title":957,"description":957,"categories":958},"c-avatar-32","Avatar with ring animation",[30],{"name":960,"type":576,"title":961,"description":961,"categories":962},"c-avatar-33","Avatar with gradient animated ring",[30],{"name":964,"type":576,"title":965,"description":965,"categories":966},"c-avatar-34","Avatar with multiple badges",[30],{"name":968,"type":576,"title":969,"description":969,"categories":970},"c-avatar-35","Compact avatar dropdown menu",[30],{"name":972,"type":576,"title":973,"description":973,"categories":974},"c-badge-1","Default badge",[35],{"name":976,"type":576,"title":977,"description":977,"categories":978},"c-badge-2","Secondary badge",[35],{"name":980,"type":576,"title":981,"description":981,"categories":982},"c-badge-3","Destructive badge",[35],{"name":984,"type":576,"title":985,"description":985,"categories":986},"c-badge-4","Success badge",[35],{"name":988,"type":576,"title":989,"description":989,"categories":990},"c-badge-5","Info badge",[35],{"name":992,"type":576,"title":993,"description":993,"categories":994},"c-badge-6","Warning badge",[35],{"name":996,"type":576,"title":997,"description":997,"categories":998},"c-badge-7","Outline badge",[35],{"name":1000,"type":576,"title":1001,"description":1001,"categories":1002},"c-badge-8","Primary outline badge",[35],{"name":1004,"type":576,"title":1005,"description":1005,"categories":1006},"c-badge-9","Destructive outline badge",[35],{"name":1008,"type":576,"title":1009,"description":1009,"categories":1010},"c-badge-10","Info outline badge",[35],{"name":1012,"type":576,"title":1013,"description":1013,"categories":1014},"c-badge-11","Success outline badge",[35],{"name":1016,"type":576,"title":1017,"description":1017,"categories":1018},"c-badge-12","Warning outline badge",[35],{"name":1020,"type":576,"title":1021,"description":1021,"categories":1022},"c-badge-13","Primary light badge",[35],{"name":1024,"type":576,"title":1025,"description":1025,"categories":1026},"c-badge-14","Destructive light badge",[35],{"name":1028,"type":576,"title":1029,"description":1029,"categories":1030},"c-badge-15","Success light badge",[35],{"name":1032,"type":576,"title":1033,"description":1033,"categories":1034},"c-badge-16","Info light badge",[35],{"name":1036,"type":576,"title":1037,"description":1037,"categories":1038},"c-badge-17","Warning light badge",[35],{"name":1040,"type":576,"title":1041,"description":1041,"categories":1042},"c-badge-18","Badge size variations",[35],{"name":1044,"type":576,"title":1045,"description":1045,"categories":1046},"c-badge-19","Badge with full radius (radius=\"full\")",[35],{"name":1048,"type":576,"title":1049,"description":1049,"categories":1050},"c-badge-20","Badge with an icon",[35],{"name":1052,"type":576,"title":1053,"description":1053,"categories":1054},"c-badge-21","Badge with a dismiss button",[35],{"name":1056,"type":576,"title":1057,"description":1057,"categories":1058},"c-badge-22","Badge with a status dot",[35],{"name":1060,"type":576,"title":1061,"description":1061,"categories":1062},"c-badge-23","Badge rendered as a link",[35],{"name":1064,"type":576,"title":1065,"description":1065,"categories":1066},"c-badge-24","Badge with avatar",[35],{"name":1068,"type":576,"title":1069,"description":1069,"categories":1070},"c-badge-25","Badge with flag image",[35],{"name":1072,"type":576,"title":1073,"description":1073,"categories":1074},"c-breadcrumb-1","Basic breadcrumb",[40],{"name":1076,"type":576,"title":1077,"description":1077,"categories":1078},"c-breadcrumb-2","Breadcrumb with dropdown menu",[40],{"name":1080,"type":576,"title":1081,"description":1081,"categories":1082},"c-breadcrumb-3","Breadcrumb with Next.js link",[40],{"name":1084,"type":576,"title":1085,"description":1085,"categories":1086},"c-breadcrumb-4","Breadcrumb with a custom slash separator",[40],{"name":1088,"type":576,"title":1089,"description":1089,"categories":1090},"c-breadcrumb-5","Breadcrumb with icons for each item",[40],{"name":1092,"type":576,"title":1093,"description":1093,"categories":1094},"c-breadcrumb-6","Breadcrumb with ellipsis for long paths",[40],{"name":1096,"type":576,"title":1097,"description":1097,"categories":1098},"c-breadcrumb-7","Breadcrumb items with avatars",[40],{"name":1100,"type":576,"title":1101,"description":1101,"categories":1102},"c-breadcrumb-8","Breadcrumb with double chevron separators",[40],{"name":1104,"type":576,"title":1105,"description":1105,"categories":1106},"c-breadcrumb-9","Breadcrumb inside card",[40],{"name":1108,"type":576,"title":1109,"description":1109,"categories":1110},"c-breadcrumb-10","Pill-style breadcrumb inside frame",[40],{"name":1112,"type":576,"title":1113,"description":1113,"categories":1114},"c-breadcrumb-11","Breadcrumb items containing badge with count",[40],{"name":1116,"type":576,"title":1117,"description":1117,"categories":1118},"c-breadcrumb-12","Breadcrumb starting with home icon item",[40],{"name":1120,"type":576,"title":1121,"description":1121,"categories":1122},"c-breadcrumb-13","Breadcrumb with a custom separator",[40],{"name":1124,"type":576,"title":1125,"description":1125,"categories":1126},"c-breadcrumb-14","Button-style breadcrumb",[40],{"name":1128,"type":576,"title":1129,"description":1129,"categories":1130},"c-breadcrumb-15","Breadcrumb with project, user and document info",[40],{"name":1132,"type":576,"title":1133,"description":1133,"categories":1134},"c-button-group-1","Basic button group with two buttons",[50],{"name":1136,"type":576,"title":1137,"description":1137,"categories":1138},"c-button-group-2","Button group with button followed by input",[50],{"name":1140,"type":576,"title":1141,"description":1141,"categories":1142},"c-button-group-3","Button group with buttons and badge",[50],{"name":1144,"type":576,"title":1145,"description":1145,"categories":1146},"c-button-group-4","Button group with dropdown menu",[50],{"name":1148,"type":576,"title":1149,"description":1149,"categories":1150},"c-button-group-5","Team activity and collaboration group",[50],{"name":1152,"type":576,"title":1153,"description":1153,"categories":1154},"c-button-group-6","Button group using icons for visual actions",[50],{"name":1156,"type":576,"title":1157,"description":1157,"categories":1158},"c-button-group-7","Dropdown menu with status indicator",[50],{"name":1160,"type":576,"title":1161,"description":1161,"categories":1162},"c-button-group-8","Button group styled as a like button with a counter",[50],{"name":1164,"type":576,"title":1165,"description":1165,"categories":1166},"c-button-group-9","Nested button groups for complex action sets",[50],{"name":1168,"type":576,"title":1169,"description":1169,"categories":1170},"c-button-group-10","Button group used for standard pagination",[50],{"name":1172,"type":576,"title":1173,"description":1173,"categories":1174},"c-button-group-11","Pagination split into page numbers and navigation arrows",[50],{"name":1176,"type":576,"title":1177,"description":1177,"categories":1178},"c-button-group-12","Button group for editor text alignment controls",[50],{"name":1180,"type":576,"title":1181,"description":1181,"categories":1182},"c-button-group-13","Vertical button group orientation",[50],{"name":1184,"type":576,"title":1185,"description":1185,"categories":1186},"c-button-group-14","Nested vertical button group for complex tool palettes",[50],{"name":1188,"type":576,"title":1189,"description":1189,"categories":1190},"c-button-group-15","Star button group with count and dropdown",[50],{"name":1192,"type":576,"title":1193,"description":1193,"categories":1194},"c-button-group-16","Search input with filter menu and clear button",[50],{"name":1196,"type":576,"title":1197,"description":1197,"categories":1198},"c-button-group-17","Button group with comprehensive action menu",[50],{"name":1200,"type":576,"title":1201,"description":1201,"categories":1202},"c-button-group-18","Advanced git toolbar with branch selection and split commit button",[50],{"name":1204,"type":576,"title":1205,"description":1205,"categories":1206},"c-button-group-19","Button group with dropdown menu and input group",[50],{"name":1208,"type":576,"title":1209,"description":1209,"categories":1210},"c-button-group-20","Button group with input group and button",[50],{"name":1212,"type":576,"title":1205,"description":1205,"categories":1213},"c-button-group-21",[50],{"name":1215,"type":576,"title":1216,"description":1216,"categories":1217},"c-button-group-22","Basic button group with disabled button",[50],{"name":1219,"type":576,"title":1220,"description":1220,"categories":1221},"c-button-group-23","Button group buttons with separators",[50],{"name":1223,"type":576,"title":1224,"description":1224,"categories":1225},"c-button-group-24","View switcher for dashboard layouts",[50],{"name":1227,"type":576,"title":1228,"description":1228,"categories":1229},"c-button-group-25","Rating scale using numerical buttons",[50],{"name":1231,"type":576,"title":1232,"description":1232,"categories":1233},"c-button-group-26","Button group with user selection select",[50],{"name":1235,"type":576,"title":1236,"description":1236,"categories":1237},"c-button-group-27","Button group with select status addon",[50],{"name":1239,"type":576,"title":1240,"description":1240,"categories":1241},"c-button-group-28","Volume controller with plus\u002Fminus actions",[50],{"name":1243,"type":576,"title":1244,"description":1244,"categories":1245},"c-button-group-29","Button group with follower count",[50],{"name":1247,"type":576,"title":1248,"description":1248,"categories":1249},"c-button-group-30","Active state button group with count",[50],{"name":1251,"type":576,"title":1252,"description":1252,"categories":1253},"c-button-group-31","Horizontal button group with primary and secondary labels",[50],{"name":1255,"type":576,"title":1256,"description":1256,"categories":1257},"c-button-group-32","Button group with dropdown menu and view toggle",[50],{"name":1259,"type":576,"title":1260,"description":1260,"categories":1261},"c-button-group-33","Button group with select controls",[50],{"name":1263,"type":576,"title":1264,"description":1264,"categories":1265},"c-button-group-34","Segmented control with dropdown inside button group",[50],{"name":1267,"type":576,"title":1268,"description":1268,"categories":1269},"c-button-group-35","Pagination button group",[50],{"name":1271,"type":576,"title":1272,"description":1272,"categories":1273},"c-button-group-36","View switcher button group",[50],{"name":1275,"type":576,"title":1276,"description":1276,"categories":1277},"c-button-group-37","Zoom controls button group",[50],{"name":1279,"type":576,"title":1280,"description":1280,"categories":1281},"c-button-group-38","Media player controls button group",[50],{"name":1283,"type":576,"title":1284,"description":1284,"categories":1285},"c-button-group-39","Split button with dropdown trigger",[50],{"name":1287,"type":576,"title":1288,"description":1288,"categories":1289},"c-button-group-40","Vertical button group",[50],{"name":1291,"type":576,"title":1292,"description":1292,"categories":1293},"c-button-group-41","Model selector with tier badges",[50],{"name":1295,"type":576,"title":1296,"description":1296,"categories":1297},"c-button-group-42","Segmented order type selector",[50],{"name":1299,"type":576,"title":1300,"description":1300,"categories":1301},"c-button-group-43","Buy sell hold toggle group",[50],{"name":1303,"type":576,"title":1304,"description":1304,"categories":1305},"c-button-group-44","Pipeline stage mover with dropdown",[50],{"name":1307,"type":576,"title":1308,"description":1308,"categories":1309},"c-button-group-45","Environment switcher with indicator",[50],{"name":1311,"type":576,"title":1312,"description":1312,"categories":1313},"c-button-group-46","Compact time interval selector",[50],{"name":1315,"type":576,"title":1316,"description":1316,"categories":1317},"c-button-group-47","Review actions split button",[50],{"name":1319,"type":576,"title":1320,"description":1320,"categories":1321},"c-button-group-48","Toolbar filter with export and view toggle",[50],{"name":1323,"type":576,"title":1324,"description":1324,"categories":1325},"c-button-group-49","Vertical nav links with icons",[50],{"name":1327,"type":576,"title":1328,"description":1328,"categories":1329},"c-button-group-50","Toolbar filter sort and more",[50],{"name":1331,"type":576,"title":1332,"description":1332,"categories":1333},"c-button-group-51","New button with create dropdown",[50],{"name":1335,"type":576,"title":1336,"description":1336,"categories":1337},"c-button-group-52","Refresh share and export dropdown",[50],{"name":1339,"type":576,"title":1340,"description":1340,"categories":1341},"c-button-group-53","Publish controls with split button and overflow",[50],{"name":1343,"type":576,"title":1344,"description":1344,"categories":1345},"c-button-group-54","API service environment and version selectors",[50],{"name":1347,"type":576,"title":1348,"description":1348,"categories":1349},"c-button-group-55","Payout release controls with amount context",[50],{"name":1351,"type":576,"title":1352,"description":1352,"categories":1353},"c-button-group-56","Attachment button group with download action",[50],{"name":1355,"type":576,"title":1356,"description":1356,"categories":1357},"c-button-group-57","Agent mode selector with credit cap dropdown",[50],{"name":1359,"type":576,"title":1360,"description":1360,"categories":1361},"c-button-1","Default button",[45],{"name":1363,"type":576,"title":1364,"description":1364,"categories":1365},"c-button-2","Secondary button",[45],{"name":1367,"type":576,"title":1368,"description":1368,"categories":1369},"c-button-3","Outline button",[45],{"name":1371,"type":576,"title":1372,"description":1372,"categories":1373},"c-button-4","Ghost button",[45],{"name":1375,"type":576,"title":1376,"description":1376,"categories":1377},"c-button-5","Destructive button",[45],{"name":1379,"type":576,"title":1380,"description":1380,"categories":1381},"c-button-6","Link button variant",[45],{"name":1383,"type":576,"title":1384,"description":1384,"categories":1385},"c-button-7","Extra small button",[45],{"name":1387,"type":576,"title":1388,"description":1388,"categories":1389},"c-button-8","Small button",[45],{"name":1391,"type":576,"title":1392,"description":1392,"categories":1393},"c-button-9","Large button",[45],{"name":1395,"type":576,"title":1396,"description":1396,"categories":1397},"c-button-10","Disabled button",[45],{"name":1399,"type":576,"title":1400,"description":1400,"categories":1401},"c-button-11","Icon button",[45],{"name":1403,"type":576,"title":1404,"description":1404,"categories":1405},"c-button-12","Button with an icon on the right",[45],{"name":1407,"type":576,"title":1408,"description":1408,"categories":1409},"c-button-13","Button in a loading state",[45],{"name":1411,"type":576,"title":1412,"description":1412,"categories":1413},"c-button-14","Button with an icon on the left",[45],{"name":1415,"type":576,"title":1416,"description":1416,"categories":1417},"c-button-15","Button with an invalid state highlight",[45],{"name":1419,"type":576,"title":1420,"description":1420,"categories":1421},"c-button-16","Secondary button with an icon on the left",[45],{"name":1423,"type":576,"title":1424,"description":1424,"categories":1425},"c-button-17","Secondary button with an icon on the right",[45],{"name":1427,"type":576,"title":1428,"description":1428,"categories":1429},"c-button-18","Outline button with an icon on the left",[45],{"name":1431,"type":576,"title":1432,"description":1432,"categories":1433},"c-button-19","Outline button with an icon on the right",[45],{"name":1435,"type":576,"title":1436,"description":1436,"categories":1437},"c-button-20","Ghost button with an icon on the left",[45],{"name":1439,"type":576,"title":1440,"description":1440,"categories":1441},"c-button-21","Ghost button with an icon on the right",[45],{"name":1443,"type":576,"title":1444,"description":1444,"categories":1445},"c-button-22","Destructive button with an icon on the left",[45],{"name":1447,"type":576,"title":1448,"description":1448,"categories":1449},"c-button-23","Destructive button with an icon on the right",[45],{"name":1451,"type":576,"title":1452,"description":1452,"categories":1453},"c-button-24","Extra small icon button",[45],{"name":1455,"type":576,"title":1456,"description":1456,"categories":1457},"c-button-25","Small icon button",[45],{"name":1459,"type":576,"title":1460,"description":1460,"categories":1461},"c-button-26","Large (lg) icon-only button",[45],{"name":1463,"type":576,"title":1464,"description":1464,"categories":1465},"c-button-27","Button rendered as a Next.js Link",[45],{"name":1467,"type":576,"title":1468,"description":1468,"categories":1469},"c-button-28","Link button with an icon on the left",[45],{"name":1471,"type":576,"title":1472,"description":1472,"categories":1473},"c-button-29","Link button with an icon on the right",[45],{"name":1475,"type":576,"title":1476,"description":1476,"categories":1477},"c-button-30","Large button with an icon on the left",[45],{"name":1479,"type":576,"title":1480,"description":1480,"categories":1481},"c-button-31","Large button with an icon on the right",[45],{"name":1483,"type":576,"title":1484,"description":1484,"categories":1485},"c-button-32","Outline button with an invalid state",[45],{"name":1487,"type":576,"title":1488,"description":1488,"categories":1489},"c-button-33","Ghost button with an invalid state",[45],{"name":1491,"type":576,"title":1412,"description":1412,"categories":1492},"c-button-34",[45],{"name":1494,"type":576,"title":1495,"description":1495,"categories":1496},"c-button-35","Ghost button with more\u002Fless toggle",[45],{"name":1498,"type":576,"title":1499,"description":1499,"categories":1500},"c-button-36","Social login buttons with Remix Icons",[45],{"name":1502,"type":576,"title":1503,"description":1503,"categories":1504},"c-button-37","Outline like button with count",[45],{"name":1506,"type":576,"title":1507,"description":1507,"categories":1508},"c-button-38","Star button with count",[45],{"name":1510,"type":576,"title":1511,"description":1511,"categories":1512},"c-button-39","Button with an unread badge",[45],{"name":1514,"type":576,"title":1515,"description":1515,"categories":1516},"c-button-40","Button with icon, label, and shortcut keys",[45],{"name":1518,"type":576,"title":1519,"description":1519,"categories":1520},"c-button-41","Copy button with feedback",[45],{"name":1522,"type":576,"title":1523,"description":1523,"categories":1524},"c-button-42","Icon-only copy button with feedback",[45],{"name":1526,"type":576,"title":1527,"description":1527,"categories":1528},"c-button-43","Animated hamburger \u002F close toggle button",[45],{"name":1530,"type":576,"title":1531,"description":1531,"categories":1532},"c-button-44","Async action button with loading and success states",[45],{"name":1534,"type":576,"title":1535,"description":1535,"categories":1536},"c-button-45","Outline button with inline count badge",[45],{"name":1538,"type":576,"title":1539,"description":1539,"categories":1540},"c-button-46","Button with status dot badge",[45],{"name":1542,"type":576,"title":1543,"description":1543,"categories":1544},"c-button-47","Ghost button with a status badge",[45],{"name":1546,"type":576,"title":1547,"description":1547,"categories":1548},"c-button-48","Icon button with notification badge",[45],{"name":1550,"type":576,"title":1551,"description":1551,"categories":1552},"c-button-49","Go back link button",[45],{"name":1554,"type":576,"title":1555,"description":1555,"categories":1556},"c-button-50","Go back link button with animation",[45],{"name":1558,"type":576,"title":1559,"description":1559,"categories":1560},"c-button-51","Expanding button from icon to label",[45],{"name":1562,"type":576,"title":1563,"description":1563,"categories":1564},"c-button-52","Multi-line button with icon, title & description",[45],{"name":1566,"type":576,"title":1567,"description":1567,"categories":1568},"c-button-53","Sliding Icon Button (Hover reveal)",[45],{"name":1570,"type":576,"title":1571,"description":1571,"categories":1572},"c-button-54","Shortcut Tooltip Button (Kbd hints)",[45],{"name":1574,"type":576,"title":1575,"description":1575,"categories":1576},"c-button-55","Button with avatar",[45],{"name":1578,"type":576,"title":1579,"description":1579,"categories":1580},"c-button-56","Outline button with avatar",[45],{"name":1582,"type":576,"title":1583,"description":1583,"categories":1584},"c-button-57","Small button with avatar",[45],{"name":1586,"type":576,"title":1587,"description":1587,"categories":1588},"c-button-58","Small outline button with avatar",[45],{"name":1590,"type":576,"title":1591,"description":1591,"categories":1592},"c-button-59","Social login buttons with Remix icons",[45],{"name":1594,"type":576,"title":1595,"description":1595,"categories":1596},"c-button-60","Social icon-only buttons with Remix icons",[45],{"name":1598,"type":576,"title":1599,"description":1599,"categories":1600},"c-button-61","Theme toggle button with animated moon and sun icons",[45],{"name":1602,"type":576,"title":1603,"description":1603,"categories":1604},"c-calendar-1","Basic calendar",[55],{"name":1606,"type":576,"title":1607,"description":1607,"categories":1608},"c-calendar-2","Range calendar",[55],{"name":1610,"type":576,"title":1611,"description":1611,"categories":1612},"c-calendar-3","Disabled dates",[55],{"name":1614,"type":576,"title":1615,"description":1615,"categories":1616},"c-calendar-4","Multiple day selection",[55],{"name":1618,"type":576,"title":1619,"description":1619,"categories":1620},"c-calendar-5","Custom select day style",[55],{"name":1622,"type":576,"title":1623,"description":1623,"categories":1624},"c-calendar-6","Custom select range style",[55],{"name":1626,"type":576,"title":1627,"description":1627,"categories":1628},"c-calendar-7","Right navigation",[55],{"name":1630,"type":576,"title":1631,"description":1631,"categories":1632},"c-calendar-8","Month and year selection",[55],{"name":1634,"type":576,"title":1635,"description":1635,"categories":1636},"c-calendar-9","Year select with navigation",[55],{"name":1638,"type":576,"title":1639,"description":1639,"categories":1640},"c-calendar-10","Display week numbers",[55],{"name":1642,"type":576,"title":1643,"description":1643,"categories":1644},"c-calendar-11","Current month button",[55],{"name":1646,"type":576,"title":1647,"description":1647,"categories":1648},"c-calendar-12","Today button",[55],{"name":1650,"type":576,"title":1651,"description":1651,"categories":1652},"c-calendar-13","Custom navigation with year view",[55],{"name":1654,"type":576,"title":1655,"description":1655,"categories":1656},"c-calendar-14","Preset time selection",[55],{"name":1658,"type":576,"title":1659,"description":1659,"categories":1660},"c-calendar-15","Calendar with presets",[55],{"name":1662,"type":576,"title":1663,"description":1663,"categories":1664},"c-calendar-16","Range calendar with presets",[55],{"name":1666,"type":576,"title":1667,"description":1667,"categories":1668},"c-calendar-17","Calendar with pricing",[55],{"name":1670,"type":576,"title":1659,"description":1659,"categories":1671},"c-calendar-18",[55],{"name":1673,"type":576,"title":1674,"description":1674,"categories":1675},"c-calendar-19","Appointment calendar",[55],{"name":1677,"type":576,"title":1678,"description":1678,"categories":1679},"c-calendar-20","Display 2 months",[55],{"name":1681,"type":576,"title":1682,"description":1682,"categories":1683},"c-calendar-21","Display 2 months with range picker",[55],{"name":1685,"type":576,"title":1686,"description":1686,"categories":1687},"c-calendar-22","Calendar with event list",[55],{"name":1689,"type":576,"title":1690,"description":1690,"categories":1691},"c-calendar-23","Localize calendar",[55],{"name":1693,"type":576,"title":1694,"description":1694,"categories":1695},"c-calendar-24","Calendar with date picker",[55],{"name":1697,"type":576,"title":1698,"description":1698,"categories":1699},"c-calendar-25","Calendar with date range picker",[55],{"name":1701,"type":576,"title":1702,"description":1702,"categories":1703},"c-calendar-26","Calendar with date picker and year view",[55],{"name":1705,"type":576,"title":1706,"description":1706,"categories":1707},"c-calendar-27","Calendar with date and appointment picker",[55],{"name":1709,"type":576,"title":1710,"description":1710,"categories":1711},"c-calendar-28","Calendar with date picker and presets",[55],{"name":1713,"type":576,"title":1714,"description":1714,"categories":1715},"c-calendar-29","Range calendar with date picker and presets",[55],{"name":1717,"type":576,"title":1718,"description":1718,"categories":1719},"c-calendar-30","Calendar with date and time range picker",[55],{"name":1721,"type":576,"title":1722,"description":1722,"categories":1723},"c-card-1","Basic card",[60],{"name":1725,"type":576,"title":1726,"description":1726,"categories":1727},"c-card-2","Card header with border",[60],{"name":1729,"type":576,"title":1730,"description":1730,"categories":1731},"c-card-3","Card with border separation",[60],{"name":1733,"type":576,"title":1734,"description":1734,"categories":1735},"c-card-4","Card with header and footer",[60],{"name":1737,"type":576,"title":1738,"description":1738,"categories":1739},"c-card-5","Card with link",[60],{"name":1741,"type":576,"title":1742,"description":1742,"categories":1743},"c-card-6","Card with dropdown menu",[60],{"name":1745,"type":576,"title":1746,"description":1746,"categories":1747},"c-card-7","Card with image",[60],{"name":1749,"type":576,"title":1750,"description":1750,"categories":1751},"c-card-8","Card with image scale hover effect",[60],{"name":1753,"type":576,"title":1754,"description":1754,"categories":1755},"c-card-9","Card with full image",[60],{"name":1757,"type":576,"title":1758,"description":1758,"categories":1759},"c-card-10","Full card with image and shadow fade effect",[60],{"name":1761,"type":576,"title":1762,"description":1762,"categories":1763},"c-card-11","Card with stacked depth effect",[60],{"name":1765,"type":576,"title":1766,"description":1766,"categories":1767},"c-card-12","Advanced clean login form card",[60],{"name":1769,"type":576,"title":1770,"description":1770,"categories":1771},"c-card-13","Expandable billing usage card",[60],{"name":1773,"type":576,"title":1774,"description":1774,"categories":1775},"c-card-14","Deployment status summary card",[60],{"name":1777,"type":576,"title":1778,"description":1778,"categories":1779},"c-card-15","Stat card with trend and overflow menu",[60],{"name":1781,"type":576,"title":1782,"description":1782,"categories":1783},"c-card-16","Card with header badge and actions",[60],{"name":1785,"type":576,"title":1786,"description":1786,"categories":1787},"c-card-17","Card with icon, title and link",[60],{"name":1789,"type":576,"title":1790,"description":1790,"categories":1791},"c-card-18","Card with header label and link",[60],{"name":1793,"type":576,"title":1794,"description":1794,"categories":1795},"c-carousel-1","Basic carousel with single item",[65],{"name":1797,"type":576,"title":1798,"description":1798,"categories":1799},"c-carousel-2","Vertical carousel orientation",[65],{"name":1801,"type":576,"title":1802,"description":1802,"categories":1803},"c-carousel-3","Carousel with multiple items visible",[65],{"name":1805,"type":576,"title":1806,"description":1806,"categories":1807},"c-carousel-4","Carousel with responsive basis",[65],{"name":1809,"type":576,"title":1810,"description":1810,"categories":1811},"c-carousel-5","Carousel with autoplay plugin",[65],{"name":1813,"type":576,"title":1814,"description":1814,"categories":1815},"c-carousel-6","Carousel with centered slide alignment",[65],{"name":1817,"type":576,"title":1818,"description":1818,"categories":1819},"c-carousel-7","Carousel with custom spacing",[65],{"name":1821,"type":576,"title":1822,"description":1822,"categories":1823},"c-carousel-8","Carousel with images and overlays",[65],{"name":1825,"type":576,"title":1826,"description":1826,"categories":1827},"c-carousel-9","Carousel with thumbnail navigation",[65],{"name":1829,"type":576,"title":1830,"description":1830,"categories":1831},"c-carousel-10","Carousel with overlay thumbnail navigation",[65],{"name":1833,"type":576,"title":1834,"description":1834,"categories":1835},"c-carousel-11","Carousel with dots navigation and content overlays",[65],{"name":1837,"type":576,"title":1838,"description":1838,"categories":1839},"c-chart-1","Basic bar chart",[69],{"name":1841,"type":576,"title":1842,"description":1842,"categories":1843},"c-chart-2","Multi-dataset bar chart",[69],{"name":1845,"type":576,"title":1846,"description":1846,"categories":1847},"c-chart-3","Diagonal stripe bar chart",[69],{"name":1849,"type":576,"title":1850,"description":1850,"categories":1851},"c-chart-4","Dotted pattern bar chart",[69],{"name":1853,"type":576,"title":1854,"description":1854,"categories":1855},"c-chart-5","Striped and solid bar chart",[69],{"name":1857,"type":576,"title":1858,"description":1858,"categories":1859},"c-chart-6","3D gradient bar chart",[69],{"name":1861,"type":576,"title":1862,"description":1862,"categories":1863},"c-chart-7","Gradient bar chart",[69],{"name":1865,"type":576,"title":1866,"description":1866,"categories":1867},"c-chart-8","3D isometric bar chart",[69],{"name":1869,"type":576,"title":1870,"description":1870,"categories":1871},"c-chart-9","Dotted and solid bar chart",[69],{"name":1873,"type":576,"title":1874,"description":1874,"categories":1875},"c-chart-10","Duotone gradient bar chart",[69],{"name":1877,"type":576,"title":1878,"description":1878,"categories":1879},"c-chart-11","Animated monochrome bar chart",[69],{"name":1881,"type":576,"title":1882,"description":1882,"categories":1883},"c-chart-12","Vertical bar chart",[69],{"name":1885,"type":576,"title":1886,"description":1886,"categories":1887},"c-chart-13","Gradient area chart with stripe overlay",[69],{"name":1889,"type":576,"title":1890,"description":1890,"categories":1891},"c-chart-14","Stacked area chart with dashed strokes",[69],{"name":1893,"type":576,"title":1894,"description":1894,"categories":1895},"c-chart-15","Step area chart with dotted pattern fill",[69],{"name":1897,"type":576,"title":1898,"description":1898,"categories":1899},"c-chart-16","Area chart with glowing dot markers",[69],{"name":1901,"type":576,"title":1902,"description":1902,"categories":1903},"c-chart-17","Forecast line chart with stripe pattern zone",[69],{"name":1905,"type":576,"title":1906,"description":1906,"categories":1907},"c-chart-18","Stacked area chart with crosshatch pattern fill",[69],{"name":1909,"type":576,"title":1910,"description":1910,"categories":1911},"c-chart-19","Donut chart with center total",[69],{"name":1913,"type":576,"title":1914,"description":1914,"categories":1915},"c-chart-20","Donut chart with center stats",[69],{"name":1917,"type":576,"title":1918,"description":1918,"categories":1919},"c-chart-21","Bug priority pie with stripe patterns",[69],{"name":1921,"type":576,"title":1922,"description":1922,"categories":1923},"c-chart-22","Active segment donut with center label",[69],{"name":1925,"type":576,"title":1926,"description":1926,"categories":1927},"c-chart-23","Radar chart with gradient fill",[69],{"name":1929,"type":576,"title":1930,"description":1930,"categories":1931},"c-chart-24","Filled radar with glowing stroke",[69],{"name":1933,"type":576,"title":1934,"description":1934,"categories":1935},"c-chart-25","Lighthouse scores radial with labels",[69],{"name":1937,"type":576,"title":1938,"description":1938,"categories":1939},"c-checkbox-1","Basic checkbox with label",[73],{"name":1941,"type":576,"title":1942,"description":1942,"categories":1943},"c-checkbox-2","Disabled checkbox",[73],{"name":1945,"type":576,"title":1946,"description":1946,"categories":1947},"c-checkbox-3","Invalid checkbox",[73],{"name":1949,"type":576,"title":1950,"description":1950,"categories":1951},"c-checkbox-4","Indeterminate checkbox",[73],{"name":1953,"type":576,"title":1954,"description":1954,"categories":1955},"c-checkbox-5","Checkbox with label and description",[73],{"name":1957,"type":576,"title":1958,"description":1958,"categories":1959},"c-checkbox-6","Colored checkbox",[73],{"name":1961,"type":576,"title":1962,"description":1962,"categories":1963},"c-checkbox-7","Circle checkbox",[73],{"name":1965,"type":576,"title":1966,"description":1966,"categories":1967},"c-checkbox-8","Checkbox group",[73],{"name":1969,"type":576,"title":1970,"description":1970,"categories":1971},"c-checkbox-9","Card checkbox with group",[73],{"name":1973,"type":576,"title":1974,"description":1974,"categories":1975},"c-checkbox-10","Checkbox group in a frame",[73],{"name":1977,"type":576,"title":1978,"description":1978,"categories":1979},"c-checkbox-11","Card checkbox group with icons",[73],{"name":1981,"type":576,"title":1978,"description":1978,"categories":1982},"c-checkbox-12",[73],{"name":1984,"type":576,"title":1985,"description":1985,"categories":1986},"c-checkbox-13","Custom positioned checkbox",[73],{"name":1988,"type":576,"title":1985,"description":1985,"categories":1989},"c-checkbox-14",[73],{"name":1991,"type":576,"title":1992,"description":1992,"categories":1993},"c-checkbox-15","Avatar based card checkbox",[73],{"name":1995,"type":576,"title":1996,"description":1996,"categories":1997},"c-checkbox-16","Nested checkbox group",[73],{"name":1999,"type":576,"title":2000,"description":2000,"categories":2001},"c-checkbox-17","Payment method card checkbox",[73],{"name":2003,"type":576,"title":2004,"description":2004,"categories":2005},"c-checkbox-18","Checkbox with label and tooltip info",[73],{"name":2007,"type":576,"title":2008,"description":2008,"categories":2009},"c-checkbox-19","Checkbox group with badge",[73],{"name":2011,"type":576,"title":2004,"description":2004,"categories":2012},"c-checkbox-20",[73],{"name":2014,"type":576,"title":2015,"description":2015,"categories":2016},"c-checkbox-21","Inline horizontal checkbox group",[73],{"name":2018,"type":576,"title":2019,"description":2019,"categories":2020},"c-checkbox-22","Checkbox with feature badge",[73],{"name":2022,"type":576,"title":2023,"description":2023,"categories":2024},"c-collapsible-1","Basic collapsible",[78],{"name":2026,"type":576,"title":2027,"description":2027,"categories":2028},"c-collapsible-2","Collapsible with checkbox settings",[78],{"name":2030,"type":576,"title":2031,"description":2031,"categories":2032},"c-collapsible-3","Collapsible animated card",[78],{"name":2034,"type":576,"title":2035,"description":2035,"categories":2036},"c-collapsible-4","Collapsible card with bottom trigger",[78],{"name":2038,"type":576,"title":2039,"description":2039,"categories":2040},"c-collapsible-5","Collapsible form fields",[78],{"name":2042,"type":576,"title":2043,"description":2043,"categories":2044},"c-collapsible-6","Collapsible frame",[78],{"name":2046,"type":576,"title":2047,"description":2047,"categories":2048},"c-collapsible-7","Nested collapsible list with actions",[78],{"name":2050,"type":576,"title":2051,"description":2051,"categories":2052},"c-collapsible-8","Collapsible User profile",[78],{"name":2054,"type":576,"title":2055,"description":2055,"categories":2056},"c-collapsible-9","Multi-level collapsible menu",[78],{"name":2058,"type":576,"title":2059,"description":2059,"categories":2060},"c-collapsible-10","Tree view with file actions",[78],{"name":2062,"type":576,"title":2063,"description":2063,"categories":2064},"c-combobox-1","A basic combobox with a list of options",[83],{"name":2066,"type":576,"title":2067,"description":2067,"categories":2068},"c-combobox-2","A disabled combobox",[83],{"name":2070,"type":576,"title":2071,"description":2071,"categories":2072},"c-combobox-3","A combobox in an invalid state",[83],{"name":2074,"type":576,"title":2075,"description":2075,"categories":2076},"c-combobox-4","A combobox with a clear button",[83],{"name":2078,"type":576,"title":2079,"description":2079,"categories":2080},"c-combobox-5","A combobox with auto-highlight enabled",[83],{"name":2082,"type":576,"title":2083,"description":2083,"categories":2084},"c-combobox-6","A combobox with grouped options",[83],{"name":2086,"type":576,"title":2087,"description":2087,"categories":2088},"c-combobox-7","A combobox with grouped options and separators",[83],{"name":2090,"type":576,"title":2091,"description":2091,"categories":2092},"c-combobox-8","A combobox with a large list of options",[83],{"name":2094,"type":576,"title":2095,"description":2095,"categories":2096},"c-combobox-9","A combobox with an icon addon",[83],{"name":2098,"type":576,"title":2099,"description":2099,"categories":2100},"c-combobox-10","A combobox rendered inside a popup",[83],{"name":2102,"type":576,"title":2103,"description":2103,"categories":2104},"c-combobox-11","A combobox used within a form",[83],{"name":2106,"type":576,"title":2107,"description":2107,"categories":2108},"c-combobox-12","A multi-select combobox",[83],{"name":2110,"type":576,"title":2111,"description":2111,"categories":2112},"c-combobox-13","A disabled multi-select combobox",[83],{"name":2114,"type":576,"title":2115,"description":2115,"categories":2116},"c-combobox-14","A multi-select combobox in an invalid state",[83],{"name":2118,"type":576,"title":2119,"description":2119,"categories":2120},"c-combobox-15","A multi-select with chips that cannot be removed",[83],{"name":2122,"type":576,"title":2123,"description":2123,"categories":2124},"c-combobox-16","A combobox with custom item rendering",[83],{"name":2126,"type":576,"title":2127,"description":2127,"categories":2128},"c-combobox-17","A combobox used within a dialog",[83],{"name":2130,"type":576,"title":2131,"description":2131,"categories":2132},"c-combobox-18","A combobox with a custom trigger icon",[83],{"name":2134,"type":576,"title":2135,"description":2135,"categories":2136},"c-combobox-19","A multi-select combobox with user tags",[83],{"name":2138,"type":576,"title":2139,"description":2139,"categories":2140},"c-combobox-20","Invisible combobox with member tags",[83],{"name":2142,"type":576,"title":2143,"description":2143,"categories":2144},"c-combobox-21","A status change combobox",[83],{"name":2146,"type":576,"title":2147,"description":2147,"categories":2148},"c-combobox-22","A priority change combobox",[83],{"name":2150,"type":576,"title":2151,"description":2151,"categories":2152},"c-combobox-23","A lead selection combobox",[83],{"name":2154,"type":576,"title":2155,"description":2155,"categories":2156},"c-combobox-24","A multi-member selection combobox",[83],{"name":2158,"type":576,"title":2159,"description":2159,"categories":2160},"c-combobox-25","A date selection combobox with an optional custom picker dialog",[83],{"name":2162,"type":576,"title":2163,"description":2163,"categories":2164},"c-combobox-26","A multi-label selection combobox with a no-label mode",[83],{"name":2166,"type":576,"title":2167,"description":2167,"categories":2168},"c-combobox-27","A team selection combobox",[83],{"name":2170,"type":576,"title":2171,"description":2171,"categories":2172},"c-combobox-28","An assignee selection combobox",[83],{"name":2174,"type":576,"title":2175,"description":2175,"categories":2176},"c-command-1","Basic command",[88],{"name":2178,"type":576,"title":2179,"description":2179,"categories":2180},"c-command-2","Command with shortcuts",[88],{"name":2182,"type":576,"title":2183,"description":2183,"categories":2184},"c-command-3","Command with groups",[88],{"name":2186,"type":576,"title":2187,"description":2187,"categories":2188},"c-command-4","Command with many groups",[88],{"name":2190,"type":576,"title":2191,"description":2191,"categories":2192},"c-command-5","File search command palette",[88],{"name":2194,"type":576,"title":2195,"description":2195,"categories":2196},"c-command-6","User search command with avatars",[88],{"name":2198,"type":576,"title":2199,"description":2199,"categories":2200},"c-command-7","Action palette with keyboard shortcuts",[88],{"name":2202,"type":576,"title":2203,"description":2203,"categories":2204},"c-command-8","Command with recent and favorites sections",[88],{"name":2206,"type":576,"title":2207,"description":2207,"categories":2208},"c-context-menu-1","Basic context menu.",[92],{"name":2210,"type":576,"title":2211,"description":2211,"categories":2212},"c-context-menu-2","Context menu with icons for common actions.",[92],{"name":2214,"type":576,"title":2215,"description":2215,"categories":2216},"c-context-menu-3","Context menu with keyboard shortcuts.",[92],{"name":2218,"type":576,"title":2219,"description":2219,"categories":2220},"c-context-menu-4","Context menu with nested submenus.",[92],{"name":2222,"type":576,"title":2223,"description":2223,"categories":2224},"c-context-menu-5","Context menu labels and separators.",[92],{"name":2226,"type":576,"title":2227,"description":2227,"categories":2228},"c-context-menu-6","Context menu with checkbox items.",[92],{"name":2230,"type":576,"title":2231,"description":2231,"categories":2232},"c-context-menu-7","Context menu with radio items.",[92],{"name":2234,"type":576,"title":2235,"description":2235,"categories":2236},"c-context-menu-8","Context menu with destructive actions.",[92],{"name":2238,"type":576,"title":2239,"description":2239,"categories":2240},"c-context-menu-9","Context menu with different alignment sides.",[92],{"name":2242,"type":576,"title":2243,"description":2243,"categories":2244},"c-context-menu-10","Context menu used inside a dialog component.",[92],{"name":2246,"type":576,"title":2247,"description":2247,"categories":2248},"c-data-grid-1","Data grid with pagination",[96],{"name":2250,"type":576,"title":2251,"description":2251,"categories":2252},"c-data-grid-2","Data grid with cell border",[96],{"name":2254,"type":576,"title":2255,"description":2255,"categories":2256},"c-data-grid-3","Data grid with dense layout",[96],{"name":2258,"type":576,"title":2259,"description":2259,"categories":2260},"c-data-grid-4","Data grid without table borders",[96],{"name":2262,"type":576,"title":2263,"description":2263,"categories":2264},"c-data-grid-5","Data grid with striped rows",[96],{"name":2266,"type":576,"title":2267,"description":2267,"categories":2268},"c-data-grid-6","Data grid with auto width table layout",[96],{"name":2270,"type":576,"title":2271,"description":2271,"categories":2272},"c-data-grid-7","Data grid with row selection",[96],{"name":2274,"type":576,"title":2275,"description":2275,"categories":2276},"c-data-grid-8","Data grid with expandable rows",[96],{"name":2278,"type":576,"title":2279,"description":2279,"categories":2280},"c-data-grid-9","Data grid with sub table",[96],{"name":2282,"type":576,"title":2283,"description":2283,"categories":2284},"c-data-grid-10","Data grid with column icons",[96],{"name":2286,"type":576,"title":2287,"description":2287,"categories":2288},"c-data-grid-11","Data grid with sortable columns",[96],{"name":2290,"type":576,"title":2291,"description":2291,"categories":2292},"c-data-grid-12","Data grid with movable columns",[96],{"name":2294,"type":576,"title":2295,"description":2295,"categories":2296},"c-data-grid-13","Data grid with draggable columns",[96],{"name":2298,"type":576,"title":2299,"description":2299,"categories":2300},"c-data-grid-14","Data grid with draggable rows",[96],{"name":2302,"type":576,"title":2303,"description":2303,"categories":2304},"c-data-grid-15","Data grid with column resizing",[96],{"name":2306,"type":576,"title":2307,"description":2307,"categories":2308},"c-data-grid-16","Data grid with pinnable columns",[96],{"name":2310,"type":576,"title":2311,"description":2311,"categories":2312},"c-data-grid-17","Data grid with sticky header",[96],{"name":2314,"type":576,"title":2315,"description":2315,"categories":2316},"c-data-grid-18","Data grid with column controls",[96],{"name":2318,"type":576,"title":2319,"description":2319,"categories":2320},"c-data-grid-19","Data grid with card container",[96],{"name":2322,"type":576,"title":2323,"description":2323,"categories":2324},"c-data-grid-20","Data grid with column visibility controls",[96],{"name":2326,"type":576,"title":2327,"description":2327,"categories":2328},"c-data-grid-21","Data grid with loading skeleton",[96],{"name":2330,"type":576,"title":2331,"description":2331,"categories":2332},"c-data-grid-22","Data grid with CRUD features",[96],{"name":2334,"type":576,"title":2335,"description":2335,"categories":2336},"c-data-grid-23","Data grid with CRUD in frame container",[96],{"name":2338,"type":576,"title":2339,"description":2339,"categories":2340},"c-data-grid-24","Data grid with column totals footer",[96],{"name":2342,"type":576,"title":2343,"description":2343,"categories":2344},"c-data-grid-25","Data grid with summary stats footer",[96],{"name":2346,"type":576,"title":2347,"description":2347,"categories":2348},"c-data-grid-26","Data grid with per-column aggregate footer",[96],{"name":2350,"type":576,"title":2351,"description":2351,"categories":2352},"c-data-grid-27","Data grid with local infinite scroll",[96],{"name":2354,"type":576,"title":2355,"description":2355,"categories":2356},"c-data-grid-28","Data grid with remote infinite scroll",[96],{"name":2358,"type":576,"title":2359,"description":2359,"categories":2360},"c-data-grid-29","Data grid with row pinning support",[96],{"name":2362,"type":576,"title":2363,"description":2363,"categories":2364},"c-date-selector-1","Basic date selector",[101],{"name":2366,"type":576,"title":2367,"description":2367,"categories":2368},"c-date-selector-2","Date selector with popover",[101],{"name":2370,"type":576,"title":2371,"description":2371,"categories":2372},"c-date-selector-3","Date selector with dialog",[101],{"name":2374,"type":576,"title":2375,"description":2375,"categories":2376},"c-date-selector-4","Date selector with dropdown menu",[101],{"name":2378,"type":576,"title":2379,"description":2379,"categories":2380},"c-dialog-1","Basic dialog",[106],{"name":2382,"type":576,"title":2383,"description":2383,"categories":2384},"c-dialog-2","Dialog with scrollable content",[106],{"name":2386,"type":576,"title":2387,"description":2387,"categories":2388},"c-dialog-3","Dialog with scrollable content and sticky footer.",[106],{"name":2390,"type":576,"title":2391,"description":2391,"categories":2392},"c-dialog-4","Dialog without a close button.",[106],{"name":2394,"type":576,"title":2395,"description":2395,"categories":2396},"c-dialog-5","Dialog with custom close button",[106],{"name":2398,"type":576,"title":2399,"description":2399,"categories":2400},"c-dialog-6","Full-screen fluid dialog with sticky header and footer",[106],{"name":2402,"type":576,"title":2403,"description":2403,"categories":2404},"c-dialog-7","Confirmation dialog with destructive action",[106],{"name":2406,"type":576,"title":2407,"description":2407,"categories":2408},"c-dialog-8","Cookie consent dialog",[106],{"name":2410,"type":576,"title":2411,"description":2411,"categories":2412},"c-dialog-9","Dialog with keyboard shortcuts list",[106],{"name":2414,"type":576,"title":2415,"description":2415,"categories":2416},"c-dialog-10","Dialog with full width button",[106],{"name":2418,"type":576,"title":2419,"description":2419,"categories":2420},"c-drawer-1","A basic drawer with scrollable content",[110],{"name":2422,"type":576,"title":2423,"description":2423,"categories":2424},"c-drawer-2","A drawer that opens from the right side",[110],{"name":2426,"type":576,"title":2427,"description":2427,"categories":2428},"c-drawer-3","A drawer that opens from the left side",[110],{"name":2430,"type":576,"title":2431,"description":2431,"categories":2432},"c-drawer-4","A drawer that opens from the top side",[110],{"name":2434,"type":576,"title":2435,"description":2435,"categories":2436},"c-drawer-5","Drawers opening from different sides",[110],{"name":2438,"type":576,"title":2439,"description":2439,"categories":2440},"c-dropdown-menu-1","Basic dropdown menu",[115],{"name":2442,"type":576,"title":2443,"description":2443,"categories":2444},"c-dropdown-menu-2","Dropdown menus opening positions",[115],{"name":2446,"type":576,"title":2447,"description":2447,"categories":2448},"c-dropdown-menu-3","Dropdown menu with icons",[115],{"name":2450,"type":576,"title":2451,"description":2451,"categories":2452},"c-dropdown-menu-4","Dropdown menu with keyboard shortcuts",[115],{"name":2454,"type":576,"title":2455,"description":2455,"categories":2456},"c-dropdown-menu-5","Dropdown menu with nested submenus",[115],{"name":2458,"type":576,"title":2459,"description":2459,"categories":2460},"c-dropdown-menu-6","Dropdown menu with checkboxes",[115],{"name":2462,"type":576,"title":2463,"description":2463,"categories":2464},"c-dropdown-menu-7","Dropdown menu with radio groups",[115],{"name":2466,"type":576,"title":2467,"description":2467,"categories":2468},"c-dropdown-menu-8","Advance dropdown menu",[115],{"name":2470,"type":576,"title":2471,"description":2471,"categories":2472},"c-dropdown-menu-9","User profile dropdown menu",[115],{"name":2474,"type":576,"title":2475,"description":2475,"categories":2476},"c-dropdown-menu-10","Workspace switcher dropdown menu",[115],{"name":2478,"type":576,"title":2479,"description":2479,"categories":2480},"c-dropdown-menu-11","Notifications dropdown menu",[115],{"name":2482,"type":576,"title":2483,"description":2483,"categories":2484},"c-dropdown-menu-12","Actions dropdown menu",[115],{"name":2486,"type":576,"title":2487,"description":2487,"categories":2488},"c-dropdown-menu-13","Share and export dropdown menu",[115],{"name":2490,"type":576,"title":2491,"description":2491,"categories":2492},"c-dropdown-menu-14","User profile dropdown menu with theme toggle and status selector",[115],{"name":2494,"type":576,"title":2495,"description":2495,"categories":2496},"c-dropdown-menu-15","User and create menu",[115],{"name":2498,"type":576,"title":2499,"description":2499,"categories":2500},"c-dropdown-menu-16","Quick action menu",[115],{"name":2502,"type":576,"title":2503,"description":2503,"categories":2504},"c-dropdown-menu-17","Notifications dropdown with items",[115],{"name":2506,"type":576,"title":2507,"description":2507,"categories":2508},"c-dropdown-menu-18","AI model selector with provider icons",[115],{"name":2510,"type":576,"title":2511,"description":2511,"categories":2512},"c-empty-1","Basic empty state",[119],{"name":2514,"type":576,"title":2515,"description":2515,"categories":2516},"c-empty-2","Search empty state",[119],{"name":2518,"type":576,"title":2519,"description":2519,"categories":2520},"c-empty-3","Empty state with search input",[119],{"name":2522,"type":576,"title":2523,"description":2523,"categories":2524},"c-empty-4","Empty state with add button",[119],{"name":2526,"type":576,"title":2527,"description":2527,"categories":2528},"c-empty-5","Document empty state",[119],{"name":2530,"type":576,"title":2531,"description":2531,"categories":2532},"c-empty-6","Dashed upload empty state",[119],{"name":2534,"type":576,"title":2535,"description":2535,"categories":2536},"c-empty-7","Inbox empty state",[119],{"name":2538,"type":576,"title":2539,"description":2539,"categories":2540},"c-empty-8","Team members empty state",[119],{"name":2542,"type":576,"title":2543,"description":2543,"categories":2544},"c-empty-9","No notifications empty state",[119],{"name":2546,"type":576,"title":2547,"description":2547,"categories":2548},"c-empty-10","No data analytics empty state",[119],{"name":2550,"type":576,"title":2551,"description":2551,"categories":2552},"c-empty-11","Bookmarks empty state",[119],{"name":2554,"type":576,"title":2555,"description":2555,"categories":2556},"c-empty-12","Tasks empty state",[119],{"name":2558,"type":576,"title":2559,"description":2559,"categories":2560},"c-empty-13","No automations empty state with toggle illustration",[119],{"name":2562,"type":576,"title":2563,"description":2563,"categories":2564},"c-empty-14","Comments empty state with isometric board illustration",[119],{"name":2566,"type":576,"title":2567,"description":2567,"categories":2568},"c-empty-15","No products empty state with stacked cards and blur effect",[119],{"name":2570,"type":576,"title":2571,"description":2571,"categories":2572},"c-empty-16","Search empty state with stacked file cards illustration",[119],{"name":2574,"type":576,"title":2575,"description":2575,"categories":2576},"c-empty-17","No messages empty state with chat bubbles illustration",[119],{"name":2578,"type":576,"title":2579,"description":2579,"categories":2580},"c-empty-18","No payments empty state with credit card illustration",[119],{"name":2582,"type":576,"title":2583,"description":2583,"categories":2584},"c-empty-19","No integrations empty state with connected nodes illustration",[119],{"name":2586,"type":576,"title":2587,"description":2587,"categories":2588},"c-empty-20","No events empty state with calendar illustration",[119],{"name":2590,"type":576,"title":2591,"description":2591,"categories":2592},"c-event-calendar-1","Event calendar with all views and live settings",[123],{"name":2594,"type":576,"title":2595,"description":2595,"categories":2596},"c-event-calendar-2","Event calendar with resource view for room bookings",[123],{"name":2598,"type":576,"title":2599,"description":2600,"categories":2601},"c-event-calendar-3","Event calendar with create and edit dialog","Month calendar with event CRUD in one dialog: open from an empty day, an event, or Add event, commit via apiRef. Title, color, start, duration, all-day fields. ReUI EventCalendar, Nav, Toolbar; shadcn Dialog, Field, Select, Switch. Scheduling apps.",[123],{"name":2603,"type":576,"title":2604,"description":2604,"categories":2605},"c-event-calendar-4","Event calendar with custom event chips",[123],{"name":2607,"type":576,"title":2608,"description":2608,"categories":2609},"c-event-calendar-5","Event calendar with drag-to-book appointments",[123],{"name":2611,"type":576,"title":2612,"description":2612,"categories":2613},"c-field-1","Fields with input groups",[127],{"name":2615,"type":576,"title":2616,"description":2616,"categories":2617},"c-field-2","Field with input and textarea",[127],{"name":2619,"type":576,"title":2620,"description":2620,"categories":2621},"c-field-3","Field with select control",[127],{"name":2623,"type":576,"title":2624,"description":2624,"categories":2625},"c-field-4","Field with radio groups and checkboxes",[127],{"name":2627,"type":576,"title":2628,"description":2628,"categories":2629},"c-field-5","Filed with slider and switch",[127],{"name":2631,"type":576,"title":2632,"description":2632,"categories":2633},"c-field-6","Field with OTP input",[127],{"name":2635,"type":576,"title":2636,"description":2636,"categories":2637},"c-field-7","Settings form with validation",[127],{"name":2639,"type":576,"title":2640,"description":2640,"categories":2641},"c-field-8","Permission settings with checkboxes",[127],{"name":2643,"type":576,"title":2644,"description":2644,"categories":2645},"c-field-9","Responsive field layout",[127],{"name":2647,"type":576,"title":2648,"description":2648,"categories":2649},"c-field-10","Notification preferences form",[127],{"name":2651,"type":576,"title":2652,"description":2652,"categories":2653},"c-field-11","Form with validation errors",[127],{"name":2655,"type":576,"title":2656,"description":2656,"categories":2657},"c-file-upload-1","Basic file upload",[131],{"name":2659,"type":576,"title":2660,"description":2660,"categories":2661},"c-file-upload-2","Avatar upload",[131],{"name":2663,"type":576,"title":2664,"description":2664,"categories":2665},"c-file-upload-3","Basic drag and drop file upload",[131],{"name":2667,"type":576,"title":2668,"description":2668,"categories":2669},"c-file-upload-4","Gallery file upload",[131],{"name":2671,"type":576,"title":2672,"description":2672,"categories":2673},"c-file-upload-5","Progress file upload",[131],{"name":2675,"type":576,"title":2676,"description":2676,"categories":2677},"c-file-upload-6","Table file upload",[131],{"name":2679,"type":576,"title":2680,"description":2680,"categories":2681},"c-file-upload-7","Image upload",[131],{"name":2683,"type":576,"title":2684,"description":2684,"categories":2685},"c-file-upload-8","Image upload with sorting.",[131],{"name":2687,"type":576,"title":2688,"description":2688,"categories":2689},"c-file-upload-9","Card file upload.",[131],{"name":2691,"type":576,"title":2692,"description":2692,"categories":2693},"c-file-upload-10","Cover image upload.",[131],{"name":2695,"type":576,"title":2696,"description":2696,"categories":2697},"c-filters-1","Filters with various field types",[135],{"name":2699,"type":576,"title":2700,"description":2700,"categories":2701},"c-filters-2","Filters with input validation",[135],{"name":2703,"type":576,"title":2704,"description":2704,"categories":2705},"c-filters-3","Filters with custom trigger button",[135],{"name":2707,"type":576,"title":2708,"description":2708,"categories":2709},"c-filters-4","Filters with small size controls",[135],{"name":2711,"type":576,"title":2712,"description":2712,"categories":2713},"c-filters-5","Filters with large size controls",[135],{"name":2715,"type":576,"title":2716,"description":2716,"categories":2717},"c-filters-6","Filters with custom controls",[135],{"name":2719,"type":576,"title":2720,"description":2720,"categories":2721},"c-filters-7","Filters with data grid",[135],{"name":2723,"type":576,"title":2724,"description":2724,"categories":2725},"c-filters-8","Filters with data grid and async mode",[135],{"name":2727,"type":576,"title":2728,"description":2728,"categories":2729},"c-filters-9","Filters with i18n support",[135],{"name":2731,"type":576,"title":2732,"description":2732,"categories":2733},"c-filters-10","Filters with virtualized large lists",[135],{"name":2735,"type":576,"title":2736,"description":2736,"categories":2737},"c-filters-11","Filters with prefetched async options",[135],{"name":2739,"type":576,"title":2740,"description":2740,"categories":2741},"c-filters-12","Filters with async server-side search",[135],{"name":2743,"type":576,"title":2744,"description":2744,"categories":2745},"c-frame-1","Basic frame",[139],{"name":2747,"type":576,"title":2748,"description":2748,"categories":2749},"c-frame-2","Frame with separated panels",[139],{"name":2751,"type":576,"title":2752,"description":2752,"categories":2753},"c-frame-3","Frame with stacked panels",[139],{"name":2755,"type":576,"title":2756,"description":2756,"categories":2757},"c-frame-4","Frame with stacked panels and dense style",[139],{"name":2759,"type":576,"title":2760,"description":2760,"categories":2761},"c-frame-5","Frame with collapsible panels",[139],{"name":2763,"type":576,"title":2764,"description":2764,"categories":2765},"c-frame-6","Frame with ghost(no outer border) variant",[139],{"name":2767,"type":576,"title":2768,"description":2768,"categories":2769},"c-frame-7","Frame with dense layout",[139],{"name":2771,"type":576,"title":2752,"description":2752,"categories":2772},"c-frame-8",[139],{"name":2774,"type":576,"title":2775,"description":2775,"categories":2776},"c-frame-9","Frame with extra small spacing",[139],{"name":2778,"type":576,"title":2779,"description":2779,"categories":2780},"c-frame-10","Frame with small spacing",[139],{"name":2782,"type":576,"title":2783,"description":2783,"categories":2784},"c-frame-11","Frame with default spacing",[139],{"name":2786,"type":576,"title":2787,"description":2787,"categories":2788},"c-frame-12","Frame with large spacing",[139],{"name":2790,"type":576,"title":2791,"description":2791,"categories":2792},"c-frame-13","Frame with small border radius",[139],{"name":2794,"type":576,"title":2795,"description":2795,"categories":2796},"c-frame-14","Frame with medium border radius",[139],{"name":2798,"type":576,"title":2799,"description":2799,"categories":2800},"c-frame-15","Frame with large border radius",[139],{"name":2802,"type":576,"title":2803,"description":2803,"categories":2804},"c-frame-16","Frame with default border radius",[139],{"name":2806,"type":576,"title":2807,"description":2807,"categories":2808},"c-frame-17","Frame with extra large border radius",[139],{"name":2810,"type":576,"title":2811,"description":2811,"categories":2812},"c-frame-18","Frame with content-only panels",[139],{"name":2814,"type":576,"title":2815,"description":2815,"categories":2816},"c-frame-19","Frame with stacked content-only panels",[139],{"name":2818,"type":576,"title":2819,"description":2819,"categories":2820},"c-gantt-1","Gantt chart with settings menu and schedulable rows",[144],{"name":2822,"type":576,"title":2823,"description":2823,"categories":2824},"c-gantt-2","Gantt chart with drag-to-reorder tree rows",[144],{"name":2826,"type":576,"title":2827,"description":2828,"categories":2829},"c-gantt-3","Gantt chart with quarter roadmap and rollups","Quarter-scale roadmap where workstream groups form swimlanes and parent rows roll children into one summary bar. Toolbar button calls addEvent via apiRef to schedule backlog items. ReUI Gantt, GanttNav, GanttToolbar, GanttView; shadcn Card, Button.",[144],{"name":2831,"type":576,"title":2832,"description":2832,"categories":2833},"c-gantt-4","Gantt chart with weekly capacity board",[144],{"name":2835,"type":576,"title":2836,"description":2836,"categories":2837},"c-gantt-5","Gantt chart with task table and progress",[144],{"name":2839,"type":576,"title":2840,"description":2840,"categories":2841},"c-hover-card-1","Basic hover card.",[148],{"name":2843,"type":576,"title":2844,"description":2844,"categories":2845},"c-hover-card-2","Hover card with positions.",[148],{"name":2847,"type":576,"title":2848,"description":2848,"categories":2849},"c-hover-card-3","Hover card with profile information.",[148],{"name":2851,"type":576,"title":2852,"description":2852,"categories":2853},"c-hover-card-4","Hover card with icon",[148],{"name":2855,"type":576,"title":2856,"description":2856,"categories":2857},"c-hover-card-5","Hover card with an image and text content.",[148],{"name":2859,"type":576,"title":2860,"description":2860,"categories":2861},"c-hover-card-6","Hover card inside a dialog.",[148],{"name":2863,"type":576,"title":2864,"description":2864,"categories":2865},"c-hover-card-7","Timestamp hover card with active relative time",[148],{"name":2867,"type":576,"title":2868,"description":2868,"categories":2869},"c-hover-card-8","Hover card with paginated release notes",[148],{"name":2871,"type":576,"title":2872,"description":2873,"categories":2874},"c-icon-stack-1","Isometric icon stack","Layered isometric icon",[152],{"name":2876,"type":576,"title":2877,"description":2878,"categories":2879},"c-icon-stack-2","Icon stack sizes","Responsive icon stack sizes",[152],{"name":2881,"type":576,"title":2882,"description":2883,"categories":2884},"c-icon-stack-3","Icon stack colors","Semantic icon stack colors",[152],{"name":2886,"type":576,"title":2887,"description":2888,"categories":2889},"c-icon-stack-4","Icon badge stack","Icon stack with badge overlay",[152],{"name":2891,"type":576,"title":2892,"description":2893,"categories":2894},"c-icon-stack-5","Empty state illustration","Shadcn empty state illustration",[152],{"name":2896,"type":576,"title":2897,"description":2898,"categories":2899},"c-icon-stack-6","Item media stack","Icon stack in shadcn item",[152],{"name":2901,"type":576,"title":2902,"description":2902,"categories":2903},"c-icon-tile-1","Default icon tile",[157],{"name":2905,"type":576,"title":2906,"description":2907,"categories":2908},"c-icon-tile-2","Elevated icon tile","Icon tile with elevated surface",[157],{"name":2910,"type":576,"title":2911,"description":2912,"categories":2913},"c-icon-tile-3","Framed icon tile","Icon tile with framed surface",[157],{"name":2915,"type":576,"title":2916,"description":2917,"categories":2918},"c-icon-tile-4","All variants","Every icon tile variant",[157],{"name":2920,"type":576,"title":2921,"description":2922,"categories":2923},"c-icon-tile-5","Sizes","Icon tile size scale",[157],{"name":2925,"type":576,"title":2926,"description":2927,"categories":2928},"c-icon-tile-6","Circular tiles","Icon tiles with circular shape",[157],{"name":2930,"type":576,"title":2931,"description":2932,"categories":2933},"c-icon-tile-7","Custom sizing","Icon tile with custom sizing",[157],{"name":2935,"type":576,"title":2936,"description":2937,"categories":2938},"c-icon-tile-8","Color tones","Semantic icon tile color tones",[157],{"name":2940,"type":576,"title":2941,"description":2942,"categories":2943},"c-icon-tile-9","Text content","Icon tile with text content",[157],{"name":2945,"type":576,"title":2946,"description":2947,"categories":2948},"c-icon-tile-10","List row","Icon tile in a list row",[157],{"name":2950,"type":576,"title":2951,"description":2952,"categories":2953},"c-icon-tile-11","Feature card","Icon tile in a feature card",[157],{"name":2955,"type":576,"title":2956,"description":2957,"categories":2958},"c-icon-tile-12","Empty state","Icon tile in an empty state",[157],{"name":2960,"type":576,"title":2961,"description":2962,"categories":2963},"c-icon-tile-13","Interactive tile","Interactive icon tile",[157],{"name":2965,"type":576,"title":2966,"description":2967,"categories":2968},"c-icon-tile-14","Status overlay","Icon tile with status overlay",[157],{"name":2970,"type":576,"title":2971,"description":2972,"categories":2973},"c-icon-tile-15","Soft tones","Tone-adjustable soft variant",[157],{"name":2975,"type":576,"title":2976,"description":2977,"categories":2978},"c-icon-tile-16","Solid tones","Tone-adjustable solid variant",[157],{"name":2980,"type":576,"title":2981,"description":2982,"categories":2983},"c-icon-tile-17","Brand colors","Elevated tile with a Tailwind color fill",[157],{"name":2985,"type":576,"title":2986,"description":2986,"categories":2987},"c-input-group-1","Basic input group",[167],{"name":2989,"type":576,"title":2990,"description":2990,"categories":2991},"c-input-group-2","Input group in disabled state",[167],{"name":2993,"type":576,"title":2994,"description":2994,"categories":2995},"c-input-group-3","Input group in invalid state",[167],{"name":2997,"type":576,"title":2998,"description":2998,"categories":2999},"c-input-group-4","Input group with prefix icon",[167],{"name":3001,"type":576,"title":3002,"description":3002,"categories":3003},"c-input-group-5","Input group with suffix icon",[167],{"name":3005,"type":576,"title":3006,"description":3006,"categories":3007},"c-input-group-6","Input group with both prefix and suffix icons",[167],{"name":3009,"type":576,"title":3010,"description":3010,"categories":3011},"c-input-group-7","Input group with prefix text addon",[167],{"name":3013,"type":576,"title":3014,"description":3014,"categories":3015},"c-input-group-8","Input group with suffix text addon",[167],{"name":3017,"type":576,"title":3018,"description":3018,"categories":3019},"c-input-group-9","Input group with both prefix and suffix text addons",[167],{"name":3021,"type":576,"title":3022,"description":3022,"categories":3023},"c-input-group-10","Input group with action button addon",[167],{"name":3025,"type":576,"title":3026,"description":3026,"categories":3027},"c-input-group-11","Input group with icon button action",[167],{"name":3029,"type":576,"title":3030,"description":3030,"categories":3031},"c-input-group-12","Input group with dropdown menu selection",[167],{"name":3033,"type":576,"title":3034,"description":3034,"categories":3035},"c-input-group-13","Input group with keyboard shortcut (Kbd)",[167],{"name":3037,"type":576,"title":3038,"description":3038,"categories":3039},"c-input-group-14","Input group with tooltip action",[167],{"name":3041,"type":576,"title":3042,"description":3042,"categories":3043},"c-input-group-15","Input group with loading spinner",[167],{"name":3045,"type":576,"title":3046,"description":3046,"categories":3047},"c-input-group-16","Input group with block-start addon",[167],{"name":3049,"type":576,"title":3050,"description":3050,"categories":3051},"c-input-group-17","Textarea input group with dynamic character limit",[167],{"name":3053,"type":576,"title":3054,"description":3054,"categories":3055},"c-input-group-18","AI Chat textarea with rich toolbar actions",[167],{"name":3057,"type":576,"title":3058,"description":3058,"categories":3059},"c-input-group-19","AI Chat interface with file and context attachments",[167],{"name":3061,"type":576,"title":3062,"description":3062,"categories":3063},"c-input-group-20","Input group demonstrating label usage",[167],{"name":3065,"type":576,"title":3066,"description":3066,"categories":3067},"c-input-group-21","Input group with multiple icons\u002Fbuttons at the end",[167],{"name":3069,"type":576,"title":3070,"description":3070,"categories":3071},"c-input-group-22","Input group with popover trigger addon",[167],{"name":3073,"type":576,"title":3074,"description":3074,"categories":3075},"c-input-group-23","Input group with Sparkles icon and complex Kbd shortcut",[167],{"name":3077,"type":576,"title":3078,"description":3078,"categories":3079},"c-input-group-24","Input group with success indicator circle",[167],{"name":3081,"type":576,"title":3082,"description":3082,"categories":3083},"c-input-group-25","Input group with search results count",[167],{"name":3085,"type":576,"title":3086,"description":3086,"categories":3087},"c-input-group-26","Textarea input group with action buttons",[167],{"name":3089,"type":576,"title":3090,"description":3090,"categories":3091},"c-input-group-27","Input group wrapped in a button group with text prefixes\u002Fsuffixes",[167],{"name":3093,"type":576,"title":3094,"description":3094,"categories":3095},"c-input-group-28","Input group with a menu button (three dots) at the end",[167],{"name":3097,"type":576,"title":3098,"description":3098,"categories":3099},"c-input-group-29","Pill-shaped input group with a category dropdown at the end",[167],{"name":3101,"type":576,"title":3102,"description":3102,"categories":3103},"c-input-group-30","Input group with inline addons (no separating borders)",[167],{"name":3105,"type":576,"title":3106,"description":3106,"categories":3107},"c-input-group-31","Input group with inline start and block-end addon",[167],{"name":3109,"type":576,"title":3110,"description":3110,"categories":3111},"c-input-group-32","Member row with avatar, email and role selection",[167],{"name":3113,"type":576,"title":3114,"description":3114,"categories":3115},"c-input-group-33","Project save interface with status and action buttons",[167],{"name":3117,"type":576,"title":3118,"description":3118,"categories":3119},"c-input-group-34","Pill-shaped AI prompt bar with voice and audio icons",[167],{"name":3121,"type":576,"title":3122,"description":3122,"categories":3123},"c-input-group-35","Password input with visibility toggle",[167],{"name":3125,"type":576,"title":3126,"description":3126,"categories":3127},"c-input-group-36","API request input with method selector and send action",[167],{"name":3129,"type":576,"title":3130,"description":3130,"categories":3131},"c-input-group-37","Order search input with status filter",[167],{"name":3133,"type":576,"title":3134,"description":3134,"categories":3135},"c-input-group-38","Company search input with region selector",[167],{"name":3137,"type":576,"title":3138,"description":3138,"categories":3139},"c-input-group-39","Contact search input with filter and actions menu",[167],{"name":3141,"type":576,"title":3142,"description":3142,"categories":3143},"c-input-group-40","Share link input with visibility selector and copy action",[167],{"name":3145,"type":576,"title":3146,"description":3146,"categories":3147},"c-input-otp-1","Basic OTP input.",[172],{"name":3149,"type":576,"title":3150,"description":3150,"categories":3151},"c-input-otp-2","OTP input with numeric digits.",[172],{"name":3153,"type":576,"title":3154,"description":3154,"categories":3155},"c-input-otp-3","OTP input with multiple separators.",[172],{"name":3157,"type":576,"title":3158,"description":3158,"categories":3159},"c-input-otp-4","OTP input with letters and numbers.",[172],{"name":3161,"type":576,"title":3162,"description":3162,"categories":3163},"c-input-otp-5","OTP input for PIN codes.",[172],{"name":3165,"type":576,"title":3166,"description":3166,"categories":3167},"c-input-otp-6","OTP input verification code.",[172],{"name":3169,"type":576,"title":3170,"description":3170,"categories":3171},"c-input-1","Basic input",[162],{"name":3173,"type":576,"title":3174,"description":3174,"categories":3175},"c-input-2","Input with label",[162],{"name":3177,"type":576,"title":3178,"description":3178,"categories":3179},"c-input-3","Input with description",[162],{"name":3181,"type":576,"title":3182,"description":3182,"categories":3183},"c-input-4","Disabled input",[162],{"name":3185,"type":576,"title":3186,"description":3186,"categories":3187},"c-input-5","Input with error message",[162],{"name":3189,"type":576,"title":3190,"description":3190,"categories":3191},"c-input-6","Input with character counter",[162],{"name":3193,"type":576,"title":3194,"description":3194,"categories":3195},"c-input-7","Input with password type",[162],{"name":3197,"type":576,"title":3198,"description":3198,"categories":3199},"c-input-8","Input with phone type",[162],{"name":3201,"type":576,"title":3202,"description":3202,"categories":3203},"c-input-9","Input with URL type",[162],{"name":3205,"type":576,"title":3206,"description":3206,"categories":3207},"c-input-10","Input with number type",[162],{"name":3209,"type":576,"title":3210,"description":3210,"categories":3211},"c-input-11","Input with date type",[162],{"name":3213,"type":576,"title":3214,"description":3214,"categories":3215},"c-input-12","Input with file type",[162],{"name":3217,"type":576,"title":3218,"description":3218,"categories":3219},"c-input-13","Input with required indicator",[162],{"name":3221,"type":576,"title":3222,"description":3222,"categories":3223},"c-input-14","Input with time type",[162],{"name":3225,"type":576,"title":3226,"description":3226,"categories":3227},"c-input-15","Complex input form with multiple fields",[162],{"name":3229,"type":576,"title":3230,"description":3230,"categories":3231},"c-input-16","Input label with tooltip",[162],{"name":3233,"type":576,"title":3234,"description":3234,"categories":3235},"c-input-17","Input label with badge",[162],{"name":3237,"type":576,"title":3238,"description":3238,"categories":3239},"c-input-18","Input label with optional badge",[162],{"name":3241,"type":576,"title":3242,"description":3242,"categories":3243},"c-input-19","Input label with link and visibility toggle",[162],{"name":3245,"type":576,"title":3246,"description":3246,"categories":3247},"c-input-20","Input with horizontal orientation",[162],{"name":3249,"type":576,"title":3250,"description":3250,"categories":3251},"c-input-21","Input with multiple error messages",[162],{"name":3253,"type":576,"title":3254,"description":3254,"categories":3255},"c-input-22","Basic password strength with dynamic hint and icons",[162],{"name":3257,"type":576,"title":3258,"description":3258,"categories":3259},"c-input-23","Advanced password strength indicator with progress",[162],{"name":3261,"type":576,"title":3262,"description":3262,"categories":3263},"c-input-24","Input with pulsed background animation",[162],{"name":3265,"type":576,"title":3266,"description":3266,"categories":3267},"c-input-25","Input with custom focus ring",[162],{"name":3269,"type":576,"title":3270,"description":3270,"categories":3271},"c-input-26","Input with subtle background",[162],{"name":3273,"type":576,"title":3274,"description":3274,"categories":3275},"c-input-27","Input with bottom border only",[162],{"name":3277,"type":576,"title":3278,"description":3278,"categories":3279},"c-input-28","Color input",[162],{"name":3281,"type":576,"title":3282,"description":3282,"categories":3283},"c-input-29","Range input with value indicator",[162],{"name":3285,"type":576,"title":3286,"description":3286,"categories":3287},"c-input-30","Pill-shaped input",[162],{"name":3289,"type":576,"title":3290,"description":3290,"categories":3291},"c-input-31","Minimal input without borders or background",[162],{"name":3293,"type":576,"title":3294,"description":3294,"categories":3295},"c-item-1","Basic item with title and description",[176],{"name":3297,"type":576,"title":3298,"description":3298,"categories":3299},"c-item-2","Items with icon media and action buttons",[176],{"name":3301,"type":576,"title":3302,"description":3302,"categories":3303},"c-item-3","User item with avatar, info, and follow button",[176],{"name":3305,"type":576,"title":3306,"description":3306,"categories":3307},"c-item-4","Clickable navigation items with icons and chevron",[176],{"name":3309,"type":576,"title":3310,"description":3310,"categories":3311},"c-item-5","Item group with status badges",[176],{"name":3313,"type":576,"title":3314,"description":3314,"categories":3315},"c-item-6","File items with icon media, size, and actions",[176],{"name":3317,"type":576,"title":3318,"description":3318,"categories":3319},"c-item-7","Items with keyboard shortcuts",[176],{"name":3321,"type":576,"title":3322,"description":3322,"categories":3323},"c-item-8","Small-size items with badges",[176],{"name":3325,"type":576,"title":3326,"description":3326,"categories":3327},"c-item-9","Team members with roles and multiple actions",[176],{"name":3329,"type":576,"title":3330,"description":3330,"categories":3331},"c-item-10","Item with header and footer sections",[176],{"name":3333,"type":576,"title":3334,"description":3334,"categories":3335},"c-item-11","Integration items with connect actions",[176],{"name":3337,"type":576,"title":3338,"description":3338,"categories":3339},"c-item-12","Activity feed items with avatars and actions",[176],{"name":3341,"type":576,"title":3342,"description":3342,"categories":3343},"c-kanban-1","Kanban board with placeholder overlay",[180],{"name":3345,"type":576,"title":3346,"description":3346,"categories":3347},"c-kanban-2","Kanban board with dynamic overlay",[180],{"name":3349,"type":576,"title":3350,"description":3350,"categories":3351},"c-kanban-3","Kanban board with frame columns",[180],{"name":3353,"type":576,"title":3354,"description":3354,"categories":3355},"c-kanban-4","Minimal kanban with stacked frame",[180],{"name":3357,"type":576,"title":3358,"description":3358,"categories":3359},"c-kanban-5","Feature roadmap kanban with progress",[180],{"name":3361,"type":576,"title":3362,"description":3363,"categories":3364},"c-kanban-6","Kanban board persisted to a backend","Persist moves with onValueCommit, optimistic updates, and Sonner rollback",[180],{"name":3366,"type":576,"title":3367,"description":3367,"categories":3368},"c-kbd-1","Basic keyboard keys.",[184],{"name":3370,"type":576,"title":3371,"description":3371,"categories":3372},"c-kbd-2","Keyboard keys grouped together.",[184],{"name":3374,"type":576,"title":3375,"description":3375,"categories":3376},"c-kbd-3","Keyboard keys combined with icons.",[184],{"name":3378,"type":576,"title":3379,"description":3379,"categories":3380},"c-kbd-4","Keyboard key within an input.",[184],{"name":3382,"type":576,"title":3383,"description":3383,"categories":3384},"c-kbd-5","Keyboard shortcut in a tooltip.",[184],{"name":3386,"type":576,"title":3387,"description":3387,"categories":3388},"c-kbd-6","Keyboard shortcuts reference list",[184],{"name":3390,"type":576,"title":3391,"description":3391,"categories":3392},"c-label-1","Basic label.",[188],{"name":3394,"type":576,"title":3395,"description":3395,"categories":3396},"c-label-2","Label paired with a checkbox.",[188],{"name":3398,"type":576,"title":3399,"description":3399,"categories":3400},"c-label-3","Label for a textarea field.",[188],{"name":3402,"type":576,"title":3403,"description":3403,"categories":3404},"c-label-4","Label in a disabled state.",[188],{"name":3406,"type":576,"title":3407,"description":3407,"categories":3408},"c-label-5","Label with required indicator",[188],{"name":3410,"type":576,"title":3411,"description":3411,"categories":3412},"c-label-6","Label with optional indicator",[188],{"name":3414,"type":576,"title":3415,"description":3415,"categories":3416},"c-label-7","Label with tooltip info icon",[188],{"name":3418,"type":576,"title":3419,"description":3419,"categories":3420},"c-label-8","Label with badge indicator",[188],{"name":3422,"type":576,"title":3423,"description":3423,"categories":3424},"c-label-9","Label with character counter",[188],{"name":3426,"type":576,"title":3427,"description":3427,"categories":3428},"c-label-10","Label with helper description text",[188],{"name":3430,"type":576,"title":3431,"description":3431,"categories":3432},"c-label-11","Label with error state",[188],{"name":3434,"type":576,"title":3435,"description":3435,"categories":3436},"c-label-12","Label with inline edit toggle",[188],{"name":3438,"type":576,"title":3439,"description":3439,"categories":3440},"c-label-13","Label with status indicator dot",[188],{"name":3442,"type":576,"title":3443,"description":3443,"categories":3444},"c-menubar-1","Basic menubar.",[193],{"name":3446,"type":576,"title":3447,"description":3447,"categories":3448},"c-menubar-2","Menubar with dropdown submenus.",[193],{"name":3450,"type":576,"title":3451,"description":3451,"categories":3452},"c-menubar-3","Menubar with checkbox & radio items.",[193],{"name":3454,"type":576,"title":3455,"description":3455,"categories":3456},"c-menubar-4","Menubar with icons.",[193],{"name":3458,"type":576,"title":3459,"description":3459,"categories":3460},"c-menubar-5","Menubar for formatting and media.",[193],{"name":3462,"type":576,"title":3463,"description":3463,"categories":3464},"c-native-select-1","Basic native select.",[197],{"name":3466,"type":576,"title":3467,"description":3467,"categories":3468},"c-native-select-2","Native select with options grouped.",[197],{"name":3470,"type":576,"title":3471,"description":3471,"categories":3472},"c-native-select-3","Small native select.",[197],{"name":3474,"type":576,"title":3475,"description":3475,"categories":3476},"c-native-select-4","Native select embedded within a field.",[197],{"name":3478,"type":576,"title":3479,"description":3479,"categories":3480},"c-native-select-5","Disabled native select.",[197],{"name":3482,"type":576,"title":3483,"description":3483,"categories":3484},"c-native-select-6","Invalid native select.",[197],{"name":3486,"type":576,"title":3487,"description":3487,"categories":3488},"c-navigation-menu-1","Basic navigation menu.",[201],{"name":3490,"type":576,"title":3491,"description":3491,"categories":3492},"c-navigation-menu-2","Navigation menu with grid layout.",[201],{"name":3494,"type":576,"title":3495,"description":3495,"categories":3496},"c-navigation-menu-3","Navigation menu with icons.",[201],{"name":3498,"type":576,"title":3499,"description":3499,"categories":3500},"c-navigation-menu-4","Navigation menu with grid layout and learn more button.",[201],{"name":3502,"type":576,"title":3503,"description":3503,"categories":3504},"c-number-field-1","Basic number field",[205],{"name":3506,"type":576,"title":3503,"description":3503,"categories":3507},"c-number-field-2",[205],{"name":3509,"type":576,"title":3503,"description":3503,"categories":3510},"c-number-field-3",[205],{"name":3512,"type":576,"title":3513,"description":3513,"categories":3514},"c-number-field-4","Number filed wiith buttons on right",[205],{"name":3516,"type":576,"title":3517,"description":3517,"categories":3518},"c-number-field-5","Number field with spinner buttons",[205],{"name":3520,"type":576,"title":3521,"description":3521,"categories":3522},"c-number-field-6","Number field in form",[205],{"name":3524,"type":576,"title":3525,"description":3525,"categories":3526},"c-pagination-1","Basic pagination.",[209],{"name":3528,"type":576,"title":3529,"description":3529,"categories":3530},"c-pagination-2","Pagination without labels.",[209],{"name":3532,"type":576,"title":3533,"description":3533,"categories":3534},"c-pagination-3","Pagination with hover effect.",[209],{"name":3536,"type":576,"title":3537,"description":3537,"categories":3538},"c-pagination-4","Pagination with circle buttons.",[209],{"name":3540,"type":576,"title":3541,"description":3541,"categories":3542},"c-pagination-5","Pagination with go-to-page input",[209],{"name":3544,"type":576,"title":3545,"description":3545,"categories":3546},"c-pagination-6","Numbered pagination in card",[209],{"name":3548,"type":576,"title":3549,"description":3549,"categories":3550},"c-pagination-7","Pagination with arrows buttons",[209],{"name":3552,"type":576,"title":3553,"description":3553,"categories":3554},"c-pagination-8","Pagination with page info on center",[209],{"name":3556,"type":576,"title":3557,"description":3557,"categories":3558},"c-pagination-9","Pagination with page info on left",[209],{"name":3560,"type":576,"title":3561,"description":3561,"categories":3562},"c-pagination-10","Pagination with ellipsis indicator",[209],{"name":3564,"type":576,"title":3565,"description":3565,"categories":3566},"c-pagination-11","Pagination with outline style buttons",[209],{"name":3568,"type":576,"title":3569,"description":3569,"categories":3570},"c-pagination-12","Rows per page select with range info and first\u002Fprev\u002Fnext\u002Flast icons",[209],{"name":3572,"type":576,"title":3573,"description":3573,"categories":3574},"c-pagination-13","Pagination with page select dropdown and first\u002Flast navigation",[209],{"name":3576,"type":576,"title":3577,"description":3577,"categories":3578},"c-pagination-14","Numbered pagination with go-to-page input",[209],{"name":3580,"type":576,"title":3581,"description":3581,"categories":3582},"c-pagination-15","Pagination with page info, numbered pages, ellipsis, and per-page select",[209],{"name":3584,"type":576,"title":3585,"description":3585,"categories":3586},"c-phone-input-1","Basic phone input",[213],{"name":3588,"type":576,"title":3589,"description":3589,"categories":3590},"c-phone-input-2","Small phone input",[213],{"name":3592,"type":576,"title":3593,"description":3593,"categories":3594},"c-phone-input-3","Large phone input",[213],{"name":3596,"type":576,"title":3597,"description":3597,"categories":3598},"c-phone-input-4","Disabled phone input",[213],{"name":3600,"type":576,"title":3601,"description":3601,"categories":3602},"c-phone-input-5","Phone input with preset value",[213],{"name":3604,"type":576,"title":3605,"description":3605,"categories":3606},"c-phone-input-6","Phone input with error state",[213],{"name":3608,"type":576,"title":3609,"description":3609,"categories":3610},"c-phone-input-7","Phone input with specific default country",[213],{"name":3612,"type":576,"title":3613,"description":3613,"categories":3614},"c-phone-input-8","Read-only phone input",[213],{"name":3616,"type":576,"title":3617,"description":3617,"categories":3618},"c-popover-1","Basic popover.",[217],{"name":3620,"type":576,"title":3621,"description":3621,"categories":3622},"c-popover-2","Popovers opening from different sides.",[217],{"name":3624,"type":576,"title":3625,"description":3625,"categories":3626},"c-popover-3","Popover with form.",[217],{"name":3628,"type":576,"title":3629,"description":3629,"categories":3630},"c-popover-4","Popover alignment positions.",[217],{"name":3632,"type":576,"title":3633,"description":3633,"categories":3634},"c-popover-5","Popover within a dialog.",[217],{"name":3636,"type":576,"title":3637,"description":3637,"categories":3638},"c-popover-6","Popover with user profile details.",[217],{"name":3640,"type":576,"title":3641,"description":3641,"categories":3642},"c-popover-7","Popover with custom content",[217],{"name":3644,"type":576,"title":3645,"description":3645,"categories":3646},"c-popover-8","Popover with media preview.",[217],{"name":3648,"type":576,"title":3649,"description":3649,"categories":3650},"c-popover-9","Relative time popover with timezone details",[217],{"name":3652,"type":576,"title":3653,"description":3653,"categories":3654},"c-popover-10","Popover with controls",[217],{"name":3656,"type":576,"title":3657,"description":3657,"categories":3658},"c-popover-11","Popover with navigation",[217],{"name":3660,"type":576,"title":3661,"description":3661,"categories":3662},"c-progress-1","Basic progress.",[221],{"name":3664,"type":576,"title":3665,"description":3665,"categories":3666},"c-progress-2","Small progress.",[221],{"name":3668,"type":576,"title":3669,"description":3669,"categories":3670},"c-progress-3","Large progress.",[221],{"name":3672,"type":576,"title":3673,"description":3673,"categories":3674},"c-progress-4","Progress bar with status messages.",[221],{"name":3676,"type":576,"title":3677,"description":3677,"categories":3678},"c-progress-5","File upload list with progress & status.",[221],{"name":3680,"type":576,"title":3681,"description":3681,"categories":3682},"c-progress-6","Progress bar with slider.",[221],{"name":3684,"type":576,"title":3685,"description":3685,"categories":3686},"c-progress-7","Multi-step progress indicator",[221],{"name":3688,"type":576,"title":3689,"description":3689,"categories":3690},"c-progress-8","Progress bar with custom colors.",[221],{"name":3692,"type":576,"title":3693,"description":3693,"categories":3694},"c-radio-group-1","Basic radio group",[225],{"name":3696,"type":576,"title":3697,"description":3697,"categories":3698},"c-radio-group-2","Disabled radio group",[225],{"name":3700,"type":576,"title":3701,"description":3701,"categories":3702},"c-radio-group-3","Radio with description",[225],{"name":3704,"type":576,"title":3705,"description":3705,"categories":3706},"c-radio-group-4","Invalid radio group",[225],{"name":3708,"type":576,"title":3709,"description":3709,"categories":3710},"c-radio-group-5","Colored radio group",[225],{"name":3712,"type":576,"title":3713,"description":3713,"categories":3714},"c-radio-group-6","Radio group with legend and description",[225],{"name":3716,"type":576,"title":3717,"description":3717,"categories":3718},"c-radio-group-7","Card radio group with descriptions",[225],{"name":3720,"type":576,"title":3721,"description":3721,"categories":3722},"c-radio-group-8","Radio group in card with separators",[225],{"name":3724,"type":576,"title":3725,"description":3725,"categories":3726},"c-radio-group-9","Radio group in card with icons",[225],{"name":3728,"type":576,"title":3729,"description":3729,"categories":3730},"c-radio-group-10","Radio group in frame",[225],{"name":3732,"type":576,"title":3733,"description":3733,"categories":3734},"c-radio-group-11","Radio group with grid layout",[225],{"name":3736,"type":576,"title":3737,"description":3737,"categories":3738},"c-radio-group-12","Avatar based card radio group",[225],{"name":3740,"type":576,"title":3741,"description":3741,"categories":3742},"c-radio-group-13","Payment method radio cards",[225],{"name":3744,"type":576,"title":3745,"description":3745,"categories":3746},"c-radio-group-14","Radio group with tooltip info",[225],{"name":3748,"type":576,"title":3749,"description":3749,"categories":3750},"c-radio-group-15","Radio group with badges",[225],{"name":3752,"type":576,"title":3753,"description":3753,"categories":3754},"c-radio-group-16","Inline horizontal radio group",[225],{"name":3756,"type":576,"title":3757,"description":3757,"categories":3758},"c-radio-group-17","Pricing plan radio cards",[225],{"name":3760,"type":576,"title":3761,"description":3761,"categories":3762},"c-rating-1","Basic rating.",[229],{"name":3764,"type":576,"title":3765,"description":3765,"categories":3766},"c-rating-2","Rating with decimal value.",[229],{"name":3768,"type":576,"title":3769,"description":3769,"categories":3770},"c-rating-3","Rating with show value.",[229],{"name":3772,"type":576,"title":3773,"description":3773,"categories":3774},"c-rating-4","Rating with editable.",[229],{"name":3776,"type":576,"title":3777,"description":3777,"categories":3778},"c-rating-5","Rating with size.",[229],{"name":3780,"type":576,"title":3781,"description":3781,"categories":3782},"c-rating-6","Rating with review summary",[229],{"name":3784,"type":576,"title":3785,"description":3785,"categories":3786},"c-rating-7","Interactive half-star rating",[229],{"name":3788,"type":576,"title":3789,"description":3789,"categories":3790},"c-rating-8","Emoji reaction rating",[229],{"name":3792,"type":576,"title":3793,"description":3793,"categories":3794},"c-rating-9","Rating with review text input",[229],{"name":3796,"type":576,"title":3797,"description":3797,"categories":3798},"c-resizable-1","Horizontal resizable layout",[234],{"name":3800,"type":576,"title":3801,"description":3801,"categories":3802},"c-resizable-2","Vertical resizable layout.",[234],{"name":3804,"type":576,"title":3805,"description":3805,"categories":3806},"c-resizable-3","Nested mixed-direction resizable layout.",[234],{"name":3808,"type":576,"title":3809,"description":3809,"categories":3810},"c-resizable-4","Nested resizable",[234],{"name":3812,"type":576,"title":3813,"description":3813,"categories":3814},"c-resizable-5","Handle with animated pill indicator",[234],{"name":3816,"type":576,"title":3817,"description":3817,"categories":3818},"c-resizable-6","Handle pill with spring scale on drag",[234],{"name":3820,"type":576,"title":3821,"description":3821,"categories":3822},"c-resizable-7","Handle with large capsule expansion on drag",[234],{"name":3824,"type":576,"title":3825,"description":3825,"categories":3826},"c-resizable-8","Nested layout with animated pill handles",[234],{"name":3828,"type":576,"title":3829,"description":3829,"categories":3830},"c-resizable-9","Three-panel layout with animated pill handles",[234],{"name":3832,"type":576,"title":3833,"description":3833,"categories":3834},"c-resizable-10","State-tracked resizable layout.",[234],{"name":3836,"type":576,"title":3837,"description":3837,"categories":3838},"c-scroll-area-1","Basic scroll area",[238],{"name":3840,"type":576,"title":3841,"description":3841,"categories":3842},"c-scroll-area-2","Scroll area with horizontal scrollbar",[238],{"name":3844,"type":576,"title":3845,"description":3845,"categories":3846},"c-scroll-area-3","Scroll area with both scrollbars",[238],{"name":3848,"type":576,"title":3849,"description":3849,"categories":3850},"c-scroll-area-4","Scroll area with fade effect",[238],{"name":3852,"type":576,"title":3853,"description":3853,"categories":3854},"c-scroll-area-5","Scroll area with scrollbar gutter",[238],{"name":3856,"type":576,"title":3857,"description":3857,"categories":3858},"c-scrollspy-1","Basic scrollspy",[242],{"name":3860,"type":576,"title":3837,"description":3837,"categories":3861},"c-scrollspy-2",[242],{"name":3863,"type":576,"title":3864,"description":3864,"categories":3865},"c-select-1","A basic select component with a list of options",[247],{"name":3867,"type":576,"title":3868,"description":3868,"categories":3869},"c-select-2","Select with icons and placeholder state",[247],{"name":3871,"type":576,"title":3872,"description":3872,"categories":3873},"c-select-3","Select component with grouped options and labels",[247],{"name":3875,"type":576,"title":3876,"description":3876,"categories":3877},"c-select-4","Select component with a large list of options",[247],{"name":3879,"type":576,"title":3880,"description":3880,"categories":3881},"c-select-5","Select component with small trigger size",[247],{"name":3883,"type":576,"title":3884,"description":3884,"categories":3885},"c-select-6","Select component with a subscription plan style",[247],{"name":3887,"type":576,"title":3888,"description":3888,"categories":3889},"c-select-7","Select component with item alignment disabled",[247],{"name":3891,"type":576,"title":3892,"description":3892,"categories":3893},"c-select-8","Select component within a Field with label and description",[247],{"name":3895,"type":576,"title":3896,"description":3896,"categories":3897},"c-select-9","Select component in an invalid state",[247],{"name":3899,"type":576,"title":3900,"description":3900,"categories":3901},"c-select-10","Select component in a disabled state",[247],{"name":3903,"type":576,"title":3904,"description":3904,"categories":3905},"c-select-11","Select component inside a Dialog",[247],{"name":3907,"type":576,"title":3908,"description":3908,"categories":3909},"c-select-12","Select component with single selection",[247],{"name":3911,"type":576,"title":3912,"description":3912,"categories":3913},"c-select-13","Select component inline with Input",[247],{"name":3915,"type":576,"title":3916,"description":3916,"categories":3917},"c-select-14","Select component with Button side by side",[247],{"name":3919,"type":576,"title":3920,"description":3920,"categories":3921},"c-select-15","Select component with item alignment enabled",[247],{"name":3923,"type":576,"title":3924,"description":3924,"categories":3925},"c-select-16","Select with custom access level descriptions",[247],{"name":3927,"type":576,"title":3928,"description":3928,"categories":3929},"c-select-17","Select with colored bullets for status",[247],{"name":3931,"type":576,"title":3932,"description":3932,"categories":3933},"c-select-18","Select with user avatars",[247],{"name":3935,"type":576,"title":3936,"description":3936,"categories":3937},"c-select-19","Select with status badges",[247],{"name":3939,"type":576,"title":3940,"description":3940,"categories":3941},"c-select-20","Select with indicator on the left side",[247],{"name":3943,"type":576,"title":3944,"description":3944,"categories":3945},"c-select-21","Select with clear button",[247],{"name":3947,"type":576,"title":3948,"description":3948,"categories":3949},"c-select-22","Select with custom chevrons up down icon",[247],{"name":3951,"type":576,"title":3952,"description":3952,"categories":3953},"c-select-23","Select with colored status dots",[247],{"name":3955,"type":576,"title":3956,"description":3956,"categories":3957},"c-select-24","Select with grouped options and separators",[247],{"name":3959,"type":576,"title":3960,"description":3960,"categories":3961},"c-select-25","Country picker select with flag emojis",[247],{"name":3963,"type":576,"title":3964,"description":3964,"categories":3965},"c-select-26","Status filter select with colored dots",[247],{"name":3967,"type":576,"title":3968,"description":3968,"categories":3969},"c-select-27","Select with description text per option",[247],{"name":3971,"type":576,"title":3972,"description":3972,"categories":3973},"c-select-28","Timezone select with UTC offsets",[247],{"name":3975,"type":576,"title":3976,"description":3976,"categories":3977},"c-select-29","Select with avatar items for team member assignment",[247],{"name":3979,"type":576,"title":3980,"description":3980,"categories":3981},"c-select-30","Priority select with colored badges",[247],{"name":3983,"type":576,"title":3984,"description":3984,"categories":3985},"c-select-31","Font family select with preview",[247],{"name":3987,"type":576,"title":3988,"description":3988,"categories":3989},"c-select-32","Select with icon-labeled categories",[247],{"name":3991,"type":576,"title":3992,"description":3992,"categories":3993},"c-select-33","Size variant select with small trigger",[247],{"name":3995,"type":576,"title":3996,"description":3996,"categories":3997},"c-separator-1","Horizontal separator for content sections.",[252],{"name":3999,"type":576,"title":4000,"description":4000,"categories":4001},"c-separator-2","Vertical separator for inline elements.",[252],{"name":4003,"type":576,"title":4004,"description":4004,"categories":4005},"c-separator-3","Vertical separator groups related menu items.",[252],{"name":4007,"type":576,"title":4008,"description":4008,"categories":4009},"c-separator-4","Horizontal separator between items in a list.",[252],{"name":4011,"type":576,"title":4012,"description":4012,"categories":4013},"c-separator-5","Separator with centered text label",[252],{"name":4015,"type":576,"title":4016,"description":4016,"categories":4017},"c-separator-6","Order summary with separators",[252],{"name":4019,"type":576,"title":4020,"description":4020,"categories":4021},"c-sheet-1","Sheet containing a form for editing profile information.",[256],{"name":4023,"type":576,"title":4020,"description":4020,"categories":4024},"c-sheet-2",[256],{"name":4026,"type":576,"title":4027,"description":4027,"categories":4028},"c-sheet-3","Sheets that open from any side.",[256],{"name":4030,"type":576,"title":4031,"description":4031,"categories":4032},"c-sheet-4","Sheet with scrollable content",[256],{"name":4034,"type":576,"title":4035,"description":4035,"categories":4036},"c-skeleton-1","Skeleton loader for avatars and user info.",[260],{"name":4038,"type":576,"title":4039,"description":4039,"categories":4040},"c-skeleton-2","Skeleton loader for a card component.",[260],{"name":4042,"type":576,"title":4043,"description":4043,"categories":4044},"c-skeleton-3","Skeleton loader for text and paragraphs.",[260],{"name":4046,"type":576,"title":4047,"description":4047,"categories":4048},"c-skeleton-4","Skeleton loader for a form.",[260],{"name":4050,"type":576,"title":4051,"description":4051,"categories":4052},"c-skeleton-5","Skeleton loader for a data table.",[260],{"name":4054,"type":576,"title":4055,"description":4055,"categories":4056},"c-skeleton-6","Skeleton loader for a dashboard stats row",[260],{"name":4058,"type":576,"title":4059,"description":4059,"categories":4060},"c-skeleton-7","Skeleton loader for a list with actions",[260],{"name":4062,"type":576,"title":4063,"description":4063,"categories":4064},"c-skeleton-8","Skeleton loader for a card grid",[260],{"name":4066,"type":576,"title":4067,"description":4067,"categories":4068},"c-skeleton-9","Skeleton loader for a full profile page",[260],{"name":4070,"type":576,"title":4071,"description":4071,"categories":4072},"c-skeleton-10","Skeleton loader for chat messages",[260],{"name":4074,"type":576,"title":4075,"description":4075,"categories":4076},"c-slider-1","Basic slider.",[264],{"name":4078,"type":576,"title":4079,"description":4079,"categories":4080},"c-slider-2","Disabled slider",[264],{"name":4082,"type":576,"title":4083,"description":4083,"categories":4084},"c-slider-3","Slider with multiple discrete values",[264],{"name":4086,"type":576,"title":4087,"description":4087,"categories":4088},"c-slider-4","Vertical slider with range selection",[264],{"name":4090,"type":576,"title":4091,"description":4091,"categories":4092},"c-slider-5","Slider with controlled value tracking",[264],{"name":4094,"type":576,"title":4095,"description":4095,"categories":4096},"c-slider-6","Slider with range selection",[264],{"name":4098,"type":576,"title":4099,"description":4099,"categories":4100},"c-slider-7","Slider synced with number input",[264],{"name":4102,"type":576,"title":4103,"description":4103,"categories":4104},"c-slider-8","Color temperature slider",[264],{"name":4106,"type":576,"title":4107,"description":4107,"categories":4108},"c-slider-9","Slider with reference labels",[264],{"name":4110,"type":576,"title":4111,"description":4111,"categories":4112},"c-slider-10","Slider with tick marks",[264],{"name":4114,"type":576,"title":4115,"description":4115,"categories":4116},"c-slider-11","Slider with dynamic tooltip indicator",[264],{"name":4118,"type":576,"title":4119,"description":4119,"categories":4120},"c-slider-12","Rating slider with emoji feedback",[264],{"name":4122,"type":576,"title":4123,"description":4123,"categories":4124},"c-sonner-1","Basic toast notification.",[268],{"name":4126,"type":576,"title":4127,"description":4127,"categories":4128},"c-sonner-2","Toast notification with description.",[268],{"name":4130,"type":576,"title":4131,"description":4131,"categories":4132},"c-sonner-3","Toast positions",[268],{"name":4134,"type":576,"title":4135,"description":4135,"categories":4136},"c-sonner-4","Toast variants with colored icons",[268],{"name":4138,"type":576,"title":4139,"description":4139,"categories":4140},"c-sonner-5","Toast duration options",[268],{"name":4142,"type":576,"title":4143,"description":4143,"categories":4144},"c-sonner-6","Toast with action button",[268],{"name":4146,"type":576,"title":4147,"description":4147,"categories":4148},"c-sonner-7","Promise toast with loading state",[268],{"name":4150,"type":576,"title":4151,"description":4151,"categories":4152},"c-sonner-8","Toast with custom close and cancel buttons",[268],{"name":4154,"type":576,"title":4155,"description":4155,"categories":4156},"c-sonner-9","Toast with custom rich content",[268],{"name":4158,"type":576,"title":4159,"description":4159,"categories":4160},"c-sonner-10","Toast with upload progress simulation",[268],{"name":4162,"type":576,"title":4163,"description":4163,"categories":4164},"c-sonner-11","Toast with status alert markup",[268],{"name":4166,"type":576,"title":4167,"description":4167,"categories":4168},"c-sonner-12","Custom accent border toast",[268],{"name":4170,"type":576,"title":4171,"description":4171,"categories":4172},"c-sonner-13","Custom invert success toast",[268],{"name":4174,"type":576,"title":4175,"description":4175,"categories":4176},"c-sonner-14","Custom invert error toast with details",[268],{"name":4178,"type":576,"title":4179,"description":4179,"categories":4180},"c-sonner-15","Custom invert info toast with avatar",[268],{"name":4182,"type":576,"title":4183,"description":4183,"categories":4184},"c-sonner-16","Custom invert warning toast with countdown",[268],{"name":4186,"type":576,"title":4187,"description":4187,"categories":4188},"c-sonner-17","Multi-action invert toast with avatar group",[268],{"name":4190,"type":576,"title":4191,"description":4191,"categories":4192},"c-sonner-18","Toast with close button on top-right",[268],{"name":4194,"type":576,"title":4195,"description":4195,"categories":4196},"c-sonner-19","Toast with custom icon",[268],{"name":4198,"type":576,"title":4199,"description":4199,"categories":4200},"c-sonner-20","Custom integration toast",[268],{"name":4202,"type":576,"title":4203,"description":4203,"categories":4204},"c-sonner-21","Updatable toast with ID",[268],{"name":4206,"type":576,"title":4207,"description":4207,"categories":4208},"c-sortable-1","Sortable list of items with drag-and-drop",[273],{"name":4210,"type":576,"title":4211,"description":4211,"categories":4212},"c-sortable-2","Sortable list of items with grid layout",[273],{"name":4214,"type":576,"title":4215,"description":4215,"categories":4216},"c-sortable-3","Sortable list of items with nested layout",[273],{"name":4218,"type":576,"title":4219,"description":4219,"categories":4220},"c-sortable-4","Sortable playlist with frame",[273],{"name":4222,"type":576,"title":4223,"description":4223,"categories":4224},"c-sortable-5","Sortable settings priority with frame",[273],{"name":4226,"type":576,"title":4227,"description":4227,"categories":4228},"c-sortable-6","Sortable sidebar navigation with frame",[273],{"name":4230,"type":576,"title":4231,"description":4231,"categories":4232},"c-sortable-7","Sortable image gallery grid with frame",[273],{"name":4234,"type":576,"title":4235,"description":4236,"categories":4237},"c-sortable-8","Sortable list persisted to a backend","Persist the new order with onValueCommit, optimistic updates, and Sonner rollback",[273],{"name":4239,"type":576,"title":4240,"description":4240,"categories":4241},"c-spinner-1","Basic spinner.",[277],{"name":4243,"type":576,"title":4244,"description":4244,"categories":4245},"c-spinner-2","Spinners in buttons.",[277],{"name":4247,"type":576,"title":4248,"description":4248,"categories":4249},"c-spinner-3","Spinners in badges.",[277],{"name":4251,"type":576,"title":4252,"description":4252,"categories":4253},"c-spinner-4","Spinner in input group.",[277],{"name":4255,"type":576,"title":4256,"description":4256,"categories":4257},"c-spinner-5","Spinner in empty state.",[277],{"name":4259,"type":576,"title":4260,"description":4260,"categories":4261},"c-spinner-6","Button loading states",[277],{"name":4263,"type":576,"title":4264,"description":4264,"categories":4265},"c-spinner-7","Overlay loading spinner",[277],{"name":4267,"type":576,"title":4268,"description":4268,"categories":4269},"c-spinner-8","Full page loading state",[277],{"name":4271,"type":576,"title":4272,"description":4272,"categories":4273},"c-spinner-9","Inline loading text with spinner",[277],{"name":4275,"type":576,"title":4276,"description":4276,"categories":4277},"c-spinner-10","Animated loading dots",[277],{"name":4279,"type":576,"title":4280,"description":4280,"categories":4281},"c-spinner-11","Spinner overlay on card",[277],{"name":4283,"type":576,"title":4284,"description":4284,"categories":4285},"c-spinner-12","Spinner color variants",[277],{"name":4287,"type":576,"title":4288,"description":4288,"categories":4289},"c-stepper-1","Basic stepper",[281],{"name":4291,"type":576,"title":4292,"description":4292,"categories":4293},"c-stepper-2","Stepper with completed state",[281],{"name":4295,"type":576,"title":4296,"description":4296,"categories":4297},"c-stepper-3","Stepper with loading state",[281],{"name":4299,"type":576,"title":4300,"description":4300,"categories":4301},"c-stepper-4","Controlled stepper",[281],{"name":4303,"type":576,"title":4304,"description":4304,"categories":4305},"c-stepper-5","Stepper with title and indicator",[281],{"name":4307,"type":576,"title":4308,"description":4308,"categories":4309},"c-stepper-6","Stepper with progress bar indicator",[281],{"name":4311,"type":576,"title":4312,"description":4312,"categories":4313},"c-stepper-7","Stepper with icons and badges",[281],{"name":4315,"type":576,"title":4316,"description":4316,"categories":4317},"c-stepper-8","Stepper with descriptions",[281],{"name":4319,"type":576,"title":4320,"description":4320,"categories":4321},"c-stepper-9","Stepper with inline titles",[281],{"name":4323,"type":576,"title":4324,"description":4324,"categories":4325},"c-stepper-10","Stepper with content for each step",[281],{"name":4327,"type":576,"title":4328,"description":4328,"categories":4329},"c-stepper-11","Stepper with progress bar and titles",[281],{"name":4331,"type":576,"title":4332,"description":4332,"categories":4333},"c-stepper-12","Stepper with segmented progress bar",[281],{"name":4335,"type":576,"title":4336,"description":4336,"categories":4337},"c-stepper-13","Stepper with vertical orientation and descriptions",[281],{"name":4339,"type":576,"title":4340,"description":4340,"categories":4341},"c-stepper-14","Stepper with vertical orientation",[281],{"name":4343,"type":576,"title":4344,"description":4344,"categories":4345},"c-stepper-15","Stepper with vertical orientation and titles",[281],{"name":4347,"type":576,"title":4348,"description":4348,"categories":4349},"c-switch-1","Basic switch.",[285],{"name":4351,"type":576,"title":4352,"description":4352,"categories":4353},"c-switch-2","Switch with description.",[285],{"name":4355,"type":576,"title":4356,"description":4356,"categories":4357},"c-switch-3","Disabled switch.",[285],{"name":4359,"type":576,"title":4360,"description":4360,"categories":4361},"c-switch-4","Switch in different sizes.",[285],{"name":4363,"type":576,"title":4364,"description":4364,"categories":4365},"c-switch-5","Switch group",[285],{"name":4367,"type":576,"title":4368,"description":4368,"categories":4369},"c-switch-6","Switch list in card with separators",[285],{"name":4371,"type":576,"title":4372,"description":4372,"categories":4373},"c-switch-7","Switch list in card with icons",[285],{"name":4375,"type":576,"title":4376,"description":4376,"categories":4377},"c-switch-8","Switch in frame",[285],{"name":4379,"type":576,"title":4380,"description":4380,"categories":4381},"c-switch-9","Switch with tooltip info",[285],{"name":4383,"type":576,"title":4384,"description":4384,"categories":4385},"c-switch-10","Switch with badges",[285],{"name":4387,"type":576,"title":4388,"description":4388,"categories":4389},"c-switch-11","Colored switches",[285],{"name":4391,"type":576,"title":4392,"description":4392,"categories":4393},"c-switch-12","Destructive switch with confirmation text",[285],{"name":4395,"type":576,"title":4396,"description":4396,"categories":4397},"c-switch-13","Compact settings table with switches",[285],{"name":4399,"type":576,"title":4400,"description":4400,"categories":4401},"c-switch-14","Switch with descriptions in card grid",[285],{"name":4403,"type":576,"title":4404,"description":4404,"categories":4405},"c-table-1","Basic table.",[289],{"name":4407,"type":576,"title":4408,"description":4408,"categories":4409},"c-table-2","Table with footer.",[289],{"name":4411,"type":576,"title":4412,"description":4412,"categories":4413},"c-table-3","Table in card with status badges.",[289],{"name":4415,"type":576,"title":4416,"description":4416,"categories":4417},"c-table-4","Table card with actions column.",[289],{"name":4419,"type":576,"title":4420,"description":4420,"categories":4421},"c-table-5","Table with interactive elements.",[289],{"name":4423,"type":576,"title":4424,"description":4424,"categories":4425},"c-table-6","Team members table with avatars, roles, and status",[289],{"name":4427,"type":576,"title":4428,"description":4428,"categories":4429},"c-table-7","Orders table with customer info and payment status",[289],{"name":4431,"type":576,"title":4432,"description":4432,"categories":4433},"c-table-8","Projects table with team avatars and status",[289],{"name":4435,"type":576,"title":4436,"description":4436,"categories":4437},"c-table-9","Activity log table with user avatars and timestamps",[289],{"name":4439,"type":576,"title":4440,"description":4440,"categories":4441},"c-table-10","Subscriptions table with plan badges and billing info",[289],{"name":4443,"type":576,"title":4444,"description":4444,"categories":4445},"c-table-11","Product inventory table with stock badges and prices",[289],{"name":4447,"type":576,"title":4448,"description":4448,"categories":4449},"c-table-12","API keys table with permission badges and actions",[289],{"name":4451,"type":576,"title":4452,"description":4452,"categories":4453},"c-table-13","File manager table with owners and sharing badges",[289],{"name":4455,"type":576,"title":4456,"description":4456,"categories":4457},"c-table-14","Issues table with priority, assignee, and labels",[289],{"name":4459,"type":576,"title":4460,"description":4460,"categories":4461},"c-table-15","Leaderboard table with rank, score, and level badges",[289],{"name":4463,"type":576,"title":4464,"description":4464,"categories":4465},"c-table-16","Vertical table with employee profile details",[289],{"name":4467,"type":576,"title":4468,"description":4468,"categories":4469},"c-table-17","Vertical table with server configuration details",[289],{"name":4471,"type":576,"title":4472,"description":4472,"categories":4473},"c-tabs-1","Basic tabs.",[293],{"name":4475,"type":576,"title":4476,"description":4476,"categories":4477},"c-tabs-2","Tabs with line variant.",[293],{"name":4479,"type":576,"title":4480,"description":4480,"categories":4481},"c-tabs-3","Tabs with vertical orientation.",[293],{"name":4483,"type":576,"title":4484,"description":4484,"categories":4485},"c-tabs-4","Tabs with vertical orientation and line variant.",[293],{"name":4487,"type":576,"title":4488,"description":4488,"categories":4489},"c-tabs-5","Tabs with icons.",[293],{"name":4491,"type":576,"title":4492,"description":4492,"categories":4493},"c-tabs-6","Tabs with icons",[293],{"name":4495,"type":576,"title":4496,"description":4496,"categories":4497},"c-tabs-7","Tabs with badge counts",[293],{"name":4499,"type":576,"title":4500,"description":4500,"categories":4501},"c-tabs-8","Tabs with icons and line variant",[293],{"name":4503,"type":576,"title":4504,"description":4504,"categories":4505},"c-tabs-9","Segmented control tabs",[293],{"name":4507,"type":576,"title":4508,"description":4508,"categories":4509},"c-textarea-1","Basic textarea.",[297],{"name":4511,"type":576,"title":4512,"description":4512,"categories":4513},"c-textarea-2","Invalid textarea.",[297],{"name":4515,"type":576,"title":4516,"description":4516,"categories":4517},"c-textarea-3","Textarea with label.",[297],{"name":4519,"type":576,"title":4520,"description":4520,"categories":4521},"c-textarea-4","Textarea with description.",[297],{"name":4523,"type":576,"title":4524,"description":4524,"categories":4525},"c-textarea-5","Disabled textarea.",[297],{"name":4527,"type":576,"title":4528,"description":4528,"categories":4529},"c-textarea-6","Auto-resize textarea with character count",[297],{"name":4531,"type":576,"title":4532,"description":4532,"categories":4533},"c-timeline-1","Basic timeline.",[301],{"name":4535,"type":576,"title":4536,"description":4536,"categories":4537},"c-timeline-2","Timeline with roadmap.",[301],{"name":4539,"type":576,"title":4540,"description":4540,"categories":4541},"c-timeline-3","Timeline with order status.",[301],{"name":4543,"type":576,"title":4544,"description":4544,"categories":4545},"c-timeline-4","Timeline with git activity.",[301],{"name":4547,"type":576,"title":4548,"description":4548,"categories":4549},"c-timeline-5","Timeline with milestones.",[301],{"name":4551,"type":576,"title":4552,"description":4552,"categories":4553},"c-timeline-6","Timeline with pipeline steps.",[301],{"name":4555,"type":576,"title":4556,"description":4556,"categories":4557},"c-timeline-7","Timeline with roadmap items.",[301],{"name":4559,"type":576,"title":4560,"description":4560,"categories":4561},"c-timeline-8","Vertical timeline",[301],{"name":4563,"type":576,"title":4564,"description":4564,"categories":4565},"c-timeline-9","Horizontal timeline with leading labels",[301],{"name":4567,"type":576,"title":4568,"description":4568,"categories":4569},"c-timeline-10","Deployment log timeline",[301],{"name":4571,"type":576,"title":4572,"description":4572,"categories":4573},"c-timeline-11","Activity feed timeline with user avatars",[301],{"name":4575,"type":576,"title":4576,"description":4576,"categories":4577},"c-timeline-12","Compact horizontal milestone timeline",[301],{"name":4579,"type":576,"title":4580,"description":4580,"categories":4581},"c-toggle-group-1","Basic toggle group.",[309],{"name":4583,"type":576,"title":4584,"description":4584,"categories":4585},"c-toggle-group-2","Toggle group with outline variant.",[309],{"name":4587,"type":576,"title":4588,"description":4588,"categories":4589},"c-toggle-group-3","Toggle groups in different sizes.",[309],{"name":4591,"type":576,"title":4592,"description":4592,"categories":4593},"c-toggle-group-4","Toggle group with custom spacing.",[309],{"name":4595,"type":576,"title":4596,"description":4596,"categories":4597},"c-toggle-group-5","Toggle group with filter control.",[309],{"name":4599,"type":576,"title":4600,"description":4600,"categories":4601},"c-toggle-group-6","Toggle group with vertical orientation.",[309],{"name":4603,"type":576,"title":4604,"description":4604,"categories":4605},"c-toggle-group-7","Toggle group for text alignment",[309],{"name":4607,"type":576,"title":4608,"description":4608,"categories":4609},"c-toggle-group-8","Toggle group for view mode switching",[309],{"name":4611,"type":576,"title":4612,"description":4612,"categories":4613},"c-toggle-group-9","Vertical toggle group for settings",[309],{"name":4615,"type":576,"title":4616,"description":4616,"categories":4617},"c-toggle-group-10","Toggle group for color theme",[309],{"name":4619,"type":576,"title":4620,"description":4620,"categories":4621},"c-toggle-group-11","Toggle group for font size",[309],{"name":4623,"type":576,"title":4624,"description":4624,"categories":4625},"c-toggle-group-12","Toggle group for time range filter",[309],{"name":4627,"type":576,"title":4628,"description":4628,"categories":4629},"c-toggle-group-13","Toggle group for notification channels",[309],{"name":4631,"type":576,"title":4632,"description":4632,"categories":4633},"c-toggle-group-14","Toggle group for layout columns",[309],{"name":4635,"type":576,"title":4636,"description":4636,"categories":4637},"c-toggle-group-15","Toggle group for sort direction",[309],{"name":4639,"type":576,"title":4640,"description":4640,"categories":4641},"c-toggle-group-16","Toggle group for pricing tier",[309],{"name":4643,"type":576,"title":4644,"description":4644,"categories":4645},"c-toggle-1","Basic toggle.",[305],{"name":4647,"type":576,"title":4648,"description":4648,"categories":4649},"c-toggle-2","Toggle buttons with outline variant.",[305],{"name":4651,"type":576,"title":4652,"description":4652,"categories":4653},"c-toggle-3","Toggle buttons in different sizes.",[305],{"name":4655,"type":576,"title":4656,"description":4656,"categories":4657},"c-toggle-4","Toggle with button and icon.",[305],{"name":4659,"type":576,"title":4660,"description":4660,"categories":4661},"c-toggle-5","Disabled toggle.",[305],{"name":4663,"type":576,"title":4664,"description":4664,"categories":4665},"c-toggle-6","Toggle with icon.",[305],{"name":4667,"type":576,"title":4668,"description":4668,"categories":4669},"c-toggle-7","Toggle with notification count badge",[305],{"name":4671,"type":576,"title":4672,"description":4672,"categories":4673},"c-toggle-8","Toggle size variants showcase",[305],{"name":4675,"type":576,"title":4676,"description":4676,"categories":4677},"c-toggle-9","Toggle with icon swap on press",[305],{"name":4679,"type":576,"title":4680,"description":4680,"categories":4681},"c-toggle-10","Toggle with text label that changes",[305],{"name":4683,"type":576,"title":4684,"description":4684,"categories":4685},"c-toggle-11","Social media reaction toggles",[305],{"name":4687,"type":576,"title":4688,"description":4688,"categories":4689},"c-toggle-12","Toggle with tooltip",[305],{"name":4691,"type":576,"title":4692,"description":4692,"categories":4693},"c-toggle-13","Disabled toggle states",[305],{"name":4695,"type":576,"title":4696,"description":4696,"categories":4697},"c-toggle-14","Toggle as mute\u002Funmute button",[305],{"name":4699,"type":576,"title":4700,"description":4700,"categories":4701},"c-tooltip-1","Basic tooltip.",[314],{"name":4703,"type":576,"title":4704,"description":4704,"categories":4705},"c-tooltip-2","Tooltips opening from different sides.",[314],{"name":4707,"type":576,"title":4708,"description":4708,"categories":4709},"c-tooltip-3","Tooltip with icon trigger.",[314],{"name":4711,"type":576,"title":4712,"description":4712,"categories":4713},"c-tooltip-4","Tooltip with keyboard shortcut.",[314],{"name":4715,"type":576,"title":4716,"description":4716,"categories":4717},"c-tooltip-5","Tooltip on notification bell with badge count",[314],{"name":4719,"type":576,"title":4720,"description":4720,"categories":4721},"c-tooltip-6","Tooltip with status badge",[314],{"name":4723,"type":576,"title":4724,"description":4724,"categories":4725},"c-tooltip-7","Tooltip with icon and description",[314],{"name":4727,"type":576,"title":4728,"description":4728,"categories":4729},"c-tooltip-8","Toolbar with tooltip actions",[314],{"name":4731,"type":576,"title":4732,"description":4732,"categories":4733},"c-tooltip-9","Tooltip with warning badge",[314],{"name":4735,"type":576,"title":4736,"description":4736,"categories":4737},"c-tooltip-10","Tooltip with feature badge and upgrade link",[314],{"name":4739,"type":576,"title":4740,"description":4740,"categories":4741},"c-tooltip-11","Tooltip with avatar and role badge",[314],{"name":4743,"type":576,"title":4744,"description":4744,"categories":4745},"c-tooltip-12","Tooltip on disabled button with wrapper",[314],{"name":4747,"type":576,"title":4748,"description":4748,"categories":4749},"c-tooltip-13","Tooltip with online status indicator",[314],{"name":4751,"type":576,"title":4752,"description":4752,"categories":4753},"c-tooltip-14","Tooltip with file info and badges",[314],{"name":4755,"type":576,"title":4756,"description":4756,"categories":4757},"c-tooltip-15","Tooltip with label badges",[314],{"name":4759,"type":576,"title":4760,"description":4760,"categories":4761},"c-tooltip-16","Tooltip with action button inside",[314],{"name":4763,"type":576,"title":4764,"description":4764,"categories":4765},"c-tree-1","Basic tree.",[318],{"name":4767,"type":576,"title":4768,"description":4768,"categories":4769},"c-tree-2","Tree with indented lines.",[318],{"name":4771,"type":576,"title":4772,"description":4772,"categories":4773},"c-tree-3","Tree with custom indent.",[318],{"name":4775,"type":576,"title":4772,"description":4772,"categories":4776},"c-tree-4",[318],{"name":4778,"type":576,"title":4779,"description":4779,"categories":4780},"c-tree-5","File explorer tree with type icons",[318],{"name":4782,"type":576,"title":4783,"description":4783,"categories":4784},"c-tree-6","Organization chart tree with avatars",[318],{"name":4786,"type":576,"title":4787,"description":4787,"categories":4788},"c-tree-7","Permissions tree with checkboxes",[318],{"$schema":4790,"name":123,"type":480,"title":124,"description":497,"categories":4791,"registryDependencies":4792,"dependencies":4793,"files":4797,"meta":4870},"https:\u002F\u002Fshadcn-vue.com\u002Fschema\u002Fregistry-item.json",[483],[45,152,238,542],[4794,4795,4796],"@date-fns\u002Ftz","date-fns","reka-ui",[4798,4802,4806,4810,4814,4818,4822,4826,4830,4834,4838,4842,4846,4850,4854,4858,4862,4866],{"path":4799,"type":480,"target":4800,"content":4801},"src\u002Freui\u002Fevent-calendar\u002FEventCalendar.vue","components\u002Freui\u002Fevent-calendar\u002FEventCalendar.vue","\u003Cscript setup lang=\"ts\" generic=\"TData = unknown\">\n\u002F**\n * Порт корневого ReUI `\u003CEventCalendar>` (event-calendar.tsx, MIT) —\n * провайдер движка + контейнер + announcer.\n *\n * ponytail: принимает `EventCalendarOptions` (состояние\u002Fколбэки) плюс один\n * плоский `viewConfig`-проп (частичный `EventCalendarViewConfig`, см.\n * `context.ts`) — а не полный список отдельных плоских пропов\n * (`maxEventsPerCell`, `renderEvent` и т.п. по одному), как в оригинале\n * (`splitOptions`\u002F`OPTION_KEYS`\u002F`VIEW_CONFIG_KEYS`). Добавлено, когда\n * `packages\u002Fblocks\u002Fsrc\u002Fevent-calendar\u002F` понадобился root-level оверрайд\n * `renderEvent`\u002F`renderEventTooltip`\u002F`eventTooltip`\u002F`maxEventsPerCell`\n * (composite-блоки `c-event-calendar-1\u002F4\u002F5`, которые в оригинале передают\n * эти пропы прямо на `\u003CEventCalendar>`, а не на отдельный view-компонент,\n * как единственный до того кейс `ui-event-calendar`). Не реализованы\n * `calendar`\u002F`apiRef`-пропы (adopt вынесенного инстанса) и `asChild` — оба\n * используются только вокруг составных сценариев (внешнее состояние,\n * полиморфный корень), которых пока нет ни у одного кейса\u002Fблока.\n *\n * Боевая реализация `EventCalendarGestures` (`dnd.ts`) провайдится здесь —\n * единственное место, которое знает и про движок, и про pointer-engine;\n * потребители (`EventCalendarEvent.vue` и виды) не меняются вообще, они уже\n * читали заглушку через тот же `EventCalendarGesturesContextKey`.\n *\u002F\nimport { provide, type HTMLAttributes } from \"vue\"\nimport { cn } from \"@\u002Flib\u002Futils\"\nimport {\n  createEventCalendar,\n  DEFAULT_EVENT_CALENDAR_VIEW_CONFIG,\n  EventCalendarContextKey,\n  EventCalendarGesturesContextKey,\n  EventCalendarViewConfigContextKey,\n  type EventCalendarOptions,\n  type EventCalendarViewConfig,\n} from \".\u002Fcontext\"\nimport { createEventCalendarGestures } from \".\u002Fdnd\"\n\n\u002F\u002F withDefaults(..., { fixedWeeks: undefined, ... }) is load-bearing, not\n\u002F\u002F decorative: Vue casts an ABSENT boolean-typed prop to `false` (not\n\u002F\u002F `undefined`) unless it has an explicit `default` key — silently turning\n\u002F\u002F `fixedWeeks ?? true` in resolveSettings() into `false ?? true` => `false`\n\u002F\u002F (5 grid rows instead of 6). An explicit `default: undefined` makes\n\u002F\u002F `hasDefault` true and suppresses that cast. Same trap for every other\n\u002F\u002F boolean-typed field of EventCalendarOptions (loading, showOutsideDays).\nconst props = withDefaults(\n  defineProps\u003C\n    EventCalendarOptions\u003CTData> & {\n      class?: HTMLAttributes[\"class\"]\n      viewConfig?: Partial\u003CEventCalendarViewConfig\u003CTData>>\n    }\n  >(),\n  { fixedWeeks: undefined, showOutsideDays: undefined, loading: undefined }\n)\n\nconst instance = createEventCalendar\u003CTData>(props)\nprovide(EventCalendarContextKey, instance)\nprovide(EventCalendarGesturesContextKey, createEventCalendarGestures\u003CTData>(instance))\n\u002F\u002F Plain merged object, not a `computed()`: consumers (`useEventCalendarViewConfig()`\n\u002F\u002F callers) read fields straight off the injected value (`viewConfig.classNames`,\n\u002F\u002F `viewConfig.maxEventsPerCell`, ...) with no `.value` — same v1 uncontrolled\n\u002F\u002F contract as the rest of `EventCalendarOptions` (read once at creation, see\n\u002F\u002F file header). Providing a `ComputedRef` here instead would silently break\n\u002F\u002F every existing reader the same way §33 (gantt) documents.\nprovide(\n  EventCalendarViewConfigContextKey,\n  props.viewConfig\n    ? { ...DEFAULT_EVENT_CALENDAR_VIEW_CONFIG, ...props.viewConfig }\n    : DEFAULT_EVENT_CALENDAR_VIEW_CONFIG\n)\n\ndefineExpose({ api: instance.api, state: instance.state })\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv data-slot=\"event-calendar\" :class=\"cn('flex min-h-0 min-w-0 flex-col text-xs', props.class)\">\n    \u003Cslot \u002F>\n    \u003Cdiv data-slot=\"event-calendar-announcer\" aria-live=\"polite\" class=\"sr-only\" \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",{"path":4803,"type":480,"target":4804,"content":4805},"src\u002Freui\u002Fevent-calendar\u002FEventCalendarAgendaView.vue","components\u002Freui\u002Fevent-calendar\u002FEventCalendarAgendaView.vue","\u003Cscript setup lang=\"ts\">\n\u002F**\n * Порт ReUI EventCalendarAgendaView (event-calendar-agenda-view.tsx, MIT) —\n * хронологический список по дням: заголовок дня + плоский список событий.\n *\n * ponytail: `scrollbars: \"native\"` ветка не перенесена — всегда `ScrollArea`\n * (дефолт оригинала), как и в EventCalendarTimeGrid.vue; `asChild` тоже\n * пропущен. `renderNoEvents`\u002F`renderAgendaEventDetails` (раскрывающиеся\n * детали строки) не перенесены — ни один текущий кейс не показывает пустой\n * агенду и не использует details-колбэк.\n * `IconPlaceholder` (docs\u002FPORTING.md §5) заменён инлайновым `\u003Csvg>` (путь\n * lucide \"calendar\" v0.545.0) внутри уже портированного `IconStack`.\n *\u002F\nimport { computed, provide } from \"vue\"\nimport { addDays, format } from \"date-fns\"\nimport { cn } from \"@\u002Flib\u002Futils\"\nimport { ScrollArea } from \"@\u002Fcomponents\u002Fui\u002Fscroll-area\"\nimport { IconStack } from \"@\u002Fcomponents\u002Freui\u002Ficon-stack\"\nimport {\n  EventCalendarViewContextKey,\n  useEventCalendar,\n  useEventCalendarSettings,\n  useEventCalendarViewConfig,\n} from \".\u002Fcontext\"\nimport { getDayKey, toZoned, zonedStartOfDay } from \".\u002Flib\"\nimport EventCalendarEvent from \".\u002FEventCalendarEvent.vue\"\nimport type { EventCalendarDayBucket } from \".\u002Flib\"\nimport type { EventCalendarSegment } from \".\u002Ftypes\"\n\nprovide(EventCalendarViewContextKey, { view: \"agenda\" })\n\nconst instance = useEventCalendar()\nconst settings = useEventCalendarSettings()\nconst viewConfig = useEventCalendarViewConfig()\n\nconst visibleRange = computed(() => instance.state.value.visibleRange)\n\nconst days = computed(() => {\n  const result: Date[] = []\n  let cursor = zonedStartOfDay(visibleRange.value.start, settings.timeZone)\n  while (cursor \u003C visibleRange.value.end) {\n    result.push(cursor)\n    cursor = zonedStartOfDay(addDays(toZoned(cursor, settings.timeZone), 1), settings.timeZone)\n  }\n  return result\n})\n\ninterface DayGroup {\n  day: Date\n  bucket: EventCalendarDayBucket | undefined\n  items: EventCalendarSegment[]\n}\n\nconst groups = computed\u003CDayGroup[]>(() => {\n  const index = instance.api.getIndex()\n  return days.value\n    .map((day) => ({ day, bucket: index.byDay.get(getDayKey(day, settings.timeZone)) }))\n    .filter((g) => (g.bucket?.allDay.length ?? 0) + (g.bucket?.timed.length ?? 0) > 0)\n    .map((g) => ({ ...g, items: [...(g.bucket?.allDay ?? []), ...(g.bucket?.timed ?? [])] }))\n})\n\nfunction isToday(day: Date): boolean {\n  return getDayKey(day, settings.timeZone) === getDayKey(new Date(), settings.timeZone)\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv\n    data-slot=\"event-calendar-agenda-view\"\n    data-view=\"agenda\"\n    role=\"group\"\n    :aria-label=\"settings.i18n.functions.formatDayRange(visibleRange, { locale: settings.locale })\"\n    :class=\"cn('flex min-h-0 flex-1 flex-col overflow-hidden border-t', viewConfig.classNames?.agendaView)\"\n  >\n    \u003CScrollArea class=\"h-full\">\n      \u003Cdiv v-if=\"groups.length === 0\" data-slot=\"event-calendar-no-events\" :class=\"cn('flex min-h-72 flex-col items-center justify-center gap-4 py-16', viewConfig.classNames?.noEvents)\">\n        \u003CIconStack>\n          \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"size-5\" aria-hidden=\"true\">\u003Cpath d=\"M8 2v4\" \u002F>\u003Cpath d=\"M16 2v4\" \u002F>\u003Crect width=\"18\" height=\"18\" x=\"3\" y=\"4\" rx=\"2\" \u002F>\u003Cpath d=\"M3 10h18\" \u002F>\u003C\u002Fsvg>\n        \u003C\u002FIconStack>\n        \u003Cspan class=\"text-muted-foreground text-sm\">{{ settings.i18n.labels.noEvents }}\u003C\u002Fspan>\n      \u003C\u002Fdiv>\n      \u003Cdiv v-else class=\"flex flex-col [&>*:last-child>*:last-child]:border-b-0\">\n        \u003Cdiv\n          v-for=\"group in groups\"\n          :key=\"group.day.getTime()\"\n          data-slot=\"event-calendar-agenda-day\"\n          :data-today=\"isToday(group.day) || undefined\"\n          role=\"group\"\n          :aria-label=\"`${format(toZoned(group.day, settings.timeZone), 'EEEE', { locale: settings.locale })}, ${format(toZoned(group.day, settings.timeZone), 'MMMM d, yyyy', { locale: settings.locale })}, ${settings.i18n.labels.events(group.items.length)}`\"\n        >\n          \u003Cdiv\n            data-slot=\"event-calendar-agenda-day-header\"\n            role=\"heading\"\n            aria-level=\"3\"\n            :class=\"cn('bg-muted\u002F60 sticky top-0 z-10 flex items-baseline justify-between gap-4 border-b px-4 py-2 me-2.5', viewConfig.classNames?.agendaDayHeader)\"\n          >\n            \u003Cspan :class=\"cn('text-foreground font-semibold', isToday(group.day) && 'text-primary')\">\n              {{ format(toZoned(group.day, settings.timeZone), \"EEEE\", { locale: settings.locale }) }}\n            \u003C\u002Fspan>\n            \u003Cspan class=\"text-muted-foreground font-medium tabular-nums\">\n              {{ format(toZoned(group.day, settings.timeZone), \"MMMM d, yyyy\", { locale: settings.locale }) }}\n            \u003C\u002Fspan>\n          \u003C\u002Fdiv>\n          \u003CEventCalendarEvent\n            v-for=\"segment in group.items\"\n            :key=\"segment.occurrence.key\"\n            :segment=\"segment\"\n            :class=\"cn('hover:bg-accent\u002F40 gap-3 rounded-none border-b px-4 py-2.5 transition-colors', viewConfig.classNames?.agendaItem)\"\n          \u002F>\n        \u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n    \u003C\u002FScrollArea>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",{"path":4807,"type":480,"target":4808,"content":4809},"src\u002Freui\u002Fevent-calendar\u002FEventCalendarContent.vue","components\u002Freui\u002Fevent-calendar\u002FEventCalendarContent.vue","\u003Cscript setup lang=\"ts\">\n\u002F**\n * Порт ReUI EventCalendarContent (event-calendar-content.tsx, MIT) —\n * коммутатор активного представления.\n *\n * ponytail: `DEFAULT_VIEW_COMPONENTS`\u002F`components`-проп теперь содержат все\n * шесть `CalendarView` — весь визуальный слой представлений портирован\n * (см. docs\u002FPORTING.md). Остаётся только `event-calendar-dnd.tsx`.\n *\u002F\nimport { computed, type Component, type HTMLAttributes } from \"vue\"\nimport { cn } from \"@\u002Flib\u002Futils\"\nimport { useEventCalendar, useEventCalendarViewConfig } from \".\u002Fcontext\"\nimport EventCalendarMonthView from \".\u002FEventCalendarMonthView.vue\"\nimport EventCalendarWeekView from \".\u002FEventCalendarWeekView.vue\"\nimport EventCalendarDayView from \".\u002FEventCalendarDayView.vue\"\nimport EventCalendarDaysView from \".\u002FEventCalendarDaysView.vue\"\nimport EventCalendarAgendaView from \".\u002FEventCalendarAgendaView.vue\"\nimport EventCalendarResourceView from \".\u002FEventCalendarResourceView.vue\"\nimport type { CalendarView } from \".\u002Ftypes\"\n\nconst props = defineProps\u003C{\n  class?: HTMLAttributes[\"class\"]\n  components?: Partial\u003CRecord\u003CCalendarView, Component>>\n}>()\n\nconst instance = useEventCalendar()\nconst viewConfig = useEventCalendarViewConfig()\n\nconst defaultViewComponents: Partial\u003CRecord\u003CCalendarView, Component>> = {\n  month: EventCalendarMonthView,\n  week: EventCalendarWeekView,\n  day: EventCalendarDayView,\n  days: EventCalendarDaysView,\n  agenda: EventCalendarAgendaView,\n  resource: EventCalendarResourceView,\n}\n\nconst view = computed(() => instance.state.value.view)\nconst loading = computed(() => instance.state.value.loading)\nconst activeView = computed(\n  () =>\n    props.components?.[view.value] ??\n    viewConfig.components?.[view.value] ??\n    defaultViewComponents[view.value]\n)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv\n    data-slot=\"event-calendar-content\"\n    :data-view=\"view\"\n    :data-loading=\"loading || undefined\"\n    :class=\"\n      cn(\n        'relative flex min-h-0 min-w-0 flex-1 flex-col',\n        'data-loading:pointer-events-none data-loading:opacity-60',\n        viewConfig.classNames?.content,\n        props.class\n      )\n    \"\n  >\n    \u003Cslot>\n      \u003Ccomponent :is=\"activeView\" v-if=\"activeView\" \u002F>\n    \u003C\u002Fslot>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",{"path":4811,"type":480,"target":4812,"content":4813},"src\u002Freui\u002Fevent-calendar\u002FEventCalendarDayView.vue","components\u002Freui\u002Fevent-calendar\u002FEventCalendarDayView.vue","\u003Cscript setup lang=\"ts\">\n\u002F** Тонкая обёртка над EventCalendarTimeGrid с фиксированным `view=\"day\"`, как в оригинале. *\u002F\nimport type { HTMLAttributes } from \"vue\"\nimport EventCalendarTimeGrid from \".\u002FEventCalendarTimeGrid.vue\"\n\n\u002F\u002F showAllDay: undefined в withDefaults — иначе Vue приводит отсутствующий\n\u002F\u002F boolean-проп к `false` вместо `undefined` и глушит дефолт `true` из\n\u002F\u002F EventCalendarTimeGrid.vue (та же ловушка, что задокументирована в\n\u002F\u002F docs\u002FPORTING.md §32 \u002F EventCalendar.vue).\nconst props = withDefaults(\n  defineProps\u003C{\n    class?: HTMLAttributes[\"class\"]\n    dayStartHour?: number\n    dayEndHour?: number\n    showAllDay?: boolean\n    interval?: number\n  }>(),\n  { showAllDay: undefined }\n)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CEventCalendarTimeGrid\n    view=\"day\"\n    :class=\"props.class\"\n    :day-start-hour=\"props.dayStartHour\"\n    :day-end-hour=\"props.dayEndHour\"\n    :show-all-day=\"props.showAllDay\"\n    :interval=\"props.interval\"\n  \u002F>\n\u003C\u002Ftemplate>\n",{"path":4815,"type":480,"target":4816,"content":4817},"src\u002Freui\u002Fevent-calendar\u002FEventCalendarDaysView.vue","components\u002Freui\u002Fevent-calendar\u002FEventCalendarDaysView.vue","\u003Cscript setup lang=\"ts\">\n\u002F** Тонкая обёртка над EventCalendarTimeGrid с фиксированным `view=\"days\"`, как в оригинале. *\u002F\nimport type { HTMLAttributes } from \"vue\"\nimport EventCalendarTimeGrid from \".\u002FEventCalendarTimeGrid.vue\"\n\n\u002F\u002F showAllDay: undefined в withDefaults — иначе Vue приводит отсутствующий\n\u002F\u002F boolean-проп к `false` вместо `undefined` и глушит дефолт `true` из\n\u002F\u002F EventCalendarTimeGrid.vue (та же ловушка, что задокументирована в\n\u002F\u002F docs\u002FPORTING.md §32 \u002F EventCalendar.vue).\nconst props = withDefaults(\n  defineProps\u003C{\n    class?: HTMLAttributes[\"class\"]\n    dayStartHour?: number\n    dayEndHour?: number\n    showAllDay?: boolean\n    interval?: number\n  }>(),\n  { showAllDay: undefined }\n)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CEventCalendarTimeGrid\n    view=\"days\"\n    :class=\"props.class\"\n    :day-start-hour=\"props.dayStartHour\"\n    :day-end-hour=\"props.dayEndHour\"\n    :show-all-day=\"props.showAllDay\"\n    :interval=\"props.interval\"\n  \u002F>\n\u003C\u002Ftemplate>\n",{"path":4819,"type":480,"target":4820,"content":4821},"src\u002Freui\u002Fevent-calendar\u002FEventCalendarEvent.vue","components\u002Freui\u002Fevent-calendar\u002FEventCalendarEvent.vue","\u003Cscript setup lang=\"ts\">\n\u002F**\n * Порт ReUI EventCalendarEvent (event-calendar-event.tsx, MIT) — переиспользуемый\n * чип\u002Fбар\u002Fблок события: позиционирование остаётся за вызывающим представлением\n * (month-view\u002Ftime-grid\u002Fagenda-view), этот компонент — сам интерактивный\n * элемент: выбор, клики, атрибуты доступности, --ec-event-color.\n *\n * ponytail: перенесены выбор\u002Fклики\u002Fдефолтный контент\u002Fручки ресайза (сама\n * разметка `data-slot=\"event-calendar-resize-handle\"`); ЧТО ПРОПУЩЕНО и\n * почему:\n *  - `TooltipProvider`\u002F`Tooltip` (`viewConfig.eventTooltip`) — дефолт `false`,\n *    не нужен для первого рендера; добавить как обычный reui\u002Ftooltip враппер,\n *    когда появится кейс с `eventTooltip: true`.\n *  - `useMemo` для `customContent` — в оригинале это защита от лишних\n *    ре-рендеров React при перетаскивании; Vue `computed()` даёт то же самое\n *    бесплатно (см. context.ts header, тот же приём).\n * `IconPlaceholder` (docs\u002FPORTING.md §5) заменён инлайновым `\u003Csvg>` (путь\n * lucide \"repeat\" v0.545.0), как и во всех остальных портах.\n *\u002F\nimport { computed, type HTMLAttributes, type StyleValue } from \"vue\"\nimport { Primitive, useForwardExpose } from \"reka-ui\"\nimport { addDays, format } from \"date-fns\"\nimport { cn } from \"@\u002Flib\u002Futils\"\nimport {\n  useEventCalendar,\n  useEventCalendarGestures,\n  useEventCalendarSettings,\n  useEventCalendarViewConfig,\n  useEventCalendarViewContext,\n} from \".\u002Fcontext\"\nimport {\n  spansMultipleDays,\n  toZoned,\n  zonedStartOfDay,\n} from \".\u002Flib\"\nimport type { EventCalendarSegment } from \".\u002Ftypes\"\n\nconst props = withDefaults(\n  defineProps\u003C{\n    class?: HTMLAttributes[\"class\"]\n    segment: EventCalendarSegment\n    \u002F** Static drag clone: chip rendered as-is but inert. *\u002F\n    preview?: boolean\n    asChild?: boolean\n    style?: StyleValue\n  }>(),\n  { preview: false, asChild: false }\n)\n\ndefineSlots\u003C{ default?(): unknown }>()\n\nconst { forwardRef } = useForwardExpose()\nconst instance = useEventCalendar()\nconst viewConfig = useEventCalendarViewConfig()\nconst settings = useEventCalendarSettings()\nconst { view } = useEventCalendarViewContext()\nconst gestures = useEventCalendarGestures()\n\nconst occurrence = computed(() => props.segment.occurrence)\nconst event = computed(() => occurrence.value.event)\n\nconst isSelectedRaw = computed(() =>\n  instance.state.value.selection.eventKeys.includes(occurrence.value.key)\n)\nconst isDraggingRaw = computed(\n  () => instance.state.value.drag?.occurrence.key === occurrence.value.key\n)\nconst resizeOn = computed(() => instance.state.value.interactions.resize)\n\u002F\u002F A preview clone must never inherit the source's selected\u002Fdragging state.\nconst isSelected = computed(() => (props.preview ? false : isSelectedRaw.value))\nconst isDragging = computed(() => (props.preview ? false : isDraggingRaw.value))\n\nconst isBar = computed(\n  () => occurrence.value.allDay || spansMultipleDays(occurrence.value, settings.timeZone)\n)\nconst inTimeGrid = computed(\n  () => view === \"week\" || view === \"day\" || view === \"days\" || view === \"resource\"\n)\nconst interactive = computed(() => view !== \"agenda\" && !props.preview)\nconst timedBlock = computed(() => inTimeGrid.value && !isBar.value)\nconst horizontalBar = computed(() => isBar.value && !inTimeGrid.value)\nconst stackedBlock = computed(\n  () =>\n    timedBlock.value &&\n    (props.segment.endMin ?? 0) - (props.segment.startMin ?? 0) >=\n      viewConfig.compactEventMinutes\n)\n\nconst FADE_TRUNCATE =\n  \"w-full truncate @max-[10rem]:text-clip @max-[10rem]:[mask-image:linear-gradient(to_right,#000_calc(100%-0.75rem),transparent)] @max-[10rem]:rtl:[mask-image:linear-gradient(to_left,#000_calc(100%-0.75rem),transparent)]\"\n\nconst startTimeLabel = computed(() =>\n  format(\n    toZoned(occurrence.value.start, settings.timeZone),\n    settings.i18n.formats.eventTime,\n    { locale: settings.locale }\n  )\n)\nconst rangeTimeLabel = computed(() =>\n  settings.i18n.functions.formatEventTime(\n    toZoned(occurrence.value.start, settings.timeZone),\n    toZoned(occurrence.value.end, settings.timeZone),\n    occurrence.value.allDay,\n    { locale: settings.locale }\n  )\n)\n\n\u002F\u002F Agenda time text is per-day for multi-day events (see original comment).\nconst agendaTimeText = computed(() => {\n  if (view !== \"agenda\") return \"\"\n  if (occurrence.value.allDay) return settings.i18n.labels.allDay\n  const dayStart = zonedStartOfDay(props.segment.day, settings.timeZone)\n  const dayEnd = addDays(toZoned(dayStart, settings.timeZone), 1)\n  const startsBefore = occurrence.value.start \u003C dayStart\n  const endsAfter = occurrence.value.end > dayEnd\n  if (startsBefore && endsAfter) return settings.i18n.labels.allDay\n  if (endsAfter) return settings.i18n.labels.timeFrom(startTimeLabel.value)\n  if (startsBefore) {\n    return settings.i18n.labels.timeUntil(\n      format(\n        toZoned(occurrence.value.end, settings.timeZone),\n        settings.i18n.formats.eventTime,\n        { locale: settings.locale }\n      )\n    )\n  }\n  return rangeTimeLabel.value\n})\n\nconst timeLabel = rangeTimeLabel\nconst label = computed(() =>\n  settings.i18n.functions.formatEventLabel\n    ? settings.i18n.functions.formatEventLabel(event.value.title, timeLabel.value)\n    : `${event.value.title}, ${timeLabel.value}`\n)\n\nconst showResize = computed(\n  () =>\n    interactive.value &&\n    resizeOn.value &&\n    !event.value.readOnly &&\n    event.value.resizable !== false\n)\n\nconst chipStyle = computed(() => ({\n  \"--ec-event-color\": event.value.color ?? \"var(--color-primary)\",\n  ...(props.style as Record\u003Cstring, string> | undefined),\n}))\n\nconst ariaLabel = computed(\n  () =>\n    settings.i18n.functions.formatEventAriaLabel?.(\n      event.value.title,\n      timeLabel.value,\n      props.segment.continuesBefore || props.segment.continuesAfter\n    ) ??\n    `${event.value.title}, ${timeLabel.value}${\n      props.segment.continuesBefore || props.segment.continuesAfter\n        ? `, ${settings.i18n.labels.continues}`\n        : \"\"\n    }`\n)\n\nfunction onPointerDown(e: PointerEvent) {\n  e.stopPropagation()\n  gestures.markChipPress()\n  if (interactive.value) gestures.beginMove(e, props.segment)\n}\n\nfunction onClick(e: MouseEvent) {\n  e.stopPropagation()\n  if (gestures.wasRecentDrag()) return\n  settings.onEventClick?.(occurrence.value, e)\n  if (e.defaultPrevented || view === \"agenda\") return\n  instance.api.selectEvent(occurrence.value.key)\n}\n\nfunction onDoubleClick(e: MouseEvent) {\n  e.stopPropagation()\n  settings.onEventDoubleClick?.(occurrence.value, e)\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CPrimitive\n    :ref=\"forwardRef\"\n    as=\"button\"\n    :as-child=\"asChild\"\n    type=\"button\"\n    data-slot=\"event-calendar-event\"\n    :data-view=\"view\"\n    :data-all-day=\"occurrence.allDay || undefined\"\n    :data-recurring=\"occurrence.isRecurring || undefined\"\n    :data-selected=\"isSelected || undefined\"\n    :data-dragging=\"isDragging || undefined\"\n    :data-preview=\"preview || undefined\"\n    :data-past=\"occurrence.end.getTime() \u003C Date.now() || undefined\"\n    :title=\"preview ? undefined : label\"\n    :aria-label=\"ariaLabel\"\n    :aria-pressed=\"interactive ? isSelected : undefined\"\n    :aria-hidden=\"preview || undefined\"\n    :tabindex=\"preview ? -1 : undefined\"\n    :style=\"chipStyle\"\n    :class=\"\n      cn(\n        'group\u002Fec-event text-foreground relative flex w-full min-w-0 cursor-pointer touch-none items-center overflow-hidden text-start select-none',\n        'focus-visible:ring-ring\u002F50 outline-none focus-visible:ring-2',\n        preview && 'pointer-events-none',\n        view === 'agenda'\n          ? 'gap-3 rounded-md text-sm'\n          : cn(\n              '@container gap-1.5 rounded-sm px-1.5 py-1 leading-normal',\n              'bg-(--ec-event-color)\u002F15 hover:bg-(--ec-event-color)\u002F25',\n              'dark:bg-(--ec-event-color)\u002F20 dark:hover:bg-(--ec-event-color)\u002F30',\n              'inset-ring inset-ring-(--ec-event-color)\u002F15',\n              'transition-[background-color,box-shadow] duration-150',\n              'data-dragging:opacity-40',\n              'data-selected:bg-(--ec-event-color)\u002F30 data-selected:inset-ring-(--ec-event-color)\u002F40',\n              segment.continuesBefore && 'rounded-s-none',\n              segment.continuesAfter && 'rounded-e-none'\n            ),\n        viewConfig.classNames?.event,\n        props.class\n      )\n    \"\n    @pointerdown=\"onPointerDown\"\n    @click=\"onClick\"\n    @dblclick=\"onDoubleClick\"\n  >\n    \u003Cslot>\n      \u003Ctemplate v-if=\"view === 'agenda'\">\n        \u003Cspan class=\"text-muted-foreground w-40 shrink-0 truncate tabular-nums\">{{ agendaTimeText }}\u003C\u002Fspan>\n        \u003Cspan aria-hidden data-slot=\"event-calendar-agenda-dot\" class=\"size-2 shrink-0 rounded-full bg-(--ec-event-color)\" \u002F>\n        \u003Cspan class=\"truncate text-sm\">{{ event.title }}\u003C\u002Fspan>\n        \u003Csvg v-if=\"occurrence.isRecurring\" xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"text-muted-foreground size-2.5 shrink-0\" aria-hidden=\"true\">\u003Cpath d=\"m17 2 4 4-4 4\" \u002F>\u003Cpath d=\"M3 11v-1a4 4 0 0 1 4-4h14\" \u002F>\u003Cpath d=\"m7 22-4-4 4-4\" \u002F>\u003Cpath d=\"M21 13v1a4 4 0 0 1-4 4H3\" \u002F>\u003C\u002Fsvg>\n      \u003C\u002Ftemplate>\n      \u003Ctemplate v-else>\n        \u003Cspan v-if=\"!timedBlock\" aria-hidden data-slot=\"event-calendar-event-dot\" class=\"-me-0.5 size-1.5 shrink-0 rounded-full bg-(--ec-event-color)\" \u002F>\n        \u003Csvg v-if=\"occurrence.isRecurring\" xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"size-2.5 shrink-0 opacity-70\" aria-hidden=\"true\">\u003Cpath d=\"m17 2 4 4-4 4\" \u002F>\u003Cpath d=\"M3 11v-1a4 4 0 0 1 4-4h14\" \u002F>\u003Cpath d=\"m7 22-4-4 4-4\" \u002F>\u003Cpath d=\"M21 13v1a4 4 0 0 1-4 4H3\" \u002F>\u003C\u002Fsvg>\n        \u003Cspan :class=\"cn('font-medium', stackedBlock ? FADE_TRUNCATE : 'truncate')\">{{ event.title }}\u003C\u002Fspan>\n        \u003Ctemplate v-if=\"!occurrence.allDay && segment.isStart\">\n          \u003Cspan v-if=\"view === 'month'\" class=\"text-muted-foreground shrink-0\">{{ startTimeLabel }}\u003C\u002Fspan>\n          \u003Cspan v-else :class=\"cn('text-muted-foreground hidden @[8rem]:inline', stackedBlock ? FADE_TRUNCATE : 'truncate')\">{{ rangeTimeLabel }}\u003C\u002Fspan>\n        \u003C\u002Ftemplate>\n      \u003C\u002Ftemplate>\n    \u003C\u002Fslot>\n    \u003Ctemplate v-if=\"showResize\">\n      \u003Cspan\n        v-if=\"timedBlock && segment.isStart\"\n        data-slot=\"event-calendar-resize-handle\"\n        data-edge=\"start\"\n        :class=\"cn('absolute inset-x-1 top-0 flex h-1.5 cursor-ns-resize items-center justify-center opacity-0 transition-opacity duration-150 group-hover\u002Fec-event:opacity-100', viewConfig.classNames?.resizeHandle)\"\n        @pointerdown=\"(e: PointerEvent) => gestures.beginResize(e, segment, 'start')\"\n      >\n        \u003Cspan aria-hidden data-slot=\"event-calendar-resize-grip\" :class=\"cn('bg-foreground\u002F40 rounded-full', timedBlock ? 'h-0.5 w-2.5' : 'h-2.5 w-0.5', viewConfig.classNames?.resizeGrip)\" \u002F>\n      \u003C\u002Fspan>\n      \u003Cspan\n        v-if=\"timedBlock && segment.isEnd\"\n        data-slot=\"event-calendar-resize-handle\"\n        data-edge=\"end\"\n        :class=\"cn('absolute inset-x-1 bottom-0 flex h-1.5 cursor-ns-resize items-center justify-center opacity-0 transition-opacity duration-150 group-hover\u002Fec-event:opacity-100', viewConfig.classNames?.resizeHandle)\"\n        @pointerdown=\"(e: PointerEvent) => gestures.beginResize(e, segment, 'end')\"\n      >\n        \u003Cspan aria-hidden data-slot=\"event-calendar-resize-grip\" :class=\"cn('bg-foreground\u002F40 rounded-full', timedBlock ? 'h-0.5 w-2.5' : 'h-2.5 w-0.5', viewConfig.classNames?.resizeGrip)\" \u002F>\n      \u003C\u002Fspan>\n      \u003Cspan\n        v-if=\"(horizontalBar || (isBar && inTimeGrid)) && segment.isStart\"\n        data-slot=\"event-calendar-resize-handle\"\n        data-edge=\"start\"\n        :class=\"cn('absolute inset-y-0 start-0 flex w-2 cursor-ew-resize items-center justify-center opacity-0 transition-opacity duration-150 group-hover\u002Fec-event:opacity-100', viewConfig.classNames?.resizeHandle)\"\n        @pointerdown=\"(e: PointerEvent) => gestures.beginResize(e, segment, 'start')\"\n      >\n        \u003Cspan aria-hidden data-slot=\"event-calendar-resize-grip\" :class=\"cn('bg-foreground\u002F40 rounded-full', timedBlock ? 'h-0.5 w-2.5' : 'h-2.5 w-0.5', viewConfig.classNames?.resizeGrip)\" \u002F>\n      \u003C\u002Fspan>\n      \u003Cspan\n        v-if=\"(horizontalBar || (isBar && inTimeGrid)) && segment.isEnd\"\n        data-slot=\"event-calendar-resize-handle\"\n        data-edge=\"end\"\n        :class=\"cn('absolute inset-y-0 end-0 flex w-2 cursor-ew-resize items-center justify-center opacity-0 transition-opacity duration-150 group-hover\u002Fec-event:opacity-100', viewConfig.classNames?.resizeHandle)\"\n        @pointerdown=\"(e: PointerEvent) => gestures.beginResize(e, segment, 'end')\"\n      >\n        \u003Cspan aria-hidden data-slot=\"event-calendar-resize-grip\" :class=\"cn('bg-foreground\u002F40 rounded-full', timedBlock ? 'h-0.5 w-2.5' : 'h-2.5 w-0.5', viewConfig.classNames?.resizeGrip)\" \u002F>\n      \u003C\u002Fspan>\n    \u003C\u002Ftemplate>\n  \u003C\u002FPrimitive>\n\u003C\u002Ftemplate>\n",{"path":4823,"type":480,"target":4824,"content":4825},"src\u002Freui\u002Fevent-calendar\u002FEventCalendarMonthView.vue","components\u002Freui\u002Fevent-calendar\u002FEventCalendarMonthView.vue","\u003Cscript setup lang=\"ts\">\n\u002F**\n * Порт ReUI EventCalendarMonthView (event-calendar-month-view.tsx, MIT).\n * Первое представление — минимальное ядро для запуска визуального гейта.\n *\n * ponytail — сознательно НЕ перенесено в этом проходе (добавить по мере\n * появления кейсов, которые это используют):\n *  - drag\u002Fresize ghosts, inline drop placeholder, `data-drop-target` —\n *    зависят от `event-calendar-dnd.tsx`, которого ещё нет (план: последним).\n *  - \"auto\" measuring `maxEventsPerCell` через ResizeObserver — используется\n *    фиксированный fallback (3), как в оригинале при отсутствии измерения.\n *  - \"+N more\" — статичный неинтерактивный индикатор (`\u003Cspan>`), а не Popover\n *    со списком скрытых событий (оригинал: `Popover`\u002F`PopoverContent`).\n *  - week-number gutter, off-days marking, `showDayAddButton`, `renderMonthCell`\n *    и прочие render-пропы, `asChild`, фокус-реставрация после ре-ключевания\n *    чипа (`restoreChipFocus`, актуально только вместе с dnd).\n *  - `useEventCalendarViewSettings` (слияние view-level пропов с\n *    `state.viewSettings`) — weekends\u002FweekNumbers\u002FnowIndicator\u002FoffDays\n *    читаются прямо из `state.viewSettings` (root-level), без per-view\n *    プроп-оверрайдов (эта view не принимает `weekends`\u002F`weekNumbers` пропы).\n *\n * Раскладка бар-оверлея (colStart\u002FcolSpan\u002Flane) и упаковка НЕ пересчитываются\n * здесь — переиспользуются уже упакованные `index.weekRows[].bars` из lib.ts\n * (`packWeekRowLanes`), тот же источник, что и `useEventCalendarWeek` в\n * оригинале.\n *\u002F\nimport { computed, provide, type HTMLAttributes } from \"vue\"\nimport { addDays, format } from \"date-fns\"\nimport { cn } from \"@\u002Flib\u002Futils\"\nimport {\n  EventCalendarViewContextKey,\n  useEventCalendar,\n  useEventCalendarSettings,\n  useEventCalendarViewConfig,\n} from \".\u002Fcontext\"\nimport { getDayKey, toZoned, zonedStartOfDay } from \".\u002Flib\"\nimport EventCalendarEvent from \".\u002FEventCalendarEvent.vue\"\nimport type { EventCalendarDayBucket } from \".\u002Flib\"\nimport type { EventCalendarSegment } from \".\u002Ftypes\"\n\nconst props = defineProps\u003C{\n  class?: HTMLAttributes[\"class\"]\n  maxEventsPerCell?: number | \"auto\"\n}>()\n\nprovide(EventCalendarViewContextKey, { view: \"month\" })\n\nconst instance = useEventCalendar()\nconst settings = useEventCalendarSettings()\nconst viewConfig = useEventCalendarViewConfig()\n\nconst visibleRange = computed(() => instance.state.value.visibleRange)\nconst anchorDate = computed(() => instance.state.value.date)\nconst weekendsOn = computed(() => instance.state.value.viewSettings.weekends ?? true)\n\nconst weeks = computed(() => {\n  const days: Date[] = []\n  let cursor = zonedStartOfDay(visibleRange.value.start, settings.timeZone)\n  while (cursor \u003C visibleRange.value.end) {\n    days.push(cursor)\n    cursor = zonedStartOfDay(addDays(toZoned(cursor, settings.timeZone), 1), settings.timeZone)\n  }\n  const rows: Date[][] = []\n  for (let i = 0; i \u003C days.length; i += 7) rows.push(days.slice(i, i + 7))\n  if (weekendsOn.value) return rows\n  return rows.map((row) =>\n    row.filter((day) => !settings.weekendDays.includes(toZoned(day, settings.timeZone).getDay()))\n  )\n})\n\nconst headerDays = computed(() => weeks.value[0] ?? [])\nconst title = computed(() =>\n  settings.i18n.functions.formatTitle(\"month\", {\n    date: toZoned(anchorDate.value, settings.timeZone),\n    activeRange: instance.api.getActiveRange(),\n    visibleRange: visibleRange.value,\n    locale: settings.locale,\n  })\n)\nconst gridTemplateColumns = computed(\n  () => `repeat(${headerDays.value.length}, minmax(0, 1fr))`\n)\nconst cap = computed(() => {\n  const configured = props.maxEventsPerCell ?? viewConfig.maxEventsPerCell\n  return configured === \"auto\" ? 3 : configured\n})\n\nfunction weekRowFor(weekStart: Date) {\n  const startMs = zonedStartOfDay(weekStart, settings.timeZone).getTime()\n  return instance.api\n    .getIndex()\n    .weekRows.find(\n      (r) => zonedStartOfDay(r.rowStart, settings.timeZone).getTime() === startMs\n    )\n}\n\nfunction dayBucket(day: Date): EventCalendarDayBucket {\n  return (\n    instance.api.getIndex().byDay.get(getDayKey(day, settings.timeZone)) ?? {\n      allDay: [],\n      timed: [],\n    }\n  )\n}\n\nfunction isToday(day: Date): boolean {\n  return getDayKey(new Date(), settings.timeZone) === getDayKey(day, settings.timeZone)\n}\n\nfunction isOutside(day: Date): boolean {\n  const dayStart = zonedStartOfDay(day, settings.timeZone)\n  const active = instance.state.value.activeRange\n  return dayStart \u003C active.start || dayStart >= active.end\n}\n\ninterface WeekLayout {\n  week: Date[]\n  offsets: number[]\n  visibleBars: EventCalendarSegment[]\n  gridPos: (colStart: number, colSpan: number) => { col: number; span: number } | null\n  reservedLanes: (col: number) => number\n  hiddenBarKeys: (col: number) => Set\u003Cstring>\n}\n\nfunction layoutWeek(week: Date[]): WeekLayout {\n  const rowStart = weekRowFor(week[0]!)?.rowStart ?? week[0]!\n  const bars = weekRowFor(week[0]!)?.bars ?? []\n  const rowStartMs = zonedStartOfDay(rowStart, settings.timeZone).getTime()\n  const dayMs = 86400000\n  const offsets = week.map((d) =>\n    Math.round((zonedStartOfDay(d, settings.timeZone).getTime() - rowStartMs) \u002F dayMs)\n  )\n  const gridPos = (colStart: number, colSpan: number) => {\n    let start = -1\n    let end = -1\n    for (let o = colStart; o \u003C colStart + colSpan; o++) {\n      const col = offsets.indexOf(o)\n      if (col === -1) continue\n      if (start === -1) start = col\n      end = col\n    }\n    return start === -1 ? null : { col: start, span: end - start + 1 }\n  }\n  const visibleBars = bars.filter((b) => (b.lane ?? 0) \u003C cap.value)\n  const covers = (b: EventCalendarSegment, dayOffset: number) =>\n    (b.colStart ?? 0) \u003C= dayOffset && dayOffset \u003C (b.colStart ?? 0) + (b.colSpan ?? 1)\n  return {\n    week,\n    offsets,\n    visibleBars,\n    gridPos,\n    reservedLanes: (col) =>\n      visibleBars.reduce(\n        (max, b) => (covers(b, offsets[col]!) ? Math.max(max, (b.lane ?? 0) + 1) : max),\n        0\n      ),\n    hiddenBarKeys: (col) =>\n      new Set(\n        bars\n          .filter((b) => (b.lane ?? 0) >= cap.value && covers(b, offsets[col]!))\n          .map((b) => b.occurrence.key)\n      ),\n  }\n}\n\ninterface CellView {\n  bucket: EventCalendarDayBucket\n  visibleTimed: EventCalendarSegment[]\n  overflowCount: number\n}\n\nfunction cellView(day: Date, layout: WeekLayout, col: number): CellView {\n  const bucket = dayBucket(day)\n  const hiddenBarKeys = layout.hiddenBarKeys(col)\n  const reservedLanes = layout.reservedLanes(col)\n  const timedSlots = Math.max(0, cap.value - reservedLanes)\n  const visibleTimed = bucket.timed.slice(0, timedSlots)\n  const overflowCount = hiddenBarKeys.size + Math.max(0, bucket.timed.length - timedSlots)\n  return { bucket, visibleTimed, overflowCount }\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv\n    data-slot=\"event-calendar-month-view\"\n    data-view=\"month\"\n    role=\"grid\"\n    :aria-label=\"title\"\n    :class=\"cn('flex min-h-0 flex-1 flex-col overflow-hidden border-t', viewConfig.classNames?.monthView, props.class)\"\n  >\n    \u003Cdiv\n      role=\"row\"\n      data-slot=\"event-calendar-month-header\"\n      :class=\"cn('@container grid border-b', viewConfig.classNames?.monthHeader)\"\n      :style=\"{ gridTemplateColumns }\"\n    >\n      \u003Cdiv\n        v-for=\"day in headerDays\"\n        :key=\"day.getTime()\"\n        role=\"columnheader\"\n        :class=\"cn('text-muted-foreground truncate px-2 py-1.5 font-medium', viewConfig.classNames?.monthDayHeader)\"\n      >\n        \u003Cspan class=\"@max-[36rem]:hidden\">{{ format(toZoned(day, settings.timeZone), settings.i18n.formats.monthDayHeader, { locale: settings.locale }) }}\u003C\u002Fspan>\n        \u003Cspan class=\"hidden @max-[36rem]:inline\">{{ format(toZoned(day, settings.timeZone), settings.i18n.formats.monthDayHeaderNarrow, { locale: settings.locale }) }}\u003C\u002Fspan>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n    \u003Cdiv\n      data-slot=\"event-calendar-month-body\"\n      :class=\"cn('grid min-h-0 flex-1', viewConfig.classNames?.monthBody)\"\n      :style=\"{ gridTemplateRows: `repeat(${weeks.length}, minmax(0, 1fr))` }\"\n    >\n      \u003Cdiv\n        v-for=\"(week, rowIndex) in weeks\"\n        :key=\"rowIndex\"\n        role=\"row\"\n        data-slot=\"event-calendar-month-row\"\n        :class=\"cn('relative grid min-h-0 border-b last:border-b-0', viewConfig.classNames?.monthRow)\"\n        :style=\"{ gridTemplateColumns }\"\n      >\n        \u003Ctemplate v-for=\"(day, col) in week\" :key=\"day.getTime()\">\n          \u003Cdiv\n            role=\"gridcell\"\n            data-slot=\"event-calendar-month-cell\"\n            :data-today=\"isToday(day) || undefined\"\n            :data-outside=\"isOutside(day) || undefined\"\n            :data-weekend=\"settings.weekendDays.includes(toZoned(day, settings.timeZone).getDay()) || undefined\"\n            :data-ec-day=\"zonedStartOfDay(day, settings.timeZone).getTime()\"\n            :aria-label=\"format(toZoned(day, settings.timeZone), settings.i18n.formats.monthCellAriaLabel, { locale: settings.locale })\"\n            :class=\"\n              cn(\n                'group\u002Fec-cell relative flex min-h-0 min-w-0 flex-col overflow-hidden',\n                col !== week.length - 1 && 'border-e',\n                isOutside(day) && !settings.showOutsideDays && 'invisible',\n                isToday(day) && cn('bg-primary\u002F3 border-b-primary\u002F40 relative border-b-2', viewConfig.todayClassName),\n                viewConfig.classNames?.monthCell\n              )\n            \"\n            @click=\"settings.onSlotClick?.({ date: day, allDay: true, view: 'month' }, $event)\"\n          >\n            \u003Cdiv :class=\"cn('flex min-h-0 flex-1 flex-col gap-0.5 overflow-hidden px-1 pt-1.5', viewConfig.classNames?.monthCellContent)\">\n              \u003Cdiv\n                v-if=\"layoutWeek(week).reservedLanes(col) > 0\"\n                aria-hidden\n                class=\"shrink-0\"\n                :style=\"{ height: `calc(${layoutWeek(week).reservedLanes(col)} * var(--ec-month-bar-h, 1.75rem) - 0.125rem)` }\"\n              \u002F>\n              \u003CEventCalendarEvent\n                v-for=\"segment in cellView(day, layoutWeek(week), col).visibleTimed\"\n                :key=\"segment.occurrence.key\"\n                :segment=\"segment\"\n                class=\"shrink-0\"\n              \u002F>\n              \u003Cspan\n                v-if=\"cellView(day, layoutWeek(week), col).overflowCount > 0\"\n                data-slot=\"event-calendar-more\"\n                :class=\"cn('text-muted-foreground shrink-0 truncate px-1 text-xs font-medium', viewConfig.classNames?.moreIndicator)\"\n              >\n                {{ settings.i18n.labels.more(cellView(day, layoutWeek(week), col).overflowCount) }}\n              \u003C\u002Fspan>\n            \u003C\u002Fdiv>\n            \u003Cdiv :class=\"cn('flex items-center justify-end gap-1 px-2 pb-1.5', viewConfig.classNames?.monthCellFooter)\">\n              \u003Cspan\n                data-slot=\"event-calendar-month-day-number\"\n                :class=\"\n                  cn(\n                    'flex size-5 items-center justify-center rounded-full',\n                    isOutside(day) && 'text-muted-foreground',\n                    isToday(day) && 'bg-primary text-primary-foreground font-light',\n                    viewConfig.classNames?.monthDayNumber\n                  )\n                \"\n              >\n                {{ format(toZoned(day, settings.timeZone), settings.i18n.formats.monthCellDay, { locale: settings.locale }) }}\n              \u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fdiv>\n        \u003C\u002Ftemplate>\n        \u003Cdiv\n          v-if=\"layoutWeek(week).visibleBars.length > 0\"\n          data-slot=\"event-calendar-month-bar-overlay\"\n          class=\"pointer-events-none absolute inset-x-0 top-0 z-10 grid pt-1.5\"\n          :style=\"{ gridTemplateColumns, gridAutoRows: 'var(--ec-month-bar-h, 1.75rem)' }\"\n        >\n          \u003Ctemplate v-for=\"bar in layoutWeek(week).visibleBars\" :key=\"bar.occurrence.key\">\n            \u003Cdiv\n              v-if=\"layoutWeek(week).gridPos(bar.colStart ?? 0, bar.colSpan ?? 1)\"\n              :class=\"cn('pointer-events-auto min-w-0 px-1', viewConfig.classNames?.monthBar)\"\n              :style=\"{\n                gridColumn: `${(layoutWeek(week).gridPos(bar.colStart ?? 0, bar.colSpan ?? 1)!.col) + 1} \u002F span ${layoutWeek(week).gridPos(bar.colStart ?? 0, bar.colSpan ?? 1)!.span}`,\n                gridRow: (bar.lane ?? 0) + 1,\n              }\"\n            >\n              \u003CEventCalendarEvent :segment=\"bar\" class=\"h-[calc(var(--ec-month-bar-h,1.75rem)-0.125rem)]\" \u002F>\n            \u003C\u002Fdiv>\n          \u003C\u002Ftemplate>\n        \u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",{"path":4827,"type":480,"target":4828,"content":4829},"src\u002Freui\u002Fevent-calendar\u002FEventCalendarNav.vue","components\u002Freui\u002Fevent-calendar\u002FEventCalendarNav.vue","\u003Cscript setup lang=\"ts\">\n\u002F**\n * Порт ReUI EventCalendarNav (event-calendar-nav.tsx, MIT) — Today\u002Fprev\u002Fnext\u002F\n * заголовок периода. Композиция составлена по образцу `EventCalendarNav`\n * оригинала (Today, prev\u002Fnext, заголовок, growing spacer).\n *\n * ponytail — НЕ портировано в этом проходе (ни одного текущего кейса не\n * блокирует, ни один не переключает вид):\n *  - `EventCalendarViewSwitcher` (DropdownMenu со списком видов) и\n *    `EventCalendarDatePicker` (Popover+Calendar) — обе плавающие поверхности,\n *    требуют reui\u002Fdropdown-menu и ui\u002Fcalendar интеграции сверху уже большого\n *    файла; добавить, когда появится кейс с несколькими видами\u002Fдатапикером.\n *  - `EventCalendarToolbar` — тонкая обёртка-層 (`flex items-center gap-2`),\n *    добавить вместе с view switcher, когда понадобится слот тулбара.\n *  - Tooltip на каждой кнопке (`NavTooltip`\u002F`viewConfig.navTooltips`) — не\n *    влияет на закрытый статичный рендер (TooltipTrigger asChild ничего не\n *    добавляет в DOM), пропущен ради объёма; добавить как обычный\n *    reui\u002Ftooltip враппер.\n *  - `asChild` на кнопках\u002Fзаголовке\u002Ftoolbar.\n * `IconPlaceholder` (docs\u002FPORTING.md §5) заменён инлайновым `\u003Csvg>` (пути\n * lucide \"chevron-left\"\u002F\"chevron-right\" v0.545.0), тем же приёмом, что и\n * везде в порте.\n *\u002F\nimport { computed, type HTMLAttributes } from \"vue\"\nimport { cn } from \"@\u002Flib\u002Futils\"\nimport { Button } from \"@\u002Fcomponents\u002Fui\u002Fbutton\"\nimport { useEventCalendar, useEventCalendarSettings, useEventCalendarViewConfig } from \".\u002Fcontext\"\nimport { toZoned } from \".\u002Flib\"\n\nconst props = defineProps\u003C{ class?: HTMLAttributes[\"class\"] }>()\n\nconst instance = useEventCalendar()\nconst settings = useEventCalendarSettings()\nconst viewConfig = useEventCalendarViewConfig()\n\nconst navVariant = computed(() => viewConfig.navButtonVariant)\nconst navSize = computed(() => viewConfig.navButtonSize)\nconst navIconSize = computed(() => (viewConfig.navButtonSize === \"sm\" ? \"icon-sm\" : \"icon\"))\n\nconst date = computed(() => instance.state.value.date)\nconst title = computed(() =>\n  settings.i18n.functions.formatTitle(instance.state.value.view, {\n    date: toZoned(date.value, settings.timeZone),\n    activeRange: instance.state.value.activeRange,\n    visibleRange: instance.state.value.visibleRange,\n    locale: settings.locale,\n  })\n)\nconst isToday = computed(() => {\n  const now = toZoned(new Date(), settings.timeZone)\n  return now >= instance.state.value.activeRange.start && now \u003C instance.state.value.activeRange.end\n})\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv\n    data-slot=\"event-calendar-nav\"\n    :class=\"\n      cn(\n        'flex min-w-0 flex-wrap items-center gap-1 px-2 py-2',\n        viewConfig.stickyNav && 'bg-background sticky top-0 z-30',\n        viewConfig.classNames?.nav,\n        props.class\n      )\n    \"\n  >\n    \u003CButton\n      :variant=\"navVariant\"\n      :size=\"navSize\"\n      data-slot=\"event-calendar-nav-today\"\n      :data-active=\"isToday || undefined\"\n      :class=\"viewConfig.classNames?.navButton\"\n      @click=\"instance.api.today()\"\n    >\n      {{ settings.i18n.labels.today }}\n    \u003C\u002FButton>\n    \u003Cdiv class=\"flex items-center\">\n      \u003CButton\n        :variant=\"navVariant\"\n        :size=\"navIconSize\"\n        data-slot=\"event-calendar-nav-prev\"\n        :aria-label=\"settings.i18n.labels.previous\"\n        :class=\"viewConfig.classNames?.navButton\"\n        @click=\"instance.api.prev()\"\n      >\n        \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"size-4\" aria-hidden=\"true\">\u003Cpath d=\"m15 18-6-6 6-6\" \u002F>\u003C\u002Fsvg>\n      \u003C\u002FButton>\n      \u003CButton\n        :variant=\"navVariant\"\n        :size=\"navIconSize\"\n        data-slot=\"event-calendar-nav-next\"\n        :aria-label=\"settings.i18n.labels.next\"\n        :class=\"viewConfig.classNames?.navButton\"\n        @click=\"instance.api.next()\"\n      >\n        \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"size-4\" aria-hidden=\"true\">\u003Cpath d=\"m9 18 6-6-6-6\" \u002F>\u003C\u002Fsvg>\n      \u003C\u002FButton>\n    \u003C\u002Fdiv>\n    \u003Cdiv data-slot=\"event-calendar-title\" aria-live=\"polite\" :class=\"cn('ms-3 min-w-0 truncate text-sm font-semibold', viewConfig.classNames?.title)\">\n      {{ title }}\n    \u003C\u002Fdiv>\n    \u003Cdiv class=\"grow\" \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",{"path":4831,"type":480,"target":4832,"content":4833},"src\u002Freui\u002Fevent-calendar\u002FEventCalendarResourceView.vue","components\u002Freui\u002Fevent-calendar\u002FEventCalendarResourceView.vue","\u003Cscript setup lang=\"ts\">\n\u002F**\n * Порт ReUI EventCalendarResourceView (event-calendar-resource-view.tsx, MIT)\n * — колонки-ресурсы на один день (бронирования): одна часовая шкала, одна\n * колонка на лист-ресурс.\n *\n * ponytail — тот же список причин, что в EventCalendarTimeGrid.vue (dnd,\n * измерение реального DOM, не нужно ни одному текущему кейсу):\n *  - drag\u002Fresize ghosts, slot-draft, `data-drop-target` — ждут dnd.\n *  - `EventCalendarNowIndicator`, начальный скролл к `scrollToHour`,\n *    `--ec-scrollbar-w` — не перенесены (см. EventCalendarTimeGrid.vue).\n *  - off-days marking, render-пропы (`renderResourceHeader`\u002F\n *    `renderAllDaySection`), `asChild`, `scrollbars: \"native\"` ветка.\n * `flattenResources`\u002F`packTimedSegments` (lib.ts) переиспользованы как есть.\n * НЕ забыт `provide(EventCalendarViewContextKey, ...)` (§ найдено на\n * agenda-view: без него `EventCalendarEvent` бросает и роняет всё дерево —\n * см. docs\u002FPORTING.md).\n *\u002F\nimport { computed, provide, type HTMLAttributes } from \"vue\"\nimport { format } from \"date-fns\"\nimport { cn } from \"@\u002Flib\u002Futils\"\nimport { ScrollArea } from \"@\u002Fcomponents\u002Fui\u002Fscroll-area\"\nimport {\n  EventCalendarViewContextKey,\n  useEventCalendar,\n  useEventCalendarSettings,\n  useEventCalendarViewConfig,\n} from \".\u002Fcontext\"\nimport { flattenResources, getDayKey, getDayTotalMinutes, packTimedSegments, toZoned, zonedStartOfDay } from \".\u002Flib\"\nimport EventCalendarEvent from \".\u002FEventCalendarEvent.vue\"\nimport type { EventCalendarResource, EventCalendarSegment } from \".\u002Ftypes\"\n\nconst props = withDefaults(\n  defineProps\u003C{\n    class?: HTMLAttributes[\"class\"]\n    dayStartHour?: number\n    dayEndHour?: number\n    showAllDay?: boolean\n    interval?: number\n  }>(),\n  { showAllDay: undefined, dayStartHour: undefined, dayEndHour: undefined, interval: undefined }\n)\n\nprovide(EventCalendarViewContextKey, { view: \"resource\" })\n\nconst instance = useEventCalendar()\nconst settings = useEventCalendarSettings()\nconst viewConfig = useEventCalendarViewConfig()\n\nconst showAllDay = computed(() => props.showAllDay ?? true)\nconst startHour = computed(() => props.dayStartHour ?? settings.dayStartHour)\nconst endHour = computed(() => props.dayEndHour ?? settings.dayEndHour)\nconst interval = computed(() => Math.min(Math.max(props.interval ?? viewConfig.interval, 5), 240))\nconst day = computed(() => zonedStartOfDay(instance.state.value.date, settings.timeZone))\n\nconst resources = computed\u003CEventCalendarResource[]>(() =>\n  flattenResources(settings.resources)\n    .filter(({ resource }) => !resource.children?.length)\n    .map(({ resource }) => resource)\n)\n\nconst slots = computed(() => {\n  const result: number[] = []\n  for (let m = startHour.value * 60; m \u003C endHour.value * 60; m += interval.value) result.push(m)\n  return result\n})\n\nconst gridTemplateColumns = computed(() => `repeat(${resources.value.length || 1}, minmax(8rem, 1fr))`)\n\nfunction dayBucketAllDay(): EventCalendarSegment[] {\n  return instance.api.getIndex().byDay.get(getDayKey(day.value, settings.timeZone))?.allDay ?? []\n}\nfunction dayBucketTimed(): EventCalendarSegment[] {\n  return instance.api.getIndex().byDay.get(getDayKey(day.value, settings.timeZone))?.timed ?? []\n}\n\nfunction allDayForResource(resourceId: string): EventCalendarSegment[] {\n  return dayBucketAllDay().filter((segment) => segment.occurrence.event.resourceId === resourceId)\n}\n\ninterface ColumnView {\n  boundsStartMin: number\n  boundsEndMin: number\n  boundsMinutes: number\n  packedTimed: EventCalendarSegment[]\n}\n\nfunction columnView(resourceId: string): ColumnView {\n  const totalMinutes = getDayTotalMinutes(day.value, settings.timeZone)\n  const boundsStartMin = startHour.value * 60\n  const boundsEndMin = Math.min(endHour.value * 60, totalMinutes)\n  const boundsMinutes = Math.max(60, boundsEndMin - boundsStartMin)\n  const mine = dayBucketTimed()\n    .filter((segment) => {\n      if (segment.occurrence.event.resourceId !== resourceId) return false\n      const startMin = Math.max(segment.startMin ?? 0, boundsStartMin)\n      const endMin = Math.min(segment.endMin ?? startMin, boundsEndMin)\n      return endMin > boundsStartMin && startMin \u003C boundsEndMin\n    })\n    .map((segment) => ({ ...segment }))\n  packTimedSegments(mine)\n  return { boundsStartMin, boundsEndMin, boundsMinutes, packedTimed: mine }\n}\n\nfunction minuteBlockStyle(startMin: number, endMin: number, boundsStartMin: number) {\n  const top = (startMin - boundsStartMin) \u002F 60\n  const height = Math.max((endMin - startMin) \u002F 60, 0.25)\n  return {\n    top: `calc(var(--ec-hour-height) * ${top})`,\n    height: `calc(var(--ec-hour-height) * ${height})`,\n  }\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv\n    data-slot=\"event-calendar-resource-view\"\n    data-view=\"resource\"\n    :class=\"cn('flex min-h-0 flex-1 flex-col overflow-hidden border-t', viewConfig.classNames?.timeGrid, props.class)\"\n    :style=\"{ '--ec-hour-height': '4rem' }\"\n  >\n    \u003Cdiv :class=\"cn('flex border-b', viewConfig.classNames?.timeGridHeader)\">\n      \u003Cdiv class=\"w-(--ec-gutter-width,4.5rem) shrink-0 border-e\" \u002F>\n      \u003Cdiv class=\"grid min-w-0 flex-1\" :style=\"{ gridTemplateColumns }\">\n        \u003Cdiv\n          v-for=\"resource in resources\"\n          :key=\"resource.id\"\n          data-slot=\"event-calendar-resource-header\"\n          :class=\"cn('min-w-0 truncate border-e px-2 py-1.5 text-center font-medium last:border-e-0', viewConfig.classNames?.resourceHeader)\"\n        >\n          {{ resource.title }}\n        \u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n    \u003Cdiv v-if=\"showAllDay\" data-slot=\"event-calendar-all-day-section\" :class=\"cn('flex border-b', viewConfig.classNames?.allDaySection)\">\n      \u003Cdiv :class=\"cn('text-muted-foreground w-(--ec-gutter-width,4.5rem) shrink-0 border-e ps-2 pe-2.5 pt-1.5', viewConfig.classNames?.allDayLabel)\">\n        \u003Cspan class=\"flex h-[calc(var(--ec-month-bar-h,1.625rem)-0.125rem)] items-center justify-end\">{{ settings.i18n.labels.allDay }}\u003C\u002Fspan>\n      \u003C\u002Fdiv>\n      \u003Cdiv class=\"grid min-w-0 flex-1\" :style=\"{ gridTemplateColumns }\">\n        \u003Cdiv\n          v-for=\"resource in resources\"\n          :key=\"resource.id\"\n          data-slot=\"event-calendar-all-day-cell\"\n          :class=\"cn('relative flex min-h-[calc(var(--ec-month-bar-h,1.625rem)+0.625rem)] min-w-0 flex-col gap-0.5 border-e px-1 py-1.5 last:border-e-0', viewConfig.classNames?.allDayCell)\"\n        >\n          \u003CEventCalendarEvent\n            v-for=\"segment in allDayForResource(resource.id)\"\n            :key=\"segment.occurrence.key\"\n            :segment=\"segment\"\n            class=\"h-[calc(var(--ec-month-bar-h,1.625rem)-0.125rem)]\"\n          \u002F>\n        \u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n    \u003Cdiv class=\"min-h-0 flex-1\">\n      \u003CScrollArea class=\"h-full\">\n        \u003Cdiv class=\"relative flex\">\n          \u003Cdiv data-slot=\"event-calendar-time-gutter\" :class=\"cn('relative w-(--ec-gutter-width,4.5rem) shrink-0 border-e', viewConfig.classNames?.timeGutter)\">\n            \u003Cdiv\n              v-for=\"minutes in slots\"\n              :key=\"minutes\"\n              class=\"relative\"\n              :style=\"{ height: `calc(var(--ec-hour-height) * ${interval \u002F 60})` }\"\n            >\n              \u003Cspan\n                v-if=\"minutes > startHour * 60\"\n                :class=\"cn('text-muted-foreground absolute end-2.5 -top-2', viewConfig.classNames?.timeGutterLabel)\"\n              >\n                {{ format(toZoned(new Date(day.getTime() + minutes * 60000), settings.timeZone), interval % 60 === 0 ? settings.i18n.formats.timeGutter : settings.i18n.formats.timeGutterMinute, { locale: settings.locale }) }}\n              \u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fdiv>\n          \u003Cdiv class=\"grid min-w-0 flex-1\" :style=\"{ gridTemplateColumns }\">\n            \u003Cdiv\n              v-for=\"resource in resources\"\n              :key=\"resource.id\"\n              data-slot=\"event-calendar-day-column\"\n              :aria-label=\"resource.title\"\n              role=\"group\"\n              :data-ec-day=\"day.getTime()\"\n              :data-ec-bounds-start=\"columnView(resource.id).boundsStartMin\"\n              :data-ec-bounds-end=\"columnView(resource.id).boundsEndMin\"\n              :data-ec-resource=\"resource.id\"\n              :class=\"cn('relative min-w-0 border-e last:border-e-0', viewConfig.classNames?.dayColumn)\"\n              :style=\"{\n                height: `calc(var(--ec-hour-height) * ${columnView(resource.id).boundsMinutes \u002F 60})`,\n                backgroundImage: `repeating-linear-gradient(to bottom, transparent, transparent calc(var(--ec-hour-height) * ${interval \u002F 60} - var(--ec-slot-line-width, 1px)), var(--ec-slot-line-color, var(--color-border)) calc(var(--ec-hour-height) * ${interval \u002F 60} - var(--ec-slot-line-width, 1px)), var(--ec-slot-line-color, var(--color-border)) calc(var(--ec-hour-height) * ${interval \u002F 60}))`,\n              }\"\n            >\n              \u003Cdiv\n                v-for=\"segment in columnView(resource.id).packedTimed\"\n                :key=\"segment.occurrence.key\"\n                class=\"absolute z-(--ec-z) min-h-(--ec-event-min-h,1.5rem) px-0.5 hover:z-40\"\n                :style=\"{\n                  ...minuteBlockStyle(Math.max(segment.startMin ?? 0, columnView(resource.id).boundsStartMin), Math.min(segment.endMin ?? 0, columnView(resource.id).boundsEndMin), columnView(resource.id).boundsStartMin),\n                  left: `${(segment.column ?? 0) * (100 \u002F (segment.columnCount ?? 1))}%`,\n                  width: `${(segment.columnSpan ?? 1) * (100 \u002F (segment.columnCount ?? 1))}%`,\n                  '--ec-z': segment.occurrence.event.zIndex ?? 10 + (segment.column ?? 0),\n                }\"\n              >\n                \u003CEventCalendarEvent\n                  :segment=\"segment\"\n                  :class=\"\n                    cn(\n                      (segment.columnCount ?? 1) > 1 && 'ring-background ring-1',\n                      (segment.endMin ?? 0) - (segment.startMin ?? 0) \u003C viewConfig.compactEventMinutes\n                        ? 'h-full gap-1 py-0 leading-4'\n                        : 'h-full flex-col items-start justify-start gap-0 py-1',\n                      viewConfig.classNames?.timedChip\n                    )\n                  \"\n                \u002F>\n              \u003C\u002Fdiv>\n            \u003C\u002Fdiv>\n          \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n      \u003C\u002FScrollArea>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",{"path":4835,"type":480,"target":4836,"content":4837},"src\u002Freui\u002Fevent-calendar\u002FEventCalendarTimeGrid.vue","components\u002Freui\u002Fevent-calendar\u002FEventCalendarTimeGrid.vue","\u003Cscript setup lang=\"ts\">\n\u002F**\n * Порт ReUI EventCalendarTimeGrid (event-calendar-time-grid.tsx, MIT) —\n * общий движок week\u002Fday\u002FN-days: часовая шкала, минутное позиционирование\n * событий, all-day строка.\n *\n * ponytail — сознательно НЕ перенесено в этом проходе (тот же список\n * причин, что в EventCalendarMonthView.vue: зависят либо от dnd, либо от\n * измерения реального DOM, либо не нужны ни одному текущему кейсу):\n *  - drag\u002Fresize ghosts, slot-draft — ждут `event-calendar-dnd.tsx`.\n *  - `EventCalendarNowIndicator` — линия \"сейчас\"; кейс (15 июня 2026)\n *    сознательно не пересекает реальную дату прогона, поэтому линия и так\n *    никогда не попала бы в видимый диапазон — добавить вместе с\n *    `useNow()` (setInterval-тик), когда появится кейс, где это видно.\n *  - `--ec-scrollbar-w`\u002F`api.scrollToTime`\u002Fначальный скролл к `scrollToHour`\n *    (ResizeObserver + измерение реального DOM) — контейнер просто\n *    прокручивается нативно; начальная прокрутка к `scrollToHour` не\n *    выставляется.\n *  - off-days marking, `renderDayColumnBackground`\u002F`renderTimeGutterSlot`\u002F\n *    `renderAllDaySection`\u002F`renderDayHeader` рендер-пропы, `asChild`,\n *    `scrollbars: \"native\"` ветка (всегда `ScrollArea`, кастомный скролл —\n *    дефолт оригинала).\n * `packTimedSegments` (lib.ts) переиспользован для перепаковки сегментов,\n * обрезанных границами часов (`boundsStartMin`\u002F`boundsEndMin`), как и в\n * оригинале.\n *\u002F\nimport { computed, provide, type HTMLAttributes } from \"vue\"\nimport { addDays, addMinutes, format } from \"date-fns\"\nimport { cn } from \"@\u002Flib\u002Futils\"\nimport { ScrollArea } from \"@\u002Fcomponents\u002Fui\u002Fscroll-area\"\nimport {\n  EventCalendarViewContextKey,\n  useEventCalendar,\n  useEventCalendarSettings,\n  useEventCalendarViewConfig,\n} from \".\u002Fcontext\"\nimport { getDayKey, getDayTotalMinutes, packTimedSegments, toZoned, zonedStartOfDay } from \".\u002Flib\"\nimport EventCalendarEvent from \".\u002FEventCalendarEvent.vue\"\nimport type { EventCalendarDayBucket } from \".\u002Flib\"\nimport type { CalendarView, EventCalendarSegment } from \".\u002Ftypes\"\n\nconst props = withDefaults(\n  defineProps\u003C{\n    class?: HTMLAttributes[\"class\"]\n    view: Extract\u003CCalendarView, \"week\" | \"day\" | \"days\">\n    dayStartHour?: number\n    dayEndHour?: number\n    showAllDay?: boolean\n    interval?: number\n  }>(),\n  { showAllDay: true, dayStartHour: undefined, dayEndHour: undefined, interval: undefined }\n)\n\nprovide(EventCalendarViewContextKey, { view: props.view })\n\nconst instance = useEventCalendar()\nconst settings = useEventCalendarSettings()\nconst viewConfig = useEventCalendarViewConfig()\n\nconst visibleRange = computed(() => instance.state.value.visibleRange)\nconst weekendsOn = computed(() => instance.state.value.viewSettings.weekends ?? true)\nconst startHour = computed(() => props.dayStartHour ?? settings.dayStartHour)\nconst endHour = computed(() => props.dayEndHour ?? settings.dayEndHour)\nconst interval = computed(() => Math.min(Math.max(props.interval ?? viewConfig.interval, 5), 240))\n\nconst days = computed(() => {\n  const result: Date[] = []\n  let cursor = zonedStartOfDay(visibleRange.value.start, settings.timeZone)\n  while (cursor \u003C visibleRange.value.end) {\n    result.push(cursor)\n    cursor = zonedStartOfDay(addDays(toZoned(cursor, settings.timeZone), 1), settings.timeZone)\n  }\n  if (weekendsOn.value || props.view === \"day\") return result\n  const filtered = result.filter(\n    (day) => !settings.weekendDays.includes(toZoned(day, settings.timeZone).getDay())\n  )\n  return filtered.length ? filtered : result\n})\n\nconst slots = computed(() => {\n  const result: number[] = []\n  for (let m = startHour.value * 60; m \u003C endHour.value * 60; m += interval.value) result.push(m)\n  return result\n})\n\nconst gridTemplateColumns = computed(() => `repeat(${days.value.length}, minmax(0, 1fr))`)\n\nfunction isToday(day: Date): boolean {\n  return getDayKey(new Date(), settings.timeZone) === getDayKey(day, settings.timeZone)\n}\n\nfunction dayBucket(day: Date): EventCalendarDayBucket {\n  return (\n    instance.api.getIndex().byDay.get(getDayKey(day, settings.timeZone)) ?? { allDay: [], timed: [] }\n  )\n}\n\n\u002F\u002F All-day bars: consecutive-day segments of the same occurrence merged into\n\u002F\u002F one bar spanning its columns, lane-packed (same treatment as month view).\nconst allDayBars = computed(() => {\n  type Bar = { seg: EventCalendarSegment; colStart: number; colEnd: number; isStart: boolean; isEnd: boolean; lane: number }\n  const merged = new Map\u003Cstring, Bar>()\n  days.value.forEach((day, col) => {\n    for (const seg of dayBucket(day).allDay) {\n      const key = seg.occurrence.key\n      const bar = merged.get(key)\n      if (bar) {\n        bar.colEnd = col\n        bar.isEnd = seg.isEnd\n      } else {\n        merged.set(key, { seg, colStart: col, colEnd: col, isStart: seg.isStart, isEnd: seg.isEnd, lane: 0 })\n      }\n    }\n  })\n  const packed = Array.from(merged.values()).sort(\n    (a, b) =>\n      a.colStart - b.colStart ||\n      b.colEnd - b.colStart - (a.colEnd - a.colStart) ||\n      a.seg.occurrence.key.localeCompare(b.seg.occurrence.key)\n  )\n  const lanes: boolean[][] = []\n  for (const bar of packed) {\n    let lane = 0\n    for (;;) {\n      const row = (lanes[lane] ??= new Array(days.value.length).fill(false))\n      let free = true\n      for (let c = bar.colStart; c \u003C= bar.colEnd; c++) {\n        if (row[c]) {\n          free = false\n          break\n        }\n      }\n      if (free) break\n      lane++\n    }\n    const row = lanes[lane]!\n    for (let c = bar.colStart; c \u003C= bar.colEnd; c++) row[c] = true\n    bar.lane = lane\n  }\n  return {\n    bars: packed.map((bar) => ({\n      ...bar.seg,\n      isStart: bar.isStart,\n      isEnd: bar.isEnd,\n      continuesBefore: !bar.isStart,\n      continuesAfter: !bar.isEnd,\n      colStart: bar.colStart,\n      colSpan: bar.colEnd - bar.colStart + 1,\n      lane: bar.lane,\n    })),\n    laneCount: lanes.length,\n  }\n})\n\ninterface DayColumnView {\n  isToday: boolean\n  boundsStartMin: number\n  boundsEndMin: number\n  boundsMinutes: number\n  packedTimed: EventCalendarSegment[]\n}\n\nfunction dayColumnView(day: Date): DayColumnView {\n  const totalMinutes = getDayTotalMinutes(day, settings.timeZone)\n  const boundsStartMin = startHour.value * 60\n  const boundsEndMin = Math.min(endHour.value * 60, totalMinutes)\n  const boundsMinutes = Math.max(60, boundsEndMin - boundsStartMin)\n  const timed = dayBucket(day).timed\n  const visible = timed.filter((segment) => {\n    const startMin = Math.max(segment.startMin ?? 0, boundsStartMin)\n    const endMin = Math.min(segment.endMin ?? startMin, boundsEndMin)\n    return endMin > boundsStartMin && startMin \u003C boundsEndMin\n  })\n  let packedTimed = visible\n  if (visible.length !== timed.length) {\n    packedTimed = visible.map((segment) => ({ ...segment }))\n    packTimedSegments(packedTimed)\n  }\n  return { isToday: isToday(day), boundsStartMin, boundsEndMin, boundsMinutes, packedTimed }\n}\n\nfunction minuteBlockStyle(startMin: number, endMin: number, boundsStartMin: number) {\n  const top = (startMin - boundsStartMin) \u002F 60\n  const height = Math.max((endMin - startMin) \u002F 60, 0.25)\n  return {\n    top: `calc(var(--ec-hour-height) * ${top})`,\n    height: `calc(var(--ec-hour-height) * ${height})`,\n  }\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv\n    data-slot=\"event-calendar-time-grid\"\n    :data-view=\"view\"\n    :class=\"cn('flex min-h-0 flex-1 flex-col overflow-hidden border-t', viewConfig.classNames?.timeGrid, props.class)\"\n    :style=\"{ '--ec-hour-height': '4rem' }\"\n  >\n    \u003Cdiv :class=\"cn('flex border-b', viewConfig.classNames?.timeGridHeader)\">\n      \u003Cdiv class=\"w-(--ec-gutter-width,4.5rem) shrink-0 border-e\" \u002F>\n      \u003Cdiv class=\"grid min-w-0 flex-1\" :style=\"{ gridTemplateColumns }\">\n        \u003Cdiv\n          v-for=\"day in days\"\n          :key=\"day.getTime()\"\n          data-slot=\"event-calendar-day-header\"\n          :data-today=\"isToday(day) || undefined\"\n          :class=\"cn('data-today:text-primary min-w-0 truncate border-e px-2 py-1.5 font-medium last:border-e-0', isToday(day) && viewConfig.todayClassName)\"\n        >\n          {{ format(toZoned(day, settings.timeZone), settings.i18n.formats.timeGridDayHeader, { locale: settings.locale }) }}\n        \u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n    \u003Cdiv v-if=\"showAllDay\" data-slot=\"event-calendar-all-day-section\" :class=\"cn('flex border-b', viewConfig.classNames?.allDaySection)\">\n      \u003Cdiv :class=\"cn('text-muted-foreground w-(--ec-gutter-width,4.5rem) shrink-0 border-e ps-2 pe-2.5 pt-1.5', viewConfig.classNames?.allDayLabel)\">\n        \u003Cspan class=\"flex h-[calc(var(--ec-month-bar-h,1.625rem)-0.125rem)] items-center justify-end\">{{ settings.i18n.labels.allDay }}\u003C\u002Fspan>\n      \u003C\u002Fdiv>\n      \u003Cdiv class=\"relative min-w-0 flex-1\">\n        \u003Cdiv\n          class=\"grid h-full\"\n          :style=\"{ gridTemplateColumns, minHeight: `calc(${Math.max(allDayBars.laneCount, 1)} * var(--ec-month-bar-h, 1.625rem) + 0.625rem)` }\"\n        >\n          \u003Cdiv v-for=\"day in days\" :key=\"day.getTime()\" class=\"border-e last:border-e-0\" \u002F>\n        \u003C\u002Fdiv>\n        \u003Cdiv\n          v-if=\"allDayBars.bars.length > 0\"\n          data-slot=\"event-calendar-all-day-bar-overlay\"\n          class=\"pointer-events-none absolute inset-x-0 top-0 grid pt-1.5\"\n          :style=\"{ gridTemplateColumns, gridAutoRows: 'var(--ec-month-bar-h, 1.625rem)' }\"\n        >\n          \u003Cdiv\n            v-for=\"segment in allDayBars.bars\"\n            :key=\"segment.occurrence.key\"\n            class=\"pointer-events-auto min-w-0 px-1\"\n            :style=\"{ gridColumn: `${(segment.colStart ?? 0) + 1} \u002F span ${segment.colSpan ?? 1}`, gridRow: (segment.lane ?? 0) + 1 }\"\n          >\n            \u003CEventCalendarEvent :segment=\"segment\" class=\"h-[calc(var(--ec-month-bar-h,1.625rem)-0.125rem)]\" \u002F>\n          \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n    \u003Cdiv class=\"min-h-0 flex-1\">\n      \u003CScrollArea class=\"h-full\">\n        \u003Cdiv class=\"relative flex\">\n          \u003Cdiv data-slot=\"event-calendar-time-gutter\" :class=\"cn('relative w-(--ec-gutter-width,4.5rem) shrink-0 border-e', viewConfig.classNames?.timeGutter)\">\n            \u003Cdiv\n              v-for=\"minutes in slots\"\n              :key=\"minutes\"\n              class=\"relative\"\n              :style=\"{ height: `calc(var(--ec-hour-height) * ${interval \u002F 60})` }\"\n            >\n              \u003Cspan\n                v-if=\"minutes > startHour * 60\"\n                :class=\"cn('text-muted-foreground absolute end-2.5 -top-2', viewConfig.classNames?.timeGutterLabel)\"\n              >\n                {{ format(addMinutes(zonedStartOfDay(days[0] ?? new Date(), settings.timeZone), minutes), interval % 60 === 0 ? settings.i18n.formats.timeGutter : settings.i18n.formats.timeGutterMinute, { locale: settings.locale }) }}\n              \u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fdiv>\n          \u003Cdiv class=\"grid min-w-0 flex-1\" :style=\"{ gridTemplateColumns }\">\n            \u003Cdiv\n              v-for=\"day in days\"\n              :key=\"day.getTime()\"\n              data-slot=\"event-calendar-day-column\"\n              :data-today=\"dayColumnView(day).isToday || undefined\"\n              :data-ec-day=\"zonedStartOfDay(day, settings.timeZone).getTime()\"\n              :data-ec-bounds-start=\"dayColumnView(day).boundsStartMin\"\n              :data-ec-bounds-end=\"dayColumnView(day).boundsEndMin\"\n              :class=\"cn('relative min-w-0 border-e last:border-e-0', dayColumnView(day).isToday && viewConfig.todayClassName, viewConfig.classNames?.dayColumn)\"\n              :style=\"{\n                height: `calc(var(--ec-hour-height) * ${dayColumnView(day).boundsMinutes \u002F 60})`,\n                backgroundImage: `repeating-linear-gradient(to bottom, transparent, transparent calc(var(--ec-hour-height) * ${interval \u002F 60} - var(--ec-slot-line-width, 1px)), var(--ec-slot-line-color, var(--color-border)) calc(var(--ec-hour-height) * ${interval \u002F 60} - var(--ec-slot-line-width, 1px)), var(--ec-slot-line-color, var(--color-border)) calc(var(--ec-hour-height) * ${interval \u002F 60}))`,\n              }\"\n            >\n              \u003Ctemplate v-for=\"segment in dayColumnView(day).packedTimed\" :key=\"segment.occurrence.key\">\n                \u003Cdiv\n                  v-if=\"!(Math.min(segment.endMin ?? 0, dayColumnView(day).boundsEndMin) \u003C= dayColumnView(day).boundsStartMin || Math.max(segment.startMin ?? 0, dayColumnView(day).boundsStartMin) >= dayColumnView(day).boundsEndMin)\"\n                  class=\"absolute z-(--ec-z) min-h-(--ec-event-min-h,1.5rem) px-0.5 hover:z-40\"\n                  :style=\"{\n                    ...minuteBlockStyle(Math.max(segment.startMin ?? 0, dayColumnView(day).boundsStartMin), Math.min(segment.endMin ?? 0, dayColumnView(day).boundsEndMin), dayColumnView(day).boundsStartMin),\n                    left: `${(segment.column ?? 0) * (100 \u002F (segment.columnCount ?? 1))}%`,\n                    width: `${(segment.columnSpan ?? 1) * (100 \u002F (segment.columnCount ?? 1))}%`,\n                    '--ec-z': segment.occurrence.event.zIndex ?? 10 + (segment.column ?? 0),\n                  }\"\n                >\n                  \u003CEventCalendarEvent\n                    :segment=\"segment\"\n                    :class=\"\n                      cn(\n                        (segment.columnCount ?? 1) > 1 && 'ring-background ring-1',\n                        (segment.endMin ?? 0) - (segment.startMin ?? 0) \u003C viewConfig.compactEventMinutes\n                          ? 'h-full gap-1 py-0 leading-4'\n                          : 'h-full flex-col items-start justify-start gap-0 py-1',\n                        viewConfig.classNames?.timedChip\n                      )\n                    \"\n                  \u002F>\n                \u003C\u002Fdiv>\n              \u003C\u002Ftemplate>\n            \u003C\u002Fdiv>\n          \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n      \u003C\u002FScrollArea>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",{"path":4839,"type":480,"target":4840,"content":4841},"src\u002Freui\u002Fevent-calendar\u002FEventCalendarWeekView.vue","components\u002Freui\u002Fevent-calendar\u002FEventCalendarWeekView.vue","\u003Cscript setup lang=\"ts\">\n\u002F** Тонкая обёртка над EventCalendarTimeGrid с фиксированным `view=\"week\"`, как в оригинале. *\u002F\nimport type { HTMLAttributes } from \"vue\"\nimport EventCalendarTimeGrid from \".\u002FEventCalendarTimeGrid.vue\"\n\n\u002F\u002F showAllDay: undefined в withDefaults — иначе Vue приводит отсутствующий\n\u002F\u002F boolean-проп к `false` вместо `undefined` и глушит дефолт `true` из\n\u002F\u002F EventCalendarTimeGrid.vue (та же ловушка, что задокументирована в\n\u002F\u002F docs\u002FPORTING.md §32 \u002F EventCalendar.vue).\nconst props = withDefaults(\n  defineProps\u003C{\n    class?: HTMLAttributes[\"class\"]\n    dayStartHour?: number\n    dayEndHour?: number\n    showAllDay?: boolean\n    interval?: number\n  }>(),\n  { showAllDay: undefined }\n)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CEventCalendarTimeGrid\n    view=\"week\"\n    :class=\"props.class\"\n    :day-start-hour=\"props.dayStartHour\"\n    :day-end-hour=\"props.dayEndHour\"\n    :show-all-day=\"props.showAllDay\"\n    :interval=\"props.interval\"\n  \u002F>\n\u003C\u002Ftemplate>\n",{"path":4843,"type":480,"target":4844,"content":4845},"src\u002Freui\u002Fevent-calendar\u002Fcontext.ts","components\u002Freui\u002Fevent-calendar\u002Fcontext.ts","\u002F**\n * Порт движка ReUI EventCalendar (event-calendar.tsx, MIT) поверх Vue\n * reactivity — НЕ порт `useSyncExternalStore`\u002F`createEventCalendarStore`, а\n * переписывание (тот же приём, что и DataGrid, см. комментарий в\n * `data-grid\u002Fcontext.ts`): в оригинале `getState()`\u002F`subscribe()`\u002Fручной\n * `snapshot`\u002F`indexCache`\u002F`rangeCache` существуют только затем, чтобы дать\n * React стабильный по ссылке снимок между рендерами — Vue `computed()` делает\n * это бесплатно (кэшируется, пока не изменились реактивные зависимости).\n *\n * ponytail: v1 — только неуправляемый (uncontrolled) режим: `createEventCalendar`\n * читает `options` один раз при создании (как React `default*`-пропы), без\n * `value`\u002F`onXChange`-пары и без реакции на смену пропов извне. Двусторонний\n * `v-model` на каждое поле — задача корневого `EventCalendar.vue` (ещё не\n * портирован); добавить, когда он появится.\n *\n * ponytail: `EventCalendarGestures` (move\u002Fresize\u002Fcreate) здесь — заглушка\n * (no-op). Настоящая реализация — `event-calendar-dnd.tsx`, портируется\n * последним по плану. `EventCalendarEvent.vue` уже вызывает\n * `useEventCalendarGestures()`, чтобы не переписывать её потом: корневой\n * компонент вызовет `provide(EventCalendarGesturesContextKey, ...)` с боевой\n * реализацией, ничего в этом файле\u002Fпотребителях менять не придётся.\n *\u002F\nimport type { Component, ComputedRef, InjectionKey, VNodeChild } from \"vue\"\nimport { computed, inject, shallowReactive } from \"vue\"\nimport type { Locale } from \"date-fns\"\nimport {\n  buildEventIndex,\n  defaultEventOrder,\n  eventsOverlap,\n  getDayKey,\n  getViewDateRange,\n  stepDate,\n  toZoned as toZonedLib,\n  type EventCalendarIndex,\n  type WeekStartsOn,\n} from \".\u002Flib\"\nimport {\n  mergeEventCalendarI18n,\n  type EventCalendarI18nConfig,\n  type EventCalendarI18nOverrides,\n} from \".\u002Fi18n\"\nimport type {\n  CalendarEvent,\n  CalendarView,\n  EventCalendarDateRange,\n  EventCalendarDragState,\n  EventCalendarEventId,\n  EventCalendarInteractions,\n  EventCalendarOccurrence,\n  EventCalendarOffDaysConfig,\n  EventCalendarProposedUpdate,\n  EventCalendarResource,\n  EventCalendarSegment,\n  EventCalendarSelection,\n  EventCalendarSlotDraft,\n  EventCalendarSlotInfo,\n  EventCalendarState,\n  EventCalendarUpdateResult,\n  EventCalendarViewSettings,\n} from \".\u002Ftypes\"\n\nconst BASE_VIEWS: CalendarView[] = [\"month\", \"week\", \"day\", \"days\", \"agenda\"]\nconst ALL_VIEWS: CalendarView[] = [...BASE_VIEWS, \"resource\"]\n\nconst DEFAULT_INTERACTIONS: EventCalendarInteractions = {\n  drag: true,\n  resize: true,\n  selectSlot: true,\n}\n\nconst EMPTY_SELECTION: EventCalendarSelection = { eventKeys: [], slot: null }\nconst DEFAULT_WEEKEND_DAYS: number[] = [0, 6]\nconst EMPTY_RESOURCES: EventCalendarResource[] = []\nconst DEFAULT_EVENT_PRIORITY = (event: CalendarEvent\u003Cnever>) =>\n  event.priority ?? 0\n\ntype EventOrder\u003CTData> = (\n  a: EventCalendarOccurrence\u003CTData>,\n  b: EventCalendarOccurrence\u003CTData>\n) => number\n\nfunction priorityEventOrder\u003CTData>(\n  getEventPriority: (event: CalendarEvent\u003CTData>) => number\n): EventOrder\u003CTData> {\n  return (a, b) =>\n    getEventPriority(b.event) - getEventPriority(a.event) ||\n    defaultEventOrder(a, b)\n}\n\nexport interface EventCalendarActivationConfig {\n  moveDistancePx: number\n  createDistancePx: number\n  touchDelayMs: number\n  touchTolerancePx: number\n  autoScrollEdgePx: number\n  autoScrollMaxStepPx: number\n}\n\nexport interface EventCalendarCallbacks\u003CTData = unknown> {\n  onEventClick?: (\n    occurrence: EventCalendarOccurrence\u003CTData>,\n    e: MouseEvent\n  ) => void\n  onEventDoubleClick?: (\n    occurrence: EventCalendarOccurrence\u003CTData>,\n    e: MouseEvent\n  ) => void\n  onEventUpdate?: (\n    update: EventCalendarProposedUpdate\u003CTData>\n  ) => EventCalendarUpdateResult\n  canDropEvent?: (update: EventCalendarProposedUpdate\u003CTData>) => boolean\n  onDragBlocked?: (\n    occurrence: EventCalendarOccurrence\u003CTData>,\n    info: {\n      gesture: \"move\" | \"resize\"\n      reason: \"readOnly\" | \"disabled\" | \"interactions-off\"\n    }\n  ) => void\n  onSlotClick?: (slot: EventCalendarSlotInfo, e: MouseEvent) => void\n  onSelectSlot?: (slot: EventCalendarSlotDraft) => void\n  canSelectSlot?: (slot: EventCalendarSlotDraft) => boolean\n  onViewChange?: (view: CalendarView) => void\n  onDateChange?: (date: Date) => void\n  onMoreClick?: (\n    day: Date,\n    segments: EventCalendarOccurrence\u003CTData>[],\n    e: MouseEvent\n  ) => void | false\n}\n\n\u002F** Input to `createEventCalendar` — uncontrolled-only initial values (see file header). *\u002F\nexport interface EventCalendarOptions\u003CTData = unknown>\n  extends EventCalendarCallbacks\u003CTData> {\n  events?: CalendarEvent\u003CTData>[]\n  view?: CalendarView\n  date?: Date\n  dayCount?: number\n  selection?: EventCalendarSelection\n  interactions?: Partial\u003CEventCalendarInteractions>\n  viewSettings?: EventCalendarViewSettings\n  loading?: boolean\n  views?: CalendarView[]\n  timeZone?: string\n  locale?: Locale\n  weekStartsOn?: WeekStartsOn\n  dayStartHour?: number\n  dayEndHour?: number\n  slotDuration?: number\n  snapDuration?: number\n  agendaDayCount?: number\n  fixedWeeks?: boolean\n  showOutsideDays?: boolean\n  i18n?: EventCalendarI18nOverrides\n  resources?: EventCalendarResource[]\n  getEventPriority?: (event: CalendarEvent\u003CTData>) => number\n  eventOrder?: (\n    a: EventCalendarOccurrence\u003CTData>,\n    b: EventCalendarOccurrence\u003CTData>\n  ) => number\n  getOccurrences?: (\n    event: CalendarEvent\u003CTData>,\n    range: EventCalendarDateRange,\n    ctx: { timeZone: string }\n  ) => Array\u003C{ start: Date; end: Date }> | null\n  weekendDays?: number[]\n  activation?: Partial\u003CEventCalendarActivationConfig>\n}\n\nexport interface EventCalendarSettings\u003CTData = unknown>\n  extends EventCalendarCallbacks\u003CTData> {\n  timeZone: string\n  locale?: Locale\n  weekStartsOn: WeekStartsOn\n  views: CalendarView[]\n  dayStartHour: number\n  dayEndHour: number\n  slotDuration: number\n  snapDuration: number\n  agendaDayCount: number\n  fixedWeeks: boolean\n  showOutsideDays: boolean\n  i18n: EventCalendarI18nConfig\n  resources: EventCalendarResource[]\n  weekendDays: number[]\n  activation?: Partial\u003CEventCalendarActivationConfig>\n  getEventPriority: (event: CalendarEvent\u003CTData>) => number\n  eventOrder: (\n    a: EventCalendarOccurrence\u003CTData>,\n    b: EventCalendarOccurrence\u003CTData>\n  ) => number\n  getOccurrences?: (\n    event: CalendarEvent\u003CTData>,\n    range: EventCalendarDateRange,\n    ctx: { timeZone: string }\n  ) => Array\u003C{ start: Date; end: Date }> | null\n}\n\nfunction resolveSettings\u003CTData>(\n  options: EventCalendarOptions\u003CTData>\n): EventCalendarSettings\u003CTData> {\n  const {\n    events: _events,\n    view: _view,\n    date: _date,\n    dayCount: _dayCount,\n    selection: _selection,\n    interactions: _interactions,\n    viewSettings: _viewSettings,\n    loading: _loading,\n    ...rest\n  } = options\n  const getEventPriority =\n    options.getEventPriority ??\n    (DEFAULT_EVENT_PRIORITY as (event: CalendarEvent\u003CTData>) => number)\n  return {\n    ...rest,\n    timeZone:\n      options.timeZone ?? Intl.DateTimeFormat().resolvedOptions().timeZone,\n    locale: options.locale,\n    weekStartsOn:\n      options.weekStartsOn ?? options.locale?.options?.weekStartsOn ?? 0,\n    views:\n      options.views ?? (options.resources?.length ? ALL_VIEWS : BASE_VIEWS),\n    dayStartHour: options.dayStartHour ?? 0,\n    dayEndHour: options.dayEndHour ?? 24,\n    slotDuration: options.slotDuration ?? 30,\n    snapDuration: options.snapDuration ?? 15,\n    agendaDayCount: options.agendaDayCount ?? 30,\n    fixedWeeks: options.fixedWeeks ?? true,\n    showOutsideDays: options.showOutsideDays ?? true,\n    i18n: mergeEventCalendarI18n(options.i18n),\n    resources: options.resources ?? EMPTY_RESOURCES,\n    getEventPriority,\n    eventOrder: options.eventOrder ?? priorityEventOrder(getEventPriority),\n    getOccurrences: options.getOccurrences,\n    weekendDays: options.weekendDays ?? DEFAULT_WEEKEND_DAYS,\n    activation: options.activation,\n  }\n}\n\nexport interface EventCalendarApi\u003CTData = unknown> {\n  next(): void\n  prev(): void\n  today(): void\n  goTo(date: Date): void\n  setView(view: CalendarView, opts?: { dayCount?: number }): void\n  setDayCount(count: number): void\n  getEvents(): CalendarEvent\u003CTData>[]\n  getEvent(id: EventCalendarEventId): CalendarEvent\u003CTData> | undefined\n  setEvents(events: CalendarEvent\u003CTData>[]): void\n  addEvent(event: CalendarEvent\u003CTData>): void\n  updateEvent(\n    id: EventCalendarEventId,\n    patch: Partial\u003CCalendarEvent\u003CTData>>\n  ): void\n  removeEvent(id: EventCalendarEventId): void\n  getOccurrences(\n    range?: EventCalendarDateRange\n  ): EventCalendarOccurrence\u003CTData>[]\n  getOccurrencesForDay(day: Date): EventCalendarOccurrence\u003CTData>[]\n  findOverlapping(candidate: {\n    start: Date\n    end: Date\n    excludeEventId?: string\n  }): EventCalendarOccurrence\u003CTData>[]\n  select(selection: Partial\u003CEventCalendarSelection>): void\n  selectEvent(key: string, opts?: { additive?: boolean }): void\n  clearSelection(): void\n  setInteractions(patch: Partial\u003CEventCalendarInteractions>): void\n  setViewSettings(patch: EventCalendarViewSettings): void\n  getVisibleRange(): EventCalendarDateRange\n  getActiveRange(): EventCalendarDateRange\n  \u002F** TZDate in the calendar's display time zone. *\u002F\n  toZoned(date: Date): Date\n  applyProposedUpdate(\n    update: EventCalendarProposedUpdate\u003CTData>,\n    extraPatch?: Partial\u003CCalendarEvent\u003CTData>>\n  ): boolean\n  getIndex(): EventCalendarIndex\u003CTData>\n  \u002F** Cross-file plumbing for dnd.ts (live drag\u002Fresize preview); not part of the original public API. *\u002F\n  setDrag(drag: EventCalendarDragState\u003CTData> | null): void\n  setSlotDraft(draft: EventCalendarSlotDraft | null): void\n}\n\nexport interface EventCalendarInstance\u003CTData = unknown> {\n  state: ComputedRef\u003CEventCalendarState\u003CTData>>\n  api: EventCalendarApi\u003CTData>\n  settings: EventCalendarSettings\u003CTData>\n}\n\n\u002F**\n * The full engine: reactive internal fields + derived `state`, matching\n * `createEventCalendarStore`'s snapshot shape field-for-field (see file\n * header for why there is no separate snapshot\u002Fsubscribe machinery here).\n *\u002F\nexport function createEventCalendar\u003CTData = unknown>(\n  options: EventCalendarOptions\u003CTData> = {}\n): EventCalendarInstance\u003CTData> {\n  const settings = resolveSettings(options)\n\n  const resolveView = (view: CalendarView): CalendarView =>\n    settings.views.includes(view) ? view : (settings.views[0] ?? \"month\")\n\n  const internal = shallowReactive({\n    view: resolveView(options.view ?? \"month\"),\n    date: options.date ?? new Date(),\n    dayCount: Math.max(1, options.dayCount ?? 3),\n    events: (options.events ?? []) as CalendarEvent\u003CTData>[],\n    selection: options.selection ?? EMPTY_SELECTION,\n    interactions: { ...DEFAULT_INTERACTIONS, ...options.interactions },\n    viewSettings: options.viewSettings ?? {},\n    loading: options.loading ?? false,\n    drag: null as EventCalendarDragState\u003CTData> | null,\n    slotDraft: null as EventCalendarSlotDraft | null,\n  })\n\n  const state: ComputedRef\u003CEventCalendarState\u003CTData>> = computed(() => {\n    const view = resolveView(internal.view)\n    const dayCount = Math.max(1, internal.dayCount)\n    const { visibleRange, activeRange } = getViewDateRange(view, internal.date, {\n      timeZone: settings.timeZone,\n      weekStartsOn: settings.weekStartsOn,\n      dayCount,\n      agendaDayCount: settings.agendaDayCount,\n      fixedWeeks: settings.fixedWeeks,\n    })\n    return {\n      view,\n      date: internal.date,\n      dayCount,\n      visibleRange,\n      activeRange,\n      events: internal.events,\n      selection: internal.selection,\n      interactions: internal.interactions,\n      loading: internal.loading,\n      drag: internal.drag,\n      slotDraft: internal.slotDraft,\n      viewSettings: internal.viewSettings,\n    }\n  })\n\n  const index = computed(() =>\n    buildEventIndex(state.value.events, state.value.visibleRange, {\n      timeZone: settings.timeZone,\n      weekStartsOn: settings.weekStartsOn,\n      eventOrder: settings.eventOrder,\n      getOccurrences: settings.getOccurrences,\n    })\n  )\n\n  const remapSelectionKey = (\n    id: EventCalendarEventId,\n    oldKey: string,\n    nextStart: Date\n  ) => {\n    const newKey = `${id}::${nextStart.toISOString()}`\n    if (newKey === oldKey) return\n    if (!internal.selection.eventKeys.includes(oldKey)) return\n    internal.selection = {\n      ...internal.selection,\n      eventKeys: internal.selection.eventKeys.map((key) =>\n        key === oldKey ? newKey : key\n      ),\n    }\n  }\n\n  const applyProposedUpdate = (\n    update: EventCalendarProposedUpdate\u003CTData>,\n    extraPatch?: Partial\u003CCalendarEvent\u003CTData>>\n  ): boolean => {\n    const result = settings.onEventUpdate?.(update)\n    if (result === false) return false\n    const adjusted: Partial\u003CCalendarEvent\u003CTData>> =\n      result && typeof result === \"object\"\n        ? {\n            start: result.start ?? update.start,\n            end: result.end ?? update.end,\n            allDay: result.allDay ?? update.allDay,\n          }\n        : { start: update.start, end: update.end, allDay: update.allDay }\n    if (update.resourceId !== undefined) adjusted.resourceId = update.resourceId\n    const stored = internal.events.find((event) => event.id === update.event.id)\n    const oldKey =\n      update.occurrence?.key ??\n      (stored ? `${stored.id}::${stored.start.toISOString()}` : null)\n    if (oldKey) {\n      remapSelectionKey(update.event.id, oldKey, adjusted.start ?? update.start)\n    }\n    internal.events = internal.events.map((event) =>\n      event.id === update.event.id\n        ? { ...event, ...extraPatch, ...adjusted }\n        : event\n    )\n    return true\n  }\n\n  const api: EventCalendarApi\u003CTData> = {\n    next() {\n      internal.date = stepDate(state.value.view, internal.date, 1, {\n        timeZone: settings.timeZone,\n        dayCount: state.value.dayCount,\n        agendaDayCount: settings.agendaDayCount,\n      })\n      settings.onDateChange?.(internal.date)\n    },\n    prev() {\n      internal.date = stepDate(state.value.view, internal.date, -1, {\n        timeZone: settings.timeZone,\n        dayCount: state.value.dayCount,\n        agendaDayCount: settings.agendaDayCount,\n      })\n      settings.onDateChange?.(internal.date)\n    },\n    today() {\n      internal.date = new Date()\n      settings.onDateChange?.(internal.date)\n    },\n    goTo(date) {\n      internal.date = date\n      settings.onDateChange?.(date)\n    },\n    setView(view, opts) {\n      if (opts?.dayCount !== undefined) {\n        internal.dayCount = Math.max(1, opts.dayCount)\n      }\n      internal.view = resolveView(view)\n      settings.onViewChange?.(internal.view)\n    },\n    setDayCount(count) {\n      internal.dayCount = Math.max(1, count)\n    },\n    getEvents() {\n      return internal.events\n    },\n    getEvent(id) {\n      return internal.events.find((event) => event.id === id)\n    },\n    setEvents(events) {\n      internal.events = events\n    },\n    addEvent(event) {\n      internal.events = [...internal.events, event]\n    },\n    updateEvent(id, patch) {\n      const event = api.getEvent(id)\n      if (!event) return\n      const merged = { ...event, ...patch }\n      const timingChanged =\n        patch.start !== undefined ||\n        patch.end !== undefined ||\n        patch.allDay !== undefined\n      if (timingChanged && settings.onEventUpdate) {\n        const rest = { ...patch }\n        delete rest.start\n        delete rest.end\n        delete rest.allDay\n        applyProposedUpdate(\n          {\n            event: merged,\n            occurrence: null,\n            start: merged.start,\n            end: merged.end,\n            allDay: merged.allDay ?? false,\n            source: \"api\",\n          },\n          rest\n        )\n        return\n      }\n      if (timingChanged) {\n        remapSelectionKey(id, `${id}::${event.start.toISOString()}`, merged.start)\n      }\n      internal.events = internal.events.map((e) => (e.id === id ? merged : e))\n    },\n    removeEvent(id) {\n      internal.events = internal.events.filter((event) => event.id !== id)\n    },\n    getOccurrences(range) {\n      if (!range) return index.value.occurrences\n      const within =\n        range.start >= state.value.visibleRange.start &&\n        range.end \u003C= state.value.visibleRange.end\n      if (within) {\n        return index.value.occurrences.filter((occ) => eventsOverlap(occ, range))\n      }\n      \u002F\u002F ponytail: no throwaway-range cache (see createEventCalendarStore's\n      \u002F\u002F rangeCache) — Vue callers read this through a computed of their own\n      \u002F\u002F when they need referential stability; add a cache here if a caller\n      \u002F\u002F ends up polling getOccurrences(range) every render.\n      return buildEventIndex(internal.events, range, {\n        timeZone: settings.timeZone,\n        weekStartsOn: settings.weekStartsOn,\n        eventOrder: settings.eventOrder,\n        getOccurrences: settings.getOccurrences,\n      }).occurrences\n    },\n    getOccurrencesForDay(day) {\n      const bucket = index.value.byDay.get(getDayKey(day, settings.timeZone))\n      if (!bucket) return []\n      const seen = new Set\u003Cstring>()\n      const result: EventCalendarOccurrence\u003CTData>[] = []\n      for (const seg of [...bucket.allDay, ...bucket.timed]) {\n        if (seen.has(seg.occurrence.key)) continue\n        seen.add(seg.occurrence.key)\n        result.push(seg.occurrence)\n      }\n      return result\n    },\n    findOverlapping({ start, end, excludeEventId }) {\n      return api\n        .getOccurrences({ start, end })\n        .filter((occ) => occ.eventId !== excludeEventId)\n    },\n    select(partial) {\n      internal.selection = {\n        eventKeys: partial.eventKeys ?? internal.selection.eventKeys,\n        slot: partial.slot !== undefined ? partial.slot : internal.selection.slot,\n      }\n    },\n    selectEvent(key, opts) {\n      const current = internal.selection\n      const eventKeys = opts?.additive\n        ? current.eventKeys.includes(key)\n          ? current.eventKeys.filter((k) => k !== key)\n          : [...current.eventKeys, key]\n        : [key]\n      internal.selection = { ...current, eventKeys }\n    },\n    clearSelection() {\n      internal.selection = EMPTY_SELECTION\n    },\n    setInteractions(patch) {\n      internal.interactions = { ...internal.interactions, ...patch }\n    },\n    setViewSettings(patch) {\n      internal.viewSettings = { ...internal.viewSettings, ...patch }\n    },\n    getVisibleRange() {\n      return state.value.visibleRange\n    },\n    getActiveRange() {\n      return state.value.activeRange\n    },\n    toZoned(date) {\n      return toZonedLib(date, settings.timeZone)\n    },\n    applyProposedUpdate,\n    getIndex() {\n      return index.value\n    },\n    setDrag(drag) {\n      internal.drag = drag\n    },\n    setSlotDraft(draft) {\n      internal.slotDraft = draft\n    },\n  }\n\n  return { state, api, settings }\n}\n\nexport const EventCalendarContextKey: InjectionKey\u003CEventCalendarInstance\u003Cany>> =\n  \u002F\u002F eslint-disable-next-line @typescript-eslint\u002Fno-explicit-any\n  Symbol(\"EventCalendarContext\")\n\n\u002F** Соответствует `useEventCalendar()` оригинала — бросает вне `\u003CEventCalendar>`. *\u002F\nexport function useEventCalendar\u003CTData = unknown>(): EventCalendarInstance\u003CTData> {\n  const instance = inject(EventCalendarContextKey, undefined)\n  if (!instance) {\n    throw new Error(\"useEventCalendar must be used within \u003CEventCalendar>\")\n  }\n  return instance as EventCalendarInstance\u003CTData>\n}\n\n\u002F** Convenience accessor — `instance.settings` is a plain resolved object (v1: not per-prop reactive, see file header). *\u002F\nexport function useEventCalendarSettings\u003C\n  TData = unknown,\n>(): EventCalendarSettings\u003CTData> {\n  return useEventCalendar\u003CTData>().settings\n}\n\nexport const EventCalendarViewContextKey: InjectionKey\u003C{ view: CalendarView }> =\n  Symbol(\"EventCalendarViewContext\")\n\n\u002F** Соответствует `useEventCalendarViewContext()` оригинала — бросает вне вида. *\u002F\nexport function useEventCalendarViewContext(): { view: CalendarView } {\n  const ctx = inject(EventCalendarViewContextKey, undefined)\n  if (!ctx) {\n    throw new Error(\n      \"useEventCalendarViewContext must be used inside a calendar view\"\n    )\n  }\n  return ctx\n}\n\n\u002F\u002F ---------------------------------------------------------------------------\n\u002F\u002F View-layer config: display props + render overrides (EventCalendarViewConfig)\n\u002F\u002F ---------------------------------------------------------------------------\n\nexport interface EventCalendarClassNames {\n  nav?: string\n  toolbar?: string\n  content?: string\n  monthView?: string\n  monthCell?: string\n  timeGrid?: string\n  timeGutter?: string\n  dayColumn?: string\n  allDaySection?: string\n  agendaView?: string\n  event?: string\n  eventTooltip?: string\n  moreIndicator?: string\n  morePopover?: string\n  morePopoverHeader?: string\n  navButton?: string\n  title?: string\n  navTooltip?: string\n  viewSwitcherContent?: string\n  viewSwitcherLabel?: string\n  viewShortcut?: string\n  datePickerContent?: string\n  monthHeader?: string\n  monthDayHeader?: string\n  monthBody?: string\n  monthRow?: string\n  weekNumber?: string\n  monthBarOverlay?: string\n  monthBar?: string\n  monthCellContent?: string\n  monthCellFooter?: string\n  monthDayNumber?: string\n  dayAddButton?: string\n  timeGridHeader?: string\n  timeGutterLabel?: string\n  allDayLabel?: string\n  allDayCell?: string\n  timedChip?: string\n  resourceHeader?: string\n  dragGhost?: string\n  dragCarry?: string\n  dragCarryInvalid?: string\n  dropHint?: string\n  dropIndicator?: string\n  slotDraft?: string\n  resizeHandle?: string\n  resizeGrip?: string\n  noEvents?: string\n  agendaDay?: string\n  agendaDayHeader?: string\n  agendaDayGutter?: string\n  agendaDate?: string\n  agendaDayToggle?: string\n  agendaDayContent?: string\n  agendaItem?: string\n  agendaItemSurface?: string\n  agendaItemToggle?: string\n  agendaDaySummary?: string\n  agendaSummaryDot?: string\n}\n\nexport interface EventCalendarRenderEventProps\u003CTData = unknown> {\n  occurrence: EventCalendarOccurrence\u003CTData>\n  segment: EventCalendarSegment\u003CTData>\n  view: CalendarView\n  isDragging: boolean\n  isSelected: boolean\n}\n\n\u002F** View-layer configuration: display props and render overrides. *\u002F\nexport interface EventCalendarViewConfig\u003CTData = unknown> {\n  scrollToHour: number\n  nowIndicator: boolean\n  interval: number\n  maxEventsPerCell: number | \"auto\"\n  showWeekNumbers: boolean\n  enableShortcuts: boolean\n  shortcutsScope: \"focus-within\" | \"global\"\n  scrollMode: \"contained\" | \"page\"\n  stickyNav: boolean\n  dayClassName?: (day: Date) => string | undefined\n  todayClassName?: string\n  showDayAddButton: boolean\n  scrollbars: \"custom\" | \"native\"\n  navButtonVariant: \"ghost\" | \"outline\" | \"secondary\" | \"default\"\n  navButtonSize: \"sm\" | \"default\"\n  offDays?: boolean | EventCalendarOffDaysConfig\n  classNames?: EventCalendarClassNames\n  components?: Partial\u003CRecord\u003CCalendarView, Component>>\n  renderEvent?: (props: EventCalendarRenderEventProps\u003CTData>) => VNodeChild\n  renderAgendaEvent?: (props: EventCalendarRenderEventProps\u003CTData>) => VNodeChild\n  renderEventTooltip?: (props: {\n    occurrence: EventCalendarOccurrence\u003CTData>\n    segment: EventCalendarSegment\u003CTData>\n    view: CalendarView\n    label: string | undefined\n  }) => VNodeChild\n  renderDragPreview?: (props: { drag: EventCalendarDragState\u003CTData> }) => VNodeChild\n  renderMonthCell?: (props: {\n    day: Date\n    isToday: boolean\n    isOutside: boolean\n    overflowCount: number\n    defaultContent: VNodeChild\n  }) => VNodeChild\n  renderDayColumnBackground?: (props: {\n    day: Date\n    boundsStartMin: number\n    boundsEndMin: number\n    totalMinutes: number\n  }) => VNodeChild\n  renderDayHeader?: (props: {\n    day: Date\n    view: CalendarView\n    isToday: boolean\n  }) => VNodeChild\n  renderTimeGutterSlot?: (props: {\n    time: Date\n    hour: number\n    minute: number\n  }) => VNodeChild\n  renderAllDaySection?: (props: {\n    days: Date[]\n    segments: EventCalendarSegment\u003CTData>[]\n  }) => VNodeChild\n  renderMoreIndicator?: (props: {\n    day: Date\n    count: number\n    segments: EventCalendarSegment\u003CTData>[]\n  }) => VNodeChild\n  renderMoreContent?: (props: {\n    day: Date\n    segments: EventCalendarSegment\u003CTData>[]\n    close: () => void\n  }) => VNodeChild\n  renderAgendaEventDetails?: (\n    occurrence: EventCalendarOccurrence\u003CTData>\n  ) => VNodeChild\n  renderNowIndicator?: (props: { time: Date }) => VNodeChild\n  renderNoEvents?: () => VNodeChild\n  renderResourceHeader?: (props: { resource: EventCalendarResource }) => VNodeChild\n  renderAgendaDayHeader?: (props: {\n    day: Date\n    collapsed: boolean\n    count: number\n    toggle: () => void\n    defaultContent: VNodeChild\n  }) => VNodeChild\n  renderAgendaDaySummary?: (props: {\n    day: Date\n    occurrences: EventCalendarOccurrence\u003CTData>[]\n    count: number\n    expand: () => void\n    defaultContent: VNodeChild\n  }) => VNodeChild\n  dayCountPresets: number[]\n  navTooltips?:\n    | false\n    | {\n        side?: \"top\" | \"bottom\" | \"left\" | \"right\"\n        delay?: number\n        closeDelay?: number\n        timeout?: number\n      }\n  eventTooltip?:\n    | boolean\n    | {\n        side?: \"top\" | \"bottom\" | \"left\" | \"right\"\n        delay?: number\n      }\n  compactEventMinutes: number\n  morePopoverAlign: \"start\" | \"center\" | \"end\"\n  nowIndicatorInterval: number\n  agendaSummaryMaxDots: number\n}\n\nexport const DEFAULT_EVENT_CALENDAR_VIEW_CONFIG: EventCalendarViewConfig = {\n  scrollToHour: 7,\n  nowIndicator: true,\n  interval: 60,\n  maxEventsPerCell: \"auto\",\n  showWeekNumbers: false,\n  enableShortcuts: true,\n  shortcutsScope: \"focus-within\",\n  scrollMode: \"contained\",\n  stickyNav: false,\n  showDayAddButton: false,\n  scrollbars: \"custom\",\n  navButtonVariant: \"ghost\",\n  navButtonSize: \"sm\",\n  dayCountPresets: [5],\n  eventTooltip: false,\n  compactEventMinutes: 45,\n  morePopoverAlign: \"start\",\n  nowIndicatorInterval: 30_000,\n  agendaSummaryMaxDots: 6,\n}\n\nexport const EventCalendarViewConfigContextKey: InjectionKey\u003C\n  EventCalendarViewConfig\u003Cany>\n  \u002F\u002F eslint-disable-next-line @typescript-eslint\u002Fno-explicit-any\n> = Symbol(\"EventCalendarViewConfigContext\")\n\n\u002F** Соответствует `useEventCalendarViewConfig()` оригинала — не бросает, дефолт `DEFAULT_EVENT_CALENDAR_VIEW_CONFIG`. *\u002F\nexport function useEventCalendarViewConfig\u003C\n  TData = unknown,\n>(): EventCalendarViewConfig\u003CTData> {\n  return inject(\n    EventCalendarViewConfigContextKey,\n    DEFAULT_EVENT_CALENDAR_VIEW_CONFIG\n  ) as EventCalendarViewConfig\u003CTData>\n}\n\n\u002F\u002F ---------------------------------------------------------------------------\n\u002F\u002F Gestures — placeholder until event-calendar-dnd.tsx is ported (see file header)\n\u002F\u002F ---------------------------------------------------------------------------\n\nexport interface EventCalendarGestures\u003CTData = unknown> {\n  canResize: boolean\n  beginMove: (e: PointerEvent, segment: EventCalendarSegment\u003CTData>) => void\n  beginResize: (\n    e: PointerEvent,\n    segment: EventCalendarSegment\u003CTData>,\n    edge: \"start\" | \"end\"\n  ) => void\n  beginCreate: (e: PointerEvent, day: Date, allDay: boolean) => void\n  \u002F** Suppresses the trailing click after a real drag; see `event-calendar-dnd.tsx`'s `wasRecentDrag`. *\u002F\n  wasRecentDrag: () => boolean\n  \u002F** Marks a chip pointerdown so a non-drag press does not trigger create-on-click; see `markChipPress`. *\u002F\n  markChipPress: () => void\n}\n\nfunction noopGestures\u003CTData = unknown>(): EventCalendarGestures\u003CTData> {\n  return {\n    canResize: false,\n    beginMove: () => {},\n    beginResize: () => {},\n    beginCreate: () => {},\n    wasRecentDrag: () => false,\n    markChipPress: () => {},\n  }\n}\n\nexport const EventCalendarGesturesContextKey: InjectionKey\u003C\n  EventCalendarGestures\u003Cany>\n  \u002F\u002F eslint-disable-next-line @typescript-eslint\u002Fno-explicit-any\n> = Symbol(\"EventCalendarGesturesContext\")\n\n\u002F** Соответствует `useEventCalendarGestures()` оригинала — не бросает, дефолт no-op до портирования dnd. *\u002F\nexport function useEventCalendarGestures\u003C\n  TData = unknown,\n>(): EventCalendarGestures\u003CTData> {\n  return inject(\n    EventCalendarGesturesContextKey,\n    noopGestures,\n    true\n  ) as EventCalendarGestures\u003CTData>\n}\n",{"path":4847,"type":480,"target":4848,"content":4849},"src\u002Freui\u002Fevent-calendar\u002Fdnd.ts","components\u002Freui\u002Fevent-calendar\u002Fdnd.ts","\u002F**\n * Порт ReUI event-calendar-dnd.tsx (MIT) — переиспользуемая композиция\n * pointer-event хендлеров на голом DOM.\n *\n * ВАЖНО, отличается от Kanban\u002FSortable\u002FDataGrid: оригинал `event-calendar-\n * dnd.tsx` НЕ использует dnd-kit вообще — это уже framework-агностичный\n * движок на `pointerdown`\u002F`pointermove`\u002F`pointerup`, window-листенерах и\n * ручной геометрии (`getBoundingClientRect`). ADR-002 (dnd-kit -> Pragmatic\n * Drag and Drop) сюда НЕ применяется: заменять нечего, переносится\n * оригинальная pointer-математика почти дословно, framework-специфичная\n * прослойка — только вызов `instance.api.*` вместо React setState и\n * `provide()` вместо React Context.\n *\n * ponytail — сознательно НЕ перенесено (граница эквивалентности ADR-002\n * прямо разрешает расхождение в \"физике\"\u002Fвизуальной обратной связи, только\n * итоговая дата\u002Fмодель обязаны совпасть):\n *  - Курсор-клон события (`createCarry`\u002F`positionCarry`) и подсказка\n *    \"нельзя бросить\" (`updateHint`) — vanilla-DOM оверлеи, чисто\n *    визуальные, не влияют на itogovoe состояние. Добавить как есть из\n *    оригинала, если понадобится визуальное качество перетаскивания.\n *  - Автоскролл контейнера (`autoScroll`) — у наших кейсов вся сетка\n *    помещается без прокрутки; `pointerMinutes` здесь не компенсирует\n *    scrollTop (дельта всегда 0).\n *  - Touch\u002Flong-press активация (`touchDelayMs`) — интеракционный гейт\n *    проверяет только мышь; активация происходит сразу по dnd-порогу.\n *  - `beginBlockedGesture` (визуальный \"not-allowed\" на readOnly\u002Fdisabled\n *    событии) — ни один текущий кейс не имеет readOnly-событий;\n *    `canDrag`\u002F`canResize` просто отказывают без обратной связи.\n *  - Drag-create (выделение слота пустым перетаскиванием) — `beginCreate`\n *    существует и работает, но ни один вид (`MonthView`\u002F`TimeGrid`\u002F\n *    `ResourceView`) пока не вызывает его из `pointerdown` пустой ячейки\n *    (там сейчас только `onSlotClick` по клику) — добавить вызов\n *    `gestures.beginCreate` в `onPointerDown` дня\u002Fколонки, когда появится\n *    кейс с созданием событий перетаскиванием.\n * `computeProposal` (слой координата -> дата\u002Fвремя, дискретный по дням и\n * непрерывный по минутам) перенесён дословно — это ядро, которое обязано\n * дать идентичный итог с оригиналом.\n *\u002F\nimport type {\n  EventCalendarInstance,\n  EventCalendarGestures,\n} from \".\u002Fcontext\"\nimport { snapMinutes, toZoned, zonedStartOfDay } from \".\u002Flib\"\nimport type {\n  EventCalendarProposedUpdate,\n  EventCalendarSegment,\n} from \".\u002Ftypes\"\nimport { addDays, addMinutes, differenceInCalendarDays } from \"date-fns\"\n\nconst EVENT_CALENDAR_ACTIVATION = {\n  moveDistancePx: 5,\n  createDistancePx: 4,\n} as const\n\ntype GestureKind = \"move\" | \"resize-start\" | \"resize-end\" | \"create\"\n\ninterface TimeColumnRect {\n  day: Date\n  rect: DOMRect\n  boundsStartMin: number\n  boundsEndMin: number\n  resourceId?: string\n}\n\ninterface DayCellRect {\n  day: Date\n  rect: DOMRect\n}\n\ninterface Surface {\n  columns: TimeColumnRect[]\n  cells: DayCellRect[]\n}\n\nlet lastGestureEndedAt = 0\nfunction wasRecentDrag(): boolean {\n  return performance.now() - lastGestureEndedAt \u003C 250\n}\n\nlet lastChipPressAt = 0\nfunction markChipPress(): void {\n  lastChipPressAt = performance.now()\n  window.addEventListener(\n    \"pointerup\",\n    () => {\n      lastChipPressAt = performance.now()\n    },\n    { once: true, capture: true }\n  )\n}\nfunction wasRecentChipPress(): boolean {\n  return performance.now() - lastChipPressAt \u003C 300\n}\n\nconst activeGestureCancels = new Set\u003C() => void>()\nfunction cancelActiveEventCalendarGestures(): void {\n  for (const cancel of [...activeGestureCancels]) cancel()\n}\n\nfunction collectSurface(origin: HTMLElement): Surface {\n  const root =\n    origin.closest\u003CHTMLElement>(\"[data-slot=event-calendar-time-grid]\") ??\n    origin.closest\u003CHTMLElement>(\"[data-slot=event-calendar-resource-view]\") ??\n    origin.closest\u003CHTMLElement>(\"[data-slot=event-calendar-month-view]\") ??\n    origin.closest\u003CHTMLElement>(\"[data-slot=event-calendar]\") ??\n    null\n\n  const columns: TimeColumnRect[] = []\n  const cells: DayCellRect[] = []\n  if (root) {\n    for (const el of root.querySelectorAll\u003CHTMLElement>(\"[data-ec-day]\")) {\n      const day = new Date(Number(el.dataset.ecDay))\n      if (el.dataset.ecBoundsStart !== undefined) {\n        columns.push({\n          day,\n          rect: el.getBoundingClientRect(),\n          boundsStartMin: Number(el.dataset.ecBoundsStart),\n          boundsEndMin: Number(el.dataset.ecBoundsEnd),\n          resourceId: el.dataset.ecResource,\n        })\n      } else {\n        cells.push({ day, rect: el.getBoundingClientRect() })\n      }\n    }\n  }\n  return { columns, cells }\n}\n\nfunction findColumn(surface: Surface, clientX: number): TimeColumnRect | undefined {\n  let best: TimeColumnRect | undefined\n  for (const col of surface.columns) {\n    if (clientX >= col.rect.left && clientX \u003C col.rect.right) return col\n    if (!best) best = col\n    const bestDist = Math.min(Math.abs(clientX - best.rect.left), Math.abs(clientX - best.rect.right))\n    const dist = Math.min(Math.abs(clientX - col.rect.left), Math.abs(clientX - col.rect.right))\n    if (dist \u003C bestDist) best = col\n  }\n  return best\n}\n\nfunction findCell(surface: Surface, x: number, y: number): DayCellRect | undefined {\n  return surface.cells.find(\n    (cell) => x >= cell.rect.left && x \u003C cell.rect.right && y >= cell.rect.top && y \u003C cell.rect.bottom\n  )\n}\n\n\u002F\u002F ponytail: no scroll-delta compensation (see file header) — the grid never\n\u002F\u002F scrolls in our cases, so the raw client Y maps straight onto the column.\nfunction pointerMinutes(col: TimeColumnRect, clientY: number): number {\n  const boundsMinutes = col.boundsEndMin - col.boundsStartMin\n  const pxPerMinute = col.rect.height \u002F Math.max(1, boundsMinutes)\n  const y = clientY - col.rect.top\n  return col.boundsStartMin + y \u002F pxPerMinute\n}\n\ninterface BeginGestureConfig\u003CTData> {\n  instance: EventCalendarInstance\u003CTData>\n  kind: GestureKind\n  origin: HTMLElement\n  startEvent: PointerEvent\n  segment?: EventCalendarSegment\u003CTData>\n  createDay?: Date\n  createAllDay?: boolean\n}\n\nfunction beginGesture\u003CTData>(config: BeginGestureConfig\u003CTData>) {\n  const { instance, kind, origin, startEvent, segment } = config\n  const { settings, api } = instance\n  const timeZone = settings.timeZone\n  const snap = settings.snapDuration\n  const activation = { ...EVENT_CALENDAR_ACTIVATION, ...settings.activation }\n  const startX = startEvent.clientX\n  const startY = startEvent.clientY\n  const pointerId = startEvent.pointerId\n\n  let active = kind.startsWith(\"resize\")\n  let surface: Surface | null = active ? collectSurface(origin) : null\n  let lastProposalKey = \"\"\n\n  const occurrence = segment?.occurrence\n  const isBar = occurrence\n    ? occurrence.allDay || occurrence.end.getTime() - occurrence.start.getTime() > 24 * 60 * 60 * 1000\n    : false\n\n  \u002F\u002F Preserve the grab offset so the event does not jump to the pointer.\n  let grabOffsetMin = 0\n  let grabLeadMs = 0\n  let grabSegDurationMs = occurrence ? occurrence.end.getTime() - occurrence.start.getTime() : 0\n  let grabDayOffset = 0\n\n  const activationDistance = kind === \"create\" ? activation.createDistancePx : activation.moveDistancePx\n\n  const activate = () => {\n    if (active) return\n    active = true\n    surface = collectSurface(origin)\n    if (kind === \"move\" && occurrence) {\n      const grabCell = findCell(surface, startX, startY)\n      if (grabCell) {\n        const originDay = zonedStartOfDay(occurrence.start, timeZone)\n        const lastDay = zonedStartOfDay(\n          new Date(Math.max(occurrence.end.getTime() - 1, occurrence.start.getTime())),\n          timeZone\n        )\n        const offset = differenceInCalendarDays(zonedStartOfDay(grabCell.day, timeZone), originDay)\n        if (offset >= 0 && offset \u003C= differenceInCalendarDays(lastDay, originDay)) {\n          grabDayOffset = offset\n        }\n      }\n      if (surface.columns.length > 0 && !isBar) {\n        const col = findColumn(surface, startX)\n        if (col) {\n          const colDayStart = zonedStartOfDay(col.day, timeZone)\n          const segStartMs = Math.max(occurrence.start.getTime(), colDayStart.getTime())\n          grabLeadMs = segStartMs - occurrence.start.getTime()\n          grabSegDurationMs = Math.min(occurrence.end.getTime(), addDays(colDayStart, 1).getTime()) - segStartMs\n          grabOffsetMin = pointerMinutes(col, startY) - (segStartMs - colDayStart.getTime()) \u002F 60000\n        }\n      }\n    }\n  }\n\n  let createAnchorMin: number | null = null\n\n  const computeProposal = (\n    e: PointerEvent\n  ): { start: Date; end: Date; allDay: boolean; dayGranular?: boolean; resourceId?: string } | null => {\n    if (!surface) return null\n\n    \u002F\u002F ---- create: select a slot range\n    if (kind === \"create\") {\n      if (config.createAllDay || surface.columns.length === 0) {\n        const anchor = zonedStartOfDay(config.createDay!, timeZone)\n        const cell = findCell(surface, e.clientX, e.clientY)\n        const target = cell ? zonedStartOfDay(cell.day, timeZone) : anchor\n        const start = anchor \u003C= target ? anchor : target\n        const end = addDays(anchor \u003C= target ? target : anchor, 1)\n        return { start, end, allDay: true, dayGranular: true }\n      }\n      const col = findColumn(surface, startX)\n      if (!col) return null\n      if (createAnchorMin === null) createAnchorMin = snapMinutes(pointerMinutes(col, startY), snap)\n      const anchorMin = createAnchorMin\n      const curMin = snapMinutes(pointerMinutes(col, e.clientY), snap)\n      const lo = Math.max(col.boundsStartMin, Math.min(anchorMin, curMin))\n      const hi = Math.min(col.boundsEndMin, Math.max(anchorMin, curMin, lo + snap))\n      const dayStart = zonedStartOfDay(col.day, timeZone)\n      return { start: addMinutes(dayStart, lo), end: addMinutes(dayStart, hi), allDay: false, resourceId: col.resourceId }\n    }\n\n    if (!occurrence) return null\n    const durationMs = occurrence.end.getTime() - occurrence.start.getTime()\n\n    \u002F\u002F ---- day-granularity: month cells and bars in the all-day row\n    const overCell = findCell(surface, e.clientX, e.clientY)\n\n    if (kind === \"move\" && !isBar && surface.columns.length > 0 && overCell !== undefined) {\n      const targetDay = zonedStartOfDay(overCell.day, timeZone)\n      return { start: targetDay, end: addDays(targetDay, 1), allDay: true, dayGranular: true }\n    }\n\n    const useCells = surface.columns.length === 0 || (isBar && overCell !== undefined)\n\n    if (useCells) {\n      const cell = overCell ?? findCell(surface, startX, startY)\n      if (!cell) return null\n      const targetDay = zonedStartOfDay(cell.day, timeZone)\n      if (kind === \"move\") {\n        const originDay = zonedStartOfDay(occurrence.start, timeZone)\n        const delta = differenceInCalendarDays(targetDay, originDay) - grabDayOffset\n        const start = addDays(toZoned(occurrence.start, timeZone), delta)\n        return { start, end: new Date(start.getTime() + durationMs), allDay: occurrence.allDay, dayGranular: true }\n      }\n      if (kind === \"resize-start\") {\n        const time = occurrence.start.getTime() - zonedStartOfDay(occurrence.start, timeZone).getTime()\n        const start = new Date(targetDay.getTime() + time)\n        if (start >= occurrence.end) return null\n        return { start, end: occurrence.end, allDay: occurrence.allDay, dayGranular: true }\n      }\n      const time = occurrence.allDay ? 0 : occurrence.end.getTime() - zonedStartOfDay(occurrence.end, timeZone).getTime()\n      const end = occurrence.allDay\n        ? addDays(targetDay, 1)\n        : new Date(addDays(targetDay, time > 0 ? 0 : 1).getTime() + time)\n      if (end \u003C= occurrence.start) return null\n      return { start: occurrence.start, end, allDay: occurrence.allDay, dayGranular: true }\n    }\n\n    \u002F\u002F ---- minute-granularity: time-grid columns\n    const col = findColumn(surface, e.clientX)\n    if (!col) return null\n    const dayStart = zonedStartOfDay(col.day, timeZone)\n    const rawMin = pointerMinutes(col, e.clientY)\n\n    if (kind === \"move\") {\n      const newStartMin = snapMinutes(rawMin - grabOffsetMin, snap)\n      const chipDurationMin = Math.round(grabSegDurationMs \u002F 60000)\n      const clamped = Math.min(Math.max(newStartMin, col.boundsStartMin), col.boundsEndMin - chipDurationMin)\n      const start = new Date(addMinutes(dayStart, clamped).getTime() - grabLeadMs)\n      return { start, end: new Date(start.getTime() + durationMs), allDay: false, resourceId: col.resourceId }\n    }\n\n    const min = snapMinutes(rawMin, snap)\n    const occStartMinInCol = Math.round((occurrence.start.getTime() - dayStart.getTime()) \u002F 60000)\n    const occEndMinInCol = Math.round((occurrence.end.getTime() - dayStart.getTime()) \u002F 60000)\n    if (kind === \"resize-start\") {\n      const clamped = Math.min(Math.max(min, col.boundsStartMin), Math.min(occEndMinInCol - snap, col.boundsEndMin))\n      const start = addMinutes(dayStart, clamped)\n      if (start >= occurrence.end) return null\n      return { start, end: occurrence.end, allDay: false }\n    }\n    const clamped = Math.max(Math.min(min, col.boundsEndMin), Math.max(occStartMinInCol + snap, col.boundsStartMin))\n    const end = addMinutes(dayStart, clamped)\n    if (end \u003C= occurrence.start) return null\n    return { start: occurrence.start, end, allDay: false }\n  }\n\n  const applyProposal = (e: PointerEvent) => {\n    const proposal = computeProposal(e)\n    if (!proposal) return\n    const key = `${proposal.start.getTime()}-${proposal.end.getTime()}-${proposal.allDay}-${proposal.resourceId ?? \"\"}`\n    if (key === lastProposalKey) return\n    lastProposalKey = key\n\n    if (kind === \"create\") {\n      const draft = { ...proposal, view: instance.state.value.view }\n      if (settings.canSelectSlot && !settings.canSelectSlot(draft)) return\n      api.setSlotDraft(draft)\n      return\n    }\n    const update: EventCalendarProposedUpdate\u003CTData> = {\n      event: occurrence!.event,\n      occurrence: occurrence!,\n      ...proposal,\n      source: kind === \"move\" ? \"drag\" : (kind as \"resize-start\" | \"resize-end\"),\n    }\n    const valid = settings.canDropEvent ? settings.canDropEvent(update) : true\n    api.setDrag({\n      kind: kind === \"move\" ? \"move\" : (kind as \"resize-start\" | \"resize-end\"),\n      occurrence: occurrence!,\n      proposedStart: proposal.start,\n      proposedEnd: proposal.end,\n      proposedAllDay: proposal.allDay,\n      proposedDayGranular: proposal.dayGranular ?? false,\n      proposedResourceId: proposal.resourceId,\n      valid,\n    })\n  }\n\n  let finished = false\n  const cleanup = () => {\n    if (finished) return\n    finished = true\n    activeGestureCancels.delete(cancel)\n    window.removeEventListener(\"pointermove\", onPointerMove)\n    window.removeEventListener(\"pointerup\", onPointerUp)\n    window.removeEventListener(\"pointercancel\", onCancel)\n    window.removeEventListener(\"blur\", onWindowBlur)\n    window.removeEventListener(\"keydown\", onKeyDown, true)\n  }\n\n  const cancel = () => {\n    cleanup()\n    if (active) {\n      lastGestureEndedAt = performance.now()\n      api.setDrag(null)\n      api.setSlotDraft(null)\n    }\n  }\n\n  const onKeyDown = (e: KeyboardEvent) => {\n    if (e.key === \"Escape\") {\n      e.stopPropagation()\n      cancel()\n    }\n  }\n  const onWindowBlur = () => cancel()\n\n  const onPointerMove = (e: PointerEvent) => {\n    if (e.pointerId !== pointerId) return\n    if (!active) {\n      const distance = Math.hypot(e.clientX - startX, e.clientY - startY)\n      if (distance \u003C activationDistance) return\n      activate()\n    }\n    applyProposal(e)\n  }\n\n  const onPointerUp = (e: PointerEvent) => {\n    if (e.pointerId !== pointerId) return\n    cleanup()\n    if (!active) return\n    lastGestureEndedAt = performance.now()\n\n    const state = instance.state.value\n    if (kind === \"create\") {\n      const draft = state.slotDraft\n      api.setSlotDraft(null)\n      if (draft) {\n        api.select({ slot: { start: draft.start, end: draft.end, allDay: draft.allDay } })\n        settings.onSelectSlot?.(draft)\n      }\n      return\n    }\n    const drag = state.drag\n    api.setDrag(null)\n    if (!drag || !occurrence) return\n    const unchanged =\n      drag.proposedStart.getTime() === occurrence.start.getTime() &&\n      drag.proposedEnd.getTime() === occurrence.end.getTime() &&\n      (drag.proposedResourceId === undefined || drag.proposedResourceId === occurrence.event.resourceId)\n    if (unchanged) return\n    api.applyProposedUpdate({\n      event: occurrence.event,\n      occurrence,\n      start: drag.proposedStart,\n      end: drag.proposedEnd,\n      allDay: drag.proposedAllDay,\n      resourceId: drag.proposedResourceId,\n      source: kind === \"move\" ? \"drag\" : (kind as \"resize-start\" | \"resize-end\"),\n    })\n  }\n\n  const onCancel = (e: PointerEvent) => {\n    if (e.pointerId !== pointerId) return\n    cancel()\n  }\n\n  window.addEventListener(\"pointermove\", onPointerMove)\n  window.addEventListener(\"pointerup\", onPointerUp)\n  window.addEventListener(\"pointercancel\", onCancel)\n  if (active) window.addEventListener(\"blur\", onWindowBlur)\n  window.addEventListener(\"keydown\", onKeyDown, true)\n  activeGestureCancels.add(cancel)\n}\n\n\u002F** Соответствует `useEventCalendarGestures()` оригинала — построен один раз в `EventCalendar.vue` и провайден через `EventCalendarGesturesContextKey`. *\u002F\nexport function createEventCalendarGestures\u003CTData = unknown>(\n  instance: EventCalendarInstance\u003CTData>\n): EventCalendarGestures\u003CTData> {\n  const canDrag = (segment: EventCalendarSegment\u003CTData>): boolean => {\n    const { interactions } = instance.state.value\n    const event = segment.occurrence.event\n    return interactions.drag && !event.readOnly && event.draggable !== false\n  }\n  const canResizeSegment = (segment: EventCalendarSegment\u003CTData>): boolean => {\n    const { interactions } = instance.state.value\n    const event = segment.occurrence.event\n    return interactions.resize && !event.readOnly && event.resizable !== false\n  }\n\n  return {\n    \u002F\u002F ponytail: static `true` (see EventCalendarGestures — Event.vue does not\n    \u002F\u002F read this field; it derives handle visibility from state.interactions\n    \u002F\u002F itself). Kept only to satisfy the interface.\n    canResize: true,\n    beginMove(e, segment) {\n      if (e.button !== 0 || !canDrag(segment)) return\n      beginGesture({ instance, kind: \"move\", origin: e.currentTarget as HTMLElement, startEvent: e, segment })\n    },\n    beginResize(e, segment, edge) {\n      if (e.button !== 0 || !canResizeSegment(segment)) return\n      \u002F\u002F Must not bubble: the resize handle is a DOM child of the chip's own\n      \u002F\u002F button, which has its own pointerdown -> beginMove listener (see\n      \u002F\u002F EventCalendarEvent.vue). Without this, grabbing the handle starts a\n      \u002F\u002F move AND a resize gesture at once.\n      e.stopPropagation()\n      e.preventDefault()\n      beginGesture({\n        instance,\n        kind: edge === \"start\" ? \"resize-start\" : \"resize-end\",\n        origin: e.currentTarget as HTMLElement,\n        startEvent: e,\n        segment,\n      })\n    },\n    beginCreate(e, day, allDay) {\n      if (e.button !== 0 || !instance.state.value.interactions.selectSlot) return\n      beginGesture({ instance, kind: \"create\", origin: e.currentTarget as HTMLElement, startEvent: e, createDay: day, createAllDay: allDay })\n    },\n    wasRecentDrag,\n    markChipPress,\n  }\n}\n\nexport { cancelActiveEventCalendarGestures, wasRecentChipPress }\n",{"path":4851,"type":480,"target":4852,"content":4853},"src\u002Freui\u002Fevent-calendar\u002Fi18n.ts","components\u002Freui\u002Fevent-calendar\u002Fi18n.ts","\u002F\u002F Title: Event Calendar I18n\n\u002F\u002F Description: Default UI texts, date-format strings, and formatter functions for the event calendar, fully overridable per key.\n\u002F\u002F Port of ReUI event-calendar-i18n.tsx (MIT) — pure TS\u002Fdate-fns, ported verbatim.\n\nimport type { CalendarView, EventCalendarDateRange } from \".\u002Ftypes\"\nimport {\n  format,\n  isSameMonth,\n  isSameYear,\n  subMilliseconds,\n  type Locale,\n} from \"date-fns\"\n\ninterface EventCalendarI18nConfig {\n  labels: {\n    today: string\n    previous: string\n    next: string\n    addEvent: string\n    allDay: string\n    more: (count: number) => string\n    noEvents: string\n    loading: string\n    event: string\n    events: (count: number) => string\n    selectView: string\n    week: (weekNumber: number) => string\n    resources: string\n    goToDate: string\n    \u002F** Cursor hint while a drag\u002Fresize hovers a rejected position. *\u002F\n    dropNotAllowed: string\n    \u002F** Aria-label suffix on chip segments that continue past the cell. *\u002F\n    continues: string\n    \u002F** Agenda label for the first day of a multi-day event. *\u002F\n    timeFrom: (time: string) => string\n    \u002F** Agenda label for the last day of a multi-day event. *\u002F\n    timeUntil: (time: string) => string\n    \u002F** View-switcher shortcut hint characters, per view. *\u002F\n    viewShortcuts: Record\u003CCalendarView, string>\n    \u002F** Aria-label of the agenda day collapse\u002Fexpand toggle. *\u002F\n    toggleDayEvents: (count: number, expanded: boolean) => string\n    \u002F** Aria-label of the agenda event details toggle. *\u002F\n    eventDetails: (title: string) => string\n    \u002F** Compact \"+N\" overflow (agenda summary dot stack). *\u002F\n    moreCompact: (count: number) => string\n    \u002F** Joins a bounded from-to time span. *\u002F\n    timeRange: (from: string, to: string) => string\n  }\n  viewNames: {\n    month: string\n    week: string\n    day: string\n    days: (count: number) => string\n    agenda: string\n    resource: string\n  }\n  \u002F** date-fns format strings, applied with the calendar `locale`. *\u002F\n  formats: {\n    monthTitle: string\n    \u002F** Undefined = smart cross-month range via functions.formatTitle. *\u002F\n    weekTitle?: string\n    dayTitle: string\n    \u002F** Undefined = smart range label via functions.formatTitle. *\u002F\n    agendaTitle?: string\n    monthDayHeader: string\n    \u002F** Narrow variant used by the month view below the compact breakpoint. *\u002F\n    monthDayHeaderNarrow: string\n    timeGridDayHeader: string\n    agendaDayHeader: string\n    \u002F** Agenda date-gutter day number. *\u002F\n    agendaDayNumber: string\n    \u002F** Agenda date-gutter weekday label. *\u002F\n    agendaWeekday: string\n    \u002F** \"+N more\" popover day header. *\u002F\n    moreDayHeader: string\n    \u002F** Month cell aria-label date. *\u002F\n    monthCellAriaLabel: string\n    \u002F** Time-grid day column aria-label date. *\u002F\n    dayAria: string\n    \u002F** Undefined = the resource view title falls back to dayTitle. *\u002F\n    resourceTitle?: string\n    timeGutter: string\n    \u002F** Sub-hour gutter labels (interval below 60 minutes). *\u002F\n    timeGutterMinute: string\n    eventTime: string\n    monthCellDay: string\n  }\n  functions: {\n    formatTitle: (\n      view: CalendarView,\n      ctx: {\n        date: Date\n        activeRange: EventCalendarDateRange\n        visibleRange: EventCalendarDateRange\n        locale?: Locale\n      }\n    ) => string\n    formatEventTime: (\n      start: Date,\n      end: Date,\n      allDay: boolean,\n      \u002F** date-fns options (the calendar `locale`); trailing so a 3-arg override still fits. *\u002F\n      opts?: { locale?: Locale }\n    ) => string\n    formatDayRange: (\n      range: EventCalendarDateRange,\n      opts?: { locale?: Locale }\n    ) => string\n    \u002F** Chip native tooltip text; return undefined to drop the attribute. *\u002F\n    formatEventLabel?: (title: string, timeLabel: string) => string | undefined\n    \u002F** Chip aria-label composition. *\u002F\n    formatEventAriaLabel?: (\n      title: string,\n      timeLabel: string,\n      continues: boolean\n    ) => string\n  }\n}\n\nconst DEFAULT_LABELS: EventCalendarI18nConfig[\"labels\"] = {\n  today: \"Today\",\n  previous: \"Previous\",\n  next: \"Next\",\n  addEvent: \"Add event\",\n  allDay: \"All day\",\n  more: (count) => `+${count} more`,\n  noEvents: \"No events\",\n  loading: \"Loading events\",\n  event: \"event\",\n  events: (count) => (count === 1 ? \"1 event\" : `${count} events`),\n  selectView: \"Select view\",\n  week: (weekNumber) => `W${weekNumber}`,\n  resources: \"Resources\",\n  goToDate: \"Go to date\",\n  dropNotAllowed: \"Can't place here\",\n  continues: \"continues\",\n  timeFrom: (time) => `From ${time}`,\n  timeUntil: (time) => `Until ${time}`,\n  viewShortcuts: {\n    month: \"M\",\n    week: \"W\",\n    day: \"D\",\n    days: \"5\",\n    agenda: \"A\",\n    resource: \"G\",\n  },\n  toggleDayEvents: (count) => (count === 1 ? \"1 event\" : `${count} events`),\n  eventDetails: (title) => title,\n  moreCompact: (count) => `+${count}`,\n  timeRange: (from, to) => `${from} - ${to}`,\n}\n\nconst DEFAULT_VIEW_NAMES: EventCalendarI18nConfig[\"viewNames\"] = {\n  month: \"Month\",\n  week: \"Week\",\n  day: \"Day\",\n  days: (count) => (count === 1 ? \"1 day\" : `${count} days`),\n  agenda: \"Agenda\",\n  resource: \"Time Grid\",\n}\n\nconst DEFAULT_FORMATS: EventCalendarI18nConfig[\"formats\"] = {\n  monthTitle: \"MMMM yyyy\",\n  weekTitle: undefined,\n  dayTitle: \"EEEE, MMMM d, yyyy\",\n  agendaTitle: undefined,\n  monthDayHeader: \"EEE\",\n  monthDayHeaderNarrow: \"EEEEE\",\n  timeGridDayHeader: \"EEE d\",\n  agendaDayHeader: \"EEEE, MMMM d\",\n  agendaDayNumber: \"d\",\n  agendaWeekday: \"EEE\",\n  moreDayHeader: \"EEEE, MMMM d\",\n  monthCellAriaLabel: \"PPPP\",\n  dayAria: \"PPPP\",\n  resourceTitle: undefined,\n  timeGutter: \"h a\",\n  timeGutterMinute: \"h:mm a\",\n  eventTime: \"h:mm a\",\n  monthCellDay: \"d\",\n}\n\n\u002F**\n * Default formatting functions BOUND to a config's labels\u002Fformats, so that\n * `formats` overrides flow into the default renderers (a consumer overriding\n * formats.monthTitle without replacing formatTitle still sees it applied).\n *\u002F\nfunction makeDefaultFunctions(\n  cfg: Pick\u003CEventCalendarI18nConfig, \"labels\" | \"formats\">\n): EventCalendarI18nConfig[\"functions\"] {\n  return {\n    formatTitle: (view, { date, activeRange, locale }) => {\n      const opts = { locale }\n      if (view === \"month\") {\n        return format(date, cfg.formats.monthTitle, opts)\n      }\n      if (view === \"resource\") {\n        return format(\n          date,\n          cfg.formats.resourceTitle ?? cfg.formats.dayTitle,\n          opts\n        )\n      }\n      if (view === \"day\") {\n        return format(date, cfg.formats.dayTitle, opts)\n      }\n      if (view === \"week\" && cfg.formats.weekTitle) {\n        return format(date, cfg.formats.weekTitle, opts)\n      }\n      if (view === \"agenda\" && cfg.formats.agendaTitle) {\n        return format(date, cfg.formats.agendaTitle, opts)\n      }\n      \u002F\u002F week \u002F days \u002F agenda: smart range label, last day is activeRange.end - 1ms.\n      \u002F\u002F subMilliseconds keeps the zoned date type (a plain new Date(ms)\n      \u002F\u002F would flip the label to the machine zone near midnight)\n      const rangeEnd = subMilliseconds(activeRange.end, 1)\n      const start = activeRange.start\n      if (isSameMonth(start, rangeEnd)) {\n        return `${format(start, \"MMMM d\", opts)} - ${format(rangeEnd, \"d, yyyy\", opts)}`\n      }\n      if (isSameYear(start, rangeEnd)) {\n        return `${format(start, \"MMM d\", opts)} - ${format(rangeEnd, \"MMM d, yyyy\", opts)}`\n      }\n      return `${format(start, \"MMM d, yyyy\", opts)} - ${format(rangeEnd, \"MMM d, yyyy\", opts)}`\n    },\n    formatEventTime: (start, end, allDay, opts) => {\n      if (allDay) return cfg.labels.allDay\n      const fmt = cfg.formats.eventTime\n      \u002F\u002F Multi-day timed events carry the date on both sides. Compare calendar\n      \u002F\u002F days off the last rendered instant (end is exclusive, so a 14:00 to\n      \u002F\u002F midnight event still ends on the start day). Elapsed ms would miss an\n      \u002F\u002F exactly-24h event and a DST day that only runs 23 hours.\n      const lastInstant =\n        end.getTime() - 1 >= start.getTime() ? subMilliseconds(end, 1) : start\n      if (format(start, \"yyyy-MM-dd\") !== format(lastInstant, \"yyyy-MM-dd\")) {\n        return `${format(start, `MMM d, ${fmt}`, opts)} - ${format(end, `MMM d, ${fmt}`, opts)}`\n      }\n      return `${format(start, fmt, opts)} - ${format(end, fmt, opts)}`\n    },\n    formatDayRange: (range, opts) => {\n      \u002F\u002F subMilliseconds keeps the zoned date type, same reason as formatTitle\n      const rangeEnd = subMilliseconds(range.end, 1)\n      return `${format(range.start, \"MMM d\", opts)} - ${format(rangeEnd, \"MMM d\", opts)}`\n    },\n  }\n}\n\nconst DEFAULT_EVENT_CALENDAR_I18N: EventCalendarI18nConfig = {\n  labels: DEFAULT_LABELS,\n  viewNames: DEFAULT_VIEW_NAMES,\n  formats: DEFAULT_FORMATS,\n  functions: makeDefaultFunctions({\n    labels: DEFAULT_LABELS,\n    formats: DEFAULT_FORMATS,\n  }),\n}\n\n\u002F**\n * One level deeper than `Partial`, because the merge below is per nested\n * section: overriding a single label must not force a consumer to restate the\n * other 22. Unknown keys are still rejected by the excess property check.\n *\u002F\ntype EventCalendarI18nOverrides = {\n  [K in keyof EventCalendarI18nConfig]?: Partial\u003CEventCalendarI18nConfig[K]>\n}\n\n\u002F**\n * Shallow merge per nested object, matching the filters.tsx i18n contract:\n * a partial override replaces individual keys, never whole sections. Default\n * functions are re-bound to the MERGED labels\u002Fformats; explicit `functions`\n * overrides still win.\n *\u002F\nfunction mergeEventCalendarI18n(\n  overrides?: EventCalendarI18nOverrides\n): EventCalendarI18nConfig {\n  if (!overrides) return DEFAULT_EVENT_CALENDAR_I18N\n  const labels = { ...DEFAULT_LABELS, ...overrides.labels }\n  const viewNames = { ...DEFAULT_VIEW_NAMES, ...overrides.viewNames }\n  const formats = { ...DEFAULT_FORMATS, ...overrides.formats }\n  return {\n    labels,\n    viewNames,\n    formats,\n    functions: {\n      ...makeDefaultFunctions({ labels, formats }),\n      ...overrides.functions,\n    },\n  }\n}\n\nexport { DEFAULT_EVENT_CALENDAR_I18N, mergeEventCalendarI18n }\nexport type { EventCalendarI18nConfig, EventCalendarI18nOverrides }\n",{"path":4855,"type":480,"target":4856,"content":4857},"src\u002Freui\u002Fevent-calendar\u002Findex.ts","components\u002Freui\u002Fevent-calendar\u002Findex.ts","\u002F\u002F Примечание: lib.ts\u002Frecurrence.ts НЕ реэкспортируются целиком отсюда — это\n\u002F\u002F внутренняя чистая математика (buildEventIndex, expandRecurrence и т.п.),\n\u002F\u002F имена которой совпадают с одноимёнными помощниками reui\u002Fgantt (общее\n\u002F\u002F происхождение в апстриме). `export *` из обоих барелей дал бы коллизию в\n\u002F\u002F публичном API @revueui\u002Fui (тот же приём, что уже применён в reui\u002Fkanban\n\u002F\u002F для useIsOverlay\u002FIsOverlayContextKey). Остальные файлы event-calendar\n\u002F\u002F импортируют их напрямую через относительный путь (\".\u002Flib\", \".\u002Frecurrence\").\nexport * from \".\u002Ftypes\"\nexport * from \".\u002Fcontext\"\nexport { default as EventCalendar } from \".\u002FEventCalendar.vue\"\nexport { default as EventCalendarContent } from \".\u002FEventCalendarContent.vue\"\nexport { default as EventCalendarNav } from \".\u002FEventCalendarNav.vue\"\nexport { default as EventCalendarEvent } from \".\u002FEventCalendarEvent.vue\"\nexport { default as EventCalendarMonthView } from \".\u002FEventCalendarMonthView.vue\"\nexport { default as EventCalendarTimeGrid } from \".\u002FEventCalendarTimeGrid.vue\"\nexport { default as EventCalendarWeekView } from \".\u002FEventCalendarWeekView.vue\"\nexport { default as EventCalendarDayView } from \".\u002FEventCalendarDayView.vue\"\nexport { default as EventCalendarDaysView } from \".\u002FEventCalendarDaysView.vue\"\nexport { default as EventCalendarAgendaView } from \".\u002FEventCalendarAgendaView.vue\"\nexport { default as EventCalendarResourceView } from \".\u002FEventCalendarResourceView.vue\"\n",{"path":4859,"type":480,"target":4860,"content":4861},"src\u002Freui\u002Fevent-calendar\u002Flib.ts","components\u002Freui\u002Fevent-calendar\u002Flib.ts","\u002F\u002F Title: Event Calendar Lib\n\u002F\u002F Description: Pure, framework-free calendar math: view ranges, zoned day keys, multi-day segmentation, overlap packing, lane packing, and the event index.\n\u002F\u002F Port of ReUI event-calendar-lib.tsx (MIT) — pure TS\u002Fdate-fns, ported verbatim.\n\nimport { expandRecurrence } from \".\u002Frecurrence\"\nimport type {\n  CalendarEvent,\n  CalendarView,\n  EventCalendarDateRange,\n  EventCalendarOccurrence,\n  EventCalendarOffDaysConfig,\n  EventCalendarResource,\n  EventCalendarSegment,\n} from \".\u002Ftypes\"\nimport { TZDate } from \"@date-fns\u002Ftz\"\nimport {\n  addDays,\n  addMonths,\n  addWeeks,\n  differenceInCalendarDays,\n  differenceInMinutes,\n  format,\n  startOfDay,\n  startOfMonth,\n  startOfWeek,\n} from \"date-fns\"\n\ntype WeekStartsOn = 0 | 1 | 2 | 3 | 4 | 5 | 6\n\n\u002F** Packing-effective minimum in minutes so tiny events do not stack invisibly. *\u002F\nconst MIN_PACK_SLOT = 30\n\n\u002F** The instant re-expressed in the display time zone (TZDate extends Date). *\u002F\nfunction toZoned(date: Date, timeZone: string): TZDate {\n  return new TZDate(date.getTime(), timeZone)\n}\n\n\u002F** Zoned midnight of the day containing the instant. *\u002F\nfunction zonedStartOfDay(date: Date, timeZone: string): TZDate {\n  return startOfDay(toZoned(date, timeZone))\n}\n\n\u002F** Stable per-day key in the display time zone. *\u002F\nfunction getDayKey(date: Date, timeZone: string): string {\n  return format(toZoned(date, timeZone), \"yyyy-MM-dd\")\n}\n\n\u002F** Day length in minutes; 1380\u002F1500 on DST transition days - never assume 1440. *\u002F\nfunction getDayTotalMinutes(dayStart: Date, timeZone: string): number {\n  const next = zonedStartOfDay(\n    addDays(toZoned(dayStart, timeZone), 1),\n    timeZone\n  )\n  return differenceInMinutes(next, dayStart)\n}\n\nfunction snapMinutes(minutes: number, snap: number): number {\n  return Math.round(minutes \u002F snap) * snap\n}\n\ninterface ViewRangeOptions {\n  timeZone: string\n  weekStartsOn: WeekStartsOn\n  dayCount: number\n  agendaDayCount: number\n  fixedWeeks: boolean\n}\n\ninterface ViewDateRanges {\n  visibleRange: EventCalendarDateRange\n  activeRange: EventCalendarDateRange\n}\n\nfunction getViewDateRange(\n  view: CalendarView,\n  date: Date,\n  opts: ViewRangeOptions\n): ViewDateRanges {\n  const { timeZone, weekStartsOn, dayCount, agendaDayCount, fixedWeeks } = opts\n  const zoned = toZoned(date, timeZone)\n\n  if (view === \"month\") {\n    const activeStart = startOfMonth(zoned)\n    const activeEnd = startOfMonth(addMonths(zoned, 1))\n    const visibleStart = startOfWeek(activeStart, { weekStartsOn })\n    let visibleEnd: Date\n    if (fixedWeeks) {\n      visibleEnd = addDays(visibleStart, 42)\n    } else {\n      visibleEnd = startOfWeek(addDays(activeEnd, -1), { weekStartsOn })\n      visibleEnd = addWeeks(visibleEnd, 1)\n    }\n    return {\n      activeRange: { start: activeStart, end: activeEnd },\n      visibleRange: { start: visibleStart, end: visibleEnd },\n    }\n  }\n\n  if (view === \"week\") {\n    const start = startOfWeek(zoned, { weekStartsOn })\n    const range = { start, end: addWeeks(start, 1) }\n    return { activeRange: range, visibleRange: range }\n  }\n\n  if (view === \"day\" || view === \"resource\") {\n    const start = startOfDay(zoned)\n    const range = { start, end: addDays(start, 1) }\n    return { activeRange: range, visibleRange: range }\n  }\n\n  if (view === \"days\") {\n    const start = startOfDay(zoned)\n    const range = { start, end: addDays(start, Math.max(1, dayCount)) }\n    return { activeRange: range, visibleRange: range }\n  }\n\n  \u002F\u002F agenda\n  const start = startOfDay(zoned)\n  const range = { start, end: addDays(start, Math.max(1, agendaDayCount)) }\n  return { activeRange: range, visibleRange: range }\n}\n\n\u002F** Day of month of the last day of the month containing the zoned date. *\u002F\nfunction lastDayOfZonedMonth(date: Date): number {\n  return addDays(startOfMonth(addMonths(date, 1)), -1).getDate()\n}\n\n\u002F** The anchor date stepped one period forward or backward for the view. *\u002F\nfunction stepDate(\n  view: CalendarView,\n  date: Date,\n  direction: 1 | -1,\n  opts: Pick\u003CViewRangeOptions, \"timeZone\" | \"dayCount\" | \"agendaDayCount\">\n): Date {\n  const zoned = toZoned(date, opts.timeZone)\n  if (view === \"month\") {\n    const stepped = addMonths(zoned, direction)\n    \u002F\u002F addMonths clamps the day down into a shorter month and never restores\n    \u002F\u002F it, so next-then-prev from the 31st would leave the anchor on the 28th.\n    \u002F\u002F Sticking a month end to the target month's end keeps stepping\n    \u002F\u002F invertible, which matters because the anchor is what day and week view\n    \u002F\u002F open on after a month navigation.\n    if (zoned.getDate() !== lastDayOfZonedMonth(zoned)) return stepped\n    return addDays(stepped, lastDayOfZonedMonth(stepped) - stepped.getDate())\n  }\n  if (view === \"week\") return addWeeks(zoned, direction)\n  if (view === \"day\" || view === \"resource\") return addDays(zoned, direction)\n  if (view === \"days\")\n    return addDays(zoned, direction * Math.max(1, opts.dayCount))\n  return addDays(zoned, direction * Math.max(1, opts.agendaDayCount))\n}\n\nfunction rangesIntersect(\n  a: EventCalendarDateRange,\n  b: EventCalendarDateRange\n): boolean {\n  return a.start \u003C b.end && a.end > b.start\n}\n\nfunction eventsOverlap(\n  a: { start: Date; end: Date },\n  b: { start: Date; end: Date }\n): boolean {\n  return a.start \u003C b.end && a.end > b.start\n}\n\n\u002F**\n * The one canonical multi-day segmentation. Splits an occurrence into per-day\n * segments clamped to the range. Rules (unit-tested in M1): exclusive end - an\n * event ending exactly at zoned midnight emits NO segment for that day;\n * zero-duration events emit one min-height segment; allDay occurrences walk\n * the same absolute instants as timed ones and only drop startMin\u002FendMin, so\n * their bounds have to already BE display-zone midnights (see\n * CalendarEvent.allDay) or the bar paints on the wrong days.\n *\u002F\nfunction segmentOccurrence\u003CTData>(\n  occurrence: EventCalendarOccurrence\u003CTData>,\n  range: EventCalendarDateRange,\n  timeZone: string\n): EventCalendarSegment\u003CTData>[] {\n  const occStart = occurrence.start\n  const occEnd = occurrence.end\n  const isZeroLength = occEnd.getTime() === occStart.getTime()\n\n  const clampStart = occStart > range.start ? occStart : range.start\n  const clampEnd = occEnd \u003C range.end ? occEnd : range.end\n  if (clampEnd \u003C clampStart) return []\n  if (clampEnd.getTime() === clampStart.getTime() && !isZeroLength) return []\n\n  const segments: EventCalendarSegment\u003CTData>[] = []\n  let cursor = zonedStartOfDay(clampStart, timeZone)\n\n  while (cursor \u003C clampEnd || (isZeroLength && segments.length === 0)) {\n    const next = zonedStartOfDay(\n      addDays(toZoned(cursor, timeZone), 1),\n      timeZone\n    )\n    const segStart = clampStart > cursor ? clampStart : cursor\n    const segEnd = clampEnd \u003C next ? clampEnd : next\n\n    const emptySeg = segEnd.getTime() \u003C= segStart.getTime()\n    if (!emptySeg || isZeroLength) {\n      const isStart = segStart.getTime() === occStart.getTime()\n      const isEnd = segEnd.getTime() === occEnd.getTime()\n      segments.push({\n        occurrence,\n        day: cursor,\n        isStart,\n        isEnd,\n        continuesBefore: !isStart,\n        continuesAfter: !isEnd,\n        startMin: occurrence.allDay\n          ? undefined\n          : differenceInMinutes(segStart, cursor),\n        endMin: occurrence.allDay\n          ? undefined\n          : Math.max(\n              differenceInMinutes(segEnd, cursor),\n              differenceInMinutes(segStart, cursor)\n            ),\n      })\n    }\n    if (isZeroLength) break\n    cursor = next\n  }\n\n  return segments\n}\n\n\u002F** True when the occurrence should render as a bar (all-day row \u002F month lanes). *\u002F\nfunction isBarOccurrence(\n  occurrence: EventCalendarOccurrence,\n  timeZone?: string\n): boolean {\n  return occurrence.allDay || spansMultipleDays(occurrence, timeZone)\n}\n\nfunction spansMultipleDays(\n  occ: { start: Date; end: Date },\n  timeZone?: string\n): boolean {\n  \u002F\u002F An event ending exactly at the next midnight is still single-day\n  \u002F\u002F (exclusive end), so compare against a strictly-later instant. The\n  \u002F\u002F yardstick is the length of the day the event starts on, never a flat 24h:\n  \u002F\u002F a fall-back day is 25h long, and a 00:00-to-00:00 shift on it is still one\n  \u002F\u002F calendar day that belongs in the hour track, not in the all-day row.\n  \u002F\u002F Without a display zone the dates answer in their own frame (TZDate) or in\n  \u002F\u002F the host zone.\n  const dayStart = startOfDay(\n    timeZone ? toZoned(occ.start, timeZone) : occ.start\n  )\n  const nextDayStart = startOfDay(addDays(dayStart, 1))\n  return (\n    occ.end.getTime() - occ.start.getTime() >\n    nextDayStart.getTime() - dayStart.getTime()\n  )\n}\n\ninterface PackedPosition {\n  column: number\n  columnCount: number\n  columnSpan: number\n}\n\n\u002F**\n * Google-style overlap packing for one day's timed segments.\n * Mutates column\u002FcolumnCount\u002FcolumnSpan on the segments, in place.\n * z resolution happens at render: event.zIndex verbatim, else 10 + column.\n *\u002F\nfunction packTimedSegments\u003CTData>(\n  segments: EventCalendarSegment\u003CTData>[]\n): void {\n  if (segments.length === 0) return\n\n  type Working = {\n    seg: EventCalendarSegment\u003CTData>\n    startMin: number\n    effEnd: number\n  }\n\n  const items: Working[] = segments\n    .map((seg) => {\n      const startMin = seg.startMin ?? 0\n      const endMin = seg.endMin ?? startMin\n      return {\n        seg,\n        startMin,\n        effEnd: Math.max(endMin, startMin + MIN_PACK_SLOT),\n      }\n    })\n    .sort(\n      (a, b) =>\n        a.startMin - b.startMin ||\n        b.effEnd - b.startMin - (a.effEnd - a.startMin) ||\n        a.seg.occurrence.key.localeCompare(b.seg.occurrence.key)\n    )\n\n  \u002F\u002F Sweep into connected clusters\n  const clusters: Working[][] = []\n  let current: Working[] = []\n  let clusterEnd = -Infinity\n  for (const item of items) {\n    if (item.startMin >= clusterEnd) {\n      current = []\n      clusters.push(current)\n      clusterEnd = -Infinity\n    }\n    current.push(item)\n    clusterEnd = Math.max(clusterEnd, item.effEnd)\n  }\n\n  for (const cluster of clusters) {\n    \u002F\u002F Greedy column assignment\n    const colEnds: number[] = []\n    const byColumn = new Map\u003Cnumber, Working[]>()\n    for (const item of cluster) {\n      let col = colEnds.findIndex((end) => end \u003C= item.startMin)\n      if (col === -1) {\n        col = colEnds.length\n        colEnds.push(0)\n      }\n      colEnds[col] = item.effEnd\n      item.seg.column = col\n      const bucket = byColumn.get(col) ?? []\n      bucket.push(item)\n      byColumn.set(col, bucket)\n    }\n    const columnCount = colEnds.length\n\n    \u002F\u002F Partial-overlap expansion: widen rightward into free columns\n    for (const item of cluster) {\n      let span = 1\n      const col = item.seg.column ?? 0\n      while (col + span \u003C columnCount) {\n        const occupants = byColumn.get(col + span) ?? []\n        const blocked = occupants.some(\n          (o) => o.startMin \u003C item.effEnd && o.effEnd > item.startMin\n        )\n        if (blocked) break\n        span++\n      }\n      item.seg.columnCount = columnCount\n      item.seg.columnSpan = span\n    }\n  }\n}\n\n\u002F**\n * Greedy lane packing for bar segments within one week row (7 columns).\n * Mutates lane\u002FrowIndex\u002FcolStart\u002FcolSpan on the segments, in place.\n *\u002F\n\u002F**\n * Build the laned month-row bars for one week: consecutive-day segments of\n * the same occurrence merge into ONE bar (colStart -> colSpan) stacked into\n * lanes. Returns NEW segment objects - the shared per-day segments (also\n * rendered by the all-day rows and day cells) must stay pristine: mutating\n * their isEnd\u002Fcontinues flags gave the first-day chip a whole-bar shape and\n * a bogus end resize handle in the week all-day row, where dragging it\n * collapsed the event to a single day.\n *\u002F\nfunction packWeekRowLanes\u003CTData>(\n  segments: EventCalendarSegment\u003CTData>[],\n  rowIndex: number,\n  rowStart: Date,\n  timeZone: string\n): EventCalendarSegment\u003CTData>[] {\n  type Bar = {\n    seg: EventCalendarSegment\u003CTData>\n    colStart: number\n    colSpan: number\n    isStart: boolean\n    isEnd: boolean\n    lane: number\n  }\n\n  const bars: Bar[] = segments.map((seg) => {\n    const dayIndex = Math.round(\n      (zonedStartOfDay(seg.day, timeZone).getTime() -\n        zonedStartOfDay(rowStart, timeZone).getTime()) \u002F\n        (24 * 60 * 60 * 1000)\n    )\n    return {\n      seg,\n      colStart: Math.max(0, Math.min(6, dayIndex)),\n      colSpan: 1,\n      isStart: seg.isStart,\n      isEnd: seg.isEnd,\n      lane: 0,\n    }\n  })\n\n  \u002F\u002F Merge consecutive-day segments of the same occurrence into one bar per row\n  const merged = new Map\u003Cstring, Bar>()\n  for (const bar of bars) {\n    const key = bar.seg.occurrence.key\n    const existing = merged.get(key)\n    if (existing) {\n      const start = Math.min(existing.colStart, bar.colStart)\n      const end = Math.max(\n        existing.colStart + existing.colSpan,\n        bar.colStart + bar.colSpan\n      )\n      existing.colStart = start\n      existing.colSpan = end - start\n      existing.isStart = existing.isStart || bar.isStart\n      existing.isEnd = existing.isEnd || bar.isEnd\n    } else {\n      merged.set(key, bar)\n    }\n  }\n\n  const rowBars = Array.from(merged.values()).sort(\n    (a, b) =>\n      a.colStart - b.colStart ||\n      b.colSpan - a.colSpan ||\n      a.seg.occurrence.key.localeCompare(b.seg.occurrence.key)\n  )\n\n  const lanes: boolean[][] = []\n  for (const bar of rowBars) {\n    let lane = 0\n    for (;;) {\n      const row = (lanes[lane] ??= new Array(7).fill(false))\n      let free = true\n      for (let c = bar.colStart; c \u003C bar.colStart + bar.colSpan; c++) {\n        if (row[c]) {\n          free = false\n          break\n        }\n      }\n      if (free) break\n      lane++\n    }\n    const row = lanes[lane]!\n    for (let c = bar.colStart; c \u003C bar.colStart + bar.colSpan; c++) {\n      row[c] = true\n    }\n    bar.lane = lane\n  }\n\n  return rowBars.map((bar) => ({\n    ...bar.seg,\n    isStart: bar.isStart,\n    isEnd: bar.isEnd,\n    continuesBefore: !bar.isStart,\n    continuesAfter: !bar.isEnd,\n    lane: bar.lane,\n    rowIndex,\n    colStart: bar.colStart,\n    colSpan: bar.colSpan,\n  }))\n}\n\ninterface EventCalendarDayBucket\u003CTData = unknown> {\n  allDay: EventCalendarSegment\u003CTData>[]\n  timed: EventCalendarSegment\u003CTData>[]\n}\n\ninterface EventCalendarWeekRow\u003CTData = unknown> {\n  rowIndex: number\n  rowStart: Date\n  \u002F** Laned bar segments (one per occurrence per row). *\u002F\n  bars: EventCalendarSegment\u003CTData>[]\n}\n\ninterface EventCalendarIndex\u003CTData = unknown> {\n  occurrences: EventCalendarOccurrence\u003CTData>[]\n  byDay: Map\u003Cstring, EventCalendarDayBucket\u003CTData>>\n  weekRows: EventCalendarWeekRow\u003CTData>[]\n}\n\ninterface BuildIndexOptions\u003CTData> {\n  timeZone: string\n  weekStartsOn: WeekStartsOn\n  eventOrder?: (\n    a: EventCalendarOccurrence\u003CTData>,\n    b: EventCalendarOccurrence\u003CTData>\n  ) => number\n  getOccurrences?: (\n    event: CalendarEvent\u003CTData>,\n    range: EventCalendarDateRange,\n    ctx: { timeZone: string }\n  ) => Array\u003C{ start: Date; end: Date }> | null\n}\n\nfunction defaultEventOrder(\n  a: EventCalendarOccurrence,\n  b: EventCalendarOccurrence\n): number {\n  return (\n    a.start.getTime() - b.start.getTime() ||\n    b.end.getTime() -\n      b.start.getTime() -\n      (a.end.getTime() - a.start.getTime()) ||\n    a.key.localeCompare(b.key)\n  )\n}\n\nfunction buildEventIndex\u003CTData>(\n  events: CalendarEvent\u003CTData>[],\n  visibleRange: EventCalendarDateRange,\n  opts: BuildIndexOptions\u003CTData>\n): EventCalendarIndex\u003CTData> {\n  const { timeZone, weekStartsOn } = opts\n  const order = opts.eventOrder ?? defaultEventOrder\n\n  \u002F\u002F RECURRENCE-ID override replacement: an event carrying recurringEventId +\n  \u002F\u002F originalStart is an edited single occurrence of that series. The parent's\n  \u002F\u002F expansion drops the replaced instant; the override renders as its own\n  \u002F\u002F occurrence through the normal path below.\n  const overrideTimes = new Map\u003Cstring, Set\u003Cnumber>>()\n  for (const event of events) {\n    if (!event.recurringEventId || !event.originalStart) continue\n    let times = overrideTimes.get(event.recurringEventId)\n    if (!times) overrideTimes.set(event.recurringEventId, (times = new Set()))\n    times.add(event.originalStart.getTime())\n  }\n\n  const occurrences: EventCalendarOccurrence\u003CTData>[] = []\n  for (const event of events) {\n    const replaced = overrideTimes.get(event.id)\n    const custom = opts.getOccurrences?.(event, visibleRange, { timeZone })\n    if (custom) {\n      custom.forEach((occ, i) => {\n        if (replaced?.has(occ.start.getTime())) return\n        if (!rangesIntersect({ start: occ.start, end: occ.end }, visibleRange))\n          return\n        occurrences.push({\n          key: `${event.id}::${occ.start.toISOString()}`,\n          eventId: event.id,\n          event,\n          start: occ.start,\n          end: occ.end,\n          allDay: event.allDay ?? false,\n          isRecurring: true,\n          recurrenceIndex: i,\n        })\n      })\n      continue\n    }\n    const expanded = expandRecurrence(event, visibleRange, { timeZone })\n    occurrences.push(\n      ...(replaced\n        ? expanded.filter((occ) => !replaced.has(occ.start.getTime()))\n        : expanded)\n    )\n  }\n  occurrences.sort(order)\n\n  const byDay = new Map\u003Cstring, EventCalendarDayBucket\u003CTData>>()\n  const barSegmentsByRow = new Map\u003Cnumber, EventCalendarSegment\u003CTData>[]>()\n  const firstRowStart = startOfWeek(toZoned(visibleRange.start, timeZone), {\n    weekStartsOn,\n  })\n\n  for (const occurrence of occurrences) {\n    const segments = segmentOccurrence(occurrence, visibleRange, timeZone)\n    const bar = isBarOccurrence(occurrence, timeZone)\n    for (const seg of segments) {\n      const key = getDayKey(seg.day, timeZone)\n      let bucket = byDay.get(key)\n      if (!bucket) {\n        bucket = { allDay: [], timed: [] }\n        byDay.set(key, bucket)\n      }\n      if (bar) {\n        bucket.allDay.push(seg)\n        \u002F\u002F calendar-day math, not a fixed 168h divisor: DST transition weeks\n        \u002F\u002F are 167\u002F169h long and the fixed divisor mis-buckets every later\n        \u002F\u002F Sunday one row early (which then clamps into the wrong column)\n        const rowIndex = Math.floor(\n          differenceInCalendarDays(toZoned(seg.day, timeZone), firstRowStart) \u002F\n            7\n        )\n        const rowBucket = barSegmentsByRow.get(rowIndex) ?? []\n        rowBucket.push(seg)\n        barSegmentsByRow.set(rowIndex, rowBucket)\n      } else {\n        bucket.timed.push(seg)\n      }\n    }\n  }\n\n  for (const bucket of byDay.values()) {\n    packTimedSegments(bucket.timed)\n  }\n\n  const weekRows: EventCalendarWeekRow\u003CTData>[] = []\n  for (const [rowIndex, segs] of barSegmentsByRow) {\n    const rowStart = addWeeks(firstRowStart, rowIndex)\n    weekRows.push({\n      rowIndex,\n      rowStart,\n      bars: packWeekRowLanes(segs, rowIndex, rowStart, timeZone),\n    })\n  }\n  weekRows.sort((a, b) => a.rowIndex - b.rowIndex)\n\n  return { occurrences, byDay, weekRows }\n}\n\n\u002F** Cache key for index memoization; cheap string compare. *\u002F\nfunction getRangeKey(range: EventCalendarDateRange): string {\n  return `${range.start.getTime()}-${range.end.getTime()}`\n}\n\n\u002F** Depth-first flatten of the resource tree (parents included). *\u002F\nfunction flattenResources(\n  resources: EventCalendarResource[],\n  depth = 0\n): Array\u003C{ resource: EventCalendarResource; depth: number }> {\n  const rows: Array\u003C{ resource: EventCalendarResource; depth: number }> = []\n  for (const resource of resources) {\n    rows.push({ resource, depth })\n    if (resource.children?.length) {\n      rows.push(...flattenResources(resource.children, depth + 1))\n    }\n  }\n  return rows\n}\n\nconst DEFAULT_WEEKEND_DAYS = [0, 6]\n\n\u002F**\n * Resolves whether a day is an off day (non-working) in the display zone.\n * Callers pass the calendar's own weekendDays so the shading cannot contradict\n * the weekend the rest of the calendar renders; an explicit offDays.weekendDays\n * still wins over it.\n *\u002F\nfunction resolveOffDay(\n  day: Date,\n  timeZone: string,\n  config: boolean | EventCalendarOffDaysConfig | undefined,\n  defaultWeekendDays?: number[]\n): boolean {\n  if (!config) return false\n  const resolved: EventCalendarOffDaysConfig = config === true ? {} : config\n  const weekendDays =\n    resolved.weekendDays ?? defaultWeekendDays ?? DEFAULT_WEEKEND_DAYS\n  const zoned = toZoned(day, timeZone)\n  if (weekendDays.includes(zoned.getDay())) return true\n  if (resolved.dates?.length) {\n    const key = getDayKey(day, timeZone)\n    if (resolved.dates.some((date) => getDayKey(date, timeZone) === key)) {\n      return true\n    }\n  }\n  return resolved.isOffDay?.(day) ?? false\n}\n\nexport {\n  buildEventIndex,\n  defaultEventOrder,\n  eventsOverlap,\n  flattenResources,\n  getDayKey,\n  getDayTotalMinutes,\n  getRangeKey,\n  getViewDateRange,\n  isBarOccurrence,\n  MIN_PACK_SLOT,\n  packTimedSegments,\n  packWeekRowLanes,\n  rangesIntersect,\n  resolveOffDay,\n  segmentOccurrence,\n  snapMinutes,\n  spansMultipleDays,\n  stepDate,\n  toZoned,\n  zonedStartOfDay,\n}\nexport type {\n  BuildIndexOptions,\n  EventCalendarDayBucket,\n  EventCalendarIndex,\n  EventCalendarWeekRow,\n  PackedPosition,\n  ViewDateRanges,\n  ViewRangeOptions,\n  WeekStartsOn,\n}\n",{"path":4863,"type":480,"target":4864,"content":4865},"src\u002Freui\u002Fevent-calendar\u002Frecurrence.ts","components\u002Freui\u002Fevent-calendar\u002Frecurrence.ts","\u002F\u002F Title: Event Calendar Recurrence\n\u002F\u002F Description: RFC 5545 subset recurrence expansion for the event calendar - structured rules or raw RRULE strings, with a hard occurrence cap.\n\u002F\u002F Port of ReUI event-calendar-recurrence.tsx (MIT) — pure TS\u002Fdate-fns, ported verbatim.\n\nimport type {\n  CalendarEvent,\n  EventCalendarDateRange,\n  EventCalendarOccurrence,\n  EventCalendarRecurrenceRule,\n  EventCalendarWeekday,\n} from \".\u002Ftypes\"\nimport { TZDate } from \"@date-fns\u002Ftz\"\nimport { addDays, addMonths, addWeeks, addYears } from \"date-fns\"\n\n\u002F** Guard: max window-intersecting occurrences per event per expansion. *\u002F\nconst MAX_OCCURRENCES = 1000\n\n\u002F** Runaway guard: absolute cap on period iterations regardless of visibility. *\u002F\nconst MAX_ITERATIONS = 10000\n\n\u002F** Gregorian mean period lengths for the O(1) fast-forward approximation. *\u002F\nconst PERIOD_MS: Record\u003CEventCalendarRecurrenceRule[\"freq\"], number> = {\n  daily: 86400000,\n  weekly: 604800000,\n  monthly: 2629746000, \u002F\u002F 365.2425 \u002F 12 days\n  yearly: 31556952000, \u002F\u002F 365.2425 days\n}\n\nconst WEEKDAYS: EventCalendarWeekday[] = [\n  \"SU\",\n  \"MO\",\n  \"TU\",\n  \"WE\",\n  \"TH\",\n  \"FR\",\n  \"SA\",\n]\n\nclass EventCalendarRecurrenceError extends Error {\n  constructor(part: string) {\n    super(\n      `Unsupported recurrence part: ${part}. Use the getOccurrences prop to plug a full RRULE engine for exotic rules.`\n    )\n    this.name = \"EventCalendarRecurrenceError\"\n  }\n}\n\n\u002F**\n * Parses a raw RRULE line (with or without the \"RRULE:\" prefix) into the\n * structured subset. Pass the display time zone so Z-less UNTIL values are\n * interpreted as wall time in that zone rather than the machine zone.\n *\u002F\nfunction parseRRuleString(\n  input: string,\n  timeZone?: string\n): EventCalendarRecurrenceRule {\n  const body = input.trim().replace(\u002F^RRULE:\u002Fi, \"\")\n  const rule: Partial\u003CEventCalendarRecurrenceRule> = {}\n\n  for (const pair of body.split(\";\")) {\n    if (!pair) continue\n    const [rawKey, rawValue] = pair.split(\"=\")\n    const key = rawKey?.toUpperCase()\n    const value = rawValue ?? \"\"\n\n    switch (key) {\n      case \"FREQ\": {\n        const freq = value.toLowerCase()\n        if (\n          freq !== \"daily\" &&\n          freq !== \"weekly\" &&\n          freq !== \"monthly\" &&\n          freq !== \"yearly\"\n        ) {\n          throw new EventCalendarRecurrenceError(`FREQ=${value}`)\n        }\n        rule.freq = freq\n        break\n      }\n      case \"INTERVAL\":\n        rule.interval = Math.max(1, parseInt(value, 10) || 1)\n        break\n      case \"COUNT\":\n        rule.count = Math.max(1, parseInt(value, 10) || 1)\n        break\n      case \"UNTIL\":\n        rule.until = parseRRuleDate(value, timeZone)\n        break\n      case \"BYDAY\":\n        rule.byWeekday = value.split(\",\").map((token) => {\n          \u002F\u002F RFC 5545 3.1: enumerated values are case-insensitive, and FREQ is\n          \u002F\u002F already folded above - rejecting \"mo\" here would be inconsistent\n          const match = \u002F^(-?\\d+)?(SU|MO|TU|WE|TH|FR|SA)$\u002F.exec(\n            token.trim().toUpperCase()\n          )\n          if (!match) throw new EventCalendarRecurrenceError(`BYDAY=${token}`)\n          const day = match[2] as EventCalendarWeekday\n          return match[1] ? { day, ordinal: parseInt(match[1], 10) } : day\n        })\n        break\n      case \"BYMONTHDAY\":\n        rule.byMonthDay = value.split(\",\").map((v) => {\n          const day = parseInt(v, 10)\n          \u002F\u002F NaN would survive parsing, match no day in any month and leave the\n          \u002F\u002F event permanently invisible with no error anywhere\n          if (Number.isNaN(day)) {\n            throw new EventCalendarRecurrenceError(`BYMONTHDAY=${v}`)\n          }\n          return day\n        })\n        break\n      case \"BYMONTH\":\n        rule.byMonth = value.split(\",\").map((v) => parseInt(v, 10))\n        break\n      case \"WKST\": {\n        const day = value.trim().toUpperCase() as EventCalendarWeekday\n        if (!WEEKDAYS.includes(day)) {\n          throw new EventCalendarRecurrenceError(`WKST=${value}`)\n        }\n        rule.weekStart = day\n        break\n      }\n      default:\n        throw new EventCalendarRecurrenceError(key ?? pair)\n    }\n  }\n\n  if (!rule.freq) throw new EventCalendarRecurrenceError(\"missing FREQ\")\n  return rule as EventCalendarRecurrenceRule\n}\n\nfunction parseRRuleDate(value: string, timeZone?: string): Date {\n  \u002F\u002F RFC 5545 basic formats: YYYYMMDD or YYYYMMDDTHHMMSS(Z). The T and Z\n  \u002F\u002F designators are case-insensitive too (RFC 5545 3.1), so fold before matching.\n  const match = \u002F^(\\d{4})(\\d{2})(\\d{2})(?:T(\\d{2})(\\d{2})(\\d{2})(Z)?)?$\u002F.exec(\n    value.trim().toUpperCase()\n  )\n  if (!match) throw new EventCalendarRecurrenceError(`UNTIL=${value}`)\n  const [, y0, m0, d0, hh = \"23\", mm = \"59\", ss = \"59\", z] = match\n  \u002F\u002F y\u002Fm\u002Fd are always captured (required groups in the regex above); TS can't\n  \u002F\u002F see that, so assert non-null rather than widen the type everywhere below.\n  const y = y0!\n  const m = m0!\n  const d = d0!\n  \u002F\u002F Z-less values (including date-only ones, which mean end of that day\n  \u002F\u002F inclusive) are wall time in the display zone, not the machine zone.\n  const date = z\n    ? new Date(`${y}-${m}-${d}T${hh}:${mm}:${ss}Z`)\n    : timeZone\n      ? new Date(new TZDate(+y, +m - 1, +d, +hh, +mm, +ss, timeZone).getTime())\n      : new Date(`${y}-${m}-${d}T${hh}:${mm}:${ss}`)\n  if (Number.isNaN(date.getTime())) {\n    throw new EventCalendarRecurrenceError(`UNTIL=${value}`)\n  }\n  return date\n}\n\n\u002F** Serializes the structured subset back to an RRULE line (without prefix). *\u002F\nfunction formatRRuleString(rule: EventCalendarRecurrenceRule): string {\n  const parts: string[] = [`FREQ=${rule.freq.toUpperCase()}`]\n  if (rule.interval && rule.interval > 1)\n    parts.push(`INTERVAL=${rule.interval}`)\n  if (rule.count) parts.push(`COUNT=${rule.count}`)\n  if (rule.until) {\n    const u = rule.until\n    const pad = (n: number) => String(n).padStart(2, \"0\")\n    parts.push(\n      `UNTIL=${u.getUTCFullYear()}${pad(u.getUTCMonth() + 1)}${pad(u.getUTCDate())}T${pad(u.getUTCHours())}${pad(u.getUTCMinutes())}${pad(u.getUTCSeconds())}Z`\n    )\n  }\n  if (rule.byWeekday?.length) {\n    parts.push(\n      `BYDAY=${rule.byWeekday\n        .map((d) => (typeof d === \"string\" ? d : `${d.ordinal}${d.day}`))\n        .join(\",\")}`\n    )\n  }\n  if (rule.byMonthDay?.length)\n    parts.push(`BYMONTHDAY=${rule.byMonthDay.join(\",\")}`)\n  if (rule.byMonth?.length) parts.push(`BYMONTH=${rule.byMonth.join(\",\")}`)\n  if (rule.weekStart) parts.push(`WKST=${rule.weekStart}`)\n  return parts.join(\";\")\n}\n\nfunction resolveRule(\n  recurrence: EventCalendarRecurrenceRule | string,\n  timeZone?: string\n): EventCalendarRecurrenceRule {\n  return typeof recurrence === \"string\"\n    ? parseRRuleString(recurrence, timeZone)\n    : recurrence\n}\n\n\u002F**\n * Expands one event into its occurrences intersecting the range.\n * Non-recurring events yield at most one occurrence. Recurrence iteration is\n * wall-time based in the display zone (DST-safe day\u002Fweek\u002Fmonth steps), and a\n * span that is a whole number of local days keeps that day count across a DST\n * transition (timed spans keep their absolute length instead).\n *\n * exDates remove exactly-matching instants (after COUNT numbering,\n * Google-style: an exception still consumes its COUNT slot); rDates add extra\n * instants with the same duration. RECURRENCE-ID override replacement lives\n * in buildEventIndex, where the override event and its parent series meet.\n *\u002F\nfunction expandRecurrence\u003CTData>(\n  event: CalendarEvent\u003CTData>,\n  range: EventCalendarDateRange,\n  ctx: { timeZone: string }\n): EventCalendarOccurrence\u003CTData>[] {\n  const allDay = event.allDay ?? false\n\n  if (!event.recurrence) {\n    \u002F\u002F The exclusive `end > start` test is right for anything with duration,\n    \u002F\u002F but it also drops a zero-length milestone pinned to the first visible\n    \u002F\u002F instant - which reads as an event that randomly disappears until you\n    \u002F\u002F page one period back. A point occurrence only has to be inside.\n    const isPoint = event.end.getTime() === event.start.getTime()\n    if (\n      event.start \u003C range.end &&\n      (event.end > range.start || (isPoint && event.start >= range.start))\n    ) {\n      return [\n        {\n          key: `${event.id}::${event.start.toISOString()}`,\n          eventId: event.id,\n          event,\n          start: event.start,\n          end: event.end,\n          allDay,\n          isRecurring: false,\n        },\n      ]\n    }\n    return []\n  }\n\n  const rule = resolveRule(event.recurrence, ctx.timeZone)\n  const interval = Math.max(1, rule.interval ?? 1)\n  const durationMs = event.end.getTime() - event.start.getTime()\n  const zonedStart = new TZDate(event.start.getTime(), ctx.timeZone)\n  \u002F\u002F A span of whole local days is wall time, not an absolute delta: a 3 day\n  \u002F\u002F all-day bar crossing spring forward would otherwise end at 01:00 and\n  \u002F\u002F occupy a fourth day in the month grid. Timed spans stay absolute so a two\n  \u002F\u002F hour meeting is still two hours.\n  const daySpan = Math.round(durationMs \u002F 86400000)\n  const wallDaySpan =\n    daySpan > 0 &&\n    addDays(zonedStart, daySpan).getTime() === event.end.getTime()\n      ? daySpan\n      : null\n  const endFor = (start: Date): Date =>\n    wallDaySpan === null\n      ? new Date(start.getTime() + durationMs)\n      : new Date(\n          addDays(\n            new TZDate(start.getTime(), ctx.timeZone),\n            wallDaySpan\n          ).getTime()\n        )\n  \u002F\u002F Excluded instants matched exactly; filtering happens at push time so an\n  \u002F\u002F exception still consumes its COUNT slot (Google-style numbering).\n  const exTimes = new Set((rule.exDates ?? []).map((d) => d.getTime()))\n\n  const weeklyDays: number[] | null =\n    rule.freq === \"weekly\" && rule.byWeekday?.length\n      ? [\n          ...new Set(\n            rule.byWeekday.map((d) => {\n              if (typeof d !== \"string\") {\n                throw new EventCalendarRecurrenceError(\n                  \"BYDAY ordinal outside monthly\u002Fyearly\"\n                )\n              }\n              return WEEKDAYS.indexOf(d)\n            })\n          ),\n        ]\n      : null\n\n  \u002F\u002F BYDAY resolved inside a month: monthly, and yearly within each BYMONTH\n  \u002F\u002F (FREQ=YEARLY;BYMONTH=11;BYDAY=4TH is Thanksgiving, not \"the anchor's day\")\n  const monthlyByDay =\n    (rule.freq === \"monthly\" || rule.freq === \"yearly\") &&\n    rule.byWeekday?.length\n      ? rule.byWeekday\n      : null\n\n  \u002F\u002F RFC 5545 3.3.10 week numbering: with INTERVAL > 1 the week start decides\n  \u002F\u002F which selected days share a period, so an ignored WKST puts half of every\n  \u002F\u002F biweekly series a week off. Default MO, per the RFC.\n  const weekStartIndex = WEEKDAYS.indexOf(rule.weekStart ?? \"MO\")\n  \u002F** Days from the WKST-aligned week start to `day` (0-6). *\u002F\n  const fromWeekStart = (day: number) => (day - weekStartIndex + 7) % 7\n\n  \u002F\u002F yearly BYMONTH filter (1-12), ascending; defaults to the anchor's month\n  const validByMonth = rule.byMonth?.filter((m) => m >= 1 && m \u003C= 12) ?? []\n  const yearlyMonths: number[] =\n    validByMonth.length > 0\n      ? [...new Set(validByMonth)].sort((a, b) => a - b)\n      : [zonedStart.getMonth() + 1]\n\n  \u002F\u002F month-shaped BY* parts make the per-period occurrence count variable\n  const hasMonthDayParts =\n    (rule.freq === \"monthly\" &&\n      Boolean(rule.byMonthDay?.length || monthlyByDay)) ||\n    (rule.freq === \"yearly\" &&\n      Boolean(rule.byMonth?.length || rule.byMonthDay?.length || monthlyByDay))\n\n  const daysInMonth = (year: number, month: number) =>\n    new Date(year, month + 1, 0).getDate()\n\n  \u002F\u002F RFC 5545 3.3.10 LIMIT filters: at these frequencies a BY* part narrows the\n  \u002F\u002F set instead of reshaping it. Dropping them silently expanded the series as\n  \u002F\u002F if the part were absent (FREQ=DAILY;BYDAY=MO filled every day). Filtering\n  \u002F\u002F here rather than at push time keeps COUNT numbering RFC-correct: a\n  \u002F\u002F candidate the filter removes is not an occurrence and consumes no slot.\n  const limitByMonth =\n    rule.freq !== \"yearly\" && validByMonth.length > 0 ? validByMonth : null\n  const limitByMonthDay =\n    rule.freq === \"daily\" && rule.byMonthDay?.length ? rule.byMonthDay : null\n  const limitByWeekday =\n    rule.freq === \"daily\" && rule.byWeekday?.length\n      ? rule.byWeekday.map((d) =>\n          WEEKDAYS.indexOf(typeof d === \"string\" ? d : d.day)\n        )\n      : null\n  const hasLimits = Boolean(limitByMonth || limitByMonthDay || limitByWeekday)\n\n  const passesLimits = (candidate: TZDate): boolean => {\n    if (limitByMonth && !limitByMonth.includes(candidate.getMonth() + 1)) {\n      return false\n    }\n    if (limitByWeekday && !limitByWeekday.includes(candidate.getDay())) {\n      return false\n    }\n    if (limitByMonthDay) {\n      const total = daysInMonth(candidate.getFullYear(), candidate.getMonth())\n      const day = candidate.getDate()\n      \u002F\u002F negative BYMONTHDAY counts back from month end, as in monthDays\n      if (!limitByMonthDay.some((n) => (n \u003C 0 ? total + 1 + n : n) === day)) {\n        return false\n      }\n    }\n    return true\n  }\n\n  \u002F** Wall-clock instant in the display zone carrying DTSTART's time-of-day. *\u002F\n  const zonedDate = (year: number, month: number, day: number) =>\n    new TZDate(\n      year,\n      month,\n      day,\n      zonedStart.getHours(),\n      zonedStart.getMinutes(),\n      zonedStart.getSeconds(),\n      zonedStart.getMilliseconds(),\n      ctx.timeZone\n    )\n\n  \u002F** Selected days-of-month, ascending: BYMONTHDAY (and) BYDAY, else the clamped anchor day. *\u002F\n  const monthDays = (year: number, month: number): number[] => {\n    const total = daysInMonth(year, month)\n    let days: number[] | null = null\n    if (rule.byMonthDay?.length) {\n      \u002F\u002F negative BYMONTHDAY counts back from month end; nonexistent days skip\n      days = rule.byMonthDay\n        .map((n) => (n \u003C 0 ? total + 1 + n : n))\n        .filter((n) => n >= 1 && n \u003C= total)\n    }\n    if (monthlyByDay) {\n      const byDayMatches: number[] = []\n      for (const entry of monthlyByDay) {\n        const day = typeof entry === \"string\" ? entry : entry.day\n        const ordinal = typeof entry === \"string\" ? 0 : entry.ordinal\n        const weekday = WEEKDAYS.indexOf(day)\n        const matches: number[] = []\n        for (let d = 1; d \u003C= total; d++) {\n          if (new Date(year, month, d).getDay() === weekday) matches.push(d)\n        }\n        if (ordinal === 0) {\n          byDayMatches.push(...matches) \u002F\u002F plain BYDAY: every matching weekday\n        } else {\n          \u002F\u002F 2TU = 2nd Tuesday, -1FR = last Friday; absent ordinals skip\n          const pick =\n            ordinal > 0\n              ? matches[ordinal - 1]\n              : matches[matches.length + ordinal]\n          if (pick !== undefined) byDayMatches.push(pick)\n        }\n      }\n      days = days ? days.filter((n) => byDayMatches.includes(n)) : byDayMatches\n    }\n    if (!days) days = [Math.min(zonedStart.getDate(), total)] \u002F\u002F clamp to month end\n    return [...new Set(days)].sort((a, b) => a - b)\n  }\n\n  \u002F** Chronological candidates of one period, derived from the DTSTART anchor by index (no drift). *\u002F\n  const periodCandidates = (period: number): TZDate[] => {\n    if (rule.freq === \"daily\") return [addDays(zonedStart, period * interval)]\n    if (rule.freq === \"weekly\") {\n      const base = addWeeks(zonedStart, period * interval)\n      if (!weeklyDays) return [base]\n      const week: TZDate[] = []\n      \u002F\u002F walk the WKST-aligned week so candidates stay chronological\n      const baseOffset = fromWeekStart(base.getDay())\n      for (let offset = 0; offset \u003C 7; offset++) {\n        const candidate = addDays(base, offset - baseOffset)\n        if (!weeklyDays.includes(candidate.getDay())) continue\n        \u002F\u002F days of the DTSTART week before DTSTART are not part of the series\n        if (candidate.getTime() \u003C zonedStart.getTime()) continue\n        week.push(candidate)\n      }\n      return week\n    }\n    if (rule.freq === \"monthly\") {\n      const anchor = addMonths(zonedStart, period * interval)\n      const year = anchor.getFullYear()\n      const month = anchor.getMonth()\n      return monthDays(year, month)\n        .map((day) => zonedDate(year, month, day))\n        .filter((c) => c.getTime() >= zonedStart.getTime())\n    }\n    \u002F\u002F yearly\n    const year = addYears(zonedStart, period * interval).getFullYear()\n    const dates: TZDate[] = []\n    for (const month of yearlyMonths) {\n      for (const day of monthDays(year, month - 1)) {\n        dates.push(zonedDate(year, month - 1, day))\n      }\n    }\n    return dates.filter((c) => c.getTime() >= zonedStart.getTime())\n  }\n\n  \u002F** Candidates of one period with the LIMIT filters applied. *\u002F\n  const candidatesFor = (period: number): TZDate[] =>\n    hasLimits\n      ? periodCandidates(period).filter(passesLimits)\n      : periodCandidates(period)\n\n  \u002F** Earliest\u002Flatest instant a period can produce - loop bounds without expanding it. *\u002F\n  const periodEdge = (period: number, edge: \"first\" | \"last\"): TZDate => {\n    if (rule.freq === \"daily\") return addDays(zonedStart, period * interval)\n    if (rule.freq === \"weekly\") {\n      const base = addWeeks(zonedStart, period * interval)\n      if (!weeklyDays) return base\n      return addDays(\n        base,\n        (edge === \"first\" ? 0 : 6) - fromWeekStart(base.getDay())\n      )\n    }\n    if (rule.freq === \"monthly\") {\n      const anchor = addMonths(zonedStart, period * interval)\n      const year = anchor.getFullYear()\n      const month = anchor.getMonth()\n      return zonedDate(\n        year,\n        month,\n        edge === \"first\" ? 1 : daysInMonth(year, month)\n      )\n    }\n    const year = addYears(zonedStart, period * interval).getFullYear()\n    const month =\n      \u002F\u002F yearlyMonths always has >= 1 entry (empty BYMONTH falls back to the\n      \u002F\u002F anchor's month above); TS can't see that through the index access.\n      (edge === \"first\"\n        ? yearlyMonths[0]!\n        : yearlyMonths[yearlyMonths.length - 1]!) - 1\n    return zonedDate(\n      year,\n      month,\n      edge === \"first\" ? 1 : daysInMonth(year, month)\n    )\n  }\n\n  \u002F\u002F O(1) fast-forward: land a couple of periods before the window instead of\n  \u002F\u002F iterating from DTSTART, so years-old series still reach the visible range.\n  const aheadMs = range.start.getTime() - durationMs - zonedStart.getTime()\n  const stepMs = PERIOD_MS[rule.freq] * interval\n  let startPeriod =\n    aheadMs > 0 ? Math.max(0, Math.floor(aheadMs \u002F stepMs) - 2) : 0\n  \u002F\u002F mean-length drift is bounded well under one period - refine forward\n  while (\n    periodEdge(startPeriod, \"last\").getTime() + durationMs \u003C=\n    range.start.getTime()\n  ) {\n    startPeriod++\n  }\n\n  \u002F\u002F series ordinal at startPeriod, so COUNT and recurrenceIndex stay exact\n  let index = 0\n  if (startPeriod > 0) {\n    if (hasMonthDayParts || hasLimits) {\n      \u002F\u002F per-period counts vary (skipped days, 4-vs-5 weekday months, a LIMIT\n      \u002F\u002F filter that empties a whole period) - sum them\n      for (let period = 0; period \u003C startPeriod; period++) {\n        index += candidatesFor(period).length\n      }\n    } else if (weeklyDays) {\n      \u002F\u002F week 0 only counts selected weekdays at\u002Fafter DTSTART's, inside the\n      \u002F\u002F WKST-aligned week that holds it\n      const anchorOffset = fromWeekStart(zonedStart.getDay())\n      const firstWeek = weeklyDays.filter(\n        (d) => fromWeekStart(d) >= anchorOffset\n      ).length\n      index = firstWeek + (startPeriod - 1) * weeklyDays.length\n    } else {\n      index = startPeriod \u002F\u002F one occurrence per period\n    }\n  }\n\n  const occurrences: EventCalendarOccurrence\u003CTData>[] = []\n\n  const pushIfVisible = (rawStart: Date) => {\n    \u002F\u002F normalize to a plain instant so consumers never receive zone-carrying\n    \u002F\u002F TZDate instances (mixed-zone formatting bugs)\n    const start = new Date(rawStart.getTime())\n    if (exTimes.has(start.getTime())) return\n    const end = endFor(start)\n    if (start \u003C range.end && end > range.start) {\n      occurrences.push({\n        key: `${event.id}::${start.toISOString()}`,\n        eventId: event.id,\n        event,\n        start,\n        end,\n        allDay,\n        isRecurring: true,\n        recurrenceIndex: index,\n      })\n    }\n  }\n\n  let iterations = 0\n  let period = startPeriod\n  while (iterations \u003C MAX_ITERATIONS && occurrences.length \u003C MAX_OCCURRENCES) {\n    iterations++\n    if (rule.count !== undefined && index >= rule.count) break\n    \u002F\u002F whole-period bounds: never break on a mid-period weekday\u002Fday-of-month,\n    \u002F\u002F so earlier candidates of the final period are still emitted\n    const earliest = periodEdge(period, \"first\")\n    if (earliest.getTime() >= range.end.getTime()) break\n    if (rule.until && earliest.getTime() > rule.until.getTime()) break\n\n    let ended = false\n    for (const candidate of candidatesFor(period)) {\n      if (rule.count !== undefined && index >= rule.count) {\n        ended = true\n        break\n      }\n      if (rule.until && candidate.getTime() > rule.until.getTime()) {\n        ended = true\n        break\n      }\n      pushIfVisible(candidate)\n      index++\n      if (occurrences.length >= MAX_OCCURRENCES) {\n        ended = true\n        break\n      }\n    }\n    if (ended) break\n    period++\n  }\n\n  \u002F\u002F RDATE: extra instants join the set (deduped against generated starts and\n  \u002F\u002F exclusions) with the same wall-time duration. Sorted so direct consumers\n  \u002F\u002F still receive chronological order (buildEventIndex re-sorts regardless).\n  if (rule.rDates?.length) {\n    const seen = new Set(occurrences.map((o) => o.start.getTime()))\n    for (const rDate of rule.rDates) {\n      const start = new Date(rDate.getTime())\n      if (seen.has(start.getTime()) || exTimes.has(start.getTime())) continue\n      const end = endFor(start)\n      if (start >= range.end || end \u003C= range.start) continue\n      seen.add(start.getTime())\n      occurrences.push({\n        key: `${event.id}::${start.toISOString()}`,\n        eventId: event.id,\n        event,\n        start,\n        end,\n        allDay,\n        isRecurring: true,\n        \u002F\u002F keep counting past the generated instants: an RDATE with no index\n        \u002F\u002F would fall back to undefined and break any consumer that identifies\n        \u002F\u002F an instance by its position in the series\n        recurrenceIndex: index++,\n      })\n    }\n    occurrences.sort((a, b) => a.start.getTime() - b.start.getTime())\n  }\n\n  return occurrences\n}\n\nexport {\n  EventCalendarRecurrenceError,\n  expandRecurrence,\n  formatRRuleString,\n  MAX_OCCURRENCES,\n  parseRRuleString,\n}\n",{"path":4867,"type":480,"target":4868,"content":4869},"src\u002Freui\u002Fevent-calendar\u002Ftypes.ts","components\u002Freui\u002Fevent-calendar\u002Ftypes.ts","\u002F\u002F Title: Event Calendar Types\n\u002F\u002F Description: Public TypeScript contract for the headless event calendar: events, occurrences, segments, state, and callbacks.\n\u002F\u002F Port of ReUI event-calendar-types.tsx (MIT) — pure TS, ported verbatim (framework-agnostic).\n\nexport type EventCalendarEventId = string\n\nexport type CalendarView = \"month\" | \"week\" | \"day\" | \"days\" | \"agenda\" | \"resource\"\n\n\u002F**\n * A bookable resource (room, person, equipment). Nesting via children renders\n * with children; the resource day view shows leaves as booking columns.\n *\u002F\nexport interface EventCalendarResource {\n  id: string\n  title: string\n  \u002F** Token or css color used for subtle row\u002Fcolumn accents. *\u002F\n  color?: string\n  children?: EventCalendarResource[]\n}\n\nexport interface EventCalendarDateRange {\n  \u002F** Inclusive instant. *\u002F\n  start: Date\n  \u002F** Exclusive instant. *\u002F\n  end: Date\n}\n\nexport type EventCalendarWeekday = \"MO\" | \"TU\" | \"WE\" | \"TH\" | \"FR\" | \"SA\" | \"SU\"\n\nexport interface EventCalendarRecurrenceRule {\n  freq: \"daily\" | \"weekly\" | \"monthly\" | \"yearly\"\n  interval?: number\n  count?: number\n  \u002F** Inclusive instant. *\u002F\n  until?: Date\n  byWeekday?: Array\u003C\n    EventCalendarWeekday | { day: EventCalendarWeekday; ordinal: number }\n  >\n  byMonthDay?: number[]\n  byMonth?: number[]\n  weekStart?: EventCalendarWeekday\n  exDates?: Date[]\n  rDates?: Date[]\n}\n\nexport interface CalendarEvent\u003CTData = unknown> {\n  id: EventCalendarEventId\n  title: string\n  \u002F** Plain instant; consumers parse ISO strings themselves. *\u002F\n  start: Date\n  \u002F** Exclusive; must be >= start. *\u002F\n  end: Date\n  \u002F**\n   * Start and end must be midnights in the calendar's display time zone:\n   * segmentation walks the raw instants, so a row stored at another zone's\n   * midnight paints on the wrong days.\n   *\u002F\n  allDay?: boolean\n  \u002F** Structured rule or a raw \"RRULE:...\" line. *\u002F\n  recurrence?: EventCalendarRecurrenceRule | string\n  \u002F** This event is an edited single occurrence of that series. *\u002F\n  recurringEventId?: EventCalendarEventId\n  \u002F** Which occurrence it replaces (RECURRENCE-ID semantics). *\u002F\n  originalStart?: Date\n  \u002F** Token or css color; flows to the --ec-event-color css var. *\u002F\n  color?: string\n  \u002F** Excluded from drag and resize regardless of interactions state. *\u002F\n  readOnly?: boolean\n  \u002F** Per-event override; default comes from interactions.drag. *\u002F\n  draggable?: boolean\n  \u002F** Per-event override; default comes from interactions.resize. *\u002F\n  resizable?: boolean\n  \u002F** Packing prominence; feeds getEventPriority ordering. *\u002F\n  priority?: number\n  \u002F** Explicit stacking override; wins over the computed z. *\u002F\n  zIndex?: number\n  \u002F** Bookable resource this event belongs to (resource view). *\u002F\n  resourceId?: string\n  \u002F** Consumer payload, fully generic. *\u002F\n  data?: TData\n}\n\nexport interface EventCalendarOccurrence\u003CTData = unknown> {\n  \u002F** Stable per instance: `${event.id}::${startISO}`. *\u002F\n  key: string\n  eventId: EventCalendarEventId\n  event: CalendarEvent\u003CTData>\n  start: Date\n  end: Date\n  allDay: boolean\n  isRecurring: boolean\n  recurrenceIndex?: number\n}\n\nexport interface EventCalendarSegment\u003CTData = unknown> {\n  occurrence: EventCalendarOccurrence\u003CTData>\n  \u002F** Zoned day this segment belongs to. *\u002F\n  day: Date\n  isStart: boolean\n  isEnd: boolean\n  continuesBefore: boolean\n  continuesAfter: boolean\n  \u002F** Timed only: minutes from the zoned day start. *\u002F\n  startMin?: number\n  endMin?: number\n  \u002F** Month \u002F all-day lane index. *\u002F\n  lane?: number\n  \u002F** Time-grid overlap packing. *\u002F\n  column?: number\n  columnCount?: number\n  columnSpan?: number\n  \u002F** Week-row granularity (month bars \u002F all-day lanes). *\u002F\n  rowIndex?: number\n  colStart?: number\n  colSpan?: number\n}\n\nexport interface EventCalendarSelection {\n  eventKeys: string[]\n  \u002F** Committed slot selection; see EventCalendarSlotDraft for the in-gesture value. *\u002F\n  slot: { start: Date; end: Date; allDay: boolean } | null\n}\n\nexport interface EventCalendarInteractions {\n  drag: boolean\n  resize: boolean\n  selectSlot: boolean\n}\n\nexport interface EventCalendarDragState\u003CTData = unknown> {\n  kind: \"move\" | \"resize-start\" | \"resize-end\"\n  occurrence: EventCalendarOccurrence\u003CTData>\n  proposedStart: Date\n  proposedEnd: Date\n  proposedAllDay: boolean\n  \u002F**\n   * True when the proposal was resolved on the day-granular surface (month\n   * cells \u002F the all-day lane) rather than minute columns - the all-day lane\n   * ghost keys on this, covering timed MULTI-DAY bars whose proposals stay\n   * timed (proposedAllDay alone misses them).\n   *\u002F\n  proposedDayGranular: boolean\n  \u002F** Target resource when dragging across resource columns\u002Frows. *\u002F\n  proposedResourceId?: string\n  \u002F** Last canDropEvent verdict; drives data-drop-invalid styling. *\u002F\n  valid: boolean\n}\n\n\u002F**\n * The in-progress drag-create rectangle ONLY, cleared on commit or cancel.\n * The committed slot selection lives in EventCalendarSelection.slot.\n *\u002F\nexport interface EventCalendarSlotDraft {\n  start: Date\n  end: Date\n  allDay: boolean\n  view: CalendarView\n  \u002F** Present when the slot was selected inside a resource column\u002Frow. *\u002F\n  resourceId?: string\n}\n\n\u002F**\n * User-adjustable display toggles (the \"View settings\" submenu). Every field\n * is optional; undefined defers to the matching root view-config prop.\n *\u002F\nexport interface EventCalendarViewSettings {\n  \u002F** Show Saturday\u002FSunday columns in month, week, and N-day grids. *\u002F\n  weekends?: boolean\n  \u002F** Week-number gutter in the month view. *\u002F\n  weekNumbers?: boolean\n  nowIndicator?: boolean\n  \u002F** Off-day (non-working) background marking. *\u002F\n  offDays?: boolean\n}\n\nexport interface EventCalendarState\u003CTData = unknown> {\n  view: CalendarView\n  \u002F** Anchor date. *\u002F\n  date: Date\n  \u002F** For the \"days\" view. *\u002F\n  dayCount: number\n  \u002F** Full rendered grid incl. outside days - fetch remote data for THIS. *\u002F\n  visibleRange: EventCalendarDateRange\n  \u002F** The logical period (the month\u002Fweek itself). *\u002F\n  activeRange: EventCalendarDateRange\n  events: CalendarEvent\u003CTData>[]\n  selection: EventCalendarSelection\n  interactions: EventCalendarInteractions\n  loading: boolean\n  drag: EventCalendarDragState\u003CTData> | null\n  slotDraft: EventCalendarSlotDraft | null\n  viewSettings: EventCalendarViewSettings\n}\n\nexport interface EventCalendarRangeInfo {\n  range: EventCalendarDateRange\n  activeRange: EventCalendarDateRange\n  view: CalendarView\n  date: Date\n  timeZone: string\n}\n\nexport interface EventCalendarProposedUpdate\u003CTData = unknown> {\n  event: CalendarEvent\u003CTData>\n  \u002F** null when source === \"api\". *\u002F\n  occurrence: EventCalendarOccurrence\u003CTData> | null\n  start: Date\n  end: Date\n  allDay: boolean\n  \u002F** Proposed resource when the gesture crossed resource columns\u002Frows. *\u002F\n  resourceId?: string\n  source: \"drag\" | \"resize-start\" | \"resize-end\" | \"keyboard\" | \"api\"\n}\n\n\u002F** false = reject\u002Frevert; void or true = accept; object = accept with adjustment. *\u002F\nexport type EventCalendarUpdateResult =\n  | boolean\n  | void\n  | { start?: Date; end?: Date; allDay?: boolean }\n\n\u002F** A click is a point, not a range; `end` is present for timed slots. *\u002F\nexport interface EventCalendarSlotInfo {\n  date: Date\n  end?: Date\n  allDay: boolean\n  view: CalendarView\n  \u002F** Present when the click happened inside a resource column\u002Frow. *\u002F\n  resourceId?: string\n}\n\n\u002F**\n * Off-day marking (non-working days). `true` uses the defaults: weekends\n * with a muted background. Custom weekday sets, explicit dates, a predicate,\n * and a custom class are all supported; marked cells carry `data-off` for\n * CSS-selector customization.\n *\u002F\nexport interface EventCalendarOffDaysConfig {\n  \u002F** Weekday numbers treated as off (0 = Sunday). Default [0, 6]. *\u002F\n  weekendDays?: number[]\n  \u002F** Additional explicit off dates (compared by day in the display zone). *\u002F\n  dates?: Date[]\n  \u002F** Full custom predicate; runs in addition to weekendDays\u002Fdates. *\u002F\n  isOffDay?: (day: Date) => boolean\n  \u002F** Marker classes; default \"bg-muted\u002F25\". *\u002F\n  className?: string\n}\n\n\u002F**\n * External-data contract. v1 ships the type plus docs recipes (Google\n * events.list \u002F MS Graph calendarView map to CalendarEvent in ~15 lines);\n * OAuth, tokens, and sync loops are application backend territory.\n *\u002F\nexport interface EventCalendarDataAdapter\u003CTData = unknown> {\n  getEvents(\n    range: EventCalendarDateRange,\n    signal?: AbortSignal\n  ): Promise\u003CCalendarEvent\u003CTData>[]>\n}\n",{"source":483},1785737589247]