@torpor/ui 0.3.7 → 0.4.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 (87) hide show
  1. package/dist/Accordion/Accordion.torp +26 -25
  2. package/dist/Accordion/AccordionItem.torp +3 -3
  3. package/dist/Accordion/AccordionTypes.ts +5 -5
  4. package/dist/Accordion/index.d.ts +2 -2
  5. package/dist/Calendar/CalendarTypes.ts +1 -1
  6. package/dist/{Chart → Charts}/GridLines.torp +3 -0
  7. package/dist/{Chart → Charts}/XAxis.torp +7 -1
  8. package/dist/{Chart → Charts}/YAxis.torp +7 -1
  9. package/dist/{Chart → Charts}/index.js +8 -8
  10. package/dist/Contextual/Contextual.torp +8 -3
  11. package/dist/Contextual/ContextualTypes.ts +1 -1
  12. package/dist/Dialog/Dialog.torp +12 -16
  13. package/dist/Dialog/DialogButton.torp +3 -0
  14. package/dist/Dialog/DialogTypes.ts +2 -2
  15. package/dist/Dialog/index.d.ts +2 -0
  16. package/dist/Disclosure/Disclosure.torp +3 -3
  17. package/dist/Disclosure/DisclosureTypes.ts +1 -1
  18. package/dist/Drawer/Drawer.torp +2 -2
  19. package/dist/Drawer/DrawerTypes.ts +1 -1
  20. package/dist/Form/CheckBox.torp +1 -2
  21. package/dist/Form/Input.torp +1 -1
  22. package/dist/Form/MessageSummary.torp +38 -0
  23. package/dist/Form/index.d.ts +23 -1
  24. package/dist/Form/index.js +4 -0
  25. package/dist/ListBox/ListBox.torp +271 -0
  26. package/dist/ListBox/ListBoxItem.torp +107 -0
  27. package/dist/ListBox/ListBoxSeparator.torp +26 -0
  28. package/dist/ListBox/ListBoxTypes.ts +23 -0
  29. package/dist/ListBox/index.d.ts +97 -0
  30. package/dist/ListBox/index.js +14 -0
  31. package/dist/ListBox/index.js.map +1 -0
  32. package/dist/Menu/Menu.torp +19 -14
  33. package/dist/Menu/MenuTypes.ts +5 -4
  34. package/dist/MenuBar/MenuBarItem.torp +5 -8
  35. package/dist/MenuBar/MenuBarTypes.ts +2 -2
  36. package/dist/Modal/Modal.torp +7 -2
  37. package/dist/Modal/ModalTypes.ts +1 -1
  38. package/dist/NavMenu/NavMenu.torp +7 -0
  39. package/dist/NavMenu/NavMenuButton.torp +5 -2
  40. package/dist/NavMenu/NavMenuPopout.torp +1 -1
  41. package/dist/NavMenu/{NavMenuPopoutButton.torp → NavMenuPopoutTrigger.torp} +4 -4
  42. package/dist/NavMenu/NavMenuSeparator.torp +2 -1
  43. package/dist/NavMenu/NavMenuTypes.ts +4 -3
  44. package/dist/NavMenu/index.d.ts +22 -18
  45. package/dist/NavMenu/index.js +4 -4
  46. package/dist/Pagination/Pagination.torp +145 -0
  47. package/dist/Pagination/PaginationItem.torp +100 -0
  48. package/dist/Pagination/PaginationTypes.ts +25 -0
  49. package/dist/Pagination/buildPages.ts +57 -0
  50. package/dist/Pagination/index.d.ts +53 -0
  51. package/dist/Pagination/index.js +40 -0
  52. package/dist/Pagination/index.js.map +1 -0
  53. package/dist/Popover/Popover.torp +8 -3
  54. package/dist/Popover/PopoverTypes.ts +1 -1
  55. package/dist/SelectBox/SelectBox.torp +136 -0
  56. package/dist/SelectBox/SelectBoxContent.torp +81 -0
  57. package/dist/SelectBox/SelectBoxInput.torp +95 -0
  58. package/dist/SelectBox/SelectBoxTrigger.torp +41 -0
  59. package/dist/SelectBox/SelectBoxTypes.ts +18 -0
  60. package/dist/SelectBox/index.d.ts +127 -0
  61. package/dist/SelectBox/index.js +18 -0
  62. package/dist/SelectBox/index.js.map +1 -0
  63. package/dist/TabGroup/TabGroup.torp +3 -3
  64. package/dist/TabGroup/TabGroupTypes.ts +2 -2
  65. package/dist/ToolBar/ToolBar.torp +198 -0
  66. package/dist/ToolBar/ToolBarButton.torp +57 -0
  67. package/dist/ToolBar/ToolBarElement.torp +55 -0
  68. package/dist/ToolBar/ToolBarPopout.torp +97 -0
  69. package/dist/ToolBar/ToolBarPopoutContent.torp +92 -0
  70. package/dist/ToolBar/ToolBarPopoutTrigger.torp +138 -0
  71. package/dist/ToolBar/ToolBarSeparator.torp +25 -0
  72. package/dist/ToolBar/ToolBarTypes.ts +35 -0
  73. package/dist/ToolBar/index.d.ts +212 -0
  74. package/dist/ToolBar/index.js +30 -0
  75. package/dist/ToolBar/index.js.map +1 -0
  76. package/dist/metafile-esm.json +1 -1
  77. package/dist/utils/PopoutTypes.ts +35 -0
  78. package/dist/utils/chartUtils.ts +1 -1
  79. package/package.json +22 -6
  80. /package/dist/{Chart → Charts}/BarChart.torp +0 -0
  81. /package/dist/{Chart → Charts}/DataSeries.ts +0 -0
  82. /package/dist/{Chart → Charts}/LineChart.torp +0 -0
  83. /package/dist/{Chart → Charts}/PieChart.torp +0 -0
  84. /package/dist/{Chart → Charts}/ScatterChart.torp +0 -0
  85. /package/dist/{Chart → Charts}/SparkLine.torp +0 -0
  86. /package/dist/{Chart → Charts}/index.d.ts +0 -0
  87. /package/dist/{Chart → Charts}/index.js.map +0 -0
