@svgrid/grid 3.0.0 → 3.0.1
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/CHANGELOG.md +116 -88
- package/README.md +199 -199
- package/dist/FlexRender.svelte +96 -96
- package/dist/GridFooter.svelte +181 -181
- package/dist/SvAutoComplete.svelte +169 -169
- package/dist/SvAvatar.svelte +75 -75
- package/dist/SvCalendar.svelte +503 -503
- package/dist/SvCarousel.svelte +141 -141
- package/dist/SvCheckBox.svelte +102 -102
- package/dist/SvCircularProgress.svelte +109 -109
- package/dist/SvColorInput.svelte +181 -181
- package/dist/SvComboBox.svelte +279 -279
- package/dist/SvContextMenu.svelte +116 -116
- package/dist/SvCountryInput.svelte +163 -163
- package/dist/SvDrawer.svelte +254 -254
- package/dist/SvDropDownList.svelte +378 -378
- package/dist/SvDurationInput.svelte +126 -126
- package/dist/SvField.svelte +293 -293
- package/dist/SvForm.svelte +437 -437
- package/dist/SvGridCellEditor.svelte +748 -744
- package/dist/SvGridChart.svelte +1716 -1716
- package/dist/SvGridChartPanel.svelte +485 -485
- package/dist/SvGridChartView.svelte +70 -70
- package/dist/SvGridDropdown.svelte +728 -728
- package/dist/SvGridSelect.svelte +270 -270
- package/dist/SvGroupCell.svelte +116 -116
- package/dist/SvListBox.svelte +334 -334
- package/dist/SvMaskedInput.svelte +122 -122
- package/dist/SvMenu.svelte +124 -124
- package/dist/SvMenuList.svelte +146 -146
- package/dist/SvMultiSelect.svelte +293 -293
- package/dist/SvNumberInput.svelte +172 -172
- package/dist/SvOtpInput.svelte +158 -158
- package/dist/SvPasswordInput.svelte +151 -151
- package/dist/SvPhoneInput.svelte +133 -133
- package/dist/SvPopover.svelte +197 -197
- package/dist/SvProgress.svelte +116 -116
- package/dist/SvRadioGroup.svelte +107 -107
- package/dist/SvRating.svelte +112 -112
- package/dist/SvResult.svelte +73 -73
- package/dist/SvRichText.svelte +211 -211
- package/dist/SvRowGroupPanel.svelte +170 -170
- package/dist/SvScrollArea.svelte +61 -61
- package/dist/SvSlider.svelte +203 -203
- package/dist/SvSwitchButton.svelte +108 -108
- package/dist/SvTagsInput.svelte +115 -115
- package/dist/SvTextInput.svelte +147 -147
- package/dist/SvTimePicker.svelte +245 -245
- package/dist/SvToaster.svelte +159 -159
- package/dist/SvToggleButton.svelte +85 -85
- package/dist/SvTooltip.svelte +161 -161
- package/dist/SvTour.svelte +208 -208
- package/dist/SvTree.svelte +444 -444
- package/dist/SvTreeSelect.svelte +239 -239
- package/dist/cdn/{GridMenus-DMihUtma.js → GridMenus-CYzOvmNQ.js} +3 -3
- package/dist/cdn/{GridMenus-nmNDj1a3.js → GridMenus-DFB6iwF8.js} +3 -3
- package/dist/cdn/{SvDateRangeInput-DflbiP7N.js → SvDateRangeInput-CaOuMs8O.js} +1 -1
- package/dist/cdn/{SvDateRangeInput-Bh0A0JkF.js → SvDateRangeInput-DMLKmGEc.js} +1 -1
- package/dist/cdn/{SvDateTimePicker-Bivn8dAP.js → SvDateTimePicker-CCbDZNZB.js} +1 -1
- package/dist/cdn/{SvDateTimePicker-BWwpfB_o.js → SvDateTimePicker-sonaH0oh.js} +1 -1
- package/dist/cdn/{SvGridCellEditor-Ba7rY3eu.js → SvGridCellEditor-BWnTi2N7.js} +2 -2
- package/dist/cdn/{SvGridCellEditor-AXL8cHGO.js → SvGridCellEditor-CjEJMJKc.js} +2 -2
- package/dist/cdn/{SvGridChart-CwhFz7GV.js → SvGridChart-BEJmNNx9.js} +1 -1
- package/dist/cdn/{SvGridChart-Bs2GIR2Q.js → SvGridChart-BwVos976.js} +1 -1
- package/dist/cdn/{SvGridChartPanel-1WXuStzM.js → SvGridChartPanel-BOknOkrP.js} +1 -1
- package/dist/cdn/{SvGridChartPanel-e5_nqNP9.js → SvGridChartPanel-D2PjII4O.js} +1 -1
- package/dist/cdn/{SvGridChartView-SmPW10dI.js → SvGridChartView-00LPUHL1.js} +1 -1
- package/dist/cdn/{SvGridChartView-eSPuJE6g.js → SvGridChartView-BhUEJ5ki.js} +1 -1
- package/dist/cdn/{SvGridDropdown-B1ZcLpgs.js → SvGridDropdown-D0VdjeR8.js} +1 -1
- package/dist/cdn/{SvGridDropdown-CtdbHcIS.js → SvGridDropdown-D13MtJ2j.js} +1 -1
- package/dist/cdn/{date-format-DZT7T1wf.js → date-format-BNii4zeD.js} +2 -2
- package/dist/cdn/{date-format-CcP1tafP.js → date-format-BnnHlqGw.js} +2 -2
- package/dist/cdn/{src-B_YS5AOc.js → src-C8QjSaq-.js} +42 -44
- package/dist/cdn/{src-DYXXpuSk.js → src-D0hO2eYN.js} +41 -43
- package/dist/cdn/svgrid.js +7 -7
- package/dist/cdn/svgrid.svelte-external.js +7 -7
- package/dist/chart-export.js +8 -8
- package/dist/editing.js +22 -13
- package/package.json +11 -11
- package/src/FlexRender.svelte +96 -96
- package/src/GridFooter.svelte +181 -181
- package/src/SvAutoComplete.svelte +169 -169
- package/src/SvAvatar.svelte +75 -75
- package/src/SvCalendar.svelte +503 -503
- package/src/SvCalendar.test.ts +226 -226
- package/src/SvCarousel.svelte +141 -141
- package/src/SvCheckBox.svelte +102 -102
- package/src/SvCircularProgress.svelte +109 -109
- package/src/SvColorInput.svelte +181 -181
- package/src/SvComboBox.svelte +279 -279
- package/src/SvContextMenu.svelte +116 -116
- package/src/SvCountryInput.svelte +163 -163
- package/src/SvDrawer.svelte +254 -254
- package/src/SvDropDownList.svelte +378 -378
- package/src/SvDurationInput.svelte +126 -126
- package/src/SvField.svelte +293 -293
- package/src/SvForm.svelte +437 -437
- package/src/SvForm.test.ts +411 -411
- package/src/SvGrid.types.ts +2092 -2092
- package/src/SvGridCellEditor.svelte +748 -744
- package/src/SvGridChart.svelte +1716 -1716
- package/src/SvGridChartPanel.svelte +485 -485
- package/src/SvGridChartView.svelte +70 -70
- package/src/SvGridDropdown.svelte +728 -728
- package/src/SvGridSelect.svelte +270 -270
- package/src/SvGroupCell.svelte +116 -116
- package/src/SvListBox.svelte +334 -334
- package/src/SvMaskedInput.svelte +122 -122
- package/src/SvMenu.svelte +124 -124
- package/src/SvMenu.test.ts +97 -97
- package/src/SvMenuList.svelte +146 -146
- package/src/SvMultiSelect.svelte +293 -293
- package/src/SvNumberInput.svelte +172 -172
- package/src/SvOtpInput.svelte +158 -158
- package/src/SvPasswordInput.svelte +151 -151
- package/src/SvPhoneInput.svelte +133 -133
- package/src/SvPopover.svelte +197 -197
- package/src/SvProgress.svelte +116 -116
- package/src/SvRadioGroup.svelte +107 -107
- package/src/SvRating.svelte +112 -112
- package/src/SvResult.svelte +73 -73
- package/src/SvRichText.svelte +211 -211
- package/src/SvRowGroupPanel.svelte +170 -170
- package/src/SvScrollArea.svelte +61 -61
- package/src/SvSlider.svelte +203 -203
- package/src/SvSwitchButton.svelte +108 -108
- package/src/SvTagsInput.svelte +115 -115
- package/src/SvTextInput.svelte +147 -147
- package/src/SvTimePicker.svelte +245 -245
- package/src/SvToaster.svelte +159 -159
- package/src/SvToaster.test.ts +95 -95
- package/src/SvToggleButton.svelte +85 -85
- package/src/SvTooltip.svelte +161 -161
- package/src/SvTour.svelte +208 -208
- package/src/SvTree.svelte +444 -444
- package/src/SvTreeSelect.svelte +239 -239
- package/src/a11y/dismissable.test.ts +119 -119
- package/src/a11y/dismissable.ts +114 -114
- package/src/a11y.contract.test.ts +49 -49
- package/src/a11y.test.ts +59 -59
- package/src/a11y.ts +61 -61
- package/src/ai.test.ts +502 -502
- package/src/ai.ts +1419 -1419
- package/src/build-api.coverage.test.ts +633 -633
- package/src/build-api.ts +846 -846
- package/src/builtin-editors.grid.test.ts +83 -83
- package/src/cell-formatting.ts +171 -171
- package/src/cell-render.test.ts +513 -513
- package/src/cell-render.ts +496 -496
- package/src/cell-values.ts +148 -148
- package/src/chart-export.ts +202 -202
- package/src/chart-view.svelte.ts +36 -36
- package/src/chart.ts +2321 -2321
- package/src/collaboration.test.ts +104 -104
- package/src/collaboration.ts +167 -167
- package/src/column-groups.ts +78 -78
- package/src/core.performance.test.ts +30 -30
- package/src/core.ts +1865 -1865
- package/src/createAutocomplete.svelte.ts +132 -132
- package/src/createCombobox.svelte.ts +191 -191
- package/src/createCountryInput.svelte.ts +157 -157
- package/src/createDropdownList.svelte.ts +168 -168
- package/src/createForm.svelte.ts +386 -386
- package/src/createGrid.svelte.ts +42 -42
- package/src/createGrid.test.ts +10 -10
- package/src/createGridState.svelte.ts +17 -17
- package/src/createListbox.svelte.ts +250 -250
- package/src/createMenu.svelte.ts +224 -224
- package/src/createPopoverSelect.svelte.ts +213 -213
- package/src/createSlider.svelte.ts +191 -191
- package/src/createTooltip.svelte.ts +144 -144
- package/src/createTree.svelte.ts +322 -322
- package/src/datetime/date-core.ts +206 -206
- package/src/datetime/date-restrict.ts +61 -61
- package/src/datetime/timezone.ts +135 -135
- package/src/dock-manager-model.ts +596 -596
- package/src/dock-model.ts +374 -374
- package/src/editing.test.ts +974 -974
- package/src/editing.ts +618 -609
- package/src/editor-contract.ts +171 -171
- package/src/editor-registry.grid.test.ts +144 -144
- package/src/editor-registry.ts +122 -122
- package/src/export-data-api.test.ts +126 -126
- package/src/export-format.test.ts +107 -107
- package/src/export-format.ts +601 -601
- package/src/filter-operators.ts +160 -160
- package/src/filtering/excel-filters.ts +325 -325
- package/src/flex-render.ts +3 -3
- package/src/form-field.ts +127 -127
- package/src/group-display.test.ts +167 -167
- package/src/group-display.ts +200 -200
- package/src/headless.ts +87 -87
- package/src/js-scroller.svelte.ts +173 -173
- package/src/keyboard-handlers.ts +270 -270
- package/src/keyboard.test.ts +59 -59
- package/src/keyboard.ts +97 -97
- package/src/list-nav.test.ts +49 -49
- package/src/list-nav.ts +29 -29
- package/src/list-option.test.ts +56 -56
- package/src/list-option.ts +179 -179
- package/src/menus.ts +597 -597
- package/src/merge-objects.ts +48 -48
- package/src/overlays.test.ts +90 -90
- package/src/positioning.ts +268 -268
- package/src/render-component.ts +28 -28
- package/src/row-drag.test.ts +401 -401
- package/src/row-drag.ts +419 -419
- package/src/row-resize.test.ts +524 -524
- package/src/row-resize.ts +228 -228
- package/src/scheduler-ical.ts +181 -181
- package/src/scheduler-model.test.ts +562 -562
- package/src/scheduler-model.ts +873 -873
- package/src/selection.test.ts +885 -885
- package/src/server-data-source.test.ts +383 -383
- package/src/server-data-source.ts +469 -469
- package/src/sparkline.test.ts +68 -68
- package/src/sparkline.ts +169 -169
- package/src/spreadsheet.test.ts +488 -488
- package/src/spreadsheet.ts +312 -312
- package/src/static-functions.ts +11 -11
- package/src/subscribe.ts +38 -38
- package/src/summaries.ts +113 -113
- package/src/svgrid-wrapper.types.ts +563 -563
- package/src/svgrid.async-editor-options.test.ts +273 -273
- package/src/svgrid.auto-row-height.test.ts +204 -204
- package/src/svgrid.behavior.test.ts +910 -910
- package/src/svgrid.charting.test.ts +534 -534
- package/src/svgrid.comments-autocomplete.test.ts +127 -127
- package/src/svgrid.context-menu.test.ts +147 -147
- package/src/svgrid.features.test.ts +157 -157
- package/src/svgrid.filter-depth.test.ts +163 -163
- package/src/svgrid.filter-menu-listbox.svelte.test.ts +382 -377
- package/src/svgrid.filter-menu-scroll.test.ts +112 -112
- package/src/svgrid.grand-total.test.ts +188 -188
- package/src/svgrid.group-display-mode.test.ts +171 -171
- package/src/svgrid.group-footers.test.ts +121 -121
- package/src/svgrid.group-pagination.test.ts +153 -153
- package/src/svgrid.new-features.wrapper.test.ts +251 -251
- package/src/svgrid.tree-data.test.ts +186 -186
- package/src/svgrid.wrapper.test.ts +63 -63
- package/src/svgriddropdown.async-panel.svelte.test.ts +195 -195
- package/src/test-setup.ts +62 -62
- package/src/themes/index.ts +288 -288
- package/src/toast-store.svelte.ts +250 -250
- package/src/toast-store.test.ts +147 -147
- package/src/tree-row-model.test.ts +168 -168
- package/src/ui-buttons.test.ts +144 -144
- package/src/ui-inputs.test.ts +118 -118
- package/src/ui-localization.test.ts +113 -113
- package/src/ui-range.test.ts +70 -70
- package/src/ui-selection.test.ts +155 -155
- package/src/ui-tier1.test.ts +142 -142
- package/src/virtual.test.ts +88 -88
- package/src/virtualization/column-virtualizer.test.ts +27 -27
- package/src/virtualization/column-virtualizer.ts +30 -30
- package/src/virtualization/svelte-virtualizer.svelte.ts +26 -26
- package/src/virtualization/types.ts +30 -30
- package/src/virtualization/virtualizer.test.ts +47 -47
- package/src/virtualization/virtualizer.ts +322 -322
|
@@ -1,113 +1,113 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Every user-facing string in the kit must be overridable.
|
|
3
|
-
*
|
|
4
|
-
* These components shipped chrome copy - toolbar tooltips, "No matches", the
|
|
5
|
-
* lazy-load placeholder, search-box labels - baked in as literals, so an app in
|
|
6
|
-
* any other language had English fragments it could not reach. Each is now a
|
|
7
|
-
* prop; these tests pin that down so the strings cannot quietly go back to
|
|
8
|
-
* being hard-coded.
|
|
9
|
-
*/
|
|
10
|
-
import { describe, expect, it, afterEach } from 'vitest'
|
|
11
|
-
import { mount, unmount, flushSync } from 'svelte'
|
|
12
|
-
import SvRichText from './SvRichText.svelte'
|
|
13
|
-
import SvMultiSelect from './SvMultiSelect.svelte'
|
|
14
|
-
import SvGridSelect from './SvGridSelect.svelte'
|
|
15
|
-
import SvTree from './SvTree.svelte'
|
|
16
|
-
|
|
17
|
-
function mnt(Comp: unknown, props: Record<string, unknown>) {
|
|
18
|
-
const target = document.createElement('div')
|
|
19
|
-
document.body.appendChild(target)
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
|
-
const app = mount(Comp as any, { target, props: props as any })
|
|
22
|
-
flushSync()
|
|
23
|
-
return { target, destroy: () => { unmount(app); target.remove() } }
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
let cleanup: (() => void) | null = null
|
|
27
|
-
afterEach(() => {
|
|
28
|
-
cleanup?.()
|
|
29
|
-
cleanup = null
|
|
30
|
-
document.querySelectorAll('.sv-ms__panel, .sv-gs__panel').forEach((n) => n.remove())
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
describe('SvRichText localization', () => {
|
|
34
|
-
it('defaults to English toolbar labels', () => {
|
|
35
|
-
const g = mnt(SvRichText, {})
|
|
36
|
-
cleanup = g.destroy
|
|
37
|
-
const bold = g.target.querySelector('[data-tool="bold"]')!
|
|
38
|
-
expect(bold.getAttribute('title')).toBe('Bold')
|
|
39
|
-
expect(bold.getAttribute('aria-label')).toBe('Bold')
|
|
40
|
-
expect(g.target.querySelector('[role="toolbar"]')!.getAttribute('aria-label')).toBe('Formatting')
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
it('takes per-tool overrides through `messages`', () => {
|
|
44
|
-
const g = mnt(SvRichText, { messages: { bold: 'Fett', italic: 'Kursiv', toolbar: 'Formatierung' } })
|
|
45
|
-
cleanup = g.destroy
|
|
46
|
-
const bold = g.target.querySelector('[data-tool="bold"]')!
|
|
47
|
-
expect(bold.getAttribute('title')).toBe('Fett')
|
|
48
|
-
expect(bold.getAttribute('aria-label')).toBe('Fett')
|
|
49
|
-
expect(g.target.querySelector('[data-tool="italic"]')!.getAttribute('title')).toBe('Kursiv')
|
|
50
|
-
expect(g.target.querySelector('[role="toolbar"]')!.getAttribute('aria-label')).toBe('Formatierung')
|
|
51
|
-
// An un-overridden key keeps its default rather than going blank.
|
|
52
|
-
expect(g.target.querySelector('[data-tool="underline"]')!.getAttribute('title')).toBe('Underline')
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('keeps the glyphs fixed - they are not language-dependent', () => {
|
|
56
|
-
const g = mnt(SvRichText, { messages: { bold: 'Fett' } })
|
|
57
|
-
cleanup = g.destroy
|
|
58
|
-
expect(g.target.querySelector('[data-tool="bold"]')!.textContent?.trim()).toBe('B')
|
|
59
|
-
})
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
describe('empty / search text is overridable', () => {
|
|
63
|
-
it('SvMultiSelect emptyText + search chrome', () => {
|
|
64
|
-
const g = mnt(SvMultiSelect, {
|
|
65
|
-
options: [],
|
|
66
|
-
emptyText: 'Keine Treffer',
|
|
67
|
-
searchPlaceholder: 'Suchen…',
|
|
68
|
-
searchLabel: 'Optionen suchen',
|
|
69
|
-
})
|
|
70
|
-
cleanup = g.destroy
|
|
71
|
-
g.target.querySelector<HTMLButtonElement>('.sv-ms__trigger')?.click()
|
|
72
|
-
flushSync()
|
|
73
|
-
const panel = document.querySelector('.sv-ms__panel')
|
|
74
|
-
expect(panel?.textContent).toContain('Keine Treffer')
|
|
75
|
-
const search = panel?.querySelector('input')
|
|
76
|
-
expect(search?.getAttribute('placeholder')).toBe('Suchen…')
|
|
77
|
-
expect(search?.getAttribute('aria-label')).toBe('Optionen suchen')
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
it('SvGridSelect emptyText + search chrome', () => {
|
|
81
|
-
const g = mnt(SvGridSelect, {
|
|
82
|
-
columns: [{ field: 'name', header: 'Name' }],
|
|
83
|
-
options: [],
|
|
84
|
-
emptyText: 'Sin resultados',
|
|
85
|
-
searchPlaceholder: 'Buscar…',
|
|
86
|
-
searchLabel: 'Buscar opciones',
|
|
87
|
-
})
|
|
88
|
-
cleanup = g.destroy
|
|
89
|
-
g.target.querySelector<HTMLButtonElement>('.sv-gs__trigger')?.click()
|
|
90
|
-
flushSync()
|
|
91
|
-
const panel = document.querySelector('.sv-gs__panel')
|
|
92
|
-
expect(panel?.textContent).toContain('Sin resultados')
|
|
93
|
-
const search = panel?.querySelector('input')
|
|
94
|
-
expect(search?.getAttribute('placeholder')).toBe('Buscar…')
|
|
95
|
-
expect(search?.getAttribute('aria-label')).toBe('Buscar opciones')
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
it('SvTree lazy-load placeholder', async () => {
|
|
99
|
-
let resolveKids: (v: Array<{ id: string; label: string }>) => void = () => {}
|
|
100
|
-
const g = mnt(SvTree, {
|
|
101
|
-
nodes: [{ id: 'root', label: 'Root', lazy: true }],
|
|
102
|
-
loadChildren: () => new Promise<Array<{ id: string; label: string }>>((r) => { resolveKids = r }),
|
|
103
|
-
loadingText: 'Chargement…',
|
|
104
|
-
})
|
|
105
|
-
cleanup = g.destroy
|
|
106
|
-
g.target.querySelector<HTMLElement>('.sv-tree__twist')?.click()
|
|
107
|
-
flushSync()
|
|
108
|
-
await Promise.resolve()
|
|
109
|
-
flushSync()
|
|
110
|
-
expect(g.target.textContent).toContain('Chargement…')
|
|
111
|
-
resolveKids([{ id: 'kid', label: 'Child' }])
|
|
112
|
-
})
|
|
113
|
-
})
|
|
1
|
+
/**
|
|
2
|
+
* Every user-facing string in the kit must be overridable.
|
|
3
|
+
*
|
|
4
|
+
* These components shipped chrome copy - toolbar tooltips, "No matches", the
|
|
5
|
+
* lazy-load placeholder, search-box labels - baked in as literals, so an app in
|
|
6
|
+
* any other language had English fragments it could not reach. Each is now a
|
|
7
|
+
* prop; these tests pin that down so the strings cannot quietly go back to
|
|
8
|
+
* being hard-coded.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, expect, it, afterEach } from 'vitest'
|
|
11
|
+
import { mount, unmount, flushSync } from 'svelte'
|
|
12
|
+
import SvRichText from './SvRichText.svelte'
|
|
13
|
+
import SvMultiSelect from './SvMultiSelect.svelte'
|
|
14
|
+
import SvGridSelect from './SvGridSelect.svelte'
|
|
15
|
+
import SvTree from './SvTree.svelte'
|
|
16
|
+
|
|
17
|
+
function mnt(Comp: unknown, props: Record<string, unknown>) {
|
|
18
|
+
const target = document.createElement('div')
|
|
19
|
+
document.body.appendChild(target)
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
|
+
const app = mount(Comp as any, { target, props: props as any })
|
|
22
|
+
flushSync()
|
|
23
|
+
return { target, destroy: () => { unmount(app); target.remove() } }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let cleanup: (() => void) | null = null
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
cleanup?.()
|
|
29
|
+
cleanup = null
|
|
30
|
+
document.querySelectorAll('.sv-ms__panel, .sv-gs__panel').forEach((n) => n.remove())
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
describe('SvRichText localization', () => {
|
|
34
|
+
it('defaults to English toolbar labels', () => {
|
|
35
|
+
const g = mnt(SvRichText, {})
|
|
36
|
+
cleanup = g.destroy
|
|
37
|
+
const bold = g.target.querySelector('[data-tool="bold"]')!
|
|
38
|
+
expect(bold.getAttribute('title')).toBe('Bold')
|
|
39
|
+
expect(bold.getAttribute('aria-label')).toBe('Bold')
|
|
40
|
+
expect(g.target.querySelector('[role="toolbar"]')!.getAttribute('aria-label')).toBe('Formatting')
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('takes per-tool overrides through `messages`', () => {
|
|
44
|
+
const g = mnt(SvRichText, { messages: { bold: 'Fett', italic: 'Kursiv', toolbar: 'Formatierung' } })
|
|
45
|
+
cleanup = g.destroy
|
|
46
|
+
const bold = g.target.querySelector('[data-tool="bold"]')!
|
|
47
|
+
expect(bold.getAttribute('title')).toBe('Fett')
|
|
48
|
+
expect(bold.getAttribute('aria-label')).toBe('Fett')
|
|
49
|
+
expect(g.target.querySelector('[data-tool="italic"]')!.getAttribute('title')).toBe('Kursiv')
|
|
50
|
+
expect(g.target.querySelector('[role="toolbar"]')!.getAttribute('aria-label')).toBe('Formatierung')
|
|
51
|
+
// An un-overridden key keeps its default rather than going blank.
|
|
52
|
+
expect(g.target.querySelector('[data-tool="underline"]')!.getAttribute('title')).toBe('Underline')
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('keeps the glyphs fixed - they are not language-dependent', () => {
|
|
56
|
+
const g = mnt(SvRichText, { messages: { bold: 'Fett' } })
|
|
57
|
+
cleanup = g.destroy
|
|
58
|
+
expect(g.target.querySelector('[data-tool="bold"]')!.textContent?.trim()).toBe('B')
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
describe('empty / search text is overridable', () => {
|
|
63
|
+
it('SvMultiSelect emptyText + search chrome', () => {
|
|
64
|
+
const g = mnt(SvMultiSelect, {
|
|
65
|
+
options: [],
|
|
66
|
+
emptyText: 'Keine Treffer',
|
|
67
|
+
searchPlaceholder: 'Suchen…',
|
|
68
|
+
searchLabel: 'Optionen suchen',
|
|
69
|
+
})
|
|
70
|
+
cleanup = g.destroy
|
|
71
|
+
g.target.querySelector<HTMLButtonElement>('.sv-ms__trigger')?.click()
|
|
72
|
+
flushSync()
|
|
73
|
+
const panel = document.querySelector('.sv-ms__panel')
|
|
74
|
+
expect(panel?.textContent).toContain('Keine Treffer')
|
|
75
|
+
const search = panel?.querySelector('input')
|
|
76
|
+
expect(search?.getAttribute('placeholder')).toBe('Suchen…')
|
|
77
|
+
expect(search?.getAttribute('aria-label')).toBe('Optionen suchen')
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('SvGridSelect emptyText + search chrome', () => {
|
|
81
|
+
const g = mnt(SvGridSelect, {
|
|
82
|
+
columns: [{ field: 'name', header: 'Name' }],
|
|
83
|
+
options: [],
|
|
84
|
+
emptyText: 'Sin resultados',
|
|
85
|
+
searchPlaceholder: 'Buscar…',
|
|
86
|
+
searchLabel: 'Buscar opciones',
|
|
87
|
+
})
|
|
88
|
+
cleanup = g.destroy
|
|
89
|
+
g.target.querySelector<HTMLButtonElement>('.sv-gs__trigger')?.click()
|
|
90
|
+
flushSync()
|
|
91
|
+
const panel = document.querySelector('.sv-gs__panel')
|
|
92
|
+
expect(panel?.textContent).toContain('Sin resultados')
|
|
93
|
+
const search = panel?.querySelector('input')
|
|
94
|
+
expect(search?.getAttribute('placeholder')).toBe('Buscar…')
|
|
95
|
+
expect(search?.getAttribute('aria-label')).toBe('Buscar opciones')
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('SvTree lazy-load placeholder', async () => {
|
|
99
|
+
let resolveKids: (v: Array<{ id: string; label: string }>) => void = () => {}
|
|
100
|
+
const g = mnt(SvTree, {
|
|
101
|
+
nodes: [{ id: 'root', label: 'Root', lazy: true }],
|
|
102
|
+
loadChildren: () => new Promise<Array<{ id: string; label: string }>>((r) => { resolveKids = r }),
|
|
103
|
+
loadingText: 'Chargement…',
|
|
104
|
+
})
|
|
105
|
+
cleanup = g.destroy
|
|
106
|
+
g.target.querySelector<HTMLElement>('.sv-tree__twist')?.click()
|
|
107
|
+
flushSync()
|
|
108
|
+
await Promise.resolve()
|
|
109
|
+
flushSync()
|
|
110
|
+
expect(g.target.textContent).toContain('Chargement…')
|
|
111
|
+
resolveKids([{ id: 'kid', label: 'Child' }])
|
|
112
|
+
})
|
|
113
|
+
})
|
package/src/ui-range.test.ts
CHANGED
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
/** Group E (slider + gauge) component tests. */
|
|
2
|
-
import { describe, expect, it } from 'vitest'
|
|
3
|
-
import { mount, unmount, flushSync } from 'svelte'
|
|
4
|
-
import SvSlider from './SvSlider.svelte'
|
|
5
|
-
import SvGauge from './SvGauge.svelte'
|
|
6
|
-
|
|
7
|
-
function mnt(Comp: any, props: Record<string, unknown>) {
|
|
8
|
-
const target = document.createElement('div')
|
|
9
|
-
document.body.appendChild(target)
|
|
10
|
-
const app = mount(Comp, { target, props: props as any })
|
|
11
|
-
flushSync()
|
|
12
|
-
return { target, destroy: () => { unmount(app); target.remove() } }
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
describe('SvSlider', () => {
|
|
16
|
-
it('single: arrow keys step within bounds', () => {
|
|
17
|
-
let got: any
|
|
18
|
-
const { target, destroy } = mnt(SvSlider, { value: 50, min: 0, max: 100, step: 5, onChange: (v: any) => (got = v) })
|
|
19
|
-
try {
|
|
20
|
-
const thumb = target.querySelector<HTMLElement>('[role="slider"]')!
|
|
21
|
-
expect(thumb.getAttribute('aria-valuenow')).toBe('50')
|
|
22
|
-
thumb.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }))
|
|
23
|
-
flushSync()
|
|
24
|
-
expect(got).toBe(55)
|
|
25
|
-
thumb.dispatchEvent(new KeyboardEvent('keydown', { key: 'Home', bubbles: true }))
|
|
26
|
-
flushSync()
|
|
27
|
-
expect(got).toBe(0)
|
|
28
|
-
} finally { destroy() }
|
|
29
|
-
})
|
|
30
|
-
it('range: two thumbs, low thumb capped at high value', () => {
|
|
31
|
-
let got: any
|
|
32
|
-
const { target, destroy } = mnt(SvSlider, { value: [20, 80], range: true, min: 0, max: 100, step: 10, onChange: (v: any) => (got = v) })
|
|
33
|
-
try {
|
|
34
|
-
const thumbs = target.querySelectorAll<HTMLElement>('[role="slider"]')
|
|
35
|
-
expect(thumbs.length).toBe(2)
|
|
36
|
-
thumbs[0]!.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }))
|
|
37
|
-
flushSync()
|
|
38
|
-
expect(got).toEqual([30, 80])
|
|
39
|
-
} finally { destroy() }
|
|
40
|
-
})
|
|
41
|
-
it('wires validation ARIA onto the thumb (aria-invalid + describedby)', () => {
|
|
42
|
-
const { target, destroy } = mnt(SvSlider, { value: 50, invalid: true, error: 'Out of range', id: 'vol', required: true })
|
|
43
|
-
try {
|
|
44
|
-
const thumb = target.querySelector<HTMLElement>('[role="slider"]')!
|
|
45
|
-
expect(thumb.getAttribute('aria-invalid')).toBe('true')
|
|
46
|
-
expect(thumb.getAttribute('aria-required')).toBe('true')
|
|
47
|
-
expect(thumb.getAttribute('aria-describedby')).toContain('vol__error')
|
|
48
|
-
} finally { destroy() }
|
|
49
|
-
})
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
describe('SvGauge', () => {
|
|
53
|
-
it('exposes a meter role with clamped value + label', () => {
|
|
54
|
-
const { target, destroy } = mnt(SvGauge, { value: 150, min: 0, max: 100 })
|
|
55
|
-
try {
|
|
56
|
-
const meter = target.querySelector('[role="meter"]')!
|
|
57
|
-
expect(meter.getAttribute('aria-valuenow')).toBe('100') // clamped to max
|
|
58
|
-
expect(target.querySelector('.sv-gauge__label')!.textContent).toContain('100')
|
|
59
|
-
} finally { destroy() }
|
|
60
|
-
})
|
|
61
|
-
it('renders one path per band when bands are given', () => {
|
|
62
|
-
const { target, destroy } = mnt(SvGauge, {
|
|
63
|
-
value: 50, bands: [{ from: 0, to: 50, color: '#16a34a' }, { from: 50, to: 100, color: '#dc2626' }],
|
|
64
|
-
})
|
|
65
|
-
try {
|
|
66
|
-
// track + 2 bands = 3 paths, no value arc
|
|
67
|
-
expect(target.querySelectorAll('path').length).toBe(3)
|
|
68
|
-
} finally { destroy() }
|
|
69
|
-
})
|
|
70
|
-
})
|
|
1
|
+
/** Group E (slider + gauge) component tests. */
|
|
2
|
+
import { describe, expect, it } from 'vitest'
|
|
3
|
+
import { mount, unmount, flushSync } from 'svelte'
|
|
4
|
+
import SvSlider from './SvSlider.svelte'
|
|
5
|
+
import SvGauge from './SvGauge.svelte'
|
|
6
|
+
|
|
7
|
+
function mnt(Comp: any, props: Record<string, unknown>) {
|
|
8
|
+
const target = document.createElement('div')
|
|
9
|
+
document.body.appendChild(target)
|
|
10
|
+
const app = mount(Comp, { target, props: props as any })
|
|
11
|
+
flushSync()
|
|
12
|
+
return { target, destroy: () => { unmount(app); target.remove() } }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
describe('SvSlider', () => {
|
|
16
|
+
it('single: arrow keys step within bounds', () => {
|
|
17
|
+
let got: any
|
|
18
|
+
const { target, destroy } = mnt(SvSlider, { value: 50, min: 0, max: 100, step: 5, onChange: (v: any) => (got = v) })
|
|
19
|
+
try {
|
|
20
|
+
const thumb = target.querySelector<HTMLElement>('[role="slider"]')!
|
|
21
|
+
expect(thumb.getAttribute('aria-valuenow')).toBe('50')
|
|
22
|
+
thumb.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }))
|
|
23
|
+
flushSync()
|
|
24
|
+
expect(got).toBe(55)
|
|
25
|
+
thumb.dispatchEvent(new KeyboardEvent('keydown', { key: 'Home', bubbles: true }))
|
|
26
|
+
flushSync()
|
|
27
|
+
expect(got).toBe(0)
|
|
28
|
+
} finally { destroy() }
|
|
29
|
+
})
|
|
30
|
+
it('range: two thumbs, low thumb capped at high value', () => {
|
|
31
|
+
let got: any
|
|
32
|
+
const { target, destroy } = mnt(SvSlider, { value: [20, 80], range: true, min: 0, max: 100, step: 10, onChange: (v: any) => (got = v) })
|
|
33
|
+
try {
|
|
34
|
+
const thumbs = target.querySelectorAll<HTMLElement>('[role="slider"]')
|
|
35
|
+
expect(thumbs.length).toBe(2)
|
|
36
|
+
thumbs[0]!.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }))
|
|
37
|
+
flushSync()
|
|
38
|
+
expect(got).toEqual([30, 80])
|
|
39
|
+
} finally { destroy() }
|
|
40
|
+
})
|
|
41
|
+
it('wires validation ARIA onto the thumb (aria-invalid + describedby)', () => {
|
|
42
|
+
const { target, destroy } = mnt(SvSlider, { value: 50, invalid: true, error: 'Out of range', id: 'vol', required: true })
|
|
43
|
+
try {
|
|
44
|
+
const thumb = target.querySelector<HTMLElement>('[role="slider"]')!
|
|
45
|
+
expect(thumb.getAttribute('aria-invalid')).toBe('true')
|
|
46
|
+
expect(thumb.getAttribute('aria-required')).toBe('true')
|
|
47
|
+
expect(thumb.getAttribute('aria-describedby')).toContain('vol__error')
|
|
48
|
+
} finally { destroy() }
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
describe('SvGauge', () => {
|
|
53
|
+
it('exposes a meter role with clamped value + label', () => {
|
|
54
|
+
const { target, destroy } = mnt(SvGauge, { value: 150, min: 0, max: 100 })
|
|
55
|
+
try {
|
|
56
|
+
const meter = target.querySelector('[role="meter"]')!
|
|
57
|
+
expect(meter.getAttribute('aria-valuenow')).toBe('100') // clamped to max
|
|
58
|
+
expect(target.querySelector('.sv-gauge__label')!.textContent).toContain('100')
|
|
59
|
+
} finally { destroy() }
|
|
60
|
+
})
|
|
61
|
+
it('renders one path per band when bands are given', () => {
|
|
62
|
+
const { target, destroy } = mnt(SvGauge, {
|
|
63
|
+
value: 50, bands: [{ from: 0, to: 50, color: '#16a34a' }, { from: 50, to: 100, color: '#dc2626' }],
|
|
64
|
+
})
|
|
65
|
+
try {
|
|
66
|
+
// track + 2 bands = 3 paths, no value arc
|
|
67
|
+
expect(target.querySelectorAll('path').length).toBe(3)
|
|
68
|
+
} finally { destroy() }
|
|
69
|
+
})
|
|
70
|
+
})
|