@torpor/ui 0.1.7 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/dist/Accordion/Accordion.torp +25 -13
  3. package/dist/Accordion/AccordionContent.torp +15 -8
  4. package/dist/Accordion/AccordionHeader.torp +16 -7
  5. package/dist/Accordion/AccordionItem.torp +24 -10
  6. package/dist/Accordion/AccordionTrigger.torp +16 -8
  7. package/dist/Accordion/AccordionTypes.ts +2 -0
  8. package/dist/Accordion/index.d.ts +157 -0
  9. package/dist/Breadcrumb/Breadcrumb.torp +42 -0
  10. package/dist/Breadcrumb/BreadcrumbItem.torp +28 -0
  11. package/dist/Breadcrumb/BreadcrumbSeparator.torp +25 -0
  12. package/dist/Breadcrumb/index.d.ts +84 -0
  13. package/dist/Breadcrumb/index.js +14 -0
  14. package/dist/Calendar/Calendar.torp +273 -0
  15. package/dist/Calendar/CalendarDay.torp +75 -0
  16. package/dist/Calendar/CalendarTypes.ts +22 -0
  17. package/dist/Calendar/index.d.ts +36 -0
  18. package/dist/Calendar/index.js +10 -0
  19. package/dist/Calendar/index.js.map +1 -0
  20. package/dist/Dialog/Dialog.torp +16 -6
  21. package/dist/Dialog/DialogBody.torp +13 -5
  22. package/dist/Dialog/DialogButton.torp +18 -6
  23. package/dist/Dialog/DialogFooter.torp +13 -3
  24. package/dist/Dialog/DialogHeader.torp +13 -4
  25. package/dist/Dialog/index.d.ts +135 -0
  26. package/dist/Disclosure/Disclosure.torp +79 -0
  27. package/dist/Disclosure/DisclosureContent.torp +43 -0
  28. package/dist/Disclosure/DisclosureHeader.torp +43 -0
  29. package/dist/Disclosure/DisclosureTrigger.torp +44 -0
  30. package/dist/Disclosure/DisclosureTypes.ts +14 -0
  31. package/dist/Disclosure/index.d.ts +113 -0
  32. package/dist/Disclosure/index.js +18 -0
  33. package/dist/Disclosure/index.js.map +1 -0
  34. package/{src/Offscreen/Offscreen.torp → dist/Drawer/Drawer.torp} +20 -19
  35. package/dist/Drawer/index.d.ts +21 -0
  36. package/dist/Drawer/index.js +6 -0
  37. package/dist/Drawer/index.js.map +1 -0
  38. package/dist/Form/Field.torp +93 -0
  39. package/dist/Form/Form.torp +131 -0
  40. package/dist/Form/FormTypes.ts +30 -0
  41. package/dist/Form/Input.torp +94 -0
  42. package/dist/Form/Label.torp +31 -0
  43. package/dist/Form/Message.torp +35 -0
  44. package/dist/Form/StandardSchemaV1.ts +70 -0
  45. package/dist/Form/index.d.ts +117 -0
  46. package/dist/Form/index.js +22 -0
  47. package/dist/Form/index.js.map +1 -0
  48. package/dist/Menu/Menu.torp +169 -0
  49. package/dist/Menu/MenuButton.torp +64 -0
  50. package/dist/Menu/MenuCheck.torp +81 -0
  51. package/dist/Menu/MenuGroup.torp +29 -0
  52. package/dist/Menu/MenuIndicator.torp +38 -0
  53. package/dist/Menu/MenuPopout.torp +82 -0
  54. package/dist/Menu/MenuPopoutContent.torp +83 -0
  55. package/dist/Menu/MenuPopoutTrigger.torp +126 -0
  56. package/dist/Menu/MenuRadio.torp +99 -0
  57. package/dist/Menu/MenuRadioGroup.torp +97 -0
  58. package/dist/Menu/MenuSeparator.torp +24 -0
  59. package/dist/Menu/MenuTypes.ts +58 -0
  60. package/dist/Menu/index.d.ts +293 -0
  61. package/dist/Menu/index.js +46 -0
  62. package/dist/Menu/index.js.map +1 -0
  63. package/dist/MenuBar/MenuBar.torp +159 -0
  64. package/dist/MenuBar/MenuBarItem.torp +115 -0
  65. package/dist/MenuBar/MenuBarItemContent.torp +117 -0
  66. package/dist/MenuBar/MenuBarItemTrigger.torp +98 -0
  67. package/dist/MenuBar/MenuBarTypes.ts +36 -0
  68. package/dist/MenuBar/index.d.ts +125 -0
  69. package/dist/MenuBar/index.js +18 -0
  70. package/dist/MenuBar/index.js.map +1 -0
  71. package/dist/NavMenu/NavMenu.torp +15 -6
  72. package/dist/NavMenu/NavMenuButton.torp +14 -7
  73. package/dist/NavMenu/NavMenuElement.torp +16 -8
  74. package/dist/NavMenu/NavMenuGroup.torp +14 -5
  75. package/dist/NavMenu/NavMenuGroupHeader.torp +14 -6
  76. package/dist/NavMenu/NavMenuLink.torp +18 -10
  77. package/dist/NavMenu/NavMenuPopout.torp +13 -5
  78. package/dist/NavMenu/NavMenuPopoutButton.torp +17 -11
  79. package/dist/NavMenu/NavMenuPopoutContent.torp +42 -30
  80. package/dist/NavMenu/NavMenuSeparator.torp +12 -3
  81. package/dist/NavMenu/index.d.ts +259 -0
  82. package/dist/Notification/Notification.torp +58 -0
  83. package/dist/Notification/NotificationClose.torp +37 -0
  84. package/dist/Notification/NotificationContainer.torp +24 -0
  85. package/dist/Notification/NotificationContent.torp +23 -0
  86. package/dist/Notification/NotificationTypes.ts +5 -0
  87. package/dist/Notification/index.d.ts +92 -0
  88. package/dist/Notification/index.js +36 -0
  89. package/dist/Notification/index.js.map +1 -0
  90. package/dist/Notification/showNotification.ts +30 -0
  91. package/dist/Popover/Popover.torp +22 -8
  92. package/dist/Popover/PopoverContent.torp +41 -29
  93. package/dist/Popover/PopoverContentAnchored.torp +52 -44
  94. package/dist/Popover/PopoverContentContextual.torp +49 -37
  95. package/dist/Popover/PopoverOverlay.torp +13 -4
  96. package/dist/Popover/PopoverTrigger.torp +12 -3
  97. package/dist/Popover/PopoverTriggerContextual.torp +12 -3
  98. package/dist/Popover/PopoverTriggerHover.torp +14 -5
  99. package/dist/Popover/index.d.ts +191 -0
  100. package/dist/TabGroup/TabContent.torp +13 -7
  101. package/dist/TabGroup/TabGroup.torp +23 -11
  102. package/dist/TabGroup/TabHeader.torp +16 -7
  103. package/dist/TabGroup/TabList.torp +15 -6
  104. package/dist/TabGroup/TabTrigger.torp +14 -6
  105. package/dist/TabGroup/index.d.ts +150 -0
  106. package/dist/icons/ArrowDown.torp +15 -0
  107. package/dist/icons/ArrowLeft.torp +15 -0
  108. package/dist/icons/ArrowRight.torp +15 -0
  109. package/dist/icons/ArrowUp.torp +15 -0
  110. package/dist/icons/Bars.torp +17 -0
  111. package/dist/icons/Check.torp +15 -0
  112. package/dist/icons/ChevronDown.torp +15 -0
  113. package/dist/icons/ChevronLeft.torp +15 -0
  114. package/dist/icons/ChevronRight.torp +15 -0
  115. package/dist/icons/ChevronUp.torp +15 -0
  116. package/dist/icons/Cross.torp +16 -0
  117. package/dist/icons/Loading.torp +16 -0
  118. package/dist/icons/Minus.torp +15 -0
  119. package/dist/icons/Plus.torp +16 -0
  120. package/dist/icons/index.d.ts +142 -0
  121. package/dist/icons/index.js +58 -0
  122. package/dist/icons/index.js.map +1 -0
  123. package/dist/{motion.d.cts → index.d.ts} +2 -2
  124. package/dist/metafile-esm.json +1 -1
  125. package/dist/motion/fade.ts +7 -0
  126. package/dist/motion/index.d.ts +2 -0
  127. package/dist/{motion.js → motion/index.js} +1 -1
  128. package/dist/motion/index.js.map +1 -0
  129. package/dist/mount/index.d.ts +2 -0
  130. package/dist/utils/dateUtils.ts +244 -0
  131. package/dist/utils/index.d.ts +2 -0
  132. package/dist/utils/setPopoverPosition.ts +4 -0
  133. package/package.json +60 -35
  134. package/scripts/postbuild.ts +42 -5
  135. package/src/Accordion/Accordion.torp +25 -13
  136. package/src/Accordion/AccordionContent.torp +15 -8
  137. package/src/Accordion/AccordionHeader.torp +16 -7
  138. package/src/Accordion/AccordionItem.torp +24 -10
  139. package/src/Accordion/AccordionTrigger.torp +16 -8
  140. package/src/Accordion/AccordionTypes.ts +2 -0
  141. package/src/Breadcrumb/Breadcrumb.torp +42 -0
  142. package/src/Breadcrumb/BreadcrumbItem.torp +28 -0
  143. package/src/Breadcrumb/BreadcrumbSeparator.torp +25 -0
  144. package/src/Breadcrumb/index.ts +5 -0
  145. package/src/Calendar/Calendar.torp +273 -0
  146. package/src/Calendar/CalendarDay.torp +75 -0
  147. package/src/Calendar/CalendarTypes.ts +22 -0
  148. package/src/Calendar/index.ts +4 -0
  149. package/src/Dialog/Dialog.torp +16 -6
  150. package/src/Dialog/DialogBody.torp +13 -5
  151. package/src/Dialog/DialogButton.torp +18 -6
  152. package/src/Dialog/DialogFooter.torp +13 -3
  153. package/src/Dialog/DialogHeader.torp +13 -4
  154. package/src/Disclosure/Disclosure.torp +79 -0
  155. package/src/Disclosure/DisclosureContent.torp +43 -0
  156. package/src/Disclosure/DisclosureHeader.torp +43 -0
  157. package/src/Disclosure/DisclosureTrigger.torp +44 -0
  158. package/src/Disclosure/DisclosureTypes.ts +14 -0
  159. package/src/Disclosure/index.ts +6 -0
  160. package/{dist/Offscreen/Offscreen.torp → src/Drawer/Drawer.torp} +20 -19
  161. package/src/Drawer/index.ts +3 -0
  162. package/src/Form/Field.torp +93 -0
  163. package/src/Form/Form.torp +131 -0
  164. package/src/Form/FormTypes.ts +30 -0
  165. package/src/Form/Input.torp +94 -0
  166. package/src/Form/Label.torp +31 -0
  167. package/src/Form/Message.torp +35 -0
  168. package/src/Form/StandardSchemaV1.ts +70 -0
  169. package/src/Form/index.ts +7 -0
  170. package/src/Menu/Menu.torp +169 -0
  171. package/src/Menu/MenuButton.torp +64 -0
  172. package/src/Menu/MenuCheck.torp +81 -0
  173. package/src/Menu/MenuGroup.torp +29 -0
  174. package/src/Menu/MenuIndicator.torp +38 -0
  175. package/src/Menu/MenuPopout.torp +82 -0
  176. package/src/Menu/MenuPopoutContent.torp +83 -0
  177. package/src/Menu/MenuPopoutTrigger.torp +126 -0
  178. package/src/Menu/MenuRadio.torp +99 -0
  179. package/src/Menu/MenuRadioGroup.torp +97 -0
  180. package/src/Menu/MenuSeparator.torp +24 -0
  181. package/src/Menu/MenuTypes.ts +58 -0
  182. package/src/Menu/index.ts +25 -0
  183. package/src/MenuBar/MenuBar.torp +159 -0
  184. package/src/MenuBar/MenuBarItem.torp +115 -0
  185. package/src/MenuBar/MenuBarItemContent.torp +117 -0
  186. package/src/MenuBar/MenuBarItemTrigger.torp +98 -0
  187. package/src/MenuBar/MenuBarTypes.ts +36 -0
  188. package/src/MenuBar/index.ts +6 -0
  189. package/src/NavMenu/NavMenu.torp +15 -6
  190. package/src/NavMenu/NavMenuButton.torp +14 -7
  191. package/src/NavMenu/NavMenuElement.torp +16 -8
  192. package/src/NavMenu/NavMenuGroup.torp +14 -5
  193. package/src/NavMenu/NavMenuGroupHeader.torp +14 -6
  194. package/src/NavMenu/NavMenuLink.torp +18 -10
  195. package/src/NavMenu/NavMenuPopout.torp +13 -5
  196. package/src/NavMenu/NavMenuPopoutButton.torp +17 -11
  197. package/src/NavMenu/NavMenuPopoutContent.torp +42 -30
  198. package/src/NavMenu/NavMenuSeparator.torp +12 -3
  199. package/src/Notification/Notification.torp +58 -0
  200. package/src/Notification/NotificationClose.torp +37 -0
  201. package/src/Notification/NotificationContainer.torp +24 -0
  202. package/src/Notification/NotificationContent.torp +23 -0
  203. package/src/Notification/NotificationTypes.ts +5 -0
  204. package/src/Notification/index.ts +13 -0
  205. package/src/Notification/showNotification.ts +30 -0
  206. package/src/Popover/Popover.torp +22 -8
  207. package/src/Popover/PopoverContent.torp +41 -29
  208. package/src/Popover/PopoverContentAnchored.torp +52 -44
  209. package/src/Popover/PopoverContentContextual.torp +49 -37
  210. package/src/Popover/PopoverOverlay.torp +13 -4
  211. package/src/Popover/PopoverTrigger.torp +12 -3
  212. package/src/Popover/PopoverTriggerContextual.torp +12 -3
  213. package/src/Popover/PopoverTriggerHover.torp +14 -5
  214. package/src/Slider/Slider.torp +83 -0
  215. package/src/Slider/index.ts +3 -0
  216. package/src/TabGroup/TabContent.torp +13 -7
  217. package/src/TabGroup/TabGroup.torp +23 -11
  218. package/src/TabGroup/TabHeader.torp +16 -7
  219. package/src/TabGroup/TabList.torp +15 -6
  220. package/src/TabGroup/TabTrigger.torp +14 -6
  221. package/src/icons/ArrowDown.torp +15 -0
  222. package/src/icons/ArrowLeft.torp +15 -0
  223. package/src/icons/ArrowRight.torp +15 -0
  224. package/src/icons/ArrowUp.torp +15 -0
  225. package/src/icons/Bars.torp +17 -0
  226. package/src/icons/Check.torp +15 -0
  227. package/src/icons/ChevronDown.torp +15 -0
  228. package/src/icons/ChevronLeft.torp +15 -0
  229. package/src/icons/ChevronRight.torp +15 -0
  230. package/src/icons/ChevronUp.torp +15 -0
  231. package/src/icons/Cross.torp +16 -0
  232. package/src/icons/Loading.torp +16 -0
  233. package/src/icons/Minus.torp +15 -0
  234. package/src/icons/Plus.torp +16 -0
  235. package/src/icons/index.ts +31 -0
  236. package/src/motion/fade.ts +2 -2
  237. package/src/motion/index.ts +3 -0
  238. package/src/utils/dateUtils.ts +244 -0
  239. package/src/utils/setPopoverPosition.ts +4 -0
  240. package/test/Accordion/components/AccordionAccessibility.torp +2 -0
  241. package/test/Accordion/components/AccordionKeyboard.torp +2 -0
  242. package/test/Accordion/components/AccordionList.torp +2 -0
  243. package/test/Accordion/components/AccordionMultiple.torp +2 -0
  244. package/test/Accordion/components/AccordionSingle.torp +2 -0
  245. package/test/Breadcrumb/accessibility.test.ts +29 -0
  246. package/test/Breadcrumb/basic.test.ts +17 -0
  247. package/test/Breadcrumb/components/BreadcrumbTest.torp +15 -0
  248. package/test/Calendar/components/CalendarTest.torp +9 -0
  249. package/test/Calendar/default.test.ts +18 -0
  250. package/test/Dialog/components/DialogAccessibility.torp +5 -5
  251. package/test/Disclosure/accessibility.test.ts +31 -0
  252. package/test/Disclosure/components/DisclosureTest.torp +19 -0
  253. package/test/Disclosure/default.test.ts +15 -0
  254. package/test/Disclosure/toggle.test.ts +20 -0
  255. package/test/Form/components/FieldTest.torp +25 -0
  256. package/test/Form/components/FormTest.torp +31 -0
  257. package/test/Form/components/InputTest.torp +9 -0
  258. package/test/Form/field.test.ts +34 -0
  259. package/test/Form/form.test.ts +34 -0
  260. package/test/Form/input.test.ts +19 -0
  261. package/test/Menu/accessibility.test.ts +83 -0
  262. package/test/Menu/basic.test.ts +58 -0
  263. package/test/Menu/components/MenuAccessibility.torp +59 -0
  264. package/test/Menu/components/MenuBasic.torp +58 -0
  265. package/test/MenuBar/accessibility.test.ts +87 -0
  266. package/test/MenuBar/basic.test.ts +22 -0
  267. package/test/MenuBar/components/MenuBarAccessibility.torp +34 -0
  268. package/test/MenuBar/components/MenuBarBasic.torp +25 -0
  269. package/test/NavMenu/basic.test.ts +1 -1
  270. package/test/NavMenu/components/{NavMenu.torp → NavMenuBasic.torp} +1 -1
  271. package/test/Notification/accessibility.test.ts +21 -0
  272. package/test/Notification/components/CustomNotification.torp +14 -0
  273. package/test/Notification/components/NotificationAccessibility.torp +14 -0
  274. package/test/Notification/components/NotificationFunction.torp +20 -0
  275. package/test/Notification/components/NotificationVariable.torp +22 -0
  276. package/test/Notification/function.test.ts +25 -0
  277. package/test/Notification/variable.test.ts +25 -0
  278. package/test/Popover/components/CustomDialog.torp +25 -0
  279. package/test/Popover/components/PromptFunction.torp +19 -0
  280. package/test/Popover/components/PromptVariable.torp +38 -0
  281. package/test/Popover/function.test.ts +26 -0
  282. package/test/Popover/variable.test.ts +27 -0
  283. package/test/TabGroup/components/TabGroupAccessibility.torp +2 -0
  284. package/test/TabGroup/components/TabGroupKeyboard.torp +2 -0
  285. package/test/TabGroup/components/TabGroupList.torp +2 -0
  286. package/test/TabGroup/components/TabGroupTrigger.torp +2 -0
  287. package/tsup.config.ts +12 -4
  288. package/dist/Accordion/index.cjs +0 -53
  289. package/dist/Accordion/index.cjs.map +0 -1
  290. package/dist/Dialog/index.cjs +0 -53
  291. package/dist/Dialog/index.cjs.map +0 -1
  292. package/dist/NavMenu/index.cjs +0 -78
  293. package/dist/NavMenu/index.cjs.map +0 -1
  294. package/dist/Offscreen/index.cjs +0 -33
  295. package/dist/Offscreen/index.cjs.map +0 -1
  296. package/dist/Offscreen/index.js +0 -6
  297. package/dist/Popover/index.cjs +0 -222
  298. package/dist/Popover/index.cjs.map +0 -1
  299. package/dist/TabGroup/index.cjs +0 -53
  300. package/dist/TabGroup/index.cjs.map +0 -1
  301. package/dist/metafile-cjs.json +0 -1
  302. package/dist/motion.cjs +0 -34
  303. package/dist/motion.cjs.map +0 -1
  304. package/dist/motion.d.ts +0 -6
  305. package/dist/motion.js.map +0 -1
  306. package/src/Accordion.ts +0 -7
  307. package/src/Dialog.ts +0 -7
  308. package/src/NavMenu.ts +0 -23
  309. package/src/Offscreen/index.ts +0 -3
  310. package/src/Popover.ts +0 -29
  311. package/src/TabGroup.ts +0 -7
  312. package/src/motion.ts +0 -3
  313. /package/dist/{Offscreen → Breadcrumb}/index.js.map +0 -0
