@proyecto-viviana/solidaria 0.2.4 → 0.2.8
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/actiongroup/createActionGroup.d.ts +29 -0
- package/dist/actiongroup/createActionGroup.d.ts.map +1 -0
- package/dist/actiongroup/index.d.ts +2 -0
- package/dist/actiongroup/index.d.ts.map +1 -0
- package/dist/autocomplete/createAutocomplete.d.ts +6 -2
- package/dist/autocomplete/createAutocomplete.d.ts.map +1 -1
- package/dist/breadcrumbs/createBreadcrumbs.d.ts +2 -0
- package/dist/breadcrumbs/createBreadcrumbs.d.ts.map +1 -1
- package/dist/button/createToggleButtonGroup.d.ts +32 -0
- package/dist/button/createToggleButtonGroup.d.ts.map +1 -0
- package/dist/button/index.d.ts +2 -0
- package/dist/button/index.d.ts.map +1 -1
- package/dist/calendar/createCalendarCell.d.ts +2 -0
- package/dist/calendar/createCalendarCell.d.ts.map +1 -1
- package/dist/calendar/createCalendarGrid.d.ts.map +1 -1
- package/dist/calendar/createRangeCalendarCell.d.ts +3 -1
- package/dist/calendar/createRangeCalendarCell.d.ts.map +1 -1
- package/dist/checkbox/createCheckboxGroup.d.ts +5 -1
- package/dist/checkbox/createCheckboxGroup.d.ts.map +1 -1
- package/dist/collections/index.d.ts +56 -0
- package/dist/collections/index.d.ts.map +1 -0
- package/dist/color/createColorArea.d.ts.map +1 -1
- package/dist/color/createColorSlider.d.ts.map +1 -1
- package/dist/color/createColorWheel.d.ts.map +1 -1
- package/dist/combobox/createComboBox.d.ts +6 -0
- package/dist/combobox/createComboBox.d.ts.map +1 -1
- package/dist/datepicker/createDatePicker.d.ts +6 -0
- package/dist/datepicker/createDatePicker.d.ts.map +1 -1
- package/dist/datepicker/createDateRangePicker.d.ts +40 -0
- package/dist/datepicker/createDateRangePicker.d.ts.map +1 -0
- package/dist/datepicker/createDateSegment.d.ts +1 -1
- package/dist/datepicker/createDateSegment.d.ts.map +1 -1
- package/dist/datepicker/createTimeSegment.d.ts +29 -0
- package/dist/datepicker/createTimeSegment.d.ts.map +1 -0
- package/dist/datepicker/index.d.ts +2 -0
- package/dist/datepicker/index.d.ts.map +1 -1
- package/dist/disclosure/createDisclosureGroup.d.ts +2 -1
- package/dist/disclosure/createDisclosureGroup.d.ts.map +1 -1
- package/dist/dnd/createDrag.d.ts.map +1 -1
- package/dist/dnd/createDraggableCollection.d.ts +4 -0
- package/dist/dnd/createDraggableCollection.d.ts.map +1 -1
- package/dist/dnd/createDraggableItem.d.ts.map +1 -1
- package/dist/dnd/createDrop.d.ts.map +1 -1
- package/dist/dnd/createDroppableCollection.d.ts +32 -1
- package/dist/dnd/createDroppableCollection.d.ts.map +1 -1
- package/dist/dnd/createDroppableItem.d.ts.map +1 -1
- package/dist/dnd/index.d.ts +1 -1
- package/dist/dnd/index.d.ts.map +1 -1
- package/dist/grid/createGrid.d.ts.map +1 -1
- package/dist/gridlist/createGridList.d.ts.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4659 -3452
- package/dist/index.js.map +1 -7
- package/dist/index.ssr.js +4659 -3452
- package/dist/index.ssr.js.map +1 -7
- package/dist/interactions/createFocus.d.ts.map +1 -1
- package/dist/interactions/createFocusWithin.d.ts.map +1 -1
- package/dist/link/createLink.d.ts +10 -0
- package/dist/link/createLink.d.ts.map +1 -1
- package/dist/listbox/createListBox.d.ts +1 -0
- package/dist/listbox/createListBox.d.ts.map +1 -1
- package/dist/listbox/createOption.d.ts.map +1 -1
- package/dist/menu/createMenu.d.ts +1 -0
- package/dist/menu/createMenu.d.ts.map +1 -1
- package/dist/meter/createMeter.d.ts.map +1 -1
- package/dist/numberfield/createNumberField.d.ts +18 -0
- package/dist/numberfield/createNumberField.d.ts.map +1 -1
- package/dist/overlays/createModal.d.ts +16 -0
- package/dist/overlays/createModal.d.ts.map +1 -1
- package/dist/overlays/createOverlay.d.ts.map +1 -1
- package/dist/overlays/index.d.ts +1 -1
- package/dist/overlays/index.d.ts.map +1 -1
- package/dist/popover/createOverlayPosition.d.ts.map +1 -1
- package/dist/popover/createPopover.d.ts.map +1 -1
- package/dist/progress/createProgressBar.d.ts.map +1 -1
- package/dist/radio/createRadioGroup.d.ts +2 -2
- package/dist/radio/createRadioGroup.d.ts.map +1 -1
- package/dist/searchfield/createSearchField.d.ts.map +1 -1
- package/dist/select/createHiddenSelect.d.ts.map +1 -1
- package/dist/select/createSelect.d.ts.map +1 -1
- package/dist/slider/createSlider.d.ts.map +1 -1
- package/dist/table/createTable.d.ts.map +1 -1
- package/dist/tabs/createTabs.d.ts +1 -1
- package/dist/tabs/createTabs.d.ts.map +1 -1
- package/dist/tag/createTag.d.ts.map +1 -1
- package/dist/tag/createTagGroup.d.ts.map +1 -1
- package/dist/toast/createToast.d.ts +4 -0
- package/dist/toast/createToast.d.ts.map +1 -1
- package/dist/toast/createToastRegion.d.ts.map +1 -1
- package/dist/toolbar/createToolbar.d.ts.map +1 -1
- package/dist/tooltip/createTooltipTrigger.d.ts.map +1 -1
- package/dist/tree/createTree.d.ts.map +1 -1
- package/dist/tree/createTreeItem.d.ts.map +1 -1
- package/dist/tree/types.d.ts +4 -0
- package/dist/tree/types.d.ts.map +1 -1
- package/dist/utils/env.d.ts +1 -1
- package/dist/utils/env.d.ts.map +1 -1
- package/dist/utils/platform.d.ts.map +1 -1
- package/dist/visually-hidden/createVisuallyHidden.d.ts.map +1 -1
- package/package.json +8 -6
- package/src/actiongroup/createActionGroup.ts +324 -0
- package/src/actiongroup/index.ts +8 -0
- package/src/autocomplete/createAutocomplete.ts +32 -9
- package/src/breadcrumbs/createBreadcrumbs.ts +10 -15
- package/src/button/createButton.ts +1 -1
- package/src/button/createToggleButtonGroup.ts +128 -0
- package/src/button/index.ts +9 -0
- package/src/calendar/createCalendarCell.ts +6 -4
- package/src/calendar/createCalendarGrid.ts +27 -18
- package/src/calendar/createRangeCalendarCell.ts +26 -9
- package/src/checkbox/createCheckboxGroup.ts +21 -4
- package/src/collections/index.ts +242 -0
- package/src/color/createColorArea.ts +380 -314
- package/src/color/createColorField.ts +137 -137
- package/src/color/createColorSlider.ts +286 -197
- package/src/color/createColorSwatch.ts +40 -40
- package/src/color/createColorWheel.ts +218 -208
- package/src/color/index.ts +24 -24
- package/src/color/types.ts +116 -116
- package/src/combobox/createComboBox.ts +670 -647
- package/src/combobox/index.ts +6 -6
- package/src/datepicker/createDatePicker.ts +54 -16
- package/src/datepicker/createDateRangePicker.ts +246 -0
- package/src/datepicker/createDateSegment.ts +185 -31
- package/src/datepicker/createTimeSegment.ts +370 -0
- package/src/datepicker/index.ts +14 -0
- package/src/dialog/createDialog.ts +120 -120
- package/src/dialog/index.ts +2 -2
- package/src/dialog/types.ts +19 -19
- package/src/disclosure/createDisclosureGroup.ts +5 -2
- package/src/dnd/createDrag.ts +224 -209
- package/src/dnd/createDraggableCollection.ts +96 -63
- package/src/dnd/createDraggableItem.ts +259 -243
- package/src/dnd/createDrop.ts +322 -321
- package/src/dnd/createDroppableCollection.ts +682 -293
- package/src/dnd/createDroppableItem.ts +215 -213
- package/src/dnd/index.ts +55 -47
- package/src/dnd/types.ts +89 -89
- package/src/dnd/utils.ts +294 -294
- package/src/focus/createAutoFocus.ts +321 -321
- package/src/focus/createFocusRestore.ts +313 -313
- package/src/focus/createVirtualFocus.ts +396 -396
- package/src/form/createFormValidation.ts +224 -224
- package/src/form/index.ts +11 -11
- package/src/grid/createGrid.ts +3 -1
- package/src/gridlist/createGridList.ts +16 -0
- package/src/gridlist/createGridListItem.ts +1 -1
- package/src/i18n/NumberFormatter.ts +266 -266
- package/src/i18n/createCollator.ts +79 -79
- package/src/i18n/createDateFormatter.ts +83 -83
- package/src/i18n/createFilter.ts +131 -131
- package/src/i18n/createNumberFormatter.ts +52 -52
- package/src/i18n/index.ts +40 -40
- package/src/i18n/locale.tsx +188 -188
- package/src/i18n/utils.ts +99 -99
- package/src/index.ts +51 -0
- package/src/interactions/createFocus.ts +6 -5
- package/src/interactions/createFocusWithin.ts +6 -5
- package/src/interactions/createLongPress.ts +174 -174
- package/src/interactions/createMove.ts +289 -289
- package/src/interactions/createPress.ts +5 -5
- package/src/landmark/createLandmark.ts +377 -377
- package/src/landmark/index.ts +8 -8
- package/src/link/createLink.ts +23 -8
- package/src/listbox/createListBox.ts +308 -269
- package/src/listbox/createOption.ts +162 -151
- package/src/listbox/index.ts +12 -12
- package/src/live-announcer/announce.ts +322 -322
- package/src/live-announcer/index.ts +9 -9
- package/src/menu/createMenu.ts +405 -396
- package/src/menu/createMenuItem.ts +149 -149
- package/src/menu/createMenuTrigger.ts +88 -88
- package/src/menu/index.ts +18 -18
- package/src/meter/createMeter.ts +1 -6
- package/src/numberfield/createNumberField.ts +311 -268
- package/src/numberfield/index.ts +5 -5
- package/src/overlays/ariaHideOutside.ts +219 -219
- package/src/overlays/createInteractOutside.ts +149 -149
- package/src/overlays/createModal.tsx +238 -202
- package/src/overlays/createOverlay.ts +165 -155
- package/src/overlays/createOverlayTrigger.ts +85 -85
- package/src/overlays/createPreventScroll.ts +266 -266
- package/src/overlays/index.ts +48 -44
- package/src/popover/calculatePosition.ts +6 -6
- package/src/popover/createOverlayPosition.ts +7 -4
- package/src/popover/createPopover.ts +21 -7
- package/src/progress/createProgressBar.ts +6 -1
- package/src/radio/createRadioGroup.ts +88 -14
- package/src/searchfield/createSearchField.ts +241 -186
- package/src/searchfield/index.ts +2 -2
- package/src/select/createHiddenSelect.tsx +263 -236
- package/src/select/createSelect.ts +373 -395
- package/src/select/index.ts +14 -14
- package/src/slider/createSlider.ts +364 -349
- package/src/slider/index.ts +2 -2
- package/src/ssr/index.tsx +370 -370
- package/src/table/createTable.ts +3 -1
- package/src/table/createTableColumnHeader.ts +1 -1
- package/src/table/createTableRow.ts +1 -1
- package/src/tabs/createTabs.ts +80 -51
- package/src/tag/createTag.ts +135 -6
- package/src/tag/createTagGroup.ts +7 -2
- package/src/toast/createToast.ts +8 -2
- package/src/toast/createToastRegion.ts +0 -1
- package/src/toolbar/createToolbar.ts +75 -1
- package/src/tooltip/createTooltip.ts +79 -79
- package/src/tooltip/createTooltipTrigger.ts +226 -222
- package/src/tooltip/index.ts +6 -6
- package/src/tree/createTree.ts +261 -246
- package/src/tree/createTreeItem.ts +282 -233
- package/src/tree/createTreeSelectionCheckbox.ts +68 -68
- package/src/tree/index.ts +16 -16
- package/src/tree/types.ts +91 -87
- package/src/utils/env.ts +55 -54
- package/src/utils/platform.ts +16 -6
- package/src/visually-hidden/createVisuallyHidden.ts +139 -124
- package/src/visually-hidden/index.ts +6 -6
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* createCollator hook for solidaria
|
|
3
|
-
*
|
|
4
|
-
* Provides localized string comparison/collation with caching.
|
|
5
|
-
*
|
|
6
|
-
* Port of @react-aria/i18n useCollator.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { createMemo } from 'solid-js';
|
|
10
|
-
import { useLocale } from './locale';
|
|
11
|
-
import { createCacheKey } from './utils';
|
|
12
|
-
|
|
13
|
-
// ============================================
|
|
14
|
-
// CACHE
|
|
15
|
-
// ============================================
|
|
16
|
-
|
|
17
|
-
const collatorCache = new Map<string, Intl.Collator>();
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Gets or creates a cached collator.
|
|
21
|
-
*/
|
|
22
|
-
function getCachedCollator(
|
|
23
|
-
locale: string,
|
|
24
|
-
options?: Intl.CollatorOptions
|
|
25
|
-
): Intl.Collator {
|
|
26
|
-
const cacheKey = createCacheKey(locale, options as Record<string, unknown>);
|
|
27
|
-
|
|
28
|
-
if (collatorCache.has(cacheKey)) {
|
|
29
|
-
return collatorCache.get(cacheKey)!;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const collator = new Intl.Collator(locale, options);
|
|
33
|
-
collatorCache.set(cacheKey, collator);
|
|
34
|
-
return collator;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// ============================================
|
|
38
|
-
// HOOK
|
|
39
|
-
// ============================================
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Provides localized string collation for the current locale.
|
|
43
|
-
* Useful for sorting strings according to locale-specific rules.
|
|
44
|
-
*
|
|
45
|
-
* @example
|
|
46
|
-
* ```tsx
|
|
47
|
-
* function SortedList(props: { items: string[] }) {
|
|
48
|
-
* const collator = createCollator();
|
|
49
|
-
*
|
|
50
|
-
* const sortedItems = () =>
|
|
51
|
-
* [...props.items].sort((a, b) => collator().compare(a, b));
|
|
52
|
-
*
|
|
53
|
-
* return (
|
|
54
|
-
* <ul>
|
|
55
|
-
* <For each={sortedItems()}>
|
|
56
|
-
* {(item) => <li>{item}</li>}
|
|
57
|
-
* </For>
|
|
58
|
-
* </ul>
|
|
59
|
-
* );
|
|
60
|
-
* }
|
|
61
|
-
* ```
|
|
62
|
-
*
|
|
63
|
-
* @example
|
|
64
|
-
* ```tsx
|
|
65
|
-
* // Case-insensitive sorting
|
|
66
|
-
* const collator = createCollator({ sensitivity: 'base' });
|
|
67
|
-
*
|
|
68
|
-
* // Numeric sorting
|
|
69
|
-
* const numericCollator = createCollator({ numeric: true });
|
|
70
|
-
* // ['a1', 'a10', 'a2'].sort(numericCollator().compare) -> ['a1', 'a2', 'a10']
|
|
71
|
-
* ```
|
|
72
|
-
*/
|
|
73
|
-
export function createCollator(
|
|
74
|
-
options?: Intl.CollatorOptions
|
|
75
|
-
): () => Intl.Collator {
|
|
76
|
-
const locale = useLocale();
|
|
77
|
-
|
|
78
|
-
return createMemo(() => getCachedCollator(locale().locale, options));
|
|
79
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* createCollator hook for solidaria
|
|
3
|
+
*
|
|
4
|
+
* Provides localized string comparison/collation with caching.
|
|
5
|
+
*
|
|
6
|
+
* Port of @react-aria/i18n useCollator.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createMemo } from 'solid-js';
|
|
10
|
+
import { useLocale } from './locale';
|
|
11
|
+
import { createCacheKey } from './utils';
|
|
12
|
+
|
|
13
|
+
// ============================================
|
|
14
|
+
// CACHE
|
|
15
|
+
// ============================================
|
|
16
|
+
|
|
17
|
+
const collatorCache = new Map<string, Intl.Collator>();
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Gets or creates a cached collator.
|
|
21
|
+
*/
|
|
22
|
+
function getCachedCollator(
|
|
23
|
+
locale: string,
|
|
24
|
+
options?: Intl.CollatorOptions
|
|
25
|
+
): Intl.Collator {
|
|
26
|
+
const cacheKey = createCacheKey(locale, options as Record<string, unknown>);
|
|
27
|
+
|
|
28
|
+
if (collatorCache.has(cacheKey)) {
|
|
29
|
+
return collatorCache.get(cacheKey)!;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const collator = new Intl.Collator(locale, options);
|
|
33
|
+
collatorCache.set(cacheKey, collator);
|
|
34
|
+
return collator;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ============================================
|
|
38
|
+
// HOOK
|
|
39
|
+
// ============================================
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Provides localized string collation for the current locale.
|
|
43
|
+
* Useful for sorting strings according to locale-specific rules.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```tsx
|
|
47
|
+
* function SortedList(props: { items: string[] }) {
|
|
48
|
+
* const collator = createCollator();
|
|
49
|
+
*
|
|
50
|
+
* const sortedItems = () =>
|
|
51
|
+
* [...props.items].sort((a, b) => collator().compare(a, b));
|
|
52
|
+
*
|
|
53
|
+
* return (
|
|
54
|
+
* <ul>
|
|
55
|
+
* <For each={sortedItems()}>
|
|
56
|
+
* {(item) => <li>{item}</li>}
|
|
57
|
+
* </For>
|
|
58
|
+
* </ul>
|
|
59
|
+
* );
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```tsx
|
|
65
|
+
* // Case-insensitive sorting
|
|
66
|
+
* const collator = createCollator({ sensitivity: 'base' });
|
|
67
|
+
*
|
|
68
|
+
* // Numeric sorting
|
|
69
|
+
* const numericCollator = createCollator({ numeric: true });
|
|
70
|
+
* // ['a1', 'a10', 'a2'].sort(numericCollator().compare) -> ['a1', 'a2', 'a10']
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export function createCollator(
|
|
74
|
+
options?: Intl.CollatorOptions
|
|
75
|
+
): () => Intl.Collator {
|
|
76
|
+
const locale = useLocale();
|
|
77
|
+
|
|
78
|
+
return createMemo(() => getCachedCollator(locale().locale, options));
|
|
79
|
+
}
|
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* createDateFormatter hook for solidaria
|
|
3
|
-
*
|
|
4
|
-
* Provides localized date formatting with caching.
|
|
5
|
-
*
|
|
6
|
-
* Port of @react-aria/i18n useDateFormatter.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { createMemo } from 'solid-js';
|
|
10
|
-
import { useLocale } from './locale';
|
|
11
|
-
import { createCacheKey } from './utils';
|
|
12
|
-
|
|
13
|
-
// ============================================
|
|
14
|
-
// CACHE
|
|
15
|
-
// ============================================
|
|
16
|
-
|
|
17
|
-
const dateFormatterCache = new Map<string, Intl.DateTimeFormat>();
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Gets or creates a cached date formatter.
|
|
21
|
-
*/
|
|
22
|
-
function getCachedDateFormatter(
|
|
23
|
-
locale: string,
|
|
24
|
-
options?: Intl.DateTimeFormatOptions
|
|
25
|
-
): Intl.DateTimeFormat {
|
|
26
|
-
const cacheKey = createCacheKey(locale, options as Record<string, unknown>);
|
|
27
|
-
|
|
28
|
-
if (dateFormatterCache.has(cacheKey)) {
|
|
29
|
-
return dateFormatterCache.get(cacheKey)!;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const formatter = new Intl.DateTimeFormat(locale, options);
|
|
33
|
-
dateFormatterCache.set(cacheKey, formatter);
|
|
34
|
-
return formatter;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// ============================================
|
|
38
|
-
// HOOK
|
|
39
|
-
// ============================================
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Provides localized date and time formatting for the current locale.
|
|
43
|
-
* Automatically updates when the locale changes.
|
|
44
|
-
*
|
|
45
|
-
* @example
|
|
46
|
-
* ```tsx
|
|
47
|
-
* function DateDisplay(props: { date: Date }) {
|
|
48
|
-
* const formatter = createDateFormatter({
|
|
49
|
-
* year: 'numeric',
|
|
50
|
-
* month: 'long',
|
|
51
|
-
* day: 'numeric',
|
|
52
|
-
* });
|
|
53
|
-
*
|
|
54
|
-
* return <span>{formatter().format(props.date)}</span>;
|
|
55
|
-
* }
|
|
56
|
-
* ```
|
|
57
|
-
*
|
|
58
|
-
* @example
|
|
59
|
-
* ```tsx
|
|
60
|
-
* // Short date
|
|
61
|
-
* const shortDate = createDateFormatter({ dateStyle: 'short' });
|
|
62
|
-
* shortDate().format(new Date()); // '1/19/26' (US) or '19/01/26' (UK)
|
|
63
|
-
*
|
|
64
|
-
* // Full date with time
|
|
65
|
-
* const fullDateTime = createDateFormatter({
|
|
66
|
-
* dateStyle: 'full',
|
|
67
|
-
* timeStyle: 'short',
|
|
68
|
-
* });
|
|
69
|
-
*
|
|
70
|
-
* // Time only
|
|
71
|
-
* const timeFormatter = createDateFormatter({
|
|
72
|
-
* hour: 'numeric',
|
|
73
|
-
* minute: '2-digit',
|
|
74
|
-
* });
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
export function createDateFormatter(
|
|
78
|
-
options?: Intl.DateTimeFormatOptions
|
|
79
|
-
): () => Intl.DateTimeFormat {
|
|
80
|
-
const locale = useLocale();
|
|
81
|
-
|
|
82
|
-
return createMemo(() => getCachedDateFormatter(locale().locale, options));
|
|
83
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* createDateFormatter hook for solidaria
|
|
3
|
+
*
|
|
4
|
+
* Provides localized date formatting with caching.
|
|
5
|
+
*
|
|
6
|
+
* Port of @react-aria/i18n useDateFormatter.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createMemo } from 'solid-js';
|
|
10
|
+
import { useLocale } from './locale';
|
|
11
|
+
import { createCacheKey } from './utils';
|
|
12
|
+
|
|
13
|
+
// ============================================
|
|
14
|
+
// CACHE
|
|
15
|
+
// ============================================
|
|
16
|
+
|
|
17
|
+
const dateFormatterCache = new Map<string, Intl.DateTimeFormat>();
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Gets or creates a cached date formatter.
|
|
21
|
+
*/
|
|
22
|
+
function getCachedDateFormatter(
|
|
23
|
+
locale: string,
|
|
24
|
+
options?: Intl.DateTimeFormatOptions
|
|
25
|
+
): Intl.DateTimeFormat {
|
|
26
|
+
const cacheKey = createCacheKey(locale, options as Record<string, unknown>);
|
|
27
|
+
|
|
28
|
+
if (dateFormatterCache.has(cacheKey)) {
|
|
29
|
+
return dateFormatterCache.get(cacheKey)!;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const formatter = new Intl.DateTimeFormat(locale, options);
|
|
33
|
+
dateFormatterCache.set(cacheKey, formatter);
|
|
34
|
+
return formatter;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ============================================
|
|
38
|
+
// HOOK
|
|
39
|
+
// ============================================
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Provides localized date and time formatting for the current locale.
|
|
43
|
+
* Automatically updates when the locale changes.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```tsx
|
|
47
|
+
* function DateDisplay(props: { date: Date }) {
|
|
48
|
+
* const formatter = createDateFormatter({
|
|
49
|
+
* year: 'numeric',
|
|
50
|
+
* month: 'long',
|
|
51
|
+
* day: 'numeric',
|
|
52
|
+
* });
|
|
53
|
+
*
|
|
54
|
+
* return <span>{formatter().format(props.date)}</span>;
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```tsx
|
|
60
|
+
* // Short date
|
|
61
|
+
* const shortDate = createDateFormatter({ dateStyle: 'short' });
|
|
62
|
+
* shortDate().format(new Date()); // '1/19/26' (US) or '19/01/26' (UK)
|
|
63
|
+
*
|
|
64
|
+
* // Full date with time
|
|
65
|
+
* const fullDateTime = createDateFormatter({
|
|
66
|
+
* dateStyle: 'full',
|
|
67
|
+
* timeStyle: 'short',
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* // Time only
|
|
71
|
+
* const timeFormatter = createDateFormatter({
|
|
72
|
+
* hour: 'numeric',
|
|
73
|
+
* minute: '2-digit',
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export function createDateFormatter(
|
|
78
|
+
options?: Intl.DateTimeFormatOptions
|
|
79
|
+
): () => Intl.DateTimeFormat {
|
|
80
|
+
const locale = useLocale();
|
|
81
|
+
|
|
82
|
+
return createMemo(() => getCachedDateFormatter(locale().locale, options));
|
|
83
|
+
}
|
package/src/i18n/createFilter.ts
CHANGED
|
@@ -1,131 +1,131 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* createFilter hook for solidaria
|
|
3
|
-
*
|
|
4
|
-
* Provides localized string filtering with collation support.
|
|
5
|
-
*
|
|
6
|
-
* Port of @react-aria/i18n useFilter.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { createMemo } from 'solid-js';
|
|
10
|
-
import { createCollator } from './createCollator';
|
|
11
|
-
|
|
12
|
-
// ============================================
|
|
13
|
-
// TYPES
|
|
14
|
-
// ============================================
|
|
15
|
-
|
|
16
|
-
export interface Filter {
|
|
17
|
-
/** Returns whether a string starts with a given substring. */
|
|
18
|
-
startsWith(string: string, substring: string): boolean;
|
|
19
|
-
/** Returns whether a string ends with a given substring. */
|
|
20
|
-
endsWith(string: string, substring: string): boolean;
|
|
21
|
-
/** Returns whether a string contains a given substring. */
|
|
22
|
-
contains(string: string, substring: string): boolean;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// ============================================
|
|
26
|
-
// HOOK
|
|
27
|
-
// ============================================
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Provides localized string search functionality for filtering or matching items.
|
|
31
|
-
* Respects locale-specific collation rules for case and diacritic sensitivity.
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* ```tsx
|
|
35
|
-
* function SearchableList(props: { items: { name: string }[] }) {
|
|
36
|
-
* const [query, setQuery] = createSignal('');
|
|
37
|
-
* const filter = createFilter({ sensitivity: 'base' });
|
|
38
|
-
*
|
|
39
|
-
* const filteredItems = () =>
|
|
40
|
-
* props.items.filter((item) =>
|
|
41
|
-
* filter().contains(item.name, query())
|
|
42
|
-
* );
|
|
43
|
-
*
|
|
44
|
-
* return (
|
|
45
|
-
* <>
|
|
46
|
-
* <input
|
|
47
|
-
* value={query()}
|
|
48
|
-
* onInput={(e) => setQuery(e.target.value)}
|
|
49
|
-
* placeholder="Search..."
|
|
50
|
-
* />
|
|
51
|
-
* <ul>
|
|
52
|
-
* <For each={filteredItems()}>
|
|
53
|
-
* {(item) => <li>{item.name}</li>}
|
|
54
|
-
* </For>
|
|
55
|
-
* </ul>
|
|
56
|
-
* </>
|
|
57
|
-
* );
|
|
58
|
-
* }
|
|
59
|
-
* ```
|
|
60
|
-
*
|
|
61
|
-
* @example
|
|
62
|
-
* ```tsx
|
|
63
|
-
* // Case-insensitive, diacritic-insensitive filtering
|
|
64
|
-
* const filter = createFilter({ sensitivity: 'base' });
|
|
65
|
-
* filter().contains('Café', 'cafe'); // true
|
|
66
|
-
* filter().startsWith('Hello', 'hello'); // true
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
export function createFilter(options?: Intl.CollatorOptions): () => Filter {
|
|
70
|
-
const collator = createCollator({
|
|
71
|
-
usage: 'search',
|
|
72
|
-
...options,
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
return createMemo(() => {
|
|
76
|
-
const coll = collator();
|
|
77
|
-
|
|
78
|
-
const startsWith = (str: string, substring: string): boolean => {
|
|
79
|
-
if (substring.length === 0) {
|
|
80
|
-
return true;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Normalize both strings for safe slicing
|
|
84
|
-
const normalizedStr = str.normalize('NFC');
|
|
85
|
-
const normalizedSub = substring.normalize('NFC');
|
|
86
|
-
|
|
87
|
-
return (
|
|
88
|
-
coll.compare(normalizedStr.slice(0, normalizedSub.length), normalizedSub) ===
|
|
89
|
-
0
|
|
90
|
-
);
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const endsWith = (str: string, substring: string): boolean => {
|
|
94
|
-
if (substring.length === 0) {
|
|
95
|
-
return true;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const normalizedStr = str.normalize('NFC');
|
|
99
|
-
const normalizedSub = substring.normalize('NFC');
|
|
100
|
-
|
|
101
|
-
return (
|
|
102
|
-
coll.compare(normalizedStr.slice(-normalizedSub.length), normalizedSub) === 0
|
|
103
|
-
);
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
const contains = (str: string, substring: string): boolean => {
|
|
107
|
-
if (substring.length === 0) {
|
|
108
|
-
return true;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const normalizedStr = str.normalize('NFC');
|
|
112
|
-
const normalizedSub = substring.normalize('NFC');
|
|
113
|
-
const sliceLen = normalizedSub.length;
|
|
114
|
-
|
|
115
|
-
for (let scan = 0; scan + sliceLen <= normalizedStr.length; scan++) {
|
|
116
|
-
const slice = normalizedStr.slice(scan, scan + sliceLen);
|
|
117
|
-
if (coll.compare(normalizedSub, slice) === 0) {
|
|
118
|
-
return true;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return false;
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
return {
|
|
126
|
-
startsWith,
|
|
127
|
-
endsWith,
|
|
128
|
-
contains,
|
|
129
|
-
};
|
|
130
|
-
});
|
|
131
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* createFilter hook for solidaria
|
|
3
|
+
*
|
|
4
|
+
* Provides localized string filtering with collation support.
|
|
5
|
+
*
|
|
6
|
+
* Port of @react-aria/i18n useFilter.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createMemo } from 'solid-js';
|
|
10
|
+
import { createCollator } from './createCollator';
|
|
11
|
+
|
|
12
|
+
// ============================================
|
|
13
|
+
// TYPES
|
|
14
|
+
// ============================================
|
|
15
|
+
|
|
16
|
+
export interface Filter {
|
|
17
|
+
/** Returns whether a string starts with a given substring. */
|
|
18
|
+
startsWith(string: string, substring: string): boolean;
|
|
19
|
+
/** Returns whether a string ends with a given substring. */
|
|
20
|
+
endsWith(string: string, substring: string): boolean;
|
|
21
|
+
/** Returns whether a string contains a given substring. */
|
|
22
|
+
contains(string: string, substring: string): boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// ============================================
|
|
26
|
+
// HOOK
|
|
27
|
+
// ============================================
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Provides localized string search functionality for filtering or matching items.
|
|
31
|
+
* Respects locale-specific collation rules for case and diacritic sensitivity.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```tsx
|
|
35
|
+
* function SearchableList(props: { items: { name: string }[] }) {
|
|
36
|
+
* const [query, setQuery] = createSignal('');
|
|
37
|
+
* const filter = createFilter({ sensitivity: 'base' });
|
|
38
|
+
*
|
|
39
|
+
* const filteredItems = () =>
|
|
40
|
+
* props.items.filter((item) =>
|
|
41
|
+
* filter().contains(item.name, query())
|
|
42
|
+
* );
|
|
43
|
+
*
|
|
44
|
+
* return (
|
|
45
|
+
* <>
|
|
46
|
+
* <input
|
|
47
|
+
* value={query()}
|
|
48
|
+
* onInput={(e) => setQuery(e.target.value)}
|
|
49
|
+
* placeholder="Search..."
|
|
50
|
+
* />
|
|
51
|
+
* <ul>
|
|
52
|
+
* <For each={filteredItems()}>
|
|
53
|
+
* {(item) => <li>{item.name}</li>}
|
|
54
|
+
* </For>
|
|
55
|
+
* </ul>
|
|
56
|
+
* </>
|
|
57
|
+
* );
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```tsx
|
|
63
|
+
* // Case-insensitive, diacritic-insensitive filtering
|
|
64
|
+
* const filter = createFilter({ sensitivity: 'base' });
|
|
65
|
+
* filter().contains('Café', 'cafe'); // true
|
|
66
|
+
* filter().startsWith('Hello', 'hello'); // true
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export function createFilter(options?: Intl.CollatorOptions): () => Filter {
|
|
70
|
+
const collator = createCollator({
|
|
71
|
+
usage: 'search',
|
|
72
|
+
...options,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return createMemo(() => {
|
|
76
|
+
const coll = collator();
|
|
77
|
+
|
|
78
|
+
const startsWith = (str: string, substring: string): boolean => {
|
|
79
|
+
if (substring.length === 0) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Normalize both strings for safe slicing
|
|
84
|
+
const normalizedStr = str.normalize('NFC');
|
|
85
|
+
const normalizedSub = substring.normalize('NFC');
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
coll.compare(normalizedStr.slice(0, normalizedSub.length), normalizedSub) ===
|
|
89
|
+
0
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const endsWith = (str: string, substring: string): boolean => {
|
|
94
|
+
if (substring.length === 0) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const normalizedStr = str.normalize('NFC');
|
|
99
|
+
const normalizedSub = substring.normalize('NFC');
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
coll.compare(normalizedStr.slice(-normalizedSub.length), normalizedSub) === 0
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const contains = (str: string, substring: string): boolean => {
|
|
107
|
+
if (substring.length === 0) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const normalizedStr = str.normalize('NFC');
|
|
112
|
+
const normalizedSub = substring.normalize('NFC');
|
|
113
|
+
const sliceLen = normalizedSub.length;
|
|
114
|
+
|
|
115
|
+
for (let scan = 0; scan + sliceLen <= normalizedStr.length; scan++) {
|
|
116
|
+
const slice = normalizedStr.slice(scan, scan + sliceLen);
|
|
117
|
+
if (coll.compare(normalizedSub, slice) === 0) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return false;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
startsWith,
|
|
127
|
+
endsWith,
|
|
128
|
+
contains,
|
|
129
|
+
};
|
|
130
|
+
});
|
|
131
|
+
}
|