@placeholderco/placeholder-ui 2.5.4 → 2.6.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/dist/display/Avatar.svelte +1 -1
- package/dist/editors/tiptap/toolbar/ColorButton.svelte +17 -1
- package/dist/editors/tiptap/toolbar/LinkButton.svelte +4 -2
- package/dist/form/ComboBox.svelte +1 -0
- package/dist/form/ComboBoxMulti.svelte +1 -0
- package/dist/form/DatePicker.svelte +4 -2
- package/dist/form/DateRangePicker.svelte +4 -2
- package/dist/form/DateTimePicker.svelte +4 -2
- package/dist/form/SegmentedControl.svelte +1 -0
- package/dist/form/Select.svelte +1 -0
- package/dist/form/SelectMulti.svelte +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/ui/Badge.svelte +4 -2
- package/dist/ui/ConfirmDialog.svelte +191 -0
- package/dist/ui/ConfirmDialog.svelte.d.ts +52 -0
- package/dist/ui/Popover.svelte +1 -0
- package/dist/ui/Tabs.svelte +1 -0
- package/package.json +3 -3
|
@@ -84,6 +84,7 @@
|
|
|
84
84
|
<div class="color-preset-grid">
|
|
85
85
|
{#each brandColors as swatch}
|
|
86
86
|
<button
|
|
87
|
+
type="button"
|
|
87
88
|
class="color-preset"
|
|
88
89
|
style="background: {swatch.value}"
|
|
89
90
|
onclick={() => applyColor(swatch.value)}
|
|
@@ -97,6 +98,7 @@
|
|
|
97
98
|
<div class="color-section-title">Common Colors</div>
|
|
98
99
|
<div class="color-preset-grid">
|
|
99
100
|
<button
|
|
101
|
+
type="button"
|
|
100
102
|
class="color-preset"
|
|
101
103
|
style="background: #000000"
|
|
102
104
|
onclick={() => applyColor('#000000')}
|
|
@@ -104,6 +106,7 @@
|
|
|
104
106
|
aria-label="Black"
|
|
105
107
|
></button>
|
|
106
108
|
<button
|
|
109
|
+
type="button"
|
|
107
110
|
class="color-preset"
|
|
108
111
|
style="background: #495057"
|
|
109
112
|
onclick={() => applyColor('#495057')}
|
|
@@ -111,6 +114,7 @@
|
|
|
111
114
|
aria-label="Gray"
|
|
112
115
|
></button>
|
|
113
116
|
<button
|
|
117
|
+
type="button"
|
|
114
118
|
class="color-preset"
|
|
115
119
|
style="background: #fa5252"
|
|
116
120
|
onclick={() => applyColor('#fa5252')}
|
|
@@ -118,6 +122,7 @@
|
|
|
118
122
|
aria-label="Red"
|
|
119
123
|
></button>
|
|
120
124
|
<button
|
|
125
|
+
type="button"
|
|
121
126
|
class="color-preset"
|
|
122
127
|
style="background: #ff922b"
|
|
123
128
|
onclick={() => applyColor('#ff922b')}
|
|
@@ -125,6 +130,7 @@
|
|
|
125
130
|
aria-label="Orange"
|
|
126
131
|
></button>
|
|
127
132
|
<button
|
|
133
|
+
type="button"
|
|
128
134
|
class="color-preset"
|
|
129
135
|
style="background: #fcc419"
|
|
130
136
|
onclick={() => applyColor('#fcc419')}
|
|
@@ -132,6 +138,7 @@
|
|
|
132
138
|
aria-label="Yellow"
|
|
133
139
|
></button>
|
|
134
140
|
<button
|
|
141
|
+
type="button"
|
|
135
142
|
class="color-preset"
|
|
136
143
|
style="background: #51cf66"
|
|
137
144
|
onclick={() => applyColor('#51cf66')}
|
|
@@ -139,6 +146,7 @@
|
|
|
139
146
|
aria-label="Green"
|
|
140
147
|
></button>
|
|
141
148
|
<button
|
|
149
|
+
type="button"
|
|
142
150
|
class="color-preset"
|
|
143
151
|
style="background: #22b8cf"
|
|
144
152
|
onclick={() => applyColor('#22b8cf')}
|
|
@@ -146,6 +154,7 @@
|
|
|
146
154
|
aria-label="Cyan"
|
|
147
155
|
></button>
|
|
148
156
|
<button
|
|
157
|
+
type="button"
|
|
149
158
|
class="color-preset"
|
|
150
159
|
style="background: #228be6"
|
|
151
160
|
onclick={() => applyColor('#228be6')}
|
|
@@ -153,6 +162,7 @@
|
|
|
153
162
|
aria-label="Blue"
|
|
154
163
|
></button>
|
|
155
164
|
<button
|
|
165
|
+
type="button"
|
|
156
166
|
class="color-preset"
|
|
157
167
|
style="background: #9775fa"
|
|
158
168
|
onclick={() => applyColor('#9775fa')}
|
|
@@ -160,6 +170,7 @@
|
|
|
160
170
|
aria-label="Purple"
|
|
161
171
|
></button>
|
|
162
172
|
<button
|
|
173
|
+
type="button"
|
|
163
174
|
class="color-preset"
|
|
164
175
|
style="background: #f06595"
|
|
165
176
|
onclick={() => applyColor('#f06595')}
|
|
@@ -175,7 +186,12 @@
|
|
|
175
186
|
class="color-input"
|
|
176
187
|
title="Custom Color"
|
|
177
188
|
/>
|
|
178
|
-
<button
|
|
189
|
+
<button
|
|
190
|
+
type="button"
|
|
191
|
+
onclick={removeColor}
|
|
192
|
+
class="color-remove-button"
|
|
193
|
+
title="Remove Color"
|
|
194
|
+
>
|
|
179
195
|
Clear
|
|
180
196
|
</button>
|
|
181
197
|
</div>
|
|
@@ -99,9 +99,11 @@
|
|
|
99
99
|
placeholder="Enter URL"
|
|
100
100
|
class="link-input"
|
|
101
101
|
/>
|
|
102
|
-
<button onclick={setLink} class="link-submit-button" title="Apply">✓</button>
|
|
102
|
+
<button type="button" onclick={setLink} class="link-submit-button" title="Apply">✓</button>
|
|
103
103
|
{#if editor.isActive('link')}
|
|
104
|
-
<button onclick={removeLink} class="link-remove-button" title="Remove Link"
|
|
104
|
+
<button type="button" onclick={removeLink} class="link-remove-button" title="Remove Link"
|
|
105
|
+
>✕</button
|
|
106
|
+
>
|
|
105
107
|
{/if}
|
|
106
108
|
</div>
|
|
107
109
|
<label class="link-checkbox-label">
|
|
@@ -108,6 +108,7 @@
|
|
|
108
108
|
localIndex}
|
|
109
109
|
{@const localClasses = [selectedIndex === globalIndex ? 'selected p-2' : 'p-2']}
|
|
110
110
|
<button
|
|
111
|
+
type="button"
|
|
111
112
|
class="combobox-item {localClasses.join(' ')} {option.class}"
|
|
112
113
|
role="option"
|
|
113
114
|
aria-selected={selectedIndex === globalIndex}
|
|
@@ -336,7 +336,7 @@
|
|
|
336
336
|
size="1.5rem"
|
|
337
337
|
onclick={() => incrementYearRange(-1)}
|
|
338
338
|
/>
|
|
339
|
-
<button class="month-label clickable" onclick={toggleYearPicker}>
|
|
339
|
+
<button type="button" class="month-label clickable" onclick={toggleYearPicker}>
|
|
340
340
|
{yearRangeStart} - {yearRangeStart + yearRangeSize - 1}
|
|
341
341
|
</button>
|
|
342
342
|
<ActionIcon
|
|
@@ -350,7 +350,7 @@
|
|
|
350
350
|
size="1.5rem"
|
|
351
351
|
onclick={() => incrementFocusedMonth(-1)}
|
|
352
352
|
/>
|
|
353
|
-
<button class="month-label clickable" onclick={toggleYearPicker}>
|
|
353
|
+
<button type="button" class="month-label clickable" onclick={toggleYearPicker}>
|
|
354
354
|
{focusedMonth.format('MMMM YYYY')}
|
|
355
355
|
</button>
|
|
356
356
|
<ActionIcon
|
|
@@ -365,6 +365,7 @@
|
|
|
365
365
|
<div class="year-grid">
|
|
366
366
|
{#each getYearRange() as year}
|
|
367
367
|
<button
|
|
368
|
+
type="button"
|
|
368
369
|
class="year-button"
|
|
369
370
|
class:selected={focusedMonth.year() === year}
|
|
370
371
|
class:current-year={todayDate.year() === year}
|
|
@@ -387,6 +388,7 @@
|
|
|
387
388
|
<div class="days-grid">
|
|
388
389
|
{#each calculateDays(selectedDate, focusedMonth) as day, i (i)}
|
|
389
390
|
<button
|
|
391
|
+
type="button"
|
|
390
392
|
class="day-button {buildDayClasses(day)}"
|
|
391
393
|
disabled={day.isDisabled}
|
|
392
394
|
onclick={(e) => handleDateChangeClick(e, day.date, day.isDisabled)}
|
|
@@ -342,7 +342,7 @@
|
|
|
342
342
|
size="1.5rem"
|
|
343
343
|
onclick={() => incrementYearRange(-1)}
|
|
344
344
|
/>
|
|
345
|
-
<button class="month-label clickable" onclick={toggleYearPicker}>
|
|
345
|
+
<button type="button" class="month-label clickable" onclick={toggleYearPicker}>
|
|
346
346
|
{yearRangeStart} – {yearRangeStart + yearRangeSize - 1}
|
|
347
347
|
</button>
|
|
348
348
|
<ActionIcon
|
|
@@ -356,7 +356,7 @@
|
|
|
356
356
|
size="1.5rem"
|
|
357
357
|
onclick={() => incrementFocusedMonth(-1)}
|
|
358
358
|
/>
|
|
359
|
-
<button class="month-label clickable" onclick={toggleYearPicker}>
|
|
359
|
+
<button type="button" class="month-label clickable" onclick={toggleYearPicker}>
|
|
360
360
|
{focusedMonth.format('MMMM YYYY')}
|
|
361
361
|
</button>
|
|
362
362
|
<ActionIcon
|
|
@@ -375,6 +375,7 @@
|
|
|
375
375
|
<div class="year-grid">
|
|
376
376
|
{#each getYearRange() as year}
|
|
377
377
|
<button
|
|
378
|
+
type="button"
|
|
378
379
|
class="year-button"
|
|
379
380
|
class:selected={focusedMonth.year() === year}
|
|
380
381
|
class:current-year={todayDate.year() === year}
|
|
@@ -408,6 +409,7 @@
|
|
|
408
409
|
}}
|
|
409
410
|
>
|
|
410
411
|
<button
|
|
412
|
+
type="button"
|
|
411
413
|
class={buildButtonClasses(d)}
|
|
412
414
|
disabled={d.isDisabled}
|
|
413
415
|
onclick={(e) => handleDayClick(d, e)}
|
|
@@ -331,7 +331,7 @@
|
|
|
331
331
|
size="1.5rem"
|
|
332
332
|
onclick={() => incrementYearRange(-1)}
|
|
333
333
|
/>
|
|
334
|
-
<button class="month-label clickable" onclick={toggleYearPicker}>
|
|
334
|
+
<button type="button" class="month-label clickable" onclick={toggleYearPicker}>
|
|
335
335
|
{yearRangeStart} - {yearRangeStart + yearRangeSize - 1}
|
|
336
336
|
</button>
|
|
337
337
|
<ActionIcon
|
|
@@ -345,7 +345,7 @@
|
|
|
345
345
|
size="1.5rem"
|
|
346
346
|
onclick={() => incrementFocusedMonth(-1)}
|
|
347
347
|
/>
|
|
348
|
-
<button class="month-label clickable" onclick={toggleYearPicker}>
|
|
348
|
+
<button type="button" class="month-label clickable" onclick={toggleYearPicker}>
|
|
349
349
|
{focusedMonth.format('MMMM YYYY')}
|
|
350
350
|
</button>
|
|
351
351
|
<ActionIcon
|
|
@@ -360,6 +360,7 @@
|
|
|
360
360
|
<div class="year-grid">
|
|
361
361
|
{#each getYearRange() as year}
|
|
362
362
|
<button
|
|
363
|
+
type="button"
|
|
363
364
|
class="year-button"
|
|
364
365
|
class:selected={focusedMonth.year() === year}
|
|
365
366
|
class:current-year={todayDate.year() === year}
|
|
@@ -382,6 +383,7 @@
|
|
|
382
383
|
<div class="days-grid">
|
|
383
384
|
{#each calculateDays(selectedDate, focusedMonth) as day, i (i)}
|
|
384
385
|
<button
|
|
386
|
+
type="button"
|
|
385
387
|
class="day-button {buildDayClasses(day)}"
|
|
386
388
|
disabled={day.isDisabled}
|
|
387
389
|
onclick={(e) => handleDateChangeClick(e, day.date, day.isDisabled)}
|
package/dist/form/Select.svelte
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export { default as Badge } from './ui/Badge.svelte';
|
|
|
10
10
|
export type { BadgeProps } from './ui/Badge.svelte';
|
|
11
11
|
export { default as Dialog } from './ui/Dialog.svelte';
|
|
12
12
|
export type { DialogProps, DialogContext } from './ui/Dialog.svelte';
|
|
13
|
+
export { default as ConfirmDialog } from './ui/ConfirmDialog.svelte';
|
|
14
|
+
export type { ConfirmDialogProps } from './ui/ConfirmDialog.svelte';
|
|
13
15
|
export { default as Drawer } from './ui/Drawer.svelte';
|
|
14
16
|
export type { DrawerProps } from './ui/Drawer.svelte';
|
|
15
17
|
export { default as Dropdown } from './ui/Dropdown.svelte';
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export { default as Button } from './ui/Button.svelte';
|
|
|
4
4
|
export { default as ActionIcon } from './ui/ActionIcon.svelte';
|
|
5
5
|
export { default as Badge } from './ui/Badge.svelte';
|
|
6
6
|
export { default as Dialog } from './ui/Dialog.svelte';
|
|
7
|
+
export { default as ConfirmDialog } from './ui/ConfirmDialog.svelte';
|
|
7
8
|
export { default as Drawer } from './ui/Drawer.svelte';
|
|
8
9
|
export { default as Dropdown } from './ui/Dropdown.svelte';
|
|
9
10
|
export { default as Dropzone } from './ui/Dropzone.svelte';
|
package/dist/ui/Badge.svelte
CHANGED
|
@@ -52,14 +52,16 @@
|
|
|
52
52
|
{#if type == 'a' && !disabled}
|
|
53
53
|
<a class={elClass} {href} {target}> {@render children?.()}</a>
|
|
54
54
|
{:else if type == 'button'}
|
|
55
|
-
<button class={elClass} disabled={isDisabled} onclick={onClick}>
|
|
55
|
+
<button type="button" class={elClass} disabled={isDisabled} onclick={onClick}>
|
|
56
|
+
{@render children?.()}</button
|
|
57
|
+
>
|
|
56
58
|
{:else}
|
|
57
59
|
<div class={elClass}>
|
|
58
60
|
{@render children?.()}
|
|
59
61
|
</div>
|
|
60
62
|
{/if}
|
|
61
63
|
{#if onDelete}
|
|
62
|
-
<button class="badge-button {variant}" disabled={isDisabled} onclick={onDelete}>
|
|
64
|
+
<button type="button" class="badge-button {variant}" disabled={isDisabled} onclick={onDelete}>
|
|
63
65
|
<Icon size={size === 'sm' ? '12px' : size === 'lg' ? '16px' : '14px'} svg={iconX} />
|
|
64
66
|
</button>
|
|
65
67
|
{/if}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import Button from './Button.svelte';
|
|
4
|
+
import Dialog from './Dialog.svelte';
|
|
5
|
+
import type { ButtonVariant } from './ButtonVariant.js';
|
|
6
|
+
|
|
7
|
+
export interface ConfirmDialogProps {
|
|
8
|
+
/** Whether the dialog is visible (bindable) */
|
|
9
|
+
show: boolean;
|
|
10
|
+
/** Dialog title displayed in the header */
|
|
11
|
+
title?: string | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Plain-text body. Ignored when `children` is provided, so pass a snippet
|
|
14
|
+
* for richer content.
|
|
15
|
+
*/
|
|
16
|
+
message?: string | undefined;
|
|
17
|
+
/** Label for the confirming button */
|
|
18
|
+
okText?: string;
|
|
19
|
+
/** Label for the dismissing button */
|
|
20
|
+
cancelText?: string;
|
|
21
|
+
/** Visual variant of the confirming button (use `danger` for destructive actions) */
|
|
22
|
+
okVariant?: ButtonVariant;
|
|
23
|
+
/** Visual variant of the dismissing button */
|
|
24
|
+
cancelVariant?: ButtonVariant;
|
|
25
|
+
/** Icon shown on the left of the confirming button */
|
|
26
|
+
okSvg?: string;
|
|
27
|
+
/** Disable the confirming button (e.g. while a form is invalid) */
|
|
28
|
+
okDisabled?: boolean;
|
|
29
|
+
/** Hide the Cancel button entirely, leaving an acknowledgement-style dialog */
|
|
30
|
+
hideCancel?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Which button receives focus when the dialog opens. Defaults to the
|
|
33
|
+
* confirming button, or to Cancel when `okVariant` is a danger variant so
|
|
34
|
+
* a stray Enter cannot trigger a destructive action.
|
|
35
|
+
*/
|
|
36
|
+
initialFocus?: 'ok' | 'cancel' | 'none';
|
|
37
|
+
/**
|
|
38
|
+
* Called when OK is pressed. Returning a promise puts the OK button into a
|
|
39
|
+
* loading state and keeps the dialog open until it settles. Return `false`
|
|
40
|
+
* (or resolve to `false`) to keep the dialog open.
|
|
41
|
+
*/
|
|
42
|
+
onConfirm?: () => void | boolean | Promise<void | boolean>;
|
|
43
|
+
/** Called when the dialog is dismissed via Cancel, the close icon, Escape or the backdrop */
|
|
44
|
+
onCancel?: () => void;
|
|
45
|
+
/** Allow closing by clicking backdrop or pressing Escape */
|
|
46
|
+
allowImplicitClose?: boolean;
|
|
47
|
+
/** Size preset for the dialog width */
|
|
48
|
+
size?: 'md' | 'lg' | 'xl' | 'full';
|
|
49
|
+
/** Additional CSS classes passed through to the dialog */
|
|
50
|
+
class?: string;
|
|
51
|
+
/** Custom body content; overrides `message` */
|
|
52
|
+
children?: Snippet;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let {
|
|
56
|
+
show = $bindable(false),
|
|
57
|
+
title = undefined,
|
|
58
|
+
message = undefined,
|
|
59
|
+
okText = 'Save',
|
|
60
|
+
cancelText = 'Cancel',
|
|
61
|
+
okVariant = 'primary',
|
|
62
|
+
cancelVariant = 'secondary',
|
|
63
|
+
okSvg = undefined,
|
|
64
|
+
okDisabled = false,
|
|
65
|
+
hideCancel = false,
|
|
66
|
+
initialFocus = undefined,
|
|
67
|
+
onConfirm = undefined,
|
|
68
|
+
onCancel = undefined,
|
|
69
|
+
allowImplicitClose = true,
|
|
70
|
+
size = 'md',
|
|
71
|
+
class: classes = '',
|
|
72
|
+
children
|
|
73
|
+
}: ConfirmDialogProps = $props();
|
|
74
|
+
|
|
75
|
+
let loading = $state(false);
|
|
76
|
+
let footerElement: HTMLDivElement | undefined = $state(undefined);
|
|
77
|
+
|
|
78
|
+
// Track whether the close was the result of OK so the cancel callback only
|
|
79
|
+
// fires for genuine dismissals (Cancel button, close icon, Escape, backdrop)
|
|
80
|
+
let confirmed = false;
|
|
81
|
+
let wasOpen = false;
|
|
82
|
+
|
|
83
|
+
const resolvedFocus = $derived(
|
|
84
|
+
initialFocus ?? (okVariant.startsWith('danger') && !hideCancel ? 'cancel' : 'ok')
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
$effect(() => {
|
|
88
|
+
if (show && !wasOpen) {
|
|
89
|
+
wasOpen = true;
|
|
90
|
+
confirmed = false;
|
|
91
|
+
loading = false;
|
|
92
|
+
focusInitialButton();
|
|
93
|
+
} else if (!show && wasOpen) {
|
|
94
|
+
wasOpen = false;
|
|
95
|
+
loading = false;
|
|
96
|
+
if (!confirmed) onCancel?.();
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
function focusInitialButton() {
|
|
101
|
+
if (resolvedFocus === 'none') return;
|
|
102
|
+
// showModal() runs in the parent Dialog's effect and moves focus to the
|
|
103
|
+
// first focusable element; wait a frame so this focus call lands after it
|
|
104
|
+
requestAnimationFrame(() => {
|
|
105
|
+
const target = footerElement?.querySelector<HTMLButtonElement>(
|
|
106
|
+
`.confirm-dialog-${resolvedFocus} button`
|
|
107
|
+
);
|
|
108
|
+
target?.focus();
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async function handleConfirm() {
|
|
113
|
+
if (loading) return;
|
|
114
|
+
let result: void | boolean;
|
|
115
|
+
try {
|
|
116
|
+
const pending = onConfirm?.();
|
|
117
|
+
if (pending instanceof Promise) {
|
|
118
|
+
loading = true;
|
|
119
|
+
result = await pending;
|
|
120
|
+
} else {
|
|
121
|
+
result = pending;
|
|
122
|
+
}
|
|
123
|
+
} finally {
|
|
124
|
+
loading = false;
|
|
125
|
+
}
|
|
126
|
+
if (result === false) return;
|
|
127
|
+
confirmed = true;
|
|
128
|
+
show = false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function handleCancel() {
|
|
132
|
+
if (loading) return;
|
|
133
|
+
show = false;
|
|
134
|
+
}
|
|
135
|
+
</script>
|
|
136
|
+
|
|
137
|
+
<Dialog
|
|
138
|
+
bind:show
|
|
139
|
+
{title}
|
|
140
|
+
{size}
|
|
141
|
+
class={classes}
|
|
142
|
+
allowImplicitClose={allowImplicitClose && !loading}
|
|
143
|
+
>
|
|
144
|
+
{#if children}
|
|
145
|
+
{@render children()}
|
|
146
|
+
{:else if message}
|
|
147
|
+
<p class="confirm-dialog-message">{message}</p>
|
|
148
|
+
{/if}
|
|
149
|
+
{#snippet footer()}
|
|
150
|
+
<div class="confirm-dialog-actions" bind:this={footerElement}>
|
|
151
|
+
{#if !hideCancel}
|
|
152
|
+
<span class="confirm-dialog-cancel">
|
|
153
|
+
<Button variant={cancelVariant} disabled={loading} onclick={handleCancel}>
|
|
154
|
+
{cancelText}
|
|
155
|
+
</Button>
|
|
156
|
+
</span>
|
|
157
|
+
{/if}
|
|
158
|
+
<span class="confirm-dialog-ok">
|
|
159
|
+
<Button
|
|
160
|
+
variant={okVariant}
|
|
161
|
+
svg={okSvg}
|
|
162
|
+
{loading}
|
|
163
|
+
disabled={okDisabled}
|
|
164
|
+
onclick={handleConfirm}
|
|
165
|
+
>
|
|
166
|
+
{okText}
|
|
167
|
+
</Button>
|
|
168
|
+
</span>
|
|
169
|
+
</div>
|
|
170
|
+
{/snippet}
|
|
171
|
+
</Dialog>
|
|
172
|
+
|
|
173
|
+
<style>
|
|
174
|
+
.confirm-dialog-message {
|
|
175
|
+
margin: 0;
|
|
176
|
+
white-space: pre-line;
|
|
177
|
+
overflow-wrap: anywhere;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.confirm-dialog-actions {
|
|
181
|
+
display: flex;
|
|
182
|
+
align-items: center;
|
|
183
|
+
justify-content: flex-end;
|
|
184
|
+
gap: 0.5rem;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.confirm-dialog-cancel,
|
|
188
|
+
.confirm-dialog-ok {
|
|
189
|
+
display: contents;
|
|
190
|
+
}
|
|
191
|
+
</style>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { ButtonVariant } from './ButtonVariant.js';
|
|
3
|
+
export interface ConfirmDialogProps {
|
|
4
|
+
/** Whether the dialog is visible (bindable) */
|
|
5
|
+
show: boolean;
|
|
6
|
+
/** Dialog title displayed in the header */
|
|
7
|
+
title?: string | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Plain-text body. Ignored when `children` is provided, so pass a snippet
|
|
10
|
+
* for richer content.
|
|
11
|
+
*/
|
|
12
|
+
message?: string | undefined;
|
|
13
|
+
/** Label for the confirming button */
|
|
14
|
+
okText?: string;
|
|
15
|
+
/** Label for the dismissing button */
|
|
16
|
+
cancelText?: string;
|
|
17
|
+
/** Visual variant of the confirming button (use `danger` for destructive actions) */
|
|
18
|
+
okVariant?: ButtonVariant;
|
|
19
|
+
/** Visual variant of the dismissing button */
|
|
20
|
+
cancelVariant?: ButtonVariant;
|
|
21
|
+
/** Icon shown on the left of the confirming button */
|
|
22
|
+
okSvg?: string;
|
|
23
|
+
/** Disable the confirming button (e.g. while a form is invalid) */
|
|
24
|
+
okDisabled?: boolean;
|
|
25
|
+
/** Hide the Cancel button entirely, leaving an acknowledgement-style dialog */
|
|
26
|
+
hideCancel?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Which button receives focus when the dialog opens. Defaults to the
|
|
29
|
+
* confirming button, or to Cancel when `okVariant` is a danger variant so
|
|
30
|
+
* a stray Enter cannot trigger a destructive action.
|
|
31
|
+
*/
|
|
32
|
+
initialFocus?: 'ok' | 'cancel' | 'none';
|
|
33
|
+
/**
|
|
34
|
+
* Called when OK is pressed. Returning a promise puts the OK button into a
|
|
35
|
+
* loading state and keeps the dialog open until it settles. Return `false`
|
|
36
|
+
* (or resolve to `false`) to keep the dialog open.
|
|
37
|
+
*/
|
|
38
|
+
onConfirm?: () => void | boolean | Promise<void | boolean>;
|
|
39
|
+
/** Called when the dialog is dismissed via Cancel, the close icon, Escape or the backdrop */
|
|
40
|
+
onCancel?: () => void;
|
|
41
|
+
/** Allow closing by clicking backdrop or pressing Escape */
|
|
42
|
+
allowImplicitClose?: boolean;
|
|
43
|
+
/** Size preset for the dialog width */
|
|
44
|
+
size?: 'md' | 'lg' | 'xl' | 'full';
|
|
45
|
+
/** Additional CSS classes passed through to the dialog */
|
|
46
|
+
class?: string;
|
|
47
|
+
/** Custom body content; overrides `message` */
|
|
48
|
+
children?: Snippet;
|
|
49
|
+
}
|
|
50
|
+
declare const ConfirmDialog: import("svelte").Component<ConfirmDialogProps, {}, "show">;
|
|
51
|
+
type ConfirmDialog = ReturnType<typeof ConfirmDialog>;
|
|
52
|
+
export default ConfirmDialog;
|
package/dist/ui/Popover.svelte
CHANGED
package/dist/ui/Tabs.svelte
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@placeholderco/placeholder-ui",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "A modern, customizable Svelte 5 UI component library with comprehensive theming support. Re-brand it with a single config object.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Placeholderco",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"@sveltejs/kit": "^2.70.3",
|
|
57
57
|
"@sveltejs/package": "^2.5.8",
|
|
58
58
|
"@sveltejs/vite-plugin-svelte": "^7.3.0",
|
|
59
|
-
"@types/node": "^26.
|
|
59
|
+
"@types/node": "^26.5.1",
|
|
60
60
|
"globals": "^17.12.0",
|
|
61
61
|
"prettier": "^3.9.6",
|
|
62
62
|
"prettier-plugin-svelte": "^4.1.1",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"svelte": "^5.57.0",
|
|
66
66
|
"svelte-check": "^4.7.6",
|
|
67
67
|
"typescript": "^6.0.3",
|
|
68
|
-
"vite": "^8.
|
|
68
|
+
"vite": "^8.3.0"
|
|
69
69
|
},
|
|
70
70
|
"dependencies": {
|
|
71
71
|
"@codemirror/autocomplete": "^6.20.3",
|