@torpor/ui 0.3.4 → 0.3.6

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 (226) hide show
  1. package/dist/Form/Form.torp +1 -0
  2. package/dist/metafile-esm.json +1 -1
  3. package/package.json +12 -9
  4. package/CHANGELOG.md +0 -338
  5. package/scripts/postbuild.ts +0 -127
  6. package/src/Accordion/Accordion.torp +0 -230
  7. package/src/Accordion/AccordionContent.torp +0 -46
  8. package/src/Accordion/AccordionHeader.torp +0 -45
  9. package/src/Accordion/AccordionItem.torp +0 -101
  10. package/src/Accordion/AccordionTrigger.torp +0 -70
  11. package/src/Accordion/AccordionTypes.ts +0 -36
  12. package/src/Accordion/index.ts +0 -7
  13. package/src/Breadcrumb/Breadcrumb.torp +0 -45
  14. package/src/Breadcrumb/BreadcrumbItem.torp +0 -30
  15. package/src/Breadcrumb/BreadcrumbSeparator.torp +0 -27
  16. package/src/Breadcrumb/index.ts +0 -5
  17. package/src/Calendar/Calendar.torp +0 -277
  18. package/src/Calendar/CalendarDay.torp +0 -78
  19. package/src/Calendar/CalendarTypes.ts +0 -22
  20. package/src/Calendar/index.ts +0 -4
  21. package/src/Contextual/Contextual.torp +0 -129
  22. package/src/Contextual/ContextualContent.torp +0 -112
  23. package/src/Contextual/ContextualTrigger.torp +0 -70
  24. package/src/Contextual/ContextualTypes.ts +0 -30
  25. package/src/Contextual/index.ts +0 -5
  26. package/src/Dialog/Dialog.torp +0 -136
  27. package/src/Dialog/DialogBody.torp +0 -44
  28. package/src/Dialog/DialogButton.torp +0 -66
  29. package/src/Dialog/DialogFooter.torp +0 -25
  30. package/src/Dialog/DialogHeader.torp +0 -45
  31. package/src/Dialog/DialogTypes.ts +0 -17
  32. package/src/Dialog/index.ts +0 -7
  33. package/src/Disclosure/Disclosure.torp +0 -82
  34. package/src/Disclosure/DisclosureContent.torp +0 -46
  35. package/src/Disclosure/DisclosureHeader.torp +0 -45
  36. package/src/Disclosure/DisclosureTrigger.torp +0 -47
  37. package/src/Disclosure/DisclosureTypes.ts +0 -13
  38. package/src/Disclosure/index.ts +0 -6
  39. package/src/Drawer/Drawer.torp +0 -127
  40. package/src/Drawer/DrawerContent.torp +0 -83
  41. package/src/Drawer/DrawerOverlay.torp +0 -42
  42. package/src/Drawer/DrawerTrigger.torp +0 -39
  43. package/src/Drawer/DrawerTypes.ts +0 -24
  44. package/src/Drawer/index.ts +0 -6
  45. package/src/Form/CheckBox.torp +0 -94
  46. package/src/Form/Field.torp +0 -95
  47. package/src/Form/File.torp +0 -102
  48. package/src/Form/Form.torp +0 -146
  49. package/src/Form/FormTypes.ts +0 -35
  50. package/src/Form/Hidden.torp +0 -25
  51. package/src/Form/Input.torp +0 -112
  52. package/src/Form/Label.torp +0 -35
  53. package/src/Form/Message.torp +0 -39
  54. package/src/Form/Option.torp +0 -28
  55. package/src/Form/Select.torp +0 -101
  56. package/src/Form/StandardSchemaV1.ts +0 -70
  57. package/src/Form/TextArea.torp +0 -105
  58. package/src/Form/index.ts +0 -13
  59. package/src/Menu/Menu.torp +0 -174
  60. package/src/Menu/MenuButton.torp +0 -74
  61. package/src/Menu/MenuCheck.torp +0 -89
  62. package/src/Menu/MenuGroup.torp +0 -31
  63. package/src/Menu/MenuIndicator.torp +0 -40
  64. package/src/Menu/MenuPopout.torp +0 -83
  65. package/src/Menu/MenuPopoutContent.torp +0 -84
  66. package/src/Menu/MenuPopoutTrigger.torp +0 -128
  67. package/src/Menu/MenuRadio.torp +0 -103
  68. package/src/Menu/MenuRadioGroup.torp +0 -109
  69. package/src/Menu/MenuSeparator.torp +0 -26
  70. package/src/Menu/MenuTypes.ts +0 -60
  71. package/src/Menu/index.ts +0 -25
  72. package/src/MenuBar/MenuBar.torp +0 -162
  73. package/src/MenuBar/MenuBarItem.torp +0 -116
  74. package/src/MenuBar/MenuBarItemContent.torp +0 -119
  75. package/src/MenuBar/MenuBarItemTrigger.torp +0 -99
  76. package/src/MenuBar/MenuBarTypes.ts +0 -36
  77. package/src/MenuBar/index.ts +0 -6
  78. package/src/Modal/Modal.torp +0 -122
  79. package/src/Modal/ModalContent.torp +0 -81
  80. package/src/Modal/ModalOverlay.torp +0 -42
  81. package/src/Modal/ModalTrigger.torp +0 -54
  82. package/src/Modal/ModalTypes.ts +0 -22
  83. package/src/Modal/index.ts +0 -10
  84. package/src/Modal/showModal.ts +0 -19
  85. package/src/Modal/showPrompt.ts +0 -23
  86. package/src/NavMenu/NavMenu.torp +0 -190
  87. package/src/NavMenu/NavMenuButton.torp +0 -55
  88. package/src/NavMenu/NavMenuElement.torp +0 -55
  89. package/src/NavMenu/NavMenuGroup.torp +0 -41
  90. package/src/NavMenu/NavMenuGroupHeader.torp +0 -41
  91. package/src/NavMenu/NavMenuLink.torp +0 -60
  92. package/src/NavMenu/NavMenuPopout.torp +0 -89
  93. package/src/NavMenu/NavMenuPopoutButton.torp +0 -129
  94. package/src/NavMenu/NavMenuPopoutContent.torp +0 -92
  95. package/src/NavMenu/NavMenuSeparator.torp +0 -24
  96. package/src/NavMenu/NavMenuTypes.ts +0 -32
  97. package/src/NavMenu/index.ts +0 -23
  98. package/src/Notification/Notification.torp +0 -71
  99. package/src/Notification/NotificationClose.torp +0 -39
  100. package/src/Notification/NotificationContainer.torp +0 -26
  101. package/src/Notification/NotificationContent.torp +0 -25
  102. package/src/Notification/NotificationTypes.ts +0 -5
  103. package/src/Notification/index.ts +0 -13
  104. package/src/Notification/showNotification.ts +0 -30
  105. package/src/Popover/Popover.torp +0 -129
  106. package/src/Popover/PopoverContent.torp +0 -117
  107. package/src/Popover/PopoverTrigger.torp +0 -62
  108. package/src/Popover/PopoverTypes.ts +0 -30
  109. package/src/Popover/index.ts +0 -6
  110. package/src/Popover/showPopover.ts +0 -24
  111. package/src/Slider/Slider.torp +0 -84
  112. package/src/Slider/index.ts +0 -3
  113. package/src/TabGroup/TabContent.torp +0 -49
  114. package/src/TabGroup/TabGroup.torp +0 -250
  115. package/src/TabGroup/TabGroupTypes.ts +0 -44
  116. package/src/TabGroup/TabHeader.torp +0 -81
  117. package/src/TabGroup/TabList.torp +0 -61
  118. package/src/TabGroup/TabTrigger.torp +0 -76
  119. package/src/TabGroup/index.ts +0 -7
  120. package/src/ambient.d.ts +0 -7
  121. package/src/icons/ArrowDown.torp +0 -18
  122. package/src/icons/ArrowLeft.torp +0 -18
  123. package/src/icons/ArrowRight.torp +0 -18
  124. package/src/icons/ArrowUp.torp +0 -18
  125. package/src/icons/Bars.torp +0 -20
  126. package/src/icons/Check.torp +0 -18
  127. package/src/icons/ChevronDown.torp +0 -18
  128. package/src/icons/ChevronLeft.torp +0 -18
  129. package/src/icons/ChevronRight.torp +0 -18
  130. package/src/icons/ChevronUp.torp +0 -18
  131. package/src/icons/Cross.torp +0 -19
  132. package/src/icons/IconTypes.ts +0 -10
  133. package/src/icons/Loading.torp +0 -19
  134. package/src/icons/Minus.torp +0 -18
  135. package/src/icons/Plus.torp +0 -19
  136. package/src/icons/index.ts +0 -31
  137. package/src/motion/fade.ts +0 -16
  138. package/src/motion/grow.ts +0 -23
  139. package/src/motion/index.ts +0 -6
  140. package/src/motion/measure.ts +0 -28
  141. package/src/motion/slide.ts +0 -45
  142. package/src/mount/clickPopover.ts +0 -51
  143. package/src/mount/contextPopover.ts +0 -51
  144. package/src/mount/disableScroll.ts +0 -28
  145. package/src/mount/hoverPopover.ts +0 -58
  146. package/src/mount/hoverTrigger.ts +0 -59
  147. package/src/mount/trapFocus.ts +0 -58
  148. package/src/utils/dateUtils.ts +0 -244
  149. package/src/utils/documentEvents.ts +0 -17
  150. package/src/utils/getId.ts +0 -6
  151. package/src/utils/getScrollParent.ts +0 -22
  152. package/src/utils/setContextPosition.ts +0 -31
  153. package/src/utils/setPopoverPosition.ts +0 -142
  154. package/test/Accordion/accessibility.test.ts +0 -59
  155. package/test/Accordion/components/AccordionAccessibility.torp +0 -44
  156. package/test/Accordion/components/AccordionKeyboard.torp +0 -32
  157. package/test/Accordion/components/AccordionList.torp +0 -23
  158. package/test/Accordion/components/AccordionMultiple.torp +0 -32
  159. package/test/Accordion/components/AccordionSingle.torp +0 -32
  160. package/test/Accordion/for-items.test.ts +0 -52
  161. package/test/Accordion/keyboard.test.ts +0 -64
  162. package/test/Accordion/multiple-item-toggle.test.ts +0 -32
  163. package/test/Accordion/multiple-item-value.test.ts +0 -17
  164. package/test/Accordion/single-item-toggle.test.ts +0 -31
  165. package/test/Accordion/single-item-value.test.ts +0 -17
  166. package/test/Breadcrumb/accessibility.test.ts +0 -29
  167. package/test/Breadcrumb/basic.test.ts +0 -17
  168. package/test/Breadcrumb/components/BreadcrumbTest.torp +0 -15
  169. package/test/Calendar/components/CalendarTest.torp +0 -9
  170. package/test/Calendar/default.test.ts +0 -18
  171. package/test/Dialog/accessibility-alert.test.ts +0 -40
  172. package/test/Dialog/accessibility-modal.test.ts +0 -52
  173. package/test/Dialog/components/DialogAccessibility.torp +0 -25
  174. package/test/Dialog/components/DialogFunction.torp +0 -36
  175. package/test/Dialog/components/DialogModal.torp +0 -30
  176. package/test/Dialog/components/DialogVariable.torp +0 -33
  177. package/test/Dialog/function.test.ts +0 -26
  178. package/test/Dialog/variable.test.ts +0 -27
  179. package/test/Disclosure/accessibility.test.ts +0 -31
  180. package/test/Disclosure/components/DisclosureTest.torp +0 -17
  181. package/test/Disclosure/default.test.ts +0 -15
  182. package/test/Disclosure/toggle.test.ts +0 -20
  183. package/test/Form/components/FieldTest.torp +0 -25
  184. package/test/Form/components/FormTest.torp +0 -31
  185. package/test/Form/components/InputTest.torp +0 -9
  186. package/test/Form/field.test.ts +0 -34
  187. package/test/Form/form.test.ts +0 -34
  188. package/test/Form/input.test.ts +0 -19
  189. package/test/Menu/accessibility.test.ts +0 -83
  190. package/test/Menu/basic.test.ts +0 -58
  191. package/test/Menu/components/MenuAccessibility.torp +0 -59
  192. package/test/Menu/components/MenuBasic.torp +0 -58
  193. package/test/MenuBar/accessibility.test.ts +0 -87
  194. package/test/MenuBar/basic.test.ts +0 -22
  195. package/test/MenuBar/components/MenuBarAccessibility.torp +0 -34
  196. package/test/MenuBar/components/MenuBarBasic.torp +0 -25
  197. package/test/NavMenu/accessibility.test.ts +0 -97
  198. package/test/NavMenu/basic.test.ts +0 -22
  199. package/test/NavMenu/components/NavMenuAccessibility.torp +0 -35
  200. package/test/NavMenu/components/NavMenuBasic.torp +0 -28
  201. package/test/Notification/accessibility.test.ts +0 -21
  202. package/test/Notification/components/CustomNotification.torp +0 -14
  203. package/test/Notification/components/NotificationAccessibility.torp +0 -14
  204. package/test/Notification/components/NotificationFunction.torp +0 -17
  205. package/test/Notification/components/NotificationVariable.torp +0 -22
  206. package/test/Notification/function.test.ts +0 -25
  207. package/test/Notification/variable.test.ts +0 -25
  208. package/test/Popover/components/CustomDialog.torp +0 -25
  209. package/test/Popover/components/PopoverFunction.torp +0 -37
  210. package/test/Popover/components/PopoverTrigger.torp +0 -36
  211. package/test/Popover/components/PopoverVariable.torp +0 -40
  212. package/test/Popover/function.test.ts +0 -21
  213. package/test/Popover/trigger.test.ts +0 -27
  214. package/test/Popover/variable.test.ts +0 -27
  215. package/test/TabGroup/accessibility.test.ts +0 -67
  216. package/test/TabGroup/components/TabGroupAccessibility.torp +0 -28
  217. package/test/TabGroup/components/TabGroupKeyboard.torp +0 -28
  218. package/test/TabGroup/components/TabGroupList.torp +0 -26
  219. package/test/TabGroup/components/TabGroupTrigger.torp +0 -28
  220. package/test/TabGroup/for-items.test.ts +0 -52
  221. package/test/TabGroup/item-trigger.test.ts +0 -33
  222. package/test/TabGroup/item-value.test.ts +0 -17
  223. package/test/TabGroup/keyboard.test.ts +0 -72
  224. package/tsconfig.json +0 -4
  225. package/tsup.config.ts +0 -37
  226. package/vitest.config.ts +0 -12
