@torpor/ui 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/Accordion/Accordion.torp +44 -25
  3. package/dist/Accordion/AccordionContent.torp +18 -12
  4. package/dist/Accordion/AccordionHeader.torp +15 -8
  5. package/dist/Accordion/AccordionItem.torp +34 -17
  6. package/dist/Accordion/AccordionTrigger.torp +17 -10
  7. package/dist/Accordion/AccordionTypes.ts +6 -3
  8. package/dist/Accordion/index.d.ts +100 -35
  9. package/dist/Breadcrumb/Breadcrumb.torp +18 -10
  10. package/dist/Breadcrumb/BreadcrumbItem.torp +14 -7
  11. package/dist/Breadcrumb/BreadcrumbSeparator.torp +10 -3
  12. package/dist/Breadcrumb/index.d.ts +50 -21
  13. package/dist/Calendar/Calendar.torp +21 -14
  14. package/dist/Calendar/CalendarDay.torp +12 -4
  15. package/dist/Calendar/index.d.ts +16 -18
  16. package/dist/Contextual/Contextual.torp +125 -0
  17. package/dist/{Popover/PopoverContentContextual.torp → Contextual/ContextualContent.torp} +21 -12
  18. package/dist/Contextual/ContextualTrigger.torp +66 -0
  19. package/dist/Contextual/ContextualTypes.ts +30 -0
  20. package/dist/Contextual/index.d.ts +90 -0
  21. package/dist/Contextual/index.js +14 -0
  22. package/dist/Contextual/index.js.map +1 -0
  23. package/dist/Dialog/Dialog.torp +49 -73
  24. package/dist/Dialog/DialogBody.torp +15 -9
  25. package/dist/Dialog/DialogButton.torp +27 -13
  26. package/dist/Dialog/DialogFooter.torp +11 -3
  27. package/dist/Dialog/DialogHeader.torp +15 -8
  28. package/dist/Dialog/DialogTypes.ts +3 -2
  29. package/dist/Dialog/index.d.ts +83 -35
  30. package/dist/Disclosure/Disclosure.torp +34 -25
  31. package/dist/Disclosure/DisclosureContent.torp +18 -12
  32. package/dist/Disclosure/DisclosureHeader.torp +16 -9
  33. package/dist/Disclosure/DisclosureTrigger.torp +15 -8
  34. package/dist/Disclosure/DisclosureTypes.ts +0 -1
  35. package/dist/Disclosure/index.d.ts +67 -28
  36. package/dist/Drawer/Drawer.torp +109 -68
  37. package/dist/Drawer/DrawerContent.torp +80 -0
  38. package/dist/Drawer/DrawerOverlay.torp +38 -0
  39. package/dist/Drawer/DrawerTrigger.torp +35 -0
  40. package/dist/Drawer/DrawerTypes.ts +24 -0
  41. package/dist/Drawer/index.d.ts +96 -8
  42. package/dist/Drawer/index.js +13 -1
  43. package/dist/Form/Field.torp +91 -0
  44. package/dist/Form/Form.torp +129 -0
  45. package/dist/Form/FormTypes.ts +30 -0
  46. package/dist/Form/Input.torp +97 -0
  47. package/dist/Form/Label.torp +31 -0
  48. package/dist/Form/Message.torp +35 -0
  49. package/dist/Form/StandardSchemaV1.ts +70 -0
  50. package/dist/Form/index.d.ts +131 -0
  51. package/dist/Form/index.js +22 -0
  52. package/dist/Form/index.js.map +1 -0
  53. package/dist/Menu/Menu.torp +25 -15
  54. package/dist/Menu/MenuButton.torp +30 -13
  55. package/dist/Menu/MenuCheck.torp +29 -14
  56. package/dist/Menu/MenuGroup.torp +14 -6
  57. package/dist/Menu/MenuIndicator.torp +14 -7
  58. package/dist/Menu/MenuPopout.torp +23 -15
  59. package/dist/Menu/MenuPopoutContent.torp +17 -10
  60. package/dist/Menu/MenuPopoutTrigger.torp +23 -16
  61. package/dist/Menu/MenuRadio.torp +27 -16
  62. package/dist/Menu/MenuRadioGroup.torp +34 -15
  63. package/dist/Menu/MenuSeparator.torp +11 -3
  64. package/dist/Menu/MenuTypes.ts +7 -5
  65. package/dist/Menu/index.d.ts +176 -77
  66. package/dist/MenuBar/MenuBar.torp +24 -16
  67. package/dist/MenuBar/MenuBarItem.torp +24 -16
  68. package/dist/MenuBar/MenuBarItemContent.torp +18 -11
  69. package/dist/MenuBar/MenuBarItemTrigger.torp +15 -9
  70. package/dist/MenuBar/index.d.ts +79 -28
  71. package/dist/Modal/Modal.torp +118 -0
  72. package/dist/Modal/ModalContent.torp +77 -0
  73. package/dist/Modal/ModalOverlay.torp +38 -0
  74. package/dist/Modal/ModalTrigger.torp +50 -0
  75. package/dist/Modal/ModalTypes.ts +22 -0
  76. package/dist/Modal/index.d.ts +108 -0
  77. package/dist/Modal/index.js +33 -0
  78. package/dist/Modal/index.js.map +1 -0
  79. package/dist/Modal/showModal.ts +19 -0
  80. package/dist/Modal/showPrompt.ts +23 -0
  81. package/dist/NavMenu/NavMenu.torp +18 -10
  82. package/dist/NavMenu/NavMenuButton.torp +15 -10
  83. package/dist/NavMenu/NavMenuElement.torp +19 -11
  84. package/dist/NavMenu/NavMenuGroup.torp +13 -6
  85. package/dist/NavMenu/NavMenuGroupHeader.torp +15 -8
  86. package/dist/NavMenu/NavMenuLink.torp +21 -16
  87. package/dist/NavMenu/NavMenuPopout.torp +34 -18
  88. package/dist/NavMenu/NavMenuPopoutButton.torp +23 -18
  89. package/dist/NavMenu/NavMenuPopoutContent.torp +23 -13
  90. package/dist/NavMenu/NavMenuSeparator.torp +10 -3
  91. package/dist/NavMenu/index.d.ts +153 -70
  92. package/dist/Notification/Notification.torp +35 -16
  93. package/dist/Notification/NotificationClose.torp +10 -3
  94. package/dist/Notification/NotificationContainer.torp +11 -3
  95. package/dist/Notification/NotificationContent.torp +11 -3
  96. package/dist/Notification/index.d.ts +46 -28
  97. package/dist/Popover/Popover.torp +48 -28
  98. package/dist/Popover/PopoverContent.torp +42 -8
  99. package/dist/Popover/PopoverTrigger.torp +32 -3
  100. package/dist/Popover/PopoverTypes.ts +1 -1
  101. package/dist/Popover/index.d.ts +48 -111
  102. package/dist/Popover/index.js +1 -163
  103. package/dist/Popover/index.js.map +1 -1
  104. package/dist/TabGroup/TabContent.torp +20 -11
  105. package/dist/TabGroup/TabGroup.torp +58 -40
  106. package/dist/TabGroup/TabGroupTypes.ts +10 -5
  107. package/dist/TabGroup/TabHeader.torp +26 -10
  108. package/dist/TabGroup/TabList.torp +14 -7
  109. package/dist/TabGroup/TabTrigger.torp +17 -10
  110. package/dist/TabGroup/index.d.ts +101 -35
  111. package/dist/icons/ArrowDown.torp +5 -3
  112. package/dist/icons/ArrowLeft.torp +5 -3
  113. package/dist/icons/ArrowRight.torp +5 -3
  114. package/dist/icons/ArrowUp.torp +5 -3
  115. package/dist/icons/Bars.torp +5 -3
  116. package/dist/icons/Check.torp +5 -3
  117. package/dist/icons/ChevronDown.torp +5 -3
  118. package/dist/icons/ChevronLeft.torp +5 -3
  119. package/dist/icons/ChevronRight.torp +5 -3
  120. package/dist/icons/ChevronUp.torp +5 -3
  121. package/dist/icons/Cross.torp +5 -3
  122. package/dist/icons/IconTypes.ts +6 -0
  123. package/dist/icons/Loading.torp +5 -3
  124. package/dist/icons/Minus.torp +5 -3
  125. package/dist/icons/Plus.torp +5 -3
  126. package/dist/icons/index.d.ts +271 -126
  127. package/dist/index.d.ts +17 -4
  128. package/dist/metafile-esm.json +1 -1
  129. package/dist/motion/fade.ts +15 -6
  130. package/dist/motion/grow.ts +23 -0
  131. package/dist/motion/index.d.ts +19 -2
  132. package/dist/motion/index.js +93 -3
  133. package/dist/motion/index.js.map +1 -1
  134. package/dist/motion/measure.ts +28 -0
  135. package/dist/motion/slide.ts +45 -0
  136. package/dist/mount/clickPopover.ts +51 -0
  137. package/dist/mount/contextPopover.ts +51 -0
  138. package/dist/mount/hoverPopover.ts +58 -0
  139. package/package.json +28 -12
  140. package/scripts/postbuild.ts +11 -1
  141. package/src/Accordion/Accordion.torp +44 -25
  142. package/src/Accordion/AccordionContent.torp +18 -12
  143. package/src/Accordion/AccordionHeader.torp +15 -8
  144. package/src/Accordion/AccordionItem.torp +34 -17
  145. package/src/Accordion/AccordionTrigger.torp +17 -10
  146. package/src/Accordion/AccordionTypes.ts +6 -3
  147. package/src/Breadcrumb/Breadcrumb.torp +18 -10
  148. package/src/Breadcrumb/BreadcrumbItem.torp +14 -7
  149. package/src/Breadcrumb/BreadcrumbSeparator.torp +10 -3
  150. package/src/Calendar/Calendar.torp +21 -14
  151. package/src/Calendar/CalendarDay.torp +12 -4
  152. package/src/Contextual/Contextual.torp +125 -0
  153. package/src/{Popover/PopoverContentContextual.torp → Contextual/ContextualContent.torp} +21 -12
  154. package/src/Contextual/ContextualTrigger.torp +66 -0
  155. package/src/Contextual/ContextualTypes.ts +30 -0
  156. package/src/Contextual/index.ts +5 -0
  157. package/src/Dialog/Dialog.torp +49 -73
  158. package/src/Dialog/DialogBody.torp +15 -9
  159. package/src/Dialog/DialogButton.torp +27 -13
  160. package/src/Dialog/DialogFooter.torp +11 -3
  161. package/src/Dialog/DialogHeader.torp +15 -8
  162. package/src/Dialog/DialogTypes.ts +3 -2
  163. package/src/Disclosure/Disclosure.torp +34 -25
  164. package/src/Disclosure/DisclosureContent.torp +18 -12
  165. package/src/Disclosure/DisclosureHeader.torp +16 -9
  166. package/src/Disclosure/DisclosureTrigger.torp +15 -8
  167. package/src/Disclosure/DisclosureTypes.ts +0 -1
  168. package/src/Drawer/Drawer.torp +109 -68
  169. package/src/Drawer/DrawerContent.torp +80 -0
  170. package/src/Drawer/DrawerOverlay.torp +38 -0
  171. package/src/Drawer/DrawerTrigger.torp +35 -0
  172. package/src/Drawer/DrawerTypes.ts +24 -0
  173. package/src/Drawer/index.ts +4 -1
  174. package/src/Form/Field.torp +91 -0
  175. package/src/Form/Form.torp +129 -0
  176. package/src/Form/FormTypes.ts +30 -0
  177. package/src/Form/Input.torp +97 -0
  178. package/src/Form/Label.torp +31 -0
  179. package/src/Form/Message.torp +35 -0
  180. package/src/Form/StandardSchemaV1.ts +70 -0
  181. package/src/Form/index.ts +7 -0
  182. package/src/Menu/Menu.torp +25 -15
  183. package/src/Menu/MenuButton.torp +30 -13
  184. package/src/Menu/MenuCheck.torp +29 -14
  185. package/src/Menu/MenuGroup.torp +14 -6
  186. package/src/Menu/MenuIndicator.torp +14 -7
  187. package/src/Menu/MenuPopout.torp +23 -15
  188. package/src/Menu/MenuPopoutContent.torp +17 -10
  189. package/src/Menu/MenuPopoutTrigger.torp +23 -16
  190. package/src/Menu/MenuRadio.torp +27 -16
  191. package/src/Menu/MenuRadioGroup.torp +34 -15
  192. package/src/Menu/MenuSeparator.torp +11 -3
  193. package/src/Menu/MenuTypes.ts +7 -5
  194. package/src/MenuBar/MenuBar.torp +24 -16
  195. package/src/MenuBar/MenuBarItem.torp +24 -16
  196. package/src/MenuBar/MenuBarItemContent.torp +18 -11
  197. package/src/MenuBar/MenuBarItemTrigger.torp +15 -9
  198. package/src/Modal/Modal.torp +118 -0
  199. package/src/Modal/ModalContent.torp +77 -0
  200. package/src/Modal/ModalOverlay.torp +38 -0
  201. package/src/Modal/ModalTrigger.torp +50 -0
  202. package/src/Modal/ModalTypes.ts +22 -0
  203. package/src/Modal/index.ts +10 -0
  204. package/src/Modal/showModal.ts +19 -0
  205. package/src/Modal/showPrompt.ts +23 -0
  206. package/src/NavMenu/NavMenu.torp +18 -10
  207. package/src/NavMenu/NavMenuButton.torp +15 -10
  208. package/src/NavMenu/NavMenuElement.torp +19 -11
  209. package/src/NavMenu/NavMenuGroup.torp +13 -6
  210. package/src/NavMenu/NavMenuGroupHeader.torp +15 -8
  211. package/src/NavMenu/NavMenuLink.torp +21 -16
  212. package/src/NavMenu/NavMenuPopout.torp +34 -18
  213. package/src/NavMenu/NavMenuPopoutButton.torp +23 -18
  214. package/src/NavMenu/NavMenuPopoutContent.torp +23 -13
  215. package/src/NavMenu/NavMenuSeparator.torp +10 -3
  216. package/src/Notification/Notification.torp +35 -16
  217. package/src/Notification/NotificationClose.torp +10 -3
  218. package/src/Notification/NotificationContainer.torp +11 -3
  219. package/src/Notification/NotificationContent.torp +11 -3
  220. package/src/Popover/Popover.torp +48 -28
  221. package/src/Popover/PopoverContent.torp +42 -8
  222. package/src/Popover/PopoverTrigger.torp +32 -3
  223. package/src/Popover/PopoverTypes.ts +1 -1
  224. package/src/Popover/index.ts +1 -24
  225. package/src/Slider/Slider.torp +3 -3
  226. package/src/TabGroup/TabContent.torp +20 -11
  227. package/src/TabGroup/TabGroup.torp +58 -40
  228. package/src/TabGroup/TabGroupTypes.ts +10 -5
  229. package/src/TabGroup/TabHeader.torp +26 -10
  230. package/src/TabGroup/TabList.torp +14 -7
  231. package/src/TabGroup/TabTrigger.torp +17 -10
  232. package/src/icons/ArrowDown.torp +5 -3
  233. package/src/icons/ArrowLeft.torp +5 -3
  234. package/src/icons/ArrowRight.torp +5 -3
  235. package/src/icons/ArrowUp.torp +5 -3
  236. package/src/icons/Bars.torp +5 -3
  237. package/src/icons/Check.torp +5 -3
  238. package/src/icons/ChevronDown.torp +5 -3
  239. package/src/icons/ChevronLeft.torp +5 -3
  240. package/src/icons/ChevronRight.torp +5 -3
  241. package/src/icons/ChevronUp.torp +5 -3
  242. package/src/icons/Cross.torp +5 -3
  243. package/src/icons/IconTypes.ts +6 -0
  244. package/src/icons/Loading.torp +5 -3
  245. package/src/icons/Minus.torp +5 -3
  246. package/src/icons/Plus.torp +5 -3
  247. package/src/motion/fade.ts +15 -6
  248. package/src/motion/grow.ts +23 -0
  249. package/src/motion/index.ts +4 -1
  250. package/src/motion/measure.ts +28 -0
  251. package/src/motion/slide.ts +45 -0
  252. package/src/mount/clickPopover.ts +51 -0
  253. package/src/mount/contextPopover.ts +51 -0
  254. package/src/mount/hoverPopover.ts +58 -0
  255. package/test/Accordion/components/AccordionAccessibility.torp +1 -1
  256. package/test/Accordion/components/AccordionKeyboard.torp +1 -1
  257. package/test/Accordion/components/AccordionList.torp +1 -1
  258. package/test/Accordion/components/AccordionMultiple.torp +2 -2
  259. package/test/Accordion/components/AccordionSingle.torp +2 -2
  260. package/test/Dialog/accessibility-modal.test.ts +2 -2
  261. package/test/Dialog/components/DialogAccessibility.torp +8 -14
  262. package/test/Dialog/components/DialogFunction.torp +20 -4
  263. package/test/Dialog/components/DialogModal.torp +30 -0
  264. package/test/Dialog/components/DialogVariable.torp +7 -7
  265. package/test/Disclosure/accessibility.test.ts +3 -2
  266. package/test/Disclosure/components/DisclosureTest.torp +1 -1
  267. package/test/Disclosure/toggle.test.ts +3 -2
  268. package/test/Form/components/FieldTest.torp +25 -0
  269. package/test/Form/components/FormTest.torp +31 -0
  270. package/test/Form/components/InputTest.torp +9 -0
  271. package/test/Form/field.test.ts +34 -0
  272. package/test/Form/form.test.ts +34 -0
  273. package/test/Form/input.test.ts +19 -0
  274. package/test/Menu/accessibility.test.ts +3 -2
  275. package/test/Menu/basic.test.ts +11 -10
  276. package/test/Menu/components/MenuAccessibility.torp +5 -5
  277. package/test/Menu/components/MenuBasic.torp +5 -5
  278. package/test/MenuBar/accessibility.test.ts +3 -2
  279. package/test/MenuBar/basic.test.ts +3 -2
  280. package/test/NavMenu/basic.test.ts +1 -1
  281. package/test/NavMenu/components/{NavMenu.torp → NavMenuBasic.torp} +1 -1
  282. package/test/Notification/components/NotificationFunction.torp +0 -3
  283. package/test/Notification/components/NotificationVariable.torp +1 -1
  284. package/test/Popover/components/PopoverFunction.torp +37 -0
  285. package/test/Popover/components/PopoverTrigger.torp +36 -0
  286. package/test/Popover/components/{PromptVariable.torp → PopoverVariable.torp} +5 -3
  287. package/test/Popover/function.test.ts +2 -7
  288. package/test/Popover/trigger.test.ts +27 -0
  289. package/test/Popover/variable.test.ts +2 -2
  290. package/test/TabGroup/components/TabGroupAccessibility.torp +1 -1
  291. package/test/TabGroup/components/TabGroupKeyboard.torp +1 -1
  292. package/test/TabGroup/components/TabGroupList.torp +1 -1
  293. package/test/TabGroup/components/TabGroupTrigger.torp +1 -1
  294. package/tsup.config.ts +3 -1
  295. package/dist/Popover/PopoverContentAnchored.torp +0 -106
  296. package/dist/Popover/PopoverOverlay.torp +0 -30
  297. package/dist/Popover/PopoverTriggerContextual.torp +0 -37
  298. package/dist/Popover/PopoverTriggerHover.torp +0 -38
  299. package/dist/Popover/mountClickPopover.ts +0 -50
  300. package/dist/Popover/mountContextPopover.ts +0 -50
  301. package/dist/Popover/mountHoverPopover.ts +0 -57
  302. package/dist/Popover/showPopoverPrompt.ts +0 -23
  303. package/src/Popover/PopoverContentAnchored.torp +0 -106
  304. package/src/Popover/PopoverOverlay.torp +0 -30
  305. package/src/Popover/PopoverTriggerContextual.torp +0 -37
  306. package/src/Popover/PopoverTriggerHover.torp +0 -38
  307. package/src/Popover/mountClickPopover.ts +0 -50
  308. package/src/Popover/mountContextPopover.ts +0 -50
  309. package/src/Popover/mountHoverPopover.ts +0 -57
  310. package/src/Popover/showPopoverPrompt.ts +0 -23
  311. package/test/Dialog/components/CustomDialog.torp +0 -20
  312. package/test/Popover/components/PromptFunction.torp +0 -19
