@torpor/ui 0.2.0 → 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 (213) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/Accordion/Accordion.torp +23 -11
  3. package/dist/Accordion/AccordionContent.torp +13 -6
  4. package/dist/Accordion/AccordionHeader.torp +14 -5
  5. package/dist/Accordion/AccordionItem.torp +22 -8
  6. package/dist/Accordion/AccordionTrigger.torp +14 -6
  7. package/dist/Accordion/AccordionTypes.ts +2 -0
  8. package/dist/Accordion/index.d.ts +100 -35
  9. package/dist/Breadcrumb/Breadcrumb.torp +12 -3
  10. package/dist/Breadcrumb/BreadcrumbItem.torp +12 -3
  11. package/dist/Breadcrumb/BreadcrumbSeparator.torp +10 -1
  12. package/dist/Breadcrumb/index.d.ts +49 -21
  13. package/dist/Calendar/Calendar.torp +9 -1
  14. package/dist/Calendar/CalendarDay.torp +9 -1
  15. package/dist/Calendar/index.d.ts +16 -18
  16. package/dist/Dialog/Dialog.torp +13 -3
  17. package/dist/Dialog/DialogBody.torp +11 -3
  18. package/dist/Dialog/DialogButton.torp +16 -4
  19. package/dist/Dialog/DialogFooter.torp +11 -1
  20. package/dist/Dialog/DialogHeader.torp +11 -2
  21. package/dist/Dialog/index.d.ts +78 -35
  22. package/dist/Disclosure/Disclosure.torp +17 -7
  23. package/dist/Disclosure/DisclosureContent.torp +13 -6
  24. package/dist/Disclosure/DisclosureHeader.torp +14 -5
  25. package/dist/Disclosure/DisclosureTrigger.torp +10 -2
  26. package/dist/Disclosure/index.d.ts +67 -28
  27. package/dist/Drawer/Drawer.torp +11 -1
  28. package/dist/Drawer/index.d.ts +10 -9
  29. package/dist/Form/Field.torp +93 -0
  30. package/dist/Form/Form.torp +131 -0
  31. package/dist/Form/FormTypes.ts +30 -0
  32. package/dist/Form/Input.torp +94 -0
  33. package/dist/Form/Label.torp +31 -0
  34. package/dist/Form/Message.torp +35 -0
  35. package/dist/Form/StandardSchemaV1.ts +70 -0
  36. package/dist/Form/index.d.ts +117 -0
  37. package/dist/Form/index.js +22 -0
  38. package/dist/Form/index.js.map +1 -0
  39. package/dist/Menu/Menu.torp +12 -3
  40. package/dist/Menu/MenuButton.torp +14 -3
  41. package/dist/Menu/MenuCheck.torp +14 -3
  42. package/dist/Menu/MenuGroup.torp +13 -3
  43. package/dist/Menu/MenuIndicator.torp +12 -3
  44. package/dist/Menu/MenuPopout.torp +17 -6
  45. package/dist/Menu/MenuPopoutContent.torp +13 -4
  46. package/dist/Menu/MenuPopoutTrigger.torp +13 -4
  47. package/dist/Menu/MenuRadio.torp +16 -5
  48. package/dist/Menu/MenuRadioGroup.torp +16 -5
  49. package/dist/Menu/MenuSeparator.torp +11 -1
  50. package/dist/Menu/index.d.ts +170 -77
  51. package/dist/MenuBar/MenuBar.torp +13 -4
  52. package/dist/MenuBar/MenuBarItem.torp +17 -6
  53. package/dist/MenuBar/MenuBarItemContent.torp +13 -4
  54. package/dist/MenuBar/MenuBarItemTrigger.torp +11 -2
  55. package/dist/MenuBar/index.d.ts +79 -28
  56. package/dist/NavMenu/NavMenu.torp +13 -4
  57. package/dist/NavMenu/NavMenuButton.torp +12 -5
  58. package/dist/NavMenu/NavMenuElement.torp +14 -6
  59. package/dist/NavMenu/NavMenuGroup.torp +12 -3
  60. package/dist/NavMenu/NavMenuGroupHeader.torp +12 -4
  61. package/dist/NavMenu/NavMenuLink.torp +16 -8
  62. package/dist/NavMenu/NavMenuPopout.torp +11 -3
  63. package/dist/NavMenu/NavMenuPopoutButton.torp +14 -8
  64. package/dist/NavMenu/NavMenuPopoutContent.torp +13 -3
  65. package/dist/NavMenu/NavMenuSeparator.torp +10 -1
  66. package/dist/NavMenu/index.d.ts +147 -70
  67. package/dist/Notification/Notification.torp +15 -5
  68. package/dist/Notification/NotificationClose.torp +10 -1
  69. package/dist/Notification/NotificationContainer.torp +11 -1
  70. package/dist/Notification/NotificationContent.torp +11 -1
  71. package/dist/Notification/index.d.ts +46 -28
  72. package/dist/Popover/Popover.torp +20 -6
  73. package/dist/Popover/PopoverContent.torp +10 -1
  74. package/dist/Popover/PopoverContentAnchored.torp +13 -6
  75. package/dist/Popover/PopoverContentContextual.torp +10 -1
  76. package/dist/Popover/PopoverOverlay.torp +10 -1
  77. package/dist/Popover/PopoverTrigger.torp +10 -1
  78. package/dist/Popover/PopoverTriggerContextual.torp +10 -1
  79. package/dist/Popover/PopoverTriggerHover.torp +11 -2
  80. package/dist/Popover/index.d.ts +101 -56
  81. package/dist/TabGroup/TabContent.torp +11 -5
  82. package/dist/TabGroup/TabGroup.torp +21 -9
  83. package/dist/TabGroup/TabHeader.torp +14 -5
  84. package/dist/TabGroup/TabList.torp +13 -4
  85. package/dist/TabGroup/TabTrigger.torp +12 -4
  86. package/dist/TabGroup/index.d.ts +93 -35
  87. package/dist/icons/ArrowDown.torp +3 -3
  88. package/dist/icons/ArrowLeft.torp +3 -3
  89. package/dist/icons/ArrowRight.torp +3 -3
  90. package/dist/icons/ArrowUp.torp +3 -3
  91. package/dist/icons/Bars.torp +3 -3
  92. package/dist/icons/Check.torp +3 -3
  93. package/dist/icons/ChevronDown.torp +3 -3
  94. package/dist/icons/ChevronLeft.torp +3 -3
  95. package/dist/icons/ChevronRight.torp +3 -3
  96. package/dist/icons/ChevronUp.torp +3 -3
  97. package/dist/icons/Cross.torp +3 -3
  98. package/dist/icons/Loading.torp +3 -3
  99. package/dist/icons/Minus.torp +3 -3
  100. package/dist/icons/Plus.torp +3 -3
  101. package/dist/icons/index.d.ts +14 -126
  102. package/dist/metafile-esm.json +1 -1
  103. package/package.json +13 -4
  104. package/src/Accordion/Accordion.torp +23 -11
  105. package/src/Accordion/AccordionContent.torp +13 -6
  106. package/src/Accordion/AccordionHeader.torp +14 -5
  107. package/src/Accordion/AccordionItem.torp +22 -8
  108. package/src/Accordion/AccordionTrigger.torp +14 -6
  109. package/src/Accordion/AccordionTypes.ts +2 -0
  110. package/src/Breadcrumb/Breadcrumb.torp +12 -3
  111. package/src/Breadcrumb/BreadcrumbItem.torp +12 -3
  112. package/src/Breadcrumb/BreadcrumbSeparator.torp +10 -1
  113. package/src/Calendar/Calendar.torp +9 -1
  114. package/src/Calendar/CalendarDay.torp +9 -1
  115. package/src/Dialog/Dialog.torp +13 -3
  116. package/src/Dialog/DialogBody.torp +11 -3
  117. package/src/Dialog/DialogButton.torp +16 -4
  118. package/src/Dialog/DialogFooter.torp +11 -1
  119. package/src/Dialog/DialogHeader.torp +11 -2
  120. package/src/Disclosure/Disclosure.torp +17 -7
  121. package/src/Disclosure/DisclosureContent.torp +13 -6
  122. package/src/Disclosure/DisclosureHeader.torp +14 -5
  123. package/src/Disclosure/DisclosureTrigger.torp +10 -2
  124. package/src/Drawer/Drawer.torp +11 -1
  125. package/src/Form/Field.torp +93 -0
  126. package/src/Form/Form.torp +131 -0
  127. package/src/Form/FormTypes.ts +30 -0
  128. package/src/Form/Input.torp +94 -0
  129. package/src/Form/Label.torp +31 -0
  130. package/src/Form/Message.torp +35 -0
  131. package/src/Form/StandardSchemaV1.ts +70 -0
  132. package/src/Form/index.ts +7 -0
  133. package/src/Menu/Menu.torp +12 -3
  134. package/src/Menu/MenuButton.torp +14 -3
  135. package/src/Menu/MenuCheck.torp +14 -3
  136. package/src/Menu/MenuGroup.torp +13 -3
  137. package/src/Menu/MenuIndicator.torp +12 -3
  138. package/src/Menu/MenuPopout.torp +17 -6
  139. package/src/Menu/MenuPopoutContent.torp +13 -4
  140. package/src/Menu/MenuPopoutTrigger.torp +13 -4
  141. package/src/Menu/MenuRadio.torp +16 -5
  142. package/src/Menu/MenuRadioGroup.torp +16 -5
  143. package/src/Menu/MenuSeparator.torp +11 -1
  144. package/src/MenuBar/MenuBar.torp +13 -4
  145. package/src/MenuBar/MenuBarItem.torp +17 -6
  146. package/src/MenuBar/MenuBarItemContent.torp +13 -4
  147. package/src/MenuBar/MenuBarItemTrigger.torp +11 -2
  148. package/src/NavMenu/NavMenu.torp +13 -4
  149. package/src/NavMenu/NavMenuButton.torp +12 -5
  150. package/src/NavMenu/NavMenuElement.torp +14 -6
  151. package/src/NavMenu/NavMenuGroup.torp +12 -3
  152. package/src/NavMenu/NavMenuGroupHeader.torp +12 -4
  153. package/src/NavMenu/NavMenuLink.torp +16 -8
  154. package/src/NavMenu/NavMenuPopout.torp +11 -3
  155. package/src/NavMenu/NavMenuPopoutButton.torp +14 -8
  156. package/src/NavMenu/NavMenuPopoutContent.torp +13 -3
  157. package/src/NavMenu/NavMenuSeparator.torp +10 -1
  158. package/src/Notification/Notification.torp +15 -5
  159. package/src/Notification/NotificationClose.torp +10 -1
  160. package/src/Notification/NotificationContainer.torp +11 -1
  161. package/src/Notification/NotificationContent.torp +11 -1
  162. package/src/Popover/Popover.torp +20 -6
  163. package/src/Popover/PopoverContent.torp +10 -1
  164. package/src/Popover/PopoverContentAnchored.torp +13 -6
  165. package/src/Popover/PopoverContentContextual.torp +10 -1
  166. package/src/Popover/PopoverOverlay.torp +10 -1
  167. package/src/Popover/PopoverTrigger.torp +10 -1
  168. package/src/Popover/PopoverTriggerContextual.torp +10 -1
  169. package/src/Popover/PopoverTriggerHover.torp +11 -2
  170. package/src/TabGroup/TabContent.torp +11 -5
  171. package/src/TabGroup/TabGroup.torp +21 -9
  172. package/src/TabGroup/TabHeader.torp +14 -5
  173. package/src/TabGroup/TabList.torp +13 -4
  174. package/src/TabGroup/TabTrigger.torp +12 -4
  175. package/src/icons/ArrowDown.torp +3 -3
  176. package/src/icons/ArrowLeft.torp +3 -3
  177. package/src/icons/ArrowRight.torp +3 -3
  178. package/src/icons/ArrowUp.torp +3 -3
  179. package/src/icons/Bars.torp +3 -3
  180. package/src/icons/Check.torp +3 -3
  181. package/src/icons/ChevronDown.torp +3 -3
  182. package/src/icons/ChevronLeft.torp +3 -3
  183. package/src/icons/ChevronRight.torp +3 -3
  184. package/src/icons/ChevronUp.torp +3 -3
  185. package/src/icons/Cross.torp +3 -3
  186. package/src/icons/Loading.torp +3 -3
  187. package/src/icons/Minus.torp +3 -3
  188. package/src/icons/Plus.torp +3 -3
  189. package/test/Accordion/components/AccordionAccessibility.torp +2 -0
  190. package/test/Accordion/components/AccordionKeyboard.torp +2 -0
  191. package/test/Accordion/components/AccordionList.torp +2 -0
  192. package/test/Accordion/components/AccordionMultiple.torp +2 -0
  193. package/test/Accordion/components/AccordionSingle.torp +2 -0
  194. package/test/Disclosure/accessibility.test.ts +3 -2
  195. package/test/Disclosure/components/DisclosureTest.torp +2 -0
  196. package/test/Disclosure/toggle.test.ts +3 -2
  197. package/test/Form/components/FieldTest.torp +25 -0
  198. package/test/Form/components/FormTest.torp +31 -0
  199. package/test/Form/components/InputTest.torp +9 -0
  200. package/test/Form/field.test.ts +34 -0
  201. package/test/Form/form.test.ts +34 -0
  202. package/test/Form/input.test.ts +19 -0
  203. package/test/Menu/accessibility.test.ts +3 -2
  204. package/test/Menu/basic.test.ts +11 -10
  205. package/test/MenuBar/accessibility.test.ts +3 -2
  206. package/test/MenuBar/basic.test.ts +3 -2
  207. package/test/NavMenu/basic.test.ts +1 -1
  208. package/test/NavMenu/components/{NavMenu.torp → NavMenuBasic.torp} +1 -1
  209. package/test/TabGroup/components/TabGroupAccessibility.torp +2 -0
  210. package/test/TabGroup/components/TabGroupKeyboard.torp +2 -0
  211. package/test/TabGroup/components/TabGroupList.torp +2 -0
  212. package/test/TabGroup/components/TabGroupTrigger.torp +2 -0
  213. package/tsup.config.ts +1 -1