@@ -1,78 +0,0 @@
1
- import type { ClassValue, StyleValue } from "@torpor/view";
2
- import { areDatesEqual } from "../utils/dateUtils";
3
- import { type CalendarContext, type CalendarEvent, CalendarContextName } from "./CalendarTypes";
4
-
5
- interface CalendarDayProps {
6
- /** An ID for the root element */
7
- id?: string;
8
- /** Classes for the root element */
9
- class?: ClassValue,
10
- /** Styles for the root element */
11
- style?: StyleValue,
12
- }
13
-
14
- export default function CalendarDay($props: CalendarDayProps) {
15
- $props ??= $watch({});
16
- $props.date ??= new Date();
17
- $props.selectable ??= false;
18
- $props.muted ??= false;
19
- $props.active ??= false;
20
- $props.events ??= [];
21
-
22
- // HACK: can't unwrap in @render
23
- let date = $unwrap($props.date);
24
-
25
- // Register this item with the parent Calendar, which will handle toggling active for all days
26
- const { registerDay } = $context[CalendarContextName] as CalendarContext;
27
- registerDay($props.date, setActive);
28
-
29
- // This function is called by the parent Calendar to set this item's active value
30
- function setActive(value: boolean) {
31
- //if (active !== value) {
32
- // active = value;
33
- // dispatch("activeChange", value);
34
- //}
35
- }
36
-
37
- function isToday() {
38
- const today = new Date();
39
- return areDatesEqual(date, today);
40
- }
41
-
42
- async function handleClick() {
43
- //dispatch("click", date);
44
- if ($props.onclick) $props.onclick($props.date);
45
- }
46
-
47
- async function handleKey() {
48
- //dispatch("click", date);
49
- if ($props.onkeydown) $props.onkeydown();
50
- }
51
-
52
- @render {
53
- <div
54
- {$props?.id}
55
- class={[
56
- `torp-calendar-day ${$props?.class ?? ""}`.trim(),
57
- {
58
- muted: $props.muted,
59
- today: isToday(),
60
- active: $props.selectable && $props.active
61
- }
62
- ]}
63
- >
64
- @if ($props.selectable) {
65
- <button type="button" tabindex="-1" onclick={handleClick} onkeydown={handleKey}>
66
- <span>{date.getDate()}</span>
67
- </button>
68
- } else {
69
- <span>{date.getDate()}</span>
70
- }
71
- <ul class={`torp-calendar-day-events ${$props?.class ?? ""}`.trim()}>
72
- @for (ev of $props.events) {
73
- <li title={ev.content} />
74
- }
75
- </ul>
76
- </div>
77
- }
78
- }
@@ -1,22 +0,0 @@
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
- }
@@ -1,4 +0,0 @@
1
- import Calendar from "./Calendar.torp";
2
- import CalendarDay from "./CalendarDay.torp";
3
-
4
- export { Calendar, CalendarDay };
@@ -1,129 +0,0 @@
1
- import type { ClassValue, StyleValue } from "@torpor/view";
2
- import { ContextualContextName, type Point, type ContextualContext, type ContextualState } from "./ContextualTypes";
3
-
4
- interface ContextualProps {
5
- /** An ID for the root element */
6
- id?: string;
7
- /** Classes for the root element */
8
- class?: ClassValue,
9
- /** Styles for the root element */
10
- style?: StyleValue,
11
- /** Whether the contextual is modal. If true, an overlay should be supplied to obscure outside content, and only the context content will be visible to screen readers */
12
- modal?: boolean,
13
- /** Whether the contextual is visible */
14
- visible?: boolean,
15
- /** The element to anchor this contextual to, as an alternative to supplying a ContextualTrigger */
16
- anchor?: HTMLElement,
17
- /** The position to display this contextual at */
18
- position?: Point,
19
- /** A function to be called when the user selects a response */
20
- callback?: ((value: any) => void),
21
- /** Raised when this contextual is opened or closed */
22
- ontoggle?: (open: boolean) => void,
23
- /** Raised when the contextual has opened */
24
- onopen?: () => void,
25
- /** Raised when the contextual has closed */
26
- onclose?: (result: any) => void,
27
- }
28
-
29
- /**
30
- * A contextual window that is shown to the user at the cursor's location.
31
- *
32
- * The structure of a Contextual is:
33
- *
34
- * ```
35
- * <Contextual>
36
- * <ContextualTrigger /> (optional)
37
- * <ContextualContent />
38
- * </Contextual>
39
- * ```
40
- */
41
- export default function Contextual($props: ContextualProps | undefined) {
42
- let $state: ContextualState = $watch({
43
- visible: false,
44
- position: { x: 0, y: 0 }
45
- })
46
-
47
- // Sync props and state
48
- $run(() => {
49
- $state.visible = $props?.visible ?? false;
50
- $state.position = $props?.position ?? { x: 0, y: 0 };
51
- });
52
- $run(() => {
53
- if ($props !== undefined) {
54
- $props.visible = $state.visible;
55
- }
56
- });
57
-
58
- let result: any;
59
-
60
- // Set the context to pass down to items
61
- let context: ContextualContext = {
62
- handleButton,
63
- handleClickOutside,
64
- state: $state,
65
- modal: $props?.modal,
66
- anchorElement: $props?.anchor ? $unwrap($props.anchor) : undefined,
67
- };
68
- $context[ContextualContextName] = context;
69
-
70
- // Dispatch the toggle event when the contextual is opened or closed
71
- let firstToggle = true;
72
- $run(() => {
73
- const ontoggle = $props?.ontoggle;
74
- const onopen = $props?.onopen;
75
- const onclose = $props?.onclose;
76
- const visible = $state.visible;
77
- if (firstToggle) {
78
- firstToggle = false;
79
- } else {
80
- if (ontoggle) ontoggle(visible);
81
- if (visible) {
82
- if (onopen) onopen()
83
- } else {
84
- if (onclose) onclose(result);
85
- }
86
- }
87
- });
88
-
89
- function handleButton(type: "confirm" | "cancel" | undefined, value?: any) {
90
- // Get the button's result
91
- switch (type) {
92
- case "confirm": {
93
- result = value || true;
94
- break;
95
- }
96
- case "cancel": {
97
- result = value || false;
98
- break;
99
- }
100
- default: {
101
- result = value;
102
- break;
103
- }
104
- }
105
-
106
- // Hide the contextual
107
- $state.visible = false;
108
-
109
- // Call the callback
110
- if ($props?.callback) {
111
- $props.callback(result);
112
- }
113
- }
114
-
115
- function handleClickOutside(e: MouseEvent) {
116
- e.preventDefault();
117
- $state.visible = false;
118
- }
119
-
120
- @render {
121
- <div
122
- {$props?.id}
123
- class={["torp-context", $props?.class]}
124
- {$props?.style}
125
- >
126
- <slot />
127
- </div>
128
- }
129
- }
@@ -1,112 +0,0 @@
1
- import type { ClassValue, StyleValue } from "@torpor/view";
2
- import { addDocumentEvent, removeDocumentEvent } from "../utils/documentEvents";
3
- import getScrollParent from "../utils/getScrollParent";
4
- import setContextPosition from "../utils/setContextPosition";
5
- import { ContextualContextName, type ContextualContext } from "./ContextualTypes";
6
-
7
- interface ContextualContentProps {
8
- /** An ID for the root element */
9
- id?: string;
10
- /** Classes for the root element */
11
- class?: ClassValue,
12
- /** Styles for the root element */
13
- style?: StyleValue,
14
- }
15
-
16
- /**
17
- * The content that is displayed for a Contextual when it is open, displayed at the
18
- * position that the user right-clicked.
19
- */
20
- export default function ContextualContent($props: ContextualContentProps | undefined) {
21
- let div: HTMLDivElement;
22
- let shown = false;
23
- let closeOnClick = false;
24
-
25
- // Get stuff out of the ContextualContext
26
- const context = $context[ContextualContextName] as ContextualContext;
27
- if (!context) {
28
- throw new Error("ContextualContent must be contained within a Contextual");
29
- }
30
- let $state = context.state;
31
-
32
- $run(() => {
33
- if (!$state.visible) {
34
- hide();
35
- }
36
- });
37
-
38
- function show() {
39
- shown = true;
40
-
41
- // HACK: Because this Contextual could be shown with a click, we need to wait for another mousedown
42
- // before we close on click. Otherwise the click immediately bubbles to the document
43
- closeOnClick = false;
44
- addDocumentEvent("mousedown", handleDocumentMouseDown);
45
- addDocumentEvent("click", handleDocumentClick);
46
-
47
- // Set the position and listen for window resize and scroll to reset the position
48
- setPosition();
49
- const anchorElement = context.anchorElement!;
50
- const scrollParent = getScrollParent(anchorElement)
51
- scrollParent.addEventListener("resize", setPosition);
52
- scrollParent.addEventListener("scroll", setPosition);
53
- if (context.focusFirstElement) {
54
- context.focusFirstElement();
55
- }
56
- }
57
-
58
- function hide() {
59
- if (!shown) return;
60
-
61
- removeDocumentEvent("mousedown", handleDocumentMouseDown);
62
- removeDocumentEvent("click", handleDocumentClick);
63
-
64
- // Stop listening for window resize and focus the anchor element per WAI guidelines
65
- const anchorElement = context.anchorElement!;
66
- const scrollParent = getScrollParent(anchorElement)
67
- scrollParent.removeEventListener("resize", setPosition);
68
- scrollParent.removeEventListener("scroll", setPosition);
69
- if (anchorElement.focus) {
70
- anchorElement.focus();
71
- }
72
- }
73
-
74
- function handleDocumentMouseDown() {
75
- closeOnClick = true;
76
- }
77
-
78
- function handleDocumentClick(e: MouseEvent) {
79
- if (
80
- closeOnClick &&
81
- div &&
82
- !div.contains(e.target as HTMLElement) &&
83
- (!context.anchorElement || !context.anchorElement.contains(e.target as HTMLElement))
84
- ) {
85
- context.handleClickOutside!(e);
86
- }
87
- }
88
-
89
- function setPosition() {
90
- if (!context.anchorElement) {
91
- throw new Error("ContextualContent must have an anchor element");
92
- }
93
-
94
- if ($state.position) {
95
- setContextPosition(context.anchorElement, div, $state.position);
96
- }
97
- }
98
-
99
- @render {
100
- @if ($state.visible) {
101
- <div
102
- {$props?.id}
103
- class={["torp-popover-content-contextual", $props?.class]}
104
- {$props?.style}
105
- &ref={div}
106
- onmount={show}
107
- >
108
- <slot />
109
- </div>
110
- }
111
- }
112
- }
@@ -1,70 +0,0 @@
1
- import type { ClassValue, StyleValue } from "@torpor/view";
2
- import { ContextualContextName, type ContextualContext } from "./ContextualTypes";
3
- import hoverTrigger from "../mount/hoverTrigger";
4
-
5
- interface ContextualTriggerProps {
6
- /** An ID for the root element */
7
- id?: string;
8
- /** Classes for the root element */
9
- class?: ClassValue,
10
- /** Styles for the root element */
11
- style?: StyleValue,
12
- /** Whether the popover is activated by click/press or by hover **/
13
- activation?: "press" | "hover"
14
- }
15
-
16
- /**
17
- * The element that causes a Contextual to appear or disappear when right-clicked.
18
- */
19
- export default function ContextualTrigger($props: ContextualTriggerProps | undefined) {
20
- let activation = $props?.activation ?? "press";
21
-
22
- // Get stuff out of the ContextualContext
23
- const context = $context[ContextualContextName] as ContextualContext;
24
- if (!context) {
25
- throw new Error("ContextualTrigger must be contained within a Contextual");
26
- }
27
- let $state = context.state;
28
-
29
- function handleContextualMenu(e: MouseEvent & { currentTarget: EventTarget & HTMLDivElement }) {
30
- if (activation !== "press") return;
31
-
32
- e.preventDefault();
33
- if ($state.position) {
34
- // Get the position relative to the element, so we can reposition on scroll
35
- const rect = e.currentTarget.getBoundingClientRect();
36
- const x = e.clientX - rect.left;
37
- const y = e.clientY - rect.top;
38
- $state.position = { x, y };
39
- //$state.position = { x: window.scrollX + e.clientX, y: window.scrollY + e.clientY };
40
- }
41
- $state.visible = !$state.visible;
42
- }
43
-
44
- function handleHover(node: HTMLElement, e: MouseEvent) {
45
- if (activation !== "hover") return;
46
-
47
- if ($state.position) {
48
- // Get the position relative to the element, so we can reposition on scroll
49
- const rect = node.getBoundingClientRect();
50
- const x = e.clientX - rect.left;
51
- const y = e.clientY - rect.top;
52
- $state.position = { x, y };
53
- //$state.position = { x: window.scrollX + e.clientX, y: window.scrollY + e.clientY };
54
- }
55
- $state.visible = !$state.visible
56
- }
57
-
58
- @render {
59
- <div
60
- {$props?.id}
61
- class={["torp-popover-trigger-contextual", $props?.class]}
62
- {$props?.style}
63
- oncontextmenu={handleContextualMenu}
64
- onmount={(el) => hoverTrigger(el, { onHover: handleHover, onExit: handleHover })}
65
- &ref={context.anchorElement}
66
- >
67
- <slot />
68
- </div>
69
- }
70
- }
@@ -1,30 +0,0 @@
1
- export const ContextualContextName = "Contextual";
2
-
3
- /** The shared context for popover components (Contextual, Prompt and Contextual) */
4
- export interface ContextualContext {
5
- handleButton: (type: "confirm" | "cancel" | undefined, value?: any) => void;
6
- // HACK: We need to be able to let children (i.e. Dialogs) override the click outside functionality
7
- // There may be a more elegant way to accomplish this too
8
- handleClickOutside?: (e: MouseEvent) => void;
9
- state: ContextualState;
10
- //modal: boolean;
11
- anchorElement?: HTMLElement;
12
- // HACK: focusFirstElement is necessary because if we focus the first element e.g. in a Dialog's
13
- // onMount, it will scroll the page to the focused element and mess up our careful positioning
14
- // We need to be able to manually set the order to
15
- // 1. set visible (so we have an element with content)
16
- // 2. set position (so the element is in the right place)
17
- // 3. set focus (for accessibility)
18
- // There may be a more elegant way to accomplish this!
19
- focusFirstElement?: () => void;
20
- }
21
-
22
- export interface ContextualState {
23
- visible: boolean;
24
- position: Point;
25
- }
26
-
27
- export interface Point {
28
- x: number;
29
- y: number;
30
- }
@@ -1,5 +0,0 @@
1
- import Contextual from "./Contextual.torp";
2
- import ContextualContent from "./ContextualContent.torp";
3
- import ContextualTrigger from "./ContextualTrigger.torp";
4
-
5
- export { Contextual, ContextualContent, ContextualTrigger };
@@ -1,136 +0,0 @@
1
- import type { ClassValue, StyleValue } from "@torpor/view";
2
- import getId from "../utils/getId";
3
- import { trapFocus, type TrapFocusOptions } from "../mount/trapFocus";
4
- import { ModalContextName, type ModalContext } from "../Modal/ModalTypes";
5
- import { PopoverContextName } from "../Popover/PopoverTypes";
6
- import { DialogContextName, type DialogContext, type DialogState, type HandleButtonPress } from "./DialogTypes";
7
-
8
- interface DialogProps {
9
- /** An ID for the root element */
10
- id?: string;
11
- /** Classes for the root element */
12
- class?: ClassValue,
13
- /** Styles for the root element */
14
- style?: StyleValue,
15
- /** An ARIA label for describing the popover to screen readers */
16
- ariaLabel?: string,
17
- /** Whether the dialog should alert the user via the screen reader */
18
- alert?: boolean,
19
- }
20
-
21
- /**
22
- * A dialog that can be used to show a message to the user, or get information from the user.
23
- *
24
- * Dialogs are typically shown within a Modal or Popover.
25
- *
26
- * See [the WAI ARIA guidelines for Dialogs](https://www.w3.org/WAI/ARIA/apg/patterns/dialogmodal/).
27
- *
28
- * The structure of a Dialog is:
29
- *
30
- * ```
31
- * <Dialog>
32
- * <ModalOverlay /> (optional -- will set `modal` to true)
33
- * <DialogHeader /> (optional)
34
- * <DialogBody /> (optional)
35
- * <DialogFooter> (optional)
36
- * <DialogButton /> (optional)
37
- * </DialogFooter>
38
- * </Dialog>
39
- * ```
40
- *
41
- */
42
- export default function Dialog($props: DialogProps | undefined) {
43
- let defaultId = getId();
44
-
45
- //let div: HTMLDivElement;
46
-
47
- let trapFocusOptions: TrapFocusOptions = {
48
- focusableElements: []
49
- };
50
-
51
- // Maybe get stuff out of a Modal context
52
- let modal = false;
53
- let visible = true;
54
- let handleButton: HandleButtonPress | undefined = undefined;
55
- const modalContext = $context[ModalContextName] ?? $context[PopoverContextName] as ModalContext;
56
- if (modalContext) {
57
- modal = true;
58
- visible = modalContext.state.visible;
59
- handleButton = modalContext.handleButton;
60
-
61
- modalContext.handleClickOutside = handleClickOutside;
62
- // Set the focusFirstElement method in the ModalContext so that it can be
63
- // called after everything has been shown
64
- modalContext.focusFirstElement = focusFirstElement;
65
- }
66
-
67
- // Set the IDs for using in the Dialog's ARIA attributes
68
- let $state: DialogState = $watch({
69
- dialogId: $props?.id ?? defaultId,
70
- headerId: "",
71
- bodyId: "",
72
- visible
73
- })
74
-
75
- // Set the context to pass down to items
76
- let context: DialogContext = {
77
- handleButton,
78
- state: $state,
79
- anchorElement: modalContext ? modalContext.anchorElement : undefined
80
- };
81
- $context[DialogContextName] = context;
82
-
83
- function focusFirstElement() {
84
- if (trapFocusOptions.focusableElements.length) {
85
- trapFocusOptions.focusableElements[0].focus();
86
- }
87
- }
88
-
89
- function handleClickOutside(e: MouseEvent) {
90
- // Don't allow the user to click outside -- they must press a button or
91
- // the Esc key
92
- e.preventDefault();
93
- if (!modal) {
94
- modalContext.state.visible = false;
95
- }
96
- }
97
-
98
- function handleKey(e: KeyboardEvent) {
99
- switch (e.key) {
100
- case "Esc":
101
- case "Escape": {
102
- if (context.cancelButton) {
103
- context.cancelButton.click();
104
- e.preventDefault();
105
- }
106
- break;
107
- }
108
- case "Enter": {
109
- if (context.confirmButton) {
110
- context.confirmButton.click();
111
- e.preventDefault();
112
- }
113
- break;
114
- }
115
- }
116
- }
117
-
118
- @render {
119
- <div
120
- id={$props?.id ?? defaultId}
121
- class={["torp-dialog", $props?.class]}
122
- {$props?.style}
123
- tabindex="0"
124
- role={$props?.alert === true ? "alertdialog" : "dialog"}
125
- aria-modal={modal}
126
- aria-label={$props?.ariaLabel}
127
- aria-labelledby={!$props?.ariaLabel && $state.headerId ? $state.headerId : undefined}
128
- aria-describedby={$state.bodyId ? $state.bodyId : undefined}
129
- onkeydown={handleKey}
130
- onmount={(el) => trapFocus(el, trapFocusOptions)}
131
- @//&ref={div}
132
- >
133
- <slot />
134
- </div>
135
- }
136
- }
@@ -1,44 +0,0 @@
1
- import type { ClassValue, StyleValue } from "@torpor/view";
2
- import getId from "../utils/getId";
3
- import { DialogContextName, type DialogContext } from "./DialogTypes";
4
-
5
- interface DialogBodyProps {
6
- /** An ID for the root element */
7
- id?: string;
8
- /** Classes for the root element */
9
- class?: ClassValue,
10
- /** Styles for the root element */
11
- style?: StyleValue,
12
- /** Whether the body content will be announced by screen readers when the Dialog is opened */
13
- ariaAnnounce?: boolean,
14
- }
15
-
16
- /**
17
- * The body information for a Dialog. Content in the body will be announced by
18
- * screen readers when the Dialog is opened, unless ariaAnnounce is false.
19
- */
20
- export default function DialogBody($props: DialogBodyProps | undefined) {
21
- let defaultId = getId();
22
-
23
- // Get stuff out of the DialogContext
24
- const context = $context[DialogContextName] as DialogContext;
25
- if (!context) {
26
- throw new Error("DialogBody must be contained within a Dialog");
27
- }
28
- let $state = context.state;
29
-
30
- // Set the body id for using in the Dialog's ARIA attributes
31
- if ($props?.ariaAnnounce !== false) {
32
- $state.bodyId = $props?.id || defaultId;
33
- }
34
-
35
- @render {
36
- <div
37
- id={$props?.id ?? defaultId}
38
- class={["torp-dialog-body", $props?.class]}
39
- {$props?.style}
40
- >
41
- <slot />
42
- </div>
43
- }
44
- }