@proyecto-viviana/solidaria-components 0.1.3 → 0.2.2
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.jsx +9056 -0
- package/dist/index.jsx.map +7 -0
- 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/utils.tsx
DELETED
|
@@ -1,329 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Utility functions for solidaria-components
|
|
3
|
-
* Port of react-aria-components/src/utils.tsx
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
type JSX,
|
|
8
|
-
type Accessor,
|
|
9
|
-
type FlowComponent,
|
|
10
|
-
createContext,
|
|
11
|
-
useContext,
|
|
12
|
-
createMemo,
|
|
13
|
-
createSignal,
|
|
14
|
-
onMount,
|
|
15
|
-
Show,
|
|
16
|
-
} from 'solid-js';
|
|
17
|
-
import { isServer } from 'solid-js/web';
|
|
18
|
-
|
|
19
|
-
// ============================================
|
|
20
|
-
// TYPES
|
|
21
|
-
// ============================================
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Render props pattern - children can be a function that receives state
|
|
25
|
-
*/
|
|
26
|
-
export type RenderChildren<T> = JSX.Element | ((renderProps: T) => JSX.Element);
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Class name can be a string or a function that computes based on state
|
|
30
|
-
*/
|
|
31
|
-
export type ClassNameOrFunction<T> = string | ((renderProps: T) => string);
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Style can be an object or a function that computes based on state
|
|
35
|
-
*/
|
|
36
|
-
export type StyleOrFunction<T> = JSX.CSSProperties | ((renderProps: T) => JSX.CSSProperties);
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Common render props interface
|
|
40
|
-
*/
|
|
41
|
-
export interface RenderPropsBase<T> {
|
|
42
|
-
/** The children of the component. A function may be provided to receive render props. */
|
|
43
|
-
children?: RenderChildren<T>;
|
|
44
|
-
/** The CSS className for the element. A function may be provided to compute the class based on state. */
|
|
45
|
-
class?: ClassNameOrFunction<T>;
|
|
46
|
-
/** The inline style for the element. A function may be provided to compute the style based on state. */
|
|
47
|
-
style?: StyleOrFunction<T>;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Slot props for named slots
|
|
52
|
-
*/
|
|
53
|
-
export interface SlotProps {
|
|
54
|
-
/** A slot name for the component. */
|
|
55
|
-
slot?: string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// ============================================
|
|
59
|
-
// RENDER PROPS
|
|
60
|
-
// ============================================
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Return type for useRenderProps
|
|
64
|
-
*/
|
|
65
|
-
export interface RenderPropsResult<T> {
|
|
66
|
-
/** Accessor for class - safe to call anytime */
|
|
67
|
-
class: Accessor<string>;
|
|
68
|
-
/** Accessor for style - safe to call anytime */
|
|
69
|
-
style: Accessor<JSX.CSSProperties | undefined>;
|
|
70
|
-
/**
|
|
71
|
-
* Render the children. This is a function that returns JSX, NOT a getter.
|
|
72
|
-
* For SSR compatibility, this should be called within the JSX tree.
|
|
73
|
-
*
|
|
74
|
-
* Usage in components:
|
|
75
|
-
* {renderProps.renderChildren()}
|
|
76
|
-
*
|
|
77
|
-
* Or if you need the raw children/function:
|
|
78
|
-
* {renderProps.renderChildren()}
|
|
79
|
-
*/
|
|
80
|
-
renderChildren: () => JSX.Element;
|
|
81
|
-
/** The raw children prop (function or JSX) - use renderChildren() in most cases */
|
|
82
|
-
children: RenderChildren<T> | undefined;
|
|
83
|
-
/** The render props values accessor */
|
|
84
|
-
values: Accessor<T>;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Resolves render props (children, class, style) based on component state.
|
|
89
|
-
*
|
|
90
|
-
* For SSR compatibility, children are NOT evaluated eagerly. Instead:
|
|
91
|
-
* - Use `renderChildren()` to render children with current values
|
|
92
|
-
* - Or access `children` directly if you need the raw prop
|
|
93
|
-
*
|
|
94
|
-
* This avoids the getter pattern that causes SSR hydration mismatches.
|
|
95
|
-
*/
|
|
96
|
-
export function useRenderProps<T extends object>(
|
|
97
|
-
props: RenderPropsBase<T> & { defaultClassName?: string },
|
|
98
|
-
values: Accessor<T>
|
|
99
|
-
): RenderPropsResult<T> {
|
|
100
|
-
const { children, class: className, style, defaultClassName = '' } = props;
|
|
101
|
-
|
|
102
|
-
// Compute class and style eagerly (they don't depend on context)
|
|
103
|
-
const computedClass = createMemo(() => {
|
|
104
|
-
const currentValues = values();
|
|
105
|
-
return typeof className === 'function'
|
|
106
|
-
? className(currentValues)
|
|
107
|
-
: className ?? defaultClassName;
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
const computedStyle = createMemo(() => {
|
|
111
|
-
const currentValues = values();
|
|
112
|
-
return typeof style === 'function'
|
|
113
|
-
? style(currentValues)
|
|
114
|
-
: style;
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
// Return object with explicit function for rendering children
|
|
118
|
-
// This avoids the getter pattern that causes SSR issues
|
|
119
|
-
return {
|
|
120
|
-
class: computedClass,
|
|
121
|
-
style: computedStyle,
|
|
122
|
-
renderChildren: () => {
|
|
123
|
-
const currentValues = values();
|
|
124
|
-
return typeof children === 'function'
|
|
125
|
-
? children(currentValues)
|
|
126
|
-
: children;
|
|
127
|
-
},
|
|
128
|
-
children,
|
|
129
|
-
values,
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// ============================================
|
|
134
|
-
// CONTEXT UTILITIES
|
|
135
|
-
// ============================================
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Context value that can be null or the actual value
|
|
139
|
-
*/
|
|
140
|
-
export type ContextValue<T> = T | null;
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Creates a context with props and ref merging support
|
|
144
|
-
*/
|
|
145
|
-
export function createSlottedContext<T>() {
|
|
146
|
-
return createContext<T | null>(null);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Use context with null check
|
|
151
|
-
*/
|
|
152
|
-
export function useSlottedContext<T>(context: ReturnType<typeof createContext<T | null>>): T | null {
|
|
153
|
-
return useContext(context);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// ============================================
|
|
157
|
-
// DATA ATTRIBUTES
|
|
158
|
-
// ============================================
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Converts boolean state values to data attributes
|
|
162
|
-
*/
|
|
163
|
-
export function dataAttr(value: boolean | undefined): '' | undefined {
|
|
164
|
-
return value ? '' : undefined;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Creates data attributes from render props
|
|
169
|
-
*/
|
|
170
|
-
export function createDataAttributes<T extends Record<string, boolean | string | undefined>>(
|
|
171
|
-
values: T
|
|
172
|
-
): Record<string, string | undefined> {
|
|
173
|
-
const result: Record<string, string | undefined> = {};
|
|
174
|
-
|
|
175
|
-
for (const [key, value] of Object.entries(values)) {
|
|
176
|
-
if (typeof value === 'boolean') {
|
|
177
|
-
result[`data-${camelToKebab(key)}`] = value ? '' : undefined;
|
|
178
|
-
} else if (value !== undefined) {
|
|
179
|
-
result[`data-${camelToKebab(key)}`] = value;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
return result;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function camelToKebab(str: string): string {
|
|
187
|
-
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// ============================================
|
|
191
|
-
// PROPS UTILITIES
|
|
192
|
-
// ============================================
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Remove data attributes from props (for internal use)
|
|
196
|
-
*/
|
|
197
|
-
export function removeDataAttributes<T extends Record<string, unknown>>(props: T): T {
|
|
198
|
-
const result: Record<string, unknown> = {};
|
|
199
|
-
|
|
200
|
-
for (const [key, value] of Object.entries(props)) {
|
|
201
|
-
if (!key.startsWith('data-')) {
|
|
202
|
-
result[key] = value;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return result as T;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Filter DOM props - keep only valid DOM attributes.
|
|
211
|
-
*
|
|
212
|
-
* @param props - Component props to filter
|
|
213
|
-
* @param options - Options for filtering (global: include global attrs)
|
|
214
|
-
* @returns Object containing only valid DOM props. Use type parameter R to specify return type.
|
|
215
|
-
*/
|
|
216
|
-
export function filterDOMProps<R extends object = Record<string, unknown>>(
|
|
217
|
-
props: object,
|
|
218
|
-
options: { global?: boolean } = {}
|
|
219
|
-
): R {
|
|
220
|
-
const { global = false } = options;
|
|
221
|
-
const result: Record<string, unknown> = {};
|
|
222
|
-
|
|
223
|
-
const globalAttrs = new Set([
|
|
224
|
-
'id', 'class', 'style', 'tabIndex', 'role', 'title', 'lang', 'dir',
|
|
225
|
-
'hidden', 'draggable', 'accessKey', 'contentEditable', 'spellcheck',
|
|
226
|
-
]);
|
|
227
|
-
|
|
228
|
-
const ariaAttrs = /^aria-/;
|
|
229
|
-
const dataAttrs = /^data-/;
|
|
230
|
-
const eventHandlers = /^on[A-Z]/;
|
|
231
|
-
|
|
232
|
-
for (const key in props) {
|
|
233
|
-
if (
|
|
234
|
-
Object.prototype.hasOwnProperty.call(props, key) &&
|
|
235
|
-
(
|
|
236
|
-
(global && globalAttrs.has(key)) ||
|
|
237
|
-
ariaAttrs.test(key) ||
|
|
238
|
-
dataAttrs.test(key) ||
|
|
239
|
-
eventHandlers.test(key)
|
|
240
|
-
)
|
|
241
|
-
) {
|
|
242
|
-
result[key] = (props as Record<string, unknown>)[key];
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
return result as R;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// ============================================
|
|
250
|
-
// CLIENT-ONLY UTILITIES
|
|
251
|
-
// ============================================
|
|
252
|
-
|
|
253
|
-
export interface ClientOnlyProps {
|
|
254
|
-
/** The children to render only on the client */
|
|
255
|
-
children: JSX.Element;
|
|
256
|
-
/** Optional fallback to render during SSR and initial hydration */
|
|
257
|
-
fallback?: JSX.Element;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* ClientOnly component - renders children only on the client side.
|
|
262
|
-
*
|
|
263
|
-
* During SSR, renders the fallback (or nothing).
|
|
264
|
-
* During hydration, renders the same fallback to match SSR.
|
|
265
|
-
* After hydration completes, switches to render children.
|
|
266
|
-
*
|
|
267
|
-
* This is useful for components that rely on browser APIs or
|
|
268
|
-
* have different server/client output.
|
|
269
|
-
*
|
|
270
|
-
* @example
|
|
271
|
-
* ```tsx
|
|
272
|
-
* <ClientOnly fallback={<div>Loading...</div>}>
|
|
273
|
-
* <Calendar />
|
|
274
|
-
* </ClientOnly>
|
|
275
|
-
* ```
|
|
276
|
-
*/
|
|
277
|
-
export const ClientOnly: FlowComponent<ClientOnlyProps> = (props) => {
|
|
278
|
-
// On server, always render fallback
|
|
279
|
-
if (isServer) {
|
|
280
|
-
return <>{props.fallback}</>;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// On client, track if we've hydrated
|
|
284
|
-
const [isHydrated, setIsHydrated] = createSignal(false);
|
|
285
|
-
|
|
286
|
-
// onMount runs after hydration is complete
|
|
287
|
-
onMount(() => {
|
|
288
|
-
setIsHydrated(true);
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
return (
|
|
292
|
-
<Show when={isHydrated()} fallback={props.fallback}>
|
|
293
|
-
{props.children}
|
|
294
|
-
</Show>
|
|
295
|
-
);
|
|
296
|
-
};
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* Returns true only on the client after hydration is complete.
|
|
300
|
-
* Can be used to conditionally render client-only content.
|
|
301
|
-
*
|
|
302
|
-
* @example
|
|
303
|
-
* ```tsx
|
|
304
|
-
* const hydrated = useIsHydrated();
|
|
305
|
-
* return (
|
|
306
|
-
* <Show when={hydrated()} fallback={<Placeholder />}>
|
|
307
|
-
* <ClientOnlyComponent />
|
|
308
|
-
* </Show>
|
|
309
|
-
* );
|
|
310
|
-
* ```
|
|
311
|
-
*/
|
|
312
|
-
export function useIsHydrated(): Accessor<boolean> {
|
|
313
|
-
// On server, always return false
|
|
314
|
-
if (isServer) {
|
|
315
|
-
return () => false;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// On client, start false and switch to true after animation frame
|
|
319
|
-
// This ensures we're past the hydration phase
|
|
320
|
-
const [isHydrated, setIsHydrated] = createSignal(false);
|
|
321
|
-
|
|
322
|
-
// Use requestAnimationFrame to ensure we're past hydration
|
|
323
|
-
// onMount may not fire during hydration for matching DOM
|
|
324
|
-
requestAnimationFrame(() => {
|
|
325
|
-
setIsHydrated(true);
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
return isHydrated;
|
|
329
|
-
}
|