@proyecto-viviana/solidaria-components 0.2.9 → 0.3.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 (222) hide show
  1. package/README.md +39 -272
  2. package/dist/ActionBar.d.ts +21 -13
  3. package/dist/ActionBar.d.ts.map +1 -1
  4. package/dist/ActionGroup.d.ts +8 -8
  5. package/dist/ActionGroup.d.ts.map +1 -1
  6. package/dist/Alert.d.ts +5 -5
  7. package/dist/Alert.d.ts.map +1 -1
  8. package/dist/Autocomplete.d.ts +5 -5
  9. package/dist/Autocomplete.d.ts.map +1 -1
  10. package/dist/Breadcrumbs.d.ts +18 -7
  11. package/dist/Breadcrumbs.d.ts.map +1 -1
  12. package/dist/Button.d.ts +24 -5
  13. package/dist/Button.d.ts.map +1 -1
  14. package/dist/Calendar.d.ts +38 -7
  15. package/dist/Calendar.d.ts.map +1 -1
  16. package/dist/Checkbox.d.ts +32 -7
  17. package/dist/Checkbox.d.ts.map +1 -1
  18. package/dist/Collection.d.ts +19 -14
  19. package/dist/Collection.d.ts.map +1 -1
  20. package/dist/Color.d.ts +103 -14
  21. package/dist/Color.d.ts.map +1 -1
  22. package/dist/ColorEditor.d.ts +6 -6
  23. package/dist/ColorEditor.d.ts.map +1 -1
  24. package/dist/ComboBox.d.ts +85 -19
  25. package/dist/ComboBox.d.ts.map +1 -1
  26. package/dist/ContextualHelpTrigger.d.ts +2 -2
  27. package/dist/ContextualHelpTrigger.d.ts.map +1 -1
  28. package/dist/DateField.d.ts +8 -6
  29. package/dist/DateField.d.ts.map +1 -1
  30. package/dist/DatePicker.d.ts +53 -22
  31. package/dist/DatePicker.d.ts.map +1 -1
  32. package/dist/DateRangePickerContext.d.ts +30 -0
  33. package/dist/DateRangePickerContext.d.ts.map +1 -0
  34. package/dist/Dialog.d.ts +5 -5
  35. package/dist/Dialog.d.ts.map +1 -1
  36. package/dist/Disclosure.d.ts +23 -5
  37. package/dist/Disclosure.d.ts.map +1 -1
  38. package/dist/DragAndDrop.d.ts +6 -6
  39. package/dist/DragAndDrop.d.ts.map +1 -1
  40. package/dist/DragPreview.d.ts +2 -2
  41. package/dist/DragPreview.d.ts.map +1 -1
  42. package/dist/DropZone.d.ts +4 -4
  43. package/dist/DropZone.d.ts.map +1 -1
  44. package/dist/FieldError.d.ts +9 -5
  45. package/dist/FieldError.d.ts.map +1 -1
  46. package/dist/FileTrigger.d.ts +3 -3
  47. package/dist/FileTrigger.d.ts.map +1 -1
  48. package/dist/Focusable.d.ts +2 -2
  49. package/dist/Focusable.d.ts.map +1 -1
  50. package/dist/Form.d.ts +18 -4
  51. package/dist/Form.d.ts.map +1 -1
  52. package/dist/GridList.d.ts +32 -12
  53. package/dist/GridList.d.ts.map +1 -1
  54. package/dist/HiddenDateInput.d.ts +26 -0
  55. package/dist/HiddenDateInput.d.ts.map +1 -0
  56. package/dist/HiddenTimeInput.d.ts +25 -0
  57. package/dist/HiddenTimeInput.d.ts.map +1 -0
  58. package/dist/Icon.d.ts +5 -5
  59. package/dist/Icon.d.ts.map +1 -1
  60. package/dist/Keyboard.d.ts +1 -1
  61. package/dist/Landmark.d.ts +3 -3
  62. package/dist/Landmark.d.ts.map +1 -1
  63. package/dist/Link.d.ts +10 -4
  64. package/dist/Link.d.ts.map +1 -1
  65. package/dist/ListBox.d.ts +32 -12
  66. package/dist/ListBox.d.ts.map +1 -1
  67. package/dist/ListDropTargetDelegate.d.ts +6 -6
  68. package/dist/ListDropTargetDelegate.d.ts.map +1 -1
  69. package/dist/Menu.d.ts +65 -14
  70. package/dist/Menu.d.ts.map +1 -1
  71. package/dist/Meter.d.ts +3 -3
  72. package/dist/Meter.d.ts.map +1 -1
  73. package/dist/Modal.d.ts +5 -5
  74. package/dist/Modal.d.ts.map +1 -1
  75. package/dist/NumberField.d.ts +8 -12
  76. package/dist/NumberField.d.ts.map +1 -1
  77. package/dist/Popover.d.ts +28 -5
  78. package/dist/Popover.d.ts.map +1 -1
  79. package/dist/Pressable.d.ts +2 -2
  80. package/dist/Pressable.d.ts.map +1 -1
  81. package/dist/ProgressBar.d.ts +5 -3
  82. package/dist/ProgressBar.d.ts.map +1 -1
  83. package/dist/RadioGroup.d.ts +43 -9
  84. package/dist/RadioGroup.d.ts.map +1 -1
  85. package/dist/RangeCalendar.d.ts +34 -7
  86. package/dist/RangeCalendar.d.ts.map +1 -1
  87. package/dist/RouterProvider.d.ts +2 -2
  88. package/dist/RouterProvider.d.ts.map +1 -1
  89. package/dist/SearchField.d.ts +23 -20
  90. package/dist/SearchField.d.ts.map +1 -1
  91. package/dist/Select.d.ts +41 -11
  92. package/dist/Select.d.ts.map +1 -1
  93. package/dist/SelectionIndicator.d.ts +3 -3
  94. package/dist/SelectionIndicator.d.ts.map +1 -1
  95. package/dist/Separator.d.ts +9 -3
  96. package/dist/Separator.d.ts.map +1 -1
  97. package/dist/SharedElementTransition.d.ts +6 -4
  98. package/dist/SharedElementTransition.d.ts.map +1 -1
  99. package/dist/Slider.d.ts +12 -8
  100. package/dist/Slider.d.ts.map +1 -1
  101. package/dist/StepList.d.ts +90 -0
  102. package/dist/StepList.d.ts.map +1 -0
  103. package/dist/Switch.d.ts +11 -5
  104. package/dist/Switch.d.ts.map +1 -1
  105. package/dist/Table.d.ts +187 -23
  106. package/dist/Table.d.ts.map +1 -1
  107. package/dist/Tabs.d.ts +45 -9
  108. package/dist/Tabs.d.ts.map +1 -1
  109. package/dist/TagGroup.d.ts +12 -10
  110. package/dist/TagGroup.d.ts.map +1 -1
  111. package/dist/Text.d.ts +2 -2
  112. package/dist/TextField.d.ts +15 -11
  113. package/dist/TextField.d.ts.map +1 -1
  114. package/dist/TimeField.d.ts +6 -6
  115. package/dist/TimeField.d.ts.map +1 -1
  116. package/dist/Toast.d.ts +29 -14
  117. package/dist/Toast.d.ts.map +1 -1
  118. package/dist/ToggleButton.d.ts +11 -5
  119. package/dist/ToggleButton.d.ts.map +1 -1
  120. package/dist/ToggleButtonGroup.d.ts +7 -7
  121. package/dist/ToggleButtonGroup.d.ts.map +1 -1
  122. package/dist/Toolbar.d.ts +7 -3
  123. package/dist/Toolbar.d.ts.map +1 -1
  124. package/dist/Tooltip.d.ts +50 -8
  125. package/dist/Tooltip.d.ts.map +1 -1
  126. package/dist/Tree.d.ts +66 -17
  127. package/dist/Tree.d.ts.map +1 -1
  128. package/dist/Virtualizer.d.ts +12 -12
  129. package/dist/Virtualizer.d.ts.map +1 -1
  130. package/dist/VirtualizerLayouts.d.ts +2 -2
  131. package/dist/VirtualizerLayouts.d.ts.map +1 -1
  132. package/dist/VisuallyHidden.d.ts +1 -1
  133. package/dist/VisuallyHidden.d.ts.map +1 -1
  134. package/dist/contexts.d.ts +5 -1
  135. package/dist/contexts.d.ts.map +1 -1
  136. package/dist/index.d.ts +73 -71
  137. package/dist/index.d.ts.map +1 -1
  138. package/dist/index.js +23253 -18564
  139. package/dist/index.js.map +1 -1
  140. package/dist/index.jsx +18116 -0
  141. package/dist/index.jsx.map +1 -0
  142. package/dist/useDragAndDrop.d.ts +13 -13
  143. package/dist/useDragAndDrop.d.ts.map +1 -1
  144. package/dist/utils.d.ts +2 -2
  145. package/dist/utils.d.ts.map +1 -1
  146. package/dist/virtualizer/Layout.d.ts +1 -1
  147. package/dist/virtualizer/Layout.d.ts.map +1 -1
  148. package/package.json +31 -32
  149. package/src/ActionBar.tsx +75 -72
  150. package/src/ActionGroup.tsx +53 -61
  151. package/src/Alert.tsx +17 -42
  152. package/src/Autocomplete.tsx +39 -44
  153. package/src/Breadcrumbs.tsx +149 -80
  154. package/src/Button.tsx +267 -70
  155. package/src/Calendar.tsx +218 -138
  156. package/src/Checkbox.tsx +413 -121
  157. package/src/Collection.tsx +67 -58
  158. package/src/Color.tsx +803 -380
  159. package/src/ColorEditor.tsx +131 -149
  160. package/src/ComboBox.tsx +414 -249
  161. package/src/ContextualHelpTrigger.tsx +86 -74
  162. package/src/DateField.tsx +185 -91
  163. package/src/DatePicker.tsx +524 -213
  164. package/src/DateRangePickerContext.tsx +44 -0
  165. package/src/Dialog.tsx +156 -118
  166. package/src/Disclosure.tsx +127 -80
  167. package/src/DragAndDrop.tsx +60 -54
  168. package/src/DragPreview.tsx +13 -11
  169. package/src/DropZone.tsx +42 -22
  170. package/src/FieldError.tsx +45 -23
  171. package/src/FileTrigger.tsx +19 -19
  172. package/src/Focusable.tsx +21 -24
  173. package/src/Form.tsx +71 -16
  174. package/src/GridList.tsx +273 -197
  175. package/src/HiddenDateInput.tsx +153 -0
  176. package/src/HiddenTimeInput.tsx +133 -0
  177. package/src/Icon.tsx +22 -43
  178. package/src/Keyboard.tsx +3 -3
  179. package/src/Landmark.tsx +37 -63
  180. package/src/Link.tsx +125 -75
  181. package/src/ListBox.tsx +332 -233
  182. package/src/ListDropTargetDelegate.ts +81 -80
  183. package/src/Menu.tsx +1023 -274
  184. package/src/Meter.tsx +38 -56
  185. package/src/Modal.tsx +251 -176
  186. package/src/NumberField.tsx +139 -143
  187. package/src/Popover.tsx +396 -234
  188. package/src/Pressable.tsx +21 -21
  189. package/src/ProgressBar.tsx +48 -57
  190. package/src/RadioGroup.tsx +524 -122
  191. package/src/RangeCalendar.tsx +157 -90
  192. package/src/RouterProvider.tsx +30 -47
  193. package/src/SearchField.tsx +362 -143
  194. package/src/Select.tsx +656 -233
  195. package/src/SelectionIndicator.tsx +18 -15
  196. package/src/Separator.tsx +47 -49
  197. package/src/SharedElementTransition.tsx +103 -97
  198. package/src/Slider.tsx +138 -98
  199. package/src/StepList.tsx +272 -0
  200. package/src/Switch.tsx +93 -46
  201. package/src/Table.tsx +1308 -342
  202. package/src/Tabs.tsx +324 -103
  203. package/src/TagGroup.tsx +139 -126
  204. package/src/Text.tsx +3 -3
  205. package/src/TextField.tsx +389 -79
  206. package/src/TimeField.tsx +136 -76
  207. package/src/Toast.tsx +216 -158
  208. package/src/ToggleButton.tsx +47 -37
  209. package/src/ToggleButtonGroup.tsx +39 -34
  210. package/src/Toolbar.tsx +54 -69
  211. package/src/Tooltip.tsx +387 -119
  212. package/src/Tree.tsx +651 -368
  213. package/src/Virtualizer.tsx +208 -180
  214. package/src/VirtualizerLayouts.ts +45 -30
  215. package/src/VisuallyHidden.tsx +19 -19
  216. package/src/contexts.ts +29 -37
  217. package/src/index.ts +110 -195
  218. package/src/useDragAndDrop.ts +87 -71
  219. package/src/utils.tsx +49 -60
  220. package/src/virtualizer/Layout.ts +14 -22
  221. package/dist/index.ssr.js +0 -16996
  222. package/dist/index.ssr.js.map +0 -1
