@proyecto-viviana/solidaria-components 0.2.5 → 0.2.9

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 (194) hide show
  1. package/LICENSE +21 -0
  2. package/dist/ActionBar.d.ts +71 -0
  3. package/dist/ActionBar.d.ts.map +1 -0
  4. package/dist/ActionGroup.d.ts +74 -0
  5. package/dist/ActionGroup.d.ts.map +1 -0
  6. package/dist/Alert.d.ts +70 -0
  7. package/dist/Alert.d.ts.map +1 -0
  8. package/dist/Breadcrumbs.d.ts +10 -2
  9. package/dist/Breadcrumbs.d.ts.map +1 -1
  10. package/dist/Button.d.ts +4 -0
  11. package/dist/Button.d.ts.map +1 -1
  12. package/dist/Calendar.d.ts +13 -0
  13. package/dist/Calendar.d.ts.map +1 -1
  14. package/dist/Checkbox.d.ts +2 -2
  15. package/dist/Checkbox.d.ts.map +1 -1
  16. package/dist/Collection.d.ts +125 -0
  17. package/dist/Collection.d.ts.map +1 -0
  18. package/dist/Color.d.ts +114 -2
  19. package/dist/Color.d.ts.map +1 -1
  20. package/dist/ColorEditor.d.ts +42 -0
  21. package/dist/ColorEditor.d.ts.map +1 -0
  22. package/dist/ComboBox.d.ts +64 -0
  23. package/dist/ComboBox.d.ts.map +1 -1
  24. package/dist/ContextualHelpTrigger.d.ts +40 -0
  25. package/dist/ContextualHelpTrigger.d.ts.map +1 -0
  26. package/dist/DateField.d.ts +27 -2
  27. package/dist/DateField.d.ts.map +1 -1
  28. package/dist/DatePicker.d.ts +67 -2
  29. package/dist/DatePicker.d.ts.map +1 -1
  30. package/dist/Dialog.d.ts.map +1 -1
  31. package/dist/Disclosure.d.ts +2 -0
  32. package/dist/Disclosure.d.ts.map +1 -1
  33. package/dist/DragAndDrop.d.ts +80 -0
  34. package/dist/DragAndDrop.d.ts.map +1 -0
  35. package/dist/DragPreview.d.ts +14 -0
  36. package/dist/DragPreview.d.ts.map +1 -0
  37. package/dist/DropZone.d.ts +27 -0
  38. package/dist/DropZone.d.ts.map +1 -0
  39. package/dist/FieldError.d.ts +23 -0
  40. package/dist/FieldError.d.ts.map +1 -0
  41. package/dist/FileTrigger.d.ts +26 -0
  42. package/dist/FileTrigger.d.ts.map +1 -0
  43. package/dist/Focusable.d.ts +27 -0
  44. package/dist/Focusable.d.ts.map +1 -0
  45. package/dist/Form.d.ts +27 -0
  46. package/dist/Form.d.ts.map +1 -0
  47. package/dist/GridList.d.ts +40 -1
  48. package/dist/GridList.d.ts.map +1 -1
  49. package/dist/Icon.d.ts +57 -0
  50. package/dist/Icon.d.ts.map +1 -0
  51. package/dist/Keyboard.d.ts +13 -0
  52. package/dist/Keyboard.d.ts.map +1 -0
  53. package/dist/Link.d.ts.map +1 -1
  54. package/dist/ListBox.d.ts +43 -1
  55. package/dist/ListBox.d.ts.map +1 -1
  56. package/dist/ListDropTargetDelegate.d.ts +38 -0
  57. package/dist/ListDropTargetDelegate.d.ts.map +1 -0
  58. package/dist/Menu.d.ts +20 -2
  59. package/dist/Menu.d.ts.map +1 -1
  60. package/dist/Meter.d.ts +2 -2
  61. package/dist/Meter.d.ts.map +1 -1
  62. package/dist/Modal.d.ts +2 -0
  63. package/dist/Modal.d.ts.map +1 -1
  64. package/dist/NumberField.d.ts +2 -0
  65. package/dist/NumberField.d.ts.map +1 -1
  66. package/dist/Popover.d.ts +4 -2
  67. package/dist/Popover.d.ts.map +1 -1
  68. package/dist/Pressable.d.ts +27 -0
  69. package/dist/Pressable.d.ts.map +1 -0
  70. package/dist/ProgressBar.d.ts +2 -2
  71. package/dist/ProgressBar.d.ts.map +1 -1
  72. package/dist/RadioGroup.d.ts.map +1 -1
  73. package/dist/RangeCalendar.d.ts +5 -0
  74. package/dist/RangeCalendar.d.ts.map +1 -1
  75. package/dist/RouterProvider.d.ts +75 -0
  76. package/dist/RouterProvider.d.ts.map +1 -0
  77. package/dist/SearchField.d.ts +2 -3
  78. package/dist/SearchField.d.ts.map +1 -1
  79. package/dist/Select.d.ts +11 -0
  80. package/dist/Select.d.ts.map +1 -1
  81. package/dist/SelectionIndicator.d.ts +30 -0
  82. package/dist/SelectionIndicator.d.ts.map +1 -0
  83. package/dist/SharedElementTransition.d.ts +39 -0
  84. package/dist/SharedElementTransition.d.ts.map +1 -0
  85. package/dist/Slider.d.ts +6 -3
  86. package/dist/Slider.d.ts.map +1 -1
  87. package/dist/Table.d.ts +39 -0
  88. package/dist/Table.d.ts.map +1 -1
  89. package/dist/Tabs.d.ts +4 -3
  90. package/dist/Tabs.d.ts.map +1 -1
  91. package/dist/TagGroup.d.ts +12 -2
  92. package/dist/TagGroup.d.ts.map +1 -1
  93. package/dist/Text.d.ts +10 -0
  94. package/dist/Text.d.ts.map +1 -0
  95. package/dist/TextField.d.ts +4 -0
  96. package/dist/TextField.d.ts.map +1 -1
  97. package/dist/TimeField.d.ts +26 -1
  98. package/dist/TimeField.d.ts.map +1 -1
  99. package/dist/Toast.d.ts.map +1 -1
  100. package/dist/ToggleButton.d.ts +30 -0
  101. package/dist/ToggleButton.d.ts.map +1 -0
  102. package/dist/ToggleButtonGroup.d.ts +33 -0
  103. package/dist/ToggleButtonGroup.d.ts.map +1 -0
  104. package/dist/Toolbar.d.ts.map +1 -1
  105. package/dist/Tooltip.d.ts +9 -0
  106. package/dist/Tooltip.d.ts.map +1 -1
  107. package/dist/Tree.d.ts +44 -2
  108. package/dist/Tree.d.ts.map +1 -1
  109. package/dist/Virtualizer.d.ts +61 -0
  110. package/dist/Virtualizer.d.ts.map +1 -0
  111. package/dist/VirtualizerLayouts.d.ts +82 -0
  112. package/dist/VirtualizerLayouts.d.ts.map +1 -0
  113. package/dist/VisuallyHidden.d.ts +3 -1
  114. package/dist/VisuallyHidden.d.ts.map +1 -1
  115. package/dist/contexts.d.ts +1 -0
  116. package/dist/contexts.d.ts.map +1 -1
  117. package/dist/index.d.ts +57 -25
  118. package/dist/index.d.ts.map +1 -1
  119. package/dist/index.js +13961 -5946
  120. package/dist/index.js.map +1 -7
  121. package/dist/index.ssr.js +9612 -2401
  122. package/dist/index.ssr.js.map +1 -7
  123. package/dist/useDragAndDrop.d.ts +93 -0
  124. package/dist/useDragAndDrop.d.ts.map +1 -0
  125. package/dist/utils.d.ts +7 -1
  126. package/dist/utils.d.ts.map +1 -1
  127. package/dist/virtualizer/Layout.d.ts +79 -0
  128. package/dist/virtualizer/Layout.d.ts.map +1 -0
  129. package/package.json +8 -6
  130. package/src/ActionBar.tsx +248 -0
  131. package/src/ActionGroup.tsx +285 -0
  132. package/src/Alert.tsx +177 -0
  133. package/src/Autocomplete.tsx +1 -1
  134. package/src/Breadcrumbs.tsx +103 -17
  135. package/src/Button.tsx +65 -21
  136. package/src/Calendar.tsx +179 -53
  137. package/src/Checkbox.tsx +1 -2
  138. package/src/Collection.tsx +341 -0
  139. package/src/Color.tsx +652 -34
  140. package/src/ColorEditor.tsx +231 -0
  141. package/src/ComboBox.tsx +315 -81
  142. package/src/ContextualHelpTrigger.tsx +183 -0
  143. package/src/DateField.tsx +93 -19
  144. package/src/DatePicker.tsx +495 -25
  145. package/src/Dialog.tsx +40 -9
  146. package/src/Disclosure.tsx +33 -27
  147. package/src/DragAndDrop.tsx +334 -0
  148. package/src/DragPreview.tsx +45 -0
  149. package/src/DropZone.tsx +213 -0
  150. package/src/FieldError.tsx +67 -0
  151. package/src/FileTrigger.tsx +83 -0
  152. package/src/Focusable.tsx +106 -0
  153. package/src/Form.tsx +85 -0
  154. package/src/GridList.tsx +379 -41
  155. package/src/Icon.tsx +154 -0
  156. package/src/Keyboard.tsx +26 -0
  157. package/src/Link.tsx +14 -1
  158. package/src/ListBox.tsx +484 -33
  159. package/src/ListDropTargetDelegate.ts +282 -0
  160. package/src/Menu.tsx +388 -35
  161. package/src/Meter.tsx +7 -3
  162. package/src/Modal.tsx +32 -4
  163. package/src/NumberField.tsx +163 -43
  164. package/src/Popover.tsx +136 -180
  165. package/src/Pressable.tsx +108 -0
  166. package/src/ProgressBar.tsx +7 -3
  167. package/src/RadioGroup.tsx +35 -25
  168. package/src/RangeCalendar.tsx +100 -68
  169. package/src/RouterProvider.tsx +240 -0
  170. package/src/SearchField.tsx +142 -34
  171. package/src/Select.tsx +221 -73
  172. package/src/SelectionIndicator.tsx +105 -0
  173. package/src/SharedElementTransition.tsx +258 -0
  174. package/src/Slider.tsx +16 -6
  175. package/src/Table.tsx +417 -57
  176. package/src/Tabs.tsx +68 -35
  177. package/src/TagGroup.tsx +121 -36
  178. package/src/Text.tsx +18 -0
  179. package/src/TextField.tsx +25 -8
  180. package/src/TimeField.tsx +101 -151
  181. package/src/Toast.tsx +108 -14
  182. package/src/ToggleButton.tsx +159 -0
  183. package/src/ToggleButtonGroup.tsx +136 -0
  184. package/src/Toolbar.tsx +14 -8
  185. package/src/Tooltip.tsx +108 -19
  186. package/src/Tree.tsx +1143 -87
  187. package/src/Virtualizer.tsx +702 -0
  188. package/src/VirtualizerLayouts.ts +265 -0
  189. package/src/VisuallyHidden.tsx +15 -21
  190. package/src/contexts.ts +1 -0
  191. package/src/index.ts +1057 -620
  192. package/src/useDragAndDrop.ts +351 -0
  193. package/src/utils.tsx +37 -3
  194. package/src/virtualizer/Layout.ts +200 -0