@@ -0,0 +1,244 @@
1
+ // TODO: Can we get these from the locale?
2
+ const monthNames: string[] = [
3
+ "January",
4
+ "February",
5
+ "March",
6
+ "April",
7
+ "May",
8
+ "June",
9
+ "July",
10
+ "August",
11
+ "September",
12
+ "October",
13
+ "November",
14
+ "December",
15
+ ];
16
+ const shortMonthNames: string[] = monthNames.map((n) => n.substring(0, 3).toLowerCase());
17
+
18
+ const dayNames: string[] = [
19
+ "Sunday",
20
+ "Monday",
21
+ "Tuesday",
22
+ "Wednesday",
23
+ "Thursday",
24
+ "Friday",
25
+ "Saturday",
26
+ "Sunday",
27
+ ];
28
+ const shortDayNames: string[] = dayNames.map((n) => n.substring(0, 3).toLowerCase());
29
+
30
+ export { monthNames, shortMonthNames, dayNames, shortDayNames };
31
+
32
+ export function areDatesEqual(date1: Date, date2: Date): boolean {
33
+ if ((date1 && !date2) || (date2 && !date1)) {
34
+ return false;
35
+ }
36
+ return (
37
+ date1.getFullYear() === date2.getFullYear() &&
38
+ date1.getMonth() === date2.getMonth() &&
39
+ date1.getDate() === date2.getDate()
40
+ );
41
+ }
42
+
43
+ export function parseDateTime(text: string, dateOrder: string): Date {
44
+ const parts = text
45
+ .toString()
46
+ .toLowerCase()
47
+ .split(/[.,/ :-]/);
48
+
49
+ const today = new Date();
50
+ let day = today.getDate();
51
+ let month = today.getMonth();
52
+ let year = today.getFullYear();
53
+ let hour = 9;
54
+ let minute = 0;
55
+ //let ampm = "";
56
+
57
+ let dayPart = -1;
58
+ let monthPart = -1;
59
+ let yearPart = -1;
60
+ //let hourPart = -1;
61
+
62
+ // Try to get the month if it's been supplied as a word
63
+ for (let i = 0; i < parts.length; i++) {
64
+ const index = shortMonthNames.indexOf(parts[i].substring(0, 3));
65
+ if (index !== -1) {
66
+ month = index;
67
+ monthPart = i;
68
+ break;
69
+ }
70
+ }
71
+
72
+ // Get each date part based on the dateOrder supplied
73
+ const dateOrderLower = dateOrder.toLowerCase();
74
+ for (let i = 0; i < dateOrder.length; i++) {
75
+ if (dateOrderLower[i] === "d") {
76
+ const dayResult = getDayPart(parts, monthPart, yearPart);
77
+ if (dayResult) {
78
+ day = dayResult.value;
79
+ dayPart = dayResult.part;
80
+ }
81
+ }
82
+ if (dateOrderLower[i] === "m" && monthPart === -1) {
83
+ const monthResult = getMonthPart(parts, dayPart, yearPart);
84
+ if (monthResult) {
85
+ month = monthResult.value;
86
+ monthPart = monthResult.part;
87
+ }
88
+ }
89
+ if (dateOrderLower[i] === "y") {
90
+ const yearResult = getYearPart(parts, dayPart, monthPart);
91
+ if (yearResult) {
92
+ year = yearResult.value;
93
+ yearPart = yearResult.part;
94
+ }
95
+ }
96
+ }
97
+
98
+ // TODO: Time...
99
+ //if (includeTime) {
100
+ // // Hour part is the first part that isn't a date part
101
+ // for (let i = 0; i < parts.length; i++) {
102
+ // if (i !== yearPart && i !== monthPart && i !== dayPart) {
103
+ // const maybehour = parseInt(parts[i])
104
+ // if (!isNaN(maybehour)) {
105
+ // hour = maybehour
106
+ // hourPart = i
107
+ // break
108
+ // }
109
+ // }
110
+ // }
111
+ //
112
+ // // Minute part is the first part that isn't a date part or the hour part
113
+ // for (let i = 0; i < parts.length; i++) {
114
+ // if (i !== yearPart && i !== monthPart && i !== dayPart && i !== hourPart) {
115
+ // const maybeminute = parseInt(parts[i])
116
+ // if (!isNaN(maybeminute)) {
117
+ // minute = maybeminute
118
+ // break
119
+ // }
120
+ // }
121
+ // }
122
+ //
123
+ // // Look for AM or PM
124
+ // for (let i = 0; i < parts.length; i++) {
125
+ // if (parts[i] === 'am' || parts[i] === 'pm') {
126
+ // ampm = parts[i].toString().toUpperCase()
127
+ // if (ampm === 'PM') {
128
+ // hour = hour + 12
129
+ // }
130
+ // break
131
+ // }
132
+ // }
133
+ //}
134
+
135
+ return new Date(year, month, day, hour, minute);
136
+ }
137
+
138
+ interface DatePart {
139
+ value: number;
140
+ part: number;
141
+ }
142
+
143
+ function getDayPart(parts: string[], monthPart: number, yearPart: number): DatePart | undefined {
144
+ for (let i = 0; i < parts.length; i++) {
145
+ if (i !== monthPart && i !== yearPart) {
146
+ const maybeday = parseInt(parts[i]);
147
+ if (!isNaN(maybeday)) {
148
+ const value = maybeday;
149
+ const part = i;
150
+ return { value, part };
151
+ }
152
+ }
153
+ }
154
+ }
155
+
156
+ function getMonthPart(parts: string[], dayPart: number, yearPart: number): DatePart | undefined {
157
+ for (let i = 0; i < parts.length; i++) {
158
+ if (i !== dayPart && i !== yearPart) {
159
+ const maybemonth = parseInt(parts[i]);
160
+ if (!isNaN(maybemonth)) {
161
+ const value = maybemonth - 1;
162
+ const part = i;
163
+ return { value, part };
164
+ }
165
+ }
166
+ }
167
+ }
168
+
169
+ function getYearPart(parts: string[], dayPart: number, monthPart: number): DatePart | undefined {
170
+ for (let i = 0; i < parts.length; i++) {
171
+ if (i !== monthPart && i !== dayPart) {
172
+ const maybeyear = parseInt(parts[i]);
173
+ if (!isNaN(maybeyear)) {
174
+ const value = maybeyear < 100 ? maybeyear + 2000 : maybeyear;
175
+ const part = i;
176
+ return { value, part };
177
+ }
178
+ }
179
+ }
180
+ }
181
+
182
+ export function formatDate(value: Date, dateFormat: string): string {
183
+ if (!value) {
184
+ return "";
185
+ }
186
+
187
+ const date = new Date(value);
188
+
189
+ // Build the text that will be displayed
190
+ return dateFormat.replace(/(d+)|(M+)|(y+)/g, (m) => {
191
+ if (m.indexOf("d") >= 0) {
192
+ return formatDay(date, m);
193
+ } else if (m.indexOf("M") >= 0) {
194
+ return formatMonth(date, m);
195
+ } else if (m.indexOf("y") >= 0) {
196
+ return formatYear(date, m);
197
+ } else {
198
+ throw new Error("Invalid date format string");
199
+ }
200
+ });
201
+
202
+ // TODO: Time
203
+ //if (includeTime) {
204
+ // const ampm = hour >= 12 ? 'PM' : 'AM'
205
+ // hour = hour % 12
206
+ // hour = hour || 12 // the hour '0' should be '12'
207
+ //
208
+ // minute = minute < 10 ? '0' + minute : minute
209
+ // text = text + ' ' + hour + ':' + minute + ' ' + ampm
210
+ //}
211
+ }
212
+
213
+ function formatDay(date: Date, d: string): string {
214
+ if (d.length >= 4) {
215
+ return dayNames[date.getDay()];
216
+ } else if (d.length === 3) {
217
+ return dayNames[date.getDay()].substring(0, 3);
218
+ } else if (d.length == 2) {
219
+ let text = date.getDate().toString();
220
+ return text.length < 2 ? "0" + text : text;
221
+ } else {
222
+ return date.getDate().toString();
223
+ }
224
+ }
225
+
226
+ function formatMonth(date: Date, m: string): string {
227
+ if (m.length >= 4) {
228
+ return monthNames[date.getMonth()];
229
+ } else if (m.length === 3) {
230
+ return monthNames[date.getMonth()].substring(0, 3);
231
+ } else if (m.length == 2) {
232
+ let text = date.getMonth().toString();
233
+ return text.length < 2 ? "0" + text : text;
234
+ } else {
235
+ return date.getMonth().toString();
236
+ }
237
+ }
238
+
239
+ function formatYear(date: Date, y: string): string {
240
+ return date
241
+ .getFullYear()
242
+ .toString()
243
+ .substring(4 - y.length, y.length);
244
+ }
@@ -0,0 +1,2 @@
1
+ import { type SlotRender } from "@torpor/view";
2
+ export { };
@@ -42,6 +42,7 @@ export default function setPopoverPosition(
42
42
  break;
43
43
  }