@@ -0,0 +1,153 @@
1
+ /**
2
+ * HiddenDateInput component for solidaria-components
3
+ *
4
+ * A hidden native date/datetime-local input for form submission.
5
+ * Renders server-side with the initial value for SSR safety.
6
+ */
7
+ import { type JSX, createEffect, createSignal } from "solid-js";
8
+ import { type DateValue, type FormValidationState } from "@proyecto-viviana/solid-stately";
9
+ import { createFormValidation } from "@proyecto-viviana/solidaria";
10
+
11
+ type MaybeAccessor<T> = T | (() => T);
12
+
13
+ export interface HiddenDateInputProps {
14
+ name?: string;
15
+ form?: string;
16
+ value?: MaybeAccessor<DateValue | null | undefined>;
17
+ autoComplete?: string;
18
+ isDisabled?: boolean;
19
+ isRequired?: boolean;
20
+ validationBehavior?: "aria" | "native";
21
+ validationState?: FormValidationState;
22
+ focus?: () => void;
23
+ minValue?: MaybeAccessor<DateValue | undefined>;
24
+ maxValue?: MaybeAccessor<DateValue | undefined>;
25
+ granularity?: "day" | "hour" | "minute" | "second";
26
+ }
27
+
28
+ function accessValue<T>(value: MaybeAccessor<T> | undefined): T | undefined {
29
+ return typeof value === "function" ? (value as () => T)() : value;
30
+ }
31
+
32
+ function formatDateValue(
33
+ value: DateValue | undefined | null,
34
+ granularity: "day" | "hour" | "minute" | "second",
35
+ ): string {
36
+ if (!value) return "";
37
+
38
+ if ("timeZone" in value) {
39
+ return String(value);
40
+ }
41
+
42
+ const dateValue = value;
43
+
44
+ const year = String(dateValue.year).padStart(4, "0");
45
+ const month = String(dateValue.month).padStart(2, "0");
46
+ const day = String(dateValue.day).padStart(2, "0");
47
+
48
+ if (granularity === "day") {
49
+ return `${year}-${month}-${day}`;
50
+ }
51
+
52
+ const hasHour = "hour" in dateValue;
53
+ const hour = hasHour ? String((dateValue as { hour: number }).hour).padStart(2, "0") : "00";
54
+ const hasMinute = hasHour && "minute" in dateValue;
55
+ const minute = hasMinute
56
+ ? String((dateValue as { minute: number }).minute).padStart(2, "0")
57
+ : "00";
58
+
59
+ if (granularity === "second" && hasMinute && "second" in dateValue) {
60
+ const second = String((dateValue as { second: number }).second).padStart(2, "0");
61
+ return `${year}-${month}-${day}T${hour}:${minute}:${second}`;
62
+ }
63
+
64
+ return `${year}-${month}-${day}T${hour}:${minute}`;
65
+ }
66
+
67
+ export function HiddenDateInput(props: HiddenDateInputProps): JSX.Element {
68
+ const granularity = () => props.granularity ?? "day";
69
+ const hasValidationBehavior = () => props.validationBehavior != null;
70
+ const validationBehavior = () => props.validationBehavior;
71
+ const usesNativeValidation = () => validationBehavior() === "native";
72
+ const value = () => accessValue(props.value);
73
+ const minValue = () => accessValue(props.minValue);
74
+ const maxValue = () => accessValue(props.maxValue);
75
+ const hasTimeZoneValue = () =>
76
+ Boolean(
77
+ (value() && "timeZone" in value()!) ||
78
+ (minValue() && "timeZone" in minValue()!) ||
79
+ (maxValue() && "timeZone" in maxValue()!),
80
+ );
81
+ const inputType = () =>
82
+ usesNativeValidation()
83
+ ? "text"
84
+ : hasValidationBehavior()
85
+ ? "hidden"
86
+ : hasTimeZoneValue()
87
+ ? "hidden"
88
+ : granularity() === "day"
89
+ ? "date"
90
+ : "datetime-local";
91
+ const formattedValue = () => formatDateValue(value(), granularity());
92
+ const formattedMin = () => formatDateValue(minValue(), granularity());
93
+ const formattedMax = () => formatDateValue(maxValue(), granularity());
94
+
95
+ const [inputRef, setInputRef] = createSignal<HTMLInputElement>();
96
+
97
+ if (props.validationState) {
98
+ createFormValidation(
99
+ {
100
+ get validationBehavior() {
101
+ return validationBehavior();
102
+ },
103
+ get focus() {
104
+ return props.focus;
105
+ },
106
+ },
107
+ props.validationState,
108
+ inputRef,
109
+ );
110
+ }
111
+
112
+ createEffect(() => {
113
+ const val = formattedValue();
114
+ const input = inputRef();
115
+ if (input && input.value !== val) {
116
+ input.value = val;
117
+ }
118
+ });
119
+
120
+ return (
121
+ <input
122
+ ref={(el) => {
123
+ setInputRef(el);
124
+ }}
125
+ type={inputType()}
126
+ name={props.name}
127
+ form={props.form}
128
+ value={formattedValue()}
129
+ autocomplete={props.autoComplete}
130
+ disabled={props.isDisabled}
131
+ required={usesNativeValidation() && props.isRequired ? true : undefined}
132
+ hidden={usesNativeValidation() || undefined}
133
+ min={hasValidationBehavior() ? undefined : formattedMin() || undefined}
134
+ max={hasValidationBehavior() ? undefined : formattedMax() || undefined}
135
+ onChange={usesNativeValidation() ? () => {} : undefined}
136
+ tabIndex={-1}
137
+ aria-hidden="true"
138
+ style={
139
+ {
140
+ position: "absolute",
141
+ width: "1px",
142
+ height: "1px",
143
+ padding: "0",
144
+ margin: "-1px",
145
+ overflow: "hidden",
146
+ clip: "rect(0, 0, 0, 0)",
147
+ "white-space": "nowrap",
148
+ "border-width": "0",
149
+ } as JSX.CSSProperties
150
+ }
151
+ />
152
+ );
153
+ }
@@ -0,0 +1,133 @@
1
+ /**
2
+ * HiddenTimeInput component for solidaria-components
3
+ *
4
+ * A hidden native time input for form submission.
5
+ */
6
+ import { type JSX, createEffect, createSignal } from "solid-js";
7
+ import { type FormValidationState, type TimeValue } from "@proyecto-viviana/solid-stately";
8
+ import { createFormValidation } from "@proyecto-viviana/solidaria";
9
+
10
+ type MaybeAccessor<T> = T | (() => T);
11
+
12
+ export interface HiddenTimeInputProps {
13
+ name?: string;
14
+ form?: string;
15
+ value?: MaybeAccessor<TimeValue | null | undefined>;
16
+ autoComplete?: string;
17
+ isDisabled?: boolean;
18
+ isRequired?: boolean;
19
+ validationBehavior?: "aria" | "native";
20
+ validationState?: FormValidationState;
21
+ focus?: () => void;
22
+ minValue?: MaybeAccessor<TimeValue | undefined>;
23
+ maxValue?: MaybeAccessor<TimeValue | undefined>;
24
+ granularity?: "hour" | "minute" | "second";
25
+ }
26
+
27
+ function accessValue<T>(value: MaybeAccessor<T> | undefined): T | undefined {
28
+ return typeof value === "function" ? (value as () => T)() : value;
29
+ }
30
+
31
+ function formatTimeValue(
32
+ value: TimeValue | undefined | null,
33
+ granularity: "hour" | "minute" | "second",
34
+ ): string {
35
+ if (!value) return "";
36
+
37
+ const hour = String(value.hour).padStart(2, "0");
38
+ const minute = String(granularity === "hour" ? 0 : value.minute).padStart(2, "0");
39
+
40
+ if (granularity === "second") {
41
+ const second = String(value.second).padStart(2, "0");
42
+ return `${hour}:${minute}:${second}`;
43
+ }
44
+
45
+ return `${hour}:${minute}`;
46
+ }
47
+
48
+ function stepForGranularity(granularity: "hour" | "minute" | "second"): number {
49
+ switch (granularity) {
50
+ case "hour":
51
+ return 3600;
52
+ case "second":
53
+ return 1;
54
+ case "minute":
55
+ default:
56
+ return 60;
57
+ }
58
+ }
59
+
60
+ export function HiddenTimeInput(props: HiddenTimeInputProps): JSX.Element {
61
+ const granularity = () => props.granularity ?? "minute";
62
+ const hasValidationBehavior = () => props.validationBehavior != null;
63
+ const validationBehavior = () => props.validationBehavior;
64
+ const usesNativeValidation = () => validationBehavior() === "native";
65
+ const value = () => accessValue(props.value);
66
+ const minValue = () => accessValue(props.minValue);
67
+ const maxValue = () => accessValue(props.maxValue);
68
+ const inputType = () =>
69
+ usesNativeValidation() ? "text" : hasValidationBehavior() ? "hidden" : "time";
70
+ const formattedValue = () => formatTimeValue(value(), granularity());
71
+ const formattedMin = () => formatTimeValue(minValue(), granularity());
72
+ const formattedMax = () => formatTimeValue(maxValue(), granularity());
73
+
74
+ const [inputRef, setInputRef] = createSignal<HTMLInputElement>();
75
+
76
+ if (props.validationState) {
77
+ createFormValidation(
78
+ {
79
+ get validationBehavior() {
80
+ return validationBehavior();
81
+ },
82
+ get focus() {
83
+ return props.focus;
84
+ },
85
+ },
86
+ props.validationState,
87
+ inputRef,
88
+ );
89
+ }
90
+
91
+ createEffect(() => {
92
+ const val = formattedValue();
93
+ const input = inputRef();
94
+ if (input && input.value !== val) {
95
+ input.value = val;
96
+ }
97
+ });
98
+
99
+ return (
100
+ <input
101
+ ref={(el) => {
102
+ setInputRef(el);
103
+ }}
104
+ type={inputType()}
105
+ name={props.name}
106
+ form={props.form}
107
+ value={formattedValue()}
108
+ autocomplete={props.autoComplete}
109
+ disabled={props.isDisabled}
110
+ required={usesNativeValidation() && props.isRequired ? true : undefined}
111
+ hidden={usesNativeValidation() || undefined}
112
+ min={hasValidationBehavior() ? undefined : formattedMin() || undefined}
113
+ max={hasValidationBehavior() ? undefined : formattedMax() || undefined}
114
+ step={hasValidationBehavior() ? undefined : stepForGranularity(granularity())}
115
+ onChange={usesNativeValidation() ? () => {} : undefined}
116
+ tabIndex={-1}
117
+ aria-hidden="true"
118
+ style={
119
+ {
120
+ position: "absolute",
121
+ width: "1px",
122
+ height: "1px",
123
+ padding: "0",
124
+ margin: "-1px",
125
+ overflow: "hidden",
126
+ clip: "rect(0, 0, 0, 0)",
127
+ "white-space": "nowrap",
128
+ "border-width": "0",
129
+ } as JSX.CSSProperties
130
+ }
131
+ />
132
+ );
133
+ }
package/src/Icon.tsx CHANGED
@@ -9,13 +9,7 @@
9
9
  * The UI layer consumes this for styling/composition only.