@@ -11,11 +11,11 @@ interface AccordionProps {
11
11
  /** Whether a single AccordionItem or multiple AccordionItems can be expanded at the same time */
12
12
  type?: "single" | "multiple",
13
13
  /** The value of the expanded AccordionItem, or an array of values if the type is "multiple" */
14
- value?: string | string[],
14
+ value?: any | any[],
15
15
  /** If set to true, the user cannot interact with any items in the Accordion */
16
16
  disabled?: boolean,
17
17
  /** Raised when the expanded item(s) have changed */
18
- onchange?: (value: string | string[]) => void,
18
+ onchange?: (value: any | any[]) => void,
19
19
  }
20
20
 
21
21
  /**
@@ -41,9 +41,15 @@ export default function Accordion($props: AccordionProps | undefined) {
41
41
  let type = $props?.type ?? "single";
42
42
 
43
43
  let $state = $watch({
44
- value: $props?.value ?? (type === "single" ? "" : [] as string[])
44
+ value: $props?.value ?? (type === "single" ? undefined : [])
45
45
  });
46
46
 
47
+ // Update $state on $props change
48
+ $run(() => {
49
+ $state.value = $props?.value ?? (type === "single" ? undefined : [])
50
+ });
51
+
52
+ // Update $props on $state change
47
53
  $run(() => {
48
54
  if ($props !== undefined) {
49
55
  $props.value = $state.value;
@@ -65,48 +71,43 @@ export default function Accordion($props: AccordionProps | undefined) {
65
71
  $context[AccordionContextName] = context;
66
72
 
67
73
  $run(() => {
68
- // HACK: This should probably be done with setters?
69
- let newValue = $state.value;
74
+ // Get the value to ensure that this effect will be subscribed
75
+ let value = $state.value;
70
76
 
71
- // Get the value
77
+ // And set the expanded item(s)
72
78
  switch (type) {
73
79
  case "single": {
74
- // Ensure the value passed in was a string (in case e.g. the user has set values to ints)
75
- newValue = newValue.toString();
76
80
  for (let item of itemStates) {
77
- item.expanded = item.value === newValue;
81
+ item.expanded = item.value === value;
78
82
  }
79
83
  break;
80
84
  }
81
85
  case "multiple": {
82
- // Ensure the value passed in is an array
83
- if (!Array.isArray(newValue)) {
84
- newValue = [newValue];
86
+ if (!Array.isArray(value)) {
87
+ value = [value];
85
88
  }
86
89
  for (let item of itemStates) {
87
- item.expanded = newValue.indexOf(item.value) !== -1;
90
+ item.expanded = value.indexOf(item.value) !== -1;
88
91
  }
89
92
  break;
90
93
  }
91
94
  }
92
-
93
- // Set the value
94
- $state.value = newValue;
95
95
  })
96
96
 
97
97
  $run(() => {
98
- itemStates.forEach((s) => s.parentDisabled = $props?.disabled === true);
98
+ let disabled = $props?.disabled;
99
+ itemStates.forEach((s) => s.parentDisabled = disabled === true);
99
100
  });
100
101
 
101
102
  // Dispatch the change event when the value changes
102
103
  let firstChange = true;
103
104
  $run(() => {
104
- const ev = $props?.onchange;
105
+ const onchange = $props?.onchange;
105
106
  const value = $state.value;
106
107
  if (firstChange) {
107
108
  firstChange = false;
108
- } else if (ev) {
109
- ev(value);
109
+ } else if (onchange) {
110
+ onchange(value);
110
111
  }
111
112
  });
112
113
 
@@ -118,11 +119,11 @@ export default function Accordion($props: AccordionProps | undefined) {
118
119
 
119
120
  // If a value wasn't set for the item, set it to the index
120
121
  if (!itemState.value) {
121
- itemState.value = itemState.index.toString();
122
+ itemState.value = itemState.index;
122
123
  }
123
124
 
124
125
  // If we have a value, set whether the item should be expanded
125
- if ($state.value) {
126
+ if ($state.value !== undefined && $state.value !== null) {
126
127
  switch (type) {
127
128
  case "single": {
128
129
  itemState.expanded = $state.value === itemState.value;
@@ -166,7 +167,7 @@ export default function Accordion($props: AccordionProps | undefined) {
166
167
  break;
167
168
  }
168
169
  case "multiple": {
169
- let newValue = [];
170
+ let value = [];
170
171
  for (let item of itemStates) {
171
172
  // The item is expanded if it has the supplied value (i.e. if it was clicked) or if it
172
173
  // was already expanded
@@ -174,10 +175,10 @@ export default function Accordion($props: AccordionProps | undefined) {
174
175
  (item.value === toggleValue && !item.expanded) ||
175
176
  (item.value !== toggleValue && item.expanded)
176
177
  ) {
177
- newValue.push(item.value);
178
+ value.push(item.value);
178
179
  }
179
180
  }
180
- $state.value = newValue.sort();
181
+ $state.value = value.sort();
181
182
  break;
182
183
  }
183
184
  }
@@ -71,12 +71,12 @@ export default function AccordionItem($props: AccordionItemProps | undefined) {
71
71
  // Dispatch the toggle event when the value of expanded changes
72
72
  let firstToggle = true;
73
73
  $run(() => {
74
- const ev = $props?.ontoggle;
74
+ const ontoggle = $props?.ontoggle;
75
75
  const expanded = $state.expanded;
76
76
  if (firstToggle) {
77
77
  firstToggle = false;
78
- } else if (ev) {
79
- ev(expanded);
78
+ } else if (ontoggle) {
79
+ ontoggle(expanded);
80
80
  }
81
81
  });
82
82
 
@@ -1,5 +1,5 @@
1
- export const AccordionContextName = "Accordion";
2
- export const AccordionItemContextName = "AccordionItem";
1
+ export const AccordionContextName: unique symbol = Symbol.for("torp.Accordion");
2
+ export const AccordionItemContextName: unique symbol = Symbol.for("torp.AccordionItem");
3
3
 
4
4
  export interface AccordionContext {
5
5
  /** Called from an AccordionItem when it is added */
