@svgrid/grid 2.2.16 → 2.2.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/GridFooter.svelte +12 -11
- package/dist/SvAnchor.svelte +65 -0
- package/dist/SvAnchor.svelte.d.ts +24 -0
- package/dist/SvAspectRatio.svelte +38 -0
- package/dist/SvAspectRatio.svelte.d.ts +16 -0
- package/dist/SvAutoComplete.svelte +52 -7
- package/dist/SvAutoComplete.svelte.d.ts +4 -1
- package/dist/SvBlockquote.svelte +43 -0
- package/dist/SvBlockquote.svelte.d.ts +16 -0
- package/dist/SvCalendar.svelte +33 -2
- package/dist/SvCalendar.svelte.d.ts +8 -1
- package/dist/SvCheckBox.svelte +6 -2
- package/dist/SvCode.svelte +52 -0
- package/dist/SvCode.svelte.d.ts +19 -0
- package/dist/SvCollapsible.svelte +75 -0
- package/dist/SvCollapsible.svelte.d.ts +27 -0
- package/dist/SvColorInput.svelte +11 -17
- package/dist/SvColorInput.svelte.d.ts +2 -0
- package/dist/SvComboBox.svelte +85 -8
- package/dist/SvComboBox.svelte.d.ts +14 -0
- package/dist/SvCountryInput.svelte +2 -2
- package/dist/SvCountryInput.svelte.d.ts +1 -1
- package/dist/SvDropDownList.svelte +154 -51
- package/dist/SvDropDownList.svelte.d.ts +17 -3
- package/dist/SvDurationInput.svelte +59 -41
- package/dist/SvDurationInput.svelte.d.ts +18 -0
- package/dist/SvField.svelte +203 -12
- package/dist/SvField.svelte.d.ts +45 -8
- package/dist/SvForm.svelte +195 -21
- package/dist/SvForm.svelte.d.ts +23 -0
- package/dist/SvGrid.controller.svelte.d.ts +12 -1
- package/dist/SvGrid.controller.svelte.js +87 -7
- package/dist/SvGrid.svelte +383 -181
- package/dist/SvGrid.types.d.ts +123 -2
- package/dist/SvGridChartView.svelte +70 -0
- package/dist/SvGridChartView.svelte.d.ts +11 -0
- package/dist/SvGridDropdown.svelte +9 -2
- package/dist/SvGridSelect.svelte +5 -2
- package/dist/SvGridSelect.svelte.d.ts +1 -1
- package/dist/SvGroup.svelte +41 -0
- package/dist/SvGroup.svelte.d.ts +27 -0
- package/dist/SvHoverCard.svelte +70 -0
- package/dist/SvHoverCard.svelte.d.ts +41 -0
- package/dist/SvKbd.svelte +51 -0
- package/dist/SvKbd.svelte.d.ts +18 -0
- package/dist/SvList.svelte +55 -0
- package/dist/SvList.svelte.d.ts +23 -0
- package/dist/SvListBox.svelte +166 -77
- package/dist/SvListBox.svelte.d.ts +17 -4
- package/dist/SvLoadingOverlay.svelte +53 -0
- package/dist/SvLoadingOverlay.svelte.d.ts +28 -0
- package/dist/SvMark.svelte +36 -0
- package/dist/SvMark.svelte.d.ts +14 -0
- package/dist/SvMaskedInput.svelte +50 -35
- package/dist/SvMaskedInput.svelte.d.ts +17 -2
- package/dist/SvMenuList.svelte +32 -3
- package/dist/SvMenubar.svelte +200 -0
- package/dist/SvMenubar.svelte.d.ts +18 -0
- package/dist/SvMultiSelect.svelte +7 -4
- package/dist/SvMultiSelect.svelte.d.ts +1 -1
- package/dist/SvNumberInput.svelte +79 -42
- package/dist/SvNumberInput.svelte.d.ts +25 -0
- package/dist/SvOtpInput.svelte +2 -2
- package/dist/SvPasswordInput.svelte +51 -31
- package/dist/SvPasswordInput.svelte.d.ts +17 -0
- package/dist/SvPhoneInput.svelte +39 -28
- package/dist/SvPhoneInput.svelte.d.ts +4 -0
- package/dist/SvPopconfirm.svelte +79 -0
- package/dist/SvPopconfirm.svelte.d.ts +42 -0
- package/dist/SvPopover.svelte +87 -29
- package/dist/SvPopover.svelte.d.ts +18 -4
- package/dist/SvRadioGroup.svelte +5 -1
- package/dist/SvResult.svelte +73 -0
- package/dist/SvResult.svelte.d.ts +28 -0
- package/dist/SvSegmented.svelte +114 -0
- package/dist/SvSegmented.svelte.d.ts +29 -0
- package/dist/SvSimpleGrid.svelte +41 -0
- package/dist/SvSimpleGrid.svelte.d.ts +25 -0
- package/dist/SvSlider.svelte +23 -10
- package/dist/SvSpinner.svelte +43 -0
- package/dist/SvSpinner.svelte.d.ts +20 -0
- package/dist/SvStack.svelte +37 -0
- package/dist/SvStack.svelte.d.ts +24 -0
- package/dist/SvSwitchButton.svelte +6 -1
- package/dist/SvTagsInput.svelte +9 -5
- package/dist/SvText.svelte +76 -0
- package/dist/SvText.svelte.d.ts +31 -0
- package/dist/SvTextInput.svelte +75 -43
- package/dist/SvTextInput.svelte.d.ts +28 -1
- package/dist/SvTimePicker.svelte +32 -2
- package/dist/SvTimePicker.svelte.d.ts +8 -9
- package/dist/SvTitle.svelte +57 -0
- package/dist/SvTitle.svelte.d.ts +24 -0
- package/dist/SvToaster.svelte +41 -6
- package/dist/SvToggleButton.svelte +4 -1
- package/dist/SvTooltip.svelte +68 -34
- package/dist/SvTooltip.svelte.d.ts +14 -2
- package/dist/SvTree.svelte +81 -21
- package/dist/SvTree.svelte.d.ts +3 -2
- package/dist/SvTreeSelect.svelte +5 -2
- package/dist/SvTreeSelect.svelte.d.ts +1 -1
- package/dist/SvVisuallyHidden.svelte +49 -0
- package/dist/SvVisuallyHidden.svelte.d.ts +19 -0
- package/dist/ai.d.ts +289 -0
- package/dist/ai.js +1013 -0
- package/dist/board-view.svelte.d.ts +22 -0
- package/dist/board-view.svelte.js +13 -0
- package/dist/build-api.js +36 -6
- package/dist/cdn/GridMenus-0AK9O7qG.js +420 -0
- package/dist/cdn/GridMenus-BjUoCXoD.js +416 -0
- package/dist/cdn/SvDateTimePicker-CYC7gRER.js +2176 -0
- package/dist/cdn/SvDateTimePicker-DtQKd4Ns.js +2198 -0
- package/dist/cdn/SvGridChart-BcLCYvw9.js +1195 -0
- package/dist/cdn/SvGridChart-BhnFdLd0.js +1203 -0
- package/dist/cdn/SvGridChartPanel-Cmx9DHAS.js +561 -0
- package/dist/cdn/SvGridChartPanel-DvjwxLvK.js +577 -0
- package/dist/cdn/SvGridChartView-B40DTJSX.js +54 -0
- package/dist/cdn/SvGridChartView-PwqI4s02.js +53 -0
- package/dist/cdn/SvGridDropdown-DjALc_4f.js +255 -0
- package/dist/cdn/SvGridDropdown-hpnHvOGt.js +254 -0
- package/dist/cdn/chart-T1usDN0o.js +1212 -0
- package/dist/cdn/disclose-version-DoD9AFD_.js +2958 -0
- package/dist/cdn/export-format-JT5pWVT8.js +561 -0
- package/dist/cdn/popover-P-9P2YYn.js +69 -0
- package/dist/cdn/rolldown-runtime-Dy4uBu1J.js +11 -0
- package/dist/cdn/src-BLhdLmoN.js +25707 -0
- package/dist/cdn/src-BwnUVj3T.js +25623 -0
- package/dist/cdn/svgrid.js +9 -32897
- package/dist/cdn/svgrid.svelte-external.js +9 -30052
- package/dist/cell-formatting.d.ts +2 -2
- package/dist/cell-render.js +4 -4
- package/dist/chart-view.svelte.d.ts +25 -0
- package/dist/chart-view.svelte.js +14 -0
- package/dist/createCombobox.svelte.d.ts +5 -0
- package/dist/createCombobox.svelte.js +21 -5
- package/dist/createDropdownList.svelte.d.ts +3 -0
- package/dist/createDropdownList.svelte.js +8 -2
- package/dist/createForm.svelte.d.ts +18 -0
- package/dist/createForm.svelte.js +51 -6
- package/dist/createMenu.svelte.js +27 -0
- package/dist/createPopoverSelect.svelte.d.ts +3 -0
- package/dist/createPopoverSelect.svelte.js +9 -1
- package/dist/createSlider.svelte.d.ts +8 -21
- package/dist/createSlider.svelte.js +34 -0
- package/dist/createTooltip.svelte.d.ts +12 -0
- package/dist/createTooltip.svelte.js +72 -9
- package/dist/editor-contract.d.ts +15 -0
- package/dist/export-provider.d.ts +27 -0
- package/dist/export-provider.js +9 -0
- package/dist/filter-operators.d.ts +6 -0
- package/dist/filter-operators.js +33 -0
- package/dist/form-field.d.ts +45 -2
- package/dist/grid-messages.d.ts +61 -0
- package/dist/grid-messages.js +72 -0
- package/dist/group-display.d.ts +62 -0
- package/dist/group-display.js +78 -0
- package/dist/index.d.ts +36 -4
- package/dist/index.js +43 -2
- package/dist/js-scroller.svelte.d.ts +35 -0
- package/dist/js-scroller.svelte.js +154 -0
- package/dist/list-option.d.ts +46 -0
- package/dist/list-option.js +53 -0
- package/dist/menus.js +25 -11
- package/dist/pivot-view.svelte.d.ts +72 -0
- package/dist/pivot-view.svelte.js +13 -0
- package/dist/positioning.d.ts +111 -0
- package/dist/positioning.js +191 -0
- package/dist/scheduler-model.d.ts +3 -0
- package/dist/scheduler-model.js +22 -5
- package/dist/svgrid-wrapper.types.d.ts +18 -0
- package/dist/toast-store.svelte.d.ts +54 -0
- package/dist/toast-store.svelte.js +65 -15
- package/package.json +9 -1
- package/src/GridFooter.svelte +12 -11
- package/src/SvAnchor.svelte +65 -0
- package/src/SvAspectRatio.svelte +38 -0
- package/src/SvAutoComplete.svelte +52 -7
- package/src/SvBlockquote.svelte +43 -0
- package/src/SvCalendar.svelte +33 -2
- package/src/SvCalendar.test.ts +15 -0
- package/src/SvCheckBox.svelte +6 -2
- package/src/SvCode.svelte +52 -0
- package/src/SvCollapsible.svelte +75 -0
- package/src/SvColorInput.svelte +11 -17
- package/src/SvComboBox.svelte +85 -8
- package/src/SvCountryInput.svelte +2 -2
- package/src/SvDropDownList.svelte +154 -51
- package/src/SvDurationInput.svelte +59 -41
- package/src/SvField.svelte +203 -12
- package/src/SvForm.svelte +195 -21
- package/src/SvForm.test.ts +112 -0
- package/src/SvGrid.controller.svelte.ts +88 -7
- package/src/SvGrid.svelte +383 -181
- package/src/SvGrid.types.ts +125 -1
- package/src/SvGridChartView.svelte +70 -0
- package/src/SvGridDropdown.svelte +9 -2
- package/src/SvGridSelect.svelte +5 -2
- package/src/SvGroup.svelte +41 -0
- package/src/SvHoverCard.svelte +70 -0
- package/src/SvKbd.svelte +51 -0
- package/src/SvList.svelte +55 -0
- package/src/SvListBox.svelte +166 -77
- package/src/SvLoadingOverlay.svelte +53 -0
- package/src/SvMark.svelte +36 -0
- package/src/SvMaskedInput.svelte +50 -35
- package/src/SvMenuList.svelte +32 -3
- package/src/SvMenubar.svelte +200 -0
- package/src/SvMultiSelect.svelte +7 -4
- package/src/SvNumberInput.svelte +79 -42
- package/src/SvOtpInput.svelte +2 -2
- package/src/SvPasswordInput.svelte +51 -31
- package/src/SvPhoneInput.svelte +39 -28
- package/src/SvPopconfirm.svelte +79 -0
- package/src/SvPopover.svelte +87 -29
- package/src/SvRadioGroup.svelte +5 -1
- package/src/SvResult.svelte +73 -0
- package/src/SvSegmented.svelte +114 -0
- package/src/SvSimpleGrid.svelte +41 -0
- package/src/SvSlider.svelte +23 -10
- package/src/SvSpinner.svelte +43 -0
- package/src/SvStack.svelte +37 -0
- package/src/SvSwitchButton.svelte +6 -1
- package/src/SvTagsInput.svelte +9 -5
- package/src/SvText.svelte +76 -0
- package/src/SvTextInput.svelte +75 -43
- package/src/SvTimePicker.svelte +32 -2
- package/src/SvTitle.svelte +57 -0
- package/src/SvToaster.svelte +41 -6
- package/src/SvToaster.test.ts +32 -0
- package/src/SvToggleButton.svelte +4 -1
- package/src/SvTooltip.svelte +68 -34
- package/src/SvTree.svelte +81 -21
- package/src/SvTreeSelect.svelte +5 -2
- package/src/SvVisuallyHidden.svelte +49 -0
- package/src/ai.test.ts +502 -0
- package/src/ai.ts +1391 -0
- package/src/board-view.svelte.ts +33 -0
- package/src/build-api.coverage.test.ts +101 -0
- package/src/build-api.ts +43 -18
- package/src/builtin-editors.grid.test.ts +1 -1
- package/src/cell-formatting.ts +5 -5
- package/src/cell-render.ts +4 -4
- package/src/chart-view.svelte.ts +36 -0
- package/src/createCombobox.svelte.ts +17 -5
- package/src/createDropdownList.svelte.ts +8 -2
- package/src/createForm.svelte.ts +59 -6
- package/src/createMenu.svelte.ts +23 -0
- package/src/createPopoverSelect.svelte.ts +8 -1
- package/src/createSlider.svelte.ts +20 -0
- package/src/createTooltip.svelte.ts +67 -9
- package/src/editor-contract.ts +16 -0
- package/src/export-provider.ts +40 -0
- package/src/filter-operators.ts +37 -0
- package/src/form-field.ts +42 -2
- package/src/grid-messages.test.ts +24 -0
- package/src/grid-messages.ts +137 -0
- package/src/group-display.test.ts +77 -0
- package/src/group-display.ts +117 -0
- package/src/i18n.grid.test.ts +73 -0
- package/src/index.ts +91 -2
- package/src/js-scroller.svelte.ts +173 -0
- package/src/list-option.test.ts +56 -0
- package/src/list-option.ts +81 -0
- package/src/menus.test.ts +32 -0
- package/src/menus.ts +25 -12
- package/src/pivot-view.svelte.ts +90 -0
- package/src/pivot-view.test.ts +38 -0
- package/src/pivot.grid.test.ts +102 -0
- package/src/positioning.test.ts +141 -0
- package/src/positioning.ts +266 -0
- package/src/scheduler-model.test.ts +16 -0
- package/src/scheduler-model.ts +24 -5
- package/src/svgrid-wrapper.types.ts +23 -0
- package/src/svgrid.charting.test.ts +8 -1
- package/src/svgrid.comments-autocomplete.test.ts +7 -2
- package/src/svgrid.context-menu.test.ts +8 -3
- package/src/toast-store.svelte.ts +98 -0
- package/src/toast-store.test.ts +62 -1
- package/src/ui-breadth.test.ts +138 -0
- package/src/ui-buttons.test.ts +39 -0
- package/src/ui-inputs.test.ts +2 -2
- package/src/ui-range.test.ts +9 -0
- package/src/ui-selection.test.ts +36 -0
- package/src/ui-tier1.test.ts +1 -1
- package/src/virtual.test.ts +20 -6
- package/dist/SvGridBoard.svelte +0 -2339
- package/dist/SvGridBoard.svelte.d.ts +0 -31
- package/src/SvGridBoard.svelte +0 -2339
- package/src/board.test.ts +0 -927
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* SvText - the workhorse text primitive: a paragraph or inline span with
|
|
4
|
+
* consistent size / weight / colour tokens, optional truncation and line
|
|
5
|
+
* clamping. Themes from the shared `--sg-*` tokens.
|
|
6
|
+
*
|
|
7
|
+
* <SvText size="sm" tone="muted">Last synced 2 minutes ago</SvText>
|
|
8
|
+
* <SvText clamp={2}>A long description that wraps then ellipsises...</SvText>
|
|
9
|
+
*/
|
|
10
|
+
import type { Snippet } from 'svelte'
|
|
11
|
+
|
|
12
|
+
type Props = {
|
|
13
|
+
/** Font size step. */
|
|
14
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
|
15
|
+
/** Font weight. */
|
|
16
|
+
weight?: 'normal' | 'medium' | 'semibold' | 'bold'
|
|
17
|
+
/** Semantic colour. */
|
|
18
|
+
tone?: 'default' | 'muted' | 'accent' | 'success' | 'warning' | 'error'
|
|
19
|
+
/** Text alignment. */
|
|
20
|
+
align?: 'start' | 'center' | 'end'
|
|
21
|
+
/** Truncate to a single line with an ellipsis. */
|
|
22
|
+
truncate?: boolean
|
|
23
|
+
/** Clamp to N lines with an ellipsis (overrides truncate). */
|
|
24
|
+
clamp?: number
|
|
25
|
+
/** Render inline (`span`) instead of a block (`p`). */
|
|
26
|
+
inline?: boolean
|
|
27
|
+
/** Override the element/tag. */
|
|
28
|
+
as?: string
|
|
29
|
+
children?: Snippet
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let {
|
|
33
|
+
size = 'md', weight = 'normal', tone = 'default', align,
|
|
34
|
+
truncate = false, clamp, inline = false, as, children,
|
|
35
|
+
}: Props = $props()
|
|
36
|
+
|
|
37
|
+
const sizeMap = { xs: '11px', sm: '13px', md: '14px', lg: '16px', xl: '20px' } as const
|
|
38
|
+
const weightMap = { normal: 400, medium: 500, semibold: 600, bold: 700 } as const
|
|
39
|
+
const toneMap = {
|
|
40
|
+
default: 'var(--sg-fg, #0f172a)',
|
|
41
|
+
muted: 'var(--sg-muted, #64748b)',
|
|
42
|
+
accent: 'var(--sg-accent, #2563eb)',
|
|
43
|
+
success: 'var(--sg-success, #16a34a)',
|
|
44
|
+
warning: 'var(--sg-warning, #d97706)',
|
|
45
|
+
error: 'var(--sg-danger, #dc2626)',
|
|
46
|
+
} as const
|
|
47
|
+
const alignMap = { start: 'left', center: 'center', end: 'right' } as const
|
|
48
|
+
|
|
49
|
+
const tag = $derived(as ?? (inline ? 'span' : 'p'))
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<svelte:element
|
|
53
|
+
this={tag}
|
|
54
|
+
class="sv-text"
|
|
55
|
+
class:is-truncate={truncate && !clamp}
|
|
56
|
+
class:is-clamp={clamp != null}
|
|
57
|
+
style:font-size={sizeMap[size]}
|
|
58
|
+
style:font-weight={weightMap[weight]}
|
|
59
|
+
style:color={toneMap[tone]}
|
|
60
|
+
style:text-align={align ? alignMap[align] : undefined}
|
|
61
|
+
style:--sv-text-clamp={clamp}
|
|
62
|
+
>
|
|
63
|
+
{@render children?.()}
|
|
64
|
+
</svelte:element>
|
|
65
|
+
|
|
66
|
+
<style>
|
|
67
|
+
.sv-text { margin: 0; font-family: var(--sg-font, inherit); line-height: 1.5; }
|
|
68
|
+
.sv-text.is-truncate { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
|
|
69
|
+
.sv-text.is-clamp {
|
|
70
|
+
display: -webkit-box;
|
|
71
|
+
-webkit-box-orient: vertical;
|
|
72
|
+
-webkit-line-clamp: var(--sv-text-clamp, 2);
|
|
73
|
+
line-clamp: var(--sv-text-clamp, 2);
|
|
74
|
+
overflow: hidden;
|
|
75
|
+
}
|
|
76
|
+
</style>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SvText - the workhorse text primitive: a paragraph or inline span with
|
|
3
|
+
* consistent size / weight / colour tokens, optional truncation and line
|
|
4
|
+
* clamping. Themes from the shared `--sg-*` tokens.
|
|
5
|
+
*
|
|
6
|
+
* <SvText size="sm" tone="muted">Last synced 2 minutes ago</SvText>
|
|
7
|
+
* <SvText clamp={2}>A long description that wraps then ellipsises...</SvText>
|
|
8
|
+
*/
|
|
9
|
+
import type { Snippet } from 'svelte';
|
|
10
|
+
type Props = {
|
|
11
|
+
/** Font size step. */
|
|
12
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
13
|
+
/** Font weight. */
|
|
14
|
+
weight?: 'normal' | 'medium' | 'semibold' | 'bold';
|
|
15
|
+
/** Semantic colour. */
|
|
16
|
+
tone?: 'default' | 'muted' | 'accent' | 'success' | 'warning' | 'error';
|
|
17
|
+
/** Text alignment. */
|
|
18
|
+
align?: 'start' | 'center' | 'end';
|
|
19
|
+
/** Truncate to a single line with an ellipsis. */
|
|
20
|
+
truncate?: boolean;
|
|
21
|
+
/** Clamp to N lines with an ellipsis (overrides truncate). */
|
|
22
|
+
clamp?: number;
|
|
23
|
+
/** Render inline (`span`) instead of a block (`p`). */
|
|
24
|
+
inline?: boolean;
|
|
25
|
+
/** Override the element/tag. */
|
|
26
|
+
as?: string;
|
|
27
|
+
children?: Snippet;
|
|
28
|
+
};
|
|
29
|
+
declare const SvText: import("svelte").Component<Props, {}, "">;
|
|
30
|
+
type SvText = ReturnType<typeof SvText>;
|
|
31
|
+
export default SvText;
|
package/dist/SvTextInput.svelte
CHANGED
|
@@ -4,9 +4,14 @@
|
|
|
4
4
|
* (label / hint / error / RTL / a11y via SvField). Handles `text`, `email`,
|
|
5
5
|
* `url`, `tel` and `search`. As a grid cell editor it honours the interaction
|
|
6
6
|
* contract: Enter commits, Escape cancels. Parity: Smart `smart-input`.
|
|
7
|
+
*
|
|
8
|
+
* The control box, size, invalid state, clear button and leading/trailing
|
|
9
|
+
* adornments are all owned by SvField's `frame` mode, so they behave identically
|
|
10
|
+
* across the text-input family.
|
|
7
11
|
*/
|
|
12
|
+
import type { Snippet } from 'svelte'
|
|
8
13
|
import SvField from './SvField.svelte'
|
|
9
|
-
import { editorAria, nextEditorId, type SvEditorProps } from './editor-contract'
|
|
14
|
+
import { editorAria, nextEditorId, type EditorAction, type SvEditorProps } from './editor-contract'
|
|
10
15
|
|
|
11
16
|
type Props = SvEditorProps & {
|
|
12
17
|
value?: string
|
|
@@ -23,6 +28,22 @@
|
|
|
23
28
|
autocomplete?: AutoFill
|
|
24
29
|
/** Autofocus + select on mount (used when mounted as a cell editor). */
|
|
25
30
|
autofocus?: boolean
|
|
31
|
+
/** Select the whole value whenever the field is focused. */
|
|
32
|
+
selectOnFocus?: boolean
|
|
33
|
+
/** Leading adornment (icon/button) inside the field. */
|
|
34
|
+
leading?: Snippet
|
|
35
|
+
/** Trailing adornment (icon/button) inside the field. */
|
|
36
|
+
trailing?: Snippet
|
|
37
|
+
/** Plain-text affix at the start (e.g. a `$` or protocol). */
|
|
38
|
+
prefix?: string
|
|
39
|
+
/** Plain-text affix at the end (e.g. a unit). */
|
|
40
|
+
suffix?: string
|
|
41
|
+
/** `floating` animates the label up on focus/value. Default `static`. */
|
|
42
|
+
labelMode?: 'static' | 'floating'
|
|
43
|
+
/** Compact in-field action buttons (lookup/generate/copy...). */
|
|
44
|
+
actions?: EditorAction[]
|
|
45
|
+
/** Stretch to the container width. */
|
|
46
|
+
block?: boolean
|
|
26
47
|
}
|
|
27
48
|
|
|
28
49
|
let {
|
|
@@ -46,8 +67,17 @@
|
|
|
46
67
|
hint,
|
|
47
68
|
dir,
|
|
48
69
|
id,
|
|
70
|
+
loading = false,
|
|
49
71
|
autocomplete,
|
|
50
72
|
autofocus = false,
|
|
73
|
+
selectOnFocus = false,
|
|
74
|
+
leading,
|
|
75
|
+
trailing,
|
|
76
|
+
prefix,
|
|
77
|
+
suffix,
|
|
78
|
+
labelMode = 'static',
|
|
79
|
+
actions,
|
|
80
|
+
block = false,
|
|
51
81
|
}: Props = $props()
|
|
52
82
|
|
|
53
83
|
const autoId = nextEditorId('sv-text')
|
|
@@ -68,48 +98,50 @@
|
|
|
68
98
|
function mountFocus(node: HTMLInputElement) {
|
|
69
99
|
if (autofocus) { node.focus(); node.select() }
|
|
70
100
|
}
|
|
101
|
+
function onFocus(e: FocusEvent) {
|
|
102
|
+
if (selectOnFocus) (e.currentTarget as HTMLInputElement).select()
|
|
103
|
+
}
|
|
71
104
|
</script>
|
|
72
105
|
|
|
73
|
-
<SvField
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
106
|
+
<SvField
|
|
107
|
+
frame
|
|
108
|
+
id={uid}
|
|
109
|
+
{label}
|
|
110
|
+
{hint}
|
|
111
|
+
{error}
|
|
112
|
+
{required}
|
|
113
|
+
{dir}
|
|
114
|
+
{size}
|
|
115
|
+
{invalid}
|
|
116
|
+
{disabled}
|
|
117
|
+
{readonly}
|
|
118
|
+
{loading}
|
|
119
|
+
{block}
|
|
120
|
+
{leading}
|
|
121
|
+
{trailing}
|
|
122
|
+
{prefix}
|
|
123
|
+
{suffix}
|
|
124
|
+
{labelMode}
|
|
125
|
+
filled={!!value}
|
|
126
|
+
{actions}
|
|
127
|
+
clearable={clearable}
|
|
128
|
+
showClear={!!value}
|
|
129
|
+
onclear={() => set('')}
|
|
130
|
+
>
|
|
131
|
+
<input
|
|
132
|
+
use:mountFocus
|
|
133
|
+
class="sv-text__input"
|
|
134
|
+
{type}
|
|
135
|
+
{value}
|
|
136
|
+
placeholder={labelMode === 'floating' ? undefined : placeholder}
|
|
137
|
+
{disabled}
|
|
138
|
+
{readonly}
|
|
139
|
+
{maxlength}
|
|
140
|
+
{autocomplete}
|
|
141
|
+
oninput={onInput}
|
|
142
|
+
onkeydown={onKeydown}
|
|
143
|
+
onfocus={onFocus}
|
|
144
|
+
{...editorAria({ id: uid, invalid, required, error, hint, ariaLabel })}
|
|
145
|
+
/>
|
|
146
|
+
{#if name}<input type="hidden" {name} value={value} />{/if}
|
|
96
147
|
</SvField>
|
|
97
|
-
|
|
98
|
-
<style>
|
|
99
|
-
.sv-text { --_accent: var(--sg-accent, #2563eb); display: inline-flex; flex-direction: column; width: 220px; }
|
|
100
|
-
.sv-text.is-disabled { opacity: 0.6; }
|
|
101
|
-
.sv-text__field {
|
|
102
|
-
display: flex; align-items: center;
|
|
103
|
-
background: var(--sg-input-bg, #fff); color: var(--sg-fg, #0f172a);
|
|
104
|
-
border: 1px solid var(--sg-input-border, var(--sg-border, #cbd5e1)); border-radius: var(--sg-radius, 8px);
|
|
105
|
-
}
|
|
106
|
-
.sv-text__field:focus-within { border-color: var(--_accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--_accent) 22%, transparent); }
|
|
107
|
-
.sv-text__field.is-invalid { border-color: var(--sg-danger, #dc2626); }
|
|
108
|
-
.sv-text__field.is-invalid:focus-within { box-shadow: 0 0 0 2px color-mix(in srgb, var(--sg-danger, #dc2626) 22%, transparent); }
|
|
109
|
-
.sv-text__input { flex: 1; min-width: 0; border: 0; background: none; outline: none; color: inherit; font: inherit; padding: 0 10px; }
|
|
110
|
-
.sv-text--sm .sv-text__field { height: 28px; font-size: 12px; }
|
|
111
|
-
.sv-text--md .sv-text__field { height: 34px; font-size: 13px; }
|
|
112
|
-
.sv-text--lg .sv-text__field { height: 40px; font-size: 15px; }
|
|
113
|
-
.sv-text__clear { display: grid; place-items: center; width: 28px; align-self: stretch; background: none; border: 0; color: var(--sg-muted, #64748b); cursor: pointer; font-size: 17px; line-height: 1; }
|
|
114
|
-
.sv-text__clear:hover { color: var(--sg-fg, #0f172a); }
|
|
115
|
-
</style>
|
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* SvTextInput - the base single-line text editor on the shared editor contract
|
|
3
|
+
* (label / hint / error / RTL / a11y via SvField). Handles `text`, `email`,
|
|
4
|
+
* `url`, `tel` and `search`. As a grid cell editor it honours the interaction
|
|
5
|
+
* contract: Enter commits, Escape cancels. Parity: Smart `smart-input`.
|
|
6
|
+
*
|
|
7
|
+
* The control box, size, invalid state, clear button and leading/trailing
|
|
8
|
+
* adornments are all owned by SvField's `frame` mode, so they behave identically
|
|
9
|
+
* across the text-input family.
|
|
10
|
+
*/
|
|
11
|
+
import type { Snippet } from 'svelte';
|
|
12
|
+
import { type EditorAction, type SvEditorProps } from './editor-contract';
|
|
2
13
|
type Props = SvEditorProps & {
|
|
3
14
|
value?: string;
|
|
4
15
|
onChange?: (value: string) => void;
|
|
@@ -14,6 +25,22 @@ type Props = SvEditorProps & {
|
|
|
14
25
|
autocomplete?: AutoFill;
|
|
15
26
|
/** Autofocus + select on mount (used when mounted as a cell editor). */
|
|
16
27
|
autofocus?: boolean;
|
|
28
|
+
/** Select the whole value whenever the field is focused. */
|
|
29
|
+
selectOnFocus?: boolean;
|
|
30
|
+
/** Leading adornment (icon/button) inside the field. */
|
|
31
|
+
leading?: Snippet;
|
|
32
|
+
/** Trailing adornment (icon/button) inside the field. */
|
|
33
|
+
trailing?: Snippet;
|
|
34
|
+
/** Plain-text affix at the start (e.g. a `$` or protocol). */
|
|
35
|
+
prefix?: string;
|
|
36
|
+
/** Plain-text affix at the end (e.g. a unit). */
|
|
37
|
+
suffix?: string;
|
|
38
|
+
/** `floating` animates the label up on focus/value. Default `static`. */
|
|
39
|
+
labelMode?: 'static' | 'floating';
|
|
40
|
+
/** Compact in-field action buttons (lookup/generate/copy...). */
|
|
41
|
+
actions?: EditorAction[];
|
|
42
|
+
/** Stretch to the container width. */
|
|
43
|
+
block?: boolean;
|
|
17
44
|
};
|
|
18
45
|
declare const SvTextInput: import("svelte").Component<Props, {}, "value">;
|
|
19
46
|
type SvTextInput = ReturnType<typeof SvTextInput>;
|
package/dist/SvTimePicker.svelte
CHANGED
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
* and ARIA; this component keeps the DOM-bound pointer capture + hit-testing.
|
|
12
12
|
* All visuals come from `--sg-*` tokens so every theme applies for free.
|
|
13
13
|
*/
|
|
14
|
-
import
|
|
14
|
+
import SvField from './SvField.svelte'
|
|
15
|
+
import { nextEditorId, resolveMessages, type EditorDir, type EditorSize } from './editor-contract'
|
|
15
16
|
import { createTimePicker, type TimeValue, type TimeFormat, type TimeSelection } from './createTimePicker.svelte'
|
|
16
17
|
|
|
17
18
|
/** User-facing strings (localizable via `messages`). */
|
|
@@ -38,6 +39,16 @@
|
|
|
38
39
|
dir?: EditorDir
|
|
39
40
|
/** Override the built-in strings (group label + AM/PM/Now). */
|
|
40
41
|
messages?: Partial<TimeMessages>
|
|
42
|
+
// Optional field chrome: when any of label/hint/error is set, the dial is
|
|
43
|
+
// wrapped in <SvField> so it gains a label/hint/error line; otherwise it
|
|
44
|
+
// renders bare (as embedded inside SvDateTimePicker's popover).
|
|
45
|
+
label?: string
|
|
46
|
+
hint?: string
|
|
47
|
+
error?: string
|
|
48
|
+
required?: boolean
|
|
49
|
+
invalid?: boolean
|
|
50
|
+
size?: EditorSize
|
|
51
|
+
id?: string
|
|
41
52
|
}
|
|
42
53
|
|
|
43
54
|
let {
|
|
@@ -53,8 +64,18 @@
|
|
|
53
64
|
selection = 'hour',
|
|
54
65
|
dir,
|
|
55
66
|
messages,
|
|
67
|
+
label,
|
|
68
|
+
hint,
|
|
69
|
+
error,
|
|
70
|
+
required = false,
|
|
71
|
+
invalid = false,
|
|
72
|
+
id,
|
|
56
73
|
}: Props = $props()
|
|
57
74
|
|
|
75
|
+
const autoId = nextEditorId('sv-tp')
|
|
76
|
+
const uid = $derived(id ?? autoId)
|
|
77
|
+
const hasChrome = $derived(!!(label || hint || error))
|
|
78
|
+
|
|
58
79
|
const M = $derived(resolveMessages(DEFAULT_MESSAGES, messages))
|
|
59
80
|
const resolvedDir = $derived(dir === 'ltr' || dir === 'rtl' ? dir : undefined)
|
|
60
81
|
|
|
@@ -107,7 +128,8 @@
|
|
|
107
128
|
}
|
|
108
129
|
</script>
|
|
109
130
|
|
|
110
|
-
|
|
131
|
+
{#snippet dialBody()}
|
|
132
|
+
<div class="sv-tp" class:sv-tp--disabled={disabled} class:sv-tp--invalid={invalid} id={uid} role="group" aria-label={label ?? M.label} dir={resolvedDir}>
|
|
111
133
|
<div class="sv-tp__head">
|
|
112
134
|
<button class="sv-tp__seg" class:is-active={tp.selection === 'hour'} {...tp.segProps('hour')}>
|
|
113
135
|
{String(tp.displayHour).padStart(2, '0')}
|
|
@@ -159,6 +181,13 @@
|
|
|
159
181
|
|
|
160
182
|
{#if name}<input type="hidden" {name} value={`${String(tp.hours).padStart(2, '0')}:${tp.mm}`} />{/if}
|
|
161
183
|
</div>
|
|
184
|
+
{/snippet}
|
|
185
|
+
|
|
186
|
+
{#if hasChrome}
|
|
187
|
+
<SvField id={uid} {label} {hint} {error} {required} {dir}>{@render dialBody()}</SvField>
|
|
188
|
+
{:else}
|
|
189
|
+
{@render dialBody()}
|
|
190
|
+
{/if}
|
|
162
191
|
|
|
163
192
|
<style>
|
|
164
193
|
.sv-tp {
|
|
@@ -175,6 +204,7 @@
|
|
|
175
204
|
border: 1px solid var(--_border); border-radius: calc(var(--_radius) + 4px);
|
|
176
205
|
user-select: none;
|
|
177
206
|
}
|
|
207
|
+
.sv-tp--invalid { border-color: var(--sg-danger, #dc2626); }
|
|
178
208
|
.sv-tp--disabled { opacity: 0.55; pointer-events: none; }
|
|
179
209
|
|
|
180
210
|
.sv-tp__head { display: flex; align-items: center; gap: 2px; font-variant-numeric: tabular-nums; }
|
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
export type { TimeValue } from './createTimePicker.svelte';
|
|
2
|
-
|
|
3
|
-
* SvTimePicker - an analog clock-dial time picker (parity: Smart
|
|
4
|
-
* `smart-time-picker`). 12/24-hour, minute snapping, hour->minute auto-switch,
|
|
5
|
-
* pointer-drag + keyboard. It is a styled renderer over the headless
|
|
6
|
-
* `createTimePicker` core: the core owns the value math, dial geometry, keyboard
|
|
7
|
-
* and ARIA; this component keeps the DOM-bound pointer capture + hit-testing.
|
|
8
|
-
* All visuals come from `--sg-*` tokens so every theme applies for free.
|
|
9
|
-
*/
|
|
10
|
-
import { type EditorDir } from './editor-contract';
|
|
2
|
+
import { type EditorDir, type EditorSize } from './editor-contract';
|
|
11
3
|
import { type TimeValue, type TimeFormat, type TimeSelection } from './createTimePicker.svelte';
|
|
12
4
|
/** User-facing strings (localizable via `messages`). */
|
|
13
5
|
type TimeMessages = {
|
|
@@ -36,6 +28,13 @@ type Props = {
|
|
|
36
28
|
dir?: EditorDir;
|
|
37
29
|
/** Override the built-in strings (group label + AM/PM/Now). */
|
|
38
30
|
messages?: Partial<TimeMessages>;
|
|
31
|
+
label?: string;
|
|
32
|
+
hint?: string;
|
|
33
|
+
error?: string;
|
|
34
|
+
required?: boolean;
|
|
35
|
+
invalid?: boolean;
|
|
36
|
+
size?: EditorSize;
|
|
37
|
+
id?: string;
|
|
39
38
|
};
|
|
40
39
|
declare const SvTimePicker: import("svelte").Component<Props, {}, "">;
|
|
41
40
|
type SvTimePicker = ReturnType<typeof SvTimePicker>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* SvTitle - a heading primitive. `order` sets the semantic level (h1-h6) and,
|
|
4
|
+
* by default, the visual size; pass `size` to decouple the two (e.g. an h2 that
|
|
5
|
+
* looks like an h4). Themes from the shared `--sg-*` tokens.
|
|
6
|
+
*
|
|
7
|
+
* <SvTitle order={1}>Dashboard</SvTitle>
|
|
8
|
+
* <SvTitle order={3} size={5}>Small but semantic h3</SvTitle>
|
|
9
|
+
*/
|
|
10
|
+
import type { Snippet } from 'svelte'
|
|
11
|
+
|
|
12
|
+
type Level = 1 | 2 | 3 | 4 | 5 | 6
|
|
13
|
+
|
|
14
|
+
type Props = {
|
|
15
|
+
/** Semantic heading level (h1-h6). */
|
|
16
|
+
order?: Level
|
|
17
|
+
/** Visual size step, defaults to `order`. */
|
|
18
|
+
size?: Level
|
|
19
|
+
/** Text alignment. */
|
|
20
|
+
align?: 'start' | 'center' | 'end'
|
|
21
|
+
/** Truncate to a single line with an ellipsis. */
|
|
22
|
+
truncate?: boolean
|
|
23
|
+
children?: Snippet
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let { order = 2, size, align, truncate = false, children }: Props = $props()
|
|
27
|
+
|
|
28
|
+
// px + weight per visual step - a compact, balanced type scale.
|
|
29
|
+
const sizeMap = { 1: '30px', 2: '24px', 3: '20px', 4: '17px', 5: '15px', 6: '13px' } as const
|
|
30
|
+
const weightMap = { 1: 700, 2: 700, 3: 600, 4: 600, 5: 600, 6: 600 } as const
|
|
31
|
+
const alignMap = { start: 'left', center: 'center', end: 'right' } as const
|
|
32
|
+
|
|
33
|
+
const step = $derived(size ?? order)
|
|
34
|
+
const tag = $derived(`h${order}`)
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<svelte:element
|
|
38
|
+
this={tag}
|
|
39
|
+
class="sv-title"
|
|
40
|
+
class:is-truncate={truncate}
|
|
41
|
+
style:font-size={sizeMap[step]}
|
|
42
|
+
style:font-weight={weightMap[step]}
|
|
43
|
+
style:text-align={align ? alignMap[align] : undefined}
|
|
44
|
+
>
|
|
45
|
+
{@render children?.()}
|
|
46
|
+
</svelte:element>
|
|
47
|
+
|
|
48
|
+
<style>
|
|
49
|
+
.sv-title {
|
|
50
|
+
margin: 0;
|
|
51
|
+
font-family: var(--sg-font, inherit);
|
|
52
|
+
color: var(--sg-fg, #0f172a);
|
|
53
|
+
line-height: 1.25;
|
|
54
|
+
letter-spacing: -0.01em;
|
|
55
|
+
}
|
|
56
|
+
.sv-title.is-truncate { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
|
|
57
|
+
</style>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SvTitle - a heading primitive. `order` sets the semantic level (h1-h6) and,
|
|
3
|
+
* by default, the visual size; pass `size` to decouple the two (e.g. an h2 that
|
|
4
|
+
* looks like an h4). Themes from the shared `--sg-*` tokens.
|
|
5
|
+
*
|
|
6
|
+
* <SvTitle order={1}>Dashboard</SvTitle>
|
|
7
|
+
* <SvTitle order={3} size={5}>Small but semantic h3</SvTitle>
|
|
8
|
+
*/
|
|
9
|
+
import type { Snippet } from 'svelte';
|
|
10
|
+
type Level = 1 | 2 | 3 | 4 | 5 | 6;
|
|
11
|
+
type Props = {
|
|
12
|
+
/** Semantic heading level (h1-h6). */
|
|
13
|
+
order?: Level;
|
|
14
|
+
/** Visual size step, defaults to `order`. */
|
|
15
|
+
size?: Level;
|
|
16
|
+
/** Text alignment. */
|
|
17
|
+
align?: 'start' | 'center' | 'end';
|
|
18
|
+
/** Truncate to a single line with an ellipsis. */
|
|
19
|
+
truncate?: boolean;
|
|
20
|
+
children?: Snippet;
|
|
21
|
+
};
|
|
22
|
+
declare const SvTitle: import("svelte").Component<Props, {}, "">;
|
|
23
|
+
type SvTitle = ReturnType<typeof SvTitle>;
|
|
24
|
+
export default SvTitle;
|
package/dist/SvToaster.svelte
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* ```
|
|
11
11
|
*/
|
|
12
12
|
import { portalToBody } from './popover'
|
|
13
|
-
import { toastStore, dismissToast, pauseToast, resumeToast, type Toast } from './toast-store.svelte'
|
|
13
|
+
import { toastStore, dismissToast, pauseToast, resumeToast, type Toast, type ToastAction } from './toast-store.svelte'
|
|
14
14
|
|
|
15
15
|
type Position =
|
|
16
16
|
| 'top-left' | 'top-center' | 'top-right'
|
|
@@ -32,6 +32,12 @@
|
|
|
32
32
|
// Swipe-to-dismiss: drag a toast sideways past ~60px to dismiss it.
|
|
33
33
|
let drag = $state<{ id: number; startX: number; dx: number } | null>(null)
|
|
34
34
|
function onDown(e: PointerEvent, id: number) {
|
|
35
|
+
// Only the primary button starts a swipe.
|
|
36
|
+
if (e.button !== 0) return
|
|
37
|
+
// Don't hijack presses on the toast's own controls (dismiss X, action /
|
|
38
|
+
// cancel buttons). Capturing the pointer here would redirect the pointerup
|
|
39
|
+
// to the toast and swallow the button's click.
|
|
40
|
+
if (e.target instanceof Element && e.target.closest('button')) return
|
|
35
41
|
drag = { id, startX: e.clientX, dx: 0 }
|
|
36
42
|
;(e.currentTarget as HTMLElement).setPointerCapture?.(e.pointerId)
|
|
37
43
|
pauseToast(id)
|
|
@@ -47,6 +53,12 @@
|
|
|
47
53
|
else resumeToast(id)
|
|
48
54
|
}
|
|
49
55
|
const dragDx = (id: number) => (drag?.id === id ? drag.dx : 0)
|
|
56
|
+
|
|
57
|
+
// Run a toast action, then dismiss the toast unless it opted to stay open.
|
|
58
|
+
function runAction(a: ToastAction, id: number) {
|
|
59
|
+
a.onClick?.(id)
|
|
60
|
+
if (!a.keepOpen) dismissToast(id)
|
|
61
|
+
}
|
|
50
62
|
</script>
|
|
51
63
|
|
|
52
64
|
<div class="sv-toaster sv-toaster--{position}" use:portalToBody role="region" aria-label="Notifications">
|
|
@@ -67,11 +79,25 @@
|
|
|
67
79
|
onpointerup={() => onUp(t.id)}
|
|
68
80
|
onpointercancel={() => onUp(t.id)}
|
|
69
81
|
>
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
<
|
|
74
|
-
|
|
82
|
+
{#if t.render}
|
|
83
|
+
<div class="sv-toast__content">{@render t.render(t)}</div>
|
|
84
|
+
{:else}
|
|
85
|
+
<span class="sv-toast__icon" aria-hidden="true">{icon(t.variant)}</span>
|
|
86
|
+
<div class="sv-toast__content">
|
|
87
|
+
{#if t.title}<div class="sv-toast__title">{t.title}</div>{/if}
|
|
88
|
+
<div class="sv-toast__msg">{t.message}</div>
|
|
89
|
+
{#if t.action || t.cancel}
|
|
90
|
+
<div class="sv-toast__actions">
|
|
91
|
+
{#if t.cancel}
|
|
92
|
+
<button type="button" class="sv-toast__action sv-toast__action--cancel" onclick={() => runAction(t.cancel!, t.id)}>{t.cancel.label}</button>
|
|
93
|
+
{/if}
|
|
94
|
+
{#if t.action}
|
|
95
|
+
<button type="button" class="sv-toast__action" onclick={() => runAction(t.action!, t.id)}>{t.action.label}</button>
|
|
96
|
+
{/if}
|
|
97
|
+
</div>
|
|
98
|
+
{/if}
|
|
99
|
+
</div>
|
|
100
|
+
{/if}
|
|
75
101
|
{#if t.dismissible}
|
|
76
102
|
<button type="button" class="sv-toast__x" aria-label="Dismiss" onclick={() => dismissToast(t.id)}>×</button>
|
|
77
103
|
{/if}
|
|
@@ -116,6 +142,15 @@
|
|
|
116
142
|
:global(.sv-toast__content) { flex: 1; min-width: 0; }
|
|
117
143
|
:global(.sv-toast__title) { font-weight: 650; margin-bottom: 1px; }
|
|
118
144
|
:global(.sv-toast__msg) { color: var(--sg-fg, #0f172a); overflow-wrap: anywhere; }
|
|
145
|
+
:global(.sv-toast__actions) { display: flex; gap: 8px; margin-top: 9px; }
|
|
146
|
+
:global(.sv-toast__action) {
|
|
147
|
+
font: inherit; font-size: 12.5px; font-weight: 600; padding: 4px 11px; border-radius: 6px;
|
|
148
|
+
border: 1px solid var(--_accent, var(--sg-accent, #2563eb)); background: none; color: var(--_accent, var(--sg-accent, #2563eb));
|
|
149
|
+
cursor: pointer;
|
|
150
|
+
}
|
|
151
|
+
:global(.sv-toast__action:hover) { background: color-mix(in srgb, var(--_accent, #2563eb) 12%, transparent); }
|
|
152
|
+
:global(.sv-toast__action--cancel) { border-color: var(--sg-border, #e2e8f0); color: var(--sg-muted, #64748b); }
|
|
153
|
+
:global(.sv-toast__action--cancel:hover) { background: var(--sg-row-hover-bg, #f1f5f9); color: var(--sg-fg, #0f172a); }
|
|
119
154
|
:global(.sv-toast__x) {
|
|
120
155
|
flex: none; width: 22px; height: 22px; display: grid; place-items: center; margin: -2px -2px 0 0;
|
|
121
156
|
background: none; border: 0; color: var(--sg-muted, #64748b); cursor: pointer; border-radius: 5px; font-size: 17px; line-height: 1;
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
pressed = false,
|
|
19
19
|
onChange,
|
|
20
20
|
disabled = false,
|
|
21
|
+
readonly = false,
|
|
21
22
|
size = 'md',
|
|
22
23
|
ariaLabel,
|
|
23
24
|
invalid = false,
|
|
@@ -36,7 +37,7 @@
|
|
|
36
37
|
// The styled toggle is just a renderer over the headless core.
|
|
37
38
|
const t = createToggle({
|
|
38
39
|
pressed: () => pressed,
|
|
39
|
-
onChange: (v) => onChange?.(v),
|
|
40
|
+
onChange: (v) => { if (readonly) return; onChange?.(v) },
|
|
40
41
|
disabled: () => disabled,
|
|
41
42
|
ariaLabel: () => ariaLabel,
|
|
42
43
|
id: () => uid,
|
|
@@ -52,6 +53,7 @@
|
|
|
52
53
|
class="sv-toggle sv-toggle--{size}"
|
|
53
54
|
class:is-pressed={pressed}
|
|
54
55
|
class:is-invalid={invalid}
|
|
56
|
+
class:is-readonly={readonly}
|
|
55
57
|
{...t.buttonProps()}
|
|
56
58
|
>
|
|
57
59
|
{#if children}{@render children()}{/if}
|
|
@@ -77,6 +79,7 @@
|
|
|
77
79
|
background: var(--_accent); color: var(--sg-on-accent, #fff); border-color: var(--_accent);
|
|
78
80
|
}
|
|
79
81
|
.sv-toggle[disabled] { opacity: 0.55; cursor: not-allowed; }
|
|
82
|
+
.sv-toggle.is-readonly { cursor: default; }
|
|
80
83
|
.sv-toggle.is-invalid { border-color: var(--sg-danger, #dc2626); }
|
|
81
84
|
.sv-toggle:focus-visible { outline: 2px solid var(--sg-focus-ring, var(--_accent)); outline-offset: 2px; }
|
|
82
85
|
</style>
|