10
10
  */
11
11
 
12
- import {
13
- type JSX,
14
- createContext,
15
- createMemo,
16
- Show,
17
- splitProps,
18
- } from 'solid-js';
12
+ import { type JSX, createContext, createMemo, Show, splitProps } from "solid-js";
19
13
  import {
20
14
  type RenderChildren,
21
15
  type ClassNameOrFunction,
@@ -23,13 +17,9 @@ import {
23
17
  type SlotProps,
24
18
  useRenderProps,
25
19
  filterDOMProps,
26
- } from './utils';
27
- import { Button } from './Button';
28
- import type { PressEvent } from '@proyecto-viviana/solidaria';
29
-
30
- // ============================================
31
- // TYPES
32
- // ============================================
20
+ } from "./utils";
21
+ import { Button } from "./Button";
22
+ import type { PressEvent } from "@proyecto-viviana/solidaria";
33
23
 
34
24
  export interface IconRenderProps {
35
25
  /** Whether the icon is purely decorative (no label). */
@@ -42,9 +32,9 @@ export interface IconProps extends SlotProps {
42
32
  /** Handler called when the icon is pressed (makes it interactive). */
43
33
  onPress?: (e: PressEvent) => void;
44
34
  /** Accessible label for the icon. When provided, the icon is informative (role="img"). */
45
- 'aria-label'?: string;
35
+ "aria-label"?: string;
46
36
  /** ID of an element that labels this icon. */
47
- 'aria-labelledby'?: string;
37
+ "aria-labelledby"?: string;
48
38
  /** The children of the component. A function may be provided to receive render props. */
49
39
  children?: RenderChildren<IconRenderProps>;
50
40
  /** The CSS className for the element. */
@@ -55,16 +45,8 @@ export interface IconProps extends SlotProps {
55
45
  id?: string;
56
46
  }
57
47
 
58
- // ============================================
59
- // CONTEXT
60
- // ============================================
61
-
62
48
  export const IconContext = createContext<IconProps | null>(null);
63
49
 
64
- // ============================================
65
- // ICON COMPONENT
66
- // ============================================
67
-
68
50
  /**
69
51
  * An icon wrapper that provides correct ARIA semantics.
70
52
  *
@@ -86,37 +68,34 @@ export const IconContext = createContext<IconProps | null>(null);
86
68
  */
87
69
  export function Icon(props: IconProps): JSX.Element {
88
70
  const [local, rest] = splitProps(props, [
89
- 'children',
90
- 'class',
91
- 'style',
92
- 'slot',
93
- 'onPress',
94
- 'aria-label',
95
- 'aria-labelledby',
71
+ "children",
72
+ "class",
73
+ "style",
74
+ "slot",
75
+ "onPress",
76
+ "aria-label",
77
+ "aria-labelledby",
96
78
  ]);
97
79
 
98
- const hasLabel = () => !!(local['aria-label'] || local['aria-labelledby']);
80
+ const hasLabel = () => !!(local["aria-label"] || local["aria-labelledby"]);
99
81
  const isInteractive = () => !!local.onPress;
100
82
  const isDecorative = () => !hasLabel();
101
83
 
102
- // Render props values
103
84
  const renderValues = createMemo<IconRenderProps>(() => ({
104
85
  isDecorative: isDecorative(),
105
86
  isInteractive: isInteractive(),
106
87
  }));
107
88
 
108
- // Resolve render props
109
89
  const renderProps = useRenderProps(
110
90
  {
111
91
  children: local.children,
112
92
  class: local.class,
113
93
  style: local.style,
114
- defaultClassName: 'solidaria-Icon',
94
+ defaultClassName: "solidaria-Icon",
115
95
  },
116
- renderValues
96
+ renderValues,
117
97
  );
118
98
 
119
- // Filter DOM props
120
99
  const domProps = createMemo(() => filterDOMProps(rest, { global: true }));
121
100
 
122
101
  return (
@@ -125,10 +104,10 @@ export function Icon(props: IconProps): JSX.Element {
125
104
  fallback={
126
105
  <span
127
106
  {...domProps()}
128
- role={hasLabel() ? 'img' : undefined}
129
- aria-hidden={isDecorative() ? 'true' : undefined}
130
- aria-label={local['aria-label']}
131
- aria-labelledby={local['aria-labelledby']}
107
+ role={hasLabel() ? "img" : undefined}
108
+ aria-hidden={isDecorative() ? "true" : undefined}
109
+ aria-label={local["aria-label"]}
110
+ aria-labelledby={local["aria-labelledby"]}
132
111
  class={renderProps.class()}
133
112
  style={renderProps.style()}
134
113
  data-interactive={undefined}
@@ -141,8 +120,8 @@ export function Icon(props: IconProps): JSX.Element {
141
120
  <Button
142
121
  {...domProps()}
143
122
  onPress={local.onPress}
144
- aria-label={local['aria-label']}
145
- aria-labelledby={local['aria-labelledby']}
123
+ aria-label={local["aria-label"]}
124
+ aria-labelledby={local["aria-labelledby"]}
146
125
  class={renderProps.class()}
147
126
  style={renderProps.style()}
148
127
  data-interactive=""
package/src/Keyboard.tsx CHANGED
@@ -5,7 +5,7 @@
5
5
  * Port direction: react-aria-components/src/Keyboard.tsx
6
6
  */
7
7
 
8
- import { type JSX, createContext, splitProps, useContext } from 'solid-js';
8
+ import { type JSX, createContext, splitProps, useContext } from "solid-js";
9
9
 
10
10
  export interface KeyboardProps extends JSX.HTMLAttributes<HTMLElement> {
11
11
  children?: JSX.Element;
@@ -15,8 +15,8 @@ export const KeyboardContext = createContext<KeyboardProps | null>(null);
15
15
 
16
16
  export function Keyboard(props: KeyboardProps): JSX.Element {
17
17
  const context = useContext(KeyboardContext);
18
- const merged = () => ({ ...(context ?? {}), ...props });
19
- const [local, domProps] = splitProps(merged(), ['children']);
18
+ const merged = () => ({ ...context, ...props });
19
+ const [local, domProps] = splitProps(merged(), ["children"]);
20
20
 
21
21
  return (
22
22
  <kbd dir="ltr" {...domProps}>
package/src/Landmark.tsx CHANGED
@@ -5,38 +5,23 @@
5
5
  * Enables F6 keyboard navigation between major page sections.
6
6
  */
7
7
 
8
- import {
9
- type JSX,
10
- createContext,
11
- createMemo,
12
- createSignal,
13
- splitProps,
14
- } from 'solid-js';
15
- import { Dynamic } from 'solid-js/web';
8
+ import { type JSX, createContext, createMemo, createSignal, splitProps } from "solid-js";
9
+ import { Dynamic } from "solid-js/web";
16
10
  import {
17
11
  createLandmark,
18
12
  getLandmarkController,
19
13
  type AriaLandmarkProps,
20
14
  type AriaLandmarkRole,
21
15
  type LandmarkController,
22
- } from '@proyecto-viviana/solidaria';
23
- import {
24
- type SlotProps,
25
- filterDOMProps,
26
- } from './utils';
27
-
28
- // ============================================
29
- // TYPES
30
- // ============================================
16
+ } from "@proyecto-viviana/solidaria";
17
+ import { type SlotProps, filterDOMProps } from "./utils";
31
18
 
32
19
  export interface LandmarkRenderProps {
33
20
  /** The ARIA landmark role. */
34
21
  role: AriaLandmarkRole;
35
22
  }
36
23
 
37
- export interface LandmarkProps
38
- extends AriaLandmarkProps,
39
- SlotProps {
24
+ export interface LandmarkProps extends AriaLandmarkProps, SlotProps {
40
25
  /**
41
26
  * The HTML element type to render.
42
27
  * @default 'div' (or semantic element based on role)
@@ -50,38 +35,25 @@ export interface LandmarkProps
50
35
  children?: JSX.Element;
51
36
  }
52
37
 
53
- // Re-export types
54
38
  export type { AriaLandmarkRole, LandmarkController };
55
39
 
56
- // ============================================
57
- // CONTEXT
58
- // ============================================
59
-
60
40
  export const LandmarkContext = createContext<LandmarkProps | null>(null);
61
41
 
62
- // ============================================
63
- // SEMANTIC ELEMENT MAPPING
64
- // ============================================
65
-
66
42
  /**
67
43
  * Maps ARIA landmark roles to their semantic HTML elements.
68
44
  * Using semantic elements is preferred when possible.
69
45
  */
70
46
  const roleToSemanticElement: Partial<Record<AriaLandmarkRole, keyof JSX.IntrinsicElements>> = {
71
- main: 'main',
72
- navigation: 'nav',
73
- search: 'search', // HTML5.3 <search> element
74
- banner: 'header',
75
- contentinfo: 'footer',
76
- complementary: 'aside',
77
- form: 'form',
78
- region: 'section',
47
+ main: "main",
48
+ navigation: "nav",
49
+ search: "search", // HTML5.3 <search> element
50
+ banner: "header",
51
+ contentinfo: "footer",
52
+ complementary: "aside",
53
+ form: "form",
54
+ region: "section",
79
55
  };
80
56
 
81
- // ============================================
82
- // LANDMARK COMPONENT
83
- // ============================================
84
-
85
57
  /**
86
58
  * A landmark is a region of the page that helps screen reader users navigate.
87
59
  * Press F6 to cycle through landmarks, or Shift+F6 to go backwards.
@@ -112,11 +84,11 @@ const roleToSemanticElement: Partial<Record<AriaLandmarkRole, keyof JSX.Intrinsi
112
84
  */
113
85
  export function Landmark(props: LandmarkProps): JSX.Element {
114
86
  const [local, ariaProps] = splitProps(props, [
115
- 'class',
116
- 'style',
117
- 'slot',
118
- 'children',
119
- 'elementType',
87
+ "class",
88
+ "style",
89
+ "slot",
90
+ "children",
91
+ "elementType",
120
92
  ]);
121
93
 
122
94
  // Element ref
@@ -127,45 +99,51 @@ export function Landmark(props: LandmarkProps): JSX.Element {
127
99
  if (local.elementType) {
128
100
  return local.elementType;
129
101
  }
130
- return roleToSemanticElement[ariaProps.role] ?? 'div';
102
+ return roleToSemanticElement[ariaProps.role] ?? "div";
131
103
  });
132
104
 
133
105
  // Create landmark aria props
134
106
  const landmarkAria = createLandmark(
135
107
  {
136
- get role() { return ariaProps.role; },
137
- get 'aria-label'() { return ariaProps['aria-label']; },
138
- get 'aria-labelledby'() { return ariaProps['aria-labelledby']; },
139
- get id() { return ariaProps.id; },
140
- get focus() { return ariaProps.focus; },
108
+ get role() {
109
+ return ariaProps.role;
110
+ },
111
+ get "aria-label"() {
112
+ return ariaProps["aria-label"];
113
+ },
114
+ get "aria-labelledby"() {
115
+ return ariaProps["aria-labelledby"];
116
+ },
117
+ get id() {
118
+ return ariaProps.id;
119
+ },
120
+ get focus() {
121
+ return ariaProps.focus;
122
+ },
141
123
  },
142
- ref
124
+ ref,
143
125
  );
144
126
 
145
- // Render props values
146
127
  const renderValues = createMemo<LandmarkRenderProps>(() => ({
147
128
  role: ariaProps.role,
148
129
  }));
149
130
 
150
- // Resolve class
151
131
  const resolvedClass = createMemo(() => {
152
132
  const cls = local.class;
153
- if (typeof cls === 'function') {
133
+ if (typeof cls === "function") {
154
134
  return cls(renderValues());
155
135
  }
156
136
  return cls ?? `solidaria-Landmark solidaria-Landmark--${ariaProps.role}`;
157
137
  });
158
138
 
159
- // Resolve style
160
139
  const resolvedStyle = createMemo(() => {
161
140
  const style = local.style;
162
- if (typeof style === 'function') {
141
+ if (typeof style === "function") {
163
142
  return style(renderValues());
164
143
  }
165
144
  return style;
166
145
  });
167
146
 
168
- // Filter DOM props
169
147
  const domProps = createMemo(() => filterDOMProps(ariaProps, { global: true }));
170
148
 
171
149
  return (
@@ -183,10 +161,6 @@ export function Landmark(props: LandmarkProps): JSX.Element {
183
161
  );
184
162
  }
185
163
 
186
- // ============================================
187
- // LANDMARK CONTROLLER EXPORT
188
- // ============================================
189
-
190
164
  /**
191
165
  * Returns a controller for programmatic landmark navigation.
192
166
  *