@@ -0,0 +1,183 @@
1
+ /**
2
+ * ContextualHelpTrigger headless component
3
+ *
4
+ * A button trigger that opens contextual help in a popover or dialog.
5
+ * Uses existing overlay infrastructure.
6
+ */
7
+
8
+ import { type JSX, createSignal, splitProps, Show, onCleanup, createEffect, createUniqueId } from 'solid-js'
9
+
10
+ // ============================================
11
+ // TYPES
12
+ // ============================================
13
+
14
+ export interface ContextualHelpTriggerProps extends Omit<JSX.ButtonHTMLAttributes<HTMLButtonElement>, 'class' | 'children'> {
15
+ /** Whether the trigger is currently unavailable (shows different styling). */
16
+ isUnavailable?: boolean
17
+ /**
18
+ * Two children: [trigger element, help content].
19
+ * The trigger renders as a button, the content opens in a popover.
20
+ */
21
+ children?: [JSX.Element, JSX.Element]
22
+ /** CSS class name. */
23
+ class?: string
24
+ /** Whether the trigger is disabled. */
25
+ isDisabled?: boolean
26
+ }
27
+
28
+ export interface ContextualHelpTriggerRenderProps {
29
+ isOpen: boolean
30
+ isUnavailable: boolean
31
+ isDisabled: boolean
32
+ }
33
+
34
+ // ============================================
35
+ // COMPONENT
36
+ // ============================================
37
+
38
+ /**
39
+ * A trigger that opens contextual help content.
40
+ *
41
+ * @example
42
+ * ```tsx
43
+ * <ContextualHelpTrigger>
44
+ * {[
45
+ * <span>What is this?</span>,
46
+ * <div>Help content goes here...</div>
47
+ * ]}
48
+ * </ContextualHelpTrigger>
49
+ * ```
50
+ */
51
+ export function ContextualHelpTrigger(props: ContextualHelpTriggerProps): JSX.Element {
52
+ const [local, triggerProps] = splitProps(props, ['isUnavailable', 'children', 'class', 'isDisabled'])
53
+ const [isOpen, setIsOpen] = createSignal(false)
54
+ const triggerId = createUniqueId()
55
+ const contentId = createUniqueId()
56
+ let triggerRef: HTMLButtonElement | undefined
57
+ let contentRef: HTMLDivElement | undefined
58
+
59
+ const isUnavailable = () => local.isUnavailable ?? false
60
+ const isDisabled = () => local.isDisabled ?? false
61
+
62
+ const toggle = () => {
63
+ if (!isDisabled()) {
64
+ setIsOpen(!isOpen())
65
+ }
66
+ }
67
+
68
+ const close = () => setIsOpen(false)
69
+
70
+ const callHandler = <E extends Event>(
71
+ handler: JSX.EventHandlerUnion<HTMLButtonElement, E> | undefined,
72
+ event: E
73
+ ) => {
74
+ if (!handler) return
75
+ if (Array.isArray(handler)) {
76
+ handler[1].call(handler[0], event)
77
+ return
78
+ }
79
+ if (typeof handler === 'function') {
80
+ (handler as (evt: E) => void)(event)
81
+ return
82
+ }
83
+ if (typeof handler === 'object' && 'handleEvent' in handler && typeof handler.handleEvent === 'function') {
84
+ (handler.handleEvent as (evt: E) => void)(event)
85
+ }
86
+ }
87
+
88
+ const handleTriggerClick = (e: MouseEvent) => {
89
+ callHandler(triggerProps.onClick, e)
90
+ if (e.defaultPrevented) return
91
+ toggle()
92
+ }
93
+
94
+ const handleTriggerKeyDown = (e: KeyboardEvent) => {
95
+ callHandler(triggerProps.onKeyDown, e)
96
+ if (e.defaultPrevented) return
97
+ if (e.key === 'Escape' && isOpen()) {
98
+ e.preventDefault()
99
+ e.stopPropagation()
100
+ close()
101
+ triggerRef?.focus()
102
+ }
103
+ }
104
+
105
+ // Close on outside click
106
+ const handleDocumentClick = (e: MouseEvent) => {
107
+ if (
108
+ isOpen() &&
109
+ triggerRef &&
110
+ contentRef &&
111
+ !triggerRef.contains(e.target as Node) &&
112
+ !contentRef.contains(e.target as Node)
113
+ ) {
114
+ close()
115
+ }
116
+ }
117
+
118
+ createEffect(() => {
119
+ if (!isOpen()) return
120
+ document.addEventListener('mousedown', handleDocumentClick)
121
+ onCleanup(() => {
122
+ document.removeEventListener('mousedown', handleDocumentClick)
123
+ })
124
+ })
125
+
126
+ // Focus trap: return focus to trigger on close
127
+ createEffect(() => {
128
+ if (!isOpen()) return
129
+ // Focus the content on open
130
+ contentRef?.focus()
131
+ })
132
+
133
+ const children = () => local.children ?? [null, null] as [JSX.Element, JSX.Element]
134
+ const trigger = () => children()[0]
135
+ const content = () => children()[1]
136
+
137
+ return (
138
+ <div
139
+ class={`solidaria-ContextualHelpTrigger ${local.class ?? ''}`}
140
+ style={{ position: 'relative', display: 'inline-block' }}
141
+ >
142
+ <button
143
+ {...triggerProps}
144
+ type="button"
145
+ id={triggerId}
146
+ ref={triggerRef}
147
+ aria-haspopup="dialog"
148
+ aria-expanded={isOpen()}
149
+ aria-controls={isOpen() ? contentId : undefined}
150
+ data-unavailable={isUnavailable() || undefined}
151
+ data-disabled={isDisabled() || undefined}
152
+ disabled={isDisabled()}
153
+ onClick={handleTriggerClick}
154
+ onKeyDown={handleTriggerKeyDown}
155
+ class="solidaria-ContextualHelpTrigger-trigger"
156
+ >
157
+ {trigger()}
158
+ </button>
159
+
160
+ <Show when={isOpen()}>
161
+ <div
162
+ id={contentId}
163
+ ref={contentRef}
164
+ role="dialog"
165
+ aria-labelledby={triggerId}
166
+ tabIndex={-1}
167
+ class="solidaria-ContextualHelpTrigger-content"
168
+ style={{ position: 'absolute', 'z-index': '50' }}
169
+ onKeyDown={(e) => {
170
+ if (e.key === 'Escape') {
171
+ e.preventDefault()
172
+ e.stopPropagation()
173
+ close()
174
+ triggerRef?.focus()
175
+ }
176
+ }}
177
+ >
178
+ {content()}
179
+ </div>
180
+ </Show>
181
+ </div>
182
+ )
183
+ }
package/src/DateField.tsx CHANGED
@@ -111,9 +111,20 @@ export interface DateSegmentProps extends SlotProps {
111
111
  // CONTEXT
112
112
  // ============================================
113
113
 
114
- export const DateFieldContext = createContext<DateFieldState<DateValue> | null>(null);
114
+ export interface DateFieldContextValue {
115
+ state: DateFieldState<DateValue>;
116
+ aria: {
117
+ labelProps: Record<string, unknown>;
118
+ inputProps: Record<string, unknown>;
119
+ descriptionProps: Record<string, unknown>;
120
+ errorMessageProps: Record<string, unknown>;
121
+ };
122
+ }
123
+
124
+ export const DateFieldContext = createContext<DateFieldContextValue | null>(null);
125
+ export const DateFieldStateContext = createContext<DateFieldState<DateValue> | null>(null);
115
126
 
116
- export function useDateFieldContext(): DateFieldState<DateValue> {
127
+ export function useDateFieldContext(): DateFieldContextValue {
117
128
  const context = useContext(DateFieldContext);
118
129
  if (!context) {
119
130
  throw new Error('DateField components must be used within a DateField');
@@ -189,7 +200,15 @@ function DateFieldInner<T extends DateValue = CalendarDate>(
189
200
  const state = createDateFieldState(stateProps);
190
201
 
191
202
  // Create date field ARIA props
192
- const fieldAria = createDateField(rest, state as unknown as DateFieldState<DateValue>, fieldRef);
203
+ const fieldAria = createDateField(
204
+ () => ({
205
+ ...(rest as Record<string, unknown>),
206
+ description: stateProps.description,
207
+ errorMessage: stateProps.errorMessage,
208
+ }),
209
+ state as unknown as DateFieldState<DateValue>,
210
+ fieldRef
211
+ );
193
212
 
194
213
  // Render props values
195
214
  const renderValues = createMemo<DateFieldRenderProps>(() => ({
@@ -210,20 +229,32 @@ function DateFieldInner<T extends DateValue = CalendarDate>(
210
229
  );
211
230
 
212
231
  return (
213
- <DateFieldContext.Provider value={state as unknown as DateFieldState<DateValue>}>
214
- <div
215
- ref={setFieldRef}
216
- {...fieldAria.fieldProps}
217
- class={renderProps.class()}
218
- style={renderProps.style()}
219
- data-disabled={dataAttr(state.isDisabled())}
220
- data-readonly={dataAttr(state.isReadOnly())}
221
- data-required={dataAttr(state.isRequired())}
222
- data-invalid={dataAttr(state.isInvalid())}
232
+ <DateFieldStateContext.Provider value={state as unknown as DateFieldState<DateValue>}>
233
+ <DateFieldContext.Provider
234
+ value={{
235
+ state: state as unknown as DateFieldState<DateValue>,
236
+ aria: {
237
+ labelProps: fieldAria.labelProps,
238
+ inputProps: fieldAria.inputProps,
239
+ descriptionProps: fieldAria.descriptionProps,
240
+ errorMessageProps: fieldAria.errorMessageProps,
241
+ },
242
+ }}
223
243
  >
224
- {props.children as JSX.Element}
225
- </div>
226
- </DateFieldContext.Provider>
244
+ <div
245
+ ref={setFieldRef}
246
+ {...fieldAria.fieldProps}
247
+ class={renderProps.class()}
248
+ style={renderProps.style()}
249
+ data-disabled={dataAttr(state.isDisabled())}
250
+ data-readonly={dataAttr(state.isReadOnly())}
251
+ data-required={dataAttr(state.isRequired())}
252
+ data-invalid={dataAttr(state.isInvalid())}
253
+ >
254
+ {props.children as JSX.Element}
255
+ </div>
256
+ </DateFieldContext.Provider>
257
+ </DateFieldStateContext.Provider>
227
258
  );
228
259
  }
229
260
 
@@ -235,7 +266,8 @@ function DateFieldInner<T extends DateValue = CalendarDate>(
235
266
  * The input area containing date segments.
236
267
  */
237
268
  export function DateInput(props: DateInputProps): JSX.Element {
238
- const state = useDateFieldContext();
269
+ const context = useDateFieldContext();
270
+ const { state, aria } = context;
239
271
  const [isFocused, setIsFocused] = createSignal(false);
240
272
 
241
273
  // Render props values
@@ -256,7 +288,7 @@ export function DateInput(props: DateInputProps): JSX.Element {
256
288
 
257
289
  return (
258
290
  <div
259
- role="presentation"
291
+ {...aria.inputProps}
260
292
  class={renderProps.class()}
261
293
  style={renderProps.style()}
262
294
  data-disabled={dataAttr(state.isDisabled())}
@@ -279,7 +311,7 @@ export function DateInput(props: DateInputProps): JSX.Element {
279
311
  * A segment of a date field (year, month, day, etc.).
280
312
  */
281
313
  export function DateSegment(props: DateSegmentProps): JSX.Element {
282
- const state = useDateFieldContext();
314
+ const { state } = useDateFieldContext();
283
315
  const [segmentRef, setSegmentRef] = createSignal<HTMLDivElement | null>(null);
284
316
 
285
317
  // Create segment ARIA props
@@ -333,5 +365,47 @@ export function DateSegment(props: DateSegmentProps): JSX.Element {
333
365
  );
334
366
  }
335
367
 
368
+ export interface DateFieldLabelProps {
369
+ children?: JSX.Element;
370
+ class?: string;
371
+ }
372
+
373
+ export function DateFieldLabel(props: DateFieldLabelProps): JSX.Element {
374
+ const { aria } = useDateFieldContext();
375
+ return (
376
+ <span {...aria.labelProps} class={props.class}>
377
+ {props.children}
378
+ </span>
379
+ );
380
+ }
381
+
382
+ export interface DateFieldDescriptionProps {
383
+ children?: JSX.Element;
384
+ class?: string;
385
+ }
386
+
387
+ export function DateFieldDescription(props: DateFieldDescriptionProps): JSX.Element {
388
+ const { aria } = useDateFieldContext();
389
+ return (
390
+ <p {...aria.descriptionProps} class={props.class}>
391
+ {props.children}
392
+ </p>
393
+ );
394
+ }
395
+
396
+ export interface DateFieldErrorMessageProps {
397
+ children?: JSX.Element;
398
+ class?: string;
399
+ }
400
+
401
+ export function DateFieldErrorMessage(props: DateFieldErrorMessageProps): JSX.Element {
402
+ const { aria } = useDateFieldContext();
403
+ return (
404
+ <p {...aria.errorMessageProps} class={props.class}>
405
+ {props.children}
406
+ </p>
407
+ );
408
+ }
409
+
336
410
  // Re-export types
337
411
  export type { DateFieldState, DateSegmentType };