@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.
- package/LICENSE +21 -0
- package/dist/ActionBar.d.ts +71 -0
- package/dist/ActionBar.d.ts.map +1 -0
- package/dist/ActionGroup.d.ts +74 -0
- package/dist/ActionGroup.d.ts.map +1 -0
- package/dist/Alert.d.ts +70 -0
- package/dist/Alert.d.ts.map +1 -0
- package/dist/Breadcrumbs.d.ts +10 -2
- package/dist/Breadcrumbs.d.ts.map +1 -1
- package/dist/Button.d.ts +4 -0
- package/dist/Button.d.ts.map +1 -1
- package/dist/Calendar.d.ts +13 -0
- package/dist/Calendar.d.ts.map +1 -1
- package/dist/Checkbox.d.ts +2 -2
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Collection.d.ts +125 -0
- package/dist/Collection.d.ts.map +1 -0
- package/dist/Color.d.ts +114 -2
- package/dist/Color.d.ts.map +1 -1
- package/dist/ColorEditor.d.ts +42 -0
- package/dist/ColorEditor.d.ts.map +1 -0
- package/dist/ComboBox.d.ts +64 -0
- package/dist/ComboBox.d.ts.map +1 -1
- package/dist/ContextualHelpTrigger.d.ts +40 -0
- package/dist/ContextualHelpTrigger.d.ts.map +1 -0
- package/dist/DateField.d.ts +27 -2
- package/dist/DateField.d.ts.map +1 -1
- package/dist/DatePicker.d.ts +67 -2
- package/dist/DatePicker.d.ts.map +1 -1
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Disclosure.d.ts +2 -0
- package/dist/Disclosure.d.ts.map +1 -1
- package/dist/DragAndDrop.d.ts +80 -0
- package/dist/DragAndDrop.d.ts.map +1 -0
- package/dist/DragPreview.d.ts +14 -0
- package/dist/DragPreview.d.ts.map +1 -0
- package/dist/DropZone.d.ts +27 -0
- package/dist/DropZone.d.ts.map +1 -0
- package/dist/FieldError.d.ts +23 -0
- package/dist/FieldError.d.ts.map +1 -0
- package/dist/FileTrigger.d.ts +26 -0
- package/dist/FileTrigger.d.ts.map +1 -0
- package/dist/Focusable.d.ts +27 -0
- package/dist/Focusable.d.ts.map +1 -0
- package/dist/Form.d.ts +27 -0
- package/dist/Form.d.ts.map +1 -0
- package/dist/GridList.d.ts +40 -1
- package/dist/GridList.d.ts.map +1 -1
- package/dist/Icon.d.ts +57 -0
- package/dist/Icon.d.ts.map +1 -0
- package/dist/Keyboard.d.ts +13 -0
- package/dist/Keyboard.d.ts.map +1 -0
- package/dist/Link.d.ts.map +1 -1
- package/dist/ListBox.d.ts +43 -1
- package/dist/ListBox.d.ts.map +1 -1
- package/dist/ListDropTargetDelegate.d.ts +38 -0
- package/dist/ListDropTargetDelegate.d.ts.map +1 -0
- package/dist/Menu.d.ts +20 -2
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Meter.d.ts +2 -2
- package/dist/Meter.d.ts.map +1 -1
- package/dist/Modal.d.ts +2 -0
- package/dist/Modal.d.ts.map +1 -1
- package/dist/NumberField.d.ts +2 -0
- package/dist/NumberField.d.ts.map +1 -1
- package/dist/Popover.d.ts +4 -2
- package/dist/Popover.d.ts.map +1 -1
- package/dist/Pressable.d.ts +27 -0
- package/dist/Pressable.d.ts.map +1 -0
- package/dist/ProgressBar.d.ts +2 -2
- package/dist/ProgressBar.d.ts.map +1 -1
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RangeCalendar.d.ts +5 -0
- package/dist/RangeCalendar.d.ts.map +1 -1
- package/dist/RouterProvider.d.ts +75 -0
- package/dist/RouterProvider.d.ts.map +1 -0
- package/dist/SearchField.d.ts +2 -3
- package/dist/SearchField.d.ts.map +1 -1
- package/dist/Select.d.ts +11 -0
- package/dist/Select.d.ts.map +1 -1
- package/dist/SelectionIndicator.d.ts +30 -0
- package/dist/SelectionIndicator.d.ts.map +1 -0
- package/dist/SharedElementTransition.d.ts +39 -0
- package/dist/SharedElementTransition.d.ts.map +1 -0
- package/dist/Slider.d.ts +6 -3
- package/dist/Slider.d.ts.map +1 -1
- package/dist/Table.d.ts +39 -0
- package/dist/Table.d.ts.map +1 -1
- package/dist/Tabs.d.ts +4 -3
- package/dist/Tabs.d.ts.map +1 -1
- package/dist/TagGroup.d.ts +12 -2
- package/dist/TagGroup.d.ts.map +1 -1
- package/dist/Text.d.ts +10 -0
- package/dist/Text.d.ts.map +1 -0
- package/dist/TextField.d.ts +4 -0
- package/dist/TextField.d.ts.map +1 -1
- package/dist/TimeField.d.ts +26 -1
- package/dist/TimeField.d.ts.map +1 -1
- package/dist/Toast.d.ts.map +1 -1
- package/dist/ToggleButton.d.ts +30 -0
- package/dist/ToggleButton.d.ts.map +1 -0
- package/dist/ToggleButtonGroup.d.ts +33 -0
- package/dist/ToggleButtonGroup.d.ts.map +1 -0
- package/dist/Toolbar.d.ts.map +1 -1
- package/dist/Tooltip.d.ts +9 -0
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/Tree.d.ts +44 -2
- package/dist/Tree.d.ts.map +1 -1
- package/dist/Virtualizer.d.ts +61 -0
- package/dist/Virtualizer.d.ts.map +1 -0
- package/dist/VirtualizerLayouts.d.ts +82 -0
- package/dist/VirtualizerLayouts.d.ts.map +1 -0
- package/dist/VisuallyHidden.d.ts +3 -1
- package/dist/VisuallyHidden.d.ts.map +1 -1
- package/dist/contexts.d.ts +1 -0
- package/dist/contexts.d.ts.map +1 -1
- package/dist/index.d.ts +57 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13961 -5946
- package/dist/index.js.map +1 -7
- package/dist/index.ssr.js +9612 -2401
- package/dist/index.ssr.js.map +1 -7
- package/dist/useDragAndDrop.d.ts +93 -0
- package/dist/useDragAndDrop.d.ts.map +1 -0
- package/dist/utils.d.ts +7 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/virtualizer/Layout.d.ts +79 -0
- package/dist/virtualizer/Layout.d.ts.map +1 -0
- package/package.json +8 -6
- package/src/ActionBar.tsx +248 -0
- package/src/ActionGroup.tsx +285 -0
- package/src/Alert.tsx +177 -0
- package/src/Autocomplete.tsx +1 -1
- package/src/Breadcrumbs.tsx +103 -17
- package/src/Button.tsx +65 -21
- package/src/Calendar.tsx +179 -53
- package/src/Checkbox.tsx +1 -2
- package/src/Collection.tsx +341 -0
- package/src/Color.tsx +652 -34
- package/src/ColorEditor.tsx +231 -0
- package/src/ComboBox.tsx +315 -81
- package/src/ContextualHelpTrigger.tsx +183 -0
- package/src/DateField.tsx +93 -19
- package/src/DatePicker.tsx +495 -25
- package/src/Dialog.tsx +40 -9
- package/src/Disclosure.tsx +33 -27
- package/src/DragAndDrop.tsx +334 -0
- package/src/DragPreview.tsx +45 -0
- package/src/DropZone.tsx +213 -0
- package/src/FieldError.tsx +67 -0
- package/src/FileTrigger.tsx +83 -0
- package/src/Focusable.tsx +106 -0
- package/src/Form.tsx +85 -0
- package/src/GridList.tsx +379 -41
- package/src/Icon.tsx +154 -0
- package/src/Keyboard.tsx +26 -0
- package/src/Link.tsx +14 -1
- package/src/ListBox.tsx +484 -33
- package/src/ListDropTargetDelegate.ts +282 -0
- package/src/Menu.tsx +388 -35
- package/src/Meter.tsx +7 -3
- package/src/Modal.tsx +32 -4
- package/src/NumberField.tsx +163 -43
- package/src/Popover.tsx +136 -180
- package/src/Pressable.tsx +108 -0
- package/src/ProgressBar.tsx +7 -3
- package/src/RadioGroup.tsx +35 -25
- package/src/RangeCalendar.tsx +100 -68
- package/src/RouterProvider.tsx +240 -0
- package/src/SearchField.tsx +142 -34
- package/src/Select.tsx +221 -73
- package/src/SelectionIndicator.tsx +105 -0
- package/src/SharedElementTransition.tsx +258 -0
- package/src/Slider.tsx +16 -6
- package/src/Table.tsx +417 -57
- package/src/Tabs.tsx +68 -35
- package/src/TagGroup.tsx +121 -36
- package/src/Text.tsx +18 -0
- package/src/TextField.tsx +25 -8
- package/src/TimeField.tsx +101 -151
- package/src/Toast.tsx +108 -14
- package/src/ToggleButton.tsx +159 -0
- package/src/ToggleButtonGroup.tsx +136 -0
- package/src/Toolbar.tsx +14 -8
- package/src/Tooltip.tsx +108 -19
- package/src/Tree.tsx +1143 -87
- package/src/Virtualizer.tsx +702 -0
- package/src/VirtualizerLayouts.ts +265 -0
- package/src/VisuallyHidden.tsx +15 -21
- package/src/contexts.ts +1 -0
- package/src/index.ts +1057 -620
- package/src/useDragAndDrop.ts +351 -0
- package/src/utils.tsx +37 -3
- package/src/virtualizer/Layout.ts +200 -0
package/src/Tabs.tsx
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
|
+
type Accessor,
|
|
9
10
|
type JSX,
|
|
10
11
|
createContext,
|
|
11
12
|
createMemo,
|
|
@@ -39,6 +40,19 @@ import {
|
|
|
39
40
|
useRenderProps,
|
|
40
41
|
filterDOMProps,
|
|
41
42
|
} from './utils';
|
|
43
|
+
import {
|
|
44
|
+
SelectionIndicator,
|
|
45
|
+
SelectionIndicatorContext,
|
|
46
|
+
type SelectionIndicatorContextValue,
|
|
47
|
+
} from './SelectionIndicator';
|
|
48
|
+
import { SharedElementTransition } from './SharedElementTransition';
|
|
49
|
+
|
|
50
|
+
export {
|
|
51
|
+
SelectionIndicator,
|
|
52
|
+
SelectionIndicatorContext,
|
|
53
|
+
type SelectionIndicatorProps,
|
|
54
|
+
type SelectionIndicatorRenderProps,
|
|
55
|
+
} from './SelectionIndicator';
|
|
42
56
|
|
|
43
57
|
// ============================================
|
|
44
58
|
// TYPES
|
|
@@ -154,7 +168,7 @@ export interface TabPanelProps extends AriaTabPanelProps, SlotProps {
|
|
|
154
168
|
|
|
155
169
|
interface TabsContextValue<T> {
|
|
156
170
|
state: TabListState<T>;
|
|
157
|
-
items: T[]
|
|
171
|
+
items: Accessor<T[]>;
|
|
158
172
|
}
|
|
159
173
|
|
|
160
174
|
export const TabsContext = createContext<TabsContextValue<unknown> | null>(null);
|
|
@@ -232,7 +246,7 @@ export function Tabs<T>(props: TabsProps<T>): JSX.Element {
|
|
|
232
246
|
const domProps = createMemo(() => filterDOMProps(rest as Record<string, unknown>, { global: true }));
|
|
233
247
|
|
|
234
248
|
return (
|
|
235
|
-
<TabsContext.Provider value={{ state, items: stateProps.items ?? [] }}>
|
|
249
|
+
<TabsContext.Provider value={{ state, items: () => stateProps.items ?? [] }}>
|
|
236
250
|
<TabsStateContext.Provider value={state}>
|
|
237
251
|
<div
|
|
238
252
|
{...domProps()}
|
|
@@ -286,7 +300,7 @@ function TabListInner<T>(props: {
|
|
|
286
300
|
children?: (item: T) => JSX.Element;
|
|
287
301
|
}): JSX.Element {
|
|
288
302
|
const state = props.context.state as TabListState<T>;
|
|
289
|
-
const items = props.context.items as T[]
|
|
303
|
+
const items = props.context.items as Accessor<T[]>;
|
|
290
304
|
|
|
291
305
|
// Create tab list aria props
|
|
292
306
|
const { tabListProps } = createTabList<T>(props.ariaProps as AriaTabListProps, state);
|
|
@@ -314,14 +328,20 @@ function TabListInner<T>(props: {
|
|
|
314
328
|
|
|
315
329
|
// Helper to safely call event handlers that may be bound tuples
|
|
316
330
|
const callHandler = <E extends Event>(
|
|
317
|
-
handler:
|
|
331
|
+
handler: JSX.EventHandlerUnion<HTMLElement, E> | undefined,
|
|
318
332
|
event: E
|
|
319
333
|
) => {
|
|
320
334
|
if (!handler) return;
|
|
321
335
|
if (Array.isArray(handler)) {
|
|
322
336
|
handler[1].call(handler[0], event);
|
|
323
|
-
|
|
324
|
-
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
if (typeof handler === 'function') {
|
|
340
|
+
(handler as (evt: E) => void)(event);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
if (typeof handler === 'object' && 'handleEvent' in handler && typeof handler.handleEvent === 'function') {
|
|
344
|
+
(handler.handleEvent as (evt: E) => void)(event);
|
|
325
345
|
}
|
|
326
346
|
};
|
|
327
347
|
|
|
@@ -332,12 +352,12 @@ function TabListInner<T>(props: {
|
|
|
332
352
|
|
|
333
353
|
const handleFocus = (e: FocusEvent) => {
|
|
334
354
|
tabListProps.onFocus(e);
|
|
335
|
-
callHandler(focusProps.onFocus
|
|
355
|
+
callHandler(focusProps.onFocus, e);
|
|
336
356
|
};
|
|
337
357
|
|
|
338
358
|
const handleBlur = (e: FocusEvent) => {
|
|
339
359
|
tabListProps.onBlur(e);
|
|
340
|
-
callHandler(focusProps.onBlur
|
|
360
|
+
callHandler(focusProps.onBlur, e);
|
|
341
361
|
};
|
|
342
362
|
|
|
343
363
|
return (
|
|
@@ -357,7 +377,9 @@ function TabListInner<T>(props: {
|
|
|
357
377
|
data-orientation={state.orientation()}
|
|
358
378
|
data-disabled={state.isDisabled() || undefined}
|
|
359
379
|
>
|
|
360
|
-
<
|
|
380
|
+
<SharedElementTransition>
|
|
381
|
+
<For each={items()}>{(item) => props.children?.(item)}</For>
|
|
382
|
+
</SharedElementTransition>
|
|
361
383
|
</div>
|
|
362
384
|
);
|
|
363
385
|
}
|
|
@@ -400,6 +422,8 @@ function TabInner(props: {
|
|
|
400
422
|
ariaProps: Omit<TabProps, 'children' | 'class' | 'style' | 'slot' | 'id'>;
|
|
401
423
|
children?: RenderChildren<TabRenderProps>;
|
|
402
424
|
}): JSX.Element {
|
|
425
|
+
let tabRef: HTMLDivElement | undefined;
|
|
426
|
+
|
|
403
427
|
// Create tab aria props
|
|
404
428
|
const tabAria = createTab<unknown>(
|
|
405
429
|
{
|
|
@@ -411,7 +435,8 @@ function TabInner(props: {
|
|
|
411
435
|
return props.ariaProps['aria-label'];
|
|
412
436
|
},
|
|
413
437
|
},
|
|
414
|
-
props.state
|
|
438
|
+
props.state,
|
|
439
|
+
() => tabRef ?? null
|
|
415
440
|
);
|
|
416
441
|
|
|
417
442
|
// Create hover
|
|
@@ -442,32 +467,39 @@ function TabInner(props: {
|
|
|
442
467
|
renderValues
|
|
443
468
|
);
|
|
444
469
|
|
|
470
|
+
const selectionIndicatorContext = createMemo<SelectionIndicatorContextValue>(() => ({
|
|
471
|
+
isSelected: tabAria.isSelected,
|
|
472
|
+
}));
|
|
473
|
+
|
|
445
474
|
return (
|
|
446
|
-
<
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
475
|
+
<SelectionIndicatorContext.Provider value={selectionIndicatorContext()}>
|
|
476
|
+
<div
|
|
477
|
+
ref={tabRef}
|
|
478
|
+
id={tabAria.tabProps.id}
|
|
479
|
+
role={tabAria.tabProps.role}
|
|
480
|
+
aria-selected={tabAria.isSelected()}
|
|
481
|
+
aria-disabled={tabAria.isDisabled() || undefined}
|
|
482
|
+
aria-controls={tabAria.isSelected() ? tabAria.tabProps['aria-controls'] : undefined}
|
|
483
|
+
aria-label={tabAria.tabProps['aria-label']}
|
|
484
|
+
tabIndex={tabAria.isSelected() && !tabAria.isDisabled() ? 0 : -1}
|
|
485
|
+
class={renderProps.class()}
|
|
486
|
+
style={renderProps.style()}
|
|
487
|
+
onKeyDown={tabAria.tabProps.onKeyDown}
|
|
488
|
+
onMouseDown={tabAria.tabProps.onMouseDown}
|
|
489
|
+
onPointerDown={tabAria.tabProps.onPointerDown}
|
|
490
|
+
onClick={tabAria.tabProps.onClick}
|
|
491
|
+
onFocus={tabAria.tabProps.onFocus}
|
|
492
|
+
{...hoverProps}
|
|
493
|
+
data-selected={tabAria.isSelected() || undefined}
|
|
494
|
+
data-focused={tabAria.isFocused() || undefined}
|
|
495
|
+
data-focus-visible={tabAria.isFocusVisible() || undefined}
|
|
496
|
+
data-pressed={tabAria.isPressed() || undefined}
|
|
497
|
+
data-hovered={isHovered() || undefined}
|
|
498
|
+
data-disabled={tabAria.isDisabled() || undefined}
|
|
499
|
+
>
|
|
500
|
+
{renderProps.renderChildren()}
|
|
501
|
+
</div>
|
|
502
|
+
</SelectionIndicatorContext.Provider>
|
|
471
503
|
);
|
|
472
504
|
}
|
|
473
505
|
|
|
@@ -550,3 +582,4 @@ export function TabPanel(props: TabPanelProps): JSX.Element {
|
|
|
550
582
|
Tabs.List = TabList;
|
|
551
583
|
Tabs.Tab = Tab;
|
|
552
584
|
Tabs.Panel = TabPanel;
|
|
585
|
+
Tabs.SelectionIndicator = SelectionIndicator;
|
package/src/TagGroup.tsx
CHANGED
|
@@ -39,6 +39,11 @@ import {
|
|
|
39
39
|
filterDOMProps,
|
|
40
40
|
dataAttr,
|
|
41
41
|
} from './utils';
|
|
42
|
+
import { SharedElementTransition } from './SharedElementTransition';
|
|
43
|
+
import {
|
|
44
|
+
SelectionIndicatorContext,
|
|
45
|
+
type SelectionIndicatorContextValue,
|
|
46
|
+
} from './SelectionIndicator';
|
|
42
47
|
|
|
43
48
|
// ============================================
|
|
44
49
|
// TYPES
|
|
@@ -53,7 +58,8 @@ export interface TagGroupRenderProps {
|
|
|
53
58
|
|
|
54
59
|
export interface TagGroupProps
|
|
55
60
|
extends Omit<AriaTagGroupProps, 'id'>,
|
|
56
|
-
SlotProps
|
|
61
|
+
SlotProps,
|
|
62
|
+
Omit<JSX.HTMLAttributes<HTMLDivElement>, 'class' | 'style' | 'children'> {
|
|
57
63
|
/** The children of the component. */
|
|
58
64
|
children?: JSX.Element;
|
|
59
65
|
/** The CSS className for the element. */
|
|
@@ -69,7 +75,7 @@ export interface TagListRenderProps {
|
|
|
69
75
|
isFocused: boolean;
|
|
70
76
|
}
|
|
71
77
|
|
|
72
|
-
export interface TagListProps<T> extends SlotProps {
|
|
78
|
+
export interface TagListProps<T> extends SlotProps, Omit<JSX.HTMLAttributes<HTMLDivElement>, 'class' | 'style' | 'children' | 'onSelectionChange'> {
|
|
73
79
|
/** The items to display in the tag list. */
|
|
74
80
|
items: T[];
|
|
75
81
|
/** Function to render each item. */
|
|
@@ -121,6 +127,8 @@ export interface TagRenderProps {
|
|
|
121
127
|
allowsRemoving: boolean;
|
|
122
128
|
/** The selection mode. */
|
|
123
129
|
selectionMode: SelectionMode;
|
|
130
|
+
/** Props for the remove button when removal is allowed. */
|
|
131
|
+
removeButtonProps: Record<string, unknown>;
|
|
124
132
|
}
|
|
125
133
|
|
|
126
134
|
export interface TagProps extends SlotProps {
|
|
@@ -145,10 +153,17 @@ export interface TagProps extends SlotProps {
|
|
|
145
153
|
interface TagGroupContextValue {
|
|
146
154
|
state: ListState;
|
|
147
155
|
onRemove?: (keys: Set<Key>) => void;
|
|
156
|
+
isDisabled?: boolean;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
interface TagContextValue {
|
|
160
|
+
removeButtonProps: Record<string, unknown>;
|
|
161
|
+
allowsRemoving: boolean;
|
|
148
162
|
}
|
|
149
163
|
|
|
150
164
|
export const TagGroupContext = createContext<TagGroupContextValue | null>(null);
|
|
151
165
|
export const TagListStateContext = createContext<ListState | null>(null);
|
|
166
|
+
export const TagContext = createContext<TagContextValue | null>(null);
|
|
152
167
|
|
|
153
168
|
export function useTagGroupContext(): TagGroupContextValue | null {
|
|
154
169
|
return useContext(TagGroupContext);
|
|
@@ -172,15 +187,17 @@ export function useTagGroupContext(): TagGroupContextValue | null {
|
|
|
172
187
|
* ```
|
|
173
188
|
*/
|
|
174
189
|
export function TagGroup(props: TagGroupProps): JSX.Element {
|
|
175
|
-
const [local] = splitProps(props, [
|
|
190
|
+
const [local, domProps] = splitProps(props, [
|
|
176
191
|
'class',
|
|
177
192
|
'style',
|
|
178
193
|
'slot',
|
|
194
|
+
'children',
|
|
179
195
|
]);
|
|
180
196
|
|
|
181
197
|
// We need TagList to provide the state, so TagGroup just provides context
|
|
182
198
|
return (
|
|
183
199
|
<div
|
|
200
|
+
{...domProps}
|
|
184
201
|
class={typeof local.class === 'string' ? local.class : 'solidaria-TagGroup'}
|
|
185
202
|
style={typeof local.style === 'object' ? local.style : undefined}
|
|
186
203
|
slot={local.slot}
|
|
@@ -198,12 +215,13 @@ export function TagGroup(props: TagGroupProps): JSX.Element {
|
|
|
198
215
|
* TagList contains the list of tags within a TagGroup.
|
|
199
216
|
*/
|
|
200
217
|
export function TagList<T extends { id?: Key; key?: Key }>(props: TagListProps<T>): JSX.Element {
|
|
201
|
-
const [local] = splitProps(props, [
|
|
218
|
+
const [local, domProps] = splitProps(props, [
|
|
202
219
|
'items',
|
|
203
220
|
'class',
|
|
204
221
|
'style',
|
|
205
222
|
'slot',
|
|
206
223
|
'renderEmptyState',
|
|
224
|
+
'children',
|
|
207
225
|
'selectionMode',
|
|
208
226
|
'selectionBehavior',
|
|
209
227
|
'selectedKeys',
|
|
@@ -245,8 +263,7 @@ export function TagList<T extends { id?: Key; key?: Key }>(props: TagListProps<T
|
|
|
245
263
|
// Create tag group accessibility props
|
|
246
264
|
const tagGroupAria = createTagGroup(
|
|
247
265
|
{
|
|
248
|
-
get label() { return local.label; },
|
|
249
|
-
get 'aria-label'() { return local['aria-label']; },
|
|
266
|
+
get 'aria-label'() { return local['aria-label'] ?? (!local['aria-labelledby'] ? local.label : undefined); },
|
|
250
267
|
get 'aria-labelledby'() { return local['aria-labelledby']; },
|
|
251
268
|
get 'aria-describedby'() { return local['aria-describedby']; },
|
|
252
269
|
get isDisabled() { return local.isDisabled; },
|
|
@@ -279,6 +296,7 @@ export function TagList<T extends { id?: Key; key?: Key }>(props: TagListProps<T
|
|
|
279
296
|
const contextValue: TagGroupContextValue = {
|
|
280
297
|
state,
|
|
281
298
|
get onRemove() { return local.onRemove; },
|
|
299
|
+
get isDisabled() { return local.isDisabled; },
|
|
282
300
|
};
|
|
283
301
|
|
|
284
302
|
return (
|
|
@@ -286,22 +304,36 @@ export function TagList<T extends { id?: Key; key?: Key }>(props: TagListProps<T
|
|
|
286
304
|
<TagListStateContext.Provider value={state}>
|
|
287
305
|
<div
|
|
288
306
|
ref={setGridRef}
|
|
307
|
+
{...domProps}
|
|
289
308
|
{...tagGroupAria.gridProps}
|
|
290
309
|
class={renderProps.class()}
|
|
291
310
|
style={renderProps.style()}
|
|
292
|
-
onFocus={() =>
|
|
293
|
-
|
|
311
|
+
onFocus={() => {
|
|
312
|
+
setIsFocused(true);
|
|
313
|
+
state.setFocused(true);
|
|
314
|
+
}}
|
|
315
|
+
onBlur={(e) => {
|
|
316
|
+
const nextTarget = e.relatedTarget as Node | null;
|
|
317
|
+
if (nextTarget && e.currentTarget.contains(nextTarget)) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
setIsFocused(false);
|
|
322
|
+
state.setFocused(false);
|
|
323
|
+
}}
|
|
294
324
|
data-empty={dataAttr(local.items.length === 0)}
|
|
295
325
|
data-focused={dataAttr(isFocused())}
|
|
296
326
|
>
|
|
297
|
-
<
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
{
|
|
303
|
-
|
|
304
|
-
|
|
327
|
+
<SharedElementTransition>
|
|
328
|
+
<Show
|
|
329
|
+
when={local.items.length > 0}
|
|
330
|
+
fallback={local.renderEmptyState?.()}
|
|
331
|
+
>
|
|
332
|
+
<For each={local.items}>
|
|
333
|
+
{(item) => props.children(item)}
|
|
334
|
+
</For>
|
|
335
|
+
</Show>
|
|
336
|
+
</SharedElementTransition>
|
|
305
337
|
</div>
|
|
306
338
|
</TagListStateContext.Provider>
|
|
307
339
|
</TagGroupContext.Provider>
|
|
@@ -326,6 +358,7 @@ export function Tag(props: TagProps): JSX.Element {
|
|
|
326
358
|
]);
|
|
327
359
|
|
|
328
360
|
const state = useContext(TagListStateContext);
|
|
361
|
+
const groupContext = useContext(TagGroupContext);
|
|
329
362
|
|
|
330
363
|
// Create a ref for the tag
|
|
331
364
|
const [tagRef, setTagRef] = createSignal<HTMLDivElement | null>(null);
|
|
@@ -334,13 +367,28 @@ export function Tag(props: TagProps): JSX.Element {
|
|
|
334
367
|
const tagAria = createTag(
|
|
335
368
|
{
|
|
336
369
|
get key() { return local.id; },
|
|
337
|
-
get isDisabled() { return local.isDisabled; },
|
|
370
|
+
get isDisabled() { return local.isDisabled || groupContext?.isDisabled; },
|
|
338
371
|
get textValue() { return local.textValue; },
|
|
339
372
|
},
|
|
340
373
|
state!,
|
|
341
374
|
tagRef
|
|
342
375
|
);
|
|
343
376
|
|
|
377
|
+
const normalizedRemoveButtonProps = createMemo<Record<string, unknown>>(() => {
|
|
378
|
+
const raw = tagAria.removeButtonProps;
|
|
379
|
+
const rawHandler = typeof raw.onPress === 'function' ? (raw.onPress as () => void) : undefined;
|
|
380
|
+
return {
|
|
381
|
+
...raw,
|
|
382
|
+
onPress: () => {
|
|
383
|
+
if (!tagAria.isDisabled && groupContext?.onRemove) {
|
|
384
|
+
groupContext.onRemove(new Set([local.id]));
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
rawHandler?.();
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
});
|
|
391
|
+
|
|
344
392
|
// Render props values
|
|
345
393
|
const renderValues = createMemo<TagRenderProps>(() => ({
|
|
346
394
|
isSelected: tagAria.isSelected,
|
|
@@ -349,6 +397,7 @@ export function Tag(props: TagProps): JSX.Element {
|
|
|
349
397
|
isPressed: tagAria.isPressed,
|
|
350
398
|
allowsRemoving: tagAria.allowsRemoving,
|
|
351
399
|
selectionMode: state?.selectionMode() ?? 'none',
|
|
400
|
+
removeButtonProps: normalizedRemoveButtonProps(),
|
|
352
401
|
}));
|
|
353
402
|
|
|
354
403
|
// Resolve render props
|
|
@@ -362,26 +411,39 @@ export function Tag(props: TagProps): JSX.Element {
|
|
|
362
411
|
renderValues
|
|
363
412
|
);
|
|
364
413
|
|
|
414
|
+
const selectionIndicatorContext = createMemo<SelectionIndicatorContextValue>(() => ({
|
|
415
|
+
isSelected: () => tagAria.isSelected,
|
|
416
|
+
}));
|
|
417
|
+
|
|
365
418
|
// Filter DOM props
|
|
366
419
|
const domProps = createMemo(() => filterDOMProps(rest, { global: true }));
|
|
367
420
|
|
|
368
421
|
return (
|
|
369
|
-
<
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
422
|
+
<SelectionIndicatorContext.Provider value={selectionIndicatorContext()}>
|
|
423
|
+
<TagContext.Provider
|
|
424
|
+
value={{
|
|
425
|
+
get removeButtonProps() { return normalizedRemoveButtonProps(); },
|
|
426
|
+
get allowsRemoving() { return tagAria.allowsRemoving; },
|
|
427
|
+
}}
|
|
428
|
+
>
|
|
429
|
+
<div
|
|
430
|
+
ref={setTagRef}
|
|
431
|
+
{...domProps()}
|
|
432
|
+
{...tagAria.rowProps}
|
|
433
|
+
class={renderProps.class()}
|
|
434
|
+
style={renderProps.style()}
|
|
435
|
+
data-selected={dataAttr(tagAria.isSelected)}
|
|
436
|
+
data-disabled={dataAttr(tagAria.isDisabled)}
|
|
437
|
+
data-focused={dataAttr(tagAria.isFocused)}
|
|
438
|
+
data-pressed={dataAttr(tagAria.isPressed)}
|
|
439
|
+
data-allows-removing={dataAttr(tagAria.allowsRemoving)}
|
|
440
|
+
>
|
|
441
|
+
<div {...tagAria.gridCellProps} style={{ display: 'contents' }}>
|
|
442
|
+
{renderProps.renderChildren()}
|
|
443
|
+
</div>
|
|
444
|
+
</div>
|
|
445
|
+
</TagContext.Provider>
|
|
446
|
+
</SelectionIndicatorContext.Provider>
|
|
385
447
|
);
|
|
386
448
|
}
|
|
387
449
|
|
|
@@ -396,6 +458,8 @@ export interface TagRemoveButtonProps {
|
|
|
396
458
|
class?: string;
|
|
397
459
|
/** The inline style for the element. */
|
|
398
460
|
style?: JSX.CSSProperties;
|
|
461
|
+
/** Explicit button props from Tag render props. */
|
|
462
|
+
buttonProps?: Record<string, unknown>;
|
|
399
463
|
}
|
|
400
464
|
|
|
401
465
|
/**
|
|
@@ -403,14 +467,35 @@ export interface TagRemoveButtonProps {
|
|
|
403
467
|
* It should be placed inside a Tag component.
|
|
404
468
|
*/
|
|
405
469
|
export function TagRemoveButton(props: TagRemoveButtonProps): JSX.Element {
|
|
406
|
-
|
|
407
|
-
|
|
470
|
+
const tagContext = useContext(TagContext);
|
|
471
|
+
const getRemoveButtonProps = () => props.buttonProps ?? tagContext?.removeButtonProps ?? {};
|
|
472
|
+
const getIsDisabled = () => Boolean(getRemoveButtonProps().isDisabled);
|
|
473
|
+
const rawId = getRemoveButtonProps().id;
|
|
474
|
+
const rawAriaLabel = getRemoveButtonProps()['aria-label'];
|
|
475
|
+
const rawAriaLabelledBy = getRemoveButtonProps()['aria-labelledby'];
|
|
476
|
+
const buttonId: string | undefined = typeof rawId === 'string' ? rawId : undefined;
|
|
477
|
+
const ariaLabel: string = typeof rawAriaLabel === 'string' ? rawAriaLabel : 'Remove';
|
|
478
|
+
const ariaLabelledBy: string | undefined = typeof rawAriaLabelledBy === 'string' ? rawAriaLabelledBy : undefined;
|
|
479
|
+
|
|
480
|
+
const handleClick: JSX.EventHandler<HTMLButtonElement, MouseEvent> = (event) => {
|
|
481
|
+
event.stopPropagation();
|
|
482
|
+
const handler = getRemoveButtonProps().onPress;
|
|
483
|
+
if (typeof handler === 'function' && !getIsDisabled()) {
|
|
484
|
+
(handler as () => void)();
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
|
|
408
488
|
return (
|
|
409
489
|
<button
|
|
410
490
|
type="button"
|
|
411
491
|
class={props.class ?? 'solidaria-TagRemoveButton'}
|
|
412
492
|
style={props.style}
|
|
413
|
-
|
|
493
|
+
id={buttonId}
|
|
494
|
+
aria-label={ariaLabel}
|
|
495
|
+
aria-labelledby={ariaLabelledBy}
|
|
496
|
+
disabled={getIsDisabled()}
|
|
497
|
+
data-allows-removing={dataAttr(tagContext?.allowsRemoving ?? false)}
|
|
498
|
+
onClick={handleClick}
|
|
414
499
|
>
|
|
415
500
|
{props.children ?? '×'}
|
|
416
501
|
</button>
|
package/src/Text.tsx
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type JSX, createContext } from 'solid-js';
|
|
2
|
+
import type { SlotProps } from './utils';
|
|
3
|
+
|
|
4
|
+
export interface TextProps extends SlotProps {
|
|
5
|
+
children?: JSX.Element;
|
|
6
|
+
class?: string;
|
|
7
|
+
style?: JSX.CSSProperties;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const TextContext = createContext<null>(null);
|
|
11
|
+
|
|
12
|
+
export function Text(props: TextProps): JSX.Element {
|
|
13
|
+
return (
|
|
14
|
+
<span class={props.class ?? 'solidaria-Text'} style={props.style}>
|
|
15
|
+
{props.children}
|
|
16
|
+
</span>
|
|
17
|
+
);
|
|
18
|
+
}
|
package/src/TextField.tsx
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
createTextField,
|
|
17
17
|
createFocusRing,
|
|
18
18
|
createHover,
|
|
19
|
+
mergeProps,
|
|
19
20
|
type AriaTextFieldProps,
|
|
20
21
|
} from '@proyecto-viviana/solidaria';
|
|
21
22
|
import { createTextFieldState } from '@proyecto-viviana/solid-stately';
|
|
@@ -73,6 +74,10 @@ export interface TextFieldContextValue {
|
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
export const TextFieldContext = createContext<TextFieldContextValue | null>(null);
|
|
77
|
+
export const LabelContext = TextFieldContext;
|
|
78
|
+
export const InputContext = TextFieldContext;
|
|
79
|
+
export const TextAreaContext = TextFieldContext;
|
|
80
|
+
export const FieldInputContext = TextFieldContext;
|
|
76
81
|
|
|
77
82
|
// ============================================
|
|
78
83
|
// SUB-COMPONENTS
|
|
@@ -238,15 +243,27 @@ export function TextField(props: TextFieldProps): JSX.Element {
|
|
|
238
243
|
return rest;
|
|
239
244
|
};
|
|
240
245
|
|
|
241
|
-
// Context value for sub-components
|
|
242
|
-
//
|
|
243
|
-
// immediately when children access the context
|
|
246
|
+
// Context value for sub-components.
|
|
247
|
+
// Use property getters so sub-components always read the latest aria/focus state.
|
|
244
248
|
const contextValue: TextFieldContextValue = {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
249
|
+
get labelProps() {
|
|
250
|
+
return textFieldAria.labelProps as JSX.LabelHTMLAttributes<HTMLLabelElement>;
|
|
251
|
+
},
|
|
252
|
+
get inputProps() {
|
|
253
|
+
return mergeProps(
|
|
254
|
+
textFieldAria.inputProps as Record<string, unknown>,
|
|
255
|
+
focusProps as Record<string, unknown>
|
|
256
|
+
) as JSX.InputHTMLAttributes<HTMLInputElement>;
|
|
257
|
+
},
|
|
258
|
+
get descriptionProps() {
|
|
259
|
+
return textFieldAria.descriptionProps as JSX.HTMLAttributes<HTMLElement>;
|
|
260
|
+
},
|
|
261
|
+
get errorMessageProps() {
|
|
262
|
+
return textFieldAria.errorMessageProps as JSX.HTMLAttributes<HTMLElement>;
|
|
263
|
+
},
|
|
264
|
+
get isInvalid() {
|
|
265
|
+
return textFieldAria.isInvalid;
|
|
266
|
+
},
|
|
250
267
|
};
|
|
251
268
|
|
|
252
269
|
return (
|