@ibobbyts/svelte-ui-utils 0.4.1 → 0.4.3
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/README.md +26 -1
- package/dist/dropdown/Dropdown.svelte +58 -12
- package/dist/dropdown/Dropdown.svelte.d.ts +1 -0
- package/dist/dropdown/Dropdown.svelte.d.ts.map +1 -1
- package/dist/dropdown/DropdownMultiSelect.svelte +2 -0
- package/dist/dropdown/DropdownMultiSelect.svelte.d.ts +1 -0
- package/dist/dropdown/DropdownMultiSelect.svelte.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/segmented-date/SegmentedDateInput.svelte +193 -0
- package/dist/segmented-date/SegmentedDateInput.svelte.d.ts +26 -0
- package/dist/segmented-date/SegmentedDateInput.svelte.d.ts.map +1 -0
- package/dist/segmented-date/index.d.ts +3 -0
- package/dist/segmented-date/index.d.ts.map +1 -0
- package/dist/segmented-date/index.js +2 -0
- package/dist/segmented-date/state.d.ts +10 -0
- package/dist/segmented-date/state.d.ts.map +1 -0
- package/dist/segmented-date/state.js +67 -0
- package/dist/style.css +26 -0
- package/package.json +11 -2
package/README.md
CHANGED
|
@@ -511,7 +511,12 @@ relational pseudo-class.
|
|
|
511
511
|
The original flat `options` API remains available. New callers may opt into
|
|
512
512
|
grouped options with `optionGroups`; each group can have an
|
|
513
513
|
optional accessible label and its options keep the same keyboard and disabled
|
|
514
|
-
semantics.
|
|
514
|
+
semantics. Set `groupsCollapsedByDefault` to `"true"` to initially collapse
|
|
515
|
+
all groups, or to `"auto"` to initially expand only groups containing a
|
|
516
|
+
selected option; `"false"` is the default. The initial state is evaluated each
|
|
517
|
+
time the menu opens, and selecting options while it remains open does not
|
|
518
|
+
change the current collapsed state. Group headings can always be toggled
|
|
519
|
+
manually. `width`, `minWidth`, `maxWidth`, and `className` are optional styling
|
|
515
520
|
hooks. `onTriggerClick` runs before the dropdown toggles, so a nested control
|
|
516
521
|
can stop event propagation without preventing the dropdown from opening.
|
|
517
522
|
|
|
@@ -845,3 +850,23 @@ bun add @ibobbyts/svelte-ui-utils@0.3.1 svelte
|
|
|
845
850
|
```
|
|
846
851
|
|
|
847
852
|
Use it after each release when a Bun-based project will consume the package.
|
|
853
|
+
|
|
854
|
+
## 分段日期输入(本地新增,尚未发布)
|
|
855
|
+
|
|
856
|
+
```svelte
|
|
857
|
+
<script lang="ts">
|
|
858
|
+
import { SegmentedDateInput } from '@ibobbyts/svelte-ui-utils/segmented-date';
|
|
859
|
+
let dob = $state('');
|
|
860
|
+
</script>
|
|
861
|
+
|
|
862
|
+
<SegmentedDateInput name="dob" bind:value={dob} ariaLabel="生日"
|
|
863
|
+
yearLabel="年" monthLabel="月" dayLabel="日" autocomplete="bday" />
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
支持 `precision="year" | "month" | "day"`(默认 `day`)、数字输入、全角数字归一化、完整日期粘贴及月日失焦补零。`value` 可双向绑定;`onvalueinput` 接收用户输入后的组合值。日历有效性和业务范围由调用方校验。
|
|
867
|
+
|
|
868
|
+
默认用隐藏字段提交组合值;`submitParts={true}` 改为提交 `${name}Year`、`${name}Month`、`${name}Day`(按精度决定字段)。支持 `required`、`readonly`、`disabled`、`id`(关联年输入框)和生日自动填充。`ariaLabel`、各段标签及占位符由调用方提供,以接入应用本地化。
|
|
869
|
+
|
|
870
|
+
引入公共 `style.css` 后可独立使用,无需 Tailwind 或 DaisyUI。`class` 定制容器;`inputClass` 替换默认输入框装饰样式,布局仍由组件负责。MMS 通过该参数保留 DaisyUI 外观。
|
|
871
|
+
|
|
872
|
+
纯函数和类型可从 `@ibobbyts/svelte-ui-utils/segmented-date/state` 引入:`splitSegmentedDate`、`composeSegmentedDate`、`parsePastedSegmentedDate`、`SegmentedDateParts`、`SegmentedDatePrecision`;此入口不加载 Svelte,适用于服务端和 Node。
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
export let multiselect = false;
|
|
22
22
|
export let options: DropdownOption[] = [];
|
|
23
23
|
export let optionGroups: DropdownOptionGroup[] | undefined = undefined;
|
|
24
|
+
export let groupsCollapsedByDefault: 'true' | 'false' | 'auto' = 'false';
|
|
24
25
|
export let ariaLabel: string | undefined = undefined;
|
|
25
26
|
export let placement: DropdownPlacement = 'auto';
|
|
26
27
|
export let menuAlign: DropdownMenuAlign = 'left';
|
|
@@ -56,11 +57,15 @@
|
|
|
56
57
|
let typeaheadBuffer = '';
|
|
57
58
|
let typeaheadTimer: ReturnType<typeof setTimeout> | undefined;
|
|
58
59
|
let typeaheadGeneration = 0;
|
|
60
|
+
let collapsedGroupIndexes = new Set<number>();
|
|
59
61
|
// Keep the buffer long enough for users to type multi-character aliases
|
|
60
62
|
// while the menu is rendering a large option list.
|
|
61
63
|
const typeaheadTimeoutMs = 1000;
|
|
62
64
|
|
|
63
65
|
$: resolvedOptions = optionGroups === undefined ? options : optionGroups.flatMap((group) => group.options);
|
|
66
|
+
$: visibleOptions = optionGroups === undefined
|
|
67
|
+
? options
|
|
68
|
+
: optionGroups.flatMap((group, groupIndex) => group.label && collapsedGroupIndexes.has(groupIndex) ? [] : group.options);
|
|
64
69
|
$: selectedValues = normalizeSelectedValues(multiselect && Array.isArray(value) ? value : []);
|
|
65
70
|
$: selectedOption = Array.isArray(value) ? undefined : resolvedOptions.find((option) => option.value === value);
|
|
66
71
|
$: selectedText = multiselect
|
|
@@ -89,7 +94,7 @@
|
|
|
89
94
|
}
|
|
90
95
|
|
|
91
96
|
function firstEnabledOption(): DropdownOption | undefined {
|
|
92
|
-
return
|
|
97
|
+
return visibleOptions.find((option) => !option.disabled);
|
|
93
98
|
}
|
|
94
99
|
|
|
95
100
|
function normalizeSelectedValues(nextValues: DropdownMultiValue): DropdownMultiValue {
|
|
@@ -104,7 +109,7 @@
|
|
|
104
109
|
}
|
|
105
110
|
|
|
106
111
|
function initialActiveValue(): DropdownValue {
|
|
107
|
-
const firstSelectedEnabled =
|
|
112
|
+
const firstSelectedEnabled = visibleOptions.find(
|
|
108
113
|
(option) => selectedValues.includes(option.value) && !option.disabled
|
|
109
114
|
);
|
|
110
115
|
return firstSelectedEnabled?.value ?? selectedOption?.value ?? firstEnabledOption()?.value ?? '';
|
|
@@ -115,21 +120,21 @@
|
|
|
115
120
|
}
|
|
116
121
|
|
|
117
122
|
function activeOptionIndex(nextActiveValue: DropdownValue): number {
|
|
118
|
-
const index =
|
|
123
|
+
const index = visibleOptions.findIndex((option) => option.value === nextActiveValue && !option.disabled);
|
|
119
124
|
if (index >= 0) {
|
|
120
125
|
return index;
|
|
121
126
|
}
|
|
122
|
-
const fallbackIndex =
|
|
127
|
+
const fallbackIndex = visibleOptions.findIndex(
|
|
123
128
|
(option) => isOptionSelected(option) && !option.disabled
|
|
124
129
|
);
|
|
125
130
|
if (fallbackIndex >= 0) {
|
|
126
131
|
return fallbackIndex;
|
|
127
132
|
}
|
|
128
|
-
return
|
|
133
|
+
return visibleOptions.findIndex((option) => !option.disabled);
|
|
129
134
|
}
|
|
130
135
|
|
|
131
136
|
function moveActiveOption(offset: number) {
|
|
132
|
-
const enabledOptions =
|
|
137
|
+
const enabledOptions = visibleOptions.filter((option) => !option.disabled);
|
|
133
138
|
if (enabledOptions.length === 0) {
|
|
134
139
|
return;
|
|
135
140
|
}
|
|
@@ -180,7 +185,7 @@
|
|
|
180
185
|
: key.toLocaleLowerCase();
|
|
181
186
|
const nextBuffer = `${typeaheadBuffer}${normalizedKey}`;
|
|
182
187
|
const findMatch = (prefix: string) =>
|
|
183
|
-
|
|
188
|
+
visibleOptions.find(
|
|
184
189
|
(option) =>
|
|
185
190
|
!option.disabled &&
|
|
186
191
|
[option.searchText, option.label]
|
|
@@ -233,12 +238,42 @@
|
|
|
233
238
|
}
|
|
234
239
|
if (!open) {
|
|
235
240
|
updateResolvedPlacement();
|
|
241
|
+
initializeCollapsedGroups();
|
|
236
242
|
}
|
|
237
243
|
clearTypeaheadBuffer();
|
|
238
244
|
open = !open;
|
|
239
245
|
activeValue = initialActiveValue();
|
|
240
246
|
}
|
|
241
247
|
|
|
248
|
+
function isGroupCollapsed(groupIndex: number): boolean {
|
|
249
|
+
return collapsedGroupIndexes.has(groupIndex);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function initializeCollapsedGroups() {
|
|
253
|
+
if (optionGroups === undefined || groupsCollapsedByDefault === 'false') {
|
|
254
|
+
collapsedGroupIndexes = new Set();
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
if (groupsCollapsedByDefault === 'true') {
|
|
258
|
+
collapsedGroupIndexes = new Set(
|
|
259
|
+
optionGroups.flatMap((group, index) => group.label ? [index] : [])
|
|
260
|
+
);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
collapsedGroupIndexes = new Set(
|
|
264
|
+
optionGroups.flatMap((group, index) =>
|
|
265
|
+
group.label && group.options.some((option) => isOptionSelected(option)) ? [] : group.label ? [index] : []
|
|
266
|
+
)
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function toggleGroup(groupIndex: number) {
|
|
271
|
+
const next = new Set(collapsedGroupIndexes);
|
|
272
|
+
if (next.has(groupIndex)) next.delete(groupIndex);
|
|
273
|
+
else next.add(groupIndex);
|
|
274
|
+
collapsedGroupIndexes = next;
|
|
275
|
+
}
|
|
276
|
+
|
|
242
277
|
function handleTriggerClick(event: MouseEvent) {
|
|
243
278
|
onTriggerClick?.(event);
|
|
244
279
|
toggleOpen();
|
|
@@ -284,7 +319,7 @@
|
|
|
284
319
|
if ((event.key === 'Enter' || event.key === ' ') && open) {
|
|
285
320
|
event.preventDefault();
|
|
286
321
|
const index = activeOptionIndex(activeValue);
|
|
287
|
-
const option = index >= 0 ?
|
|
322
|
+
const option = index >= 0 ? visibleOptions[index] : undefined;
|
|
288
323
|
if (option) {
|
|
289
324
|
selectOption(option);
|
|
290
325
|
}
|
|
@@ -558,15 +593,25 @@
|
|
|
558
593
|
</button>
|
|
559
594
|
{/each}
|
|
560
595
|
{:else}
|
|
561
|
-
{#each optionGroups as group}
|
|
596
|
+
{#each optionGroups as group, groupIndex}
|
|
562
597
|
<div class="suu-dropdown__group" role="group" aria-label={group.label}>
|
|
563
598
|
{#if group.label}
|
|
564
|
-
<
|
|
599
|
+
<button
|
|
600
|
+
type="button"
|
|
601
|
+
class="suu-dropdown__group-label"
|
|
602
|
+
aria-expanded={!collapsedGroupIndexes.has(groupIndex)}
|
|
603
|
+
on:click|stopPropagation={() => toggleGroup(groupIndex)}
|
|
604
|
+
>
|
|
605
|
+
<span>{group.label}</span>
|
|
606
|
+
<span class="suu-dropdown__group-chevron" aria-hidden="true"></span>
|
|
607
|
+
</button>
|
|
565
608
|
{/if}
|
|
566
|
-
{#
|
|
609
|
+
{#if !group.label || !collapsedGroupIndexes.has(groupIndex)}
|
|
610
|
+
{#each group.options as option, optionIndex}
|
|
567
611
|
<button
|
|
568
612
|
type="button"
|
|
569
613
|
class="suu-dropdown__option"
|
|
614
|
+
class:suu-dropdown__option--group-first={Boolean(group.label) && optionIndex === 0}
|
|
570
615
|
class:suu-dropdown__option--active={option.value === activeValue}
|
|
571
616
|
class:suu-dropdown__option--disabled={option.disabled}
|
|
572
617
|
role="option"
|
|
@@ -591,7 +636,8 @@
|
|
|
591
636
|
{/if}
|
|
592
637
|
<span class="suu-dropdown__label">{option.label}</span>
|
|
593
638
|
</button>
|
|
594
|
-
|
|
639
|
+
{/each}
|
|
640
|
+
{/if}
|
|
595
641
|
</div>
|
|
596
642
|
{/each}
|
|
597
643
|
{/if}
|
|
@@ -18,6 +18,7 @@ declare const Dropdown: $$__sveltets_2_IsomorphicComponent<{
|
|
|
18
18
|
multiselect?: boolean;
|
|
19
19
|
options?: DropdownOption[];
|
|
20
20
|
optionGroups?: DropdownOptionGroup[] | undefined;
|
|
21
|
+
groupsCollapsedByDefault?: "true" | "false" | "auto";
|
|
21
22
|
ariaLabel?: string | undefined;
|
|
22
23
|
placement?: DropdownPlacement;
|
|
23
24
|
menuAlign?: DropdownMenuAlign;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dropdown.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/Dropdown.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAER,iBAAiB,EAGjB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,8BAA8B,EAC9B,iBAAiB,EACjB,2BAA2B,EAE5B,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"Dropdown.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/Dropdown.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAER,iBAAiB,EAGjB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,8BAA8B,EAC9B,iBAAiB,EACjB,2BAA2B,EAE5B,MAAM,YAAY,CAAC;AAuiBtB,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IAC9G,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,QAAQ;SAV0e,MAAM,GAAG,SAAS;YAAU,iBAAiB;;cAA8C,cAAc,EAAE;mBAAiB,mBAAmB,EAAE,GAAG,SAAS;+BAA6B,MAAM,GAAG,OAAO,GAAG,MAAM;gBAAc,MAAM,GAAG,SAAS;gBAAc,iBAAiB;gBAAc,iBAAiB;;;;WAAuG,MAAM,GAAG,SAAS;;YAAsC,MAAM,GAAG,SAAS;eAAa,MAAM,GAAG,SAAS;eAAa,MAAM,GAAG,SAAS;gBAAc,MAAM,GAAG,SAAS;;eAAqC,8BAA8B,GAAG,SAAS;qBAAmB,2BAA2B,GAAG,SAAS;;;kBAUpmC,CAAC;AAC5E,KAAK,QAAQ,GAAG,YAAY,CAAC,OAAO,QAAQ,CAAC,CAAC;AAChD,eAAe,QAAQ,CAAC"}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
export let value: DropdownMultiValue = [];
|
|
17
17
|
export let options: DropdownOption[] = [];
|
|
18
18
|
export let optionGroups: DropdownOptionGroup[] | undefined = undefined;
|
|
19
|
+
export let groupsCollapsedByDefault: 'true' | 'false' | 'auto' = 'false';
|
|
19
20
|
export let ariaLabel: string | undefined = undefined;
|
|
20
21
|
export let placement: DropdownPlacement = 'auto';
|
|
21
22
|
export let menuAlign: DropdownMenuAlign = 'left';
|
|
@@ -37,6 +38,7 @@
|
|
|
37
38
|
multiselect={true}
|
|
38
39
|
{options}
|
|
39
40
|
{optionGroups}
|
|
41
|
+
{groupsCollapsedByDefault}
|
|
40
42
|
{ariaLabel}
|
|
41
43
|
{placement}
|
|
42
44
|
{menuAlign}
|
|
@@ -17,6 +17,7 @@ declare const DropdownMultiSelect: $$__sveltets_2_IsomorphicComponent<{
|
|
|
17
17
|
value?: DropdownMultiValue;
|
|
18
18
|
options?: DropdownOption[];
|
|
19
19
|
optionGroups?: DropdownOptionGroup[] | undefined;
|
|
20
|
+
groupsCollapsedByDefault?: "true" | "false" | "auto";
|
|
20
21
|
ariaLabel?: string | undefined;
|
|
21
22
|
placement?: DropdownPlacement;
|
|
22
23
|
menuAlign?: DropdownMenuAlign;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DropdownMultiSelect.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/DropdownMultiSelect.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACR,iBAAiB,EACjB,0BAA0B,EAC1B,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,2BAA2B,EAC5B,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"DropdownMultiSelect.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/DropdownMultiSelect.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACR,iBAAiB,EACjB,0BAA0B,EAC1B,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,2BAA2B,EAC5B,MAAM,YAAY,CAAC;AAgCtB,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IAC9G,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,mBAAmB;SAVka,MAAM,GAAG,SAAS;YAAU,kBAAkB;cAAY,cAAc,EAAE;mBAAiB,mBAAmB,EAAE,GAAG,SAAS;+BAA6B,MAAM,GAAG,OAAO,GAAG,MAAM;gBAAc,MAAM,GAAG,SAAS;gBAAc,iBAAiB;gBAAc,iBAAiB;;;;YAAwG,MAAM,GAAG,SAAS;eAAa,MAAM,GAAG,SAAS;eAAa,MAAM,GAAG,SAAS;gBAAc,MAAM,GAAG,SAAS;;eAAqC,0BAA0B,GAAG,SAAS;qBAAmB,2BAA2B,GAAG,SAAS;;;kBAUh8B,CAAC;AACvF,KAAK,mBAAmB,GAAG,YAAY,CAAC,OAAO,mBAAmB,CAAC,CAAC;AACtE,eAAe,mBAAmB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,4 +9,5 @@ export * from './ordered-list/index.js';
|
|
|
9
9
|
export * from './sortable-table/index.js';
|
|
10
10
|
export { getUiMessages, resolveUiLanguage, uiLanguages } from './i18n.js';
|
|
11
11
|
export type { UiLanguage, UiMessages } from './i18n.js';
|
|
12
|
+
export * from './segmented-date/index.js';
|
|
12
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC1E,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC1E,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACxD,cAAc,2BAA2B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { untrack } from "svelte";
|
|
3
|
+
import {
|
|
4
|
+
composeSegmentedDate,
|
|
5
|
+
parsePastedSegmentedDate,
|
|
6
|
+
splitSegmentedDate,
|
|
7
|
+
type SegmentedDatePrecision,
|
|
8
|
+
} from "./state.js";
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
value = $bindable(""),
|
|
12
|
+
precision = "day",
|
|
13
|
+
name,
|
|
14
|
+
id,
|
|
15
|
+
required = false,
|
|
16
|
+
readonly = false,
|
|
17
|
+
disabled = false,
|
|
18
|
+
ariaLabel,
|
|
19
|
+
yearLabel,
|
|
20
|
+
monthLabel,
|
|
21
|
+
dayLabel,
|
|
22
|
+
yearPlaceholder = "YYYY",
|
|
23
|
+
monthPlaceholder = "MM",
|
|
24
|
+
dayPlaceholder = "DD",
|
|
25
|
+
submitParts = false,
|
|
26
|
+
autocomplete,
|
|
27
|
+
class: className = "",
|
|
28
|
+
inputClass = "",
|
|
29
|
+
onvalueinput,
|
|
30
|
+
} = $props<{
|
|
31
|
+
value?: string;
|
|
32
|
+
precision?: SegmentedDatePrecision;
|
|
33
|
+
name: string;
|
|
34
|
+
id?: string;
|
|
35
|
+
required?: boolean;
|
|
36
|
+
readonly?: boolean;
|
|
37
|
+
disabled?: boolean;
|
|
38
|
+
ariaLabel: string;
|
|
39
|
+
yearLabel: string;
|
|
40
|
+
monthLabel?: string;
|
|
41
|
+
dayLabel?: string;
|
|
42
|
+
yearPlaceholder?: string;
|
|
43
|
+
monthPlaceholder?: string;
|
|
44
|
+
dayPlaceholder?: string;
|
|
45
|
+
submitParts?: boolean;
|
|
46
|
+
autocomplete?: "bday";
|
|
47
|
+
class?: string;
|
|
48
|
+
inputClass?: string;
|
|
49
|
+
onvalueinput?: (value: string) => void;
|
|
50
|
+
}>();
|
|
51
|
+
|
|
52
|
+
let year = $state("");
|
|
53
|
+
let month = $state("");
|
|
54
|
+
let day = $state("");
|
|
55
|
+
|
|
56
|
+
$effect(() => {
|
|
57
|
+
const parts = splitSegmentedDate(value, precision);
|
|
58
|
+
// Keep partially entered segments while the child is emitting an incomplete value.
|
|
59
|
+
const current = untrack(() => composeSegmentedDate({ year, month, day }, precision));
|
|
60
|
+
if (value !== current) {
|
|
61
|
+
year = parts.year;
|
|
62
|
+
month = parts.month;
|
|
63
|
+
day = parts.day;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
function updateValue() {
|
|
68
|
+
const nextValue = composeSegmentedDate({ year, month, day }, precision);
|
|
69
|
+
if (nextValue === value) return;
|
|
70
|
+
value = nextValue;
|
|
71
|
+
onvalueinput?.(value);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function handleInput(part: SegmentedDatePrecision, event: Event) {
|
|
75
|
+
const input = event.currentTarget as HTMLInputElement;
|
|
76
|
+
const normalized = input.value.normalize("NFKC").replace(/\D/g, "")
|
|
77
|
+
.slice(0, part === "year" ? 4 : 2);
|
|
78
|
+
input.value = normalized;
|
|
79
|
+
if (part === "year") year = normalized;
|
|
80
|
+
if (part === "month") month = normalized;
|
|
81
|
+
if (part === "day") day = normalized;
|
|
82
|
+
updateValue();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function handleBlur(part: "month" | "day") {
|
|
86
|
+
if (part === "month" && /^\d$/.test(month)) month = month.padStart(2, "0");
|
|
87
|
+
if (part === "day" && /^\d$/.test(day)) day = day.padStart(2, "0");
|
|
88
|
+
updateValue();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function handlePaste(event: ClipboardEvent) {
|
|
92
|
+
const parts = parsePastedSegmentedDate(
|
|
93
|
+
event.clipboardData?.getData("text") ?? "",
|
|
94
|
+
precision,
|
|
95
|
+
);
|
|
96
|
+
if (!parts) return;
|
|
97
|
+
event.preventDefault();
|
|
98
|
+
year = parts.year;
|
|
99
|
+
month = parts.month;
|
|
100
|
+
day = parts.day;
|
|
101
|
+
updateValue();
|
|
102
|
+
}
|
|
103
|
+
</script>
|
|
104
|
+
|
|
105
|
+
{#if !submitParts}
|
|
106
|
+
<input type="hidden" {name} {value} {disabled} />
|
|
107
|
+
{/if}
|
|
108
|
+
|
|
109
|
+
<div
|
|
110
|
+
class={["suu-segmented-date", className]}
|
|
111
|
+
data-precision={precision}
|
|
112
|
+
role="group"
|
|
113
|
+
aria-label={ariaLabel}
|
|
114
|
+
>
|
|
115
|
+
<input
|
|
116
|
+
class={["suu-segmented-date__input", inputClass]}
|
|
117
|
+
class:suu-segmented-date__input--default={!inputClass}
|
|
118
|
+
type="text"
|
|
119
|
+
name={submitParts ? `${name}Year` : undefined}
|
|
120
|
+
{id}
|
|
121
|
+
bind:value={year}
|
|
122
|
+
oninput={(event) => handleInput("year", event)}
|
|
123
|
+
onpaste={handlePaste}
|
|
124
|
+
inputmode="numeric"
|
|
125
|
+
pattern="[0-9][0-9][0-9][0-9]"
|
|
126
|
+
maxlength="4"
|
|
127
|
+
placeholder={yearPlaceholder}
|
|
128
|
+
aria-label={yearLabel}
|
|
129
|
+
autocomplete={autocomplete ? "bday-year" : undefined}
|
|
130
|
+
{required}
|
|
131
|
+
{readonly}
|
|
132
|
+
{disabled}
|
|
133
|
+
/>
|
|
134
|
+
{#if precision !== "year"}
|
|
135
|
+
<input
|
|
136
|
+
class={["suu-segmented-date__input", inputClass]}
|
|
137
|
+
class:suu-segmented-date__input--default={!inputClass}
|
|
138
|
+
type="text"
|
|
139
|
+
name={submitParts ? `${name}Month` : undefined}
|
|
140
|
+
bind:value={month}
|
|
141
|
+
oninput={(event) => handleInput("month", event)}
|
|
142
|
+
onblur={() => handleBlur("month")}
|
|
143
|
+
onpaste={handlePaste}
|
|
144
|
+
inputmode="numeric"
|
|
145
|
+
pattern="[0-9][0-9]?"
|
|
146
|
+
maxlength="2"
|
|
147
|
+
placeholder={monthPlaceholder}
|
|
148
|
+
aria-label={monthLabel}
|
|
149
|
+
autocomplete={autocomplete ? "bday-month" : undefined}
|
|
150
|
+
{required}
|
|
151
|
+
{readonly}
|
|
152
|
+
{disabled}
|
|
153
|
+
/>
|
|
154
|
+
{/if}
|
|
155
|
+
{#if precision === "day"}
|
|
156
|
+
<input
|
|
157
|
+
class={["suu-segmented-date__input", inputClass]}
|
|
158
|
+
class:suu-segmented-date__input--default={!inputClass}
|
|
159
|
+
type="text"
|
|
160
|
+
name={submitParts ? `${name}Day` : undefined}
|
|
161
|
+
bind:value={day}
|
|
162
|
+
oninput={(event) => handleInput("day", event)}
|
|
163
|
+
onblur={() => handleBlur("day")}
|
|
164
|
+
onpaste={handlePaste}
|
|
165
|
+
inputmode="numeric"
|
|
166
|
+
pattern="[0-9][0-9]?"
|
|
167
|
+
maxlength="2"
|
|
168
|
+
placeholder={dayPlaceholder}
|
|
169
|
+
aria-label={dayLabel}
|
|
170
|
+
autocomplete={autocomplete ? "bday-day" : undefined}
|
|
171
|
+
{required}
|
|
172
|
+
{readonly}
|
|
173
|
+
{disabled}
|
|
174
|
+
/>
|
|
175
|
+
{/if}
|
|
176
|
+
</div>
|
|
177
|
+
|
|
178
|
+
<style>
|
|
179
|
+
.suu-segmented-date { display: grid; min-width: 0; gap: 0.5rem; }
|
|
180
|
+
.suu-segmented-date[data-precision="year"] { grid-template-columns: minmax(0, 1fr); }
|
|
181
|
+
.suu-segmented-date[data-precision="month"] { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
|
|
182
|
+
.suu-segmented-date[data-precision="day"] { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr); }
|
|
183
|
+
.suu-segmented-date__input { min-width: 0; width: 100%; box-sizing: border-box; }
|
|
184
|
+
.suu-segmented-date__input--default {
|
|
185
|
+
padding: 0.5rem 0.75rem;
|
|
186
|
+
border: 1px solid var(--suu-color-border);
|
|
187
|
+
border-radius: var(--suu-radius);
|
|
188
|
+
background: var(--suu-color-bg);
|
|
189
|
+
color: var(--suu-color-text);
|
|
190
|
+
font: inherit;
|
|
191
|
+
}
|
|
192
|
+
.suu-segmented-date__input--default:focus-visible { outline: 2px solid var(--suu-color-accent); outline-offset: 2px; }
|
|
193
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type SegmentedDatePrecision } from "./state.js";
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
value?: string;
|
|
4
|
+
precision?: SegmentedDatePrecision;
|
|
5
|
+
name: string;
|
|
6
|
+
id?: string;
|
|
7
|
+
required?: boolean;
|
|
8
|
+
readonly?: boolean;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
ariaLabel: string;
|
|
11
|
+
yearLabel: string;
|
|
12
|
+
monthLabel?: string;
|
|
13
|
+
dayLabel?: string;
|
|
14
|
+
yearPlaceholder?: string;
|
|
15
|
+
monthPlaceholder?: string;
|
|
16
|
+
dayPlaceholder?: string;
|
|
17
|
+
submitParts?: boolean;
|
|
18
|
+
autocomplete?: "bday";
|
|
19
|
+
class?: string;
|
|
20
|
+
inputClass?: string;
|
|
21
|
+
onvalueinput?: (value: string) => void;
|
|
22
|
+
};
|
|
23
|
+
declare const SegmentedDateInput: import("svelte").Component<$$ComponentProps, {}, "value">;
|
|
24
|
+
type SegmentedDateInput = ReturnType<typeof SegmentedDateInput>;
|
|
25
|
+
export default SegmentedDateInput;
|
|
26
|
+
//# sourceMappingURL=SegmentedDateInput.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SegmentedDateInput.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/segmented-date/SegmentedDateInput.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,EAIC,KAAK,sBAAsB,EAC9B,MAAM,YAAY,CAAC;AAEvB,KAAK,gBAAgB,GAAG;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,sBAAsB,CAAC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C,CAAC;AAkGN,QAAA,MAAM,kBAAkB,2DAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/segmented-date/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type SegmentedDatePrecision = "year" | "month" | "day";
|
|
2
|
+
export type SegmentedDateParts = {
|
|
3
|
+
year: string;
|
|
4
|
+
month: string;
|
|
5
|
+
day: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function splitSegmentedDate(value: string, precision: SegmentedDatePrecision): SegmentedDateParts;
|
|
8
|
+
export declare function composeSegmentedDate(parts: SegmentedDateParts, precision: SegmentedDatePrecision): string;
|
|
9
|
+
export declare function parsePastedSegmentedDate(value: string, precision: SegmentedDatePrecision): SegmentedDateParts | null;
|
|
10
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/lib/segmented-date/state.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAE9D,MAAM,MAAM,kBAAkB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACf,CAAC;AAQF,wBAAgB,kBAAkB,CAC9B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,sBAAsB,GAClC,kBAAkB,CAuBpB;AAED,wBAAgB,oBAAoB,CAChC,KAAK,EAAE,kBAAkB,EACzB,SAAS,EAAE,sBAAsB,GAClC,MAAM,CAqBR;AAED,wBAAgB,wBAAwB,CACpC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,sBAAsB,GAClC,kBAAkB,GAAG,IAAI,CAe3B"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const EMPTY_PARTS = { year: "", month: "", day: "" };
|
|
2
|
+
function normalizePart(value) {
|
|
3
|
+
return value.normalize("NFKC").trim();
|
|
4
|
+
}
|
|
5
|
+
export function splitSegmentedDate(value, precision) {
|
|
6
|
+
const normalized = value.normalize("NFKC").trim();
|
|
7
|
+
const patterns = {
|
|
8
|
+
year: /^([^-]*)$/,
|
|
9
|
+
month: /^([^-]*)-([^-]*)$/,
|
|
10
|
+
day: /^([^-]*)-([^-]*)-([^-]*)$/,
|
|
11
|
+
};
|
|
12
|
+
const match = normalized.match(patterns[precision]);
|
|
13
|
+
if (!match) {
|
|
14
|
+
if (precision === "month" && /^\d{4}$/.test(normalized)) {
|
|
15
|
+
return { year: normalized, month: "", day: "" };
|
|
16
|
+
}
|
|
17
|
+
if (precision === "month" && /^\d{1,2}$/.test(normalized)) {
|
|
18
|
+
return { year: "", month: normalized, day: "" };
|
|
19
|
+
}
|
|
20
|
+
return { ...EMPTY_PARTS };
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
year: match[1] ?? "",
|
|
24
|
+
month: precision === "year" ? "" : (match[2] ?? ""),
|
|
25
|
+
day: precision === "day" ? (match[3] ?? "") : "",
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function composeSegmentedDate(parts, precision) {
|
|
29
|
+
const year = normalizePart(parts.year);
|
|
30
|
+
const month = normalizePart(parts.month);
|
|
31
|
+
const day = normalizePart(parts.day);
|
|
32
|
+
if (!year && (precision === "year" || !month) && (precision !== "day" || !day)) {
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
if (precision === "year")
|
|
36
|
+
return year;
|
|
37
|
+
if (precision === "month") {
|
|
38
|
+
if (/^\d{4}$/.test(year) && /^\d{1,2}$/.test(month)) {
|
|
39
|
+
return `${year}-${month.padStart(2, "0")}`;
|
|
40
|
+
}
|
|
41
|
+
if (/^\d{4}$/.test(year) && !month)
|
|
42
|
+
return year;
|
|
43
|
+
if (!year && /^\d{1,2}$/.test(month))
|
|
44
|
+
return month.padStart(2, "0");
|
|
45
|
+
return `${year}-${month}`;
|
|
46
|
+
}
|
|
47
|
+
if (/^\d{4}$/.test(year) && /^\d{1,2}$/.test(month) && /^\d{1,2}$/.test(day)) {
|
|
48
|
+
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
|
|
49
|
+
}
|
|
50
|
+
return `${year}-${month}-${day}`;
|
|
51
|
+
}
|
|
52
|
+
export function parsePastedSegmentedDate(value, precision) {
|
|
53
|
+
const normalized = value.normalize("NFKC").trim();
|
|
54
|
+
const patterns = {
|
|
55
|
+
year: /^(\d{4})$/,
|
|
56
|
+
month: /^(?:(\d{4})[-/.](\d{1,2})|(\d{1,2}))$/,
|
|
57
|
+
day: /^(\d{4})[-/.](\d{1,2})[-/.](\d{1,2})$/,
|
|
58
|
+
};
|
|
59
|
+
const match = normalized.match(patterns[precision]);
|
|
60
|
+
if (!match)
|
|
61
|
+
return null;
|
|
62
|
+
return {
|
|
63
|
+
year: match[1] ?? "",
|
|
64
|
+
month: precision === "year" ? "" : (match[2] ?? match[3]).padStart(2, "0"),
|
|
65
|
+
day: precision === "day" ? match[3].padStart(2, "0") : "",
|
|
66
|
+
};
|
|
67
|
+
}
|
package/dist/style.css
CHANGED
|
@@ -1283,6 +1283,7 @@
|
|
|
1283
1283
|
.suu-dropdown__panel {
|
|
1284
1284
|
max-height: var(--suu-dropdown-panel-max-height, 100vh);
|
|
1285
1285
|
overflow-y: auto;
|
|
1286
|
+
overflow-x: hidden;
|
|
1286
1287
|
background: var(--suu-color-bg);
|
|
1287
1288
|
overscroll-behavior: contain;
|
|
1288
1289
|
}
|
|
@@ -1292,12 +1293,33 @@
|
|
|
1292
1293
|
}
|
|
1293
1294
|
|
|
1294
1295
|
.suu-dropdown__group-label {
|
|
1296
|
+
display: flex;
|
|
1297
|
+
width: 100%;
|
|
1298
|
+
border: 0;
|
|
1295
1299
|
padding: 8px 14px 6px;
|
|
1296
1300
|
background: var(--suu-color-surface);
|
|
1297
1301
|
color: var(--suu-color-muted);
|
|
1302
|
+
cursor: pointer;
|
|
1298
1303
|
font-size: 0.75em;
|
|
1299
1304
|
font-weight: 700;
|
|
1300
1305
|
letter-spacing: 0.02em;
|
|
1306
|
+
font: inherit;
|
|
1307
|
+
text-align: left;
|
|
1308
|
+
align-items: center;
|
|
1309
|
+
justify-content: space-between;
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
.suu-dropdown__group-chevron {
|
|
1313
|
+
width: 7px;
|
|
1314
|
+
height: 7px;
|
|
1315
|
+
border-right: 2px solid currentColor;
|
|
1316
|
+
border-bottom: 2px solid currentColor;
|
|
1317
|
+
transform: rotate(225deg);
|
|
1318
|
+
transition: transform 120ms ease;
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
.suu-dropdown__group-label[aria-expanded='true'] .suu-dropdown__group-chevron {
|
|
1322
|
+
transform: rotate(45deg);
|
|
1301
1323
|
}
|
|
1302
1324
|
|
|
1303
1325
|
.suu-dropdown__option {
|
|
@@ -1313,6 +1335,10 @@
|
|
|
1313
1335
|
text-align: left;
|
|
1314
1336
|
}
|
|
1315
1337
|
|
|
1338
|
+
.suu-dropdown__option--group-first {
|
|
1339
|
+
border-top: 1px solid var(--suu-color-border);
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1316
1342
|
.suu-dropdown--multiselect .suu-dropdown__option {
|
|
1317
1343
|
display: flex;
|
|
1318
1344
|
gap: 10px;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ibobbyts/svelte-ui-utils",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "Reusable Svelte 5 UI utilities for dialogs, toast notifications, dropdown search, and data tables.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -77,7 +77,16 @@
|
|
|
77
77
|
"svelte": "./dist/sortable-table/index.js",
|
|
78
78
|
"default": "./dist/sortable-table/index.js"
|
|
79
79
|
},
|
|
80
|
-
"./style.css": "./dist/style.css"
|
|
80
|
+
"./style.css": "./dist/style.css",
|
|
81
|
+
"./segmented-date": {
|
|
82
|
+
"types": "./dist/segmented-date/index.d.ts",
|
|
83
|
+
"svelte": "./dist/segmented-date/index.js",
|
|
84
|
+
"default": "./dist/segmented-date/index.js"
|
|
85
|
+
},
|
|
86
|
+
"./segmented-date/state": {
|
|
87
|
+
"types": "./dist/segmented-date/state.d.ts",
|
|
88
|
+
"default": "./dist/segmented-date/state.js"
|
|
89
|
+
}
|
|
81
90
|
},
|
|
82
91
|
"publishConfig": {
|
|
83
92
|
"access": "public",
|