fluentui-svelte 0.1.0
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/README.md +201 -0
- package/dist/components/auto-suggest-box/auto-suggest-box.d.ts +2 -0
- package/dist/components/auto-suggest-box/auto-suggest-box.js +2 -0
- package/dist/components/auto-suggest-box/auto-suggest-box.svelte +457 -0
- package/dist/components/auto-suggest-box/auto-suggest-box.svelte.d.ts +4 -0
- package/dist/components/auto-suggest-box/docs/llms.md +73 -0
- package/dist/components/auto-suggest-box/option.svelte +82 -0
- package/dist/components/auto-suggest-box/option.svelte.d.ts +4 -0
- package/dist/components/auto-suggest-box/types.d.ts +140 -0
- package/dist/components/auto-suggest-box/types.js +1 -0
- package/dist/components/avatar/avatar.svelte +269 -0
- package/dist/components/avatar/avatar.svelte.d.ts +20 -0
- package/dist/components/avatar/docs/llms.md +92 -0
- package/dist/components/avatar/type.d.ts +63 -0
- package/dist/components/avatar/type.js +1 -0
- package/dist/components/badge/badge-icon.svelte +103 -0
- package/dist/components/badge/badge-icon.svelte.d.ts +25 -0
- package/dist/components/badge/badge.svelte +163 -0
- package/dist/components/badge/badge.svelte.d.ts +20 -0
- package/dist/components/badge/docs/llms.md +133 -0
- package/dist/components/badge/types.d.ts +70 -0
- package/dist/components/badge/types.js +1 -0
- package/dist/components/badge/utils.svelte.d.ts +16 -0
- package/dist/components/badge/utils.svelte.js +35 -0
- package/dist/components/button/button.svelte +203 -0
- package/dist/components/button/button.svelte.d.ts +38 -0
- package/dist/components/button/docs/llms.md +102 -0
- package/dist/components/button/split-button.svelte +66 -0
- package/dist/components/button/split-button.svelte.d.ts +4 -0
- package/dist/components/button/types.d.ts +84 -0
- package/dist/components/button/types.js +1 -0
- package/dist/components/calendar-date-picker/calendar-date-picker.svelte +119 -0
- package/dist/components/calendar-date-picker/calendar-date-picker.svelte.d.ts +4 -0
- package/dist/components/calendar-date-picker/docs/llms.md +33 -0
- package/dist/components/calendar-date-picker/types.d.ts +36 -0
- package/dist/components/calendar-date-picker/types.js +1 -0
- package/dist/components/calendar-view/calendar-view-controls.svelte +115 -0
- package/dist/components/calendar-view/calendar-view-controls.svelte.d.ts +3 -0
- package/dist/components/calendar-view/calendar-view-days.svelte +210 -0
- package/dist/components/calendar-view/calendar-view-days.svelte.d.ts +3 -0
- package/dist/components/calendar-view/calendar-view-grid.d.ts +38 -0
- package/dist/components/calendar-view/calendar-view-grid.js +140 -0
- package/dist/components/calendar-view/calendar-view-header.svelte +66 -0
- package/dist/components/calendar-view/calendar-view-header.svelte.d.ts +18 -0
- package/dist/components/calendar-view/calendar-view-item.svelte +181 -0
- package/dist/components/calendar-view/calendar-view-item.svelte.d.ts +4 -0
- package/dist/components/calendar-view/calendar-view-months.svelte +165 -0
- package/dist/components/calendar-view/calendar-view-months.svelte.d.ts +3 -0
- package/dist/components/calendar-view/calendar-view-years.svelte +161 -0
- package/dist/components/calendar-view/calendar-view-years.svelte.d.ts +3 -0
- package/dist/components/calendar-view/calendar-view.svelte +451 -0
- package/dist/components/calendar-view/calendar-view.svelte.d.ts +9 -0
- package/dist/components/calendar-view/calendar-view.svelte.js +196 -0
- package/dist/components/calendar-view/docs/llms.md +121 -0
- package/dist/components/calendar-view/index.d.ts +1 -0
- package/dist/components/calendar-view/index.js +1 -0
- package/dist/components/calendar-view/types.d.ts +174 -0
- package/dist/components/calendar-view/types.js +1 -0
- package/dist/components/checkbox/checkbox.svelte +171 -0
- package/dist/components/checkbox/checkbox.svelte.d.ts +40 -0
- package/dist/components/checkbox/docs/llms.md +78 -0
- package/dist/components/checkbox/types.d.ts +50 -0
- package/dist/components/checkbox/types.js +1 -0
- package/dist/components/date-picker/date-picker.svelte +381 -0
- package/dist/components/date-picker/date-picker.svelte.d.ts +4 -0
- package/dist/components/date-picker/docs/llms.md +52 -0
- package/dist/components/date-picker/index.d.ts +1 -0
- package/dist/components/date-picker/index.js +1 -0
- package/dist/components/date-picker/types.d.ts +74 -0
- package/dist/components/date-picker/types.js +1 -0
- package/dist/components/dialog/dialog-actions.svelte +37 -0
- package/dist/components/dialog/dialog-actions.svelte.d.ts +4 -0
- package/dist/components/dialog/dialog-content.svelte +17 -0
- package/dist/components/dialog/dialog-content.svelte.d.ts +4 -0
- package/dist/components/dialog/dialog-surface.svelte +95 -0
- package/dist/components/dialog/dialog-surface.svelte.d.ts +4 -0
- package/dist/components/dialog/dialog-title.svelte +33 -0
- package/dist/components/dialog/dialog-title.svelte.d.ts +25 -0
- package/dist/components/dialog/dialog-trigger.svelte +23 -0
- package/dist/components/dialog/dialog-trigger.svelte.d.ts +4 -0
- package/dist/components/dialog/dialog.svelte +64 -0
- package/dist/components/dialog/dialog.svelte.d.ts +7 -0
- package/dist/components/dialog/dialog.svelte.js +2 -0
- package/dist/components/dialog/docs/llms.md +131 -0
- package/dist/components/dialog/types.d.ts +92 -0
- package/dist/components/dialog/types.js +1 -0
- package/dist/components/divider/divider.svelte +120 -0
- package/dist/components/divider/divider.svelte.d.ts +39 -0
- package/dist/components/divider/docs/llms.md +83 -0
- package/dist/components/divider/types.d.ts +32 -0
- package/dist/components/divider/types.js +1 -0
- package/dist/components/dropdown/docs/llms.md +70 -0
- package/dist/components/dropdown/dropdown-context.d.ts +2 -0
- package/dist/components/dropdown/dropdown-context.js +2 -0
- package/dist/components/dropdown/dropdown-option.svelte +31 -0
- package/dist/components/dropdown/dropdown-option.svelte.d.ts +4 -0
- package/dist/components/dropdown/dropdown.svelte +309 -0
- package/dist/components/dropdown/dropdown.svelte.d.ts +4 -0
- package/dist/components/dropdown/types.d.ts +82 -0
- package/dist/components/dropdown/types.js +1 -0
- package/dist/components/dropdown-select/docs/llms.md +72 -0
- package/dist/components/dropdown-select/dropdown-select-option.svelte +87 -0
- package/dist/components/dropdown-select/dropdown-select-option.svelte.d.ts +4 -0
- package/dist/components/dropdown-select/dropdown-select.svelte +165 -0
- package/dist/components/dropdown-select/dropdown-select.svelte.d.ts +4 -0
- package/dist/components/dropdown-select/dropdown-select.svelte.js +48 -0
- package/dist/components/dropdown-select/index.d.ts +2 -0
- package/dist/components/dropdown-select/index.js +2 -0
- package/dist/components/dropdown-select/types.d.ts +46 -0
- package/dist/components/dropdown-select/types.js +1 -0
- package/dist/components/expander/docs/llms.md +88 -0
- package/dist/components/expander/expander.svelte +249 -0
- package/dist/components/expander/expander.svelte.d.ts +21 -0
- package/dist/components/expander/types.d.ts +47 -0
- package/dist/components/expander/types.js +1 -0
- package/dist/components/flyout/docs/llms.md +31 -0
- package/dist/components/flyout/flyout.svelte +148 -0
- package/dist/components/flyout/flyout.svelte.d.ts +19 -0
- package/dist/components/flyout/types.d.ts +36 -0
- package/dist/components/flyout/types.js +1 -0
- package/dist/components/hyperlink/docs/llms.md +33 -0
- package/dist/components/hyperlink/hyperlink.svelte +66 -0
- package/dist/components/hyperlink/hyperlink.svelte.d.ts +16 -0
- package/dist/components/hyperlink/types.d.ts +14 -0
- package/dist/components/hyperlink/types.js +1 -0
- package/dist/components/info-bar/docs/llms.md +81 -0
- package/dist/components/info-bar/info-bar.svelte +140 -0
- package/dist/components/info-bar/info-bar.svelte.d.ts +19 -0
- package/dist/components/info-bar/types.d.ts +27 -0
- package/dist/components/info-bar/types.js +1 -0
- package/dist/components/label/docs/llms.md +67 -0
- package/dist/components/label/label.svelte +95 -0
- package/dist/components/label/label.svelte.d.ts +4 -0
- package/dist/components/label/types.d.ts +32 -0
- package/dist/components/label/types.js +1 -0
- package/dist/components/list-view/docs/llms.md +110 -0
- package/dist/components/list-view/list-view-item.svelte +168 -0
- package/dist/components/list-view/list-view-item.svelte.d.ts +25 -0
- package/dist/components/list-view/list-view.svelte +137 -0
- package/dist/components/list-view/list-view.svelte.d.ts +25 -0
- package/dist/components/list-view/types.d.ts +95 -0
- package/dist/components/list-view/types.js +1 -0
- package/dist/components/list-view/utils.d.ts +6 -0
- package/dist/components/list-view/utils.js +12 -0
- package/dist/components/menu/context-menu-trigger.svelte +84 -0
- package/dist/components/menu/context-menu-trigger.svelte.d.ts +9 -0
- package/dist/components/menu/docs/llms.md +169 -0
- package/dist/components/menu/menu-divider.svelte +9 -0
- package/dist/components/menu/menu-divider.svelte.d.ts +26 -0
- package/dist/components/menu/menu-group.svelte +31 -0
- package/dist/components/menu/menu-group.svelte.d.ts +4 -0
- package/dist/components/menu/menu-item-checkbox.svelte +143 -0
- package/dist/components/menu/menu-item-checkbox.svelte.d.ts +15 -0
- package/dist/components/menu/menu-item-radio.svelte +147 -0
- package/dist/components/menu/menu-item-radio.svelte.d.ts +15 -0
- package/dist/components/menu/menu-item-switch.svelte +194 -0
- package/dist/components/menu/menu-item-switch.svelte.d.ts +15 -0
- package/dist/components/menu/menu-item.svelte +124 -0
- package/dist/components/menu/menu-item.svelte.d.ts +18 -0
- package/dist/components/menu/menu-list.svelte +38 -0
- package/dist/components/menu/menu-list.svelte.d.ts +5 -0
- package/dist/components/menu/menu-popover.svelte +125 -0
- package/dist/components/menu/menu-popover.svelte.d.ts +12 -0
- package/dist/components/menu/menu-trigger.svelte +121 -0
- package/dist/components/menu/menu-trigger.svelte.d.ts +4 -0
- package/dist/components/menu/menu.svelte +124 -0
- package/dist/components/menu/menu.svelte.d.ts +4 -0
- package/dist/components/menu/menu.svelte.js +77 -0
- package/dist/components/menu/types.d.ts +127 -0
- package/dist/components/menu/types.js +1 -0
- package/dist/components/number-box/docs/llms.md +37 -0
- package/dist/components/number-box/number-box.svelte +115 -0
- package/dist/components/number-box/number-box.svelte.d.ts +15 -0
- package/dist/components/number-box/types.d.ts +16 -0
- package/dist/components/number-box/types.js +1 -0
- package/dist/components/persona/docs/llms.md +107 -0
- package/dist/components/persona/persona.svelte +79 -0
- package/dist/components/persona/persona.svelte.d.ts +4 -0
- package/dist/components/persona/types.d.ts +42 -0
- package/dist/components/persona/types.js +1 -0
- package/dist/components/progress-bar/docs/llms.md +67 -0
- package/dist/components/progress-bar/progress-bar.svelte +167 -0
- package/dist/components/progress-bar/progress-bar.svelte.d.ts +15 -0
- package/dist/components/progress-bar/types.d.ts +39 -0
- package/dist/components/progress-bar/types.js +1 -0
- package/dist/components/progress-ring/docs/llms.md +76 -0
- package/dist/components/progress-ring/progress-ring.svelte +145 -0
- package/dist/components/progress-ring/progress-ring.svelte.d.ts +15 -0
- package/dist/components/progress-ring/types.d.ts +42 -0
- package/dist/components/progress-ring/types.js +1 -0
- package/dist/components/radio-button/docs/llms.md +64 -0
- package/dist/components/radio-button/radio-button.svelte +129 -0
- package/dist/components/radio-button/radio-button.svelte.d.ts +19 -0
- package/dist/components/radio-button/types.d.ts +24 -0
- package/dist/components/radio-button/types.js +1 -0
- package/dist/components/skeleton/docs/llms.md +67 -0
- package/dist/components/skeleton/skeleton.svelte +106 -0
- package/dist/components/skeleton/skeleton.svelte.d.ts +39 -0
- package/dist/components/skeleton/types.d.ts +24 -0
- package/dist/components/skeleton/types.js +1 -0
- package/dist/components/slider/docs/llms.md +75 -0
- package/dist/components/slider/slider.svelte +486 -0
- package/dist/components/slider/slider.svelte.d.ts +19 -0
- package/dist/components/slider/types.d.ts +102 -0
- package/dist/components/slider/types.js +1 -0
- package/dist/components/text-box/docs/llms.md +86 -0
- package/dist/components/text-box/text-box-button.svelte +65 -0
- package/dist/components/text-box/text-box-button.svelte.d.ts +9 -0
- package/dist/components/text-box/text-box.svelte +299 -0
- package/dist/components/text-box/text-box.svelte.d.ts +16 -0
- package/dist/components/text-box/types.d.ts +60 -0
- package/dist/components/text-box/types.js +1 -0
- package/dist/components/textarea/docs/llms.md +55 -0
- package/dist/components/textarea/textarea.svelte +151 -0
- package/dist/components/textarea/textarea.svelte.d.ts +17 -0
- package/dist/components/textarea/types.d.ts +33 -0
- package/dist/components/textarea/types.js +1 -0
- package/dist/components/time-picker/docs/llms.md +47 -0
- package/dist/components/time-picker/index.d.ts +1 -0
- package/dist/components/time-picker/index.js +1 -0
- package/dist/components/time-picker/time-picker.svelte +336 -0
- package/dist/components/time-picker/time-picker.svelte.d.ts +4 -0
- package/dist/components/time-picker/types.d.ts +54 -0
- package/dist/components/time-picker/types.js +1 -0
- package/dist/components/toggle-switch/docs/llms.md +39 -0
- package/dist/components/toggle-switch/toggle-switch.svelte +151 -0
- package/dist/components/toggle-switch/toggle-switch.svelte.d.ts +17 -0
- package/dist/components/toggle-switch/types.d.ts +20 -0
- package/dist/components/toggle-switch/types.js +1 -0
- package/dist/components/tooltip/docs/llms.md +74 -0
- package/dist/components/tooltip/tooltip.svelte +246 -0
- package/dist/components/tooltip/tooltip.svelte.d.ts +18 -0
- package/dist/components/tooltip/types.d.ts +67 -0
- package/dist/components/tooltip/types.js +1 -0
- package/dist/components/tree-view/docs/llms.md +117 -0
- package/dist/components/tree-view/tree-view-item-content.svelte +158 -0
- package/dist/components/tree-view/tree-view-item-content.svelte.d.ts +4 -0
- package/dist/components/tree-view/tree-view-item.svelte +197 -0
- package/dist/components/tree-view/tree-view-item.svelte.d.ts +4 -0
- package/dist/components/tree-view/tree-view.svelte +220 -0
- package/dist/components/tree-view/tree-view.svelte.d.ts +4 -0
- package/dist/components/tree-view/tree-view.svelte.js +111 -0
- package/dist/components/tree-view/types.d.ts +185 -0
- package/dist/components/tree-view/types.js +1 -0
- package/dist/css/class-darkmode.css +186 -0
- package/dist/css/media-darkmode.css +189 -0
- package/dist/css/reset.css +53 -0
- package/dist/css/theme.css +276 -0
- package/dist/css/typography.css +67 -0
- package/dist/css/utils.d.ts +1 -0
- package/dist/css/utils.js +153 -0
- package/dist/index.d.ts +63 -0
- package/dist/index.js +129 -0
- package/dist/internal/components/dynamic-carousel/dynamic-carousel.svelte +449 -0
- package/dist/internal/components/dynamic-carousel/dynamic-carousel.svelte.d.ts +22 -0
- package/dist/internal/components/render-soc/render-soc.svelte +29 -0
- package/dist/internal/components/render-soc/render-soc.svelte.d.ts +30 -0
- package/dist/internal/constants.d.ts +26 -0
- package/dist/internal/constants.js +4036 -0
- package/dist/internal/context.d.ts +14 -0
- package/dist/internal/context.js +13 -0
- package/dist/internal/dom-utils.svelte.d.ts +6 -0
- package/dist/internal/dom-utils.svelte.js +46 -0
- package/dist/internal/floating-ui/floating.svelte.d.ts +15 -0
- package/dist/internal/floating-ui/floating.svelte.js +26 -0
- package/dist/internal/floating-ui/utils.d.ts +3 -0
- package/dist/internal/floating-ui/utils.js +30 -0
- package/dist/internal/index.d.ts +9 -0
- package/dist/internal/index.js +9 -0
- package/dist/internal/polyfills/expander.svelte.d.ts +21 -0
- package/dist/internal/polyfills/expander.svelte.js +96 -0
- package/dist/internal/transitions.d.ts +32 -0
- package/dist/internal/transitions.js +37 -0
- package/dist/internal/utils.d.ts +22 -0
- package/dist/internal/utils.js +63 -0
- package/dist/providers/fluentui-svelte/fluentui-svelte.d.ts +19 -0
- package/dist/providers/fluentui-svelte/fluentui-svelte.js +11 -0
- package/dist/providers/fluentui-svelte/fluentui-svelte.svelte +68 -0
- package/dist/providers/fluentui-svelte/fluentui-svelte.svelte.d.ts +9 -0
- package/dist/types/index.d.ts +117 -0
- package/dist/types/index.js +1 -0
- package/package.json +142 -0
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { DatePickerProps } from './types.js';
|
|
3
|
+
import { Flyout, Button, Divider } from '../../index.js';
|
|
4
|
+
import { on } from 'svelte/events';
|
|
5
|
+
import { tick } from 'svelte';
|
|
6
|
+
import { PREFIX } from '../../internal/constants.js';
|
|
7
|
+
import { floating } from '../../internal/index.js';
|
|
8
|
+
import { flip, hide, offset, shift } from '@floating-ui/dom';
|
|
9
|
+
import DynamicCarousel from '../../internal/components/dynamic-carousel/dynamic-carousel.svelte';
|
|
10
|
+
import { CheckmarkRegular, DismissRegular } from 'fluentui-icons-svelte';
|
|
11
|
+
|
|
12
|
+
let {
|
|
13
|
+
format = 'dd/MM/yyyy',
|
|
14
|
+
value = $bindable(''),
|
|
15
|
+
open = $bindable(false),
|
|
16
|
+
hideYears = false,
|
|
17
|
+
hideMonths = false,
|
|
18
|
+
hideDays = false,
|
|
19
|
+
minYear = new Date().getFullYear() - 100,
|
|
20
|
+
maxYear = new Date().getFullYear() + 100,
|
|
21
|
+
disabledDates = [],
|
|
22
|
+
disabledMonths = [],
|
|
23
|
+
disabledYears = [],
|
|
24
|
+
ref = $bindable(),
|
|
25
|
+
wrapperRef = $bindable(),
|
|
26
|
+
wrapperAttributes,
|
|
27
|
+
inputElement = $bindable(),
|
|
28
|
+
inputProps,
|
|
29
|
+
popupLabel = 'Choose a date',
|
|
30
|
+
...attributes
|
|
31
|
+
}: DatePickerProps = $props();
|
|
32
|
+
|
|
33
|
+
const FALLBACK_ID = $props.id();
|
|
34
|
+
const POPUP_ID = `${PREFIX}datepicker-${FALLBACK_ID}-popup`;
|
|
35
|
+
|
|
36
|
+
let popupRef: HTMLElement | undefined = $state();
|
|
37
|
+
|
|
38
|
+
/** Closing always hands the focus back, so the keyboard never lands nowhere. */
|
|
39
|
+
function closePopup() {
|
|
40
|
+
open = false;
|
|
41
|
+
ref?.focus();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Escape has to work from inside the popup too, and the popup is not a descendant
|
|
45
|
+
// of the trigger, so the listener goes on the document.
|
|
46
|
+
$effect(() => {
|
|
47
|
+
if (!open) return;
|
|
48
|
+
|
|
49
|
+
return on(document, 'keydown', (event: KeyboardEvent) => {
|
|
50
|
+
if (event.key !== 'Escape') return;
|
|
51
|
+
event.preventDefault();
|
|
52
|
+
closePopup();
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Move into the dialog on open: the first wheel, so the arrows work straight away.
|
|
57
|
+
$effect(() => {
|
|
58
|
+
if (!open || !popupRef) return;
|
|
59
|
+
|
|
60
|
+
tick().then(() => {
|
|
61
|
+
(popupRef?.querySelector<HTMLElement>('[role="listbox"]') ?? popupRef)?.focus();
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
type Column = 'month' | 'day' | 'year';
|
|
66
|
+
|
|
67
|
+
const MONTH_NAMES = [
|
|
68
|
+
'January',
|
|
69
|
+
'February',
|
|
70
|
+
'March',
|
|
71
|
+
'April',
|
|
72
|
+
'May',
|
|
73
|
+
'June',
|
|
74
|
+
'July',
|
|
75
|
+
'August',
|
|
76
|
+
'September',
|
|
77
|
+
'October',
|
|
78
|
+
'November',
|
|
79
|
+
'December'
|
|
80
|
+
];
|
|
81
|
+
const LABELS: Record<Column, string> = { month: 'Month', day: 'Day', year: 'Year' };
|
|
82
|
+
|
|
83
|
+
// Working selection (actual values). Kept in sync with `value` while the popup is closed,
|
|
84
|
+
// so each open starts from the committed value and Cancel/dismiss discards edits.
|
|
85
|
+
let month = $state(new Date().getMonth()); // 0-11
|
|
86
|
+
let day = $state(new Date().getDate()); // 1-31 (raw intent; clamped for display via effectiveDay)
|
|
87
|
+
let year = $state(new Date().getFullYear());
|
|
88
|
+
|
|
89
|
+
// Descending list of selectable years within [minYear, maxYear].
|
|
90
|
+
const yearsList = $derived(Array.from({ length: Math.max(0, maxYear - minYear) + 1 }, (_, i) => maxYear - i));
|
|
91
|
+
const yearStrings = $derived(yearsList.map(String));
|
|
92
|
+
|
|
93
|
+
// Days available in the selected month/year (leap-year aware): new Date(y, m + 1, 0) === last day.
|
|
94
|
+
const daysInMonth = $derived(new Date(year, month + 1, 0).getDate());
|
|
95
|
+
const effectiveDay = $derived(Math.min(day, daysInMonth));
|
|
96
|
+
const dayList = $derived(Array.from({ length: daysInMonth }, (_, i) => (i + 1).toString().padStart(2, '0')));
|
|
97
|
+
|
|
98
|
+
const yearIdx = $derived(Math.max(0, yearsList.indexOf(year)));
|
|
99
|
+
|
|
100
|
+
// The trigger shows the committed value; `true` once `value` holds a full date.
|
|
101
|
+
const hasValue = $derived(/^\d{4}-\d{2}-\d{2}$/.test(value ?? ''));
|
|
102
|
+
|
|
103
|
+
// Parsed committed value used for the trigger label, so the trigger reflects `value`
|
|
104
|
+
const committed = $derived(parseValue(value));
|
|
105
|
+
|
|
106
|
+
// Columns to render, ordered by `format` and filtered by the hide* flags.
|
|
107
|
+
const columns = $derived.by<Column[]>(() => {
|
|
108
|
+
const base: Column[] = format === 'dd/MM/yyyy' ? ['day', 'month', 'year'] : ['month', 'day', 'year'];
|
|
109
|
+
const hidden: Record<Column, boolean> = { month: hideMonths, day: hideDays, year: hideYears };
|
|
110
|
+
return base.filter((c) => !hidden[c]);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// --- disabled** → disabled carousel indices (arrays of real, 0-based indices) ---
|
|
114
|
+
const disabledYearsSet = $derived(new Set(disabledYears.map((d) => d.getFullYear())));
|
|
115
|
+
const disabledYearIdx = $derived(yearsList.flatMap((y, i) => (disabledYearsSet.has(y) ? [i] : [])));
|
|
116
|
+
const disabledMonthIdx = $derived(
|
|
117
|
+
MONTH_NAMES.flatMap((_, i) =>
|
|
118
|
+
disabledMonths.some((d) => d.getFullYear() === year && d.getMonth() === i) ? [i] : []
|
|
119
|
+
)
|
|
120
|
+
);
|
|
121
|
+
const disabledDayIdx = $derived(
|
|
122
|
+
dayList.flatMap((_, i) =>
|
|
123
|
+
disabledDates.some((d) => d.getFullYear() === year && d.getMonth() === month && d.getDate() === i + 1) ? [i] : []
|
|
124
|
+
)
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
// Whether the currently composed date lands on a disabled value (blocks Confirm as a backstop;
|
|
128
|
+
// the carousels already skip disabled items while scrolling).
|
|
129
|
+
const isSelectionDisabled = $derived(
|
|
130
|
+
disabledYearsSet.has(year) ||
|
|
131
|
+
disabledMonths.some((d) => d.getFullYear() === year && d.getMonth() === month) ||
|
|
132
|
+
disabledDates.some((d) => d.getFullYear() === year && d.getMonth() === month && d.getDate() === effectiveDay)
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
const pad = (n: number) => n.toString().padStart(2, '0');
|
|
136
|
+
|
|
137
|
+
function parseValue(v: string) {
|
|
138
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(v ?? '');
|
|
139
|
+
const t = new Date();
|
|
140
|
+
const raw = m ? { y: +m[1], mo: +m[2] - 1, d: +m[3] } : { y: t.getFullYear(), mo: t.getMonth(), d: t.getDate() };
|
|
141
|
+
const y = Math.min(maxYear, Math.max(minYear, raw.y));
|
|
142
|
+
const mo = Math.min(11, Math.max(0, raw.mo));
|
|
143
|
+
const dim = new Date(y, mo + 1, 0).getDate();
|
|
144
|
+
const d = Math.min(dim, Math.max(1, raw.d));
|
|
145
|
+
return { y, mo, d };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Keep the working selection synced with `value` while the popup is closed.
|
|
149
|
+
$effect(() => {
|
|
150
|
+
if (!open) {
|
|
151
|
+
const { y, mo, d } = parseValue(value);
|
|
152
|
+
year = y;
|
|
153
|
+
month = mo;
|
|
154
|
+
day = d;
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
function confirm() {
|
|
159
|
+
value = `${year}-${pad(month + 1)}-${pad(effectiveDay)}`;
|
|
160
|
+
closePopup();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function cancel() {
|
|
164
|
+
closePopup();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Trigger label per column
|
|
168
|
+
function display(col: Column): string {
|
|
169
|
+
if (!hasValue) return LABELS[col];
|
|
170
|
+
if (col === 'month') return MONTH_NAMES[committed.mo];
|
|
171
|
+
if (col === 'day') return pad(committed.d);
|
|
172
|
+
return String(committed.y);
|
|
173
|
+
}
|
|
174
|
+
</script>
|
|
175
|
+
|
|
176
|
+
<div class="fs-date-picker-wrapper" bind:this={wrapperRef} {...wrapperAttributes}>
|
|
177
|
+
<!-- A real button: Enter and Space, the disabled state and High Contrast styling all
|
|
178
|
+
come for free, and the hidden input cannot live inside it. -->
|
|
179
|
+
<button
|
|
180
|
+
type="button"
|
|
181
|
+
class="fs-date-picker"
|
|
182
|
+
aria-haspopup="dialog"
|
|
183
|
+
aria-expanded={open}
|
|
184
|
+
aria-controls={open ? POPUP_ID : undefined}
|
|
185
|
+
onclick={() => (open = !open)}
|
|
186
|
+
bind:this={ref}
|
|
187
|
+
{...attributes}
|
|
188
|
+
>
|
|
189
|
+
{#each columns as col, idx (col)}
|
|
190
|
+
{#if idx > 0}
|
|
191
|
+
<Divider as="span" vertical aria-hidden="true" />
|
|
192
|
+
{/if}
|
|
193
|
+
<span class="picker-content">{display(col)}</span>
|
|
194
|
+
{/each}
|
|
195
|
+
</button>
|
|
196
|
+
|
|
197
|
+
<!-- Carries the value into a form. `hidden` keeps it out of the tab order and out of
|
|
198
|
+
the accessibility tree, and a hidden control is still submitted. -->
|
|
199
|
+
<input type="date" hidden {value} bind:this={inputElement} {...inputProps} />
|
|
200
|
+
</div>
|
|
201
|
+
|
|
202
|
+
{#if open}
|
|
203
|
+
<Flyout
|
|
204
|
+
{@attach floating(ref, {
|
|
205
|
+
placement: 'bottom',
|
|
206
|
+
middleware: [
|
|
207
|
+
offset(({ rects }) => {
|
|
208
|
+
return -rects.reference.height / 2 - rects.floating.height / 2;
|
|
209
|
+
}),
|
|
210
|
+
flip(),
|
|
211
|
+
shift(),
|
|
212
|
+
hide()
|
|
213
|
+
],
|
|
214
|
+
strategy: 'fixed'
|
|
215
|
+
})}
|
|
216
|
+
reference={ref}
|
|
217
|
+
id={POPUP_ID}
|
|
218
|
+
role="dialog"
|
|
219
|
+
aria-modal="true"
|
|
220
|
+
aria-label={popupLabel}
|
|
221
|
+
tabindex={-1}
|
|
222
|
+
bind:ref={popupRef}
|
|
223
|
+
class="date-picker-flyout"
|
|
224
|
+
>
|
|
225
|
+
<div class="carousel-wrapper">
|
|
226
|
+
<div class="selection-bar"></div>
|
|
227
|
+
{#each columns as col (col)}
|
|
228
|
+
<div class="carousel-col col-{col}">
|
|
229
|
+
{#if col === 'month'}
|
|
230
|
+
<DynamicCarousel
|
|
231
|
+
values={MONTH_NAMES}
|
|
232
|
+
selectedIndex={month}
|
|
233
|
+
disabledIndices={disabledMonthIdx}
|
|
234
|
+
onSelected={(_, i) => (month = i)}
|
|
235
|
+
/>
|
|
236
|
+
{:else if col === 'day'}
|
|
237
|
+
{#key `${year}-${month}`}
|
|
238
|
+
<DynamicCarousel
|
|
239
|
+
values={dayList}
|
|
240
|
+
selectedIndex={effectiveDay - 1}
|
|
241
|
+
disabledIndices={disabledDayIdx}
|
|
242
|
+
onSelected={(_, i) => (day = i + 1)}
|
|
243
|
+
/>
|
|
244
|
+
{/key}
|
|
245
|
+
{:else}
|
|
246
|
+
<DynamicCarousel
|
|
247
|
+
values={yearStrings}
|
|
248
|
+
selectedIndex={yearIdx}
|
|
249
|
+
disabledIndices={disabledYearIdx}
|
|
250
|
+
onSelected={(_, i) => (year = yearsList[i])}
|
|
251
|
+
/>
|
|
252
|
+
{/if}
|
|
253
|
+
</div>
|
|
254
|
+
{/each}
|
|
255
|
+
</div>
|
|
256
|
+
<div class="action-bar">
|
|
257
|
+
<Button class="justify" appearance="subtle" aria-label="Confirm" disabled={isSelectionDisabled} onclick={confirm}>
|
|
258
|
+
<CheckmarkRegular />
|
|
259
|
+
</Button>
|
|
260
|
+
<Button class="justify" appearance="subtle" aria-label="Cancel" onclick={cancel}>
|
|
261
|
+
<DismissRegular />
|
|
262
|
+
</Button>
|
|
263
|
+
</div>
|
|
264
|
+
</Flyout>
|
|
265
|
+
{/if}
|
|
266
|
+
|
|
267
|
+
<style>
|
|
268
|
+
/* Layout-neutral: the button keeps the box the wrapper used to have. */
|
|
269
|
+
.fs-date-picker-wrapper {
|
|
270
|
+
display: contents;
|
|
271
|
+
}
|
|
272
|
+
.fs-date-picker {
|
|
273
|
+
display: flex;
|
|
274
|
+
position: relative;
|
|
275
|
+
border-radius: var(--fs-control-border-radius);
|
|
276
|
+
font-size: var(--fs-body-font-size);
|
|
277
|
+
line-height: var(--fs-body-line-height);
|
|
278
|
+
color: var(--fs-text-primary);
|
|
279
|
+
background: var(--fs-control-fill-default);
|
|
280
|
+
border: none;
|
|
281
|
+
padding: 1px;
|
|
282
|
+
cursor: pointer;
|
|
283
|
+
outline: none;
|
|
284
|
+
user-select: none;
|
|
285
|
+
&:after {
|
|
286
|
+
content: '';
|
|
287
|
+
inset: 0;
|
|
288
|
+
position: absolute;
|
|
289
|
+
padding: 0.063rem;
|
|
290
|
+
mask:
|
|
291
|
+
linear-gradient(#fff 0 0) content-box,
|
|
292
|
+
linear-gradient(#fff 0 0);
|
|
293
|
+
mask-composite: exclude;
|
|
294
|
+
border-radius: inherit;
|
|
295
|
+
}
|
|
296
|
+
&::after {
|
|
297
|
+
background: var(--fs-elevation-control-border);
|
|
298
|
+
}
|
|
299
|
+
&:hover {
|
|
300
|
+
background: var(--fs-control-fill-secondary);
|
|
301
|
+
}
|
|
302
|
+
&:active {
|
|
303
|
+
color: var(--fs-text-secondary);
|
|
304
|
+
&::after {
|
|
305
|
+
background: var(--fs-control-stroke-default);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
&:disabled,
|
|
309
|
+
&.disabled {
|
|
310
|
+
background: var(--fs-control-fill-disabled) !important;
|
|
311
|
+
color: var(--fs-text-disabled) !important;
|
|
312
|
+
&::after {
|
|
313
|
+
background: var(--fs-control-stroke-default) !important;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
& .picker-content {
|
|
317
|
+
display: flex;
|
|
318
|
+
align-items: center;
|
|
319
|
+
padding: 0.375rem 1.626rem 0.5rem 1.626rem;
|
|
320
|
+
&:first-child {
|
|
321
|
+
padding-right: 2rem;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
:global(.date-picker-flyout) {
|
|
326
|
+
flex-direction: column;
|
|
327
|
+
position: fixed !important;
|
|
328
|
+
top: 0;
|
|
329
|
+
left: 0;
|
|
330
|
+
max-width: min-content;
|
|
331
|
+
padding: 0 !important;
|
|
332
|
+
z-index: 10;
|
|
333
|
+
& .wrapper {
|
|
334
|
+
gap: 0 !important;
|
|
335
|
+
}
|
|
336
|
+
& .carousel-wrapper {
|
|
337
|
+
display: flex;
|
|
338
|
+
position: relative;
|
|
339
|
+
width: max-content;
|
|
340
|
+
min-width: max-content;
|
|
341
|
+
padding: 0 0.4rem !important;
|
|
342
|
+
}
|
|
343
|
+
& .carousel-col {
|
|
344
|
+
&.col-month {
|
|
345
|
+
width: 130px;
|
|
346
|
+
}
|
|
347
|
+
&.col-day {
|
|
348
|
+
width: 60px;
|
|
349
|
+
}
|
|
350
|
+
&.col-year {
|
|
351
|
+
width: 80px;
|
|
352
|
+
}
|
|
353
|
+
& :global(.fs-dynamic-carousel) {
|
|
354
|
+
width: 100%;
|
|
355
|
+
}
|
|
356
|
+
&:not(:last-child) :global(.fs-dynamic-carousel-track) {
|
|
357
|
+
border-right: 1px solid var(--fs-control-stroke-default);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
& .selection-bar {
|
|
361
|
+
position: absolute;
|
|
362
|
+
top: 50%;
|
|
363
|
+
left: 0.4rem;
|
|
364
|
+
width: calc(100% - 0.8rem);
|
|
365
|
+
height: 40px;
|
|
366
|
+
background: var(--fs-accent-fill-default);
|
|
367
|
+
transform: translateY(-50%);
|
|
368
|
+
border-radius: var(--fs-control-border-radius);
|
|
369
|
+
z-index: -1;
|
|
370
|
+
}
|
|
371
|
+
& .action-bar {
|
|
372
|
+
display: flex;
|
|
373
|
+
width: 100%;
|
|
374
|
+
padding: 0.2rem;
|
|
375
|
+
border-top: 1px solid var(--fs-control-stroke-default);
|
|
376
|
+
& :global(.justify) {
|
|
377
|
+
flex: 1;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
</style>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Date Picker
|
|
2
|
+
|
|
3
|
+
An input for selecting a date from carousel-style day, month, and year columns. The value uses the `YYYY-MM-DD` format.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```svelte
|
|
8
|
+
<script>
|
|
9
|
+
import { DatePicker } from 'fluentui-svelte';
|
|
10
|
+
|
|
11
|
+
let value = $state('');
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<DatePicker bind:value />
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Examples
|
|
18
|
+
|
|
19
|
+
### Date Format
|
|
20
|
+
|
|
21
|
+
Use the `format` prop to switch between `dd/MM/yyyy` and `MM/dd/yyyy`.
|
|
22
|
+
|
|
23
|
+
```svelte
|
|
24
|
+
<DatePicker format="dd/MM/yyyy" />
|
|
25
|
+
<DatePicker format="MM/dd/yyyy" />
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Hiding Columns
|
|
29
|
+
|
|
30
|
+
Use `hideDays`, `hideMonths`, or `hideYears` to hide individual selector columns (for example, a month/year-only picker).
|
|
31
|
+
|
|
32
|
+
```svelte
|
|
33
|
+
<DatePicker hideDays />
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Component Props
|
|
37
|
+
|
|
38
|
+
| Name | Type | Description |
|
|
39
|
+
| ---------------- | ------------------------------ | ----------------------------------------------------------------------------- |
|
|
40
|
+
| `value` | bindable `string` | Selected date as `YYYY-MM-DD` (matches the underlying `<input type="date">`). |
|
|
41
|
+
| `format` | `'MM/dd/yyyy' \| 'dd/MM/yyyy'` | The display format of the date. Default: `'dd/MM/yyyy'`. |
|
|
42
|
+
| `open` | bindable `boolean` | Whether the picker flyout is open. |
|
|
43
|
+
| `hideYears` | `boolean` | Hide the year selector column. |
|
|
44
|
+
| `hideMonths` | `boolean` | Hide the month selector column. |
|
|
45
|
+
| `hideDays` | `boolean` | Hide the day selector column. |
|
|
46
|
+
| `minYear` | `number` | Earliest selectable year. Default: current year − 100. |
|
|
47
|
+
| `maxYear` | `number` | Latest selectable year. Default: current year. |
|
|
48
|
+
| `disabledDates` | `Date[]` | Specific days (year-month-day) that cannot be selected. |
|
|
49
|
+
| `disabledMonths` | `Date[]` | Specific months (by month + year) that cannot be selected. |
|
|
50
|
+
| `disabledYears` | `Date[]` | Specific years (by year) that cannot be selected. |
|
|
51
|
+
| `element` | bindable `HTMLElement` | The DOM reference of the date picker root element. |
|
|
52
|
+
| `inputElement` | bindable `HTMLInputElement` | The DOM reference of the underlying input element. |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as DatePicker } from './date-picker.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as DatePicker } from './date-picker.svelte';
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { HTMLAttributes, HTMLButtonAttributes, HTMLInputAttributes } from 'svelte/elements';
|
|
2
|
+
/** @propsmith DatePickerProps */
|
|
3
|
+
export type DatePickerProps = {
|
|
4
|
+
/** Selected date as `YYYY-MM-DD` (matches the underlying `<input type="date">`).
|
|
5
|
+
* @default ''
|
|
6
|
+
* @bindable
|
|
7
|
+
*/
|
|
8
|
+
value?: string;
|
|
9
|
+
/** The order the three columns are laid out in.
|
|
10
|
+
* @default 'dd/MM/yyyy'
|
|
11
|
+
*/
|
|
12
|
+
format?: 'MM/dd/yyyy' | 'dd/MM/yyyy';
|
|
13
|
+
/** Controls the open state of the picker.
|
|
14
|
+
* @default false
|
|
15
|
+
* @bindable
|
|
16
|
+
*/
|
|
17
|
+
open?: boolean;
|
|
18
|
+
/** Removes the year column.
|
|
19
|
+
* @default false
|
|
20
|
+
*/
|
|
21
|
+
hideYears?: boolean;
|
|
22
|
+
/** Removes the month column.
|
|
23
|
+
* @default false
|
|
24
|
+
*/
|
|
25
|
+
hideMonths?: boolean;
|
|
26
|
+
/** Removes the day column.
|
|
27
|
+
* @default false
|
|
28
|
+
*/
|
|
29
|
+
hideDays?: boolean;
|
|
30
|
+
/** The first year offered by the year column.
|
|
31
|
+
* @default Current - 100
|
|
32
|
+
*/
|
|
33
|
+
minYear?: number;
|
|
34
|
+
/** The last year offered by the year column.
|
|
35
|
+
* @default Current + 100
|
|
36
|
+
*/
|
|
37
|
+
maxYear?: number;
|
|
38
|
+
/** Specific days (year-month-day) that cannot be selected.
|
|
39
|
+
* @default []
|
|
40
|
+
*/
|
|
41
|
+
disabledDates?: Date[];
|
|
42
|
+
/** Specific months (by month + year) that cannot be selected.
|
|
43
|
+
* @default []
|
|
44
|
+
*/
|
|
45
|
+
disabledMonths?: Date[];
|
|
46
|
+
/** Specific years (by year) that cannot be selected.
|
|
47
|
+
* @default []
|
|
48
|
+
*/
|
|
49
|
+
disabledYears?: Date[];
|
|
50
|
+
/** The DOM reference of the trigger button.
|
|
51
|
+
* @bindable
|
|
52
|
+
*/
|
|
53
|
+
ref?: HTMLButtonElement;
|
|
54
|
+
/** The DOM reference of the element wrapping the trigger and its input.
|
|
55
|
+
* @bindable
|
|
56
|
+
*/
|
|
57
|
+
wrapperRef?: HTMLDivElement;
|
|
58
|
+
/** The attributes to spread on the wrapper element.
|
|
59
|
+
* @type HTMLAttributes
|
|
60
|
+
*/
|
|
61
|
+
wrapperAttributes?: HTMLAttributes<HTMLDivElement>;
|
|
62
|
+
/** The DOM reference of the underlying input element.
|
|
63
|
+
* @bindable
|
|
64
|
+
*/
|
|
65
|
+
inputElement?: HTMLInputElement;
|
|
66
|
+
/** HTML attributes for the underlying input element. Give it a `name` to submit the
|
|
67
|
+
* value with a form.
|
|
68
|
+
*/
|
|
69
|
+
inputProps?: HTMLInputAttributes;
|
|
70
|
+
/** The accessible name of the popup, which is announced as a dialog.
|
|
71
|
+
* @default 'Choose a date'
|
|
72
|
+
*/
|
|
73
|
+
popupLabel?: string;
|
|
74
|
+
} & HTMLButtonAttributes;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getTabspotAttributes } from 'tabspot';
|
|
3
|
+
import type { DialogActionsProps } from './types.js';
|
|
4
|
+
|
|
5
|
+
let { ref = $bindable(), position = 'end', fluid, children }: DialogActionsProps = $props();
|
|
6
|
+
|
|
7
|
+
// The bar is one tab stop holding a row of buttons: without the mover the root would
|
|
8
|
+
// take the tab stop and then offer no way to reach the rest of the buttons.
|
|
9
|
+
const tabspotAttributes = getTabspotAttributes({
|
|
10
|
+
root: {},
|
|
11
|
+
mover: { axis: 'horizontal' }
|
|
12
|
+
});
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<div class={['dialog-actions', `justify-${position}`, { fluid }]} bind:this={ref} {...tabspotAttributes}>
|
|
16
|
+
{@render children?.()}
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<style>
|
|
20
|
+
.dialog-actions {
|
|
21
|
+
grid-row: 3 / 3;
|
|
22
|
+
display: flex;
|
|
23
|
+
padding: 1.4rem 2rem;
|
|
24
|
+
gap: 0.5rem;
|
|
25
|
+
border-top: 1px solid var(--fs-card-stroke-default);
|
|
26
|
+
background: var(--fs-solid-background-base);
|
|
27
|
+
&.justify-start {
|
|
28
|
+
justify-content: flex-start;
|
|
29
|
+
}
|
|
30
|
+
&.justify-center {
|
|
31
|
+
justify-content: center;
|
|
32
|
+
}
|
|
33
|
+
&.justify-end {
|
|
34
|
+
justify-content: flex-end;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
</style>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { DialogContentProps } from './types.js';
|
|
3
|
+
|
|
4
|
+
let { children }: DialogContentProps = $props();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<div class="dialog-content">
|
|
8
|
+
{@render children?.()}
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<style>
|
|
12
|
+
.dialog-content {
|
|
13
|
+
grid-row: 2 / 2;
|
|
14
|
+
padding: 1.4rem 2rem 2rem 2rem;
|
|
15
|
+
overflow-y: auto;
|
|
16
|
+
}
|
|
17
|
+
</style>
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onClickOutside } from 'runed';
|
|
3
|
+
import type { DialogSurfaceProps } from './types.js';
|
|
4
|
+
import { getDialogContext } from './dialog.svelte.js';
|
|
5
|
+
import { Button } from '../../index.js';
|
|
6
|
+
import DismissFilled from 'fluentui-icons-svelte/DismissFilled.svelte';
|
|
7
|
+
|
|
8
|
+
let { ref = $bindable(), children, ...attributes }: DialogSurfaceProps = $props();
|
|
9
|
+
|
|
10
|
+
const CONTEXT = getDialogContext();
|
|
11
|
+
|
|
12
|
+
if (!CONTEXT) {
|
|
13
|
+
throw new Error('DialogSurface must be used within a Dialog component');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { config, methods, state: _state } = CONTEXT;
|
|
17
|
+
|
|
18
|
+
const { closeDialog } = methods;
|
|
19
|
+
|
|
20
|
+
const { type } = config;
|
|
21
|
+
|
|
22
|
+
if (type !== 'alert') {
|
|
23
|
+
onClickOutside(
|
|
24
|
+
() => ref,
|
|
25
|
+
() => closeDialog()
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
$effect(() => {
|
|
30
|
+
if (!ref) return;
|
|
31
|
+
_state.dialogRef = ref;
|
|
32
|
+
});
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<dialog open={_state.open} class="fs-dialog" aria-labelledby={_state.titleId} bind:this={ref} {...attributes}>
|
|
36
|
+
<div class="dialog-wrapper">
|
|
37
|
+
{#if config.type === 'non-modal'}
|
|
38
|
+
<Button class="close-icon" appearance="subtle" onclick={() => methods.closeDialog()} aria-label="Close dialog">
|
|
39
|
+
<DismissFilled />
|
|
40
|
+
</Button>
|
|
41
|
+
{/if}
|
|
42
|
+
{@render children?.()}
|
|
43
|
+
</div>
|
|
44
|
+
</dialog>
|
|
45
|
+
|
|
46
|
+
<style>
|
|
47
|
+
.fs-dialog {
|
|
48
|
+
position: fixed;
|
|
49
|
+
top: 50%;
|
|
50
|
+
left: 50%;
|
|
51
|
+
padding: 0;
|
|
52
|
+
transform: translate(-50%, -50%);
|
|
53
|
+
border: unset;
|
|
54
|
+
z-index: 1100;
|
|
55
|
+
width: 35vw;
|
|
56
|
+
min-width: 20rem;
|
|
57
|
+
overflow: visible;
|
|
58
|
+
background: var(--fs-solid-background-base);
|
|
59
|
+
border-radius: var(--fs-control-overlay-border-radius);
|
|
60
|
+
&::backdrop {
|
|
61
|
+
background-color: var(--fs-smoke-background-default);
|
|
62
|
+
backdrop-filter: blur(0.25rem);
|
|
63
|
+
}
|
|
64
|
+
& .dialog-wrapper {
|
|
65
|
+
position: relative;
|
|
66
|
+
box-shadow: var(--fs-shadow-dialog);
|
|
67
|
+
border-radius: var(--fs-control-overlay-border-radius);
|
|
68
|
+
border: 1px solid var(--fs-control-surface-stroke-flyout);
|
|
69
|
+
display: grid;
|
|
70
|
+
grid-template-rows: auto 1fr;
|
|
71
|
+
width: 100%;
|
|
72
|
+
max-height: 95vh;
|
|
73
|
+
overflow: hidden;
|
|
74
|
+
background: var(--fs-layer-alt);
|
|
75
|
+
&::before {
|
|
76
|
+
content: '';
|
|
77
|
+
position: absolute;
|
|
78
|
+
background: var(--fs-acrilic-noise);
|
|
79
|
+
background-size: 2.5rem;
|
|
80
|
+
filter: grayscale(1);
|
|
81
|
+
opacity: 0.065;
|
|
82
|
+
border-radius: calc(var(--fs-control-overlay-border-radius) - 0.063rem);
|
|
83
|
+
pointer-events: none;
|
|
84
|
+
inset: 0;
|
|
85
|
+
z-index: 0;
|
|
86
|
+
}
|
|
87
|
+
& :global(.close-icon) {
|
|
88
|
+
position: absolute;
|
|
89
|
+
padding: 0.5rem;
|
|
90
|
+
top: 0.5rem;
|
|
91
|
+
right: 0.5rem;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
</style>
|