@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
@@ -1,4 +1,19 @@
1
- import { AccordionContextName, AccordionItemContextName, type AccordionContext, type AccordionItemContext } from "./AccordionTypes";
1
+ import { AccordionContextName, AccordionItemContextName, type ItemState, type AccordionContext, type AccordionItemContext } from "./AccordionTypes";
2
+
3
+ interface AccordionItemProps {
4
+ /** An ID for the root element */
5
+ id?: string;
6
+ /** Class name(s) for the root element */
7
+ class?: string,
8
+ /** The index of this item in the Accordion. Set this if you will be inserting, removing or sorting items. If you don't set this, it will be set automatically */
9
+ index?: number,
10
+ /** A value for the item. Set this if you need more control over which item(s) are expanded. If you don't set this, the value will be set to the item's initial index */
11
+ value?: string,
12
+ /** If set to true, the user cannot interact with this AccordionItem */
13
+ disabled?: boolean,
14
+ /** Raised when this item is opened or closed */
15
+ ontoggle?: (open: boolean) => void,
16
+ }
2
17
 
3
18
  /**
4
19
  * An item in an Accordion, which must consist of an AccordionTrigger and an AccordionContent.
@@ -13,17 +28,16 @@ import { AccordionContextName, AccordionItemContextName, type AccordionContext,
13
28
  * <AccordionContent />
14
29
  * </AccordionItem>
15
30
  * ```
16
- *
17
- * @prop {number} [index] -- The index of this item in the Accordion. Set this if you will be inserting, removing or sorting items. If you don't set this, it will be set automatically
18
- * @prop {string} [value] -- A value for the item. Set this if you need more control over which item(s) are expanded. If you don't set this, the value will be set to the item's initial index
19
- * @prop {boolean} [disabled] -- If set to true, the user cannot interact with this AccordionItem
20
- * @prop {(boolean) => void} [ontoggle] -- Raised when this item is opened or closed
21
31
  */