44
44
  default: {
45
+ // eslint-disable-next-line restrict-template-expressions
45
46
  throw new Error(`Invalid MenuPopout side: ${side}`);
46
47
  }
47
48
  }
@@ -68,6 +69,7 @@ export default function setPopoverPosition(
68
69
  break;
69
70
  }
70
71
  default: {
72
+ // eslint-disable-next-line restrict-template-expressions
71
73
  throw new Error(`Invalid MenuPopout side: ${side}`);
72
74
  }
73
75
  }
@@ -94,6 +96,7 @@ function setVerticalAlignment(
94
96
  break;
95
97
  }
96
98
  default: {
99
+ // eslint-disable-next-line restrict-template-expressions
97
100
  throw new Error(`Invalid Popout alignment: ${alignment}`);
98
101
  }
99
102
  }
@@ -126,6 +129,7 @@ function setHorizontalAlignment(
126
129
  break;
127
130
  }
128
131
  default: {
132
+ // eslint-disable-next-line restrict-template-expressions
129
133
  throw new Error(`Invalid Popout alignment: ${alignment}`);
130
134
  }
131
135
  }
package/package.json CHANGED
@@ -1,46 +1,69 @@
1
1
  {
2
2
  "name": "@torpor/ui",
3
- "version": "0.1.7",
3
+ "version": "0.2.1",
4
4
  "description": "Accessible, unstyled components for use in your Torpor front-end",
5
5
  "type": "module",
6
- "main": "dist/index.cjs",
7
- "module": "dist/index.js",
8
- "types": "dist/index.d.ts",
9
6
  "exports": {
10
7
  "./Accordion": {
11
8
  "types": "./dist/Accordion/index.d.ts",
12
- "import": "./dist/Accordion/index.js",
13
- "require": "./dist/Accordion/index.cjs"
9
+ "import": "./dist/Accordion/index.js"
10
+ },
11
+ "./Breadcrumb": {
12
+ "types": "./dist/Breadcrumb/index.d.ts",
13
+ "import": "./dist/Breadcrumb/index.js"
14
+ },
15
+ "./Calendar": {
16
+ "types": "./dist/Calendar/index.d.ts",
17
+ "import": "./dist/Calendar/index.js",
18
+ "require": "./dist/Calendar/index.cjs"
14
19
  },
15
20
  "./Dialog": {
16
21
  "types": "./dist/Dialog/index.d.ts",
17
- "import": "./dist/Dialog/index.js",
18
- "require": "./dist/Dialog/index.cjs"
22
+ "import": "./dist/Dialog/index.js"
23
+ },
24
+ "./Disclosure": {
25
+ "types": "./dist/Disclosure/index.d.ts",
26
+ "import": "./dist/Disclosure/index.js"
27
+ },
28
+ "./Drawer": {
29
+ "types": "./dist/Drawer/index.d.ts",
30
+ "import": "./dist/Drawer/index.js"
31
+ },
32
+ "./Form": {
33
+ "types": "./dist/Form/index.d.ts",
34
+ "import": "./dist/Form/index.js"
35
+ },
36
+ "./Menu": {
37
+ "types": "./dist/Menu/index.d.ts",
38
+ "import": "./dist/Menu/index.js"
39
+ },
40
+ "./MenuBar": {
41
+ "types": "./dist/MenuBar/index.d.ts",
42
+ "import": "./dist/MenuBar/index.js"
19
43
  },
20
44
  "./NavMenu": {
21
45
  "types": "./dist/NavMenu/index.d.ts",
22
- "import": "./dist/NavMenu/index.js",
23
- "require": "./dist/NavMenu/index.cjs"
46
+ "import": "./dist/NavMenu/index.js"
24
47
  },
25
- "./Offscreen": {
26
- "types": "./dist/Offscreen/index.d.ts",
27
- "import": "./dist/Offscreen/index.js",
28
- "require": "./dist/Offscreen/index.cjs"
48
+ "./Notification": {
49
+ "types": "./dist/Notification/index.d.ts",
50
+ "import": "./dist/Notification/index.js"
29
51
  },
30
52
  "./Popover": {
31
53
  "types": "./dist/Popover/index.d.ts",
32
- "import": "./dist/Popover/index.js",
33
- "require": "./dist/Popover/index.cjs"
54
+ "import": "./dist/Popover/index.js"
34
55
  },
35
56
  "./TabGroup": {
36
57
  "types": "./dist/TabGroup/index.d.ts",
37
- "import": "./dist/TabGroup/index.js",
38
- "require": "./dist/TabGroup/index.cjs"
58
+ "import": "./dist/TabGroup/index.js"
59
+ },
60
+ "./icons": {
61
+ "types": "./dist/icons.d.ts",
62
+ "import": "./dist/icons.js"
39
63
  },
40
64
  "./motion": {
41
65
  "types": "./dist/motion.d.ts",
42
- "import": "./dist/motion.js",
43
- "require": "./dist/motion.cjs"
66
+ "import": "./dist/motion.js"
44
67
  }
45
68
  },
46
69
  "publishConfig": {
@@ -49,30 +72,32 @@
49
72
  "keywords": [],
50
73
  "author": "",
51
74
  "license": "ISC",
75
+ "dependencies": {
76
+ "@torpor/view": "^0.3.2",
77
+ "@torpor/unplugin": "^0.2.0"
78
+ },
52
79
  "devDependencies": {
53
80
  "@testing-library/dom": "^10.4.1",
54
- "@testing-library/jest-dom": "^6.6.4",
81
+ "@testing-library/jest-dom": "^6.9.1",
55
82
  "@testing-library/user-event": "^14.6.1",
56
83
  "@trivago/prettier-plugin-sort-imports": "^5.2.2",
57
- "@types/jsdom": "^21.1.7",
58
- "@types/node": "^24.2.1",
59
- "chalk": "^5.5.0",
84
+ "@types/jsdom": "^27.0.0",
85
+ "@types/node": "^24.6.2",
86
+ "@typescript/native-preview": "7.0.0-dev.20251005.1",
87
+ "chalk": "^5.6.2",
60
88
  "esno": "^4.8.0",
61
89
  "fast-glob": "^3.3.3",
62
- "jsdom": "^26.1.0",
90
+ "jsdom": "^27.0.0",
91
+ "oxlint-tsgolint": "^0.2.0",
63
92
  "tsup": "^8.5.0",
64
- "typescript": "^5.9.2",
65
- "vitest": "^3.2.4"
66
- },
67
- "dependencies": {
68
- "@torpor/unplugin": "^0.1.17",
69
- "@torpor/view": "^0.2.0"
93
+ "typescript": "^5.9.3",
94
+ "vitest": "^3.2.4",
95
+ "zod": "^4.1.12"
70
96
  },
71
97
  "scripts": {
72
- "build": "tsc --noEmit && tsup",
98
+ "build": "tsgo --noEmit && tsup",
73
99
  "build:fix": "esno scripts/postbuild.ts",
74
- "check": "tsc --noEmit",
75
- "test": "vitest run",
76
- "test:watch": "vitest"
100
+ "check": "tsgo --noEmit && pnpm dlx oxlint --type-aware",
101
+ "test": "vitest"
77
102
  }
78
103
  }
@@ -1,3 +1,4 @@
1
+ import { buildType, parse } from "@torpor/view/compile";
1
2
  import chalk from "chalk";
2
3
  import { existsSync, promises as fs, lstatSync } from "node:fs";
3
4
  import { basename, dirname, join, resolve } from "node:path";
@@ -11,6 +12,11 @@ async function run() {
11
12
  const sourceFolder = resolve(scriptsFolder, "../src");
12
13
  const distFolder = resolve(scriptsFolder, "../dist");
13
14
 
15
+ // Wait for the types to be generated, then wait another 500ms, because
16
+ // otherwise the types WE generate get deleted
17
+ await waitUntilFileExists(join(distFolder, "index.d.ts"));
18
+ await new Promise((resolve, _reject) => setTimeout(() => resolve(true), 500));
19
+
14
20
  // Read the dist files first, not for every component
15
21
  const distFiles = (await fs.readdir(distFolder)).filter((f) => f.endsWith(".torp"));
16
22
 
@@ -32,6 +38,8 @@ async function run() {
32
38
  }
33
39
 
34
40
  // Move all *.torp files for the component into this folder
41
+ // And while we're at it, create type definitions
42
+ let typeDefs: string[] = [];
35
43
  let relatedFiles = (await fs.readdir(join(sourceFolder, component)))
36
44
  .filter((f) => f.endsWith(".torp") && f !== component)
37
45
  .map((f) => basename(f, ".torp"))
@@ -43,8 +51,13 @@ async function run() {
43
51
  return output!;
44
52
  });
45
53
  for (let file of relatedFiles) {
46
- const newfile = file.substring(0, file.indexOf("-")) + ".torp";
47
- await fs.rename(join(distFolder, file), join(distFolder, component, newfile));
54
+ const newFileName = file.substring(0, file.indexOf("-")) + ".torp";
55
+ const newFilePath = join(distFolder, component, newFileName);
56
+ await fs.rename(join(distFolder, file), newFilePath);
57
+
58
+ const parsed = parse(await fs.readFile(newFilePath, "utf8"));
59
+ // HACK: by this point we should be certain there's no errors
60
+ typeDefs.push(buildType(parsed.template!));
48
61
  }
49
62
 
50
63
  // Move all *.ts files into this folder
@@ -55,11 +68,26 @@ async function run() {
55
68
  for (const file of tsFiles) {
56
69
  await fs.copyFile(join(srcFolder, file), join(distFolder, component, file));
57
70
  }
71
+
72
+ // Create the d.ts file from the type definitions
73
+ let dts = `import { type SlotRender } from "@torpor/view";\n`;
74
+ let exportNames: string[] = [];
75
+ for (let typeDef of typeDefs) {
76
+ const match = /export default (.+?);/.exec(typeDef);
77
+ if (match) {
78
+ exportNames.push(match[1]);
79
+ typeDef = typeDef.replace(match[0], "");
80
+ }
81
+ typeDef = typeDef.replace(`import { type SlotRender } from "@torpor/view";`, "");
82
+ dts += typeDef;
83
+ }
84
+ dts += `export { ${exportNames.join(", ")} };`;
85
+ await fs.writeFile(join(distFolder, component, "index.d.ts"), dts);
58
86
  }
59
87
 
60
88
  // Move all utils/*.ts files into the dest folder
61
- moveUtils(distFolder, "utils");
62
- moveUtils(distFolder, "mount");
89
+ await moveUtils(distFolder, "utils");
90
+ await moveUtils(distFolder, "mount");
63
91
  }
64
92
 
65
93
  async function moveUtils(distFolder: string, folderName: string) {
@@ -77,4 +105,13 @@ async function moveUtils(distFolder: string, folderName: string) {
77
105
  }
78
106
  }
79
107
 
80
- run();
108
+ // From https://stackoverflow.com/a/62339353
109
+ async function waitUntilFileExists(filePath: string, currentTime = 0, timeout = 5000) {
110
+ if (existsSync(filePath)) return true;
111
+ if (currentTime === timeout) return false;
112
+ const interval = 500;
113
+ await new Promise((resolve, _reject) => setTimeout(() => resolve(true), interval));
114
+ return waitUntilFileExists(filePath, currentTime + interval, timeout);
115
+ }
116
+
117
+ await run();
@@ -1,5 +1,20 @@
1
1
  import { AccordionContextName, type AccordionContext, type ItemState } from "./AccordionTypes";
2
2
 
3
+ interface AccordionProps {
4
+ /** An ID for the root element */
5
+ id?: string;
6
+ /** Class name(s) for the root element */
7
+ class?: string,
8
+ /** Whether a single AccordionItem or multiple AccordionItems can be expanded at the same time */
9
+ type?: "single" | "multiple",
10
+ /** The value of the expanded AccordionItem, or an array of values if the type is "multiple" */
11
+ value?: string | string[],
12
+ /** If set to true, the user cannot interact with any items in the Accordion */
13
+ disabled?: boolean,
14
+ /** Raised when the expanded item(s) have changed */
15
+ onchange?: (value: string | string[]) => void,
16
+ }
17
+
3
18
  /**
4
19
  * A vertically stacked set of interactive headings that enable users to reveal
5
20
  * or hide associated sections of content.
@@ -18,13 +33,10 @@ import { AccordionContextName, type AccordionContext, type ItemState } from "./A
18
33
  * </AccordionItem>
19
34
  * </Accordion>
20
35
  * ```
21
- *
22
- * @prop {"single" | "multiple"} type -- Whether a single AccordionItem or multiple AccordionItems can be expanded at the same time
23
- * @prop {string | string[]} value -- The value of the expanded AccordionItem, or an array of values if the type is "multiple"
24
- * @prop {boolean} disabled -- If set to true, the user cannot interact with any items in the Accordion
25
- * @prop {(value: string | string[]) => void} [onchange] -- Raised when the expanded item(s) have changed
26
36
  */
27
- export default function Accordion($props: any) {
37
+ export default function Accordion($props: AccordionProps) {
38
+ $props ??= $watch({ type: "single", value: "" });
39
+
28
40
  $props.type ||= "single";
29
41
  $props.value ||= $props.type === "single" ? "" : [];
30
42
 
@@ -44,10 +56,10 @@ export default function Accordion($props: any) {
44
56
 
45
57
  $run(() => {
46
58
  // HACK: This should probably be done with setters?
47
- let newValue = $props.value;
59
+ let newValue = $props.value!;
48
60
 
49
61
  // Get the value
50
- switch ($props.type) {
62
+ switch ($props!.type) {
51
63
  case "single": {
52
64
  // Ensure the value passed in was a string (in case e.g. the user has set values to ints)
53
65
  newValue = newValue?.toString();
@@ -73,7 +85,7 @@ export default function Accordion($props: any) {
73
85
  })
74
86
 
75
87
  $run(() => {
76
- itemStates.forEach((s) => s.parentDisabled = $props.disabled);
88
+ itemStates.forEach((s) => s.parentDisabled = $props.disabled === true);
77
89
  });
78
90
 
79
91
  // Dispatch the change event when the value changes
@@ -84,7 +96,7 @@ export default function Accordion($props: any) {
84
96
  if (firstChange) {
85
97
  firstChange = false;
86
98
  } else if (ev) {
87
- ev(value);
99
+ ev(value!);
88
100
  }
89
101
  });
90
102
 
@@ -114,7 +126,7 @@ export default function Accordion($props: any) {
114
126
  }
115
127
 
116
128
  // Set whether the Accordion itself is disabled
117
- itemState.parentDisabled = $props.disabled
129
+ itemState.parentDisabled = $props.disabled === true
118
130
 
119
131
  // Add the item's state to the array
120
132
  itemStates.splice(itemState.index, 0, itemState);
@@ -198,10 +210,10 @@ export default function Accordion($props: any) {
198
210
 
199
211
  @render {
200
212
  <div
201
- id={$props.id}
213
+ {$props.id}
202
214
  class={`torp-accordion ${$props.class ?? ""}`.trim()}
203
215
  >
204
- <:slot />
216
+ <slot />
205
217
  </div>
206
218
  }
207
219
  }
@@ -1,35 +1,42 @@
1
1
  import getId from "../utils/getId";
2
2
  import { AccordionItemContextName, type AccordionItemContext } from "./AccordionTypes";
3
3
 
4
+ interface AccordionContentProps {
5
+ /** An ID for the root element */
6
+ id?: string;
7
+ /** Class name(s) for the root element */
8
+ class?: string,
9
+ /** Whether this content should act as a region. Set this when the content contains heading elements or a nested Accordion */
10
+ ariaRegion?: boolean,
11
+ }
12
+
4
13
  /**
5
14
  * Content for an AccordionItem, which can be revealed or hidden by an associated AccordionTrigger.
6
- *
7
- * @prop {string} [id] -- An ID for the AccordionContent's div container
8
- * @prop {boolean} [ariaRegion] -- Whether this content should act as a region. Set this when the content contains heading elements or a nested Accordion
9
15
  */
10
- export default function AccordionContent($props: any) {
16
+ export default function AccordionContent($props: AccordionContentProps) {
17
+ $props ??= $watch({});
11
18
  $props.id ||= getId();
12
19
 
13
20
  const context = $context[AccordionItemContextName] as AccordionItemContext;
14
21
  if (!context) {
15
22
  throw new Error("AccordionContent must be contained within an AccordionItem");
16
23
  }
17
- let $state = $context[AccordionItemContextName].state
24
+ let $state = context.state
18
25
 
19
26
  // Set the content ID so that it can be used with aria-controls in AccordionTrigger
20
27
  $state.contentId = $props.id;
21
28
 
22
29
  @render {
23
30
  <div
24
- id={$props.id}
31
+ {$props.id}
25
32
  class={`torp-accordion-content ${$props.class ?? ""}`.trim()}
26
33
  role={$props.ariaRegion ? "region" : undefined}
27
34
  aria-labelledby={$state.headerId}
28
35
  data-state={$state.dataState}
29
- data-disabled={$state.dataDisabled}
36
+ data-disabled={$state.disabled ? "true" : undefined}
30
37
  >
31
38
  @if ($state.expanded) {
32
- <:slot />
39
+ <slot />
33
40
  }
34
41
  </div>
35
42
  }
@@ -1,5 +1,14 @@
1
1
  import { AccordionItemContextName, type AccordionItemContext } from "./AccordionTypes";
2
2
 
3
+ interface AccordionHeaderProps {
4
+ /** An ID for the root element */
5
+ id?: string;
6
+ /** Class name(s) for the root element */
7
+ class?: string,
8
+ /** The type of HTML header to use */
9
+ as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6",
10
+ }
11
+
3
12
  /**
4
13
  * The header for an AccordionItem, which contains the AccordionTrigger.
5
14
  *
@@ -10,25 +19,25 @@ import { AccordionItemContextName, type AccordionItemContext } from "./Accordion
10
19
  * <AccordionTrigger />
11
20
  * </AccordionHeader>
12
21
  * ```
13
- *
14
- * @prop {"h1" | "h2" | "h3" | "h4" | "h5" | "h6"} as -- The type of HTML header to use
15
22
  */
16
- export default function AccordionHeader($props: any) {
23
+ export default function AccordionHeader($props: AccordionHeaderProps) {
24
+ $props ??= $watch({});
25
+
17
26
  const context = $context[AccordionItemContextName] as AccordionItemContext;
18
27
  if (!context) {
19
28
  throw new Error("AccordionHeader must be contained within an AccordionItem");
20
29
  }
21
- let $state = $context[AccordionItemContextName].state
30
+ let $state = context.state
22
31
 
23
32
  @render {
24
33
  @// TODO: $props.as
25
34
  <h4
26
- id={$props.id}
35
+ {$props.id}
27
36
  class={`torp-accordion-header ${$props.class ?? ""}`.trim()}
28
37
  data-state={$state.dataState}
29
- data-disabled={$state.dataDisabled}
38
+ data-disabled={$state.disabled ? "true" : undefined}
30
39
  >
31
- <:slot />
40
+ <slot />
32
41
  </h4>
33
42
  }
34
43
  }