@@ -1,4 +1,17 @@
1
- import { DisclosureContextName, type DisclosureContext } from "./DisclosureTypes";
1
+ import { DisclosureContextName, type DisclosureContext, type DisclosureState } from "./DisclosureTypes";
2
+
3
+ interface DisclosureProps {
4
+ /** An ID for the root element */
5
+ id?: string;
6
+ /** Class name(s) for the root element */
7
+ class?: string,
8
+ /** Whether the disclosure is expanded and its content visible */
9
+ expanded?: boolean,
10
+ /** If set to true, the user cannot interact with this disclosure */
11
+ disabled?: boolean,
12
+ /** Raised when the disclosure is opened or closed */
13
+ ontoggle?: (open: boolean) => void,
14
+ }
2
15
 
3
16
  /**
4
17
  * An interactive header that enables users to reveal or hide an associated section of content.
@@ -9,33 +22,29 @@ import { DisclosureContextName, type DisclosureContext } from "./DisclosureTypes
9
22
  *
10
23
  * ```
11
24
  * <Disclosure>
12
- * <DisclosureHeader>
13
- * <DisclosureTrigger />
14
- * </DisclosureHeader>
15
- * <DisclosureContent />
25
+ * <DisclosureHeader>
26
+ * <DisclosureTrigger />
27
+ * </DisclosureHeader>
28
+ * <DisclosureContent />
16
29
  * </Disclosure>
17
30
  * ```
18
- *
19
- * @prop {boolean} [expanded] -- Whether the Disclosure is expanded and its content visible
20
- * @prop {boolean} [disabled] -- If set to true, the user cannot interact with this Disclosure
21
- * @prop {(boolean) => void} [ontoggle] -- Raised when this item is opened or closed
22
31
  */