@@ -7,14 +7,14 @@ export interface AccordionContext {
7
7
  /** Called from an AccordionItem when it is removed */
8
8
  removeItem: (index: number) => void;
9
9
  /** Called from an AccordionItem when it is toggled */
10
- toggleItem: (value: string) => void;
10
+ toggleItem: (value: any) => void;
11
11
  /** Called from an AccordionHeader when it receives a keyboard event */
12
12
  handleHeaderKey: (index: number, e: KeyboardEvent) => void;
13
13
  }
14
14
 
15
15
  export interface AccordionItemContext {
16
16
  /** Raised when an AccordionItem is toggled */
17
- toggleItem: (value: string) => void;
17
+ toggleItem: (value: any) => void;
18
18
  /** Raised when an AccordionHeader receives a keyboard event */
19
19
  handleHeaderKey: (index: number, e: KeyboardEvent) => void;
20
20
  /** The reactive state for an AccordionItem */
@@ -25,7 +25,7 @@ export interface AccordionItemContext {
25
25
 
26
26
  export interface ItemState {
27
27
  index: number;
28
- value: string;
28
+ value: any;
29
29
  expanded: boolean;
30
30
  headerId: string;
31
31
  contentId: string;
@@ -11,11 +11,11 @@ interface AccordionProps {
11
11
  /** Whether a single AccordionItem or multiple AccordionItems can be expanded at the same time */
12
12
  type?: "single" | "multiple",
13
13
  /** The value of the expanded AccordionItem, or an array of values if the type is "multiple" */
14
- value?: string | string[],
14
+ value?: any | any[],
15
15
  /** If set to true, the user cannot interact with any items in the Accordion */
16
16
  disabled?: boolean,
17
17
  /** Raised when the expanded item(s) have changed */
18
- onchange?: (value: string | string[]) => void,
18
+ onchange?: (value: any | any[]) => void,
19
19
  }
20
20
 
21
21
  /**
@@ -1,4 +1,4 @@
1
- export const CalendarContextName = "Calendar";
1
+ export const CalendarContextName: unique symbol = Symbol.for("torp.Calendar");
2
2
 
3
3
  export interface CalendarContext {
4
4
  // The registerDay function is called from each CalendarDay to register itself with this
@@ -32,6 +32,7 @@ export default function GridLines($props: GridLinesProps) {
32
32
  y1={$props.chartBottom - i * $props.yStepValue * $props.valueHeight}
33
33
  x2={$props.width ?? 0}
34
34
  y2={$props.chartBottom - i * $props.yStepValue * $props.valueHeight}
35
+ stroke="currentcolor"
35
36
  />
36
37
  }
37
38
  }
@@ -44,6 +45,7 @@ export default function GridLines($props: GridLinesProps) {
44
45
  y1={$props.chartBottom}
45
46
  x2={$props.chartLeft + i * $props.xStepValue * $props.itemWidth}
46
47
  y2={0}
48
+ stroke="currentcolor"
47
49
  />
48
50
  }
49
51
  } else {
@@ -53,6 +55,7 @@ export default function GridLines($props: GridLinesProps) {
53
55
  y1={$props.chartBottom}
54
56
  x2={$props.chartLeft + i * $props.itemWidth + ($props.type === "bar" ? 0 : $props.itemWidth / 2)}
55
57
  y2={0}
58
+ stroke="currentcolor"
56
59
  />
57
60
  }
58
61
  }
@@ -20,7 +20,13 @@ export default function XAxis($props: XAxisProps) {
20
20
  @render {
21
21
  <svg>
22
22
  @if ($props.showAxis) {
23
- <line x1={$props.chartLeft} y1={$props.chartBottom} x2={$props.width} y2={$props.chartBottom} />
23
+ <line
24
+ x1={$props.chartLeft}
25
+ y1={$props.chartBottom}
26
+ x2={$props.width}
27
+ y2={$props.chartBottom}
28
+ stroke="currentcolor"
29
+ />
24
30
  }
25
31
  @if ($props.xLabel) {
26
32
  <text
@@ -13,7 +13,13 @@ export default function YAxis($props: YAxisProps) {
13
13
  @render {
14
14
  <svg>
15
15
  @if ($props.showAxis) {
16
- <line x1={$props.chartLeft} y1={$props.chartBottom} x2={$props.chartLeft} y2={0} />
16
+ <line
17
+ x1={$props.chartLeft}
18
+ y1={$props.chartBottom}
19
+ x2={$props.chartLeft}
20
+ y2={0}
21
+ stroke="currentcolor"
22
+ />
17
23
  }
18
24
  @if ($props.yLabel) {
19
25
  <text
@@ -1,25 +1,25 @@
1
- // src/Chart/BarChart.torp
1
+ // src/Charts/BarChart.torp
2
2
  import BarChart_default from "./BarChart.torp";
3
3
 
4
- // src/Chart/GridLines.torp
4
+ // src/Charts/GridLines.torp
5
5
  import GridLines_default from "./GridLines.torp";
6
6
 
7
- // src/Chart/LineChart.torp
7
+ // src/Charts/LineChart.torp
8
8
  import LineChart_default from "./LineChart.torp";
9
9
 
10
- // src/Chart/PieChart.torp
10
+ // src/Charts/PieChart.torp
11
11
  import PieChart_default from "./PieChart.torp";
12
12
 
13
- // src/Chart/ScatterChart.torp
13
+ // src/Charts/ScatterChart.torp
14
14
  import ScatterChart_default from "./ScatterChart.torp";
15
15
 
16
- // src/Chart/SparkLine.torp
16
+ // src/Charts/SparkLine.torp
17
17
  import SparkLine_default from "./SparkLine.torp";
18
18
 
19
- // src/Chart/XAxis.torp
19
+ // src/Charts/XAxis.torp
20
20
  import XAxis_default from "./XAxis.torp";
21
21
 
22
- // src/Chart/YAxis.torp
22
+ // src/Charts/YAxis.torp
23
23
  import YAxis_default from "./YAxis.torp";
24
24
  export {
25
25
  BarChart_default as BarChart,
@@ -1,5 +1,6 @@
1
1
  import type { ClassValue, StyleValue } from "@torpor/view";
2
2
  import { ContextualContextName, type Point, type ContextualContext, type ContextualState } from "./ContextualTypes";
3
+ import { PopoutContextName, type PopoutContext } from "../utils/PopoutTypes";
3
4
 
4
5
  interface ContextualProps {
5
6
  /** An ID for the root element */
@@ -62,11 +63,15 @@ export default function Contextual($props: ContextualProps | undefined) {
62
63
  handleButton,
63
64
  handleClickOutside,
64
65
  state: $state,
65
- modal: $props?.modal,
66
+ //modal: $props?.modal,
66
67
  anchorElement: $props?.anchor ? $unwrap($props.anchor) : undefined,
67
68
  };
68
69
  $context[ContextualContextName] = context;
69
70
 
71
+ // Set the context to pass down to items
72
+ let popoutContext: PopoutContext = context;
73
+ $context[PopoutContextName] = popoutContext;
74
+
70
75
  // Dispatch the toggle event when the contextual is opened or closed
71
76
  let firstToggle = true;
72
77
  $run(() => {
@@ -90,11 +95,11 @@ export default function Contextual($props: ContextualProps | undefined) {
90
95
  // Get the button's result
91
96
  switch (type) {
92
97
  case "confirm": {
93
- result = value || true;
98
+ result = value ?? true;
94
99
  break;
95
100
  }
96
101
  case "cancel": {
97
- result = value || false;
102
+ result = value ?? false;
98
103
  break;
99
104
  }
100
105
  default: {
@@ -1,4 +1,4 @@
1
- export const ContextualContextName = "Contextual";
1
+ export const ContextualContextName: unique symbol = Symbol.for("torp.Contextual");
2
2
 
3
3
  /** The shared context for popover components (Contextual, Prompt and Contextual) */
4
4
  export interface ContextualContext {
@@ -1,9 +1,8 @@
1
1
  import type { ClassValue, StyleValue } from "@torpor/view";
2
2
  import getId from "../utils/getId";
3
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";
4
+ import { PopoutContextName, type PopoutContext, type HandleButtonPress } from "../utils/PopoutTypes";
5
+ import { DialogContextName, type DialogContext, type DialogState } from "./DialogTypes";
7
6
 
8
7
  interface DialogProps {
9
8
  /** An ID for the root element */
@@ -48,20 +47,18 @@ export default function Dialog($props: DialogProps | undefined) {
48
47
  focusableElements: []
49
48
  };
50
49
 
51
- // Maybe get stuff out of a Modal context
50
+ // Maybe get stuff out of a popout context
52
51
  let modal = false;
53
- let visible = true;
54
52
  let handleButton: HandleButtonPress | undefined = undefined;
55
- const modalContext = $context[ModalContextName] ?? $context[PopoverContextName] as ModalContext;
56
- if (modalContext) {
53
+ const popoutContext = $context[PopoutContextName] as PopoutContext;
54
+ if (popoutContext) {
57
55
  modal = true;
58
- visible = modalContext.state.visible;
59
- handleButton = modalContext.handleButton;
56
+ handleButton = popoutContext.handleButton;
60
57
 
61
- modalContext.handleClickOutside = handleClickOutside;
62
- // Set the focusFirstElement method in the ModalContext so that it can be
58
+ popoutContext.handleClickOutside = handleClickOutside;
59
+ // Set the focusFirstElement method in the PopoutContext so that it can be
63
60
  // called after everything has been shown
64
- modalContext.focusFirstElement = focusFirstElement;
61
+ popoutContext.focusFirstElement = focusFirstElement;
65
62
  }
66
63
 
67
64
  // Set the IDs for using in the Dialog's ARIA attributes
@@ -69,14 +66,13 @@ export default function Dialog($props: DialogProps | undefined) {
69
66
  dialogId: $props?.id ?? defaultId,
70
67
  headerId: "",
71
68
  bodyId: "",
72
- visible
73
- })
69
+ });
74
70
 
75
71
  // Set the context to pass down to items
76
72
  let context: DialogContext = {
77
73
  handleButton,
78
74
  state: $state,
79
- anchorElement: modalContext ? modalContext.anchorElement : undefined
75
+ anchorElement: popoutContext ? popoutContext.anchorElement : undefined
80
76
  };
81
77
  $context[DialogContextName] = context;
82
78
 
@@ -91,7 +87,7 @@ export default function Dialog($props: DialogProps | undefined) {
91
87
  // the Esc key
92
88
  e.preventDefault();
93
89
  if (!modal) {
94
- modalContext.state.visible = false;
90
+ popoutContext.state.visible = false;
95
91
  }
96
92
  }
97
93
 
@@ -16,6 +16,8 @@ interface DialogButtonProps {
16
16
  disabled?: boolean,
17
17
  /** Raised when the button is clicked */
18
18
  onclick?: (e: MouseEvent) => void,
19
+ /** Raised when a key is pressed down */
20
+ onkeydown?: (e: KeyboardEvent) => void,
19
21
  }
20
22
 
21
23
  /**
@@ -58,6 +60,7 @@ export default function DialogButton($props: DialogButtonProps | undefined) {
58
60
  {$props?.style}
59
61
  disabled={$props?.disabled}
60
62
  onclick={handleClick}
63
+ {$props?.onkeydown}
61
64
  &ref={button}
62
65
  >
63
66
  <slot />
@@ -1,6 +1,6 @@
1
- export const DialogContextName = "Dialog";
1
+ import { type HandleButtonPress } from "../utils/PopoutTypes";
2
2
 
3
- export type HandleButtonPress = (type: "confirm" | "cancel" | undefined, value?: any) => void;
3
+ export const DialogContextName: unique symbol = Symbol.for("torp.Dialog");
4
4
 
5
5
  export interface DialogContext {
6
6
  handleButton?: HandleButtonPress;
@@ -85,6 +85,8 @@ interface DialogButtonProps {
85
85
  disabled?: boolean,
86
86
  /** Raised when the button is clicked */
87
87
  onclick?: (e: MouseEvent) => void,
88
+ /** Raised when a key is pressed down */
89
+ onkeydown?: (e: KeyboardEvent) => void,
88
90
  }
89
91
 
90
92
  /**
@@ -59,12 +59,12 @@ export default function Disclosure($props: DisclosureProps | undefined) {
59
59
  // Dispatch the toggle event when the value of expanded changes
60
60
  let firstToggle = true;
61
61
  $run(() => {
62
- const ev = $props?.ontoggle;
62
+ const ontoggle = $props?.ontoggle;
63
63
  const expanded = $state.expanded;
64
64
  if (firstToggle) {
65
65
  firstToggle = false;
66
- } else if (ev) {
67
- ev(expanded);
66
+ } else if (ontoggle) {
67
+ ontoggle(expanded);
68
68
  }
69
69
  });
70
70
 
@@ -1,4 +1,4 @@
1
- export const DisclosureContextName = "Disclosure";
1
+ export const DisclosureContextName: unique symbol = Symbol.for("torp.Disclosure");
2
2
 
3
3
  export interface DisclosureContext {
4
4
  /** The reactive state for a Disclosure */
@@ -88,11 +88,11 @@ export default function Drawer($props: DrawerProps | undefined) {
88
88
  // Get the button's result
89
89
  switch (type) {
90
90
  case "confirm": {
91
- result = value || true;
91
+ result = value ?? true;
92
92
  break;
93
93
  }
94
94
  case "cancel": {
95
- result = value || false;
95
+ result = value ?? false;
96
96
  break;
97
97
  }
98
98
  default: {
@@ -1,4 +1,4 @@
1
- export const DrawerContextName = "Drawer";
1
+ export const DrawerContextName: unique symbol = Symbol.for("torp.Drawer");
2
2
 
3
3
  /** The shared context for drawer components (Contextual, Prompt and Drawer) */
4
4
  export interface DrawerContext {
@@ -79,8 +79,7 @@ export default function CheckBox($props: CheckBoxProps | undefined) {
79
79
  @render {
80
80
  <input
81
81
  id={$props?.id ?? defaultId}
82
- class={`torp-check-box
83
- ${$props?.class ?? ""}`.trim()}
82
+ class={["torp-check-box", $props?.class]}
84
83
  type="checkbox"
85
84
  {name}
86
85
  &checked={$state.value}
@@ -71,7 +71,7 @@ export default function Input($props: InputProps | undefined) {
71
71
  // NOTE: Adapted this from https://stackoverflow.com/a/57393751,
72
72
  // not sure if it's still a good way to do things
73
73
  function handleInput(e: Event & { currentTarget: EventTarget & HTMLInputElement }) {
74
- $state.value = $props!.type?.match(/^(number|range)$/) ? +e.currentTarget.value : e.currentTarget.value;
74
+ $state.value = $props?.type?.match(/^(number|range)$/) ? +e.currentTarget.value : e.currentTarget.value;
75
75
  if (formContext) {
76
76
  formContext.validate();
77
77
  }
@@ -0,0 +1,38 @@
1
+ import type { ClassValue, StyleValue } from "@torpor/view";
2
+ import { FormContextName, type FormContext } from "./FormTypes";
3
+
4
+ interface MessageSummaryProps {
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
+ }
12
+
13
+ /**
14
+ * Shows all validation messages for a form in a list.
15
+ */
16
+ export default function MessageSummary($props: MessageSummaryProps | undefined) {
17
+ // Get stuff out of the FormContext
18
+ const context = $context[FormContextName] as FormContext;
19
+ if (!context) {
20
+ throw new Error("MessageSummary must be contained within a Form");
21
+ }
22
+ const { state: $state } = context;
23
+
24
+ @render {
25
+ @if ($state.issues.length > 0) {
26
+ <ul
27
+ {$props?.id}
28
+ class={["torp-message-summary", $props?.class]}
29
+ {$props?.style}
30
+ >
31
+ <slot />
32
+ @for (let issue of $state.issues) {
33
+ <li>{issue.message}</li>
34
+ }
35
+ </ul>
36
+ }
37
+ }
38
+ }
@@ -245,6 +245,28 @@ declare function Message(
245
245
 
246
246
 
247
247
 
248
+ interface MessageSummaryProps {
249
+ /** An ID for the root element */
250
+ id?: string;
251
+ /** Classes for the root element */
252
+ class?: ClassValue,
253
+ /** Styles for the root element */
254
+ style?: StyleValue,
255
+ }
256
+
257
+ /**
258
+ * Shows all validation messages for a form in a list.
259
+ */
260
+ declare function MessageSummary(
261
+ $parent: ParentNode,
262
+ $anchor: Node | null,
263
+ $props: MessageSummaryProps | undefined,
264
+ $context?: Record<PropertyKey, any>,
265
+ $slots?: Record<string, SlotRender>,
266
+ ): void;
267
+
268
+
269
+
248
270
  interface OptionProps {
249
271
  /** An ID for the root element */
250
272
  id?: string;
@@ -345,4 +367,4 @@ declare function TextArea(
345
367
  $slots?: Record<string, SlotRender>,
346
368
  ): void;
347
369
 
348
- export { CheckBox, Field, File, Form, Hidden, Input, Label, Message, Option, Select, TextArea };
370
+ export { CheckBox, Field, File, Form, Hidden, Input, Label, Message, MessageSummary, Option, Select, TextArea };
@@ -22,6 +22,9 @@ import Label_default from "./Label.torp";
22
22
  // src/Form/Message.torp
23
23
  import Message_default from "./Message.torp";
24
24
 
25
+ // src/Form/MessageSummary.torp
26
+ import MessageSummary_default from "./MessageSummary.torp";
27
+
25
28
  // src/Form/Option.torp
26
29
  import Option_default from "./Option.torp";
27
30
 
@@ -39,6 +42,7 @@ export {
39
42
  Input_default as Input,
40
43
  Label_default as Label,
41
44
  Message_default as Message,
45
+ MessageSummary_default as MessageSummary,
42
46
  Option_default as Option,
43
47
  Select_default as Select,
44
48
  TextArea_default as TextArea