@svgrid/grid 2.2.16 → 2.2.17
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
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@ That is a real, accessible grid. Sorting, filtering, virtualization, cell select
|
|
|
75
75
|
- **UI components** - a Svelte 5 component suite ships in the package (inputs, selection, date/time, overlays, layout, feedback) - standalone or as grid cell editors.
|
|
76
76
|
- **Accessibility** - WAI-ARIA grid roles, full keyboard navigation, RTL, high-contrast theme.
|
|
77
77
|
- **Engineered for production** - first-class TypeScript types, CSP / Trusted-Types safe rendering, SSR-friendly, themeable via `--sg-*` CSS tokens.
|
|
78
|
-
- **Lean** - ~
|
|
78
|
+
- **Lean** - ~2 KB gzipped headless core, ~77 KB gzipped full grid (+ ~9 KB CSS); charts, cell editors and export load on demand as their own chunks, and the Kanban board + scheduler are Enterprise views. Svelte stays a peer dependency.
|
|
79
79
|
|
|
80
80
|
## Headless or render-ready
|
|
81
81
|
|
package/dist/GridFooter.svelte
CHANGED
|
@@ -77,6 +77,7 @@
|
|
|
77
77
|
const changePage = $derived(ctrl.changePage);
|
|
78
78
|
const goToPage = $derived(ctrl.goToPage);
|
|
79
79
|
const setPageSize = $derived(ctrl.setPageSize);
|
|
80
|
+
const messages = $derived(ctrl.messages);
|
|
80
81
|
</script>
|
|
81
82
|
|
|
82
83
|
{#if showStatus && statusBarEnabled && statusBarStats}
|
|
@@ -85,7 +86,7 @@
|
|
|
85
86
|
{#each statusBarAggregates as agg (agg)}
|
|
86
87
|
{#if agg === "count"}
|
|
87
88
|
<span class="sv-grid-status-item"
|
|
88
|
-
><span class="sv-grid-status-label">
|
|
89
|
+
><span class="sv-grid-status-label">{messages.statCount}</span>{fmtStat(s.count)}</span
|
|
89
90
|
>
|
|
90
91
|
{:else if agg === "numericCount"}
|
|
91
92
|
<span class="sv-grid-status-item"
|
|
@@ -93,19 +94,19 @@
|
|
|
93
94
|
>
|
|
94
95
|
{:else if s.numericCount > 0 && agg === "sum"}
|
|
95
96
|
<span class="sv-grid-status-item"
|
|
96
|
-
><span class="sv-grid-status-label">
|
|
97
|
+
><span class="sv-grid-status-label">{messages.statSum}</span>{fmtStat(s.sum)}</span
|
|
97
98
|
>
|
|
98
99
|
{:else if s.numericCount > 0 && agg === "avg"}
|
|
99
100
|
<span class="sv-grid-status-item"
|
|
100
|
-
><span class="sv-grid-status-label">
|
|
101
|
+
><span class="sv-grid-status-label">{messages.statAvg}</span>{fmtStat(s.avg)}</span
|
|
101
102
|
>
|
|
102
103
|
{:else if s.numericCount > 0 && agg === "min"}
|
|
103
104
|
<span class="sv-grid-status-item"
|
|
104
|
-
><span class="sv-grid-status-label">
|
|
105
|
+
><span class="sv-grid-status-label">{messages.statMin}</span>{fmtStat(s.min)}</span
|
|
105
106
|
>
|
|
106
107
|
{:else if s.numericCount > 0 && agg === "max"}
|
|
107
108
|
<span class="sv-grid-status-item"
|
|
108
|
-
><span class="sv-grid-status-label">
|
|
109
|
+
><span class="sv-grid-status-label">{messages.statMax}</span>{fmtStat(s.max)}</span
|
|
109
110
|
>
|
|
110
111
|
{/if}
|
|
111
112
|
{/each}
|
|
@@ -125,7 +126,7 @@
|
|
|
125
126
|
{@const sizes = pageSizeOptions && pageSizeOptions.length ? pageSizeOptions : [10, 25, 50, 100]}
|
|
126
127
|
<div class="sv-grid-pagination" class:sv-grid-pagination-top={top} role="navigation" aria-label="Pagination">
|
|
127
128
|
<div class="sv-grid-pagination-pagesize">
|
|
128
|
-
<span>
|
|
129
|
+
<span>{messages.pageSize}</span>
|
|
129
130
|
<div class="sv-grid-pagination-pagesize-dd">
|
|
130
131
|
<SvGridDropdown
|
|
131
132
|
options={sizes.map((n) => ({ value: n, label: String(n) }))}
|
|
@@ -146,17 +147,17 @@
|
|
|
146
147
|
class="sv-grid-pagination-btn"
|
|
147
148
|
disabled={onFirst}
|
|
148
149
|
onclick={() => goToPage(0)}
|
|
149
|
-
aria-label=
|
|
150
|
+
aria-label={messages.firstPage}>⇤</button
|
|
150
151
|
>
|
|
151
152
|
<button
|
|
152
153
|
type="button"
|
|
153
154
|
class="sv-grid-pagination-btn"
|
|
154
155
|
disabled={onFirst}
|
|
155
156
|
onclick={() => changePage(-1)}
|
|
156
|
-
aria-label=
|
|
157
|
+
aria-label={messages.prevPage}>‹</button
|
|
157
158
|
>
|
|
158
159
|
<span class="sv-grid-pagination-label">
|
|
159
|
-
|
|
160
|
+
{messages.page} <strong>{currentPage.toLocaleString()}</strong> {messages.of}
|
|
160
161
|
<strong>{pageCount.toLocaleString()}</strong>
|
|
161
162
|
</span>
|
|
162
163
|
<button
|
|
@@ -164,14 +165,14 @@
|
|
|
164
165
|
class="sv-grid-pagination-btn"
|
|
165
166
|
disabled={onLast}
|
|
166
167
|
onclick={() => changePage(1)}
|
|
167
|
-
aria-label=
|
|
168
|
+
aria-label={messages.nextPage}>›</button
|
|
168
169
|
>
|
|
169
170
|
<button
|
|
170
171
|
type="button"
|
|
171
172
|
class="sv-grid-pagination-btn"
|
|
172
173
|
disabled={onLast}
|
|
173
174
|
onclick={() => goToPage(pageCount - 1)}
|
|
174
|
-
aria-label=
|
|
175
|
+
aria-label={messages.lastPage}>⇥</button
|
|
175
176
|
>
|
|
176
177
|
</div>
|
|
177
178
|
</div>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* SvAnchor - a themed link. Underline on hover by default; `external` adds
|
|
4
|
+
* `target="_blank"` + safe `rel` and an offscreen "opens in new tab" hint.
|
|
5
|
+
*
|
|
6
|
+
* <SvAnchor href="/docs">Read the docs</SvAnchor>
|
|
7
|
+
* <SvAnchor href="https://svelte.dev" external>Svelte</SvAnchor>
|
|
8
|
+
*/
|
|
9
|
+
import type { Snippet } from 'svelte'
|
|
10
|
+
|
|
11
|
+
type Props = {
|
|
12
|
+
href?: string
|
|
13
|
+
/** Open in a new tab with safe `rel`. */
|
|
14
|
+
external?: boolean
|
|
15
|
+
/** Underline behaviour. */
|
|
16
|
+
underline?: 'hover' | 'always' | 'none'
|
|
17
|
+
/** Semantic colour. */
|
|
18
|
+
tone?: 'accent' | 'default' | 'muted'
|
|
19
|
+
/** Font size step. */
|
|
20
|
+
size?: 'sm' | 'md' | 'lg'
|
|
21
|
+
onclick?: (e: MouseEvent) => void
|
|
22
|
+
children?: Snippet
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let { href, external = false, underline = 'hover', tone = 'accent', size = 'md', onclick, children }: Props = $props()
|
|
26
|
+
|
|
27
|
+
const sizeMap = { sm: '13px', md: '14px', lg: '16px' } as const
|
|
28
|
+
const toneMap = {
|
|
29
|
+
accent: 'var(--sg-accent, #2563eb)',
|
|
30
|
+
default: 'var(--sg-fg, #0f172a)',
|
|
31
|
+
muted: 'var(--sg-muted, #64748b)',
|
|
32
|
+
} as const
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<a
|
|
36
|
+
{href}
|
|
37
|
+
{onclick}
|
|
38
|
+
class="sv-anchor sv-anchor--u-{underline}"
|
|
39
|
+
style:font-size={sizeMap[size]}
|
|
40
|
+
style:color={toneMap[tone]}
|
|
41
|
+
target={external ? '_blank' : undefined}
|
|
42
|
+
rel={external ? 'noopener noreferrer' : undefined}
|
|
43
|
+
>
|
|
44
|
+
{@render children?.()}{#if external}<span class="sv-anchor__ext" aria-hidden="true">↗</span><span class="sv-anchor__sr">(opens in a new tab)</span>{/if}
|
|
45
|
+
</a>
|
|
46
|
+
|
|
47
|
+
<style>
|
|
48
|
+
.sv-anchor {
|
|
49
|
+
font-family: var(--sg-font, inherit);
|
|
50
|
+
text-decoration: none;
|
|
51
|
+
border-radius: 2px;
|
|
52
|
+
cursor: pointer;
|
|
53
|
+
}
|
|
54
|
+
.sv-anchor--u-always { text-decoration: underline; text-underline-offset: 2px; }
|
|
55
|
+
.sv-anchor--u-hover:hover { text-decoration: underline; text-underline-offset: 2px; }
|
|
56
|
+
.sv-anchor:focus-visible {
|
|
57
|
+
outline: 2px solid var(--sg-focus-ring, #2563eb);
|
|
58
|
+
outline-offset: 2px;
|
|
59
|
+
}
|
|
60
|
+
.sv-anchor__ext { margin-left: 2px; font-size: 0.85em; }
|
|
61
|
+
.sv-anchor__sr {
|
|
62
|
+
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
|
|
63
|
+
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
|
|
64
|
+
}
|
|
65
|
+
</style>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SvAnchor - a themed link. Underline on hover by default; `external` adds
|
|
3
|
+
* `target="_blank"` + safe `rel` and an offscreen "opens in new tab" hint.
|
|
4
|
+
*
|
|
5
|
+
* <SvAnchor href="/docs">Read the docs</SvAnchor>
|
|
6
|
+
* <SvAnchor href="https://svelte.dev" external>Svelte</SvAnchor>
|
|
7
|
+
*/
|
|
8
|
+
import type { Snippet } from 'svelte';
|
|
9
|
+
type Props = {
|
|
10
|
+
href?: string;
|
|
11
|
+
/** Open in a new tab with safe `rel`. */
|
|
12
|
+
external?: boolean;
|
|
13
|
+
/** Underline behaviour. */
|
|
14
|
+
underline?: 'hover' | 'always' | 'none';
|
|
15
|
+
/** Semantic colour. */
|
|
16
|
+
tone?: 'accent' | 'default' | 'muted';
|
|
17
|
+
/** Font size step. */
|
|
18
|
+
size?: 'sm' | 'md' | 'lg';
|
|
19
|
+
onclick?: (e: MouseEvent) => void;
|
|
20
|
+
children?: Snippet;
|
|
21
|
+
};
|
|
22
|
+
declare const SvAnchor: import("svelte").Component<Props, {}, "">;
|
|
23
|
+
type SvAnchor = ReturnType<typeof SvAnchor>;
|
|
24
|
+
export default SvAnchor;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* SvAspectRatio - hold a fixed width:height ratio for its content (media,
|
|
4
|
+
* embeds, maps, skeletons) so it never causes layout shift. The child fills
|
|
5
|
+
* the box.
|
|
6
|
+
*
|
|
7
|
+
* <SvAspectRatio ratio={16 / 9}><img src={src} alt="" /></SvAspectRatio>
|
|
8
|
+
*/
|
|
9
|
+
import type { Snippet } from 'svelte'
|
|
10
|
+
|
|
11
|
+
type Props = {
|
|
12
|
+
/** Width / height ratio (e.g. `16 / 9`, `1`, `4 / 3`). */
|
|
13
|
+
ratio?: number
|
|
14
|
+
children?: Snippet
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let { ratio = 16 / 9, children }: Props = $props()
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<div class="sv-aspect" style:aspect-ratio={ratio}>
|
|
21
|
+
{@render children?.()}
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<style>
|
|
25
|
+
.sv-aspect {
|
|
26
|
+
position: relative;
|
|
27
|
+
width: 100%;
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
}
|
|
30
|
+
/* Make the single child fill the ratio box by default. */
|
|
31
|
+
.sv-aspect > :global(*) {
|
|
32
|
+
position: absolute;
|
|
33
|
+
inset: 0;
|
|
34
|
+
width: 100%;
|
|
35
|
+
height: 100%;
|
|
36
|
+
object-fit: cover;
|
|
37
|
+
}
|
|
38
|
+
</style>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SvAspectRatio - hold a fixed width:height ratio for its content (media,
|
|
3
|
+
* embeds, maps, skeletons) so it never causes layout shift. The child fills
|
|
4
|
+
* the box.
|
|
5
|
+
*
|
|
6
|
+
* <SvAspectRatio ratio={16 / 9}><img src={src} alt="" /></SvAspectRatio>
|
|
7
|
+
*/
|
|
8
|
+
import type { Snippet } from 'svelte';
|
|
9
|
+
type Props = {
|
|
10
|
+
/** Width / height ratio (e.g. `16 / 9`, `1`, `4 / 3`). */
|
|
11
|
+
ratio?: number;
|
|
12
|
+
children?: Snippet;
|
|
13
|
+
};
|
|
14
|
+
declare const SvAspectRatio: import("svelte").Component<Props, {}, "">;
|
|
15
|
+
type SvAspectRatio = ReturnType<typeof SvAspectRatio>;
|
|
16
|
+
export default SvAspectRatio;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* portal/measure render concerns live here.
|
|
9
9
|
*/
|
|
10
10
|
import { anchoredRect, portalToBody, popIn, type AnchoredRect } from './popover'
|
|
11
|
+
import { startPanelResize } from './panel-resize'
|
|
11
12
|
import { createDismissableLayer } from './a11y/dismissable'
|
|
12
13
|
import { type ListOption } from './list-option'
|
|
13
14
|
import SvField from './SvField.svelte'
|
|
@@ -21,14 +22,18 @@
|
|
|
21
22
|
suggestions?: ReadonlyArray<string | ListOption>
|
|
22
23
|
minChars?: number
|
|
23
24
|
placeholder?: string
|
|
25
|
+
/** Show a bottom drag grip so the user can resize the open suggestion panel's
|
|
26
|
+
* height (hidden when the panel flips upward, where there is no room to grow). */
|
|
27
|
+
resizable?: boolean
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
let {
|
|
27
|
-
value = '',
|
|
31
|
+
value = $bindable(''),
|
|
28
32
|
onChange,
|
|
29
33
|
suggestions = [],
|
|
30
34
|
minChars = 1,
|
|
31
35
|
placeholder,
|
|
36
|
+
resizable = false,
|
|
32
37
|
disabled = false,
|
|
33
38
|
name,
|
|
34
39
|
size = 'md',
|
|
@@ -40,6 +45,7 @@
|
|
|
40
45
|
hint,
|
|
41
46
|
dir,
|
|
42
47
|
id,
|
|
48
|
+
loading = false,
|
|
43
49
|
}: Props = $props()
|
|
44
50
|
|
|
45
51
|
const autoId = nextEditorId('sv-ac')
|
|
@@ -48,10 +54,17 @@
|
|
|
48
54
|
let fieldEl = $state<HTMLInputElement | null>(null)
|
|
49
55
|
let panelEl = $state<HTMLDivElement | null>(null)
|
|
50
56
|
let rect = $state<AnchoredRect>({ top: 0, left: 0, width: 0, openUpward: false, maxHeight: 0, availHeight: 0 })
|
|
57
|
+
// User-chosen panel height (px) once they drag the resize grip; null = auto.
|
|
58
|
+
let userHeight = $state<number | null>(null)
|
|
59
|
+
const DEFAULT_CAP = 288
|
|
60
|
+
const panelMaxH = $derived(
|
|
61
|
+
resizable && userHeight != null ? Math.min(userHeight, rect.availHeight) : Math.min(rect.availHeight, DEFAULT_CAP),
|
|
62
|
+
)
|
|
63
|
+
const showGrip = $derived(resizable && !rect.openUpward)
|
|
51
64
|
|
|
52
65
|
const ac = createAutocomplete({
|
|
53
66
|
value: () => value,
|
|
54
|
-
onChange: (v) => onChange?.(v),
|
|
67
|
+
onChange: (v) => { value = v; onChange?.(v) },
|
|
55
68
|
suggestions: () => suggestions,
|
|
56
69
|
minChars: () => minChars,
|
|
57
70
|
disabled: () => disabled,
|
|
@@ -67,8 +80,20 @@
|
|
|
67
80
|
function updatePos() {
|
|
68
81
|
if (!fieldEl) return
|
|
69
82
|
// estimatedHeight only picks the flip direction; real max-height is availHeight
|
|
70
|
-
// below, so the panel takes its natural content height. See SvComboBox.
|
|
71
|
-
|
|
83
|
+
// below, so the panel takes its natural content height. See SvComboBox. When
|
|
84
|
+
// the user has dragged the grip, anchor the flip decision to THAT height.
|
|
85
|
+
const est = resizable && userHeight != null ? userHeight : Math.min(ac.filtered.length, 8) * 34 + 12
|
|
86
|
+
rect = anchoredRect(fieldEl.getBoundingClientRect(), { estimatedHeight: est })
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function startResize(e: PointerEvent) {
|
|
90
|
+
if (!panelEl) return
|
|
91
|
+
startPanelResize(e, {
|
|
92
|
+
startHeight: panelEl.clientHeight,
|
|
93
|
+
min: 96,
|
|
94
|
+
max: () => rect.availHeight,
|
|
95
|
+
onHeight: (h) => { userHeight = h; updatePos() },
|
|
96
|
+
})
|
|
72
97
|
}
|
|
73
98
|
|
|
74
99
|
$effect(() => {
|
|
@@ -82,7 +107,7 @@
|
|
|
82
107
|
})
|
|
83
108
|
</script>
|
|
84
109
|
|
|
85
|
-
<SvField id={uid} {label} {hint} {error} {required} {dir}>
|
|
110
|
+
<SvField id={uid} {label} {hint} {error} {required} {dir} {loading}>
|
|
86
111
|
<input
|
|
87
112
|
bind:this={fieldEl}
|
|
88
113
|
class="sv-ac sv-ac--{size}"
|
|
@@ -94,11 +119,17 @@
|
|
|
94
119
|
</SvField>
|
|
95
120
|
|
|
96
121
|
{#if ac.open}
|
|
97
|
-
<div bind:this={panelEl} class="sv-ddl__panel" use:portalToBody use:popIn={{ up: rect.openUpward }} style:position="fixed" style:top={rect.openUpward ? undefined : `${rect.top}px`} style:bottom={rect.openUpward ? `${rect.bottom}px` : undefined} style:left={`${rect.left}px`} style:min-width={`${rect.width}px`} style:max-height={`${
|
|
98
|
-
{#each ac.filtered as opt, i (
|
|
122
|
+
<div bind:this={panelEl} class="sv-ddl__panel" class:is-resizable={showGrip} use:portalToBody use:popIn={{ up: rect.openUpward }} style:position="fixed" style:top={rect.openUpward ? undefined : `${rect.top}px`} style:bottom={rect.openUpward ? `${rect.bottom}px` : undefined} style:left={`${rect.left}px`} style:min-width={`${rect.width}px`} style:max-height={`${panelMaxH}px`} style:height={resizable && userHeight != null && !rect.openUpward ? `${panelMaxH}px` : undefined} {...ac.listboxProps()}>
|
|
123
|
+
{#each ac.filtered as opt, i (i)}
|
|
99
124
|
<!-- svelte-ignore a11y_click_events_have_key_events a11y_interactive_supports_focus -->
|
|
100
125
|
<div class="sv-ddl__opt" class:is-active={ac.isActive(i)} {...ac.optionProps(i)}>{opt.label}</div>
|
|
101
126
|
{/each}
|
|
127
|
+
{#if showGrip}
|
|
128
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
129
|
+
<div class="sv-ddl__grip" onpointerdown={startResize} title="Drag to resize" aria-hidden="true">
|
|
130
|
+
<span class="sv-ddl__grip-dots"></span>
|
|
131
|
+
</div>
|
|
132
|
+
{/if}
|
|
102
133
|
</div>
|
|
103
134
|
{/if}
|
|
104
135
|
{#if name}<input type="hidden" {name} value={value} />{/if}
|
|
@@ -117,4 +148,18 @@
|
|
|
117
148
|
.sv-ac:focus { border-color: var(--_accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--_accent) 22%, transparent); }
|
|
118
149
|
.sv-ac.is-invalid { border-color: var(--sg-danger, #dc2626); }
|
|
119
150
|
.sv-ac.is-invalid:focus { box-shadow: 0 0 0 2px color-mix(in srgb, var(--sg-danger, #dc2626) 22%, transparent); }
|
|
151
|
+
/* Bottom resize grip (shared "····" handle - see SvDropDownList / panel-resize). */
|
|
152
|
+
:global(.sv-ddl__panel.is-resizable) { padding-bottom: 0; }
|
|
153
|
+
:global(.sv-ddl__grip) {
|
|
154
|
+
position: sticky; bottom: 0; z-index: 1; margin: 2px -4px -4px; height: 15px;
|
|
155
|
+
display: flex; align-items: center; justify-content: center; cursor: ns-resize;
|
|
156
|
+
background: var(--sg-bg, #fff); border-top: 1px solid var(--sg-border, #e2e8f0);
|
|
157
|
+
border-radius: 0 0 10px 10px; touch-action: none;
|
|
158
|
+
}
|
|
159
|
+
:global(.sv-ddl__grip-dots) {
|
|
160
|
+
width: 26px; height: 4px; color: var(--sg-muted, #94a3b8); opacity: 0.6;
|
|
161
|
+
background-image: radial-gradient(currentColor 1px, transparent 1.6px);
|
|
162
|
+
background-size: 6px 4px; background-position: center; background-repeat: repeat-x;
|
|
163
|
+
}
|
|
164
|
+
:global(.sv-ddl__grip:hover .sv-ddl__grip-dots) { opacity: 1; }
|
|
120
165
|
</style>
|
|
@@ -7,7 +7,10 @@ type Props = SvEditorProps & {
|
|
|
7
7
|
suggestions?: ReadonlyArray<string | ListOption>;
|
|
8
8
|
minChars?: number;
|
|
9
9
|
placeholder?: string;
|
|
10
|
+
/** Show a bottom drag grip so the user can resize the open suggestion panel's
|
|
11
|
+
* height (hidden when the panel flips upward, where there is no room to grow). */
|
|
12
|
+
resizable?: boolean;
|
|
10
13
|
};
|
|
11
|
-
declare const SvAutoComplete: import("svelte").Component<Props, {}, "">;
|
|
14
|
+
declare const SvAutoComplete: import("svelte").Component<Props, {}, "value">;
|
|
12
15
|
type SvAutoComplete = ReturnType<typeof SvAutoComplete>;
|
|
13
16
|
export default SvAutoComplete;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* SvBlockquote - a quotation block with an accent rule and an optional citation.
|
|
4
|
+
*
|
|
5
|
+
* <SvBlockquote cite="Ada Lovelace">The Analytical Engine weaves algebraic patterns.</SvBlockquote>
|
|
6
|
+
*/
|
|
7
|
+
import type { Snippet } from 'svelte'
|
|
8
|
+
|
|
9
|
+
type Props = {
|
|
10
|
+
/** Attribution shown under the quote. */
|
|
11
|
+
cite?: string
|
|
12
|
+
/** Accent colour of the rule. */
|
|
13
|
+
tone?: 'accent' | 'muted' | 'success' | 'warning' | 'error'
|
|
14
|
+
children?: Snippet
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let { cite, tone = 'accent', children }: Props = $props()
|
|
18
|
+
|
|
19
|
+
const toneMap = {
|
|
20
|
+
accent: 'var(--sg-accent, #2563eb)',
|
|
21
|
+
muted: 'var(--sg-muted, #64748b)',
|
|
22
|
+
success: 'var(--sg-success, #16a34a)',
|
|
23
|
+
warning: 'var(--sg-warning, #d97706)',
|
|
24
|
+
error: 'var(--sg-danger, #dc2626)',
|
|
25
|
+
} as const
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<blockquote class="sv-blockquote" style:--sv-bq-rule={toneMap[tone]}>
|
|
29
|
+
<div class="sv-blockquote__body">{@render children?.()}</div>
|
|
30
|
+
{#if cite}<footer class="sv-blockquote__cite">- {cite}</footer>{/if}
|
|
31
|
+
</blockquote>
|
|
32
|
+
|
|
33
|
+
<style>
|
|
34
|
+
.sv-blockquote {
|
|
35
|
+
margin: 0;
|
|
36
|
+
padding: 4px 0 4px 16px;
|
|
37
|
+
border-left: 3px solid var(--sv-bq-rule, #2563eb);
|
|
38
|
+
font-family: var(--sg-font, inherit);
|
|
39
|
+
color: var(--sg-fg, #0f172a);
|
|
40
|
+
}
|
|
41
|
+
.sv-blockquote__body { font-size: 15px; line-height: 1.55; }
|
|
42
|
+
.sv-blockquote__cite { margin-top: 8px; font-size: 13px; color: var(--sg-muted, #64748b); }
|
|
43
|
+
</style>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SvBlockquote - a quotation block with an accent rule and an optional citation.
|
|
3
|
+
*
|
|
4
|
+
* <SvBlockquote cite="Ada Lovelace">The Analytical Engine weaves algebraic patterns.</SvBlockquote>
|
|
5
|
+
*/
|
|
6
|
+
import type { Snippet } from 'svelte';
|
|
7
|
+
type Props = {
|
|
8
|
+
/** Attribution shown under the quote. */
|
|
9
|
+
cite?: string;
|
|
10
|
+
/** Accent colour of the rule. */
|
|
11
|
+
tone?: 'accent' | 'muted' | 'success' | 'warning' | 'error';
|
|
12
|
+
children?: Snippet;
|
|
13
|
+
};
|
|
14
|
+
declare const SvBlockquote: import("svelte").Component<Props, {}, "">;
|
|
15
|
+
type SvBlockquote = ReturnType<typeof SvBlockquote>;
|
|
16
|
+
export default SvBlockquote;
|
package/dist/SvCalendar.svelte
CHANGED
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
* important dates, week numbers, firstDayOfWeek, drill navigation, keyboard).
|
|
18
18
|
*/
|
|
19
19
|
import { untrack, type Snippet } from 'svelte'
|
|
20
|
-
import
|
|
20
|
+
import SvField from './SvField.svelte'
|
|
21
|
+
import { nextEditorId, resolveMessages, type EditorDir, type EditorSize } from './editor-contract'
|
|
21
22
|
import {
|
|
22
23
|
createCalendar,
|
|
23
24
|
type CalendarValue,
|
|
@@ -91,6 +92,16 @@
|
|
|
91
92
|
* the date + its day-state. Switches the month grid to a taller,
|
|
92
93
|
* top-aligned layout so there's room for the content. */
|
|
93
94
|
day?: Snippet<[Date, CalendarDayState]>
|
|
95
|
+
// Optional field chrome: when any of label/hint/error is set, the calendar is
|
|
96
|
+
// wrapped in <SvField> so it gains a label/hint/error line; otherwise it
|
|
97
|
+
// renders bare (as embedded inside SvDateTimePicker's popover).
|
|
98
|
+
label?: string
|
|
99
|
+
hint?: string
|
|
100
|
+
error?: string
|
|
101
|
+
required?: boolean
|
|
102
|
+
invalid?: boolean
|
|
103
|
+
size?: EditorSize
|
|
104
|
+
id?: string
|
|
94
105
|
}
|
|
95
106
|
|
|
96
107
|
let {
|
|
@@ -124,8 +135,17 @@
|
|
|
124
135
|
messages,
|
|
125
136
|
recurrence = null,
|
|
126
137
|
day,
|
|
138
|
+
label,
|
|
139
|
+
hint,
|
|
140
|
+
error,
|
|
141
|
+
required = false,
|
|
142
|
+
invalid = false,
|
|
143
|
+
id,
|
|
127
144
|
}: Props = $props()
|
|
128
145
|
|
|
146
|
+
const calAutoId = nextEditorId('sv-cal')
|
|
147
|
+
const uid = $derived(id ?? calAutoId)
|
|
148
|
+
const hasChrome = $derived(!!(label || hint || error))
|
|
129
149
|
const M = $derived(resolveMessages(DEFAULT_MESSAGES, messages))
|
|
130
150
|
const resolvedDir = $derived(dir === 'ltr' || dir === 'rtl' ? dir : undefined)
|
|
131
151
|
// With several month panels side by side, leading/trailing days of adjacent
|
|
@@ -206,14 +226,17 @@
|
|
|
206
226
|
}
|
|
207
227
|
</script>
|
|
208
228
|
|
|
229
|
+
{#snippet calBody()}
|
|
209
230
|
<div
|
|
210
231
|
class="sv-cal"
|
|
211
232
|
class:sv-cal--disabled={disabled}
|
|
233
|
+
class:sv-cal--invalid={invalid}
|
|
212
234
|
class:sv-cal--with-presets={presets && presets.length}
|
|
213
235
|
class:sv-cal--band={selectionMode === 'range' || selectionMode === 'week'}
|
|
214
236
|
class:sv-cal--rich={!!day}
|
|
237
|
+
id={uid}
|
|
215
238
|
role="group"
|
|
216
|
-
aria-label={M.label}
|
|
239
|
+
aria-label={label ?? M.label}
|
|
217
240
|
aria-disabled={disabled}
|
|
218
241
|
dir={resolvedDir}
|
|
219
242
|
>
|
|
@@ -314,6 +337,13 @@
|
|
|
314
337
|
|
|
315
338
|
{#if name}<input type="hidden" {name} value={cal.selectedDates.map((d) => d.toISOString()).join(',')} />{/if}
|
|
316
339
|
</div>
|
|
340
|
+
{/snippet}
|
|
341
|
+
|
|
342
|
+
{#if hasChrome}
|
|
343
|
+
<SvField id={uid} {label} {hint} {error} {required} {dir}>{@render calBody()}</SvField>
|
|
344
|
+
{:else}
|
|
345
|
+
{@render calBody()}
|
|
346
|
+
{/if}
|
|
317
347
|
|
|
318
348
|
<style>
|
|
319
349
|
.sv-cal {
|
|
@@ -336,6 +366,7 @@
|
|
|
336
366
|
user-select: none;
|
|
337
367
|
}
|
|
338
368
|
.sv-cal--disabled { opacity: 0.55; pointer-events: none; }
|
|
369
|
+
.sv-cal--invalid { border-color: var(--sg-danger, #dc2626); }
|
|
339
370
|
.sv-cal__main { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
|
|
340
371
|
/* Clip so animated content slides in from the edge (not past the border). Day
|
|
341
372
|
focus outlines use outline-offset:-2px, so they stay inside and aren't clipped. */
|
|
@@ -11,7 +11,7 @@ export type { CalendarValue, CalendarPreset, CalendarAnimation, DisplayMode } fr
|
|
|
11
11
|
* important dates, week numbers, firstDayOfWeek, drill navigation, keyboard).
|
|
12
12
|
*/
|
|
13
13
|
import { type Snippet } from 'svelte';
|
|
14
|
-
import { type EditorDir } from './editor-contract';
|
|
14
|
+
import { type EditorDir, type EditorSize } from './editor-contract';
|
|
15
15
|
import { type CalendarValue, type CalendarPreset, type CalendarAnimation, type CalendarDayState, type DisplayMode } from './createCalendar.svelte';
|
|
16
16
|
import type { SelectionMode } from './datetime/date-selection';
|
|
17
17
|
import type { RestrictOptions } from './datetime/date-restrict';
|
|
@@ -79,6 +79,13 @@ type Props = {
|
|
|
79
79
|
* the date + its day-state. Switches the month grid to a taller,
|
|
80
80
|
* top-aligned layout so there's room for the content. */
|
|
81
81
|
day?: Snippet<[Date, CalendarDayState]>;
|
|
82
|
+
label?: string;
|
|
83
|
+
hint?: string;
|
|
84
|
+
error?: string;
|
|
85
|
+
required?: boolean;
|
|
86
|
+
invalid?: boolean;
|
|
87
|
+
size?: EditorSize;
|
|
88
|
+
id?: string;
|
|
82
89
|
};
|
|
83
90
|
declare const SvCalendar: import("svelte").Component<Props, {}, "">;
|
|
84
91
|
type SvCalendar = ReturnType<typeof SvCalendar>;
|
package/dist/SvCheckBox.svelte
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
indeterminate = false,
|
|
22
22
|
onChange,
|
|
23
23
|
disabled = false,
|
|
24
|
+
readonly = false,
|
|
24
25
|
size = 'md',
|
|
25
26
|
name,
|
|
26
27
|
value,
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
const cb = createCheckbox({
|
|
43
44
|
checked: () => checked,
|
|
44
45
|
indeterminate: () => indeterminate,
|
|
45
|
-
onChange: (v) => onChange?.(v),
|
|
46
|
+
onChange: (v) => { if (readonly) return; onChange?.(v) },
|
|
46
47
|
disabled: () => disabled,
|
|
47
48
|
ariaLabel: () => ariaLabel ?? (children ? undefined : 'checkbox'),
|
|
48
49
|
id: () => uid,
|
|
@@ -54,12 +55,14 @@
|
|
|
54
55
|
</script>
|
|
55
56
|
|
|
56
57
|
<SvField id={uid} {hint} {error} {required} {dir}>
|
|
57
|
-
<label class="sv-check sv-check--{size}" class:is-disabled={disabled} class:is-invalid={invalid}>
|
|
58
|
+
<label class="sv-check sv-check--{size}" class:is-disabled={disabled} class:is-readonly={readonly} class:is-invalid={invalid}>
|
|
58
59
|
<button
|
|
60
|
+
role="checkbox"
|
|
59
61
|
class="sv-check__box"
|
|
60
62
|
class:is-checked={checked && !indeterminate}
|
|
61
63
|
class:is-indeterminate={indeterminate}
|
|
62
64
|
{...cb.boxProps()}
|
|
65
|
+
aria-readonly={readonly ? 'true' : undefined}
|
|
63
66
|
>
|
|
64
67
|
{#if indeterminate}
|
|
65
68
|
<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M4 8h8" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" /></svg>
|
|
@@ -82,6 +85,7 @@
|
|
|
82
85
|
.sv-check--sm { --_sz: 15px; font-size: 12px; }
|
|
83
86
|
.sv-check--lg { --_sz: 22px; font-size: 15px; }
|
|
84
87
|
.sv-check.is-disabled { opacity: 0.55; cursor: not-allowed; }
|
|
88
|
+
.sv-check.is-readonly { cursor: default; }
|
|
85
89
|
.sv-check__box {
|
|
86
90
|
width: var(--_sz); height: var(--_sz); flex: none; padding: 0; cursor: inherit;
|
|
87
91
|
display: grid; place-items: center;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* SvCode - monospace code. Inline by default; set `block` for a padded,
|
|
4
|
+
* horizontally-scrolling code block. Pass `code` as a string or use the
|
|
5
|
+
* `children` snippet. No syntax highlighting (bring your own).
|
|
6
|
+
*
|
|
7
|
+
* <SvCode>npm i @svgrid/grid</SvCode>
|
|
8
|
+
* <SvCode block code={snippet} />
|
|
9
|
+
*/
|
|
10
|
+
import type { Snippet } from 'svelte'
|
|
11
|
+
|
|
12
|
+
type Props = {
|
|
13
|
+
/** Render as a padded block instead of inline. */
|
|
14
|
+
block?: boolean
|
|
15
|
+
/** Code as a string (skip the snippet). */
|
|
16
|
+
code?: string
|
|
17
|
+
children?: Snippet
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let { block = false, code, children }: Props = $props()
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
{#if block}
|
|
24
|
+
<pre class="sv-code sv-code--block"><code>{#if code != null}{code}{:else}{@render children?.()}{/if}</code></pre>
|
|
25
|
+
{:else}
|
|
26
|
+
<code class="sv-code sv-code--inline">{#if code != null}{code}{:else}{@render children?.()}{/if}</code>
|
|
27
|
+
{/if}
|
|
28
|
+
|
|
29
|
+
<style>
|
|
30
|
+
.sv-code {
|
|
31
|
+
font-family: var(--sg-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
32
|
+
font-size: 0.9em;
|
|
33
|
+
color: var(--sg-fg, #0f172a);
|
|
34
|
+
}
|
|
35
|
+
.sv-code--inline {
|
|
36
|
+
padding: 1px 5px;
|
|
37
|
+
background: var(--sg-muted-bg, color-mix(in srgb, var(--sg-fg, #0f172a) 7%, var(--sg-bg, #fff)));
|
|
38
|
+
border: 1px solid var(--sg-border, #e2e8f0);
|
|
39
|
+
border-radius: 4px;
|
|
40
|
+
white-space: nowrap;
|
|
41
|
+
}
|
|
42
|
+
.sv-code--block {
|
|
43
|
+
margin: 0;
|
|
44
|
+
padding: 12px 14px;
|
|
45
|
+
background: var(--sg-muted-bg, color-mix(in srgb, var(--sg-fg, #0f172a) 7%, var(--sg-bg, #fff)));
|
|
46
|
+
border: 1px solid var(--sg-border, #e2e8f0);
|
|
47
|
+
border-radius: 8px;
|
|
48
|
+
overflow-x: auto;
|
|
49
|
+
line-height: 1.55;
|
|
50
|
+
}
|
|
51
|
+
.sv-code--block code { font-size: 13px; white-space: pre; }
|
|
52
|
+
</style>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SvCode - monospace code. Inline by default; set `block` for a padded,
|
|
3
|
+
* horizontally-scrolling code block. Pass `code` as a string or use the
|
|
4
|
+
* `children` snippet. No syntax highlighting (bring your own).
|
|
5
|
+
*
|
|
6
|
+
* <SvCode>npm i @svgrid/grid</SvCode>
|
|
7
|
+
* <SvCode block code={snippet} />
|
|
8
|
+
*/
|
|
9
|
+
import type { Snippet } from 'svelte';
|
|
10
|
+
type Props = {
|
|
11
|
+
/** Render as a padded block instead of inline. */
|
|
12
|
+
block?: boolean;
|
|
13
|
+
/** Code as a string (skip the snippet). */
|
|
14
|
+
code?: string;
|
|
15
|
+
children?: Snippet;
|
|
16
|
+
};
|
|
17
|
+
declare const SvCode: import("svelte").Component<Props, {}, "">;
|
|
18
|
+
type SvCode = ReturnType<typeof SvCode>;
|
|
19
|
+
export default SvCode;
|