22
- export default function AccordionItem($props: any) {
32
+ export default function AccordionItem($props: AccordionItemProps) {
33
+ $props ??= $watch({});
34
+
23
35
  let $state: ItemState = $watch({
24
36
  index: -1,
25
37
  value: "",
26
38
  expanded: false,
39
+ headerId: "",
40
+ contentId: "",
27
41
  disabled: $props.disabled,
28
42
  parentDisabled: false,
29
43
  get dataState() {
@@ -69,12 +83,12 @@ export default function AccordionItem($props: any) {
69
83
 
70
84
  @render {
71
85
  <div
72
- id={$props.id}
86
+ {$props.id}
73
87
  class={`torp-accordion-item ${$props.class ?? ""}`.trim()}
74
88
  data-state={$state.dataState}
75
- data-disabled={$state.dataDisabled}
89
+ data-disabled={$state.disabled ? "true" : undefined}
76
90
  >
77
- <:slot />
91
+ <slot />
78
92
  </div>
79
93
  }
80
94
  }
@@ -1,20 +1,28 @@
1
1
  import getId from "../utils/getId";
2
2
  import { AccordionItemContextName, type AccordionItemContext } from "./AccordionTypes";
3
3
 
4
+ interface AccordionTriggerProps {
5
+ /** An ID for the root element */
6
+ id?: string;
7
+ /** Class name(s) for the root element */
8
+ class?: string,
9
+ }
10
+
4
11
  /**
5
12
  * A header button for an AccordionItem, which can be used to reveal or hide an associated AccordionContent.
6
13
  */
7
- export default function AccordionTrigger() {
8
- let button: HTMLButtonElement;
9
-
14
+ export default function AccordionTrigger($props: AccordionTriggerProps) {
15
+ $props ??= $watch({});
10
16
  $props.id ||= getId();
11
17
 
18
+ let button: HTMLButtonElement;
19
+
12
20
  // Get stuff out of the AccordionItemContext
13
21
  const context = $context[AccordionItemContextName] as AccordionItemContext;
14
22
  if (!context) {
15
23
  throw new Error("AccordionTrigger must be contained within an AccordionItem");
16
24
  }
17
- let $state = $context[AccordionItemContextName].state;
25
+ let $state = context.state;
18
26
 
19
27
  // Set the header ID so that it can be used with aria-labelledby in AccordionContent
20
28
  $state.headerId = $props.id;
@@ -41,19 +49,19 @@ export default function AccordionTrigger() {
41
49
  @render {
42
50
  <button
43
51
  type="button"
44
- id={$props.id}
52
+ {$props.id}
45
53
  class={`torp-accordion-trigger ${$props.class ?? ""}`.trim()}
46
54
  disabled={$state.disabled || $state.parentDisabled}
47
55
  aria-expanded={$state.expanded.toString()}
48
- aria-disabled={$state.disabled}
56
+ aria-disabled={$state.disabled ? "true" : undefined}
49
57
  aria-controls={$state.contentId}
50
58
  data-state={$state.dataState}
51
- data-disabled={$state.disabled}
59
+ data-disabled={$state.disabled ? "true" : undefined}
52
60
  &ref={button}
53
61
  onclick={handleClick}
54
62
  onkeydown={handleKey}
55
63
  >
56
- <:slot />
64
+ <slot />
57
65
  </button>
58
66
  }
59
67
  }
@@ -25,6 +25,8 @@ export interface ItemState {
25
25
  index: number;
26
26
  value: string;
27
27
  expanded: boolean;
28
+ headerId: string;
29
+ contentId: string;
28
30
  disabled: boolean;
29
31
  parentDisabled: boolean;
30
32
  dataState: "open" | "closed";
@@ -0,0 +1,42 @@
1
+
2
+ interface BreadcrumbProps {
3
+ /** An ID for the root element */
4
+ id?: string;
5
+ /** Class name(s) for the root element */
6
+ class?: string,
7
+ /** An ARIA label for describing the popover to screen readers */
8
+ ariaLabel?: string | undefined,
9
+ }
10
+
11
+ /**
12
+ *
13
+ * A list of links to the parent pages of the current page in hierarchical order.
14
+ *
15
+ * See [the WAI ARIA guidelines for Breadcrumbs](https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/).
16
+ *
17
+ * The structure of a Breadcrumb is:
18
+ *
19
+ * ```
20
+ * <Breadcrumb>
21
+ * <BreadcrumbItem />
22
+ * <BreadcrumbSeparator /> (optional)
23
+ * <BreadcrumbItem />
24
+ * ...
25
+ * </Breadcrumb>
26
+ * ```
27
+ *
28
+ * You can separate BreadcrumbItems using BreadcrumbSeparators or by using CSS.
29
+ */
30
+ export default function Breadcrumb($props: BreadcrumbProps) {
31
+ $props ??= $watch({});
32
+
33
+ @render {
34
+ <nav
35
+ {$props.id}
36
+ class={`torp-breadcrumb ${$props.class ?? ""}`.trim()}
37
+ aria-label={$props.ariaLabel}
38
+ >
39
+ <slot />
40
+ </nav>
41
+ }
42
+ }
@@ -0,0 +1,28 @@
1
+
2
+ interface BreadcrumbItemProps {
3
+ /** An ID for the root element */
4
+ id?: string;
5
+ /** Class name(s) for the root element */
6
+ class?: string,
7
+ /** Whether this is the current page */
8
+ current?: boolean,
9
+ }
10
+
11
+ /**
12
+ * An item in a breadcrumb, containing a link to one of the parent pages of the
13
+ * current page (or the current page).
14
+ */
15
+ export default function BreadcrumbItem($props: BreadcrumbItemProps) {
16
+ $props ??= $watch({});
17
+
18
+ @render {
19
+ <div
20
+ {$props.id}
21
+ class={`torp-breadcrumb ${$props.class ?? ""}`.trim()}
22
+ aria-current={$props.current ? "page" : undefined}
23
+ data-current={$props.current ? "current" : undefined}
24
+ >
25
+ <slot />
26
+ </div>
27
+ }
28
+ }
@@ -0,0 +1,25 @@
1
+
2
+ interface BreadcrumbSeparatorProps {
3
+ /** An ID for the root element */
4
+ id?: string;
5
+ /** Class name(s) for the root element */
6
+ class?: string,
7
+ }
8
+
9
+ /**
10
+ * A separator between links in a Breadcrumb component. It is hidden from
11
+ * screen readers.
12
+ */
13
+ export default function BreadcrumbSeparator($props: BreadcrumbSeparatorProps) {
14
+ $props ??= $watch({});
15
+
16
+ @render {
17
+ <div
18
+ {$props.id}
19
+ class={`torp-breadcrumb-separator ${$props.class ?? ""}`.trim()}
20
+ aria-hidden="true"
21
+ >
22
+ <slot />
23
+ </div>
24
+ }
25
+ }
@@ -0,0 +1,5 @@
1
+ import Breadcrumb from "./Breadcrumb.torp";
2
+ import BreadcrumbItem from "./BreadcrumbItem.torp";
3
+ import BreadcrumbSeparator from "./BreadcrumbSeparator.torp";
4
+
5
+ export { Breadcrumb, BreadcrumbItem, BreadcrumbSeparator };
@@ -0,0 +1,273 @@
1
+ import { ReactiveDate } from "@torpor/view";
2
+ import { areDatesEqual, dayNames, monthNames } from "../utils/dateUtils";
3
+ import CalendarDay from "./CalendarDay.torp";
4
+ import { type CalendarContext, type DayState, type CalendarEvent, CalendarContextName } from "./CalendarTypes";
5
+ import ChevronLeft from "../icons/ChevronLeft.torp";
6
+ import ChevronRight from "../icons/ChevronRight.torp";
7
+
8
+ // TODO: Split this out into Calendar, CalendarHeader, CalendarPreviousTrigger, CalendarGrid etc
9
+
10
+ interface CalendarProps {
11
+ /** An ID for the root element */
12
+ id?: string;
13
+ /** Class name(s) for the root element */
14
+ class?: string,
15
+ }
16
+
17
+ export default function Calendar($props: CalendarProps) {
18
+ $props ??= $watch({});
19
+ $props.startOfWeek ??= 1;
20
+ $props.selectable ??= false;
21
+ $props.value ??= new Date();
22
+ $props.events ??= [];
23
+
24
+ // Ensure the value is a reactive date
25
+ $props.value = new ReactiveDate($unwrap($props.value));
26
+
27
+ // A note on dates:
28
+ // * value is the selected value
29
+ // * activeDate is the date that is active when the user is navigating via keyboard
30
+ // * visibleDate is the date that is currently being displayed in the calendar (really only the month part is important here)
31
+
32
+ let $state = $watch({
33
+ activeDate: $props.value,
34
+ visibleDate: $props.value,
35
+ //get days() {
36
+ // // TODO: $cache
37
+ // return buildDays($state.visibleDate, $props.startOfWeek)
38
+ //},
39
+ });
40
+
41
+ let visibleStartDate = $props.value;
42
+ let visibleEndDate = $props.value;
43
+ let container: HTMLElement;
44
+ let refocus = false;
45
+
46
+ const context: CalendarContext = {
47
+ registerDay
48
+ };
49
+ $context[CalendarContextName] = context;
50
+
51
+ $run(() => {
52
+ $state.days = buildDays($state.visibleDate, $props.startOfWeek)
53
+
54
+ // HACK: Shouldn't need this
55
+ if (refocus) {
56
+ refocus = false;
57
+ const el = container.getElementsByClassName("active")[0];
58
+ if (el && el.children[0] instanceof HTMLElement) {
59
+ el.children[0].focus();
60
+ }
61
+ }
62
+ });
63
+
64
+ function registerDay(date: ReactiveDate, setActive: (value: boolean) => void) {
65
+ const day = $state.days.find((day) => areDatesEqual(day.date, date));
66
+ if (day) {
67
+ day.setActive = setActive;
68
+ }
69
+ }
70
+
71
+ function buildDays(date: ReactiveDate, start: number): DayState[] {
72
+ const newDays = [];
73
+
74
+ // Set the first day to the start of the week before the first day of
75
+ // the month (e.g. Monday the 28th of the previous month)
76
+ visibleStartDate = new Date();
77
+ visibleStartDate.setFullYear(date.getFullYear(), date.getMonth(), 1);
78
+ visibleStartDate.setDate(
79
+ visibleStartDate.getDate() - ((visibleStartDate.getDay() + 7 - start) % 7)
80
+ );
81
+
82
+ // Set the last day to the end of the week after the last day of the
83
+ // month (e.g. Sunday the 6th of the next month)
84
+ visibleEndDate = new Date();
85
+ visibleEndDate.setFullYear(date.getFullYear(), date.getMonth() + 1, 0);
86
+ visibleEndDate.setDate(
87
+ visibleEndDate.getDate() + ((start - 1 - visibleEndDate.getDay() + 7) % 7)
88
+ );
89
+
90
+ const dayDiff =
91
+ Math.round((visibleEndDate.getTime() - visibleStartDate.getTime()) / (1000 * 60 * 60 * 24)) +
92
+ 1;
93
+
94
+ for (let i = 0; i < dayDiff; i++) {
95
+ const dayDate = new ReactiveDate();
96
+ dayDate.setFullYear(
97
+ visibleStartDate.getFullYear(),
98
+ visibleStartDate.getMonth(),
99
+ visibleStartDate.getDate() + i
100
+ );
101
+ dayDate.setHours(0);
102
+ dayDate.setMinutes(0);
103
+ dayDate.setSeconds(0);
104
+ dayDate.setMilliseconds(0);
105
+ const newDay: DayState = {
106
+ date: dayDate,
107
+ muted: dayDate.getMonth() !== date.getMonth(),
108
+ active: areDatesEqual(dayDate, $state.activeDate)
109
+ };
110
+ newDays.push(newDay);
111
+ }
112
+
113
+ return newDays;
114
+ }
115
+
116
+ function setValue(date: Date) {
117
+ $state.value = new ReactiveDate(date);
118
+
119
+ // Also set the active date so that the user knows where they are
120
+ setActiveDate(date);
121
+
122
+ if ($props.onchange) $props.onchange(value);
123
+ }
124
+
125
+ function setActiveDate(date: Date) {
126
+ $state.activeDate = new ReactiveDate(date);
127
+
128
+ // If the selected date is outside the visible date range, move the date range
129
+ if (date < visibleStartDate || date > visibleEndDate) {
130
+ refocus = true;
131
+ $state.visibleDate = new ReactiveDate(date);
132
+ if ($props.onchangedate) $props.onchangedate(date);
133
+ }
134
+
135
+ $state.days.forEach((day) => {
136
+ const active = areDatesEqual(day.date, new Date(date));
137
+ if (day.setActive) {
138
+ day.setActive(active);
139
+ }
140
+ day.active = active;
141
+ });
142
+ }
143
+
144
+ function handleFocus(e: FocusEvent & { currentTarget: EventTarget & HTMLElement }) {
145
+ const el = e.currentTarget.getElementsByClassName("active")[0];
146
+ if (el && el.children[0] instanceof HTMLElement) {
147
+ el.children[0].focus();
148
+ e.preventDefault();
149
+ }
150
+ }
151
+
152
+ function handlePrevMonth(e: Event) {
153
+ e.preventDefault();
154
+ $state.visibleDate.setMonth($state.visibleDate.getMonth() - 1);
155
+ if ($props.onchangedate) $props.onchangedate(visibleDate);
156
+ }
157
+
158
+ function handleNextMonth(e: Event) {
159
+ e.preventDefault();
160
+ $state.visibleDate.setMonth($state.visibleDate.getMonth() + 1);
161
+ if ($props.onchangedate) $props.onchangedate(visibleDate);
162
+ }
163
+
164
+ async function handleDayClick(date: ReactiveDate) {
165
+ if (!$props.selectable) return;
166
+
167
+ setValue(date);
168
+ }
169
+
170
+ function handleKey(e: KeyboardEvent) {
171
+ if (!$props.selectable) return;
172
+
173
+ switch (e.key) {
174
+ case "Enter": {
175
+ e.preventDefault();
176
+ setValue($state.activeDate);
177
+ break;
178
+ }
179
+ case "Esc":
180
+ case "Escape": {
181
+ e.preventDefault();
182
+ if ($props.onclose) $props.onclose();
183
+ break;
184
+ }
185
+ case "Left":
186
+ case "ArrowLeft": {
187
+ e.preventDefault();
188
+ // Move to the date one day before
189
+ const newDate = new Date($state.activeDate.getTime() - 1 * 86400000)
190
+ setActiveDate(newDate);
191
+ break;
192
+ }
193
+ case "Up":
194
+ case "ArrowUp": {
195
+ e.preventDefault();
196
+ // Move to the date seven days before
197
+ const newDate = new Date($state.activeDate.getTime() - 7 * 86400000)
198
+ setActiveDate(newDate);
199
+ break;
200
+ }
201
+ case "Right":
202
+ case "ArrowRight": {
203
+ e.preventDefault();
204
+ // Move to the date one day after
205
+ const newDate = new Date($state.activeDate.getTime() + 1 * 86400000)
206
+ setActiveDate(newDate);
207
+ break;
208
+ }
209
+ case "Down":
210
+ case "ArrowDown": {
211
+ e.preventDefault();
212
+ // Move to the date seven days after
213
+ const newDate = new Date($state.activeDate.getTime() + 7 * 86400000)
214
+ setActiveDate(newDate);
215
+ break;
216
+ }
217
+ }
218
+ }
219
+
220
+ @render {
221
+ <div
222
+ {$props.id}
223
+ class={`torp-calendar ${$props.class ?? ""}`.trim()}
224
+ &ref={container}
225
+ >
226
+ <div class={`torp-calendar-header ${$props.class ?? ""}`.trim()}>
227
+ <button class={`torp-calendar-previous-trigger ${$props.class ?? ""}`.trim()} onclick={handlePrevMonth}>
228
+ <slot name="prev-button">
229
+ <ChevronLeft />
230
+ </slot>
231
+ </button>
232
+ <span class={`torp-calendar-month-name ${$props.class ?? ""}`.trim()}>
233
+ {monthNames[$state.visibleDate.getMonth()] + " " + $state.visibleDate.getFullYear()}
234
+ </span>
235
+ <button class={`torp-calendar-next-trigger ${$props.class ?? ""}`.trim()} onclick={handleNextMonth}>
236
+ <slot name="next-button">
237
+ <ChevronRight />
238
+ </slot>
239
+ </button>
240
+ </div>
241
+ <div
242
+ class={`torp-calendar-grid ${$props.class ?? ""}`.trim()}
243
+ tabindex={$props.selectable ? 0 : -1}
244
+ onfocus={handleFocus}
245
+ onkeydown={handleKey}
246
+ >
247
+ @for (let index of [0, 1, 2, 3, 4, 5, 6]) {
248
+ <span>
249
+ {dayNames[(Math.abs($props.startOfWeek) + index) % 7].substring(0, 2)}
250
+ </span>
251
+ }
252
+ @for (let day of $state.days) {
253
+ @key = day.date;
254
+ <CalendarDay
255
+ {day.date}
256
+ {day.muted}
257
+ {day.active}
258
+ {$props.selectable}
259
+ events={$props.events.filter((ev) => areDatesEqual(new Date(ev.date), day.date))}
260
+ onclick={handleDayClick}
261
+ />
262
+ }
263
+ </div>
264
+ </div>
265
+ }
266
+
267
+ @style {
268
+ .torp-calendar-grid {
269
+ display: grid;
270
+ grid-template-columns: repeat(7, 1fr);
271
+ }
272
+ }
273
+ }
@@ -0,0 +1,75 @@
1
+ import { areDatesEqual } from "../utils/dateUtils";
2
+ import { type CalendarContext, type CalendarEvent, CalendarContextName } from "./CalendarTypes";
3
+
4
+ interface CalendarDayProps {
5
+ /** An ID for the root element */
6
+ id?: string;
7
+ /** Class name(s) for the root element */
8
+ class?: string,
9
+ }
10
+
11
+ export default function CalendarDay($props: CalendarDayProps) {
12
+ $props ??= $watch({});
13
+ $props.date ??= new Date();
14
+ $props.selectable ??= false;
15
+ $props.muted ??= false;
16
+ $props.active ??= false;
17
+ $props.events ??= [];
18
+
19
+ // HACK: can't unwrap in @render
20
+ let date = $unwrap($props.date);
21
+
22
+ // Register this item with the parent Calendar, which will handle toggling active for all days
23
+ const { registerDay } = $context[CalendarContextName] as CalendarContext;
24
+ registerDay($props.date, setActive);
25
+
26
+ // This function is called by the parent Calendar to set this item's active value
27
+ function setActive(value: boolean) {
28
+ //if (active !== value) {
29
+ // active = value;
30
+ // dispatch("activeChange", value);
31
+ //}
32
+ }
33
+
34
+ function isToday() {
35
+ const today = new Date();
36
+ return areDatesEqual(date, today);
37
+ }
38
+
39
+ async function handleClick() {
40
+ //dispatch("click", date);
41
+ if ($props.onclick) $props.onclick($props.date);
42
+ }
43
+
44
+ async function handleKey() {
45
+ //dispatch("click", date);
46
+ if ($props.onkeydown) $props.onkeydown();
47
+ }
48
+
49
+ @render {
50
+ <div
51
+ {$props.id}
52
+ class={[
53
+ `torp-calendar-day ${$props.class ?? ""}`.trim(),
54
+ {
55
+ muted: $props.muted,
56
+ today: isToday(),
57
+ active: $props.selectable && $props.active
58
+ }
59
+ ]}
60
+ >
61
+ @if ($props.selectable) {
62
+ <button type="button" tabindex="-1" onclick={handleClick} onkeydown={handleKey}>
63
+ <span>{date.getDate()}</span>
64
+ </button>
65
+ } else {
66
+ <span>{date.getDate()}</span>
67
+ }
68
+ <ul class={`torp-calendar-day-events ${$props.class ?? ""}`.trim()}>
69
+ @for (ev of $props.events) {
70
+ <li title={ev.content} />
71
+ }
72
+ </ul>
73
+ </div>
74
+ }
75
+ }
@@ -0,0 +1,22 @@
1
+ export const CalendarContextName = "Calendar";
2
+
3
+ export interface CalendarContext {
4
+ // The registerDay function is called from each CalendarDay to register itself with this
5
+ // Calendar. They pass us a setActive method that we can call
6
+ registerDay: (date: Date, setActive: (value: boolean) => void) => void;
7
+ }
8
+
9
+ export interface DayState {
10
+ date: Date;
11
+ muted: boolean;
12
+ state: {
13
+ active: boolean;
14
+ };
15
+ setActive?: (value: boolean) => void;
16
+ }
17
+
18
+ export interface CalendarEvent {
19
+ date: Date;
20
+ content: string;
21
+ color: string;
22
+ }
@@ -0,0 +1,4 @@
1
+ import Calendar from "./Calendar.torp";
2
+ import CalendarDay from "./CalendarDay.torp";
3
+
4
+ export { Calendar, CalendarDay };
@@ -4,6 +4,17 @@ import { trapFocus, type TrapFocusOptions } from "../mount/trapFocus";
4
4
  import { PopoverContextName, type PopoverContext } from "../Popover/PopoverTypes";
5
5
  import { DialogContextName, type DialogContext, type DialogState } from "./DialogTypes";
6
6
 
7
+ interface DialogProps {
8
+ /** An ID for the root element */
9
+ id?: string;
10
+ /** Class name(s) for the root element */
11
+ class?: string,
12
+ /** An ARIA label for describing the popover to screen readers */
13
+ ariaLabel?: string,
14
+ /** Whether the dialog should alert the user via the screen reader */
15
+ alert?: boolean,
16
+ }
17
+
7
18
  /**
8
19
  * Content for a window displayed in a Popover.
9
20
  *
@@ -21,10 +32,9 @@ import { DialogContextName, type DialogContext, type DialogState } from "./Dialo
21
32
  * </Dialog>
22
33
  * ```
23
34
  *
24
- * @prop {string | undefined} ariaLabel -- An ARIA label for describing the popover to screen readers
25
- * @prop {boolean} alert -- Whether the dialog should alert the user via the screen reader
26
35
  */
27
- export default function Dialog($props: any) {
36
+ export default function Dialog($props: DialogProps) {
37
+ $props ??= $watch({});
28
38
  $props.id ??= getId();
29
39
  $props.dialog ??= false;
30
40
 
@@ -138,7 +148,7 @@ export default function Dialog($props: any) {
138
148
 
139
149
  @render {
140
150
  <div
141
- id={$props.id}
151
+ {$props.id}
142
152
  class={`torp-dialog ${$props.class ?? ""}`.trim()}
143
153
  tabindex="0"
144
154
  role={$props.alert ? "alertdialog" : "dialog"}
@@ -147,10 +157,10 @@ export default function Dialog($props: any) {
147
157
  aria-labelledby={!$props.ariaLabel && $state.headerId ? $state.headerId : undefined}
148
158
  aria-describedby={$state.bodyId ? $state.bodyId : undefined}
149
159
  onkeydown={handleKey}
150
- :onmount={(el) => trapFocus(el, trapFocusOptions)}
160
+ onmount={(el) => trapFocus(el, trapFocusOptions)}
151
161
  &ref={div}
152
162
  >
153
- <:slot />
163
+ <slot />
154
164
  </div>
155
165
  }
156
166
  }