@proyecto-viviana/solidaria-components 0.1.3 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Color.d.ts +6 -2
- package/dist/Color.d.ts.map +1 -1
- package/dist/ComboBox.d.ts +3 -3
- package/dist/ComboBox.d.ts.map +1 -1
- package/dist/GridList.d.ts +2 -2
- package/dist/GridList.d.ts.map +1 -1
- package/dist/ListBox.d.ts +5 -5
- package/dist/ListBox.d.ts.map +1 -1
- package/dist/Menu.d.ts +3 -3
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Select.d.ts +3 -3
- package/dist/Select.d.ts.map +1 -1
- package/dist/Table.d.ts +2 -2
- package/dist/Table.d.ts.map +1 -1
- package/dist/Tabs.d.ts +1 -1
- package/dist/Tabs.d.ts.map +1 -1
- package/dist/index.js +15 -15
- package/dist/index.js.map +2 -2
- package/dist/index.ssr.js +15 -15
- package/dist/index.ssr.js.map +2 -2
- package/package.json +8 -10
- package/src/Autocomplete.tsx +0 -174
- package/src/Breadcrumbs.tsx +0 -264
- package/src/Button.tsx +0 -238
- package/src/Calendar.tsx +0 -471
- package/src/Checkbox.tsx +0 -387
- package/src/Color.tsx +0 -1370
- package/src/ComboBox.tsx +0 -824
- package/src/DateField.tsx +0 -337
- package/src/DatePicker.tsx +0 -367
- package/src/Dialog.tsx +0 -262
- package/src/Disclosure.tsx +0 -439
- package/src/GridList.tsx +0 -511
- package/src/Landmark.tsx +0 -203
- package/src/Link.tsx +0 -201
- package/src/ListBox.tsx +0 -346
- package/src/Menu.tsx +0 -544
- package/src/Meter.tsx +0 -157
- package/src/Modal.tsx +0 -433
- package/src/NumberField.tsx +0 -542
- package/src/Popover.tsx +0 -540
- package/src/ProgressBar.tsx +0 -162
- package/src/RadioGroup.tsx +0 -356
- package/src/RangeCalendar.tsx +0 -462
- package/src/SearchField.tsx +0 -479
- package/src/Select.tsx +0 -734
- package/src/Separator.tsx +0 -130
- package/src/Slider.tsx +0 -500
- package/src/Switch.tsx +0 -213
- package/src/Table.tsx +0 -857
- package/src/Tabs.tsx +0 -552
- package/src/TagGroup.tsx +0 -421
- package/src/TextField.tsx +0 -271
- package/src/TimeField.tsx +0 -455
- package/src/Toast.tsx +0 -503
- package/src/Toolbar.tsx +0 -160
- package/src/Tooltip.tsx +0 -423
- package/src/Tree.tsx +0 -551
- package/src/VisuallyHidden.tsx +0 -60
- package/src/contexts.ts +0 -74
- package/src/index.ts +0 -620
- package/src/utils.tsx +0 -329
package/src/Tabs.tsx
DELETED
|
@@ -1,552 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tabs component for solidaria-components
|
|
3
|
-
*
|
|
4
|
-
* A pre-wired headless tabs component that combines state + aria hooks.
|
|
5
|
-
* Port of react-aria-components/src/Tabs.tsx
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
type JSX,
|
|
10
|
-
createContext,
|
|
11
|
-
createMemo,
|
|
12
|
-
splitProps,
|
|
13
|
-
useContext,
|
|
14
|
-
For,
|
|
15
|
-
Show,
|
|
16
|
-
} from 'solid-js';
|
|
17
|
-
import {
|
|
18
|
-
createTabList,
|
|
19
|
-
createTab,
|
|
20
|
-
createTabPanel,
|
|
21
|
-
createFocusRing,
|
|
22
|
-
createHover,
|
|
23
|
-
type AriaTabListProps,
|
|
24
|
-
type AriaTabProps,
|
|
25
|
-
type AriaTabPanelProps,
|
|
26
|
-
} from '@proyecto-viviana/solidaria';
|
|
27
|
-
import {
|
|
28
|
-
createTabListState,
|
|
29
|
-
type TabListState,
|
|
30
|
-
type Key,
|
|
31
|
-
type TabOrientation,
|
|
32
|
-
type KeyboardActivation,
|
|
33
|
-
} from '@proyecto-viviana/solid-stately';
|
|
34
|
-
import {
|
|
35
|
-
type RenderChildren,
|
|
36
|
-
type ClassNameOrFunction,
|
|
37
|
-
type StyleOrFunction,
|
|
38
|
-
type SlotProps,
|
|
39
|
-
useRenderProps,
|
|
40
|
-
filterDOMProps,
|
|
41
|
-
} from './utils';
|
|
42
|
-
|
|
43
|
-
// ============================================
|
|
44
|
-
// TYPES
|
|
45
|
-
// ============================================
|
|
46
|
-
|
|
47
|
-
export interface TabsRenderProps {
|
|
48
|
-
/** The orientation of the tabs. */
|
|
49
|
-
orientation: TabOrientation;
|
|
50
|
-
/** Whether the tabs are disabled. */
|
|
51
|
-
isDisabled: boolean;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export interface TabsProps<T> extends SlotProps {
|
|
55
|
-
/** The items to render in the tab list. */
|
|
56
|
-
items?: T[];
|
|
57
|
-
/** Function to get the key from an item. */
|
|
58
|
-
getKey?: (item: T) => Key;
|
|
59
|
-
/** Function to get the text value from an item. */
|
|
60
|
-
getTextValue?: (item: T) => string;
|
|
61
|
-
/** Function to check if an item is disabled. */
|
|
62
|
-
getDisabled?: (item: T) => boolean;
|
|
63
|
-
/** Keys of disabled tabs. */
|
|
64
|
-
disabledKeys?: Iterable<Key>;
|
|
65
|
-
/** The currently selected tab key (controlled). */
|
|
66
|
-
selectedKey?: Key | null;
|
|
67
|
-
/** The default selected tab key (uncontrolled). */
|
|
68
|
-
defaultSelectedKey?: Key;
|
|
69
|
-
/** Handler for tab selection changes. */
|
|
70
|
-
onSelectionChange?: (key: Key) => void;
|
|
71
|
-
/** Whether the tabs are disabled. */
|
|
72
|
-
isDisabled?: boolean;
|
|
73
|
-
/** The keyboard activation mode. */
|
|
74
|
-
keyboardActivation?: KeyboardActivation;
|
|
75
|
-
/** The orientation of the tabs. */
|
|
76
|
-
orientation?: TabOrientation;
|
|
77
|
-
/** The children of the component. */
|
|
78
|
-
children?: RenderChildren<TabsRenderProps>;
|
|
79
|
-
/** The CSS className for the element. */
|
|
80
|
-
class?: ClassNameOrFunction<TabsRenderProps>;
|
|
81
|
-
/** The inline style for the element. */
|
|
82
|
-
style?: StyleOrFunction<TabsRenderProps>;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export interface TabListRenderProps {
|
|
86
|
-
/** The orientation of the tab list. */
|
|
87
|
-
orientation: TabOrientation;
|
|
88
|
-
/** Whether the tab list is disabled. */
|
|
89
|
-
isDisabled: boolean;
|
|
90
|
-
/** Whether the tab list has focus. */
|
|
91
|
-
isFocused: boolean;
|
|
92
|
-
/** Whether the tab list has visible focus. */
|
|
93
|
-
isFocusVisible: boolean;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export interface TabListProps<T> extends Omit<AriaTabListProps, 'children'>, SlotProps {
|
|
97
|
-
/** The children of the tab list - render function for each item. */
|
|
98
|
-
children: (item: T) => JSX.Element;
|
|
99
|
-
/** The CSS className for the element. */
|
|
100
|
-
class?: ClassNameOrFunction<TabListRenderProps>;
|
|
101
|
-
/** The inline style for the element. */
|
|
102
|
-
style?: StyleOrFunction<TabListRenderProps>;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export interface TabRenderProps {
|
|
106
|
-
/** Whether the tab is selected. */
|
|
107
|
-
isSelected: boolean;
|
|
108
|
-
/** Whether the tab is focused. */
|
|
109
|
-
isFocused: boolean;
|
|
110
|
-
/** Whether the tab has visible focus ring. */
|
|
111
|
-
isFocusVisible: boolean;
|
|
112
|
-
/** Whether the tab is pressed. */
|
|
113
|
-
isPressed: boolean;
|
|
114
|
-
/** Whether the tab is hovered. */
|
|
115
|
-
isHovered: boolean;
|
|
116
|
-
/** Whether the tab is disabled. */
|
|
117
|
-
isDisabled: boolean;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export interface TabProps extends Omit<AriaTabProps, 'key'>, SlotProps {
|
|
121
|
-
/** The unique key for the tab. */
|
|
122
|
-
id: Key;
|
|
123
|
-
/** The children of the tab. */
|
|
124
|
-
children?: RenderChildren<TabRenderProps>;
|
|
125
|
-
/** The CSS className for the element. */
|
|
126
|
-
class?: ClassNameOrFunction<TabRenderProps>;
|
|
127
|
-
/** The inline style for the element. */
|
|
128
|
-
style?: StyleOrFunction<TabRenderProps>;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export interface TabPanelRenderProps {
|
|
132
|
-
/** Whether the panel is the selected one. */
|
|
133
|
-
isSelected: boolean;
|
|
134
|
-
/** Whether the panel is focused. */
|
|
135
|
-
isFocused: boolean;
|
|
136
|
-
/** Whether the panel has visible focus ring. */
|
|
137
|
-
isFocusVisible: boolean;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
export interface TabPanelProps extends AriaTabPanelProps, SlotProps {
|
|
141
|
-
/** The children of the tab panel. */
|
|
142
|
-
children?: RenderChildren<TabPanelRenderProps>;
|
|
143
|
-
/** The CSS className for the element. */
|
|
144
|
-
class?: ClassNameOrFunction<TabPanelRenderProps>;
|
|
145
|
-
/** The inline style for the element. */
|
|
146
|
-
style?: StyleOrFunction<TabPanelRenderProps>;
|
|
147
|
-
/** Whether to keep the panel mounted when not selected. */
|
|
148
|
-
shouldForceMount?: boolean;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// ============================================
|
|
152
|
-
// CONTEXT
|
|
153
|
-
// ============================================
|
|
154
|
-
|
|
155
|
-
interface TabsContextValue<T> {
|
|
156
|
-
state: TabListState<T>;
|
|
157
|
-
items: T[];
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
export const TabsContext = createContext<TabsContextValue<unknown> | null>(null);
|
|
161
|
-
export const TabsStateContext = createContext<TabListState<unknown> | null>(null);
|
|
162
|
-
|
|
163
|
-
// ============================================
|
|
164
|
-
// COMPONENTS
|
|
165
|
-
// ============================================
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Tabs provide a way to organize content into multiple sections, with only one section visible at a time.
|
|
169
|
-
*/
|
|
170
|
-
export function Tabs<T>(props: TabsProps<T>): JSX.Element {
|
|
171
|
-
const [local, stateProps, rest] = splitProps(
|
|
172
|
-
props,
|
|
173
|
-
['class', 'style', 'slot'],
|
|
174
|
-
['items', 'getKey', 'getTextValue', 'getDisabled', 'disabledKeys', 'selectedKey', 'defaultSelectedKey', 'onSelectionChange', 'isDisabled', 'keyboardActivation', 'orientation']
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
// Create tab list state
|
|
178
|
-
const state = createTabListState<T>({
|
|
179
|
-
get items() {
|
|
180
|
-
return stateProps.items;
|
|
181
|
-
},
|
|
182
|
-
get getKey() {
|
|
183
|
-
return stateProps.getKey;
|
|
184
|
-
},
|
|
185
|
-
get getTextValue() {
|
|
186
|
-
return stateProps.getTextValue;
|
|
187
|
-
},
|
|
188
|
-
get getDisabled() {
|
|
189
|
-
return stateProps.getDisabled;
|
|
190
|
-
},
|
|
191
|
-
get disabledKeys() {
|
|
192
|
-
return stateProps.disabledKeys;
|
|
193
|
-
},
|
|
194
|
-
get selectedKey() {
|
|
195
|
-
return stateProps.selectedKey;
|
|
196
|
-
},
|
|
197
|
-
get defaultSelectedKey() {
|
|
198
|
-
return stateProps.defaultSelectedKey;
|
|
199
|
-
},
|
|
200
|
-
get onSelectionChange() {
|
|
201
|
-
return stateProps.onSelectionChange;
|
|
202
|
-
},
|
|
203
|
-
get isDisabled() {
|
|
204
|
-
return stateProps.isDisabled;
|
|
205
|
-
},
|
|
206
|
-
get keyboardActivation() {
|
|
207
|
-
return stateProps.keyboardActivation;
|
|
208
|
-
},
|
|
209
|
-
get orientation() {
|
|
210
|
-
return stateProps.orientation;
|
|
211
|
-
},
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
// Render props values
|
|
215
|
-
const renderValues = createMemo<TabsRenderProps>(() => ({
|
|
216
|
-
orientation: state.orientation(),
|
|
217
|
-
isDisabled: state.isDisabled(),
|
|
218
|
-
}));
|
|
219
|
-
|
|
220
|
-
// Resolve render props
|
|
221
|
-
const renderProps = useRenderProps(
|
|
222
|
-
{
|
|
223
|
-
class: local.class,
|
|
224
|
-
style: local.style,
|
|
225
|
-
children: props.children,
|
|
226
|
-
defaultClassName: 'solidaria-Tabs',
|
|
227
|
-
},
|
|
228
|
-
renderValues
|
|
229
|
-
);
|
|
230
|
-
|
|
231
|
-
// Filter DOM props
|
|
232
|
-
const domProps = createMemo(() => filterDOMProps(rest as Record<string, unknown>, { global: true }));
|
|
233
|
-
|
|
234
|
-
return (
|
|
235
|
-
<TabsContext.Provider value={{ state, items: stateProps.items ?? [] }}>
|
|
236
|
-
<TabsStateContext.Provider value={state}>
|
|
237
|
-
<div
|
|
238
|
-
{...domProps()}
|
|
239
|
-
class={renderProps.class()}
|
|
240
|
-
style={renderProps.style()}
|
|
241
|
-
data-orientation={state.orientation()}
|
|
242
|
-
data-disabled={state.isDisabled() || undefined}
|
|
243
|
-
>
|
|
244
|
-
{props.children as JSX.Element}
|
|
245
|
-
</div>
|
|
246
|
-
</TabsStateContext.Provider>
|
|
247
|
-
</TabsContext.Provider>
|
|
248
|
-
);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* A TabList contains Tab elements that represent the available tabs.
|
|
253
|
-
*/
|
|
254
|
-
export function TabList<T>(props: TabListProps<T>): JSX.Element {
|
|
255
|
-
const [local, ariaProps] = splitProps(props, [
|
|
256
|
-
'class',
|
|
257
|
-
'style',
|
|
258
|
-
'slot',
|
|
259
|
-
]);
|
|
260
|
-
|
|
261
|
-
// Get state from context
|
|
262
|
-
const context = useContext(TabsContext);
|
|
263
|
-
|
|
264
|
-
return (
|
|
265
|
-
<Show
|
|
266
|
-
when={context}
|
|
267
|
-
fallback={<div class="solidaria-TabList" role="tablist" />}
|
|
268
|
-
>
|
|
269
|
-
{(ctx) => (
|
|
270
|
-
<TabListInner
|
|
271
|
-
context={ctx()}
|
|
272
|
-
local={local}
|
|
273
|
-
ariaProps={ariaProps}
|
|
274
|
-
children={props.children}
|
|
275
|
-
/>
|
|
276
|
-
)}
|
|
277
|
-
</Show>
|
|
278
|
-
);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/** Inner TabList component that has access to context */
|
|
282
|
-
function TabListInner<T>(props: {
|
|
283
|
-
context: TabsContextValue<unknown>;
|
|
284
|
-
local: { class?: ClassNameOrFunction<TabListRenderProps>; style?: StyleOrFunction<TabListRenderProps>; slot?: string };
|
|
285
|
-
ariaProps: Omit<TabListProps<T>, 'children' | 'class' | 'style' | 'slot'>;
|
|
286
|
-
children?: (item: T) => JSX.Element;
|
|
287
|
-
}): JSX.Element {
|
|
288
|
-
const state = props.context.state as TabListState<T>;
|
|
289
|
-
const items = props.context.items as T[];
|
|
290
|
-
|
|
291
|
-
// Create tab list aria props
|
|
292
|
-
const { tabListProps } = createTabList<T>(props.ariaProps as AriaTabListProps, state);
|
|
293
|
-
|
|
294
|
-
// Create focus ring
|
|
295
|
-
const { isFocused, isFocusVisible, focusProps } = createFocusRing();
|
|
296
|
-
|
|
297
|
-
// Render props values
|
|
298
|
-
const renderValues = createMemo<TabListRenderProps>(() => ({
|
|
299
|
-
orientation: state.orientation(),
|
|
300
|
-
isDisabled: state.isDisabled(),
|
|
301
|
-
isFocused: state.isFocused() || isFocused(),
|
|
302
|
-
isFocusVisible: isFocusVisible(),
|
|
303
|
-
}));
|
|
304
|
-
|
|
305
|
-
// Resolve render props
|
|
306
|
-
const renderProps = useRenderProps(
|
|
307
|
-
{
|
|
308
|
-
class: props.local.class,
|
|
309
|
-
style: props.local.style,
|
|
310
|
-
defaultClassName: 'solidaria-TabList',
|
|
311
|
-
},
|
|
312
|
-
renderValues
|
|
313
|
-
);
|
|
314
|
-
|
|
315
|
-
// Helper to safely call event handlers that may be bound tuples
|
|
316
|
-
const callHandler = <E extends Event>(
|
|
317
|
-
handler: ((e: E) => void) | [object, (e: E) => void] | undefined,
|
|
318
|
-
event: E
|
|
319
|
-
) => {
|
|
320
|
-
if (!handler) return;
|
|
321
|
-
if (Array.isArray(handler)) {
|
|
322
|
-
handler[1].call(handler[0], event);
|
|
323
|
-
} else {
|
|
324
|
-
handler(event);
|
|
325
|
-
}
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
// Combine event handlers
|
|
329
|
-
const handleKeyDown = (e: KeyboardEvent) => {
|
|
330
|
-
tabListProps.onKeyDown(e);
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
const handleFocus = (e: FocusEvent) => {
|
|
334
|
-
tabListProps.onFocus(e);
|
|
335
|
-
callHandler(focusProps.onFocus as any, e);
|
|
336
|
-
};
|
|
337
|
-
|
|
338
|
-
const handleBlur = (e: FocusEvent) => {
|
|
339
|
-
tabListProps.onBlur(e);
|
|
340
|
-
callHandler(focusProps.onBlur as any, e);
|
|
341
|
-
};
|
|
342
|
-
|
|
343
|
-
return (
|
|
344
|
-
<div
|
|
345
|
-
role={tabListProps.role}
|
|
346
|
-
aria-orientation={tabListProps['aria-orientation']}
|
|
347
|
-
aria-label={tabListProps['aria-label']}
|
|
348
|
-
aria-labelledby={tabListProps['aria-labelledby']}
|
|
349
|
-
aria-describedby={tabListProps['aria-describedby']}
|
|
350
|
-
class={renderProps.class()}
|
|
351
|
-
style={renderProps.style()}
|
|
352
|
-
onKeyDown={handleKeyDown}
|
|
353
|
-
onFocus={handleFocus}
|
|
354
|
-
onBlur={handleBlur}
|
|
355
|
-
data-focused={state.isFocused() || undefined}
|
|
356
|
-
data-focus-visible={isFocusVisible() || undefined}
|
|
357
|
-
data-orientation={state.orientation()}
|
|
358
|
-
data-disabled={state.isDisabled() || undefined}
|
|
359
|
-
>
|
|
360
|
-
<For each={items}>{(item) => props.children?.(item)}</For>
|
|
361
|
-
</div>
|
|
362
|
-
);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* A Tab represents an individual tab in a TabList.
|
|
367
|
-
*/
|
|
368
|
-
export function Tab(props: TabProps): JSX.Element {
|
|
369
|
-
const [local, ariaProps] = splitProps(props, [
|
|
370
|
-
'class',
|
|
371
|
-
'style',
|
|
372
|
-
'slot',
|
|
373
|
-
'id',
|
|
374
|
-
]);
|
|
375
|
-
|
|
376
|
-
// Get state from context
|
|
377
|
-
const context = useContext(TabsStateContext);
|
|
378
|
-
|
|
379
|
-
return (
|
|
380
|
-
<Show
|
|
381
|
-
when={context}
|
|
382
|
-
fallback={<div class="solidaria-Tab" role="tab" />}
|
|
383
|
-
>
|
|
384
|
-
{(state) => (
|
|
385
|
-
<TabInner
|
|
386
|
-
state={state()}
|
|
387
|
-
local={local}
|
|
388
|
-
ariaProps={ariaProps}
|
|
389
|
-
children={props.children}
|
|
390
|
-
/>
|
|
391
|
-
)}
|
|
392
|
-
</Show>
|
|
393
|
-
);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
/** Inner Tab component that has access to context */
|
|
397
|
-
function TabInner(props: {
|
|
398
|
-
state: TabListState<unknown>;
|
|
399
|
-
local: { class?: ClassNameOrFunction<TabRenderProps>; style?: StyleOrFunction<TabRenderProps>; slot?: string; id: Key };
|
|
400
|
-
ariaProps: Omit<TabProps, 'children' | 'class' | 'style' | 'slot' | 'id'>;
|
|
401
|
-
children?: RenderChildren<TabRenderProps>;
|
|
402
|
-
}): JSX.Element {
|
|
403
|
-
// Create tab aria props
|
|
404
|
-
const tabAria = createTab<unknown>(
|
|
405
|
-
{
|
|
406
|
-
key: props.local.id,
|
|
407
|
-
get isDisabled() {
|
|
408
|
-
return props.ariaProps.isDisabled;
|
|
409
|
-
},
|
|
410
|
-
get 'aria-label'() {
|
|
411
|
-
return props.ariaProps['aria-label'];
|
|
412
|
-
},
|
|
413
|
-
},
|
|
414
|
-
props.state
|
|
415
|
-
);
|
|
416
|
-
|
|
417
|
-
// Create hover
|
|
418
|
-
const { isHovered, hoverProps } = createHover({
|
|
419
|
-
get isDisabled() {
|
|
420
|
-
return tabAria.isDisabled();
|
|
421
|
-
},
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
// Render props values
|
|
425
|
-
const renderValues = createMemo<TabRenderProps>(() => ({
|
|
426
|
-
isSelected: tabAria.isSelected(),
|
|
427
|
-
isFocused: tabAria.isFocused(),
|
|
428
|
-
isFocusVisible: tabAria.isFocusVisible(),
|
|
429
|
-
isPressed: tabAria.isPressed(),
|
|
430
|
-
isHovered: isHovered(),
|
|
431
|
-
isDisabled: tabAria.isDisabled(),
|
|
432
|
-
}));
|
|
433
|
-
|
|
434
|
-
// Resolve render props
|
|
435
|
-
const renderProps = useRenderProps(
|
|
436
|
-
{
|
|
437
|
-
children: props.children,
|
|
438
|
-
class: props.local.class,
|
|
439
|
-
style: props.local.style,
|
|
440
|
-
defaultClassName: 'solidaria-Tab',
|
|
441
|
-
},
|
|
442
|
-
renderValues
|
|
443
|
-
);
|
|
444
|
-
|
|
445
|
-
return (
|
|
446
|
-
<div
|
|
447
|
-
id={tabAria.tabProps.id}
|
|
448
|
-
role={tabAria.tabProps.role}
|
|
449
|
-
aria-selected={tabAria.isSelected()}
|
|
450
|
-
aria-disabled={tabAria.isDisabled() || undefined}
|
|
451
|
-
aria-controls={tabAria.isSelected() ? tabAria.tabProps['aria-controls'] : undefined}
|
|
452
|
-
aria-label={tabAria.tabProps['aria-label']}
|
|
453
|
-
tabIndex={tabAria.isSelected() && !tabAria.isDisabled() ? 0 : -1}
|
|
454
|
-
class={renderProps.class()}
|
|
455
|
-
style={renderProps.style()}
|
|
456
|
-
onKeyDown={tabAria.tabProps.onKeyDown}
|
|
457
|
-
onMouseDown={tabAria.tabProps.onMouseDown}
|
|
458
|
-
onPointerDown={tabAria.tabProps.onPointerDown}
|
|
459
|
-
onClick={tabAria.tabProps.onClick}
|
|
460
|
-
onFocus={tabAria.tabProps.onFocus}
|
|
461
|
-
{...hoverProps}
|
|
462
|
-
data-selected={tabAria.isSelected() || undefined}
|
|
463
|
-
data-focused={tabAria.isFocused() || undefined}
|
|
464
|
-
data-focus-visible={tabAria.isFocusVisible() || undefined}
|
|
465
|
-
data-pressed={tabAria.isPressed() || undefined}
|
|
466
|
-
data-hovered={isHovered() || undefined}
|
|
467
|
-
data-disabled={tabAria.isDisabled() || undefined}
|
|
468
|
-
>
|
|
469
|
-
{renderProps.renderChildren()}
|
|
470
|
-
</div>
|
|
471
|
-
);
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* A TabPanel displays the content for a selected Tab.
|
|
476
|
-
*/
|
|
477
|
-
export function TabPanel(props: TabPanelProps): JSX.Element {
|
|
478
|
-
const [local, ariaProps] = splitProps(props, [
|
|
479
|
-
'class',
|
|
480
|
-
'style',
|
|
481
|
-
'slot',
|
|
482
|
-
'shouldForceMount',
|
|
483
|
-
]);
|
|
484
|
-
|
|
485
|
-
// Get state from context (may be null for SSR scenarios)
|
|
486
|
-
const state = useContext(TabsStateContext);
|
|
487
|
-
|
|
488
|
-
// Create tab panel aria props
|
|
489
|
-
const { tabPanelProps, isSelected } = createTabPanel<unknown>(ariaProps, state);
|
|
490
|
-
|
|
491
|
-
// Create focus ring for the panel
|
|
492
|
-
const { isFocused, isFocusVisible, focusProps } = createFocusRing();
|
|
493
|
-
|
|
494
|
-
// Render props values
|
|
495
|
-
const renderValues = createMemo<TabPanelRenderProps>(() => ({
|
|
496
|
-
isSelected: isSelected(),
|
|
497
|
-
isFocused: isFocused(),
|
|
498
|
-
isFocusVisible: isFocusVisible(),
|
|
499
|
-
}));
|
|
500
|
-
|
|
501
|
-
// Resolve render props
|
|
502
|
-
const renderProps = useRenderProps(
|
|
503
|
-
{
|
|
504
|
-
children: props.children,
|
|
505
|
-
class: local.class,
|
|
506
|
-
style: local.style,
|
|
507
|
-
defaultClassName: 'solidaria-TabPanel',
|
|
508
|
-
},
|
|
509
|
-
renderValues
|
|
510
|
-
);
|
|
511
|
-
|
|
512
|
-
// Determine if we should render the panel
|
|
513
|
-
// If no id is provided, render when any tab is selected (shared panel pattern)
|
|
514
|
-
// If id is provided, render when that specific tab is selected
|
|
515
|
-
const shouldRender = () => {
|
|
516
|
-
if (local.shouldForceMount) return true;
|
|
517
|
-
if (ariaProps.id === undefined) {
|
|
518
|
-
// Shared panel pattern - render when any tab is selected
|
|
519
|
-
return state ? state.selectedKey() !== null : true;
|
|
520
|
-
}
|
|
521
|
-
return isSelected();
|
|
522
|
-
};
|
|
523
|
-
|
|
524
|
-
return (
|
|
525
|
-
<Show when={shouldRender()}>
|
|
526
|
-
<div
|
|
527
|
-
id={tabPanelProps.id}
|
|
528
|
-
role={tabPanelProps.role}
|
|
529
|
-
aria-labelledby={tabPanelProps['aria-labelledby']}
|
|
530
|
-
aria-label={tabPanelProps['aria-label']}
|
|
531
|
-
aria-describedby={tabPanelProps['aria-describedby']}
|
|
532
|
-
tabIndex={tabPanelProps.tabIndex}
|
|
533
|
-
class={renderProps.class()}
|
|
534
|
-
style={renderProps.style()}
|
|
535
|
-
onFocus={focusProps.onFocus}
|
|
536
|
-
onBlur={focusProps.onBlur}
|
|
537
|
-
data-selected={isSelected() || undefined}
|
|
538
|
-
data-focused={isFocused() || undefined}
|
|
539
|
-
data-focus-visible={isFocusVisible() || undefined}
|
|
540
|
-
inert={ariaProps.id !== undefined && !isSelected() ? true : undefined}
|
|
541
|
-
hidden={ariaProps.id !== undefined && !isSelected() && !local.shouldForceMount ? true : undefined}
|
|
542
|
-
>
|
|
543
|
-
{renderProps.renderChildren()}
|
|
544
|
-
</div>
|
|
545
|
-
</Show>
|
|
546
|
-
);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
// Attach sub-components
|
|
550
|
-
Tabs.List = TabList;
|
|
551
|
-
Tabs.Tab = Tab;
|
|
552
|
-
Tabs.Panel = TabPanel;
|