23
- export default function Disclosure($props: any) {
24
- $props.expanded ??= false;
25
- $props.disabled ??= false;
26
-
32
+ export default function Disclosure($props: DisclosureProps | undefined) {
27
33
  let $state: DisclosureState = $watch({
28
- expanded: $props.expanded && $props.expanded !== "false",
29
- disabled: $props.disabled,
30
- get dataState() {
31
- return this.expanded ? "open" : "closed";
32
- },
34
+ expanded: false,
35
+ disabled: false,
36
+ headerId: "",
37
+ contentId: "",
33
38
  });
34
39
 
35
40
  // Update $state with $props
36
41
  $run(() => {
37
- $state.expanded = $props.expanded && $props.expanded !== "false";
38
- $state.disabled = $props.disabled;
42
+ $state.expanded = $props?.expanded === true ||
43
+ // @ts-ignore
44
+ $props?.expanded === "true";
45
+ $state.disabled = $props?.disabled === true ||
46
+ // @ts-ignore
47
+ $props?.disabled === "true";
39
48
  });
40
49
 
41
50
  // Put stuff into a DisclosureContext
@@ -47,7 +56,7 @@ export default function Disclosure($props: any) {
47
56
  // Dispatch the toggle event when the value of expanded changes
48
57
  let firstToggle = true;
49
58
  $run(() => {
50
- const ev = $props.ontoggle;
59
+ const ev = $props?.ontoggle;
51
60
  const expanded = $state.expanded;
52
61
  if (firstToggle) {
53
62
  firstToggle = false;
@@ -58,10 +67,10 @@ export default function Disclosure($props: any) {
58
67
 
59
68
  @render {
60
69
  <div
61
- {$props.id}
62
- class={`torp-disclosure-item ${$props.class ?? ""}`.trim()}
63
- data-state={$state.dataState}
64
- data-disabled={$state.dataDisabled}
70
+ {$props?.id}
71
+ class={`torp-disclosure-item ${$props?.class ?? ""}`.trim()}
72
+ data-state={$state.expanded ? "open" : "closed"}
73
+ data-disabled={$state.disabled ? "true" : undefined}
65
74
  >
66
75
  <slot />
67
76
  </div>
@@ -1,32 +1,38 @@
1
1
  import getId from "../utils/getId";
2
2
  import { DisclosureContextName, type DisclosureContext } from "./DisclosureTypes";
3
3
 
4
+ interface DisclosureContentProps {
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 Disclosure */
10
+ ariaRegion?: boolean,
11
+ }
12
+
4
13
  /**
5
14
  * Content for a Disclosure, which can be revealed or hidden by an associated DisclosureTrigger.
6
- *
7
- * @prop {string} [id] -- An ID for the DisclosureContent'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 Disclosure
9
15
  */
10
- export default function DisclosureContent($props: any) {
11
- $props.id ||= getId();
16
+ export default function DisclosureContent($props: DisclosureContentProps | undefined) {
17
+ let defaultId = getId();
12
18
 
13
19
  const context = $context[DisclosureContextName] as DisclosureContext;
14
20
  if (!context) {
15
21
  throw new Error("DisclosureContent must be contained within a Disclosure");
16
22
  }
17
- let $state = $context[DisclosureContextName].state
23
+ let $state = context.state
18
24
 
19
25
  // Set the content ID so that it can be used with aria-controls in DisclosureTrigger
20
- $state.contentId = $props.id;
26
+ $state.contentId = $props?.id ?? defaultId;
21
27
 
22
28
  @render {
23
29
  <div
24
- {$props.id}
25
- class={`torp-disclosure-content ${$props.class ?? ""}`.trim()}
26
- role={$props.ariaRegion ? "region" : undefined}
30
+ id={$props?.id ?? defaultId}
31
+ class={`torp-disclosure-content ${$props?.class ?? ""}`.trim()}
32
+ role={$props?.ariaRegion ? "region" : undefined}
27
33
  aria-labelledby={$state.headerId}
28
- data-state={$state.dataState}
29
- data-disabled={$state.dataDisabled}
34
+ data-state={$state.expanded ? "open" : "closed"}
35
+ data-disabled={$state.disabled ? "true" : undefined}
30
36
  >
31
37
  @if ($state.expanded) {
32
38
  <slot />
@@ -1,5 +1,14 @@
1
1
  import { DisclosureContextName, type DisclosureContext } from "./DisclosureTypes";
2
2
 
3
+ interface DisclosureHeaderProps {
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 a Disclosure, which contains the DisclosureTrigger.
5
14
  *
@@ -7,26 +16,24 @@ import { DisclosureContextName, type DisclosureContext } from "./DisclosureTypes
7
16
  *
8
17
  * ```
9
18
  * <DisclosureHeader>
10
- * <DisclosureTrigger />
19
+ * <DisclosureTrigger />
11
20
  * </DisclosureHeader>
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 DisclosureHeader($props: any) {
23
+ export default function DisclosureHeader($props: DisclosureHeaderProps | undefined) {
17
24
  const context = $context[DisclosureContextName] as DisclosureContext;
18
25
  if (!context) {
19
26
  throw new Error("DisclosureHeader must be contained within a Disclosure");
20
27
  }
21
- let $state = $context[DisclosureContextName].state
28
+ let $state = context.state
22
29
 
23
30
  @render {
24
31
  @// TODO: $props.as
25
32
  <h4
26
- {$props.id}
27
- class={`torp-disclosure-header ${$props.class ?? ""}`.trim()}
28
- data-state={$state.dataState}
29
- data-disabled={$state.dataDisabled}
33
+ {$props?.id}
34
+ class={`torp-disclosure-header ${$props?.class ?? ""}`.trim()}
35
+ data-state={$state.expanded ? "open" : "closed"}
36
+ data-disabled={$state.disabled ? "true" : undefined}
30
37
  >
31
38
  <slot />
32
39
  </h4>
@@ -1,32 +1,39 @@
1
1
  import getId from "../utils/getId";
2
2
  import { DisclosureContextName, type DisclosureContext } from "./DisclosureTypes";
3
3
 
4
+ interface DisclosureTriggerProps {
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 a Disclosure, which can be used to reveal or hide an associated DisclosureContent.
6
13
  */
7
- export default function DisclosureTrigger() {
8
- $props.id ||= getId();
14
+ export default function DisclosureTrigger($props: DisclosureTriggerProps | undefined) {
15
+ let defaultId = getId();
9
16
 
10
17
  // Get stuff out of the DisclosureContext
11
18
  const context = $context[DisclosureContextName] as DisclosureContext;
12
19
  if (!context) {
13
20
  throw new Error("DisclosureTrigger must be contained within a Disclosure");
14
21
  }
15
- let $state = $context[DisclosureContextName].state;
22
+ let $state = context.state;
16
23
 
17
24
  // Set the header ID so that it can be used with aria-labelledby in DisclosureContent
18
- $state.headerId = $props.id;
25
+ $state.headerId = $props?.id ?? defaultId;
19
26
 
20
27
  @render {
21
28
  <button
22
29
  type="button"
23
- {$props.id}
24
- class={`torp-disclosure-trigger ${$props.class ?? ""}`.trim()}
25
- disabled={$state.disabled || $state.parentDisabled}
30
+ id={$props?.id ?? defaultId}
31
+ class={`torp-disclosure-trigger ${$props?.class ?? ""}`.trim()}
32
+ disabled={$state.disabled}
26
33
  aria-expanded={$state.expanded.toString()}
27
34
  aria-disabled={$state.disabled}
28
35
  aria-controls={$state.contentId}
29
- data-state={$state.dataState}
36
+ data-state={$state.expanded ? "open" : "closed"}
30
37
  data-disabled={$state.disabled}
31
38
  onclick={() => $state.expanded = !$state.expanded}
32
39
  >
@@ -10,5 +10,4 @@ export interface DisclosureState {
10
10
  contentId: string;
11
11
  expanded: boolean;
12
12
  disabled: boolean;
13
- dataState: "open" | "closed";
14
13
  }
@@ -1,72 +1,111 @@
1
1
  import { type SlotRender } from "@torpor/view";
2
2
 
3
3
 
4
+ interface DisclosureProps {
5
+ /** An ID for the root element */
6
+ id?: string;
7
+ /** Class name(s) for the root element */
8
+ class?: string,
9
+ /** Whether the disclosure is expanded and its content visible */
10
+ expanded?: boolean,
11
+ /** If set to true, the user cannot interact with this disclosure */
12
+ disabled?: boolean,
13
+ /** Raised when the disclosure is opened or closed */
14
+ ontoggle?: (open: boolean) => void,
15
+ }
16
+
4
17
  /**
5
- * Mounts or hydrates the component into the supplied parent node.
6
- * @param $parent -- The parent node.
7
- * @param $anchor -- The node to mount the component before.
8
- * @param $props -- The values that have been passed into the component as properties.
9
- * @param $context -- Values that have been passed into the component from its ancestors.
10
- * @param $slots -- Functions for rendering children into slot nodes within the component.
18
+ * An interactive header that enables users to reveal or hide an associated section of content.
19
+ *
20
+ * See [the WAI ARIA guidelines for Disclosures](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/).
21
+ *
22
+ * The structure of a Disclosure is:
23
+ *
24
+ * ```
25
+ * <Disclosure>
26
+ * <DisclosureHeader>
27
+ * <DisclosureTrigger />
28
+ * </DisclosureHeader>
29
+ * <DisclosureContent />
30
+ * </Disclosure>
31
+ * ```
11
32
  */
12
33
  declare function Disclosure(
13
34
  $parent: ParentNode,
14
35
  $anchor: Node | null,
15
- $props: any,
36
+ $props: DisclosureProps | undefined,
16
37
  $context?: Record<PropertyKey, any>,
17
38
  $slots?: Record<string, SlotRender>,
18
39
  ): void;
19
40
 
20
41
 
21
42
 
43
+ interface DisclosureContentProps {
44
+ /** An ID for the root element */
45
+ id?: string;
46
+ /** Class name(s) for the root element */
47
+ class?: string,
48
+ /** Whether this content should act as a region. Set this when the content contains heading elements or a nested Disclosure */
49
+ ariaRegion?: boolean,
50
+ }
51
+
22
52
  /**
23
- * Mounts or hydrates the component into the supplied parent node.
24
- * @param $parent -- The parent node.
25
- * @param $anchor -- The node to mount the component before.
26
- * @param $props -- The values that have been passed into the component as properties.
27
- * @param $context -- Values that have been passed into the component from its ancestors.
28
- * @param $slots -- Functions for rendering children into slot nodes within the component.
53
+ * Content for a Disclosure, which can be revealed or hidden by an associated DisclosureTrigger.
29
54
  */
30
55
  declare function DisclosureContent(
31
56
  $parent: ParentNode,
32
57
  $anchor: Node | null,
33
- $props: any,
58
+ $props: DisclosureContentProps | undefined,
34
59
  $context?: Record<PropertyKey, any>,
35
60
  $slots?: Record<string, SlotRender>,
36
61
  ): void;
37
62
 
38
63
 
39
64
 
65
+ interface DisclosureHeaderProps {
66
+ /** An ID for the root element */
67
+ id?: string;
68
+ /** Class name(s) for the root element */
69
+ class?: string,
70
+ /** The type of HTML header to use */
71
+ as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6",
72
+ }
73
+
40
74
  /**
41
- * Mounts or hydrates the component into the supplied parent node.
42
- * @param $parent -- The parent node.
43
- * @param $anchor -- The node to mount the component before.
44
- * @param $props -- The values that have been passed into the component as properties.
45
- * @param $context -- Values that have been passed into the component from its ancestors.
46
- * @param $slots -- Functions for rendering children into slot nodes within the component.
75
+ * The header for a Disclosure, which contains the DisclosureTrigger.
76
+ *
77
+ * The structure of a DisclosureHeader is:
78
+ *
79
+ * ```
80
+ * <DisclosureHeader>
81
+ * <DisclosureTrigger />
82
+ * </DisclosureHeader>
83
+ * ```
47
84
  */
48
85
  declare function DisclosureHeader(
49
86
  $parent: ParentNode,
50
87
  $anchor: Node | null,
51
- $props: any,
88
+ $props: DisclosureHeaderProps | undefined,
52
89
  $context?: Record<PropertyKey, any>,
53
90
  $slots?: Record<string, SlotRender>,
54
91
  ): void;
55
92
 
56
93
 
57
94
 
95
+ interface DisclosureTriggerProps {
96
+ /** An ID for the root element */
97
+ id?: string;
98
+ /** Class name(s) for the root element */
99
+ class?: string,
100
+ }
101
+
58
102
  /**
59
- * Mounts or hydrates the component into the supplied parent node.
60
- * @param $parent -- The parent node.
61
- * @param $anchor -- The node to mount the component before.
62
- * @param $props -- The values that have been passed into the component as properties.
63
- * @param $context -- Values that have been passed into the component from its ancestors.
64
- * @param $slots -- Functions for rendering children into slot nodes within the component.
103
+ * A header button for a Disclosure, which can be used to reveal or hide an associated DisclosureContent.
65
104
  */
66
105
  declare function DisclosureTrigger(
67
106
  $parent: ParentNode,
68
107
  $anchor: Node | null,
69
- $props?: Record<PropertyKey, any>,
108
+ $props: DisclosureTriggerProps | undefined,
70
109
  $context?: Record<PropertyKey, any>,
71
110
  $slots?: Record<string, SlotRender>,
72
111
  ): void;
@@ -1,82 +1,123 @@
1
+ import { DrawerContextName, type DrawerContext, type DrawerState } from "./DrawerTypes";
1
2
 
2
- export default function Drawer($props: any) {
3
- $props.visible ??= true;
4
- $props.position ||= "left";
3
+ interface DrawerProps {
4
+ /** An ID for the root element */
5
+ id?: string;
6
+ /** Class name(s) for the root element */
7
+ class?: string,
8
+ /** Whether the drawer is modal. If true, an overlay should be supplied to obscure outside content, and only the drawer content will be visible to screen readers */
9
+ modal?: boolean,
10
+ /** Whether the drawer is visible */
11
+ visible?: boolean,
12
+ /** Which side of the window to show the drawer from */
13
+ position?: "left" | "right" | "top" | "bottom",
14
+ /** A function to be called when the user selects a response */
15
+ callback?: ((value: any) => void),
16
+ /** Raised when the drawer is opened or closed */
17
+ ontoggle?: (open: boolean) => void,
18
+ /** Raised when the drawer has opened */
19
+ onopen?: () => void,
20
+ /** Raised when the drawer has closed */
21
+ onclose?: (result: any) => void,
22
+ }
5
23
 
6
- let offscreen: HTMLElement | undefined;
24
+ /**
25
+ * A drawer that can be used to show rich content or obtain information from a user.
26
+ *
27
+ * See [the WAI ARIA guidelines for Dialogs](https://www.w3.org/WAI/ARIA/apg/patterns/dialogmodal/).
28
+ *
29
+ * The structure of a Drawer is:
30
+ *
31
+ * ```
32
+ * <Drawer>
33
+ * <DrawerTrigger /> (optional)
34
+ * <DrawerContent />
35
+ * </Drawer>
36
+ * ```
37
+ */
38
+ export default function Drawer($props: DrawerProps | undefined) {
39
+ let $state: DrawerState = $watch({
40
+ visible: false,
41
+ modal: $props?.modal ?? false,
42
+ position: $props?.position ?? "left",
43
+ });
7
44
 
8
- // From https://stackoverflow.com/a/46707458
9
- function measure(el, fn) {
10
- let oldVisibility = el.style.visibility;
11
- let oldPosition = el.style.position;
45
+ // Sync props and state
46
+ $run(() => {
47
+ $state.visible = $props?.visible ?? false;
48
+ });
49
+ $run(() => {
50
+ if ($props !== undefined) {
51
+ $props.visible = $state.visible;
52
+ }
53
+ });
12
54
 
13
- let oldParent = el.parentNode;
14
- let oldBefore = el.nextNode;
55
+ let result: any;
15
56
 
16
- el.style.visibility = "hidden";
17
- el.style.position = "absolute";
57
+ // Set the context to pass down to items
58
+ let context: DrawerContext = {
59
+ handleButton,
60
+ handleClickOutside,
61
+ state: $state,
62
+ };
63
+ $context[DrawerContextName] = context;
18
64
 
19
- document.body.appendChild(el);
20
- let result = fn(el);
21
- el.parentNode.removeChild(el);
65
+ // Dispatch the toggle event when the drawer is opened or closed
66
+ let firstToggle = true;
67
+ $run(() => {
68
+ const ontoggle = $props?.ontoggle;
69
+ const onopen = $props?.onopen;
70
+ const onclose = $props?.onclose;
71
+ const visible = $state.visible;
72
+ if (firstToggle) {
73
+ firstToggle = false;
74
+ } else {
75
+ if (ontoggle) ontoggle(visible);
76
+ if (visible) {
77
+ if (onopen) onopen()
78
+ } else {
79
+ if (onclose) onclose(result);
80
+ }
81
+ }
82
+ });
83
+
84
+ function handleButton(type: "confirm" | "cancel" | undefined, value?: any) {
85
+ // Get the button's result
86
+ switch (type) {
87
+ case "confirm": {
88
+ result = value || true;
89
+ break;
90
+ }
91
+ case "cancel": {
92
+ result = value || false;
93
+ break;
94
+ }
95
+ default: {
96
+ result = value;
97
+ break;
98
+ }
99
+ }
22
100
 
23
- oldParent.appendChild(el, oldBefore);
24
- el.style.visibility = oldVisibility;
25
- el.style.position = oldPosition;
101
+ // Hide the drawer
102
+ $state.visible = false;
26
103
 
27
- return result;
104
+ // Call the callback
105
+ if ($props?.callback) {
106
+ $props?.callback(result);
107
+ }
28
108
  }
29
109
 
30
- function transitionArgs() {
31
- if (offscreen) {
32
- switch ($props.position) {
33
- case "left": {
34
- offscreen.style.left = 0;
35
- const width = measure(offscreen, (el) => el.offsetWidth);
36
- return [
37
- { transform: `translateX(-${width}px)` },
38
- { transform: "translateX(0px)" }
39
- ];
40
- }
41
- case "top": {
42
- offscreen.style.top = 0;
43
- const height = measure(offscreen, (el) => el.offsetHeight);
44
- return [
45
- { transform: `translateY(-${height}px)` },
46
- { transform: "translateY(0px)" }
47
- ];
48
- }
49
- case "right": {
50
- offscreen.style.right = 0;
51
- const width = measure(offscreen, (el) => el.offsetWidth);
52
- return [
53
- { transform: `translateX(${width}px)` },
54
- { transform: "translateX(0px)" }
55
- ];
56
- }
57
- case "bottom": {
58
- offscreen.style.bottom = 0;
59
- const height = measure(offscreen, (el) => el.offsetHeight);
60
- return [
61
- { transform: `translateY(${height}px)` },
62
- { transform: "translateY(0px)" }
63
- ];
64
- }
65
- }
66
- }
110
+ function handleClickOutside(e: MouseEvent) {
111
+ e.preventDefault();
112
+ $state.visible = false;
67
113
  }
68
114
 
69
115
  @render {
70
- @if ($props.visible) {
71
- <div
72
- {$props.id}
73
- class={`torp-offscreen ${$props.class ?? ""}`.trim()}
74
- style="position: fixed;"
75
- transition={transitionArgs()}
76
- &ref={offscreen}
77
- >
78
- <slot />
79
- </div>
80
- }
116
+ <div
117
+ {$props?.id}
118
+ class={`torp-drawer ${$props?.class ?? ""}`.trim()}
119
+ >
120
+ <slot />
121
+ </div>
81
122
  }
82
- }
123
+ }
@@ -0,0 +1,80 @@
1
+ import { type Animation } from "@torpor/view";
2
+ import { slide } from "../motion";
3
+ import { addDocumentEvent, removeDocumentEvent } from "../utils/documentEvents";
4
+ import { DrawerContextName, type DrawerContext } from "./DrawerTypes";
5
+
6
+ interface DrawerContentProps {
7
+ /** An ID for the root element */
8
+ id?: string;
9
+ /** Class name(s) for the root element */
10
+ class?: string,
11
+ }
12
+
13
+ /**
14
+ * The content that is displayed for a Drawer when it is open.
15
+ */
16
+ export default function DrawerContent($props: DrawerContentProps | undefined) {
17
+ let drawer: HTMLElement;
18
+ let shown = false;
19
+ let closeOnClick = false;
20
+
21
+ // Get stuff out of the DrawerContext
22
+ const context = $context[DrawerContextName] as DrawerContext;
23
+ if (!context) {
24
+ throw new Error("DrawerContent must be contained within a Drawer");
25
+ }
26
+ let $state = context.state;
27
+
28
+ $run(() => {
29
+ if (!$state.visible) {
30
+ hide();
31
+ }
32
+ });
33
+
34
+ function show() {
35
+ shown = true;
36
+
37
+ // HACK: Because this Drawer could be shown with a click, we need to wait for another mousedown
38
+ // before we close on click. Otherwise the click immediately bubbles to the document
39
+ closeOnClick = false;
40
+ addDocumentEvent("mousedown", handleDocumentMouseDown);
41
+ addDocumentEvent("click", handleDocumentClick);
42
+ }
43
+
44
+ function hide() {
45
+ if (!shown) return;
46
+
47
+ removeDocumentEvent("mousedown", handleDocumentMouseDown);
48
+ removeDocumentEvent("click", handleDocumentClick);
49
+ }
50
+
51
+ function handleDocumentMouseDown() {
52
+ closeOnClick = true;
53
+ }
54
+
55
+ function handleDocumentClick(e: MouseEvent) {
56
+ if (
57
+ closeOnClick &&
58
+ drawer &&
59
+ !drawer.contains(e.target as HTMLElement)
60
+ ) {
61
+ e.preventDefault();
62
+ context.handleClickOutside!(e);
63
+ }
64
+ }
65
+
66
+ @render {
67
+ @if ($state.visible) {
68
+ <div
69
+ {$props?.id}
70
+ class={`torp-drawer-content ${$props?.class ?? ""}`.trim()}
71
+ style="position: fixed;"
72
+ transition={(e) => slide(e, { side: $state.position })}
73
+ &ref={drawer}
74
+ onmount={show}
75
+ >
76
+ <slot />
77
+ </div>
78
+ }
79
+ }
80
+ }