@placeholderco/placeholder-ui 1.0.3 → 1.0.6
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 +26 -26
- package/README.md +179 -179
- package/dist/display/Alert.svelte +179 -179
- package/dist/display/Avatar.svelte +166 -166
- package/dist/display/LinkCollection.svelte +161 -161
- package/dist/display/Paper.svelte +118 -118
- package/dist/form/Autocomplete.svelte +223 -191
- package/dist/form/Autocomplete.svelte.d.ts +3 -1
- package/dist/form/AutocompleteMulti.svelte +356 -0
- package/dist/form/AutocompleteMulti.svelte.d.ts +28 -0
- package/dist/form/Checkbox.svelte +201 -201
- package/dist/form/Chips.svelte +128 -128
- package/dist/form/ComboBox.svelte +158 -158
- package/dist/form/ComboBox.svelte.d.ts +1 -1
- package/dist/form/ComboBoxItemBuilder.svelte +460 -460
- package/dist/form/ComboBoxMulti.svelte +197 -197
- package/dist/form/ComboBoxMulti.svelte.d.ts +1 -1
- package/dist/form/CronBuilder.svelte +693 -693
- package/dist/form/DatePicker.svelte +672 -672
- package/dist/form/DateTimePicker.svelte +712 -712
- package/dist/form/FileInput.svelte +235 -235
- package/dist/form/FormGroup.svelte +68 -68
- package/dist/form/Number.svelte +238 -238
- package/dist/form/PasswordInput.svelte +252 -252
- package/dist/form/RadioGroup.svelte +210 -210
- package/dist/form/Rating.svelte +235 -235
- package/dist/form/SegmentedControl.svelte +149 -149
- package/dist/form/Select.svelte +590 -590
- package/dist/form/Select.svelte.d.ts +1 -1
- package/dist/form/SelectMulti.svelte +613 -613
- package/dist/form/SelectMulti.svelte.d.ts +1 -1
- package/dist/form/Slider.svelte +358 -358
- package/dist/form/Switch.svelte +147 -147
- package/dist/form/TextArea.svelte +148 -148
- package/dist/form/Textbox.svelte +228 -228
- package/dist/form/TimePicker.svelte +267 -267
- package/dist/icon/Icon.svelte +52 -52
- package/dist/icon/alert-octagon.svg +5 -5
- package/dist/icon/alert-triangle.svg +5 -5
- package/dist/icon/archive.svg +1 -1
- package/dist/icon/arrow-down.svg +1 -1
- package/dist/icon/arrow-left.svg +1 -1
- package/dist/icon/arrow-right.svg +1 -1
- package/dist/icon/arrow-up.svg +1 -1
- package/dist/icon/at.svg +1 -1
- package/dist/icon/bell.svg +1 -1
- package/dist/icon/bookmark.svg +1 -1
- package/dist/icon/calendar.svg +1 -1
- package/dist/icon/camera.svg +1 -1
- package/dist/icon/chart-bar.svg +1 -1
- package/dist/icon/chart-line.svg +1 -1
- package/dist/icon/chart-pie.svg +1 -1
- package/dist/icon/checkbox.svg +1 -1
- package/dist/icon/checklist.svg +1 -1
- package/dist/icon/circle-check.svg +1 -1
- package/dist/icon/circle-x.svg +1 -1
- package/dist/icon/clock.svg +1 -1
- package/dist/icon/credit-card.svg +1 -1
- package/dist/icon/dots-vertical.svg +1 -1
- package/dist/icon/dots.svg +1 -1
- package/dist/icon/external-link.svg +1 -1
- package/dist/icon/eye-off.svg +1 -1
- package/dist/icon/eye.svg +1 -1
- package/dist/icon/filter.svg +1 -1
- package/dist/icon/fingerprint.svg +1 -1
- package/dist/icon/flag.svg +1 -1
- package/dist/icon/heart.svg +1 -1
- package/dist/icon/home.svg +1 -1
- package/dist/icon/key.svg +1 -1
- package/dist/icon/list-check.svg +1 -1
- package/dist/icon/login.svg +1 -1
- package/dist/icon/logout.svg +1 -1
- package/dist/icon/map-pin.svg +1 -1
- package/dist/icon/maximize.svg +1 -1
- package/dist/icon/microphone.svg +1 -1
- package/dist/icon/minimize.svg +1 -1
- package/dist/icon/note.svg +1 -1
- package/dist/icon/player-pause.svg +1 -1
- package/dist/icon/printer.svg +1 -1
- package/dist/icon/qrcode.svg +1 -1
- package/dist/icon/send.svg +1 -1
- package/dist/icon/settings.svg +1 -1
- package/dist/icon/share.svg +1 -1
- package/dist/icon/shopping-cart.svg +1 -1
- package/dist/icon/sort-ascending.svg +1 -1
- package/dist/icon/sort-descending.svg +1 -1
- package/dist/icon/star.svg +1 -1
- package/dist/icon/tag.svg +1 -1
- package/dist/icon/trending-down.svg +1 -1
- package/dist/icon/trending-up.svg +1 -1
- package/dist/icon/upload.svg +1 -1
- package/dist/icon/volume-off.svg +1 -1
- package/dist/icon/volume.svg +1 -1
- package/dist/icon/world.svg +1 -1
- package/dist/icon/zoom-in.svg +1 -1
- package/dist/icon/zoom-out.svg +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/layout/AppShell.svelte +169 -169
- package/dist/layout/CustomNavbar.svelte +61 -61
- package/dist/layout/Navbar.svelte +206 -206
- package/dist/layout/NavbarItemDisplay.svelte +29 -29
- package/dist/layout/Sidenav.svelte +712 -712
- package/dist/styles/components.css +199 -199
- package/dist/styles/dark.css +146 -146
- package/dist/styles/index.css +116 -116
- package/dist/styles/reset.css +110 -110
- package/dist/styles/semantic.css +86 -86
- package/dist/styles/tokens.css +203 -197
- package/dist/styles/utilities.css +523 -523
- package/dist/ui/Accordion.svelte +289 -289
- package/dist/ui/ActionIcon.svelte +76 -76
- package/dist/ui/Badge.svelte +329 -279
- package/dist/ui/Breadcrumbs.svelte +131 -131
- package/dist/ui/Button.svelte +432 -370
- package/dist/ui/ButtonVariant.d.ts +1 -1
- package/dist/ui/Dialog.svelte +307 -307
- package/dist/ui/Drawer.svelte +524 -524
- package/dist/ui/Dropdown.svelte +97 -97
- package/dist/ui/Dropzone.svelte +122 -122
- package/dist/ui/Link.svelte +32 -32
- package/dist/ui/Loader.svelte +70 -70
- package/dist/ui/LoadingOverlay.svelte +53 -53
- package/dist/ui/Pagination.svelte +135 -135
- package/dist/ui/Popover.svelte +225 -225
- package/dist/ui/Progress.svelte +191 -191
- package/dist/ui/RingProgress.svelte +141 -141
- package/dist/ui/Skeleton.svelte +85 -85
- package/dist/ui/Stepper.svelte +355 -355
- package/dist/ui/Table.svelte +345 -345
- package/dist/ui/Tabs.svelte +146 -146
- package/dist/ui/ThemeSwitcher.svelte +39 -39
- package/dist/ui/Timeline.svelte +225 -225
- package/dist/ui/Toaster.svelte +6 -6
- package/dist/ui/Tooltip.svelte +434 -434
- package/package.json +14 -14
|
@@ -1,267 +1,267 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import dayjs from 'dayjs';
|
|
3
|
-
import Button from '../ui/Button.svelte';
|
|
4
|
-
import Number from './Number.svelte';
|
|
5
|
-
import { themeState } from '../theme.svelte.js';
|
|
6
|
-
import customParseFormat from 'dayjs/plugin/customParseFormat.js';
|
|
7
|
-
|
|
8
|
-
interface Props {
|
|
9
|
-
label?: string;
|
|
10
|
-
disabled?: boolean;
|
|
11
|
-
required?: boolean;
|
|
12
|
-
containerClass?: string;
|
|
13
|
-
value?: string | undefined;
|
|
14
|
-
rounded?: boolean;
|
|
15
|
-
minDate?: string | undefined;
|
|
16
|
-
maxDate?: string | undefined;
|
|
17
|
-
selectedDate?: string | undefined;
|
|
18
|
-
onchange?: (date: string | undefined) => void;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
let {
|
|
22
|
-
label,
|
|
23
|
-
disabled,
|
|
24
|
-
required,
|
|
25
|
-
containerClass,
|
|
26
|
-
value = $bindable(undefined),
|
|
27
|
-
onchange,
|
|
28
|
-
rounded,
|
|
29
|
-
minDate,
|
|
30
|
-
maxDate,
|
|
31
|
-
selectedDate
|
|
32
|
-
}: Props = $props();
|
|
33
|
-
|
|
34
|
-
dayjs.extend(customParseFormat);
|
|
35
|
-
let time: dayjs.Dayjs = $derived(value ? dayjs(value, ['HH:mm:ss', 'HH:mm']) : dayjs());
|
|
36
|
-
|
|
37
|
-
let amPm: 'am' | 'pm' = $derived(time.hour() >= 12 ? 'pm' : 'am');
|
|
38
|
-
let hours: number = $derived(time.hour() % 12 == 0 ? 12 : time.hour() % 12);
|
|
39
|
-
let minutes: number = $derived(time.minute());
|
|
40
|
-
|
|
41
|
-
// Calculate time constraints based on selected date
|
|
42
|
-
const isMinDateSelected = $derived(selectedDate && minDate && dayjs(selectedDate).isSame(dayjs(minDate), 'day'));
|
|
43
|
-
const isMaxDateSelected = $derived(selectedDate && maxDate && dayjs(selectedDate).isSame(dayjs(maxDate), 'day'));
|
|
44
|
-
|
|
45
|
-
const minHour = $derived.by(() => {
|
|
46
|
-
if (!isMinDateSelected || !minDate) return 1;
|
|
47
|
-
const minTime = dayjs(minDate);
|
|
48
|
-
const minHour24 = minTime.hour();
|
|
49
|
-
const isPM = amPm === 'pm';
|
|
50
|
-
|
|
51
|
-
if (isPM) {
|
|
52
|
-
// PM: min hour is 12 (noon) or later
|
|
53
|
-
return minHour24 >= 12 ? (minHour24 === 12 ? 12 : minHour24 - 12) : 1;
|
|
54
|
-
} else {
|
|
55
|
-
// AM: min hour is before noon
|
|
56
|
-
return minHour24 < 12 ? (minHour24 === 0 ? 12 : minHour24) : 12;
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const maxHour = $derived.by(() => {
|
|
61
|
-
if (!isMaxDateSelected || !maxDate) return 12;
|
|
62
|
-
const maxTime = dayjs(maxDate);
|
|
63
|
-
const maxHour24 = maxTime.hour();
|
|
64
|
-
const isPM = amPm === 'pm';
|
|
65
|
-
|
|
66
|
-
if (isPM) {
|
|
67
|
-
// PM: max hour is noon or later
|
|
68
|
-
return maxHour24 >= 12 ? (maxHour24 === 12 ? 12 : maxHour24 - 12) : 1;
|
|
69
|
-
} else {
|
|
70
|
-
// AM: max hour is before noon
|
|
71
|
-
return maxHour24 < 12 ? (maxHour24 === 0 ? 12 : maxHour24) : 12;
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
const minMinute = $derived.by(() => {
|
|
76
|
-
if (!isMinDateSelected || !minDate) return 0;
|
|
77
|
-
const minTime = dayjs(minDate);
|
|
78
|
-
const minHour24 = minTime.hour();
|
|
79
|
-
const currentHour24 = amPm === 'pm' ? (hours === 12 ? 12 : hours + 12) : (hours === 12 ? 0 : hours);
|
|
80
|
-
|
|
81
|
-
// Only apply minute constraint if we're on the same hour
|
|
82
|
-
return minHour24 === currentHour24 ? minTime.minute() : 0;
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
const maxMinute = $derived.by(() => {
|
|
86
|
-
if (!isMaxDateSelected || !maxDate) return 59;
|
|
87
|
-
const maxTime = dayjs(maxDate);
|
|
88
|
-
const maxHour24 = maxTime.hour();
|
|
89
|
-
const currentHour24 = amPm === 'pm' ? (hours === 12 ? 12 : hours + 12) : (hours === 12 ? 0 : hours);
|
|
90
|
-
|
|
91
|
-
// Only apply minute constraint if we're on the same hour
|
|
92
|
-
return maxHour24 === currentHour24 ? maxTime.minute() : 59;
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
// Check if AM/PM switch should be disabled
|
|
96
|
-
const isAmPmDisabled = $derived.by(() => {
|
|
97
|
-
if (disabled) return true;
|
|
98
|
-
|
|
99
|
-
// If min date is selected, check if switching to AM would be invalid
|
|
100
|
-
if (isMinDateSelected && minDate) {
|
|
101
|
-
const minTime = dayjs(minDate);
|
|
102
|
-
const minHour24 = minTime.hour();
|
|
103
|
-
|
|
104
|
-
// If min time is PM and we're currently on PM, can't switch to AM
|
|
105
|
-
if (amPm === 'pm' && minHour24 >= 12) {
|
|
106
|
-
return true;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// If max date is selected, check if switching to PM would be invalid
|
|
111
|
-
if (isMaxDateSelected && maxDate) {
|
|
112
|
-
const maxTime = dayjs(maxDate);
|
|
113
|
-
const maxHour24 = maxTime.hour();
|
|
114
|
-
|
|
115
|
-
// If max time is AM and we're currently on AM, can't switch to PM
|
|
116
|
-
if (amPm === 'am' && maxHour24 < 12) {
|
|
117
|
-
return true;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return false;
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
let UpdateTime = () => {
|
|
125
|
-
if (hours && minutes !== undefined) {
|
|
126
|
-
let hour24 = hours;
|
|
127
|
-
if (amPm === 'pm' && hours !== 12) {
|
|
128
|
-
hour24 += 12;
|
|
129
|
-
} else if (amPm === 'am' && hours === 12) {
|
|
130
|
-
hour24 = 0;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const timeString = `${hour24.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:00`;
|
|
134
|
-
onchange?.(timeString);
|
|
135
|
-
value = timeString;
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
value = dayjs().format('HH:mm');
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
if (value === undefined) {
|
|
142
|
-
UpdateTime();
|
|
143
|
-
}
|
|
144
|
-
</script>
|
|
145
|
-
|
|
146
|
-
<div class="element-container {rounded && 'rounded'} {containerClass}">
|
|
147
|
-
<div class="time-label">{label}</div>
|
|
148
|
-
<div class="time-wrapper">
|
|
149
|
-
<div class="time-container">
|
|
150
|
-
<Number
|
|
151
|
-
{disabled}
|
|
152
|
-
bind:value={hours}
|
|
153
|
-
min={minHour}
|
|
154
|
-
max={maxHour}
|
|
155
|
-
onchange={() => {
|
|
156
|
-
UpdateTime();
|
|
157
|
-
}}
|
|
158
|
-
/>
|
|
159
|
-
:
|
|
160
|
-
<Number
|
|
161
|
-
{disabled}
|
|
162
|
-
bind:value={minutes}
|
|
163
|
-
min={minMinute}
|
|
164
|
-
max={maxMinute}
|
|
165
|
-
onchange={() => {
|
|
166
|
-
UpdateTime();
|
|
167
|
-
}}
|
|
168
|
-
/>
|
|
169
|
-
</div>
|
|
170
|
-
<div class="am-pm-container">
|
|
171
|
-
<Button
|
|
172
|
-
disabled={isAmPmDisabled}
|
|
173
|
-
onclick={() => {
|
|
174
|
-
amPm = amPm === 'am' ? 'pm' : 'am';
|
|
175
|
-
UpdateTime();
|
|
176
|
-
}}
|
|
177
|
-
variant={themeState.isDarkMode ? 'secondary' : 'primary'}
|
|
178
|
-
>
|
|
179
|
-
{amPm.toUpperCase()}
|
|
180
|
-
</Button>
|
|
181
|
-
</div>
|
|
182
|
-
</div>
|
|
183
|
-
</div>
|
|
184
|
-
|
|
185
|
-
<style>
|
|
186
|
-
.time-label {
|
|
187
|
-
margin-bottom: var(--pui-spacing-1);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
.time-wrapper {
|
|
191
|
-
display: flex;
|
|
192
|
-
justify-content: space-between;
|
|
193
|
-
align-items: center;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
.time-picker-container {
|
|
197
|
-
border-radius: var(--pui-radius-lg);
|
|
198
|
-
overflow: hidden;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
.time-container {
|
|
202
|
-
display: flex;
|
|
203
|
-
justify-content: space-between;
|
|
204
|
-
align-items: center;
|
|
205
|
-
flex-grow: 1;
|
|
206
|
-
gap: var(--pui-spacing-1);
|
|
207
|
-
background-color: var(--pui-color-gray-100);
|
|
208
|
-
border: 1px solid var(--pui-border-default);
|
|
209
|
-
border-top-left-radius: var(--pui-radius-md);
|
|
210
|
-
border-bottom-left-radius: var(--pui-radius-md);
|
|
211
|
-
|
|
212
|
-
:global(.number-container) {
|
|
213
|
-
flex-grow: 1;
|
|
214
|
-
|
|
215
|
-
:global(.number-input input) {
|
|
216
|
-
text-align: center;
|
|
217
|
-
background-color: var(--pui-color-gray-100);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
.time-container :global(.number) {
|
|
223
|
-
border-radius: 0;
|
|
224
|
-
border: none !important;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
.time-container :global(.number-container:first-child .number:hover) {
|
|
228
|
-
border-right: 1px solid var(--pui-border-default) !important;
|
|
229
|
-
background-color: var(--pui-bg-hover) !important;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
.time-container :global(.number-container:last-child .number:hover) {
|
|
233
|
-
border-left: 1px solid var(--pui-border-default) !important;
|
|
234
|
-
background-color: var(--pui-bg-hover) !important;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
.time-container :global(.number-container:first-child .number) {
|
|
238
|
-
border-top-left-radius: var(--pui-radius-md);
|
|
239
|
-
border-bottom-left-radius: var(--pui-radius-md);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
.am-pm-container :global(.pui-button) {
|
|
243
|
-
border-radius: 0;
|
|
244
|
-
border-top-right-radius: var(--pui-radius-md);
|
|
245
|
-
border-bottom-right-radius: var(--pui-radius-md);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
:global(.dark) {
|
|
249
|
-
.time-container {
|
|
250
|
-
background-color: var(--pui-color-dark-200);
|
|
251
|
-
|
|
252
|
-
:global(.number-container) {
|
|
253
|
-
:global(.number-input input) {
|
|
254
|
-
background-color: var(--pui-color-dark-200);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
.time-container :global(.number-container:first-child .number:hover) {
|
|
260
|
-
background-color: var(--pui-bg-hover) !important;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
.time-container :global(.number-container:last-child .number:hover) {
|
|
264
|
-
background-color: var(--pui-bg-hover) !important;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
</style>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import dayjs from 'dayjs';
|
|
3
|
+
import Button from '../ui/Button.svelte';
|
|
4
|
+
import Number from './Number.svelte';
|
|
5
|
+
import { themeState } from '../theme.svelte.js';
|
|
6
|
+
import customParseFormat from 'dayjs/plugin/customParseFormat.js';
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
label?: string;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
required?: boolean;
|
|
12
|
+
containerClass?: string;
|
|
13
|
+
value?: string | undefined;
|
|
14
|
+
rounded?: boolean;
|
|
15
|
+
minDate?: string | undefined;
|
|
16
|
+
maxDate?: string | undefined;
|
|
17
|
+
selectedDate?: string | undefined;
|
|
18
|
+
onchange?: (date: string | undefined) => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let {
|
|
22
|
+
label,
|
|
23
|
+
disabled,
|
|
24
|
+
required,
|
|
25
|
+
containerClass,
|
|
26
|
+
value = $bindable(undefined),
|
|
27
|
+
onchange,
|
|
28
|
+
rounded,
|
|
29
|
+
minDate,
|
|
30
|
+
maxDate,
|
|
31
|
+
selectedDate
|
|
32
|
+
}: Props = $props();
|
|
33
|
+
|
|
34
|
+
dayjs.extend(customParseFormat);
|
|
35
|
+
let time: dayjs.Dayjs = $derived(value ? dayjs(value, ['HH:mm:ss', 'HH:mm']) : dayjs());
|
|
36
|
+
|
|
37
|
+
let amPm: 'am' | 'pm' = $derived(time.hour() >= 12 ? 'pm' : 'am');
|
|
38
|
+
let hours: number = $derived(time.hour() % 12 == 0 ? 12 : time.hour() % 12);
|
|
39
|
+
let minutes: number = $derived(time.minute());
|
|
40
|
+
|
|
41
|
+
// Calculate time constraints based on selected date
|
|
42
|
+
const isMinDateSelected = $derived(selectedDate && minDate && dayjs(selectedDate).isSame(dayjs(minDate), 'day'));
|
|
43
|
+
const isMaxDateSelected = $derived(selectedDate && maxDate && dayjs(selectedDate).isSame(dayjs(maxDate), 'day'));
|
|
44
|
+
|
|
45
|
+
const minHour = $derived.by(() => {
|
|
46
|
+
if (!isMinDateSelected || !minDate) return 1;
|
|
47
|
+
const minTime = dayjs(minDate);
|
|
48
|
+
const minHour24 = minTime.hour();
|
|
49
|
+
const isPM = amPm === 'pm';
|
|
50
|
+
|
|
51
|
+
if (isPM) {
|
|
52
|
+
// PM: min hour is 12 (noon) or later
|
|
53
|
+
return minHour24 >= 12 ? (minHour24 === 12 ? 12 : minHour24 - 12) : 1;
|
|
54
|
+
} else {
|
|
55
|
+
// AM: min hour is before noon
|
|
56
|
+
return minHour24 < 12 ? (minHour24 === 0 ? 12 : minHour24) : 12;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const maxHour = $derived.by(() => {
|
|
61
|
+
if (!isMaxDateSelected || !maxDate) return 12;
|
|
62
|
+
const maxTime = dayjs(maxDate);
|
|
63
|
+
const maxHour24 = maxTime.hour();
|
|
64
|
+
const isPM = amPm === 'pm';
|
|
65
|
+
|
|
66
|
+
if (isPM) {
|
|
67
|
+
// PM: max hour is noon or later
|
|
68
|
+
return maxHour24 >= 12 ? (maxHour24 === 12 ? 12 : maxHour24 - 12) : 1;
|
|
69
|
+
} else {
|
|
70
|
+
// AM: max hour is before noon
|
|
71
|
+
return maxHour24 < 12 ? (maxHour24 === 0 ? 12 : maxHour24) : 12;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const minMinute = $derived.by(() => {
|
|
76
|
+
if (!isMinDateSelected || !minDate) return 0;
|
|
77
|
+
const minTime = dayjs(minDate);
|
|
78
|
+
const minHour24 = minTime.hour();
|
|
79
|
+
const currentHour24 = amPm === 'pm' ? (hours === 12 ? 12 : hours + 12) : (hours === 12 ? 0 : hours);
|
|
80
|
+
|
|
81
|
+
// Only apply minute constraint if we're on the same hour
|
|
82
|
+
return minHour24 === currentHour24 ? minTime.minute() : 0;
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const maxMinute = $derived.by(() => {
|
|
86
|
+
if (!isMaxDateSelected || !maxDate) return 59;
|
|
87
|
+
const maxTime = dayjs(maxDate);
|
|
88
|
+
const maxHour24 = maxTime.hour();
|
|
89
|
+
const currentHour24 = amPm === 'pm' ? (hours === 12 ? 12 : hours + 12) : (hours === 12 ? 0 : hours);
|
|
90
|
+
|
|
91
|
+
// Only apply minute constraint if we're on the same hour
|
|
92
|
+
return maxHour24 === currentHour24 ? maxTime.minute() : 59;
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Check if AM/PM switch should be disabled
|
|
96
|
+
const isAmPmDisabled = $derived.by(() => {
|
|
97
|
+
if (disabled) return true;
|
|
98
|
+
|
|
99
|
+
// If min date is selected, check if switching to AM would be invalid
|
|
100
|
+
if (isMinDateSelected && minDate) {
|
|
101
|
+
const minTime = dayjs(minDate);
|
|
102
|
+
const minHour24 = minTime.hour();
|
|
103
|
+
|
|
104
|
+
// If min time is PM and we're currently on PM, can't switch to AM
|
|
105
|
+
if (amPm === 'pm' && minHour24 >= 12) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// If max date is selected, check if switching to PM would be invalid
|
|
111
|
+
if (isMaxDateSelected && maxDate) {
|
|
112
|
+
const maxTime = dayjs(maxDate);
|
|
113
|
+
const maxHour24 = maxTime.hour();
|
|
114
|
+
|
|
115
|
+
// If max time is AM and we're currently on AM, can't switch to PM
|
|
116
|
+
if (amPm === 'am' && maxHour24 < 12) {
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return false;
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
let UpdateTime = () => {
|
|
125
|
+
if (hours && minutes !== undefined) {
|
|
126
|
+
let hour24 = hours;
|
|
127
|
+
if (amPm === 'pm' && hours !== 12) {
|
|
128
|
+
hour24 += 12;
|
|
129
|
+
} else if (amPm === 'am' && hours === 12) {
|
|
130
|
+
hour24 = 0;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const timeString = `${hour24.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:00`;
|
|
134
|
+
onchange?.(timeString);
|
|
135
|
+
value = timeString;
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
value = dayjs().format('HH:mm');
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
if (value === undefined) {
|
|
142
|
+
UpdateTime();
|
|
143
|
+
}
|
|
144
|
+
</script>
|
|
145
|
+
|
|
146
|
+
<div class="element-container {rounded && 'rounded'} {containerClass}">
|
|
147
|
+
<div class="time-label">{label}</div>
|
|
148
|
+
<div class="time-wrapper">
|
|
149
|
+
<div class="time-container">
|
|
150
|
+
<Number
|
|
151
|
+
{disabled}
|
|
152
|
+
bind:value={hours}
|
|
153
|
+
min={minHour}
|
|
154
|
+
max={maxHour}
|
|
155
|
+
onchange={() => {
|
|
156
|
+
UpdateTime();
|
|
157
|
+
}}
|
|
158
|
+
/>
|
|
159
|
+
:
|
|
160
|
+
<Number
|
|
161
|
+
{disabled}
|
|
162
|
+
bind:value={minutes}
|
|
163
|
+
min={minMinute}
|
|
164
|
+
max={maxMinute}
|
|
165
|
+
onchange={() => {
|
|
166
|
+
UpdateTime();
|
|
167
|
+
}}
|
|
168
|
+
/>
|
|
169
|
+
</div>
|
|
170
|
+
<div class="am-pm-container">
|
|
171
|
+
<Button
|
|
172
|
+
disabled={isAmPmDisabled}
|
|
173
|
+
onclick={() => {
|
|
174
|
+
amPm = amPm === 'am' ? 'pm' : 'am';
|
|
175
|
+
UpdateTime();
|
|
176
|
+
}}
|
|
177
|
+
variant={themeState.isDarkMode ? 'secondary' : 'primary'}
|
|
178
|
+
>
|
|
179
|
+
{amPm.toUpperCase()}
|
|
180
|
+
</Button>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
|
|
185
|
+
<style>
|
|
186
|
+
.time-label {
|
|
187
|
+
margin-bottom: var(--pui-spacing-1);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.time-wrapper {
|
|
191
|
+
display: flex;
|
|
192
|
+
justify-content: space-between;
|
|
193
|
+
align-items: center;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.time-picker-container {
|
|
197
|
+
border-radius: var(--pui-radius-lg);
|
|
198
|
+
overflow: hidden;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.time-container {
|
|
202
|
+
display: flex;
|
|
203
|
+
justify-content: space-between;
|
|
204
|
+
align-items: center;
|
|
205
|
+
flex-grow: 1;
|
|
206
|
+
gap: var(--pui-spacing-1);
|
|
207
|
+
background-color: var(--pui-color-gray-100);
|
|
208
|
+
border: 1px solid var(--pui-border-default);
|
|
209
|
+
border-top-left-radius: var(--pui-radius-md);
|
|
210
|
+
border-bottom-left-radius: var(--pui-radius-md);
|
|
211
|
+
|
|
212
|
+
:global(.number-container) {
|
|
213
|
+
flex-grow: 1;
|
|
214
|
+
|
|
215
|
+
:global(.number-input input) {
|
|
216
|
+
text-align: center;
|
|
217
|
+
background-color: var(--pui-color-gray-100);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.time-container :global(.number) {
|
|
223
|
+
border-radius: 0;
|
|
224
|
+
border: none !important;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.time-container :global(.number-container:first-child .number:hover) {
|
|
228
|
+
border-right: 1px solid var(--pui-border-default) !important;
|
|
229
|
+
background-color: var(--pui-bg-hover) !important;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.time-container :global(.number-container:last-child .number:hover) {
|
|
233
|
+
border-left: 1px solid var(--pui-border-default) !important;
|
|
234
|
+
background-color: var(--pui-bg-hover) !important;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.time-container :global(.number-container:first-child .number) {
|
|
238
|
+
border-top-left-radius: var(--pui-radius-md);
|
|
239
|
+
border-bottom-left-radius: var(--pui-radius-md);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.am-pm-container :global(.pui-button) {
|
|
243
|
+
border-radius: 0;
|
|
244
|
+
border-top-right-radius: var(--pui-radius-md);
|
|
245
|
+
border-bottom-right-radius: var(--pui-radius-md);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
:global(.dark) {
|
|
249
|
+
.time-container {
|
|
250
|
+
background-color: var(--pui-color-dark-200);
|
|
251
|
+
|
|
252
|
+
:global(.number-container) {
|
|
253
|
+
:global(.number-input input) {
|
|
254
|
+
background-color: var(--pui-color-dark-200);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.time-container :global(.number-container:first-child .number:hover) {
|
|
260
|
+
background-color: var(--pui-bg-hover) !important;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.time-container :global(.number-container:last-child .number:hover) {
|
|
264
|
+
background-color: var(--pui-bg-hover) !important;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
</style>
|
package/dist/icon/Icon.svelte
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
/** Raw HTML. Do NOT retrieve this from external sources; it will be executed in the browser */
|
|
3
|
-
interface Props {
|
|
4
|
-
svg: string;
|
|
5
|
-
stroke?: string;
|
|
6
|
-
fill?: string;
|
|
7
|
-
size?: string;
|
|
8
|
-
flip?: boolean;
|
|
9
|
-
class?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
let {
|
|
13
|
-
svg,
|
|
14
|
-
stroke = 'currentColor',
|
|
15
|
-
fill = 'none',
|
|
16
|
-
size = '',
|
|
17
|
-
flip = false,
|
|
18
|
-
class: classes = ''
|
|
19
|
-
}: Props = $props();
|
|
20
|
-
|
|
21
|
-
let sizeStyle = $derived(size ? `width:${size};height:${size};` : '');
|
|
22
|
-
</script>
|
|
23
|
-
|
|
24
|
-
<span style="--svg-stroke: {stroke}; --svg-fill: {fill}; {sizeStyle}" class:flip class="cu-icon {classes}">
|
|
25
|
-
{@html svg}
|
|
26
|
-
</span>
|
|
27
|
-
|
|
28
|
-
<style>
|
|
29
|
-
.cu-icon {
|
|
30
|
-
display: inline-flex;
|
|
31
|
-
align-items: center;
|
|
32
|
-
justify-content: center;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
.cu-icon :global(svg) {
|
|
36
|
-
width: 100%;
|
|
37
|
-
height: 100%;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.cu-icon :global(svg:not(.icons-tabler-filled)) {
|
|
41
|
-
stroke: var(--svg-stroke);
|
|
42
|
-
fill: var(--svg-fill);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.flip {
|
|
46
|
-
transform: scale(-1, 1);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.text-accent {
|
|
50
|
-
stroke: var(--accent-color);
|
|
51
|
-
}
|
|
52
|
-
</style>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/** Raw HTML. Do NOT retrieve this from external sources; it will be executed in the browser */
|
|
3
|
+
interface Props {
|
|
4
|
+
svg: string;
|
|
5
|
+
stroke?: string;
|
|
6
|
+
fill?: string;
|
|
7
|
+
size?: string;
|
|
8
|
+
flip?: boolean;
|
|
9
|
+
class?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let {
|
|
13
|
+
svg,
|
|
14
|
+
stroke = 'currentColor',
|
|
15
|
+
fill = 'none',
|
|
16
|
+
size = '',
|
|
17
|
+
flip = false,
|
|
18
|
+
class: classes = ''
|
|
19
|
+
}: Props = $props();
|
|
20
|
+
|
|
21
|
+
let sizeStyle = $derived(size ? `width:${size};height:${size};` : '');
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<span style="--svg-stroke: {stroke}; --svg-fill: {fill}; {sizeStyle}" class:flip class="cu-icon {classes}">
|
|
25
|
+
{@html svg}
|
|
26
|
+
</span>
|
|
27
|
+
|
|
28
|
+
<style>
|
|
29
|
+
.cu-icon {
|
|
30
|
+
display: inline-flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: center;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.cu-icon :global(svg) {
|
|
36
|
+
width: 100%;
|
|
37
|
+
height: 100%;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.cu-icon :global(svg:not(.icons-tabler-filled)) {
|
|
41
|
+
stroke: var(--svg-stroke);
|
|
42
|
+
fill: var(--svg-fill);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.flip {
|
|
46
|
+
transform: scale(-1, 1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.text-accent {
|
|
50
|
+
stroke: var(--accent-color);
|
|
51
|
+
}
|
|
52
|
+
</style>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-alert-octagon">
|
|
2
|
-
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
|
3
|
-
<path d="M12.802 2.165l5.575 2.389c.48 .206 .863 .589 1.07 1.07l2.388 5.574c.22 .512 .22 1.092 0 1.604l-2.389 5.575c-.206 .48 -.589 .863 -1.07 1.07l-5.574 2.388c-.512 .22 -1.092 .22 -1.604 0l-5.575 -2.389a2.036 2.036 0 0 1 -1.07 -1.07l-2.388 -5.574a2.036 2.036 0 0 1 0 -1.604l2.389 -5.575c.206 -.48 .589 -.863 1.07 -1.07l5.574 -2.388a2.036 2.036 0 0 1 1.604 0z" />
|
|
4
|
-
<path d="M12 8v4" />
|
|
5
|
-
<path d="M12 16h.01" />
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-alert-octagon">
|
|
2
|
+
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
|
3
|
+
<path d="M12.802 2.165l5.575 2.389c.48 .206 .863 .589 1.07 1.07l2.388 5.574c.22 .512 .22 1.092 0 1.604l-2.389 5.575c-.206 .48 -.589 .863 -1.07 1.07l-5.574 2.388c-.512 .22 -1.092 .22 -1.604 0l-5.575 -2.389a2.036 2.036 0 0 1 -1.07 -1.07l-2.388 -5.574a2.036 2.036 0 0 1 0 -1.604l2.389 -5.575c.206 -.48 .589 -.863 1.07 -1.07l5.574 -2.388a2.036 2.036 0 0 1 1.604 0z" />
|
|
4
|
+
<path d="M12 8v4" />
|
|
5
|
+
<path d="M12 16h.01" />
|
|
6
6
|
</svg>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-alert-triangle">
|
|
2
|
-
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
|
3
|
-
<path d="M12 9v4" />
|
|
4
|
-
<path d="M10.363 3.591l-8.106 13.534a1.914 1.914 0 0 0 1.636 2.871h16.214a1.914 1.914 0 0 0 1.636 -2.87l-8.106 -13.536a1.914 1.914 0 0 0 -3.274 0z" />
|
|
5
|
-
<path d="M12 16h.01" />
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-alert-triangle">
|
|
2
|
+
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
|
3
|
+
<path d="M12 9v4" />
|
|
4
|
+
<path d="M10.363 3.591l-8.106 13.534a1.914 1.914 0 0 0 1.636 2.871h16.214a1.914 1.914 0 0 0 1.636 -2.87l-8.106 -13.536a1.914 1.914 0 0 0 -3.274 0z" />
|
|
5
|
+
<path d="M12 16h.01" />
|
|
6
6
|
</svg>
|
package/dist/icon/archive.svg
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-archive"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M3 4m0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z" /><path d="M5 8v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-10" /><path d="M10 12l4 0" /></svg>
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-archive"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M3 4m0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z" /><path d="M5 8v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-10" /><path d="M10 12l4 0" /></svg>
|