@@ -0,0 +1,94 @@
1
+ import getId from "../utils/getId";
2
+ import { FormContextName, FieldContextName, type FormContext, type FieldContext } from "./FormTypes";
3
+
4
+ interface InputProps {
5
+ /** An ID for the root element */
6
+ id?: string;
7
+ /** Class name(s) for the root element */
8
+ class?: string,
9
+ /** The input type */
10
+ type?: "text" | "number" | "password" | "email" | "url" | "tel",
11
+ /** The name of the input's form data field */
12
+ name?: string,
13
+ /** The data value that this field is bound to */
14
+ value?: any,
15
+ /** Text to display when the input value is empty */
16
+ placeholder?: string,
17
+ /** Whether the input should be readonly */
18
+ readonly?: boolean,
19
+ /** The maximum number of characters allowed for the input value */
20
+ maxlength?: number,
21
+ /** An ARIA label for describing the input to screen readers when there is no associated label element */
22
+ ariaLabel?: string,
23
+ };
24
+
25
+ /**
26
+ * A standard input in a form.
27
+ */
28
+ export default function Input($props: InputProps) {
29
+ $props ??= $watch({});
30
+ $props.id ??= getId();
31
+ $props.type ??= "text";
32
+
33
+ let blurred = false;
34
+
35
+ // Get stuff out of the FormContext and FieldContext
36
+ const formContext = $context[FormContextName] as FormContext;
37
+ const fieldContext = $context[FieldContextName] as FieldContext;
38
+ if (fieldContext) {
39
+ $props.name ??= fieldContext.name;
40
+ }
41
+
42
+ // Use the FieldContext's state, or create a new one
43
+ let $state = fieldContext?.state ?? $watch({
44
+ inputId: $props.id,
45
+ value: $props.value,
46
+ errors: {} as Record<string, string>,
47
+ valid: false,
48
+ message: "",
49
+ });
50
+
51
+ // Binding
52
+ $run(() => {
53
+ $props.value = $state.value;
54
+ });
55
+
56
+ // Set the input ID now that we know it and it will get linked with the associated label
57
+ $state.inputId = $props.id;
58
+
59
+ // NOTE: Adapted this from https://stackoverflow.com/a/57393751,
60
+ // not sure if it's still a good way to do things
61
+ function handleInput(e: Event & { currentTarget: EventTarget & HTMLInputElement }) {
62
+ $state.value = $props!.type?.match(/^(number|range)$/) ? +e.currentTarget.value : e.currentTarget.value;
63
+ if (formContext) {
64
+ formContext.validate();
65
+ }
66
+ if (fieldContext && blurred) {
67
+ fieldContext.validate();
68
+ }
69
+ }
70
+
71
+ function handleBlur() {
72
+ if (fieldContext) {
73
+ fieldContext.validate();
74
+ }
75
+ blurred = true;
76
+ }
77
+
78
+ @render {
79
+ <input
80
+ {$props.id}
81
+ class={`torp-input ${$props.class ?? ""}`.trim()}
82
+ {$props.name}
83
+ &value={$state.value}
84
+ {$props.type}
85
+ {$props.placeholder}
86
+ {$props.readonly}
87
+ {$props.maxlength}
88
+ aria-label={$props.ariaLabel}
89
+ data-valid={$state.valid ? "valid" : "invalid"}
90
+ oninput={handleInput}
91
+ onblur={handleBlur}
92
+ />
93
+ }
94
+ }
@@ -0,0 +1,31 @@
1
+ import { FieldContextName, type FieldContext } from "./FormTypes";
2
+
3
+ interface LabelProps {
4
+ /** An ID for the root element */
5
+ id?: string;
6
+ /** Class name(s) for the root element */
7
+ class?: string,
8
+ }
9
+
10
+ /**
11
+ * A label to describe the contents of an input in a form.
12
+ */
13
+ export default function Label($props?: LabelProps) {
14
+ // Get stuff out of the FieldContext
15
+ const context = $context[FieldContextName] as FieldContext;
16
+ if (!context) {
17
+ throw new Error("Label must be contained within a Field");
18
+ }
19
+ let { state: $state } = context;
20
+
21
+ @render {
22
+ <label
23
+ {$props?.id}
24
+ class={`torp-label ${$props?.class ?? ""}`.trim()}
25
+ for={$state.inputId}
26
+ data-valid={$state.valid ? "valid" : "invalid"}
27
+ >
28
+ <slot />
29
+ </label>
30
+ }
31
+ }
@@ -0,0 +1,35 @@
1
+ import { FieldContextName, type FieldContext } from "./FormTypes";
2
+
3
+ interface MessageProps {
4
+ /** An ID for the root element */
5
+ id?: string;
6
+ /** Class name(s) for the root element */
7
+ class?: string,
8
+ }
9
+
10
+ /**
11
+ * A validation message to show when the contents of an input component have
12
+ * problems that need to be fixed.
13
+ */
14
+ export default function Message($props?: MessageProps) {
15
+ // Get stuff out of the FieldContext
16
+ const context = $context[FieldContextName] as FieldContext;
17
+ if (!context) {
18
+ throw new Error("Message must be contained within a Field");
19
+ }
20
+ const { state: $state } = context;
21
+
22
+ @render {
23
+ @if ($state.message) {
24
+ <div
25
+ {$props?.id}
26
+ class={`torp-message ${$props?.class ?? ""}`.trim()}
27
+ data-valid={$state.valid ? "valid" : "invalid"}
28
+ >
29
+ <slot name="message">
30
+ {$state.message}
31
+ </slot>
32
+ </div>
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,70 @@
1
+ // From https://github.com/standard-schema/standard-schema
2
+
3
+ /** The Standard Schema interface. */
4
+ export interface StandardSchemaV1<Input = unknown, Output = Input> {
5
+ /** The Standard Schema properties. */
6
+ readonly "~standard": StandardSchemaV1.Props<Input, Output>;
7
+ }
8
+
9
+ export declare namespace StandardSchemaV1 {
10
+ /** The Standard Schema properties interface. */
11
+ export interface Props<Input = unknown, Output = Input> {
12
+ /** The version number of the standard. */
13
+ readonly version: 1;
14
+ /** The vendor name of the schema library. */
15
+ readonly vendor: string;
16
+ /** Validates unknown input values. */
17
+ readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;
18
+ /** Inferred types associated with the schema. */
19
+ readonly types?: Types<Input, Output> | undefined;
20
+ }
21
+
22
+ /** The result interface of the validate function. */
23
+ export type Result<Output> = SuccessResult<Output> | FailureResult;
24
+
25
+ /** The result interface if validation succeeds. */
26
+ export interface SuccessResult<Output> {
27
+ /** The typed output value. */
28
+ readonly value: Output;
29
+ /** The non-existent issues. */
30
+ readonly issues?: undefined;
31
+ }
32
+
33
+ /** The result interface if validation fails. */
34
+ export interface FailureResult {
35
+ /** The issues of failed validation. */
36
+ readonly issues: ReadonlyArray<Issue>;
37
+ }
38
+
39
+ /** The issue interface of the failure output. */
40
+ export interface Issue {
41
+ /** The error message of the issue. */
42
+ readonly message: string;
43
+ /** The path of the issue, if any. */
44
+ readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
45
+ }
46
+
47
+ /** The path segment interface of the issue. */
48
+ export interface PathSegment {
49
+ /** The key representing a path segment. */
50
+ readonly key: PropertyKey;
51
+ }
52
+
53
+ /** The Standard Schema types interface. */
54
+ export interface Types<Input = unknown, Output = Input> {
55
+ /** The input type of the schema. */
56
+ readonly input: Input;
57
+ /** The output type of the schema. */
58
+ readonly output: Output;
59
+ }
60
+
61
+ /** Infers the input type of a Standard Schema. */
62
+ export type InferInput<Schema extends StandardSchemaV1> = NonNullable<
63
+ Schema["~standard"]["types"]
64
+ >["input"];
65
+
66
+ /** Infers the output type of a Standard Schema. */
67
+ export type InferOutput<Schema extends StandardSchemaV1> = NonNullable<
68
+ Schema["~standard"]["types"]
69
+ >["output"];
70
+ }
@@ -0,0 +1,7 @@
1
+ import Field from "./Field.torp";
2
+ import Form from "./Form.torp";
3
+ import Input from "./Input.torp";
4
+ import Label from "./Label.torp";
5
+ import Message from "./Message.torp";
6
+
7
+ export { Form, Field, Label, Input, Message };
@@ -7,6 +7,15 @@ import {
7
7
  type MenuPopoutContext
8
8
  } from "./MenuTypes";
9
9
 
10
+ interface MenuProps {
11
+ /** An ID for the root element */
12
+ id?: string;
13
+ /** Class name(s) for the root element */
14
+ class?: string,
15
+ /** An ARIA label for describing the menu to screen readers */
16
+ ariaLabel?: string,
17
+ }
18
+
10
19
  /**
11
20
  * A list of choices for the user, such as a set of actions or functions. A
12
21
  * menu is usually hidden until made visible by the user.
@@ -24,10 +33,10 @@ import {
24
33
  * </MenuGroup>
25
34
  * </Menu>
26
35
  * ```
27
- *
28
- * @prop {string} ariaLabel -- An ARIA label for describing the menu to screen readers
29
36
  */
30
- export default function Menu() {
37
+ export default function Menu($props: MenuProps) {
38
+ $props ??= $watch({});
39
+
31
40
  // A collection containing the state and some functions for each item
32
41
  let itemStates: ItemState[] = [];
33
42
  let focusIndex = -1;
@@ -1,12 +1,23 @@
1
1
  import { MenuContextName, type MenuContext } from "./MenuTypes";
2
2
 
3
+ interface MenuButtonProps {
4
+ /** An ID for the root element */
5
+ id?: string;
6
+ /** Class name(s) for the root element */
7
+ class?: string,
8
+ /** The value that should be returned when this button is pressed and the Dialog was invoked by calling showContextual, showPrompt or showPopover */
9
+ value?: any,
10
+ /** Whether this button is disabled */
11
+ disabled?: boolean,
12
+ }
13
+
3
14
  /**
4
15
  * A button that is placed in a Menu or MenuGroup and signals a response by a user.
5
16
  *
6
- * @prop {any} value -- The value that should be returned when this button is pressed and the Dialog was invoked by calling showContextual, showPrompt or showPopover
7
- * @prop {boolean} disabled -- Whether this button is disabled
8
17
  */
9
- export default function MenuButton() {
18
+ export default function MenuButton($props: MenuButtonProps) {
19
+ $props ??= $watch({});
20
+
10
21
  let button: HTMLButtonElement;
11
22
 
12
23
  // Get stuff out of the MenuContext
@@ -5,14 +5,25 @@ import {
5
5
  type MenuContext
6
6
  } from "./MenuTypes";
7
7
 
8
+ interface MenuCheckProps {
9
+ /** An ID for the root element */
10
+ id?: string;
11
+ /** Class name(s) for the root element */
12
+ class?: string,
13
+ /** Whether this item is checked */
14
+ checked?: boolean,
15
+ /** Whether this item is disabled */
16
+ disabled?: boolean,
17
+ }
18
+
8
19
  /**
9
20
  * A button that is placed in a Menu or MenuGroup to allow the user to turn an
10
21
  * option on or off.
11
22
  *
12
- * @prop {boolean} checked -- Whether this item is checked
13
- * @prop {boolean} disabled -- Whether this item is disabled
14
23
  */
15
- export default function MenuCheck() {
24
+ export default function MenuCheck($props: MenuCheckProps) {
25
+ $props ??= $watch({});
26
+
16
27
  let $state = $watch({
17
28
  checked: $props.checked
18
29
  });
@@ -1,9 +1,19 @@
1
+
2
+ interface MenuGroupProps {
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 group to screen readers */
8
+ ariaLabel?: string,
9
+ }
10
+
1
11
  /**
2
12
  * A container for a logical group of menu items.
3
- *
4
- * @prop {string} ariaLabel -- An ARIA label for describing the group to screen readers
5
13
  */
6
- export default function MenuGroup() {
14
+ export default function MenuGroup($props: MenuGroupProps) {
15
+ $props ??= $watch({});
16
+
7
17
  // TODO: Intercept the context to steal toggleItem??
8
18
 
9
19
  @render {
@@ -1,12 +1,21 @@
1
1
  import { MenuButtonContextName, type MenuButtonContext } from "./MenuTypes";
2
2
 
3
+ interface MenuIndicatorProps {
4
+ /** An ID for the root element */
5
+ id?: string;
6
+ /** Class name(s) for the root element */
7
+ class?: string,
8
+ /** Whether this item is disabled */
9
+ disabled?: boolean,
10
+ }
11
+
3
12
  /**
4
13
  * An indicator for a MenuCheck or MenuRadio component, which is displayed
5
14
  * when the value of checked is true.
6
- *
7
- * @prop {boolean} disabled -- Whether this item is disabled
8
15
  */
9
- export default function MenuIndicator() {
16
+ export default function MenuIndicator($props: MenuIndicatorProps) {
17
+ $props ??= $watch({});
18
+
10
19
  // Get stuff out of the MenuButtonContext
11
20
  const context = $context[MenuButtonContextName] as MenuButtonContext;
12
21
  if (!context) {
@@ -1,5 +1,20 @@
1
1
  import { MenuPopoutContextName, type MenuPopoutContext } from "./MenuTypes";
2
2
 
3
+ interface MenuPopoutProps {
4
+ /** An ID for the root element */
5
+ id?: string;
6
+ /** Class name(s) for the root element */
7
+ class?: string,
8
+ /** Whether the popout is visible */
9
+ visible?: boolean,
10
+ /** Called when the popout is opened or closed */
11
+ ontoggle?: (open: boolean) => void,
12
+ /** Called when the popout has opened */
13
+ onopen?: () => void,
14
+ /** Called when the popout has closed */
15
+ onclose?: () => void,
16
+ }
17
+
3
18
  /**
4
19
  * A popout that is attached to a menu button and can be used to show a submenu.
5
20
  *
@@ -11,13 +26,9 @@ import { MenuPopoutContextName, type MenuPopoutContext } from "./MenuTypes";
11
26
  * <MenuPopoutContent />
12
27
  * </MenuPopout>
13
28
  * ```
14
- *
15
- * @prop {boolean} visible -- Whether the popout is visible
16
- * @prop {(boolean) => void} ontoggle -- Called when the popout is opened or closed
17
- * @prop {() => void} onopen -- Called when the popout has opened
18
- * @prop {() => void} onclose -- Called when the popout has closed
19
29
  */
20
- export default function MenuPopout($props) {
30
+ export default function MenuPopout($props: MenuPopoutProps) {
31
+ $props ??= $watch({});
21
32
  $props.visible ??= false;
22
33
 
23
34
  let $state = $watch({
@@ -2,13 +2,22 @@
2
2
  import setPopoverPosition from "../utils/setPopoverPosition";
3
3
  import { MenuPopoutContextName, type MenuPopoutContext } from "./MenuTypes";
4
4
 
5
+ interface MenuPopoutContentProps {
6
+ /** An ID for the root element */
7
+ id?: string;
8
+ /** Class name(s) for the root element */
9
+ class?: string,
10
+ /** Where the popout will be shown, relative to the popout button */
11
+ side?: "top" | "right" | "bottom" | "left",
12
+ /** How the popout will be aligned, relative to the popout button */
13
+ alignment?: "start" | "center" | "end",
14
+ }
15
+
5
16
  /**
6
17
  * The content that is displayed for a MenuPopout when it is open.
7
- *
8
- * @prop {"top" | "right" | "bottom" | "left"} side -- Where the popout will be shown, relative to the popout button
9
- * @prop {"start" | "center" | "end"} alignment -- How the popout will be aligned, relative to the popout button
10
18
  */
11
- export default function MenuPopoutContent() {
19
+ export default function MenuPopoutContent($props: MenuPopoutContentProps) {
20
+ $props ??= $watch({});
12
21
  $props.side ??= "right";
13
22
  $props.alignment ??= "start";
14
23
 
@@ -5,13 +5,22 @@ import {
5
5
  type MenuPopoutContext
6
6
  } from "./MenuTypes";
7
7
 
8
+ interface MenuPopoutTriggerProps {
9
+ /** An ID for the root element */
10
+ id?: string;
11
+ /** Class name(s) for the root element */
12
+ class?: string,
13
+ /** The delay before showing the popout, in milliseconds */
14
+ hoverDelay?: number,
15
+ /** Whether this button is disabled */
16
+ disabled?: boolean,
17
+ }
18
+
8
19
  /**
9
20
  * A button that is placed in a Menu or MenuGroup and signals a response by a user.
10
- *
11
- * @prop {number} hoverDelay -- The delay before showing the popout, in milliseconds
12
- * @prop {boolean} disabled -- Whether this button is disabled
13
21
  */
14
- export default function MenuPopoutTrigger() {
22
+ export default function MenuPopoutTrigger($props: MenuPopoutTriggerProps) {
23
+ $props ??= $watch({});
15
24
  $props.hoverDelay ??= 500;
16
25
  $props.disabled ??= false;
17
26
 
@@ -7,15 +7,26 @@ import {
7
7
  type MenuRadioGroupContext
8
8
  } from "./MenuTypes";
9
9
 
10
+ interface MenuRadioProps {
11
+ /** An ID for the root element */
12
+ id?: string;
13
+ /** Class name(s) for the root element */
14
+ class?: string,
15
+ /** The value of the item */
16
+ value?: string,
17
+ /** Whether this item is checked */
18
+ checked?: boolean,
19
+ /** Whether this item is disabled */
20
+ disabled?: boolean,
21
+ }
22
+
10
23
  /**
11
24
  * A button that is placed in a Menu or MenuGroup to allow the user to select
12
25
  * from a number of options.
13
- *
14
- * @prop {string} value -- The value of the item
15
- * @prop {boolean} checked -- Whether this item is checked
16
- * @prop {boolean} disabled -- Whether this item is disabled
17
26
  */
18
- export default function MenuRadio() {
27
+ export default function MenuRadio($props: MenuRadioProps) {
28
+ $props ??= $watch({});
29
+
19
30
  let $state = $watch({
20
31
  checked: $props.checked,
21
32
  });
@@ -4,14 +4,25 @@ import {
4
4
  type RadioGroupItemState
5
5
  } from "./MenuTypes";
6
6
 
7
+ interface MenuRadioGroupProps {
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 menu to screen readers */
13
+ ariaLabel?: string,
14
+ /** The value of the checked MenuRadio */
15
+ value?: string | undefined,
16
+ /** Called when the checked item has changed */
17
+ onchange?: (value: any) => void,
18
+ }
19
+
7
20
  /**
8
21
  * A container for a logical group of menu RadioGroup items.
9
- *
10
- * @prop {string} ariaLabel -- An ARIA label for describing the menu to screen readers
11
- * @prop {string | undefined} value -- The value of the checked MenuRadio
12
- * @prop {(any) => void} onchange - Called when the checked item has changed
13
22
  */
14
- export default function MenuRadioGroup() {
23
+ export default function MenuRadioGroup($props: MenuRadioGroupProps) {
24
+ $props ??= $watch({});
25
+
15
26
  // A collection containing the state and some functions for each item
16
27
  let itemStates: RadioGroupItemState[] = [];
17
28
 
@@ -1,7 +1,17 @@
1
+
2
+ interface MenuSeparatorProps {
3
+ /** An ID for the root element */
4
+ id?: string;
5
+ /** Class name(s) for the root element */
6
+ class?: string,
7
+ }
8
+
1
9
  /**
2
10
  * An element in a menu that separates logical sets of menu items.
3
11
  */
4
- export default function MenuSeparator() {
12
+ export default function MenuSeparator($props: MenuSeparatorProps) {
13
+ $props ??= $watch({});
14
+
5
15
  @render {
6
16
  <div
7
17
  {$props.id}
@@ -1,5 +1,16 @@
1
1
  import { MenuBarContextName, type MenuBarContext, type ItemState } from "./MenuBarTypes";
2
2
 
3
+ interface MenuBarProps {
4
+ /** An ID for the root element */
5
+ id?: string;
6
+ /** Class name(s) for the root element */
7
+ class?: string,
8
+ /** An ARIA label for describing the menu to screen readers */
9
+ ariaLabel?: string,
10
+ /** The orientation of the menu, which affects keyboard navigation */
11
+ orientation?: "horizontal" | "vertical",
12
+ }
13
+
3
14
  /**
4
15
  * A menu bar, similar to that shown at the top of Windows applications or at the top of the screen on Macs.
5
16
  *
@@ -17,11 +28,9 @@ import { MenuBarContextName, type MenuBarContext, type ItemState } from "./MenuB
17
28
  * </MenuBarItem>
18
29
  * </MenuBar>
19
30
  * ```
20
- *
21
- * @prop {string} ariaLabel -- An ARIA label for describing the menu to screen readers
22
- * @prop {"horizontal" | "vertical"} orientation -- The orientation of the menu, which affects keyboard navigation
23
31
  */
24
- export default function MenuBar() {
32
+ export default function MenuBar($props: MenuBarProps) {
33
+ $props ??= $watch({});
25
34
  $props.orientation ??= "horizontal";
26
35
 
27
36
  let $state = $watch({
@@ -6,6 +6,21 @@ import {
6
6
  } from "./MenuBarTypes";
7
7
  import { PopoverContextName, type PopoverContext } from "../Popover/PopoverTypes";
8
8
 
9
+ interface MenuBarItemProps {
10
+ /** An ID for the root element */
11
+ id?: string;
12
+ /** Class name(s) for the root element */
13
+ class?: string,
14
+ /** Whether the item is visible */
15
+ visible?: boolean,
16
+ /** Called when the item is opened or closed */
17
+ ontoggle?: (visible: boolean) => void,
18
+ /** Called when the item has opened */
19
+ onopen?: () => void,
20
+ /** Called when the item has closed */
21
+ onclose?: () => void,
22
+ }
23
+
9
24
  /**
10
25
  * A popout that is attached to a menubar button and can be used to show a submenu.
11
26
  *
@@ -17,13 +32,9 @@ import { PopoverContextName, type PopoverContext } from "../Popover/PopoverTypes
17
32
  * <MenuBarItemContent />
18
33
  * </MenuBarItem>
19
34
  * ```
20
- *
21
- * @prop {boolean} visible -- Whether the item is visible
22
- * @prop {(boolean) => void} ontoggle -- Called when the item is opened or closed
23
- * @prop {() => void} onopen -- Called when the item has opened
24
- * @prop {() => void} onclose -- Called when the item has closed
25
35
  */
26
- export default function MenuBarItem() {
36
+ export default function MenuBarItem($props: MenuBarItemProps) {
37
+ $props ??= $watch({});
27
38
  $props.visible ??= false;
28
39
 
29
40
  let $state = $watch({
@@ -7,13 +7,22 @@ import {
7
7
  type MenuBarItemContext
8
8
  } from "./MenuBarTypes";
9
9
 
10
+ interface MenuBarItemContentProps {
11
+ /** An ID for the root element */
12
+ id?: string;
13
+ /** Class name(s) for the root element */
14
+ class?: string,
15
+ /** Where the popout will be shown, relative to the popout button */
16
+ side?: "top" | "right" | "bottom" | "left",
17
+ /** How the popout will be aligned, relative to the popout button */
18
+ alignment?: "start" | "center" | "end",
19
+ }
20
+
10
21
  /**
11
22
  * The content that is displayed for a MenuBarItem when it is open.
12
- *
13
- * @prop {"top" | "right" | "bottom" | "left"} side -- Where the popout will be shown, relative to the popout button
14
- * @prop {"start" | "center" | "end"} alignment -- How the popout will be aligned, relative to the popout button
15
23
  */
16
- export default function MenuBarItemContent() {
24
+ export default function MenuBarItemContent($props: MenuBarItemContentProps) {
25
+ $props ??= $watch({});
17
26
  $props.side ??= "bottom";
18
27
  $props.alignment ??= "start";
19
28
 
@@ -5,12 +5,21 @@ import {
5
5
  type MenuBarItemContext
6
6
  } from "./MenuBarTypes";
7
7
 
8
+ interface MenuBarItemTriggerProps {
9
+ /** An ID for the root element */
10
+ id?: string;
11
+ /** Class name(s) for the root element */
12
+ class?: string,
13
+ /** Whether this button is disabled */
14
+ disabled?: boolean,
15
+ }
16
+
8
17
  /**
9
18
  * A button that is placed in a MenuBar and opens a submenu.
10
19
  *
11
- * @prop {boolean} disabled -- Whether this button is disabled
12
20
  */
13
- export default function MenuBarItemTrigger() {
21
+ export default function MenuBarItemTrigger($props: MenuBarItemTriggerProps) {
22
+ $props ??= $watch({});
14
23
  $props.disabled ??= false;
15
24
 
16
25
  let button: HTMLButtonElement;